use crate::bootstrap::resolve_config_path;
use zeph_core::config::Config;
use zeph_db::{DbConfig, redact_url};
pub(crate) async fn handle_db_migrate(config_path: Option<&std::path::Path>) -> anyhow::Result<()> {
let config_path = resolve_config_path(config_path);
let config = Config::load(&config_path).unwrap_or_default();
let db_url = crate::db_url::resolve_db_url(&config);
#[cfg(feature = "postgres")]
if !zeph_db::is_postgres_url(db_url) {
let safe = redact_url(db_url).unwrap_or_else(|| db_url.to_owned());
anyhow::bail!(
"postgres build requires a postgres:// or postgresql:// URL, but got: {safe:?}. \
Set database_url in [memory] config or run: \
zeph vault set ZEPH_DATABASE_URL \"postgres://user:pass@localhost:5432/zeph\""
);
}
#[cfg(feature = "sqlite")]
if zeph_db::is_postgres_url(db_url) {
let safe = redact_url(db_url).unwrap_or_else(|| db_url.to_owned());
anyhow::bail!(
"sqlite build cannot connect to a postgres:// URL: {safe:?}. \
Recompile with --features postgres or use a sqlite file path."
);
}
let display_url = redact_url(db_url).unwrap_or_else(|| db_url.to_owned());
eprintln!("Running migrations on: {display_url}");
let db_config = DbConfig {
url: db_url.to_owned(),
max_connections: 1,
pool_size: 1,
};
let _pool = db_config.connect().await?;
eprintln!("Migrations complete.");
Ok(())
}
#[cfg(test)]
mod tests {
use crate::cli::{Cli, Command, DbCommand};
use clap::Parser;
#[test]
fn db_migrate_parses() {
let cli = Cli::try_parse_from(["zeph", "db", "migrate"]).expect("parse");
assert!(matches!(
cli.command,
Some(Command::Db {
command: DbCommand::Migrate
})
));
}
#[cfg(feature = "postgres")]
#[test]
fn is_postgres_url_accepts_postgres_schemes() {
assert!(zeph_db::is_postgres_url("postgres://localhost/test"));
assert!(zeph_db::is_postgres_url("postgresql://localhost/test"));
assert!(!zeph_db::is_postgres_url("/tmp/test.db"));
assert!(!zeph_db::is_postgres_url("sqlite:///tmp/test.db"));
}
#[cfg(feature = "sqlite")]
#[test]
fn is_postgres_url_rejects_sqlite_paths() {
assert!(!zeph_db::is_postgres_url("/tmp/test.db"));
assert!(!zeph_db::is_postgres_url("sqlite:///tmp/test.db"));
assert!(zeph_db::is_postgres_url("postgres://localhost/test"));
assert!(zeph_db::is_postgres_url("postgresql://localhost/test"));
}
}