ryo-app 0.1.0

[preview] Application layer for RYO - Project management, Intent handling, API
Documentation
//! JSON Schema generation for RYO DSL types.
//!
//! Provides auto-generated schemas derived from Rust types, ensuring
//! documentation stays in sync with the code.

use crate::intent::Goal;

/// Generate JSON Schema for the Goal type (the complete DSL structure).
///
/// This includes:
/// - Goal (top-level structure)
/// - Intent (all 30+ variants)
/// - Pattern, IdentKind, Visibility, Location
/// - ScopeHint, EstimatedScope, Constraint
/// - ItemKind
#[cfg(feature = "schemars")]
pub fn generate_goal_schema() -> schemars::Schema {
    schemars::schema_for!(Goal)
}

/// Generate JSON Schema as a pretty-printed JSON string.
#[cfg(feature = "schemars")]
pub fn generate_goal_schema_json() -> String {
    let schema = generate_goal_schema();
    serde_json::to_string_pretty(&schema).expect("Schema serialization should never fail")
}

#[cfg(all(test, feature = "schemars"))]
mod tests {
    use super::*;

    #[test]
    fn test_schema_generation() {
        let schema = generate_goal_schema();

        // Verify root has title (schemars 1.x uses title instead of metadata)
        assert!(schema.get("title").is_some() || schema.get("$ref").is_some());

        // Verify definitions exist (schemars 1.x uses $defs)
        let defs = schema.pointer("/$defs").expect("$defs should exist");
        let defs_obj = defs.as_object().expect("$defs should be an object");
        assert!(
            defs_obj.contains_key("Intent"),
            "Intent should be in definitions"
        );
        assert!(
            defs_obj.contains_key("ScopeHint"),
            "ScopeHint should be in definitions"
        );
        assert!(
            defs_obj.contains_key("Constraint"),
            "Constraint should be in definitions"
        );
    }

    #[test]
    fn test_schema_json_output() {
        let json = generate_goal_schema_json();

        // Should be valid JSON
        let parsed: serde_json::Value = serde_json::from_str(&json).expect("Should be valid JSON");

        // Should have $schema field
        assert!(parsed.get("$schema").is_some());

        // Should have $defs (schemars 1.x)
        assert!(parsed.get("$defs").is_some());
    }

    #[test]
    fn test_intent_variants_in_schema() {
        let schema = generate_goal_schema();
        let intent_def = schema
            .pointer("/$defs/Intent")
            .expect("Intent should exist");

        // Intent uses #[serde(tag = "type")] so it should have oneOf with type discriminator
        // The schema should contain variant information
        assert!(!format!("{:?}", intent_def).is_empty());
    }
}