@hookform/resolvers 3.6.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/README.md +107 -25
  2. package/ajv/dist/ajv.js.map +1 -1
  3. package/ajv/dist/ajv.modern.mjs.map +1 -1
  4. package/ajv/dist/ajv.module.js.map +1 -1
  5. package/ajv/dist/ajv.umd.js.map +1 -1
  6. package/ajv/dist/types.d.ts +1 -1
  7. package/ajv/src/__tests__/ajv.ts +7 -1
  8. package/ajv/src/ajv.ts +1 -1
  9. package/ajv/src/types.ts +1 -5
  10. package/arktype/dist/arktype.js +1 -1
  11. package/arktype/dist/arktype.js.map +1 -1
  12. package/arktype/dist/arktype.mjs +1 -1
  13. package/arktype/dist/arktype.modern.mjs +1 -1
  14. package/arktype/dist/arktype.modern.mjs.map +1 -1
  15. package/arktype/dist/arktype.module.js +1 -1
  16. package/arktype/dist/arktype.module.js.map +1 -1
  17. package/arktype/dist/arktype.umd.js +1 -1
  18. package/arktype/dist/arktype.umd.js.map +1 -1
  19. package/arktype/dist/types.d.ts +1 -1
  20. package/arktype/package.json +2 -1
  21. package/arktype/src/__tests__/Form-native-validation.tsx +5 -5
  22. package/arktype/src/__tests__/Form.tsx +2 -2
  23. package/arktype/src/__tests__/__fixtures__/data.ts +1 -1
  24. package/arktype/src/__tests__/__snapshots__/arktype.ts.snap +29 -29
  25. package/arktype/src/__tests__/arktype.ts +1 -1
  26. package/arktype/src/arktype.ts +2 -2
  27. package/arktype/src/types.ts +1 -1
  28. package/class-validator/dist/class-validator.js.map +1 -1
  29. package/class-validator/dist/class-validator.modern.mjs.map +1 -1
  30. package/class-validator/dist/class-validator.module.js.map +1 -1
  31. package/class-validator/dist/class-validator.umd.js.map +1 -1
  32. package/class-validator/dist/types.d.ts +2 -2
  33. package/class-validator/src/__tests__/Form-native-validation.tsx +2 -2
  34. package/class-validator/src/__tests__/Form.tsx +2 -2
  35. package/class-validator/src/__tests__/__snapshots__/class-validator.ts.snap +2 -2
  36. package/class-validator/src/__tests__/class-validator.ts +4 -4
  37. package/class-validator/src/class-validator.ts +2 -2
  38. package/class-validator/src/types.ts +2 -2
  39. package/computed-types/dist/computed-types.js.map +1 -1
  40. package/computed-types/dist/computed-types.modern.mjs.map +1 -1
  41. package/computed-types/dist/computed-types.module.js.map +1 -1
  42. package/computed-types/dist/computed-types.umd.js.map +1 -1
  43. package/computed-types/dist/types.d.ts +1 -1
  44. package/computed-types/src/__tests__/Form-native-validation.tsx +2 -2
  45. package/computed-types/src/__tests__/Form.tsx +2 -2
  46. package/computed-types/src/__tests__/__fixtures__/data.ts +1 -1
  47. package/computed-types/src/__tests__/__snapshots__/computed-types.ts.snap +6 -6
  48. package/computed-types/src/__tests__/computed-types.ts +1 -1
  49. package/computed-types/src/computed-types.ts +2 -2
  50. package/computed-types/src/types.ts +1 -1
  51. package/dist/resolvers.js +1 -1
  52. package/dist/resolvers.js.map +1 -1
  53. package/dist/resolvers.mjs +1 -1
  54. package/dist/resolvers.mjs.map +1 -1
  55. package/dist/resolvers.module.js +1 -1
  56. package/dist/resolvers.module.js.map +1 -1
  57. package/dist/resolvers.umd.js +1 -1
  58. package/dist/resolvers.umd.js.map +1 -1
  59. package/dist/toNestErrors.d.ts +1 -6
  60. package/dist/validateFieldsNatively.d.ts +1 -1
  61. package/effect-ts/dist/effect-ts.js +1 -1
  62. package/effect-ts/dist/effect-ts.js.map +1 -1
  63. package/effect-ts/dist/effect-ts.mjs +1 -1
  64. package/effect-ts/dist/effect-ts.modern.mjs +1 -1
  65. package/effect-ts/dist/effect-ts.modern.mjs.map +1 -1
  66. package/effect-ts/dist/effect-ts.module.js +1 -1
  67. package/effect-ts/dist/effect-ts.module.js.map +1 -1
  68. package/effect-ts/dist/effect-ts.umd.js +1 -1
  69. package/effect-ts/dist/effect-ts.umd.js.map +1 -1
  70. package/effect-ts/src/__tests__/Form-native-validation.tsx +2 -2
  71. package/effect-ts/src/__tests__/Form.tsx +2 -2
  72. package/effect-ts/src/__tests__/__snapshots__/effect-ts.ts.snap +2 -2
  73. package/effect-ts/src/__tests__/effect-ts.ts +1 -1
  74. package/effect-ts/src/effect-ts.ts +1 -1
  75. package/io-ts/dist/errorsToRecord.d.ts +0 -1
  76. package/io-ts/dist/io-ts.js +1 -1
  77. package/io-ts/dist/io-ts.js.map +1 -1
  78. package/io-ts/dist/io-ts.mjs +1 -1
  79. package/io-ts/dist/io-ts.modern.mjs +1 -1
  80. package/io-ts/dist/io-ts.modern.mjs.map +1 -1
  81. package/io-ts/dist/io-ts.module.js +1 -1
  82. package/io-ts/dist/io-ts.module.js.map +1 -1
  83. package/io-ts/dist/io-ts.umd.js +1 -1
  84. package/io-ts/dist/io-ts.umd.js.map +1 -1
  85. package/io-ts/src/__tests__/Form-native-validation.tsx +2 -2
  86. package/io-ts/src/__tests__/Form.tsx +2 -2
  87. package/io-ts/src/__tests__/__snapshots__/io-ts.ts.snap +9 -9
  88. package/io-ts/src/__tests__/errorsToRecord.ts +29 -19
  89. package/io-ts/src/__tests__/io-ts.ts +1 -1
  90. package/io-ts/src/errorsToRecord.ts +19 -10
  91. package/io-ts/src/io-ts.ts +1 -1
  92. package/joi/dist/joi.js +1 -1
  93. package/joi/dist/joi.js.map +1 -1
  94. package/joi/dist/joi.mjs +1 -1
  95. package/joi/dist/joi.modern.mjs +1 -1
  96. package/joi/dist/joi.modern.mjs.map +1 -1
  97. package/joi/dist/joi.module.js +1 -1
  98. package/joi/dist/joi.module.js.map +1 -1
  99. package/joi/dist/joi.umd.js +1 -1
  100. package/joi/dist/joi.umd.js.map +1 -1
  101. package/joi/dist/types.d.ts +1 -1
  102. package/joi/src/__tests__/Form-native-validation.tsx +2 -2
  103. package/joi/src/__tests__/Form.tsx +2 -2
  104. package/joi/src/__tests__/__snapshots__/joi.ts.snap +56 -56
  105. package/joi/src/__tests__/joi.ts +1 -1
  106. package/joi/src/joi.ts +1 -1
  107. package/joi/src/types.ts +1 -5
  108. package/nope/dist/nope.js.map +1 -1
  109. package/nope/dist/nope.modern.mjs.map +1 -1
  110. package/nope/dist/nope.module.js.map +1 -1
  111. package/nope/dist/nope.umd.js.map +1 -1
  112. package/nope/dist/types.d.ts +1 -1
  113. package/nope/src/__tests__/Form-native-validation.tsx +2 -2
  114. package/nope/src/__tests__/Form.tsx +2 -2
  115. package/nope/src/__tests__/__fixtures__/data.ts +1 -1
  116. package/nope/src/__tests__/nope.ts +1 -1
  117. package/nope/src/nope.ts +1 -1
  118. package/nope/src/types.ts +2 -2
  119. package/package.json +69 -54
  120. package/superstruct/dist/superstruct.js.map +1 -1
  121. package/superstruct/dist/superstruct.modern.mjs.map +1 -1
  122. package/superstruct/dist/superstruct.module.js.map +1 -1
  123. package/superstruct/dist/superstruct.umd.js.map +1 -1
  124. package/superstruct/dist/types.d.ts +1 -1
  125. package/superstruct/src/__tests__/Form-native-validation.tsx +2 -2
  126. package/superstruct/src/__tests__/Form.tsx +2 -2
  127. package/superstruct/src/__tests__/__fixtures__/data.ts +8 -8
  128. package/superstruct/src/__tests__/__snapshots__/superstruct.ts.snap +4 -4
  129. package/superstruct/src/__tests__/superstruct.ts +1 -1
  130. package/superstruct/src/superstruct.ts +1 -1
  131. package/superstruct/src/types.ts +1 -1
  132. package/typanion/dist/typanion.js.map +1 -1
  133. package/typanion/dist/typanion.modern.mjs.map +1 -1
  134. package/typanion/dist/typanion.module.js.map +1 -1
  135. package/typanion/dist/typanion.umd.js.map +1 -1
  136. package/typanion/dist/types.d.ts +1 -1
  137. package/typanion/src/__tests__/Form-native-validation.tsx +1 -1
  138. package/typanion/src/__tests__/Form.tsx +1 -1
  139. package/typanion/src/__tests__/__fixtures__/data.ts +12 -7
  140. package/typanion/src/__tests__/__snapshots__/typanion.ts.snap +4 -4
  141. package/typanion/src/__tests__/typanion.ts +1 -1
  142. package/typanion/src/typanion.ts +1 -1
  143. package/typanion/src/types.ts +4 -4
  144. package/typebox/dist/typebox.js +1 -1
  145. package/typebox/dist/typebox.js.map +1 -1
  146. package/typebox/dist/typebox.mjs +1 -1
  147. package/typebox/dist/typebox.modern.mjs +1 -1
  148. package/typebox/dist/typebox.modern.mjs.map +1 -1
  149. package/typebox/dist/typebox.module.js +1 -1
  150. package/typebox/dist/typebox.module.js.map +1 -1
  151. package/typebox/dist/typebox.umd.js +1 -1
  152. package/typebox/dist/typebox.umd.js.map +1 -1
  153. package/typebox/dist/types.d.ts +3 -2
  154. package/typebox/src/__tests__/Form-compiler.tsx +57 -0
  155. package/typebox/src/__tests__/Form-native-validation-compiler.tsx +86 -0
  156. package/typebox/src/__tests__/Form-native-validation.tsx +4 -4
  157. package/typebox/src/__tests__/Form.tsx +3 -3
  158. package/typebox/src/__tests__/__fixtures__/data.ts +6 -2
  159. package/typebox/src/__tests__/__snapshots__/typebox-compiler.ts.snap +188 -0
  160. package/typebox/src/__tests__/__snapshots__/typebox.ts.snap +13 -13
  161. package/typebox/src/__tests__/typebox-compiler.ts +37 -0
  162. package/typebox/src/__tests__/typebox.ts +1 -1
  163. package/typebox/src/typebox.ts +8 -3
  164. package/typebox/src/types.ts +3 -2
  165. package/typeschema/dist/index.d.ts +2 -0
  166. package/typeschema/dist/types.d.ts +9 -0
  167. package/typeschema/dist/typeschema.d.ts +2 -0
  168. package/typeschema/dist/typeschema.js +2 -0
  169. package/typeschema/dist/typeschema.js.map +1 -0
  170. package/typeschema/dist/typeschema.mjs +2 -0
  171. package/typeschema/dist/typeschema.modern.mjs +2 -0
  172. package/typeschema/dist/typeschema.modern.mjs.map +1 -0
  173. package/typeschema/dist/typeschema.module.js +2 -0
  174. package/typeschema/dist/typeschema.module.js.map +1 -0
  175. package/typeschema/dist/typeschema.umd.js +2 -0
  176. package/typeschema/dist/typeschema.umd.js.map +1 -0
  177. package/typeschema/package.json +18 -0
  178. package/typeschema/src/__tests__/Form-native-validation.tsx +82 -0
  179. package/typeschema/src/__tests__/Form.tsx +53 -0
  180. package/typeschema/src/__tests__/__fixtures__/data.ts +88 -0
  181. package/typeschema/src/__tests__/__snapshots__/typeschema.ts.snap +225 -0
  182. package/typeschema/src/__tests__/typeschema.ts +70 -0
  183. package/typeschema/src/index.ts +2 -0
  184. package/typeschema/src/types.ts +18 -0
  185. package/typeschema/src/typeschema.ts +70 -0
  186. package/valibot/dist/types.d.ts +1 -1
  187. package/valibot/dist/valibot.js +1 -1
  188. package/valibot/dist/valibot.js.map +1 -1
  189. package/valibot/dist/valibot.mjs +1 -1
  190. package/valibot/dist/valibot.modern.mjs +1 -1
  191. package/valibot/dist/valibot.modern.mjs.map +1 -1
  192. package/valibot/dist/valibot.module.js +1 -1
  193. package/valibot/dist/valibot.module.js.map +1 -1
  194. package/valibot/dist/valibot.umd.js +1 -1
  195. package/valibot/dist/valibot.umd.js.map +1 -1
  196. package/valibot/package.json +1 -1
  197. package/valibot/src/__tests__/Form-native-validation.tsx +2 -2
  198. package/valibot/src/__tests__/Form.tsx +1 -1
  199. package/valibot/src/__tests__/valibot.ts +4 -4
  200. package/valibot/src/types.ts +1 -1
  201. package/valibot/src/valibot.ts +12 -6
  202. package/vest/dist/types.d.ts +2 -2
  203. package/vest/dist/vest.js.map +1 -1
  204. package/vest/dist/vest.modern.mjs.map +1 -1
  205. package/vest/dist/vest.module.js.map +1 -1
  206. package/vest/dist/vest.umd.js.map +1 -1
  207. package/vest/src/__tests__/Form-native-validation.tsx +1 -1
  208. package/vest/src/__tests__/Form.tsx +1 -1
  209. package/vest/src/__tests__/__snapshots__/vest.ts.snap +0 -6
  210. package/vest/src/__tests__/vest.ts +14 -8
  211. package/vest/src/types.ts +11 -4
  212. package/vest/src/vest.ts +1 -1
  213. package/vine/dist/index.d.ts +2 -0
  214. package/vine/dist/types.d.ts +6 -0
  215. package/vine/dist/vine.d.ts +2 -0
  216. package/vine/dist/vine.js +2 -0
  217. package/vine/dist/vine.js.map +1 -0
  218. package/vine/dist/vine.mjs +2 -0
  219. package/vine/dist/vine.modern.mjs +2 -0
  220. package/vine/dist/vine.modern.mjs.map +1 -0
  221. package/vine/dist/vine.module.js +2 -0
  222. package/vine/dist/vine.module.js.map +1 -0
  223. package/vine/dist/vine.umd.js +2 -0
  224. package/vine/dist/vine.umd.js.map +1 -0
  225. package/vine/package.json +18 -0
  226. package/vine/src/__tests__/Form-native-validation.tsx +85 -0
  227. package/vine/src/__tests__/Form.tsx +59 -0
  228. package/vine/src/__tests__/__fixtures__/data.ts +76 -0
  229. package/vine/src/__tests__/__snapshots__/vine.ts.snap +180 -0
  230. package/vine/src/__tests__/vine.ts +53 -0
  231. package/vine/src/index.ts +2 -0
  232. package/vine/src/types.ts +13 -0
  233. package/vine/src/vine.ts +68 -0
  234. package/yup/dist/yup.d.ts +1 -1
  235. package/yup/dist/yup.js.map +1 -1
  236. package/yup/dist/yup.modern.mjs.map +1 -1
  237. package/yup/dist/yup.module.js.map +1 -1
  238. package/yup/dist/yup.umd.js.map +1 -1
  239. package/yup/src/__tests__/Form-native-validation.tsx +1 -1
  240. package/yup/src/__tests__/Form.tsx +1 -1
  241. package/yup/src/__tests__/__snapshots__/yup.ts.snap +13 -13
  242. package/yup/src/__tests__/yup.ts +9 -7
  243. package/yup/src/yup.ts +2 -2
  244. package/zod/dist/types.d.ts +1 -1
  245. package/zod/dist/zod.js +1 -1
  246. package/zod/dist/zod.js.map +1 -1
  247. package/zod/dist/zod.mjs +1 -1
  248. package/zod/dist/zod.modern.mjs +1 -1
  249. package/zod/dist/zod.modern.mjs.map +1 -1
  250. package/zod/dist/zod.module.js +1 -1
  251. package/zod/dist/zod.module.js.map +1 -1
  252. package/zod/dist/zod.umd.js +1 -1
  253. package/zod/dist/zod.umd.js.map +1 -1
  254. package/zod/src/__tests__/Form-native-validation.tsx +2 -2
  255. package/zod/src/__tests__/Form.tsx +1 -1
  256. package/zod/src/__tests__/zod.ts +1 -1
  257. package/zod/src/types.ts +1 -1
  258. package/zod/src/zod.ts +4 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vine.js","sources":["../src/vine.ts"],"sourcesContent":["import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport { SimpleErrorReporter, errors } from '@vinejs/vine';\nimport { FieldError, FieldErrors, appendErrors } from 'react-hook-form';\nimport type { Resolver } from './types';\n\nconst parseErrorSchema = (\n vineErrors: SimpleErrorReporter['errors'],\n validateAllFieldCriteria: boolean,\n) => {\n const schemaErrors: Record<string, FieldError> = {};\n\n for (; vineErrors.length; ) {\n const error = vineErrors[0];\n const path = error.field;\n\n if (!(path in schemaErrors)) {\n schemaErrors[path] = { message: error.message, type: error.rule };\n }\n\n if (validateAllFieldCriteria) {\n const { types } = schemaErrors[path];\n const messages = types && types[error.rule];\n\n schemaErrors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n schemaErrors,\n error.rule,\n messages ? [...(messages as string[]), error.message] : error.message,\n ) as FieldError;\n }\n\n vineErrors.shift();\n }\n\n return schemaErrors;\n};\n\nexport const vineResolver: Resolver =\n (schema, schemaOptions, resolverOptions = {}) =>\n async (values, _, options) => {\n try {\n const data = await schema.validate(values, schemaOptions);\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return {\n errors: {} as FieldErrors,\n values: resolverOptions.raw ? values : data,\n };\n } catch (error: any) {\n if (error instanceof errors.E_VALIDATION_ERROR) {\n return {\n values: {},\n errors: toNestErrors(\n parseErrorSchema(\n error.messages,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n throw error;\n }\n };\n"],"names":["parseErrorSchema","vineErrors","validateAllFieldCriteria","schemaErrors","length","error","path","field","message","type","rule","types","messages","appendErrors","concat","shift","schema","schemaOptions","resolverOptions","values","_","options","Promise","resolve","validate","then","data","shouldUseNativeValidation","validateFieldsNatively","errors","raw","_catch","E_VALIDATION_ERROR","toNestErrors","criteriaMode","e","reject"],"mappings":"4FAKMA,EAAmB,SACvBC,EACAC,GAIA,IAFA,IAAMC,EAA2C,CAAA,EAE1CF,EAAWG,QAAU,CAC1B,IAAMC,EAAQJ,EAAW,GACnBK,EAAOD,EAAME,MAMnB,GAJMD,KAAQH,IACZA,EAAaG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMK,OAGzDR,EAA0B,CAC5B,IAAQS,EAAUR,EAAaG,GAAvBK,MACFC,EAAWD,GAASA,EAAMN,EAAMK,MAEtCP,EAAaG,GAAQO,eACnBP,EACAJ,EACAC,EACAE,EAAMK,KACNE,EAAQ,GAAAE,OAAQF,EAAuBP,CAAAA,EAAMG,UAAWH,EAAMG,QAElE,CAEAP,EAAWc,OACb,CAEA,OAAOZ,CACT,uBAGE,SAACa,EAAQC,EAAeC,GACjBC,YADiBD,IAAAA,IAAAA,EAAkB,CAAE,GACrCC,SAAAA,EAAQC,EAAGC,GAAW,IAAA,OAAAC,QAAAC,gCACvBD,QAAAC,QACiBP,EAAOQ,SAASL,EAAQF,IAAcQ,KAAnDC,SAAAA,GAIN,OAFAL,EAAQM,2BAA6BC,EAAAA,uBAAuB,CAAE,EAAEP,GAEzD,CACLQ,OAAQ,GACRV,OAAQD,EAAgBY,IAAMX,EAASO,EACvC,4DATuBK,GAU1B,SAAQ1B,GACP,GAAIA,aAAiBwB,EAAMA,OAACG,mBAC1B,MAAO,CACLb,OAAQ,CAAA,EACRU,OAAQI,EAAYA,aAClBjC,EACEK,EAAMO,UACLS,EAAQM,2BACkB,QAAzBN,EAAQa,cAEZb,IAKN,MAAMhB,CACR,GACF,CAAC,MAAA8B,GAAA,OAAAb,QAAAc,OAAAD,EAAA,CAAA,CAAA"}
@@ -0,0 +1,2 @@
1
+ import{validateFieldsNatively as e,toNestErrors as r}from"@hookform/resolvers";import{errors as t}from"@vinejs/vine";import{appendErrors as o}from"react-hook-form";var n=function(e,r){for(var t={};e.length;){var n=e[0],i=n.field;if(i in t||(t[i]={message:n.message,type:n.rule}),r){var s=t[i].types,a=s&&s[n.rule];t[i]=o(i,r,t,n.rule,a?[].concat(a,[n.message]):n.message)}e.shift()}return t},i=function(o,i,s){return void 0===s&&(s={}),function(a,u,f){try{return Promise.resolve(function(r,t){try{var n=Promise.resolve(o.validate(a,i)).then(function(r){return f.shouldUseNativeValidation&&e({},f),{errors:{},values:s.raw?a:r}})}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}(0,function(e){if(e instanceof t.E_VALIDATION_ERROR)return{values:{},errors:r(n(e.messages,!f.shouldUseNativeValidation&&"all"===f.criteriaMode),f)};throw e}))}catch(e){return Promise.reject(e)}}};export{i as vineResolver};
2
+ //# sourceMappingURL=vine.module.js.map
@@ -0,0 +1,2 @@
1
+ import{validateFieldsNatively as e,toNestErrors as r}from"@hookform/resolvers";import{errors as s}from"@vinejs/vine";import{appendErrors as o}from"react-hook-form";const t=(e,r)=>{const s={};for(;e.length;){const t=e[0],a=t.field;if(a in s||(s[a]={message:t.message,type:t.rule}),r){const{types:e}=s[a],i=e&&e[t.rule];s[a]=o(a,r,s,t.rule,i?[...i,t.message]:t.message)}e.shift()}return s},a=(o,a,i={})=>async(n,l,m)=>{try{const r=await o.validate(n,a);return m.shouldUseNativeValidation&&e({},m),{errors:{},values:i.raw?n:r}}catch(e){if(e instanceof s.E_VALIDATION_ERROR)return{values:{},errors:r(t(e.messages,!m.shouldUseNativeValidation&&"all"===m.criteriaMode),m)};throw e}};export{a as vineResolver};
2
+ //# sourceMappingURL=vine.modern.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vine.modern.mjs","sources":["../src/vine.ts"],"sourcesContent":["import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport { SimpleErrorReporter, errors } from '@vinejs/vine';\nimport { FieldError, FieldErrors, appendErrors } from 'react-hook-form';\nimport type { Resolver } from './types';\n\nconst parseErrorSchema = (\n vineErrors: SimpleErrorReporter['errors'],\n validateAllFieldCriteria: boolean,\n) => {\n const schemaErrors: Record<string, FieldError> = {};\n\n for (; vineErrors.length; ) {\n const error = vineErrors[0];\n const path = error.field;\n\n if (!(path in schemaErrors)) {\n schemaErrors[path] = { message: error.message, type: error.rule };\n }\n\n if (validateAllFieldCriteria) {\n const { types } = schemaErrors[path];\n const messages = types && types[error.rule];\n\n schemaErrors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n schemaErrors,\n error.rule,\n messages ? [...(messages as string[]), error.message] : error.message,\n ) as FieldError;\n }\n\n vineErrors.shift();\n }\n\n return schemaErrors;\n};\n\nexport const vineResolver: Resolver =\n (schema, schemaOptions, resolverOptions = {}) =>\n async (values, _, options) => {\n try {\n const data = await schema.validate(values, schemaOptions);\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return {\n errors: {} as FieldErrors,\n values: resolverOptions.raw ? values : data,\n };\n } catch (error: any) {\n if (error instanceof errors.E_VALIDATION_ERROR) {\n return {\n values: {},\n errors: toNestErrors(\n parseErrorSchema(\n error.messages,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n throw error;\n }\n };\n"],"names":["parseErrorSchema","vineErrors","validateAllFieldCriteria","schemaErrors","length","error","path","field","message","type","rule","types","messages","appendErrors","shift","vineResolver","schema","schemaOptions","resolverOptions","async","values","_","options","data","validate","shouldUseNativeValidation","validateFieldsNatively","errors","raw","E_VALIDATION_ERROR","toNestErrors","criteriaMode"],"mappings":"oKAKA,MAAMA,EAAmBA,CACvBC,EACAC,KAEA,MAAMC,EAA2C,CAAE,EAEnD,KAAOF,EAAWG,QAAU,CAC1B,MAAMC,EAAQJ,EAAW,GACnBK,EAAOD,EAAME,MAMnB,GAJMD,KAAQH,IACZA,EAAaG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMK,OAGzDR,EAA0B,CAC5B,MAAMS,MAAEA,GAAUR,EAAaG,GACzBM,EAAWD,GAASA,EAAMN,EAAMK,MAEtCP,EAAaG,GAAQO,EACnBP,EACAJ,EACAC,EACAE,EAAMK,KACNE,EAAW,IAAKA,EAAuBP,EAAMG,SAAWH,EAAMG,QAElE,CAEAP,EAAWa,OACb,CAEA,OAAOX,GAGIY,EACXA,CAACC,EAAQC,EAAeC,EAAkB,CAAE,IAC5CC,MAAOC,EAAQC,EAAGC,KAChB,IACE,MAAMC,QAAaP,EAAOQ,SAASJ,EAAQH,GAI3C,OAFAK,EAAQG,2BAA6BC,EAAuB,CAAA,EAAIJ,GAEzD,CACLK,OAAQ,GACRP,OAAQF,EAAgBU,IAAMR,EAASG,EAE3C,CAAE,MAAOlB,GACP,GAAIA,aAAiBsB,EAAOE,mBAC1B,MAAO,CACLT,OAAQ,CAAA,EACRO,OAAQG,EACN9B,EACEK,EAAMO,UACLU,EAAQG,2BACkB,QAAzBH,EAAQS,cAEZT,IAKN,MAAMjB,CACR"}
@@ -0,0 +1,2 @@
1
+ import{validateFieldsNatively as e,toNestErrors as r}from"@hookform/resolvers";import{errors as t}from"@vinejs/vine";import{appendErrors as o}from"react-hook-form";var n=function(e,r){for(var t={};e.length;){var n=e[0],i=n.field;if(i in t||(t[i]={message:n.message,type:n.rule}),r){var s=t[i].types,a=s&&s[n.rule];t[i]=o(i,r,t,n.rule,a?[].concat(a,[n.message]):n.message)}e.shift()}return t},i=function(o,i,s){return void 0===s&&(s={}),function(a,u,f){try{return Promise.resolve(function(r,t){try{var n=Promise.resolve(o.validate(a,i)).then(function(r){return f.shouldUseNativeValidation&&e({},f),{errors:{},values:s.raw?a:r}})}catch(e){return t(e)}return n&&n.then?n.then(void 0,t):n}(0,function(e){if(e instanceof t.E_VALIDATION_ERROR)return{values:{},errors:r(n(e.messages,!f.shouldUseNativeValidation&&"all"===f.criteriaMode),f)};throw e}))}catch(e){return Promise.reject(e)}}};export{i as vineResolver};
2
+ //# sourceMappingURL=vine.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vine.module.js","sources":["../src/vine.ts"],"sourcesContent":["import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport { SimpleErrorReporter, errors } from '@vinejs/vine';\nimport { FieldError, FieldErrors, appendErrors } from 'react-hook-form';\nimport type { Resolver } from './types';\n\nconst parseErrorSchema = (\n vineErrors: SimpleErrorReporter['errors'],\n validateAllFieldCriteria: boolean,\n) => {\n const schemaErrors: Record<string, FieldError> = {};\n\n for (; vineErrors.length; ) {\n const error = vineErrors[0];\n const path = error.field;\n\n if (!(path in schemaErrors)) {\n schemaErrors[path] = { message: error.message, type: error.rule };\n }\n\n if (validateAllFieldCriteria) {\n const { types } = schemaErrors[path];\n const messages = types && types[error.rule];\n\n schemaErrors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n schemaErrors,\n error.rule,\n messages ? [...(messages as string[]), error.message] : error.message,\n ) as FieldError;\n }\n\n vineErrors.shift();\n }\n\n return schemaErrors;\n};\n\nexport const vineResolver: Resolver =\n (schema, schemaOptions, resolverOptions = {}) =>\n async (values, _, options) => {\n try {\n const data = await schema.validate(values, schemaOptions);\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return {\n errors: {} as FieldErrors,\n values: resolverOptions.raw ? values : data,\n };\n } catch (error: any) {\n if (error instanceof errors.E_VALIDATION_ERROR) {\n return {\n values: {},\n errors: toNestErrors(\n parseErrorSchema(\n error.messages,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n throw error;\n }\n };\n"],"names":["parseErrorSchema","vineErrors","validateAllFieldCriteria","schemaErrors","length","error","path","field","message","type","rule","types","messages","appendErrors","concat","shift","vineResolver","schema","schemaOptions","resolverOptions","values","_","options","Promise","resolve","validate","then","data","shouldUseNativeValidation","validateFieldsNatively","errors","raw","_catch","E_VALIDATION_ERROR","toNestErrors","criteriaMode","e","reject"],"mappings":"oKAKA,IAAMA,EAAmB,SACvBC,EACAC,GAIA,IAFA,IAAMC,EAA2C,CAAA,EAE1CF,EAAWG,QAAU,CAC1B,IAAMC,EAAQJ,EAAW,GACnBK,EAAOD,EAAME,MAMnB,GAJMD,KAAQH,IACZA,EAAaG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMK,OAGzDR,EAA0B,CAC5B,IAAQS,EAAUR,EAAaG,GAAvBK,MACFC,EAAWD,GAASA,EAAMN,EAAMK,MAEtCP,EAAaG,GAAQO,EACnBP,EACAJ,EACAC,EACAE,EAAMK,KACNE,EAAQ,GAAAE,OAAQF,EAAuBP,CAAAA,EAAMG,UAAWH,EAAMG,QAElE,CAEAP,EAAWc,OACb,CAEA,OAAOZ,CACT,EAEaa,EACX,SAACC,EAAQC,EAAeC,GACjBC,YADiBD,IAAAA,IAAAA,EAAkB,CAAE,GACrCC,SAAAA,EAAQC,EAAGC,GAAW,IAAA,OAAAC,QAAAC,gCACvBD,QAAAC,QACiBP,EAAOQ,SAASL,EAAQF,IAAcQ,KAAnDC,SAAAA,GAIN,OAFAL,EAAQM,2BAA6BC,EAAuB,CAAE,EAAEP,GAEzD,CACLQ,OAAQ,GACRV,OAAQD,EAAgBY,IAAMX,EAASO,EACvC,4DATuBK,GAU1B,SAAQ3B,GACP,GAAIA,aAAiByB,EAAOG,mBAC1B,MAAO,CACLb,OAAQ,CAAA,EACRU,OAAQI,EACNlC,EACEK,EAAMO,UACLU,EAAQM,2BACkB,QAAzBN,EAAQa,cAEZb,IAKN,MAAMjB,CACR,GACF,CAAC,MAAA+B,GAAA,OAAAb,QAAAc,OAAAD,EAAA,CAAA,CAAA"}
@@ -0,0 +1,2 @@
1
+ !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("@hookform/resolvers"),require("@vinejs/vine"),require("react-hook-form")):"function"==typeof define&&define.amd?define(["exports","@hookform/resolvers","@vinejs/vine","react-hook-form"],r):r((e||self).hookformResolversVine={},e.hookformResolvers,e.vine,e.ReactHookForm)}(this,function(e,r,o,t){var n=function(e,r){for(var o={};e.length;){var n=e[0],i=n.field;if(i in o||(o[i]={message:n.message,type:n.rule}),r){var s=o[i].types,a=s&&s[n.rule];o[i]=t.appendErrors(i,r,o,n.rule,a?[].concat(a,[n.message]):n.message)}e.shift()}return o};e.vineResolver=function(e,t,i){return void 0===i&&(i={}),function(s,a,f){try{return Promise.resolve(function(o,n){try{var a=Promise.resolve(e.validate(s,t)).then(function(e){return f.shouldUseNativeValidation&&r.validateFieldsNatively({},f),{errors:{},values:i.raw?s:e}})}catch(e){return n(e)}return a&&a.then?a.then(void 0,n):a}(0,function(e){if(e instanceof o.errors.E_VALIDATION_ERROR)return{values:{},errors:r.toNestErrors(n(e.messages,!f.shouldUseNativeValidation&&"all"===f.criteriaMode),f)};throw e}))}catch(e){return Promise.reject(e)}}}});
2
+ //# sourceMappingURL=vine.umd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vine.umd.js","sources":["../src/vine.ts"],"sourcesContent":["import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport { SimpleErrorReporter, errors } from '@vinejs/vine';\nimport { FieldError, FieldErrors, appendErrors } from 'react-hook-form';\nimport type { Resolver } from './types';\n\nconst parseErrorSchema = (\n vineErrors: SimpleErrorReporter['errors'],\n validateAllFieldCriteria: boolean,\n) => {\n const schemaErrors: Record<string, FieldError> = {};\n\n for (; vineErrors.length; ) {\n const error = vineErrors[0];\n const path = error.field;\n\n if (!(path in schemaErrors)) {\n schemaErrors[path] = { message: error.message, type: error.rule };\n }\n\n if (validateAllFieldCriteria) {\n const { types } = schemaErrors[path];\n const messages = types && types[error.rule];\n\n schemaErrors[path] = appendErrors(\n path,\n validateAllFieldCriteria,\n schemaErrors,\n error.rule,\n messages ? [...(messages as string[]), error.message] : error.message,\n ) as FieldError;\n }\n\n vineErrors.shift();\n }\n\n return schemaErrors;\n};\n\nexport const vineResolver: Resolver =\n (schema, schemaOptions, resolverOptions = {}) =>\n async (values, _, options) => {\n try {\n const data = await schema.validate(values, schemaOptions);\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return {\n errors: {} as FieldErrors,\n values: resolverOptions.raw ? values : data,\n };\n } catch (error: any) {\n if (error instanceof errors.E_VALIDATION_ERROR) {\n return {\n values: {},\n errors: toNestErrors(\n parseErrorSchema(\n error.messages,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n\n throw error;\n }\n };\n"],"names":["parseErrorSchema","vineErrors","validateAllFieldCriteria","schemaErrors","length","error","path","field","message","type","rule","types","messages","appendErrors","concat","shift","schema","schemaOptions","resolverOptions","values","_","options","Promise","resolve","validate","then","data","shouldUseNativeValidation","validateFieldsNatively","errors","raw","_catch","E_VALIDATION_ERROR","toNestErrors","criteriaMode","e","reject"],"mappings":"yaAKA,IAAMA,EAAmB,SACvBC,EACAC,GAIA,IAFA,IAAMC,EAA2C,CAAA,EAE1CF,EAAWG,QAAU,CAC1B,IAAMC,EAAQJ,EAAW,GACnBK,EAAOD,EAAME,MAMnB,GAJMD,KAAQH,IACZA,EAAaG,GAAQ,CAAEE,QAASH,EAAMG,QAASC,KAAMJ,EAAMK,OAGzDR,EAA0B,CAC5B,IAAQS,EAAUR,EAAaG,GAAvBK,MACFC,EAAWD,GAASA,EAAMN,EAAMK,MAEtCP,EAAaG,GAAQO,eACnBP,EACAJ,EACAC,EACAE,EAAMK,KACNE,EAAQ,GAAAE,OAAQF,EAAuBP,CAAAA,EAAMG,UAAWH,EAAMG,QAElE,CAEAP,EAAWc,OACb,CAEA,OAAOZ,CACT,iBAGE,SAACa,EAAQC,EAAeC,GACjBC,YADiBD,IAAAA,IAAAA,EAAkB,CAAE,GACrCC,SAAAA,EAAQC,EAAGC,GAAW,IAAA,OAAAC,QAAAC,gCACvBD,QAAAC,QACiBP,EAAOQ,SAASL,EAAQF,IAAcQ,KAAnDC,SAAAA,GAIN,OAFAL,EAAQM,2BAA6BC,EAAAA,uBAAuB,CAAE,EAAEP,GAEzD,CACLQ,OAAQ,GACRV,OAAQD,EAAgBY,IAAMX,EAASO,EACvC,4DATuBK,GAU1B,SAAQ1B,GACP,GAAIA,aAAiBwB,EAAMA,OAACG,mBAC1B,MAAO,CACLb,OAAQ,CAAA,EACRU,OAAQI,EAAYA,aAClBjC,EACEK,EAAMO,UACLS,EAAQM,2BACkB,QAAzBN,EAAQa,cAEZb,IAKN,MAAMhB,CACR,GACF,CAAC,MAAA8B,GAAA,OAAAb,QAAAc,OAAAD,EAAA,CAAA,CAAA"}
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "@hookform/resolvers/vine",
3
+ "amdName": "hookformResolversVine",
4
+ "version": "1.0.0",
5
+ "private": true,
6
+ "description": "React Hook Form validation resolver: vine",
7
+ "main": "dist/vine.js",
8
+ "module": "dist/vine.module.js",
9
+ "umd:main": "dist/vine.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
+ "@vinejs/vine": "^2.0.0"
17
+ }
18
+ }
@@ -0,0 +1,85 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import user from '@testing-library/user-event';
3
+ import vine from '@vinejs/vine';
4
+ import { Infer } from '@vinejs/vine/build/src/types';
5
+ import React from 'react';
6
+ import { useForm } from 'react-hook-form';
7
+ import { vineResolver } from '..';
8
+
9
+ const schema = vine.compile(
10
+ vine.object({
11
+ username: vine.string().minLength(1),
12
+ password: vine.string().minLength(1),
13
+ }),
14
+ );
15
+
16
+ type FormData = Infer<typeof schema> & { unusedProperty: string };
17
+
18
+ interface Props {
19
+ onSubmit: (data: FormData) => void;
20
+ }
21
+
22
+ function TestComponent({ onSubmit }: Props) {
23
+ const { register, handleSubmit } = useForm<FormData>({
24
+ resolver: vineResolver(schema),
25
+ shouldUseNativeValidation: true,
26
+ });
27
+
28
+ return (
29
+ <form onSubmit={handleSubmit(onSubmit)}>
30
+ <input {...register('username')} placeholder="username" />
31
+
32
+ <input {...register('password')} placeholder="password" />
33
+
34
+ <button type="submit">submit</button>
35
+ </form>
36
+ );
37
+ }
38
+
39
+ test("form's native validation with Zod", async () => {
40
+ const handleSubmit = vi.fn();
41
+ render(<TestComponent onSubmit={handleSubmit} />);
42
+
43
+ // username
44
+ let usernameField = screen.getByPlaceholderText(
45
+ /username/i,
46
+ ) as HTMLInputElement;
47
+ expect(usernameField.validity.valid).toBe(true);
48
+ expect(usernameField.validationMessage).toBe('');
49
+
50
+ // password
51
+ let passwordField = screen.getByPlaceholderText(
52
+ /password/i,
53
+ ) as HTMLInputElement;
54
+ expect(passwordField.validity.valid).toBe(true);
55
+ expect(passwordField.validationMessage).toBe('');
56
+
57
+ await user.click(screen.getByText(/submit/i));
58
+
59
+ // username
60
+ usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
61
+ expect(usernameField.validity.valid).toBe(false);
62
+ expect(usernameField.validationMessage).toBe(
63
+ 'The username field must have at least 1 characters',
64
+ );
65
+
66
+ // password
67
+ passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement;
68
+ expect(passwordField.validity.valid).toBe(false);
69
+ expect(passwordField.validationMessage).toBe(
70
+ 'The password field must have at least 1 characters',
71
+ );
72
+
73
+ await user.type(screen.getByPlaceholderText(/username/i), 'joe');
74
+ await user.type(screen.getByPlaceholderText(/password/i), 'password');
75
+
76
+ // username
77
+ usernameField = screen.getByPlaceholderText(/username/i) as HTMLInputElement;
78
+ expect(usernameField.validity.valid).toBe(true);
79
+ expect(usernameField.validationMessage).toBe('');
80
+
81
+ // password
82
+ passwordField = screen.getByPlaceholderText(/password/i) as HTMLInputElement;
83
+ expect(passwordField.validity.valid).toBe(true);
84
+ expect(passwordField.validationMessage).toBe('');
85
+ });
@@ -0,0 +1,59 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import user from '@testing-library/user-event';
3
+ import vine from '@vinejs/vine';
4
+ import { Infer } from '@vinejs/vine/build/src/types';
5
+ import React from 'react';
6
+ import { useForm } from 'react-hook-form';
7
+ import { vineResolver } from '..';
8
+
9
+ const schema = vine.compile(
10
+ vine.object({
11
+ username: vine.string().minLength(1),
12
+ password: vine.string().minLength(1),
13
+ }),
14
+ );
15
+
16
+ type FormData = Infer<typeof schema> & { unusedProperty: string };
17
+
18
+ interface Props {
19
+ onSubmit: (data: FormData) => void;
20
+ }
21
+
22
+ function TestComponent({ onSubmit }: Props) {
23
+ const {
24
+ register,
25
+ handleSubmit,
26
+ formState: { errors },
27
+ } = useForm<FormData>({
28
+ resolver: vineResolver(schema), // Useful to check TypeScript regressions
29
+ });
30
+
31
+ return (
32
+ <form onSubmit={handleSubmit(onSubmit)}>
33
+ <input {...register('username')} />
34
+ {errors.username && <span role="alert">{errors.username.message}</span>}
35
+
36
+ <input {...register('password')} />
37
+ {errors.password && <span role="alert">{errors.password.message}</span>}
38
+
39
+ <button type="submit">submit</button>
40
+ </form>
41
+ );
42
+ }
43
+
44
+ test("form's validation with Vine and TypeScript's integration", async () => {
45
+ const handleSubmit = vi.fn();
46
+ render(<TestComponent onSubmit={handleSubmit} />);
47
+
48
+ expect(screen.queryAllByRole('alert')).toHaveLength(0);
49
+
50
+ await user.click(screen.getByText(/submit/i));
51
+
52
+ expect(
53
+ screen.getByText(/The username field must have at least 1 characters/i),
54
+ ).toBeInTheDocument();
55
+ expect(
56
+ screen.getByText(/The password field must have at least 1 characters/i),
57
+ ).toBeInTheDocument();
58
+ expect(handleSubmit).not.toHaveBeenCalled();
59
+ });
@@ -0,0 +1,76 @@
1
+ import vine from '@vinejs/vine';
2
+ import { Infer } from '@vinejs/vine/build/src/types';
3
+ import { Field, InternalFieldName } from 'react-hook-form';
4
+
5
+ export const schema = vine.compile(
6
+ vine.object({
7
+ username: vine.string().regex(/^\w+$/).minLength(3).maxLength(30),
8
+ password: vine
9
+ .string()
10
+ .regex(new RegExp('.*[A-Z].*'))
11
+ .regex(new RegExp('.*[a-z].*'))
12
+ .regex(new RegExp('.*\\d.*'))
13
+ .regex(new RegExp('.*[`~<>?,./!@#$%^&*()\\-_+="\'|{}\\[\\];:\\\\].*'))
14
+ .minLength(8)
15
+ .confirmed({ confirmationField: 'repeatPassword' }),
16
+ repeatPassword: vine.string().sameAs('password'),
17
+ accessToken: vine.unionOfTypes([vine.string(), vine.number()]),
18
+ birthYear: vine.number().min(1900).max(2013),
19
+ email: vine.string().email().optional(),
20
+ tags: vine.array(vine.string()),
21
+ enabled: vine.boolean(),
22
+ like: vine.array(
23
+ vine.object({
24
+ id: vine.number(),
25
+ name: vine.string().fixedLength(4),
26
+ }),
27
+ ),
28
+ dateStr: vine
29
+ .string()
30
+ .transform((value: string) => new Date(value).toISOString()),
31
+ }),
32
+ );
33
+
34
+ export const validData: Infer<typeof schema> = {
35
+ username: 'Doe',
36
+ password: 'Password123_',
37
+ repeatPassword: 'Password123_',
38
+ birthYear: 2000,
39
+ email: 'john@doe.com',
40
+ tags: ['tag1', 'tag2'],
41
+ enabled: true,
42
+ accessToken: 'accessToken',
43
+ like: [
44
+ {
45
+ id: 1,
46
+ name: 'name',
47
+ },
48
+ ],
49
+ dateStr: '2020-01-01T00:00:00.000Z',
50
+ };
51
+
52
+ export const invalidData = {
53
+ password: '___',
54
+ email: '',
55
+ birthYear: 'birthYear',
56
+ like: [{ id: 'z' }],
57
+ };
58
+
59
+ export const fields: Record<InternalFieldName, Field['_f']> = {
60
+ username: {
61
+ ref: { name: 'username' },
62
+ name: 'username',
63
+ },
64
+ password: {
65
+ ref: { name: 'password' },
66
+ name: 'password',
67
+ },
68
+ email: {
69
+ ref: { name: 'email' },
70
+ name: 'email',
71
+ },
72
+ birthday: {
73
+ ref: { name: 'birthday' },
74
+ name: 'birthday',
75
+ },
76
+ };
@@ -0,0 +1,180 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`vineResolver > should return a single error from vineResolver when validation fails 1`] = `
4
+ {
5
+ "errors": {
6
+ "accessToken": {
7
+ "message": "Invalid value provided for accessToken field",
8
+ "ref": undefined,
9
+ "type": "unionOfTypes",
10
+ },
11
+ "birthYear": {
12
+ "message": "The birthYear field must be a number",
13
+ "ref": undefined,
14
+ "type": "number",
15
+ },
16
+ "dateStr": {
17
+ "message": "The dateStr field must be defined",
18
+ "ref": undefined,
19
+ "type": "required",
20
+ },
21
+ "email": {
22
+ "message": "The email field must be a valid email address",
23
+ "ref": {
24
+ "name": "email",
25
+ },
26
+ "type": "email",
27
+ },
28
+ "enabled": {
29
+ "message": "The enabled field must be defined",
30
+ "ref": undefined,
31
+ "type": "required",
32
+ },
33
+ "like": [
34
+ {
35
+ "id": {
36
+ "message": "The id field must be a number",
37
+ "ref": undefined,
38
+ "type": "number",
39
+ },
40
+ "name": {
41
+ "message": "The name field must be defined",
42
+ "ref": undefined,
43
+ "type": "required",
44
+ },
45
+ },
46
+ ],
47
+ "password": {
48
+ "message": "The password field format is invalid",
49
+ "ref": {
50
+ "name": "password",
51
+ },
52
+ "type": "regex",
53
+ },
54
+ "repeatPassword": {
55
+ "message": "The repeatPassword field must be defined",
56
+ "ref": undefined,
57
+ "type": "required",
58
+ },
59
+ "tags": {
60
+ "message": "The tags field must be defined",
61
+ "ref": undefined,
62
+ "type": "required",
63
+ },
64
+ "username": {
65
+ "message": "The username field must be defined",
66
+ "ref": {
67
+ "name": "username",
68
+ },
69
+ "type": "required",
70
+ },
71
+ },
72
+ "values": {},
73
+ }
74
+ `;
75
+
76
+ exports[`vineResolver > should return all the errors from vineResolver when validation fails with \`validateAllFieldCriteria\` set to true 1`] = `
77
+ {
78
+ "errors": {
79
+ "accessToken": {
80
+ "message": "Invalid value provided for accessToken field",
81
+ "ref": undefined,
82
+ "type": "unionOfTypes",
83
+ "types": {
84
+ "unionOfTypes": "Invalid value provided for accessToken field",
85
+ },
86
+ },
87
+ "birthYear": {
88
+ "message": "The birthYear field must be a number",
89
+ "ref": undefined,
90
+ "type": "number",
91
+ "types": {
92
+ "number": "The birthYear field must be a number",
93
+ },
94
+ },
95
+ "dateStr": {
96
+ "message": "The dateStr field must be defined",
97
+ "ref": undefined,
98
+ "type": "required",
99
+ "types": {
100
+ "required": "The dateStr field must be defined",
101
+ },
102
+ },
103
+ "email": {
104
+ "message": "The email field must be a valid email address",
105
+ "ref": {
106
+ "name": "email",
107
+ },
108
+ "type": "email",
109
+ "types": {
110
+ "email": "The email field must be a valid email address",
111
+ },
112
+ },
113
+ "enabled": {
114
+ "message": "The enabled field must be defined",
115
+ "ref": undefined,
116
+ "type": "required",
117
+ "types": {
118
+ "required": "The enabled field must be defined",
119
+ },
120
+ },
121
+ "like": [
122
+ {
123
+ "id": {
124
+ "message": "The id field must be a number",
125
+ "ref": undefined,
126
+ "type": "number",
127
+ "types": {
128
+ "number": "The id field must be a number",
129
+ },
130
+ },
131
+ "name": {
132
+ "message": "The name field must be defined",
133
+ "ref": undefined,
134
+ "type": "required",
135
+ "types": {
136
+ "required": "The name field must be defined",
137
+ },
138
+ },
139
+ },
140
+ ],
141
+ "password": {
142
+ "message": "The password field format is invalid",
143
+ "ref": {
144
+ "name": "password",
145
+ },
146
+ "type": "regex",
147
+ "types": {
148
+ "regex": "The password field format is invalid",
149
+ },
150
+ },
151
+ "repeatPassword": {
152
+ "message": "The repeatPassword field must be defined",
153
+ "ref": undefined,
154
+ "type": "required",
155
+ "types": {
156
+ "required": "The repeatPassword field must be defined",
157
+ },
158
+ },
159
+ "tags": {
160
+ "message": "The tags field must be defined",
161
+ "ref": undefined,
162
+ "type": "required",
163
+ "types": {
164
+ "required": "The tags field must be defined",
165
+ },
166
+ },
167
+ "username": {
168
+ "message": "The username field must be defined",
169
+ "ref": {
170
+ "name": "username",
171
+ },
172
+ "type": "required",
173
+ "types": {
174
+ "required": "The username field must be defined",
175
+ },
176
+ },
177
+ },
178
+ "values": {},
179
+ }
180
+ `;
@@ -0,0 +1,53 @@
1
+ import { vineResolver } from '..';
2
+ import { fields, invalidData, schema, validData } from './__fixtures__/data';
3
+
4
+ const shouldUseNativeValidation = false;
5
+
6
+ describe('vineResolver', () => {
7
+ it('should return values from vineResolver when validation pass', async () => {
8
+ const schemaSpy = vi.spyOn(schema, 'validate');
9
+
10
+ const result = await vineResolver(schema)(validData, undefined, {
11
+ fields,
12
+ shouldUseNativeValidation,
13
+ });
14
+
15
+ expect(schemaSpy).toHaveBeenCalledTimes(1);
16
+ expect(result).toEqual({ errors: {}, values: validData });
17
+ });
18
+
19
+ it('should return a single error from vineResolver when validation fails', async () => {
20
+ const result = await vineResolver(schema)(invalidData, undefined, {
21
+ fields,
22
+ shouldUseNativeValidation,
23
+ });
24
+
25
+ expect(result).toMatchSnapshot();
26
+ });
27
+
28
+ it('should return all the errors from vineResolver when validation fails with `validateAllFieldCriteria` set to true', async () => {
29
+ const result = await vineResolver(schema)(invalidData, undefined, {
30
+ fields,
31
+ criteriaMode: 'all',
32
+ shouldUseNativeValidation,
33
+ });
34
+
35
+ expect(result).toMatchSnapshot();
36
+ });
37
+
38
+ it('should return values from vineResolver when validation pass & raw=true', async () => {
39
+ const schemaSpy = vi.spyOn(schema, 'validate');
40
+
41
+ const result = await vineResolver(schema, undefined, { raw: true })(
42
+ validData,
43
+ undefined,
44
+ {
45
+ fields,
46
+ shouldUseNativeValidation,
47
+ },
48
+ );
49
+
50
+ expect(schemaSpy).toHaveBeenCalledTimes(1);
51
+ expect(result).toEqual({ errors: {}, values: validData });
52
+ });
53
+ });
@@ -0,0 +1,2 @@
1
+ export * from './vine';
2
+ export * from './types';
@@ -0,0 +1,13 @@
1
+ import { VineValidator } from '@vinejs/vine';
2
+ import { ValidationOptions } from '@vinejs/vine/build/src/types';
3
+ import { FieldValues, ResolverOptions, ResolverResult } from 'react-hook-form';
4
+
5
+ export type Resolver = <T extends VineValidator<any, any>>(
6
+ schema: T,
7
+ schemaOptions?: ValidationOptions<any>,
8
+ resolverOptions?: { raw?: boolean },
9
+ ) => <TFieldValues extends FieldValues, TContext>(
10
+ values: TFieldValues,
11
+ context: TContext | undefined,
12
+ options: ResolverOptions<TFieldValues>,
13
+ ) => Promise<ResolverResult<TFieldValues>>;
@@ -0,0 +1,68 @@
1
+ import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';
2
+ import { SimpleErrorReporter, errors } from '@vinejs/vine';
3
+ import { FieldError, FieldErrors, appendErrors } from 'react-hook-form';
4
+ import type { Resolver } from './types';
5
+
6
+ const parseErrorSchema = (
7
+ vineErrors: SimpleErrorReporter['errors'],
8
+ validateAllFieldCriteria: boolean,
9
+ ) => {
10
+ const schemaErrors: Record<string, FieldError> = {};
11
+
12
+ for (; vineErrors.length; ) {
13
+ const error = vineErrors[0];
14
+ const path = error.field;
15
+
16
+ if (!(path in schemaErrors)) {
17
+ schemaErrors[path] = { message: error.message, type: error.rule };
18
+ }
19
+
20
+ if (validateAllFieldCriteria) {
21
+ const { types } = schemaErrors[path];
22
+ const messages = types && types[error.rule];
23
+
24
+ schemaErrors[path] = appendErrors(
25
+ path,
26
+ validateAllFieldCriteria,
27
+ schemaErrors,
28
+ error.rule,
29
+ messages ? [...(messages as string[]), error.message] : error.message,
30
+ ) as FieldError;
31
+ }
32
+
33
+ vineErrors.shift();
34
+ }
35
+
36
+ return schemaErrors;
37
+ };
38
+
39
+ export const vineResolver: Resolver =
40
+ (schema, schemaOptions, resolverOptions = {}) =>
41
+ async (values, _, options) => {
42
+ try {
43
+ const data = await schema.validate(values, schemaOptions);
44
+
45
+ options.shouldUseNativeValidation && validateFieldsNatively({}, options);
46
+
47
+ return {
48
+ errors: {} as FieldErrors,
49
+ values: resolverOptions.raw ? values : data,
50
+ };
51
+ } catch (error: any) {
52
+ if (error instanceof errors.E_VALIDATION_ERROR) {
53
+ return {
54
+ values: {},
55
+ errors: toNestErrors(
56
+ parseErrorSchema(
57
+ error.messages,
58
+ !options.shouldUseNativeValidation &&
59
+ options.criteriaMode === 'all',
60
+ ),
61
+ options,
62
+ ),
63
+ };
64
+ }
65
+
66
+ throw error;
67
+ }
68
+ };
package/yup/dist/yup.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import * as Yup from 'yup';
2
1
  import { FieldValues, Resolver } from 'react-hook-form';
2
+ import * as Yup from 'yup';
3
3
  export declare function yupResolver<TFieldValues extends FieldValues>(schema: Yup.ObjectSchema<TFieldValues> | ReturnType<typeof Yup.lazy<Yup.ObjectSchema<TFieldValues>>>, schemaOptions?: Parameters<(typeof schema)['validate']>[1], resolverOptions?: {
4
4
  /**
5
5
  * @default async
@@ -1 +1 @@
1
- {"version":3,"file":"yup.js","sources":["../src/yup.ts"],"sourcesContent":["import * as Yup from 'yup';\nimport { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport {\n appendErrors,\n FieldError,\n FieldValues,\n Resolver,\n} from 'react-hook-form';\n\n/**\n * Why `path!` ? because it could be `undefined` in some case\n * https://github.com/jquense/yup#validationerrorerrors-string--arraystring-value-any-path-string\n */\nconst parseErrorSchema = (\n error: Yup.ValidationError,\n validateAllFieldCriteria: boolean,\n) => {\n return (error.inner || []).reduce<Record<string, FieldError>>(\n (previous, error) => {\n if (!previous[error.path!]) {\n previous[error.path!] = { message: error.message, type: error.type! };\n }\n\n if (validateAllFieldCriteria) {\n const types = previous[error.path!].types;\n const messages = types && types[error.type!];\n\n previous[error.path!] = appendErrors(\n error.path!,\n validateAllFieldCriteria,\n previous,\n error.type!,\n messages\n ? ([] as string[]).concat(messages as string[], error.message)\n : error.message,\n ) as FieldError;\n }\n\n return previous;\n },\n {},\n );\n};\n\nexport function yupResolver<TFieldValues extends FieldValues>(\n schema:\n | Yup.ObjectSchema<TFieldValues>\n | ReturnType<typeof Yup.lazy<Yup.ObjectSchema<TFieldValues>>>,\n schemaOptions: Parameters<(typeof schema)['validate']>[1] = {},\n resolverOptions: {\n /**\n * @default async\n */\n mode?: 'async' | 'sync';\n /**\n * Return the raw input values rather than the parsed values.\n * @default false\n */\n raw?: boolean;\n } = {},\n): Resolver<Yup.InferType<typeof schema>> {\n return async (values, context, options) => {\n try {\n if (schemaOptions.context && process.env.NODE_ENV === 'development') {\n // eslint-disable-next-line no-console\n console.warn(\n \"You should not used the yup options context. Please, use the 'useForm' context object instead\",\n );\n }\n\n const result = await schema[\n resolverOptions.mode === 'sync' ? 'validateSync' : 'validate'\n ](\n values,\n Object.assign({ abortEarly: false }, schemaOptions, { context }),\n );\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return {\n values: resolverOptions.raw ? values : result,\n errors: {},\n };\n } catch (e: any) {\n if (!e.inner) {\n throw e;\n }\n\n return {\n values: {},\n errors: toNestErrors(\n parseErrorSchema(\n e,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n };\n}\n"],"names":["schema","schemaOptions","resolverOptions","values","context","options","Promise","resolve","process","env","NODE_ENV","console","warn","mode","Object","assign","abortEarly","then","result","shouldUseNativeValidation","validateFieldsNatively","raw","errors","_catch","e","inner","toNestErrors","error","validateAllFieldCriteria","criteriaMode","reduce","previous","path","message","type","types","messages","appendErrors","concat","reject"],"mappings":"sFA4CgB,SACdA,EAGAC,EACAC,GAYA,YAbAD,IAAAA,IAAAA,EAA4D,CAAE,QAC9DC,IAAAA,IAAAA,EAUI,IAEUC,SAAAA,EAAQC,EAASC,GAAW,IAAA,OAAAC,QAAAC,iCAElCN,EAAcG,SAAoC,gBAAzBI,QAAQC,IAAIC,UAEvCC,QAAQC,KACN,iGAEHN,QAAAC,QAEoBP,EACM,SAAzBE,EAAgBW,KAAkB,eAAiB,YAEnDV,EACAW,OAAOC,OAAO,CAAEC,YAAY,GAASf,EAAe,CAAEG,QAAAA,MACvDa,cALKC,GASN,OAFAb,EAAQc,2BAA6BC,EAAAA,uBAAuB,CAAE,EAAEf,GAEzD,CACLF,OAAQD,EAAgBmB,IAAMlB,EAASe,EACvCI,OAAQ,CAAA,EACR,6DArBoCC,CAAA,WAsB/BC,GACP,IAAKA,EAAEC,MACL,MAAMD,EAGR,MAAO,CACLrB,OAAQ,CAAE,EACVmB,OAAQI,EAAAA,cA5EdC,EA8EUH,EA7EVI,GA8EWvB,EAAQc,2BACkB,QAAzBd,EAAQwB,cA7EZF,EAAMF,OAAS,IAAIK,OACzB,SAACC,EAAUJ,GAKT,GAJKI,EAASJ,EAAMK,QAClBD,EAASJ,EAAMK,MAAS,CAAEC,QAASN,EAAMM,QAASC,KAAMP,EAAMO,OAG5DN,EAA0B,CAC5B,IAAMO,EAAQJ,EAASJ,EAAMK,MAAOG,MAC9BC,EAAWD,GAASA,EAAMR,EAAMO,MAEtCH,EAASJ,EAAMK,MAASK,EAAAA,aACtBV,EAAMK,KACNJ,EACAG,EACAJ,EAAMO,KACNE,EACK,GAAgBE,OAAOF,EAAsBT,EAAMM,SACpDN,EAAMM,QAEb,CAED,OAAOF,CACT,EACA,KAwDM1B,IAnFe,IACvBsB,EACAC,CAoFG,GACH,CAAC,MAAAJ,GAAA,OAAAlB,QAAAiC,OAAAf,EACH,CAAA,CAAA"}
1
+ {"version":3,"file":"yup.js","sources":["../src/yup.ts"],"sourcesContent":["import { toNestErrors, validateFieldsNatively } from '@hookform/resolvers';\nimport {\n FieldError,\n FieldValues,\n Resolver,\n appendErrors,\n} from 'react-hook-form';\nimport * as Yup from 'yup';\n\n/**\n * Why `path!` ? because it could be `undefined` in some case\n * https://github.com/jquense/yup#validationerrorerrors-string--arraystring-value-any-path-string\n */\nconst parseErrorSchema = (\n error: Yup.ValidationError,\n validateAllFieldCriteria: boolean,\n) => {\n return (error.inner || []).reduce<Record<string, FieldError>>(\n (previous, error) => {\n if (!previous[error.path!]) {\n previous[error.path!] = { message: error.message, type: error.type! };\n }\n\n if (validateAllFieldCriteria) {\n const types = previous[error.path!].types;\n const messages = types && types[error.type!];\n\n previous[error.path!] = appendErrors(\n error.path!,\n validateAllFieldCriteria,\n previous,\n error.type!,\n messages\n ? ([] as string[]).concat(messages as string[], error.message)\n : error.message,\n ) as FieldError;\n }\n\n return previous;\n },\n {},\n );\n};\n\nexport function yupResolver<TFieldValues extends FieldValues>(\n schema:\n | Yup.ObjectSchema<TFieldValues>\n | ReturnType<typeof Yup.lazy<Yup.ObjectSchema<TFieldValues>>>,\n schemaOptions: Parameters<(typeof schema)['validate']>[1] = {},\n resolverOptions: {\n /**\n * @default async\n */\n mode?: 'async' | 'sync';\n /**\n * Return the raw input values rather than the parsed values.\n * @default false\n */\n raw?: boolean;\n } = {},\n): Resolver<Yup.InferType<typeof schema>> {\n return async (values, context, options) => {\n try {\n if (schemaOptions.context && process.env.NODE_ENV === 'development') {\n // eslint-disable-next-line no-console\n console.warn(\n \"You should not used the yup options context. Please, use the 'useForm' context object instead\",\n );\n }\n\n const result = await schema[\n resolverOptions.mode === 'sync' ? 'validateSync' : 'validate'\n ](\n values,\n Object.assign({ abortEarly: false }, schemaOptions, { context }),\n );\n\n options.shouldUseNativeValidation && validateFieldsNatively({}, options);\n\n return {\n values: resolverOptions.raw ? values : result,\n errors: {},\n };\n } catch (e: any) {\n if (!e.inner) {\n throw e;\n }\n\n return {\n values: {},\n errors: toNestErrors(\n parseErrorSchema(\n e,\n !options.shouldUseNativeValidation &&\n options.criteriaMode === 'all',\n ),\n options,\n ),\n };\n }\n };\n}\n"],"names":["schema","schemaOptions","resolverOptions","values","context","options","Promise","resolve","process","env","NODE_ENV","console","warn","mode","Object","assign","abortEarly","then","result","shouldUseNativeValidation","validateFieldsNatively","raw","errors","_catch","e","inner","toNestErrors","error","validateAllFieldCriteria","criteriaMode","reduce","previous","path","message","type","types","messages","appendErrors","concat","reject"],"mappings":"sFA4CgB,SACdA,EAGAC,EACAC,GAYA,YAbAD,IAAAA,IAAAA,EAA4D,CAAE,QAC9DC,IAAAA,IAAAA,EAUI,IAEUC,SAAAA,EAAQC,EAASC,GAAW,IAAA,OAAAC,QAAAC,iCAElCN,EAAcG,SAAoC,gBAAzBI,QAAQC,IAAIC,UAEvCC,QAAQC,KACN,iGAEHN,QAAAC,QAEoBP,EACM,SAAzBE,EAAgBW,KAAkB,eAAiB,YAEnDV,EACAW,OAAOC,OAAO,CAAEC,YAAY,GAASf,EAAe,CAAEG,QAAAA,MACvDa,cALKC,GASN,OAFAb,EAAQc,2BAA6BC,EAAAA,uBAAuB,CAAE,EAAEf,GAEzD,CACLF,OAAQD,EAAgBmB,IAAMlB,EAASe,EACvCI,OAAQ,CAAA,EACR,6DArBoCC,CAAA,WAsB/BC,GACP,IAAKA,EAAEC,MACL,MAAMD,EAGR,MAAO,CACLrB,OAAQ,CAAE,EACVmB,OAAQI,EAAAA,cA5EdC,EA8EUH,EA7EVI,GA8EWvB,EAAQc,2BACkB,QAAzBd,EAAQwB,cA7EZF,EAAMF,OAAS,IAAIK,OACzB,SAACC,EAAUJ,GAKT,GAJKI,EAASJ,EAAMK,QAClBD,EAASJ,EAAMK,MAAS,CAAEC,QAASN,EAAMM,QAASC,KAAMP,EAAMO,OAG5DN,EAA0B,CAC5B,IAAMO,EAAQJ,EAASJ,EAAMK,MAAOG,MAC9BC,EAAWD,GAASA,EAAMR,EAAMO,MAEtCH,EAASJ,EAAMK,MAASK,EAAAA,aACtBV,EAAMK,KACNJ,EACAG,EACAJ,EAAMO,KACNE,EACK,GAAgBE,OAAOF,EAAsBT,EAAMM,SACpDN,EAAMM,QAEd,CAEA,OAAOF,CACT,EACA,KAwDM1B,IAnFe,IACvBsB,EACAC,CAoFE,GACF,CAAC,MAAAJ,GAAA,OAAAlB,QAAAiC,OAAAf,EACH,CAAA,CAAA"}