/** * Schema validation utilities using Ajv * Validates JSON payloads against canonical JSON Schemas */ import Ajv from 'ajv'; import addFormats from 'ajv-formats'; import { readFileSync } from 'fs'; import { join } from 'path'; const ajv = new Ajv({ allErrors: true, strict: false }); addFormats(ajv); // Schema cache const schemaCache = new Map(); /** * Load a JSON Schema from the schemas directory */ export function loadSchema(schemaName: string, version: string = 'v1'): any { const cacheKey = `${version}/${schemaName}`; if (schemaCache.has(cacheKey)) { return schemaCache.get(cacheKey); } const schemaPath = join( __dirname, '../../packages/schemas/jsonschema', `${schemaName}.json` ); try { const schema = JSON.parse(readFileSync(schemaPath, 'utf-8')); schemaCache.set(cacheKey, schema); return schema; } catch (error) { throw new Error(`Failed to load schema ${schemaName}: ${error}`); } } /** * Load an enum schema */ export function loadEnumSchema(enumName: string): any { const cacheKey = `enum/${enumName}`; if (schemaCache.has(cacheKey)) { return schemaCache.get(cacheKey); } const schemaPath = join( __dirname, '../../packages/schemas/enums', `${enumName}.json` ); try { const schema = JSON.parse(readFileSync(schemaPath, 'utf-8')); schemaCache.set(cacheKey, schema); return schema; } catch (error) { throw new Error(`Failed to load enum schema ${enumName}: ${error}`); } } /** * Validate a JSON object against a schema */ export function validate( schemaName: string, data: unknown, version: string = 'v1' ): { valid: boolean; data?: T; errors?: any[] } { const schema = loadSchema(schemaName, version); const validate = ajv.compile(schema); const valid = validate(data); if (valid) { return { valid: true, data: data as T }; } else { return { valid: false, errors: validate.errors || [], }; } } /** * Validate against an enum schema */ export function validateEnum( enumName: string, value: unknown ): { valid: boolean; errors?: any[] } { const schema = loadEnumSchema(enumName); const validate = ajv.compile(schema); const valid = validate(value); if (valid) { return { valid: true }; } else { return { valid: false, errors: validate.errors || [], }; } } /** * Create a validator function for a specific schema */ export function createValidator(schemaName: string, version: string = 'v1') { return (data: unknown): { valid: boolean; data?: T; errors?: any[] } => { return validate(schemaName, data, version); }; } /** * Check schema compatibility between versions */ export function checkCompatibility( oldVersion: string, newVersion: string, schemaName: string ): { compatible: boolean; breakingChanges?: string[] } { // TODO: Implement schema compatibility checking // This would compare schemas and detect breaking changes return { compatible: true }; }