// 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: Message; 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; }; export interface Message { [key: string]: any; } /** * 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: Message = {}; /** * 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; // if (this.errors[field.getFieldPath()]) { // this.errors[field.getFieldPath()]?.push(message); // } else { // this.errors[field.getFieldPath()] = [message]; // } const error: SimpleError = { message, rule, field: field.wildCardPath ?field.wildCardPath.split('.')[0] : 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); // } if (field.isArrayMember) { // Check if the field has wildCardPath and if the error field already exists if (this.errors[error.field] && field.wildCardPath) { // Do nothing, as we don't want to push further messages } else { // If the error field already exists, push the message if (this.errors[error.field]) { this.errors[error.field].push(message); } else { this.errors[error.field] = [message]; } } } else { // normal field 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 {};