use toasty::{Db, ModelSet};
use crate::Result;
pub use toasty_core::driver::operation::TransactionMode;
pub const URL_ENV: &str = "DATABASE_URL";
pub const DEFAULT_URL: &str = "turso:database/database.db";
#[derive(Debug, Clone)]
pub struct DatabaseConfig {
pub url: String,
}
impl DatabaseConfig {
pub fn from_env() -> Self {
Self {
url: crate::env::var_or(URL_ENV, DEFAULT_URL),
}
}
}
pub async fn connect(models: ModelSet, config: &DatabaseConfig) -> Result<Db> {
if let Some(dir) = file_path(&config.url).and_then(|path| path.parent()) {
if !dir.as_os_str().is_empty() {
std::fs::create_dir_all(dir).map_err(crate::Error::DatabaseDir)?;
}
}
Ok(Db::builder().models(models).connect(&config.url).await?)
}
fn file_path(url: &str) -> Option<&std::path::Path> {
let path = url
.strip_prefix("turso:")
.or_else(|| url.strip_prefix("sqlite:"))?;
(!path.starts_with("//") && !path.starts_with(':')).then(|| std::path::Path::new(path))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn file_paths() {
let path = |url| file_path(url).map(|p| p.to_str().unwrap().to_owned());
assert_eq!(path("turso:database/app.db").as_deref(), Some("database/app.db"));
assert_eq!(path("sqlite:/tmp/x.db").as_deref(), Some("/tmp/x.db"));
assert_eq!(path("turso::memory:"), None);
assert_eq!(path("turso://db.example.com"), None);
assert_eq!(path("postgresql://localhost/app"), None);
}
}