diff --git a/src/lib.rs b/src/lib.rs index 4bb373c..9412ad9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ pg_module_magic!(); use serde_json::{json, Value}; use std::{collections::HashMap, sync::RwLock}; -use boon::{Compiler, Schemas, ValidationError, SchemaIndex}; +use boon::{Compiler, Schemas, ValidationError, SchemaIndex, CompileError}; use lazy_static::lazy_static; struct BoonCache { @@ -27,9 +27,7 @@ fn cache_json_schema(schema_id: &str, schema: JsonB) -> JsonB { let mut compiler = Compiler::new(); compiler.enable_format_assertions(); - let schema_url = format!("urn:jspg:{}", schema_id); - - if let Err(e) = compiler.add_resource(&schema_url, schema_value) { + if let Err(e) = compiler.add_resource(schema_id, schema_value) { return JsonB(json!({ "success": false, "error": { @@ -40,19 +38,42 @@ fn cache_json_schema(schema_id: &str, schema: JsonB) -> JsonB { })); } - match compiler.compile(&schema_url, &mut cache.schemas) { + match compiler.compile(schema_id, &mut cache.schemas) { Ok(sch_index) => { cache.id_to_index.insert(schema_id.to_string(), sch_index); JsonB(json!({ "success": true })) } - Err(e) => JsonB(json!({ - "success": false, - "error": { - "kind": "SchemaCompilationError", - "message": format!("Schema compilation failed: {}", e), - "schema_id": schema_id - } - })), + Err(e) => { + // Enhance error reporting by matching on the CompileError variant + let error_details = match &e { + CompileError::ValidationError { url, src } => { + // Metaschema validation failed - provide more detail + json!({ + "kind": "SchemaCompilationError", + "sub_kind": "ValidationError", // Explicitly state it's a metaschema validation error + "message": format!("Schema failed validation against its metaschema: {}", src), + "schema_id": schema_id, + "failed_at_url": url, + "validation_details": format!("{:?}", src), // Include full debug info of the validation error + }) + } + // Handle other potential compilation errors + _ => { + let error_type = format!("{:?}", e).split('(').next().unwrap_or("Unknown").to_string(); + json!({ + "kind": "SchemaCompilationError", + "sub_kind": error_type, // e.g., "InvalidJsonPointer", "UnsupportedUrlScheme" + "message": format!("Schema compilation failed: {}", e), + "schema_id": schema_id, + "details": format!("{:?}", e), // Generic debug info + }) + } + }; + JsonB(json!({ + "success": false, + "error": error_details + })) + } } } @@ -218,9 +239,13 @@ mod tests { assert!(!result.0["success"].as_bool().unwrap()); let error_obj = result.0.get("error").expect("Expected top-level 'error' object for compilation failure"); assert_eq!(error_obj.get("kind").and_then(Value::as_str), Some("SchemaCompilationError")); + assert_eq!(error_obj.get("sub_kind").and_then(Value::as_str), Some("ValidationError"), "Expected sub_kind 'ValidationError' for metaschema failure"); assert!(error_obj.get("message").and_then(Value::as_str).is_some(), "Expected 'message' field in error object"); - assert!(error_obj["message"].as_str().unwrap().contains("Schema compilation failed")); // Check content of message + assert!(error_obj["message"].as_str().unwrap().contains("Schema failed validation against its metaschema"), "Error message mismatch"); assert_eq!(error_obj.get("schema_id").and_then(Value::as_str), Some(schema_id)); + let failed_at_url = error_obj.get("failed_at_url").and_then(Value::as_str).expect("Expected 'failed_at_url' string"); + assert!(failed_at_url.ends_with(&format!("{}#", schema_id)), "failed_at_url ('{}') should end with schema_id + '#' ('{}#')", failed_at_url, schema_id); + assert!(error_obj.get("validation_details").and_then(Value::as_str).is_some(), "Expected 'validation_details' field"); } #[pg_test]