UNPKG

@matthew.ngo/reform

Version:

A flexible and powerful React form management library with advanced validation, state observation, and multi-group support

110 lines (95 loc) 3.1 kB
import { FieldError, FieldErrors } from 'react-hook-form'; import { FormGroup } from '../form/form-groups'; const extractFieldName = (path: string): string => { // Match pattern: groups[0].data.fieldName or groups.0.data.fieldName const matches = path.match(/groups(?:\[(\d+)\]|\.\d+)\.data\.(.+)$/); return matches ? matches[2] : path; }; const formatErrorMessage = ( message: string, fieldName: string, label?: string ): string => { // Replace all occurrences of groups[n].data.fieldName or groups.n.data.fieldName with label return message.replace( /groups(?:\[\d+\]|\.\d+)\.data\.[^\ ]+/g, label || fieldName ); }; const normalizeErrorType = (type: any): FieldError['type'] => { // Convert any error type to valid FieldError type const validTypes = [ 'required', 'min', 'max', 'minLength', 'maxLength', 'pattern', 'validate', ] as const; return validTypes.includes(type as any) ? type : 'validate'; }; // Add this new utility function const getNestedLabel = ( labels: Record<string, any> | undefined, path: string ): string | undefined => { if (!labels) return undefined; const parts = path.split('.'); let current = labels; for (const part of parts) { if (!current || typeof current !== 'object') return undefined; current = current[part]; } return typeof current === 'string' ? current : undefined; }; export const transformFormErrors = <T>( errors: FieldErrors<{ groups: FormGroup<T>[] }>, labels?: Record<string, any> ): Record<string, FieldError> => { const result: Record<string, FieldError> = {}; // Transform root error if (errors.root) { result.root = { type: normalizeErrorType(errors.root.type), message: errors.root.message || '', }; } // Transform group errors if (errors.groups) { Array.isArray(errors.groups) && errors.groups.forEach((group, index) => { if (group?.message) { result[`groups.${index}`] = { type: normalizeErrorType(group.type), message: group.message, }; } if (group?.data) { const processNestedErrors = ( errors: Record<string, any>, basePath: string ) => { Object.entries(errors).forEach(([field, error]) => { if (error?.message) { const fieldPath = `${basePath}${field}`; const fieldName = extractFieldName( error.ref?.name || fieldPath ); const label = getNestedLabel(labels, fieldName); result[`groups.${index}.${fieldPath}`] = { type: normalizeErrorType(error.type), message: formatErrorMessage(error.message, fieldName, label), }; } else if (error && typeof error === 'object') { // Handle nested objects processNestedErrors(error, `${field}.`); } }); }; processNestedErrors(group.data, ''); } }); } return result; };