Skip to main content

rain_metadata/cli/schema/
show.rs

1use clap::Parser;
2use std::path::PathBuf;
3use crate::meta::KnownMeta;
4use crate::cli::output::SupportedOutputEncoding;
5use super::json_schema;
6
7#[derive(Parser)]
8pub struct Show {
9    /// One of a set of known JSON schemas that can be produced to match a subset
10    /// of the validation performed on known metas. Additional validation beyond
11    /// what can be expressed by JSON schema is performed when parsing and
12    /// validating metadata.
13    #[arg(value_parser = clap::value_parser!(KnownMeta))]
14    schema: KnownMeta,
15    /// If provided the schema will be written to the given path instead of
16    /// stdout.
17    #[arg(short, long)]
18    output_path: Option<PathBuf>,
19    /// If true the schema will be pretty printed. Defaults to false.
20    #[arg(short, long)]
21    pretty_print: bool,
22}
23
24pub fn show(s: Show) -> anyhow::Result<()> {
25    let schema_json = json_schema(s.schema)
26        .ok_or_else(|| anyhow::anyhow!("Unsupported for {} meta", s.schema))?;
27    let schema_string = if s.pretty_print {
28        serde_json::to_string_pretty(&schema_json)?
29    } else {
30        serde_json::to_string(&schema_json)?
31    };
32
33    crate::cli::output::output(
34        &s.output_path,
35        SupportedOutputEncoding::Binary,
36        schema_string.as_bytes(),
37    )
38}
39
40#[cfg(all(test, not(target_family = "wasm")))]
41mod tests {
42    use super::*;
43
44    fn show_to_string(schema: KnownMeta, pretty_print: bool) -> anyhow::Result<String> {
45        let file = tempfile::NamedTempFile::new().unwrap();
46        let path = file.path().to_path_buf();
47        show(Show {
48            schema,
49            output_path: Some(path.clone()),
50            pretty_print,
51        })?;
52        Ok(std::fs::read_to_string(&path).unwrap())
53    }
54
55    /// Each supported meta produces its own schema; compact output by
56    /// default (no newlines).
57    #[test]
58    fn test_show_authoring_v1_schema_compact() {
59        let s = show_to_string(KnownMeta::AuthoringMetaV1, false).unwrap();
60        let v: serde_json::Value = serde_json::from_str(&s).unwrap();
61        assert!(s.contains("AuthoringMeta"), "{}", v["title"]);
62        assert!(!s.contains('\n'));
63    }
64
65    /// OpV1 is a known meta with no schema here, so show refuses it rather
66    /// than producing one.
67    #[test]
68    fn test_show_refuses_op_v1() {
69        assert!(show_to_string(KnownMeta::OpV1, false).is_err());
70    }
71
72    /// The pretty flag pretty-prints the same schema.
73    #[test]
74    fn test_show_pretty_print() {
75        let s = show_to_string(KnownMeta::AuthoringMetaV1, true).unwrap();
76        assert!(s.starts_with("{\n"));
77        let v: serde_json::Value = serde_json::from_str(&s).unwrap();
78        assert!(v["title"].is_string());
79    }
80
81    /// All three supported arms return the schema of their own meta type.
82    #[test]
83    fn test_show_supported_schemas_are_distinct() {
84        let authoring = show_to_string(KnownMeta::AuthoringMetaV1, false).unwrap();
85        assert!(authoring.contains("AuthoringMeta"));
86        let solidity = show_to_string(KnownMeta::SolidityAbiV2, false).unwrap();
87        assert!(solidity.contains("SolidityAbi"));
88        let caller = show_to_string(KnownMeta::InterpreterCallerMetaV1, false).unwrap();
89        assert!(caller.contains("InterpreterCallerMeta"));
90        for pair in [
91            (&authoring, &solidity),
92            (&authoring, &caller),
93            (&solidity, &caller),
94        ] {
95            assert_ne!(pair.0, pair.1);
96        }
97    }
98
99    /// Metas without a JSON schema error with the exact unsupported
100    /// message.
101    #[test]
102    fn test_show_unsupported_meta_error() {
103        let file = tempfile::NamedTempFile::new().unwrap();
104        let err = show(Show {
105            schema: KnownMeta::DotrainV1,
106            output_path: Some(file.path().to_path_buf()),
107            pretty_print: false,
108        })
109        .unwrap_err();
110        assert_eq!(err.to_string(), "Unsupported for dotrain-v1 meta");
111    }
112}