FactuGES_ERP/packages/rdx-ddd/src/errors/domain-validation-error.ts

92 lines
2.5 KiB
TypeScript

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;
/** 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<string, unknown> }
) {
// Mensaje humano compacto y útil para logs
super(`[${field}] ${detail}`, {
...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<string, unknown> }
) {
return new DomainValidationError("REQUIRED_VALUE", field, "cannot be empty", options);
}
static invalidFormat(
field: string,
detail = "invalid format",
options?: ErrorOptions & { metadata?: Record<string, unknown> }
) {
return new DomainValidationError("INVALID_FORMAT", field, detail, options);
}
static invalidValue(
field: string,
value: unknown,
detail = "invalid value",
options?: ErrorOptions & { metadata?: Record<string, unknown> }
) {
// `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;