add newtype
This commit is contained in:
parent
76e5e31411
commit
1455068e0c
10 changed files with 101 additions and 52 deletions
|
@ -9,6 +9,7 @@ edition = "2021"
|
|||
async-trait = "0.1.68"
|
||||
chrono = "0.4.24"
|
||||
database = { path = "../database" }
|
||||
derive_more = "0.99.17"
|
||||
jsonschema = "0.17.0"
|
||||
once_cell = "1.17.1"
|
||||
parse-display = "0.8.0"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! `SeaORM` Entity. Generated by sea-orm-codegen 0.11.3
|
||||
|
||||
use super::sea_orm_active_enums::AntennaSrcEnum;
|
||||
use super::{newtype, sea_orm_active_enums::AntennaSrcEnum};
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||
|
@ -17,7 +17,7 @@ pub struct Model {
|
|||
#[sea_orm(column_name = "userListId")]
|
||||
pub user_list_id: Option<String>,
|
||||
#[sea_orm(column_type = "JsonBinary")]
|
||||
pub keywords: Json,
|
||||
pub keywords: newtype::Keyword,
|
||||
#[sea_orm(column_name = "withFile")]
|
||||
pub with_file: bool,
|
||||
pub expression: Option<String>,
|
||||
|
@ -28,11 +28,11 @@ pub struct Model {
|
|||
pub with_replies: bool,
|
||||
#[sea_orm(column_name = "userGroupJoiningId")]
|
||||
pub user_group_joining_id: Option<String>,
|
||||
pub users: Vec<String>,
|
||||
pub users: newtype::StringVec,
|
||||
#[sea_orm(column_name = "excludeKeywords", column_type = "JsonBinary")]
|
||||
pub exclude_keywords: Json,
|
||||
pub exclude_keywords: newtype::Keyword,
|
||||
#[sea_orm(column_type = "JsonBinary")]
|
||||
pub instances: Json,
|
||||
pub instances: newtype::StringVec,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
|
|
|
@ -33,6 +33,7 @@ pub mod migrations;
|
|||
pub mod moderation_log;
|
||||
pub mod muted_note;
|
||||
pub mod muting;
|
||||
pub mod newtype;
|
||||
pub mod note;
|
||||
pub mod note_edit;
|
||||
pub mod note_favorite;
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
#[macro_export]
|
||||
macro_rules! impl_json_newtype {
|
||||
($a:tt) => {
|
||||
impl From<$a> for Value {
|
||||
fn from(source: $a) -> Self {
|
||||
Value::Json(serde_json::to_value(source).ok().map(Box::new))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryGetable for $a {
|
||||
fn try_get_by<I: sea_orm::ColIdx>(
|
||||
res: &QueryResult,
|
||||
idx: I,
|
||||
) -> Result<Self, TryGetError> {
|
||||
let json_value: serde_json::Value =
|
||||
res.try_get_by(idx).map_err(TryGetError::DbErr)?;
|
||||
serde_json::from_value(json_value)
|
||||
.map_err(|e| TryGetError::DbErr(DbErr::Json(e.to_string())))
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_query::ValueType for $a {
|
||||
fn try_from(v: Value) -> Result<Self, sea_query::ValueTypeErr> {
|
||||
match v {
|
||||
Value::Json(Some(x)) => Ok($a(
|
||||
serde_json::from_value(*x).map_err(|_| sea_query::ValueTypeErr)?
|
||||
)),
|
||||
_ => Err(sea_query::ValueTypeErr),
|
||||
}
|
||||
}
|
||||
|
||||
fn type_name() -> String {
|
||||
stringify!($a).to_owned()
|
||||
}
|
||||
|
||||
fn array_type() -> sea_orm::sea_query::ArrayType {
|
||||
sea_orm::sea_query::ArrayType::Json
|
||||
}
|
||||
|
||||
fn column_type() -> sea_query::ColumnType {
|
||||
sea_query::ColumnType::Json
|
||||
}
|
||||
}
|
||||
|
||||
impl sea_query::Nullable for $a {
|
||||
fn null() -> Value {
|
||||
Value::Json(None)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
mod macros;
|
||||
|
||||
use derive_more::From;
|
||||
use schemars::JsonSchema;
|
||||
use sea_orm::{sea_query, DbErr, QueryResult, TryGetError, TryGetable, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::impl_json_newtype;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, From)]
|
||||
pub struct Keyword(pub Vec<Vec<String>>);
|
||||
impl_json_newtype!(Keyword);
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema, From)]
|
||||
|
||||
pub struct StringVec(pub Vec<String>);
|
||||
impl_json_newtype!(StringVec);
|
|
@ -3,7 +3,7 @@ use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
|
|||
|
||||
use crate::entity::{antenna, antenna_note, user_group_joining};
|
||||
use crate::error::Error;
|
||||
use crate::schema::{antenna::Antenna, json_to_keyword, json_to_string_list};
|
||||
use crate::schema::antenna::Antenna;
|
||||
|
||||
use super::Repository;
|
||||
|
||||
|
@ -30,13 +30,13 @@ impl Repository<Antenna> for antenna::Model {
|
|||
id: self.id,
|
||||
created_at: self.created_at.into(),
|
||||
name: self.name,
|
||||
keywords: json_to_keyword(&self.keywords),
|
||||
exclude_keywords: json_to_keyword(&self.exclude_keywords),
|
||||
keywords: self.keywords,
|
||||
exclude_keywords: self.exclude_keywords,
|
||||
src: self.src.try_into()?,
|
||||
user_list_id: self.user_list_id,
|
||||
user_group_id,
|
||||
users: self.users,
|
||||
instances: json_to_string_list(&self.instances),
|
||||
instances: self.instances,
|
||||
case_sensitive: self.case_sensitive,
|
||||
notify: self.notify,
|
||||
with_replies: self.with_replies,
|
||||
|
|
|
@ -4,8 +4,8 @@ use parse_display::FromStr;
|
|||
use schemars::JsonSchema;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use super::{Keyword, Schema, StringList};
|
||||
use crate::entity::sea_orm_active_enums::AntennaSrcEnum;
|
||||
use super::Schema;
|
||||
use crate::entity::{newtype, sea_orm_active_enums::AntennaSrcEnum};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, JsonSchema, ToSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
@ -13,14 +13,14 @@ pub struct Antenna {
|
|||
pub id: String,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
pub name: String,
|
||||
pub keywords: Keyword,
|
||||
pub exclude_keywords: Keyword,
|
||||
pub keywords: newtype::Keyword,
|
||||
pub exclude_keywords: newtype::Keyword,
|
||||
#[schema(inline)]
|
||||
pub src: AntennaSrc,
|
||||
pub user_list_id: Option<String>,
|
||||
pub user_group_id: Option<String>,
|
||||
pub users: StringList,
|
||||
pub instances: StringList,
|
||||
pub users: newtype::StringVec,
|
||||
pub instances: newtype::StringVec,
|
||||
#[serde(default)]
|
||||
pub case_sensitive: bool,
|
||||
#[serde(default)]
|
||||
|
|
|
@ -3,10 +3,6 @@ pub mod app;
|
|||
|
||||
use jsonschema::JSONSchema;
|
||||
use schemars::{schema_for, JsonSchema};
|
||||
use serde_json::Value;
|
||||
|
||||
type Keyword = Vec<Vec<String>>;
|
||||
type StringList = Vec<String>;
|
||||
|
||||
/// Structs of schema defitions implement this trait in order to
|
||||
/// provide the JSON Schema validator [`jsonschema::JSONSchema`].
|
||||
|
@ -23,29 +19,3 @@ trait Schema<T: JsonSchema> {
|
|||
.expect("Unable to compile schema")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn json_to_keyword(value: &Value) -> Keyword {
|
||||
match value.as_array() {
|
||||
None => vec![vec![]],
|
||||
Some(or_vec) => or_vec
|
||||
.iter()
|
||||
.map(|and_val| match and_val.as_array() {
|
||||
None => vec![],
|
||||
Some(and_vec) => and_vec
|
||||
.iter()
|
||||
.map(|word| word.as_str().unwrap_or_default().to_string())
|
||||
.collect(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn json_to_string_list(value: &Value) -> StringList {
|
||||
match value.as_array() {
|
||||
None => vec![],
|
||||
Some(v) => v
|
||||
.iter()
|
||||
.map(|s| s.as_str().unwrap_or_default().to_string())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use model::entity::{antenna, sea_orm_active_enums::AntennaSrcEnum, user};
|
|||
use sea_orm::{
|
||||
ActiveModelTrait, ActiveValue::Set, DatabaseConnection, DbErr, EntityTrait, TransactionTrait,
|
||||
};
|
||||
use serde_json::json;
|
||||
use std::env;
|
||||
use util::{
|
||||
id::{create_id, init_id},
|
||||
|
@ -64,8 +63,16 @@ async fn setup_model(db: &DatabaseConnection) {
|
|||
user_id: Set(user_id.to_owned()),
|
||||
name: Set("Test Antenna".to_string()),
|
||||
src: Set(AntennaSrcEnum::All),
|
||||
keywords: Set(json!([["foo", "bar"], ["foobar"]])),
|
||||
exclude_keywords: Set(json!([["abc"], ["def", "ghi"]])),
|
||||
keywords: Set(vec![
|
||||
vec!["foo".to_string(), "bar".to_string()],
|
||||
vec!["foobar".to_string()],
|
||||
]
|
||||
.into()),
|
||||
exclude_keywords: Set(vec![
|
||||
vec!["abc".to_string()],
|
||||
vec!["def".to_string(), "ghi".to_string()],
|
||||
]
|
||||
.into()),
|
||||
with_file: Set(false),
|
||||
notify: Set(true),
|
||||
case_sensitive: Set(true),
|
||||
|
|
|
@ -38,16 +38,18 @@ mod it_test {
|
|||
keywords: vec![
|
||||
vec!["foo".to_string(), "bar".to_string()],
|
||||
vec!["foobar".to_string()]
|
||||
],
|
||||
]
|
||||
.into(),
|
||||
exclude_keywords: vec![
|
||||
vec!["abc".to_string()],
|
||||
vec!["def".to_string(), "ghi".to_string()]
|
||||
],
|
||||
]
|
||||
.into(),
|
||||
src: schema::antenna::AntennaSrc::All,
|
||||
user_list_id: None,
|
||||
user_group_id: None,
|
||||
users: vec![],
|
||||
instances: vec![],
|
||||
users: vec![].into(),
|
||||
instances: vec![].into(),
|
||||
case_sensitive: true,
|
||||
notify: true,
|
||||
with_replies: false,
|
||||
|
|
Loading…
Reference in a new issue