Skip to main content

greentic_dev/dev_runner/
schema.rs

1use serde_json::Value as JsonValue;
2use serde_yaml_bw::Value as YamlValue;
3
4pub fn validate_yaml_against_schema(node: &YamlValue, schema_json: &str) -> Result<(), String> {
5    let schema: JsonValue = serde_json::from_str(schema_json)
6        .map_err(|error| format!("invalid schema JSON: {error}"))?;
7    let node_json = serde_json::to_value(node)
8        .map_err(|error| format!("failed to convert YAML to JSON: {error}"))?;
9
10    let validator = jsonschema::validator_for(&schema)
11        .map_err(|error| format!("schema did not compile: {error}"))?;
12
13    validator
14        .validate(&node_json)
15        .map_err(|error| error.to_string())
16}
17
18pub fn schema_id_from_json(schema_json: &str) -> Option<String> {
19    let schema: JsonValue = serde_json::from_str(schema_json).ok()?;
20    schema
21        .get("$id")
22        .and_then(|value| value.as_str())
23        .map(|value| value.to_string())
24}
25
26#[cfg(test)]
27mod tests {
28    use super::{schema_id_from_json, validate_yaml_against_schema};
29    use serde_yaml_bw::Value as YamlValue;
30
31    #[test]
32    fn validates_matching_document() {
33        let node: YamlValue = serde_yaml_bw::from_str("name: demo\n").unwrap();
34        let schema = r#"{
35          "type": "object",
36          "required": ["name"],
37          "properties": {
38            "name": { "type": "string" }
39          }
40        }"#;
41
42        assert!(validate_yaml_against_schema(&node, schema).is_ok());
43    }
44
45    #[test]
46    fn rejects_invalid_schema_json() {
47        let node: YamlValue = serde_yaml_bw::from_str("name: demo\n").unwrap();
48        let err = validate_yaml_against_schema(&node, "{").unwrap_err();
49        assert!(err.contains("invalid schema JSON"));
50    }
51
52    #[test]
53    fn extracts_schema_id() {
54        let schema = r#"{"$id":"greentic://schema/demo","type":"object"}"#;
55        assert_eq!(
56            schema_id_from_json(schema).as_deref(),
57            Some("greentic://schema/demo")
58        );
59        assert!(schema_id_from_json("not json").is_none());
60    }
61}