mecha10-core 0.8.2

Mecha10 core runtime and foundational types
Documentation
//! Built-in JSON Schema definitions for Mecha10 configuration files.

use serde_json::Value;

const PROJECT_SCHEMA_JSON: &str = include_str!("project.schema.json");

/// Get the built-in JSON Schema for mecha10.json project configuration
pub fn get_project_schema() -> Value {
    serde_json::from_str(PROJECT_SCHEMA_JSON).expect("bundled project schema should be valid JSON")
}

#[cfg(test)]
mod tests {
    use super::*;

    /// The embedded `PROJECT_SCHEMA_JSON` is this crate's only copy of the `mecha10.json`
    /// schema -- pin that it parses, and still reflects the few things the old hand-written
    /// literal it replaced (LAB-4282 follow-up) got wrong for its entire existence: `behaviors`
    /// requiring `active` (not the stale `default`), and only `name`/`version` being required.
    #[test]
    fn get_project_schema_parses_and_requires_only_name_and_version() {
        let schema = get_project_schema();
        let required: Vec<&str> = schema["required"]
            .as_array()
            .expect("project schema should have a top-level `required` array")
            .iter()
            .filter_map(Value::as_str)
            .collect();
        assert_eq!(required, vec!["name", "version"]);
    }

    #[test]
    fn get_project_schema_behaviors_requires_active_not_default() {
        let schema = get_project_schema();
        let behaviors_ref = schema["properties"]["behaviors"]["anyOf"][0]["$ref"]
            .as_str()
            .expect("behaviors should be an anyOf with a $ref variant");
        let def_name = behaviors_ref
            .rsplit('/')
            .next()
            .expect("$ref should have a final segment");
        let behaviors = &schema["$defs"][def_name];

        assert!(behaviors["properties"].get("active").is_some());
        assert!(behaviors["properties"].get("default").is_none());
    }

    /// Legacy `nodes.drivers`/`standard`/`custom` arrays (still on disk for some older
    /// projects) must keep validating -- `NodesConfig`'s own derived schema can't express this
    /// shape, so it's spliced back in by `full_project_schema()`.
    #[test]
    fn get_project_schema_still_accepts_legacy_nodes_arrays() {
        let schema = get_project_schema();
        assert!(schema["properties"]["nodes"]["properties"].get("drivers").is_some());
        assert!(schema["definitions"].get("node").is_some());
    }
}