// Remember that Server functions parameters must not be references. // They are coming from potentially other computers. // // Server functions must be: // * Be an async function // * Have arguments and a return type that both implement serialize and deserialize (with serde). // * Return a Result with an error type of ServerFnError #[cfg(feature = "server")] use std::sync::Arc; use dioxus::prelude::*; #[cfg(feature = "server")] use tokio::sync::OnceCell; use tavern::{Adventurer, Lore, Tale}; #[cfg(feature = "server")] use tavern::Database; #[cfg(feature = "server")] static BLOG_DATABASE: OnceCell> = OnceCell::const_new(); #[cfg(feature = "server")] async fn get_database_instance

(path: P) -> Result<&'static Arc, ServerFnError> where P: AsRef { BLOG_DATABASE.get_or_try_init(|| async { let db = Database::open(path).await .map_err(|e| ServerFnError::new(format!("Failed to open database: {}", e)))?; Ok(Arc::new(db)) }).await } #[cfg(feature = "server")] pub async fn init_database

(path: P) -> Result<(), ServerFnError> where P: AsRef { match get_database_instance(path).await { Ok(_) => { Ok(()) } Err(e) => { Err(e) } } } #[cfg(feature = "server")] async fn get_database() -> Result<&'static Arc, ServerFnError> { get_database_instance("tavern.db").await } #[server] pub async fn get_blog_list(categories: Vec) -> Result, ServerFnError> { let db = get_database().await?; let summaries = db.get_tales_summary(&categories).await .map_err(|e| ServerFnError::new(e))?; Ok(summaries) } #[server] pub async fn get_blog_post(slug: String) -> Result { let db = get_database().await?; let tale = db.get_tale_by_slug(&slug).await .map_err(|e| ServerFnError::new(e))?; tale.ok_or(ServerFnError::new(format!("Post {} not found", slug))) } #[server] pub async fn get_author(handle: String) -> Result { let db = get_database().await?; let author = db.get_adventurer(&handle).await .map_err(|e| ServerFnError::new(e))?; author.ok_or(ServerFnError::new(format!("Author {} not found.", handle))) }