diff --git a/.gitignore b/.gitignore index a52986b..c14a3da 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .VSCodeCounter/ Cargo.lock target/ +temp.db diff --git a/todo_api/Cargo.toml b/todo_api/Cargo.toml index 99ebecf..1de3880 100644 --- a/todo_api/Cargo.toml +++ b/todo_api/Cargo.toml @@ -2,13 +2,14 @@ name = "todo_api" version = "0.1.0" edition = "2021" - # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -rocket = { version = "0.5", features = ["json"] } -tokio = { version = "1.36", features = ["full"] } chrono = { version = "0.4", features = ["serde"] } +log = "0.4" +rocket = { version = "0.5", features = ["json"] } serde = { version = "1.0", features = ["derive"] } -surrealdb = { version = "1.2", features = ["kv-mem"] } +serde_json = { version = "1.0" } +surrealdb = { version = "1.2", features = ["kv-rocksdb", "kv-mem"] } thiserror = "1.0" +tokio = { version = "1.36", features = ["full"] } diff --git a/todo_api/src/db.rs b/todo_api/src/db.rs index 5648ac6..41fa751 100644 --- a/todo_api/src/db.rs +++ b/todo_api/src/db.rs @@ -1,11 +1,11 @@ -use crate::{prelude::W, utils::macros::map}; +use crate::utils::macros::map; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, sync::Arc}; use surrealdb::{ dbs::{Response, Session}, kvs::Datastore, - sql::{thing, Array, Object, Value}, + sql::{thing, Value}, }; #[derive(Debug, Serialize, Deserialize)] @@ -66,17 +66,17 @@ impl DB { Ok(res) } - pub async fn add_task(&self, title: &str) -> Result { + pub async fn add_task(&self, title: &str) -> Result { let sql = "CREATE tasks SET title = $title, completed = false, created_at = time::now()"; let vars: BTreeMap = map!["title".into() => Value::Strand(title.into())]; let res = self.execute(sql, Some(vars)).await?; let first_res = res.into_iter().next().expect("Did not get a response"); - W(first_res.result?.first()).try_into() + Ok(first_res.result?.into_json()) } - pub async fn get_task(&self, id: &str) -> Result { + pub async fn get_task(&self, id: &str) -> Result { let sql = "SELECT * FROM $th"; let tid = format!("{}", id); let vars: BTreeMap = map!["th".into() => thing(&tid)?.into()]; @@ -84,19 +84,17 @@ impl DB { let first_res = ress.into_iter().next().expect("Did not get a response"); - W(first_res.result?.first()).try_into() + Ok(first_res.result?.into_json()) } - pub async fn get_all_tasks(&self) -> Result, crate::error::Error> { + pub async fn get_all_tasks(&self) -> Result { let sql = "SELECT * FROM tasks ORDER BY created_at ASC;"; let res = self.execute(sql, None).await?; let first_res = res.into_iter().next().expect("Did not get a response"); - let array: Array = W(first_res.result?).try_into()?; - - array.into_iter().map(|value| W(value).try_into()).collect() + Ok(first_res.result?.into_json()) } pub async fn toggle_task(&self, id: &str) -> Result { diff --git a/todo_api/src/error.rs b/todo_api/src/error.rs index 1acdb49..6ea1ef1 100644 --- a/todo_api/src/error.rs +++ b/todo_api/src/error.rs @@ -2,15 +2,18 @@ #[derive(thiserror::Error, Debug)] pub enum Error { - #[error("Value not of type '{0}'")] - XValueNotOfType(&'static str), - - #[error(transparent)] - Surreal(#[from] surrealdb::Error), - #[error(transparent)] Surrealdb(#[from] surrealdb::error::Db), #[error(transparent)] IO(#[from] std::io::Error), } + +impl From for std::io::Error { + fn from(e: Error) -> std::io::Error { + match e { + Error::IO(e) => e, + _ => std::io::Error::new(std::io::ErrorKind::Other, e.to_string()), + } + } +} diff --git a/todo_api/src/main.rs b/todo_api/src/main.rs index a4c6b71..49d7f48 100644 --- a/todo_api/src/main.rs +++ b/todo_api/src/main.rs @@ -5,42 +5,42 @@ use crate::db::{AffectedRows, DB}; use cors::*; use rocket::{serde::json::Json, State}; use std::{io::ErrorKind, sync::Arc}; -use surrealdb::{dbs::Session, kvs::Datastore, sql::Object}; +use surrealdb::{dbs::Session, kvs::Datastore, }; mod cors; mod db; mod error; -mod prelude; mod utils; #[post("/task/")] -async fn add_task(title: &str, db: &State<DB>) -> Result<Json<Object>, std::io::Error> { +async fn add_task(title: &str, db: &State<DB>) -> Result<serde_json::Value, std::io::Error> { let task = db .add_task(title) .await .map_err(|_| std::io::Error::new(ErrorKind::Other, "Unable to create task."))?; - Ok(Json(task)) + log::info!("Task created: {:?}", task.to_string()); + Ok(task) } #[get("/task/<id>")] -async fn get_task(id: &str, db: &State<DB>) -> Result<Json<Object>, std::io::Error> { +async fn get_task(id: &str, db: &State<DB>) -> Result<serde_json::Value, std::io::Error> { let task = db .get_task(id) .await .map_err(|_| std::io::Error::new(ErrorKind::Other, "Unable to fetch task."))?; - Ok(Json(task)) + Ok(task) } #[get("/tasks")] -async fn get_all_tasks(db: &State<DB>) -> Result<Json<Vec<Object>>, std::io::Error> { +async fn get_all_tasks(db: &State<DB>) -> Result<serde_json::Value, std::io::Error> { let tasks = db .get_all_tasks() .await .map_err(|_| std::io::Error::new(ErrorKind::Other, "Unable to fetch all tasks."))?; - Ok(Json(tasks)) + Ok(tasks) } #[patch("/task/<id>")] @@ -66,7 +66,7 @@ async fn delete_task(id: &str, db: &State<DB>) -> Result<Json<AffectedRows>, std #[launch] async fn rocket() -> _ { let datastore = Arc::new(Datastore::new("memory").await.unwrap()); - let session = Session::default().with_ns("my_ns").with_db("my_db"); + let session = Session::owner().with_ns("my_ns").with_db("my_db"); let db = DB { datastore, session }; diff --git a/todo_api/src/prelude.rs b/todo_api/src/prelude.rs deleted file mode 100644 index 94e2c22..0000000 --- a/todo_api/src/prelude.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub use crate::error::Error; -pub struct W<T>(pub T); diff --git a/todo_api/src/utils/mod.rs b/todo_api/src/utils/mod.rs index 0f32391..eda363d 100644 --- a/todo_api/src/utils/mod.rs +++ b/todo_api/src/utils/mod.rs @@ -1,2 +1 @@ pub mod macros; -pub mod try_froms; diff --git a/todo_api/src/utils/try_froms.rs b/todo_api/src/utils/try_froms.rs deleted file mode 100644 index 2f77bc0..0000000 --- a/todo_api/src/utils/try_froms.rs +++ /dev/null @@ -1,56 +0,0 @@ -// from: https://github.com/rust-awesome-app/template-app-base/blob/main/src-tauri/src/store/try_froms.rs - -use surrealdb::sql::{Array, Object, Value}; - -use crate::prelude::{Error, W}; - -impl TryFrom<W<Value>> for Object { - type Error = Error; - fn try_from(val: W<Value>) -> Result<Object, Error> { - match val.0 { - Value::Object(obj) => Ok(obj), - _ => Err(Error::XValueNotOfType("Object")), - } - } -} - -impl TryFrom<W<Value>> for Array { - type Error = Error; - fn try_from(val: W<Value>) -> Result<Array, Error> { - match val.0 { - Value::Array(obj) => Ok(obj), - _ => Err(Error::XValueNotOfType("Array")), - } - } -} - -impl TryFrom<W<Value>> for i64 { - type Error = Error; - fn try_from(val: W<Value>) -> Result<i64, Error> { - match val.0 { - Value::Number(obj) => Ok(obj.as_int()), - _ => Err(Error::XValueNotOfType("i64")), - } - } -} - -impl TryFrom<W<Value>> for bool { - type Error = Error; - fn try_from(val: W<Value>) -> Result<bool, Error> { - match val.0 { - Value::Bool(obj) => Ok(obj), - _ => Err(Error::XValueNotOfType("bool")), - } - } -} - -impl TryFrom<W<Value>> for String { - type Error = Error; - fn try_from(val: W<Value>) -> Result<String, Error> { - match val.0 { - Value::Strand(strand) => Ok(strand.as_string()), - Value::Thing(thing) => Ok(thing.to_string()), - _ => Err(Error::XValueNotOfType("String")), - } - } -} diff --git a/todo_web/Cargo.toml b/todo_web/Cargo.toml index a79dc31..6ef413b 100644 --- a/todo_web/Cargo.toml +++ b/todo_web/Cargo.toml @@ -2,13 +2,12 @@ name = "todo_web" version = "0.1.0" edition = "2021" - # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -wasm-bindgen-futures = "0.4" -web-sys = "0.3" -yew = { version = "0.21", features = ["csr"] } +chrono = { version = "0.4", features = ["serde", "wasmbind"] } reqwasm = "0.5" serde = { version = "1.0", features = ["derive"] } -chrono = { version = "0.4", features = ["serde", "wasmbind"] } +wasm-bindgen-futures = "0.4" +web-sys = { version = "0.3", features = ["console"] } +yew = { version = "0.21", features = ["csr"] } diff --git a/todo_web/src/controllers.rs b/todo_web/src/controllers.rs index 1dcf29b..b8b29fb 100644 --- a/todo_web/src/controllers.rs +++ b/todo_web/src/controllers.rs @@ -2,6 +2,7 @@ use crate::{ state::{TaskAction, TaskState}, todo_api, }; +use web_sys::{console::log, js_sys::Array, wasm_bindgen::JsValue}; use yew::UseReducerHandle; pub struct TaskController { @@ -16,8 +17,15 @@ impl TaskController { pub fn init_tasks(&self) { let tasks = self.state.clone(); wasm_bindgen_futures::spawn_local(async move { - let fetched_tasks = todo_api::fetch_tasks().await.unwrap(); - tasks.dispatch(TaskAction::Set(fetched_tasks)) + match todo_api::fetch_tasks().await { + Ok(fetched_tasks) => tasks.dispatch(TaskAction::Set(fetched_tasks)), + Err(err) => { + let string = format!("{:?}", err.to_string()); + let js_val = JsValue::from_str(&string); + let arr = Array::from(&js_val); + log(&arr); + } + } }); } diff --git a/todo_web/src/main.rs b/todo_web/src/main.rs index 181fe3d..8f84b78 100644 --- a/todo_web/src/main.rs +++ b/todo_web/src/main.rs @@ -18,10 +18,7 @@ fn app() -> Html { { let tasks_controller = tasks_controller.clone(); - use_effect_with((), move |_| { - tasks_controller.init_tasks(); - || () // return empty destructor closure - }); // only call on first render + use_effect_with((), move |_| tasks_controller.init_tasks()); // only call on first render } let on_create_task = { diff --git a/todo_web/src/todo_api.rs b/todo_web/src/todo_api.rs index 1620417..afda6c8 100644 --- a/todo_web/src/todo_api.rs +++ b/todo_web/src/todo_api.rs @@ -13,12 +13,13 @@ pub async fn fetch_tasks() -> Result<Vec<Task>, Error> { } pub async fn create_task(title: &str) -> Result<Task, Error> { - Request::post(&format!("{BASE_URL}/task/{title}")) + let mut vec: Vec<Task> = Request::post(&format!("{BASE_URL}/task/{title}")) .send() .await .unwrap() .json() - .await + .await?; + Ok(vec.remove(0)) } pub async fn toggle_task(id: String) -> Result<AffectedRows, Error> {