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}