@oxog/vld 2.0.3 → 2.2.5

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 (452) hide show
  1. package/CHANGELOG.md +120 -1
  2. package/README.md +1296 -1171
  3. package/dist/chunks/errors-core-Cqi4-9ew.js +1 -0
  4. package/dist/chunks/index-CkbfQQ4n.js +1 -0
  5. package/dist/chunks/index-yjpbvFgw.js +1 -0
  6. package/dist/chunks/ip-validation-g5LWgy9t.js +1 -0
  7. package/dist/chunks/security-Dy24T8N7.js +1 -0
  8. package/dist/cjs/chunks/errors-core-DKPohm9I.cjs +1 -0
  9. package/dist/cjs/chunks/index-BEV9nG0N.cjs +1 -0
  10. package/dist/cjs/chunks/index-ZjHAxYdA.cjs +1 -0
  11. package/dist/cjs/chunks/ip-validation-BZqPamPC.cjs +1 -0
  12. package/dist/cjs/chunks/security-aXZVI7qW.cjs +1 -0
  13. package/dist/cjs/cli/bin.cjs +2 -0
  14. package/dist/cjs/cli/index.cjs +1 -0
  15. package/dist/cjs/codecs/index.cjs +1 -0
  16. package/dist/cjs/coercion/index.cjs +1 -0
  17. package/dist/cjs/compat/emitter.cjs +1 -0
  18. package/dist/cjs/compat/result.cjs +1 -0
  19. package/dist/cjs/errors.cjs +1 -387
  20. package/dist/cjs/index.cjs +1 -10759
  21. package/dist/cjs/kernel.cjs +1 -0
  22. package/dist/cjs/locales/af.cjs +1 -0
  23. package/dist/cjs/locales/ar.cjs +1 -0
  24. package/dist/cjs/locales/bn.cjs +1 -0
  25. package/dist/cjs/locales/da.cjs +1 -0
  26. package/dist/cjs/locales/de.cjs +1 -0
  27. package/dist/cjs/locales/en.cjs +1 -0
  28. package/dist/cjs/locales/es-MX.cjs +1 -0
  29. package/dist/cjs/locales/es.cjs +1 -0
  30. package/dist/cjs/locales/fi.cjs +1 -0
  31. package/dist/cjs/locales/fr.cjs +1 -0
  32. package/dist/cjs/locales/hi.cjs +1 -0
  33. package/dist/cjs/locales/id.cjs +1 -0
  34. package/dist/cjs/locales/index.cjs +1 -2877
  35. package/dist/cjs/locales/it.cjs +1 -0
  36. package/dist/cjs/locales/ja.cjs +1 -0
  37. package/dist/cjs/locales/ko.cjs +1 -0
  38. package/dist/cjs/locales/lazy.cjs +1 -3169
  39. package/dist/cjs/locales/nl.cjs +1 -0
  40. package/dist/cjs/locales/no.cjs +1 -0
  41. package/dist/cjs/locales/pl.cjs +1 -0
  42. package/dist/cjs/locales/pt-BR.cjs +1 -0
  43. package/dist/cjs/locales/pt.cjs +1 -0
  44. package/dist/cjs/locales/ru.cjs +1 -0
  45. package/dist/cjs/locales/runtime.cjs +1 -0
  46. package/dist/cjs/locales/sv.cjs +1 -0
  47. package/dist/cjs/locales/sw.cjs +1 -0
  48. package/dist/cjs/locales/th.cjs +1 -0
  49. package/dist/cjs/locales/tr.cjs +1 -0
  50. package/dist/cjs/locales/vi.cjs +1 -0
  51. package/dist/cjs/locales/zh.cjs +1 -0
  52. package/dist/cjs/mini.cjs +1 -7474
  53. package/dist/cjs/pigment.cjs +1 -0
  54. package/dist/cjs/plugins/index.cjs +1 -0
  55. package/dist/cjs/registry.cjs +1 -0
  56. package/dist/cjs/v3/index.cjs +1 -0
  57. package/dist/cjs/v4/core/index.cjs +1 -0
  58. package/dist/cjs/v4/index.cjs +1 -0
  59. package/dist/cjs/v4/locales/index.cjs +1 -0
  60. package/dist/cjs/v4/mini/index.cjs +1 -0
  61. package/dist/cjs/v4-mini/index.cjs +1 -0
  62. package/dist/cjs/validators/any.cjs +1 -0
  63. package/dist/cjs/validators/array.cjs +1 -0
  64. package/dist/cjs/validators/base.cjs +1 -0
  65. package/dist/cjs/validators/base64.cjs +1 -0
  66. package/dist/cjs/validators/bigint.cjs +1 -0
  67. package/dist/cjs/validators/boolean.cjs +1 -0
  68. package/dist/cjs/validators/codec.cjs +1 -0
  69. package/dist/cjs/validators/custom.cjs +1 -0
  70. package/dist/cjs/validators/date.cjs +1 -0
  71. package/dist/cjs/validators/discriminated-union.cjs +1 -0
  72. package/dist/cjs/validators/enum.cjs +1 -0
  73. package/dist/cjs/validators/file.cjs +1 -0
  74. package/dist/cjs/validators/function.cjs +1 -0
  75. package/dist/cjs/validators/hex.cjs +1 -0
  76. package/dist/cjs/validators/index.cjs +1 -0
  77. package/dist/cjs/validators/intersection.cjs +1 -0
  78. package/dist/cjs/validators/json.cjs +1 -0
  79. package/dist/cjs/validators/lazy.cjs +1 -0
  80. package/dist/cjs/validators/literal.cjs +1 -0
  81. package/dist/cjs/validators/map.cjs +1 -0
  82. package/dist/cjs/validators/nan.cjs +1 -0
  83. package/dist/cjs/validators/never.cjs +1 -0
  84. package/dist/cjs/validators/null.cjs +1 -0
  85. package/dist/cjs/validators/number.cjs +1 -0
  86. package/dist/cjs/validators/object.cjs +1 -0
  87. package/dist/cjs/validators/promise.cjs +1 -0
  88. package/dist/cjs/validators/record.cjs +1 -0
  89. package/dist/cjs/validators/set.cjs +1 -0
  90. package/dist/cjs/validators/string-bool.cjs +1 -0
  91. package/dist/cjs/validators/string-formats.cjs +1 -0
  92. package/dist/cjs/validators/string.cjs +1 -0
  93. package/dist/cjs/validators/symbol.cjs +1 -0
  94. package/dist/cjs/validators/template-literal.cjs +1 -0
  95. package/dist/cjs/validators/tuple.cjs +1 -0
  96. package/dist/cjs/validators/uint8array.cjs +1 -0
  97. package/dist/cjs/validators/undefined.cjs +1 -0
  98. package/dist/cjs/validators/union.cjs +1 -0
  99. package/dist/cjs/validators/unknown.cjs +1 -0
  100. package/dist/cjs/validators/void.cjs +1 -0
  101. package/dist/cjs/validators/xor.cjs +1 -0
  102. package/dist/cli/bin.d.ts +0 -1
  103. package/dist/cli/bin.js +2 -0
  104. package/dist/cli/commands/benchmark.d.ts +1 -2
  105. package/dist/cli/commands/validate.d.ts +1 -2
  106. package/dist/cli/index.d.ts +0 -1
  107. package/dist/cli/index.js +1 -0
  108. package/dist/codecs/index.d.ts +21 -4
  109. package/dist/codecs/index.js +1 -4
  110. package/dist/coercion/bigint.d.ts +2 -3
  111. package/dist/coercion/boolean.d.ts +3 -3
  112. package/dist/coercion/date.d.ts +3 -3
  113. package/dist/coercion/index.d.ts +5 -6
  114. package/dist/coercion/index.js +1 -111
  115. package/dist/coercion/number.d.ts +2 -3
  116. package/dist/coercion/string.d.ts +2 -3
  117. package/dist/compat/emitter.d.ts +0 -1
  118. package/dist/compat/emitter.js +1 -181
  119. package/dist/compat/index.d.ts +4 -5
  120. package/dist/compat/result.d.ts +1 -2
  121. package/dist/compat/result.js +1 -171
  122. package/dist/errors-core.d.ts +58 -0
  123. package/dist/errors.d.ts +4 -54
  124. package/dist/errors.js +1 -235
  125. package/dist/events.d.ts +3 -4
  126. package/dist/index.d.ts +1093 -851
  127. package/dist/index.js +1 -855
  128. package/dist/kernel.d.ts +2 -3
  129. package/dist/kernel.js +1 -405
  130. package/dist/locales/af.d.ts +1 -2
  131. package/dist/locales/af.js +1 -107
  132. package/dist/locales/ar.d.ts +1 -2
  133. package/dist/locales/ar.js +1 -107
  134. package/dist/locales/bn.d.ts +1 -2
  135. package/dist/locales/bn.js +1 -107
  136. package/dist/locales/da.d.ts +1 -2
  137. package/dist/locales/da.js +1 -107
  138. package/dist/locales/de.d.ts +1 -2
  139. package/dist/locales/de.js +1 -107
  140. package/dist/locales/en.d.ts +1 -2
  141. package/dist/locales/en.js +1 -107
  142. package/dist/locales/es-MX.d.ts +1 -2
  143. package/dist/locales/es-MX.js +1 -106
  144. package/dist/locales/es.d.ts +1 -2
  145. package/dist/locales/es.js +1 -95
  146. package/dist/locales/fi.d.ts +1 -2
  147. package/dist/locales/fi.js +1 -107
  148. package/dist/locales/fr.d.ts +1 -2
  149. package/dist/locales/fr.js +1 -95
  150. package/dist/locales/hi.d.ts +1 -2
  151. package/dist/locales/hi.js +1 -107
  152. package/dist/locales/id.d.ts +1 -2
  153. package/dist/locales/id.js +1 -107
  154. package/dist/locales/index.d.ts +10 -15
  155. package/dist/locales/index.js +1 -3
  156. package/dist/locales/it.d.ts +1 -2
  157. package/dist/locales/it.js +1 -107
  158. package/dist/locales/ja.d.ts +1 -2
  159. package/dist/locales/ja.js +1 -107
  160. package/dist/locales/ko.d.ts +1 -2
  161. package/dist/locales/ko.js +1 -107
  162. package/dist/locales/lazy.d.ts +4 -26
  163. package/dist/locales/lazy.js +1 -220
  164. package/dist/locales/nl.d.ts +1 -2
  165. package/dist/locales/nl.js +1 -107
  166. package/dist/locales/no.d.ts +1 -2
  167. package/dist/locales/no.js +1 -107
  168. package/dist/locales/pl.d.ts +1 -2
  169. package/dist/locales/pl.js +1 -107
  170. package/dist/locales/pt-BR.d.ts +1 -2
  171. package/dist/locales/pt-BR.js +1 -107
  172. package/dist/locales/pt.d.ts +1 -2
  173. package/dist/locales/pt.js +1 -107
  174. package/dist/locales/ru.d.ts +1 -2
  175. package/dist/locales/ru.js +1 -107
  176. package/dist/locales/runtime.d.ts +10 -0
  177. package/dist/locales/runtime.js +1 -0
  178. package/dist/locales/sv.d.ts +1 -2
  179. package/dist/locales/sv.js +1 -107
  180. package/dist/locales/sw.d.ts +1 -2
  181. package/dist/locales/sw.js +1 -107
  182. package/dist/locales/th.d.ts +1 -2
  183. package/dist/locales/th.js +1 -107
  184. package/dist/locales/tr.d.ts +1 -2
  185. package/dist/locales/tr.js +1 -107
  186. package/dist/locales/types.d.ts +0 -1
  187. package/dist/locales/vi.d.ts +1 -2
  188. package/dist/locales/vi.js +1 -107
  189. package/dist/locales/zh.d.ts +1 -2
  190. package/dist/locales/zh.js +1 -107
  191. package/dist/logger.d.ts +0 -1
  192. package/dist/mini.d.ts +67 -68
  193. package/dist/mini.js +1 -132
  194. package/dist/pigment.d.ts +0 -1
  195. package/dist/pigment.js +1 -178
  196. package/dist/plugins/index.d.ts +2 -3
  197. package/dist/plugins/index.js +1 -0
  198. package/dist/plugins/types.d.ts +4 -5
  199. package/dist/registry.d.ts +23 -0
  200. package/dist/registry.js +1 -0
  201. package/dist/utils/codec-utils.d.ts +0 -1
  202. package/dist/utils/deep-merge.d.ts +0 -1
  203. package/dist/utils/ip-validation.d.ts +0 -1
  204. package/dist/utils/json-schema.d.ts +26 -7
  205. package/dist/utils/security.d.ts +2 -6
  206. package/dist/v3/index.d.ts +2 -0
  207. package/dist/v3/index.js +1 -0
  208. package/dist/v4/core/index.d.ts +272 -0
  209. package/dist/v4/core/index.js +1 -0
  210. package/dist/v4/index.d.ts +4 -0
  211. package/dist/v4/index.js +1 -0
  212. package/dist/v4/locales/index.d.ts +57 -0
  213. package/dist/v4/locales/index.js +1 -0
  214. package/dist/v4/mini/index.d.ts +2 -0
  215. package/dist/v4/mini/index.js +1 -0
  216. package/dist/v4-mini/index.d.ts +22 -0
  217. package/dist/v4-mini/index.js +1 -0
  218. package/dist/validators/any.d.ts +7 -2
  219. package/dist/validators/any.js +1 -0
  220. package/dist/validators/array.d.ts +16 -2
  221. package/dist/validators/array.js +1 -0
  222. package/dist/validators/base.d.ts +213 -14
  223. package/dist/validators/base.js +1 -0
  224. package/dist/validators/base64.d.ts +1 -2
  225. package/dist/validators/base64.js +1 -0
  226. package/dist/validators/bigint.d.ts +21 -3
  227. package/dist/validators/bigint.js +1 -0
  228. package/dist/validators/boolean.d.ts +13 -4
  229. package/dist/validators/boolean.js +1 -0
  230. package/dist/validators/codec.d.ts +9 -2
  231. package/dist/validators/codec.js +1 -0
  232. package/dist/validators/custom.d.ts +15 -2
  233. package/dist/validators/custom.js +1 -0
  234. package/dist/validators/date.d.ts +19 -3
  235. package/dist/validators/date.js +1 -0
  236. package/dist/validators/discriminated-union.d.ts +6 -5
  237. package/dist/validators/discriminated-union.js +1 -0
  238. package/dist/validators/enum.d.ts +10 -7
  239. package/dist/validators/enum.js +1 -0
  240. package/dist/validators/file.d.ts +7 -2
  241. package/dist/validators/file.js +1 -0
  242. package/dist/validators/function.d.ts +11 -5
  243. package/dist/validators/function.js +1 -0
  244. package/dist/validators/hex.d.ts +1 -2
  245. package/dist/validators/hex.js +1 -0
  246. package/dist/validators/index.d.ts +38 -39
  247. package/dist/validators/index.js +1 -515
  248. package/dist/validators/intersection.d.ts +1 -2
  249. package/dist/validators/intersection.js +1 -0
  250. package/dist/validators/json.d.ts +1 -2
  251. package/dist/validators/json.js +1 -0
  252. package/dist/validators/lazy.d.ts +5 -9
  253. package/dist/validators/lazy.js +1 -0
  254. package/dist/validators/literal.d.ts +9 -5
  255. package/dist/validators/literal.js +1 -0
  256. package/dist/validators/map.d.ts +15 -2
  257. package/dist/validators/map.js +1 -0
  258. package/dist/validators/nan.d.ts +2 -3
  259. package/dist/validators/nan.js +1 -0
  260. package/dist/validators/never.d.ts +1 -2
  261. package/dist/validators/never.js +1 -0
  262. package/dist/validators/null.d.ts +3 -3
  263. package/dist/validators/null.js +1 -0
  264. package/dist/validators/number.d.ts +75 -27
  265. package/dist/validators/number.js +1 -0
  266. package/dist/validators/object.d.ts +42 -11
  267. package/dist/validators/object.js +1 -0
  268. package/dist/validators/promise.d.ts +15 -10
  269. package/dist/validators/promise.js +1 -0
  270. package/dist/validators/record.d.ts +21 -9
  271. package/dist/validators/record.js +1 -0
  272. package/dist/validators/set.d.ts +11 -2
  273. package/dist/validators/set.js +1 -0
  274. package/dist/validators/string-bool.d.ts +7 -10
  275. package/dist/validators/string-bool.js +1 -0
  276. package/dist/validators/string-formats.d.ts +64 -65
  277. package/dist/validators/string-formats.js +1 -0
  278. package/dist/validators/string.d.ts +84 -26
  279. package/dist/validators/string.js +1 -0
  280. package/dist/validators/symbol.d.ts +8 -3
  281. package/dist/validators/symbol.js +1 -0
  282. package/dist/validators/template-literal.d.ts +1 -2
  283. package/dist/validators/template-literal.js +1 -0
  284. package/dist/validators/tuple.d.ts +29 -12
  285. package/dist/validators/tuple.js +1 -0
  286. package/dist/validators/uint8array.d.ts +3 -4
  287. package/dist/validators/uint8array.js +1 -0
  288. package/dist/validators/undefined.d.ts +3 -3
  289. package/dist/validators/undefined.js +1 -0
  290. package/dist/validators/union.d.ts +7 -4
  291. package/dist/validators/union.js +1 -0
  292. package/dist/validators/unknown.d.ts +7 -2
  293. package/dist/validators/unknown.js +1 -0
  294. package/dist/validators/void.d.ts +3 -2
  295. package/dist/validators/void.js +1 -0
  296. package/dist/validators/xor.d.ts +4 -5
  297. package/dist/validators/xor.js +1 -0
  298. package/package.json +239 -154
  299. package/dist/chunks/bigint-CRS0QVsy.js +0 -1854
  300. package/dist/chunks/bigint-CRS0QVsy.js.map +0 -1
  301. package/dist/chunks/date-50JV_Mfj.js +0 -506
  302. package/dist/chunks/date-50JV_Mfj.js.map +0 -1
  303. package/dist/chunks/index-DO8CFMxD.js +0 -894
  304. package/dist/chunks/index-DO8CFMxD.js.map +0 -1
  305. package/dist/chunks/json-Cp4WO0M9.js +0 -2021
  306. package/dist/chunks/json-Cp4WO0M9.js.map +0 -1
  307. package/dist/chunks/unknown-Dhzri_T-.js +0 -28
  308. package/dist/chunks/unknown-Dhzri_T-.js.map +0 -1
  309. package/dist/cjs/errors.cjs.map +0 -1
  310. package/dist/cjs/index.cjs.map +0 -1
  311. package/dist/cjs/locales/index.cjs.map +0 -1
  312. package/dist/cjs/locales/lazy.cjs.map +0 -1
  313. package/dist/cjs/mini.cjs.map +0 -1
  314. package/dist/cli/bin.d.ts.map +0 -1
  315. package/dist/cli/commands/benchmark.d.ts.map +0 -1
  316. package/dist/cli/commands/validate.d.ts.map +0 -1
  317. package/dist/cli/index.d.ts.map +0 -1
  318. package/dist/codecs/index.d.ts.map +0 -1
  319. package/dist/codecs/index.js.map +0 -1
  320. package/dist/coercion/bigint.d.ts.map +0 -1
  321. package/dist/coercion/boolean.d.ts.map +0 -1
  322. package/dist/coercion/date.d.ts.map +0 -1
  323. package/dist/coercion/index.d.ts.map +0 -1
  324. package/dist/coercion/index.js.map +0 -1
  325. package/dist/coercion/number.d.ts.map +0 -1
  326. package/dist/coercion/string.d.ts.map +0 -1
  327. package/dist/compat/emitter.d.ts.map +0 -1
  328. package/dist/compat/emitter.js.map +0 -1
  329. package/dist/compat/index.d.ts.map +0 -1
  330. package/dist/compat/result.d.ts.map +0 -1
  331. package/dist/compat/result.js.map +0 -1
  332. package/dist/errors.d.ts.map +0 -1
  333. package/dist/errors.js.map +0 -1
  334. package/dist/events.d.ts.map +0 -1
  335. package/dist/index.d.ts.map +0 -1
  336. package/dist/index.js.map +0 -1
  337. package/dist/kernel.d.ts.map +0 -1
  338. package/dist/kernel.js.map +0 -1
  339. package/dist/locales/af.d.ts.map +0 -1
  340. package/dist/locales/af.js.map +0 -1
  341. package/dist/locales/ar.d.ts.map +0 -1
  342. package/dist/locales/ar.js.map +0 -1
  343. package/dist/locales/backup-en.d.ts +0 -3
  344. package/dist/locales/backup-en.d.ts.map +0 -1
  345. package/dist/locales/bn.d.ts.map +0 -1
  346. package/dist/locales/bn.js.map +0 -1
  347. package/dist/locales/da.d.ts.map +0 -1
  348. package/dist/locales/da.js.map +0 -1
  349. package/dist/locales/de.d.ts.map +0 -1
  350. package/dist/locales/de.js.map +0 -1
  351. package/dist/locales/en.d.ts.map +0 -1
  352. package/dist/locales/en.js.map +0 -1
  353. package/dist/locales/es-MX.d.ts.map +0 -1
  354. package/dist/locales/es-MX.js.map +0 -1
  355. package/dist/locales/es.d.ts.map +0 -1
  356. package/dist/locales/es.js.map +0 -1
  357. package/dist/locales/fi.d.ts.map +0 -1
  358. package/dist/locales/fi.js.map +0 -1
  359. package/dist/locales/fr.d.ts.map +0 -1
  360. package/dist/locales/fr.js.map +0 -1
  361. package/dist/locales/hi.d.ts.map +0 -1
  362. package/dist/locales/hi.js.map +0 -1
  363. package/dist/locales/id.d.ts.map +0 -1
  364. package/dist/locales/id.js.map +0 -1
  365. package/dist/locales/index.d.ts.map +0 -1
  366. package/dist/locales/index.js.map +0 -1
  367. package/dist/locales/it.d.ts.map +0 -1
  368. package/dist/locales/it.js.map +0 -1
  369. package/dist/locales/ja.d.ts.map +0 -1
  370. package/dist/locales/ja.js.map +0 -1
  371. package/dist/locales/ko.d.ts.map +0 -1
  372. package/dist/locales/ko.js.map +0 -1
  373. package/dist/locales/lazy.d.ts.map +0 -1
  374. package/dist/locales/lazy.js.map +0 -1
  375. package/dist/locales/nl.d.ts.map +0 -1
  376. package/dist/locales/nl.js.map +0 -1
  377. package/dist/locales/no.d.ts.map +0 -1
  378. package/dist/locales/no.js.map +0 -1
  379. package/dist/locales/pl.d.ts.map +0 -1
  380. package/dist/locales/pl.js.map +0 -1
  381. package/dist/locales/pt-BR.d.ts.map +0 -1
  382. package/dist/locales/pt-BR.js.map +0 -1
  383. package/dist/locales/pt.d.ts.map +0 -1
  384. package/dist/locales/pt.js.map +0 -1
  385. package/dist/locales/ru.d.ts.map +0 -1
  386. package/dist/locales/ru.js.map +0 -1
  387. package/dist/locales/sv.d.ts.map +0 -1
  388. package/dist/locales/sv.js.map +0 -1
  389. package/dist/locales/sw.d.ts.map +0 -1
  390. package/dist/locales/sw.js.map +0 -1
  391. package/dist/locales/th.d.ts.map +0 -1
  392. package/dist/locales/th.js.map +0 -1
  393. package/dist/locales/tr.d.ts.map +0 -1
  394. package/dist/locales/tr.js.map +0 -1
  395. package/dist/locales/types.d.ts.map +0 -1
  396. package/dist/locales/vi.d.ts.map +0 -1
  397. package/dist/locales/vi.js.map +0 -1
  398. package/dist/locales/zh.d.ts.map +0 -1
  399. package/dist/locales/zh.js.map +0 -1
  400. package/dist/logger.d.ts.map +0 -1
  401. package/dist/mini.d.ts.map +0 -1
  402. package/dist/mini.js.map +0 -1
  403. package/dist/pigment.d.ts.map +0 -1
  404. package/dist/pigment.js.map +0 -1
  405. package/dist/plugins/index.d.ts.map +0 -1
  406. package/dist/plugins/types.d.ts.map +0 -1
  407. package/dist/utils/codec-utils.d.ts.map +0 -1
  408. package/dist/utils/deep-merge.d.ts.map +0 -1
  409. package/dist/utils/ip-validation.d.ts.map +0 -1
  410. package/dist/utils/json-schema.d.ts.map +0 -1
  411. package/dist/utils/security.d.ts.map +0 -1
  412. package/dist/validators/any.d.ts.map +0 -1
  413. package/dist/validators/array.d.ts.map +0 -1
  414. package/dist/validators/base.d.ts.map +0 -1
  415. package/dist/validators/base64.d.ts.map +0 -1
  416. package/dist/validators/bigint.d.ts.map +0 -1
  417. package/dist/validators/boolean.d.ts.map +0 -1
  418. package/dist/validators/codec.d.ts.map +0 -1
  419. package/dist/validators/custom.d.ts.map +0 -1
  420. package/dist/validators/date.d.ts.map +0 -1
  421. package/dist/validators/discriminated-union.d.ts.map +0 -1
  422. package/dist/validators/enum.d.ts.map +0 -1
  423. package/dist/validators/file.d.ts.map +0 -1
  424. package/dist/validators/function.d.ts.map +0 -1
  425. package/dist/validators/hex.d.ts.map +0 -1
  426. package/dist/validators/index.d.ts.map +0 -1
  427. package/dist/validators/index.js.map +0 -1
  428. package/dist/validators/intersection.d.ts.map +0 -1
  429. package/dist/validators/json.d.ts.map +0 -1
  430. package/dist/validators/lazy.d.ts.map +0 -1
  431. package/dist/validators/literal.d.ts.map +0 -1
  432. package/dist/validators/map.d.ts.map +0 -1
  433. package/dist/validators/nan.d.ts.map +0 -1
  434. package/dist/validators/never.d.ts.map +0 -1
  435. package/dist/validators/null.d.ts.map +0 -1
  436. package/dist/validators/number.d.ts.map +0 -1
  437. package/dist/validators/object.d.ts.map +0 -1
  438. package/dist/validators/promise.d.ts.map +0 -1
  439. package/dist/validators/record.d.ts.map +0 -1
  440. package/dist/validators/set.d.ts.map +0 -1
  441. package/dist/validators/string-bool.d.ts.map +0 -1
  442. package/dist/validators/string-formats.d.ts.map +0 -1
  443. package/dist/validators/string.d.ts.map +0 -1
  444. package/dist/validators/symbol.d.ts.map +0 -1
  445. package/dist/validators/template-literal.d.ts.map +0 -1
  446. package/dist/validators/tuple.d.ts.map +0 -1
  447. package/dist/validators/uint8array.d.ts.map +0 -1
  448. package/dist/validators/undefined.d.ts.map +0 -1
  449. package/dist/validators/union.d.ts.map +0 -1
  450. package/dist/validators/unknown.d.ts.map +0 -1
  451. package/dist/validators/void.d.ts.map +0 -1
  452. package/dist/validators/xor.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,1171 +1,1296 @@
1
- # VLD - Fast & Lightweight TypeScript Validation Library
2
-
3
- [![NPM Version](https://img.shields.io/npm/v/@oxog/vld.svg)](https://www.npmjs.com/package/@oxog/vld) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/) [![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-green.svg)](package.json) [![Test Coverage](https://img.shields.io/badge/Coverage-98.34%25-brightgreen.svg)](package.json)
4
-
5
- VLD is a blazing-fast, type-safe validation library for TypeScript and JavaScript with **full Zod feature parity**. Built with performance in mind, it provides a simple and intuitive API while maintaining excellent type inference and 27+ language internationalization support.
6
-
7
- ## Table of Contents
8
-
9
- - [Features](#-features)
10
- - [Performance](#-performance)
11
- - [Installation](#-installation)
12
- - [Quick Start](#-quick-start)
13
- - [API Reference](#-api-reference)
14
- - [Internationalization (i18n)](#-internationalization-i18n)
15
- - [Error Handling & Formatting](#%EF%B8%8F-error-handling--formatting)
16
- - [Advanced Examples](#-advanced-examples)
17
- - [Why VLD?](#-why-vld)
18
- - [Codecs - Bidirectional Transformations](#-codecs---bidirectional-transformations)
19
- - [Plugin System](#-plugin-system)
20
- - [Result Pattern](#-result-pattern)
21
- - [CLI Tools](#-cli-tools)
22
- - [Migrating from Zod](#-migrating-from-zod)
23
- - [Benchmarks](#-benchmarks)
24
- - [Contributing](#-contributing)
25
- - [Links](#-links)
26
-
27
- ## Features
28
-
29
- ### Core Features
30
- - **Blazing Fast**: Optimized for V8 engine with superior performance
31
- - **Type-Safe**: Full TypeScript support with excellent type inference
32
- - **Zero Dependencies**: Lightweight with no external dependencies
33
- - **Tree-Shakeable**: Only import what you need
34
- - **Composable**: Chain validations for complex schemas
35
- - **Advanced Error Formatting**: Tree, pretty, and flatten error utilities
36
- - **Multi-language**: Built-in support for 27+ languages
37
- - **98.34% Test Coverage**: Rigorously tested with 1914 passing tests
38
- - **Industry Leading Performance**: 1.98x faster than Zod on average
39
-
40
- ### Advanced Zod-Compatible Features
41
- - **Type Coercion**: `v.coerce.string()`, `v.coerce.number()`, `v.coerce.boolean()`, etc.
42
- - **Advanced Types**: BigInt, Symbol, Tuple, Record, Set, Map validation
43
- - **Intersection Types**: Combine multiple schemas with intelligent merging
44
- - **Custom Validation**: `refine()` for custom predicates and validation logic
45
- - **Data Transformation**: `transform()` for post-validation data transformation
46
- - **Default Values**: `default()` for handling undefined inputs elegantly
47
- - **Fallback Handling**: `catch()` for graceful error recovery
48
- - **Object Utilities**: `pick()`, `omit()`, `extend()` for flexible object schemas
49
-
50
- ### NEW in v2.0.0 - Modular Architecture
51
-
52
- #### Tree-Shakable Mini API
53
- ```typescript
54
- import { string, number, object, optional } from '@oxog/vld/mini';
55
-
56
- const schema = object({
57
- name: string().min(1),
58
- age: optional(number().positive()),
59
- });
60
- ```
61
- - **82% smaller bundles** when using only needed validators
62
- - Individual factory functions for optimal tree-shaking
63
- - Full TypeScript support with identical type inference
64
-
65
- #### Lazy Locale Loading
66
- ```typescript
67
- import { setLocaleAsync } from '@oxog/vld/locales';
68
- await setLocaleAsync('tr'); // Loads Turkish on demand
69
- ```
70
- - **92% bundle reduction** - Only English bundled by default
71
- - `preloadLocales()` for SSR/batch loading
72
- - Full backwards compatibility with `setLocale()`
73
-
74
- #### Dual ESM/CJS Build
75
- - ESM builds for modern bundlers (Vite, esbuild)
76
- - CJS builds for Node.js and legacy environments
77
- - Proper `exports` field with conditional exports
78
-
79
- ### NEW in v1.5.0 - Major Platform Release
80
-
81
- #### Plugin System
82
- - **`definePlugin()`**: Create custom plugins with validators, transforms, and codecs
83
- - **`usePlugin()`**: Register plugins globally
84
- - **Plugin Hooks**: Lifecycle hooks for validation events
85
- - **Custom Validators**: Extend VLD with your own validators
86
-
87
- #### Result Pattern
88
- - **`Ok()`/`Err()`**: Functional error handling
89
- - **`match()`**: Pattern matching on results
90
- - **`map()`/`flatMap()`**: Transform results
91
- - **`tryCatch()`**: Safe function execution
92
- - **`all()`**: Combine multiple results
93
-
94
- #### Event System
95
- - **`createEmitter()`**: Type-safe event emitter
96
- - **`createEventBus()`**: Global event bus
97
- - **Validation Events**: Parse start, success, error, field validation
98
-
99
- #### CLI Tools
100
- - **`vld validate`**: Validate data from command line
101
- - **`vld benchmark`**: Run performance benchmarks
102
- - **Colored Output**: Beautiful terminal output with pigment
103
-
104
- #### New Validators
105
- - **`v.discriminatedUnion()`**: Discriminated union types
106
- - **`v.xor()`**: Exclusive OR validation
107
- - **`v.file()`**: File upload validation
108
- - **`v.function()`**: Function validation
109
- - **`v.custom()`**: Type-safe custom validators
110
- - **`v.json()`**: JSON string validation with schema
111
- - **`v.lazy()`**: Recursive schema support
112
- - **`v.nan()`**: NaN validation
113
- - **`v.null()`**: Null validation
114
- - **`v.undefined()`**: Undefined validation
115
- - **`v.templateLiteral()`**: Template literal types
116
-
117
- #### New String Format Validators
118
- - **`v.hostname()`**: Hostname validation
119
- - **`v.emoji()`**: Emoji validation
120
- - **`v.base64()`/`v.base64url()`**: Base64 format validation
121
- - **`v.hex()`**: Hex string validation
122
- - **`v.jwt()`**: JWT format validation
123
- - **`v.nanoid()`/`v.cuid()`/`v.cuid2()`/`v.ulid()`**: ID format validation
124
- - **`v.mac()`**: MAC address validation
125
- - **`v.cidrv4()`/`v.cidrv6()`**: CIDR block validation
126
- - **`v.e164()`**: E.164 phone number validation
127
- - **`v.hash()`**: Hash validation (md5, sha1, sha256, sha384, sha512)
128
- - **`v.iso.date()`/`v.iso.time()`/`v.iso.dateTime()`/`v.iso.duration()`**: ISO format validation
129
-
130
- #### Enhanced Object Utilities
131
- - **`v.strictObject()`**: Strict mode object validation
132
- - **`v.looseObject()`**: Passthrough object validation
133
- - **`v.partialRecord()`**: Partial record validation
134
- - **`v.looseRecord()`**: Loose record validation
135
- - **`v.int()`**: Integer shortcut
136
- - **`v.int32()`**: 32-bit integer shortcut
137
- - **`v.nullish()`**: Null or undefined
138
- - **`v.NEVER`**: NEVER constant for transforms (Zod 4 parity)
139
-
140
- ### Codec System - Beyond Zod
141
- - **Bidirectional Transformations**: Full encode/decode support for data conversion
142
- - **19 Built-in Codecs**: String conversions, date parsing, JSON, URL, binary data
143
- - **Zod-Compatible**: All `stringToNumber`, `jsonCodec`, `base64ToBytes`, etc.
144
- - **Async Support**: Both sync and async codec operations
145
- - **Custom Codecs**: Create your own bidirectional transformations
146
- - **Type-Safe**: Full TypeScript support with perfect type inference
147
-
148
- ## Performance
149
-
150
- VLD is designed for speed and efficiency with recent optimizations delivering exceptional performance:
151
-
152
- ### Speed Benchmarks (v1.5.0)
153
- - **3.25x faster** for email validation
154
- - **3.23x faster** for number validation
155
- - **3.16x faster** for optional validation
156
- - **2.73x faster** for safeParse operations
157
- - **2.08x faster** for enum validation
158
- - **2.03x faster** for simple string validation
159
- - **1.98x faster** overall average performance
160
-
161
- ### Optimizations
162
- - **110x improvement** in union type validation
163
- - **Simplified email regex** for maximum performance
164
- - **Inline type checks** in object validation
165
- - **Optimized loops** with direct array assignment
166
- - **SafeParse optimization** to avoid try-catch overhead
167
- - **Pre-computed keys** with Set for O(1) lookups
168
-
169
- ### Memory Efficiency
170
- - **98% less memory** for validator creation
171
- - **51% less memory** for data parsing
172
- - **86% less memory** for error handling
173
- - **78% less memory** overall average
174
-
175
- ### A Note on Real-World Benchmarking
176
-
177
- Many validation library benchmarks can be misleading because they often test with **reused schema instances**:
178
-
179
- ```javascript
180
- // What benchmarks typically test (unrealistic):
181
- const schema = z.string();
182
- for (let i = 0; i < 1000000; i++) {
183
- schema.parse(data); // Same instance reused
184
- }
185
-
186
- // What happens in real applications:
187
- app.post('/api/user', (req, res) => {
188
- // New schema created for each request
189
- const schema = z.object({
190
- email: z.string().email(),
191
- age: z.number().min(18)
192
- });
193
- schema.parse(req.body);
194
- });
195
- ```
196
-
197
- When testing real-world patterns:
198
- - **Creating new instances**: VLD is **2000x faster** than Zod
199
- - **Reused instances**: Zod benefits from V8's singleton optimization
200
- - **Real applications**: Schemas are often created dynamically, where VLD excels
201
-
202
- Run `npm run benchmark:truth` to see the real performance difference.
203
-
204
- ## Installation
205
-
206
- ```bash
207
- npm install @oxog/vld
208
- # or
209
- yarn add @oxog/vld
210
- # or
211
- pnpm add @oxog/vld
212
- ```
213
-
214
- ## Quick Start
215
-
216
- ```typescript
217
- import { v } from '@oxog/vld';
218
-
219
- // It is recommended to import as `v` for consistency with Zod's `z`
220
- // and for a more concise syntax.
221
-
222
- // Define a schema
223
- const userSchema = v.object({
224
- name: v.string().min(2),
225
- email: v.string().email(),
226
- age: v.number().min(18).max(100),
227
- isActive: v.boolean()
228
- });
229
-
230
- // Validate data
231
- const result = userSchema.safeParse({
232
- name: 'John Doe',
233
- email: 'john@example.com',
234
- age: 25,
235
- isActive: true
236
- });
237
-
238
- if (result.success) {
239
- console.log('Valid user:', result.data);
240
- } else {
241
- console.log('Validation error:', result.error);
242
- }
243
- ```
244
-
245
- For advanced error formatting:
246
- ```typescript
247
- import { v, VldError, treeifyError, prettifyError, flattenError } from '@oxog/vld';
248
- ```
249
-
250
- ## API Reference
251
-
252
- ### Basic Types
253
-
254
- ```typescript
255
- v.string() // String validation
256
- v.number() // Number validation
257
- v.int() // Integer validation (shortcut)
258
- v.int32() // 32-bit integer validation
259
- v.boolean() // Boolean validation
260
- v.bigint() // BigInt validation
261
- v.symbol() // Symbol validation
262
- v.date() // Date validation
263
- v.uint8array()// Uint8Array validation
264
- v.literal() // Literal values
265
- v.enum() // Enum values (supports TypeScript enums)
266
- v.any() // Any type
267
- v.unknown() // Unknown type
268
- v.void() // Void type
269
- v.never() // Never type
270
- v.null() // Null type
271
- v.undefined() // Undefined type
272
- v.nan() // NaN type
273
- ```
274
-
275
- ### Advanced Types
276
-
277
- ```typescript
278
- // Collections
279
- v.array(v.string()) // Array validation
280
- v.tuple(v.string(), v.number()) // Fixed-length tuple
281
- v.record(v.number()) // Record/dictionary validation
282
- v.set(v.string()) // Set validation
283
- v.map(v.string(), v.number()) // Map validation
284
-
285
- // Objects
286
- v.object({ // Object schema
287
- name: v.string(),
288
- age: v.number()
289
- })
290
- v.strictObject({...}) // No extra fields allowed
291
- v.looseObject({...}) // Extra fields passed through
292
-
293
- // Composition
294
- v.union(v.string(), v.number()) // Union types
295
- v.intersection(schemaA, schemaB) // Intersection types
296
- v.discriminatedUnion('type', ...) // Discriminated union
297
- v.xor(schemaA, schemaB) // Exclusive OR
298
- v.optional(v.string()) // Optional fields
299
- v.nullable(v.string()) // Nullable fields
300
- v.nullish(v.string()) // Null or undefined
301
- ```
302
-
303
- ### String Validators
304
-
305
- ```typescript
306
- v.string()
307
- .min(5) // Minimum length
308
- .max(10) // Maximum length
309
- .length(8) // Exact length
310
- .email() // Email format
311
- .url() // URL format
312
- .uuid() // UUID format
313
- .regex(/pattern/) // Custom regex
314
- .startsWith('prefix') // String prefix
315
- .endsWith('suffix') // String suffix
316
- .includes('substring') // Contains substring
317
- .ip() // IP address (v4 or v6)
318
- .trim() // Trim whitespace
319
- .toLowerCase() // Convert to lowercase
320
- .toUpperCase() // Convert to uppercase
321
- .nonempty() // Non-empty string
322
- ```
323
-
324
- ### String Format Validators (Top-Level)
325
-
326
- ```typescript
327
- v.email() // Email validation
328
- v.uuid() // UUID validation
329
- v.uuid({ version: 'v4' }) // UUID v4 validation
330
- v.uuidv4() // UUID v4 shortcut
331
- v.hostname() // Hostname validation
332
- v.emoji() // Emoji validation
333
- v.base64() // Base64 format
334
- v.base64url() // Base64 URL-safe format
335
- v.hex() // Hex string
336
- v.jwt() // JWT format
337
- v.nanoid() // NanoID format
338
- v.cuid() // CUID format
339
- v.cuid2() // CUID2 format
340
- v.ulid() // ULID format
341
- v.ipv4() // IPv4 address
342
- v.ipv6() // IPv6 address
343
- v.mac() // MAC address
344
- v.cidrv4() // IPv4 CIDR block
345
- v.cidrv6() // IPv6 CIDR block
346
- v.e164() // E.164 phone number
347
- v.hash('sha256') // Hash validation
348
- v.iso.date() // ISO date format
349
- v.iso.time() // ISO time format
350
- v.iso.dateTime() // ISO datetime format
351
- v.iso.duration() // ISO duration format
352
- ```
353
-
354
- ### Number Validators
355
-
356
- ```typescript
357
- v.number()
358
- .min(0) // Minimum value
359
- .max(100) // Maximum value
360
- .int() // Integer only
361
- .positive() // Positive numbers
362
- .negative() // Negative numbers
363
- .nonnegative() // >= 0
364
- .nonpositive() // <= 0
365
- .finite() // Finite numbers
366
- .safe() // Safe integers
367
- .multipleOf(5) // Multiple of value
368
- ```
369
-
370
- ### Arrays and Objects
371
-
372
- ```typescript
373
- // Arrays
374
- v.array(v.string()) // Array of strings
375
- .min(1) // Minimum length
376
- .max(10) // Maximum length
377
- .length(5) // Exact length
378
- .nonempty() // Non-empty array
379
-
380
- // Objects
381
- v.object({
382
- name: v.string(),
383
- age: v.number()
384
- })
385
- .partial() // All fields optional
386
- .strict() // No extra fields
387
- .passthrough() // Allow extra fields
388
- ```
389
-
390
- ### Composite Types
391
-
392
- ```typescript
393
- // Optional
394
- v.optional(v.string()) // string | undefined
395
-
396
- // Nullable
397
- v.nullable(v.string()) // string | null
398
-
399
- // Nullish
400
- v.nullish(v.string()) // string | null | undefined
401
-
402
- // Union
403
- v.union(v.string(), v.number()) // string | number
404
-
405
- // Discriminated Union
406
- v.discriminatedUnion('type',
407
- v.object({ type: v.literal('a'), a: v.string() }),
408
- v.object({ type: v.literal('b'), b: v.number() })
409
- )
410
-
411
- // Literal
412
- v.literal('active') // 'active'
413
-
414
- // Enum
415
- v.enum('red', 'green', 'blue') // 'red' | 'green' | 'blue'
416
- ```
417
-
418
- ### Type Coercion
419
-
420
- ```typescript
421
- // Coerce strings from various types
422
- v.coerce.string().parse(123) // "123"
423
- v.coerce.string().parse(true) // "true"
424
-
425
- // Coerce numbers from strings/booleans
426
- v.coerce.number().parse("123") // 123
427
- v.coerce.number().parse(true) // 1
428
-
429
- // Coerce booleans from strings/numbers
430
- v.coerce.boolean().parse("true") // true
431
- v.coerce.boolean().parse(1) // true
432
-
433
- // Coerce BigInt from strings/numbers
434
- v.coerce.bigint().parse("123") // 123n
435
- v.coerce.bigint().parse(456) // 456n
436
-
437
- // Coerce Date from strings/timestamps
438
- v.coerce.date().parse("2023-01-01") // Date object
439
- v.coerce.date().parse(1672531200000) // Date object
440
- ```
441
-
442
- ### Object Schema Methods
443
-
444
- ```typescript
445
- const userSchema = v.object({
446
- name: v.string(),
447
- age: v.number(),
448
- email: v.string(),
449
- role: v.string()
450
- });
451
-
452
- // Pick specific fields
453
- const publicSchema = userSchema.pick('name', 'age');
454
- // Type: { name: string; age: number }
455
-
456
- // Omit sensitive fields
457
- const safeSchema = userSchema.omit('email', 'role');
458
- // Type: { name: string; age: number }
459
-
460
- // Extend with new fields
461
- const extendedSchema = userSchema.extend({
462
- isActive: v.boolean(),
463
- lastLogin: v.date()
464
- });
465
- // Type: { name: string; age: number; email: string; role: string; isActive: boolean; lastLogin: Date }
466
- ```
467
-
468
- ### Advanced Validation Methods
469
-
470
- ```typescript
471
- // Custom validation with refine()
472
- const positiveNumber = v.number()
473
- .refine(n => n > 0, "Number must be positive");
474
-
475
- // Data transformation with transform()
476
- const uppercaseString = v.string()
477
- .transform(s => s.toUpperCase());
478
-
479
- // Default values for undefined
480
- const withDefault = v.string().default("fallback");
481
- withDefault.parse(undefined); // "fallback"
482
-
483
- // Catch errors and provide fallback
484
- const withCatch = v.number().catch(-1);
485
- withCatch.parse("invalid"); // -1
486
-
487
- // Method chaining
488
- const complexSchema = v.string()
489
- .min(3)
490
- .transform(s => s.trim())
491
- .refine(s => s.includes('@'), 'Must contain @')
492
- .default('user@example.com');
493
- ```
494
-
495
- ### Special Validators
496
-
497
- ```typescript
498
- // JSON validator with optional schema
499
- v.json() // Any valid JSON
500
- v.json(v.object({ name: v.string() })) // Typed JSON
501
-
502
- // Lazy for recursive schemas
503
- const categorySchema = v.lazy(() =>
504
- v.object({
505
- name: v.string(),
506
- children: v.array(categorySchema).optional()
507
- })
508
- );
509
-
510
- // Custom validator
511
- v.custom({
512
- check: (val) => typeof val === 'string' && val.length > 0,
513
- message: 'Must be a non-empty string'
514
- });
515
-
516
- // File validator
517
- v.file()
518
- .maxSize(5 * 1024 * 1024) // 5MB
519
- .type(['image/png', 'image/jpeg']);
520
-
521
- // Function validator
522
- v.function()
523
- .args(v.string(), v.number())
524
- .returns(v.boolean());
525
- ```
526
-
527
- ### Type Inference
528
-
529
- ```typescript
530
- import { v, Infer } from '@oxog/vld';
531
-
532
- const schema = v.object({
533
- name: v.string(),
534
- age: v.number()
535
- });
536
-
537
- // Automatically infer the type
538
- type User = Infer<typeof schema>;
539
- // { name: string; age: number }
540
- ```
541
-
542
- ### Error Formatting Types
543
-
544
- ```typescript
545
- import {
546
- VldError, // Main error class
547
- VldIssue, // Individual validation issue
548
- VldErrorTree, // Nested error structure
549
- VldFlattenedError // Flattened error structure
550
- } from '@oxog/vld';
551
- ```
552
-
553
- ### Custom Error Messages
554
-
555
- ```typescript
556
- const schema = v.string().min(8, 'Password must be at least 8 characters');
557
-
558
- const result = schema.safeParse('short');
559
- if (!result.success) {
560
- console.log(result.error.message); // 'Password must be at least 8 characters'
561
- }
562
- ```
563
-
564
- ## Internationalization (i18n)
565
-
566
- VLD supports 27+ languages out of the box with comprehensive error messages:
567
-
568
- ```typescript
569
- import { v, setLocale } from '@oxog/vld';
570
-
571
- // Default is English
572
- const schema = v.string().min(5);
573
- schema.safeParse('Hi'); // Error: "String must be at least 5 characters"
574
-
575
- // Switch to Turkish
576
- setLocale('tr');
577
- schema.safeParse('Hi'); // Error: "Metin en az 5 karakter olmali"
578
-
579
- // Switch to Spanish
580
- setLocale('es');
581
- schema.safeParse('Hi'); // Error: "La cadena debe tener al menos 5 caracteres"
582
-
583
- // Switch to Japanese
584
- setLocale('ja');
585
- schema.safeParse('Hi'); // Error: "..."
586
- ```
587
-
588
- ### Supported Languages
589
-
590
- #### Base Languages (15):
591
- - English (`en`) - Turkish (`tr`) - Spanish (`es`) - French (`fr`) - German (`de`)
592
- - Italian (`it`) - Portuguese (`pt`) - Russian (`ru`) - Japanese (`ja`) - Korean (`ko`)
593
- - Chinese (`zh`) - Arabic (`ar`) - Hindi (`hi`) - Dutch (`nl`) - Polish (`pl`)
594
-
595
- #### European Languages (4):
596
- - Danish (`da`) - Swedish (`sv`) - Norwegian (`no`) - Finnish (`fi`)
597
-
598
- #### Asian Languages (4):
599
- - Thai (`th`) - Vietnamese (`vi`) - Indonesian (`id`) - Bengali (`bn`)
600
-
601
- #### African Languages (2):
602
- - Swahili (`sw`) - Afrikaans (`af`)
603
-
604
- #### American Languages (2):
605
- - Portuguese Brazil (`pt-BR`) - Spanish Mexico (`es-MX`)
606
-
607
- **Plus 75+ additional languages** supported through comprehensive type definitions with English fallback.
608
-
609
- ## Error Handling & Formatting
610
-
611
- VLD provides advanced error formatting utilities similar to Zod's error handling system.
612
-
613
- ### Error Formatting Utilities
614
-
615
- ```typescript
616
- import { v, VldError, treeifyError, prettifyError, flattenError } from '@oxog/vld';
617
-
618
- const userSchema = v.object({
619
- username: v.string().min(3),
620
- favoriteNumbers: v.array(v.number()),
621
- profile: v.object({
622
- name: v.string(),
623
- email: v.string().email()
624
- })
625
- });
626
-
627
- const result = userSchema.safeParse({
628
- username: 'ab',
629
- favoriteNumbers: [1, 'two', 3],
630
- profile: {
631
- name: '',
632
- email: 'invalid-email'
633
- },
634
- extraField: 'not allowed'
635
- });
636
-
637
- if (!result.success) {
638
- const error = result.error as VldError;
639
-
640
- // 1. Tree Format - Nested structure for complex UIs
641
- const tree = treeifyError(error);
642
-
643
- // 2. Pretty Format - Human-readable console output
644
- const pretty = prettifyError(error);
645
-
646
- // 3. Flatten Format - Simple form validation
647
- const flattened = flattenError(error);
648
- }
649
- ```
650
-
651
- ### Using Error Formats in Practice
652
-
653
- #### React Form Validation
654
- ```typescript
655
- function UserForm() {
656
- const [errors, setErrors] = useState<VldFlattenedError | null>(null);
657
-
658
- const handleSubmit = (data: unknown) => {
659
- const result = userSchema.safeParse(data);
660
-
661
- if (!result.success) {
662
- setErrors(flattenError(result.error as VldError));
663
- } else {
664
- setErrors(null);
665
- }
666
- };
667
-
668
- return (
669
- <form onSubmit={handleSubmit}>
670
- {errors?.formErrors.map(error => (
671
- <div key={error} className="form-error">{error}</div>
672
- ))}
673
-
674
- <input name="username" />
675
- {errors?.fieldErrors.username?.map(error => (
676
- <div key={error} className="field-error">{error}</div>
677
- ))}
678
- </form>
679
- );
680
- }
681
- ```
682
-
683
- #### API Error Responses
684
- ```typescript
685
- app.post('/api/users', (req, res) => {
686
- const result = userSchema.safeParse(req.body);
687
-
688
- if (!result.success) {
689
- const tree = treeifyError(result.error as VldError);
690
- res.status(400).json({
691
- error: 'Validation failed',
692
- details: tree
693
- });
694
- }
695
- });
696
- ```
697
-
698
- ## Advanced Examples
699
-
700
- ### Complex Validation with New Features
701
-
702
- ```typescript
703
- const postSchema = v.object({
704
- id: v.union(v.string().uuid(), v.number()),
705
- title: v.string().min(5).max(100),
706
- content: v.string().min(10),
707
- author: v.object({
708
- name: v.string(),
709
- email: v.string().email(),
710
- age: v.coerce.number(),
711
- }),
712
- tags: v.set(v.string()).default(new Set()),
713
- metadata: v.record(v.any()),
714
- coordinates: v.tuple(v.number(), v.number()),
715
- publishedAt: v.date().default(() => new Date()),
716
- status: v.enum('draft', 'published', 'archived')
717
- });
718
-
719
- // Extend with additional fields
720
- const blogPostSchema = postSchema.extend({
721
- viewCount: v.bigint().default(0n),
722
- categories: v.array(v.string()).min(1),
723
- featured: v.boolean().default(false)
724
- });
725
- ```
726
-
727
- ### Discriminated Union
728
-
729
- ```typescript
730
- const eventSchema = v.discriminatedUnion('type',
731
- v.object({
732
- type: v.literal('click'),
733
- x: v.number(),
734
- y: v.number()
735
- }),
736
- v.object({
737
- type: v.literal('scroll'),
738
- direction: v.enum('up', 'down'),
739
- distance: v.number()
740
- }),
741
- v.object({
742
- type: v.literal('keypress'),
743
- key: v.string(),
744
- modifiers: v.array(v.enum('ctrl', 'alt', 'shift'))
745
- })
746
- );
747
-
748
- // Type-safe parsing
749
- const event = eventSchema.parse({
750
- type: 'click',
751
- x: 100,
752
- y: 200
753
- });
754
- ```
755
-
756
- ### Recursive Schemas
757
-
758
- ```typescript
759
- const categorySchema: ReturnType<typeof v.lazy> = v.lazy(() =>
760
- v.object({
761
- name: v.string(),
762
- slug: v.string().regex(/^[a-z0-9-]+$/),
763
- children: v.array(categorySchema).optional()
764
- })
765
- );
766
-
767
- const category = categorySchema.parse({
768
- name: 'Electronics',
769
- slug: 'electronics',
770
- children: [
771
- {
772
- name: 'Phones',
773
- slug: 'phones',
774
- children: [
775
- { name: 'Smartphones', slug: 'smartphones' }
776
- ]
777
- }
778
- ]
779
- });
780
- ```
781
-
782
- ### Type-Safe Forms
783
-
784
- ```typescript
785
- const loginSchema = v.object({
786
- username: v.string().min(3),
787
- password: v.string().min(8),
788
- rememberMe: v.optional(v.boolean())
789
- });
790
-
791
- type LoginForm = Infer<typeof loginSchema>;
792
-
793
- function handleLogin(data: unknown) {
794
- const result = loginSchema.safeParse(data);
795
-
796
- if (result.success) {
797
- const { username, password, rememberMe } = result.data;
798
- // ... handle login
799
- }
800
- }
801
- ```
802
-
803
- ## Codecs - Bidirectional Transformations
804
-
805
- VLD introduces **codecs** - powerful bidirectional transformations that can convert data between different representations.
806
-
807
- ### What are Codecs?
808
-
809
- Codecs enable safe, type-checked conversions between different data formats:
810
-
811
- ```typescript
812
- import { stringToNumber, jsonCodec, base64ToBytes } from '@oxog/vld';
813
-
814
- // String to number conversion
815
- const age = stringToNumber.parse('25'); // 25
816
- const price = stringToNumber.encode(99.99); // "99.99"
817
-
818
- // JSON codec
819
- const userJson = jsonCodec();
820
- const user = userJson.parse('{"name":"John","age":30}');
821
- const jsonString = userJson.encode(user);
822
-
823
- // Binary data
824
- const bytes = base64ToBytes.parse('SGVsbG8gV29ybGQ=');
825
- ```
826
-
827
- ### Built-in Codecs
828
-
829
- #### String Conversion Codecs
830
- ```typescript
831
- import { stringToNumber, stringToInt, stringToBigInt, stringToBoolean } from '@oxog/vld';
832
-
833
- stringToNumber.parse('42.5'); // 42.5
834
- stringToInt.parse('42'); // 42
835
- stringToBigInt.parse('123n'); // 123n
836
- stringToBoolean.parse('true'); // true
837
- ```
838
-
839
- #### Date Conversion Codecs
840
- ```typescript
841
- import { isoDatetimeToDate, epochSecondsToDate, epochMillisToDate } from '@oxog/vld';
842
-
843
- isoDatetimeToDate.parse('2023-12-25T10:30:00.000Z'); // Date
844
- epochSecondsToDate.parse(1703505000); // Date
845
- epochMillisToDate.parse(1703505000000); // Date
846
- ```
847
-
848
- #### URL Codecs
849
- ```typescript
850
- import { stringToURL, stringToHttpURL, uriComponent } from '@oxog/vld';
851
-
852
- stringToURL.parse('https://example.com/path?q=1');
853
- stringToHttpURL.parse('https://api.example.com');
854
- uriComponent.parse('Hello World!'); // "Hello%20World!"
855
- ```
856
-
857
- #### Binary Data Codecs
858
- ```typescript
859
- import { base64ToBytes, hexToBytes, utf8ToBytes, bytesToUtf8 } from '@oxog/vld';
860
-
861
- base64ToBytes.parse('SGVsbG8='); // Uint8Array
862
- hexToBytes.parse('48656c6c6f'); // Uint8Array
863
- utf8ToBytes.parse('Hello'); // Uint8Array
864
- bytesToUtf8.parse(new Uint8Array([72, 101, 108, 108, 111])); // "Hello"
865
- ```
866
-
867
- ### Custom Codecs
868
-
869
- ```typescript
870
- const csvToArray = v.codec(
871
- v.string(),
872
- v.array(v.string()),
873
- {
874
- decode: (csv: string) => csv.split(',').map(s => s.trim()),
875
- encode: (arr: string[]) => arr.join(', ')
876
- }
877
- );
878
-
879
- const tags = csvToArray.parse('react, typescript, vld');
880
- // ["react", "typescript", "vld"]
881
-
882
- const csvString = csvToArray.encode(['node', 'express', 'api']);
883
- // "node, express, api"
884
- ```
885
-
886
- ## Plugin System
887
-
888
- VLD v1.5.0 introduces a powerful plugin system for extending functionality.
889
-
890
- ### Creating a Plugin
891
-
892
- ```typescript
893
- import { definePlugin, usePlugin, v } from '@oxog/vld';
894
-
895
- // Define a custom plugin
896
- const myPlugin = definePlugin({
897
- name: 'my-plugin',
898
- version: '1.0.0',
899
-
900
- // Custom validators
901
- validators: {
902
- phoneNumber: () => v.string().regex(/^\+?[1-9]\d{1,14}$/),
903
- postalCode: () => v.string().regex(/^\d{5}(-\d{4})?$/)
904
- },
905
-
906
- // Custom transforms
907
- transforms: {
908
- normalizePhone: (phone: string) => phone.replace(/[^\d+]/g, '')
909
- },
910
-
911
- // Lifecycle hooks
912
- install(kernel) {
913
- console.log('Plugin installed!');
914
- }
915
- });
916
-
917
- // Register the plugin
918
- usePlugin(myPlugin);
919
- ```
920
-
921
- ### Using Plugin Validators
922
-
923
- ```typescript
924
- import { createVldKernel, usePlugin } from '@oxog/vld';
925
-
926
- const kernel = createVldKernel({ debug: true });
927
-
928
- kernel.use(myPlugin);
929
-
930
- // Access custom validators
931
- const phoneSchema = kernel.validator('phoneNumber');
932
- phoneSchema.parse('+1234567890');
933
- ```
934
-
935
- ## Result Pattern
936
-
937
- VLD v1.5.0 includes a functional Result pattern for error handling.
938
-
939
- ### Basic Usage
940
-
941
- ```typescript
942
- import { Ok, Err, match, map, flatMap, tryCatch } from '@oxog/vld';
943
-
944
- // Create results
945
- const success = Ok(42);
946
- const failure = Err(new Error('Something went wrong'));
947
-
948
- // Pattern matching
949
- const message = match(success, {
950
- ok: (value) => `Got: ${value}`,
951
- err: (error) => `Error: ${error.message}`
952
- });
953
-
954
- // Transform results
955
- const doubled = map(success, (n) => n * 2); // Ok(84)
956
-
957
- // Chain operations
958
- const result = flatMap(success, (n) =>
959
- n > 0 ? Ok(n * 2) : Err(new Error('Must be positive'))
960
- );
961
-
962
- // Safe function execution
963
- const parsed = tryCatch(() => JSON.parse('{"a":1}'));
964
- ```
965
-
966
- ### With Validation
967
-
968
- ```typescript
969
- import { v, isOk, isErr, unwrapOr } from '@oxog/vld';
970
-
971
- const schema = v.object({
972
- name: v.string(),
973
- age: v.number().min(0)
974
- });
975
-
976
- const result = schema.safeParse(data);
977
-
978
- if (isOk(result)) {
979
- console.log('Valid:', result.data);
980
- } else {
981
- console.log('Invalid:', result.error);
982
- }
983
-
984
- // With default value
985
- const user = unwrapOr(result, { name: 'Guest', age: 0 });
986
- ```
987
-
988
- ### Combining Results
989
-
990
- ```typescript
991
- import { all, fromNullable } from '@oxog/vld';
992
-
993
- // Combine multiple results
994
- const results = [Ok(1), Ok(2), Ok(3)];
995
- const combined = all(results); // Ok([1, 2, 3])
996
-
997
- // Convert nullable to Result
998
- const maybeValue: string | null = getValue();
999
- const result = fromNullable(maybeValue, new Error('Value is null'));
1000
- ```
1001
-
1002
- ## CLI Tools
1003
-
1004
- VLD includes command-line tools for validation and benchmarking.
1005
-
1006
- ### Installation
1007
-
1008
- ```bash
1009
- npm install -g @oxog/vld
1010
- # or use npx
1011
- npx vld --help
1012
- ```
1013
-
1014
- ### Commands
1015
-
1016
- ```bash
1017
- # Show help
1018
- vld --help
1019
-
1020
- # Validate data
1021
- vld validate schema.json data.json
1022
-
1023
- # Run benchmarks
1024
- vld benchmark
1025
-
1026
- # Show version
1027
- vld --version
1028
- ```
1029
-
1030
- ### Programmatic CLI
1031
-
1032
- ```typescript
1033
- import { createCli, vldCli } from '@oxog/vld/cli';
1034
-
1035
- // Use the built-in CLI
1036
- vldCli.run(process.argv.slice(2));
1037
-
1038
- // Or create a custom CLI
1039
- const cli = createCli('my-app', '1.0.0', 'My validation app')
1040
- .command({
1041
- name: 'validate',
1042
- description: 'Validate data',
1043
- action: async (args, options) => {
1044
- // Custom validation logic
1045
- }
1046
- });
1047
-
1048
- cli.run(process.argv.slice(2));
1049
- ```
1050
-
1051
- ## Logger & Colored Output
1052
-
1053
- VLD includes a logging system and colored terminal output.
1054
-
1055
- ### Logger
1056
-
1057
- ```typescript
1058
- import { createLogger, setLogLevel, enableDebug } from '@oxog/vld';
1059
-
1060
- // Create a logger
1061
- const logger = createLogger({ prefix: 'VLD' });
1062
-
1063
- logger.info('Processing...');
1064
- logger.warn('Deprecated feature');
1065
- logger.error('Validation failed');
1066
- logger.debug('Debug info');
1067
-
1068
- // Set log level globally
1069
- setLogLevel('debug');
1070
-
1071
- // Enable debug mode
1072
- enableDebug();
1073
- ```
1074
-
1075
- ### Colored Output (Pigment)
1076
-
1077
- ```typescript
1078
- import { pigment, red, green, blue, bold, dim } from '@oxog/vld';
1079
-
1080
- console.log(red('Error!'));
1081
- console.log(green('Success!'));
1082
- console.log(bold(blue('Important')));
1083
- console.log(dim('Less important'));
1084
-
1085
- // Or use the pigment object
1086
- console.log(pigment.red('Error!'));
1087
- console.log(pigment.bold(pigment.green('Success!')));
1088
- ```
1089
-
1090
- ## VLD vs. Zod
1091
-
1092
- VLD is designed as a compelling alternative to Zod, offering full feature parity while delivering significant improvements.
1093
-
1094
- ### Feature Comparison
1095
-
1096
- | Feature | VLD | Zod |
1097
- | ----------------------- | ---------------------------------- | ------------------------------------ |
1098
- | **Performance** | **~1.98x faster** (average) | Baseline |
1099
- | **Memory Usage** | **~78% less** overall | Baseline |
1100
- | **Internationalization**| **Built-in (27+ languages)** | Requires third-party library |
1101
- | **Dependencies** | **Zero** | `zod-i18n` for locales |
1102
- | **Bundle Size** | Smaller | Larger |
1103
- | **API** | 100% Zod-compatible | Standard Zod API |
1104
- | **Plugin System** | **Built-in** | Not available |
1105
- | **Result Pattern** | **Built-in** | Not available |
1106
- | **CLI Tools** | **Built-in** | Not available |
1107
- | **Codecs** | Built-in, bidirectional | Via external `zod-codecs` |
1108
- | **Type Inference** | Excellent | Excellent |
1109
-
1110
- ### Seamless Migration from Zod
1111
-
1112
- ```javascript
1113
- // Before (Zod)
1114
- import { z } from 'zod';
1115
- const schema = z.string().email();
1116
-
1117
- // After (VLD) - Exact same syntax!
1118
- import { v } from '@oxog/vld';
1119
- const schema = v.string().email();
1120
- ```
1121
-
1122
- ## Benchmarks
1123
-
1124
- ### Performance Results
1125
-
1126
- | Test Case | VLD Performance | Improvement |
1127
- |-----------|----------------|-------------|
1128
- | Simple String | 73.0M ops/sec | **2.03x faster** |
1129
- | Email Validation | 21.8M ops/sec | **3.25x faster** |
1130
- | Number Validation | 36.3M ops/sec | **3.23x faster** |
1131
- | Simple Object | 7.1M ops/sec | **1.02x faster** |
1132
- | Complex Object | 1.9M ops/sec | **1.34x faster** |
1133
- | Array Validation | 7.5M ops/sec | **1.35x faster** |
1134
- | Union Types | 7.1M ops/sec | **1.29x faster** |
1135
- | Optional Values | 36.1M ops/sec | **3.16x faster** |
1136
- | SafeParse | 60.0M ops/sec | **2.73x faster** |
1137
- | Type Coercion | 20.4M ops/sec | **1.01x faster** |
1138
- | Enum Validation | 60.3M ops/sec | **2.08x faster** |
1139
- | Discriminated Union | 3.6M ops/sec | Zod 1.27x faster |
1140
-
1141
- **VLD won 11/12 tests | Average: 1.98x faster than Zod**
1142
-
1143
- ### Run Benchmarks
1144
-
1145
- ```bash
1146
- # Quick performance comparison
1147
- npm run benchmark
1148
-
1149
- # Memory usage comparison
1150
- npm run benchmark:memory
1151
-
1152
- # Startup time comparison
1153
- npm run benchmark:startup
1154
-
1155
- # Run all benchmarks
1156
- npm run benchmark:all
1157
- ```
1158
-
1159
- ## Contributing
1160
-
1161
- Contributions are welcome! Please feel free to submit a Pull Request.
1162
-
1163
- ## Links
1164
-
1165
- - [Documentation](https://vld.oxog.dev)
1166
- - [NPM Package](https://www.npmjs.com/package/@oxog/vld)
1167
- - [GitHub Repository](https://github.com/ersinkoc/vld)
1168
-
1169
- ---
1170
-
1171
- Made with Love by [Ersin KOC](https://github.com/ersinkoc)
1
+ # VLD - Fast & Lightweight TypeScript Validation Library
2
+
3
+ [![NPM Version](https://img.shields.io/npm/v/@oxog/vld.svg)](https://www.npmjs.com/package/@oxog/vld) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/) [![Zero Dependencies](https://img.shields.io/badge/Dependencies-0-green.svg)](package.json) [![Test Coverage](https://img.shields.io/badge/Coverage-100%25-brightgreen.svg)](package.json)
4
+
5
+ VLD is a blazing-fast, type-safe validation library for TypeScript and JavaScript with **Zod-compatible root and subpath APIs**. Built with performance in mind, it provides a simple and intuitive API while maintaining excellent type inference and 27+ language internationalization support.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Features](#features)
10
+ - [Performance](#performance)
11
+ - [Installation](#installation)
12
+ - [Quick Start](#quick-start)
13
+ - [API Reference](#api-reference)
14
+ - [Internationalization (i18n)](#internationalization-i18n)
15
+ - [Error Handling & Formatting](#error-handling--formatting)
16
+ - [Advanced Examples](#advanced-examples)
17
+ - [Codecs - Bidirectional Transformations](#codecs---bidirectional-transformations)
18
+ - [Plugin System](#plugin-system)
19
+ - [Result Pattern](#result-pattern)
20
+ - [CLI Tools](#cli-tools)
21
+ - [Logger & Colored Output](#logger--colored-output)
22
+ - [VLD vs. Zod](#vld-vs-zod)
23
+ - [Benchmarks](#benchmarks)
24
+ - [Contributing](#contributing)
25
+ - [Links](#links)
26
+
27
+ ## Features
28
+
29
+ ### Core Features
30
+ - **Blazing Fast**: Optimized for V8 engine with superior performance
31
+ - **Type-Safe**: Full TypeScript support with excellent type inference
32
+ - **Zero Dependencies**: Lightweight with no external dependencies
33
+ - **Tree-Shakeable**: Only import what you need
34
+ - **Composable**: Chain validations for complex schemas
35
+ - **Advanced Error Formatting**: Tree, pretty, and flatten error utilities
36
+ - **Multi-language**: Built-in support for 27+ languages
37
+ - **100% Statement / Branch / Function / Line Coverage**: Rigorously tested with 2502 passing tests
38
+ - **Release-Gated Performance**: CI guards require VLD to stay faster than the latest stable Zod across runtime, startup, and memory benchmarks
39
+ - **Drop-in App Verification**: A real TypeScript fixture is compiled and run once with `zod` and once with built VLD, then normalized runtime output is compared
40
+ - **Audited Compatibility Contract**: Modern Zod 4.4.3 factory signatures, schema direction methods, release-fix behaviors, and JSON Schema defaults are differential-tested; see [the compatibility policy](docs/ZOD_COMPATIBILITY.md)
41
+
42
+ ### Advanced Zod-Compatible Features
43
+ - **Type Coercion**: `v.coerce.string()`, `v.coerce.number()`, `v.coerce.boolean()`, etc.
44
+ - **Advanced Types**: BigInt, Symbol, Tuple, Record, Set, Map validation
45
+ - **Intersection Types**: Combine multiple schemas with intelligent merging
46
+ - **Custom Validation**: `refine()` for custom predicates and validation logic
47
+ - **Data Transformation**: `transform()` for post-validation data transformation
48
+ - **Default Values**: `default()` for handling undefined inputs elegantly
49
+ - **Fallback Handling**: `catch()` for graceful error recovery
50
+ - **Object Utilities**: `pick()`, `omit()`, `extend()` for flexible object schemas
51
+
52
+ ### New in v2.2.x - Error Parity, Canary Parity, and Minified Builds
53
+
54
+ #### Zod 4-Compatible Error Issues
55
+ Validation failures now carry Zod 4's structured issue shape, so error-handling code ports across unchanged:
56
+ - `invalid_type` issues expose `expected` and `received` and use the `"Invalid input: expected X, received Y"` message format
57
+ - `too_small` / `too_big` issues expose `minimum`, `maximum`, `origin`, and `inclusive`
58
+ - `invalid_format` issues expose `format`, `origin`, and `pattern`; `invalid_value` issues expose a `values` array
59
+ - `parse()` throws `VldError` (which extends `Error`) for every validator, matching Zod's throw behavior
60
+
61
+ #### New Parity Helpers
62
+ ```typescript
63
+ import { v, deepPartial, input, output } from '@oxog/vld';
64
+
65
+ v.creditCard().parse('4242424242424242'); // regex plus Luhn checksum
66
+
67
+ const schema = v.object({
68
+ profile: v.object({ name: v.string(), age: v.number() })
69
+ });
70
+
71
+ const draft = deepPartial(schema); // every nested field optional
72
+ const inputSide = input(schema); // input-side view of a pipe
73
+ const outputSide = output(schema); // output-side view of a pipe
74
+ ```
75
+ - `deepPartial()` walks children first, mirroring Zod's `visit.js` ordering, and stays cycle-safe through lazy deferral
76
+ - `input()` / `output()` resolve pipe direction the way Zod's root helpers do
77
+ - `@oxog/vld/v4/core` gained the matching `_creditCard`, `isValidCreditCard`, `standardProps`, `handleUnrepresentable`, `$ZodCyclicError`, `attachMemoizer`, and `isBackEdge` shims
78
+
79
+ #### Minified Release Builds
80
+ - Release artifacts ship minified by default (opt out with `VLD_MINIFY=0`)
81
+ - Mangling preserves `/^Vld/` class names, because JSON Schema conversion dispatches on `schema.constructor.name`
82
+ - A built-CJS guard in `verify:drop-in` asserts name-dispatched composites against the minified bundle, so this can never silently regress again
83
+
84
+ ### NEW in v2.0.0 - Modular Architecture
85
+
86
+ #### Tree-Shakable Mini API
87
+ ```typescript
88
+ import { string, number, object, optional } from '@oxog/vld/mini';
89
+
90
+ const schema = object({
91
+ name: string().min(1),
92
+ age: optional(number().positive()),
93
+ });
94
+ ```
95
+ - **82% smaller bundles** when using only needed validators
96
+ - Individual factory functions for optimal tree-shaking
97
+ - Full TypeScript support with identical type inference
98
+
99
+ #### Lazy Locale Loading
100
+
101
+ > **Bundle-size contract:** the lazy entrypoint is published as
102
+ > `@oxog/vld/locales/lazy` (`src/locales/lazy.ts`). It uses dynamic `import()`
103
+ > for each locale on first use, so tree-shaken bundles ship **only English by
104
+ > default**. Importing the plain `@oxog/vld/locales` subpath (or the root
105
+ > `@oxog/vld` package) eagerly pulls every locale into the graph; pick the
106
+ > `lazy` subpath if you only need one or two languages in production.
107
+
108
+ ```typescript
109
+ import { setLocaleAsync, preloadLocales } from '@oxog/vld/locales/lazy';
110
+
111
+ // First call loads the locale on demand; subsequent calls hit the cache.
112
+ await setLocaleAsync('tr');
113
+
114
+ // SSR / batch warm-up: preload what you need before serving traffic.
115
+ await preloadLocales(['en', 'de', 'ja']);
116
+ ```
117
+ - **92% bundle reduction** when you only ship English plus the locales you pre-load
118
+ - `setLocaleAsync()` is true async dynamic-import, not a sync wrapper
119
+ - `preloadLocales()` for SSR/batch loading
120
+ - Backwards-compatible `setLocale()` is still available on the eager entrypoint
121
+
122
+ #### Dual ESM/CJS Build
123
+ - ESM builds for modern bundlers (Vite, esbuild)
124
+ - CJS builds for Node.js and legacy environments
125
+ - Proper `exports` field with conditional exports
126
+
127
+ ### NEW in v1.5.0 - Major Platform Release
128
+
129
+ #### Plugin System
130
+ - **`definePlugin()`**: Create custom plugins with validators, transforms, and codecs
131
+ - **`usePlugin()`**: Register plugins globally
132
+ - **Plugin Hooks**: Lifecycle hooks for validation events
133
+ - **Custom Validators**: Extend VLD with your own validators
134
+
135
+ #### Result Pattern
136
+ - **`Ok()`/`Err()`**: Functional error handling
137
+ - **`match()`**: Pattern matching on results
138
+ - **`map()`/`flatMap()`**: Transform results
139
+ - **`tryCatch()`**: Safe function execution
140
+ - **`all()`**: Combine multiple results
141
+
142
+ #### Event System
143
+ - **`createEmitter()`**: Type-safe event emitter
144
+ - **`createEventBus()`**: Global event bus
145
+ - **Validation Events**: Parse start, success, error, field validation
146
+
147
+ #### CLI Tools
148
+ - **`vld validate`**: Validate data from command line
149
+ - **`vld benchmark`**: Run performance benchmarks
150
+ - **Colored Output**: Beautiful terminal output with pigment
151
+
152
+ #### New Validators
153
+ - **`v.discriminatedUnion()`**: Discriminated union types
154
+ - **`v.xor()`**: Exclusive OR validation
155
+ - **`v.file()`**: File upload validation
156
+ - **`v.function()`**: Function validation
157
+ - **`v.custom()`**: Type-safe custom validators
158
+ - **`v.json()`**: JSON string validation with schema
159
+ - **`v.lazy()`**: Recursive schema support
160
+ - **`v.nan()`**: NaN validation
161
+ - **`v.null()`**: Null validation
162
+ - **`v.undefined()`**: Undefined validation
163
+ - **`v.templateLiteral()`**: Template literal types
164
+
165
+ #### New String Format Validators
166
+ - **`v.hostname()`**: Hostname validation
167
+ - **`v.emoji()`**: Emoji validation
168
+ - **`v.base64()`/`v.base64url()`**: Base64 format validation
169
+ - **`v.hex()`**: Hex string validation
170
+ - **`v.jwt()`**: JWT format validation
171
+ - **`v.nanoid()`/`v.cuid()`/`v.cuid2()`/`v.ulid()`**: ID format validation
172
+ - **`v.mac()`**: MAC address validation
173
+ - **`v.cidrv4()`/`v.cidrv6()`**: CIDR block validation
174
+ - **`v.e164()`**: E.164 phone number validation
175
+ - **`v.hash()`**: Hash validation (md5, sha1, sha256, sha384, sha512)
176
+ - **`v.iso.date()`/`v.iso.time()`/`v.iso.dateTime()`/`v.iso.duration()`**: ISO format validation
177
+
178
+ #### Enhanced Object Utilities
179
+ - **`v.strictObject()`**: Strict mode object validation
180
+ - **`v.looseObject()`**: Passthrough object validation
181
+ - **`v.partialRecord()`**: Partial record validation
182
+ - **`v.looseRecord()`**: Loose record validation
183
+ - **`v.int()`**: Integer shortcut
184
+ - **`v.int32()`**: 32-bit integer shortcut
185
+ - **`v.nullish()`**: Null or undefined
186
+ - **`v.NEVER`**: NEVER constant for transforms (Zod 4 parity)
187
+
188
+ ### Codec System - Beyond Zod
189
+ - **Bidirectional Transformations**: Full encode/decode support for data conversion
190
+ - **19 Built-in Codecs**: String conversions, date parsing, JSON, URL, binary data
191
+ - **Zod-Compatible**: All `stringToNumber`, `jsonCodec`, `base64ToBytes`, etc.
192
+ - **Async Support**: Both sync and async codec operations
193
+ - **Custom Codecs**: Create your own bidirectional transformations
194
+ - **Type-Safe**: Full TypeScript support with perfect type inference
195
+
196
+ ## Performance
197
+
198
+ VLD is designed for speed and efficiency with recent optimizations delivering exceptional performance:
199
+
200
+ ### Release-Gated Speed Benchmarks (v2.2.1 vs Zod 4.4.3)
201
+ - Runtime guard: VLD must stay at least 1.2x faster on every guarded hot path and keep at least a 3x average ratio
202
+ - Startup guard: cross-platform floors are 0.85x import, 0.9x total startup, and 1.25x warm parse versus Zod
203
+ - Memory guard: VLD must keep at least 2x lower total retained heap, 1.5x higher aggregate throughput, and no guarded case below 1.1x speed
204
+
205
+ ### Latest Runtime Guard Snapshot
206
+
207
+ Measured with `npm run benchmark:guard` (5 samples per case) against Zod 4.4.3:
208
+
209
+ | Guarded case | VLD | Zod | Ratio |
210
+ |--------------|-----|-----|-------|
211
+ | Nullish parse | 214.1M ops/sec | 7.0M ops/sec | **30.70x** |
212
+ | Number positive int parse | 252.9M ops/sec | 27.8M ops/sec | **9.10x** |
213
+ | Discriminated union parse | 35.0M ops/sec | 8.6M ops/sec | **4.06x** |
214
+ | Optional parse | 212.9M ops/sec | 56.6M ops/sec | **3.76x** |
215
+ | Union string and number parse | 39.1M ops/sec | 11.9M ops/sec | **3.30x** |
216
+ | Simple string parse | 620.7M ops/sec | 208.8M ops/sec | **2.97x** |
217
+ | Array number parse | 49.2M ops/sec | 28.3M ops/sec | **1.74x** |
218
+ | Simple object parse | 45.2M ops/sec | 27.7M ops/sec | **1.63x** |
219
+
220
+ 8/8 guarded cases pass with a **7.16x average ratio**. Absolute ops/sec numbers are hardware-dependent; the ratios are what the release gate enforces.
221
+
222
+ ### Optimizations
223
+ - **110x improvement** in union type validation
224
+ - **Simplified email regex** for maximum performance
225
+ - **Inline type checks** in object validation
226
+ - **Optimized loops** with direct array assignment
227
+ - **SafeParse optimization** to avoid try-catch overhead
228
+ - **Pre-computed keys** with Set for O(1) lookups
229
+
230
+ ### Memory Efficiency
231
+
232
+ Measured with `npm run benchmark:memory` against Zod 4.4.3. Heap deltas move a few percent between runs, so treat these as approximate:
233
+
234
+ - **~12.7x less memory** for schema creation
235
+ - **~7.3x less memory** for union validation
236
+ - **~2.9x less memory** for simple string validation
237
+ - **~2.7x less memory** for complex object validation
238
+ - **~5x less memory** overall
239
+
240
+ ### A Note on Real-World Benchmarking
241
+
242
+ Many validation library benchmarks can be misleading because they often test with **reused schema instances**:
243
+
244
+ ```javascript
245
+ // What benchmarks typically test (unrealistic):
246
+ const schema = z.string();
247
+ for (let i = 0; i < 1000000; i++) {
248
+ schema.parse(data); // Same instance reused
249
+ }
250
+
251
+ // What happens in real applications:
252
+ app.post('/api/user', (req, res) => {
253
+ // New schema created for each request
254
+ const schema = z.object({
255
+ email: z.string().email(),
256
+ age: z.number().min(18)
257
+ });
258
+ schema.parse(req.body);
259
+ });
260
+ ```
261
+
262
+ When testing real-world patterns:
263
+ - **Creating new instances**: VLD is **2000x faster** than Zod
264
+ - **Reused instances**: Zod benefits from V8's singleton optimization
265
+ - **Real applications**: Schemas are often created dynamically, where VLD excels
266
+
267
+ Run `npm run benchmark:truth` to see the real performance difference.
268
+
269
+ ## Installation
270
+
271
+ ```bash
272
+ npm install @oxog/vld
273
+ # or
274
+ yarn add @oxog/vld
275
+ # or
276
+ pnpm add @oxog/vld
277
+ ```
278
+
279
+ ## Quick Start
280
+
281
+ ```typescript
282
+ import { v } from '@oxog/vld';
283
+
284
+ // It is recommended to import as `v` for consistency with Zod's `z`
285
+ // and for a more concise syntax.
286
+
287
+ // Define a schema
288
+ const userSchema = v.object({
289
+ name: v.string().min(2),
290
+ email: v.string().email(),
291
+ age: v.number().min(18).max(100),
292
+ isActive: v.boolean()
293
+ });
294
+
295
+ // Validate data
296
+ const result = userSchema.safeParse({
297
+ name: 'John Doe',
298
+ email: 'john@example.com',
299
+ age: 25,
300
+ isActive: true
301
+ });
302
+
303
+ if (result.success) {
304
+ console.log('Valid user:', result.data);
305
+ } else {
306
+ console.log('Validation error:', result.error);
307
+ }
308
+ ```
309
+
310
+ For advanced error formatting:
311
+ ```typescript
312
+ import { v, VldError, treeifyError, prettifyError, flattenError } from '@oxog/vld';
313
+ ```
314
+
315
+ ## API Reference
316
+
317
+ ### Basic Types
318
+
319
+ ```typescript
320
+ v.string() // String validation
321
+ v.number() // Number validation
322
+ v.int() // Integer validation (shortcut)
323
+ v.int32() // 32-bit integer validation
324
+ v.boolean() // Boolean validation
325
+ v.bigint() // BigInt validation
326
+ v.symbol() // Symbol validation
327
+ v.date() // Date validation
328
+ v.uint8array()// Uint8Array validation
329
+ v.literal() // Literal values
330
+ v.enum() // Enum values (supports TypeScript enums)
331
+ v.any() // Any type
332
+ v.unknown() // Unknown type
333
+ v.void() // Void type
334
+ v.never() // Never type
335
+ v.null() // Null type
336
+ v.undefined() // Undefined type
337
+ v.nan() // NaN type
338
+ ```
339
+
340
+ ### Advanced Types
341
+
342
+ ```typescript
343
+ // Collections
344
+ v.array(v.string()) // Array validation
345
+ v.tuple(v.string(), v.number()) // Fixed-length tuple
346
+ v.record(v.number()) // Record/dictionary validation
347
+ v.set(v.string()) // Set validation
348
+ v.map(v.string(), v.number()) // Map validation
349
+
350
+ // Objects
351
+ v.object({ // Object schema
352
+ name: v.string(),
353
+ age: v.number()
354
+ })
355
+ v.strictObject({...}) // No extra fields allowed
356
+ v.looseObject({...}) // Extra fields passed through
357
+
358
+ // Composition
359
+ v.union(v.string(), v.number()) // Union types
360
+ v.intersection(schemaA, schemaB) // Intersection types
361
+ v.discriminatedUnion('type', ...) // Discriminated union
362
+ v.xor(schemaA, schemaB) // Exclusive OR
363
+ v.optional(v.string()) // Optional fields
364
+ v.nullable(v.string()) // Nullable fields
365
+ v.nullish(v.string()) // Null or undefined
366
+ ```
367
+
368
+ ### String Validators
369
+
370
+ ```typescript
371
+ v.string()
372
+ .min(5) // Minimum length
373
+ .max(10) // Maximum length
374
+ .length(8) // Exact length
375
+ .email() // Email format
376
+ .url() // URL format
377
+ .uuid() // UUID format
378
+ .regex(/pattern/) // Custom regex
379
+ .startsWith('prefix') // String prefix
380
+ .endsWith('suffix') // String suffix
381
+ .includes('substring') // Contains substring
382
+ .ip() // IP address (v4 or v6)
383
+ .trim() // Trim whitespace
384
+ .toLowerCase() // Convert to lowercase
385
+ .toUpperCase() // Convert to uppercase
386
+ .nonempty() // Non-empty string
387
+ ```
388
+
389
+ ### String Format Validators (Top-Level)
390
+
391
+ ```typescript
392
+ v.email() // Email validation
393
+ v.uuid() // UUID validation
394
+ v.uuid({ version: 'v4' }) // UUID v4 validation
395
+ v.uuidv4() // UUID v4 shortcut
396
+ v.hostname() // Hostname validation
397
+ v.emoji() // Emoji validation
398
+ v.base64() // Base64 format
399
+ v.base64url() // Base64 URL-safe format
400
+ v.hex() // Hex string
401
+ v.jwt() // JWT format
402
+ v.nanoid() // NanoID format
403
+ v.cuid() // CUID format
404
+ v.cuid2() // CUID2 format
405
+ v.ulid() // ULID format
406
+ v.ipv4() // IPv4 address
407
+ v.ipv6() // IPv6 address
408
+ v.mac() // MAC address
409
+ v.cidrv4() // IPv4 CIDR block
410
+ v.cidrv6() // IPv6 CIDR block
411
+ v.e164() // E.164 phone number
412
+ v.creditCard() // Credit card number (regex plus Luhn checksum)
413
+ v.hash('sha256') // Hash validation
414
+ v.iso.date() // ISO date format
415
+ v.iso.time() // ISO time format
416
+ v.iso.dateTime() // ISO datetime format
417
+ v.iso.duration() // ISO duration format
418
+ ```
419
+
420
+ ### Number Validators
421
+
422
+ ```typescript
423
+ v.number()
424
+ .min(0) // Minimum value
425
+ .max(100) // Maximum value
426
+ .int() // Integer only
427
+ .positive() // Positive numbers
428
+ .negative() // Negative numbers
429
+ .nonnegative() // >= 0
430
+ .nonpositive() // <= 0
431
+ .finite() // Finite numbers
432
+ .safe() // Safe integers
433
+ .multipleOf(5) // Multiple of value
434
+ ```
435
+
436
+ ### Arrays and Objects
437
+
438
+ ```typescript
439
+ // Arrays
440
+ v.array(v.string()) // Array of strings
441
+ .min(1) // Minimum length
442
+ .max(10) // Maximum length
443
+ .length(5) // Exact length
444
+ .nonempty() // Non-empty array
445
+
446
+ // Objects
447
+ v.object({
448
+ name: v.string(),
449
+ age: v.number()
450
+ })
451
+ .partial() // All fields optional
452
+ .strict() // No extra fields
453
+ .passthrough() // Allow extra fields
454
+ ```
455
+
456
+ ### Composite Types
457
+
458
+ ```typescript
459
+ // Optional
460
+ v.optional(v.string()) // string | undefined
461
+
462
+ // Nullable
463
+ v.nullable(v.string()) // string | null
464
+
465
+ // Nullish
466
+ v.nullish(v.string()) // string | null | undefined
467
+
468
+ // Union
469
+ v.union(v.string(), v.number()) // string | number
470
+
471
+ // Discriminated Union
472
+ v.discriminatedUnion('type',
473
+ v.object({ type: v.literal('a'), a: v.string() }),
474
+ v.object({ type: v.literal('b'), b: v.number() })
475
+ )
476
+
477
+ // Literal
478
+ v.literal('active') // 'active'
479
+
480
+ // Enum
481
+ v.enum('red', 'green', 'blue') // 'red' | 'green' | 'blue'
482
+ ```
483
+
484
+ ### Type Coercion
485
+
486
+ ```typescript
487
+ // Coerce strings from various types
488
+ v.coerce.string().parse(123) // "123"
489
+ v.coerce.string().parse(true) // "true"
490
+
491
+ // Coerce numbers from strings/booleans
492
+ v.coerce.number().parse("123") // 123
493
+ v.coerce.number().parse(true) // 1
494
+
495
+ // Coerce booleans from strings/numbers
496
+ v.coerce.boolean().parse("true") // true
497
+ v.coerce.boolean().parse(1) // true
498
+
499
+ // Coerce BigInt from strings/numbers
500
+ v.coerce.bigint().parse("123") // 123n
501
+ v.coerce.bigint().parse(456) // 456n
502
+
503
+ // Coerce Date from strings/timestamps
504
+ v.coerce.date().parse("2023-01-01") // Date object
505
+ v.coerce.date().parse(1672531200000) // Date object
506
+ ```
507
+
508
+ ### Object Schema Methods
509
+
510
+ ```typescript
511
+ const userSchema = v.object({
512
+ name: v.string(),
513
+ age: v.number(),
514
+ email: v.string(),
515
+ role: v.string()
516
+ });
517
+
518
+ // Pick specific fields
519
+ const publicSchema = userSchema.pick('name', 'age');
520
+ // Type: { name: string; age: number }
521
+
522
+ // Omit sensitive fields
523
+ const safeSchema = userSchema.omit('email', 'role');
524
+ // Type: { name: string; age: number }
525
+
526
+ // Extend with new fields
527
+ const extendedSchema = userSchema.extend({
528
+ isActive: v.boolean(),
529
+ lastLogin: v.date()
530
+ });
531
+ // Type: { name: string; age: number; email: string; role: string; isActive: boolean; lastLogin: Date }
532
+ ```
533
+
534
+ ### Advanced Validation Methods
535
+
536
+ ```typescript
537
+ // Custom validation with refine()
538
+ const positiveNumber = v.number()
539
+ .refine(n => n > 0, "Number must be positive");
540
+
541
+ // Data transformation with transform()
542
+ const uppercaseString = v.string()
543
+ .transform(s => s.toUpperCase());
544
+
545
+ // Default values for undefined
546
+ const withDefault = v.string().default("fallback");
547
+ withDefault.parse(undefined); // "fallback"
548
+
549
+ // Catch errors and provide fallback
550
+ const withCatch = v.number().catch(-1);
551
+ withCatch.parse("invalid"); // -1
552
+
553
+ // Method chaining
554
+ const complexSchema = v.string()
555
+ .min(3)
556
+ .transform(s => s.trim())
557
+ .refine(s => s.includes('@'), 'Must contain @')
558
+ .default('user@example.com');
559
+ ```
560
+
561
+ ### Special Validators
562
+
563
+ ```typescript
564
+ // JSON validator with optional schema
565
+ v.json() // Any valid JSON
566
+ v.json(v.object({ name: v.string() })) // Typed JSON
567
+
568
+ // Lazy for recursive schemas
569
+ const categorySchema = v.lazy(() =>
570
+ v.object({
571
+ name: v.string(),
572
+ children: v.array(categorySchema).optional()
573
+ })
574
+ );
575
+
576
+ // Custom validator
577
+ v.custom({
578
+ check: (val) => typeof val === 'string' && val.length > 0,
579
+ message: 'Must be a non-empty string'
580
+ });
581
+
582
+ // File validator
583
+ v.file()
584
+ .maxSize(5 * 1024 * 1024) // 5MB
585
+ .type(['image/png', 'image/jpeg']);
586
+
587
+ // Function validator
588
+ v.function()
589
+ .args(v.string(), v.number())
590
+ .returns(v.boolean());
591
+ ```
592
+
593
+ ### Type Inference
594
+
595
+ ```typescript
596
+ import { v } from '@oxog/vld';
597
+ import type { Infer } from '@oxog/vld';
598
+
599
+ const schema = v.object({
600
+ name: v.string(),
601
+ age: v.number()
602
+ });
603
+
604
+ // Automatically infer the type
605
+ type User = Infer<typeof schema>;
606
+ // { name: string; age: number }
607
+ ```
608
+
609
+ ### Error Formatting Types
610
+
611
+ ```typescript
612
+ import { VldError } from '@oxog/vld';
613
+ import type {
614
+ VldIssue, // Individual validation issue
615
+ VldErrorTree, // Nested error structure
616
+ VldFlattenedError // Flattened error structure
617
+ } from '@oxog/vld';
618
+ ```
619
+
620
+ ### Custom Error Messages
621
+
622
+ ```typescript
623
+ const schema = v.string().min(8, 'Password must be at least 8 characters');
624
+
625
+ const result = schema.safeParse('short');
626
+ if (!result.success) {
627
+ console.log(result.error.message); // 'Password must be at least 8 characters'
628
+ }
629
+ ```
630
+
631
+ ## Internationalization (i18n)
632
+
633
+ VLD supports 27+ languages out of the box with comprehensive error messages:
634
+
635
+ ```typescript
636
+ import { v, setLocale } from '@oxog/vld';
637
+
638
+ // Default is English
639
+ const schema = v.string().min(5);
640
+ schema.safeParse('Hi'); // Error: "String must be at least 5 characters"
641
+
642
+ // Switch to Turkish
643
+ setLocale('tr');
644
+ schema.safeParse('Hi'); // Error: "Metin en az 5 karakter olmali"
645
+
646
+ // Switch to Spanish
647
+ setLocale('es');
648
+ schema.safeParse('Hi'); // Error: "La cadena debe tener al menos 5 caracteres"
649
+
650
+ // Switch to Japanese
651
+ setLocale('ja');
652
+ schema.safeParse('Hi'); // Error: "..."
653
+ ```
654
+
655
+ ### Supported Languages
656
+
657
+ #### Base Languages (15):
658
+ - English (`en`) - Turkish (`tr`) - Spanish (`es`) - French (`fr`) - German (`de`)
659
+ - Italian (`it`) - Portuguese (`pt`) - Russian (`ru`) - Japanese (`ja`) - Korean (`ko`)
660
+ - Chinese (`zh`) - Arabic (`ar`) - Hindi (`hi`) - Dutch (`nl`) - Polish (`pl`)
661
+
662
+ #### European Languages (4):
663
+ - Danish (`da`) - Swedish (`sv`) - Norwegian (`no`) - Finnish (`fi`)
664
+
665
+ #### Asian Languages (4):
666
+ - Thai (`th`) - Vietnamese (`vi`) - Indonesian (`id`) - Bengali (`bn`)
667
+
668
+ #### African Languages (2):
669
+ - Swahili (`sw`) - Afrikaans (`af`)
670
+
671
+ #### American Languages (2):
672
+ - Portuguese Brazil (`pt-BR`) - Spanish Mexico (`es-MX`)
673
+
674
+ **Plus 75+ additional languages** supported through comprehensive type definitions with English fallback.
675
+
676
+ ## Error Handling & Formatting
677
+
678
+ VLD provides advanced error formatting utilities similar to Zod's error handling system.
679
+
680
+ ### Error Formatting Utilities
681
+
682
+ ```typescript
683
+ import { v, VldError, treeifyError, prettifyError, flattenError } from '@oxog/vld';
684
+
685
+ const userSchema = v.object({
686
+ username: v.string().min(3),
687
+ favoriteNumbers: v.array(v.number()),
688
+ profile: v.object({
689
+ name: v.string(),
690
+ email: v.string().email()
691
+ })
692
+ });
693
+
694
+ const result = userSchema.safeParse({
695
+ username: 'ab',
696
+ favoriteNumbers: [1, 'two', 3],
697
+ profile: {
698
+ name: '',
699
+ email: 'invalid-email'
700
+ },
701
+ extraField: 'not allowed'
702
+ });
703
+
704
+ if (!result.success) {
705
+ const error = result.error as VldError;
706
+
707
+ // 1. Tree Format - Nested structure for complex UIs
708
+ const tree = treeifyError(error);
709
+
710
+ // 2. Pretty Format - Human-readable console output
711
+ const pretty = prettifyError(error);
712
+
713
+ // 3. Flatten Format - Simple form validation
714
+ const flattened = flattenError(error);
715
+ }
716
+ ```
717
+
718
+ ### Using Error Formats in Practice
719
+
720
+ #### React Form Validation
721
+ ```typescript
722
+ function UserForm() {
723
+ const [errors, setErrors] = useState<VldFlattenedError | null>(null);
724
+
725
+ const handleSubmit = (data: unknown) => {
726
+ const result = userSchema.safeParse(data);
727
+
728
+ if (!result.success) {
729
+ setErrors(flattenError(result.error as VldError));
730
+ } else {
731
+ setErrors(null);
732
+ }
733
+ };
734
+
735
+ return (
736
+ <form onSubmit={handleSubmit}>
737
+ {errors?.formErrors.map(error => (
738
+ <div key={error} className="form-error">{error}</div>
739
+ ))}
740
+
741
+ <input name="username" />
742
+ {errors?.fieldErrors.username?.map(error => (
743
+ <div key={error} className="field-error">{error}</div>
744
+ ))}
745
+ </form>
746
+ );
747
+ }
748
+ ```
749
+
750
+ #### API Error Responses
751
+ ```typescript
752
+ app.post('/api/users', (req, res) => {
753
+ const result = userSchema.safeParse(req.body);
754
+
755
+ if (!result.success) {
756
+ const tree = treeifyError(result.error as VldError);
757
+ res.status(400).json({
758
+ error: 'Validation failed',
759
+ details: tree
760
+ });
761
+ }
762
+ });
763
+ ```
764
+
765
+ ## Advanced Examples
766
+
767
+ ### Complex Validation with New Features
768
+
769
+ ```typescript
770
+ const postSchema = v.object({
771
+ id: v.union(v.string().uuid(), v.number()),
772
+ title: v.string().min(5).max(100),
773
+ content: v.string().min(10),
774
+ author: v.object({
775
+ name: v.string(),
776
+ email: v.string().email(),
777
+ age: v.coerce.number(),
778
+ }),
779
+ tags: v.set(v.string()).default(new Set()),
780
+ metadata: v.record(v.any()),
781
+ coordinates: v.tuple(v.number(), v.number()),
782
+ publishedAt: v.date().default(() => new Date()),
783
+ status: v.enum('draft', 'published', 'archived')
784
+ });
785
+
786
+ // Extend with additional fields
787
+ const blogPostSchema = postSchema.extend({
788
+ viewCount: v.bigint().default(0n),
789
+ categories: v.array(v.string()).min(1),
790
+ featured: v.boolean().default(false)
791
+ });
792
+ ```
793
+
794
+ ### Discriminated Union
795
+
796
+ ```typescript
797
+ const eventSchema = v.discriminatedUnion('type',
798
+ v.object({
799
+ type: v.literal('click'),
800
+ x: v.number(),
801
+ y: v.number()
802
+ }),
803
+ v.object({
804
+ type: v.literal('scroll'),
805
+ direction: v.enum('up', 'down'),
806
+ distance: v.number()
807
+ }),
808
+ v.object({
809
+ type: v.literal('keypress'),
810
+ key: v.string(),
811
+ modifiers: v.array(v.enum('ctrl', 'alt', 'shift'))
812
+ })
813
+ );
814
+
815
+ // Type-safe parsing
816
+ const event = eventSchema.parse({
817
+ type: 'click',
818
+ x: 100,
819
+ y: 200
820
+ });
821
+ ```
822
+
823
+ ### Recursive Schemas
824
+
825
+ ```typescript
826
+ const categorySchema: ReturnType<typeof v.lazy> = v.lazy(() =>
827
+ v.object({
828
+ name: v.string(),
829
+ slug: v.string().regex(/^[a-z0-9-]+$/),
830
+ children: v.array(categorySchema).optional()
831
+ })
832
+ );
833
+
834
+ const category = categorySchema.parse({
835
+ name: 'Electronics',
836
+ slug: 'electronics',
837
+ children: [
838
+ {
839
+ name: 'Phones',
840
+ slug: 'phones',
841
+ children: [
842
+ { name: 'Smartphones', slug: 'smartphones' }
843
+ ]
844
+ }
845
+ ]
846
+ });
847
+ ```
848
+
849
+ ### Type-Safe Forms
850
+
851
+ ```typescript
852
+ const loginSchema = v.object({
853
+ username: v.string().min(3),
854
+ password: v.string().min(8),
855
+ rememberMe: v.optional(v.boolean())
856
+ });
857
+
858
+ type LoginForm = Infer<typeof loginSchema>;
859
+
860
+ function handleLogin(data: unknown) {
861
+ const result = loginSchema.safeParse(data);
862
+
863
+ if (result.success) {
864
+ const { username, password, rememberMe } = result.data;
865
+ // ... handle login
866
+ }
867
+ }
868
+ ```
869
+
870
+ ## Codecs - Bidirectional Transformations
871
+
872
+ VLD introduces **codecs** - powerful bidirectional transformations that can convert data between different representations.
873
+
874
+ ### What are Codecs?
875
+
876
+ Codecs enable safe, type-checked conversions between different data formats:
877
+
878
+ ```typescript
879
+ import { stringToNumber, jsonCodec, base64ToBytes } from '@oxog/vld';
880
+
881
+ // String to number conversion
882
+ const age = stringToNumber.parse('25'); // 25
883
+ const price = stringToNumber.encode(99.99); // "99.99"
884
+
885
+ // JSON codec
886
+ const userJson = jsonCodec();
887
+ const user = userJson.parse('{"name":"John","age":30}');
888
+ const jsonString = userJson.encode(user);
889
+
890
+ // Binary data
891
+ const bytes = base64ToBytes.parse('SGVsbG8gV29ybGQ=');
892
+ ```
893
+
894
+ ### Built-in Codecs
895
+
896
+ #### String Conversion Codecs
897
+ ```typescript
898
+ import { stringToNumber, stringToInt, stringToBigInt, stringToBoolean } from '@oxog/vld';
899
+
900
+ stringToNumber.parse('42.5'); // 42.5
901
+ stringToInt.parse('42'); // 42
902
+ stringToBigInt.parse('123n'); // 123n
903
+ stringToBoolean.parse('true'); // true
904
+ ```
905
+
906
+ #### Date Conversion Codecs
907
+ ```typescript
908
+ import { isoDatetimeToDate, epochSecondsToDate, epochMillisToDate } from '@oxog/vld';
909
+
910
+ isoDatetimeToDate.parse('2023-12-25T10:30:00.000Z'); // Date
911
+ epochSecondsToDate.parse(1703505000); // Date
912
+ epochMillisToDate.parse(1703505000000); // Date
913
+ ```
914
+
915
+ #### URL Codecs
916
+ ```typescript
917
+ import { stringToURL, stringToHttpURL, uriComponent } from '@oxog/vld';
918
+
919
+ stringToURL.parse('https://example.com/path?q=1');
920
+ stringToHttpURL.parse('https://api.example.com');
921
+ uriComponent.parse('Hello World!'); // "Hello%20World!"
922
+ ```
923
+
924
+ #### Binary Data Codecs
925
+ ```typescript
926
+ import { base64ToBytes, hexToBytes, utf8ToBytes, bytesToUtf8 } from '@oxog/vld';
927
+
928
+ base64ToBytes.parse('SGVsbG8='); // Uint8Array
929
+ hexToBytes.parse('48656c6c6f'); // Uint8Array
930
+ utf8ToBytes.parse('Hello'); // Uint8Array
931
+ bytesToUtf8.parse(new Uint8Array([72, 101, 108, 108, 111])); // "Hello"
932
+ ```
933
+
934
+ ### Custom Codecs
935
+
936
+ ```typescript
937
+ const csvToArray = v.codec(
938
+ v.string(),
939
+ v.array(v.string()),
940
+ {
941
+ decode: (csv: string) => csv.split(',').map(s => s.trim()),
942
+ encode: (arr: string[]) => arr.join(', ')
943
+ }
944
+ );
945
+
946
+ const tags = csvToArray.parse('react, typescript, vld');
947
+ // ["react", "typescript", "vld"]
948
+
949
+ const csvString = csvToArray.encode(['node', 'express', 'api']);
950
+ // "node, express, api"
951
+ ```
952
+
953
+ ## Plugin System
954
+
955
+ VLD v1.5.0 introduces a powerful plugin system for extending functionality.
956
+
957
+ ### Creating a Plugin
958
+
959
+ ```typescript
960
+ import { definePlugin, usePlugin, v } from '@oxog/vld';
961
+
962
+ // Define a custom plugin
963
+ const myPlugin = definePlugin({
964
+ name: 'my-plugin',
965
+ version: '1.0.0',
966
+
967
+ // Custom validators
968
+ validators: {
969
+ phoneNumber: () => v.string().regex(/^\+?[1-9]\d{1,14}$/),
970
+ postalCode: () => v.string().regex(/^\d{5}(-\d{4})?$/)
971
+ },
972
+
973
+ // Custom transforms
974
+ transforms: {
975
+ normalizePhone: (phone: string) => phone.replace(/[^\d+]/g, '')
976
+ },
977
+
978
+ // Lifecycle hooks
979
+ install(kernel) {
980
+ console.log('Plugin installed!');
981
+ }
982
+ });
983
+
984
+ // Register the plugin
985
+ usePlugin(myPlugin);
986
+ ```
987
+
988
+ ### Using Plugin Validators
989
+
990
+ ```typescript
991
+ import { createVldKernel, usePlugin } from '@oxog/vld';
992
+
993
+ const kernel = createVldKernel({ debug: true });
994
+
995
+ kernel.use(myPlugin);
996
+
997
+ // Access custom validators
998
+ const phoneSchema = kernel.validator('phoneNumber');
999
+ phoneSchema.parse('+1234567890');
1000
+ ```
1001
+
1002
+ ## Result Pattern
1003
+
1004
+ VLD v1.5.0 includes a functional Result pattern for error handling.
1005
+
1006
+ ### Basic Usage
1007
+
1008
+ ```typescript
1009
+ import { Ok, Err, match, map, flatMap, tryCatch } from '@oxog/vld';
1010
+
1011
+ // Create results
1012
+ const success = Ok(42);
1013
+ const failure = Err(new Error('Something went wrong'));
1014
+
1015
+ // Pattern matching
1016
+ const message = match(success, {
1017
+ ok: (value) => `Got: ${value}`,
1018
+ err: (error) => `Error: ${error.message}`
1019
+ });
1020
+
1021
+ // Transform results
1022
+ const doubled = map(success, (n) => n * 2); // Ok(84)
1023
+
1024
+ // Chain operations
1025
+ const result = flatMap(success, (n) =>
1026
+ n > 0 ? Ok(n * 2) : Err(new Error('Must be positive'))
1027
+ );
1028
+
1029
+ // Safe function execution
1030
+ const parsed = tryCatch(() => JSON.parse('{"a":1}'));
1031
+ ```
1032
+
1033
+ ### With Validation
1034
+
1035
+ ```typescript
1036
+ import { v, isOk, isErr, unwrapOr } from '@oxog/vld';
1037
+
1038
+ const schema = v.object({
1039
+ name: v.string(),
1040
+ age: v.number().min(0)
1041
+ });
1042
+
1043
+ const result = schema.safeParse(data);
1044
+
1045
+ if (isOk(result)) {
1046
+ console.log('Valid:', result.data);
1047
+ } else {
1048
+ console.log('Invalid:', result.error);
1049
+ }
1050
+
1051
+ // With default value
1052
+ const user = unwrapOr(result, { name: 'Guest', age: 0 });
1053
+ ```
1054
+
1055
+ ### Combining Results
1056
+
1057
+ ```typescript
1058
+ import { all, fromNullable } from '@oxog/vld';
1059
+
1060
+ // Combine multiple results
1061
+ const results = [Ok(1), Ok(2), Ok(3)];
1062
+ const combined = all(results); // Ok([1, 2, 3])
1063
+
1064
+ // Convert nullable to Result
1065
+ const maybeValue: string | null = getValue();
1066
+ const result = fromNullable(maybeValue, new Error('Value is null'));
1067
+ ```
1068
+
1069
+ ## CLI Tools
1070
+
1071
+ VLD includes command-line tools for validation and benchmarking.
1072
+
1073
+ ### Installation
1074
+
1075
+ ```bash
1076
+ npm install -g @oxog/vld
1077
+ # or use npx
1078
+ npx vld --help
1079
+ ```
1080
+
1081
+ ### Commands
1082
+
1083
+ ```bash
1084
+ # Show help
1085
+ vld --help
1086
+
1087
+ # Validate data
1088
+ vld validate schema.json data.json
1089
+
1090
+ # Run benchmarks
1091
+ vld benchmark
1092
+
1093
+ # Show version
1094
+ vld --version
1095
+ ```
1096
+
1097
+ ### Programmatic CLI
1098
+
1099
+ ```typescript
1100
+ import { createCli, vldCli } from '@oxog/vld/cli';
1101
+
1102
+ // Use the built-in CLI
1103
+ vldCli.run(process.argv.slice(2));
1104
+
1105
+ // Or create a custom CLI
1106
+ const cli = createCli('my-app', '1.0.0', 'My validation app')
1107
+ .command({
1108
+ name: 'validate',
1109
+ description: 'Validate data',
1110
+ action: async (args, options) => {
1111
+ // Custom validation logic
1112
+ }
1113
+ });
1114
+
1115
+ cli.run(process.argv.slice(2));
1116
+ ```
1117
+
1118
+ ## Logger & Colored Output
1119
+
1120
+ VLD includes a logging system and colored terminal output.
1121
+
1122
+ ### Logger
1123
+
1124
+ ```typescript
1125
+ import { createLogger, setLogLevel, enableDebug } from '@oxog/vld';
1126
+
1127
+ // Create a logger
1128
+ const logger = createLogger({ prefix: 'VLD' });
1129
+
1130
+ logger.info('Processing...');
1131
+ logger.warn('Deprecated feature');
1132
+ logger.error('Validation failed');
1133
+ logger.debug('Debug info');
1134
+
1135
+ // Set log level globally
1136
+ setLogLevel('debug');
1137
+
1138
+ // Enable debug mode
1139
+ enableDebug();
1140
+ ```
1141
+
1142
+ ### Colored Output (Pigment)
1143
+
1144
+ ```typescript
1145
+ import { pigment, red, green, blue, bold, dim } from '@oxog/vld';
1146
+
1147
+ console.log(red('Error!'));
1148
+ console.log(green('Success!'));
1149
+ console.log(bold(blue('Important')));
1150
+ console.log(dim('Less important'));
1151
+
1152
+ // Or use the pigment object
1153
+ console.log(pigment.red('Error!'));
1154
+ console.log(pigment.bold(pigment.green('Success!')));
1155
+ ```
1156
+
1157
+ ## VLD vs. Zod
1158
+
1159
+ VLD is designed as a compelling alternative to Zod, maintaining an audited compatibility baseline while delivering additional platform features.
1160
+
1161
+ ### Feature Comparison
1162
+
1163
+ | Feature | VLD | Zod |
1164
+ | ----------------------- | ---------------------------------- | ------------------------------------ |
1165
+ | **Performance** | **Release-gated faster runtime, startup, and memory paths** | Baseline |
1166
+ | **Memory Usage** | **~5x less** overall | Baseline |
1167
+ | **Internationalization**| **Built-in 27+ locales with lazy loading** | Built-in locales |
1168
+ | **Dependencies** | **Zero runtime dependencies** | Zero runtime dependencies |
1169
+ | **Bundle Size** | Smaller | Larger |
1170
+ | **API** | Zod 4.4.3 compatibility gate + extensions | Standard Zod API |
1171
+ | **Plugin System** | **Built-in** | Not available |
1172
+ | **Result Pattern** | **Built-in** | Not available |
1173
+ | **CLI Tools** | **Built-in** | Not available |
1174
+ | **Codecs** | Built-in system plus reusable presets | Built-in primitives; recipes documented |
1175
+ | **Type Inference** | Excellent | Excellent |
1176
+
1177
+ ### Seamless Migration from Zod
1178
+
1179
+ ```javascript
1180
+ // Before (Zod)
1181
+ import { z } from 'zod';
1182
+ const schema = z.string().email();
1183
+
1184
+ // After (VLD) - Exact same syntax!
1185
+ import { v } from '@oxog/vld';
1186
+ const schema = v.string().email();
1187
+ ```
1188
+
1189
+ ### Drop-in Package Subpaths
1190
+
1191
+ VLD also exposes Zod-compatible package subpaths so applications that import Zod 4 entry points can migrate by changing the package name:
1192
+
1193
+ ```typescript
1194
+ // Before
1195
+ import { z } from 'zod';
1196
+ import * as core from 'zod/v4/core';
1197
+ import * as mini from 'zod/v4-mini';
1198
+ import * as locales from 'zod/v4/locales';
1199
+
1200
+ // After
1201
+ import { z } from '@oxog/vld';
1202
+ import * as core from '@oxog/vld/v4/core';
1203
+ import * as mini from '@oxog/vld/v4-mini';
1204
+ import * as locales from '@oxog/vld/v4/locales';
1205
+ ```
1206
+
1207
+ Release checks enforce zero missing exports and zero `typeof` mismatches for `zod/v4`, `zod/v4-mini`, `zod/v4/mini`, `zod/v4/core`, and `zod/v4/locales` against the installed latest Zod.
1208
+
1209
+ ### Real App Drop-in Verification
1210
+
1211
+ `npm run verify:drop-in` creates two temporary TypeScript applications from the same fixture:
1212
+
1213
+ - One imports and runs against real `zod`.
1214
+ - One imports and runs against the locally built `@oxog/vld` package.
1215
+ - The fixture exercises root APIs, `v4`, `v4-mini`, `v4/core`, `v4/locales`, parsing, error formatting, JSON Schema output, mini helpers, and core factories.
1216
+ - The normalized runtime outputs must match exactly.
1217
+
1218
+ ## Benchmarks
1219
+
1220
+ ### Performance Results
1221
+
1222
+ Median of 11 samples per case against Zod 4.4.3, the latest stable release at the time of measurement. The release gate also runs focused runtime, startup, memory, package, install, security, Zod parity, and real drop-in app checks before publishing.
1223
+
1224
+ | Test Case | VLD Median Performance | Improvement |
1225
+ |-----------|----------------|-------------|
1226
+ | Simple String | 719.2M ops/sec | **3.40x faster** |
1227
+ | Email Validation | 22.1M ops/sec | **2.87x faster** |
1228
+ | Top-level Email Format | 22.8M ops/sec | **3.66x faster** |
1229
+ | StringBool Validation | 32.7M ops/sec | **3.44x faster** |
1230
+ | Number Validation | 226.2M ops/sec | **27.62x faster** |
1231
+ | Simple Object | 37.7M ops/sec | **1.40x faster** |
1232
+ | Complex Object | 2.3M ops/sec | **1.02x faster** |
1233
+ | Array Validation | 39.8M ops/sec | **6.74x faster** |
1234
+ | Union Types | 38.1M ops/sec | **4.10x faster** |
1235
+ | Optional Values | 236.9M ops/sec | **7.57x faster** |
1236
+ | Nullable Values | 224.7M ops/sec | **10.71x faster** |
1237
+ | Nullish Values | 228.4M ops/sec | **52.92x faster** |
1238
+ | Default Values | 207.8M ops/sec | **9.71x faster** |
1239
+ | Catch Values | 232.1M ops/sec | **46.58x faster** |
1240
+ | SafeParse | 162.0M ops/sec | **1.80x faster** |
1241
+ | Type Coercion | 204.5M ops/sec | **8.72x faster** |
1242
+ | Enum Validation | 180.3M ops/sec | **1.32x faster** |
1243
+ | Discriminated Union | 19.2M ops/sec | **1.79x faster** |
1244
+ | Tuple Validation | 50.0M ops/sec | **7.99x faster** |
1245
+ | Record Validation | 10.7M ops/sec | **5.63x faster** |
1246
+ | Set Validation | 18.9M ops/sec | **1.84x faster** |
1247
+ | Map Validation | 14.8M ops/sec | **2.37x faster** |
1248
+ | BigInt Validation | 164.8M ops/sec | **14.88x faster** |
1249
+ | Date Validation | 227.2M ops/sec | **2.57x faster** |
1250
+ | Symbol Validation | 230.0M ops/sec | **1.01x faster** |
1251
+ | Any Validation | 232.5M ops/sec | **1.01x faster** |
1252
+ | Unknown Validation | 234.9M ops/sec | **1.04x faster** |
1253
+ | Function Validation | 233.6M ops/sec | **3.52x faster** |
1254
+ | Template Literal Validation | 39.3M ops/sec | **1.15x faster** |
1255
+ | Promise Async Validation | 6.3M ops/sec | **1.38x faster** |
1256
+
1257
+ **VLD won 30/30 snapshot tests. Release checks additionally enforce runtime, startup, memory, Zod subpath parity, and real drop-in app guard thresholds against Zod.**
1258
+
1259
+ ### Run Benchmarks
1260
+
1261
+ ```bash
1262
+ # Quick performance comparison
1263
+ npm run benchmark
1264
+
1265
+ # Median-based stable comparison
1266
+ npm run benchmark:stable
1267
+
1268
+ # Fast CI-friendly performance regression guard
1269
+ npm run benchmark:guard
1270
+
1271
+ # Full release gate: lint, source and published types, tests, exports, package and install checks, security audit, Zod parity, real drop-in app verification, and performance guards
1272
+ npm run release:check
1273
+
1274
+ # Memory usage comparison
1275
+ npm run benchmark:memory
1276
+
1277
+ # Startup time comparison
1278
+ npm run benchmark:startup
1279
+
1280
+ # Run all benchmarks
1281
+ npm run benchmark:all
1282
+ ```
1283
+
1284
+ ## Contributing
1285
+
1286
+ Contributions are welcome! Please feel free to submit a Pull Request.
1287
+
1288
+ ## Links
1289
+
1290
+ - [Documentation](https://vld.oxog.dev)
1291
+ - [NPM Package](https://www.npmjs.com/package/@oxog/vld)
1292
+ - [GitHub Repository](https://github.com/ersinkoc/vld)
1293
+
1294
+ ---
1295
+
1296
+ Made with Love by [Ersin KOC](https://github.com/ersinkoc)