caretta-sync-core 0.0.2

A local-first application framework for lazy person
Documentation
use std::{fs::create_dir_all, path::Path};

use sea_orm::{Database, DatabaseConnection};
use sea_orm_migration::MigratorTrait;
use tokio::sync::OnceCell;

use crate::error::Error;

pub static LOCAL_DATABASE_CONNECTION: GlobalDatabaseConnection =
    GlobalDatabaseConnection::const_new();

pub struct GlobalDatabaseConnection {
    inner: OnceCell<DatabaseConnection>,
}

impl GlobalDatabaseConnection {
    const fn const_new() -> Self {
        Self {
            inner: OnceCell::const_new(),
        }
    }

    pub async fn get_or_try_init<P, M>(&self, path: &P) -> Result<&DatabaseConnection, Error>
    where
        P: AsRef<Path>,
        M: MigratorTrait,
    {
        self.inner
            .get_or_try_init(|| async move {
                let path = path.as_ref();
                let parent = path
                    .parent()
                    .expect("Database path should have parent directory");
                create_dir_all(parent).expect("Failed to create parent directory of database");
                let url = "sqlite://".to_owned()
                    + path.to_str().expect("Invalid path string")
                    + "?mode=rwc";
                let db = Database::connect(url).await?;
                M::up(&db, None).await?;
                Ok(db)
            })
            .await
    }

    pub fn get(&self) -> Option<&DatabaseConnection> {
        self.inner.get()
    }
    pub fn get_unchecked(&self) -> &DatabaseConnection {
        self.get()
            .expect("Global database mulst be initialized before use")
    }
}