secrets_core/
spec_schema.rs1use crate::SecretSpec;
2use serde_json::{Map, Value, json};
3use std::collections::BTreeMap;
4
5pub fn specs_to_json_schema<'a>(specs: impl Iterator<Item = &'a SecretSpec>) -> Value {
11 let mut ordered: BTreeMap<&'a str, &'a SecretSpec> = BTreeMap::new();
12 for spec in specs {
13 ordered.insert(spec.name, spec);
14 }
15
16 let mut properties = Map::new();
17 for spec in ordered.values() {
18 properties.insert(
19 spec.name.to_string(),
20 json!({
21 "type": "string",
22 "description": spec.description.unwrap_or(""),
23 }),
24 );
25 }
26
27 json!({
28 "type": "object",
29 "properties": properties,
30 })
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use crate::{SecretDescribable, SecretSpec};
37
38 struct DemoA;
39 struct DemoB;
40
41 impl SecretDescribable for DemoA {
42 fn secret_specs() -> &'static [SecretSpec] {
43 &[
44 SecretSpec {
45 name: "ALPHA",
46 description: Some("alpha description"),
47 },
48 SecretSpec {
49 name: "OMEGA",
50 description: None,
51 },
52 ]
53 }
54 }
55
56 impl SecretDescribable for DemoB {
57 fn secret_specs() -> &'static [SecretSpec] {
58 &[SecretSpec {
59 name: "BETA",
60 description: Some("beta description"),
61 }]
62 }
63 }
64
65 #[test]
66 fn schema_properties_are_stably_ordered() {
67 let schema = specs_to_json_schema(
68 DemoA::secret_specs()
69 .iter()
70 .chain(DemoB::secret_specs().iter()),
71 );
72
73 let object = schema.as_object().expect("schema object");
74 assert_eq!(object.get("type").and_then(Value::as_str), Some("object"));
75
76 let properties = object
77 .get("properties")
78 .and_then(Value::as_object)
79 .expect("properties map");
80
81 let ordered_keys: Vec<_> = properties.keys().cloned().collect();
82 assert_eq!(ordered_keys, vec!["ALPHA", "BETA", "OMEGA"]);
83
84 let alpha = properties
85 .get("ALPHA")
86 .and_then(Value::as_object)
87 .expect("alpha schema");
88 assert_eq!(alpha.get("type").and_then(Value::as_str), Some("string"));
89 assert_eq!(
90 alpha.get("description").and_then(Value::as_str),
91 Some("alpha description")
92 );
93 }
94}