use clap::Subcommand;
use sea_orm_cli::{
handle_error, run_generate_command, run_migrate_command, Commands, GenerateSubcommands,
};
#[derive(Subcommand)]
#[allow(clippy::large_enum_variant)]
pub enum DbCommand {
Create,
#[command(flatten)]
SeaOrm(Commands),
}
const DEFAULT_MIGRATION_DIR: &str = "db/migration";
const DEFAULT_ENTITY_OUTPUT_DIR: &str = "app/models/_entities";
const SEA_ORM_CLI_DEFAULT_MIGRATION_DIR: &str = "./migration";
const SEA_ORM_CLI_DEFAULT_OUTPUT_DIR: &str = "./";
pub fn ensure_database_url_from_config() {
if std::env::var_os("DATABASE_URL").is_some() {
return;
}
if let Ok(config) = doido_model::config::YamlConfig::load() {
std::env::set_var("DATABASE_URL", config.database.url);
}
}
pub async fn run(command: DbCommand, verbose: bool) {
match command {
DbCommand::Create => create().await,
DbCommand::SeaOrm(command) => run_sea_orm(command, verbose).await,
}
}
async fn create() {
let url = database_url();
match doido_model::create_database(&url).await {
Ok(()) => doido_core::tracing::info!("created database: {url}"),
Err(e) if e.to_string().contains("already exists") => {
doido_core::tracing::info!("database already exists: {url}");
}
Err(e) => handle_error(e),
}
}
fn database_url() -> String {
if let Ok(url) = std::env::var("DATABASE_URL") {
return url;
}
if let Ok(config) = doido_model::config::YamlConfig::load() {
return config.database.url;
}
doido_core::tracing::error!("DATABASE_URL is not set and config/<env>.yml could not be read");
std::process::exit(1);
}
async fn run_sea_orm(command: Commands, verbose: bool) {
match command {
Commands::Generate { mut command } => {
apply_entity_output_default(&mut command);
run_generate_command(command, verbose)
.await
.unwrap_or_else(handle_error);
}
Commands::Migrate {
migration_dir,
database_schema,
database_url,
command,
} => {
let migration_dir = override_migration_dir(migration_dir);
run_migrate_command(
command,
&migration_dir,
database_schema,
database_url,
verbose,
)
.unwrap_or_else(handle_error);
}
}
}
fn override_migration_dir(migration_dir: String) -> String {
if migration_dir == SEA_ORM_CLI_DEFAULT_MIGRATION_DIR {
DEFAULT_MIGRATION_DIR.to_string()
} else {
migration_dir
}
}
fn apply_entity_output_default(command: &mut GenerateSubcommands) {
let GenerateSubcommands::Entity { output_dir, .. } = command;
if output_dir == SEA_ORM_CLI_DEFAULT_OUTPUT_DIR {
*output_dir = DEFAULT_ENTITY_OUTPUT_DIR.to_string();
}
}