ggen_cli_lib/cmds/project/
mod.rs

1use clap::{Args, Subcommand};
2use ggen_utils::error::Result;
3
4// Declare verb modules
5pub mod apply;
6pub mod diff;
7pub mod freeze;
8pub mod gen;
9pub mod inject;
10pub mod plan;
11pub mod test;
12pub mod validate;
13pub mod watch;
14
15#[derive(Args, Debug)]
16pub struct ProjectCmd {
17    #[command(subcommand)]
18    pub verb: Verb,
19}
20
21#[derive(Subcommand, Debug)]
22pub enum Verb {
23    /// Generate artifacts from a template directly
24    ///
25    /// Examples:
26    ///   ggen project gen "rust-cli-template" --var name=myapp
27    ///   ggen project gen "web-api.tmpl" --dry-run
28    ///   ggen project gen "template.tmpl" --seed 12345
29    Gen(gen::GenArgs),
30
31    /// Create a machine-readable plan of changes without applying them (dry-run)
32    ///
33    /// Examples:
34    ///   ggen project plan "rust-cli-template" --var name=myapp
35    ///   ggen project plan "template.tmpl" --format yaml
36    Plan(plan::PlanArgs),
37
38    /// Apply a previously generated plan to the filesystem
39    ///
40    /// Examples:
41    ///   ggen project apply plan.json
42    ///   ggen project apply plan.yaml --dry-run
43    Apply(apply::ApplyArgs),
44
45    /// Show a unified diff of what a generation would change
46    ///
47    /// Examples:
48    ///   ggen project diff "rust-cli-template" --var name=myapp
49    ///   ggen project diff "template.tmpl" --var version=1.0.0
50    Diff(diff::DiffArgs),
51
52    /// Run golden file snapshot tests for templates
53    ///
54    /// Examples:
55    ///   ggen project test "template.tmpl" --golden expected/
56    ///   ggen project test "rust-cli.tmpl" --golden golden/ --update
57    ///   ggen project test "*.tmpl" --golden snapshots/ --json
58    Test(test::TestArgs),
59
60    /// Add freeze blocks to generated files for immutability
61    ///
62    /// Examples:
63    ///   ggen project freeze "src/main.rs" --blocks "impl,business_logic"
64    ///   ggen project freeze "src/" --blocks "custom" --recursive
65    ///   ggen project freeze "app.ts" --blocks "config,routes" --dry-run
66    Freeze(freeze::FreezeArgs),
67
68    /// Inject code idempotently into existing files
69    ///
70    /// Examples:
71    ///   ggen project inject "src/mod.rs" --anchor "// IMPORTS" --content "use foo;"
72    ///   ggen project inject "main.rs" --anchor "fn main()" --content "println!(\"hello\");" --after
73    ///   ggen project inject "config.toml" --anchor "[dependencies]" --content "serde = \"1.0\"" --dry-run
74    Inject(inject::InjectArgs),
75
76    /// Validate plan files or generated output
77    ///
78    /// Examples:
79    ///   ggen project validate plan.json
80    ///   ggen project validate generated/ --recursive
81    ///   ggen project validate output.rs --schema rust-file.schema.json
82    ///   ggen project validate plan.yaml --verbose --json
83    Validate(validate::ValidateArgs),
84
85    /// Watch templates and continuously regenerate on changes
86    ///
87    /// Examples:
88    ///   ggen project watch "*.tmpl" --target src/
89    ///   ggen project watch "templates/" --target output/ --recursive
90    ///   ggen project watch "api.tmpl" --target api/ --debounce 1000 --var env=dev
91    Watch(watch::WatchArgs),
92}
93
94impl ProjectCmd {
95    pub async fn run(&self) -> Result<()> {
96        match &self.verb {
97            Verb::Gen(args) => gen::run(args).await,
98            Verb::Plan(args) => plan::run(args).await,
99            Verb::Apply(args) => apply::run(args).await,
100            Verb::Diff(args) => diff::run(args).await,
101            Verb::Test(args) => test::run(args).await,
102            Verb::Freeze(args) => freeze::run(args).await,
103            Verb::Inject(args) => inject::run(args).await,
104            Verb::Validate(args) => validate::run(args).await,
105            Verb::Watch(args) => watch::run(args).await,
106        }
107    }
108}