Skip to main content

scalar_cms/
lib.rs

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}