use crate::util; use leptos::*; use leptos_use::{core::ConnectionReadyState, use_websocket, UseWebsocketReturn}; use serde::{Deserialize, Serialize}; use serde_json::json; use std::rc::Rc; #[derive(Serialize)] struct SurrealRequest { id: u32, method: String, params: Vec, } #[derive(Serialize)] #[serde(untagged)] enum SurrealParams { Participant, SigninParam(SigninParam), CreatePersonParam(CreatePersonParam), String(String), } #[derive(Serialize)] struct SigninParam { user: String, pass: String, } #[derive(Serialize)] struct CreatePersonParam { name: String, group: String, } #[derive(Clone, Debug)] pub struct Participant { name: String, group: String, } #[derive(Clone, Debug)] pub struct ParticipantsContext(pub ReadSignal>); #[derive(Clone)] pub struct SurrealContext { pub message: Signal>, send: Rc, pub ready_state: Signal, pub authenticated: ReadSignal, pub set_authenticated: WriteSignal, } #[derive(Serialize, Deserialize)] struct SurrealResponse { id: u32, result: SurrealResult, } #[derive(Serialize, Deserialize)] #[serde(untagged)] enum SurrealResult { String(String), Null, } impl SurrealContext { pub fn new( message: Signal>, send: Rc, ready_state: Signal, authenticated: ReadSignal, set_authenticated: WriteSignal, ) -> Self { Self { message, send, ready_state, authenticated, set_authenticated, } } /// Send a string to surrealDB #[inline(always)] pub fn send(&self, message: &str) { (self.send)(message) } /// sigin SurrealDB pub fn signin(&self, pass: String) { log::debug!("Signing into surrealdb"); let request = SurrealRequest { id: 0, method: String::from("signin"), params: vec![SurrealParams::SigninParam(SigninParam { user: String::from("root"), pass, })], }; self.send(&json!(request).to_string()); } pub fn add_person(&self, name: String, group: String) -> Result<(), String> { if name.is_empty() { return Err(String::from("Name cannot be empty")); } let request = SurrealRequest { id: 1, method: String::from("create"), params: vec![ SurrealParams::String(String::from("person")), SurrealParams::CreatePersonParam(CreatePersonParam { name, group: "group:".to_owned() + &group, }), ], }; Ok(self.send(&json!(request).to_string())) } } pub fn init_surrealdb() { // Initialize a connection to surrealDB let UseWebsocketReturn { ready_state, message, send, .. } = use_websocket("ws://localhost:80/rpc"); // Create reactive signals for the websocket connection to surrealDB let (participants, _set_participants) = create_signal::>(vec![]); let (authenticated, set_authenticated) = create_signal::(false); // Bind the websocket connection to a context let websocket = SurrealContext::new( message, Rc::new(send.clone()), ready_state, authenticated, set_authenticated, ); provide_context(websocket); provide_context(ParticipantsContext(participants)); // Watch for a message recieved from the surrealDB connection create_effect(move |prev_value| { let msg = message.get(); if prev_value != Some(msg.clone()) { match msg { Some(ref text) => { log::debug!("{:?}", text); surrealdb_response(text.to_string()); } None => (), } } msg }); } /// Function to execute when SurrealDB returns a message fn surrealdb_response(response: String) { let response: SurrealResponse = match serde_json::from_str(&response) { Ok(res) => res, Err(err) => { log::warn!("{}", err); return; } }; match response.id { 0 => use_surrealdb(response), 1 => log::debug!("Succesfully execute use wrb timings"), _ => return, } } /// Function to execute when DB signin is succesful fn use_surrealdb(_response: SurrealResponse) { util::toast::add_toast( "Succesfully signed into DB".to_string(), "success".to_string(), ); let websocket = expect_context::(); websocket.set_authenticated.set(true); let request = SurrealRequest { id: 1, method: String::from("use"), params: vec![ SurrealParams::String(String::from("wrb")), SurrealParams::String(String::from("timings")), ], }; websocket.send(&json!(request).to_string()) }