hyperi_rustlib/cli/commands.rs
1// Project: hyperi-rustlib
2// File: src/cli/commands.rs
3// Purpose: Standard CLI subcommands for DFE services
4// Language: Rust
5//
6// License: FSL-1.1-ALv2
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Standard subcommands shared across all DFE services.
10//!
11//! Every DFE service gets `run`, `version`, and `config-check` for free.
12//! The `top` subcommand is available when the `top` feature is enabled.
13
14/// Standard subcommands provided by rustlib.
15///
16/// Apps embed these via `#[command(flatten)]` in their own subcommand enum:
17///
18/// ```rust,ignore
19/// use clap::Subcommand;
20/// use hyperi_rustlib::cli::StandardCommand;
21///
22/// #[derive(Subcommand)]
23/// enum Commands {
24/// #[command(flatten)]
25/// Standard(StandardCommand),
26/// // App-specific subcommands here
27/// }
28/// ```
29#[derive(Debug, Clone, clap::Subcommand)]
30pub enum StandardCommand {
31 /// Start the service (default if no subcommand given).
32 Run,
33
34 /// Print version information and exit.
35 Version,
36
37 /// Validate configuration and exit.
38 #[command(name = "config-check")]
39 ConfigCheck,
40
41 /// Print metrics manifest JSON and exit.
42 ///
43 /// Outputs the full metric catalogue (names, types, labels, groups, buckets)
44 /// for this service. Use in CI to generate `docs/metrics-manifest.json`.
45 #[command(name = "metrics-manifest")]
46 MetricsManifest,
47
48 /// Generate all CI artefacts and exit.
49 ///
50 /// Produces metrics manifest, deployment contract, and container spec
51 /// in the specified output directory. Use in CI post-build:
52 /// `dfe-loader generate-artefacts --output-dir docs/`
53 #[command(name = "generate-artefacts")]
54 GenerateArtefacts(GenerateArtefactsArgs),
55
56 /// Live metrics dashboard (like `vector top`).
57 #[cfg(feature = "top")]
58 Top(TopArgs),
59}
60
61/// Arguments for the `generate-artefacts` subcommand.
62#[derive(Debug, Clone, clap::Args)]
63pub struct GenerateArtefactsArgs {
64 /// Output directory for generated artefacts.
65 #[arg(long = "output-dir", default_value = "docs")]
66 pub output_dir: String,
67}
68
69/// Arguments for the `top` subcommand.
70#[cfg(feature = "top")]
71#[derive(Debug, Clone, clap::Args)]
72pub struct TopArgs {
73 /// Metrics endpoint URL to poll.
74 #[arg(
75 long = "metrics-url",
76 env = "METRICS_URL",
77 default_value = "http://127.0.0.1:9090/metrics"
78 )]
79 pub metrics_url: String,
80
81 /// Poll interval in seconds.
82 #[arg(long = "interval", default_value = "2")]
83 pub interval: u64,
84
85 /// Single scrape: print metrics to stdout and exit (no TUI).
86 #[arg(long = "once")]
87 pub once: bool,
88
89 /// Output as JSON (implies --once).
90 #[arg(long = "json")]
91 pub json: bool,
92
93 /// Filter metrics by name (regex pattern).
94 #[arg(long = "filter", short = 'f')]
95 pub filter: Option<String>,
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_standard_command_variants() {
104 // Verify the enum variants exist and are constructible
105 let _ = StandardCommand::Run;
106 let _ = StandardCommand::Version;
107 let _ = StandardCommand::ConfigCheck;
108 }
109}