zod 4.5.4 → 4.6.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 (359) hide show
  1. package/compile.cjs +19 -0
  2. package/index.cjs +19 -0
  3. package/locales/index.cjs +19 -0
  4. package/mini/index.cjs +19 -0
  5. package/package.json +8 -7
  6. package/src/v3/helpers/errorUtil.ts +1 -1
  7. package/src/v4/classic/checks.ts +0 -1
  8. package/src/v4/classic/external.ts +2 -0
  9. package/src/v4/classic/from-json-schema.ts +248 -25
  10. package/src/v4/classic/schemas.ts +255 -164
  11. package/src/v4/classic/tests/assignability.test.ts +59 -9
  12. package/src/v4/classic/tests/bigint.test.ts +6 -0
  13. package/src/v4/classic/tests/continuability.test.ts +2 -2
  14. package/src/v4/classic/tests/cyclic-data.test.ts +274 -0
  15. package/src/v4/classic/tests/discriminated-unions.test.ts +112 -6
  16. package/src/v4/classic/tests/enum.test.ts +9 -0
  17. package/src/v4/classic/tests/error.test.ts +130 -1
  18. package/src/v4/classic/tests/firstparty.test.ts +4 -0
  19. package/src/v4/classic/tests/from-json-schema.test.ts +157 -0
  20. package/src/v4/classic/tests/iban.test.ts +81 -0
  21. package/src/v4/classic/tests/instance-footprint.test.ts +18 -2
  22. package/src/v4/classic/tests/instanceof.test.ts +27 -7
  23. package/src/v4/classic/tests/issue-schema.test.ts +88 -56
  24. package/src/v4/classic/tests/object.test.ts +56 -0
  25. package/src/v4/classic/tests/optin-ladder.test.ts +3 -2
  26. package/src/v4/classic/tests/properties.test.ts +225 -0
  27. package/src/v4/classic/tests/recursive-types.test.ts +46 -1
  28. package/src/v4/classic/tests/standard-schema.test.ts +19 -0
  29. package/src/v4/classic/tests/string.test.ts +25 -0
  30. package/src/v4/classic/tests/template-literal.test.ts +33 -1
  31. package/src/v4/classic/tests/to-json-schema.test.ts +147 -3
  32. package/src/v4/classic/tests/validate.test.ts +569 -0
  33. package/src/v4/core/api.ts +30 -6
  34. package/src/v4/core/checks.ts +1 -101
  35. package/src/v4/core/compile.ts +194 -82
  36. package/src/v4/core/doc.ts +6 -2
  37. package/src/v4/core/errors.ts +3 -6
  38. package/src/v4/core/json-schema-generator.ts +2 -2
  39. package/src/v4/core/json-schema-processors.ts +226 -68
  40. package/src/v4/core/memoizer.ts +78 -28
  41. package/src/v4/core/parse.ts +37 -16
  42. package/src/v4/core/regexes.ts +10 -4
  43. package/src/v4/core/schemas.ts +350 -113
  44. package/src/v4/core/tests/cached.test.ts +54 -0
  45. package/src/v4/core/tests/compile-generative.test.ts +445 -0
  46. package/src/v4/core/tests/compile.test.ts +222 -2
  47. package/src/v4/core/tests/email-regex.test.ts +140 -0
  48. package/src/v4/core/tests/locales/tg.test.ts +85 -0
  49. package/src/v4/core/tests/polyfill-collision.test.ts +46 -0
  50. package/src/v4/core/to-json-schema.ts +10 -8
  51. package/src/v4/core/util.ts +222 -147
  52. package/src/v4/core/versions.ts +2 -2
  53. package/src/v4/core/visit.ts +11 -0
  54. package/src/v4/locales/ar.ts +1 -0
  55. package/src/v4/locales/az.ts +1 -0
  56. package/src/v4/locales/be.ts +1 -0
  57. package/src/v4/locales/bg.ts +1 -0
  58. package/src/v4/locales/bn.ts +1 -0
  59. package/src/v4/locales/ca.ts +1 -0
  60. package/src/v4/locales/ckb.ts +1 -0
  61. package/src/v4/locales/cs.ts +1 -0
  62. package/src/v4/locales/da.ts +1 -0
  63. package/src/v4/locales/de.ts +1 -0
  64. package/src/v4/locales/el.ts +1 -0
  65. package/src/v4/locales/en.ts +1 -0
  66. package/src/v4/locales/eo.ts +1 -0
  67. package/src/v4/locales/es.ts +1 -0
  68. package/src/v4/locales/fa.ts +1 -0
  69. package/src/v4/locales/fi.ts +1 -0
  70. package/src/v4/locales/fr-CA.ts +1 -0
  71. package/src/v4/locales/fr.ts +1 -0
  72. package/src/v4/locales/gu.ts +1 -0
  73. package/src/v4/locales/he.ts +1 -0
  74. package/src/v4/locales/hi.ts +1 -0
  75. package/src/v4/locales/hr.ts +1 -0
  76. package/src/v4/locales/hu.ts +1 -0
  77. package/src/v4/locales/hy.ts +1 -0
  78. package/src/v4/locales/id.ts +1 -0
  79. package/src/v4/locales/index.ts +1 -0
  80. package/src/v4/locales/is.ts +1 -0
  81. package/src/v4/locales/it.ts +1 -0
  82. package/src/v4/locales/ja.ts +1 -0
  83. package/src/v4/locales/ka.ts +1 -0
  84. package/src/v4/locales/km.ts +1 -0
  85. package/src/v4/locales/kn.ts +1 -0
  86. package/src/v4/locales/ko.ts +1 -0
  87. package/src/v4/locales/lt.ts +1 -0
  88. package/src/v4/locales/mk.ts +1 -0
  89. package/src/v4/locales/ms.ts +1 -0
  90. package/src/v4/locales/ne.ts +1 -0
  91. package/src/v4/locales/nl.ts +1 -0
  92. package/src/v4/locales/nn.ts +1 -0
  93. package/src/v4/locales/no.ts +1 -0
  94. package/src/v4/locales/ota.ts +1 -0
  95. package/src/v4/locales/pl.ts +1 -0
  96. package/src/v4/locales/ps.ts +1 -0
  97. package/src/v4/locales/pt-BR.ts +1 -0
  98. package/src/v4/locales/pt.ts +1 -0
  99. package/src/v4/locales/ro.ts +1 -0
  100. package/src/v4/locales/ru.ts +1 -0
  101. package/src/v4/locales/sk.ts +1 -0
  102. package/src/v4/locales/sl.ts +1 -0
  103. package/src/v4/locales/sv.ts +1 -0
  104. package/src/v4/locales/ta.ts +1 -0
  105. package/src/v4/locales/tg.ts +134 -0
  106. package/src/v4/locales/th.ts +1 -0
  107. package/src/v4/locales/tk.ts +1 -0
  108. package/src/v4/locales/tr.ts +1 -0
  109. package/src/v4/locales/uk.ts +1 -0
  110. package/src/v4/locales/ur.ts +1 -0
  111. package/src/v4/locales/uz.ts +1 -0
  112. package/src/v4/locales/vi.ts +1 -0
  113. package/src/v4/locales/yo.ts +1 -0
  114. package/src/v4/locales/zh-CN.ts +1 -0
  115. package/src/v4/locales/zh-TW.ts +1 -0
  116. package/src/v4/mini/checks.ts +0 -1
  117. package/src/v4/mini/external.ts +2 -0
  118. package/src/v4/mini/schemas.ts +38 -2
  119. package/src/v4/mini/tests/checks.test.ts +1 -1
  120. package/src/v4/mini/tests/computed.test.ts +11 -17
  121. package/src/v4/mini/tests/index.test.ts +8 -0
  122. package/src/v4/mini/tests/recursive-types.test.ts +16 -0
  123. package/src/v4/mini/tests/string.test.ts +16 -0
  124. package/v3/ZodError.cjs +19 -0
  125. package/v3/errors.cjs +19 -0
  126. package/v3/external.cjs +19 -0
  127. package/v3/helpers/enumUtil.cjs +19 -0
  128. package/v3/helpers/errorUtil.cjs +20 -1
  129. package/v3/helpers/errorUtil.js +1 -1
  130. package/v3/helpers/parseUtil.cjs +19 -0
  131. package/v3/helpers/partialUtil.cjs +19 -0
  132. package/v3/helpers/typeAliases.cjs +19 -0
  133. package/v3/helpers/util.cjs +19 -0
  134. package/v3/index.cjs +19 -0
  135. package/v3/standard-schema.cjs +19 -0
  136. package/v3/types.cjs +19 -0
  137. package/v4/classic/checks.cjs +20 -2
  138. package/v4/classic/checks.d.cts +1 -1
  139. package/v4/classic/checks.d.ts +1 -1
  140. package/v4/classic/checks.js +1 -1
  141. package/v4/classic/coerce.cjs +19 -0
  142. package/v4/classic/compat.cjs +19 -0
  143. package/v4/classic/deep-partial.cjs +19 -0
  144. package/v4/classic/errors.cjs +19 -0
  145. package/v4/classic/external.cjs +22 -1
  146. package/v4/classic/external.d.cts +1 -1
  147. package/v4/classic/external.d.ts +1 -1
  148. package/v4/classic/external.js +1 -1
  149. package/v4/classic/from-json-schema.cjs +264 -24
  150. package/v4/classic/from-json-schema.js +245 -24
  151. package/v4/classic/in-out.cjs +19 -0
  152. package/v4/classic/index.cjs +19 -0
  153. package/v4/classic/iso.cjs +19 -0
  154. package/v4/classic/parse.cjs +19 -0
  155. package/v4/classic/schemas.cjs +100 -31
  156. package/v4/classic/schemas.d.cts +17 -1
  157. package/v4/classic/schemas.d.ts +17 -1
  158. package/v4/classic/schemas.js +77 -29
  159. package/v4/core/api.cjs +37 -2
  160. package/v4/core/api.d.cts +6 -4
  161. package/v4/core/api.d.ts +6 -4
  162. package/v4/core/api.js +17 -2
  163. package/v4/core/checks.cjs +19 -96
  164. package/v4/core/checks.d.cts +1 -1
  165. package/v4/core/checks.d.ts +1 -1
  166. package/v4/core/checks.js +0 -96
  167. package/v4/core/compile.cjs +165 -66
  168. package/v4/core/compile.d.cts +18 -4
  169. package/v4/core/compile.d.ts +18 -4
  170. package/v4/core/compile.js +146 -67
  171. package/v4/core/core.cjs +19 -0
  172. package/v4/core/doc.cjs +26 -2
  173. package/v4/core/doc.js +7 -2
  174. package/v4/core/errors.cjs +21 -5
  175. package/v4/core/errors.js +2 -5
  176. package/v4/core/index.cjs +19 -0
  177. package/v4/core/json-schema-generator.cjs +20 -1
  178. package/v4/core/json-schema-generator.js +2 -2
  179. package/v4/core/json-schema-processors.cjs +215 -63
  180. package/v4/core/json-schema-processors.d.cts +17 -0
  181. package/v4/core/json-schema-processors.d.ts +17 -0
  182. package/v4/core/json-schema-processors.js +195 -64
  183. package/v4/core/json-schema.cjs +19 -0
  184. package/v4/core/memoizer.cjs +114 -23
  185. package/v4/core/memoizer.js +72 -23
  186. package/v4/core/parse.cjs +56 -16
  187. package/v4/core/parse.js +37 -16
  188. package/v4/core/regexes.cjs +29 -6
  189. package/v4/core/regexes.d.cts +2 -0
  190. package/v4/core/regexes.d.ts +2 -0
  191. package/v4/core/regexes.js +8 -4
  192. package/v4/core/registries.cjs +19 -0
  193. package/v4/core/schemas.cjs +322 -95
  194. package/v4/core/schemas.d.cts +42 -7
  195. package/v4/core/schemas.d.ts +42 -7
  196. package/v4/core/schemas.js +301 -94
  197. package/v4/core/standard-schema.cjs +19 -0
  198. package/v4/core/to-json-schema.cjs +29 -7
  199. package/v4/core/to-json-schema.d.cts +7 -3
  200. package/v4/core/to-json-schema.d.ts +7 -3
  201. package/v4/core/to-json-schema.js +8 -7
  202. package/v4/core/util.cjs +181 -143
  203. package/v4/core/util.d.cts +25 -4
  204. package/v4/core/util.d.ts +25 -4
  205. package/v4/core/util.js +160 -143
  206. package/v4/core/versions.cjs +21 -2
  207. package/v4/core/versions.d.cts +1 -1
  208. package/v4/core/versions.d.ts +1 -1
  209. package/v4/core/versions.js +2 -2
  210. package/v4/core/visit.cjs +31 -0
  211. package/v4/core/visit.js +12 -0
  212. package/v4/index.cjs +19 -0
  213. package/v4/locales/ar.cjs +1 -0
  214. package/v4/locales/ar.js +1 -0
  215. package/v4/locales/az.cjs +1 -0
  216. package/v4/locales/az.js +1 -0
  217. package/v4/locales/be.cjs +1 -0
  218. package/v4/locales/be.js +1 -0
  219. package/v4/locales/bg.cjs +1 -0
  220. package/v4/locales/bg.js +1 -0
  221. package/v4/locales/bn.cjs +1 -0
  222. package/v4/locales/bn.js +1 -0
  223. package/v4/locales/ca.cjs +1 -0
  224. package/v4/locales/ca.js +1 -0
  225. package/v4/locales/ckb.cjs +1 -0
  226. package/v4/locales/ckb.js +1 -0
  227. package/v4/locales/cs.cjs +1 -0
  228. package/v4/locales/cs.js +1 -0
  229. package/v4/locales/da.cjs +1 -0
  230. package/v4/locales/da.js +1 -0
  231. package/v4/locales/de.cjs +1 -0
  232. package/v4/locales/de.js +1 -0
  233. package/v4/locales/el.cjs +1 -0
  234. package/v4/locales/el.js +1 -0
  235. package/v4/locales/en.cjs +1 -0
  236. package/v4/locales/en.js +1 -0
  237. package/v4/locales/eo.cjs +1 -0
  238. package/v4/locales/eo.js +1 -0
  239. package/v4/locales/es.cjs +1 -0
  240. package/v4/locales/es.js +1 -0
  241. package/v4/locales/fa.cjs +1 -0
  242. package/v4/locales/fa.js +1 -0
  243. package/v4/locales/fi.cjs +1 -0
  244. package/v4/locales/fi.js +1 -0
  245. package/v4/locales/fr-CA.cjs +1 -0
  246. package/v4/locales/fr-CA.js +1 -0
  247. package/v4/locales/fr.cjs +1 -0
  248. package/v4/locales/fr.js +1 -0
  249. package/v4/locales/gu.cjs +1 -0
  250. package/v4/locales/gu.js +1 -0
  251. package/v4/locales/he.cjs +1 -0
  252. package/v4/locales/he.js +1 -0
  253. package/v4/locales/hi.cjs +1 -0
  254. package/v4/locales/hi.js +1 -0
  255. package/v4/locales/hr.cjs +1 -0
  256. package/v4/locales/hr.js +1 -0
  257. package/v4/locales/hu.cjs +1 -0
  258. package/v4/locales/hu.js +1 -0
  259. package/v4/locales/hy.cjs +1 -0
  260. package/v4/locales/hy.js +1 -0
  261. package/v4/locales/id.cjs +1 -0
  262. package/v4/locales/id.js +1 -0
  263. package/v4/locales/index.cjs +22 -1
  264. package/v4/locales/index.d.cts +1 -0
  265. package/v4/locales/index.d.ts +1 -0
  266. package/v4/locales/index.js +1 -0
  267. package/v4/locales/is.cjs +1 -0
  268. package/v4/locales/is.js +1 -0
  269. package/v4/locales/it.cjs +1 -0
  270. package/v4/locales/it.js +1 -0
  271. package/v4/locales/ja.cjs +1 -0
  272. package/v4/locales/ja.js +1 -0
  273. package/v4/locales/ka.cjs +1 -0
  274. package/v4/locales/ka.js +1 -0
  275. package/v4/locales/km.cjs +1 -0
  276. package/v4/locales/km.js +1 -0
  277. package/v4/locales/kn.cjs +1 -0
  278. package/v4/locales/kn.js +1 -0
  279. package/v4/locales/ko.cjs +1 -0
  280. package/v4/locales/ko.js +1 -0
  281. package/v4/locales/lt.cjs +1 -0
  282. package/v4/locales/lt.js +1 -0
  283. package/v4/locales/mk.cjs +1 -0
  284. package/v4/locales/mk.js +1 -0
  285. package/v4/locales/ms.cjs +1 -0
  286. package/v4/locales/ms.js +1 -0
  287. package/v4/locales/ne.cjs +1 -0
  288. package/v4/locales/ne.js +1 -0
  289. package/v4/locales/nl.cjs +1 -0
  290. package/v4/locales/nl.js +1 -0
  291. package/v4/locales/nn.cjs +1 -0
  292. package/v4/locales/nn.js +1 -0
  293. package/v4/locales/no.cjs +1 -0
  294. package/v4/locales/no.js +1 -0
  295. package/v4/locales/ota.cjs +1 -0
  296. package/v4/locales/ota.js +1 -0
  297. package/v4/locales/pl.cjs +1 -0
  298. package/v4/locales/pl.js +1 -0
  299. package/v4/locales/ps.cjs +1 -0
  300. package/v4/locales/ps.js +1 -0
  301. package/v4/locales/pt-BR.cjs +1 -0
  302. package/v4/locales/pt-BR.js +1 -0
  303. package/v4/locales/pt.cjs +1 -0
  304. package/v4/locales/pt.js +1 -0
  305. package/v4/locales/ro.cjs +1 -0
  306. package/v4/locales/ro.js +1 -0
  307. package/v4/locales/ru.cjs +1 -0
  308. package/v4/locales/ru.js +1 -0
  309. package/v4/locales/sk.cjs +1 -0
  310. package/v4/locales/sk.js +1 -0
  311. package/v4/locales/sl.cjs +1 -0
  312. package/v4/locales/sl.js +1 -0
  313. package/v4/locales/sv.cjs +1 -0
  314. package/v4/locales/sv.js +1 -0
  315. package/v4/locales/ta.cjs +1 -0
  316. package/v4/locales/ta.js +1 -0
  317. package/v4/locales/tg.cjs +143 -0
  318. package/v4/locales/tg.d.cts +5 -0
  319. package/v4/locales/tg.d.ts +4 -0
  320. package/v4/locales/tg.js +116 -0
  321. package/v4/locales/th.cjs +1 -0
  322. package/v4/locales/th.js +1 -0
  323. package/v4/locales/tk.cjs +1 -0
  324. package/v4/locales/tk.js +1 -0
  325. package/v4/locales/tr.cjs +1 -0
  326. package/v4/locales/tr.js +1 -0
  327. package/v4/locales/uk.cjs +1 -0
  328. package/v4/locales/uk.js +1 -0
  329. package/v4/locales/ur.cjs +1 -0
  330. package/v4/locales/ur.js +1 -0
  331. package/v4/locales/uz.cjs +1 -0
  332. package/v4/locales/uz.js +1 -0
  333. package/v4/locales/vi.cjs +1 -0
  334. package/v4/locales/vi.js +1 -0
  335. package/v4/locales/yo.cjs +1 -0
  336. package/v4/locales/yo.js +1 -0
  337. package/v4/locales/zh-CN.cjs +1 -0
  338. package/v4/locales/zh-CN.js +1 -0
  339. package/v4/locales/zh-TW.cjs +1 -0
  340. package/v4/locales/zh-TW.js +1 -0
  341. package/v4/mini/checks.cjs +20 -2
  342. package/v4/mini/checks.d.cts +1 -1
  343. package/v4/mini/checks.d.ts +1 -1
  344. package/v4/mini/checks.js +1 -1
  345. package/v4/mini/coerce.cjs +19 -0
  346. package/v4/mini/deep-partial.cjs +19 -0
  347. package/v4/mini/external.cjs +22 -1
  348. package/v4/mini/external.d.cts +1 -1
  349. package/v4/mini/external.d.ts +1 -1
  350. package/v4/mini/external.js +1 -1
  351. package/v4/mini/in-out.cjs +19 -0
  352. package/v4/mini/index.cjs +19 -0
  353. package/v4/mini/iso.cjs +19 -0
  354. package/v4/mini/parse.cjs +19 -0
  355. package/v4/mini/schemas.cjs +42 -4
  356. package/v4/mini/schemas.d.cts +8 -0
  357. package/v4/mini/schemas.d.ts +8 -0
  358. package/v4/mini/schemas.js +19 -2
  359. package/v4-mini/index.cjs +19 -0
package/compile.cjs CHANGED
@@ -75,3 +75,22 @@ core.globalConfig.postProcessor = (inst) => {
75
75
  shim.__originalRun = originalRun;
76
76
  inst._zod.run = shim;
77
77
  };
78
+
79
+ // seal-cjs-exports
80
+ (function () {
81
+ var keys = Object.getOwnPropertyNames(exports);
82
+ for (var i = 0; i < keys.length; i++) {
83
+ var desc = Object.getOwnPropertyDescriptor(exports, keys[i]);
84
+ if (!desc || !desc.get || !desc.configurable) continue;
85
+ var value;
86
+ try {
87
+ value = desc.get();
88
+ } catch (e) {
89
+ continue;
90
+ }
91
+ // a circular require may not have settled this one yet, so leave it live
92
+ if (value === undefined) continue;
93
+ Object.defineProperty(exports, keys[i], { value: value, writable: false, enumerable: desc.enumerable, configurable: false });
94
+ }
95
+ Object.freeze(exports);
96
+ })();
package/index.cjs CHANGED
@@ -31,3 +31,22 @@ const z = __importStar(require("./v4/classic/external.cjs"));
31
31
  exports.z = z;
32
32
  exports.default = z;
33
33
  __exportStar(require("./v4/classic/external.cjs"), exports);
34
+
35
+ // seal-cjs-exports
36
+ (function () {
37
+ var keys = Object.getOwnPropertyNames(exports);
38
+ for (var i = 0; i < keys.length; i++) {
39
+ var desc = Object.getOwnPropertyDescriptor(exports, keys[i]);
40
+ if (!desc || !desc.get || !desc.configurable) continue;
41
+ var value;
42
+ try {
43
+ value = desc.get();
44
+ } catch (e) {
45
+ continue;
46
+ }
47
+ // a circular require may not have settled this one yet, so leave it live
48
+ if (value === undefined) continue;
49
+ Object.defineProperty(exports, keys[i], { value: value, writable: false, enumerable: desc.enumerable, configurable: false });
50
+ }
51
+ Object.freeze(exports);
52
+ })();
package/locales/index.cjs CHANGED
@@ -15,3 +15,22 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("../v4/locales/index.cjs"), exports);
18
+
19
+ // seal-cjs-exports
20
+ (function () {
21
+ var keys = Object.getOwnPropertyNames(exports);
22
+ for (var i = 0; i < keys.length; i++) {
23
+ var desc = Object.getOwnPropertyDescriptor(exports, keys[i]);
24
+ if (!desc || !desc.get || !desc.configurable) continue;
25
+ var value;
26
+ try {
27
+ value = desc.get();
28
+ } catch (e) {
29
+ continue;
30
+ }
31
+ // a circular require may not have settled this one yet, so leave it live
32
+ if (value === undefined) continue;
33
+ Object.defineProperty(exports, keys[i], { value: value, writable: false, enumerable: desc.enumerable, configurable: false });
34
+ }
35
+ Object.freeze(exports);
36
+ })();
package/mini/index.cjs CHANGED
@@ -30,3 +30,22 @@ exports.z = void 0;
30
30
  const z = __importStar(require("../v4/mini/external.cjs"));
31
31
  exports.z = z;
32
32
  __exportStar(require("../v4/mini/external.cjs"), exports);
33
+
34
+ // seal-cjs-exports
35
+ (function () {
36
+ var keys = Object.getOwnPropertyNames(exports);
37
+ for (var i = 0; i < keys.length; i++) {
38
+ var desc = Object.getOwnPropertyDescriptor(exports, keys[i]);
39
+ if (!desc || !desc.get || !desc.configurable) continue;
40
+ var value;
41
+ try {
42
+ value = desc.get();
43
+ } catch (e) {
44
+ continue;
45
+ }
46
+ // a circular require may not have settled this one yet, so leave it live
47
+ if (value === undefined) continue;
48
+ Object.defineProperty(exports, keys[i], { value: value, writable: false, enumerable: desc.enumerable, configurable: false });
49
+ }
50
+ Object.freeze(exports);
51
+ })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zod",
3
- "version": "4.5.4",
3
+ "version": "4.6.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "author": "Colin McDonnell <zod@colinhacks.com>",
@@ -52,7 +52,8 @@
52
52
  },
53
53
  "conditions": {
54
54
  "@zod/source": "src"
55
- }
55
+ },
56
+ "sealCjsExports": true
56
57
  },
57
58
  "exports": {
58
59
  "./package.json": "./package.json",
@@ -137,10 +138,10 @@
137
138
  },
138
139
  "scripts": {
139
140
  "clean": "git clean -xdf . -e node_modules",
140
- "build": "zshy --project tsconfig.build.json",
141
- "postbuild": "tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .",
142
- "test:watch": "pnpm vitest",
143
- "test": "pnpm vitest run",
144
- "prepublishOnly": "tsx ../../scripts/check-versions.ts"
141
+ "build": "nub exec --node zshy --project tsconfig.build.json",
142
+ "postbuild": "nub ../../scripts/write-stub-package-jsons.ts && nub exec --node biome check --write .",
143
+ "test:watch": "nub exec --node vitest",
144
+ "test": "nub exec --node vitest run",
145
+ "prepublishOnly": "nub ../../scripts/check-versions.ts"
145
146
  }
146
147
  }
@@ -2,7 +2,7 @@ export namespace errorUtil {
2
2
  export type ErrMessage = string | { message?: string | undefined };
3
3
  export const errToObj = (message?: ErrMessage): { message?: string | undefined } =>
4
4
  typeof message === "string" ? { message } : message || {};
5
- // biome-ignore lint:
5
+ // biome-ignore lint/suspicious/noShadowRestrictedNames: renaming churns 31 v3 call sites
6
6
  export const toString = (message?: ErrMessage): string | undefined =>
7
7
  typeof message === "string" ? message : message?.message;
8
8
  }
@@ -21,7 +21,6 @@ export {
21
21
  _startsWith as startsWith,
22
22
  _endsWith as endsWith,
23
23
  _property as property,
24
- _properties as properties,
25
24
  _mime as mime,
26
25
  _overwrite as overwrite,
27
26
  _normalize as normalize,
@@ -26,8 +26,10 @@ export {
26
26
  TimePrecision,
27
27
  util,
28
28
  NEVER,
29
+ INVALID,
29
30
  toZod,
30
31
  compile,
32
+ withParser,
31
33
  ZodCompileAsyncError,
32
34
  ZodCompileUnsupportedError,
33
35
  getDiscriminatedOption,
@@ -155,34 +155,225 @@ function resolveRef(ref: string, ctx: ConversionContext): JSONSchema.JSONSchema
155
155
  }
156
156
 
157
157
  /**
158
- * Rejects every own key that fails `keySchema`, before `objectSchema` runs. The
159
- * guard has to see the raw input: an object parse drops `__proto__` and can add
160
- * keys from a property `default`, so its output is not the set of names the
161
- * instance actually carried.
158
+ * Enforces the keywords that constrain an object's own keys — `propertyNames`,
159
+ * `minProperties`, `maxProperties` before `objectSchema` runs. The guard has
160
+ * to see the raw input: an object parse drops `__proto__` and can add keys from
161
+ * a property `default`, so its output is not the set of names the instance
162
+ * actually carried.
162
163
  */
163
- function checkPropertyNames(objectSchema: ZodType, keySchema: ZodType): ZodType {
164
+ function checkObjectGuards(
165
+ objectSchema: ZodType,
166
+ guards: { keySchema?: ZodType | undefined; minProperties?: number | undefined; maxProperties?: number | undefined }
167
+ ): ZodType {
164
168
  // An identity transform, not z.any(), so `toJSONSchema` reports the object on both the input and the output side of the pipe.
165
169
  const guard = z
166
170
  .transform((value: unknown) => value)
167
171
  .check((payload) => {
168
172
  const value = payload.value;
169
173
  if (typeof value !== "object" || value === null || Array.isArray(value)) return;
170
- for (const key of Object.getOwnPropertyNames(value)) {
171
- const result = keySchema.safeParse(key);
172
- if (result.success) continue;
174
+ const keys = Object.getOwnPropertyNames(value);
175
+ if (guards.minProperties !== undefined && keys.length < guards.minProperties) {
173
176
  payload.issues.push({
174
- code: "invalid_key",
175
- origin: "record",
176
- issues: result.error.issues,
177
- input: key,
178
- path: [key],
177
+ origin: "object",
178
+ code: "too_small",
179
+ minimum: guards.minProperties,
180
+ inclusive: true,
181
+ message: `Too small: expected object to have >=${guards.minProperties} properties`,
182
+ input: value,
183
+ inst: objectSchema,
179
184
  continue: true,
180
185
  });
181
186
  }
187
+ if (guards.maxProperties !== undefined && keys.length > guards.maxProperties) {
188
+ payload.issues.push({
189
+ origin: "object",
190
+ code: "too_big",
191
+ maximum: guards.maxProperties,
192
+ inclusive: true,
193
+ message: `Too big: expected object to have <=${guards.maxProperties} properties`,
194
+ input: value,
195
+ inst: objectSchema,
196
+ continue: true,
197
+ });
198
+ }
199
+ if (guards.keySchema) {
200
+ for (const key of keys) {
201
+ const result = guards.keySchema.safeParse(key);
202
+ if (result.success) continue;
203
+ payload.issues.push({
204
+ code: "invalid_key",
205
+ origin: "record",
206
+ issues: result.error.issues,
207
+ input: key,
208
+ path: [key],
209
+ continue: true,
210
+ });
211
+ }
212
+ }
182
213
  });
183
214
  return guard.pipe(objectSchema);
184
215
  }
185
216
 
217
+ /**
218
+ * An injective string for JSON data: two values share a key exactly when `uniqueItems` calls them
219
+ * equal, so duplicate detection is a Map lookup rather than a pairwise walk. Strings and keys are
220
+ * length-prefixed so no value can spell another one. `null` means "never equal to anything" — a
221
+ * cycle or a NaN, neither of which JSON can express.
222
+ */
223
+ function canonicalKey(value: unknown, seen: Set<object>): string | null {
224
+ if (value === null) return "z";
225
+ const type = typeof value;
226
+ if (type !== "object") {
227
+ if (type === "number" && Number.isNaN(value)) return null;
228
+ const raw = String(value);
229
+ return `${type[0]}${raw.length}:${raw}`;
230
+ }
231
+ if (seen.has(value as object)) return null;
232
+ seen.add(value as object);
233
+ try {
234
+ if (Array.isArray(value)) {
235
+ const parts: string[] = [];
236
+ for (const item of value) {
237
+ const key = canonicalKey(item, seen);
238
+ if (key === null) return null;
239
+ parts.push(key);
240
+ }
241
+ return `a${parts.length}:[${parts.join(",")}]`;
242
+ }
243
+ const keys = Object.keys(value as object).sort();
244
+ const parts: string[] = [];
245
+ for (const k of keys) {
246
+ const key = canonicalKey((value as any)[k], seen);
247
+ if (key === null) return null;
248
+ parts.push(`${k.length}:${k}=${key}`);
249
+ }
250
+ return `o${parts.length}:{${parts.join(",")}}`;
251
+ } finally {
252
+ seen.delete(value as object);
253
+ }
254
+ }
255
+
256
+ // keywords whose value is a schema or an array of them
257
+ const SCHEMA_KEYWORDS = /*@__PURE__*/ new Set([
258
+ "items",
259
+ "prefixItems",
260
+ "additionalItems",
261
+ "additionalProperties",
262
+ "contains",
263
+ "propertyNames",
264
+ "not",
265
+ "if",
266
+ "then",
267
+ "else",
268
+ "allOf",
269
+ "anyOf",
270
+ "oneOf",
271
+ "unevaluatedItems",
272
+ "unevaluatedProperties",
273
+ "contentSchema",
274
+ ]);
275
+
276
+ // keywords whose value maps names to schemas. draft-7 `dependencies` also allows an array of property names, which holds no schema to walk
277
+ const SCHEMA_MAP_KEYWORDS = /*@__PURE__*/ new Set([
278
+ "properties",
279
+ "patternProperties",
280
+ "dependentSchemas",
281
+ "dependencies",
282
+ "$defs",
283
+ "definitions",
284
+ ]);
285
+
286
+ /**
287
+ * True when a subschema holds a `$ref` anywhere a schema can appear. Only those positions are
288
+ * walked: `$ref` under `default` or an `x-` annotation is instance data with an ordinary key, and
289
+ * reading it as a reference would drop a constraint that resolves perfectly well.
290
+ */
291
+ function containsRef(value: unknown): boolean {
292
+ if (typeof value !== "object" || value === null) return false;
293
+ if (Array.isArray(value)) return value.some(containsRef);
294
+ if (typeof (value as any).$ref === "string") return true;
295
+ return Object.entries(value).some(([key, sub]) => {
296
+ if (SCHEMA_KEYWORDS.has(key)) return containsRef(sub);
297
+ if (!SCHEMA_MAP_KEYWORDS.has(key) || typeof sub !== "object" || sub === null) return false;
298
+ return Object.values(sub).some(containsRef);
299
+ });
300
+ }
301
+
302
+ function plural(n: number): string {
303
+ return n === 1 ? "element" : "elements";
304
+ }
305
+
306
+ /**
307
+ * Enforces `uniqueItems` and the `contains` family before `arraySchema` runs, for the same reason
308
+ * `checkObjectGuards` runs pre-pipe: an item parse can apply a nested `default`, so the parsed
309
+ * array is not the instance the keywords are defined over. A guard issue aborts the pipe, so
310
+ * `minItems`/`maxItems` are not also reported on the same parse — instance correctness is worth
311
+ * more than co-reporting two issues.
312
+ */
313
+ function checkArrayGuards(
314
+ arraySchema: ZodType,
315
+ guards: {
316
+ uniqueItems?: boolean | undefined;
317
+ containsSchema?: ZodType | undefined;
318
+ minContains?: number | undefined;
319
+ maxContains?: number | undefined;
320
+ }
321
+ ): ZodType {
322
+ // An identity transform, not z.any(), so `toJSONSchema` reports the array on both the input and the output side of the pipe.
323
+ const guard = z
324
+ .transform((value: unknown) => value)
325
+ .check((payload) => {
326
+ const items = payload.value;
327
+ if (!Array.isArray(items)) return;
328
+ if (guards.uniqueItems === true) {
329
+ const firstSeen = new Map<string, number>();
330
+ for (let i = 0; i < items.length; i++) {
331
+ const key = canonicalKey(items[i], new Set());
332
+ if (key === null) continue;
333
+ const first = firstSeen.get(key);
334
+ if (first === undefined) {
335
+ firstSeen.set(key, i);
336
+ continue;
337
+ }
338
+ payload.issues.push({
339
+ code: "custom",
340
+ message: `Array items must be unique: element at index ${i} duplicates the one at index ${first}`,
341
+ input: items,
342
+ path: [i],
343
+ continue: true,
344
+ });
345
+ }
346
+ }
347
+ if (guards.containsSchema) {
348
+ const minContains = guards.minContains ?? 1;
349
+ // one past the ceiling already proves the failure, and nothing above it changes the verdict
350
+ const ceiling = guards.maxContains !== undefined ? guards.maxContains + 1 : Number.POSITIVE_INFINITY;
351
+ let matches = 0;
352
+ for (const item of items) {
353
+ if (guards.containsSchema.safeParse(item).success && ++matches >= ceiling) break;
354
+ }
355
+ if (matches < minContains) {
356
+ // the scan ran to the end, so this count is exact
357
+ payload.issues.push({
358
+ code: "custom",
359
+ message: `Array must contain at least ${minContains} matching ${plural(minContains)}; found ${matches}`,
360
+ input: items,
361
+ continue: true,
362
+ });
363
+ }
364
+ if (guards.maxContains !== undefined && matches > guards.maxContains) {
365
+ payload.issues.push({
366
+ code: "custom",
367
+ message: `Array must contain at most ${guards.maxContains} matching ${plural(guards.maxContains)}`,
368
+ input: items,
369
+ continue: true,
370
+ });
371
+ }
372
+ }
373
+ });
374
+ return guard.pipe(arraySchema);
375
+ }
376
+
186
377
  function getTupleRest(restSchema: JSONSchema._JSONSchema | undefined, ctx: ConversionContext): ZodType | undefined {
187
378
  if (restSchema === false) {
188
379
  return undefined;
@@ -351,6 +542,8 @@ function convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext
351
542
  stringSchema = stringSchema.check(z.e164());
352
543
  } else if (format === "credit_card") {
353
544
  stringSchema = stringSchema.check(z.creditCard());
545
+ } else if (format === "iban") {
546
+ stringSchema = stringSchema.check(z.iban());
354
547
  } else if (format === "jwt") {
355
548
  stringSchema = stringSchema.check(z.jwt());
356
549
  } else if (format === "emoji") {
@@ -519,20 +712,25 @@ function convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext
519
712
  }
520
713
 
521
714
  // propertyNames constrains key *names* only, and says nothing about which keys are required or how their values validate. Layering it on top of the result keeps properties/patternProperties/additionalProperties composing underneath. `true` allows every name, so it needs no guard.
522
- if (schema.propertyNames !== undefined && schema.propertyNames !== true) {
523
- // Keys are always strings, so a propertyNames subschema that omits `type` still constrains them — without this it would convert to z.any().
524
- const keyJSONSchema =
525
- typeof schema.propertyNames === "object" && schema.propertyNames.type === undefined
526
- ? { type: "string", ...schema.propertyNames }
527
- : schema.propertyNames;
528
- zodSchema = checkPropertyNames(zodSchema, convertSchema(keyJSONSchema as JSONSchema.JSONSchema, ctx));
715
+ const hasKeyGuard = schema.propertyNames !== undefined && schema.propertyNames !== true;
716
+ const minProperties = typeof schema.minProperties === "number" ? schema.minProperties : undefined;
717
+ const maxProperties = typeof schema.maxProperties === "number" ? schema.maxProperties : undefined;
718
+ if (hasKeyGuard || minProperties !== undefined || maxProperties !== undefined) {
719
+ let keySchema: ZodType | undefined;
720
+ if (hasKeyGuard) {
721
+ // Keys are always strings, so a propertyNames subschema that omits `type` still constrains them — without this it would convert to z.any().
722
+ const keyJSONSchema =
723
+ typeof schema.propertyNames === "object" && schema.propertyNames.type === undefined
724
+ ? { type: "string", ...schema.propertyNames }
725
+ : schema.propertyNames;
726
+ keySchema = convertSchema(keyJSONSchema as JSONSchema.JSONSchema, ctx);
727
+ }
728
+ zodSchema = checkObjectGuards(zodSchema, { keySchema, minProperties, maxProperties });
529
729
  }
530
730
  break;
531
731
  }
532
732
 
533
733
  case "array": {
534
- // TODO: uniqueItems and contains/minContains/maxContains are not supported
535
-
536
734
  // Check if this is a tuple (prefixItems or items as array)
537
735
  const prefixItems = schema.prefixItems;
538
736
  const items = schema.items;
@@ -585,6 +783,18 @@ function convertBaseSchema(schema: JSONSchema.JSONSchema, ctx: ConversionContext
585
783
  // No items specified - array of any
586
784
  zodSchema = z.array(z.any());
587
785
  }
786
+
787
+ // minContains/maxContains only constrain anything when `contains` itself is present
788
+ if (schema.uniqueItems === true || schema.contains !== undefined) {
789
+ zodSchema = checkArrayGuards(zodSchema, {
790
+ uniqueItems: schema.uniqueItems === true,
791
+ containsSchema:
792
+ schema.contains !== undefined ? convertSchema(schema.contains as JSONSchema.JSONSchema, ctx) : undefined,
793
+ minContains: typeof schema.minContains === "number" ? schema.minContains : undefined,
794
+ maxContains: typeof schema.maxContains === "number" ? schema.maxContains : undefined,
795
+ });
796
+ }
797
+
588
798
  break;
589
799
  }
590
800
 
@@ -666,9 +876,22 @@ function convertSchema(schema: JSONSchema.JSONSchema | boolean, ctx: ConversionC
666
876
  }
667
877
  }
668
878
 
669
- // `propertyNames` is enforced by a key guard, which `toJSONSchema` cannot infer, so the original keyword is carried as metadata to keep the round-trip lossless. Only where it was actually applied: on any other type it is inert, and on a `$ref` the metadata would land on the target every reference shares.
670
- if (schema.propertyNames !== undefined && schema.type === "object" && schema.$ref === undefined) {
671
- extraMeta.propertyNames = schema.propertyNames;
879
+ // `propertyNames` and `contains` are enforced by a guard, which `toJSONSchema` cannot infer, so the original keyword is carried as metadata to keep the round-trip lossless. Only where it was actually applied: on any other type it is inert, and on a `$ref` the metadata would land on the target every reference shares. A carried subschema is copied verbatim while the root `$defs` stay behind, so one holding a `$ref` is dropped rather than emitted as a dangling reference.
880
+ if (schema.type === "object" && schema.$ref === undefined) {
881
+ if (schema.propertyNames !== undefined && !containsRef(schema.propertyNames)) {
882
+ extraMeta.propertyNames = schema.propertyNames;
883
+ }
884
+ for (const key of ["minProperties", "maxProperties"] as const) {
885
+ if (schema[key] !== undefined) extraMeta[key] = schema[key];
886
+ }
887
+ }
888
+ if (schema.type === "array" && schema.$ref === undefined) {
889
+ if (schema.contains !== undefined && !containsRef(schema.contains)) {
890
+ extraMeta.contains = schema.contains;
891
+ }
892
+ for (const key of ["uniqueItems", "minContains", "maxContains"] as const) {
893
+ if (schema[key] !== undefined) extraMeta[key] = schema[key];
894
+ }
672
895
  }
673
896
 
674
897
  for (const key of Object.keys(schema)) {