mod collection;
mod request;
use crate::{
GlobalArgs, Subcommand,
commands::db::{
collection::DbCollectionCommand, request::DbRequestCommand,
},
};
use anyhow::Context;
use clap::Parser;
use slumber_core::database::Database;
use std::process::ExitCode;
use tokio::process::Command;
#[derive(Clone, Debug, Parser)]
#[expect(rustdoc::invalid_html_tags)]
#[expect(rustdoc::bare_urls)]
#[clap(verbatim_doc_comment)]
pub struct DbCommand {
#[command(subcommand)]
subcommand: Option<DbSubcommand>,
#[clap(short = 'x', long, default_value = "sqlite3")]
exec: String,
#[clap(num_args = 1.., verbatim_doc_comment)]
args: Vec<String>,
#[clap(long)]
path: bool,
}
#[derive(Clone, Debug, clap::Subcommand)]
enum DbSubcommand {
#[command(visible_alias = "coll")]
Collection(DbCollectionCommand),
#[command(visible_alias = "rq")]
Request(DbRequestCommand),
}
impl Subcommand for DbCommand {
async fn execute(self, global: GlobalArgs) -> anyhow::Result<ExitCode> {
match self.subcommand {
None => {
let path = Database::path();
if self.path {
println!("{}", path.display());
return Ok(ExitCode::SUCCESS);
}
let exit_status = Command::new(self.exec)
.arg(&path)
.args(self.args)
.spawn()
.with_context(|| {
format!(
"Error opening database file `{}`",
path.display()
)
})?
.wait()
.await?;
let exit_code =
exit_status.code().and_then(|code| u8::try_from(code).ok());
if let Some(code) = exit_code {
Ok(code.into())
} else if exit_status.success() {
Ok(ExitCode::SUCCESS)
} else {
Ok(ExitCode::FAILURE)
}
}
Some(DbSubcommand::Collection(command)) => {
command.execute(global).await
}
Some(DbSubcommand::Request(command)) => {
command.execute(global).await
}
}
}
}