1pub mod table;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7#[derive(Debug, Serialize, Deserialize, Default)]
8pub struct SearchRecordsResponse {
9 pub items: Vec<Record>,
10 pub page_token: Option<String>,
11 pub has_more: bool,
12 pub total: i32,
13}
14
15#[derive(Debug, Serialize, Deserialize)]
16pub struct Record {
17 pub record_id: String,
18 pub fields: HashMap<String, Value>,
19 #[serde(default)]
20 pub created_by: Option<UserId>,
21 #[serde(default)]
22 pub created_time: Option<i64>,
23 #[serde(default)]
24 pub last_modified_by: Option<UserId>,
25 #[serde(default)]
26 pub last_modified_time: Option<i64>,
27}
28
29#[derive(Debug, Serialize, Deserialize)]
30pub struct UserId {
31 pub user_id: Option<String>,
32 pub open_id: Option<String>,
33 pub union_id: Option<String>,
34}
35
36#[derive(Debug, Serialize, Deserialize, Default)]
37pub struct SearchRecordsCond {
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub filter: Option<Filter>,
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub sort: Option<Vec<Sort>>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub field_names: Option<Vec<String>>,
44 pub view_id: String,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub automatic_fields: Option<bool>,
47}
48
49#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
51#[serde(rename_all = "lowercase")]
52pub enum FilterConjunction {
53 And,
54 Or,
55}
56
57impl Default for FilterConjunction {
58 fn default() -> Self {
59 FilterConjunction::And
60 }
61}
62
63#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
65#[serde(rename_all = "camelCase")]
66pub enum FilterOperator {
67 Is,
68 IsNot,
69 Contains,
70 DoesNotContain,
71 IsEmpty,
72 IsNotEmpty,
73 IsGreater,
74 IsGreaterEqual,
75 IsLess,
76 IsLessEqual,
77}
78
79#[derive(Debug, Serialize, Deserialize)]
80pub struct Filter {
81 pub conditions: Vec<FilterCondition>,
82 #[serde(default)]
83 pub conjunction: FilterConjunction,
84}
85
86#[derive(Debug, Serialize, Deserialize)]
87pub struct FilterCondition {
88 pub field_name: String,
89 pub operator: FilterOperator,
90 pub value: Vec<String>,
91}
92
93#[derive(Debug, Serialize, Deserialize)]
94pub struct Sort {
95 pub field_name: String,
96 #[serde(default)]
97 pub desc: bool,
98}
99
100#[derive(Debug, Serialize, Deserialize)]
101pub struct SortKey {
102 pub field_name: String,
103 #[serde(rename = "order")]
104 pub sort_order: SortOrder,
105}
106
107#[derive(Debug, Serialize, Deserialize)]
108#[serde(rename_all = "UPPERCASE")]
109pub enum SortOrder {
110 Asc,
111 Desc,
112}
113
114#[derive(Debug, Serialize, Deserialize)]
115pub struct BatchCreateRecordsRequest {
116 pub records: Vec<RecordCreate>,
117}
118
119impl From<Value> for BatchCreateRecordsRequest {
120 fn from(value: Value) -> Self {
121 match value {
122 Value::Array(array) => {
123 let records = array
124 .iter()
125 .filter_map(|item| {
126 item.as_object().map(|obj| RecordCreate {
127 fields: obj.clone().into_iter().collect(),
128 })
129 })
130 .collect();
131 Self { records }
132 }
133 _ => Self { records: vec![] },
134 }
135 }
136}
137
138#[derive(Debug, Serialize, Deserialize)]
139pub struct RecordCreate {
140 pub fields: HashMap<String, Value>,
141}
142
143#[derive(Debug, Serialize, Deserialize, Default)]
144pub struct FieldsListResponse {
145 pub items: Vec<Field>,
146 #[serde(default)]
147 pub page_token: String,
148 #[serde(default)]
149 pub has_more: bool,
150 #[serde(default)]
151 pub total: i32,
152}
153
154#[derive(Debug, Serialize, Deserialize)]
155pub struct Field {
156 pub field_name: String,
157 pub field_id: String,
158 #[serde(rename = "type")]
159 pub field_type: i32,
160 #[serde(default)]
161 pub property: Value,
162 #[serde(rename = "ui_type", default)]
163 pub ui_type: Option<String>,
164 #[serde(default)]
165 pub description: Option<String>,
166 #[serde(default)]
167 pub is_primary: Option<bool>,
168}
169
170#[derive(Debug, Serialize, Deserialize)]
171pub struct FieldInfo {
172 pub field_name: String, pub description: Option<String>, pub is_primary: Option<bool>, pub ui_type: Option<String>, pub write_type: Option<String>, }
178
179impl From<FieldsListResponse> for Vec<FieldInfo> {
180 fn from(response: FieldsListResponse) -> Self {
181 response
182 .items
183 .into_iter()
184 .map(|field| {
185 let write_type = match field.ui_type.as_deref() {
186 Some("Text") => Some("String".to_string()),
187 Some("SingleSelect") => Some("String".to_string()),
188 Some("DateTime") => Some("Timestamp".to_string()),
189 Some("MultiSelect") => Some("Array<String>".to_string()),
190 _ => Some("String".to_string()),
191 };
192
193 FieldInfo {
194 field_name: field.field_name,
195 description: field.description,
196 is_primary: field.is_primary,
197 ui_type: field.ui_type,
198 write_type,
199 }
200 })
201 .collect()
202 }
203}