UNPKG

fortify-schema

Version:

TypeScript interface-like schema validation system that's easier to use than Zod

114 lines (90 loc) 3.57 kB
import { FieldValidationResult, ValidationResult } from "../../../../types/extension.type"; import { SchemaInterface } from "../../../../types/SchemaValidator.type"; import { ValidationEngine } from "../../mods"; /** * Live validator for real-time validation */ export class LiveValidator { private currentData: any = {}; private currentErrors: Record<string, string[]> = {}; private listeners: Array<(result: ValidationResult) => void> = []; private fieldListeners: Record<string, Array<(result: FieldValidationResult) => void>> = {}; constructor(private schema: SchemaInterface) {} /** * Validate a single field in real-time */ validateField(fieldName: string, value: any): FieldValidationResult { this.currentData[fieldName] = value; // Use modular validation engine const fieldSchema = (this.schema as any)[fieldName]; const validationResult = ValidationEngine.validateField(fieldSchema, value); this.currentErrors[fieldName] = validationResult.errors; const result: FieldValidationResult = { field: fieldName, value, isValid: validationResult.isValid, errors: validationResult.errors }; // Notify field listeners if (this.fieldListeners[fieldName]) { this.fieldListeners[fieldName].forEach(listener => listener(result)); } // Notify global listeners this.notifyListeners(); return result; } /** * Validate all current data */ validateAll(): ValidationResult { const validationResult = ValidationEngine.validateObject(this.schema, this.currentData); // Update current errors with validation results this.currentErrors = validationResult.errors; const result: ValidationResult = { isValid: validationResult.isValid, data: this.currentData, errors: this.currentErrors, timestamp: new Date() }; // Notify listeners after creating the result this.listeners.forEach(listener => listener(result)); return result; } /** * Listen for validation changes */ onValidation(listener: (result: ValidationResult) => void): void { this.listeners.push(listener); } /** * Listen for specific field validation */ onFieldValidation(fieldName: string, listener: (result: FieldValidationResult) => void): void { if (!this.fieldListeners[fieldName]) { this.fieldListeners[fieldName] = []; } this.fieldListeners[fieldName].push(listener); } /** * Get current validation state */ get isValid(): boolean { return Object.values(this.currentErrors).every(errors => errors.length === 0); } get errors(): Record<string, string[]> { return { ...this.currentErrors }; } get data(): any { return { ...this.currentData }; } private notifyListeners(): void { // Create validation result without calling validateAll to avoid recursion const result: ValidationResult = { isValid: Object.values(this.currentErrors).every(errors => errors.length === 0), data: this.currentData, errors: this.currentErrors, timestamp: new Date() }; this.listeners.forEach(listener => listener(result)); } }