Skip to main content

serverust_cli/
lib.rs

1//! CLI do framework **serverust**, com paridade conceitual ao `@nestjs/cli`.
2//!
3//! O binário `serverust` provê comandos para scaffolding e workflow de
4//! desenvolvimento/deploy:
5//!
6//! ```text
7//! serverust new <name>                       # cria um projeto novo
8//! serverust generate <kind> <name>           # scaffolding (resource, module, ...)
9//! serverust dev                              # cargo watch -x run
10//! serverust build [--release]                # cargo build
11//! serverust deploy lambda [--arch arm64|x86_64]
12//! serverust info                             # versões e features
13//! serverust openapi --out openapi.json       # exporta spec sem subir servidor
14//! ```
15//!
16//! Este crate expõe também a lib (`serverust_cli`) com módulos
17//! [`cli`] (definições clap), [`commands`] (construção testável de
18//! `std::process::Command`), [`scaffold`] (IO em base dir parametrizada) e
19//! [`templates`] (strings de scaffolding). A separação permite testar parse +
20//! geração de arquivos em tempdir sem spawn de processos reais.
21
22pub mod cli;
23pub mod commands;
24pub mod scaffold;
25pub mod templates;
26
27use anyhow::Result;
28
29use crate::cli::{Cli, Command, DeployTarget};
30
31/// Executa um comando da CLI já parseado.
32///
33/// Operações de IO (criação de arquivos, spawn de processos) são executadas
34/// aqui; a separação em módulos mantém a lógica testável sem efeitos colaterais.
35pub fn run(cli: Cli) -> Result<()> {
36    match cli.command {
37        Command::New { name } => {
38            let cwd = std::env::current_dir()?;
39            scaffold::new_project(&cwd, &name)?;
40            println!("✓ project created at {}/{}", cwd.display(), name);
41            Ok(())
42        }
43        Command::Generate { kind, name } => {
44            let cwd = std::env::current_dir()?;
45            scaffold::generate(&cwd, kind, &name)?;
46            println!("✓ {kind:?} '{name}' generated");
47            Ok(())
48        }
49        Command::Dev => spawn_status(commands::dev_cargo_command(), "dev"),
50        Command::Build { release } => spawn_status(commands::build_cargo_command(release), "build"),
51        Command::Deploy { target } => match target {
52            DeployTarget::Lambda { arch } => {
53                spawn_status(commands::deploy_lambda_cargo_command(arch), "deploy lambda")
54            }
55        },
56        Command::Info => {
57            println!("{}", commands::info_text());
58            Ok(())
59        }
60        Command::Openapi { out } => spawn_status(commands::openapi_export_command(&out), "openapi"),
61    }
62}
63
64fn spawn_status(mut cmd: std::process::Command, label: &str) -> Result<()> {
65    let status = cmd
66        .status()
67        .map_err(|e| anyhow::anyhow!("failed to spawn {label}: {e}"))?;
68    if !status.success() {
69        anyhow::bail!("{label} failed with status {status}");
70    }
71    Ok(())
72}