import { DomainError } from "./domain-error"; /** * Error de validación de dominio. * * - Extiende DomainError para aprovechar `code`, `metadata`, `cause` y `toJSON`. * - Estructura estable para mapeo (Problem+JSON / telemetría). */ export class DomainValidationError extends DomainError { /** Discriminante para routing/telemetría */ public readonly kind = "VALIDATION" as const; /** Regla/identificador de error de validación (ej. INVALID_EMAIL) */ public readonly code: string; /** Campo afectado (path) */ public readonly field: string; /** Mensaje legible de negocio */ public readonly detail: string; constructor( code: string, field: string, detail: string, options?: ErrorOptions & { metadata?: Record } ) { // Mensaje humano compacto y útil para logs super(`[${field}] ${detail}`, code, { ...options, // Aseguramos metadatos ricos y estables metadata: { ...(options?.metadata ?? {}), field, detail, kind: "VALIDATION", }, }); this.name = "DomainValidationError"; this.code = code; this.field = field; this.detail = detail; Object.setPrototypeOf(this, new.target.prototype); Object.freeze(this); } /** Atajos de construcción comunes */ static requiredValue( field: string, options?: ErrorOptions & { metadata?: Record } ) { return new DomainValidationError("REQUIRED_VALUE", field, "cannot be empty", options); } static invalidFormat( field: string, detail = "invalid format", options?: ErrorOptions & { metadata?: Record } ) { return new DomainValidationError("INVALID_FORMAT", field, detail, options); } static invalidValue( field: string, value: unknown, detail = "invalid value", options?: ErrorOptions & { metadata?: Record } ) { // `cause` preserva el valor problemático para inspección sin exponerlo a cliente return new DomainValidationError("INVALID_VALUE", field, detail, { ...options, cause: value }); } /** Proyección mínima para Problem+JSON / colecciones */ toDetail() { return { path: this.field, message: this.detail, rule: this.code }; } /** Incluye proyección validación en la serialización segura */ override toJSON() { const base = super.toJSON(); return { ...base, kind: this.kind, field: this.field, detail: this.detail, }; } } /** Type guard */ export const isDomainValidationError = (e: unknown): e is DomainValidationError => e instanceof DomainValidationError;