@hookform/resolvers 4.1.3 → 5.0.1
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 +30 -0
- package/ajv/package.json +1 -1
- package/arktype/dist/arktype.d.ts +8 -20
- package/arktype/dist/arktype.js +1 -1
- package/arktype/dist/arktype.js.map +1 -1
- package/arktype/dist/arktype.mjs +1 -1
- package/arktype/dist/arktype.modern.mjs +1 -1
- package/arktype/dist/arktype.modern.mjs.map +1 -1
- package/arktype/dist/arktype.module.js +1 -1
- package/arktype/dist/arktype.module.js.map +1 -1
- package/arktype/dist/arktype.umd.js +1 -1
- package/arktype/dist/arktype.umd.js.map +1 -1
- package/arktype/package.json +1 -1
- package/arktype/src/__tests__/Form.tsx +0 -28
- package/arktype/src/__tests__/arktype.ts +56 -0
- package/arktype/src/arktype.ts +58 -22
- package/class-validator/src/__tests__/Form.tsx +0 -26
- package/computed-types/dist/computed-types.d.ts +2 -3
- package/computed-types/dist/computed-types.js.map +1 -1
- package/computed-types/dist/computed-types.modern.mjs.map +1 -1
- package/computed-types/dist/computed-types.module.js.map +1 -1
- package/computed-types/dist/computed-types.umd.js.map +1 -1
- package/computed-types/package.json +1 -1
- package/computed-types/src/__tests__/Form.tsx +0 -28
- package/computed-types/src/__tests__/computed-types.ts +55 -1
- package/computed-types/src/computed-types.ts +7 -5
- package/effect-ts/dist/effect-ts.d.ts +8 -16
- package/effect-ts/dist/effect-ts.js.map +1 -1
- package/effect-ts/dist/effect-ts.modern.mjs.map +1 -1
- package/effect-ts/dist/effect-ts.module.js.map +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__/effect-ts.ts +61 -0
- package/effect-ts/src/effect-ts.ts +21 -3
- package/fluentvalidation-ts/package.json +1 -1
- package/io-ts/dist/io-ts.d.ts +8 -17
- package/io-ts/dist/io-ts.js.map +1 -1
- package/io-ts/dist/io-ts.modern.mjs.map +1 -1
- package/io-ts/dist/io-ts.module.js.map +1 -1
- package/io-ts/dist/io-ts.umd.js.map +1 -1
- package/io-ts/package.json +1 -1
- package/io-ts/src/__tests__/__fixtures__/data.ts +3 -3
- package/io-ts/src/__tests__/io-ts.ts +54 -0
- package/io-ts/src/io-ts.ts +35 -8
- package/joi/package.json +1 -1
- package/nope/package.json +1 -1
- package/package.json +13 -13
- package/standard-schema/dist/standard-schema.d.ts +6 -23
- package/standard-schema/dist/standard-schema.js +1 -1
- package/standard-schema/dist/standard-schema.js.map +1 -1
- package/standard-schema/dist/standard-schema.mjs +1 -1
- package/standard-schema/dist/standard-schema.modern.mjs +1 -1
- package/standard-schema/dist/standard-schema.modern.mjs.map +1 -1
- package/standard-schema/dist/standard-schema.module.js +1 -1
- package/standard-schema/dist/standard-schema.module.js.map +1 -1
- package/standard-schema/dist/standard-schema.umd.js +1 -1
- package/standard-schema/dist/standard-schema.umd.js.map +1 -1
- package/standard-schema/package.json +1 -1
- package/standard-schema/src/__tests__/Form.tsx +0 -28
- package/standard-schema/src/__tests__/__fixtures__/data.ts +2 -2
- package/standard-schema/src/__tests__/standard-schema.ts +78 -1
- package/standard-schema/src/standard-schema.ts +32 -5
- package/superstruct/dist/superstruct.d.ts +6 -20
- package/superstruct/dist/superstruct.js.map +1 -1
- package/superstruct/dist/superstruct.modern.mjs.map +1 -1
- package/superstruct/dist/superstruct.module.js.map +1 -1
- package/superstruct/dist/superstruct.umd.js.map +1 -1
- package/superstruct/package.json +1 -1
- package/superstruct/src/__tests__/superstruct.ts +60 -0
- package/superstruct/src/superstruct.ts +20 -4
- package/typanion/dist/typanion.d.ts +8 -16
- package/typanion/dist/typanion.js.map +1 -1
- package/typanion/dist/typanion.modern.mjs.map +1 -1
- package/typanion/dist/typanion.module.js.map +1 -1
- package/typanion/dist/typanion.umd.js.map +1 -1
- package/typanion/package.json +1 -1
- package/typanion/src/__tests__/Form.tsx +0 -32
- package/typanion/src/__tests__/typanion.ts +49 -0
- package/typanion/src/typanion.ts +22 -4
- package/typebox/dist/typebox.d.ts +3 -3
- package/typebox/dist/typebox.js.map +1 -1
- package/typebox/dist/typebox.modern.mjs.map +1 -1
- package/typebox/dist/typebox.module.js.map +1 -1
- package/typebox/dist/typebox.umd.js.map +1 -1
- package/typebox/package.json +1 -1
- package/typebox/src/__tests__/Form-native-validation-compiler.tsx +1 -1
- package/typebox/src/__tests__/Form.tsx +0 -28
- package/typebox/src/__tests__/__fixtures__/data.ts +3 -3
- package/typebox/src/__tests__/typebox.ts +98 -0
- package/typebox/src/typebox.ts +7 -14
- package/typeschema/dist/index.d.ts +0 -1
- package/typeschema/dist/typeschema.d.ts +8 -19
- package/typeschema/dist/typeschema.js +1 -1
- package/typeschema/dist/typeschema.js.map +1 -1
- package/typeschema/dist/typeschema.mjs +1 -1
- package/typeschema/dist/typeschema.modern.mjs +1 -1
- package/typeschema/dist/typeschema.modern.mjs.map +1 -1
- package/typeschema/dist/typeschema.module.js +1 -1
- package/typeschema/dist/typeschema.module.js.map +1 -1
- package/typeschema/dist/typeschema.umd.js +1 -1
- package/typeschema/dist/typeschema.umd.js.map +1 -1
- package/typeschema/package.json +1 -1
- package/typeschema/src/__tests__/Form.tsx +2 -4
- package/typeschema/src/__tests__/__fixtures__/data.ts +1 -1
- package/typeschema/src/__tests__/typeschema.ts +77 -0
- package/typeschema/src/index.ts +0 -1
- package/typeschema/src/typeschema.ts +52 -25
- package/valibot/dist/valibot.d.ts +9 -30
- package/valibot/dist/valibot.js.map +1 -1
- package/valibot/dist/valibot.modern.mjs.map +1 -1
- package/valibot/dist/valibot.module.js.map +1 -1
- package/valibot/dist/valibot.umd.js.map +1 -1
- package/valibot/package.json +1 -1
- package/valibot/src/__tests__/valibot.ts +69 -3
- package/valibot/src/valibot.ts +29 -13
- package/vest/package.json +1 -1
- package/vine/dist/vine.d.ts +10 -24
- package/vine/dist/vine.js.map +1 -1
- package/vine/dist/vine.modern.mjs.map +1 -1
- package/vine/dist/vine.module.js.map +1 -1
- package/vine/dist/vine.umd.js.map +1 -1
- package/vine/package.json +1 -1
- package/vine/src/__tests__/Form.tsx +0 -28
- package/vine/src/__tests__/__fixtures__/data.ts +4 -4
- package/vine/src/__tests__/vine.ts +69 -0
- package/vine/src/vine.ts +26 -4
- package/yup/dist/yup.d.ts +7 -21
- package/yup/dist/yup.js +1 -1
- package/yup/dist/yup.js.map +1 -1
- package/yup/dist/yup.mjs +1 -1
- package/yup/dist/yup.modern.mjs +1 -1
- package/yup/dist/yup.modern.mjs.map +1 -1
- package/yup/dist/yup.module.js +1 -1
- package/yup/dist/yup.module.js.map +1 -1
- package/yup/dist/yup.umd.js +1 -1
- package/yup/dist/yup.umd.js.map +1 -1
- package/yup/package.json +1 -1
- package/yup/src/__tests__/yup.ts +66 -0
- package/yup/src/yup.ts +30 -8
- package/zod/dist/zod.d.ts +7 -22
- package/zod/dist/zod.js.map +1 -1
- package/zod/dist/zod.modern.mjs.map +1 -1
- package/zod/dist/zod.module.js.map +1 -1
- package/zod/dist/zod.umd.js.map +1 -1
- package/zod/package.json +1 -1
- package/zod/src/__tests__/Form.tsx +0 -28
- package/zod/src/__tests__/__fixtures__/data.ts +2 -2
- package/zod/src/__tests__/zod.ts +69 -0
- package/zod/src/zod.ts +29 -9
- package/typeschema/dist/types.d.ts +0 -9
- package/typeschema/src/types.ts +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typeschema.umd.js","sources":["../src/typeschema.ts"],"sourcesContent":["import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport
|
|
1
|
+
{"version":3,"file":"typeschema.umd.js","sources":["../src/typeschema.ts"],"sourcesContent":["import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldErrors,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { StandardSchemaV1 } from 'zod/lib/standard-schema';\n\nconst parseErrorSchema = (\n typeschemaErrors: readonly StandardSchemaV1.Issue[],\n validateAllFieldCriteria: boolean,\n): FieldErrors => {\n const schemaErrors = Object.assign([], typeschemaErrors);\n const errors: Record<string, FieldError> = {};\n\n for (; schemaErrors.length; ) {\n const error = typeschemaErrors[0];\n\n if (!error.path) {\n continue;\n }\n const _path = error.path.join('.');\n\n if (!errors[_path]) {\n errors[_path] = { message: error.message, type: '' };\n }\n\n if (validateAllFieldCriteria) {\n const types = errors[_path].types;\n const messages = types && types[''];\n\n errors[_path] = appendErrors(\n _path,\n validateAllFieldCriteria,\n errors,\n '',\n messages\n ? ([] as string[]).concat(messages as string[], error.message)\n : error.message,\n ) as FieldError;\n }\n\n schemaErrors.shift();\n }\n\n return errors;\n};\n\nexport function typeschemaResolver<Input extends FieldValues, Context, Output>(\n schema: StandardSchemaV1<Input, Output>,\n _schemaOptions?: never,\n resolverOptions?: {\n raw?: false;\n },\n): Resolver<Input, Context, Output>;\n\nexport function typeschemaResolver<Input extends FieldValues, Context, Output>(\n schema: StandardSchemaV1<Input, Output>,\n _schemaOptions: never | undefined,\n resolverOptions: {\n raw: true;\n },\n): Resolver<Input, Context, Input>;\n\n/**\n * Creates a resolver for react-hook-form using TypeSchema validation\n * @param {any} schema - The TypeSchema to validate against\n * @param {any} _ - Unused parameter\n * @param {Object} resolverOptions - Additional resolver configuration\n * @param {string} [resolverOptions.mode='async'] - Validation mode\n * @returns {Resolver} A resolver function compatible with react-hook-form\n * @example\n * const schema = z.object({\n * name: z.string().required(),\n * age: z.number().required(),\n * });\n *\n * useForm({\n * resolver: typeschemaResolver(schema)\n * });\n */\nexport function typeschemaResolver<Input extends FieldValues, Context, Output>(\n schema: StandardSchemaV1<Input, Output>,\n _schemaOptions?: never,\n resolverOptions: {\n raw?: boolean;\n } = {},\n): Resolver<Input, Context, Output | Input> {\n return async (values, _, options) => {\n let result = schema['~standard'].validate(values);\n if (result instanceof Promise) {\n result = await result;\n }\n\n if (result.issues) {\n const errors = parseErrorSchema(\n result.issues,\n !options.shouldUseNativeValidation && options.criteriaMode === 'all',\n );\n\n return {\n values: {},\n errors: toNestErrors(errors, options),\n };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return {\n values: resolverOptions.raw ? Object.assign({}, values) : result.value,\n errors: {},\n };\n };\n}\n"],"names":["schema","_schemaOptions","resolverOptions","values","_","options","_temp2","result","issues","errors","typeschemaErrors","validateAllFieldCriteria","schemaErrors","Object","assign","length","error","path","_path","join","message","type","types","messages","appendErrors","concat","shift","parseErrorSchema","shouldUseNativeValidation","criteriaMode","toNestErrors","validateFieldsNatively","raw","value","validate","_temp","Promise","resolve","then","_result","e","reject"],"mappings":"oZAmFM,SACJA,EACAC,EACAC,GAIA,YAJAA,IAAAA,IAAAA,EAEI,IAEUC,SAAAA,EAAQC,EAAGC,GAAO,QAAIC,EAAA,WAMlC,GAAIC,EAAOC,OAAQ,CACjB,IAAMC,EAvFa,SACvBC,EACAC,GAKA,IAHA,IAAMC,EAAeC,OAAOC,OAAO,GAAIJ,GACjCD,EAAqC,GAEpCG,EAAaG,QAAU,CAC5B,IAAMC,EAAQN,EAAiB,GAE/B,GAAKM,EAAMC,KAAX,CAGA,IAAMC,EAAQF,EAAMC,KAAKE,KAAK,KAM9B,GAJKV,EAAOS,KACVT,EAAOS,GAAS,CAAEE,QAASJ,EAAMI,QAASC,KAAM,KAG9CV,EAA0B,CAC5B,IAAMW,EAAQb,EAAOS,GAAOI,MACtBC,EAAWD,GAASA,EAAM,IAEhCb,EAAOS,GAASM,EAAYA,aAC1BN,EACAP,EACAF,EACA,GACAc,EACK,GAAgBE,OAAOF,EAAsBP,EAAMI,SACpDJ,EAAMI,QAEd,CAEAR,EAAac,OAtBb,CAuBF,CAEA,OAAOjB,CACT,CAiDqBkB,CACbpB,EAAOC,QACNH,EAAQuB,2BAAsD,QAAzBvB,EAAQwB,cAGhD,MAAO,CACL1B,OAAQ,CAAE,EACVM,OAAQqB,EAAAA,aAAarB,EAAQJ,GAEjC,CAIA,OAFAA,EAAQuB,2BAA6BG,yBAAuB,CAAA,EAAI1B,GAEzD,CACLF,OAAQD,EAAgB8B,IAAMnB,OAAOC,OAAO,CAAA,EAAIX,GAAUI,EAAO0B,MACjExB,OAAQ,CAAA,EACR,EAtBEF,EAASP,EAAO,aAAakC,SAAS/B,GAAQgC,EAC9C5B,WAAAA,GAAAA,aAAkB6B,QAAOA,OAAAA,QAAAC,QACZ9B,GAAM+B,cAAAC,GAArBhC,EAAMgC,CAAgB,GADpBhC,UACoB6B,QAAAC,QAAAF,GAAAA,EAAAG,KAAAH,EAAAG,KAAAhC,GAAAA,IAqB1B,CAAC,MAAAkC,GAAAJ,OAAAA,QAAAK,OAAAD,EACH,CAAA,CAAA"}
|
package/typeschema/package.json
CHANGED
|
@@ -11,10 +11,8 @@ const schema = z.object({
|
|
|
11
11
|
password: z.string().min(1, { message: 'password field is required' }),
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
type FormData = Infer<typeof schema> & { unusedProperty: string };
|
|
15
|
-
|
|
16
14
|
interface Props {
|
|
17
|
-
onSubmit: (data:
|
|
15
|
+
onSubmit: (data: Infer<typeof schema>) => void;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
function TestComponent({ onSubmit }: Props) {
|
|
@@ -22,7 +20,7 @@ function TestComponent({ onSubmit }: Props) {
|
|
|
22
20
|
register,
|
|
23
21
|
handleSubmit,
|
|
24
22
|
formState: { errors },
|
|
25
|
-
} = useForm
|
|
23
|
+
} = useForm({
|
|
26
24
|
resolver: typeschemaResolver(schema), // Useful to check TypeScript regressions
|
|
27
25
|
});
|
|
28
26
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as typeschema from '@typeschema/main';
|
|
2
|
+
import { Resolver, SubmitHandler, useForm } from 'react-hook-form';
|
|
3
|
+
import { z } from 'zod';
|
|
2
4
|
import { typeschemaResolver } from '..';
|
|
3
5
|
import { fields, invalidData, schema, validData } from './__fixtures__/data';
|
|
4
6
|
|
|
@@ -67,4 +69,79 @@ describe('typeschemaResolver', () => {
|
|
|
67
69
|
|
|
68
70
|
await expect(promise).rejects.toThrow('custom error');
|
|
69
71
|
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Type inference tests
|
|
75
|
+
*/
|
|
76
|
+
it('should correctly infer the output type from a typeschema schema', () => {
|
|
77
|
+
const resolver = typeschemaResolver(z.object({ id: z.number() }));
|
|
78
|
+
|
|
79
|
+
expectTypeOf(resolver).toEqualTypeOf<
|
|
80
|
+
Resolver<{ id: number }, unknown, { id: number }>
|
|
81
|
+
>();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should correctly infer the output type from a typeschema schema using a transform', () => {
|
|
85
|
+
const resolver = typeschemaResolver(
|
|
86
|
+
z.object({ id: z.number().transform((val) => String(val)) }),
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
expectTypeOf(resolver).toEqualTypeOf<
|
|
90
|
+
Resolver<{ id: number }, unknown, { id: string }>
|
|
91
|
+
>();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should correctly infer the output type from a typeschema schema when a different input type is specified', () => {
|
|
95
|
+
const schema = z.object({ id: z.number() }).transform(({ id }) => {
|
|
96
|
+
return { id: String(id) };
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const resolver = typeschemaResolver<
|
|
100
|
+
{ id: number },
|
|
101
|
+
any,
|
|
102
|
+
z.output<typeof schema>
|
|
103
|
+
>(schema);
|
|
104
|
+
|
|
105
|
+
expectTypeOf(resolver).toEqualTypeOf<
|
|
106
|
+
Resolver<{ id: number }, any, { id: string }>
|
|
107
|
+
>();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should correctly infer the output type from a typeschema schema for the handleSubmit function in useForm', () => {
|
|
111
|
+
const schema = z.object({ id: z.number() });
|
|
112
|
+
|
|
113
|
+
const form = useForm({
|
|
114
|
+
resolver: typeschemaResolver(schema),
|
|
115
|
+
defaultValues: {
|
|
116
|
+
id: 3,
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
expectTypeOf(form.watch('id')).toEqualTypeOf<number>();
|
|
121
|
+
|
|
122
|
+
expectTypeOf(form.handleSubmit).parameter(0).toEqualTypeOf<
|
|
123
|
+
SubmitHandler<{
|
|
124
|
+
id: number;
|
|
125
|
+
}>
|
|
126
|
+
>();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should correctly infer the output type from a typeschema schema with a transform for the handleSubmit function in useForm', () => {
|
|
130
|
+
const schema = z.object({ id: z.number().transform((val) => String(val)) });
|
|
131
|
+
|
|
132
|
+
const form = useForm({
|
|
133
|
+
resolver: typeschemaResolver(schema),
|
|
134
|
+
defaultValues: {
|
|
135
|
+
id: 3,
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
expectTypeOf(form.watch('id')).toEqualTypeOf<number>();
|
|
140
|
+
|
|
141
|
+
expectTypeOf(form.handleSubmit).parameter(0).toEqualTypeOf<
|
|
142
|
+
SubmitHandler<{
|
|
143
|
+
id: string;
|
|
144
|
+
}>
|
|
145
|
+
>();
|
|
146
|
+
});
|
|
70
147
|
});
|
package/typeschema/src/index.ts
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
import {
|
|
3
|
+
FieldError,
|
|
4
|
+
FieldErrors,
|
|
5
|
+
FieldValues,
|
|
6
|
+
Resolver,
|
|
7
|
+
appendErrors,
|
|
8
|
+
} from 'react-hook-form';
|
|
9
|
+
import { StandardSchemaV1 } from 'zod/lib/standard-schema';
|
|
6
10
|
|
|
7
11
|
const parseErrorSchema = (
|
|
8
|
-
typeschemaErrors:
|
|
12
|
+
typeschemaErrors: readonly StandardSchemaV1.Issue[],
|
|
9
13
|
validateAllFieldCriteria: boolean,
|
|
10
14
|
): FieldErrors => {
|
|
15
|
+
const schemaErrors = Object.assign([], typeschemaErrors);
|
|
11
16
|
const errors: Record<string, FieldError> = {};
|
|
12
17
|
|
|
13
|
-
for (;
|
|
18
|
+
for (; schemaErrors.length; ) {
|
|
14
19
|
const error = typeschemaErrors[0];
|
|
15
20
|
|
|
16
21
|
if (!error.path) {
|
|
@@ -37,12 +42,28 @@ const parseErrorSchema = (
|
|
|
37
42
|
) as FieldError;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
|
|
45
|
+
schemaErrors.shift();
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
return errors;
|
|
44
49
|
};
|
|
45
50
|
|
|
51
|
+
export function typeschemaResolver<Input extends FieldValues, Context, Output>(
|
|
52
|
+
schema: StandardSchemaV1<Input, Output>,
|
|
53
|
+
_schemaOptions?: never,
|
|
54
|
+
resolverOptions?: {
|
|
55
|
+
raw?: false;
|
|
56
|
+
},
|
|
57
|
+
): Resolver<Input, Context, Output>;
|
|
58
|
+
|
|
59
|
+
export function typeschemaResolver<Input extends FieldValues, Context, Output>(
|
|
60
|
+
schema: StandardSchemaV1<Input, Output>,
|
|
61
|
+
_schemaOptions: never | undefined,
|
|
62
|
+
resolverOptions: {
|
|
63
|
+
raw: true;
|
|
64
|
+
},
|
|
65
|
+
): Resolver<Input, Context, Input>;
|
|
66
|
+
|
|
46
67
|
/**
|
|
47
68
|
* Creates a resolver for react-hook-form using TypeSchema validation
|
|
48
69
|
* @param {any} schema - The TypeSchema to validate against
|
|
@@ -60,30 +81,36 @@ const parseErrorSchema = (
|
|
|
60
81
|
* resolver: typeschemaResolver(schema)
|
|
61
82
|
* });
|
|
62
83
|
*/
|
|
63
|
-
export
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
84
|
+
export function typeschemaResolver<Input extends FieldValues, Context, Output>(
|
|
85
|
+
schema: StandardSchemaV1<Input, Output>,
|
|
86
|
+
_schemaOptions?: never,
|
|
87
|
+
resolverOptions: {
|
|
88
|
+
raw?: boolean;
|
|
89
|
+
} = {},
|
|
90
|
+
): Resolver<Input, Context, Output | Input> {
|
|
91
|
+
return async (values, _, options) => {
|
|
92
|
+
let result = schema['~standard'].validate(values);
|
|
93
|
+
if (result instanceof Promise) {
|
|
94
|
+
result = await result;
|
|
95
|
+
}
|
|
67
96
|
|
|
68
|
-
|
|
97
|
+
if (result.issues) {
|
|
98
|
+
const errors = parseErrorSchema(
|
|
99
|
+
result.issues,
|
|
100
|
+
!options.shouldUseNativeValidation && options.criteriaMode === 'all',
|
|
101
|
+
);
|
|
69
102
|
|
|
70
|
-
if (result.success) {
|
|
71
103
|
return {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
? Object.assign({}, values)
|
|
75
|
-
: (result.data as any),
|
|
104
|
+
values: {},
|
|
105
|
+
errors: toNestErrors(errors, options),
|
|
76
106
|
};
|
|
77
107
|
}
|
|
78
108
|
|
|
109
|
+
options.shouldUseNativeValidation && validateFieldsNatively({}, options);
|
|
110
|
+
|
|
79
111
|
return {
|
|
80
|
-
values: {},
|
|
81
|
-
errors:
|
|
82
|
-
parseErrorSchema(
|
|
83
|
-
result.issues,
|
|
84
|
-
!options.shouldUseNativeValidation && options.criteriaMode === 'all',
|
|
85
|
-
),
|
|
86
|
-
options,
|
|
87
|
-
),
|
|
112
|
+
values: resolverOptions.raw ? Object.assign({}, values) : result.value,
|
|
113
|
+
errors: {},
|
|
88
114
|
};
|
|
89
115
|
};
|
|
116
|
+
}
|
|
@@ -1,31 +1,10 @@
|
|
|
1
1
|
import { FieldValues, Resolver } from 'react-hook-form';
|
|
2
|
-
import { BaseSchema, BaseSchemaAsync, Config, InferIssue
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* @example
|
|
12
|
-
* const schema = valibot.object({
|
|
13
|
-
* name: valibot.string().minLength(2),
|
|
14
|
-
* age: valibot.number().min(18)
|
|
15
|
-
* });
|
|
16
|
-
*
|
|
17
|
-
* useForm({
|
|
18
|
-
* resolver: valibotResolver(schema)
|
|
19
|
-
* });
|
|
20
|
-
*/
|
|
21
|
-
export declare function valibotResolver<TFieldValues extends FieldValues>(schema: BaseSchema<TFieldValues, TFieldValues, any> | BaseSchemaAsync<TFieldValues, TFieldValues, any>, schemaOptions?: Partial<Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>>, resolverOptions?: {
|
|
22
|
-
/**
|
|
23
|
-
* @default async
|
|
24
|
-
*/
|
|
25
|
-
mode?: 'sync' | 'async';
|
|
26
|
-
/**
|
|
27
|
-
* Return the raw input values rather than the parsed values.
|
|
28
|
-
* @default false
|
|
29
|
-
*/
|
|
30
|
-
raw?: boolean;
|
|
31
|
-
}): Resolver<InferOutput<typeof schema>>;
|
|
2
|
+
import { BaseSchema, BaseSchemaAsync, Config, InferIssue } from 'valibot';
|
|
3
|
+
export declare function valibotResolver<Input extends FieldValues, Context, Output>(schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>, schemaOptions?: Partial<Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>>, resolverOptions?: {
|
|
4
|
+
mode?: 'async' | 'sync';
|
|
5
|
+
raw?: false;
|
|
6
|
+
}): Resolver<Input, Context, Output>;
|
|
7
|
+
export declare function valibotResolver<Input extends FieldValues, Context, Output>(schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>, schemaOptions: Partial<Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>> | undefined, resolverOptions: {
|
|
8
|
+
mode?: 'async' | 'sync';
|
|
9
|
+
raw: true;
|
|
10
|
+
}): Resolver<Input, Context, Input>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valibot.js","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport {\n BaseSchema,\n BaseSchemaAsync
|
|
1
|
+
{"version":3,"file":"valibot.js","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport { BaseSchema, BaseSchemaAsync, Config, InferIssue } from 'valibot';\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions?: {\n mode?: 'async' | 'sync';\n raw?: false;\n },\n): Resolver<Input, Context, Output>;\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions:\n | Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >\n | undefined,\n resolverOptions: {\n mode?: 'async' | 'sync';\n raw: true;\n },\n): Resolver<Input, Context, Input>;\n\n/**\n * Creates a resolver for react-hook-form using Valibot schema validation\n * @param {BaseSchema<TFieldValues, TFieldValues, any> | BaseSchemaAsync<TFieldValues, TFieldValues, any>} schema - The Valibot schema to validate against\n * @param {Partial<Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>>} [schemaOptions] - Optional Valibot validation options\n * @param {Object} resolverOptions - Additional resolver configuration\n * @param {('sync' | 'async')} [resolverOptions.mode] - Validation mode\n * @param {boolean} [resolverOptions.raw] - If true, returns raw values rather than validated results\n * @returns {Resolver<InferOutput<typeof schema>>} A resolver function compatible with react-hook-form\n * @example\n * const schema = valibot.object({\n * name: valibot.string().minLength(2),\n * age: valibot.number().min(18)\n * });\n *\n * useForm({\n * resolver: valibotResolver(schema)\n * });\n */\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions: {\n /**\n * @default async\n */\n mode?: 'sync' | 'async';\n /**\n * Return the raw input values rather than the parsed values.\n * @default false\n */\n raw?: boolean;\n } = {},\n): Resolver<Input, Context, Output | Input> {\n return async (values: Input, _, options) => {\n // Check if we should validate all field criteria\n const validateAllFieldCriteria =\n !options.shouldUseNativeValidation && options.criteriaMode === 'all';\n\n // Parse values with Valibot schema\n const result = await safeParseAsync(\n schema,\n values,\n Object.assign({}, schemaOptions, {\n abortPipeEarly: !validateAllFieldCriteria,\n }),\n );\n\n // If there are issues, return them as errors\n if (result.issues) {\n // Create errors object\n const errors: Record<string, FieldError> = {};\n\n // Iterate over issues to add them to errors object\n for (; result.issues.length; ) {\n const issue = result.issues[0];\n // Create dot path from issue\n const path = getDotPath(issue);\n\n if (path) {\n // Add first error of path to errors object\n if (!errors[path]) {\n errors[path] = { message: issue.message, type: issue.type };\n }\n\n // If configured, add all errors of path to errors object\n if (validateAllFieldCriteria) {\n const types = errors[path].types;\n const messages = types && types[issue.type];\n errors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n errors,\n issue.type,\n messages\n ? ([] as string[]).concat(\n messages as string | string[],\n issue.message,\n )\n : issue.message,\n ) as FieldError;\n }\n }\n\n result.issues.shift();\n }\n\n // Return resolver result with errors\n return {\n values: {},\n errors: toNestErrors(errors, options),\n } as const;\n }\n\n // Otherwise, return resolver result with values\n return {\n values: resolverOptions.raw\n ? Object.assign({}, values)\n : (result.output as FieldValues),\n errors: {},\n };\n };\n}\n"],"names":["schema","schemaOptions","resolverOptions","values","_","options","validateAllFieldCriteria","shouldUseNativeValidation","criteriaMode","Promise","resolve","safeParseAsync","Object","assign","abortPipeEarly","then","result","issues","errors","length","issue","path","getDotPath","message","type","types","messages","appendErrors","concat","shift","toNestErrors","raw","output","e","reject"],"mappings":"+GAoDM,SACJA,EACAC,EAGAC,GAYA,YAZAA,IAAAA,IAAAA,EAUI,CAAA,GAEJ,SAAcC,EAAeC,EAAGC,GAAW,IAEzC,IAAMC,GACHD,EAAQE,2BAAsD,QAAzBF,EAAQG,aAAuB,OAAAC,QAAAC,QAGlDC,EAAAA,eACnBX,EACAG,EACAS,OAAOC,OAAO,CAAE,EAAEZ,EAAe,CAC/Ba,gBAAiBR,MAEpBS,KAAA,SANKC,GASN,GAAIA,EAAOC,OAAQ,CAKjB,IAHA,IAAMC,EAAqC,CAAA,EAGpCF,EAAOC,OAAOE,QAAU,CAC7B,IAAMC,EAAQJ,EAAOC,OAAO,GAEtBI,EAAOC,EAAAA,WAAWF,GAExB,GAAIC,IAEGH,EAAOG,KACVH,EAAOG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMI,OAInDlB,GAA0B,CAC5B,IAAMmB,EAAQP,EAAOG,GAAMI,MACrBC,EAAWD,GAASA,EAAML,EAAMI,MACtCN,EAAOG,GAAQM,EAAAA,aACbN,EACAf,EACAY,EACAE,EAAMI,KACNE,EACK,GAAgBE,OACfF,EACAN,EAAMG,SAERH,EAAMG,QAEd,CAGFP,EAAOC,OAAOY,OAChB,CAGA,MAAO,CACL1B,OAAQ,CAAA,EACRe,OAAQY,EAAAA,aAAaZ,EAAQb,GAEjC,CAGA,MAAO,CACLF,OAAQD,EAAgB6B,IACpBnB,OAAOC,OAAO,CAAA,EAAIV,GACjBa,EAAOgB,OACZd,OAAQ,CAAA,EACR,EACJ,CAAC,MAAAe,UAAAxB,QAAAyB,OAAAD,EACH,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valibot.modern.mjs","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport {\n BaseSchema,\n BaseSchemaAsync
|
|
1
|
+
{"version":3,"file":"valibot.modern.mjs","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport { BaseSchema, BaseSchemaAsync, Config, InferIssue } from 'valibot';\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions?: {\n mode?: 'async' | 'sync';\n raw?: false;\n },\n): Resolver<Input, Context, Output>;\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions:\n | Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >\n | undefined,\n resolverOptions: {\n mode?: 'async' | 'sync';\n raw: true;\n },\n): Resolver<Input, Context, Input>;\n\n/**\n * Creates a resolver for react-hook-form using Valibot schema validation\n * @param {BaseSchema<TFieldValues, TFieldValues, any> | BaseSchemaAsync<TFieldValues, TFieldValues, any>} schema - The Valibot schema to validate against\n * @param {Partial<Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>>} [schemaOptions] - Optional Valibot validation options\n * @param {Object} resolverOptions - Additional resolver configuration\n * @param {('sync' | 'async')} [resolverOptions.mode] - Validation mode\n * @param {boolean} [resolverOptions.raw] - If true, returns raw values rather than validated results\n * @returns {Resolver<InferOutput<typeof schema>>} A resolver function compatible with react-hook-form\n * @example\n * const schema = valibot.object({\n * name: valibot.string().minLength(2),\n * age: valibot.number().min(18)\n * });\n *\n * useForm({\n * resolver: valibotResolver(schema)\n * });\n */\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions: {\n /**\n * @default async\n */\n mode?: 'sync' | 'async';\n /**\n * Return the raw input values rather than the parsed values.\n * @default false\n */\n raw?: boolean;\n } = {},\n): Resolver<Input, Context, Output | Input> {\n return async (values: Input, _, options) => {\n // Check if we should validate all field criteria\n const validateAllFieldCriteria =\n !options.shouldUseNativeValidation && options.criteriaMode === 'all';\n\n // Parse values with Valibot schema\n const result = await safeParseAsync(\n schema,\n values,\n Object.assign({}, schemaOptions, {\n abortPipeEarly: !validateAllFieldCriteria,\n }),\n );\n\n // If there are issues, return them as errors\n if (result.issues) {\n // Create errors object\n const errors: Record<string, FieldError> = {};\n\n // Iterate over issues to add them to errors object\n for (; result.issues.length; ) {\n const issue = result.issues[0];\n // Create dot path from issue\n const path = getDotPath(issue);\n\n if (path) {\n // Add first error of path to errors object\n if (!errors[path]) {\n errors[path] = { message: issue.message, type: issue.type };\n }\n\n // If configured, add all errors of path to errors object\n if (validateAllFieldCriteria) {\n const types = errors[path].types;\n const messages = types && types[issue.type];\n errors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n errors,\n issue.type,\n messages\n ? ([] as string[]).concat(\n messages as string | string[],\n issue.message,\n )\n : issue.message,\n ) as FieldError;\n }\n }\n\n result.issues.shift();\n }\n\n // Return resolver result with errors\n return {\n values: {},\n errors: toNestErrors(errors, options),\n } as const;\n }\n\n // Otherwise, return resolver result with values\n return {\n values: resolverOptions.raw\n ? Object.assign({}, values)\n : (result.output as FieldValues),\n errors: {},\n };\n };\n}\n"],"names":["valibotResolver","schema","schemaOptions","resolverOptions","values","_","options","validateAllFieldCriteria","shouldUseNativeValidation","criteriaMode","result","safeParseAsync","Object","assign","abortPipeEarly","issues","errors","length","issue","path","getDotPath","message","type","types","messages","appendErrors","concat","shift","toNestErrors","raw","output"],"mappings":"2JAoDgB,SAAAA,EACdC,EACAC,EAGAC,EAUI,CAAA,GAEJ,OAAcC,MAAAA,EAAeC,EAAGC,KAE9B,MAAMC,GACHD,EAAQE,2BAAsD,QAAzBF,EAAQG,aAG1CC,QAAeC,EACnBV,EACAG,EACAQ,OAAOC,OAAO,CAAE,EAAEX,EAAe,CAC/BY,gBAAiBP,KAKrB,GAAIG,EAAOK,OAAQ,CAEjB,MAAMC,EAAqC,CAAA,EAG3C,KAAON,EAAOK,OAAOE,QAAU,CAC7B,MAAMC,EAAQR,EAAOK,OAAO,GAEtBI,EAAOC,EAAWF,GAExB,GAAIC,IAEGH,EAAOG,KACVH,EAAOG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMI,OAInDf,GAA0B,CAC5B,MAAMgB,EAAQP,EAAOG,GAAMI,MACrBC,EAAWD,GAASA,EAAML,EAAMI,MACtCN,EAAOG,GAAQM,EACbN,EACAZ,EACAS,EACAE,EAAMI,KACNE,EACK,GAAgBE,OACfF,EACAN,EAAMG,SAERH,EAAMG,QAEd,CAGFX,EAAOK,OAAOY,OAChB,CAGA,MAAO,CACLvB,OAAQ,CAAE,EACVY,OAAQY,EAAaZ,EAAQV,GAEjC,CAGA,MAAO,CACLF,OAAQD,EAAgB0B,IACpBjB,OAAOC,OAAO,CAAA,EAAIT,GACjBM,EAAOoB,OACZd,OAAQ,IAGd"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valibot.module.js","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport {\n BaseSchema,\n BaseSchemaAsync
|
|
1
|
+
{"version":3,"file":"valibot.module.js","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport { BaseSchema, BaseSchemaAsync, Config, InferIssue } from 'valibot';\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions?: {\n mode?: 'async' | 'sync';\n raw?: false;\n },\n): Resolver<Input, Context, Output>;\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions:\n | Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >\n | undefined,\n resolverOptions: {\n mode?: 'async' | 'sync';\n raw: true;\n },\n): Resolver<Input, Context, Input>;\n\n/**\n * Creates a resolver for react-hook-form using Valibot schema validation\n * @param {BaseSchema<TFieldValues, TFieldValues, any> | BaseSchemaAsync<TFieldValues, TFieldValues, any>} schema - The Valibot schema to validate against\n * @param {Partial<Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>>} [schemaOptions] - Optional Valibot validation options\n * @param {Object} resolverOptions - Additional resolver configuration\n * @param {('sync' | 'async')} [resolverOptions.mode] - Validation mode\n * @param {boolean} [resolverOptions.raw] - If true, returns raw values rather than validated results\n * @returns {Resolver<InferOutput<typeof schema>>} A resolver function compatible with react-hook-form\n * @example\n * const schema = valibot.object({\n * name: valibot.string().minLength(2),\n * age: valibot.number().min(18)\n * });\n *\n * useForm({\n * resolver: valibotResolver(schema)\n * });\n */\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions: {\n /**\n * @default async\n */\n mode?: 'sync' | 'async';\n /**\n * Return the raw input values rather than the parsed values.\n * @default false\n */\n raw?: boolean;\n } = {},\n): Resolver<Input, Context, Output | Input> {\n return async (values: Input, _, options) => {\n // Check if we should validate all field criteria\n const validateAllFieldCriteria =\n !options.shouldUseNativeValidation && options.criteriaMode === 'all';\n\n // Parse values with Valibot schema\n const result = await safeParseAsync(\n schema,\n values,\n Object.assign({}, schemaOptions, {\n abortPipeEarly: !validateAllFieldCriteria,\n }),\n );\n\n // If there are issues, return them as errors\n if (result.issues) {\n // Create errors object\n const errors: Record<string, FieldError> = {};\n\n // Iterate over issues to add them to errors object\n for (; result.issues.length; ) {\n const issue = result.issues[0];\n // Create dot path from issue\n const path = getDotPath(issue);\n\n if (path) {\n // Add first error of path to errors object\n if (!errors[path]) {\n errors[path] = { message: issue.message, type: issue.type };\n }\n\n // If configured, add all errors of path to errors object\n if (validateAllFieldCriteria) {\n const types = errors[path].types;\n const messages = types && types[issue.type];\n errors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n errors,\n issue.type,\n messages\n ? ([] as string[]).concat(\n messages as string | string[],\n issue.message,\n )\n : issue.message,\n ) as FieldError;\n }\n }\n\n result.issues.shift();\n }\n\n // Return resolver result with errors\n return {\n values: {},\n errors: toNestErrors(errors, options),\n } as const;\n }\n\n // Otherwise, return resolver result with values\n return {\n values: resolverOptions.raw\n ? Object.assign({}, values)\n : (result.output as FieldValues),\n errors: {},\n };\n };\n}\n"],"names":["valibotResolver","schema","schemaOptions","resolverOptions","values","_","options","validateAllFieldCriteria","shouldUseNativeValidation","criteriaMode","Promise","resolve","safeParseAsync","Object","assign","abortPipeEarly","then","result","issues","errors","length","issue","path","getDotPath","message","type","types","messages","appendErrors","concat","shift","toNestErrors","raw","output","e","reject"],"mappings":"2JAoDM,SAAUA,EACdC,EACAC,EAGAC,GAYA,YAZAA,IAAAA,IAAAA,EAUI,CAAA,GAEJ,SAAcC,EAAeC,EAAGC,GAAW,IAEzC,IAAMC,GACHD,EAAQE,2BAAsD,QAAzBF,EAAQG,aAAuB,OAAAC,QAAAC,QAGlDC,EACnBX,EACAG,EACAS,OAAOC,OAAO,CAAE,EAAEZ,EAAe,CAC/Ba,gBAAiBR,MAEpBS,KAAA,SANKC,GASN,GAAIA,EAAOC,OAAQ,CAKjB,IAHA,IAAMC,EAAqC,CAAA,EAGpCF,EAAOC,OAAOE,QAAU,CAC7B,IAAMC,EAAQJ,EAAOC,OAAO,GAEtBI,EAAOC,EAAWF,GAExB,GAAIC,IAEGH,EAAOG,KACVH,EAAOG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMI,OAInDlB,GAA0B,CAC5B,IAAMmB,EAAQP,EAAOG,GAAMI,MACrBC,EAAWD,GAASA,EAAML,EAAMI,MACtCN,EAAOG,GAAQM,EACbN,EACAf,EACAY,EACAE,EAAMI,KACNE,EACK,GAAgBE,OACfF,EACAN,EAAMG,SAERH,EAAMG,QAEd,CAGFP,EAAOC,OAAOY,OAChB,CAGA,MAAO,CACL1B,OAAQ,CAAA,EACRe,OAAQY,EAAaZ,EAAQb,GAEjC,CAGA,MAAO,CACLF,OAAQD,EAAgB6B,IACpBnB,OAAOC,OAAO,CAAA,EAAIV,GACjBa,EAAOgB,OACZd,OAAQ,CAAA,EACR,EACJ,CAAC,MAAAe,UAAAxB,QAAAyB,OAAAD,EACH,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"valibot.umd.js","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport {\n BaseSchema,\n BaseSchemaAsync
|
|
1
|
+
{"version":3,"file":"valibot.umd.js","sources":["../src/valibot.ts"],"sourcesContent":["import { toNestErrors } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport { getDotPath, safeParseAsync } from 'valibot';\nimport { BaseSchema, BaseSchemaAsync, Config, InferIssue } from 'valibot';\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions?: {\n mode?: 'async' | 'sync';\n raw?: false;\n },\n): Resolver<Input, Context, Output>;\n\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions:\n | Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >\n | undefined,\n resolverOptions: {\n mode?: 'async' | 'sync';\n raw: true;\n },\n): Resolver<Input, Context, Input>;\n\n/**\n * Creates a resolver for react-hook-form using Valibot schema validation\n * @param {BaseSchema<TFieldValues, TFieldValues, any> | BaseSchemaAsync<TFieldValues, TFieldValues, any>} schema - The Valibot schema to validate against\n * @param {Partial<Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>>} [schemaOptions] - Optional Valibot validation options\n * @param {Object} resolverOptions - Additional resolver configuration\n * @param {('sync' | 'async')} [resolverOptions.mode] - Validation mode\n * @param {boolean} [resolverOptions.raw] - If true, returns raw values rather than validated results\n * @returns {Resolver<InferOutput<typeof schema>>} A resolver function compatible with react-hook-form\n * @example\n * const schema = valibot.object({\n * name: valibot.string().minLength(2),\n * age: valibot.number().min(18)\n * });\n *\n * useForm({\n * resolver: valibotResolver(schema)\n * });\n */\nexport function valibotResolver<Input extends FieldValues, Context, Output>(\n schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,\n schemaOptions?: Partial<\n Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>\n >,\n resolverOptions: {\n /**\n * @default async\n */\n mode?: 'sync' | 'async';\n /**\n * Return the raw input values rather than the parsed values.\n * @default false\n */\n raw?: boolean;\n } = {},\n): Resolver<Input, Context, Output | Input> {\n return async (values: Input, _, options) => {\n // Check if we should validate all field criteria\n const validateAllFieldCriteria =\n !options.shouldUseNativeValidation && options.criteriaMode === 'all';\n\n // Parse values with Valibot schema\n const result = await safeParseAsync(\n schema,\n values,\n Object.assign({}, schemaOptions, {\n abortPipeEarly: !validateAllFieldCriteria,\n }),\n );\n\n // If there are issues, return them as errors\n if (result.issues) {\n // Create errors object\n const errors: Record<string, FieldError> = {};\n\n // Iterate over issues to add them to errors object\n for (; result.issues.length; ) {\n const issue = result.issues[0];\n // Create dot path from issue\n const path = getDotPath(issue);\n\n if (path) {\n // Add first error of path to errors object\n if (!errors[path]) {\n errors[path] = { message: issue.message, type: issue.type };\n }\n\n // If configured, add all errors of path to errors object\n if (validateAllFieldCriteria) {\n const types = errors[path].types;\n const messages = types && types[issue.type];\n errors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n errors,\n issue.type,\n messages\n ? ([] as string[]).concat(\n messages as string | string[],\n issue.message,\n )\n : issue.message,\n ) as FieldError;\n }\n }\n\n result.issues.shift();\n }\n\n // Return resolver result with errors\n return {\n values: {},\n errors: toNestErrors(errors, options),\n } as const;\n }\n\n // Otherwise, return resolver result with values\n return {\n values: resolverOptions.raw\n ? Object.assign({}, values)\n : (result.output as FieldValues),\n errors: {},\n };\n };\n}\n"],"names":["schema","schemaOptions","resolverOptions","values","_","options","validateAllFieldCriteria","shouldUseNativeValidation","criteriaMode","Promise","resolve","safeParseAsync","Object","assign","abortPipeEarly","then","result","issues","errors","length","issue","path","getDotPath","message","type","types","messages","appendErrors","concat","shift","toNestErrors","raw","output","e","reject"],"mappings":"ubAoDM,SACJA,EACAC,EAGAC,GAYA,YAZAA,IAAAA,IAAAA,EAUI,CAAA,GAEJ,SAAcC,EAAeC,EAAGC,GAAW,IAEzC,IAAMC,GACHD,EAAQE,2BAAsD,QAAzBF,EAAQG,aAAuB,OAAAC,QAAAC,QAGlDC,EAAAA,eACnBX,EACAG,EACAS,OAAOC,OAAO,CAAE,EAAEZ,EAAe,CAC/Ba,gBAAiBR,MAEpBS,KAAA,SANKC,GASN,GAAIA,EAAOC,OAAQ,CAKjB,IAHA,IAAMC,EAAqC,CAAA,EAGpCF,EAAOC,OAAOE,QAAU,CAC7B,IAAMC,EAAQJ,EAAOC,OAAO,GAEtBI,EAAOC,EAAAA,WAAWF,GAExB,GAAIC,IAEGH,EAAOG,KACVH,EAAOG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMI,OAInDlB,GAA0B,CAC5B,IAAMmB,EAAQP,EAAOG,GAAMI,MACrBC,EAAWD,GAASA,EAAML,EAAMI,MACtCN,EAAOG,GAAQM,EAAAA,aACbN,EACAf,EACAY,EACAE,EAAMI,KACNE,EACK,GAAgBE,OACfF,EACAN,EAAMG,SAERH,EAAMG,QAEd,CAGFP,EAAOC,OAAOY,OAChB,CAGA,MAAO,CACL1B,OAAQ,CAAA,EACRe,OAAQY,EAAAA,aAAaZ,EAAQb,GAEjC,CAGA,MAAO,CACLF,OAAQD,EAAgB6B,IACpBnB,OAAOC,OAAO,CAAA,EAAIV,GACjBa,EAAOgB,OACZd,OAAQ,CAAA,EACR,EACJ,CAAC,MAAAe,UAAAxB,QAAAyB,OAAAD,EACH,CAAA,CAAA"}
|
package/valibot/package.json
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { SubmitHandler } from 'react-hook-form';
|
|
2
|
+
import { useForm } from 'react-hook-form';
|
|
3
|
+
import { Resolver } from 'react-hook-form';
|
|
4
|
+
import * as v from 'valibot';
|
|
2
5
|
/* eslint-disable no-console, @typescript-eslint/ban-ts-comment */
|
|
3
6
|
import { valibotResolver } from '..';
|
|
4
7
|
import {
|
|
@@ -21,7 +24,7 @@ describe('valibotResolver', () => {
|
|
|
21
24
|
...a,
|
|
22
25
|
};
|
|
23
26
|
});
|
|
24
|
-
const funcSpy = vi.spyOn(
|
|
27
|
+
const funcSpy = vi.spyOn(v, 'safeParseAsync');
|
|
25
28
|
|
|
26
29
|
const result = await valibotResolver(schema, undefined, {
|
|
27
30
|
mode: 'sync',
|
|
@@ -40,7 +43,7 @@ describe('valibotResolver', () => {
|
|
|
40
43
|
...a,
|
|
41
44
|
};
|
|
42
45
|
});
|
|
43
|
-
const funcSpy = vi.spyOn(
|
|
46
|
+
const funcSpy = vi.spyOn(v, 'safeParseAsync');
|
|
44
47
|
|
|
45
48
|
const result = await valibotResolver(schema, undefined, {
|
|
46
49
|
mode: 'sync',
|
|
@@ -138,4 +141,67 @@ describe('valibotResolver', () => {
|
|
|
138
141
|
values: {},
|
|
139
142
|
});
|
|
140
143
|
});
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Type inference tests
|
|
147
|
+
*/
|
|
148
|
+
it('should correctly infer the output type from a valibot schema', () => {
|
|
149
|
+
const resolver = valibotResolver(v.object({ id: v.number() }));
|
|
150
|
+
|
|
151
|
+
expectTypeOf(resolver).toEqualTypeOf<
|
|
152
|
+
Resolver<{ id: number }, unknown, { id: number }>
|
|
153
|
+
>();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should correctly infer the output type from a valibot schema using a transform', () => {
|
|
157
|
+
const resolver = valibotResolver(
|
|
158
|
+
v.object({
|
|
159
|
+
id: v.pipe(
|
|
160
|
+
v.number(),
|
|
161
|
+
v.transform((val) => String(val)),
|
|
162
|
+
),
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expectTypeOf(resolver).toEqualTypeOf<
|
|
167
|
+
Resolver<{ id: number }, unknown, { id: string }>
|
|
168
|
+
>();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('should correctly infer the output type from a valibot schema for the handleSubmit function in useForm', () => {
|
|
172
|
+
const schema = v.object({ id: v.number() });
|
|
173
|
+
|
|
174
|
+
const form = useForm({
|
|
175
|
+
resolver: valibotResolver(schema),
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expectTypeOf(form.watch('id')).toEqualTypeOf<number>();
|
|
179
|
+
|
|
180
|
+
expectTypeOf(form.handleSubmit).parameter(0).toEqualTypeOf<
|
|
181
|
+
SubmitHandler<{
|
|
182
|
+
id: number;
|
|
183
|
+
}>
|
|
184
|
+
>();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should correctly infer the output type from a valibot schema with a transform for the handleSubmit function in useForm', () => {
|
|
188
|
+
const schema = v.object({
|
|
189
|
+
id: v.pipe(
|
|
190
|
+
v.number(),
|
|
191
|
+
v.transform((val) => String(val)),
|
|
192
|
+
),
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
const form = useForm({
|
|
196
|
+
resolver: valibotResolver(schema),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
expectTypeOf(form.watch('id')).toEqualTypeOf<number>();
|
|
200
|
+
|
|
201
|
+
expectTypeOf(form.handleSubmit).parameter(0).toEqualTypeOf<
|
|
202
|
+
SubmitHandler<{
|
|
203
|
+
id: string;
|
|
204
|
+
}>
|
|
205
|
+
>();
|
|
206
|
+
});
|
|
141
207
|
});
|
package/valibot/src/valibot.ts
CHANGED
|
@@ -6,13 +6,31 @@ import {
|
|
|
6
6
|
appendErrors,
|
|
7
7
|
} from 'react-hook-form';
|
|
8
8
|
import { getDotPath, safeParseAsync } from 'valibot';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
import { BaseSchema, BaseSchemaAsync, Config, InferIssue } from 'valibot';
|
|
10
|
+
|
|
11
|
+
export function valibotResolver<Input extends FieldValues, Context, Output>(
|
|
12
|
+
schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,
|
|
13
|
+
schemaOptions?: Partial<
|
|
14
|
+
Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>
|
|
15
|
+
>,
|
|
16
|
+
resolverOptions?: {
|
|
17
|
+
mode?: 'async' | 'sync';
|
|
18
|
+
raw?: false;
|
|
19
|
+
},
|
|
20
|
+
): Resolver<Input, Context, Output>;
|
|
21
|
+
|
|
22
|
+
export function valibotResolver<Input extends FieldValues, Context, Output>(
|
|
23
|
+
schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,
|
|
24
|
+
schemaOptions:
|
|
25
|
+
| Partial<
|
|
26
|
+
Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>
|
|
27
|
+
>
|
|
28
|
+
| undefined,
|
|
29
|
+
resolverOptions: {
|
|
30
|
+
mode?: 'async' | 'sync';
|
|
31
|
+
raw: true;
|
|
32
|
+
},
|
|
33
|
+
): Resolver<Input, Context, Input>;
|
|
16
34
|
|
|
17
35
|
/**
|
|
18
36
|
* Creates a resolver for react-hook-form using Valibot schema validation
|
|
@@ -32,10 +50,8 @@ import {
|
|
|
32
50
|
* resolver: valibotResolver(schema)
|
|
33
51
|
* });
|
|
34
52
|
*/
|
|
35
|
-
export function valibotResolver<
|
|
36
|
-
schema:
|
|
37
|
-
| BaseSchema<TFieldValues, TFieldValues, any>
|
|
38
|
-
| BaseSchemaAsync<TFieldValues, TFieldValues, any>,
|
|
53
|
+
export function valibotResolver<Input extends FieldValues, Context, Output>(
|
|
54
|
+
schema: BaseSchema<Input, Output, any> | BaseSchemaAsync<Input, Output, any>,
|
|
39
55
|
schemaOptions?: Partial<
|
|
40
56
|
Omit<Config<InferIssue<typeof schema>>, 'abortPipeEarly' | 'skipPipe'>
|
|
41
57
|
>,
|
|
@@ -50,8 +66,8 @@ export function valibotResolver<TFieldValues extends FieldValues>(
|
|
|
50
66
|
*/
|
|
51
67
|
raw?: boolean;
|
|
52
68
|
} = {},
|
|
53
|
-
): Resolver<
|
|
54
|
-
return async (values, _, options) => {
|
|
69
|
+
): Resolver<Input, Context, Output | Input> {
|
|
70
|
+
return async (values: Input, _, options) => {
|
|
55
71
|
// Check if we should validate all field criteria
|
|
56
72
|
const validateAllFieldCriteria =
|
|
57
73
|
!options.shouldUseNativeValidation && options.criteriaMode === 'all';
|