Skip to main content

cratestack_core/
schema.rs

1//! Schema IR — the parsed shape of a `.cstack` file. Every IR node
2//! carries source-span back-pointers so consumers can map errors to
3//! positions in the original text.
4
5pub mod model;
6pub mod procedure;
7pub mod selection;
8pub mod view;
9
10use serde::{Deserialize, Serialize};
11
12pub use model::{
13    Attribute, EnumDecl, EnumVariant, Field, MixinDecl, Model, TypeArity, TypeDecl, TypeRef,
14};
15pub use procedure::{Procedure, ProcedureArg, ProcedureKind};
16pub use selection::SelectionQuery;
17pub use view::{View, ViewSource};
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
20pub struct SourceSpan {
21    pub start: usize,
22    pub end: usize,
23    pub line: usize,
24}
25
26/// Wire-shape the schema generates for. Picked once per schema (via
27/// the top-level `transport rest|rpc` directive) so generated servers
28/// and clients only carry one binding's worth of surface.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
30#[serde(rename_all = "lowercase")]
31pub enum TransportStyle {
32    #[default]
33    Rest,
34    Rpc,
35}
36
37impl TransportStyle {
38    pub const fn as_str(&self) -> &'static str {
39        match self {
40            TransportStyle::Rest => "rest",
41            TransportStyle::Rpc => "rpc",
42        }
43    }
44}
45
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47pub struct Schema {
48    pub datasource: Option<Datasource>,
49    pub auth: Option<AuthBlock>,
50    pub config_blocks: Vec<ConfigBlock>,
51    pub mixins: Vec<MixinDecl>,
52    pub models: Vec<Model>,
53    pub types: Vec<TypeDecl>,
54    pub enums: Vec<EnumDecl>,
55    pub procedures: Vec<Procedure>,
56    #[serde(default)]
57    pub views: Vec<View>,
58    #[serde(default)]
59    pub transport: TransportStyle,
60}
61
62impl Schema {
63    pub fn summary(&self) -> OwnedSchemaSummary {
64        OwnedSchemaSummary {
65            mixins: self.mixins.iter().map(|mixin| mixin.name.clone()).collect(),
66            models: self.models.iter().map(|model| model.name.clone()).collect(),
67            types: self.types.iter().map(|ty| ty.name.clone()).collect(),
68            enums: self
69                .enums
70                .iter()
71                .map(|enum_decl| enum_decl.name.clone())
72                .collect(),
73            procedures: self
74                .procedures
75                .iter()
76                .map(|procedure| procedure.name.clone())
77                .collect(),
78            views: self.views.iter().map(|view| view.name.clone()).collect(),
79        }
80    }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct SchemaSummary {
85    pub mixins: &'static [&'static str],
86    pub models: &'static [&'static str],
87    pub types: &'static [&'static str],
88    pub enums: &'static [&'static str],
89    pub procedures: &'static [&'static str],
90    pub views: &'static [&'static str],
91}
92
93#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94pub struct OwnedSchemaSummary {
95    pub mixins: Vec<String>,
96    pub models: Vec<String>,
97    pub types: Vec<String>,
98    pub enums: Vec<String>,
99    pub procedures: Vec<String>,
100    #[serde(default)]
101    pub views: Vec<String>,
102}
103
104#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
105pub struct Datasource {
106    pub docs: Vec<String>,
107    pub name: String,
108    pub entries: Vec<ConfigEntry>,
109    pub span: SourceSpan,
110}
111
112#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
113pub struct AuthBlock {
114    pub docs: Vec<String>,
115    pub name: String,
116    pub fields: Vec<Field>,
117    pub span: SourceSpan,
118}
119
120#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
121pub struct ConfigBlock {
122    pub docs: Vec<String>,
123    pub name: String,
124    pub entries: Vec<String>,
125    pub span: SourceSpan,
126}
127
128#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
129pub struct ConfigEntry {
130    pub key: String,
131    pub value: String,
132}