greentic_component/
cli.rs

1use anyhow::{Error, Result, bail};
2use clap::{Parser, Subcommand};
3
4use crate::cmd::{
5    self, doctor::DoctorArgs, hash::HashArgs, inspect::InspectArgs, new::NewArgs,
6    store::StoreCommand, templates::TemplatesArgs,
7};
8use crate::scaffold::engine::ScaffoldEngine;
9
10#[derive(Parser, Debug)]
11#[command(
12    name = "greentic-component",
13    about = "Toolkit for Greentic component developers",
14    version,
15    propagate_version = true,
16    arg_required_else_help = true,
17    disable_version_flag = true
18)]
19pub struct Cli {
20    #[command(subcommand)]
21    command: Commands,
22}
23
24#[derive(Subcommand, Debug)]
25enum Commands {
26    /// Scaffold a new Greentic component project
27    New(NewArgs),
28    /// List available component templates
29    Templates(TemplatesArgs),
30    /// Run component doctor checks
31    Doctor(DoctorArgs),
32    /// Inspect manifests and describe payloads
33    Inspect(InspectArgs),
34    /// Recompute manifest hashes
35    Hash(HashArgs),
36    /// Interact with the component store
37    #[command(subcommand)]
38    Store(StoreCommand),
39}
40
41pub fn main() -> Result<()> {
42    let cli = Cli::parse();
43    let engine = ScaffoldEngine::new();
44    match cli.command {
45        Commands::New(args) => cmd::new::run(args, &engine),
46        Commands::Templates(args) => cmd::templates::run(args, &engine),
47        Commands::Doctor(args) => cmd::doctor::run(args).map_err(Error::new),
48        Commands::Inspect(args) => {
49            let result = cmd::inspect::run(&args)?;
50            cmd::inspect::emit_warnings(&result.warnings);
51            if args.strict && !result.warnings.is_empty() {
52                bail!(
53                    "component-inspect: {} warning(s) treated as errors (--strict)",
54                    result.warnings.len()
55                );
56            }
57            Ok(())
58        }
59        Commands::Hash(args) => cmd::hash::run(args),
60        Commands::Store(store_cmd) => cmd::store::run(store_cmd),
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn parses_new_subcommand() {
70        let cli = Cli::try_parse_from(["greentic-component", "new", "--name", "demo", "--json"])
71            .expect("expected CLI to parse");
72        match cli.command {
73            Commands::New(args) => {
74                assert_eq!(args.name, "demo");
75                assert!(args.json);
76                assert!(!args.no_check);
77                assert!(!args.no_git);
78            }
79            _ => panic!("expected new args"),
80        }
81    }
82}