1use std::fmt::Debug;
2
3pub use scalar_derive::{doc_enum, Document, EditorField, Enum};
4use serde::{Deserialize, Serialize};
5use ts_rs::TS;
6
7pub use chrono::{DateTime, NaiveDate, Utc};
8pub use nanoid::nanoid;
9#[cfg(feature = "rgb")]
10pub use rgb::RGBA8;
11#[cfg(feature = "url")]
12pub use url::Url;
13
14pub use db::DatabaseConnection;
15
16pub mod db;
17pub mod editor_field;
18pub mod editor_type;
19pub mod types;
20pub mod validations;
21
22pub use serde_json;
23
24pub use editor_field::EditorField;
25pub use editor_type::EditorType;
26use validations::Validate;
27
28pub use scalar_expr as expr;
29
30use crate::db::{ContentActions, ValidationContext};
31
32#[derive(Serialize, TS)]
33#[ts(export)]
34pub struct Schema {
35 identifier: &'static str,
36 title: &'static str,
37 singleton: bool,
38 label: Option<&'static str>,
39 sub_label: Option<&'static str>,
40 fields: &'static [EditorField],
41}
42
43#[derive(Serialize, TS)]
44#[ts(export)]
45pub struct DocInfo {
46 pub identifier: &'static str,
47 pub title: &'static str,
48}
49
50pub trait Document: Validate + Debug {
51 const IDENTIFIER: &'static str;
52 const TITLE: &'static str;
53 const LABEL: Option<&'static str>;
54 const SUB_LABEL: Option<&'static str>;
55 const SINGLETON: bool;
56
57 fn fields() -> &'static [EditorField];
58 #[must_use]
59 fn schema() -> Schema {
60 Schema {
61 identifier: Self::IDENTIFIER,
62 title: Self::TITLE,
63 label: Self::LABEL,
64 sub_label: Self::SUB_LABEL,
65 singleton: Self::SINGLETON,
66 fields: Self::fields(),
67 }
68 }
69}
70
71#[derive(Serialize, Deserialize, Debug, TS)]
72#[ts(export, concrete(D = String))]
73pub struct Item<D> {
74 #[serde(rename = "__sc_id")]
75 pub id: String,
76 #[serde(rename = "__sc_created_at")]
77 pub created_at: DateTime<Utc>,
78 #[serde(rename = "__sc_modified_at")]
79 pub modified_at: DateTime<Utc>,
80 #[serde(rename = "__sc_published_at")]
81 pub published_at: Option<DateTime<Utc>>,
82 #[serde(rename = "content")]
83 #[ts(type = "any")]
84 pub inner: D,
85}
86
87impl<D: Document + Send + Sync> Validate for Item<D> {
88 async fn validate<DB: DatabaseConnection + ContentActions<DD> + Sync, DD: Document + Sync>(
89 &self,
90 ctx: ValidationContext<'_, DB, DD>,
91 ) -> Result<(), validations::ValidationError> {
92 self.inner.validate(ctx).await
93 }
94}