mecha10-core 0.6.2

Mecha10 core runtime and foundational types
Documentation
//! JSON Schema Validation for Mecha10 Configuration
//!
//! Provides validation for mecha10.json project configuration files using JSON Schema.
//! This catches configuration errors early with helpful error messages.
//!
//! # Features
//!
//! - JSON Schema v7 validation
//! - Detailed error reporting with line numbers and field paths
//! - Built-in schema for mecha10.json
//! - Custom validation rules for Mecha10-specific constraints
//! - Support for $schema references
//!
//! # Example
//!
//! ```rust
//! use mecha10::prelude::*;
//! use mecha10::schema_validation::{validate_project_config, load_and_validate_project};
//!
//! # async fn example() -> Result<()> {
//! // Validate a config file
//! validate_project_config("mecha10.json")?;
//!
//! // Load and validate in one step
//! let config = load_and_validate_project("mecha10.json")?;
//! # Ok(())
//! # }
//! ```

mod rules;
mod schemas;
mod validate;

use crate::error::{Mecha10Error, Result};
use anyhow::Context as _;
use rules::validate_custom_rules;
use serde_json::Value;
use std::fs;
use std::path::Path;
use tracing::info;

pub use schemas::{get_node_config_schema, get_project_schema};
pub use validate::{validate_node_config_json, validate_project_config, validate_project_json};

// ============================================================================
// High-Level API
// ============================================================================

/// Load and validate a project configuration file
///
/// This combines loading and validation into one convenient function.
///
/// # Example
///
/// ```rust
/// use mecha10::schema_validation::load_and_validate_project;
///
/// let config = load_and_validate_project("mecha10.json")?;
/// println!("Project: {}", config["name"]);
/// ```
pub fn load_and_validate_project<P: AsRef<Path>>(path: P) -> Result<Value> {
    let path = path.as_ref();

    // Read file
    let content = fs::read_to_string(path)
        .with_context(|| format!("Failed to read config file: {}", path.display()))
        .map_err(|e| Mecha10Error::Configuration(format!("{:#}", e)))?;

    // Parse JSON
    let config: Value = serde_json::from_str(&content)
        .with_context(|| format!("Failed to parse JSON: {}", path.display()))
        .map_err(|e| Mecha10Error::Configuration(format!("{:#}", e)))?;

    // Validate
    validate_project_json(&config)?;
    validate_custom_rules(&config)?;

    Ok(config)
}

/// Export the JSON Schema to a file
///
/// Useful for IDE integration and documentation.
///
/// # Example
///
/// ```rust
/// use mecha10::schema_validation::export_project_schema;
///
/// export_project_schema("project.schema.json")?;
/// ```
pub fn export_project_schema<P: AsRef<Path>>(path: P) -> Result<()> {
    let schema = get_project_schema();
    let json = serde_json::to_string_pretty(&schema)
        .map_err(|e| Mecha10Error::Configuration(format!("Failed to serialize schema: {}", e)))?;

    fs::write(path.as_ref(), json)
        .with_context(|| format!("Failed to write schema to: {}", path.as_ref().display()))
        .map_err(|e| Mecha10Error::Configuration(format!("{:#}", e)))?;

    info!("Exported schema to: {}", path.as_ref().display());
    Ok(())
}