firestore_sdk/
lib.rs

1mod query;
2
3use async_trait::async_trait;
4use std::collections::HashMap;
5
6pub use firestore_grpc;
7
8pub mod store_field;
9
10use firestore_grpc::v1::{
11    structured_query::{
12        filter::FilterType, FieldFilter, FieldReference, Filter as QueryFilter, Order,
13    },
14    value::ValueType,
15    Cursor, Document, Value as FsValue,
16};
17
18#[derive(Debug, Default)]
19pub struct State {
20    token: Option<String>,
21    project_id: String,
22    collection: String,
23    document: String,
24    where_field: Vec<QueryFilter>,
25    order_by: Vec<firestore_grpc::v1::structured_query::Order>,
26    start_at: Option<Cursor>,
27    end_at: Option<Cursor>,
28    // offset: i32,
29    limit: Option<i32>,
30}
31
32pub struct Direction;
33impl Direction {
34    pub const ASCENDING: i32 = 1;
35    pub const DESCENDING: i32 = 2;
36}
37
38pub struct Operator;
39impl Operator {
40    pub const LESS_THAN: i32 = 1;
41    pub const LESS_THAN_OR_EQUAL: i32 = 2;
42    pub const GREATER_THAN: i32 = 3;
43    pub const GREATER_THAN_OR_EQUAL: i32 = 4;
44    pub const EQUAL: i32 = 5;
45    pub const NOT_EQUAL: i32 = 6;
46    pub const ARRAY_CONTAINS: i32 = 7;
47    pub const IN: i32 = 8;
48    pub const ARRAY_CONTAINS_ANY: i32 = 9;
49    pub const NOT_IN: i32 = 10;
50}
51
52pub type BoxError = Box<dyn std::error::Error + Sync + Send + 'static>;
53
54#[async_trait]
55pub trait FireStore {
56    fn init(&mut self, project_id: &str, token: Option<&str>) -> &mut Self;
57    fn collection(&mut self, collection: &str) -> &mut Self;
58    fn document(&mut self, document: &str) -> &mut Self;
59    fn where_field(&mut self, field: &str, operator: i32, value: ValueType) -> &mut Self;
60    fn order_by(&mut self, field: &str, direction: i32) -> &mut Self;
61    fn start_at(&mut self, document: Document) -> &mut Self;
62    fn start_after(&mut self, document: Document) -> &mut Self;
63    fn end_before(&mut self, document: Document) -> &mut Self;
64    fn end_at(&mut self, document: Document) -> &mut Self;
65    // fn offset(&mut self, offset: i32) -> &mut Self;
66    fn limit(&mut self, limit: i32) -> &mut Self;
67    async fn get_document(&mut self) -> Result<Document, BoxError>;
68    async fn get_documents(&mut self) -> Result<Vec<Document>, BoxError>;
69    async fn set_document(
70        &mut self,
71        document_id: &str,
72        fields: HashMap<String, FsValue>,
73    ) -> Result<Document, BoxError>;
74    async fn add_document(
75        &mut self,
76        fields: HashMap<String, FsValue>,
77    ) -> Result<Document, BoxError>;
78    async fn delete(&mut self) -> Result<String, BoxError>;
79}
80
81#[async_trait]
82impl FireStore for State {
83    fn init(&mut self, project_id: &str, token: Option<&str>) -> &mut Self {
84        self.project_id = project_id.to_string();
85        self.token = match token {
86            Some(token) => Some(token.to_string()),
87            None => None,
88        };
89
90        self
91    }
92
93    fn collection(&mut self, collection: &str) -> &mut Self {
94        self.collection = collection.to_string();
95        self
96    }
97
98    fn document(&mut self, document: &str) -> &mut Self {
99        self.document = document.to_string();
100        self
101    }
102
103    fn where_field(&mut self, field: &str, operator: i32, value: ValueType) -> &mut Self {
104        let field_filter = FieldFilter {
105            field: Some(FieldReference {
106                field_path: field.to_string(),
107            }),
108            op: operator,
109            value: Some(FsValue {
110                value_type: Some(value),
111            }),
112        };
113
114        self.where_field.push(QueryFilter {
115            filter_type: Some(FilterType::FieldFilter(field_filter)),
116        });
117
118        self
119    }
120
121    fn order_by(&mut self, field: &str, direction: i32) -> &mut Self {
122        self.order_by.push(Order {
123            field: Some(FieldReference {
124                field_path: field.to_string(),
125            }),
126            direction,
127        });
128        self
129    }
130
131    fn start_at(&mut self, document: Document) -> &mut Self {
132        let mut cursor_values = Vec::new();
133
134        for order_by in self.order_by.clone() {
135            let field_path = order_by.field.unwrap().field_path;
136            cursor_values.push(document.fields.get(&field_path).unwrap().clone());
137        }
138
139        self.order_by.push(Order {
140            field: Some(FieldReference {
141                field_path: "__name__".to_string(),
142            }),
143            direction: Direction::ASCENDING,
144        });
145
146        cursor_values.push(store_field::Value::reference(document.name));
147
148        self.start_at = Some(Cursor {
149            values: cursor_values,
150            before: true,
151        });
152
153        self
154    }
155
156    fn start_after(&mut self, document: Document) -> &mut Self {
157        let mut cursor_values = Vec::new();
158
159        for order_by in self.order_by.clone() {
160            let field_path = order_by.field.unwrap().field_path;
161            cursor_values.push(document.fields.get(&field_path).unwrap().clone());
162        }
163
164        self.order_by.push(Order {
165            field: Some(FieldReference {
166                field_path: "__name__".to_string(),
167            }),
168            direction: Direction::ASCENDING,
169        });
170
171        cursor_values.push(store_field::Value::reference(document.name));
172
173        self.start_at = Some(Cursor {
174            values: cursor_values,
175            before: false,
176        });
177
178        self
179    }
180
181    fn end_before(&mut self, document: Document) -> &mut Self {
182        let mut cursor_values = Vec::new();
183
184        for order_by in self.order_by.clone() {
185            let field_path = order_by.field.unwrap().field_path;
186            cursor_values.push(document.fields.get(&field_path).unwrap().clone());
187        }
188
189        self.order_by.push(Order {
190            field: Some(FieldReference {
191                field_path: "__name__".to_string(),
192            }),
193            direction: Direction::ASCENDING,
194        });
195
196        cursor_values.push(store_field::Value::reference(document.name));
197
198        self.end_at = Some(Cursor {
199            values: cursor_values,
200            before: true,
201        });
202        self
203    }
204
205    fn end_at(&mut self, document: Document) -> &mut Self {
206        let mut cursor_values = Vec::new();
207
208        for order_by in self.order_by.clone() {
209            let field_path = order_by.field.unwrap().field_path;
210            cursor_values.push(document.fields.get(&field_path).unwrap().clone());
211        }
212
213        self.order_by.push(Order {
214            field: Some(FieldReference {
215                field_path: "__name__".to_string(),
216            }),
217            direction: Direction::ASCENDING,
218        });
219
220        cursor_values.push(store_field::Value::reference(document.name));
221
222        self.end_at = Some(Cursor {
223            values: cursor_values,
224            before: false,
225        });
226        self
227    }
228
229    // RPC not working
230    // fn offset(&mut self, offset: i32) -> &mut Self {
231    //     self.offset = offset;
232    //     self
233    // }
234
235    fn limit(&mut self, limit: i32) -> &mut Self {
236        self.limit = Some(limit);
237        self
238    }
239
240    async fn get_document(&mut self) -> Result<Document, BoxError> {
241        let res = query::get_document(self).await;
242        Ok(res.unwrap().into_inner())
243    }
244
245    async fn get_documents(&mut self) -> Result<Vec<Document>, BoxError> {
246        let res = query::run_query(self).await;
247        let mut stream = res.unwrap().into_inner();
248
249        let mut vec = Vec::new();
250
251        loop {
252            let item = stream.message().await?;
253            match item {
254                Some(_) => {
255                    let document = item.unwrap().document;
256                    match document {
257                        Some(document) => vec.push(document),
258                        None => break,
259                    }
260                }
261                None => break,
262            }
263        }
264
265        Ok(vec)
266    }
267
268    async fn set_document(
269        &mut self,
270        document_id: &str,
271        fields: HashMap<String, FsValue>,
272    ) -> Result<Document, BoxError> {
273        let exists = query::get_document(self).await;
274
275        let res;
276
277        match exists {
278            Ok(_) => res = query::update_document(self, document_id, fields).await,
279            Err(_) => res = query::create_document(self, document_id, fields).await,
280        };
281
282        Ok(res.unwrap().into_inner())
283    }
284
285    async fn add_document(
286        &mut self,
287        fields: HashMap<String, FsValue>,
288    ) -> Result<Document, BoxError> {
289        let res = query::create_document(self, "".into(), fields).await;
290
291        Ok(res.unwrap().into_inner())
292    }
293
294    async fn delete(&mut self) -> Result<String, BoxError> {
295        query::delete_document(self).await.unwrap();
296
297        Ok(self.document.clone())
298    }
299}
300
301pub fn db() -> State {
302    State::default()
303}