File size: 1,879 Bytes
95ca844 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';
import { plainToClass } from 'class-transformer';
import { ValidationError, validate, validateSync } from 'class-validator';
import { FieldErrors } from 'react-hook-form';
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: toNestErrors(
parseErrors(
rawErrors,
!options.shouldUseNativeValidation &&
options.criteriaMode === 'all',
),
options,
),
};
}
options.shouldUseNativeValidation && validateFieldsNatively({}, options);
return {
values: resolverOptions.rawValues ? values : data,
errors: {},
};
};
|