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)]
54 pub audit_log: bool,
55 #[serde(default)]
58 pub versioning: Option<VersioningConfig>,
59 #[serde(default)]
65 pub global: bool,
66}
67
68#[derive(Clone, Debug, Serialize, Deserialize)]
70pub struct VersioningConfig {
71 pub enabled: bool,
72 #[serde(default)]
75 pub keep_versions: Option<i64>,
76}
77
78#[derive(Clone, Debug, Serialize, Deserialize)]
79#[serde(untagged)]
80pub enum ColumnTypeConfig {
81 Simple(String),
82 Parameterized {
83 name: String,
84 params: Option<Vec<u32>>,
85 },
86}
87
88#[derive(Clone, Debug, Serialize)]
89pub enum ColumnDefaultConfig {
90 Literal(String),
91 Expression { expression: String },
92}
93
94impl<'de> Deserialize<'de> for ColumnDefaultConfig {
95 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
96 where
97 D: Deserializer<'de>,
98 {
99 let v = serde_json::Value::deserialize(deserializer)?;
100 match v {
101 serde_json::Value::String(s) => Ok(ColumnDefaultConfig::Literal(s)),
102 serde_json::Value::Object(mut obj) => {
103 if let Some(serde_json::Value::String(s)) = obj.remove("expression") {
104 return Ok(ColumnDefaultConfig::Expression { expression: s });
105 }
106 if let Some(serde_json::Value::String(s)) = obj.remove("value").or_else(|| obj.remove("literal")) {
107 return Ok(ColumnDefaultConfig::Literal(s));
108 }
109 Err(serde::de::Error::custom(format!(
110 "column default must be a string, {{ \"expression\": \"...\" }}, or {{ \"value\": \"...\" }}; got object with keys: {:?}",
111 obj.keys().collect::<Vec<_>>()
112 )))
113 }
114 serde_json::Value::Bool(b) => Ok(ColumnDefaultConfig::Literal(b.to_string())),
115 serde_json::Value::Number(n) => Ok(ColumnDefaultConfig::Literal(n.to_string())),
116 other => Err(serde::de::Error::custom(format!(
117 "column default must be a string, boolean, number, or {{ \"expression\": \"...\" }}; got {}",
118 type_name_of_json(&other)
119 ))),
120 }
121 }
122}
123
124fn type_name_of_json(v: &serde_json::Value) -> &'static str {
125 match v {
126 serde_json::Value::Null => "null",
127 serde_json::Value::Bool(_) => "boolean",
128 serde_json::Value::Number(_) => "number",
129 serde_json::Value::String(_) => "string",
130 serde_json::Value::Array(_) => "array",
131 serde_json::Value::Object(_) => "object",
132 }
133}
134
135#[derive(Clone, Debug, Serialize, Deserialize)]
136pub struct ColumnConfig {
137 pub id: String,
138 pub table_id: String,
139 pub name: String,
140 #[serde(rename = "type")]
141 pub type_: ColumnTypeConfig,
142 #[serde(default = "default_true")]
143 pub nullable: bool,
144 #[serde(default)]
145 pub default: Option<ColumnDefaultConfig>,
146 #[serde(default)]
147 pub comment: Option<String>,
148 #[serde(default)]
149 pub asset: Option<AssetColumnConfig>,
150 #[serde(default)]
155 pub extensible: bool,
156}
157
158fn default_true() -> bool {
159 true
160}
161
162#[derive(Clone, Debug, Serialize, Deserialize)]
163#[serde(untagged)]
164pub enum IndexColumnEntry {
165 Name(String),
166 Spec {
167 name: String,
168 direction: Option<String>,
169 nulls: Option<String>,
170 },
171 Expression {
172 expression: String,
173 },
174}
175
176#[derive(Clone, Debug, Serialize, Deserialize)]
177pub struct IndexConfig {
178 pub id: String,
179 #[serde(default)]
180 pub schema_id: Option<String>,
181 pub table_id: String,
182 pub name: String,
183 #[serde(default)]
184 pub method: Option<String>,
185 #[serde(default)]
186 pub unique: bool,
187 pub columns: Vec<IndexColumnEntry>,
188 #[serde(default)]
189 pub include: Vec<String>,
190 #[serde(default, rename = "where")]
191 pub where_: Option<String>,
192 #[serde(default)]
193 pub comment: Option<String>,
194}
195
196impl IndexConfig {
197 pub fn where_clause(&self) -> Option<&str> {
198 self.where_.as_deref()
199 }
200}
201
202#[derive(Clone, Debug, Serialize, Deserialize)]
203pub struct RelationshipConfig {
204 pub id: String,
205 #[serde(default)]
207 pub from_schema_id: Option<String>,
208 pub from_table_id: String,
209 pub from_column_id: String,
210 #[serde(default)]
213 pub to_package_id: Option<String>,
214 #[serde(default)]
217 pub to_schema_id: Option<String>,
218 pub to_table_id: String,
219 pub to_column_id: String,
220 #[serde(default)]
221 pub on_update: Option<String>,
222 #[serde(default)]
223 pub on_delete: Option<String>,
224 #[serde(default)]
225 pub name: Option<String>,
226}
227
228#[derive(Clone, Debug, Default, Serialize, Deserialize)]
229pub struct ValidationRule {
230 #[serde(default)]
231 pub required: Option<bool>,
232 #[serde(default)]
233 pub format: Option<String>,
234 #[serde(default)]
235 pub max_length: Option<u32>,
236 #[serde(default)]
237 pub min_length: Option<u32>,
238 #[serde(default)]
239 pub pattern: Option<String>,
240 #[serde(default)]
241 pub allowed: Option<Vec<serde_json::Value>>,
242 #[serde(default)]
243 pub minimum: Option<f64>,
244 #[serde(default)]
245 pub maximum: Option<f64>,
246 #[serde(default)]
248 pub allowed_mime_types: Option<Vec<String>>,
249 #[serde(default)]
250 pub allowed_extensions: Option<Vec<String>>,
251 #[serde(default)]
252 pub max_size_mb: Option<f64>,
253 #[serde(default)]
254 pub min_size_kb: Option<f64>,
255 #[serde(default)]
256 pub max_filename_length: Option<u32>,
257}
258
259#[derive(Clone, Debug, Serialize, Deserialize)]
260pub struct AssetColumnConfig {
261 #[serde(default)]
263 pub prefix: Option<String>,
264 #[serde(default)]
266 pub compression: Option<String>,
267}
268
269#[derive(Clone, Debug, Serialize, Deserialize)]
270pub struct EventCondition {
271 pub field: String,
273 #[serde(default)]
275 pub changed_to: Option<serde_json::Value>,
276 #[serde(default)]
278 pub equals: Option<serde_json::Value>,
279 #[serde(default)]
281 pub not_null: Option<bool>,
282}
283
284#[derive(Clone, Debug, Serialize, Deserialize)]
285pub struct EntityEventTrigger {
286 pub id: String,
287 pub on: String,
289 #[serde(default)]
292 pub event_name: Option<String>,
293 #[serde(default)]
295 pub condition: Option<EventCondition>,
296 #[serde(default)]
300 pub include: Vec<String>,
301}
302
303#[derive(Clone, Debug, Serialize, Deserialize)]
306pub struct McpEntityConfig {
307 #[serde(default)]
309 pub enabled: bool,
310 #[serde(default)]
314 pub operations: Vec<String>,
315 #[serde(default)]
317 pub tool_prefix: Option<String>,
318 #[serde(default)]
320 pub description: Option<String>,
321}
322
323#[derive(Clone, Debug, Serialize, Deserialize)]
324pub struct ApiEntityConfig {
325 pub entity_id: String,
326 pub path_segment: String,
327 pub operations: Vec<String>,
328 #[serde(default)]
330 pub sensitive_columns: Vec<String>,
331 #[serde(default)]
332 pub validation: std::collections::HashMap<String, ValidationRule>,
333 #[serde(default)]
335 pub archive_field: Option<String>,
336 #[serde(default)]
338 pub events: Vec<EntityEventTrigger>,
339 #[serde(default)]
344 pub parent_ref_column: Option<String>,
345 #[serde(default)]
347 pub mcp: Option<McpEntityConfig>,
348}
349
350#[derive(Clone, Debug, Serialize, Deserialize)]
351pub struct KvStoreConfig {
352 pub id: String,
353 pub namespace: String,
354 #[serde(default)]
355 pub comment: Option<String>,
356}
357
358#[derive(Clone, Debug, Serialize, Deserialize)]
362pub struct ReportParam {
363 pub name: String,
364 #[serde(default)]
366 pub default: Option<serde_json::Value>,
367 #[serde(default)]
370 pub db_type: Option<String>,
371 #[serde(flatten)]
372 pub rule: ValidationRule,
373}
374
375#[derive(Clone, Debug, Serialize, Deserialize)]
380pub struct ReportConfig {
381 pub id: String,
382 pub name: String,
383 #[serde(default)]
384 pub description: Option<String>,
385 #[serde(default)]
387 pub schemas: Vec<String>,
388 pub sql: String,
390 #[serde(default)]
391 pub params: Vec<ReportParam>,
392 #[serde(default)]
396 pub validate_on_register: Option<bool>,
397 #[serde(default)]
401 pub cache_ttl_secs: Option<i64>,
402}
403
404#[derive(Clone, Debug, Default)]
406pub struct FullConfig {
407 pub schemas: Vec<SchemaConfig>,
408 pub enums: Vec<EnumConfig>,
409 pub tables: Vec<TableConfig>,
410 pub columns: Vec<ColumnConfig>,
411 pub indexes: Vec<IndexConfig>,
412 pub relationships: Vec<RelationshipConfig>,
413 pub api_entities: Vec<ApiEntityConfig>,
414 pub kv_stores: Vec<KvStoreConfig>,
415 pub reports: Vec<ReportConfig>,
416}