1use crate::FieldType;
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11#[serde(deny_unknown_fields)]
12pub struct FieldSchema {
13 #[serde(rename = "type")]
15 pub field_type: FieldType,
16
17 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
19 pub primary: bool,
20
21 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
23 pub generated: bool,
24
25 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
27 pub required: bool,
28
29 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
31 pub unique: bool,
32
33 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
35 pub nullable: bool,
36
37 #[serde(default, skip_serializing_if = "Option::is_none", rename = "ref")]
39 pub reference: Option<String>,
40
41 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub min: Option<serde_json::Value>,
44
45 #[serde(default, skip_serializing_if = "Option::is_none")]
47 pub max: Option<serde_json::Value>,
48
49 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub format: Option<String>,
52
53 #[serde(default, skip_serializing_if = "Option::is_none")]
55 pub values: Option<Vec<String>>,
56
57 #[serde(default, skip_serializing_if = "Option::is_none")]
59 pub default: Option<serde_json::Value>,
60
61 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
63 pub sensitive: bool,
64
65 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
67 pub search: bool,
68
69 #[serde(default, skip_serializing_if = "Option::is_none")]
71 pub items: Option<String>,
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn field_schema_minimal() {
80 let json = r#"{"type": "string"}"#;
81 let fs: FieldSchema = serde_json::from_str(json).unwrap();
82 assert_eq!(fs.field_type, FieldType::String);
83 assert!(!fs.primary);
84 assert!(!fs.generated);
85 assert!(!fs.required);
86 assert!(!fs.unique);
87 assert!(!fs.nullable);
88 assert!(fs.reference.is_none());
89 assert!(fs.min.is_none());
90 assert!(fs.max.is_none());
91 assert!(fs.format.is_none());
92 assert!(fs.values.is_none());
93 assert!(fs.default.is_none());
94 assert!(!fs.sensitive);
95 assert!(!fs.search);
96 assert!(fs.items.is_none());
97 }
98
99 #[test]
100 fn field_schema_full() {
101 let json = r#"{
102 "type": "enum",
103 "primary": false,
104 "generated": false,
105 "required": true,
106 "unique": false,
107 "nullable": false,
108 "values": ["admin", "member", "viewer"],
109 "default": "member"
110 }"#;
111 let fs: FieldSchema = serde_json::from_str(json).unwrap();
112 assert_eq!(fs.field_type, FieldType::Enum);
113 assert!(fs.required);
114 assert_eq!(fs.values.as_ref().unwrap().len(), 3);
115 assert_eq!(fs.default.as_ref().unwrap(), "member");
116 }
117
118 #[test]
119 fn field_schema_with_ref() {
120 let json = r#"{"type": "uuid", "ref": "organizations.id", "required": true}"#;
121 let fs: FieldSchema = serde_json::from_str(json).unwrap();
122 assert_eq!(fs.reference.as_deref(), Some("organizations.id"));
123 }
124
125 #[test]
126 fn field_schema_serde_roundtrip() {
127 let fs = FieldSchema {
128 field_type: FieldType::String,
129 primary: false,
130 generated: false,
131 required: true,
132 unique: true,
133 nullable: false,
134 reference: None,
135 min: Some(serde_json::json!(1)),
136 max: Some(serde_json::json!(200)),
137 format: Some("email".to_string()),
138 values: None,
139 default: None,
140 sensitive: false,
141 search: true,
142 items: None,
143 };
144 let json = serde_json::to_string(&fs).unwrap();
145 let back: FieldSchema = serde_json::from_str(&json).unwrap();
146 assert_eq!(fs, back);
147 }
148}