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