Skip to main content

schemaui_cli/
cli.rs

1use std::path::PathBuf;
2
3use clap::{ArgAction, Parser, Subcommand};
4
5#[cfg(feature = "web")]
6use std::net::IpAddr;
7
8#[derive(Debug, Parser)]
9#[command(
10    name = "schemaui",
11    version,
12    about = "Render JSON Schemas as interactive TUIs or Web UIs"
13)]
14pub struct Cli {
15    #[command(flatten)]
16    pub common: CommonArgs,
17
18    #[command(subcommand)]
19    pub command: Option<Commands>,
20}
21
22#[derive(Debug, Subcommand)]
23pub enum Commands {
24    /// Launch the interactive terminal UI
25    Tui,
26
27    #[cfg(feature = "web")]
28    /// Launch the interactive web UI instead of the terminal UI
29    Web(WebCommand),
30
31    #[cfg(feature = "web")]
32    /// Precompute Web session snapshots instead of launching the UI
33    WebSnapshot(WebSnapshotCommand),
34
35    /// Precompute TUI FormSchema/LayoutNavModel modules instead of launching the UI
36    TuiSnapshot(TuiSnapshotCommand),
37}
38
39#[cfg(feature = "web")]
40#[derive(Debug, Parser, Clone)]
41pub struct WebCommand {
42    #[command(flatten)]
43    pub common: CommonArgs,
44
45    /// Bind address for the temporary HTTP server
46    #[rustfmt::skip]
47    #[arg(alias = "bind", alias = "listen")]
48    #[arg( short = 'l', long = "host", value_name = "IP", default_value = "127.0.0.1" )]
49    pub host: IpAddr,
50
51    /// Bind port for the temporary HTTP server (0 picks a random free port)
52    #[arg(short = 'p', long = "port", value_name = "PORT", default_value_t = 0)]
53    pub port: u16,
54}
55
56#[cfg(feature = "web")]
57#[derive(Debug, Parser, Clone)]
58pub struct WebSnapshotCommand {
59    #[command(flatten)]
60    pub common: CommonArgs,
61
62    /// Output directory for generated Web snapshots (JSON + TS)
63    #[arg(long = "out-dir", value_name = "DIR", default_value = "web_snapshots")]
64    pub out_dir: PathBuf,
65
66    /// Name of the exported constant in the generated TS module
67    #[arg(
68        long = "ts-export",
69        value_name = "NAME",
70        default_value = "SessionSnapshot"
71    )]
72    pub ts_export: String,
73}
74
75#[derive(Debug, Parser, Clone)]
76pub struct TuiSnapshotCommand {
77    #[command(flatten)]
78    pub common: CommonArgs,
79
80    /// Output directory for generated TUI artifact modules (Rust source)
81    #[arg(long = "out-dir", value_name = "DIR", default_value = "tui_artifacts")]
82    pub out_dir: PathBuf,
83
84    /// Name of the generated TuiArtifacts constructor function
85    #[arg(long = "tui-fn", value_name = "NAME", default_value = "tui_artifacts")]
86    pub tui_fn: String,
87
88    /// Name of the generated FormSchema constructor function
89    #[arg(
90        long = "form-fn",
91        value_name = "NAME",
92        default_value = "tui_form_schema"
93    )]
94    pub form_fn: String,
95
96    /// Name of the generated LayoutNavModel constructor function
97    #[arg(
98        long = "layout-fn",
99        value_name = "NAME",
100        default_value = "tui_layout_nav"
101    )]
102    pub layout_fn: String,
103}
104
105#[derive(Debug, Parser, Clone)]
106pub struct CommonArgs {
107    /// Schema spec: file path, inline payload, or "-" for stdin
108    #[arg(short = 's', long = "schema", value_name = "SPEC")]
109    pub schema: Option<String>,
110
111    /// Config spec: file path, inline payload, or "-" for stdin
112    #[arg(short = 'c', long = "config", alias = "data", value_name = "SPEC")]
113    pub config: Option<String>,
114
115    /// Title shown at the top of the UI
116    #[arg(long = "title", value_name = "TEXT")]
117    pub title: Option<String>,
118
119    /// Output destinations ("-" writes to stdout). Accepts multiple values per flag use.
120    #[arg(short = 'o', long = "output", value_name = "DEST", num_args = 1.., action = ArgAction::Append)]
121    pub outputs: Vec<String>,
122
123    /// Override the default temp file location (only used when no other destinations are set)
124    #[arg(long = "temp-file", value_name = "PATH")]
125    pub temp_file: Option<PathBuf>,
126
127    /// Disable writing to the default temp file when no destinations are provided
128    #[arg(long = "no-temp-file")]
129    pub no_temp_file: bool,
130
131    /// Emit compact JSON/TOML rather than pretty formatting
132    #[arg(long = "no-pretty")]
133    pub no_pretty: bool,
134
135    /// Overwrite output files even if they already exist
136    #[arg(short = 'f', long = "force", short_alias = 'y', alias = "yes")]
137    pub force: bool,
138}