bupkis 0.18.0 → 0.18.2

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 (377) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/package.json +1 -4
  3. package/src/assertion/assertion-types.ts +4 -4
  4. package/src/assertion/impl/async-parametric.ts +4 -21
  5. package/src/assertion/impl/sync-parametric.ts +5 -17
  6. package/src/expect.ts +0 -4
  7. package/src/guards.ts +24 -24
  8. package/src/internal-schema.ts +16 -32
  9. package/src/value-to-schema.ts +1 -1
  10. package/dist/assertion/assertion-async.cjs +0 -268
  11. package/dist/assertion/assertion-async.cjs.map +0 -1
  12. package/dist/assertion/assertion-async.d.cts +0 -40
  13. package/dist/assertion/assertion-async.d.cts.map +0 -1
  14. package/dist/assertion/assertion-async.d.ts +0 -40
  15. package/dist/assertion/assertion-async.d.ts.map +0 -1
  16. package/dist/assertion/assertion-async.js +0 -259
  17. package/dist/assertion/assertion-async.js.map +0 -1
  18. package/dist/assertion/assertion-standard-schema-async.cjs +0 -132
  19. package/dist/assertion/assertion-standard-schema-async.cjs.map +0 -1
  20. package/dist/assertion/assertion-standard-schema-async.d.cts +0 -52
  21. package/dist/assertion/assertion-standard-schema-async.d.cts.map +0 -1
  22. package/dist/assertion/assertion-standard-schema-async.d.ts +0 -52
  23. package/dist/assertion/assertion-standard-schema-async.d.ts.map +0 -1
  24. package/dist/assertion/assertion-standard-schema-async.js +0 -128
  25. package/dist/assertion/assertion-standard-schema-async.js.map +0 -1
  26. package/dist/assertion/assertion-standard-schema-sync.cjs +0 -141
  27. package/dist/assertion/assertion-standard-schema-sync.cjs.map +0 -1
  28. package/dist/assertion/assertion-standard-schema-sync.d.cts +0 -52
  29. package/dist/assertion/assertion-standard-schema-sync.d.cts.map +0 -1
  30. package/dist/assertion/assertion-standard-schema-sync.d.ts +0 -52
  31. package/dist/assertion/assertion-standard-schema-sync.d.ts.map +0 -1
  32. package/dist/assertion/assertion-standard-schema-sync.js +0 -137
  33. package/dist/assertion/assertion-standard-schema-sync.js.map +0 -1
  34. package/dist/assertion/assertion-sync.cjs +0 -284
  35. package/dist/assertion/assertion-sync.cjs.map +0 -1
  36. package/dist/assertion/assertion-sync.d.cts +0 -60
  37. package/dist/assertion/assertion-sync.d.cts.map +0 -1
  38. package/dist/assertion/assertion-sync.d.ts +0 -60
  39. package/dist/assertion/assertion-sync.d.ts.map +0 -1
  40. package/dist/assertion/assertion-sync.js +0 -275
  41. package/dist/assertion/assertion-sync.js.map +0 -1
  42. package/dist/assertion/assertion-types.cjs +0 -20
  43. package/dist/assertion/assertion-types.cjs.map +0 -1
  44. package/dist/assertion/assertion-types.d.cts +0 -1086
  45. package/dist/assertion/assertion-types.d.cts.map +0 -1
  46. package/dist/assertion/assertion-types.d.ts +0 -1086
  47. package/dist/assertion/assertion-types.d.ts.map +0 -1
  48. package/dist/assertion/assertion-types.js +0 -19
  49. package/dist/assertion/assertion-types.js.map +0 -1
  50. package/dist/assertion/assertion.cjs +0 -382
  51. package/dist/assertion/assertion.cjs.map +0 -1
  52. package/dist/assertion/assertion.d.cts +0 -109
  53. package/dist/assertion/assertion.d.cts.map +0 -1
  54. package/dist/assertion/assertion.d.ts +0 -109
  55. package/dist/assertion/assertion.d.ts.map +0 -1
  56. package/dist/assertion/assertion.js +0 -375
  57. package/dist/assertion/assertion.js.map +0 -1
  58. package/dist/assertion/create.cjs +0 -148
  59. package/dist/assertion/create.cjs.map +0 -1
  60. package/dist/assertion/create.d.cts +0 -85
  61. package/dist/assertion/create.d.cts.map +0 -1
  62. package/dist/assertion/create.d.ts +0 -85
  63. package/dist/assertion/create.d.ts.map +0 -1
  64. package/dist/assertion/create.js +0 -143
  65. package/dist/assertion/create.js.map +0 -1
  66. package/dist/assertion/format-assertion-failure.cjs +0 -63
  67. package/dist/assertion/format-assertion-failure.cjs.map +0 -1
  68. package/dist/assertion/format-assertion-failure.d.cts +0 -21
  69. package/dist/assertion/format-assertion-failure.d.cts.map +0 -1
  70. package/dist/assertion/format-assertion-failure.d.ts +0 -21
  71. package/dist/assertion/format-assertion-failure.d.ts.map +0 -1
  72. package/dist/assertion/format-assertion-failure.js +0 -59
  73. package/dist/assertion/format-assertion-failure.js.map +0 -1
  74. package/dist/assertion/impl/assertion-util.cjs +0 -68
  75. package/dist/assertion/impl/assertion-util.cjs.map +0 -1
  76. package/dist/assertion/impl/assertion-util.d.cts +0 -36
  77. package/dist/assertion/impl/assertion-util.d.cts.map +0 -1
  78. package/dist/assertion/impl/assertion-util.d.ts +0 -36
  79. package/dist/assertion/impl/assertion-util.d.ts.map +0 -1
  80. package/dist/assertion/impl/assertion-util.js +0 -62
  81. package/dist/assertion/impl/assertion-util.js.map +0 -1
  82. package/dist/assertion/impl/async-iterable.cjs +0 -627
  83. package/dist/assertion/impl/async-iterable.cjs.map +0 -1
  84. package/dist/assertion/impl/async-iterable.d.cts +0 -406
  85. package/dist/assertion/impl/async-iterable.d.cts.map +0 -1
  86. package/dist/assertion/impl/async-iterable.d.ts +0 -406
  87. package/dist/assertion/impl/async-iterable.d.ts.map +0 -1
  88. package/dist/assertion/impl/async-iterable.js +0 -624
  89. package/dist/assertion/impl/async-iterable.js.map +0 -1
  90. package/dist/assertion/impl/async-parametric.cjs +0 -423
  91. package/dist/assertion/impl/async-parametric.cjs.map +0 -1
  92. package/dist/assertion/impl/async-parametric.d.cts +0 -278
  93. package/dist/assertion/impl/async-parametric.d.cts.map +0 -1
  94. package/dist/assertion/impl/async-parametric.d.ts +0 -278
  95. package/dist/assertion/impl/async-parametric.d.ts.map +0 -1
  96. package/dist/assertion/impl/async-parametric.js +0 -420
  97. package/dist/assertion/impl/async-parametric.js.map +0 -1
  98. package/dist/assertion/impl/async.cjs +0 -56
  99. package/dist/assertion/impl/async.cjs.map +0 -1
  100. package/dist/assertion/impl/async.d.cts +0 -179
  101. package/dist/assertion/impl/async.d.cts.map +0 -1
  102. package/dist/assertion/impl/async.d.ts +0 -179
  103. package/dist/assertion/impl/async.d.ts.map +0 -1
  104. package/dist/assertion/impl/async.js +0 -39
  105. package/dist/assertion/impl/async.js.map +0 -1
  106. package/dist/assertion/impl/index.cjs +0 -37
  107. package/dist/assertion/impl/index.cjs.map +0 -1
  108. package/dist/assertion/impl/index.d.cts +0 -21
  109. package/dist/assertion/impl/index.d.cts.map +0 -1
  110. package/dist/assertion/impl/index.d.ts +0 -21
  111. package/dist/assertion/impl/index.d.ts.map +0 -1
  112. package/dist/assertion/impl/index.js +0 -21
  113. package/dist/assertion/impl/index.js.map +0 -1
  114. package/dist/assertion/impl/iteration-util.cjs +0 -297
  115. package/dist/assertion/impl/iteration-util.cjs.map +0 -1
  116. package/dist/assertion/impl/iteration-util.d.cts +0 -12
  117. package/dist/assertion/impl/iteration-util.d.cts.map +0 -1
  118. package/dist/assertion/impl/iteration-util.d.ts +0 -12
  119. package/dist/assertion/impl/iteration-util.d.ts.map +0 -1
  120. package/dist/assertion/impl/iteration-util.js +0 -282
  121. package/dist/assertion/impl/iteration-util.js.map +0 -1
  122. package/dist/assertion/impl/snapshot.cjs +0 -276
  123. package/dist/assertion/impl/snapshot.cjs.map +0 -1
  124. package/dist/assertion/impl/snapshot.d.cts +0 -278
  125. package/dist/assertion/impl/snapshot.d.cts.map +0 -1
  126. package/dist/assertion/impl/snapshot.d.ts +0 -278
  127. package/dist/assertion/impl/snapshot.d.ts.map +0 -1
  128. package/dist/assertion/impl/snapshot.js +0 -273
  129. package/dist/assertion/impl/snapshot.js.map +0 -1
  130. package/dist/assertion/impl/sync-basic.cjs +0 -553
  131. package/dist/assertion/impl/sync-basic.cjs.map +0 -1
  132. package/dist/assertion/impl/sync-basic.d.cts +0 -528
  133. package/dist/assertion/impl/sync-basic.d.cts.map +0 -1
  134. package/dist/assertion/impl/sync-basic.d.ts +0 -528
  135. package/dist/assertion/impl/sync-basic.d.ts.map +0 -1
  136. package/dist/assertion/impl/sync-basic.js +0 -550
  137. package/dist/assertion/impl/sync-basic.js.map +0 -1
  138. package/dist/assertion/impl/sync-collection.cjs +0 -856
  139. package/dist/assertion/impl/sync-collection.cjs.map +0 -1
  140. package/dist/assertion/impl/sync-collection.d.cts +0 -607
  141. package/dist/assertion/impl/sync-collection.d.cts.map +0 -1
  142. package/dist/assertion/impl/sync-collection.d.ts +0 -607
  143. package/dist/assertion/impl/sync-collection.d.ts.map +0 -1
  144. package/dist/assertion/impl/sync-collection.js +0 -850
  145. package/dist/assertion/impl/sync-collection.js.map +0 -1
  146. package/dist/assertion/impl/sync-date.cjs +0 -341
  147. package/dist/assertion/impl/sync-date.cjs.map +0 -1
  148. package/dist/assertion/impl/sync-date.d.cts +0 -209
  149. package/dist/assertion/impl/sync-date.d.cts.map +0 -1
  150. package/dist/assertion/impl/sync-date.d.ts +0 -209
  151. package/dist/assertion/impl/sync-date.d.ts.map +0 -1
  152. package/dist/assertion/impl/sync-date.js +0 -338
  153. package/dist/assertion/impl/sync-date.js.map +0 -1
  154. package/dist/assertion/impl/sync-esoteric.cjs +0 -214
  155. package/dist/assertion/impl/sync-esoteric.cjs.map +0 -1
  156. package/dist/assertion/impl/sync-esoteric.d.cts +0 -191
  157. package/dist/assertion/impl/sync-esoteric.d.cts.map +0 -1
  158. package/dist/assertion/impl/sync-esoteric.d.ts +0 -191
  159. package/dist/assertion/impl/sync-esoteric.d.ts.map +0 -1
  160. package/dist/assertion/impl/sync-esoteric.js +0 -211
  161. package/dist/assertion/impl/sync-esoteric.js.map +0 -1
  162. package/dist/assertion/impl/sync-iterable.cjs +0 -512
  163. package/dist/assertion/impl/sync-iterable.cjs.map +0 -1
  164. package/dist/assertion/impl/sync-iterable.d.cts +0 -334
  165. package/dist/assertion/impl/sync-iterable.d.cts.map +0 -1
  166. package/dist/assertion/impl/sync-iterable.d.ts +0 -334
  167. package/dist/assertion/impl/sync-iterable.d.ts.map +0 -1
  168. package/dist/assertion/impl/sync-iterable.js +0 -509
  169. package/dist/assertion/impl/sync-iterable.js.map +0 -1
  170. package/dist/assertion/impl/sync-parametric.cjs +0 -812
  171. package/dist/assertion/impl/sync-parametric.cjs.map +0 -1
  172. package/dist/assertion/impl/sync-parametric.d.cts +0 -560
  173. package/dist/assertion/impl/sync-parametric.d.cts.map +0 -1
  174. package/dist/assertion/impl/sync-parametric.d.ts +0 -560
  175. package/dist/assertion/impl/sync-parametric.d.ts.map +0 -1
  176. package/dist/assertion/impl/sync-parametric.js +0 -809
  177. package/dist/assertion/impl/sync-parametric.js.map +0 -1
  178. package/dist/assertion/impl/sync.cjs +0 -214
  179. package/dist/assertion/impl/sync.cjs.map +0 -1
  180. package/dist/assertion/impl/sync.d.cts +0 -512
  181. package/dist/assertion/impl/sync.d.cts.map +0 -1
  182. package/dist/assertion/impl/sync.d.ts +0 -512
  183. package/dist/assertion/impl/sync.d.ts.map +0 -1
  184. package/dist/assertion/impl/sync.js +0 -197
  185. package/dist/assertion/impl/sync.js.map +0 -1
  186. package/dist/assertion/index.cjs +0 -38
  187. package/dist/assertion/index.cjs.map +0 -1
  188. package/dist/assertion/index.d.cts +0 -18
  189. package/dist/assertion/index.d.cts.map +0 -1
  190. package/dist/assertion/index.d.ts +0 -18
  191. package/dist/assertion/index.d.ts.map +0 -1
  192. package/dist/assertion/index.js +0 -17
  193. package/dist/assertion/index.js.map +0 -1
  194. package/dist/assertion/slotify.cjs +0 -165
  195. package/dist/assertion/slotify.cjs.map +0 -1
  196. package/dist/assertion/slotify.d.cts +0 -11
  197. package/dist/assertion/slotify.d.cts.map +0 -1
  198. package/dist/assertion/slotify.d.ts +0 -11
  199. package/dist/assertion/slotify.d.ts.map +0 -1
  200. package/dist/assertion/slotify.js +0 -161
  201. package/dist/assertion/slotify.js.map +0 -1
  202. package/dist/bootstrap.cjs +0 -43
  203. package/dist/bootstrap.cjs.map +0 -1
  204. package/dist/bootstrap.d.cts +0 -27
  205. package/dist/bootstrap.d.cts.map +0 -1
  206. package/dist/bootstrap.d.ts +0 -27
  207. package/dist/bootstrap.d.ts.map +0 -1
  208. package/dist/bootstrap.js +0 -40
  209. package/dist/bootstrap.js.map +0 -1
  210. package/dist/constant.cjs +0 -82
  211. package/dist/constant.cjs.map +0 -1
  212. package/dist/constant.d.cts +0 -69
  213. package/dist/constant.d.cts.map +0 -1
  214. package/dist/constant.d.ts +0 -69
  215. package/dist/constant.d.ts.map +0 -1
  216. package/dist/constant.js +0 -79
  217. package/dist/constant.js.map +0 -1
  218. package/dist/diff.cjs +0 -340
  219. package/dist/diff.cjs.map +0 -1
  220. package/dist/diff.d.cts +0 -51
  221. package/dist/diff.d.cts.map +0 -1
  222. package/dist/diff.d.ts +0 -51
  223. package/dist/diff.d.ts.map +0 -1
  224. package/dist/diff.js +0 -334
  225. package/dist/diff.js.map +0 -1
  226. package/dist/error.cjs +0 -204
  227. package/dist/error.cjs.map +0 -1
  228. package/dist/error.d.cts +0 -212
  229. package/dist/error.d.cts.map +0 -1
  230. package/dist/error.d.ts +0 -212
  231. package/dist/error.d.ts.map +0 -1
  232. package/dist/error.js +0 -191
  233. package/dist/error.js.map +0 -1
  234. package/dist/expect.cjs +0 -590
  235. package/dist/expect.cjs.map +0 -1
  236. package/dist/expect.d.cts +0 -138
  237. package/dist/expect.d.cts.map +0 -1
  238. package/dist/expect.d.ts +0 -138
  239. package/dist/expect.d.ts.map +0 -1
  240. package/dist/expect.js +0 -582
  241. package/dist/expect.js.map +0 -1
  242. package/dist/guards.cjs +0 -297
  243. package/dist/guards.cjs.map +0 -1
  244. package/dist/guards.d.cts +0 -231
  245. package/dist/guards.d.cts.map +0 -1
  246. package/dist/guards.d.ts +0 -231
  247. package/dist/guards.d.ts.map +0 -1
  248. package/dist/guards.js +0 -277
  249. package/dist/guards.js.map +0 -1
  250. package/dist/index.cjs +0 -111
  251. package/dist/index.cjs.map +0 -1
  252. package/dist/index.d.cts +0 -448
  253. package/dist/index.d.cts.map +0 -1
  254. package/dist/index.d.ts +0 -448
  255. package/dist/index.d.ts.map +0 -1
  256. package/dist/index.js +0 -71
  257. package/dist/index.js.map +0 -1
  258. package/dist/internal-schema.cjs +0 -253
  259. package/dist/internal-schema.cjs.map +0 -1
  260. package/dist/internal-schema.d.cts +0 -8
  261. package/dist/internal-schema.d.cts.map +0 -1
  262. package/dist/internal-schema.d.ts +0 -8
  263. package/dist/internal-schema.d.ts.map +0 -1
  264. package/dist/internal-schema.js +0 -248
  265. package/dist/internal-schema.js.map +0 -1
  266. package/dist/metadata.cjs +0 -57
  267. package/dist/metadata.cjs.map +0 -1
  268. package/dist/metadata.d.cts +0 -27
  269. package/dist/metadata.d.cts.map +0 -1
  270. package/dist/metadata.d.ts +0 -27
  271. package/dist/metadata.d.ts.map +0 -1
  272. package/dist/metadata.js +0 -54
  273. package/dist/metadata.js.map +0 -1
  274. package/dist/schema.cjs +0 -1522
  275. package/dist/schema.cjs.map +0 -1
  276. package/dist/schema.d.cts +0 -1196
  277. package/dist/schema.d.cts.map +0 -1
  278. package/dist/schema.d.ts +0 -1196
  279. package/dist/schema.d.ts.map +0 -1
  280. package/dist/schema.js +0 -1516
  281. package/dist/schema.js.map +0 -1
  282. package/dist/snapshot/adapter.cjs +0 -31
  283. package/dist/snapshot/adapter.cjs.map +0 -1
  284. package/dist/snapshot/adapter.d.cts +0 -258
  285. package/dist/snapshot/adapter.d.cts.map +0 -1
  286. package/dist/snapshot/adapter.d.ts +0 -258
  287. package/dist/snapshot/adapter.d.ts.map +0 -1
  288. package/dist/snapshot/adapter.js +0 -27
  289. package/dist/snapshot/adapter.js.map +0 -1
  290. package/dist/snapshot/adapters/fallback.cjs +0 -453
  291. package/dist/snapshot/adapters/fallback.cjs.map +0 -1
  292. package/dist/snapshot/adapters/fallback.d.cts +0 -185
  293. package/dist/snapshot/adapters/fallback.d.cts.map +0 -1
  294. package/dist/snapshot/adapters/fallback.d.ts +0 -185
  295. package/dist/snapshot/adapters/fallback.d.ts.map +0 -1
  296. package/dist/snapshot/adapters/fallback.js +0 -446
  297. package/dist/snapshot/adapters/fallback.js.map +0 -1
  298. package/dist/snapshot/adapters/node-test.cjs +0 -301
  299. package/dist/snapshot/adapters/node-test.cjs.map +0 -1
  300. package/dist/snapshot/adapters/node-test.d.cts +0 -131
  301. package/dist/snapshot/adapters/node-test.d.cts.map +0 -1
  302. package/dist/snapshot/adapters/node-test.d.ts +0 -131
  303. package/dist/snapshot/adapters/node-test.d.ts.map +0 -1
  304. package/dist/snapshot/adapters/node-test.js +0 -297
  305. package/dist/snapshot/adapters/node-test.js.map +0 -1
  306. package/dist/snapshot/index.cjs +0 -61
  307. package/dist/snapshot/index.cjs.map +0 -1
  308. package/dist/snapshot/index.d.cts +0 -40
  309. package/dist/snapshot/index.d.cts.map +0 -1
  310. package/dist/snapshot/index.d.ts +0 -40
  311. package/dist/snapshot/index.d.ts.map +0 -1
  312. package/dist/snapshot/index.js +0 -44
  313. package/dist/snapshot/index.js.map +0 -1
  314. package/dist/snapshot/node-version.cjs +0 -49
  315. package/dist/snapshot/node-version.cjs.map +0 -1
  316. package/dist/snapshot/node-version.d.cts +0 -34
  317. package/dist/snapshot/node-version.d.cts.map +0 -1
  318. package/dist/snapshot/node-version.d.ts +0 -34
  319. package/dist/snapshot/node-version.d.ts.map +0 -1
  320. package/dist/snapshot/node-version.js +0 -44
  321. package/dist/snapshot/node-version.js.map +0 -1
  322. package/dist/snapshot/select-adapter.cjs +0 -170
  323. package/dist/snapshot/select-adapter.cjs.map +0 -1
  324. package/dist/snapshot/select-adapter.d.cts +0 -128
  325. package/dist/snapshot/select-adapter.d.cts.map +0 -1
  326. package/dist/snapshot/select-adapter.d.ts +0 -128
  327. package/dist/snapshot/select-adapter.d.ts.map +0 -1
  328. package/dist/snapshot/select-adapter.js +0 -164
  329. package/dist/snapshot/select-adapter.js.map +0 -1
  330. package/dist/snapshot/serializer.cjs +0 -246
  331. package/dist/snapshot/serializer.cjs.map +0 -1
  332. package/dist/snapshot/serializer.d.cts +0 -126
  333. package/dist/snapshot/serializer.d.cts.map +0 -1
  334. package/dist/snapshot/serializer.d.ts +0 -126
  335. package/dist/snapshot/serializer.d.ts.map +0 -1
  336. package/dist/snapshot/serializer.js +0 -238
  337. package/dist/snapshot/serializer.js.map +0 -1
  338. package/dist/standard-schema.cjs +0 -13
  339. package/dist/standard-schema.cjs.map +0 -1
  340. package/dist/standard-schema.d.cts +0 -192
  341. package/dist/standard-schema.d.cts.map +0 -1
  342. package/dist/standard-schema.d.ts +0 -192
  343. package/dist/standard-schema.d.ts.map +0 -1
  344. package/dist/standard-schema.js +0 -12
  345. package/dist/standard-schema.js.map +0 -1
  346. package/dist/types.cjs +0 -22
  347. package/dist/types.cjs.map +0 -1
  348. package/dist/types.d.cts +0 -905
  349. package/dist/types.d.cts.map +0 -1
  350. package/dist/types.d.ts +0 -905
  351. package/dist/types.d.ts.map +0 -1
  352. package/dist/types.js +0 -21
  353. package/dist/types.js.map +0 -1
  354. package/dist/use.cjs +0 -240
  355. package/dist/use.cjs.map +0 -1
  356. package/dist/use.d.cts +0 -8
  357. package/dist/use.d.cts.map +0 -1
  358. package/dist/use.d.ts +0 -8
  359. package/dist/use.d.ts.map +0 -1
  360. package/dist/use.js +0 -236
  361. package/dist/use.js.map +0 -1
  362. package/dist/util.cjs +0 -255
  363. package/dist/util.cjs.map +0 -1
  364. package/dist/util.d.cts +0 -141
  365. package/dist/util.d.cts.map +0 -1
  366. package/dist/util.d.ts +0 -141
  367. package/dist/util.d.ts.map +0 -1
  368. package/dist/util.js +0 -234
  369. package/dist/util.js.map +0 -1
  370. package/dist/value-to-schema.cjs +0 -537
  371. package/dist/value-to-schema.cjs.map +0 -1
  372. package/dist/value-to-schema.d.cts +0 -144
  373. package/dist/value-to-schema.d.cts.map +0 -1
  374. package/dist/value-to-schema.d.ts +0 -144
  375. package/dist/value-to-schema.d.ts.map +0 -1
  376. package/dist/value-to-schema.js +0 -533
  377. package/dist/value-to-schema.js.map +0 -1
package/dist/schema.js DELETED
@@ -1,1516 +0,0 @@
1
- /**
2
- * Arguably-useful Zod schemas for common types and validation patterns.
3
- *
4
- * This module provides reusable Zod schemas for validating constructors,
5
- * functions, property keys, promises, and other common JavaScript types used
6
- * throughout the assertion system. These tend to work around the impedance
7
- * mismatch between **BUPKIS** and Zod.
8
- *
9
- * These are used internally, but consumers may also find them useful.
10
- *
11
- * For example, we have {@link FunctionSchema} which accepts any
12
- * function—regardless of its signature. We need this because Zod v4's
13
- * `z.function()` no longer returns a `ZodType` (ref:
14
- * {@link https://zod.dev/v4/changelog | Zod v4 Migration Guide}) and so behaves
15
- * differently. `FunctionSchema` allows us to work with functions as _values_
16
- * instead of something to be implemented.
17
- *
18
- * Similarly—but not a new development—`z.promise()` does not parse a
19
- * {@link Promise} object; it parses the _fulfilled value_. This is not what we
20
- * want for "is a Promise" assertions, but it _can_ be useful for making sense
21
- * of the fulfilled value. To solve this, we have
22
- * {@link WrappedPromiseLikeSchema} (which explicitly supports
23
- * {@link PromiseLike}/"thenable" objects).
24
- *
25
- * @module schema
26
- * @category API
27
- * @example
28
- *
29
- * ```ts
30
- * import * as schema from 'bupkis/schema';
31
- * ```
32
- *
33
- * @groupDescription Schema
34
- * Schemas for common types and validation patterns.
35
- */
36
- import { z } from 'zod';
37
- import { KEYPATH_REGEX } from "./constant.js";
38
- import { isConstructible, isFunction, isNonNullObject, isPromiseLike, } from "./guards.js";
39
- import { BupkisRegistry } from "./metadata.js";
40
- const { getPrototypeOf, prototype: objectPrototype } = Object;
41
- const { asyncIterator: asyncIteratorSymbol, iterator: symbolIterator } = Symbol;
42
- const { isInteger } = Number;
43
- /**
44
- * A Zod schema that validates JavaScript constructible functions.
45
- *
46
- * This schema validates values that can be used as constructors, including ES6
47
- * classes, traditional constructor functions, and built-in constructors. It
48
- * uses the {@link isConstructible} guard function to determine if a value can be
49
- * invoked with the `new` operator to create object instances.
50
- *
51
- * @privateRemarks
52
- * The schema is registered in the {@link BupkisRegistry} with the name
53
- * `ConstructibleSchema` for later reference and type checking purposes.
54
- * @example Direct Usage
55
- *
56
- * ```typescript
57
- * class MyClass {}
58
- * function MyConstructor() {}
59
- *
60
- * ConstructibleSchema.parse(MyClass); // ✓ Valid
61
- * ConstructibleSchema.parse(MyConstructor); // ✓ Valid
62
- * ConstructibleSchema.parse(Array); // ✓ Valid
63
- * ConstructibleSchema.parse(Date); // ✓ Valid
64
- * ConstructibleSchema.parse(() => {}); // ✗ Throws validation error
65
- * ConstructibleSchema.parse({}); // ✗ Throws validation error
66
- * ```
67
- *
68
- * @example Assertion Creation
69
- *
70
- * ```ts
71
- * import { createAssertion, use } from 'bupkis';
72
- * import { ConstructibleSchema } from 'bupkis/schema';
73
- *
74
- * const classAssertion = createAssertion(
75
- * [ConstructibleSchema, 'to be a subclass of Error'],
76
- * ConstructibleSchema.refine(
77
- * (subject) => subject.prototype instanceof Error,
78
- * ),
79
- * );
80
- *
81
- * const { expect } = use([classAssertion]);
82
- * expect(class MyError extends Error {}, 'to be a subclass of Error');
83
- * ```
84
- *
85
- * @group Schema
86
- */
87
- export const ConstructibleSchema = z
88
- .custom(isConstructible)
89
- .register(BupkisRegistry, { name: 'constructible' })
90
- .meta({ description: 'Constructible Function' });
91
- /**
92
- * A Zod schema that validates any JavaScript function.
93
- *
94
- * This schema accepts a function having any signature and avoids Zod's parsing
95
- * overhead.
96
- *
97
- * @remarks
98
- * Zod v~4.0.0 changed how {@link z.function z.function()} worked, which made it
99
- * unsuitable for validation. This was reverted in Zod v4.1.0.
100
- * @privateRemarks
101
- * The schema is registered in the {@link BupkisRegistry} with the name
102
- * `FunctionSchema` for later reference and type checking purposes.
103
- * @example Direct Usage
104
- *
105
- * ```typescript
106
- * FunctionSchema.parse(function () {}); // ✓ Valid
107
- * FunctionSchema.parse(() => {}); // ✓ Valid
108
- * FunctionSchema.parse(async () => {}); // ✓ Valid
109
- * FunctionSchema.parse(function* () {}); // ✓ Valid
110
- * FunctionSchema.parse(Math.max); // ✓ Valid
111
- * FunctionSchema.parse('not a function'); // ✗ Throws validation error
112
- * FunctionSchema.parse({}); // ✗ Throws validation error
113
- * ```
114
- *
115
- * @example Assertion Creation
116
- *
117
- * ```ts
118
- * import { createAssertion, use } from 'bupkis';
119
- * import { FunctionSchema } from 'bupkis/schema';
120
- *
121
- * const fnAssertion = createAssertion(
122
- * [FunctionSchema, 'to be a function with arity 2'],
123
- * FunctionSchema.refine((subject) => subject.length === 2),
124
- * );
125
- * const { expect } = use([fnAssertion]);
126
- * function add(a: number, b: number) {
127
- * return a + b;
128
- * }
129
- * expect(add, 'to be a function with arity 2');
130
- * ```
131
- *
132
- * @group Schema
133
- */
134
- export const FunctionSchema = z
135
- .custom(isFunction)
136
- .register(BupkisRegistry, {
137
- name: 'function',
138
- })
139
- .meta({ description: 'Any function' });
140
- /**
141
- * A Zod schema that validates non-collection objects and functions.
142
- *
143
- * Accepts plain objects, functions, arrays, dates, etc. but rejects collection
144
- * types like `Map`, `Set`, `WeakMap`, and `WeakSet`.
145
- *
146
- * @example Direct Usage
147
- *
148
- * ```typescript
149
- * NonCollectionObjectSchema.parse({}); // ✓ Valid
150
- * NonCollectionObjectSchema.parse({ key: 'value' }); // ✓ Valid
151
- * NonCollectionObjectSchema.parse(function () {}); // ✓ Valid
152
- * NonCollectionObjectSchema.parse(() => {}); // ✓ Valid
153
- * NonCollectionObjectSchema.parse(new Map()); // ✗ Throws validation error
154
- * NonCollectionObjectSchema.parse(new Set()); // ✗ Throws validation error
155
- * NonCollectionObjectSchema.parse(null); // ✗ Throws validation error
156
- * NonCollectionObjectSchema.parse(42); // ✗ Throws validation error
157
- * ```
158
- *
159
- * @example Assertion Creation
160
- *
161
- * ```ts
162
- * import { createAssertion, use } from 'bupkis';
163
- * import { NonCollectionObjectSchema } from 'bupkis/schema';
164
- *
165
- * const nonCollectionAssertion = createAssertion(
166
- * [NonCollectionObjectSchema, 'to be a non-collection object'],
167
- * NonCollectionObjectSchema,
168
- * );
169
- * const { expect } = use([nonCollectionAssertion]);
170
- * expect({ key: 'value' }, 'to be a non-collection object');
171
- * ```
172
- *
173
- * @group Schema
174
- */
175
- export const NonCollectionObjectSchema = z
176
- .custom((v) => (isNonNullObject(v) || isFunction(v)) &&
177
- !(v instanceof Map) &&
178
- !(v instanceof Set) &&
179
- !(v instanceof WeakMap) &&
180
- !(v instanceof WeakSet))
181
- .register(BupkisRegistry, { name: 'non-collection-object' })
182
- .meta({ description: 'Non-collection object or function' });
183
- /**
184
- * A Zod schema that validates JavaScript property keys.
185
- *
186
- * This schema validates values that can be used as object property keys in
187
- * JavaScript, which includes strings, numbers, and symbols. These are the three
188
- * types that JavaScript automatically converts to property keys when used in
189
- * object access or assignment operations.
190
- *
191
- * @privateRemarks
192
- * The schema is registered in the `BupkisRegistry` with the name
193
- * `PropertyKeySchema` for later reference and type checking purposes.
194
- * @example Direct Usage
195
- *
196
- * ```typescript
197
- * PropertyKeySchema.parse('stringKey'); // ✓ Valid
198
- * PropertyKeySchema.parse(42); // ✓ Valid
199
- * PropertyKeySchema.parse(Symbol('symbolKey')); // ✓ Valid
200
- * PropertyKeySchema.parse({}); // ✗ Throws validation error
201
- * PropertyKeySchema.parse(null); // ✗ Throws validation error
202
- * ```
203
- *
204
- * @example Assertion Creation
205
- *
206
- * ```ts
207
- * import { createAssertion, use } from 'bupkis';
208
- * import { PropertyKeySchema } from 'bupkis/schema';
209
- * const unknownRecordAssertion = createAssertion(
210
- * ['to be a record of anything'],
211
- * z.record(PropertyKeySchema, z.unknown()),
212
- * );
213
- *
214
- * const { expect } = use([unknownRecordAssertion]);
215
- * expect(
216
- * { 42: pants, shirts: 'foo', [Symbol('baz')]: null },
217
- * 'to be a record of anything',
218
- * );
219
- * ```
220
- *
221
- * @group Schema
222
- */
223
- export const PropertyKeySchema = z
224
- .union([z.string(), z.number(), z.symbol()])
225
- .register(BupkisRegistry, { name: 'property-key' })
226
- .meta({ description: 'Any valid object property name' });
227
- /**
228
- * A Zod schema that validates a keypath, which is a string featuring dot
229
- * notation or bracket notation, used to access nested object properties.
230
- *
231
- * Bare numbers must be wrapped in a string.
232
- *
233
- * @example Direct Usage
234
- *
235
- * ```typescript
236
- * KeypathSchema.parse('foo.bar'); // ✓ Valid
237
- * KeypathSchema.parse('arr[0].item'); // ✓ Valid
238
- * KeypathSchema.parse('obj["key"].prop'); // ✓ Valid
239
- * KeypathSchema.parse("obj['key'].prop"); // ✓ Valid
240
- * KeypathSchema.parse('simpleKey'); // ✓ Valid
241
- * KeypathSchema.parse('42'); // ✓ Valid
242
- * KeypathSchema.parse('invalid keypath!'); // ✗ Throws validation error
243
- * KeypathSchema.parse('foo..bar'); // ✗ Throws validation error
244
- * KeypathSchema.parse('foo[bar]'); // ✗ Throws validation error
245
- * KeypathSchema.parse(42); // ✗ Throws validation error
246
- * ```
247
- *
248
- * @example Assertion Creation
249
- *
250
- * ```ts
251
- * import { createAssertion, use } from 'bupkis';
252
- * import { KeypathSchema } from 'bupkis/schema';
253
- *
254
- * const hasKeypathAssertion = createAssertion(
255
- * [KeypathSchema, 'to be a keypath'],
256
- * KeypathSchema,
257
- * );
258
- *
259
- * const { expect } = use([hasKeypathAssertion]);
260
- * expect('foo.bar[0]["baz"]', 'to be a keypath');
261
- * ```
262
- *
263
- * @group Schema
264
- */
265
- export const KeypathSchema = z
266
- .string()
267
- .regex(KEYPATH_REGEX)
268
- .register(BupkisRegistry, { name: 'keypath' })
269
- .meta({ description: 'A keypath supporting dot and bracket notation' });
270
- /**
271
- * A Zod schema that validates "thenable" objects with a `.then()` method.
272
- *
273
- * This schema validates objects that implement the PromiseLike interface by
274
- * having a `.then()` method, which includes Promises and other thenable
275
- * objects.
276
- *
277
- * Unlike Zod's built-in `z.promise()`, this schema does not unwrap the resolved
278
- * value, meaning the result of parsing remains a Promise or thenable object.
279
- *
280
- * @privateRemarks
281
- * The schema is registered in the `BupkisRegistry` with the name
282
- * `WrappedPromiseLikeSchema` for later reference and type checking purposes.
283
- * This is useful when you need to validate that something is thenable without
284
- * automatically resolving it.
285
- * @example Direct Usage
286
- *
287
- * ```typescript
288
- * WrappedPromiseLikeSchema.parse(Promise.resolve(42)); // ✓ Valid (returns Promise)
289
- * WrappedPromiseLikeSchema.parse({ then: () => {} }); // ✓ Valid (thenable)
290
- * WrappedPromiseLikeSchema.parse(42); // ✗ Throws validation error
291
- * WrappedPromiseLikeSchema.parse({}); // ✗ Throws validation error
292
- * ```
293
- *
294
- * @example Assertion Creation
295
- *
296
- * ```ts
297
- * import { createAssertion, use } from 'bupkis';
298
- * import { WrappedPromiseLikeSchema } from 'bupkis/schema';
299
- *
300
- * const thenableAssertion = createAssertion(
301
- * [WrappedPromiseLikeSchema, 'to be a thenable'],
302
- * WrappedPromiseLikeSchema,
303
- * );
304
- *
305
- * const { expect } = use([thenableAssertion]);
306
- * // does nothing with 'pants'; await it elsewhere
307
- * expect({ then: () => Promise.resolve('pants') }, 'to be a thenable');
308
- * ```
309
- *
310
- * @group Schema
311
- */
312
- export const WrappedPromiseLikeSchema = z
313
- .custom((value) => isPromiseLike(value))
314
- .register(BupkisRegistry, { name: 'promiselike' })
315
- .meta({
316
- description: 'PromiseLike; unlike z.promise(), does not unwrap the resolved value',
317
- });
318
- /**
319
- * A Zod schema that validates plain objects with null prototypes.
320
- *
321
- * > Aliases: {@link NullProtoObjectSchema}, {@link DictionarySchema}
322
- *
323
- * This schema validates objects that have been created with
324
- * `Object.create(null)` or otherwise have their prototype set to `null`. Such
325
- * objects are "plain" objects without any inherited properties or methods from
326
- * `Object.prototype`, making them useful as pure data containers or
327
- * dictionaries.
328
- *
329
- * @privateRemarks
330
- * The schema is registered in the `BupkisRegistry` with the name
331
- * `ObjectWithNullPrototype` for later reference and type checking purposes.
332
- *
333
- * Changing this to be a `ZodRecord` would be nice, but that would end up
334
- * blasting away the original object's prototype.
335
- * @example Direct Usage
336
- *
337
- * ```typescript
338
- * const nullProtoObj = Object.create(null);
339
- * nullProtoObj.key = 'value';
340
- * NullProtoObjectSchema.parse(nullProtoObj); // ✓ Valid
341
- *
342
- * const regularObj = { key: 'value' };
343
- * NullProtoObjectSchema.parse(regularObj); // ✗ Throws validation error
344
- *
345
- * const emptyObj = {};
346
- * NullProtoObjectSchema.parse(emptyObj); // ✗ Throws validation error
347
- * ```
348
- *
349
- * @example Assertion Creation
350
- *
351
- * ```ts
352
- * import { createAssertion, use } from 'bupkis';
353
- * import { DictionarySchema } from 'bupkis/schema';
354
- *
355
- * const dictAssertion = createAssertion(
356
- * [DictionarySchema, 'to be a dictionary of numbers'],
357
- * DictionarySchema.pipe(z.record(z.number())),
358
- * );
359
- *
360
- * const { expect } = use([dictAssertion]);
361
- *
362
- * expect(Object.create(null, { pants: { value: 42, enumerable: true } }),
363
- * ```
364
- *
365
- * @group Schema
366
- */
367
- export const DictionarySchema = z
368
- .custom((value) => isNonNullObject(value) && getPrototypeOf(value) === null)
369
- .register(BupkisRegistry, { name: 'dictionary' })
370
- .meta({ description: 'Object with null prototype' });
371
- /**
372
- * {@inheritDoc DictionarySchema}
373
- *
374
- * @group Schema
375
- */
376
- export const NullProtoObjectSchema = DictionarySchema;
377
- /**
378
- * A Zod schema that validates functions declared with the `async` keyword.
379
- *
380
- * This schema validates functions that are explicitly declared as asynchronous
381
- * using the `async` keyword. It uses runtime introspection to check the
382
- * function's internal `[[ToString]]` representation to distinguish async
383
- * functions from regular functions that might return Promises.
384
- *
385
- * @remarks
386
- * **This schema _cannot_ match a function that returns a {@link Promise} but was
387
- * not declared via `async`.** Determining if a function returns a `Promise` is
388
- * only possible by execution of said function (which <span
389
- * class="bupkis">BUPKIS</span> avoids, naturally). This is a limitation of
390
- * JavaScript itself.
391
- * @example Direct Usage
392
- *
393
- * ```typescript
394
- * async function asyncFn() {
395
- * return 42;
396
- * }
397
- * AsyncFunctionSchema.parse(asyncFn); // ✓ Valid
398
- *
399
- * const asyncArrow = async () => 42;
400
- * AsyncFunctionSchema.parse(asyncArrow); // ✓ Valid
401
- *
402
- * function syncFn() {
403
- * return Promise.resolve(42);
404
- * }
405
- * AsyncFunctionSchema.parse(syncFn); // ✗ Throws validation error
406
- *
407
- * const regularFn = () => 42;
408
- * AsyncFunctionSchema.parse(regularFn); // ✗ Throws validation error
409
- * ```
410
- *
411
- * @example Assertion Creation
412
- *
413
- * ```ts
414
- * import { createAssertion, use } from 'bupkis';
415
- * import { AsyncFunctionSchema } from 'bupkis/schema';
416
- *
417
- * const asyncFnAssertion = createAssertion(
418
- * [AsyncFunctionSchema, 'to be an async function'],
419
- * AsyncFunctionSchema,
420
- * );
421
- *
422
- * const { expect } = use([asyncFnAssertion]);
423
- * expect(async () => {}, 'to be an async function');
424
- * ```
425
- *
426
- * @group Schema
427
- */
428
- export const AsyncFunctionSchema = FunctionSchema.refine((value) => objectPrototype.toString.call(value) === '[object AsyncFunction]')
429
- .describe('Function declared with the `async` keyword')
430
- .register(BupkisRegistry, { name: 'async-function' });
431
- /**
432
- * A Zod schema that validates truthy JavaScript values.
433
- *
434
- * This schema accepts any input value but only validates successfully if the
435
- * value is truthy according to JavaScript's truthiness rules. A value is truthy
436
- * if it converts to `true` when evaluated in a boolean context - essentially
437
- * any value that is not one of the eight falsy values.
438
- *
439
- * @privateRemarks
440
- * The schema is registered in the `BupkisRegistry` with the name `Truthy` and
441
- * indicates that it accepts anything as valid input for evaluation.
442
- * @example Direct Usage
443
- *
444
- * ```typescript
445
- * TruthySchema.parse(true); // ✓ Valid
446
- * TruthySchema.parse(1); // ✓ Valid
447
- * TruthySchema.parse('hello'); // ✓ Valid
448
- * TruthySchema.parse([]); // ✓ Valid (arrays are truthy)
449
- * TruthySchema.parse({}); // ✓ Valid (objects are truthy)
450
- * TruthySchema.parse(false); // ✗ Throws validation error
451
- * TruthySchema.parse(0); // ✗ Throws validation error
452
- * TruthySchema.parse(''); // ✗ Throws validation error
453
- * TruthySchema.parse(null); // ✗ Throws validation error
454
- * ```
455
- *
456
- * @example Assertion Creation
457
- *
458
- * ```ts
459
- * import { createAssertion, use } from 'bupkis';
460
- * import { TruthySchema } from 'bupkis/schema';
461
- *
462
- * const somethingAssertion = createAssertion(
463
- * ['to be something'],
464
- * TruthySchema,
465
- * );
466
- *
467
- * const { expect } = use([somethingAssertion]);
468
- *
469
- * expect('pants', 'to be something');
470
- * ```
471
- *
472
- * @group Schema
473
- * @see {@link FalsySchema}
474
- */
475
- export const TruthySchema = z
476
- .any()
477
- .nonoptional()
478
- .refine((value) => !!value)
479
- .register(BupkisRegistry, {
480
- name: 'truthy',
481
- })
482
- .meta({ description: 'Truthy value' });
483
- /**
484
- * A Zod schema that validates falsy JavaScript values.
485
- *
486
- * This schema accepts any input value but only validates successfully if the
487
- * value is falsy according to JavaScript's truthiness rules. The falsy values
488
- * in JavaScript are: `false`, `0`, `-0`, `0n`, `""` (empty string), `null`,
489
- * `undefined`, and `NaN`.
490
- *
491
- * @privateRemarks
492
- * The schema is registered in the `BupkisRegistry` with the name `Falsy` and
493
- * indicates that it accepts anything as valid input for evaluation.
494
- * @example Direct Usage
495
- *
496
- * ```typescript
497
- * FalsySchema.parse(false); // ✓ Valid
498
- * FalsySchema.parse(0); // ✓ Valid
499
- * FalsySchema.parse(-0); // ✓ Valid
500
- * FalsySchema.parse(0n); // ✓ Valid (BigInt zero)
501
- * FalsySchema.parse(''); // ✓ Valid (empty string)
502
- * FalsySchema.parse(null); // ✓ Valid
503
- * FalsySchema.parse(undefined); // ✓ Valid
504
- * FalsySchema.parse(NaN); // ✓ Valid
505
- * FalsySchema.parse(true); // ✗ Throws validation error
506
- * FalsySchema.parse(1); // ✗ Throws validation error
507
- * FalsySchema.parse('hello'); // ✗ Throws validation error
508
- * FalsySchema.parse({}); // ✗ Throws validation error
509
- * ```
510
- *
511
- * @example Assertion Creation
512
- *
513
- * ```ts
514
- * import { createAssertion, use } from 'bupkis';
515
- * import { FalsySchema } from 'bupkis/schema';
516
- *
517
- * const falsyAssertion = createAssertion(['to be nothing'], FalsySchema);
518
- *
519
- * const { expect } = use([falsyAssertion]);
520
- *
521
- * expect('', 'to be nothing');
522
- * ```
523
- *
524
- * @group Schema
525
- * @see {@link TruthySchema}
526
- */
527
- export const FalsySchema = z
528
- .any()
529
- .nullable()
530
- .refine((value) => !value)
531
- .register(BupkisRegistry, { name: 'falsy' })
532
- .meta({ description: 'Falsy value' });
533
- /**
534
- * A Zod schema that validates primitive JavaScript values.
535
- *
536
- * This schema validates any of the seven primitive data types in JavaScript:
537
- * string, number, boolean, bigint, symbol, null, and undefined. Primitive
538
- * values are immutable and are passed by value rather than by reference,
539
- * distinguishing them from objects and functions which are non-primitive
540
- * reference types.
541
- *
542
- * @privateRemarks
543
- * The schema is registered in the `BupkisRegistry` with the name `Primitive`
544
- * and indicates that it accepts primitive values as valid input.
545
- * @example Direct Usage
546
- *
547
- * ```typescript
548
- * PrimitiveSchema.parse('hello'); // ✓ Valid (string)
549
- * PrimitiveSchema.parse(42); // ✓ Valid (number)
550
- * PrimitiveSchema.parse(true); // ✓ Valid (boolean)
551
- * PrimitiveSchema.parse(BigInt(123)); // ✓ Valid (bigint)
552
- * PrimitiveSchema.parse(Symbol('test')); // ✓ Valid (symbol)
553
- * PrimitiveSchema.parse(null); // ✓ Valid (null)
554
- * PrimitiveSchema.parse(undefined); // ✓ Valid (undefined)
555
- * PrimitiveSchema.parse({}); // ✗ Throws validation error (object)
556
- * PrimitiveSchema.parse([]); // ✗ Throws validation error (array)
557
- * PrimitiveSchema.parse(() => {}); // ✗ Throws validation error (function)
558
- * ```
559
- *
560
- * @example Assertion Creation
561
- *
562
- * ```ts
563
- * import { createAssertion, use } from 'bupkis';
564
- * import { PrimitiveSchema } from 'bupkis/schema';
565
- *
566
- * const primitiveAssertion = createAssertion(
567
- * ['to be a primitive, Date, or RegExp'],
568
- * PrimitiveSchema.or(z.instanceof(Date)).or(z.instanceof(RegExp)),
569
- * );
570
- *
571
- * const { expect } = use([primitiveAssertion]);
572
- *
573
- * expect('pants', 'to be a primitive, Date, or RegExp');
574
- * ```
575
- *
576
- * @group Schema
577
- */
578
- export const PrimitiveSchema = z
579
- .union([
580
- z.string(),
581
- z.number(),
582
- z.boolean(),
583
- z.bigint(),
584
- z.symbol(),
585
- z.null(),
586
- z.undefined(),
587
- ])
588
- .register(BupkisRegistry, { name: 'primitive' })
589
- .meta({ description: 'Primitive value' });
590
- /**
591
- * A Zod schema that validates array-like structures including mutable and
592
- * readonly variants.
593
- *
594
- * This schema validates values that behave like arrays, including standard
595
- * arrays, tuples with rest elements, and their readonly counterparts. It
596
- * accepts any array-like structure that can hold elements of any type, making
597
- * it useful for validating collections where the specific array mutability or
598
- * tuple structure is not critical.
599
- *
600
- * @privateRemarks
601
- * The schema is registered in the {@link BupkisRegistry} with the name
602
- * `ArrayLike` for later reference and type checking purposes. This schema is
603
- * particularly useful when you need to accept various forms of array-like data
604
- * without being restrictive about mutability or exact tuple structure.
605
- * @example Direct Usage
606
- *
607
- * ```typescript
608
- * ArrayLikeSchema.parse([1, 2, 3]); // ✓ Valid (mutable array)
609
- * ArrayLikeSchema.parse(['a', 'b'] as const); // ✓ Valid (readonly array)
610
- * ArrayLikeSchema.parse([]); // ✓ Valid (empty array)
611
- * ArrayLikeSchema.parse([42, 'mixed', true]); // ✓ Valid (mixed types)
612
- * ArrayLikeSchema.parse('not an array'); // ✗ Throws validation error
613
- * ArrayLikeSchema.parse({}); // ✗ Throws validation error
614
- * ArrayLikeSchema.parse(null); // ✗ Throws validation error
615
- * ```
616
- *
617
- * @example Assertion Creation
618
- *
619
- * ```ts
620
- * import { createAssertion, use } from 'bupkis';
621
- * import { ArrayLikeSchema } from 'bupkis/schema';
622
- *
623
- * const argsAssertion = createAssertion(
624
- * [ArrayLikeSchema, 'to be a non-array arraylike object'],
625
- * ArrayLikeSchema.refine((subject) => !Array.isArray(subject)),
626
- * );
627
- *
628
- * const { expect } = use([argsAssertion]);
629
- * expect(
630
- * (function () {
631
- * return arguments;
632
- * })(),
633
- * 'to be a non-array arraylike object',
634
- * );
635
- * ```
636
- *
637
- * @group Schema
638
- */
639
- export const ArrayLikeSchema = z
640
- .custom((value) => value != null &&
641
- typeof value !== 'string' &&
642
- typeof value === 'object' &&
643
- symbolIterator in value &&
644
- 'length' in value &&
645
- typeof value.length === 'number' &&
646
- isInteger(value.length) &&
647
- value.length >= 0)
648
- .register(BupkisRegistry, {
649
- name: 'arraylike',
650
- })
651
- .meta({ description: 'Array-like value' });
652
- /**
653
- * A Zod schema that validates RegExp instances.
654
- *
655
- * This schema validates values that are instances of the RegExp class,
656
- * including regular expressions created with both literal syntax
657
- * (`/pattern/flags`) and the RegExp constructor (`new RegExp(pattern, flags)`).
658
- * It ensures the validated value is a proper regular expression object with all
659
- * associated methods and properties.
660
- *
661
- * @privateRemarks
662
- * The schema is registered in the `BupkisRegistry` with the name `RegExp` for
663
- * later reference and type checking purposes.
664
- * @example Direct Usage
665
- *
666
- * ```typescript
667
- * RegExpSchema.parse(/abc/gi); // ✓ Valid (literal syntax)
668
- * RegExpSchema.parse(new RegExp('abc', 'gi')); // ✓ Valid (constructor)
669
- * RegExpSchema.parse(/test/); // ✓ Valid (no flags)
670
- * RegExpSchema.parse(new RegExp('')); // ✓ Valid (empty pattern)
671
- * RegExpSchema.parse('abc'); // ✗ Throws validation error (string)
672
- * RegExpSchema.parse(/abc/.source); // ✗ Throws validation error (string pattern)
673
- * RegExpSchema.parse({}); // ✗ Throws validation error (object)
674
- * ```
675
- *
676
- * @example Assertion Creation
677
- *
678
- * ```ts
679
- * import { createAssertion, use } from 'bupkis';
680
- * import { RegExpSchema } from 'bupkis/schema';
681
- *
682
- * const globalRegexAssertion = createAssertion(
683
- * [RegExpSchema, 'to be a RegExp with the global flag'],
684
- * RegExpSchema.refine((subject) => subject.flags.includes('g')),
685
- * );
686
- *
687
- * const { expect } = use([globalRegexAssertion]);
688
- *
689
- * expect(/pants/g, 'to be a RegExp with the global flag');
690
- * ```
691
- *
692
- * @group Schema
693
- */
694
- export const RegExpSchema = z
695
- .instanceof(RegExp)
696
- .register(BupkisRegistry, { name: 'regexp' })
697
- .meta({ description: 'A RegExp instance' });
698
- /**
699
- * A Zod schema that validates non-negative integer values.
700
- *
701
- * This schema validates numbers that are both integers (whole numbers without
702
- * decimal parts) and non-negative (greater than or equal to zero). It combines
703
- * Zod's integer validation with non-negative validation to ensure the value is
704
- * a valid count, index, or other non-negative discrete quantity.
705
- *
706
- * @privateRemarks
707
- * The schema is registered in the {@link BupkisRegistry} with the name
708
- * `nonnegative-integer` for later reference and type checking purposes.
709
- * @example Direct Usage
710
- *
711
- * ```typescript
712
- * NonNegativeIntegerSchema.parse(0); // ✓ Valid (zero)
713
- * NonNegativeIntegerSchema.parse(42); // ✓ Valid (positive integer)
714
- * NonNegativeIntegerSchema.parse(1000); // ✓ Valid (large positive integer)
715
- * NonNegativeIntegerSchema.parse(-1); // ✗ Throws validation error (negative)
716
- * NonNegativeIntegerSchema.parse(3.14); // ✗ Throws validation error (not integer)
717
- * NonNegativeIntegerSchema.parse(-3.14); // ✗ Throws validation error (negative and not integer)
718
- * NonNegativeIntegerSchema.parse('42'); // ✗ Throws validation error (string)
719
- * ```
720
- *
721
- * @example Assertion Creation
722
- *
723
- * ```ts
724
- * import { createAssertion, use } from 'bupkis';
725
- * import { NonNegativeIntegerSchema } from 'bupkis/schema';
726
- *
727
- * const arrayIndexAssertion = createAssertion(
728
- * [NonNegativeIntegerSchema, 'to be a valid array index'],
729
- * NonNegativeIntegerSchema,
730
- * );
731
- *
732
- * const { expect } = use([arrayIndexAssertion]);
733
- * expect(0, 'to be a valid array index'); // Valid array index
734
- * expect(5, 'to be a valid array index'); // Valid array index
735
- * ```
736
- *
737
- * @group Schema
738
- */
739
- export const NonNegativeIntegerSchema = z
740
- .int()
741
- .nonnegative()
742
- .register(BupkisRegistry, { name: 'nonnegative-integer' })
743
- .meta({ description: 'A non-negative integer' });
744
- const MIN_TIMESTAMP = -8640000000000000;
745
- const MAX_TIMESTAMP = 8640000000000000;
746
- /**
747
- * A Zod schema that validates numeric timestamps.
748
- *
749
- * This schema validates JavaScript timestamp values (milliseconds since Unix
750
- * epoch) within the valid range for JavaScript Date objects. It ensures the
751
- * timestamp is an integer between -8,640,000,000,000,000 and
752
- * 8,640,000,000,000,000 milliseconds, which corresponds to the range of dates
753
- * that can be represented by JavaScript's Date object (approximately April 20,
754
- * 271821 BCE to September 13, 275760 CE).
755
- *
756
- * @example
757
- *
758
- * ```typescript
759
- * TimestampFormatSchema.parse(Date.now()); // ✓ Valid current timestamp
760
- * TimestampFormatSchema.parse(0); // ✓ Valid Unix epoch
761
- * TimestampFormatSchema.parse(-62135596800000); // ✓ Valid timestamp (year 1 CE)
762
- * TimestampFormatSchema.parse(1.5); // ✗ Throws - not an integer
763
- * TimestampFormatSchema.parse(9e15); // ✗ Throws - exceeds maximum timestamp
764
- * TimestampFormatSchema.parse('1234567890000'); // ✗ Throws - string not number
765
- * ```
766
- *
767
- * @group Schema
768
- */
769
- export const TimestampFormatSchema = z
770
- .int()
771
- .min(MIN_TIMESTAMP)
772
- .max(MAX_TIMESTAMP);
773
- /**
774
- * A Zod schema that validates ISO date strings.
775
- *
776
- * This schema validates ISO 8601 date and datetime strings in various formats.
777
- * It accepts both date-only formats (YYYY-MM-DD) and full datetime formats with
778
- * optional timezone information. The schema supports local datetime strings and
779
- * those with timezone offsets.
780
- *
781
- * @example
782
- *
783
- * ```typescript
784
- * ISODateFormatSchema.parse('2025-01-01'); // ✓ Valid ISO date
785
- * ISODateFormatSchema.parse('2025-01-01T10:30:00'); // ✓ Valid local datetime
786
- * ISODateFormatSchema.parse('2025-01-01T10:30:00Z'); // ✓ Valid UTC datetime
787
- * ISODateFormatSchema.parse('2025-01-01T10:30:00+05:30'); // ✓ Valid with offset
788
- * ISODateFormatSchema.parse('2025-01-01T10:30:00.123Z'); // ✓ Valid with milliseconds
789
- * ISODateFormatSchema.parse('01/01/2025'); // ✗ Throws - not ISO format
790
- * ISODateFormatSchema.parse('2025-13-01'); // ✗ Throws - invalid month
791
- * ISODateFormatSchema.parse('not-a-date'); // ✗ Throws - invalid format
792
- * ```
793
- *
794
- * @group Schema
795
- */
796
- export const ISODateFormatSchema = z.union([
797
- z.iso.datetime({ local: true, offset: true }),
798
- z.iso.date(),
799
- ]);
800
- /**
801
- * A Zod schema that validates date-like values.
802
- *
803
- * This schema accepts any value that can represent a date: native JavaScript
804
- * Date objects, ISO 8601 date strings, or numeric timestamps. It provides a
805
- * unified validation approach for date inputs across different assertion types.
806
- * The schema is registered in the BupkisRegistry for use in assertion
807
- * creation.
808
- *
809
- * @privateRemarks
810
- * This schema is registered with the name 'date-like' in the BupkisRegistry and
811
- * is commonly used in temporal assertions throughout the library.
812
- * @example
813
- *
814
- * ```typescript
815
- * DateLikeFormatSchema.parse(new Date()); // ✓ Valid Date object
816
- * DateLikeFormatSchema.parse('2025-01-01'); // ✓ Valid ISO date string
817
- * DateLikeFormatSchema.parse('2025-01-01T10:30:00Z'); // ✓ Valid ISO datetime
818
- * DateLikeFormatSchema.parse(Date.now()); // ✓ Valid timestamp
819
- * DateLikeFormatSchema.parse(0); // ✓ Valid Unix epoch
820
- * DateLikeFormatSchema.parse('invalid-date'); // ✗ Throws - invalid format
821
- * DateLikeFormatSchema.parse({}); // ✗ Throws - not date-like
822
- * DateLikeFormatSchema.parse(null); // ✗ Throws - null not accepted
823
- * ```
824
- *
825
- * @group Schema
826
- */
827
- export const DateLikeFormatSchema = z
828
- .union([z.date(), ISODateFormatSchema, TimestampFormatSchema])
829
- .register(BupkisRegistry, { name: 'date-like' })
830
- .meta({ description: 'Date, ISO string, or timestamp' });
831
- const DURATION_REGEX = /^(\d+)\s*(milliseconds?|ms|seconds?|s|minutes?|m|hours?|h|days?|d|weeks?|w|months?|months?|years?|y)$/i;
832
- /**
833
- * A Zod schema that validates duration string formats.
834
- *
835
- * This schema validates human-readable duration strings using a flexible format
836
- * that supports various time units with both full names and abbreviations. The
837
- * format is "{amount} {unit}" where amount is a positive integer and unit can
838
- * be any supported time unit. Extra whitespace is automatically trimmed.
839
- *
840
- * Supported units (case-insensitive):
841
- *
842
- * - Milliseconds: `millisecond`, `milliseconds`, `ms`
843
- * - Seconds: `second`, `seconds`, `s`
844
- * - Minutes: `minute`, `minutes`, `m`
845
- * - Hours: `hour`, `hours`, `h`
846
- * - Days: `day`, `days`, `d`
847
- * - Weeks: `week`, `weeks`, `w`
848
- * - Months: `month`, `months` (approximate: 30 days)
849
- * - Years: `year`, `years`, `y` (approximate: 365 days)
850
- *
851
- * @privateRemarks
852
- * This schema only validates the format; it does not perform any
853
- * transformations. For converting to milliseconds, use {@link DurationSchema}
854
- * instead. The schema is registered with the name 'duration' in the
855
- * BupkisRegistry.
856
- * @example
857
- *
858
- * ```typescript
859
- * DurationFormatSchema.parse('1 hour'); // ✓ Valid
860
- * DurationFormatSchema.parse('30 minutes'); // ✓ Valid
861
- * DurationFormatSchema.parse('2 days'); // ✓ Valid
862
- * DurationFormatSchema.parse(' 5 seconds '); // ✓ Valid (whitespace trimmed)
863
- * DurationFormatSchema.parse('1h'); // ✓ Valid abbreviation
864
- * DurationFormatSchema.parse('10 ms'); // ✓ Valid milliseconds
865
- * DurationFormatSchema.parse('-5 minutes'); // ✗ Throws - negative not allowed
866
- * DurationFormatSchema.parse('1.5 hours'); // ✗ Throws - decimal not allowed
867
- * DurationFormatSchema.parse('5'); // ✗ Throws - missing unit
868
- * DurationFormatSchema.parse('five minutes'); // ✗ Throws - non-numeric amount
869
- * ```
870
- *
871
- * @group Schema
872
- */
873
- export const DurationFormatSchema = z
874
- .stringFormat('duration', (val) => DURATION_REGEX.test(val.trim()))
875
- .register(BupkisRegistry, { name: 'duration' })
876
- .meta({
877
- description: 'Duration string format like "1 hour", "30 minutes", "2 days"',
878
- });
879
- /**
880
- * A Zod schema that validates and transforms duration strings to milliseconds.
881
- *
882
- * This schema extends {@link DurationFormatSchema} by adding a transformation
883
- * step that converts valid duration strings into their equivalent values in
884
- * milliseconds. It supports the same flexible duration format but returns a
885
- * numeric value representing the total duration in milliseconds.
886
- *
887
- * The transformation handles all supported time units with accurate
888
- * conversions, except for months and years which use approximate values (30
889
- * days per month, 365 days per year) due to the variability of these units.
890
- *
891
- * Conversion rates:
892
- *
893
- * - 1 millisecond = 1 ms
894
- * - 1 second = 1,000 ms
895
- * - 1 minute = 60,000 ms
896
- * - 1 hour = 3,600,000 ms
897
- * - 1 day = 86,400,000 ms
898
- * - 1 week = 604,800,000 ms
899
- * - 1 month ≈ 2,592,000,000 ms (30 days)
900
- * - 1 year ≈ 31,536,000,000 ms (365 days)
901
- *
902
- * @privateRemarks
903
- * The transformation function includes comprehensive error handling, though
904
- * errors should never occur in practice due to the format validation step. The
905
- * schema is registered with the name 'duration' in the BupkisRegistry.
906
- * @example
907
- *
908
- * ```typescript
909
- * DurationSchema.parse('1 hour'); // → 3600000
910
- * DurationSchema.parse('30 minutes'); // → 1800000
911
- * DurationSchema.parse('2 days'); // → 172800000
912
- * DurationSchema.parse('500 ms'); // → 500
913
- * DurationSchema.parse('1 week'); // → 604800000
914
- * DurationSchema.parse('1 year'); // → 31536000000 (approximate)
915
- * DurationSchema.parse('invalid'); // ✗ Throws - invalid format
916
- * ```
917
- *
918
- * @group Schema
919
- */
920
- /**
921
- * Duration unit multipliers in milliseconds. Units are stored lowercase for
922
- * case-insensitive matching.
923
- */
924
- const DURATION_MULTIPLIERS = {
925
- d: 24 * 60 * 60 * 1000,
926
- day: 24 * 60 * 60 * 1000,
927
- days: 24 * 60 * 60 * 1000,
928
- h: 60 * 60 * 1000,
929
- hour: 60 * 60 * 1000,
930
- hours: 60 * 60 * 1000,
931
- m: 60 * 1000,
932
- millisecond: 1,
933
- milliseconds: 1,
934
- minute: 60 * 1000,
935
- minutes: 60 * 1000,
936
- month: 30 * 24 * 60 * 60 * 1000, // Approximate
937
- months: 30 * 24 * 60 * 60 * 1000, // Approximate
938
- ms: 1,
939
- s: 1000,
940
- second: 1000,
941
- seconds: 1000,
942
- w: 7 * 24 * 60 * 60 * 1000,
943
- week: 7 * 24 * 60 * 60 * 1000,
944
- weeks: 7 * 24 * 60 * 60 * 1000,
945
- y: 365 * 24 * 60 * 60 * 1000, // Approximate
946
- year: 365 * 24 * 60 * 60 * 1000, // Approximate
947
- years: 365 * 24 * 60 * 60 * 1000, // Approximate
948
- };
949
- export const DurationSchema = DurationFormatSchema.transform((duration) => {
950
- const match = duration.trim().match(DURATION_REGEX);
951
- if (!match) {
952
- throw new Error('Invalid duration format'); // Should never happen due to format validation
953
- }
954
- const [, amountStr, unit] = match;
955
- const amount = parseInt(amountStr, 10);
956
- const multiplier = DURATION_MULTIPLIERS[unit.toLowerCase()];
957
- if (multiplier === undefined) {
958
- throw new Error(`Unrecognized duration unit: ${unit}`); // Should never happen
959
- }
960
- return amount * multiplier;
961
- })
962
- .register(BupkisRegistry, { name: 'duration' })
963
- .describe('Duration string like "1 hour", "30 minutes", "2 days" (transforms to milliseconds)');
964
- /**
965
- * Schema that matches any `Set` instance, including those with any element
966
- * types.
967
- *
968
- * This schema is designed for runtime type checking and assertion matching
969
- * rather than parsing or validation of Set contents. It uses `instanceof`
970
- * checking to verify that a value is a Set, regardless of what elements it
971
- * contains.
972
- *
973
- * **Usage in Assertions:**
974
- *
975
- * - Collection size validation: `expect(mySet, 'to have size', 3)`
976
- * - Set operations: `expect(setA, 'to be a subset of', setB)`
977
- * - Emptiness checks: `expect(mySet, 'to be empty')`
978
- * - Element containment: `expect(mySet, 'to contain', value)`
979
- *
980
- * **Why `instanceof` Instead of Zod's `z.set()`:**
981
- *
982
- * - `z.set()` requires knowing the element schema at compile time
983
- * - This schema works with Sets containing any element types
984
- * - Focuses on the Set structure rather than element validation
985
- * - Better performance for assertion matching scenarios
986
- *
987
- * @example
988
- *
989
- * ```ts
990
- * // Matches any Set regardless of element types
991
- * SetSchema.parse(new Set([1, 2, 3])); // ✓ passes
992
- * SetSchema.parse(new Set(['a', 'b'])); // ✓ passes
993
- * SetSchema.parse(new Set()); // ✓ passes (empty Set)
994
- * SetSchema.parse([]); // ✗ fails (not a Set)
995
- * SetSchema.parse(new WeakSet()); // ✗ fails (use AnySetSchema)
996
- * ```
997
- *
998
- * @group Schema
999
- */
1000
- export const SetSchema = z
1001
- .instanceof(Set)
1002
- .register(BupkisRegistry, { name: 'set' })
1003
- .meta({ description: 'A Set instance' });
1004
- /**
1005
- * Schema that matches either `Set` or `WeakSet` instances.
1006
- *
1007
- * This unified schema handles both strong and weak Set types, making it useful
1008
- * for assertions that should work with either variant. The distinction between
1009
- * Set and WeakSet is important for garbage collection behavior but often
1010
- * irrelevant for structural assertions.
1011
- *
1012
- * **Key Differences Between Set and WeakSet:**
1013
- *
1014
- * - **Set**: Holds strong references, prevents GC, iterable, any value types
1015
- * - **WeakSet**: Holds weak references, allows GC, not iterable, object keys only
1016
- *
1017
- * **Usage Scenarios:**
1018
- *
1019
- * - Generic containment checks that work with both types
1020
- * - Polymorphic collection handling in assertion libraries
1021
- * - APIs that accept either Set variant for flexibility
1022
- *
1023
- * **WeakSet Limitations:**
1024
- *
1025
- * - Only accepts object or symbol values (primitives will cause runtime errors)
1026
- * - Cannot be iterated or have size checked
1027
- * - Some Set-specific assertions may not work with WeakSet
1028
- *
1029
- * @example
1030
- *
1031
- * ```ts
1032
- * // Accepts both Set and WeakSet
1033
- * AnySetSchema.parse(new Set([1, 2, 3])); // ✓ passes
1034
- * AnySetSchema.parse(new WeakSet([obj1, obj2])); // ✓ passes
1035
- * AnySetSchema.parse(new Map()); // ✗ fails (wrong collection type)
1036
- *
1037
- * // Usage in assertions
1038
- * expect(myWeakSet, 'to contain', someObject); // Works with WeakSet
1039
- * expect(mySet, 'to contain', 'string'); // Works with Set
1040
- * ```
1041
- *
1042
- * @group Schema
1043
- */
1044
- export const AnySetSchema = SetSchema.or(z.instanceof(WeakSet))
1045
- .register(BupkisRegistry, { name: 'set-or-weakset' })
1046
- .describe('A Set or WeakSet instance');
1047
- /**
1048
- * Schema that matches any `Map` instance, including those with any key-value
1049
- * types.
1050
- *
1051
- * This schema provides runtime type checking for Map instances without
1052
- * requiring compile-time knowledge of key or value schemas. It uses
1053
- * `instanceof` checking to verify Map structure while being agnostic about the
1054
- * contained data types.
1055
- *
1056
- * **Usage in Assertions:**
1057
- *
1058
- * - Size validation: `expect(myMap, 'to have size', 5)`
1059
- * - Key presence: `expect(myMap, 'to have key', 'someKey')`
1060
- * - Value containment: `expect(myMap, 'to have value', expectedValue)`
1061
- * - Entry validation: `expect(myMap, 'to have entry', [key, value])`
1062
- * - Map equality: `expect(mapA, 'to equal', mapB)`
1063
- *
1064
- * **Advantages Over `z.map()`:**
1065
- *
1066
- * - Works with Maps having heterogeneous key/value types
1067
- * - No need to specify key and value schemas upfront
1068
- * - Optimized for structural validation rather than content parsing
1069
- * - Better error messages for type mismatches in assertions
1070
- *
1071
- * @example
1072
- *
1073
- * ```ts
1074
- * // Matches any Map regardless of key/value types
1075
- * MapSchema.parse(new Map([['key', 'value']])); // ✓ passes
1076
- * MapSchema.parse(
1077
- * new Map([
1078
- * [1, 'one'],
1079
- * [2, 'two'],
1080
- * ]),
1081
- * ); // ✓ passes
1082
- * MapSchema.parse(new Map()); // ✓ passes (empty Map)
1083
- * MapSchema.parse({}); // ✗ fails (plain object)
1084
- * MapSchema.parse(new WeakMap()); // ✗ fails (use AnyMapSchema)
1085
- * ```
1086
- *
1087
- * @group Schema
1088
- */
1089
- export const MapSchema = z
1090
- .instanceof(Map)
1091
- .register(BupkisRegistry, { name: 'map' })
1092
- .meta({ description: 'A Map instance' });
1093
- export const WeakMapSchema = z
1094
- .instanceof(WeakMap)
1095
- .register(BupkisRegistry, { name: 'weakmap' })
1096
- .meta({ description: 'A WeakMap instance' });
1097
- /**
1098
- * Schema that matches either `Map` or `WeakMap` instances.
1099
- *
1100
- * This union schema accommodates both strong and weak Map variants, enabling
1101
- * assertions to work polymorphically across both collection types. The choice
1102
- * between Map and WeakMap affects memory management and iteration capabilities
1103
- * but often doesn't impact structural validation logic.
1104
- *
1105
- * **Key Differences Between Map and WeakMap:**
1106
- *
1107
- * - **Map**: Strong references, enumerable, iterable, any key types, has `.size`
1108
- * - **WeakMap**: Weak references, not enumerable, not iterable, object keys only,
1109
- * no `.size`
1110
- *
1111
- * **Usage Considerations:**
1112
- *
1113
- * - Use for assertions that need to work with either Map type
1114
- * - Particularly useful in library code that accepts either variant
1115
- * - Some Map-specific operations (iteration, size) won't work with WeakMap
1116
- * - WeakMap key restrictions (objects/symbols only) should be considered
1117
- *
1118
- * **Memory Management Implications:**
1119
- *
1120
- * - Map entries prevent garbage collection of keys
1121
- * - WeakMap entries allow garbage collection when keys become unreachable
1122
- * - This affects long-lived caches and memory-sensitive applications
1123
- *
1124
- * @example
1125
- *
1126
- * ```ts
1127
- * // Accepts both Map and WeakMap
1128
- * AnyMapSchema.parse(new Map([['key', 'value']])); // ✓ passes
1129
- * AnyMapSchema.parse(new WeakMap([[obj, 'value']])); // ✓ passes
1130
- * AnyMapSchema.parse(new Set()); // ✗ fails (wrong collection type)
1131
- *
1132
- * // Usage in assertions
1133
- * expect(myWeakMap, 'to have key', someObject); // Works with WeakMap
1134
- * expect(myMap, 'to have key', 'stringKey'); // Works with Map
1135
- * expect(myWeakMap, 'to have size', 3); // ✗ Fails - WeakMap has no size
1136
- * ```
1137
- *
1138
- * @group Schema
1139
- */
1140
- export const AnyMapSchema = MapSchema.or(WeakMapSchema)
1141
- .register(BupkisRegistry, { name: 'map-or-weakmap' })
1142
- .describe('A Map or WeakMap instance');
1143
- export const StringSchema = z
1144
- .string()
1145
- .register(BupkisRegistry, { name: 'string' })
1146
- .meta({ description: 'A string' });
1147
- export const NumberSchema = z
1148
- .number()
1149
- .register(BupkisRegistry, { name: 'number' })
1150
- .meta({ description: 'A number' });
1151
- export const InfinitySchema = z
1152
- .literal(Infinity)
1153
- .register(BupkisRegistry, { name: 'infinity' })
1154
- .meta({ description: 'The number Infinity' });
1155
- export const NegativeInfinitySchema = z
1156
- .literal(-Infinity)
1157
- .register(BupkisRegistry, { name: 'negative-infinity' })
1158
- .meta({ description: 'The number -Infinity' });
1159
- export const BooleanSchema = z
1160
- .boolean()
1161
- .register(BupkisRegistry, { name: 'boolean' })
1162
- .meta({ description: 'A boolean' });
1163
- export const PositiveNumberSchema = z
1164
- .number()
1165
- .positive()
1166
- .register(BupkisRegistry, { name: 'positive-number' })
1167
- .meta({ description: 'A positive number' });
1168
- export const NegativeNumberSchema = z
1169
- .number()
1170
- .negative()
1171
- .register(BupkisRegistry, { name: 'negative-number' })
1172
- .meta({ description: 'A negative number' });
1173
- export const BigintSchema = z
1174
- .bigint()
1175
- .register(BupkisRegistry, { name: 'bigint' })
1176
- .meta({ description: 'A bigint' });
1177
- export const SymbolSchema = z
1178
- .symbol()
1179
- .register(BupkisRegistry, { name: 'symbol' })
1180
- .meta({ description: 'A symbol' });
1181
- export const UnknownSchema = z
1182
- .unknown()
1183
- .register(BupkisRegistry, { name: 'unknown' })
1184
- .meta({ description: 'Unknown value' });
1185
- export const UnknownArraySchema = z
1186
- .array(UnknownSchema)
1187
- .register(BupkisRegistry, { name: 'unknown-array' })
1188
- .meta({ description: 'An array of unknown values' });
1189
- export const DateSchema = z
1190
- .date()
1191
- .register(BupkisRegistry, { name: 'date' })
1192
- .meta({ description: 'A Date' });
1193
- export const UnknownRecordSchema = z
1194
- .record(PropertyKeySchema, UnknownSchema)
1195
- .register(BupkisRegistry, { name: 'record' })
1196
- .meta({ description: 'A record with unknown values and property keys' });
1197
- export const ErrorSchema = z
1198
- .instanceof(Error)
1199
- .register(BupkisRegistry, { name: 'error' })
1200
- .meta({ description: 'An Error instance' });
1201
- export const RegexpSchema = z
1202
- .instanceof(RegExp)
1203
- .register(BupkisRegistry, { name: 'regexp' })
1204
- .meta({ description: 'A RegExp instance' });
1205
- export const NullSchema = z
1206
- .null()
1207
- .register(BupkisRegistry, { name: 'null' })
1208
- .meta({ description: 'Null' });
1209
- export const UndefinedSchema = z
1210
- .undefined()
1211
- .register(BupkisRegistry, { name: 'undefined' })
1212
- .meta({ description: 'Undefined' });
1213
- export const WeakSetSchema = z
1214
- .instanceof(WeakSet)
1215
- .register(BupkisRegistry, { name: 'weakset' })
1216
- .meta({ description: 'A WeakSet instance' });
1217
- export const WeakRefSchema = z
1218
- .instanceof(WeakRef)
1219
- .register(BupkisRegistry, { name: 'weakref' })
1220
- .meta({ description: 'A WeakRef instance' });
1221
- export const AnyObjectSchema = z
1222
- .looseObject({})
1223
- .register(BupkisRegistry, { name: 'object' })
1224
- .meta({ description: 'An object with unknown properties' });
1225
- /**
1226
- * Memoizes {@link createErrorMessageSchema}
1227
- */
1228
- const errorMessageSchemaCache = new Map();
1229
- /**
1230
- * Memoizes {@link createErrorMessageRegexSchema}
1231
- */
1232
- const errorMessageRegexSchemaCache = new WeakMap();
1233
- /**
1234
- * @function
1235
- * @internal
1236
- */
1237
- export const createErrorMessageSchema = (param) => {
1238
- const cached = errorMessageSchemaCache.get(param);
1239
- if (cached) {
1240
- return cached;
1241
- }
1242
- const schema = z
1243
- .looseObject({
1244
- message: z.coerce.string().pipe(z.literal(param)),
1245
- })
1246
- .or(z.coerce.string().pipe(z.literal(param)));
1247
- errorMessageSchemaCache.set(param, schema);
1248
- return schema;
1249
- };
1250
- /**
1251
- * @function
1252
- * @internal
1253
- */
1254
- export const createErrorMessageRegexSchema = (param) => {
1255
- const cached = errorMessageRegexSchemaCache.get(param);
1256
- if (cached) {
1257
- return cached;
1258
- }
1259
- const schema = z
1260
- .looseObject({
1261
- message: z.coerce.string().regex(param),
1262
- })
1263
- .or(z.coerce.string().regex(param));
1264
- errorMessageRegexSchemaCache.set(param, schema);
1265
- return schema;
1266
- };
1267
- /**
1268
- * Schema for snapshot options.
1269
- */
1270
- export const SnapshotOptionsSchema = z.object({
1271
- hint: z.string().optional(),
1272
- serializer: z.any().optional(),
1273
- });
1274
- /**
1275
- * Schema matching any synchronous iterable (has `Symbol.iterator` method).
1276
- *
1277
- * This schema validates values that implement the synchronous iteration
1278
- * protocol, meaning they have a `Symbol.iterator` method that returns an
1279
- * iterator. This includes arrays, strings, Sets, Maps, generators, and custom
1280
- * iterable objects.
1281
- *
1282
- * @example Direct Usage
1283
- *
1284
- * ```typescript
1285
- * SyncIterableSchema.parse([1, 2, 3]); // ✓ Valid (array)
1286
- * SyncIterableSchema.parse('hello'); // ✓ Valid (string)
1287
- * SyncIterableSchema.parse(new Set()); // ✓ Valid (Set)
1288
- * SyncIterableSchema.parse(new Map()); // ✓ Valid (Map)
1289
- * SyncIterableSchema.parse(
1290
- * (function* () {
1291
- * yield 1;
1292
- * })(),
1293
- * ); // ✓ Valid (generator)
1294
- * SyncIterableSchema.parse(42); // ✗ Throws validation error
1295
- * SyncIterableSchema.parse({}); // ✗ Throws validation error (plain objects are not iterable)
1296
- * ```
1297
- *
1298
- * @example Assertion Creation
1299
- *
1300
- * ```ts
1301
- * import { createAssertion, use } from 'bupkis';
1302
- * import { SyncIterableSchema } from 'bupkis/schema';
1303
- *
1304
- * const iterableAssertion = createAssertion(
1305
- * [SyncIterableSchema, 'to be iterable'],
1306
- * SyncIterableSchema,
1307
- * );
1308
- *
1309
- * const { expect } = use([iterableAssertion]);
1310
- * expect([1, 2, 3], 'to be iterable');
1311
- * ```
1312
- *
1313
- * @group Schema
1314
- */
1315
- export const SyncIterableSchema = z
1316
- .custom((val) => val != null &&
1317
- typeof val[symbolIterator] === 'function', { error: 'Expected a synchronous iterable' })
1318
- .register(BupkisRegistry, { name: 'sync-iterable' })
1319
- .meta({ description: 'A synchronous iterable (has Symbol.iterator)' });
1320
- /**
1321
- * Schema matching any synchronous iterator (has `next()` method).
1322
- *
1323
- * This schema validates values that implement the iterator protocol, meaning
1324
- * they have a `next()` method that returns `{ value, done }` objects. This
1325
- * includes iterator objects returned from calling `Symbol.iterator` on
1326
- * iterables, generator objects, and custom iterator implementations.
1327
- *
1328
- * @remarks
1329
- * Note that most iterators are also iterable (they have `Symbol.iterator`
1330
- * returning `this`), but this schema specifically checks for the `next()`
1331
- * method which is the core iterator requirement.
1332
- * @example Direct Usage
1333
- *
1334
- * ```typescript
1335
- * const arr = [1, 2, 3];
1336
- * SyncIteratorSchema.parse(arr[Symbol.iterator]()); // ✓ Valid
1337
- * SyncIteratorSchema.parse(
1338
- * (function* () {
1339
- * yield 1;
1340
- * })(),
1341
- * ); // ✓ Valid (generators are iterators)
1342
- * SyncIteratorSchema.parse({
1343
- * next: () => ({ done: true, value: undefined }),
1344
- * }); // ✓ Valid
1345
- * SyncIteratorSchema.parse([1, 2, 3]); // ✗ Throws (array is iterable, not iterator)
1346
- * SyncIteratorSchema.parse({}); // ✗ Throws validation error
1347
- * ```
1348
- *
1349
- * @example Assertion Creation
1350
- *
1351
- * ```ts
1352
- * import { createAssertion, use } from 'bupkis';
1353
- * import { SyncIteratorSchema } from 'bupkis/schema';
1354
- *
1355
- * const iteratorAssertion = createAssertion(
1356
- * [SyncIteratorSchema, 'to be an iterator'],
1357
- * SyncIteratorSchema,
1358
- * );
1359
- *
1360
- * const { expect } = use([iteratorAssertion]);
1361
- * expect([1, 2, 3][Symbol.iterator](), 'to be an iterator');
1362
- * ```
1363
- *
1364
- * @group Schema
1365
- */
1366
- export const SyncIteratorSchema = z
1367
- .custom((val) => val != null &&
1368
- typeof val.next === 'function', { error: 'Expected a synchronous iterator' })
1369
- .register(BupkisRegistry, { name: 'sync-iterator' })
1370
- .meta({ description: 'A synchronous iterator (has next() method)' });
1371
- /**
1372
- * Schema matching either a sync iterable or sync iterator.
1373
- *
1374
- * This union schema accepts values that implement either the iterable protocol
1375
- * (has `Symbol.iterator`) or the iterator protocol (has `next()` method). This
1376
- * is useful for assertions that can work with either form, allowing users to
1377
- * pass arrays, generators, or raw iterators interchangeably.
1378
- *
1379
- * @example Direct Usage
1380
- *
1381
- * ```typescript
1382
- * SyncIterableOrIteratorSchema.parse([1, 2, 3]); // ✓ Valid (iterable)
1383
- * SyncIterableOrIteratorSchema.parse([1, 2, 3][Symbol.iterator]()); // ✓ Valid (iterator)
1384
- * SyncIterableOrIteratorSchema.parse(
1385
- * (function* () {
1386
- * yield 1;
1387
- * })(),
1388
- * ); // ✓ Valid (both)
1389
- * SyncIterableOrIteratorSchema.parse(42); // ✗ Throws validation error
1390
- * ```
1391
- *
1392
- * @group Schema
1393
- */
1394
- export const SyncIterableOrIteratorSchema = z
1395
- .union([SyncIterableSchema, SyncIteratorSchema])
1396
- .register(BupkisRegistry, { name: 'sync-iterable-or-iterator' })
1397
- .meta({ description: 'A synchronous iterable or iterator' });
1398
- /**
1399
- * Schema matching any asynchronous iterable (has `Symbol.asyncIterator`
1400
- * method).
1401
- *
1402
- * This schema validates values that implement the asynchronous iteration
1403
- * protocol, meaning they have a `Symbol.asyncIterator` method that returns an
1404
- * async iterator. This includes async generators, Node.js Readable streams
1405
- * (v10+), and Web ReadableStreams (in modern browsers and Node.js v22+).
1406
- *
1407
- * @example Direct Usage
1408
- *
1409
- * ```typescript
1410
- * AsyncIterableSchema.parse(
1411
- * (async function* () {
1412
- * yield 1;
1413
- * })(),
1414
- * ); // ✓ Valid (async generator)
1415
- * AsyncIterableSchema.parse(Readable.from([1, 2, 3])); // ✓ Valid (Node stream)
1416
- * AsyncIterableSchema.parse(new ReadableStream()); // ✓ Valid (Web stream, Node 22+)
1417
- * AsyncIterableSchema.parse([1, 2, 3]); // ✗ Throws (sync iterable, not async)
1418
- * AsyncIterableSchema.parse(Promise.resolve(1)); // ✗ Throws (Promise is not iterable)
1419
- * ```
1420
- *
1421
- * @example Assertion Creation
1422
- *
1423
- * ```ts
1424
- * import { createAssertion, use } from 'bupkis';
1425
- * import { AsyncIterableSchema } from 'bupkis/schema';
1426
- *
1427
- * const asyncIterableAssertion = createAssertion(
1428
- * [AsyncIterableSchema, 'to be an async iterable'],
1429
- * AsyncIterableSchema,
1430
- * );
1431
- *
1432
- * const { expect } = use([asyncIterableAssertion]);
1433
- * expect(
1434
- * (async function* () {
1435
- * yield 1;
1436
- * })(),
1437
- * 'to be an async iterable',
1438
- * );
1439
- * ```
1440
- *
1441
- * @group Schema
1442
- */
1443
- export const AsyncIterableSchema = z
1444
- .custom((val) => val != null &&
1445
- typeof val[asyncIteratorSymbol] ===
1446
- 'function', { error: 'Expected an asynchronous iterable' })
1447
- .register(BupkisRegistry, { name: 'async-iterable' })
1448
- .meta({ description: 'An asynchronous iterable (has Symbol.asyncIterator)' });
1449
- /**
1450
- * Schema matching any asynchronous iterator (has async `next()` method).
1451
- *
1452
- * This schema validates values that implement the async iterator protocol,
1453
- * meaning they have a `next()` method that returns a Promise of `{ value, done
1454
- * }`. This includes async iterator objects and custom async iterator
1455
- * implementations.
1456
- *
1457
- * @remarks
1458
- * This schema checks for the presence of a `next()` method but cannot verify at
1459
- * parse time that it returns a Promise. The async behavior is validated at
1460
- * iteration time.
1461
- * @example Direct Usage
1462
- *
1463
- * ```typescript
1464
- * const asyncGen = (async function* () {
1465
- * yield 1;
1466
- * })();
1467
- * AsyncIteratorSchema.parse(asyncGen); // ✓ Valid (async generator is also iterator)
1468
- * AsyncIteratorSchema.parse({
1469
- * next: async () => ({ done: true, value: undefined }),
1470
- * }); // ✓ Valid
1471
- * AsyncIteratorSchema.parse([1, 2, 3][Symbol.iterator]()); // ✓ Valid (has next())
1472
- * AsyncIteratorSchema.parse({}); // ✗ Throws validation error
1473
- * ```
1474
- *
1475
- * @group Schema
1476
- */
1477
- export const AsyncIteratorSchema = z
1478
- .custom((val) => val != null &&
1479
- typeof val.next === 'function', { error: 'Expected an asynchronous iterator' })
1480
- .register(BupkisRegistry, { name: 'async-iterator' })
1481
- .meta({ description: 'An asynchronous iterator (has next() method)' });
1482
- /**
1483
- * Schema matching either an async iterable or async iterator. Also accepts sync
1484
- * iterables (can be consumed async).
1485
- *
1486
- * This permissive union schema accepts values that can be iterated
1487
- * asynchronously, including:
1488
- *
1489
- * - Async iterables (has `Symbol.asyncIterator`)
1490
- * - Async iterators (has async `next()`)
1491
- * - Sync iterables (has `Symbol.iterator`) - these can be consumed via async
1492
- * iteration
1493
- *
1494
- * This flexibility allows async assertions to work uniformly with various
1495
- * iterable types.
1496
- *
1497
- * @example Direct Usage
1498
- *
1499
- * ```typescript
1500
- * AsyncIterableOrIteratorSchema.parse(
1501
- * (async function* () {
1502
- * yield 1;
1503
- * })(),
1504
- * ); // ✓ Valid
1505
- * AsyncIterableOrIteratorSchema.parse([1, 2, 3]); // ✓ Valid (sync iterable works)
1506
- * AsyncIterableOrIteratorSchema.parse(Readable.from([1, 2, 3])); // ✓ Valid
1507
- * AsyncIterableOrIteratorSchema.parse(42); // ✗ Throws validation error
1508
- * ```
1509
- *
1510
- * @group Schema
1511
- */
1512
- export const AsyncIterableOrIteratorSchema = z
1513
- .union([AsyncIterableSchema, AsyncIteratorSchema, SyncIterableSchema])
1514
- .register(BupkisRegistry, { name: 'async-iterable-or-iterator' })
1515
- .meta({ description: 'An async iterable, async iterator, or sync iterable' });
1516
- //# sourceMappingURL=schema.js.map