@hookform/resolvers 2.9.11 → 3.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.
Files changed (226) hide show
  1. package/README.md +51 -5
  2. package/ajv/dist/ajv.d.ts +2 -2
  3. package/ajv/dist/ajv.js +1 -7
  4. package/ajv/dist/ajv.js.map +1 -1
  5. package/ajv/dist/ajv.mjs +1 -7
  6. package/ajv/dist/ajv.modern.mjs +2 -0
  7. package/ajv/dist/ajv.modern.mjs.map +1 -0
  8. package/ajv/dist/ajv.module.js +1 -7
  9. package/ajv/dist/ajv.module.js.map +1 -1
  10. package/ajv/dist/ajv.umd.js +1 -7
  11. package/ajv/dist/ajv.umd.js.map +1 -1
  12. package/ajv/dist/index.d.ts +2 -2
  13. package/ajv/dist/types.d.ts +5 -5
  14. package/ajv/package.json +3 -1
  15. package/ajv/src/__tests__/Form-native-validation.tsx +5 -9
  16. package/ajv/src/__tests__/Form.tsx +4 -6
  17. package/ajv/src/__tests__/__fixtures__/data.ts +3 -4
  18. package/ajv/src/__tests__/__snapshots__/ajv.ts.snap +83 -83
  19. package/ajv/src/ajv.ts +28 -24
  20. package/class-validator/dist/class-validator.d.ts +2 -2
  21. package/class-validator/dist/class-validator.js +1 -1
  22. package/class-validator/dist/class-validator.js.map +1 -1
  23. package/class-validator/dist/class-validator.mjs +1 -1
  24. package/class-validator/dist/class-validator.modern.mjs +2 -0
  25. package/class-validator/dist/class-validator.modern.mjs.map +1 -0
  26. package/class-validator/dist/class-validator.module.js +1 -1
  27. package/class-validator/dist/class-validator.module.js.map +1 -1
  28. package/class-validator/dist/class-validator.umd.js +1 -1
  29. package/class-validator/dist/class-validator.umd.js.map +1 -1
  30. package/class-validator/dist/index.d.ts +2 -2
  31. package/class-validator/dist/types.d.ts +12 -9
  32. package/class-validator/src/__tests__/Form-native-validation.tsx +5 -9
  33. package/class-validator/src/__tests__/Form.tsx +4 -6
  34. package/class-validator/src/__tests__/__snapshots__/class-validator.ts.snap +102 -67
  35. package/class-validator/src/__tests__/class-validator.ts +66 -6
  36. package/class-validator/src/class-validator.ts +6 -4
  37. package/class-validator/src/types.ts +7 -8
  38. package/computed-types/dist/computed-types.d.ts +2 -2
  39. package/computed-types/dist/computed-types.js +1 -1
  40. package/computed-types/dist/computed-types.js.map +1 -1
  41. package/computed-types/dist/computed-types.mjs +1 -1
  42. package/computed-types/dist/computed-types.modern.mjs +2 -0
  43. package/computed-types/dist/computed-types.modern.mjs.map +1 -0
  44. package/computed-types/dist/computed-types.module.js +1 -1
  45. package/computed-types/dist/computed-types.module.js.map +1 -1
  46. package/computed-types/dist/computed-types.umd.js +1 -1
  47. package/computed-types/dist/computed-types.umd.js.map +1 -1
  48. package/computed-types/dist/index.d.ts +2 -2
  49. package/computed-types/dist/types.d.ts +2 -2
  50. package/computed-types/src/__tests__/Form-native-validation.tsx +5 -9
  51. package/computed-types/src/__tests__/Form.tsx +4 -6
  52. package/computed-types/src/__tests__/__snapshots__/computed-types.ts.snap +21 -21
  53. package/computed-types/src/__tests__/computed-types.ts +16 -0
  54. package/computed-types/src/computed-types.ts +12 -5
  55. package/dist/index.d.ts +2 -2
  56. package/dist/resolvers.js +1 -1
  57. package/dist/resolvers.js.map +1 -1
  58. package/dist/resolvers.mjs +1 -1
  59. package/dist/resolvers.mjs.map +1 -1
  60. package/dist/resolvers.module.js +1 -1
  61. package/dist/resolvers.module.js.map +1 -1
  62. package/dist/resolvers.umd.js +1 -1
  63. package/dist/resolvers.umd.js.map +1 -1
  64. package/dist/toNestError.d.ts +2 -2
  65. package/dist/validateFieldsNatively.d.ts +2 -2
  66. package/io-ts/dist/arrayToPath.d.ts +3 -3
  67. package/io-ts/dist/errorsToRecord.d.ts +5 -5
  68. package/io-ts/dist/index.d.ts +2 -2
  69. package/io-ts/dist/io-ts.d.ts +2 -2
  70. package/io-ts/dist/io-ts.js +1 -1
  71. package/io-ts/dist/io-ts.js.map +1 -1
  72. package/io-ts/dist/io-ts.mjs +1 -1
  73. package/io-ts/dist/io-ts.modern.mjs +2 -0
  74. package/io-ts/dist/io-ts.modern.mjs.map +1 -0
  75. package/io-ts/dist/io-ts.module.js +1 -1
  76. package/io-ts/dist/io-ts.module.js.map +1 -1
  77. package/io-ts/dist/io-ts.umd.js +1 -1
  78. package/io-ts/dist/io-ts.umd.js.map +1 -1
  79. package/io-ts/dist/types.d.ts +7 -7
  80. package/io-ts/src/__tests__/Form-native-validation.tsx +5 -9
  81. package/io-ts/src/__tests__/Form.tsx +4 -6
  82. package/io-ts/src/__tests__/__snapshots__/io-ts.ts.snap +28 -28
  83. package/io-ts/src/__tests__/io-ts.ts +1 -1
  84. package/joi/dist/index.d.ts +2 -2
  85. package/joi/dist/joi.d.ts +2 -2
  86. package/joi/dist/joi.js.map +1 -1
  87. package/joi/dist/{joi.modern.js → joi.modern.mjs} +1 -1
  88. package/joi/dist/joi.modern.mjs.map +1 -0
  89. package/joi/dist/joi.module.js.map +1 -1
  90. package/joi/dist/joi.umd.js.map +1 -1
  91. package/joi/dist/types.d.ts +5 -5
  92. package/joi/src/__tests__/Form-native-validation.tsx +5 -9
  93. package/joi/src/__tests__/Form.tsx +4 -6
  94. package/joi/src/__tests__/__snapshots__/joi.ts.snap +87 -87
  95. package/joi/src/__tests__/joi.ts +8 -8
  96. package/nope/dist/index.d.ts +2 -2
  97. package/nope/dist/nope.d.ts +2 -2
  98. package/nope/dist/nope.js.map +1 -1
  99. package/nope/dist/{nope.modern.js → nope.modern.mjs} +1 -1
  100. package/nope/dist/nope.modern.mjs.map +1 -0
  101. package/nope/dist/nope.module.js.map +1 -1
  102. package/nope/dist/nope.umd.js.map +1 -1
  103. package/nope/dist/types.d.ts +9 -9
  104. package/nope/src/__tests__/Form-native-validation.tsx +5 -9
  105. package/nope/src/__tests__/Form.tsx +4 -6
  106. package/nope/src/__tests__/__snapshots__/nope.ts.snap +15 -15
  107. package/nope/src/__tests__/nope.ts +1 -1
  108. package/package.json +74 -44
  109. package/superstruct/dist/index.d.ts +2 -2
  110. package/superstruct/dist/superstruct.d.ts +2 -2
  111. package/superstruct/dist/superstruct.js +1 -1
  112. package/superstruct/dist/superstruct.js.map +1 -1
  113. package/superstruct/dist/superstruct.mjs +1 -1
  114. package/superstruct/dist/superstruct.modern.mjs +2 -0
  115. package/superstruct/dist/superstruct.modern.mjs.map +1 -0
  116. package/superstruct/dist/superstruct.module.js +1 -1
  117. package/superstruct/dist/superstruct.module.js.map +1 -1
  118. package/superstruct/dist/superstruct.umd.js +1 -1
  119. package/superstruct/dist/superstruct.umd.js.map +1 -1
  120. package/superstruct/dist/types.d.ts +11 -5
  121. package/superstruct/src/__tests__/Form-native-validation.tsx +5 -9
  122. package/superstruct/src/__tests__/Form.tsx +4 -6
  123. package/superstruct/src/__tests__/__snapshots__/superstruct.ts.snap +19 -19
  124. package/superstruct/src/__tests__/superstruct.ts +13 -0
  125. package/superstruct/src/superstruct.ts +4 -3
  126. package/superstruct/src/types.ts +8 -5
  127. package/typanion/dist/index.d.ts +2 -2
  128. package/typanion/dist/typanion.d.ts +2 -2
  129. package/typanion/dist/typanion.js.map +1 -1
  130. package/typanion/dist/{typanion.modern.js → typanion.modern.mjs} +1 -1
  131. package/typanion/dist/typanion.modern.mjs.map +1 -0
  132. package/typanion/dist/typanion.module.js.map +1 -1
  133. package/typanion/dist/typanion.umd.js.map +1 -1
  134. package/typanion/dist/types.d.ts +9 -9
  135. package/typanion/src/__tests__/Form-native-validation.tsx +7 -10
  136. package/typanion/src/__tests__/Form.tsx +9 -7
  137. package/typanion/src/__tests__/__snapshots__/typanion.ts.snap +22 -22
  138. package/typanion/src/__tests__/typanion.ts +11 -7
  139. package/typanion/src/typanion.ts +1 -1
  140. package/typebox/dist/index.d.ts +2 -0
  141. package/typebox/dist/typebox.d.ts +2 -0
  142. package/typebox/dist/typebox.js +2 -0
  143. package/typebox/dist/typebox.js.map +1 -0
  144. package/typebox/dist/typebox.mjs +2 -0
  145. package/typebox/dist/typebox.modern.mjs +2 -0
  146. package/typebox/dist/typebox.modern.mjs.map +1 -0
  147. package/typebox/dist/typebox.module.js +2 -0
  148. package/typebox/dist/typebox.module.js.map +1 -0
  149. package/typebox/dist/typebox.umd.js +2 -0
  150. package/typebox/dist/typebox.umd.js.map +1 -0
  151. package/typebox/dist/types.d.ts +3 -0
  152. package/typebox/package.json +18 -0
  153. package/typebox/src/__tests__/Form-native-validation.tsx +83 -0
  154. package/typebox/src/__tests__/Form.tsx +54 -0
  155. package/typebox/src/__tests__/__fixtures__/data.ts +84 -0
  156. package/typebox/src/__tests__/__snapshots__/typebox.ts.snap +190 -0
  157. package/typebox/src/__tests__/typebox.ts +34 -0
  158. package/typebox/src/index.ts +2 -0
  159. package/typebox/src/typebox.ts +64 -0
  160. package/typebox/src/types.ts +10 -0
  161. package/vest/dist/index.d.ts +2 -2
  162. package/vest/dist/types.d.ts +8 -8
  163. package/vest/dist/vest.d.ts +2 -2
  164. package/vest/dist/vest.js.map +1 -1
  165. package/vest/dist/{vest.modern.js → vest.modern.mjs} +1 -1
  166. package/vest/dist/vest.modern.mjs.map +1 -0
  167. package/vest/dist/vest.module.js.map +1 -1
  168. package/vest/dist/vest.umd.js.map +1 -1
  169. package/vest/src/__tests__/Form-native-validation.tsx +5 -9
  170. package/vest/src/__tests__/Form.tsx +6 -10
  171. package/vest/src/__tests__/__snapshots__/vest.ts.snap +47 -47
  172. package/yup/dist/index.d.ts +2 -2
  173. package/yup/dist/types.d.ts +15 -9
  174. package/yup/dist/yup.d.ts +2 -2
  175. package/yup/dist/yup.js +1 -1
  176. package/yup/dist/yup.js.map +1 -1
  177. package/yup/dist/yup.mjs +1 -1
  178. package/yup/dist/yup.modern.mjs +2 -0
  179. package/yup/dist/yup.modern.mjs.map +1 -0
  180. package/yup/dist/yup.module.js +1 -1
  181. package/yup/dist/yup.module.js.map +1 -1
  182. package/yup/dist/yup.umd.js +1 -1
  183. package/yup/dist/yup.umd.js.map +1 -1
  184. package/yup/src/__tests__/Form-native-validation.tsx +5 -9
  185. package/yup/src/__tests__/Form.tsx +4 -6
  186. package/yup/src/__tests__/__fixtures__/data.ts +2 -3
  187. package/yup/src/__tests__/__snapshots__/yup.ts.snap +100 -87
  188. package/yup/src/__tests__/yup.ts +49 -18
  189. package/yup/src/types.ts +14 -11
  190. package/yup/src/yup.ts +1 -1
  191. package/zod/dist/index.d.ts +2 -2
  192. package/zod/dist/types.d.ts +13 -13
  193. package/zod/dist/zod.d.ts +2 -2
  194. package/zod/dist/zod.js +1 -1
  195. package/zod/dist/zod.js.map +1 -1
  196. package/zod/dist/zod.mjs +1 -1
  197. package/zod/dist/zod.modern.mjs +2 -0
  198. package/zod/dist/zod.modern.mjs.map +1 -0
  199. package/zod/dist/zod.module.js +1 -1
  200. package/zod/dist/zod.module.js.map +1 -1
  201. package/zod/dist/zod.umd.js +1 -1
  202. package/zod/dist/zod.umd.js.map +1 -1
  203. package/zod/src/__tests__/Form-native-validation.tsx +5 -9
  204. package/zod/src/__tests__/Form.tsx +4 -6
  205. package/zod/src/__tests__/__snapshots__/zod.ts.snap +120 -120
  206. package/zod/src/__tests__/zod.ts +19 -7
  207. package/zod/src/types.ts +2 -6
  208. package/zod/src/zod.ts +27 -27
  209. package/ajv/dist/ajv.modern.js +0 -8
  210. package/ajv/dist/ajv.modern.js.map +0 -1
  211. package/class-validator/dist/class-validator.modern.js +0 -2
  212. package/class-validator/dist/class-validator.modern.js.map +0 -1
  213. package/computed-types/dist/computed-types.modern.js +0 -2
  214. package/computed-types/dist/computed-types.modern.js.map +0 -1
  215. package/io-ts/dist/io-ts.modern.js +0 -2
  216. package/io-ts/dist/io-ts.modern.js.map +0 -1
  217. package/joi/dist/joi.modern.js.map +0 -1
  218. package/nope/dist/nope.modern.js.map +0 -1
  219. package/superstruct/dist/superstruct.modern.js +0 -2
  220. package/superstruct/dist/superstruct.modern.js.map +0 -1
  221. package/typanion/dist/typanion.modern.js.map +0 -1
  222. package/vest/dist/vest.modern.js.map +0 -1
  223. package/yup/dist/yup.modern.js +0 -2
  224. package/yup/dist/yup.modern.js.map +0 -1
  225. package/zod/dist/zod.modern.js +0 -2
  226. package/zod/dist/zod.modern.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"typanion.umd.js","sources":["../src/typanion.ts"],"sourcesContent":["import type {FieldError, FieldErrors} from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { Resolver } from './types';\n\nconst parseErrors = (errors: string[], parsedErrors: FieldErrors = {}) => {\n return errors.reduce((acc, error) => {\n const e = error.split(':');\n\n acc[e[0].slice(1)] = {\n message: e[1].trim(),\n } as FieldError;\n\n return acc;\n }, parsedErrors);\n};\n\nexport const typanionResolver: Resolver =\n (validator, validatorOptions = {}) =>\n (values, _, options) => {\n const rawErrors: string[] = [];\n const isValid = validator(\n values,\n Object.assign(\n {},\n {\n errors: rawErrors,\n },\n validatorOptions,\n ),\n );\n const parsedErrors = parseErrors(rawErrors);\n\n if (isValid) {\n options.shouldUseNativeValidation &&\n validateFieldsNatively(parsedErrors, options);\n\n return { values, errors: {} };\n }\n\n return { values: {}, errors: toNestError(parsedErrors, options) };\n };\n"],"names":["validator","validatorOptions","values","_","options","rawErrors","isValid","Object","assign","errors","parsedErrors","reduce","acc","error","e","split","slice","message","trim","parseErrors","shouldUseNativeValidation","validateFieldsNatively","toNestError"],"mappings":"iVAiBE,SAACA,EAAWC,mBAAAA,IAAAA,EAAmB,aAC9BC,EAAQC,EAAGC,GACV,IAAMC,EAAsB,GACtBC,EAAUN,EACdE,EACAK,OAAOC,OACL,GACA,CACEC,OAAQJ,GAEVJ,IAGES,EA1BU,SAACD,EAAkBC,GACrC,gBADqCA,IAAAA,EAA4B,IAC1DD,EAAOE,OAAO,SAACC,EAAKC,GACzB,IAAMC,EAAID,EAAME,MAAM,KAMtB,OAJAH,EAAIE,EAAE,GAAGE,MAAM,IAAM,CACnBC,QAASH,EAAE,GAAGI,QAGTN,GACNF,GAiBoBS,CAAYd,GAEjC,OAAIC,GACFF,EAAQgB,2BACNC,yBAAuBX,EAAcN,GAEhC,CAAEF,OAAAA,EAAQO,OAAQ,KAGpB,CAAEP,OAAQ,GAAIO,OAAQa,cAAYZ,EAAcN"}
1
+ {"version":3,"file":"typanion.umd.js","sources":["../src/typanion.ts"],"sourcesContent":["import type { FieldError, FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { Resolver } from './types';\n\nconst parseErrors = (errors: string[], parsedErrors: FieldErrors = {}) => {\n return errors.reduce((acc, error) => {\n const e = error.split(':');\n\n acc[e[0].slice(1)] = {\n message: e[1].trim(),\n } as FieldError;\n\n return acc;\n }, parsedErrors);\n};\n\nexport const typanionResolver: Resolver =\n (validator, validatorOptions = {}) =>\n (values, _, options) => {\n const rawErrors: string[] = [];\n const isValid = validator(\n values,\n Object.assign(\n {},\n {\n errors: rawErrors,\n },\n validatorOptions,\n ),\n );\n const parsedErrors = parseErrors(rawErrors);\n\n if (isValid) {\n options.shouldUseNativeValidation &&\n validateFieldsNatively(parsedErrors, options);\n\n return { values, errors: {} };\n }\n\n return { values: {}, errors: toNestError(parsedErrors, options) };\n };\n"],"names":["validator","validatorOptions","values","_","options","rawErrors","isValid","Object","assign","errors","parsedErrors","reduce","acc","error","e","split","slice","message","trim","parseErrors","shouldUseNativeValidation","validateFieldsNatively","toNestError"],"mappings":"iVAiBE,SAACA,EAAWC,GAAqB,gBAArBA,IAAAA,EAAmB,CAAA,YAC9BC,EAAQC,EAAGC,GACV,IAAMC,EAAsB,GACtBC,EAAUN,EACdE,EACAK,OAAOC,OACL,CAAA,EACA,CACEC,OAAQJ,GAEVJ,IAGES,EA1BU,SAACD,EAAkBC,GACrC,YADqCA,IAAAA,IAAAA,EAA4B,CAAE,GAC5DD,EAAOE,OAAO,SAACC,EAAKC,GACzB,IAAMC,EAAID,EAAME,MAAM,KAMtB,OAJAH,EAAIE,EAAE,GAAGE,MAAM,IAAM,CACnBC,QAASH,EAAE,GAAGI,QAGTN,CACT,EAAGF,EACL,CAgByBS,CAAYd,GAEjC,OAAIC,GACFF,EAAQgB,2BACNC,EAAsBA,uBAACX,EAAcN,GAEhC,CAAEF,OAAAA,EAAQO,OAAQ,KAGpB,CAAEP,OAAQ,CAAA,EAAIO,OAAQa,cAAYZ,EAAcN,GACzD,CAAC"}
@@ -1,9 +1,9 @@
1
- import type { FieldValues, ResolverOptions, ResolverResult } from 'react-hook-form';
2
- import { ValidationState, AnyStrictValidator } from 'typanion';
3
- declare type ValidateOptions = Pick<ValidationState, 'coercions' | 'coercion'>;
4
- declare type RHFResolver = <TFieldValues extends FieldValues, TContext>(values: TFieldValues, context: TContext | undefined, options: ResolverOptions<TFieldValues>) => ResolverResult<TFieldValues>;
5
- export declare type Resolver = <UnknownValidator extends AnyStrictValidator>(validator: UnknownValidator, validatorOptions?: ValidateOptions, resolverOptions?: {
6
- mode?: 'async' | 'sync';
7
- rawValues?: boolean;
8
- }) => RHFResolver;
9
- export {};
1
+ import type { FieldValues, ResolverOptions, ResolverResult } from 'react-hook-form';
2
+ import { ValidationState, AnyStrictValidator } from 'typanion';
3
+ type ValidateOptions = Pick<ValidationState, 'coercions' | 'coercion'>;
4
+ type RHFResolver = <TFieldValues extends FieldValues, TContext>(values: TFieldValues, context: TContext | undefined, options: ResolverOptions<TFieldValues>) => ResolverResult<TFieldValues>;
5
+ export type Resolver = <UnknownValidator extends AnyStrictValidator>(validator: UnknownValidator, validatorOptions?: ValidateOptions, resolverOptions?: {
6
+ mode?: 'async' | 'sync';
7
+ rawValues?: boolean;
8
+ }) => RHFResolver;
9
+ export {};
@@ -1,11 +1,12 @@
1
1
  import React from 'react';
2
- import { render, screen, act } from '@testing-library/react';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import user from '@testing-library/user-event';
4
4
  import { useForm } from 'react-hook-form';
5
5
  import * as t from 'typanion';
6
6
  import { typanionResolver } from '..';
7
7
 
8
- const ERROR_MESSAGE = 'Expected to have a length of at least 1 elements (got 0)';
8
+ const ERROR_MESSAGE =
9
+ 'Expected to have a length of at least 1 elements (got 0)';
9
10
 
10
11
  const schema = t.isObject({
11
12
  username: t.applyCascade(t.isString(), [t.hasMinLength(1)]),
@@ -40,7 +41,7 @@ function TestComponent({ onSubmit }: Props) {
40
41
  }
41
42
 
42
43
  test("form's native validation with Typanion", async () => {
43
- const handleSubmit = jest.fn();
44
+ const handleSubmit = vi.fn();
44
45
  render(<TestComponent onSubmit={handleSubmit} />);
45
46
 
46
47
  // username
@@ -57,9 +58,7 @@ test("form's native validation with Typanion", async () => {
57
58
  expect(passwordField.validity.valid).toBe(true);
58
59
  expect(passwordField.validationMessage).toBe('');
59
60
 
60
- await act(async () => {
61
- user.click(screen.getByText(/submit/i));
62
- });
61
+ await user.click(screen.getByText(/submit/i));
63
62
 
64
63
  // username
65
64
  usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
@@ -71,10 +70,8 @@ test("form's native validation with Typanion", async () => {
71
70
  expect(passwordField.validity.valid).toBe(false);
72
71
  expect(passwordField.validationMessage).toBe(ERROR_MESSAGE);
73
72
 
74
- await act(async () => {
75
- user.type(screen.getByPlaceholderText(/username/i), 'joe');
76
- user.type(screen.getByPlaceholderText(/password/i), 'password');
77
- });
73
+ await user.type(screen.getByPlaceholderText(/username/i), 'joe');
74
+ await user.type(screen.getByPlaceholderText(/password/i), 'password');
78
75
 
79
76
  // username
80
77
  usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { render, screen, act } from '@testing-library/react';
2
+ import { render, screen } from '@testing-library/react';
3
3
  import user from '@testing-library/user-event';
4
4
  import { useForm } from 'react-hook-form';
5
5
  import * as t from 'typanion';
@@ -43,15 +43,17 @@ function TestComponent({ onSubmit }: Props) {
43
43
  }
44
44
 
45
45
  test("form's validation with Typanion and TypeScript's integration", async () => {
46
- const handleSubmit = jest.fn();
46
+ const handleSubmit = vi.fn();
47
47
  render(<TestComponent onSubmit={handleSubmit} />);
48
48
 
49
- expect(screen.queryAllByRole(/alert/i)).toHaveLength(0);
49
+ expect(screen.queryAllByRole('alert')).toHaveLength(0);
50
50
 
51
- await act(async () => {
52
- user.click(screen.getByText(/submit/i));
53
- });
51
+ await user.click(screen.getByText(/submit/i));
54
52
 
55
- expect(screen.getAllByText('Expected to have a length of at least 1 elements (got 0)')).toHaveLength(2);
53
+ expect(
54
+ screen.getAllByText(
55
+ 'Expected to have a length of at least 1 elements (got 0)',
56
+ ),
57
+ ).toHaveLength(2);
56
58
  expect(handleSubmit).not.toHaveBeenCalled();
57
59
  });
@@ -1,67 +1,67 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
- exports[`typanionResolver should return a single error from typanionResolver when validation fails 1`] = `
4
- Object {
5
- "errors": Object {
6
- "accessToken": Object {
3
+ exports[`typanionResolver > should return a single error from typanionResolver when validation fails 1`] = `
4
+ {
5
+ "errors": {
6
+ "accessToken": {
7
7
  "message": "Expected a string (got undefined)",
8
8
  "ref": undefined,
9
9
  },
10
- "birthYear": Object {
10
+ "birthYear": {
11
11
  "message": "Expected a number (got \\"birthYear\\")",
12
12
  "ref": undefined,
13
13
  },
14
- "email": Object {
14
+ "email": {
15
15
  "message": "Expected to match the pattern /^\\\\S+@\\\\S+$/ (got an empty string)",
16
- "ref": Object {
16
+ "ref": {
17
17
  "name": "email",
18
18
  },
19
19
  },
20
- "enabled": Object {
20
+ "enabled": {
21
21
  "message": "Expected a boolean (got undefined)",
22
22
  "ref": undefined,
23
23
  },
24
- "like": Object {
25
- "id": Object {
24
+ "like": {
25
+ "id": {
26
26
  "message": "Expected a number (got \\"z\\")",
27
27
  "ref": undefined,
28
28
  },
29
- "name": Object {
29
+ "name": {
30
30
  "message": "Expected a string (got undefined)",
31
31
  "ref": undefined,
32
32
  },
33
33
  },
34
- "password": Object {
34
+ "password": {
35
35
  "message": "Expected to match the pattern /.*[A-Z].*/ (got \\"___\\")",
36
- "ref": Object {
36
+ "ref": {
37
37
  "name": "password",
38
38
  },
39
39
  },
40
- "repeatPassword": Object {
40
+ "repeatPassword": {
41
41
  "message": "Expected a string (got undefined)",
42
42
  "ref": undefined,
43
43
  },
44
- "tags": Array [
45
- Object {
44
+ "tags": [
45
+ {
46
46
  "message": "Expected a string (got 1)",
47
47
  "ref": undefined,
48
48
  },
49
- Object {
49
+ {
50
50
  "message": "Expected a string (got 2)",
51
51
  "ref": undefined,
52
52
  },
53
- Object {
53
+ {
54
54
  "message": "Expected a string (got 3)",
55
55
  "ref": undefined,
56
56
  },
57
57
  ],
58
- "username": Object {
58
+ "username": {
59
59
  "message": "Expected a string (got undefined)",
60
- "ref": Object {
60
+ "ref": {
61
61
  "name": "username",
62
62
  },
63
63
  },
64
64
  },
65
- "values": Object {},
65
+ "values": {},
66
66
  }
67
67
  `;
@@ -2,19 +2,23 @@ import { typanionResolver } from '..';
2
2
  import { isSchema, validData, fields, invalidData } from './__fixtures__/data';
3
3
 
4
4
  const tmpObj = {
5
- validate: isSchema
6
- }
5
+ validate: isSchema,
6
+ };
7
7
 
8
8
  const shouldUseNativeValidation = false;
9
9
 
10
10
  describe('typanionResolver', () => {
11
11
  it('should return values from typanionResolver when validation pass', async () => {
12
- const schemaSpy = jest.spyOn(tmpObj, 'validate')
12
+ const schemaSpy = vi.spyOn(tmpObj, 'validate');
13
13
 
14
- const result = await typanionResolver(schemaSpy as any)(validData, undefined, {
15
- fields,
16
- shouldUseNativeValidation,
17
- });
14
+ const result = await typanionResolver(schemaSpy as any)(
15
+ validData,
16
+ undefined,
17
+ {
18
+ fields,
19
+ shouldUseNativeValidation,
20
+ },
21
+ );
18
22
 
19
23
  expect(schemaSpy).toHaveBeenCalledTimes(1);
20
24
  expect(result).toEqual({ errors: {}, values: validData });
@@ -1,4 +1,4 @@
1
- import type {FieldError, FieldErrors} from 'react-hook-form';
1
+ import type { FieldError, FieldErrors } from 'react-hook-form';
2
2
  import { toNestError, validateFieldsNatively } from '@hookform/resolvers';
3
3
  import type { Resolver } from './types';
4
4
 
@@ -0,0 +1,2 @@
1
+ export * from './typebox';
2
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ import type { Resolver } from './types';
2
+ export declare const typeboxResolver: Resolver;
@@ -0,0 +1,2 @@
1
+ var e=require("react-hook-form"),r=require("@hookform/resolvers"),a=require("@sinclair/typebox/value"),s=function(r,a){for(var s={};r.length;){var t=r[0],o=t.type,i=t.message,l=t.path.substring(1).replace(/\//g,".");if(s[l]||(s[l]={message:i,type:""+o}),a){var n=s[l].types,u=n&&n[""+o];s[l]=e.appendErrors(l,a,s,""+o,u?[].concat(u,t.message):t.message)}r.shift()}return s};exports.typeboxResolver=function(e){return function(t,o,i){try{var l=Array.from(a.Value.Errors(e,t));return i.shouldUseNativeValidation&&r.validateFieldsNatively({},i),Promise.resolve(l.length?{values:{},errors:r.toNestError(s(l,!i.shouldUseNativeValidation&&"all"===i.criteriaMode),i)}:{errors:{},values:t})}catch(e){return Promise.reject(e)}}};
2
+ //# sourceMappingURL=typebox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox.js","sources":["../src/typebox.ts"],"sourcesContent":["import { appendErrors, FieldError, FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { Resolver } from './types';\nimport { Value, ValueError } from '@sinclair/typebox/value';\n\nconst parseErrorSchema = (\n _errors: ValueError[],\n validateAllFieldCriteria: boolean,\n) => {\n const errors: Record<string, FieldError> = {};\n for (; _errors.length; ) {\n const error = _errors[0];\n const { type, message, path } = error;\n const _path = path.substring(1).replace(/\\//g, '.');\n\n if (!errors[_path]) {\n errors[_path] = { message, type: '' + type };\n }\n\n if (validateAllFieldCriteria) {\n const types = errors[_path].types;\n const messages = types && types['' + type];\n\n errors[_path] = appendErrors(\n _path,\n validateAllFieldCriteria,\n errors,\n '' + type,\n messages\n ? ([] as string[]).concat(messages as string[], error.message)\n : error.message,\n ) as FieldError;\n }\n\n _errors.shift();\n }\n\n return errors;\n};\n\nexport const typeboxResolver: Resolver =\n (schema) => async (values, _, options) => {\n const errors = Array.from(Value.Errors(schema, values));\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n if (!errors.length) {\n return {\n errors: {} as FieldErrors,\n values,\n };\n }\n\n return {\n values: {},\n errors: toNestError(\n parseErrorSchema(\n errors,\n !options.shouldUseNativeValidation && options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n };\n"],"names":["parseErrorSchema","_errors","validateAllFieldCriteria","errors","length","error","type","message","_path","path","substring","replace","types","messages","appendErrors","concat","shift","schema","values","_","options","Array","from","Value","Errors","shouldUseNativeValidation","validateFieldsNatively","Promise","resolve","toNestError","criteriaMode","e","reject"],"mappings":"uGAKMA,EAAmB,SACvBC,EACAC,GAGA,IADA,IAAMC,EAAqC,CAAE,EACtCF,EAAQG,QAAU,CACvB,IAAMC,EAAQJ,EAAQ,GACdK,EAAwBD,EAAxBC,KAAMC,EAAkBF,EAAlBE,QACRC,EAD0BH,EAATI,KACJC,UAAU,GAAGC,QAAQ,MAAO,KAM/C,GAJKR,EAAOK,KACVL,EAAOK,GAAS,CAAED,QAAAA,EAASD,KAAM,GAAKA,IAGpCJ,EAA0B,CAC5B,IAAMU,EAAQT,EAAOK,GAAOI,MACtBC,EAAWD,GAASA,EAAM,GAAKN,GAErCH,EAAOK,GAASM,EAAYA,aAC1BN,EACAN,EACAC,EACA,GAAKG,EACLO,EACK,GAAgBE,OAAOF,EAAsBR,EAAME,SACpDF,EAAME,QAEb,CAEDN,EAAQe,OACT,CAED,OAAOb,CACT,0BAGE,SAACc,GAAM,OAAA,SAAYC,EAAQC,EAAGC,GAAW,IACvC,IAAMjB,EAASkB,MAAMC,KAAKC,EAAAA,MAAMC,OAAOP,EAAQC,IAI/C,OAFAE,EAAQK,2BAA6BC,EAAAA,uBAAuB,CAAA,EAAIN,GAShEO,QAAAC,QAPKzB,EAAOC,OAOL,CACLc,OAAQ,CAAE,EACVf,OAAQ0B,EAAAA,YACN7B,EACEG,GACCiB,EAAQK,2BAAsD,QAAzBL,EAAQU,cAEhDV,IAbK,CACLjB,OAAQ,GACRe,OAAAA,GAcN,CAAC,MAAAa,GAAAJ,OAAAA,QAAAK,OAAAD,EAAA,CAAA,CAAA"}
@@ -0,0 +1,2 @@
1
+ import{appendErrors as r}from"react-hook-form";import{validateFieldsNatively as e,toNestError as o}from"@hookform/resolvers";import{Value as t}from"@sinclair/typebox/value";var a=function(e,o){for(var t={};e.length;){var a=e[0],s=a.type,i=a.message,n=a.path.substring(1).replace(/\//g,".");if(t[n]||(t[n]={message:i,type:""+s}),o){var l=t[n].types,m=l&&l[""+s];t[n]=r(n,o,t,""+s,m?[].concat(m,a.message):a.message)}e.shift()}return t},s=function(r){return function(s,i,n){try{var l=Array.from(t.Errors(r,s));return n.shouldUseNativeValidation&&e({},n),Promise.resolve(l.length?{values:{},errors:o(a(l,!n.shouldUseNativeValidation&&"all"===n.criteriaMode),n)}:{errors:{},values:s})}catch(r){return Promise.reject(r)}}};export{s as typeboxResolver};
2
+ //# sourceMappingURL=typebox.module.js.map
@@ -0,0 +1,2 @@
1
+ import{appendErrors as r}from"react-hook-form";import{validateFieldsNatively as e,toNestError as o}from"@hookform/resolvers";import{Value as s}from"@sinclair/typebox/value";const t=(e,o)=>{const s={};for(;e.length;){const t=e[0],{type:a,message:i,path:n}=t,l=n.substring(1).replace(/\//g,".");if(s[l]||(s[l]={message:i,type:""+a}),o){const e=s[l].types,i=e&&e[""+a];s[l]=r(l,o,s,""+a,i?[].concat(i,t.message):t.message)}e.shift()}return s},a=r=>async(a,i,n)=>{const l=Array.from(s.Errors(r,a));return n.shouldUseNativeValidation&&e({},n),l.length?{values:{},errors:o(t(l,!n.shouldUseNativeValidation&&"all"===n.criteriaMode),n)}:{errors:{},values:a}};export{a as typeboxResolver};
2
+ //# sourceMappingURL=typebox.modern.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox.modern.mjs","sources":["../src/typebox.ts"],"sourcesContent":["import { appendErrors, FieldError, FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { Resolver } from './types';\nimport { Value, ValueError } from '@sinclair/typebox/value';\n\nconst parseErrorSchema = (\n _errors: ValueError[],\n validateAllFieldCriteria: boolean,\n) => {\n const errors: Record<string, FieldError> = {};\n for (; _errors.length; ) {\n const error = _errors[0];\n const { type, message, path } = error;\n const _path = path.substring(1).replace(/\\//g, '.');\n\n if (!errors[_path]) {\n errors[_path] = { message, type: '' + type };\n }\n\n if (validateAllFieldCriteria) {\n const types = errors[_path].types;\n const messages = types && types['' + type];\n\n errors[_path] = appendErrors(\n _path,\n validateAllFieldCriteria,\n errors,\n '' + type,\n messages\n ? ([] as string[]).concat(messages as string[], error.message)\n : error.message,\n ) as FieldError;\n }\n\n _errors.shift();\n }\n\n return errors;\n};\n\nexport const typeboxResolver: Resolver =\n (schema) => async (values, _, options) => {\n const errors = Array.from(Value.Errors(schema, values));\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n if (!errors.length) {\n return {\n errors: {} as FieldErrors,\n values,\n };\n }\n\n return {\n values: {},\n errors: toNestError(\n parseErrorSchema(\n errors,\n !options.shouldUseNativeValidation && options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n };\n"],"names":["parseErrorSchema","_errors","validateAllFieldCriteria","errors","length","error","type","message","path","_path","substring","replace","types","messages","appendErrors","concat","shift","typeboxResolver","schema","async","values","_","options","Array","from","Value","Errors","shouldUseNativeValidation","validateFieldsNatively","toNestError","criteriaMode"],"mappings":"6KAKA,MAAMA,EAAmBA,CACvBC,EACAC,KAEA,MAAMC,EAAqC,CAAA,EAC3C,KAAOF,EAAQG,QAAU,CACvB,MAAMC,EAAQJ,EAAQ,IAChBK,KAAEA,EAAIC,QAAEA,EAAOC,KAAEA,GAASH,EAC1BI,EAAQD,EAAKE,UAAU,GAAGC,QAAQ,MAAO,KAM/C,GAJKR,EAAOM,KACVN,EAAOM,GAAS,CAAEF,UAASD,KAAM,GAAKA,IAGpCJ,EAA0B,CAC5B,MAAMU,EAAQT,EAAOM,GAAOG,MACtBC,EAAWD,GAASA,EAAM,GAAKN,GAErCH,EAAOM,GAASK,EACdL,EACAP,EACAC,EACA,GAAKG,EACLO,EACK,GAAgBE,OAAOF,EAAsBR,EAAME,SACpDF,EAAME,QAEb,CAEDN,EAAQe,OACT,CAED,OAAOb,GAGIc,EACVC,GAAWC,MAAOC,EAAQC,EAAGC,KAC5B,MAAMnB,EAASoB,MAAMC,KAAKC,EAAMC,OAAOR,EAAQE,IAI/C,OAFAE,EAAQK,2BAA6BC,EAAuB,CAAE,EAAEN,GAE3DnB,EAAOC,OAOL,CACLgB,OAAQ,CAAA,EACRjB,OAAQ0B,EACN7B,EACEG,GACCmB,EAAQK,2BAAsD,QAAzBL,EAAQQ,cAEhDR,IAbK,CACLnB,OAAQ,CAAA,EACRiB"}
@@ -0,0 +1,2 @@
1
+ import{appendErrors as r}from"react-hook-form";import{validateFieldsNatively as e,toNestError as o}from"@hookform/resolvers";import{Value as t}from"@sinclair/typebox/value";var a=function(e,o){for(var t={};e.length;){var a=e[0],s=a.type,i=a.message,n=a.path.substring(1).replace(/\//g,".");if(t[n]||(t[n]={message:i,type:""+s}),o){var l=t[n].types,m=l&&l[""+s];t[n]=r(n,o,t,""+s,m?[].concat(m,a.message):a.message)}e.shift()}return t},s=function(r){return function(s,i,n){try{var l=Array.from(t.Errors(r,s));return n.shouldUseNativeValidation&&e({},n),Promise.resolve(l.length?{values:{},errors:o(a(l,!n.shouldUseNativeValidation&&"all"===n.criteriaMode),n)}:{errors:{},values:s})}catch(r){return Promise.reject(r)}}};export{s as typeboxResolver};
2
+ //# sourceMappingURL=typebox.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox.module.js","sources":["../src/typebox.ts"],"sourcesContent":["import { appendErrors, FieldError, FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { Resolver } from './types';\nimport { Value, ValueError } from '@sinclair/typebox/value';\n\nconst parseErrorSchema = (\n _errors: ValueError[],\n validateAllFieldCriteria: boolean,\n) => {\n const errors: Record<string, FieldError> = {};\n for (; _errors.length; ) {\n const error = _errors[0];\n const { type, message, path } = error;\n const _path = path.substring(1).replace(/\\//g, '.');\n\n if (!errors[_path]) {\n errors[_path] = { message, type: '' + type };\n }\n\n if (validateAllFieldCriteria) {\n const types = errors[_path].types;\n const messages = types && types['' + type];\n\n errors[_path] = appendErrors(\n _path,\n validateAllFieldCriteria,\n errors,\n '' + type,\n messages\n ? ([] as string[]).concat(messages as string[], error.message)\n : error.message,\n ) as FieldError;\n }\n\n _errors.shift();\n }\n\n return errors;\n};\n\nexport const typeboxResolver: Resolver =\n (schema) => async (values, _, options) => {\n const errors = Array.from(Value.Errors(schema, values));\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n if (!errors.length) {\n return {\n errors: {} as FieldErrors,\n values,\n };\n }\n\n return {\n values: {},\n errors: toNestError(\n parseErrorSchema(\n errors,\n !options.shouldUseNativeValidation && options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n };\n"],"names":["parseErrorSchema","_errors","validateAllFieldCriteria","errors","length","error","type","message","_path","path","substring","replace","types","messages","appendErrors","concat","shift","typeboxResolver","schema","values","_","options","Array","from","Value","Errors","shouldUseNativeValidation","validateFieldsNatively","Promise","resolve","toNestError","criteriaMode","e","reject"],"mappings":"6KAKA,IAAMA,EAAmB,SACvBC,EACAC,GAGA,IADA,IAAMC,EAAqC,CAAE,EACtCF,EAAQG,QAAU,CACvB,IAAMC,EAAQJ,EAAQ,GACdK,EAAwBD,EAAxBC,KAAMC,EAAkBF,EAAlBE,QACRC,EAD0BH,EAATI,KACJC,UAAU,GAAGC,QAAQ,MAAO,KAM/C,GAJKR,EAAOK,KACVL,EAAOK,GAAS,CAAED,QAAAA,EAASD,KAAM,GAAKA,IAGpCJ,EAA0B,CAC5B,IAAMU,EAAQT,EAAOK,GAAOI,MACtBC,EAAWD,GAASA,EAAM,GAAKN,GAErCH,EAAOK,GAASM,EACdN,EACAN,EACAC,EACA,GAAKG,EACLO,EACK,GAAgBE,OAAOF,EAAsBR,EAAME,SACpDF,EAAME,QAEb,CAEDN,EAAQe,OACT,CAED,OAAOb,CACT,EAEac,EACX,SAACC,GAAM,OAAA,SAAYC,EAAQC,EAAGC,GAAW,IACvC,IAAMlB,EAASmB,MAAMC,KAAKC,EAAMC,OAAOP,EAAQC,IAI/C,OAFAE,EAAQK,2BAA6BC,EAAuB,CAAA,EAAIN,GAShEO,QAAAC,QAPK1B,EAAOC,OAOL,CACLe,OAAQ,CAAE,EACVhB,OAAQ2B,EACN9B,EACEG,GACCkB,EAAQK,2BAAsD,QAAzBL,EAAQU,cAEhDV,IAbK,CACLlB,OAAQ,GACRgB,OAAAA,GAcN,CAAC,MAAAa,GAAAJ,OAAAA,QAAAK,OAAAD,EAAA,CAAA,CAAA"}
@@ -0,0 +1,2 @@
1
+ !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("react-hook-form"),require("@hookform/resolvers"),require("@sinclair/typebox/value")):"function"==typeof define&&define.amd?define(["exports","react-hook-form","@hookform/resolvers","@sinclair/typebox/value"],r):r((e||self).hookformResolversTypebox={},e.ReactHookForm,e.hookformResolvers,e.value)}(this,function(e,r,o,t){var s=function(e,o){for(var t={};e.length;){var s=e[0],a=s.type,i=s.message,l=s.path.substring(1).replace(/\//g,".");if(t[l]||(t[l]={message:i,type:""+a}),o){var n=t[l].types,f=n&&n[""+a];t[l]=r.appendErrors(l,o,t,""+a,f?[].concat(f,s.message):s.message)}e.shift()}return t};e.typeboxResolver=function(e){return function(r,a,i){try{var l=Array.from(t.Value.Errors(e,r));return i.shouldUseNativeValidation&&o.validateFieldsNatively({},i),Promise.resolve(l.length?{values:{},errors:o.toNestError(s(l,!i.shouldUseNativeValidation&&"all"===i.criteriaMode),i)}:{errors:{},values:r})}catch(e){return Promise.reject(e)}}}});
2
+ //# sourceMappingURL=typebox.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typebox.umd.js","sources":["../src/typebox.ts"],"sourcesContent":["import { appendErrors, FieldError, FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { Resolver } from './types';\nimport { Value, ValueError } from '@sinclair/typebox/value';\n\nconst parseErrorSchema = (\n _errors: ValueError[],\n validateAllFieldCriteria: boolean,\n) => {\n const errors: Record<string, FieldError> = {};\n for (; _errors.length; ) {\n const error = _errors[0];\n const { type, message, path } = error;\n const _path = path.substring(1).replace(/\\//g, '.');\n\n if (!errors[_path]) {\n errors[_path] = { message, type: '' + type };\n }\n\n if (validateAllFieldCriteria) {\n const types = errors[_path].types;\n const messages = types && types['' + type];\n\n errors[_path] = appendErrors(\n _path,\n validateAllFieldCriteria,\n errors,\n '' + type,\n messages\n ? ([] as string[]).concat(messages as string[], error.message)\n : error.message,\n ) as FieldError;\n }\n\n _errors.shift();\n }\n\n return errors;\n};\n\nexport const typeboxResolver: Resolver =\n (schema) => async (values, _, options) => {\n const errors = Array.from(Value.Errors(schema, values));\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n if (!errors.length) {\n return {\n errors: {} as FieldErrors,\n values,\n };\n }\n\n return {\n values: {},\n errors: toNestError(\n parseErrorSchema(\n errors,\n !options.shouldUseNativeValidation && options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n };\n"],"names":["parseErrorSchema","_errors","validateAllFieldCriteria","errors","length","error","type","message","_path","path","substring","replace","types","messages","appendErrors","concat","shift","schema","values","_","options","Array","from","Value","Errors","shouldUseNativeValidation","validateFieldsNatively","Promise","resolve","toNestError","criteriaMode","e","reject"],"mappings":"mcAKA,IAAMA,EAAmB,SACvBC,EACAC,GAGA,IADA,IAAMC,EAAqC,CAAE,EACtCF,EAAQG,QAAU,CACvB,IAAMC,EAAQJ,EAAQ,GACdK,EAAwBD,EAAxBC,KAAMC,EAAkBF,EAAlBE,QACRC,EAD0BH,EAATI,KACJC,UAAU,GAAGC,QAAQ,MAAO,KAM/C,GAJKR,EAAOK,KACVL,EAAOK,GAAS,CAAED,QAAAA,EAASD,KAAM,GAAKA,IAGpCJ,EAA0B,CAC5B,IAAMU,EAAQT,EAAOK,GAAOI,MACtBC,EAAWD,GAASA,EAAM,GAAKN,GAErCH,EAAOK,GAASM,EAAYA,aAC1BN,EACAN,EACAC,EACA,GAAKG,EACLO,EACK,GAAgBE,OAAOF,EAAsBR,EAAME,SACpDF,EAAME,QAEb,CAEDN,EAAQe,OACT,CAED,OAAOb,CACT,oBAGE,SAACc,GAAM,OAAA,SAAYC,EAAQC,EAAGC,GAAW,IACvC,IAAMjB,EAASkB,MAAMC,KAAKC,EAAAA,MAAMC,OAAOP,EAAQC,IAI/C,OAFAE,EAAQK,2BAA6BC,EAAAA,uBAAuB,CAAA,EAAIN,GAShEO,QAAAC,QAPKzB,EAAOC,OAOL,CACLc,OAAQ,CAAE,EACVf,OAAQ0B,EAAAA,YACN7B,EACEG,GACCiB,EAAQK,2BAAsD,QAAzBL,EAAQU,cAEhDV,IAbK,CACLjB,OAAQ,GACRe,OAAAA,GAcN,CAAC,MAAAa,GAAAJ,OAAAA,QAAAK,OAAAD,EAAA,CAAA,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { Type } from '@sinclair/typebox';
2
+ import { FieldValues, ResolverResult, ResolverOptions } from 'react-hook-form';
3
+ export type Resolver = <T extends ReturnType<typeof Type.Object>>(schema: T) => <TFieldValues extends FieldValues, TContext>(values: TFieldValues, context: TContext | undefined, options: ResolverOptions<TFieldValues>) => Promise<ResolverResult<TFieldValues>>;
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@hookform/resolvers/typebox",
3
+ "amdName": "hookformResolversTypebox",
4
+ "version": "1.0.0",
5
+ "private": true,
6
+ "description": "React Hook Form validation resolver: typebox",
7
+ "main": "dist/typebox.js",
8
+ "module": "dist/typebox.module.js",
9
+ "umd:main": "dist/typebox.umd.js",
10
+ "source": "src/index.ts",
11
+ "types": "dist/index.d.ts",
12
+ "license": "MIT",
13
+ "peerDependencies": {
14
+ "react-hook-form": "^7.0.0",
15
+ "@hookform/resolvers": "^2.0.0",
16
+ "@sinclair/typebox": "^0.25.24"
17
+ }
18
+ }
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import { useForm } from 'react-hook-form';
3
+ import { render, screen } from '@testing-library/react';
4
+ import user from '@testing-library/user-event';
5
+ import { typeboxResolver } from '..';
6
+
7
+ import { Type, Static } from '@sinclair/typebox';
8
+
9
+ const schema = Type.Object({
10
+ username: Type.String({ minLength: 1 }),
11
+ password: Type.String({ minLength: 1 }),
12
+ });
13
+
14
+ type FormData = Static<typeof schema>;
15
+
16
+ interface Props {
17
+ onSubmit: (data: FormData) => void;
18
+ }
19
+
20
+ function TestComponent({ onSubmit }: Props) {
21
+ const { register, handleSubmit } = useForm<FormData>({
22
+ resolver: typeboxResolver(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 Zod", async () => {
38
+ const handleSubmit = vi.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 user.click(screen.getByText(/submit/i));
56
+
57
+ // username
58
+ usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
59
+ expect(usernameField.validity.valid).toBe(false);
60
+ expect(usernameField.validationMessage).toBe(
61
+ 'Expected string length greater or equal to 1',
62
+ );
63
+
64
+ // password
65
+ passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement;
66
+ expect(passwordField.validity.valid).toBe(false);
67
+ expect(passwordField.validationMessage).toBe(
68
+ 'Expected string length greater or equal to 1',
69
+ );
70
+
71
+ await user.type(screen.getByPlaceholderText(/username/i), 'joe');
72
+ await user.type(screen.getByPlaceholderText(/password/i), 'password');
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
+ });
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import user from '@testing-library/user-event';
4
+ import { useForm } from 'react-hook-form';
5
+ import { typeboxResolver } from '..';
6
+ import { Type, Static } from '@sinclair/typebox';
7
+
8
+ const schema = Type.Object({
9
+ username: Type.String({ minLength: 1 }),
10
+ password: Type.String({ minLength: 1 }),
11
+ });
12
+
13
+ type FormData = Static<typeof schema> & { unusedProperty: string };
14
+
15
+ interface Props {
16
+ onSubmit: (data: FormData) => void;
17
+ }
18
+
19
+ function TestComponent({ onSubmit }: Props) {
20
+ const {
21
+ register,
22
+ handleSubmit,
23
+ formState: { errors },
24
+ } = useForm<FormData>({
25
+ resolver: typeboxResolver(schema), // Useful to check TypeScript regressions
26
+ });
27
+
28
+ return (
29
+ <form onSubmit={handleSubmit(onSubmit)}>
30
+ <input {...register('username')} />
31
+ {errors.username && <span role="alert">{errors.username.message}</span>}
32
+
33
+ <input {...register('password')} />
34
+ {errors.password && <span role="alert">{errors.password.message}</span>}
35
+
36
+ <button type="submit">submit</button>
37
+ </form>
38
+ );
39
+ }
40
+
41
+ test("form's validation with Zod and TypeScript's integration", async () => {
42
+ const handleSubmit = vi.fn();
43
+ render(<TestComponent onSubmit={handleSubmit} />);
44
+
45
+ expect(screen.queryAllByRole('alert')).toHaveLength(0);
46
+
47
+ await user.click(screen.getByText(/submit/i));
48
+
49
+ expect(
50
+ screen.getAllByText(/Expected string length greater or equal to 1/i),
51
+ ).toHaveLength(2);
52
+
53
+ expect(handleSubmit).not.toHaveBeenCalled();
54
+ });
@@ -0,0 +1,84 @@
1
+ import { Field, InternalFieldName } from 'react-hook-form';
2
+ import { Static, Type } from '@sinclair/typebox';
3
+ import { TypeSystem } from '@sinclair/typebox/system';
4
+
5
+ TypeSystem.CreateFormat('email', (value: string) => {
6
+ return /^\S+@\S+$/.test(value);
7
+ });
8
+
9
+ export const schema = Type.Object({
10
+ username: Type.String({
11
+ minLength: 3,
12
+ maxLength: 30,
13
+ pattern: '^[a-zA-Z0-9]+$',
14
+ }),
15
+ password: Type.String({
16
+ minLength: 8,
17
+ pattern: '^(.*[A-Za-z\\d].*)$',
18
+ }),
19
+ repeatPassword: Type.String(),
20
+ accessToken: Type.Union([Type.String(), Type.Number()]),
21
+ birthYear: Type.Optional(
22
+ Type.Number({
23
+ minimum: 1900,
24
+ maximum: 2013,
25
+ }),
26
+ ),
27
+ email: Type.Optional(Type.String({ format: 'email' })),
28
+ tags: Type.Array(Type.String()),
29
+ enabled: Type.Boolean(),
30
+ like: Type.Optional(
31
+ Type.Array(
32
+ Type.Object({
33
+ id: Type.Number(),
34
+ name: Type.String({ minLength: 4, maxLength: 4 }),
35
+ }),
36
+ ),
37
+ ),
38
+ dateStr: Type.Date(),
39
+ });
40
+
41
+ export const validData: Static<typeof schema> = {
42
+ username: 'Doe',
43
+ password: 'Password123_',
44
+ repeatPassword: 'Password123_',
45
+ birthYear: 2000,
46
+ email: 'tsulatsitamim@gmail.com',
47
+ tags: ['tag1', 'tag2'],
48
+ enabled: true,
49
+ accessToken: 'accessToken',
50
+ like: [
51
+ {
52
+ id: 1,
53
+ name: 'name',
54
+ },
55
+ ],
56
+ dateStr: new Date(),
57
+ };
58
+
59
+ export const invalidData = {
60
+ password: '___',
61
+ email: '',
62
+ birthYear: 'birthYear',
63
+ like: [{ id: 'z' }],
64
+ url: 'abc',
65
+ };
66
+
67
+ export const fields: Record<InternalFieldName, Field['_f']> = {
68
+ username: {
69
+ ref: { name: 'username' },
70
+ name: 'username',
71
+ },
72
+ password: {
73
+ ref: { name: 'password' },
74
+ name: 'password',
75
+ },
76
+ email: {
77
+ ref: { name: 'email' },
78
+ name: 'email',
79
+ },
80
+ birthday: {
81
+ ref: { name: 'birthday' },
82
+ name: 'birthday',
83
+ },
84
+ };