pimalaya_cli/clap/commands/json_schema.rs
1use std::{collections::BTreeMap, fs, path::PathBuf};
2
3use anyhow::Result;
4use clap::Parser;
5use log::info;
6use serde_json::Value;
7
8use crate::{clap::parsers::path_parser, printer::Printer};
9
10/// Generate JSON Schemas of every command's JSON output to the given
11/// directory.
12///
13/// This command allows you to generate one JSON Schema per command
14/// describing the structure of its `--json` output, to the given
15/// directory. If the directory does not exist, it will be created. Any
16/// existing schema will be overriden.
17#[derive(Debug, Parser)]
18pub struct JsonSchemaCommand {
19 /// Directory where JSON Schema files should be generated in.
20 #[arg(value_parser = path_parser)]
21 pub dir: PathBuf,
22}
23
24impl JsonSchemaCommand {
25 /// Generates one `<command>.json` schema file per entry and reports
26 /// how many landed where.
27 ///
28 /// The map is keyed by command name (e.g. `himalaya-envelope-list`)
29 /// and valued by the already-built JSON Schema of that command's
30 /// output, mirroring how [`ManualCommand`] renders one man page per
31 /// subcommand. Callers own the command-to-schema mapping since the
32 /// output shapes live in the binary, not in this toolkit.
33 ///
34 /// [`ManualCommand`]: crate::clap::commands::ManualCommand
35 pub fn execute(
36 self,
37 printer: &mut impl Printer,
38 schemas: BTreeMap<String, Value>,
39 ) -> Result<()> {
40 let dir = &self.dir;
41 let count = schemas.len();
42
43 fs::create_dir_all(dir)?;
44
45 for (name, schema) in schemas {
46 let json = serde_json::to_vec_pretty(&schema)?;
47 info!("generate JSON Schema for command {name}");
48 fs::write(dir.join(format!("{name}.json")), json)?;
49 }
50
51 printer.out(format!(
52 "{count} JSON Schema(s) successfully generated in {}",
53 dir.display()
54 ))
55 }
56}