rust_store_core/schema/
definition.rs1use std::collections::HashMap;
4
5use serde_json::{Map, Value};
6
7use crate::types::{is_truthy, str_list};
8
9#[derive(Debug, Clone)]
10pub struct FieldDef {
11 pub field_type: String,
12 pub required: bool,
13 pub default: Option<Value>,
14 pub read: Option<Vec<String>>,
15 pub write: Option<Vec<String>>,
16 pub fields: Option<Value>,
18}
19
20#[derive(Debug, Clone)]
21pub struct RelationDef {
22 pub model: String,
23 pub rel_type: String,
24 pub local_field: String,
25 pub foreign_field: String,
26 pub read: Option<Vec<String>>,
27}
28
29#[derive(Debug, Clone)]
30pub struct ComputeDef {
31 pub comp_type: String,
32 pub has_fn: bool,
33 pub has_async_fn: bool,
34 pub fn_ref: Option<String>,
36 pub agg: Option<Value>,
39 pub depends: Vec<String>,
40 pub read: Option<Vec<String>>,
41}
42
43#[derive(Debug, Clone)]
44pub struct Schema {
45 pub name: String,
46 pub collection: String,
47 pub id_prefix: String,
48 pub timestamps: bool,
49 pub fields: HashMap<String, FieldDef>,
50 pub relations: HashMap<String, RelationDef>,
51 pub computes: Vec<(String, ComputeDef)>,
53 pub read: Option<Vec<String>>,
54 pub write: Option<Vec<String>>,
55 pub indexes: Vec<Value>,
57 pub datasource: Option<String>,
59 pub namespace: Option<String>,
63}
64
65impl Schema {
66 pub fn compute(&self, name: &str) -> Option<&ComputeDef> {
67 self.computes
68 .iter()
69 .find(|(k, _)| k == name)
70 .map(|(_, c)| c)
71 }
72
73 pub fn source(&self) -> &str {
75 self.datasource
76 .as_deref()
77 .unwrap_or(crate::datasource::DEFAULT_SOURCE)
78 }
79
80 pub fn ns(&self) -> Option<&str> {
82 self.namespace.as_deref().filter(|s| !s.is_empty())
83 }
84}
85
86pub(super) fn normalize_fields(v: Option<&Value>) -> Result<HashMap<String, FieldDef>, String> {
88 let mut out = HashMap::new();
89 let Some(Value::Object(map)) = v else {
90 return Ok(out);
91 };
92 for (key, val) in map {
93 let fd = if let Some(s) = val.as_str() {
94 FieldDef {
95 field_type: s.to_string(),
96 required: false,
97 default: None,
98 read: None,
99 write: None,
100 fields: None,
101 }
102 } else if let Some(o) = val.as_object() {
103 FieldDef {
104 field_type: o
105 .get("type")
106 .and_then(|v| v.as_str())
107 .unwrap_or("")
108 .to_string(),
109 required: o.get("required").and_then(|v| v.as_bool()).unwrap_or(false),
110 default: o.get("default").filter(|v| !v.is_null()).cloned(),
111 read: str_list(o.get("read")),
112 write: str_list(o.get("write")),
113 fields: o.get("fields").filter(|v| is_truthy(v)).cloned(),
114 }
115 } else {
116 return Err(format!("字段 {} 定义类型非法(须为类型字符串或对象)", key));
120 };
121 out.insert(key.clone(), fd);
122 }
123 Ok(out)
124}
125
126pub fn map_of(pairs: Vec<(&str, Value)>) -> Map<String, Value> {
128 let mut m = Map::new();
129 for (k, v) in pairs {
130 m.insert(k.to_string(), v);
131 }
132 m
133}