pub mod build;
pub mod check;
pub mod doc;
pub mod doctor;
pub mod exit;
pub mod format;
pub mod generate;
pub mod lint;
pub mod output;
pub mod serve;
pub mod test;
pub mod thingd_schema;
use clap::{Parser, Subcommand};
use output::Output;
#[derive(Parser)]
#[command(
name = "arqen",
version,
about = "Arqen CLI for generating and running applications"
)]
pub struct Cli {
#[command(subcommand)]
command: Commands,
#[arg(long, global = true)]
json: bool,
#[arg(long, global = true)]
verbose: bool,
#[arg(long, global = true)]
quiet: bool,
#[arg(long, global = true, default_value = "auto")]
color: String,
}
#[derive(Subcommand)]
pub enum Commands {
New {
name: String,
},
Generate {
#[command(subcommand)]
kind: GenerateKind,
},
Dev {
#[arg(long, default_value = "127.0.0.1")]
host: String,
#[arg(short, long, default_value = "8888")]
port: u16,
#[arg(short, long, default_value = "info")]
log: String,
#[arg(short, long, default_value = "memory")]
storage: String,
#[arg(long = "file")]
config_file: Option<String>,
},
Start {
#[arg(long, default_value = "127.0.0.1")]
host: String,
#[arg(short, long, default_value = "8888")]
port: u16,
#[arg(short, long, default_value = "info")]
log: String,
#[arg(short, long, default_value = "memory")]
storage: String,
#[arg(long = "file")]
config_file: Option<String>,
},
Up {
#[arg(value_name = "SERVICE")]
services: Vec<String>,
#[arg(long, default_value = "arqen.toml")]
file: std::path::PathBuf,
#[arg(long)]
dry_run: bool,
},
Check,
Doctor,
Lint,
Format,
Test {
#[arg(long)]
release: bool,
},
Build {
#[arg(long)]
release: bool,
},
Doc,
Thingd {
#[command(subcommand)]
command: ThingdCommand,
},
}
#[derive(Subcommand)]
pub enum ThingdCommand {
SchemaValidate {
path: std::path::PathBuf,
#[arg(long)]
url: Option<String>,
#[arg(long)]
token: Option<String>,
},
SchemaRemote {
url: String,
#[arg(long)]
token: Option<String>,
},
}
#[derive(Subcommand)]
pub enum GenerateKind {
Module {
name: String,
},
Tool {
name: String,
},
Job {
name: String,
},
}
fn dispatch(cli: &Cli, output: &Output) -> anyhow::Result<()> {
match &cli.command {
Commands::New { name } => {
generate::generate_project(name, output)?;
}
Commands::Generate { kind } => match kind {
GenerateKind::Module { name } => generate::generate_module(name, output)?,
GenerateKind::Tool { name } => generate::generate_tool(name, output)?,
GenerateKind::Job { name } => generate::generate_job(name, output)?,
},
Commands::Dev {
host,
port,
log,
storage,
config_file,
} => {
let code = serve::serve_dev(config_file.as_deref(), host, *port, log, storage, output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Start {
host,
port,
log,
storage,
config_file,
} => {
let code =
serve::serve_start(config_file.as_deref(), host, *port, log, storage, output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Up {
services,
file,
dry_run,
} => {
let rt = tokio::runtime::Runtime::new().map_err(|e| anyhow::anyhow!(e))?;
rt.block_on(crate::dev::run_up(file, services, *dry_run))?;
}
Commands::Check => {
let code = check::run_check(output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Doctor => {
let code = doctor::run_doctor(output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Lint => {
let code = lint::run_lint(output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Format => {
let code = format::run_format(output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Test { release } => {
let code = test::run_test(*release, output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Build { release } => {
let code = build::run_build(*release, output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Doc => {
let code = doc::run_doc(output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
Commands::Thingd { command } => {
let code = thingd_schema::run(command, output);
if code != exit::SUCCESS {
std::process::exit(code);
}
}
}
Ok(())
}
pub fn run() -> i32 {
let cli = Cli::parse();
let output = Output::from_args(cli.json, cli.quiet, cli.verbose, &cli.color);
match dispatch(&cli, &output) {
Ok(()) => exit::SUCCESS,
Err(e) => {
output.print_error(&e.to_string());
exit::RUNTIME
}
}
}