1use serde::{Deserialize, Deserializer, Serialize};
4
5#[derive(Clone, Debug, Serialize, Deserialize)]
6pub struct SchemaConfig {
7 pub id: String,
8 pub name: String,
9 #[serde(default)]
10 pub comment: Option<String>,
11}
12
13#[derive(Clone, Debug, Serialize, Deserialize)]
14pub struct EnumConfig {
15 pub id: String,
16 #[serde(default)]
17 pub schema_id: Option<String>,
18 pub name: String,
19 pub values: Vec<String>,
20 #[serde(default)]
21 pub comment: Option<String>,
22}
23
24#[derive(Clone, Debug, Serialize, Deserialize)]
25pub struct TableCheck {
26 pub name: String,
27 pub expression: String,
28}
29
30#[derive(Clone, Debug, Serialize, Deserialize)]
31#[serde(untagged)]
32pub enum PrimaryKeyConfig {
33 Single(String),
34 Composite(Vec<String>),
35}
36
37#[derive(Clone, Debug, Serialize, Deserialize)]
38pub struct TableConfig {
39 pub id: String,
40 #[serde(default)]
41 pub schema_id: Option<String>,
42 pub name: String,
43 #[serde(default)]
44 pub comment: Option<String>,
45 pub primary_key: PrimaryKeyConfig,
46 #[serde(default)]
47 pub unique: Vec<Vec<String>>,
48 #[serde(default)]
49 pub check: Vec<TableCheck>,
50 #[serde(default)]
53 pub audit_log: bool,
54 #[serde(default)]
57 pub versioning: Option<VersioningConfig>,
58 #[serde(default)]
64 pub global: bool,
65}
66
67#[derive(Clone, Debug, Serialize, Deserialize)]
69pub struct VersioningConfig {
70 pub enabled: bool,
71 #[serde(default)]
74 pub keep_versions: Option<i64>,
75}
76
77#[derive(Clone, Debug, Serialize, Deserialize)]
78#[serde(untagged)]
79pub enum ColumnTypeConfig {
80 Simple(String),
81 Parameterized {
82 name: String,
83 params: Option<Vec<u32>>,
84 },
85}
86
87#[derive(Clone, Debug, Serialize)]
88pub enum ColumnDefaultConfig {
89 Literal(String),
90 Expression { expression: String },
91}
92
93impl<'de> Deserialize<'de> for ColumnDefaultConfig {
94 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
95 where
96 D: Deserializer<'de>,
97 {
98 let v = serde_json::Value::deserialize(deserializer)?;
99 match v {
100 serde_json::Value::String(s) => Ok(ColumnDefaultConfig::Literal(s)),
101 serde_json::Value::Object(mut obj) => {
102 if let Some(serde_json::Value::String(s)) = obj.remove("expression") {
103 return Ok(ColumnDefaultConfig::Expression { expression: s });
104 }
105 if let Some(serde_json::Value::String(s)) = obj.remove("value").or_else(|| obj.remove("literal")) {
106 return Ok(ColumnDefaultConfig::Literal(s));
107 }
108 Err(serde::de::Error::custom(format!(
109 "column default must be a string, {{ \"expression\": \"...\" }}, or {{ \"value\": \"...\" }}; got object with keys: {:?}",
110 obj.keys().collect::<Vec<_>>()
111 )))
112 }
113 serde_json::Value::Bool(b) => Ok(ColumnDefaultConfig::Literal(b.to_string())),
114 serde_json::Value::Number(n) => Ok(ColumnDefaultConfig::Literal(n.to_string())),
115 other => Err(serde::de::Error::custom(format!(
116 "column default must be a string, boolean, number, or {{ \"expression\": \"...\" }}; got {}",
117 type_name_of_json(&other)
118 ))),
119 }
120 }
121}
122
123fn type_name_of_json(v: &serde_json::Value) -> &'static str {
124 match v {
125 serde_json::Value::Null => "null",
126 serde_json::Value::Bool(_) => "boolean",
127 serde_json::Value::Number(_) => "number",
128 serde_json::Value::String(_) => "string",
129 serde_json::Value::Array(_) => "array",
130 serde_json::Value::Object(_) => "object",
131 }
132}
133
134#[derive(Clone, Debug, Serialize, Deserialize)]
135pub struct ColumnConfig {
136 pub id: String,
137 pub table_id: String,
138 pub name: String,
139 #[serde(rename = "type")]
140 pub type_: ColumnTypeConfig,
141 #[serde(default = "default_true")]
142 pub nullable: bool,
143 #[serde(default)]
144 pub default: Option<ColumnDefaultConfig>,
145 #[serde(default)]
146 pub comment: Option<String>,
147 #[serde(default)]
148 pub asset: Option<AssetColumnConfig>,
149 #[serde(default)]
154 pub extensible: bool,
155}
156
157fn default_true() -> bool {
158 true
159}
160
161#[derive(Clone, Debug, Serialize, Deserialize)]
162#[serde(untagged)]
163pub enum IndexColumnEntry {
164 Name(String),
165 Spec {
166 name: String,
167 direction: Option<String>,
168 nulls: Option<String>,
169 },
170 Expression {
171 expression: String,
172 },
173}
174
175#[derive(Clone, Debug, Serialize, Deserialize)]
176pub struct IndexConfig {
177 pub id: String,
178 #[serde(default)]
179 pub schema_id: Option<String>,
180 pub table_id: String,
181 pub name: String,
182 #[serde(default)]
183 pub method: Option<String>,
184 #[serde(default)]
185 pub unique: bool,
186 pub columns: Vec<IndexColumnEntry>,
187 #[serde(default)]
188 pub include: Vec<String>,
189 #[serde(default, rename = "where")]
190 pub where_: Option<String>,
191 #[serde(default)]
192 pub comment: Option<String>,
193}
194
195impl IndexConfig {
196 pub fn where_clause(&self) -> Option<&str> {
197 self.where_.as_deref()
198 }
199}
200
201#[derive(Clone, Debug, Serialize, Deserialize)]
202pub struct RelationshipConfig {
203 pub id: String,
204 #[serde(default)]
206 pub from_schema_id: Option<String>,
207 pub from_table_id: String,
208 pub from_column_id: String,
209 #[serde(default)]
212 pub to_package_id: Option<String>,
213 #[serde(default)]
216 pub to_schema_id: Option<String>,
217 pub to_table_id: String,
218 pub to_column_id: String,
219 #[serde(default)]
220 pub on_update: Option<String>,
221 #[serde(default)]
222 pub on_delete: Option<String>,
223 #[serde(default)]
224 pub name: Option<String>,
225}
226
227#[derive(Clone, Debug, Default, Serialize, Deserialize)]
228pub struct ValidationRule {
229 #[serde(default)]
230 pub required: Option<bool>,
231 #[serde(default)]
232 pub format: Option<String>,
233 #[serde(default)]
234 pub max_length: Option<u32>,
235 #[serde(default)]
236 pub min_length: Option<u32>,
237 #[serde(default)]
238 pub pattern: Option<String>,
239 #[serde(default)]
240 pub allowed: Option<Vec<serde_json::Value>>,
241 #[serde(default)]
242 pub minimum: Option<f64>,
243 #[serde(default)]
244 pub maximum: Option<f64>,
245 #[serde(default)]
247 pub allowed_mime_types: Option<Vec<String>>,
248 #[serde(default)]
249 pub allowed_extensions: Option<Vec<String>>,
250 #[serde(default)]
251 pub max_size_mb: Option<f64>,
252 #[serde(default)]
253 pub min_size_kb: Option<f64>,
254 #[serde(default)]
255 pub max_filename_length: Option<u32>,
256}
257
258#[derive(Clone, Debug, Serialize, Deserialize)]
259pub struct AssetColumnConfig {
260 #[serde(default)]
262 pub prefix: Option<String>,
263 #[serde(default)]
265 pub compression: Option<String>,
266}
267
268#[derive(Clone, Debug, Serialize, Deserialize)]
269pub struct EventCondition {
270 pub field: String,
272 #[serde(default)]
274 pub changed_to: Option<serde_json::Value>,
275 #[serde(default)]
277 pub equals: Option<serde_json::Value>,
278 #[serde(default)]
280 pub not_null: Option<bool>,
281}
282
283#[derive(Clone, Debug, Serialize, Deserialize)]
284pub struct EntityEventTrigger {
285 pub id: String,
286 pub on: String,
288 #[serde(default)]
291 pub event_name: Option<String>,
292 #[serde(default)]
294 pub condition: Option<EventCondition>,
295}
296
297#[derive(Clone, Debug, Serialize, Deserialize)]
300pub struct McpEntityConfig {
301 #[serde(default)]
303 pub enabled: bool,
304 #[serde(default)]
308 pub operations: Vec<String>,
309 #[serde(default)]
311 pub tool_prefix: Option<String>,
312 #[serde(default)]
314 pub description: Option<String>,
315}
316
317#[derive(Clone, Debug, Serialize, Deserialize)]
318pub struct ApiEntityConfig {
319 pub entity_id: String,
320 pub path_segment: String,
321 pub operations: Vec<String>,
322 #[serde(default)]
324 pub sensitive_columns: Vec<String>,
325 #[serde(default)]
326 pub validation: std::collections::HashMap<String, ValidationRule>,
327 #[serde(default)]
329 pub archive_field: Option<String>,
330 #[serde(default)]
332 pub events: Vec<EntityEventTrigger>,
333 #[serde(default)]
338 pub parent_ref_column: Option<String>,
339 #[serde(default)]
341 pub mcp: Option<McpEntityConfig>,
342}
343
344#[derive(Clone, Debug, Serialize, Deserialize)]
345pub struct KvStoreConfig {
346 pub id: String,
347 pub namespace: String,
348 #[serde(default)]
349 pub comment: Option<String>,
350}
351
352#[derive(Clone, Debug, Default)]
354pub struct FullConfig {
355 pub schemas: Vec<SchemaConfig>,
356 pub enums: Vec<EnumConfig>,
357 pub tables: Vec<TableConfig>,
358 pub columns: Vec<ColumnConfig>,
359 pub indexes: Vec<IndexConfig>,
360 pub relationships: Vec<RelationshipConfig>,
361 pub api_entities: Vec<ApiEntityConfig>,
362 pub kv_stores: Vec<KvStoreConfig>,
363}