ferrox_database_firebase/
lib.rs1use async_trait::async_trait;
2use ferrox_database_core::Repository;
3use ferrox_errors::AppError;
4use reqwest::Client;
5use serde::{Serialize, de::DeserializeOwned};
6use std::marker::PhantomData;
7
8pub struct FirebaseRepository<T> {
10 client: Client,
11 base_url: String,
12 collection: String,
13 _marker: PhantomData<T>,
14}
15
16impl<T> FirebaseRepository<T> {
17 pub fn new(client: Client, project_id: &str, collection: &str) -> Self {
18 Self {
19 client,
20 base_url: format!("https://{}.firebaseio.com", project_id),
21 collection: collection.to_string(),
22 _marker: PhantomData,
23 }
24 }
25}
26
27#[async_trait]
28impl<T> Repository<T, String> for FirebaseRepository<T>
29where
30 T: Serialize + DeserializeOwned + Send + Sync + Clone,
31{
32 async fn find_by_id(&self, id: String) -> Result<Option<T>, AppError> {
33 let url = format!("{}/{}/{}.json", self.base_url, self.collection, id);
34 let res = self.client.get(&url).send().await.map_err(|e| AppError::DatabaseError(e.to_string()))?;
35
36 if res.status().is_success() {
37 let entity: Option<T> = res.json().await.map_err(|e| AppError::DatabaseError(e.to_string()))?;
38 Ok(entity)
39 } else {
40 Ok(None)
41 }
42 }
43
44 async fn find_all(&self) -> Result<Vec<T>, AppError> {
45 let url = format!("{}/{}.json", self.base_url, self.collection);
46 let res = self.client.get(&url).send().await.map_err(|e| AppError::DatabaseError(e.to_string()))?;
47
48 if res.status().is_success() {
49 let map: std::collections::HashMap<String, T> = res.json().await.map_err(|e| AppError::DatabaseError(e.to_string()))?;
50 Ok(map.into_values().collect())
51 } else {
52 Ok(vec![])
53 }
54 }
55
56 async fn insert(&self, entity: T) -> Result<T, AppError> {
57 let url = format!("{}/{}.json", self.base_url, self.collection);
58
59 self.client.post(&url)
60 .json(&entity)
61 .send()
62 .await
63 .map_err(|e| AppError::DatabaseError(e.to_string()))?;
64
65 Ok(entity)
66 }
67
68 async fn update(&self, id: String, entity: T) -> Result<T, AppError> {
69 let url = format!("{}/{}/{}.json", self.base_url, self.collection, id);
70
71 self.client.put(&url)
72 .json(&entity)
73 .send()
74 .await
75 .map_err(|e| AppError::DatabaseError(e.to_string()))?;
76
77 Ok(entity)
78 }
79
80 async fn delete(&self, id: String) -> Result<(), AppError> {
81 let url = format!("{}/{}/{}.json", self.base_url, self.collection, id);
82 self.client.delete(&url)
83 .send()
84 .await
85 .map_err(|e| AppError::DatabaseError(e.to_string()))?;
86
87 Ok(())
88 }
89}