mirror of
https://github.com/modrinth/code.git
synced 2026-09-05 06:19:11 +00:00
give proper types to metadata fields
This commit is contained in:
@@ -119,14 +119,13 @@ impl MinecraftGameVersion {
|
|||||||
created: loader_field_enum_value.created,
|
created: loader_field_enum_value.created,
|
||||||
type_: loader_field_enum_value
|
type_: loader_field_enum_value
|
||||||
.metadata
|
.metadata
|
||||||
.get("type")
|
.as_ref()
|
||||||
.and_then(|x| x.as_str())
|
.map(|metadata| metadata.type_.clone())
|
||||||
.map(|x| x.to_string())
|
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
major: loader_field_enum_value
|
major: loader_field_enum_value
|
||||||
.metadata
|
.metadata
|
||||||
.get("major")
|
.as_ref()
|
||||||
.and_then(|x| x.as_bool())
|
.map(|metadata| metadata.major)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,11 @@ impl Game {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
pub struct LoaderMetadata {
|
||||||
|
pub platform: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct Loader {
|
pub struct Loader {
|
||||||
pub id: LoaderId,
|
pub id: LoaderId,
|
||||||
@@ -94,7 +99,7 @@ pub struct Loader {
|
|||||||
pub icon: String,
|
pub icon: String,
|
||||||
pub supported_project_types: Vec<String>,
|
pub supported_project_types: Vec<String>,
|
||||||
pub supported_games: Vec<String>, // slugs
|
pub supported_games: Vec<String>, // slugs
|
||||||
pub metadata: serde_json::Value,
|
pub metadata: LoaderMetadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Loader {
|
impl Loader {
|
||||||
@@ -154,7 +159,8 @@ impl Loader {
|
|||||||
|
|
||||||
let result = sqlx::query!(
|
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 pt.name) filter (where pt.name is not null) project_types,
|
||||||
ARRAY_AGG(DISTINCT g.slug) filter (where g.slug is not null) games
|
ARRAY_AGG(DISTINCT g.slug) filter (where g.slug is not null) games
|
||||||
FROM loaders l
|
FROM loaders l
|
||||||
@@ -179,7 +185,9 @@ impl Loader {
|
|||||||
supported_games: x
|
supported_games: x
|
||||||
.games
|
.games
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
metadata: x.metadata
|
metadata: LoaderMetadata {
|
||||||
|
platform: x.platform,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.try_collect::<Vec<_>>()
|
.try_collect::<Vec<_>>()
|
||||||
.await?;
|
.await?;
|
||||||
@@ -270,6 +278,13 @@ pub struct LoaderFieldEnum {
|
|||||||
pub hidable: bool,
|
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)]
|
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||||
pub struct LoaderFieldEnumValue {
|
pub struct LoaderFieldEnumValue {
|
||||||
pub id: LoaderFieldEnumValueId,
|
pub id: LoaderFieldEnumValueId,
|
||||||
@@ -278,7 +293,7 @@ pub struct LoaderFieldEnumValue {
|
|||||||
pub ordering: Option<i32>,
|
pub ordering: Option<i32>,
|
||||||
pub created: DateTime<Utc>,
|
pub created: DateTime<Utc>,
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub metadata: serde_json::Value,
|
pub metadata: Option<LoaderFieldEnumValueMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::hash::Hash for LoaderFieldEnumValue {
|
impl std::hash::Hash for LoaderFieldEnumValue {
|
||||||
@@ -357,7 +372,7 @@ pub struct QueryLoaderFieldEnumValue {
|
|||||||
pub value: String,
|
pub value: String,
|
||||||
pub ordering: Option<i32>,
|
pub ordering: Option<i32>,
|
||||||
pub created: DateTime<Utc>,
|
pub created: DateTime<Utc>,
|
||||||
pub metadata: Option<serde_json::Value>,
|
pub metadata: Option<LoaderFieldEnumValueMetadata>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LoaderField {
|
impl LoaderField {
|
||||||
@@ -617,11 +632,13 @@ impl LoaderFieldEnumValue {
|
|||||||
&loader_field_enum_ids.iter().map(|x| x.0).collect::<Vec<_>>(),
|
&loader_field_enum_ids.iter().map(|x| x.0).collect::<Vec<_>>(),
|
||||||
|loader_field_enum_ids| async move {
|
|loader_field_enum_ids| async move {
|
||||||
let values = sqlx::query!(
|
let values = sqlx::query!(
|
||||||
"
|
r#"
|
||||||
SELECT id, enum_id, value, ordering, metadata, created FROM loader_field_enum_values
|
SELECT id, enum_id, value, ordering,
|
||||||
|
metadata AS "metadata?: sqlx::types::Json<LoaderFieldEnumValueMetadata>",
|
||||||
|
created FROM loader_field_enum_values
|
||||||
WHERE enum_id = ANY($1)
|
WHERE enum_id = ANY($1)
|
||||||
ORDER BY enum_id, ordering, created DESC
|
ORDER BY enum_id, ordering, created DESC
|
||||||
",
|
"#,
|
||||||
&loader_field_enum_ids
|
&loader_field_enum_ids
|
||||||
)
|
)
|
||||||
.fetch(exec)
|
.fetch(exec)
|
||||||
@@ -632,7 +649,7 @@ impl LoaderFieldEnumValue {
|
|||||||
value: c.value,
|
value: c.value,
|
||||||
ordering: c.ordering,
|
ordering: c.ordering,
|
||||||
created: c.created,
|
created: c.created,
|
||||||
metadata: c.metadata.unwrap_or_default(),
|
metadata: c.metadata.map(|metadata| metadata.0),
|
||||||
};
|
};
|
||||||
|
|
||||||
acc.entry(c.enum_id)
|
acc.entry(c.enum_id)
|
||||||
@@ -669,15 +686,15 @@ impl LoaderFieldEnumValue {
|
|||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|x| {
|
.filter(|x| {
|
||||||
let mut bool = true;
|
filter.iter().all(|(key, value)| match key.as_str() {
|
||||||
for (key, value) in &filter {
|
"type" => x.metadata.as_ref().is_some_and(|metadata| {
|
||||||
if let Some(metadata_value) = x.metadata.get(key) {
|
value.as_str() == Some(metadata.type_.as_str())
|
||||||
bool &= metadata_value == value;
|
}),
|
||||||
} else {
|
"major" => x.metadata.as_ref().is_some_and(|metadata| {
|
||||||
bool = false;
|
value.as_bool() == Some(metadata.major)
|
||||||
}
|
}),
|
||||||
}
|
_ => false,
|
||||||
bool
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@@ -1170,10 +1187,7 @@ impl VersionFieldValue {
|
|||||||
value: lfev.value.clone(),
|
value: lfev.value.clone(),
|
||||||
ordering: lfev.ordering,
|
ordering: lfev.ordering,
|
||||||
created: lfev.created,
|
created: lfev.created,
|
||||||
metadata: lfev
|
metadata: lfev.metadata.clone(),
|
||||||
.metadata
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_default(),
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
@@ -1249,10 +1263,7 @@ impl VersionFieldValue {
|
|||||||
value: lfev.value.clone(),
|
value: lfev.value.clone(),
|
||||||
ordering: lfev.ordering,
|
ordering: lfev.ordering,
|
||||||
created: lfev.created,
|
created: lfev.created,
|
||||||
metadata: lfev
|
metadata: lfev.metadata.clone(),
|
||||||
.metadata
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_default(),
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use super::loader_fields::{
|
use super::loader_fields::{
|
||||||
QueryLoaderField, QueryLoaderFieldEnumValue, QueryVersionField,
|
LoaderFieldEnumValueMetadata, QueryLoaderField, QueryLoaderFieldEnumValue,
|
||||||
VersionField,
|
QueryVersionField, VersionField,
|
||||||
};
|
};
|
||||||
use super::{DBUser, ids::*};
|
use super::{DBUser, ids::*};
|
||||||
use crate::database::models::DatabaseError;
|
use crate::database::models::DatabaseError;
|
||||||
@@ -657,12 +657,13 @@ impl DBProject {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let loader_field_enum_values: Vec<QueryLoaderFieldEnumValue> = sqlx::query!(
|
let loader_field_enum_values: Vec<QueryLoaderFieldEnumValue> = sqlx::query!(
|
||||||
"
|
r#"
|
||||||
SELECT DISTINCT id, enum_id, value, ordering, created, metadata
|
SELECT DISTINCT id, enum_id, value, ordering, created,
|
||||||
|
metadata AS "metadata?: sqlx::types::Json<LoaderFieldEnumValueMetadata>"
|
||||||
FROM loader_field_enum_values lfev
|
FROM loader_field_enum_values lfev
|
||||||
WHERE id = ANY($1)
|
WHERE id = ANY($1)
|
||||||
ORDER BY enum_id, ordering, created DESC
|
ORDER BY enum_id, ordering, created DESC
|
||||||
",
|
"#,
|
||||||
&loader_field_enum_value_ids
|
&loader_field_enum_value_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.0)
|
.map(|x| x.0)
|
||||||
@@ -675,7 +676,7 @@ impl DBProject {
|
|||||||
value: m.value,
|
value: m.value,
|
||||||
ordering: m.ordering,
|
ordering: m.ordering,
|
||||||
created: m.created,
|
created: m.created,
|
||||||
metadata: m.metadata,
|
metadata: m.metadata.map(|metadata| metadata.0),
|
||||||
})
|
})
|
||||||
.try_collect()
|
.try_collect()
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ use super::ids::*;
|
|||||||
use super::loader_fields::VersionField;
|
use super::loader_fields::VersionField;
|
||||||
use crate::database::PgTransaction;
|
use crate::database::PgTransaction;
|
||||||
use crate::database::models::loader_fields::{
|
use crate::database::models::loader_fields::{
|
||||||
QueryLoaderField, QueryLoaderFieldEnumValue, QueryVersionField,
|
LoaderFieldEnumValueMetadata, QueryLoaderField, QueryLoaderFieldEnumValue,
|
||||||
|
QueryVersionField,
|
||||||
};
|
};
|
||||||
use crate::file_hosting::FileHost;
|
use crate::file_hosting::FileHost;
|
||||||
use crate::models::exp;
|
use crate::models::exp;
|
||||||
@@ -704,12 +705,13 @@ impl DBVersion {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let loader_field_enum_values: Vec<QueryLoaderFieldEnumValue> = sqlx::query!(
|
let loader_field_enum_values: Vec<QueryLoaderFieldEnumValue> = sqlx::query!(
|
||||||
"
|
r#"
|
||||||
SELECT DISTINCT id, enum_id, value, ordering, created, metadata
|
SELECT DISTINCT id, enum_id, value, ordering, created,
|
||||||
|
metadata AS "metadata?: sqlx::types::Json<LoaderFieldEnumValueMetadata>"
|
||||||
FROM loader_field_enum_values lfev
|
FROM loader_field_enum_values lfev
|
||||||
WHERE id = ANY($1)
|
WHERE id = ANY($1)
|
||||||
ORDER BY enum_id, ordering, created ASC
|
ORDER BY enum_id, ordering, created ASC
|
||||||
",
|
"#,
|
||||||
&loader_field_enum_value_ids
|
&loader_field_enum_value_ids
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| x.0)
|
.map(|x| x.0)
|
||||||
@@ -722,7 +724,7 @@ impl DBVersion {
|
|||||||
value: m.value,
|
value: m.value,
|
||||||
ordering: m.ordering,
|
ordering: m.ordering,
|
||||||
created: m.created,
|
created: m.created,
|
||||||
metadata: m.metadata,
|
metadata: m.metadata.map(|metadata| metadata.0),
|
||||||
})
|
})
|
||||||
.try_collect()
|
.try_collect()
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
@@ -212,15 +212,15 @@ pub async fn game_version_list(
|
|||||||
version: f.value,
|
version: f.value,
|
||||||
version_type: f
|
version_type: f
|
||||||
.metadata
|
.metadata
|
||||||
.get("type")
|
.as_ref()
|
||||||
.and_then(|m| m.as_str())
|
.map(|metadata| metadata.type_.as_str())
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
.to_string(),
|
.to_string(),
|
||||||
date: f.created,
|
date: f.created,
|
||||||
major: f
|
major: f
|
||||||
.metadata
|
.metadata
|
||||||
.get("major")
|
.as_ref()
|
||||||
.and_then(|m| m.as_bool())
|
.map(|metadata| metadata.major)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::database::models::categories::{
|
|||||||
};
|
};
|
||||||
use crate::database::models::loader_fields::{
|
use crate::database::models::loader_fields::{
|
||||||
Game, Loader, LoaderField, LoaderFieldEnumValue, LoaderFieldType,
|
Game, Loader, LoaderField, LoaderFieldEnumValue, LoaderFieldType,
|
||||||
|
LoaderMetadata,
|
||||||
};
|
};
|
||||||
use actix_web::{HttpResponse, get, web};
|
use actix_web::{HttpResponse, get, web};
|
||||||
use xredis::RedisPool;
|
use xredis::RedisPool;
|
||||||
@@ -103,7 +104,7 @@ pub struct LoaderData {
|
|||||||
pub supported_project_types: Vec<String>,
|
pub supported_project_types: Vec<String>,
|
||||||
pub supported_games: Vec<String>,
|
pub supported_games: Vec<String>,
|
||||||
pub supported_fields: Vec<String>, // Available loader fields for this loader
|
pub supported_fields: Vec<String>, // Available loader fields for this loader
|
||||||
pub metadata: Value,
|
pub metadata: LoaderMetadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[utoipa::path(tag = "tags", responses((status = OK)))]
|
#[utoipa::path(tag = "tags", responses((status = OK)))]
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use tracing::{info, warn};
|
|||||||
|
|
||||||
use crate::database::PgPool;
|
use crate::database::PgPool;
|
||||||
use crate::database::models::loader_fields::{
|
use crate::database::models::loader_fields::{
|
||||||
QueryLoaderField, QueryLoaderFieldEnumValue, QueryVersionField,
|
LoaderFieldEnumValueMetadata, QueryLoaderField, QueryLoaderFieldEnumValue,
|
||||||
VersionField,
|
QueryVersionField, VersionField,
|
||||||
};
|
};
|
||||||
use crate::database::models::{
|
use crate::database::models::{
|
||||||
DBOrganizationId, DBProjectId, DBUserId, DBVersionId, LoaderFieldEnumId,
|
DBOrganizationId, DBProjectId, DBUserId, DBVersionId, LoaderFieldEnumId,
|
||||||
@@ -394,11 +394,12 @@ async fn build_search_documents(
|
|||||||
|
|
||||||
let loader_field_enum_values: Vec<QueryLoaderFieldEnumValue> =
|
let loader_field_enum_values: Vec<QueryLoaderFieldEnumValue> =
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
r#"
|
||||||
SELECT DISTINCT id, enum_id, value, ordering, created, metadata
|
SELECT DISTINCT id, enum_id, value, ordering, created,
|
||||||
|
metadata AS "metadata?: sqlx::types::Json<LoaderFieldEnumValueMetadata>"
|
||||||
FROM loader_field_enum_values lfev
|
FROM loader_field_enum_values lfev
|
||||||
ORDER BY enum_id, ordering, created DESC
|
ORDER BY enum_id, ordering, created DESC
|
||||||
"
|
"#
|
||||||
)
|
)
|
||||||
.fetch(pool)
|
.fetch(pool)
|
||||||
.map_ok(|m| QueryLoaderFieldEnumValue {
|
.map_ok(|m| QueryLoaderFieldEnumValue {
|
||||||
@@ -407,7 +408,7 @@ async fn build_search_documents(
|
|||||||
value: m.value,
|
value: m.value,
|
||||||
ordering: m.ordering,
|
ordering: m.ordering,
|
||||||
created: m.created,
|
created: m.created,
|
||||||
metadata: m.metadata,
|
metadata: m.metadata.map(|metadata| metadata.0),
|
||||||
})
|
})
|
||||||
.try_collect()
|
.try_collect()
|
||||||
.await?;
|
.await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user