Files
tavernworks/bard/src/server.rs

95 lines
2.2 KiB
Rust

// 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<Arc<Database>> = OnceCell::const_new();
#[cfg(feature = "server")]
async fn get_database_instance<P>(path: P) -> Result<&'static Arc<Database>, ServerFnError>
where P: AsRef<std::path::Path>
{
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<P>(path: P) -> Result<(), ServerFnError>
where P: AsRef<std::path::Path>
{
match get_database_instance(path).await
{
Ok(_) => { Ok(()) }
Err(e) => { Err(e) }
}
}
#[cfg(feature = "server")]
async fn get_database() -> Result<&'static Arc<Database>, ServerFnError>
{
get_database_instance("tavern.db").await
}
#[server]
pub async fn get_blog_list(categories: Vec<String>) -> Result<Vec<Lore>, 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<Tale, ServerFnError>
{
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<Adventurer, ServerFnError>
{
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)))
}