use std::path::PathBuf;
use std::process::ExitCode;
use clap::Parser;
#[derive(Parser, Debug)]
#[command(name = "assay-engine", version, about = "Assay workflow + auth engine")]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(clap::Subcommand, Debug)]
enum Command {
Serve {
#[arg(long, short, env = "ASSAY_ENGINE_CONFIG")]
config: PathBuf,
},
#[cfg(all(feature = "backend-postgres", feature = "backend-sqlite"))]
Migrate {
#[arg(long)]
from: String,
#[arg(long)]
to: String,
#[arg(long)]
dry_run: bool,
},
}
#[tokio::main]
async fn main() -> ExitCode {
let cli = Cli::parse();
match cli.command {
Command::Serve { config } => {
let cfg = match assay_engine::EngineConfig::from_file(&config) {
Ok(c) => c,
Err(e) => {
eprintln!("config error: {e:#}");
return ExitCode::from(2);
}
};
init_tracing(&cfg.logging.level, &cfg.logging.format);
if let Err(e) = assay_engine::run(cfg).await {
eprintln!("engine error: {e:#}");
return ExitCode::from(1);
}
ExitCode::SUCCESS
}
#[cfg(all(feature = "backend-postgres", feature = "backend-sqlite"))]
Command::Migrate { from, to, dry_run } => migrate(&from, &to, dry_run).await,
}
}
#[cfg(all(feature = "backend-postgres", feature = "backend-sqlite"))]
async fn migrate(from: &str, to: &str, dry_run: bool) -> ExitCode {
use assay_engine::migrate::{Plan, parse_source, parse_target};
init_tracing("info,sqlx=warn", "pretty");
let plan = match (parse_source(from), parse_target(to)) {
(Ok(source_dir), Ok(target_url)) => Plan {
source_dir,
target_url,
dry_run,
},
(Err(e), _) | (_, Err(e)) => {
eprintln!("migrate: {e:#}");
return ExitCode::from(2);
}
};
match assay_engine::migrate::run(plan).await {
Ok(report) => {
print!("{}", report.render());
ExitCode::SUCCESS
}
Err(e) => {
eprintln!("migrate failed: {e:#}");
ExitCode::from(1)
}
}
}
fn init_tracing(level: &str, format: &str) {
use tracing_subscriber::{EnvFilter, fmt};
let filter = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new(level))
.unwrap_or_else(|_| EnvFilter::new("info"));
let builder = fmt().with_env_filter(filter);
match format {
"json" => builder.json().init(),
_ => builder.init(),
}
}