@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/joi/src/joi.ts ADDED
@@ -0,0 +1,81 @@
1
+ import { appendErrors, FieldError } from 'react-hook-form';
2
+ import { toNestError, validateFieldsNatively } from '@hookform/resolvers';
3
+ import type { ValidationError } from 'joi';
4
+ import { Resolver } from './types';
5
+
6
+ const parseErrorSchema = (
7
+ error: ValidationError,
8
+ validateAllFieldCriteria: boolean,
9
+ ) =>
10
+ error.details.length
11
+ ? error.details.reduce<Record<string, FieldError>>((previous, error) => {
12
+ const _path = error.path.join('.');
13
+
14
+ if (!previous[_path]) {
15
+ previous[_path] = { message: error.message, type: error.type };
16
+ }
17
+
18
+ if (validateAllFieldCriteria) {
19
+ const types = previous[_path].types;
20
+ const messages = types && types[error.type!];
21
+
22
+ previous[_path] = appendErrors(
23
+ _path,
24
+ validateAllFieldCriteria,
25
+ previous,
26
+ error.type,
27
+ messages
28
+ ? ([] as string[]).concat(messages as string[], error.message)
29
+ : error.message,
30
+ ) as FieldError;
31
+ }
32
+
33
+ return previous;
34
+ }, {})
35
+ : {};
36
+
37
+ export const joiResolver: Resolver =
38
+ (
39
+ schema,
40
+ schemaOptions = {
41
+ abortEarly: false,
42
+ },
43
+ resolverOptions = {},
44
+ ) =>
45
+ async (values, context, options) => {
46
+ const _schemaOptions = Object.assign({}, schemaOptions, {
47
+ context,
48
+ });
49
+
50
+ let result: Record<string, any> = {};
51
+ if (resolverOptions.mode === 'sync') {
52
+ result = schema.validate(values, _schemaOptions);
53
+ } else {
54
+ try {
55
+ result.value = await schema.validateAsync(values, _schemaOptions);
56
+ } catch (e) {
57
+ result.error = e;
58
+ }
59
+ }
60
+
61
+ if (result.error) {
62
+ return {
63
+ values: {},
64
+ errors: toNestError(
65
+ parseErrorSchema(
66
+ result.error,
67
+ !options.shouldUseNativeValidation &&
68
+ options.criteriaMode === 'all',
69
+ ),
70
+ options,
71
+ ),
72
+ };
73
+ }
74
+
75
+ options.shouldUseNativeValidation && validateFieldsNatively({}, options);
76
+
77
+ return {
78
+ errors: {},
79
+ values: result.value,
80
+ };
81
+ };
@@ -0,0 +1,16 @@
1
+ import {
2
+ ResolverOptions,
3
+ ResolverResult,
4
+ UnpackNestedValue,
5
+ } from 'react-hook-form';
6
+ import type { AsyncValidationOptions, Schema } from 'joi';
7
+
8
+ export type Resolver = <T extends Schema, TFieldValues, TContext>(
9
+ schema: T,
10
+ schemaOptions?: AsyncValidationOptions,
11
+ factoryOptions?: { mode?: 'async' | 'sync' },
12
+ ) => (
13
+ values: UnpackNestedValue<TFieldValues>,
14
+ context: TContext | undefined,
15
+ options: ResolverOptions<TFieldValues>,
16
+ ) => Promise<ResolverResult<TFieldValues>>;
@@ -0,0 +1,2 @@
1
+ export * from './nope';
2
+ export * from './types';
@@ -0,0 +1,2 @@
1
+ import type { Resolver } from './types';
2
+ export declare const nopeResolver: Resolver;
@@ -0,0 +1,2 @@
1
+ var r=require("@hookform/resolvers"),e=function r(e,o,t){return void 0===o&&(o={}),void 0===t&&(t=""),Object.keys(e).reduce(function(o,a){var i=t?t+"."+a:a,s=e[a];return"string"==typeof s?o[i]={message:s}:r(s,o,i),o},o)};exports.nopeResolver=function(o,t){return void 0===t&&(t={abortEarly:!1}),function(a,i,s){var n=o.validate(a,i,t);return n?{values:{},errors:r.toNestError(e(n),s)}:(s.shouldUseNativeValidation&&r.validateFieldsNatively({},s),{values:a,errors:{}})}};
2
+ //# sourceMappingURL=nope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nope.js","sources":["../src/nope.ts"],"sourcesContent":["import type { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { ShapeErrors } from 'nope-validator/lib/cjs/types';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ShapeErrors,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return Object.keys(errors).reduce((acc, key) => {\n const _path = path ? `${path}.${key}` : key;\n const error = errors[key];\n\n if (typeof error === 'string') {\n acc[_path] = {\n message: error,\n };\n } else {\n parseErrors(error, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const nopeResolver: Resolver =\n (\n schema,\n schemaOptions = {\n abortEarly: false,\n },\n ) =>\n (values, context, options) => {\n const result = schema.validate(values, context, schemaOptions) as\n | ShapeErrors\n | undefined;\n\n if (result) {\n return { values: {}, errors: toNestError(parseErrors(result), options) };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","parsedErrors","path","Object","keys","reduce","acc","key","_path","error","message","schema","schemaOptions","abortEarly","values","context","options","result","validate","toNestError","shouldUseNativeValidation","validateFieldsNatively"],"mappings":"qCAKMA,EAAc,SAAdA,EACJC,EACAC,EACAC,GAEA,gBAHAD,IAAAA,EAA4B,aAC5BC,IAAAA,EAAO,IAEAC,OAAOC,KAAKJ,GAAQK,OAAO,SAACC,EAAKC,GACtC,IAAMC,EAAQN,EAAUA,MAAQK,EAAQA,EAClCE,EAAQT,EAAOO,GAUrB,MARqB,iBAAVE,EACTH,EAAIE,GAAS,CACXE,QAASD,GAGXV,EAAYU,EAAOH,EAAKE,GAGnBF,GACNL,yBAIH,SACEU,EACAC,mBAAAA,IAAAA,EAAgB,CACdC,YAAY,aAGfC,EAAQC,EAASC,GAChB,IAAMC,EAASN,EAAOO,SAASJ,EAAQC,EAASH,GAIhD,OAAIK,EACK,CAAEH,OAAQ,GAAId,OAAQmB,cAAYpB,EAAYkB,GAASD,KAGhEA,EAAQI,2BAA6BC,yBAAuB,GAAIL,GAEzD,CAAEF,OAAAA,EAAQd,OAAQ"}
@@ -0,0 +1,2 @@
1
+ import{toNestError as r,validateFieldsNatively as e}from"@hookform/resolvers";var o=function r(e,o,t){return void 0===o&&(o={}),void 0===t&&(t=""),Object.keys(e).reduce(function(o,n){var a=t?t+"."+n:n,i=e[n];return"string"==typeof i?o[a]={message:i}:r(i,o,a),o},o)},t=function(t,n){return void 0===n&&(n={abortEarly:!1}),function(a,i,s){var u=t.validate(a,i,n);return u?{values:{},errors:r(o(u),s)}:(s.shouldUseNativeValidation&&e({},s),{values:a,errors:{}})}};export{t as nopeResolver};
2
+ //# sourceMappingURL=nope.module.js.map
@@ -0,0 +1,2 @@
1
+ import{toNestError as r,validateFieldsNatively as e}from"@hookform/resolvers";const o=(r,e={},s="")=>Object.keys(r).reduce((e,t)=>{const a=s?`${s}.${t}`:t,l=r[t];return"string"==typeof l?e[a]={message:l}:o(l,e,a),e},e),s=(s,t={abortEarly:!1})=>(a,l,n)=>{const i=s.validate(a,l,t);return i?{values:{},errors:r(o(i),n)}:(n.shouldUseNativeValidation&&e({},n),{values:a,errors:{}})};export{s as nopeResolver};
2
+ //# sourceMappingURL=nope.modern.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nope.modern.js","sources":["../src/nope.ts"],"sourcesContent":["import type { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { ShapeErrors } from 'nope-validator/lib/cjs/types';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ShapeErrors,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return Object.keys(errors).reduce((acc, key) => {\n const _path = path ? `${path}.${key}` : key;\n const error = errors[key];\n\n if (typeof error === 'string') {\n acc[_path] = {\n message: error,\n };\n } else {\n parseErrors(error, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const nopeResolver: Resolver =\n (\n schema,\n schemaOptions = {\n abortEarly: false,\n },\n ) =>\n (values, context, options) => {\n const result = schema.validate(values, context, schemaOptions) as\n | ShapeErrors\n | undefined;\n\n if (result) {\n return { values: {}, errors: toNestError(parseErrors(result), options) };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","parsedErrors","path","Object","keys","reduce","acc","key","_path","error","message","nopeResolver","schema","schemaOptions","abortEarly","values","context","options","result","validate","toNestError","shouldUseNativeValidation","validateFieldsNatively"],"mappings":"8EAKA,MAAMA,EAAc,CAClBC,EACAC,EAA4B,GAC5BC,EAAO,KAEAC,OAAOC,KAAKJ,GAAQK,OAAO,CAACC,EAAKC,KACtC,MAAMC,EAAQN,KAAUA,KAAQK,IAAQA,EAClCE,EAAQT,EAAOO,GAUrB,MARqB,iBAAVE,EACTH,EAAIE,GAAS,CACXE,QAASD,GAGXV,EAAYU,EAAOH,EAAKE,GAGnBF,GACNL,GAGQU,EACX,CACEC,EACAC,EAAgB,CACdC,YAAY,KAGhB,CAACC,EAAQC,EAASC,KAChB,MAAMC,EAASN,EAAOO,SAASJ,EAAQC,EAASH,GAIhD,OAAIK,EACK,CAAEH,OAAQ,GAAIf,OAAQoB,EAAYrB,EAAYmB,GAASD,KAGhEA,EAAQI,2BAA6BC,EAAuB,GAAIL,GAEzD,CAAEF,OAAAA,EAAQf,OAAQ"}
@@ -0,0 +1,2 @@
1
+ import{toNestError as r,validateFieldsNatively as e}from"@hookform/resolvers";var o=function r(e,o,t){return void 0===o&&(o={}),void 0===t&&(t=""),Object.keys(e).reduce(function(o,n){var a=t?t+"."+n:n,i=e[n];return"string"==typeof i?o[a]={message:i}:r(i,o,a),o},o)},t=function(t,n){return void 0===n&&(n={abortEarly:!1}),function(a,i,s){var u=t.validate(a,i,n);return u?{values:{},errors:r(o(u),s)}:(s.shouldUseNativeValidation&&e({},s),{values:a,errors:{}})}};export{t as nopeResolver};
2
+ //# sourceMappingURL=nope.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nope.module.js","sources":["../src/nope.ts"],"sourcesContent":["import type { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { ShapeErrors } from 'nope-validator/lib/cjs/types';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ShapeErrors,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return Object.keys(errors).reduce((acc, key) => {\n const _path = path ? `${path}.${key}` : key;\n const error = errors[key];\n\n if (typeof error === 'string') {\n acc[_path] = {\n message: error,\n };\n } else {\n parseErrors(error, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const nopeResolver: Resolver =\n (\n schema,\n schemaOptions = {\n abortEarly: false,\n },\n ) =>\n (values, context, options) => {\n const result = schema.validate(values, context, schemaOptions) as\n | ShapeErrors\n | undefined;\n\n if (result) {\n return { values: {}, errors: toNestError(parseErrors(result), options) };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","parsedErrors","path","Object","keys","reduce","acc","key","_path","error","message","nopeResolver","schema","schemaOptions","abortEarly","values","context","options","result","validate","toNestError","shouldUseNativeValidation","validateFieldsNatively"],"mappings":"8EAKA,IAAMA,EAAc,SAAdA,EACJC,EACAC,EACAC,GAEA,gBAHAD,IAAAA,EAA4B,aAC5BC,IAAAA,EAAO,IAEAC,OAAOC,KAAKJ,GAAQK,OAAO,SAACC,EAAKC,GACtC,IAAMC,EAAQN,EAAUA,MAAQK,EAAQA,EAClCE,EAAQT,EAAOO,GAUrB,MARqB,iBAAVE,EACTH,EAAIE,GAAS,CACXE,QAASD,GAGXV,EAAYU,EAAOH,EAAKE,GAGnBF,GACNL,IAGQU,EACX,SACEC,EACAC,mBAAAA,IAAAA,EAAgB,CACdC,YAAY,aAGfC,EAAQC,EAASC,GAChB,IAAMC,EAASN,EAAOO,SAASJ,EAAQC,EAASH,GAIhD,OAAIK,EACK,CAAEH,OAAQ,GAAIf,OAAQoB,EAAYrB,EAAYmB,GAASD,KAGhEA,EAAQI,2BAA6BC,EAAuB,GAAIL,GAEzD,CAAEF,OAAAA,EAAQf,OAAQ"}
@@ -0,0 +1,2 @@
1
+ !function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports,require("@hookform/resolvers")):"function"==typeof define&&define.amd?define(["exports","@hookform/resolvers"],o):o((e||self).hookformResolversNope={},e.hookformResolvers)}(this,function(e,o){var r=function e(o,r,t){return void 0===r&&(r={}),void 0===t&&(t=""),Object.keys(o).reduce(function(r,n){var s=t?t+"."+n:n,i=o[n];return"string"==typeof i?r[s]={message:i}:e(i,r,s),r},r)};e.nopeResolver=function(e,t){return void 0===t&&(t={abortEarly:!1}),function(n,s,i){var f=e.validate(n,s,t);return f?{values:{},errors:o.toNestError(r(f),i)}:(i.shouldUseNativeValidation&&o.validateFieldsNatively({},i),{values:n,errors:{}})}}});
2
+ //# sourceMappingURL=nope.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nope.umd.js","sources":["../src/nope.ts"],"sourcesContent":["import type { FieldErrors } from 'react-hook-form';\nimport { toNestError, validateFieldsNatively } from '@hookform/resolvers';\nimport type { ShapeErrors } from 'nope-validator/lib/cjs/types';\nimport type { Resolver } from './types';\n\nconst parseErrors = (\n errors: ShapeErrors,\n parsedErrors: FieldErrors = {},\n path = '',\n) => {\n return Object.keys(errors).reduce((acc, key) => {\n const _path = path ? `${path}.${key}` : key;\n const error = errors[key];\n\n if (typeof error === 'string') {\n acc[_path] = {\n message: error,\n };\n } else {\n parseErrors(error, acc, _path);\n }\n\n return acc;\n }, parsedErrors);\n};\n\nexport const nopeResolver: Resolver =\n (\n schema,\n schemaOptions = {\n abortEarly: false,\n },\n ) =>\n (values, context, options) => {\n const result = schema.validate(values, context, schemaOptions) as\n | ShapeErrors\n | undefined;\n\n if (result) {\n return { values: {}, errors: toNestError(parseErrors(result), options) };\n }\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return { values, errors: {} };\n };\n"],"names":["parseErrors","errors","parsedErrors","path","Object","keys","reduce","acc","key","_path","error","message","schema","schemaOptions","abortEarly","values","context","options","result","validate","toNestError","shouldUseNativeValidation","validateFieldsNatively"],"mappings":"0TAKA,IAAMA,EAAc,SAAdA,EACJC,EACAC,EACAC,GAEA,gBAHAD,IAAAA,EAA4B,aAC5BC,IAAAA,EAAO,IAEAC,OAAOC,KAAKJ,GAAQK,OAAO,SAACC,EAAKC,GACtC,IAAMC,EAAQN,EAAUA,MAAQK,EAAQA,EAClCE,EAAQT,EAAOO,GAUrB,MARqB,iBAAVE,EACTH,EAAIE,GAAS,CACXE,QAASD,GAGXV,EAAYU,EAAOH,EAAKE,GAGnBF,GACNL,mBAIH,SACEU,EACAC,mBAAAA,IAAAA,EAAgB,CACdC,YAAY,aAGfC,EAAQC,EAASC,GAChB,IAAMC,EAASN,EAAOO,SAASJ,EAAQC,EAASH,GAIhD,OAAIK,EACK,CAAEH,OAAQ,GAAId,OAAQmB,cAAYpB,EAAYkB,GAASD,KAGhEA,EAAQI,2BAA6BC,yBAAuB,GAAIL,GAEzD,CAAEF,OAAAA,EAAQd,OAAQ"}
@@ -0,0 +1,6 @@
1
+ import type { ResolverOptions, ResolverResult, UnpackNestedValue } from 'react-hook-form';
2
+ import type { NopeObject } from 'nope-validator/lib/cjs/NopeObject';
3
+ declare type ValidateOptions = Parameters<NopeObject['validate']>[2];
4
+ declare type Context = Parameters<NopeObject['validate']>[1];
5
+ export declare type Resolver = <T extends NopeObject, TFieldValues, TContext extends Context>(schema: T, schemaOptions?: ValidateOptions) => (values: UnpackNestedValue<TFieldValues>, context: TContext | undefined, options: ResolverOptions<TFieldValues>) => ResolverResult<TFieldValues>;
6
+ export {};
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "nope",
3
+ "amdName": "hookformResolversNope",
4
+ "version": "1.0.0",
5
+ "private": true,
6
+ "description": "React Hook Form validation resolver: nope",
7
+ "main": "dist/nope.js",
8
+ "module": "dist/nope.module.js",
9
+ "umd:main": "dist/nope.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
+ "nope-validator": "^0.12.0"
17
+ }
18
+ }
@@ -0,0 +1,89 @@
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 Nope from 'nope-validator';
6
+ import { nopeResolver } from '..';
7
+
8
+ const USERNAME_REQUIRED_MESSAGE = 'username field is required';
9
+ const PASSWORD_REQUIRED_MESSAGE = 'password field is required';
10
+
11
+ const schema = Nope.object().shape({
12
+ username: Nope.string().required(USERNAME_REQUIRED_MESSAGE),
13
+ password: Nope.string().required(PASSWORD_REQUIRED_MESSAGE),
14
+ });
15
+
16
+ interface FormData {
17
+ unusedProperty: string;
18
+ username: string;
19
+ password: string;
20
+ }
21
+
22
+ interface Props {
23
+ onSubmit: (data: FormData) => void;
24
+ }
25
+
26
+ function TestComponent({ onSubmit }: Props) {
27
+ const { register, handleSubmit } = useForm<FormData>({
28
+ resolver: nopeResolver(schema),
29
+ shouldUseNativeValidation: true,
30
+ });
31
+
32
+ return (
33
+ <form onSubmit={handleSubmit(onSubmit)}>
34
+ <input {...register('username')} placeholder="username" />
35
+
36
+ <input {...register('password')} placeholder="password" />
37
+
38
+ <button type="submit">submit</button>
39
+ </form>
40
+ );
41
+ }
42
+
43
+ test("form's native validation with Nope", async () => {
44
+ const handleSubmit = jest.fn();
45
+ render(<TestComponent onSubmit={handleSubmit} />);
46
+
47
+ // username
48
+ let usernameField = screen.getByPlaceholderText(
49
+ /username/i,
50
+ ) as HTMLInputElement;
51
+ expect(usernameField.validity.valid).toBe(true);
52
+ expect(usernameField.validationMessage).toBe('');
53
+
54
+ // password
55
+ let passwordField = screen.getByPlaceholderText(
56
+ /password/i,
57
+ ) as HTMLInputElement;
58
+ expect(passwordField.validity.valid).toBe(true);
59
+ expect(passwordField.validationMessage).toBe('');
60
+
61
+ await act(async () => {
62
+ user.click(screen.getByText(/submit/i));
63
+ });
64
+
65
+ // username
66
+ usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
67
+ expect(usernameField.validity.valid).toBe(false);
68
+ expect(usernameField.validationMessage).toBe(USERNAME_REQUIRED_MESSAGE);
69
+
70
+ // password
71
+ passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement;
72
+ expect(passwordField.validity.valid).toBe(false);
73
+ expect(passwordField.validationMessage).toBe(PASSWORD_REQUIRED_MESSAGE);
74
+
75
+ await act(async () => {
76
+ user.type(screen.getByPlaceholderText(/username/i), 'joe');
77
+ user.type(screen.getByPlaceholderText(/password/i), 'password');
78
+ });
79
+
80
+ // username
81
+ usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
82
+ expect(usernameField.validity.valid).toBe(true);
83
+ expect(usernameField.validationMessage).toBe('');
84
+
85
+ // password
86
+ passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement;
87
+ expect(passwordField.validity.valid).toBe(true);
88
+ expect(passwordField.validationMessage).toBe('');
89
+ });
@@ -0,0 +1,57 @@
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 Nope from 'nope-validator';
6
+ import { nopeResolver } from '..';
7
+
8
+ const schema = Nope.object().shape({
9
+ username: Nope.string().required(),
10
+ password: Nope.string().required(),
11
+ });
12
+
13
+ interface FormData {
14
+ unusedProperty: string;
15
+ username: string;
16
+ password: string;
17
+ }
18
+
19
+ interface Props {
20
+ onSubmit: (data: FormData) => void;
21
+ }
22
+
23
+ function TestComponent({ onSubmit }: Props) {
24
+ const {
25
+ register,
26
+ formState: { errors },
27
+ handleSubmit,
28
+ } = useForm<FormData>({
29
+ resolver: nopeResolver(schema), // Useful to check TypeScript regressions
30
+ });
31
+
32
+ return (
33
+ <form onSubmit={handleSubmit(onSubmit)}>
34
+ <input {...register('username')} />
35
+ {errors.username && <span role="alert">{errors.username.message}</span>}
36
+
37
+ <input {...register('password')} />
38
+ {errors.password && <span role="alert">{errors.password.message}</span>}
39
+
40
+ <button type="submit">submit</button>
41
+ </form>
42
+ );
43
+ }
44
+
45
+ test("form's validation with Yup and TypeScript's integration", async () => {
46
+ const handleSubmit = jest.fn();
47
+ render(<TestComponent onSubmit={handleSubmit} />);
48
+
49
+ expect(screen.queryAllByRole(/alert/i)).toHaveLength(0);
50
+
51
+ await act(async () => {
52
+ user.click(screen.getByText(/submit/i));
53
+ });
54
+
55
+ expect(screen.getAllByText(/This field is required/i)).toHaveLength(2);
56
+ expect(handleSubmit).not.toHaveBeenCalled();
57
+ });
@@ -0,0 +1,70 @@
1
+ import { Field, InternalFieldName } from 'react-hook-form';
2
+ import Nope from 'nope-validator';
3
+
4
+ export const schema = Nope.object().shape({
5
+ username: Nope.string().regex(/^\w+$/).min(2).max(30).required(),
6
+ password: Nope.string()
7
+ .regex(new RegExp('.*[A-Z].*'), 'One uppercase character')
8
+ .regex(new RegExp('.*[a-z].*'), 'One lowercase character')
9
+ .regex(new RegExp('.*\\d.*'), 'One number')
10
+ .regex(
11
+ new RegExp('.*[`~<>?,./!@#$%^&*()\\-_+="\'|{}\\[\\];:\\\\].*'),
12
+ 'One special character',
13
+ )
14
+ .min(8, 'Must be at least 8 characters in length')
15
+ .required('New Password is required'),
16
+ repeatPassword: Nope.string()
17
+ .oneOf([Nope.ref('password')], "Passwords don't match")
18
+ .required(),
19
+ accessToken: Nope.string(),
20
+ birthYear: Nope.number().min(1900).max(2013),
21
+ email: Nope.string().email(),
22
+ tags: Nope.array().of(Nope.string()).required(),
23
+ enabled: Nope.boolean(),
24
+ like: Nope.object().shape({
25
+ id: Nope.number().required(),
26
+ name: Nope.string().atLeast(4).required(),
27
+ }),
28
+ });
29
+
30
+ export const validData = {
31
+ username: 'Doe',
32
+ password: 'Password123_',
33
+ repeatPassword: 'Password123_',
34
+ birthYear: 2000,
35
+ email: 'john@doe.com',
36
+ tags: ['tag1', 'tag2'],
37
+ enabled: true,
38
+ accessToken: 'accessToken',
39
+ like: {
40
+ id: 1,
41
+ name: 'name',
42
+ },
43
+ };
44
+
45
+ export const invalidData = {
46
+ password: '___',
47
+ email: '',
48
+ birthYear: 'birthYear',
49
+ like: { id: 'z' },
50
+ tags: [1, 2, 3],
51
+ };
52
+
53
+ export const fields: Record<InternalFieldName, Field['_f']> = {
54
+ username: {
55
+ ref: { name: 'username' },
56
+ name: 'username',
57
+ },
58
+ password: {
59
+ ref: { name: 'password' },
60
+ name: 'password',
61
+ },
62
+ email: {
63
+ ref: { name: 'email' },
64
+ name: 'email',
65
+ },
66
+ birthday: {
67
+ ref: { name: 'birthday' },
68
+ name: 'birthday',
69
+ },
70
+ };
@@ -0,0 +1,43 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`nopeResolver should return a single error from nopeResolver when validation fails 1`] = `
4
+ Object {
5
+ "errors": Object {
6
+ "birthYear": Object {
7
+ "message": "The field is not a valid number",
8
+ "ref": undefined,
9
+ },
10
+ "like": Object {
11
+ "id": Object {
12
+ "message": "The field is not a valid number",
13
+ "ref": undefined,
14
+ },
15
+ "name": Object {
16
+ "message": "This field is required",
17
+ "ref": undefined,
18
+ },
19
+ },
20
+ "password": Object {
21
+ "message": "One uppercase character",
22
+ "ref": Object {
23
+ "name": "password",
24
+ },
25
+ },
26
+ "repeatPassword": Object {
27
+ "message": "This field is required",
28
+ "ref": undefined,
29
+ },
30
+ "tags": Object {
31
+ "message": "One or more elements are of invalid type",
32
+ "ref": undefined,
33
+ },
34
+ "username": Object {
35
+ "message": "This field is required",
36
+ "ref": Object {
37
+ "name": "username",
38
+ },
39
+ },
40
+ },
41
+ "values": Object {},
42
+ }
43
+ `;
@@ -0,0 +1,28 @@
1
+ /* eslint-disable no-console, @typescript-eslint/ban-ts-comment */
2
+ import { nopeResolver } from '..';
3
+ import { schema, validData, fields, invalidData } from './__fixtures__/data';
4
+
5
+ const shouldUseNativeValidation = false;
6
+
7
+ describe('nopeResolver', () => {
8
+ it('should return values from nopeResolver when validation pass', async () => {
9
+ const schemaSpy = jest.spyOn(schema, 'validate');
10
+
11
+ const result = await nopeResolver(schema)(validData, undefined, {
12
+ fields,
13
+ shouldUseNativeValidation,
14
+ });
15
+
16
+ expect(schemaSpy).toHaveBeenCalledTimes(1);
17
+ expect(result).toEqual({ errors: {}, values: validData });
18
+ });
19
+
20
+ it('should return a single error from nopeResolver when validation fails', async () => {
21
+ const result = await nopeResolver(schema)(invalidData, undefined, {
22
+ fields,
23
+ shouldUseNativeValidation,
24
+ });
25
+
26
+ expect(result).toMatchSnapshot();
27
+ });
28
+ });
@@ -0,0 +1,2 @@
1
+ export * from './nope';
2
+ export * from './types';
@@ -0,0 +1,46 @@
1
+ import type { FieldErrors } from 'react-hook-form';
2
+ import { toNestError, validateFieldsNatively } from '@hookform/resolvers';
3
+ import type { ShapeErrors } from 'nope-validator/lib/cjs/types';
4
+ import type { Resolver } from './types';
5
+
6
+ const parseErrors = (
7
+ errors: ShapeErrors,
8
+ parsedErrors: FieldErrors = {},
9
+ path = '',
10
+ ) => {
11
+ return Object.keys(errors).reduce((acc, key) => {
12
+ const _path = path ? `${path}.${key}` : key;
13
+ const error = errors[key];
14
+
15
+ if (typeof error === 'string') {
16
+ acc[_path] = {
17
+ message: error,
18
+ };
19
+ } else {
20
+ parseErrors(error, acc, _path);
21
+ }
22
+
23
+ return acc;
24
+ }, parsedErrors);
25
+ };
26
+
27
+ export const nopeResolver: Resolver =
28
+ (
29
+ schema,
30
+ schemaOptions = {
31
+ abortEarly: false,
32
+ },
33
+ ) =>
34
+ (values, context, options) => {
35
+ const result = schema.validate(values, context, schemaOptions) as
36
+ | ShapeErrors
37
+ | undefined;
38
+
39
+ if (result) {
40
+ return { values: {}, errors: toNestError(parseErrors(result), options) };
41
+ }
42
+
43
+ options.shouldUseNativeValidation && validateFieldsNatively({}, options);
44
+
45
+ return { values, errors: {} };
46
+ };
@@ -0,0 +1,22 @@
1
+ import type {
2
+ ResolverOptions,
3
+ ResolverResult,
4
+ UnpackNestedValue,
5
+ } from 'react-hook-form';
6
+ import type { NopeObject } from 'nope-validator/lib/cjs/NopeObject';
7
+
8
+ type ValidateOptions = Parameters<NopeObject['validate']>[2];
9
+ type Context = Parameters<NopeObject['validate']>[1];
10
+
11
+ export type Resolver = <
12
+ T extends NopeObject,
13
+ TFieldValues,
14
+ TContext extends Context,
15
+ >(
16
+ schema: T,
17
+ schemaOptions?: ValidateOptions,
18
+ ) => (
19
+ values: UnpackNestedValue<TFieldValues>,
20
+ context: TContext | undefined,
21
+ options: ResolverOptions<TFieldValues>,
22
+ ) => ResolverResult<TFieldValues>;