use clap::{Parser, Subcommand};
use crate::cmd;
use crate::error::CliError;
#[derive(Parser, Debug)]
#[command(
name = "sz-rust",
bin_name = "sz-rust",
version,
about = "SZ-Rust 命令行工具 — 替代 PHP think 命令",
long_about = "SZ-Rust CLI 对齐 PHP ThinkPHP 6 think 命令体系,提供 make:migration / make:model / make:controller / migrate / route:list / cache:clear 等命令。"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Command>,
}
#[derive(Subcommand, Debug)]
pub enum Command {
#[command(name = "make")]
Make {
#[command(subcommand)]
make_command: cmd::make::MakeCommand,
},
#[command(name = "migrate")]
Migrate {
#[command(flatten)]
args: cmd::migrate::MigrateArgs,
},
#[command(name = "migrate:status")]
MigrateStatus {
#[arg(short = 'p', long, default_value = "migrations")]
path: String,
},
#[command(name = "route:list")]
RouteList {
#[arg(short = 'f', long, default_value = "table")]
format: String,
},
#[command(name = "cache:clear")]
CacheClear {
#[arg(short = 's', long)]
store: Option<String>,
},
#[command(name = "scheduler")]
Scheduler {
#[command(subcommand)]
scheduler_command: cmd::scheduler::SchedulerCommand,
},
}
impl Cli {
pub fn execute(&self) -> Result<i32, CliError> {
match &self.command {
None => {
println!("SZ-Rust CLI — 使用 --help 查看可用命令");
Ok(0)
}
Some(Command::Make { make_command }) => cmd::make::execute(make_command).map(|_| 0),
Some(Command::Migrate { args }) => cmd::migrate::execute_migrate(args).map(|_| 0),
Some(Command::MigrateStatus { path }) => cmd::migrate::execute_status(path).map(|_| 0),
Some(Command::RouteList { format }) => {
cmd::route::execute_route_list(format).map(|_| 0)
}
Some(Command::CacheClear { store }) => {
cmd::cache::execute_cache_clear(store.as_deref()).map(|_| 0)
}
Some(Command::Scheduler { scheduler_command }) => {
cmd::scheduler::execute(scheduler_command).map(|_| 0)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
#[test]
fn test_parse_make_model() {
let cli = Cli::parse_from(["sz-rust", "make", "model", "User"]);
match cli.command {
Some(Command::Make { make_command }) => {
assert!(matches!(make_command, cmd::make::MakeCommand::Model { .. }));
}
_ => panic!("expected Make command"),
}
}
#[test]
fn test_parse_make_controller() {
let cli = Cli::parse_from(["sz-rust", "make", "controller", "User"]);
match cli.command {
Some(Command::Make { make_command }) => {
assert!(matches!(
make_command,
cmd::make::MakeCommand::Controller { .. }
));
}
_ => panic!("expected Make command"),
}
}
#[test]
fn test_parse_make_migration() {
let cli = Cli::parse_from(["sz-rust", "make", "migration", "create_users"]);
match cli.command {
Some(Command::Make { make_command }) => {
assert!(matches!(
make_command,
cmd::make::MakeCommand::Migration { .. }
));
}
_ => panic!("expected Make command"),
}
}
#[test]
fn test_parse_migrate() {
let cli = Cli::parse_from(["sz-rust", "migrate"]);
assert!(matches!(cli.command, Some(Command::Migrate { .. })));
}
#[test]
fn test_parse_migrate_status() {
let cli = Cli::parse_from(["sz-rust", "migrate:status"]);
assert!(matches!(cli.command, Some(Command::MigrateStatus { .. })));
}
#[test]
fn test_parse_route_list() {
let cli = Cli::parse_from(["sz-rust", "route:list"]);
assert!(matches!(cli.command, Some(Command::RouteList { .. })));
}
#[test]
fn test_parse_cache_clear() {
let cli = Cli::parse_from(["sz-rust", "cache:clear"]);
assert!(matches!(cli.command, Some(Command::CacheClear { .. })));
}
#[test]
fn test_parse_cache_clear_with_store() {
let cli = Cli::parse_from(["sz-rust", "cache:clear", "--store", "redis"]);
match cli.command {
Some(Command::CacheClear { store }) => {
assert_eq!(store.as_deref(), Some("redis"));
}
_ => panic!("expected CacheClear command"),
}
}
#[test]
fn test_parse_scheduler() {
let cli = Cli::parse_from(["sz-rust", "scheduler", "list"]);
assert!(matches!(cli.command, Some(Command::Scheduler { .. })));
}
#[test]
fn test_execute_no_command_returns_ok() {
let cli = Cli { command: None };
let result = cli.execute();
assert!(result.is_ok());
assert_eq!(result.unwrap(), 0);
}
}