1use std::fmt::Display;
2
3pub use ::bson;
4use bson::{Document, oid::ObjectId};
5use builder_pattern::Builder;
6use reqwest::{StatusCode, header::{HeaderMap, HeaderName, HeaderValue}};
7use serde::{Serialize, Deserialize};
8
9#[derive(Builder, Debug, Clone)]
10pub struct Client {
12 #[into]
13 pub application_id: String,
15 #[into]
16 pub api_token: String,
18
19 #[default(ApiVersion::v1)]
20 pub api_version: ApiVersion,
21 #[into]
22 #[default(None)]
23 pub deployment_region: Option<String>,
26}
27#[derive(Debug, Clone)]
28pub enum ApiVersion {
29 #[allow(non_camel_case_types)]
30 v1,
31}
32#[allow(unused)]
33impl Client {
34 fn get_url(&self) -> String {
36 format!(
37 "https://{}data.mongodb-api.com/app/{}/endpoint/data/{}",
38 match &self.deployment_region {
39 Some(x) => format!("{}.", x),
40 None => "".into()
41 },
42 self.application_id,
43 match &self.api_version {
44 ApiVersion::v1 => "v1",
45 }
46 )
47 }
48 fn get_auth_headers(&self) -> HeaderMap {
50 let mut header_map = HeaderMap::new();
51 header_map.append(HeaderName::from_static("apikey"), HeaderValue::from_str(&self.api_token).unwrap());
52 header_map.append(HeaderName::from_static("content-type"), HeaderValue::from_static("application/json"));
53 header_map.append(HeaderName::from_static("accept"), HeaderValue::from_static("application/json"));
54 header_map
55 }
56
57 pub async fn find_one(
67 &self,
68 collection: Collection,
69 filter: Option<Document>,
70 projection: Option<Document>,
71 http_client: &reqwest::Client
72 ) -> Result<FindResponse, Error> {
73 let req = FindRequest {
74 collection,
75 filter,
76 projection,
77 sort: None,
78 limit: None,
79 skip: None
80 };
81
82 let res = http_client.post(format!("{}/action/findOne", self.get_url()))
83 .headers(self.get_auth_headers())
84 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
85 .send()
86 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
87
88 if !res.status().is_success(){
89 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
90 }
91
92 res.json::<FindResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
93 }
94 pub async fn find(
113 &self,
114 collection: Collection,
115 filter: Option<Document>,
116 projection: Option<Document>,
117 sort: Option<Document>,
118 limit: Option<i32>,
119 skip: Option<i32>,
120 http_client: &reqwest::Client
121 ) -> Result<FindResponse, Error> {
122 let req = FindRequest {
123 collection,
124 filter,
125 projection,
126 sort,
127 limit,
128 skip
129 };
130
131 let res = http_client.post(format!("{}/action/find", self.get_url()))
132 .headers(self.get_auth_headers())
133 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
134 .send()
135 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
136
137 if !res.status().is_success(){
138 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
139 }
140
141 res.json::<FindResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
142 }
143 pub async fn insert_one(
148 &self,
149 collection: Collection,
150 document: Document,
151 http_client: &reqwest::Client
152 ) -> Result<InsertResponse, Error> {
153 let req = InsertRequest {
154 collection,
155 document: Some(document),
156 documents: None
157 };
158 let res = http_client.post(format!("{}/action/insertOne", self.get_url()))
159 .headers(self.get_auth_headers())
160 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
161 .send()
162 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
163
164 if !res.status().is_success(){
165 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
166 }
167
168 res.json::<InsertResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
169 }
170 pub async fn insert(
175 &self,
176 collection: Collection,
177 documents: Vec<Document>,
178 http_client: &reqwest::Client
179 ) -> Result<InsertResponse, Error> {
180 let req = InsertRequest {
181 collection,
182 document: None,
183 documents: Some(documents)
184 };
185 let res = http_client.post(format!("{}/action/insertMany", self.get_url()))
186 .headers(self.get_auth_headers())
187 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
188 .send()
189 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
190
191 if !res.status().is_success(){
192 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
193 }
194
195 res.json::<InsertResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
196 }
197 pub async fn update_one(
205 &self,
206 collection: Collection,
207 filter: Document,
208 update: Document,
209 upsert: Option<bool>,
210 http_client: &reqwest::Client
211 ) -> Result<UpdateResponse, Error> {
212 let req = UpdateRequest {
213 collection,
214 filter,
215 update,
216 upsert
217 };
218 let res = http_client.post(format!("{}/action/updateOne", self.get_url()))
219 .headers(self.get_auth_headers())
220 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
221 .send()
222 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
223
224 if !res.status().is_success(){
225 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
226 }
227
228 res.json::<UpdateResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
229 }
230 pub async fn update(
239 &self,
240 collection: Collection,
241 filter: Document,
242 update: Document,
243 upsert: Option<bool>,
244 http_client: &reqwest::Client
245 ) -> Result<UpdateResponse, Error> {
246 let req = UpdateRequest {
247 collection,
248 filter,
249 update,
250 upsert
251 };
252 let res = http_client.post(format!("{}/action/updateMany", self.get_url()))
253 .headers(self.get_auth_headers())
254 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
255 .send()
256 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
257
258 if !res.status().is_success(){
259 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
260 }
261
262 res.json::<UpdateResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
263 }
264
265 pub async fn replace_one(
273 &self,
274 collection: Collection,
275 filter: Document,
276 replacement: Document,
277 upsert: Option<bool>,
278 http_client: &reqwest::Client
279 ) -> Result<ReplaceResponse, Error> {
280 let req = ReplaceRequest {
281 collection,
282 filter,
283 replacement,
284 upsert
285 };
286 let res = http_client.post(format!("{}/action/replaceOne", self.get_url()))
287 .headers(self.get_auth_headers())
288 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
289 .send()
290 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
291
292 if !res.status().is_success(){
293 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
294 }
295
296 res.json::<ReplaceResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
297 }
298 pub async fn delete_one(
303 &self,
304 collection: Collection,
305 filter: Document,
306 http_client: &reqwest::Client
307 ) -> Result<DeleteResponse, Error> {
308 let req = DeleteRequest {
309 collection,
310 filter,
311 };
312 let res = http_client.post(format!("{}/action/deleteOne", self.get_url()))
313 .headers(self.get_auth_headers())
314 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
315 .send()
316 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
317
318 if !res.status().is_success(){
319 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
320 }
321
322 res.json::<DeleteResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
323 }
324 pub async fn delete(
329 &self,
330 collection: Collection,
331 filter: Document,
332 http_client: &reqwest::Client
333 ) -> Result<DeleteResponse, Error> {
334 let req = DeleteRequest {
335 collection,
336 filter,
337 };
338 let res = http_client.post(format!("{}/action/deleteMany", self.get_url()))
339 .headers(self.get_auth_headers())
340 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
341 .send()
342 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
343
344 if !res.status().is_success(){
345 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
346 }
347
348 res.json::<DeleteResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
349 }
350 pub async fn aggregate(
355 &self,
356 collection: Collection,
357 pipeline: Vec<Document>,
358 http_client: &reqwest::Client
359 ) -> Result<AggregationResponse, Error> {
360 let req = AggregationRequest {
361 collection,
362 pipeline,
363 };
364 let res = http_client.post(format!("{}/action/aggregate", self.get_url()))
365 .headers(self.get_auth_headers())
366 .body(serde_json::to_string(&req).map_err(|x| Error {status_code: None, error: format!("Format error: {:?}", x)})?)
367 .send()
368 .await.map_err(|x| Error {status_code: None, error: format!("Failed to send request: {:?}", x)})?;
369
370 if !res.status().is_success(){
371 return Err(Error { status_code: Some(res.status()), error: format!("; content: {}", res.text().await.unwrap_or_default()) })
372 }
373
374 res.json::<AggregationResponse>().await.map_err(|x| Error {status_code: None, error: format!("Failed to deserialize response: {:?}", x)})
375 }
376}
377
378#[allow(unused)]
379#[derive(Debug, Clone, Deserialize)]
380pub struct FindResponse {
381 pub document: Option<Document>,
382 pub documents: Option<Vec<Document>>
383}
384#[allow(unused)]
385#[derive(Debug, Clone, Serialize)]
386#[serde(rename_all = "camelCase")]
387struct FindRequest {
388 #[serde(flatten)]
389 collection: Collection,
390 #[serde(skip_serializing_if = "Option::is_none")]
391 filter: Option<Document>,
392 #[serde(skip_serializing_if = "Option::is_none")]
393 projection: Option<Document>,
394 #[serde(skip_serializing_if = "Option::is_none")]
395 sort: Option<Document>,
396 #[serde(skip_serializing_if = "Option::is_none")]
397 limit: Option<i32>,
398 #[serde(skip_serializing_if = "Option::is_none")]
399 skip: Option<i32>
400}
401
402#[allow(unused)]
403#[derive(Debug, Clone, Serialize)]
404#[serde(rename_all = "camelCase")]
405struct InsertRequest {
406 #[serde(flatten)]
407 collection: Collection,
408 #[serde(skip_serializing_if = "Option::is_none")]
409 document: Option<Document>,
410 #[serde(skip_serializing_if = "Option::is_none")]
411 documents: Option<Vec<Document>>
412}
413
414#[allow(unused)]
415#[derive(Debug, Clone, Deserialize)]
416pub struct InsertResponse {
417 pub inserted_id: Option<ObjectId>,
418 pub inserted_ids: Option<Vec<ObjectId>>
419}
420
421#[allow(unused)]
422#[derive(Debug, Clone, Deserialize)]
423#[serde(rename_all = "camelCase")]
424pub struct UpdateResponse {
425 pub matched_count: i32,
426 pub modified_count: i32,
427 pub upserted_id: Option<ObjectId>
428}
429
430#[allow(unused)]
431#[derive(Debug, Clone, Deserialize)]
432#[serde(rename_all = "camelCase")]
433pub struct ReplaceResponse {
434 pub matched_count: i32,
435 pub modified_count: i32,
436 pub upserted_id: Option<ObjectId>
437}
438
439#[allow(unused)]
440#[derive(Debug, Clone, Deserialize)]
441#[serde(rename_all = "camelCase")]
442pub struct DeleteResponse {
443 pub deleted_count: i32,
444}
445
446#[allow(unused)]
447#[derive(Debug, Clone, Serialize)]
448#[serde(rename_all = "camelCase")]
449struct UpdateRequest {
450 #[serde(flatten)]
451 collection: Collection,
452 filter: Document,
453 update: Document,
454 #[serde(skip_serializing_if = "Option::is_none")]
455 upsert: Option<bool>,
456}
457
458#[allow(unused)]
459#[derive(Debug, Clone, Serialize)]
460#[serde(rename_all = "camelCase")]
461struct ReplaceRequest {
462 #[serde(flatten)]
463 collection: Collection,
464 filter: Document,
465 replacement: Document,
466 #[serde(skip_serializing_if = "Option::is_none")]
467 upsert: Option<bool>,
468}
469
470#[allow(unused)]
471#[derive(Debug, Clone, Deserialize)]
472#[serde(rename_all = "camelCase")]
473pub struct AggregationResponse {
474 pub documents: Vec<Document>
475}
476
477#[allow(unused)]
478#[derive(Debug, Clone, Serialize)]
479#[serde(rename_all = "camelCase")]
480struct DeleteRequest {
481 #[serde(flatten)]
482 collection: Collection,
483 filter: Document,
484}
485
486#[allow(unused)]
487#[derive(Debug, Clone, Serialize)]
488#[serde(rename_all = "camelCase")]
489struct AggregationRequest {
490 #[serde(flatten)]
491 collection: Collection,
492 pipeline: Vec<Document>,
493}
494
495#[allow(unused)]
496#[derive(Debug, Clone)]
497pub struct Error {
498 status_code: Option<StatusCode>,
500 error: String,
501}
502impl Display for Error {
503 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
504 write!(f, "StatusCode: {:?}; {}", self.status_code, self.error)
505 }
506}
507
508#[derive(Debug, Clone, Serialize)]
509#[serde(rename_all = "camelCase")]
510pub struct Collection {
512 pub data_source: String,
514 pub database: String,
516 pub collection: String,
518}