UNPKG

@hookform/resolvers

Version:

React Hook Form validation resolvers: Yup, Joi, Superstruct, Zod, Vest, Class Validator, io-ts, Nope, computed-types, TypeBox, arktype and Typanion

65 lines (54 loc) 1.82 kB
import { FieldErrors } from 'react-hook-form'; import { toNestError, validateFieldsNatively } from '@hookform/resolvers'; import { plainToClass } from 'class-transformer'; import { validate, validateSync, ValidationError } from 'class-validator'; import type { Resolver } from './types'; const parseErrors = ( errors: ValidationError[], validateAllFieldCriteria: boolean, parsedErrors: FieldErrors = {}, path = '', ) => { return errors.reduce((acc, error) => { const _path = path ? `${path}.${error.property}` : error.property; if (error.constraints) { const key = Object.keys(error.constraints)[0]; acc[_path] = { type: key, message: error.constraints[key], }; const _e = acc[_path]; if (validateAllFieldCriteria && _e) { Object.assign(_e, { types: error.constraints }); } } if (error.children && error.children.length) { parseErrors(error.children, validateAllFieldCriteria, acc, _path); } return acc; }, parsedErrors); }; export const classValidatorResolver: Resolver = (schema, schemaOptions = {}, resolverOptions = {}) => async (values, _, options) => { const { transformer, validator } = schemaOptions; const data = plainToClass(schema, values, transformer); const rawErrors = await (resolverOptions.mode === 'sync' ? validateSync : validate)(data, validator); if (rawErrors.length) { return { values: {}, errors: toNestError( parseErrors( rawErrors, !options.shouldUseNativeValidation && options.criteriaMode === 'all', ), options, ), }; } options.shouldUseNativeValidation && validateFieldsNatively({}, options); return { values, errors: {} }; };