pocketbase_sdk/
records.rs

1use crate::client::{Auth, Client};
2use crate::httpc::Httpc;
3use anyhow::{anyhow, Result};
4use serde::Serialize;
5use serde::{de::DeserializeOwned, Deserialize};
6
7#[derive(Debug, Clone)]
8pub struct RecordsManager<'a> {
9    pub client: &'a Client<Auth>,
10    pub name: &'a str,
11}
12
13#[derive(Debug, Clone)]
14pub struct RecordsListRequestBuilder<'a> {
15    pub client: &'a Client<Auth>,
16    pub collection_name: &'a str,
17    pub filter: Option<String>,
18    pub sort: Option<String>,
19    pub page: i32,
20    pub per_page: i32,
21}
22
23#[derive(Debug, Clone, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct RecordList<T> {
26    pub page: i32,
27    pub per_page: i32,
28    pub total_items: i32,
29    pub items: Vec<T>,
30}
31
32impl<'a> RecordsListRequestBuilder<'a> {
33    pub fn call<T: Default + DeserializeOwned>(&self) -> Result<RecordList<T>> {
34        let url = format!(
35            "{}/api/collections/{}/records",
36            self.client.base_url, self.collection_name
37        );
38
39        let mut build_opts: Vec<(&str, &str)> = vec![];
40        if let Some(filter_opts) = &self.filter {
41            build_opts.push(("filter", filter_opts))
42        }
43        if let Some(sort_opts) = &self.sort {
44            build_opts.push(("sort", sort_opts))
45        }
46        let per_page_opts = self.per_page.to_string();
47        let page_opts = self.page.to_string();
48        build_opts.push(("per_page", per_page_opts.as_str()));
49        build_opts.push(("page", page_opts.as_str()));
50
51        match Httpc::get(self.client, &url, Some(build_opts)) {
52            Ok(result) => {
53                let response = result.into_json::<RecordList<T>>()?;
54                Ok(response)
55            }
56            Err(e) => Err(e),
57        }
58    }
59
60    pub fn filter(&self, filter_opts: &str) -> Self {
61        Self {
62            filter: Some(filter_opts.to_string()),
63            ..self.clone()
64        }
65    }
66
67    pub fn sort(&self, sort_opts: &str) -> Self {
68        Self {
69            sort: Some(sort_opts.to_string()),
70            ..self.clone()
71        }
72    }
73
74    pub fn page(&self, page: i32) -> Self {
75        Self {
76            page,
77            ..self.clone()
78        }
79    }
80
81    pub fn per_page(&self, per_page: i32) -> Self {
82        Self {
83            per_page,
84            ..self.clone()
85        }
86    }
87}
88
89pub struct RecordViewRequestBuilder<'a> {
90    pub client: &'a Client<Auth>,
91    pub collection_name: &'a str,
92    pub identifier: &'a str,
93}
94
95impl<'a> RecordViewRequestBuilder<'a> {
96    pub fn call<T: Default + DeserializeOwned>(&self) -> Result<T> {
97        let url = format!(
98            "{}/api/collections/{}/records/{}",
99            self.client.base_url, self.collection_name, self.identifier
100        );
101        match Httpc::get(self.client, &url, None) {
102            Ok(result) => {
103                let response = result.into_json::<T>()?;
104                Ok(response)
105            }
106            Err(e) => Err(anyhow!("error: {}", e)),
107        }
108    }
109}
110
111impl<'a> RecordDestroyRequestBuilder<'a> {
112    pub fn call(&self) -> Result<()> {
113        let url = format!(
114            "{}/api/collections/{}/records/{}",
115            self.client.base_url, self.collection_name, self.identifier
116        );
117        match Httpc::delete(self.client, url.as_str()) {
118            Ok(result) => {
119                if result.status() == 204 {
120                    Ok(())
121                } else {
122                    Err(anyhow!("Failed to delete"))
123                }
124            }
125            Err(e) => Err(anyhow!("error: {}", e)),
126        }
127    }
128}
129
130#[derive(Clone, Debug)]
131pub struct RecordDestroyRequestBuilder<'a> {
132    pub identifier: &'a str,
133    pub client: &'a Client<Auth>,
134    pub collection_name: &'a str,
135}
136
137#[derive(Debug, Clone)]
138pub struct RecordDeleteAllRequestBuilder<'a> {
139    pub client: &'a Client<Auth>,
140    pub collection_name: &'a str,
141    pub filter: Option<&'a str>,
142}
143
144#[derive(Debug, Clone)]
145pub struct RecordCreateRequestBuilder<'a, T: Serialize + Clone> {
146    pub client: &'a Client<Auth>,
147    pub collection_name: &'a str,
148    pub record: T,
149}
150
151#[derive(Deserialize, Clone, Debug)]
152pub struct CreateResponse {
153    #[serde(rename = "@collectionName")]
154    pub collection_name: Option<String>,
155    #[serde(rename = "@collectionId")]
156    pub collection_id: Option<String>,
157    pub id: String,
158    pub updated: String,
159    pub created: String,
160}
161
162impl<'a, T: Serialize + Clone> RecordCreateRequestBuilder<'a, T> {
163    pub fn call(&self) -> Result<CreateResponse> {
164        let url = format!(
165            "{}/api/collections/{}/records",
166            self.client.base_url, self.collection_name
167        );
168        let payload = serde_json::to_string(&self.record).map_err(anyhow::Error::from)?;
169        match Httpc::post(self.client, &url, payload) {
170            Ok(result) => {
171                let response = result.into_json::<CreateResponse>()?;
172                Ok(response)
173            }
174            Err(e) => Err(anyhow!("error: {}", e)),
175        }
176    }
177}
178
179pub struct RecordUpdateRequestBuilder<'a, T: Serialize + Clone> {
180    pub record: T,
181    pub collection_name: &'a str,
182    pub client: &'a Client<Auth>,
183    pub id: &'a str,
184}
185
186impl<'a, T: Serialize + Clone> RecordUpdateRequestBuilder<'a, T> {
187    pub fn call(&self) -> Result<T> {
188        let url = format!(
189            "{}/api/collections/{}/records/{}",
190            self.client.base_url, self.collection_name, self.id
191        );
192        let payload = serde_json::to_string(&self.record).map_err(anyhow::Error::from)?;
193        match Httpc::patch(self.client, &url, payload) {
194            Ok(result) => {
195                result.into_json::<CreateResponse>()?;
196                Ok(self.record.clone())
197            }
198            Err(e) => Err(anyhow!("error: {}", e)),
199        }
200    }
201}
202
203impl<'a> RecordsManager<'a> {
204    pub fn view(&self, identifier: &'a str) -> RecordViewRequestBuilder<'a> {
205        RecordViewRequestBuilder {
206            identifier,
207            client: self.client,
208            collection_name: self.name,
209        }
210    }
211
212    pub fn destroy(&self, identifier: &'a str) -> RecordDestroyRequestBuilder<'a> {
213        RecordDestroyRequestBuilder {
214            identifier,
215            client: self.client,
216            collection_name: self.name,
217        }
218    }
219
220    pub fn update<T: Serialize + Clone>(
221        &self,
222        identifier: &'a str,
223        record: T,
224    ) -> RecordUpdateRequestBuilder<'a, T> {
225        RecordUpdateRequestBuilder {
226            client: self.client,
227            collection_name: self.name,
228            id: identifier,
229            record,
230        }
231    }
232
233    pub fn create<T: Serialize + Clone>(&self, record: T) -> RecordCreateRequestBuilder<'a, T> {
234        RecordCreateRequestBuilder {
235            record,
236            client: self.client,
237            collection_name: self.name,
238        }
239    }
240
241    pub fn list(&self) -> RecordsListRequestBuilder<'a> {
242        RecordsListRequestBuilder {
243            client: self.client,
244            collection_name: self.name,
245            filter: None,
246            sort: None,
247            page: 1,
248            per_page: 100,
249        }
250    }
251}