@hookform/resolvers 5.9.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/ajv/dist/ajv.js +1 -1
- package/ajv/dist/ajv.js.map +1 -1
- package/ajv/dist/ajv.mjs +1 -1
- package/ajv/dist/ajv.modern.mjs +1 -1
- package/ajv/dist/ajv.modern.mjs.map +1 -1
- package/ajv/dist/ajv.module.js +1 -1
- package/ajv/dist/ajv.module.js.map +1 -1
- package/ajv/dist/ajv.umd.js +1 -1
- package/ajv/dist/ajv.umd.js.map +1 -1
- package/ajv/src/__tests__/ajv.ts +58 -0
- package/ajv/src/ajv.ts +7 -2
- package/effect-ts/dist/effect-ts.d.ts +3 -3
- package/effect-ts/dist/effect-ts.js +1 -1
- package/effect-ts/dist/effect-ts.js.map +1 -1
- package/effect-ts/dist/effect-ts.mjs +1 -1
- package/effect-ts/dist/effect-ts.modern.mjs +1 -1
- package/effect-ts/dist/effect-ts.modern.mjs.map +1 -1
- package/effect-ts/dist/effect-ts.module.js +1 -1
- package/effect-ts/dist/effect-ts.module.js.map +1 -1
- package/effect-ts/dist/effect-ts.umd.js +1 -1
- package/effect-ts/dist/effect-ts.umd.js.map +1 -1
- package/effect-ts/package.json +1 -1
- package/effect-ts/src/__tests__/Form-native-validation.tsx +4 -4
- package/effect-ts/src/__tests__/Form.tsx +4 -4
- package/effect-ts/src/__tests__/__fixtures__/data.ts +24 -24
- package/effect-ts/src/__tests__/__snapshots__/effect-ts.ts.snap +10 -11
- package/effect-ts/src/__tests__/effect-ts.ts +196 -15
- package/effect-ts/src/__tests__/special-path-names.ts +1 -1
- package/effect-ts/src/effect-ts.ts +82 -60
- package/package.json +6 -6
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';
|
|
2
|
-
import { Effect, Schema } from 'effect';
|
|
3
|
-
import {
|
|
4
|
-
import { ParseOptions } from 'effect/SchemaAST';
|
|
2
|
+
import { Effect, Schema, SchemaIssue } from 'effect';
|
|
3
|
+
import type { ParseOptions } from 'effect/SchemaAST';
|
|
5
4
|
import {
|
|
6
5
|
type FieldError,
|
|
7
6
|
FieldValues,
|
|
@@ -9,8 +8,37 @@ import {
|
|
|
9
8
|
appendErrors,
|
|
10
9
|
} from 'react-hook-form';
|
|
11
10
|
|
|
11
|
+
type Issue = { path: PropertyKey[]; message: string; type: string };
|
|
12
|
+
|
|
13
|
+
const formatIssue = SchemaIssue.makeFormatterStandardSchemaV1();
|
|
14
|
+
|
|
15
|
+
// Flattens the issue tree like `makeFormatterStandardSchemaV1` does, but keeps
|
|
16
|
+
// the `_tag` of the failing node so it can be reported as the error `type`.
|
|
17
|
+
const flattenIssue = (
|
|
18
|
+
issue: SchemaIssue.Issue,
|
|
19
|
+
path: PropertyKey[],
|
|
20
|
+
): Issue[] => {
|
|
21
|
+
switch (issue._tag) {
|
|
22
|
+
case 'Pointer':
|
|
23
|
+
return flattenIssue(issue.issue, [...path, ...issue.path]);
|
|
24
|
+
case 'Encoding':
|
|
25
|
+
return flattenIssue(issue.issue, path);
|
|
26
|
+
case 'Composite':
|
|
27
|
+
case 'AnyOf':
|
|
28
|
+
if (issue.issues.length) {
|
|
29
|
+
return issue.issues.flatMap((issue) => flattenIssue(issue, path));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return formatIssue(issue).issues.map((error) => ({
|
|
34
|
+
path: [...path, ...(error.path || [])] as PropertyKey[],
|
|
35
|
+
message: error.message,
|
|
36
|
+
type: issue._tag,
|
|
37
|
+
}));
|
|
38
|
+
};
|
|
39
|
+
|
|
12
40
|
export function effectTsResolver<Input extends FieldValues, Context, Output>(
|
|
13
|
-
schema: Schema.
|
|
41
|
+
schema: Schema.Codec<Output, Input, never, unknown>,
|
|
14
42
|
schemaOptions?: ParseOptions,
|
|
15
43
|
resolverOptions?: {
|
|
16
44
|
mode?: 'async' | 'sync';
|
|
@@ -19,7 +47,7 @@ export function effectTsResolver<Input extends FieldValues, Context, Output>(
|
|
|
19
47
|
): Resolver<Input, Context, Output>;
|
|
20
48
|
|
|
21
49
|
export function effectTsResolver<Input extends FieldValues, Context, Output>(
|
|
22
|
-
schema: Schema.
|
|
50
|
+
schema: Schema.Codec<Output, Input, never, unknown>,
|
|
23
51
|
schemaOptions: ParseOptions | undefined,
|
|
24
52
|
resolverOptions: {
|
|
25
53
|
mode?: 'async' | 'sync';
|
|
@@ -28,9 +56,9 @@ export function effectTsResolver<Input extends FieldValues, Context, Output>(
|
|
|
28
56
|
): Resolver<Input, Context, Input>;
|
|
29
57
|
|
|
30
58
|
/**
|
|
31
|
-
* Creates a resolver for react-hook-form using Effect
|
|
32
|
-
* @param {Schema.
|
|
33
|
-
* @param {ParseOptions} [schemaOptions] - Optional Effect
|
|
59
|
+
* Creates a resolver for react-hook-form using Effect Schema validation
|
|
60
|
+
* @param {Schema.Codec<Output, Input>} schema - The Effect schema to validate against
|
|
61
|
+
* @param {ParseOptions} [schemaOptions] - Optional Effect Schema parse options
|
|
34
62
|
* @returns {Resolver<Schema.Schema.Type<typeof schema>>} A resolver function compatible with react-hook-form
|
|
35
63
|
* @example
|
|
36
64
|
* const schema = Schema.Struct({
|
|
@@ -43,67 +71,61 @@ export function effectTsResolver<Input extends FieldValues, Context, Output>(
|
|
|
43
71
|
* });
|
|
44
72
|
*/
|
|
45
73
|
export function effectTsResolver<Input extends FieldValues, Context, Output>(
|
|
46
|
-
schema: Schema.
|
|
74
|
+
schema: Schema.Codec<Output, Input, never, unknown>,
|
|
47
75
|
schemaOptions: ParseOptions = { errors: 'all', onExcessProperty: 'ignore' },
|
|
48
76
|
): Resolver<Input, Context, Output | Input> {
|
|
49
|
-
return (values, _, options) =>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
),
|
|
57
|
-
Effect.mapError((issues) => {
|
|
58
|
-
const validateAllFieldCriteria =
|
|
59
|
-
!options.shouldUseNativeValidation && options.criteriaMode === 'all';
|
|
77
|
+
return (values, _, options) =>
|
|
78
|
+
Schema.decodeUnknownEffect(schema)(values, schemaOptions).pipe(
|
|
79
|
+
Effect.match({
|
|
80
|
+
onFailure: ({ issue }) => {
|
|
81
|
+
const validateAllFieldCriteria =
|
|
82
|
+
!options.shouldUseNativeValidation &&
|
|
83
|
+
options.criteriaMode === 'all';
|
|
60
84
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
85
|
+
// A null-prototype accumulator avoids false-positive hits from
|
|
86
|
+
// inherited members (e.g. `toString`, `constructor`) when a field
|
|
87
|
+
// is named after one of them — a plain `{}` would make `!acc[key]`
|
|
88
|
+
// truthy-skip those paths and silently drop their errors.
|
|
89
|
+
const errors = flattenIssue(issue, []).reduce(
|
|
90
|
+
(acc, error) => {
|
|
91
|
+
const key = error.path.join('.');
|
|
68
92
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
93
|
+
if (!acc[key]) {
|
|
94
|
+
acc[key] = { message: error.message, type: error.type };
|
|
95
|
+
}
|
|
72
96
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
97
|
+
if (validateAllFieldCriteria) {
|
|
98
|
+
const types = acc[key].types;
|
|
99
|
+
const messages = types && types[error.type];
|
|
76
100
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
101
|
+
acc[key] = appendErrors(
|
|
102
|
+
key,
|
|
103
|
+
validateAllFieldCriteria,
|
|
104
|
+
acc,
|
|
105
|
+
error.type,
|
|
106
|
+
messages
|
|
107
|
+
? ([] as string[]).concat(
|
|
108
|
+
messages as string[],
|
|
109
|
+
error.message,
|
|
110
|
+
)
|
|
111
|
+
: error.message,
|
|
112
|
+
) as FieldError;
|
|
113
|
+
}
|
|
87
114
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
115
|
+
return acc;
|
|
116
|
+
},
|
|
117
|
+
Object.create(null) as Record<string, FieldError>,
|
|
118
|
+
);
|
|
92
119
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
),
|
|
102
|
-
Effect.match({
|
|
103
|
-
onFailure: (errors) => ({ errors, values: {} }),
|
|
104
|
-
onSuccess: (result) => ({ errors: {}, values: result }),
|
|
120
|
+
return { errors: toNestErrors(errors, options), values: {} };
|
|
121
|
+
},
|
|
122
|
+
onSuccess: (result) => {
|
|
123
|
+
options.shouldUseNativeValidation &&
|
|
124
|
+
validateFieldsNatively({}, options);
|
|
125
|
+
|
|
126
|
+
return { errors: {}, values: result };
|
|
127
|
+
},
|
|
105
128
|
}),
|
|
106
129
|
Effect.runPromise,
|
|
107
130
|
);
|
|
108
|
-
};
|
|
109
131
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hookform/resolvers",
|
|
3
3
|
"amdName": "hookformResolvers",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "6.0.0",
|
|
5
5
|
"description": "React Hook Form validation resolvers: Yup, Joi, Superstruct, Zod, Vest, Class Validator, io-ts, Nope, computed-types, TypeBox, arktype, Typanion, Effect-TS and VineJS",
|
|
6
6
|
"main": "dist/resolvers.js",
|
|
7
7
|
"module": "dist/resolvers.module.js",
|
|
@@ -226,7 +226,7 @@
|
|
|
226
226
|
"build:arktype": "microbundle --cwd arktype --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm",
|
|
227
227
|
"build:valibot": "microbundle --cwd valibot --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm",
|
|
228
228
|
"build:typeschema": "microbundle --cwd typeschema --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm,@typeschema/main=main",
|
|
229
|
-
"build:effect-ts": "microbundle --cwd effect-ts --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm,effect=Effect,effect/SchemaAST=EffectSchemaAST
|
|
229
|
+
"build:effect-ts": "microbundle --cwd effect-ts --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm,effect=Effect,effect/SchemaAST=EffectSchemaAST",
|
|
230
230
|
"build:vine": "microbundle --cwd vine --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm,@vinejs/vine=vine",
|
|
231
231
|
"build:fluentvalidation-ts": "microbundle --cwd fluentvalidation-ts --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm",
|
|
232
232
|
"build:standard-schema": "microbundle --cwd standard-schema --globals @hookform/resolvers=hookformResolvers,react-hook-form=ReactHookForm,@standard-schema/spec=standardSchema",
|
|
@@ -291,16 +291,16 @@
|
|
|
291
291
|
"@vinejs/vine": "^4.4.0",
|
|
292
292
|
"@vitejs/plugin-react": "^4.7.0",
|
|
293
293
|
"ajv": "^8.20.0",
|
|
294
|
-
"ata-validator": "^1.2.0",
|
|
295
294
|
"ajv-errors": "^3.0.0",
|
|
296
295
|
"ajv-formats": "^2.1.1",
|
|
297
296
|
"arktype": "2.0.4",
|
|
297
|
+
"ata-validator": "^1.23.0",
|
|
298
298
|
"check-export-map": "^1.3.1",
|
|
299
299
|
"class-transformer": "^0.5.1",
|
|
300
300
|
"class-validator": "^0.14.4",
|
|
301
301
|
"computed-types": "^1.11.2",
|
|
302
302
|
"cross-env": "^7.0.3",
|
|
303
|
-
"effect": "^
|
|
303
|
+
"effect": "^4.0.5",
|
|
304
304
|
"fluentvalidation-ts": "^3.3.0",
|
|
305
305
|
"fp-ts": "^2.16.11",
|
|
306
306
|
"io-ts": "^2.2.22",
|
|
@@ -337,11 +337,11 @@
|
|
|
337
337
|
"ajv-errors": "^3.0.0",
|
|
338
338
|
"ajv-formats": "^2.1.1",
|
|
339
339
|
"arktype": "^2.0.0",
|
|
340
|
-
"ata-validator": "^1.
|
|
340
|
+
"ata-validator": "^1.23.0",
|
|
341
341
|
"class-transformer": ">=0.4.0",
|
|
342
342
|
"class-validator": ">=0.12.0",
|
|
343
343
|
"computed-types": "^1.0.0",
|
|
344
|
-
"effect": "^
|
|
344
|
+
"effect": "^4.0.0",
|
|
345
345
|
"fluentvalidation-ts": "^3.0.0",
|
|
346
346
|
"fp-ts": "^2.7.0",
|
|
347
347
|
"io-ts": "^2.0.0",
|