cache-vault 0.1.3

Caching secret values to SQLite with encryption
Documentation
use sqlx::migrate::Migrator;
use sqlx::sqlite::{SqliteConnectOptions, SqlitePool};
use std::sync::LazyLock;
use std::sync::OnceLock;

use crate::error::CacheVaultError;

#[allow(dead_code)]
static MIGRATOR: Migrator = sqlx::migrate!();

pub static POOL: LazyLock<SqlitePool> = LazyLock::new(|| {
    let options = SqliteConnectOptions::new().filename(&*DB_PATH).create_if_missing(true);
    let conn = SqlitePool::connect_lazy_with(options);
    conn
});

#[cfg(not(test))]
static DB_PATH: LazyLock<String> = LazyLock::new(|| {
    let config_dir = dirs::config_dir().expect("Unable to get default config directory");
    let default_db_path = config_dir
        .join("cache-vault/cache-vault.db")
        .to_str()
        .unwrap()
        .to_string();
    let db_path = std::env::var("CACHE_VAULT_DATABASE_PATH").unwrap_or(default_db_path);
    let db_dir = std::path::Path::new(&db_path)
        .parent()
        .expect("Unable to get  cache-vault directory");
    std::fs::create_dir_all(db_dir).expect("Unable to create cache-vault directory");
    tracing::debug!(name: "cache-vault", "DB_PATH: {}", &db_path);
    db_path
});

#[cfg(test)]
static DB_PATH: LazyLock<String> = LazyLock::new(|| {
    use tempfile::NamedTempFile;
    let file = NamedTempFile::new().unwrap();
    let path = String::from(file.path().to_string_lossy());
    let _ = file.close();
    tracing::info!("DB_PATH: {}", path);
    path
});

#[allow(dead_code)]
static MIGRATED: OnceLock<bool> = OnceLock::new();

#[allow(dead_code)]
#[tracing::instrument]
pub async fn migrate() -> Result<(), CacheVaultError> {
    if MIGRATED.get().is_none() {
        tracing::debug!("migrate");
        MIGRATOR.run(&*POOL).await.map_err(CacheVaultError::MigrateError)?;
        let _ = MIGRATED.set(true);
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tracing_test::traced_test]
    #[tokio::test]
    async fn test_database() -> Result<(), CacheVaultError> {
        migrate().await?;
        let _ = sqlx::query(r#"select 1 as id"#).fetch_one(&*POOL).await?;
        Ok(())
    }
}