// import { ValidationError } from '../errors/validation_error.js'; import { errors } from '@vinejs/vine'; import type { ErrorReporterContract, FieldContext } from '@vinejs/vine/types'; import string from '@poppinss/utils/string'; /** * Shape of the Vanilla error node */ export type VanillaErrorNode = { [field: string]: string[]; }; export interface MessagesBagContract { get(pointer: string, rule: string, message: string, arrayExpressionPointer?: string, args?: any): string; } /** * Message bag exposes the API to pull the most appropriate message for a * given validation failure. */ export class MessagesBag implements MessagesBagContract { messages; wildCardCallback; constructor(messages: string[]) { this.messages = messages; this.wildCardCallback = typeof this.messages['*'] === 'function' ? this.messages['*'] : undefined; } /** * Transform message by replace placeholders with runtime values */ transform(message: any, rule: string, pointer: string, args: any) { /** * No interpolation required */ if (!message.includes('{{')) { return message; } return string.interpolate(message, { rule, field: pointer, options: args || {} }); } /** * Returns the most appropriate message for the validation failure. */ get(pointer: string, rule: string, message: string, arrayExpressionPointer: string, args: any) { let validationMessage = this.messages[`${pointer}.${rule}`]; /** * Fetch message for the array expression pointer if it exists */ if (!validationMessage && arrayExpressionPointer) { validationMessage = this.messages[`${arrayExpressionPointer}.${rule}`]; } /** * Fallback to the message for the rule */ if (!validationMessage) { validationMessage = this.messages[rule]; } /** * Transform and return message. The wildcard callback is invoked when custom message * is not defined */ return validationMessage ? this.transform(validationMessage, rule, pointer, args) : this.wildCardCallback ? this.wildCardCallback(pointer, rule, arrayExpressionPointer, args) : message; } } /** * Shape of the error message collected by the SimpleErrorReporter */ // type SimpleError = { // message: string; // field: string; // rule: string; // index?: number; // meta?: Record; // }; /** * Simple error reporter collects error messages as an array of object. * Each object has following properties. * * - message: string * - field: string * - rule: string * - index?: number (in case of an array member) * - args?: Record */ export class VanillaErrorReporter implements ErrorReporterContract { private messages; // private bail; /** * Boolean to know one or more errors have been reported */ hasErrors: boolean = false; /** * Collection of errors */ // errors: SimpleError[] = []; errors = {}; /** * Report an error. */ // constructor(messages: MessagesBagContract) { // this.messages = messages; // } report(message: string, rule: string, field: FieldContext, meta?: Record | undefined): void { // const error: SimpleError = { // message, // rule, // field: field.getFieldPath() // }; // if (meta) { // error.meta = meta; // } // if (field.isArrayMember) { // error.index = field.name as number; // } // this.errors.push(error); this.hasErrors = true; const error = { message, rule, field: field.getFieldPath(), }; // field: 'titles.0.value' // message: 'Main Title is required' // rule: 'required' "required" if (meta) { error.meta = meta; } // if (field.isArrayMember) { // error.index = field.name; // } this.hasErrors = true; // this.errors.push(error); if (this.errors[error.field]) { this.errors[error.field]?.push(message); } else { this.errors[error.field] = [message]; } /** * Collecting errors as per the JSONAPI spec */ // this.errors.push({ // code: rule, // detail: message, // source: { // pointer: field.wildCardPath, // }, // ...(meta ? { meta } : {}), // }); // let pointer: string = field.wildCardPath as string; //'display_name' // // if (field.isArrayMember) { // // this.errors[pointer] = field.name; // // } // this.errors[pointer] = this.errors[pointer] || []; // // this.errors[pointer].push(message); // this.errors[pointer].push(this.messages.get(pointer, rule, message, arrayExpressionPointer, args)); } /** * Returns an instance of the validation error */ createError() { return new errors.E_VALIDATION_ERROR(this.errors); } } export {};