use serde::{Deserialize, Serialize}; use uuid::Uuid; #[cfg(feature = "ssr")] use fs2::FileExt; #[cfg(feature = "ssr")] use std::fs::File; #[cfg(feature = "ssr")] use std::sync::LazyLock; use std::{collections::HashMap, path::Path}; mod config; mod namespace; mod page; use config::Config; pub use namespace::{Namespace, Namespaces}; pub use page::{Page, Pages}; #[derive(Hash, PartialEq, Eq, Clone, Debug, Deserialize, Serialize)] pub struct PageUuid(Uuid); #[cfg(feature = "ssr")] pub static CONFIG: LazyLock = LazyLock::new(|| Config::read_from_file().expect("Could not open config file")); #[cfg(feature = "ssr")] static DATA_LOCK: LazyLock = LazyLock::new(|| { let config = &CONFIG; let lock_path = Path::join(&config.data_dir, ".lock"); let lockfile = std::fs::OpenOptions::new() .read(true) .write(true) .create(true) .open(&lock_path) .map_err(|_| "Could not open data directory".to_string()) .unwrap(); lockfile .try_lock_exclusive() .map_err(|_| "Could not lock data directory".to_string()) .unwrap(); StormscribeData { file_lock: lockfile, namespaces: Namespaces::init(&Path::join(&config.data_dir, "namespace/")).unwrap(), pages: Pages::init(&Path::join(&config.data_dir, "pages/")).unwrap(), } }); #[cfg(feature = "ssr")] pub struct StormscribeData { file_lock: File, namespaces: Namespaces, pages: Pages, } #[cfg(feature = "ssr")] impl StormscribeData { fn get_data() -> &'static Self { &DATA_LOCK } pub fn get_namespace() -> Namespace { DATA_LOCK.namespaces.root.clone() } pub fn get_pages() -> HashMap { DATA_LOCK.pages.pages.clone() } }