1pub mod helpers;
2
3use yesser_todo_db::Task;
4
5pub use yesser_todo_errors::api_error::ApiError;
6use yesser_todo_errors::server_error::ServerError;
7
8use crate::helpers::is_success;
9
10pub const DEFAULT_PORT: &str = "6982";
11
12pub struct Client {
13 pub hostname: String,
14 pub port: String,
15 client: ureq::Agent,
16}
17
18impl Client {
19 pub fn new(hostname: String, port: Option<String>) -> Client {
33 Client {
34 hostname,
35 port: port.unwrap_or_else(|| DEFAULT_PORT.to_string()),
36 client: ureq::Agent::config_builder().http_status_as_error(false).build().into(),
37 }
38 }
39
40 pub fn get(&self) -> Result<(u16, Vec<Task>), ApiError> {
60 let mut result = self.client.get(format!("{}:{}/tasks", self.hostname, self.port).as_str()).call()?;
61
62 let status_code = result.status();
63 if status_code.is_success() {
64 let result = result.body_mut().read_json::<Vec<Task>>();
65 match result {
66 Ok(result) => Ok((status_code.as_u16(), result)),
67 Err(err) => Err(ApiError::RequestError(err)),
68 }
69 } else {
70 match result.body_mut().read_json::<ServerError>() {
71 Ok(err) => Err(ApiError::ServerError(err)),
72 Err(_) => Err(ApiError::HTTPError(status_code.as_u16())),
73 }
74 }
75 }
76
77 pub fn add(&self, task_name: &str) -> Result<(u16, Task), ApiError> {
95 let mut result = self.client.post(format!("{}:{}/add", self.hostname, self.port).as_str()).send_json(task_name)?;
96
97 let status_code = result.status();
98 if status_code.is_success() {
99 let result = result.body_mut().read_json::<Task>();
100 match result {
101 Ok(result) => Ok((status_code.as_u16(), result)),
102 Err(err) => Err(ApiError::RequestError(err)),
103 }
104 } else {
105 match result.body_mut().read_json::<ServerError>() {
106 Ok(err) => Err(ApiError::ServerError(err)),
107 Err(_) => Err(ApiError::HTTPError(status_code.as_u16())),
108 }
109 }
110 }
111
112 pub fn get_index(&self, task_name: &str) -> Result<(u16, usize), ApiError> {
128 let mut result = self
129 .client
130 .get(format!("{}:{}/index", self.hostname, self.port).as_str())
131 .query("name", task_name)
132 .call()?;
133 let status_code = result.status();
134 if status_code.is_success() {
135 let result = result.body_mut().read_json::<usize>();
136 match result {
137 Ok(result) => Ok((status_code.as_u16(), result)),
138 Err(err) => Err(ApiError::RequestError(err)),
139 }
140 } else {
141 match result.body_mut().read_json::<ServerError>() {
142 Ok(err) => Err(ApiError::ServerError(err)),
143 Err(_) => Err(ApiError::HTTPError(status_code.as_u16())),
144 }
145 }
146 }
147
148 pub fn remove(&self, task_name: &str) -> Result<u16, ApiError> {
166 let index_result = self.get_index(task_name);
167 let index = match index_result {
168 Ok((_, result)) => result,
169 Err(err) => return Err(err),
170 };
171
172 let mut result = self
173 .client
174 .delete(format!("{}:{}/remove", self.hostname, self.port).as_str())
175 .query("index", index.to_string())
176 .call()?;
177 if result.status().is_success() {
178 Ok(result.status().as_u16())
179 } else {
180 let status_code = result.status();
181 match result.body_mut().read_json::<ServerError>() {
182 Ok(err) => Err(ApiError::ServerError(err)),
183 Err(_) => Err(ApiError::HTTPError(status_code.as_u16())),
184 }
185 }
186 }
187
188 pub fn done(&self, task_name: &str) -> Result<(u16, Task), ApiError> {
210 let index = match self.get_index(task_name) {
211 Ok((status_code, result)) => {
212 if !is_success(status_code) {
213 return Err(ApiError::HTTPError(status_code));
214 }
215 result
216 }
217 Err(err) => return Err(err),
218 };
219 let mut result = self.client.post(format!("{}:{}/done", self.hostname, self.port).as_str()).send_json(index)?;
220 let status_code = result.status();
221 if status_code.is_success() {
222 let result = result.body_mut().read_json::<Task>();
223 match result {
224 Ok(result) => Ok((status_code.as_u16(), result)),
225 Err(err) => Err(ApiError::RequestError(err)),
226 }
227 } else {
228 let status_code = result.status();
229 match result.body_mut().read_json::<ServerError>() {
230 Ok(err) => Err(ApiError::ServerError(err)),
231 Err(_) => Err(ApiError::HTTPError(status_code.as_u16())),
232 }
233 }
234 }
235
236 pub fn undone(&self, task_name: &str) -> Result<(u16, Task), ApiError> {
254 let index_result = self.get_index(task_name);
255 let index = match index_result {
256 Ok((status_code, result)) => {
257 if !is_success(status_code) {
258 return Err(ApiError::HTTPError(status_code));
259 }
260 result
261 }
262 Err(err) => return Err(err),
263 };
264
265 let mut result = self.client.post(format!("{}:{}/undone", self.hostname, self.port).as_str()).send_json(index)?;
266 let status_code = result.status();
267 if status_code.is_success() {
268 let result = result.body_mut().read_json::<Task>();
269 match result {
270 Ok(result) => Ok((status_code.as_u16(), result)),
271 Err(err) => Err(ApiError::RequestError(err)),
272 }
273 } else {
274 let status_code = result.status();
275 match result.body_mut().read_json::<ServerError>() {
276 Ok(err) => Err(ApiError::ServerError(err)),
277 Err(_) => Err(ApiError::HTTPError(status_code.as_u16())),
278 }
279 }
280 }
281
282 pub fn clear(&self) -> Result<u16, ApiError> {
301 let result = self.client.delete(format!("{}:{}/clear", self.hostname, self.port).as_str()).call()?;
302 if result.status().is_success() {
303 Ok(result.status().as_u16())
304 } else {
305 Err(ApiError::HTTPError(result.status().as_u16()))
306 }
307 }
308
309 pub fn clear_done(&self) -> Result<u16, ApiError> {
328 let result = self.client.delete(format!("{}:{}/cleardone", self.hostname, self.port).as_str()).call()?;
329 if result.status().is_success() {
330 Ok(result.status().as_u16())
331 } else {
332 Err(ApiError::HTTPError(result.status().as_u16()))
333 }
334 }
335}
336
337#[cfg(test)]
338mod tests {
339 use super::*;
340
341 #[test]
342 fn get() {
343 let client = Client::new("http://127.0.0.1".to_string(), None);
344 let result = client.get();
345 println!("{:?}", result);
346 assert!(result.is_ok() && is_success(result.unwrap().0));
347 }
348
349 #[test]
350 fn add_get_index_done_undone_remove() {
351 let client = Client::new("http://127.0.0.1".to_string(), None);
352 let result = client.add("test");
354 println!("{:?}", result);
355 assert!(result.is_ok() && is_success(result.unwrap().0));
356 let result = client.get_index("test");
358 println!("{:?}", result);
359 assert!(result.is_ok() && is_success(result.unwrap().0));
360 let result = client.done("test");
362 println!("{:?}", result);
363 assert!(result.is_ok() && is_success(result.unwrap().0));
364 let result = client.undone("test");
366 println!("{:?}", result);
367 assert!(result.is_ok() && is_success(result.unwrap().0));
368 let result = client.remove("test");
370 println!("{:?}", result);
371 assert!(result.is_ok() && is_success(result.unwrap()));
372
373 let result = client.clear();
375 println!("{:?}", result);
376 assert!(result.is_ok() && is_success(result.unwrap()));
377 }
378
379 #[test]
380 fn clear() {
381 let client = Client::new("http://127.0.0.1".to_string(), None);
382 let _ = client.add("test");
383 let _ = client.add("test");
384 let _ = client.add("test");
385 let result = client.clear();
386 println!("{:?}", result);
387 assert!(result.is_ok());
388 let result = client.get();
389 println!("{:?}", result);
390 assert!(result.is_ok());
391 let unwrapped = result.unwrap();
392 assert!(is_success(unwrapped.0) && unwrapped.1.is_empty());
393 }
394
395 #[test]
396 fn clear_done() {
397 let client = Client::new("http://127.0.0.1".to_string(), None);
398 let _ = client.add("test1");
399 let _ = client.add("test2");
400 let _ = client.add("test3");
401 let _ = client.done("test1");
402 let _ = client.done("test3");
403 let result = client.clear_done();
404 println!("{:?}", result);
405 assert!(result.is_ok());
406 let result = client.get();
407 println!("{:?}", result);
408 assert!(result.is_ok());
409 let unwrapped = result.unwrap();
410 assert!(is_success(unwrapped.0) && unwrapped.1.len() == 1 && unwrapped.1[0].name == "test2");
411
412 let result = client.clear();
414 println!("{:?}", result);
415 assert!(result.is_ok() && is_success(result.unwrap()));
416 }
417}