/
ajv.ts
84 lines (72 loc) 路 2.13 KB
/
ajv.ts
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { toNestError, validateFieldsNatively } from '@hookform/resolvers';
import Ajv, { DefinedError } from 'ajv';
import ajvErrors from 'ajv-errors';
import { appendErrors, FieldError } from 'react-hook-form';
import { Resolver } from './types';
const parseErrorSchema = (
ajvErrors: DefinedError[],
validateAllFieldCriteria: boolean,
) => {
// Ajv will return empty instancePath when require error
ajvErrors.forEach((error) => {
if (error.keyword === 'required') {
error.instancePath += '/' + error.params.missingProperty;
}
});
return ajvErrors.reduce<Record<string, FieldError>>((previous, error) => {
// `/deepObject/data` -> `deepObject.data`
const path = error.instancePath.substring(1).replace(/\//g, '.');
if (!previous[path]) {
previous[path] = {
message: error.message,
type: error.keyword,
};
}
if (validateAllFieldCriteria) {
const types = previous[path].types;
const messages = types && types[error.keyword];
previous[path] = appendErrors(
path,
validateAllFieldCriteria,
previous,
error.keyword,
messages
? ([] as string[]).concat(messages as string[], error.message || '')
: error.message,
) as FieldError;
}
return previous;
}, {});
};
export const ajvResolver: Resolver =
(schema, schemaOptions, resolverOptions = {}) =>
async (values, _, options) => {
const ajv = new Ajv({
allErrors: true,
validateSchema: true,
...schemaOptions,
});
ajvErrors(ajv);
const validate = ajv.compile(
Object.assign({ $async: resolverOptions?.mode === 'async' }, schema),
);
const valid = validate(values);
if (!valid) {
return {
values: {},
errors: toNestError(
parseErrorSchema(
validate.errors as DefinedError[],
!options.shouldUseNativeValidation &&
options.criteriaMode === 'all',
),
options,
),
};
}
options.shouldUseNativeValidation && validateFieldsNatively({}, options);
return {
values,
errors: {},
};
};