@hookform/resolvers 2.8.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.
Files changed (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +420 -0
  3. package/class-validator/dist/class-validator.d.ts +2 -0
  4. package/class-validator/dist/class-validator.js +2 -0
  5. package/class-validator/dist/class-validator.js.map +1 -0
  6. package/class-validator/dist/class-validator.mjs +2 -0
  7. package/class-validator/dist/class-validator.modern.js +2 -0
  8. package/class-validator/dist/class-validator.modern.js.map +1 -0
  9. package/class-validator/dist/class-validator.module.js +2 -0
  10. package/class-validator/dist/class-validator.module.js.map +1 -0
  11. package/class-validator/dist/class-validator.umd.js +2 -0
  12. package/class-validator/dist/class-validator.umd.js.map +1 -0
  13. package/class-validator/dist/index.d.ts +2 -0
  14. package/class-validator/dist/types.d.ts +8 -0
  15. package/class-validator/package.json +19 -0
  16. package/class-validator/src/__tests__/Form-native-validation.tsx +83 -0
  17. package/class-validator/src/__tests__/Form.tsx +55 -0
  18. package/class-validator/src/__tests__/__fixtures__/data.ts +88 -0
  19. package/class-validator/src/__tests__/__snapshots__/class-validator.ts.snap +207 -0
  20. package/class-validator/src/__tests__/class-validator.ts +87 -0
  21. package/class-validator/src/class-validator.ts +62 -0
  22. package/class-validator/src/index.ts +2 -0
  23. package/class-validator/src/types.ts +22 -0
  24. package/computed-types/dist/computed-types.d.ts +2 -0
  25. package/computed-types/dist/computed-types.js +2 -0
  26. package/computed-types/dist/computed-types.js.map +1 -0
  27. package/computed-types/dist/computed-types.mjs +2 -0
  28. package/computed-types/dist/computed-types.modern.js +2 -0
  29. package/computed-types/dist/computed-types.modern.js.map +1 -0
  30. package/computed-types/dist/computed-types.module.js +2 -0
  31. package/computed-types/dist/computed-types.module.js.map +1 -0
  32. package/computed-types/dist/computed-types.umd.js +2 -0
  33. package/computed-types/dist/computed-types.umd.js.map +1 -0
  34. package/computed-types/dist/index.d.ts +2 -0
  35. package/computed-types/dist/types.d.ts +2 -0
  36. package/computed-types/package.json +17 -0
  37. package/computed-types/src/__tests__/Form-native-validation.tsx +85 -0
  38. package/computed-types/src/__tests__/Form.tsx +54 -0
  39. package/computed-types/src/__tests__/__fixtures__/data.ts +72 -0
  40. package/computed-types/src/__tests__/__snapshots__/computed-types.ts.snap +55 -0
  41. package/computed-types/src/__tests__/computed-types.ts +24 -0
  42. package/computed-types/src/computed-types.ts +43 -0
  43. package/computed-types/src/index.ts +2 -0
  44. package/computed-types/src/types.ts +14 -0
  45. package/dist/index.d.ts +2 -0
  46. package/dist/resolvers.js +2 -0
  47. package/dist/resolvers.js.map +1 -0
  48. package/dist/resolvers.mjs +2 -0
  49. package/dist/resolvers.mjs.map +1 -0
  50. package/dist/resolvers.module.js +2 -0
  51. package/dist/resolvers.module.js.map +1 -0
  52. package/dist/resolvers.umd.js +2 -0
  53. package/dist/resolvers.umd.js.map +1 -0
  54. package/dist/toNestError.d.ts +2 -0
  55. package/dist/validateFieldsNatively.d.ts +2 -0
  56. package/io-ts/dist/arrayToPath.d.ts +3 -0
  57. package/io-ts/dist/errorsToRecord.d.ts +5 -0
  58. package/io-ts/dist/index.d.ts +2 -0
  59. package/io-ts/dist/io-ts.d.ts +2 -0
  60. package/io-ts/dist/io-ts.js +2 -0
  61. package/io-ts/dist/io-ts.js.map +1 -0
  62. package/io-ts/dist/io-ts.mjs +2 -0
  63. package/io-ts/dist/io-ts.modern.js +2 -0
  64. package/io-ts/dist/io-ts.modern.js.map +1 -0
  65. package/io-ts/dist/io-ts.module.js +2 -0
  66. package/io-ts/dist/io-ts.module.js.map +1 -0
  67. package/io-ts/dist/io-ts.umd.js +2 -0
  68. package/io-ts/dist/io-ts.umd.js.map +1 -0
  69. package/io-ts/dist/types.d.ts +7 -0
  70. package/io-ts/package.json +19 -0
  71. package/io-ts/src/__tests__/Form-native-validation.tsx +89 -0
  72. package/io-ts/src/__tests__/Form.tsx +65 -0
  73. package/io-ts/src/__tests__/__fixtures__/data.ts +129 -0
  74. package/io-ts/src/__tests__/__snapshots__/io-ts.ts.snap +89 -0
  75. package/io-ts/src/__tests__/io-ts.ts +37 -0
  76. package/io-ts/src/arrayToPath.ts +18 -0
  77. package/io-ts/src/errorsToRecord.ts +131 -0
  78. package/io-ts/src/index.ts +2 -0
  79. package/io-ts/src/io-ts.ts +33 -0
  80. package/io-ts/src/types.ts +23 -0
  81. package/joi/dist/index.d.ts +2 -0
  82. package/joi/dist/joi.d.ts +2 -0
  83. package/joi/dist/joi.js +2 -0
  84. package/joi/dist/joi.js.map +1 -0
  85. package/joi/dist/joi.mjs +2 -0
  86. package/joi/dist/joi.modern.js +2 -0
  87. package/joi/dist/joi.modern.js.map +1 -0
  88. package/joi/dist/joi.module.js +2 -0
  89. package/joi/dist/joi.module.js.map +1 -0
  90. package/joi/dist/joi.umd.js +2 -0
  91. package/joi/dist/joi.umd.js.map +1 -0
  92. package/joi/dist/types.d.ts +5 -0
  93. package/joi/package.json +17 -0
  94. package/joi/src/__tests__/Form-native-validation.tsx +89 -0
  95. package/joi/src/__tests__/Form.tsx +61 -0
  96. package/joi/src/__tests__/__fixtures__/data.ts +85 -0
  97. package/joi/src/__tests__/__snapshots__/joi.ts.snap +293 -0
  98. package/joi/src/__tests__/joi.ts +98 -0
  99. package/joi/src/index.ts +2 -0
  100. package/joi/src/joi.ts +81 -0
  101. package/joi/src/types.ts +16 -0
  102. package/nope/dist/index.d.ts +2 -0
  103. package/nope/dist/nope.d.ts +2 -0
  104. package/nope/dist/nope.js +2 -0
  105. package/nope/dist/nope.js.map +1 -0
  106. package/nope/dist/nope.mjs +2 -0
  107. package/nope/dist/nope.modern.js +2 -0
  108. package/nope/dist/nope.modern.js.map +1 -0
  109. package/nope/dist/nope.module.js +2 -0
  110. package/nope/dist/nope.module.js.map +1 -0
  111. package/nope/dist/nope.umd.js +2 -0
  112. package/nope/dist/nope.umd.js.map +1 -0
  113. package/nope/dist/types.d.ts +6 -0
  114. package/nope/package.json +18 -0
  115. package/nope/src/__tests__/Form-native-validation.tsx +89 -0
  116. package/nope/src/__tests__/Form.tsx +57 -0
  117. package/nope/src/__tests__/__fixtures__/data.ts +70 -0
  118. package/nope/src/__tests__/__snapshots__/nope.ts.snap +43 -0
  119. package/nope/src/__tests__/nope.ts +28 -0
  120. package/nope/src/index.ts +2 -0
  121. package/nope/src/nope.ts +46 -0
  122. package/nope/src/types.ts +22 -0
  123. package/package.json +216 -0
  124. package/superstruct/dist/index.d.ts +2 -0
  125. package/superstruct/dist/superstruct.d.ts +2 -0
  126. package/superstruct/dist/superstruct.js +2 -0
  127. package/superstruct/dist/superstruct.js.map +1 -0
  128. package/superstruct/dist/superstruct.mjs +2 -0
  129. package/superstruct/dist/superstruct.modern.js +2 -0
  130. package/superstruct/dist/superstruct.modern.js.map +1 -0
  131. package/superstruct/dist/superstruct.module.js +2 -0
  132. package/superstruct/dist/superstruct.module.js.map +1 -0
  133. package/superstruct/dist/superstruct.umd.js +2 -0
  134. package/superstruct/dist/superstruct.umd.js.map +1 -0
  135. package/superstruct/dist/types.d.ts +5 -0
  136. package/superstruct/package.json +18 -0
  137. package/superstruct/src/__tests__/Form-native-validation.tsx +86 -0
  138. package/superstruct/src/__tests__/Form.tsx +62 -0
  139. package/superstruct/src/__tests__/__fixtures__/data.ts +75 -0
  140. package/superstruct/src/__tests__/__snapshots__/superstruct.ts.snap +64 -0
  141. package/superstruct/src/__tests__/superstruct.ts +24 -0
  142. package/superstruct/src/index.ts +2 -0
  143. package/superstruct/src/superstruct.ts +37 -0
  144. package/superstruct/src/types.ts +17 -0
  145. package/typanion/dist/index.d.ts +2 -0
  146. package/typanion/dist/typanion.d.ts +2 -0
  147. package/typanion/dist/typanion.js +2 -0
  148. package/typanion/dist/typanion.js.map +1 -0
  149. package/typanion/dist/typanion.mjs +2 -0
  150. package/typanion/dist/typanion.modern.js +2 -0
  151. package/typanion/dist/typanion.modern.js.map +1 -0
  152. package/typanion/dist/typanion.module.js +2 -0
  153. package/typanion/dist/typanion.module.js.map +1 -0
  154. package/typanion/dist/typanion.umd.js +2 -0
  155. package/typanion/dist/typanion.umd.js.map +1 -0
  156. package/typanion/dist/types.d.ts +6 -0
  157. package/typanion/package.json +18 -0
  158. package/typanion/src/__tests__/Form-native-validation.tsx +89 -0
  159. package/typanion/src/__tests__/Form.tsx +61 -0
  160. package/typanion/src/__tests__/__fixtures__/data.ts +77 -0
  161. package/typanion/src/__tests__/__snapshots__/typanion.ts.snap +67 -0
  162. package/typanion/src/__tests__/typanion.ts +31 -0
  163. package/typanion/src/index.ts +2 -0
  164. package/typanion/src/typanion.ts +44 -0
  165. package/typanion/src/types.ts +28 -0
  166. package/vest/dist/index.d.ts +1 -0
  167. package/vest/dist/vest.d.ts +2 -0
  168. package/vest/dist/vest.js +2 -0
  169. package/vest/dist/vest.js.map +1 -0
  170. package/vest/dist/vest.mjs +2 -0
  171. package/vest/dist/vest.modern.js +2 -0
  172. package/vest/dist/vest.modern.js.map +1 -0
  173. package/vest/dist/vest.module.js +2 -0
  174. package/vest/dist/vest.module.js.map +1 -0
  175. package/vest/dist/vest.umd.js +2 -0
  176. package/vest/dist/vest.umd.js.map +1 -0
  177. package/vest/package.json +18 -0
  178. package/vest/src/__tests__/Form-native-validation.tsx +93 -0
  179. package/vest/src/__tests__/Form.tsx +64 -0
  180. package/vest/src/__tests__/__fixtures__/data.ts +67 -0
  181. package/vest/src/__tests__/__snapshots__/vest.ts.snap +141 -0
  182. package/vest/src/__tests__/vest.ts +71 -0
  183. package/vest/src/index.ts +1 -0
  184. package/vest/src/types.ts +20 -0
  185. package/vest/src/vest.ts +51 -0
  186. package/yup/dist/index.d.ts +2 -0
  187. package/yup/dist/types.d.ts +8 -0
  188. package/yup/dist/yup.d.ts +2 -0
  189. package/yup/dist/yup.js +2 -0
  190. package/yup/dist/yup.js.map +1 -0
  191. package/yup/dist/yup.mjs +2 -0
  192. package/yup/dist/yup.modern.js +2 -0
  193. package/yup/dist/yup.modern.js.map +1 -0
  194. package/yup/dist/yup.module.js +2 -0
  195. package/yup/dist/yup.module.js.map +1 -0
  196. package/yup/dist/yup.umd.js +2 -0
  197. package/yup/dist/yup.umd.js.map +1 -0
  198. package/yup/package.json +17 -0
  199. package/yup/src/__tests__/Form-native-validation.tsx +85 -0
  200. package/yup/src/__tests__/Form.tsx +54 -0
  201. package/yup/src/__tests__/__fixtures__/data.ts +72 -0
  202. package/yup/src/__tests__/__snapshots__/yup.ts.snap +231 -0
  203. package/yup/src/__tests__/yup.ts +174 -0
  204. package/yup/src/index.ts +2 -0
  205. package/yup/src/types.ts +21 -0
  206. package/yup/src/yup.ts +75 -0
  207. package/zod/dist/index.d.ts +2 -0
  208. package/zod/dist/types.d.ts +5 -0
  209. package/zod/dist/zod.d.ts +2 -0
  210. package/zod/dist/zod.js +2 -0
  211. package/zod/dist/zod.js.map +1 -0
  212. package/zod/dist/zod.mjs +2 -0
  213. package/zod/dist/zod.modern.js +2 -0
  214. package/zod/dist/zod.modern.js.map +1 -0
  215. package/zod/dist/zod.module.js +2 -0
  216. package/zod/dist/zod.module.js.map +1 -0
  217. package/zod/dist/zod.umd.js +2 -0
  218. package/zod/dist/zod.umd.js.map +1 -0
  219. package/zod/package.json +17 -0
  220. package/zod/src/__tests__/Form-native-validation.tsx +85 -0
  221. package/zod/src/__tests__/Form.tsx +54 -0
  222. package/zod/src/__tests__/__fixtures__/data.ts +81 -0
  223. package/zod/src/__tests__/__snapshots__/zod.ts.snap +377 -0
  224. package/zod/src/__tests__/zod.ts +77 -0
  225. package/zod/src/index.ts +2 -0
  226. package/zod/src/types.ts +16 -0
  227. package/zod/src/zod.ts +85 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019-present Beier(Bill) Luo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,420 @@
1
+ <div align="center">
2
+ <p align="center">
3
+ <a href="https://react-hook-form.com" title="React Hook Form - Simple React forms validation">
4
+ <img src="https://raw.githubusercontent.com/bluebill1049/react-hook-form/master/docs/logo.png" alt="React Hook Form Logo - React hook custom hook for form validation" />
5
+ </a>
6
+ </p>
7
+ </div>
8
+
9
+ <p align="center">Performant, flexible and extensible forms with easy to use validation.</p>
10
+
11
+ <div align="center">
12
+
13
+ [![npm downloads](https://img.shields.io/npm/dm/@hookform/resolvers.svg?style=for-the-badge)](https://www.npmjs.com/package/@hookform/resolvers)
14
+ [![npm](https://img.shields.io/npm/dt/@hookform/resolvers.svg?style=for-the-badge)](https://www.npmjs.com/package/@hookform/resolvers)
15
+ [![npm](https://img.shields.io/bundlephobia/minzip/@hookform/resolvers?style=for-the-badge)](https://bundlephobia.com/result?p=@hookform/resolvers)
16
+
17
+ </div>
18
+
19
+ ## Install
20
+
21
+ $ npm install @hookform/resolvers
22
+
23
+ ## Links
24
+
25
+ - [React-hook-form validation resolver documentation ](https://react-hook-form.com/api/useform/#resolver)
26
+
27
+ ## API
28
+
29
+ `resolver(schema: object, schemaOptions?: object, resolverOptions: { mode: 'async' | 'sync' })`
30
+
31
+ | | type | Required | Description |
32
+ | --------------- | -------- | -------- | --------------------------------------------- |
33
+ | schema | `object` | ✓ | validation schema |
34
+ | schemaOptions | `object` | | validation library schema options |
35
+ | resolverOptions | `object` | | resolver options, `async` is the default mode |
36
+
37
+ ## Quickstart
38
+
39
+ ### [Yup](https://github.com/jquense/yup)
40
+
41
+ Dead simple Object schema validation.
42
+
43
+ [![npm](https://img.shields.io/bundlephobia/minzip/yup?style=for-the-badge)](https://bundlephobia.com/result?p=yup)
44
+
45
+ ```typescript jsx
46
+ import { useForm } from 'react-hook-form';
47
+ import { yupResolver } from '@hookform/resolvers/yup';
48
+ import * as yup from 'yup';
49
+
50
+ const schema = yup.object().shape({
51
+ name: yup.string().required(),
52
+ age: yup.number().required(),
53
+ });
54
+
55
+ const App = () => {
56
+ const { register, handleSubmit } = useForm({
57
+ resolver: yupResolver(schema),
58
+ });
59
+
60
+ return (
61
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
62
+ <input {...register('name')} />
63
+ <input type="number" {...register('age')} />
64
+ <input type="submit" />
65
+ </form>
66
+ );
67
+ };
68
+ ```
69
+
70
+ ### [Zod](https://github.com/vriad/zod)
71
+
72
+ TypeScript-first schema validation with static type inference
73
+
74
+ [![npm](https://img.shields.io/bundlephobia/minzip/zod?style=for-the-badge)](https://bundlephobia.com/result?p=zod)
75
+
76
+ > ⚠️ Example below uses the `valueAsNumber`, which requires `react-hook-form` v6.12.0 (released Nov 28, 2020) or later.
77
+
78
+ ```tsx
79
+ import { useForm } from 'react-hook-form';
80
+ import { zodResolver } from '@hookform/resolvers/zod';
81
+ import * as z from 'zod';
82
+
83
+ const schema = z.object({
84
+ name: z.string().nonempty({ message: 'Required' }),
85
+ age: z.number().min(10),
86
+ });
87
+
88
+ const App = () => {
89
+ const {
90
+ register,
91
+ handleSubmit,
92
+ formState: { errors },
93
+ } = useForm({
94
+ resolver: zodResolver(schema),
95
+ });
96
+
97
+ return (
98
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
99
+ <input {...register('name')} />
100
+ {errors.name?.message && <p>{errors.name?.message}</p>}
101
+ <input type="number" {...register('age', { valueAsNumber: true })} />
102
+ {errors.age?.message && <p>{errors.age?.message}</p>}
103
+ <input type="submit" />
104
+ </form>
105
+ );
106
+ };
107
+ ```
108
+
109
+ ### [Superstruct](https://github.com/ianstormtaylor/superstruct)
110
+
111
+ A simple and composable way to validate data in JavaScript (or TypeScript).
112
+
113
+ [![npm](https://img.shields.io/bundlephobia/minzip/superstruct?style=for-the-badge)](https://bundlephobia.com/result?p=superstruct)
114
+
115
+ ```typescript jsx
116
+ import { useForm } from 'react-hook-form';
117
+ import { superstructResolver } from '@hookform/resolvers/superstruct';
118
+ import { object, string, number } from 'superstruct';
119
+
120
+ const schema = object({
121
+ name: string(),
122
+ age: number(),
123
+ });
124
+
125
+ const App = () => {
126
+ const { register, handleSubmit } = useForm({
127
+ resolver: superstructResolver(schema),
128
+ });
129
+
130
+ return (
131
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
132
+ <input {...register('name')} />
133
+ <input type="number" {...register('age', { valueAsNumber: true })} />
134
+ <input type="submit" />
135
+ </form>
136
+ );
137
+ };
138
+ ```
139
+
140
+ ### [Joi](https://github.com/sideway/joi)
141
+
142
+ The most powerful data validation library for JS.
143
+
144
+ [![npm](https://img.shields.io/bundlephobia/minzip/joi?style=for-the-badge)](https://bundlephobia.com/result?p=joi)
145
+
146
+ ```typescript jsx
147
+ import { useForm } from 'react-hook-form';
148
+ import { joiResolver } from '@hookform/resolvers/joi';
149
+ import Joi from 'joi';
150
+
151
+ const schema = Joi.object({
152
+ name: Joi.string().required(),
153
+ age: Joi.number().required(),
154
+ });
155
+
156
+ const App = () => {
157
+ const { register, handleSubmit } = useForm({
158
+ resolver: joiResolver(schema),
159
+ });
160
+
161
+ return (
162
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
163
+ <input {...register('name')} />
164
+ <input type="number" {...register('age')} />
165
+ <input type="submit" />
166
+ </form>
167
+ );
168
+ };
169
+ ```
170
+
171
+ ### [Vest](https://github.com/ealush/vest)
172
+
173
+ Vest 🦺 Declarative Validation Testing.
174
+
175
+ [![npm](https://img.shields.io/bundlephobia/minzip/vest?style=for-the-badge)](https://bundlephobia.com/result?p=vest)
176
+
177
+ ```typescript jsx
178
+ import { useForm } from 'react-hook-form';
179
+ import { vestResolver } from '@hookform/resolvers/vest';
180
+ import vest, { test, enforce } from 'vest';
181
+
182
+ const validationSuite = vest.create((data = {}) => {
183
+ test('username', 'Username is required', () => {
184
+ enforce(data.username).isNotEmpty();
185
+ });
186
+
187
+ test('password', 'Password is required', () => {
188
+ enforce(data.password).isNotEmpty();
189
+ });
190
+ });
191
+
192
+ const App = () => {
193
+ const { register, handleSubmit, errors } = useForm({
194
+ resolver: vestResolver(validationSuite),
195
+ });
196
+
197
+ return (
198
+ <form onSubmit={handleSubmit((data) => console.log(data))}>
199
+ <input {...register('username')} />
200
+ <input type="password" {...register('password')} />
201
+ <input type="submit" />
202
+ </form>
203
+ );
204
+ };
205
+ ```
206
+
207
+ ### [Class Validator](https://github.com/typestack/class-validator)
208
+
209
+ Decorator-based property validation for classes.
210
+
211
+ [![npm](https://img.shields.io/bundlephobia/minzip/class-validator?style=for-the-badge)](https://bundlephobia.com/result?p=class-validator)
212
+
213
+ > ⚠️ Remember to add these options to your `tsconfig.json`!
214
+
215
+ ```
216
+ "strictPropertyInitialization": false,
217
+ "experimentalDecorators": true
218
+ ```
219
+
220
+ ```tsx
221
+ import { useForm } from 'react-hook-form';
222
+ import { classValidatorResolver } from '@hookform/resolvers/class-validator';
223
+ import { Length, Min, IsEmail } from 'class-validator';
224
+
225
+ class User {
226
+ @Length(2, 30)
227
+ username: string;
228
+
229
+ @IsEmail()
230
+ email: string;
231
+ }
232
+
233
+ const resolver = classValidatorResolver(User);
234
+
235
+ const App = () => {
236
+ const {
237
+ register,
238
+ handleSubmit,
239
+ formState: { errors },
240
+ } = useForm<User>({ resolver });
241
+
242
+ return (
243
+ <form onSubmit={handleSubmit((data) => console.log(data))}>
244
+ <input type="text" {...register('username')} />
245
+ {errors.username && <span>{errors.username.message}</span>}
246
+ <input type="text" {...register('email')} />
247
+ {errors.email && <span>{errors.email.message}</span>}
248
+ <input type="submit" value="Submit" />
249
+ </form>
250
+ );
251
+ };
252
+ ```
253
+
254
+ ### [io-ts](https://github.com/gcanti/io-ts)
255
+
256
+ Validate your data with powerful decoders.
257
+
258
+ [![npm](https://img.shields.io/bundlephobia/minzip/io-ts?style=for-the-badge)](https://bundlephobia.com/result?p=io-ts)
259
+
260
+ ```typescript jsx
261
+ import React from 'react';
262
+ import { useForm } from 'react-hook-form';
263
+ import { ioTsResolver } from '@hookform/resolvers/io-ts';
264
+ import t from 'io-ts';
265
+ // you don't have to use io-ts-types but it's very useful
266
+ import tt from 'io-ts-types';
267
+
268
+ const schema = t.type({
269
+ username: t.string,
270
+ age: tt.NumberFromString,
271
+ });
272
+
273
+ const App = () => {
274
+ const { register, handleSubmit } = useForm({
275
+ resolver: ioTsResolver(schema),
276
+ });
277
+
278
+ return (
279
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
280
+ <input {...register('username')} />
281
+ <input type="number" {...register('age')} />
282
+ <input type="submit" />
283
+ </form>
284
+ );
285
+ };
286
+
287
+ export default App;
288
+ ```
289
+
290
+ ### [Nope](https://github.com/bvego/nope-validator)
291
+
292
+ A small, simple, and fast JS validator
293
+
294
+ [![npm](https://img.shields.io/bundlephobia/minzip/nope-validator?style=for-the-badge)](https://bundlephobia.com/result?p=nope-validator)
295
+
296
+ ```typescript jsx
297
+ import { useForm } from 'react-hook-form';
298
+ import { nopeResolver } from '@hookform/resolvers/nope';
299
+ import Nope from 'nope-validator';
300
+
301
+ const schema = Nope.object().shape({
302
+ name: Nope.string().required(),
303
+ age: Nope.number().required(),
304
+ });
305
+
306
+ const App = () => {
307
+ const { register, handleSubmit } = useForm({
308
+ resolver: nopeResolver(schema),
309
+ });
310
+
311
+ return (
312
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
313
+ <input {...register('name')} />
314
+ <input type="number" {...register('age')} />
315
+ <input type="submit" />
316
+ </form>
317
+ );
318
+ };
319
+ ```
320
+
321
+ ### [computed-types](https://github.com/neuledge/computed-types)
322
+
323
+ TypeScript-first schema validation with static type inference
324
+
325
+ [![npm](https://img.shields.io/bundlephobia/minzip/computed-types?style=for-the-badge)](https://bundlephobia.com/result?p=computed-types)
326
+
327
+ ```tsx
328
+ import { useForm } from 'react-hook-form';
329
+ import { computedTypesResolver } from '@hookform/resolvers/computed-types';
330
+ import Schema, { number, string } from 'computed-types';
331
+
332
+ const schema = Schema({
333
+ username: string.min(1).error('username field is required'),
334
+ age: number,
335
+ });
336
+
337
+ const App = () => {
338
+ const {
339
+ register,
340
+ handleSubmit,
341
+ formState: { errors },
342
+ } = useForm({
343
+ resolver: computedTypesResolver(schema),
344
+ });
345
+
346
+ return (
347
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
348
+ <input {...register('name')} />
349
+ {errors.name?.message && <p>{errors.name?.message}</p>}
350
+ <input type="number" {...register('age', { valueAsNumber: true })} />
351
+ {errors.age?.message && <p>{errors.age?.message}</p>}
352
+ <input type="submit" />
353
+ </form>
354
+ );
355
+ };
356
+ ```
357
+
358
+ ### [typanion](https://github.com/arcanis/typanion)
359
+
360
+ Static and runtime type assertion library with no dependencies
361
+
362
+ [![npm](https://img.shields.io/bundlephobia/minzip/typanion?style=for-the-badge)](https://bundlephobia.com/result?p=typanion)
363
+
364
+ ```tsx
365
+ import { useForm } from 'react-hook-form';
366
+ import { typanionResolver } from '@hookform/resolvers/typanion';
367
+ import * as t from 'typanion';
368
+
369
+ const isUser = t.isObject({
370
+ username: t.applyCascade(t.isString(), [t.hasMinLength(1)]),
371
+ age: t.applyCascade(t.isNumber(), [
372
+ t.isInteger(),
373
+ t.isInInclusiveRange(1, 100),
374
+ ]),
375
+ });
376
+
377
+ const App = () => {
378
+ const {
379
+ register,
380
+ handleSubmit,
381
+ formState: { errors },
382
+ } = useForm({
383
+ resolver: typanionResolver(isUser),
384
+ });
385
+
386
+ return (
387
+ <form onSubmit={handleSubmit((d) => console.log(d))}>
388
+ <input {...register('name')} />
389
+ {errors.name?.message && <p>{errors.name?.message}</p>}
390
+ <input type="number" {...register('age')} />
391
+ {errors.age?.message && <p>{errors.age?.message}</p>}
392
+ <input type="submit" />
393
+ </form>
394
+ );
395
+ };
396
+ ```
397
+
398
+ ## Backers
399
+
400
+ Thanks goes to all our backers! [[Become a backer](https://opencollective.com/react-hook-form#backer)].
401
+
402
+ <a href="https://opencollective.com/react-hook-form#backers">
403
+ <img src="https://opencollective.com/react-hook-form/backers.svg?width=950" />
404
+ </a>
405
+
406
+ ## Organizations
407
+
408
+ Thanks goes to these wonderful organizations! [[Contribute](https://opencollective.com/react-hook-form/contribute)].
409
+
410
+ <a href="https://github.com/react-hook-form/react-hook-form/graphs/contributors">
411
+ <img src="https://opencollective.com/react-hook-form/organizations.svg?width=950" />
412
+ </a>
413
+
414
+ ## Contributors
415
+
416
+ Thanks goes to these wonderful people! [[Become a contributor](CONTRIBUTING.md)].
417
+
418
+ <a href="https://github.com/react-hook-form/react-hook-form/graphs/contributors">
419
+ <img src="https://opencollective.com/react-hook-form/contributors.svg?width=950" />
420
+ </a>
@@ -0,0 +1,2 @@
1
+ import type { Resolver } from './types';
2
+ export declare const classValidatorResolver: Resolver;
@@ -0,0 +1,2 @@
1
+ var r=require("@hookform/resolvers"),e=require("class-transformer"),t=require("class-validator"),s=function r(e,t,s,i){return void 0===s&&(s={}),void 0===i&&(i=""),e.reduce(function(e,s){var a=i?i+"."+s.property:s.property;if(s.constraints){var o=Object.keys(s.constraints)[0];e[a]={type:o,message:s.constraints[o]},t&&e[a]&&Object.assign(e[a],{types:s.constraints})}return s.children&&s.children.length&&r(s.children,t,e,a),e},s)};exports.classValidatorResolver=function(i,a,o){return void 0===a&&(a={}),void 0===o&&(o={}),function(n,l,c){try{var d=e.plainToClass(i,n);return Promise.resolve(("sync"===o.mode?t.validateSync:t.validate)(d,a)).then(function(e){return e.length?{values:{},errors:r.toNestError(s(e,!c.shouldUseNativeValidation&&"all"===c.criteriaMode),c)}:(c.shouldUseNativeValidation&&r.validateFieldsNatively({},c),{values:n,errors:{}})})}catch(r){return Promise.reject(r)}}};
2
+ //# sourceMappingURL=class-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-validator.js","sources":["../src/class-validator.ts"],"sourcesContent":["import { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport { plainToClass } from 'class-transformer';\nimport { validate, validateSync, ValidationError } from 'class-validator';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ValidationError[],\n validateAllFieldCriteria: boolean,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return errors.reduce((acc, error) => {\n const _path = path ? `${path}.${error.property}` : error.property;\n\n if (error.constraints) {\n const key = Object.keys(error.constraints)[0];\n acc[_path] = {\n type: key,\n message: error.constraints[key],\n };\n\n if (validateAllFieldCriteria && acc[_path]) {\n Object.assign(acc[_path], { types: error.constraints });\n }\n }\n\n if (error.children && error.children.length) {\n parseErrors(error.children, validateAllFieldCriteria, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const classValidatorResolver: Resolver =\n (schema, schemaOptions = {}, resolverOptions = {}) =>\n async (values, _, options) => {\n const user = plainToClass(schema, values);\n\n const rawErrors = await (resolverOptions.mode === 'sync'\n ? validateSync\n : validate)(user, schemaOptions);\n\n if (rawErrors.length) {\n return {\n values: {},\n errors: toNestError(\n parseErrors(\n rawErrors,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","validateAllFieldCriteria","parsedErrors","path","reduce","acc","error","_path","property","constraints","key","Object","keys","type","message","assign","types","children","length","schema","schemaOptions","resolverOptions","values","_","options","user","plainToClass","mode","validateSync","validate","rawErrors","toNestError","shouldUseNativeValidation","criteriaMode","validateFieldsNatively"],"mappings":"iGAMMA,EAAc,SAAdA,EACJC,EACAC,EACAC,EACAC,GAEA,gBAHAD,IAAAA,EAA4B,aAC5BC,IAAAA,EAAO,IAEAH,EAAOI,OAAO,SAACC,EAAKC,GACzB,IAAMC,EAAQJ,EAAUA,MAAQG,EAAME,SAAaF,EAAME,SAEzD,GAAIF,EAAMG,YAAa,CACrB,IAAMC,EAAMC,OAAOC,KAAKN,EAAMG,aAAa,GAC3CJ,EAAIE,GAAS,CACXM,KAAMH,EACNI,QAASR,EAAMG,YAAYC,IAGzBT,GAA4BI,EAAIE,IAClCI,OAAOI,OAAOV,EAAIE,GAAQ,CAAES,MAAOV,EAAMG,cAQ7C,OAJIH,EAAMW,UAAYX,EAAMW,SAASC,QACnCnB,EAAYO,EAAMW,SAAUhB,EAA0BI,EAAKE,GAGtDF,GACNH,mCAIH,SAACiB,EAAQC,EAAoBC,mBAApBD,IAAAA,EAAgB,aAAIC,IAAAA,EAAkB,aACxCC,EAAQC,EAAGC,OAChB,IAAMC,EAAOC,eAAaP,EAAQG,2BAEgB,SAAzBD,EAAgBM,KACrCC,eACAC,YAAUJ,EAAML,kBAFdU,GAIN,OAAIA,EAAUZ,OACL,CACLI,OAAQ,GACRtB,OAAQ+B,cACNhC,EACE+B,GACCN,EAAQQ,2BACkB,QAAzBR,EAAQS,cAEZT,KAKNA,EAAQQ,2BAA6BE,yBAAuB,GAAIV,GAEzD,CAAEF,OAAAA,EAAQtB,OAAQ,OAxB3B"}
@@ -0,0 +1,2 @@
1
+ import{toNestError as r,validateFieldsNatively as e}from"@hookform/resolvers";import{plainToClass as t}from"class-transformer";import{validateSync as o,validate as n}from"class-validator";var s=function r(e,t,o,n){return void 0===o&&(o={}),void 0===n&&(n=""),e.reduce(function(e,o){var s=n?n+"."+o.property:o.property;if(o.constraints){var i=Object.keys(o.constraints)[0];e[s]={type:i,message:o.constraints[i]},t&&e[s]&&Object.assign(e[s],{types:o.constraints})}return o.children&&o.children.length&&r(o.children,t,e,s),e},o)},i=function(i,a,c){return void 0===a&&(a={}),void 0===c&&(c={}),function(l,u,d){try{var v=t(i,l);return Promise.resolve(("sync"===c.mode?o:n)(v,a)).then(function(t){return t.length?{values:{},errors:r(s(t,!d.shouldUseNativeValidation&&"all"===d.criteriaMode),d)}:(d.shouldUseNativeValidation&&e({},d),{values:l,errors:{}})})}catch(r){return Promise.reject(r)}}};export{i as classValidatorResolver};
2
+ //# sourceMappingURL=class-validator.module.js.map
@@ -0,0 +1,2 @@
1
+ import{toNestError as r,validateFieldsNatively as s}from"@hookform/resolvers";import{plainToClass as t}from"class-transformer";import{validateSync as e,validate as o}from"class-validator";const n=(r,s,t={},e="")=>r.reduce((r,t)=>{const o=e?`${e}.${t.property}`:t.property;if(t.constraints){const e=Object.keys(t.constraints)[0];r[o]={type:e,message:t.constraints[e]},s&&r[o]&&Object.assign(r[o],{types:t.constraints})}return t.children&&t.children.length&&n(t.children,s,r,o),r},t),a=(a,i={},c={})=>async(l,d,m)=>{const p=t(a,l),h=await("sync"===c.mode?e:o)(p,i);return h.length?{values:{},errors:r(n(h,!m.shouldUseNativeValidation&&"all"===m.criteriaMode),m)}:(m.shouldUseNativeValidation&&s({},m),{values:l,errors:{}})};export{a as classValidatorResolver};
2
+ //# sourceMappingURL=class-validator.modern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-validator.modern.js","sources":["../src/class-validator.ts"],"sourcesContent":["import { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport { plainToClass } from 'class-transformer';\nimport { validate, validateSync, ValidationError } from 'class-validator';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ValidationError[],\n validateAllFieldCriteria: boolean,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return errors.reduce((acc, error) => {\n const _path = path ? `${path}.${error.property}` : error.property;\n\n if (error.constraints) {\n const key = Object.keys(error.constraints)[0];\n acc[_path] = {\n type: key,\n message: error.constraints[key],\n };\n\n if (validateAllFieldCriteria && acc[_path]) {\n Object.assign(acc[_path], { types: error.constraints });\n }\n }\n\n if (error.children && error.children.length) {\n parseErrors(error.children, validateAllFieldCriteria, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const classValidatorResolver: Resolver =\n (schema, schemaOptions = {}, resolverOptions = {}) =>\n async (values, _, options) => {\n const user = plainToClass(schema, values);\n\n const rawErrors = await (resolverOptions.mode === 'sync'\n ? validateSync\n : validate)(user, schemaOptions);\n\n if (rawErrors.length) {\n return {\n values: {},\n errors: toNestError(\n parseErrors(\n rawErrors,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","validateAllFieldCriteria","parsedErrors","path","reduce","acc","error","_path","property","constraints","key","Object","keys","type","message","assign","types","children","length","classValidatorResolver","schema","schemaOptions","resolverOptions","async","values","_","options","user","plainToClass","rawErrors","mode","validateSync","validate","toNestError","shouldUseNativeValidation","criteriaMode","validateFieldsNatively"],"mappings":"4LAMA,MAAMA,EAAc,CAClBC,EACAC,EACAC,EAA4B,GAC5BC,EAAO,KAEAH,EAAOI,OAAO,CAACC,EAAKC,KACzB,MAAMC,EAAQJ,KAAUA,KAAQG,EAAME,WAAaF,EAAME,SAEzD,GAAIF,EAAMG,YAAa,CACrB,MAAMC,EAAMC,OAAOC,KAAKN,EAAMG,aAAa,GAC3CJ,EAAIE,GAAS,CACXM,KAAMH,EACNI,QAASR,EAAMG,YAAYC,IAGzBT,GAA4BI,EAAIE,IAClCI,OAAOI,OAAOV,EAAIE,GAAQ,CAAES,MAAOV,EAAMG,cAQ7C,OAJIH,EAAMW,UAAYX,EAAMW,SAASC,QACnCnB,EAAYO,EAAMW,SAAUhB,EAA0BI,EAAKE,GAGtDF,GACNH,GAGQiB,EACX,CAACC,EAAQC,EAAgB,GAAIC,EAAkB,KAC/CC,MAAOC,EAAQC,EAAGC,KAChB,MAAMC,EAAOC,EAAaR,EAAQI,GAE5BK,QAA4C,SAAzBP,EAAgBQ,KACrCC,EACAC,GAAUL,EAAMN,GAEpB,OAAIQ,EAAUX,OACL,CACLM,OAAQ,GACRxB,OAAQiC,EACNlC,EACE8B,GACCH,EAAQQ,2BACkB,QAAzBR,EAAQS,cAEZT,KAKNA,EAAQQ,2BAA6BE,EAAuB,GAAIV,GAEzD,CAAEF,OAAAA,EAAQxB,OAAQ"}
@@ -0,0 +1,2 @@
1
+ import{toNestError as r,validateFieldsNatively as e}from"@hookform/resolvers";import{plainToClass as t}from"class-transformer";import{validateSync as o,validate as n}from"class-validator";var s=function r(e,t,o,n){return void 0===o&&(o={}),void 0===n&&(n=""),e.reduce(function(e,o){var s=n?n+"."+o.property:o.property;if(o.constraints){var i=Object.keys(o.constraints)[0];e[s]={type:i,message:o.constraints[i]},t&&e[s]&&Object.assign(e[s],{types:o.constraints})}return o.children&&o.children.length&&r(o.children,t,e,s),e},o)},i=function(i,a,c){return void 0===a&&(a={}),void 0===c&&(c={}),function(l,u,d){try{var v=t(i,l);return Promise.resolve(("sync"===c.mode?o:n)(v,a)).then(function(t){return t.length?{values:{},errors:r(s(t,!d.shouldUseNativeValidation&&"all"===d.criteriaMode),d)}:(d.shouldUseNativeValidation&&e({},d),{values:l,errors:{}})})}catch(r){return Promise.reject(r)}}};export{i as classValidatorResolver};
2
+ //# sourceMappingURL=class-validator.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-validator.module.js","sources":["../src/class-validator.ts"],"sourcesContent":["import { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport { plainToClass } from 'class-transformer';\nimport { validate, validateSync, ValidationError } from 'class-validator';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ValidationError[],\n validateAllFieldCriteria: boolean,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return errors.reduce((acc, error) => {\n const _path = path ? `${path}.${error.property}` : error.property;\n\n if (error.constraints) {\n const key = Object.keys(error.constraints)[0];\n acc[_path] = {\n type: key,\n message: error.constraints[key],\n };\n\n if (validateAllFieldCriteria && acc[_path]) {\n Object.assign(acc[_path], { types: error.constraints });\n }\n }\n\n if (error.children && error.children.length) {\n parseErrors(error.children, validateAllFieldCriteria, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const classValidatorResolver: Resolver =\n (schema, schemaOptions = {}, resolverOptions = {}) =>\n async (values, _, options) => {\n const user = plainToClass(schema, values);\n\n const rawErrors = await (resolverOptions.mode === 'sync'\n ? validateSync\n : validate)(user, schemaOptions);\n\n if (rawErrors.length) {\n return {\n values: {},\n errors: toNestError(\n parseErrors(\n rawErrors,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","validateAllFieldCriteria","parsedErrors","path","reduce","acc","error","_path","property","constraints","key","Object","keys","type","message","assign","types","children","length","classValidatorResolver","schema","schemaOptions","resolverOptions","values","_","options","user","plainToClass","mode","validateSync","validate","rawErrors","toNestError","shouldUseNativeValidation","criteriaMode","validateFieldsNatively"],"mappings":"4LAMA,IAAMA,EAAc,SAAdA,EACJC,EACAC,EACAC,EACAC,GAEA,gBAHAD,IAAAA,EAA4B,aAC5BC,IAAAA,EAAO,IAEAH,EAAOI,OAAO,SAACC,EAAKC,GACzB,IAAMC,EAAQJ,EAAUA,MAAQG,EAAME,SAAaF,EAAME,SAEzD,GAAIF,EAAMG,YAAa,CACrB,IAAMC,EAAMC,OAAOC,KAAKN,EAAMG,aAAa,GAC3CJ,EAAIE,GAAS,CACXM,KAAMH,EACNI,QAASR,EAAMG,YAAYC,IAGzBT,GAA4BI,EAAIE,IAClCI,OAAOI,OAAOV,EAAIE,GAAQ,CAAES,MAAOV,EAAMG,cAQ7C,OAJIH,EAAMW,UAAYX,EAAMW,SAASC,QACnCnB,EAAYO,EAAMW,SAAUhB,EAA0BI,EAAKE,GAGtDF,GACNH,IAGQiB,EACX,SAACC,EAAQC,EAAoBC,mBAApBD,IAAAA,EAAgB,aAAIC,IAAAA,EAAkB,aACxCC,EAAQC,EAAGC,OAChB,IAAMC,EAAOC,EAAaP,EAAQG,2BAEgB,SAAzBD,EAAgBM,KACrCC,EACAC,GAAUJ,EAAML,kBAFdU,GAIN,OAAIA,EAAUb,OACL,CACLK,OAAQ,GACRvB,OAAQgC,EACNjC,EACEgC,GACCN,EAAQQ,2BACkB,QAAzBR,EAAQS,cAEZT,KAKNA,EAAQQ,2BAA6BE,EAAuB,GAAIV,GAEzD,CAAEF,OAAAA,EAAQvB,OAAQ,OAxB3B"}
@@ -0,0 +1,2 @@
1
+ !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@hookform/resolvers"),require("class-transformer"),require("class-validator")):"function"==typeof define&&define.amd?define(["exports","@hookform/resolvers","class-transformer","class-validator"],r):r((e||self).hookformResolversClassValidator={},e.hookformResolvers,e.classTransformer,e.classValidator)}(this,function(e,r,o,s){var t=function e(r,o,s,t){return void 0===s&&(s={}),void 0===t&&(t=""),r.reduce(function(r,s){var a=t?t+"."+s.property:s.property;if(s.constraints){var i=Object.keys(s.constraints)[0];r[a]={type:i,message:s.constraints[i]},o&&r[a]&&Object.assign(r[a],{types:s.constraints})}return s.children&&s.children.length&&e(s.children,o,r,a),r},s)};e.classValidatorResolver=function(e,a,i){return void 0===a&&(a={}),void 0===i&&(i={}),function(n,l,c){try{var d=o.plainToClass(e,n);return Promise.resolve(("sync"===i.mode?s.validateSync:s.validate)(d,a)).then(function(e){return e.length?{values:{},errors:r.toNestError(t(e,!c.shouldUseNativeValidation&&"all"===c.criteriaMode),c)}:(c.shouldUseNativeValidation&&r.validateFieldsNatively({},c),{values:n,errors:{}})})}catch(e){return Promise.reject(e)}}}});
2
+ //# sourceMappingURL=class-validator.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-validator.umd.js","sources":["../src/class-validator.ts"],"sourcesContent":["import { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport { plainToClass } from 'class-transformer';\nimport { validate, validateSync, ValidationError } from 'class-validator';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ValidationError[],\n validateAllFieldCriteria: boolean,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return errors.reduce((acc, error) => {\n const _path = path ? `${path}.${error.property}` : error.property;\n\n if (error.constraints) {\n const key = Object.keys(error.constraints)[0];\n acc[_path] = {\n type: key,\n message: error.constraints[key],\n };\n\n if (validateAllFieldCriteria && acc[_path]) {\n Object.assign(acc[_path], { types: error.constraints });\n }\n }\n\n if (error.children && error.children.length) {\n parseErrors(error.children, validateAllFieldCriteria, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const classValidatorResolver: Resolver =\n (schema, schemaOptions = {}, resolverOptions = {}) =>\n async (values, _, options) => {\n const user = plainToClass(schema, values);\n\n const rawErrors = await (resolverOptions.mode === 'sync'\n ? validateSync\n : validate)(user, schemaOptions);\n\n if (rawErrors.length) {\n return {\n values: {},\n errors: toNestError(\n parseErrors(\n rawErrors,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","validateAllFieldCriteria","parsedErrors","path","reduce","acc","error","_path","property","constraints","key","Object","keys","type","message","assign","types","children","length","schema","schemaOptions","resolverOptions","values","_","options","user","plainToClass","mode","validateSync","validate","rawErrors","toNestError","shouldUseNativeValidation","criteriaMode","validateFieldsNatively"],"mappings":"0cAMA,IAAMA,EAAc,SAAdA,EACJC,EACAC,EACAC,EACAC,GAEA,gBAHAD,IAAAA,EAA4B,aAC5BC,IAAAA,EAAO,IAEAH,EAAOI,OAAO,SAACC,EAAKC,GACzB,IAAMC,EAAQJ,EAAUA,MAAQG,EAAME,SAAaF,EAAME,SAEzD,GAAIF,EAAMG,YAAa,CACrB,IAAMC,EAAMC,OAAOC,KAAKN,EAAMG,aAAa,GAC3CJ,EAAIE,GAAS,CACXM,KAAMH,EACNI,QAASR,EAAMG,YAAYC,IAGzBT,GAA4BI,EAAIE,IAClCI,OAAOI,OAAOV,EAAIE,GAAQ,CAAES,MAAOV,EAAMG,cAQ7C,OAJIH,EAAMW,UAAYX,EAAMW,SAASC,QACnCnB,EAAYO,EAAMW,SAAUhB,EAA0BI,EAAKE,GAGtDF,GACNH,6BAIH,SAACiB,EAAQC,EAAoBC,mBAApBD,IAAAA,EAAgB,aAAIC,IAAAA,EAAkB,aACxCC,EAAQC,EAAGC,OAChB,IAAMC,EAAOC,eAAaP,EAAQG,2BAEgB,SAAzBD,EAAgBM,KACrCC,eACAC,YAAUJ,EAAML,kBAFdU,GAIN,OAAIA,EAAUZ,OACL,CACLI,OAAQ,GACRtB,OAAQ+B,cACNhC,EACE+B,GACCN,EAAQQ,2BACkB,QAAzBR,EAAQS,cAEZT,KAKNA,EAAQQ,2BAA6BE,yBAAuB,GAAIV,GAEzD,CAAEF,OAAAA,EAAQtB,OAAQ,OAxB3B"}
@@ -0,0 +1,2 @@
1
+ export * from './class-validator';
2
+ export * from './types';
@@ -0,0 +1,8 @@
1
+ import { FieldValues, ResolverOptions, ResolverResult, UnpackNestedValue } from 'react-hook-form';
2
+ import { ValidatorOptions } from 'class-validator';
3
+ import { ClassConstructor } from 'class-transformer';
4
+ export declare type Resolver = <T extends {
5
+ [_: string]: any;
6
+ }, TFieldValues extends FieldValues, TContext>(schema: ClassConstructor<T>, schemaOptions?: ValidatorOptions, resolverOptions?: {
7
+ mode?: 'async' | 'sync';
8
+ }) => (values: UnpackNestedValue<TFieldValues>, context: TContext | undefined, options: ResolverOptions<TFieldValues>) => Promise<ResolverResult<TFieldValues>>;
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "class-validator",
3
+ "amdName": "hookformResolversClassValidator",
4
+ "version": "1.0.0",
5
+ "private": true,
6
+ "description": "React Hook Form validation resolver: class-validator",
7
+ "main": "dist/class-validator.js",
8
+ "module": "dist/class-validator.module.js",
9
+ "umd:main": "dist/class-validator.umd.js",
10
+ "source": "src/index.ts",
11
+ "types": "dist/index.d.ts",
12
+ "license": "MIT",
13
+ "peerDependencies": {
14
+ "react-hook-form": ">=6.6.0",
15
+ "@hookform/resolvers": ">=2.0.0",
16
+ "class-transformer": "^0.4.0",
17
+ "class-validator": "^0.12.0"
18
+ }
19
+ }
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import { render, screen, act } from '@testing-library/react';
3
+ import user from '@testing-library/user-event';
4
+ import { useForm } from 'react-hook-form';
5
+ import { classValidatorResolver } from '..';
6
+ import { IsNotEmpty } from 'class-validator';
7
+
8
+ class Schema {
9
+ @IsNotEmpty()
10
+ username: string;
11
+
12
+ @IsNotEmpty()
13
+ password: string;
14
+ }
15
+
16
+ interface Props {
17
+ onSubmit: (data: Schema) => void;
18
+ }
19
+
20
+ function TestComponent({ onSubmit }: Props) {
21
+ const { register, handleSubmit } = useForm<Schema>({
22
+ resolver: classValidatorResolver(Schema),
23
+ shouldUseNativeValidation: true,
24
+ });
25
+
26
+ return (
27
+ <form onSubmit={handleSubmit(onSubmit)}>
28
+ <input {...register('username')} placeholder="username" />
29
+
30
+ <input {...register('password')} placeholder="password" />
31
+
32
+ <button type="submit">submit</button>
33
+ </form>
34
+ );
35
+ }
36
+
37
+ test("form's native validation with Class Validator", async () => {
38
+ const handleSubmit = jest.fn();
39
+ render(<TestComponent onSubmit={handleSubmit} />);
40
+
41
+ // username
42
+ let usernameField = screen.getByPlaceholderText(
43
+ /username/i,
44
+ ) as HTMLInputElement;
45
+ expect(usernameField.validity.valid).toBe(true);
46
+ expect(usernameField.validationMessage).toBe('');
47
+
48
+ // password
49
+ let passwordField = screen.getByPlaceholderText(
50
+ /password/i,
51
+ ) as HTMLInputElement;
52
+ expect(passwordField.validity.valid).toBe(true);
53
+ expect(passwordField.validationMessage).toBe('');
54
+
55
+ await act(async () => {
56
+ user.click(screen.getByText(/submit/i));
57
+ });
58
+
59
+ // username
60
+ usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
61
+ expect(usernameField.validity.valid).toBe(false);
62
+ expect(usernameField.validationMessage).toBe('username should not be empty');
63
+
64
+ // password
65
+ passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement;
66
+ expect(passwordField.validity.valid).toBe(false);
67
+ expect(passwordField.validationMessage).toBe('password should not be empty');
68
+
69
+ await act(async () => {
70
+ user.type(screen.getByPlaceholderText(/username/i), 'joe');
71
+ user.type(screen.getByPlaceholderText(/password/i), 'password');
72
+ });
73
+
74
+ // username
75
+ usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
76
+ expect(usernameField.validity.valid).toBe(true);
77
+ expect(usernameField.validationMessage).toBe('');
78
+
79
+ // password
80
+ passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement;
81
+ expect(passwordField.validity.valid).toBe(true);
82
+ expect(passwordField.validationMessage).toBe('');
83
+ });