diff --git a/apps/labrinth/src/database/models/legacy_loader_fields.rs b/apps/labrinth/src/database/models/legacy_loader_fields.rs index a11a8a504f..4449068f50 100644 --- a/apps/labrinth/src/database/models/legacy_loader_fields.rs +++ b/apps/labrinth/src/database/models/legacy_loader_fields.rs @@ -119,14 +119,13 @@ impl MinecraftGameVersion { created: loader_field_enum_value.created, type_: loader_field_enum_value .metadata - .get("type") - .and_then(|x| x.as_str()) - .map(|x| x.to_string()) + .as_ref() + .map(|metadata| metadata.type_.clone()) .unwrap_or_default(), major: loader_field_enum_value .metadata - .get("major") - .and_then(|x| x.as_bool()) + .as_ref() + .map(|metadata| metadata.major) .unwrap_or_default(), } } diff --git a/apps/labrinth/src/database/models/loader_fields.rs b/apps/labrinth/src/database/models/loader_fields.rs index a794812b25..706be3cfc4 100644 --- a/apps/labrinth/src/database/models/loader_fields.rs +++ b/apps/labrinth/src/database/models/loader_fields.rs @@ -87,6 +87,11 @@ impl Game { } } +#[derive(Clone, Serialize, Deserialize)] +pub struct LoaderMetadata { + pub platform: Option, +} + #[derive(Serialize, Deserialize, Clone)] pub struct Loader { pub id: LoaderId, @@ -94,7 +99,7 @@ pub struct Loader { pub icon: String, pub supported_project_types: Vec, pub supported_games: Vec, // slugs - pub metadata: serde_json::Value, + pub metadata: LoaderMetadata, } impl Loader { @@ -154,7 +159,8 @@ impl Loader { let result = sqlx::query!( " - SELECT l.id id, l.loader loader, l.icon icon, l.metadata metadata, + SELECT l.id id, l.loader loader, l.icon icon, + (l.metadata->>'platform')::boolean AS platform, ARRAY_AGG(DISTINCT pt.name) filter (where pt.name is not null) project_types, ARRAY_AGG(DISTINCT g.slug) filter (where g.slug is not null) games FROM loaders l @@ -179,7 +185,9 @@ impl Loader { supported_games: x .games .unwrap_or_default(), - metadata: x.metadata + metadata: LoaderMetadata { + platform: x.platform, + }, }) .try_collect::>() .await?; @@ -270,6 +278,13 @@ pub struct LoaderFieldEnum { pub hidable: bool, } +#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] +pub struct LoaderFieldEnumValueMetadata { + #[serde(rename = "type")] + pub type_: String, + pub major: bool, +} + #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)] pub struct LoaderFieldEnumValue { pub id: LoaderFieldEnumValueId, @@ -278,7 +293,7 @@ pub struct LoaderFieldEnumValue { pub ordering: Option, pub created: DateTime, #[serde(flatten)] - pub metadata: serde_json::Value, + pub metadata: Option, } impl std::hash::Hash for LoaderFieldEnumValue { @@ -357,7 +372,7 @@ pub struct QueryLoaderFieldEnumValue { pub value: String, pub ordering: Option, pub created: DateTime, - pub metadata: Option, + pub metadata: Option, } impl LoaderField { @@ -617,11 +632,13 @@ impl LoaderFieldEnumValue { &loader_field_enum_ids.iter().map(|x| x.0).collect::>(), |loader_field_enum_ids| async move { let values = sqlx::query!( - " - SELECT id, enum_id, value, ordering, metadata, created FROM loader_field_enum_values + r#" + SELECT id, enum_id, value, ordering, + metadata AS "metadata?: sqlx::types::Json", + created FROM loader_field_enum_values WHERE enum_id = ANY($1) ORDER BY enum_id, ordering, created DESC - ", + "#, &loader_field_enum_ids ) .fetch(exec) @@ -632,7 +649,7 @@ impl LoaderFieldEnumValue { value: c.value, ordering: c.ordering, created: c.created, - metadata: c.metadata.unwrap_or_default(), + metadata: c.metadata.map(|metadata| metadata.0), }; acc.entry(c.enum_id) @@ -669,15 +686,15 @@ impl LoaderFieldEnumValue { .await? .into_iter() .filter(|x| { - let mut bool = true; - for (key, value) in &filter { - if let Some(metadata_value) = x.metadata.get(key) { - bool &= metadata_value == value; - } else { - bool = false; - } - } - bool + filter.iter().all(|(key, value)| match key.as_str() { + "type" => x.metadata.as_ref().is_some_and(|metadata| { + value.as_str() == Some(metadata.type_.as_str()) + }), + "major" => x.metadata.as_ref().is_some_and(|metadata| { + value.as_bool() == Some(metadata.major) + }), + _ => false, + }) }) .collect(); @@ -1170,10 +1187,7 @@ impl VersionFieldValue { value: lfev.value.clone(), ordering: lfev.ordering, created: lfev.created, - metadata: lfev - .metadata - .clone() - .unwrap_or_default(), + metadata: lfev.metadata.clone(), } }), )) @@ -1249,10 +1263,7 @@ impl VersionFieldValue { value: lfev.value.clone(), ordering: lfev.ordering, created: lfev.created, - metadata: lfev - .metadata - .clone() - .unwrap_or_default(), + metadata: lfev.metadata.clone(), }) }) .collect::>()?, diff --git a/apps/labrinth/src/database/models/project_item.rs b/apps/labrinth/src/database/models/project_item.rs index 2b9092d489..b756743d79 100644 --- a/apps/labrinth/src/database/models/project_item.rs +++ b/apps/labrinth/src/database/models/project_item.rs @@ -1,6 +1,6 @@ use super::loader_fields::{ - QueryLoaderField, QueryLoaderFieldEnumValue, QueryVersionField, - VersionField, + LoaderFieldEnumValueMetadata, QueryLoaderField, QueryLoaderFieldEnumValue, + QueryVersionField, VersionField, }; use super::{DBUser, ids::*}; use crate::database::models::DatabaseError; @@ -657,12 +657,13 @@ impl DBProject { .await?; let loader_field_enum_values: Vec = sqlx::query!( - " - SELECT DISTINCT id, enum_id, value, ordering, created, metadata + r#" + SELECT DISTINCT id, enum_id, value, ordering, created, + metadata AS "metadata?: sqlx::types::Json" FROM loader_field_enum_values lfev WHERE id = ANY($1) ORDER BY enum_id, ordering, created DESC - ", + "#, &loader_field_enum_value_ids .iter() .map(|x| x.0) @@ -675,7 +676,7 @@ impl DBProject { value: m.value, ordering: m.ordering, created: m.created, - metadata: m.metadata, + metadata: m.metadata.map(|metadata| metadata.0), }) .try_collect() .await?; diff --git a/apps/labrinth/src/database/models/version_item.rs b/apps/labrinth/src/database/models/version_item.rs index 096bed6614..6d587d8cad 100644 --- a/apps/labrinth/src/database/models/version_item.rs +++ b/apps/labrinth/src/database/models/version_item.rs @@ -3,7 +3,8 @@ use super::ids::*; use super::loader_fields::VersionField; use crate::database::PgTransaction; use crate::database::models::loader_fields::{ - QueryLoaderField, QueryLoaderFieldEnumValue, QueryVersionField, + LoaderFieldEnumValueMetadata, QueryLoaderField, QueryLoaderFieldEnumValue, + QueryVersionField, }; use crate::file_hosting::FileHost; use crate::models::exp; @@ -704,12 +705,13 @@ impl DBVersion { .await?; let loader_field_enum_values: Vec = sqlx::query!( - " - SELECT DISTINCT id, enum_id, value, ordering, created, metadata + r#" + SELECT DISTINCT id, enum_id, value, ordering, created, + metadata AS "metadata?: sqlx::types::Json" FROM loader_field_enum_values lfev WHERE id = ANY($1) ORDER BY enum_id, ordering, created ASC - ", + "#, &loader_field_enum_value_ids .iter() .map(|x| x.0) @@ -722,7 +724,7 @@ impl DBVersion { value: m.value, ordering: m.ordering, created: m.created, - metadata: m.metadata, + metadata: m.metadata.map(|metadata| metadata.0), }) .try_collect() .await?; diff --git a/apps/labrinth/src/routes/v2/tags.rs b/apps/labrinth/src/routes/v2/tags.rs index 6f3ef45283..d589e02d1a 100644 --- a/apps/labrinth/src/routes/v2/tags.rs +++ b/apps/labrinth/src/routes/v2/tags.rs @@ -212,15 +212,15 @@ pub async fn game_version_list( version: f.value, version_type: f .metadata - .get("type") - .and_then(|m| m.as_str()) + .as_ref() + .map(|metadata| metadata.type_.as_str()) .unwrap_or_default() .to_string(), date: f.created, major: f .metadata - .get("major") - .and_then(|m| m.as_bool()) + .as_ref() + .map(|metadata| metadata.major) .unwrap_or_default(), }) .collect::>(); diff --git a/apps/labrinth/src/routes/v3/tags.rs b/apps/labrinth/src/routes/v3/tags.rs index 6a499df5df..4c1589cbbc 100644 --- a/apps/labrinth/src/routes/v3/tags.rs +++ b/apps/labrinth/src/routes/v3/tags.rs @@ -6,6 +6,7 @@ use crate::database::models::categories::{ }; use crate::database::models::loader_fields::{ Game, Loader, LoaderField, LoaderFieldEnumValue, LoaderFieldType, + LoaderMetadata, }; use actix_web::{HttpResponse, get, web}; use xredis::RedisPool; @@ -103,7 +104,7 @@ pub struct LoaderData { pub supported_project_types: Vec, pub supported_games: Vec, pub supported_fields: Vec, // Available loader fields for this loader - pub metadata: Value, + pub metadata: LoaderMetadata, } #[utoipa::path(tag = "tags", responses((status = OK)))] diff --git a/apps/labrinth/src/search/indexing.rs b/apps/labrinth/src/search/indexing.rs index 03e6c34061..7e7347395c 100644 --- a/apps/labrinth/src/search/indexing.rs +++ b/apps/labrinth/src/search/indexing.rs @@ -11,8 +11,8 @@ use tracing::{info, warn}; use crate::database::PgPool; use crate::database::models::loader_fields::{ - QueryLoaderField, QueryLoaderFieldEnumValue, QueryVersionField, - VersionField, + LoaderFieldEnumValueMetadata, QueryLoaderField, QueryLoaderFieldEnumValue, + QueryVersionField, VersionField, }; use crate::database::models::{ DBOrganizationId, DBProjectId, DBUserId, DBVersionId, LoaderFieldEnumId, @@ -394,11 +394,12 @@ async fn build_search_documents( let loader_field_enum_values: Vec = sqlx::query!( - " - SELECT DISTINCT id, enum_id, value, ordering, created, metadata + r#" + SELECT DISTINCT id, enum_id, value, ordering, created, + metadata AS "metadata?: sqlx::types::Json" FROM loader_field_enum_values lfev ORDER BY enum_id, ordering, created DESC - " + "# ) .fetch(pool) .map_ok(|m| QueryLoaderFieldEnumValue { @@ -407,7 +408,7 @@ async fn build_search_documents( value: m.value, ordering: m.ordering, created: m.created, - metadata: m.metadata, + metadata: m.metadata.map(|metadata| metadata.0), }) .try_collect() .await?;