bupkis 0.18.1 → 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.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -4
- package/src/assertion/assertion-types.ts +4 -4
- package/src/assertion/impl/sync-parametric.ts +1 -1
- package/src/expect.ts +0 -4
- package/src/guards.ts +24 -24
- package/src/internal-schema.ts +16 -32
- package/src/value-to-schema.ts +1 -1
- package/dist/assertion/assertion-async.cjs +0 -268
- package/dist/assertion/assertion-async.cjs.map +0 -1
- package/dist/assertion/assertion-async.d.cts +0 -40
- package/dist/assertion/assertion-async.d.cts.map +0 -1
- package/dist/assertion/assertion-async.d.ts +0 -40
- package/dist/assertion/assertion-async.d.ts.map +0 -1
- package/dist/assertion/assertion-async.js +0 -259
- package/dist/assertion/assertion-async.js.map +0 -1
- package/dist/assertion/assertion-standard-schema-async.cjs +0 -132
- package/dist/assertion/assertion-standard-schema-async.cjs.map +0 -1
- package/dist/assertion/assertion-standard-schema-async.d.cts +0 -52
- package/dist/assertion/assertion-standard-schema-async.d.cts.map +0 -1
- package/dist/assertion/assertion-standard-schema-async.d.ts +0 -52
- package/dist/assertion/assertion-standard-schema-async.d.ts.map +0 -1
- package/dist/assertion/assertion-standard-schema-async.js +0 -128
- package/dist/assertion/assertion-standard-schema-async.js.map +0 -1
- package/dist/assertion/assertion-standard-schema-sync.cjs +0 -141
- package/dist/assertion/assertion-standard-schema-sync.cjs.map +0 -1
- package/dist/assertion/assertion-standard-schema-sync.d.cts +0 -52
- package/dist/assertion/assertion-standard-schema-sync.d.cts.map +0 -1
- package/dist/assertion/assertion-standard-schema-sync.d.ts +0 -52
- package/dist/assertion/assertion-standard-schema-sync.d.ts.map +0 -1
- package/dist/assertion/assertion-standard-schema-sync.js +0 -137
- package/dist/assertion/assertion-standard-schema-sync.js.map +0 -1
- package/dist/assertion/assertion-sync.cjs +0 -284
- package/dist/assertion/assertion-sync.cjs.map +0 -1
- package/dist/assertion/assertion-sync.d.cts +0 -60
- package/dist/assertion/assertion-sync.d.cts.map +0 -1
- package/dist/assertion/assertion-sync.d.ts +0 -60
- package/dist/assertion/assertion-sync.d.ts.map +0 -1
- package/dist/assertion/assertion-sync.js +0 -275
- package/dist/assertion/assertion-sync.js.map +0 -1
- package/dist/assertion/assertion-types.cjs +0 -20
- package/dist/assertion/assertion-types.cjs.map +0 -1
- package/dist/assertion/assertion-types.d.cts +0 -1086
- package/dist/assertion/assertion-types.d.cts.map +0 -1
- package/dist/assertion/assertion-types.d.ts +0 -1086
- package/dist/assertion/assertion-types.d.ts.map +0 -1
- package/dist/assertion/assertion-types.js +0 -19
- package/dist/assertion/assertion-types.js.map +0 -1
- package/dist/assertion/assertion.cjs +0 -382
- package/dist/assertion/assertion.cjs.map +0 -1
- package/dist/assertion/assertion.d.cts +0 -109
- package/dist/assertion/assertion.d.cts.map +0 -1
- package/dist/assertion/assertion.d.ts +0 -109
- package/dist/assertion/assertion.d.ts.map +0 -1
- package/dist/assertion/assertion.js +0 -375
- package/dist/assertion/assertion.js.map +0 -1
- package/dist/assertion/create.cjs +0 -148
- package/dist/assertion/create.cjs.map +0 -1
- package/dist/assertion/create.d.cts +0 -85
- package/dist/assertion/create.d.cts.map +0 -1
- package/dist/assertion/create.d.ts +0 -85
- package/dist/assertion/create.d.ts.map +0 -1
- package/dist/assertion/create.js +0 -143
- package/dist/assertion/create.js.map +0 -1
- package/dist/assertion/format-assertion-failure.cjs +0 -63
- package/dist/assertion/format-assertion-failure.cjs.map +0 -1
- package/dist/assertion/format-assertion-failure.d.cts +0 -21
- package/dist/assertion/format-assertion-failure.d.cts.map +0 -1
- package/dist/assertion/format-assertion-failure.d.ts +0 -21
- package/dist/assertion/format-assertion-failure.d.ts.map +0 -1
- package/dist/assertion/format-assertion-failure.js +0 -59
- package/dist/assertion/format-assertion-failure.js.map +0 -1
- package/dist/assertion/impl/assertion-util.cjs +0 -68
- package/dist/assertion/impl/assertion-util.cjs.map +0 -1
- package/dist/assertion/impl/assertion-util.d.cts +0 -36
- package/dist/assertion/impl/assertion-util.d.cts.map +0 -1
- package/dist/assertion/impl/assertion-util.d.ts +0 -36
- package/dist/assertion/impl/assertion-util.d.ts.map +0 -1
- package/dist/assertion/impl/assertion-util.js +0 -62
- package/dist/assertion/impl/assertion-util.js.map +0 -1
- package/dist/assertion/impl/async-iterable.cjs +0 -627
- package/dist/assertion/impl/async-iterable.cjs.map +0 -1
- package/dist/assertion/impl/async-iterable.d.cts +0 -406
- package/dist/assertion/impl/async-iterable.d.cts.map +0 -1
- package/dist/assertion/impl/async-iterable.d.ts +0 -406
- package/dist/assertion/impl/async-iterable.d.ts.map +0 -1
- package/dist/assertion/impl/async-iterable.js +0 -624
- package/dist/assertion/impl/async-iterable.js.map +0 -1
- package/dist/assertion/impl/async-parametric.cjs +0 -412
- package/dist/assertion/impl/async-parametric.cjs.map +0 -1
- package/dist/assertion/impl/async-parametric.d.cts +0 -278
- package/dist/assertion/impl/async-parametric.d.cts.map +0 -1
- package/dist/assertion/impl/async-parametric.d.ts +0 -278
- package/dist/assertion/impl/async-parametric.d.ts.map +0 -1
- package/dist/assertion/impl/async-parametric.js +0 -409
- package/dist/assertion/impl/async-parametric.js.map +0 -1
- package/dist/assertion/impl/async.cjs +0 -56
- package/dist/assertion/impl/async.cjs.map +0 -1
- package/dist/assertion/impl/async.d.cts +0 -179
- package/dist/assertion/impl/async.d.cts.map +0 -1
- package/dist/assertion/impl/async.d.ts +0 -179
- package/dist/assertion/impl/async.d.ts.map +0 -1
- package/dist/assertion/impl/async.js +0 -39
- package/dist/assertion/impl/async.js.map +0 -1
- package/dist/assertion/impl/index.cjs +0 -37
- package/dist/assertion/impl/index.cjs.map +0 -1
- package/dist/assertion/impl/index.d.cts +0 -21
- package/dist/assertion/impl/index.d.cts.map +0 -1
- package/dist/assertion/impl/index.d.ts +0 -21
- package/dist/assertion/impl/index.d.ts.map +0 -1
- package/dist/assertion/impl/index.js +0 -21
- package/dist/assertion/impl/index.js.map +0 -1
- package/dist/assertion/impl/iteration-util.cjs +0 -297
- package/dist/assertion/impl/iteration-util.cjs.map +0 -1
- package/dist/assertion/impl/iteration-util.d.cts +0 -12
- package/dist/assertion/impl/iteration-util.d.cts.map +0 -1
- package/dist/assertion/impl/iteration-util.d.ts +0 -12
- package/dist/assertion/impl/iteration-util.d.ts.map +0 -1
- package/dist/assertion/impl/iteration-util.js +0 -282
- package/dist/assertion/impl/iteration-util.js.map +0 -1
- package/dist/assertion/impl/snapshot.cjs +0 -276
- package/dist/assertion/impl/snapshot.cjs.map +0 -1
- package/dist/assertion/impl/snapshot.d.cts +0 -278
- package/dist/assertion/impl/snapshot.d.cts.map +0 -1
- package/dist/assertion/impl/snapshot.d.ts +0 -278
- package/dist/assertion/impl/snapshot.d.ts.map +0 -1
- package/dist/assertion/impl/snapshot.js +0 -273
- package/dist/assertion/impl/snapshot.js.map +0 -1
- package/dist/assertion/impl/sync-basic.cjs +0 -553
- package/dist/assertion/impl/sync-basic.cjs.map +0 -1
- package/dist/assertion/impl/sync-basic.d.cts +0 -528
- package/dist/assertion/impl/sync-basic.d.cts.map +0 -1
- package/dist/assertion/impl/sync-basic.d.ts +0 -528
- package/dist/assertion/impl/sync-basic.d.ts.map +0 -1
- package/dist/assertion/impl/sync-basic.js +0 -550
- package/dist/assertion/impl/sync-basic.js.map +0 -1
- package/dist/assertion/impl/sync-collection.cjs +0 -856
- package/dist/assertion/impl/sync-collection.cjs.map +0 -1
- package/dist/assertion/impl/sync-collection.d.cts +0 -607
- package/dist/assertion/impl/sync-collection.d.cts.map +0 -1
- package/dist/assertion/impl/sync-collection.d.ts +0 -607
- package/dist/assertion/impl/sync-collection.d.ts.map +0 -1
- package/dist/assertion/impl/sync-collection.js +0 -850
- package/dist/assertion/impl/sync-collection.js.map +0 -1
- package/dist/assertion/impl/sync-date.cjs +0 -341
- package/dist/assertion/impl/sync-date.cjs.map +0 -1
- package/dist/assertion/impl/sync-date.d.cts +0 -209
- package/dist/assertion/impl/sync-date.d.cts.map +0 -1
- package/dist/assertion/impl/sync-date.d.ts +0 -209
- package/dist/assertion/impl/sync-date.d.ts.map +0 -1
- package/dist/assertion/impl/sync-date.js +0 -338
- package/dist/assertion/impl/sync-date.js.map +0 -1
- package/dist/assertion/impl/sync-esoteric.cjs +0 -214
- package/dist/assertion/impl/sync-esoteric.cjs.map +0 -1
- package/dist/assertion/impl/sync-esoteric.d.cts +0 -191
- package/dist/assertion/impl/sync-esoteric.d.cts.map +0 -1
- package/dist/assertion/impl/sync-esoteric.d.ts +0 -191
- package/dist/assertion/impl/sync-esoteric.d.ts.map +0 -1
- package/dist/assertion/impl/sync-esoteric.js +0 -211
- package/dist/assertion/impl/sync-esoteric.js.map +0 -1
- package/dist/assertion/impl/sync-iterable.cjs +0 -512
- package/dist/assertion/impl/sync-iterable.cjs.map +0 -1
- package/dist/assertion/impl/sync-iterable.d.cts +0 -334
- package/dist/assertion/impl/sync-iterable.d.cts.map +0 -1
- package/dist/assertion/impl/sync-iterable.d.ts +0 -334
- package/dist/assertion/impl/sync-iterable.d.ts.map +0 -1
- package/dist/assertion/impl/sync-iterable.js +0 -509
- package/dist/assertion/impl/sync-iterable.js.map +0 -1
- package/dist/assertion/impl/sync-parametric.cjs +0 -805
- package/dist/assertion/impl/sync-parametric.cjs.map +0 -1
- package/dist/assertion/impl/sync-parametric.d.cts +0 -560
- package/dist/assertion/impl/sync-parametric.d.cts.map +0 -1
- package/dist/assertion/impl/sync-parametric.d.ts +0 -560
- package/dist/assertion/impl/sync-parametric.d.ts.map +0 -1
- package/dist/assertion/impl/sync-parametric.js +0 -802
- package/dist/assertion/impl/sync-parametric.js.map +0 -1
- package/dist/assertion/impl/sync.cjs +0 -214
- package/dist/assertion/impl/sync.cjs.map +0 -1
- package/dist/assertion/impl/sync.d.cts +0 -512
- package/dist/assertion/impl/sync.d.cts.map +0 -1
- package/dist/assertion/impl/sync.d.ts +0 -512
- package/dist/assertion/impl/sync.d.ts.map +0 -1
- package/dist/assertion/impl/sync.js +0 -197
- package/dist/assertion/impl/sync.js.map +0 -1
- package/dist/assertion/index.cjs +0 -38
- package/dist/assertion/index.cjs.map +0 -1
- package/dist/assertion/index.d.cts +0 -18
- package/dist/assertion/index.d.cts.map +0 -1
- package/dist/assertion/index.d.ts +0 -18
- package/dist/assertion/index.d.ts.map +0 -1
- package/dist/assertion/index.js +0 -17
- package/dist/assertion/index.js.map +0 -1
- package/dist/assertion/slotify.cjs +0 -165
- package/dist/assertion/slotify.cjs.map +0 -1
- package/dist/assertion/slotify.d.cts +0 -11
- package/dist/assertion/slotify.d.cts.map +0 -1
- package/dist/assertion/slotify.d.ts +0 -11
- package/dist/assertion/slotify.d.ts.map +0 -1
- package/dist/assertion/slotify.js +0 -161
- package/dist/assertion/slotify.js.map +0 -1
- package/dist/bootstrap.cjs +0 -43
- package/dist/bootstrap.cjs.map +0 -1
- package/dist/bootstrap.d.cts +0 -27
- package/dist/bootstrap.d.cts.map +0 -1
- package/dist/bootstrap.d.ts +0 -27
- package/dist/bootstrap.d.ts.map +0 -1
- package/dist/bootstrap.js +0 -40
- package/dist/bootstrap.js.map +0 -1
- package/dist/constant.cjs +0 -82
- package/dist/constant.cjs.map +0 -1
- package/dist/constant.d.cts +0 -69
- package/dist/constant.d.cts.map +0 -1
- package/dist/constant.d.ts +0 -69
- package/dist/constant.d.ts.map +0 -1
- package/dist/constant.js +0 -79
- package/dist/constant.js.map +0 -1
- package/dist/diff.cjs +0 -340
- package/dist/diff.cjs.map +0 -1
- package/dist/diff.d.cts +0 -51
- package/dist/diff.d.cts.map +0 -1
- package/dist/diff.d.ts +0 -51
- package/dist/diff.d.ts.map +0 -1
- package/dist/diff.js +0 -334
- package/dist/diff.js.map +0 -1
- package/dist/error.cjs +0 -204
- package/dist/error.cjs.map +0 -1
- package/dist/error.d.cts +0 -212
- package/dist/error.d.cts.map +0 -1
- package/dist/error.d.ts +0 -212
- package/dist/error.d.ts.map +0 -1
- package/dist/error.js +0 -191
- package/dist/error.js.map +0 -1
- package/dist/expect.cjs +0 -590
- package/dist/expect.cjs.map +0 -1
- package/dist/expect.d.cts +0 -138
- package/dist/expect.d.cts.map +0 -1
- package/dist/expect.d.ts +0 -138
- package/dist/expect.d.ts.map +0 -1
- package/dist/expect.js +0 -582
- package/dist/expect.js.map +0 -1
- package/dist/guards.cjs +0 -297
- package/dist/guards.cjs.map +0 -1
- package/dist/guards.d.cts +0 -231
- package/dist/guards.d.cts.map +0 -1
- package/dist/guards.d.ts +0 -231
- package/dist/guards.d.ts.map +0 -1
- package/dist/guards.js +0 -277
- package/dist/guards.js.map +0 -1
- package/dist/index.cjs +0 -111
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -448
- package/dist/index.d.cts.map +0 -1
- package/dist/index.d.ts +0 -448
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -71
- package/dist/index.js.map +0 -1
- package/dist/internal-schema.cjs +0 -253
- package/dist/internal-schema.cjs.map +0 -1
- package/dist/internal-schema.d.cts +0 -8
- package/dist/internal-schema.d.cts.map +0 -1
- package/dist/internal-schema.d.ts +0 -8
- package/dist/internal-schema.d.ts.map +0 -1
- package/dist/internal-schema.js +0 -248
- package/dist/internal-schema.js.map +0 -1
- package/dist/metadata.cjs +0 -57
- package/dist/metadata.cjs.map +0 -1
- package/dist/metadata.d.cts +0 -27
- package/dist/metadata.d.cts.map +0 -1
- package/dist/metadata.d.ts +0 -27
- package/dist/metadata.d.ts.map +0 -1
- package/dist/metadata.js +0 -54
- package/dist/metadata.js.map +0 -1
- package/dist/schema.cjs +0 -1522
- package/dist/schema.cjs.map +0 -1
- package/dist/schema.d.cts +0 -1196
- package/dist/schema.d.cts.map +0 -1
- package/dist/schema.d.ts +0 -1196
- package/dist/schema.d.ts.map +0 -1
- package/dist/schema.js +0 -1516
- package/dist/schema.js.map +0 -1
- package/dist/snapshot/adapter.cjs +0 -31
- package/dist/snapshot/adapter.cjs.map +0 -1
- package/dist/snapshot/adapter.d.cts +0 -258
- package/dist/snapshot/adapter.d.cts.map +0 -1
- package/dist/snapshot/adapter.d.ts +0 -258
- package/dist/snapshot/adapter.d.ts.map +0 -1
- package/dist/snapshot/adapter.js +0 -27
- package/dist/snapshot/adapter.js.map +0 -1
- package/dist/snapshot/adapters/fallback.cjs +0 -453
- package/dist/snapshot/adapters/fallback.cjs.map +0 -1
- package/dist/snapshot/adapters/fallback.d.cts +0 -185
- package/dist/snapshot/adapters/fallback.d.cts.map +0 -1
- package/dist/snapshot/adapters/fallback.d.ts +0 -185
- package/dist/snapshot/adapters/fallback.d.ts.map +0 -1
- package/dist/snapshot/adapters/fallback.js +0 -446
- package/dist/snapshot/adapters/fallback.js.map +0 -1
- package/dist/snapshot/adapters/node-test.cjs +0 -301
- package/dist/snapshot/adapters/node-test.cjs.map +0 -1
- package/dist/snapshot/adapters/node-test.d.cts +0 -131
- package/dist/snapshot/adapters/node-test.d.cts.map +0 -1
- package/dist/snapshot/adapters/node-test.d.ts +0 -131
- package/dist/snapshot/adapters/node-test.d.ts.map +0 -1
- package/dist/snapshot/adapters/node-test.js +0 -297
- package/dist/snapshot/adapters/node-test.js.map +0 -1
- package/dist/snapshot/index.cjs +0 -61
- package/dist/snapshot/index.cjs.map +0 -1
- package/dist/snapshot/index.d.cts +0 -40
- package/dist/snapshot/index.d.cts.map +0 -1
- package/dist/snapshot/index.d.ts +0 -40
- package/dist/snapshot/index.d.ts.map +0 -1
- package/dist/snapshot/index.js +0 -44
- package/dist/snapshot/index.js.map +0 -1
- package/dist/snapshot/node-version.cjs +0 -49
- package/dist/snapshot/node-version.cjs.map +0 -1
- package/dist/snapshot/node-version.d.cts +0 -34
- package/dist/snapshot/node-version.d.cts.map +0 -1
- package/dist/snapshot/node-version.d.ts +0 -34
- package/dist/snapshot/node-version.d.ts.map +0 -1
- package/dist/snapshot/node-version.js +0 -44
- package/dist/snapshot/node-version.js.map +0 -1
- package/dist/snapshot/select-adapter.cjs +0 -170
- package/dist/snapshot/select-adapter.cjs.map +0 -1
- package/dist/snapshot/select-adapter.d.cts +0 -128
- package/dist/snapshot/select-adapter.d.cts.map +0 -1
- package/dist/snapshot/select-adapter.d.ts +0 -128
- package/dist/snapshot/select-adapter.d.ts.map +0 -1
- package/dist/snapshot/select-adapter.js +0 -164
- package/dist/snapshot/select-adapter.js.map +0 -1
- package/dist/snapshot/serializer.cjs +0 -246
- package/dist/snapshot/serializer.cjs.map +0 -1
- package/dist/snapshot/serializer.d.cts +0 -126
- package/dist/snapshot/serializer.d.cts.map +0 -1
- package/dist/snapshot/serializer.d.ts +0 -126
- package/dist/snapshot/serializer.d.ts.map +0 -1
- package/dist/snapshot/serializer.js +0 -238
- package/dist/snapshot/serializer.js.map +0 -1
- package/dist/standard-schema.cjs +0 -13
- package/dist/standard-schema.cjs.map +0 -1
- package/dist/standard-schema.d.cts +0 -192
- package/dist/standard-schema.d.cts.map +0 -1
- package/dist/standard-schema.d.ts +0 -192
- package/dist/standard-schema.d.ts.map +0 -1
- package/dist/standard-schema.js +0 -12
- package/dist/standard-schema.js.map +0 -1
- package/dist/types.cjs +0 -22
- package/dist/types.cjs.map +0 -1
- package/dist/types.d.cts +0 -905
- package/dist/types.d.cts.map +0 -1
- package/dist/types.d.ts +0 -905
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -21
- package/dist/types.js.map +0 -1
- package/dist/use.cjs +0 -240
- package/dist/use.cjs.map +0 -1
- package/dist/use.d.cts +0 -8
- package/dist/use.d.cts.map +0 -1
- package/dist/use.d.ts +0 -8
- package/dist/use.d.ts.map +0 -1
- package/dist/use.js +0 -236
- package/dist/use.js.map +0 -1
- package/dist/util.cjs +0 -255
- package/dist/util.cjs.map +0 -1
- package/dist/util.d.cts +0 -141
- package/dist/util.d.cts.map +0 -1
- package/dist/util.d.ts +0 -141
- package/dist/util.d.ts.map +0 -1
- package/dist/util.js +0 -234
- package/dist/util.js.map +0 -1
- package/dist/value-to-schema.cjs +0 -537
- package/dist/value-to-schema.cjs.map +0 -1
- package/dist/value-to-schema.d.cts +0 -144
- package/dist/value-to-schema.d.cts.map +0 -1
- package/dist/value-to-schema.d.ts +0 -144
- package/dist/value-to-schema.d.ts.map +0 -1
- package/dist/value-to-schema.js +0 -533
- 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
|