UNPKG

@sailboat-computer/event-bus

Version:

Standardized event bus for sailboat computer v3 with resilience features and offline capabilities

172 lines (147 loc) 3.48 kB
/** * Event schema validation */ import Ajv from 'ajv'; import { EventEnvelope } from './types'; // Define JSON Schema type type JSONSchemaType<T> = { type: string; properties?: Record<string, any>; required?: string[]; additionalProperties?: boolean; [key: string]: any; }; import { logger } from './utils'; /** * Schema registry for event validation */ export class SchemaRegistry { /** * Ajv instance */ private ajv: any; /** * Schema map */ private schemas: Map<string, JSONSchemaType<any>> = new Map(); /** * Constructor */ constructor() { this.ajv = new Ajv({ allErrors: true, removeAdditional: false, useDefaults: true, coerceTypes: false }); } /** * Register a schema for an event type * * @param eventType - Event type * @param schema - JSON schema */ registerSchema<T>(eventType: string, schema: JSONSchemaType<T>): void { if (this.schemas.has(eventType)) { logger.warn(`Schema for event type ${eventType} already registered, overwriting`); // Remove existing schema before adding a new one this.ajv.removeSchema(eventType); } this.schemas.set(eventType, schema); this.ajv.addSchema(schema, eventType); logger.debug(`Registered schema for event type ${eventType}`); } /** * Validate an event against its schema * * @param event - Event envelope * @returns Validation result */ validate(event: EventEnvelope): ValidationResult { const eventType = event.type; if (!this.schemas.has(eventType)) { return { valid: true, errors: null }; } const validate = this.ajv.getSchema(eventType); if (!validate) { logger.warn(`Schema for event type ${eventType} not found in AJV`); return { valid: true, errors: null }; } const valid = validate(event.data); if (!valid) { return { valid: false, errors: validate.errors || null }; } return { valid: true, errors: null }; } /** * Check if a schema is registered for an event type * * @param eventType - Event type * @returns True if a schema is registered */ hasSchema(eventType: string): boolean { return this.schemas.has(eventType); } /** * Get a schema for an event type * * @param eventType - Event type * @returns JSON schema or null if not found */ getSchema(eventType: string): JSONSchemaType<any> | null { return this.schemas.get(eventType) || null; } /** * Remove a schema for an event type * * @param eventType - Event type */ removeSchema(eventType: string): void { if (this.schemas.has(eventType)) { this.schemas.delete(eventType); this.ajv.removeSchema(eventType); logger.debug(`Removed schema for event type ${eventType}`); } } /** * Clear all schemas */ clearSchemas(): void { this.schemas.clear(); this.ajv.removeSchema(); logger.debug('Cleared all schemas'); } } /** * Validation result */ export interface ValidationResult { /** * Whether the validation passed */ valid: boolean; /** * Validation errors */ errors: any[] | null; } /** * Create a schema registry * * @returns Schema registry */ export function createSchemaRegistry(): SchemaRegistry { return new SchemaRegistry(); }