use std::collections::BTreeMap;
use std::path::Path;
use color_eyre::eyre::{Result, WrapErr, eyre};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
#[serde(default)]
pub struct OrmConfig {
pub tables_dir: String,
pub migrations_dir: String,
pub snapshot_path: String,
pub database_url_env: String,
pub required_columns: BTreeMap<String, Vec<String>>,
pub modules: Vec<String>,
}
impl Default for OrmConfig {
fn default() -> Self {
Self {
tables_dir: "src/tables".into(),
migrations_dir: "migrations".into(),
snapshot_path: ".fse/schema.json".into(),
database_url_env: "DATABASE_URL".into(),
required_columns: BTreeMap::new(),
modules: Vec::new(),
}
}
}
#[derive(Debug, Default, Deserialize)]
struct FseToml {
#[serde(default)]
orm: OrmConfig,
}
pub fn load(root: &Path) -> Result<OrmConfig> {
let path = root.join("fse.toml");
if !path.exists() {
return Ok(OrmConfig::default());
}
let raw = std::fs::read_to_string(&path)
.wrap_err_with(|| format!("cannot read {}", path.display()))?;
let parsed: FseToml = toml::from_str(&raw).wrap_err("fse.toml is not valid TOML")?;
Ok(parsed.orm)
}
pub fn resolve_database_url(
root: &Path,
cfg: &OrmConfig,
override_url: Option<&str>,
) -> Result<String> {
if let Some(url) = override_url {
return Ok(url.to_string());
}
dotenvy::from_path(root.join(".env")).ok();
std::env::var(&cfg.database_url_env)
.map_err(|_| eyre!("{} is not set (env or .env)", cfg.database_url_env))
}