typesea 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +104 -41
- package/SECURITY.md +52 -0
- package/dist/aot/index.d.ts +1 -1
- package/dist/aot/index.d.ts.map +1 -1
- package/dist/aot/index.js +22 -3
- package/dist/builders/composite.d.ts +6 -3
- package/dist/builders/composite.d.ts.map +1 -1
- package/dist/builders/composite.js +22 -13
- package/dist/builders/index.d.ts +6 -5
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +5 -4
- package/dist/builders/modifier.d.ts +6 -0
- package/dist/builders/modifier.d.ts.map +1 -1
- package/dist/builders/modifier.js +14 -0
- package/dist/builders/object/guard.d.ts +54 -2
- package/dist/builders/object/guard.d.ts.map +1 -1
- package/dist/builders/object/guard.js +117 -7
- package/dist/builders/object/index.d.ts +2 -2
- package/dist/builders/object/index.d.ts.map +1 -1
- package/dist/builders/object/index.js +1 -1
- package/dist/builders/object/schema.d.ts +33 -2
- package/dist/builders/object/schema.d.ts.map +1 -1
- package/dist/builders/object/schema.js +198 -8
- package/dist/builders/object/types.d.ts +15 -0
- package/dist/builders/object/types.d.ts.map +1 -1
- package/dist/builders/runtime.d.ts +40 -0
- package/dist/builders/runtime.d.ts.map +1 -0
- package/dist/builders/runtime.js +150 -0
- package/dist/builders/scalar.d.ts +20 -1
- package/dist/builders/scalar.d.ts.map +1 -1
- package/dist/builders/scalar.js +54 -1
- package/dist/builders/table.d.ts +31 -5
- package/dist/builders/table.d.ts.map +1 -1
- package/dist/builders/table.js +31 -5
- package/dist/builders/types.d.ts +6 -0
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/compile/check-composite.d.ts +3 -1
- package/dist/compile/check-composite.d.ts.map +1 -1
- package/dist/compile/check-composite.js +143 -11
- package/dist/compile/check-scalar.d.ts +10 -0
- package/dist/compile/check-scalar.d.ts.map +1 -1
- package/dist/compile/check-scalar.js +138 -2
- package/dist/compile/check.d.ts.map +1 -1
- package/dist/compile/check.js +25 -3
- package/dist/compile/context.d.ts.map +1 -1
- package/dist/compile/context.js +2 -0
- package/dist/compile/first.d.ts +26 -0
- package/dist/compile/first.d.ts.map +1 -0
- package/dist/compile/first.js +850 -0
- package/dist/compile/graph-predicate.d.ts.map +1 -1
- package/dist/compile/graph-predicate.js +389 -18
- package/dist/compile/guard.d.ts +2 -1
- package/dist/compile/guard.d.ts.map +1 -1
- package/dist/compile/guard.js +54 -8
- package/dist/compile/predicate.d.ts.map +1 -1
- package/dist/compile/predicate.js +156 -5
- package/dist/compile/runtime.d.ts +20 -1
- package/dist/compile/runtime.d.ts.map +1 -1
- package/dist/compile/runtime.js +31 -0
- package/dist/compile/source.d.ts.map +1 -1
- package/dist/compile/source.js +27 -3
- package/dist/compile/types.d.ts +2 -0
- package/dist/compile/types.d.ts.map +1 -1
- package/dist/decoder/index.d.ts +60 -0
- package/dist/decoder/index.d.ts.map +1 -1
- package/dist/decoder/index.js +164 -1
- package/dist/evaluate/check-composite.d.ts +52 -2
- package/dist/evaluate/check-composite.d.ts.map +1 -1
- package/dist/evaluate/check-composite.js +193 -6
- package/dist/evaluate/check-scalar.d.ts +9 -0
- package/dist/evaluate/check-scalar.d.ts.map +1 -1
- package/dist/evaluate/check-scalar.js +92 -3
- package/dist/evaluate/check.d.ts.map +1 -1
- package/dist/evaluate/check.js +19 -4
- package/dist/evaluate/shared.d.ts +19 -0
- package/dist/evaluate/shared.d.ts.map +1 -1
- package/dist/evaluate/shared.js +35 -0
- package/dist/guard/array.d.ts +48 -0
- package/dist/guard/array.d.ts.map +1 -0
- package/dist/guard/array.js +84 -0
- package/dist/guard/base.d.ts +32 -2
- package/dist/guard/base.d.ts.map +1 -1
- package/dist/guard/base.js +74 -3
- package/dist/guard/date.d.ts +34 -0
- package/dist/guard/date.d.ts.map +1 -0
- package/dist/guard/date.js +60 -0
- package/dist/guard/index.d.ts +2 -0
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +2 -0
- package/dist/guard/number.d.ts +60 -0
- package/dist/guard/number.d.ts.map +1 -1
- package/dist/guard/number.js +129 -0
- package/dist/guard/read.d.ts +53 -1
- package/dist/guard/read.d.ts.map +1 -1
- package/dist/guard/read.js +102 -0
- package/dist/guard/string.d.ts +82 -0
- package/dist/guard/string.d.ts.map +1 -1
- package/dist/guard/string.js +213 -0
- package/dist/guard/types.d.ts +18 -0
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/ir/builder.d.ts +3 -3
- package/dist/ir/builder.d.ts.map +1 -1
- package/dist/ir/builder.js +5 -2
- package/dist/ir/freeze.js +7 -0
- package/dist/ir/types.d.ts +4 -1
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/validate.d.ts.map +1 -1
- package/dist/ir/validate.js +35 -1
- package/dist/issue/index.d.ts +1 -1
- package/dist/issue/index.d.ts.map +1 -1
- package/dist/issue/index.js +4 -0
- package/dist/json-schema/emit-composite.d.ts +6 -2
- package/dist/json-schema/emit-composite.d.ts.map +1 -1
- package/dist/json-schema/emit-composite.js +66 -12
- package/dist/json-schema/emit-scalar.d.ts.map +1 -1
- package/dist/json-schema/emit-scalar.js +54 -1
- package/dist/json-schema/emit.d.ts.map +1 -1
- package/dist/json-schema/emit.js +11 -2
- package/dist/json-schema/types.d.ts +7 -1
- package/dist/json-schema/types.d.ts.map +1 -1
- package/dist/kind/index.d.ts +25 -0
- package/dist/kind/index.d.ts.map +1 -1
- package/dist/kind/index.js +26 -3
- package/dist/lower/index.d.ts.map +1 -1
- package/dist/lower/index.js +52 -3
- package/dist/message/index.d.ts +18 -0
- package/dist/message/index.d.ts.map +1 -1
- package/dist/message/index.js +67 -0
- package/dist/optimize/domain.js +6 -2
- package/dist/optimize/map-node.d.ts.map +1 -1
- package/dist/optimize/map-node.js +3 -0
- package/dist/plan/cache.js +13 -1
- package/dist/plan/predicate.d.ts.map +1 -1
- package/dist/plan/predicate.js +33 -3
- package/dist/plan/schema-predicate.d.ts.map +1 -1
- package/dist/plan/schema-predicate.js +267 -8
- package/dist/schema/freeze.js +22 -0
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +1 -1
- package/dist/schema/types.d.ts +89 -4
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +8 -1
- package/dist/schema/undefined.d.ts.map +1 -1
- package/dist/schema/undefined.js +5 -0
- package/dist/schema/validate.d.ts.map +1 -1
- package/dist/schema/validate.js +111 -4
- package/docs/api.md +79 -10
- package/docs/assets/benchmark-headline.svg +33 -33
- package/docs/engine-notes.md +9 -5
- package/docs/index.html +1366 -722
- package/docs/ko/api.md +383 -0
- package/docs/ko/engine-notes.md +156 -0
- package/docs/ko/readme.md +404 -0
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to TypeSea are recorded here.
|
|
4
4
|
|
|
5
|
+
## 0.3.1 - Unreleased
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Hardened the manual GitHub Release workflow so `workflow_dispatch` tag input
|
|
10
|
+
is passed through environment variables and validated as a release tag before
|
|
11
|
+
it reaches shell output.
|
|
12
|
+
- Added `SECURITY.md` with supported versions, reporting guidance, and the
|
|
13
|
+
security boundary for safe, unsafe, unchecked, AOT, and dynamic compilation.
|
|
14
|
+
- Added a post-publish npm registry verification step to the GitHub Publish
|
|
15
|
+
workflow.
|
|
16
|
+
- Added `release:publish` so the repository-owned publish command always uses
|
|
17
|
+
`npm publish --provenance --access public --ignore-scripts`.
|
|
18
|
+
- Removed the version-pinned Socket badge URL from the README.
|
|
19
|
+
- Refreshed the benchmark snapshot and docs graph from the 2026-07-05 local
|
|
20
|
+
`bench/ecosystem.bench.ts` run.
|
|
21
|
+
- Clarified the release path: local npm publishing is allowed for emergency
|
|
22
|
+
manual releases, but normal releases should go through GitHub Release so npm
|
|
23
|
+
provenance is attached.
|
|
24
|
+
- Expanded decoder documentation around method chaining with `transform`,
|
|
25
|
+
`default`, `prefault`, and `catch`.
|
|
26
|
+
|
|
27
|
+
## 0.3.0 - 2026-07-05
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- Added Date bounds with `t.date.min()` and `t.date.max()`.
|
|
32
|
+
- Added tuple rest support with `t.tuple([head], rest)`.
|
|
33
|
+
- Added `t.map`, `t.set`, `t.instanceOf`, `t.property`, `guard.property`, and
|
|
34
|
+
`t.json`.
|
|
35
|
+
- Added scalar aliases `t.null`, `t.undefined`, `t.void`, and presence helper
|
|
36
|
+
`t.nullish`.
|
|
37
|
+
- Added string decoder helpers `t.string.trim()`, `t.string.toLowerCase()`,
|
|
38
|
+
and `t.string.toUpperCase()`.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Hardened Date validation to use intrinsic Date reads instead of
|
|
43
|
+
user-overridable Date instance methods.
|
|
44
|
+
|
|
5
45
|
## 0.2.0 - 2026-07-04
|
|
6
46
|
|
|
7
47
|
Initial public release of TypeSea: a zero-runtime-dependency TypeScript runtime
|
package/README.md
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
# TypeSea
|
|
2
2
|
|
|
3
3
|
[](https://github.com/Feralthedogg/TypeSea/actions/workflows/ci.yml)
|
|
4
|
+
[](https://socket.dev/npm/package/typesea)
|
|
4
5
|
[](./LICENSE)
|
|
5
6
|

|
|
6
7
|

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
7
11
|

|
|
8
12
|

|
|
9
13
|
|
|
@@ -13,7 +17,7 @@ runtime compilation, and AOT source generation.
|
|
|
13
17
|
|
|
14
18
|
## Benchmark Headline
|
|
15
19
|
|
|
16
|
-
Last local benchmark on 2026-07-
|
|
20
|
+
Last local benchmark on 2026-07-05 KST:
|
|
17
21
|
`npm run bench -- bench/ecosystem.bench.ts --run`, strict-object contract,
|
|
18
22
|
operations per second on one machine.
|
|
19
23
|
|
|
@@ -36,6 +40,12 @@ loads, allocation-light strict-key loops, and V8-friendly monomorphic codegen.
|
|
|
36
40
|
> return frozen `Result` values — `any`, `try`, and `catch` are banned from the
|
|
37
41
|
> entire codebase and enforced by policy gates.
|
|
38
42
|
|
|
43
|
+
> [!WARNING]
|
|
44
|
+
> `unsafe` and `unchecked` are **not public-boundary modes**. They are for
|
|
45
|
+
> trusted, already-normalized data where the caller accepts getter execution,
|
|
46
|
+
> prototype-backed values, and weaker strict-extra-key guarantees. Use the
|
|
47
|
+
> default safe mode for external input.
|
|
48
|
+
|
|
39
49
|
---
|
|
40
50
|
|
|
41
51
|
## Why
|
|
@@ -89,8 +99,10 @@ import { compile, t, toJsonSchema, type Infer } from "typesea";
|
|
|
89
99
|
|
|
90
100
|
const User = t.strictObject({
|
|
91
101
|
id: t.string.uuid(),
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
email: t.string.email(),
|
|
103
|
+
age: t.number.int().nonnegative(),
|
|
104
|
+
role: t.enum(["admin", "user"]),
|
|
105
|
+
tags: t.array(t.string.min(1)).max(8)
|
|
94
106
|
});
|
|
95
107
|
|
|
96
108
|
type User = Infer<typeof User>;
|
|
@@ -114,8 +126,11 @@ const schema = toJsonSchema(User);
|
|
|
114
126
|
```
|
|
115
127
|
|
|
116
128
|
Use `is()` for the allocation-light boolean path. Use `check()` when callers
|
|
117
|
-
need immutable
|
|
118
|
-
|
|
129
|
+
need the full immutable diagnostic list, or `checkFirst()` when a hot rejection
|
|
130
|
+
path only needs one machine-readable issue. Use `compile()` or `emitAotModule()`
|
|
131
|
+
when a stable schema is hot enough to deserve generated validator code.
|
|
132
|
+
Compiled and AOT `checkFirst()` use a dedicated first-fault collector instead
|
|
133
|
+
of building the full issue list and slicing it afterward.
|
|
119
134
|
|
|
120
135
|
> [!CAUTION]
|
|
121
136
|
> `compile()` builds the validator with `new Function`, which throws under a
|
|
@@ -213,50 +228,50 @@ failed check() -> schema-aware diagnostic collector
|
|
|
213
228
|
|
|
214
229
|
## Performance Snapshot
|
|
215
230
|
|
|
216
|
-
Last local benchmark on 2026-07-
|
|
231
|
+
Last local benchmark on 2026-07-05 KST, using
|
|
217
232
|
`npm run bench -- bench/ecosystem.bench.ts --run` on the benchmark strict-object
|
|
218
233
|
contract. These are operations per second on one machine, not release
|
|
219
234
|
guarantees.
|
|
220
235
|
|
|
221
236
|
| Valid object path | hz |
|
|
222
237
|
| --- | ---: |
|
|
223
|
-
| TypeSea interpreted `is()` |
|
|
224
|
-
| TypeSea compiled safe `is()` |
|
|
225
|
-
| TypeSea compiled unsafe `is()` | 36,
|
|
226
|
-
| TypeSea compiled unchecked `is()` | 42,
|
|
227
|
-
| Zod `safeParse` | 1,
|
|
228
|
-
| Valibot `safeParse` | 1,
|
|
229
|
-
| Ajv compiled | 4,
|
|
238
|
+
| TypeSea interpreted `is()` | 478,576 |
|
|
239
|
+
| TypeSea compiled safe `is()` | 5,109,602 |
|
|
240
|
+
| TypeSea compiled unsafe `is()` | 36,777,097 |
|
|
241
|
+
| TypeSea compiled unchecked `is()` | 42,620,570 |
|
|
242
|
+
| Zod `safeParse` | 1,400,045 |
|
|
243
|
+
| Valibot `safeParse` | 1,400,599 |
|
|
244
|
+
| Ajv compiled | 4,238,036 |
|
|
230
245
|
|
|
231
246
|
| Valid diagnostic path | hz |
|
|
232
247
|
| --- | ---: |
|
|
233
|
-
| TypeSea interpreted `check()` |
|
|
234
|
-
| TypeSea compiled safe `check()` |
|
|
235
|
-
| TypeSea compiled unsafe `check()` |
|
|
236
|
-
| TypeSea compiled unchecked `check()` |
|
|
237
|
-
| Zod `safeParse` | 1,
|
|
238
|
-
| Valibot `safeParse` | 1,
|
|
239
|
-
| Ajv compiled | 4,
|
|
248
|
+
| TypeSea interpreted `check()` | 424,989 |
|
|
249
|
+
| TypeSea compiled safe `check()` | 4,642,948 |
|
|
250
|
+
| TypeSea compiled unsafe `check()` | 37,184,199 |
|
|
251
|
+
| TypeSea compiled unchecked `check()` | 42,487,325 |
|
|
252
|
+
| Zod `safeParse` | 1,278,859 |
|
|
253
|
+
| Valibot `safeParse` | 1,391,040 |
|
|
254
|
+
| Ajv compiled | 4,338,063 |
|
|
240
255
|
|
|
241
256
|
| Invalid object path | hz |
|
|
242
257
|
| --- | ---: |
|
|
243
|
-
| TypeSea interpreted `is()` | 3,
|
|
244
|
-
| TypeSea compiled safe `is()` |
|
|
245
|
-
| TypeSea compiled unsafe `is()` |
|
|
246
|
-
| TypeSea compiled unchecked `is()` | 50,
|
|
247
|
-
| Zod `safeParse` | 84,
|
|
248
|
-
| Valibot `safeParse` |
|
|
249
|
-
| Ajv compiled |
|
|
258
|
+
| TypeSea interpreted `is()` | 3,325,603 |
|
|
259
|
+
| TypeSea compiled safe `is()` | 43,094,061 |
|
|
260
|
+
| TypeSea compiled unsafe `is()` | 50,738,235 |
|
|
261
|
+
| TypeSea compiled unchecked `is()` | 50,898,012 |
|
|
262
|
+
| Zod `safeParse` | 84,647 |
|
|
263
|
+
| Valibot `safeParse` | 866,013 |
|
|
264
|
+
| Ajv compiled | 30,535,761 |
|
|
250
265
|
|
|
251
266
|
| Invalid diagnostic path | hz |
|
|
252
267
|
| --- | ---: |
|
|
253
|
-
| TypeSea interpreted `check()` |
|
|
254
|
-
| TypeSea compiled safe `check()` | 2,
|
|
255
|
-
| TypeSea compiled unsafe `check()` | 3,
|
|
256
|
-
| TypeSea compiled unchecked `check()` | 3,673
|
|
257
|
-
| Zod `safeParse` |
|
|
258
|
-
| Valibot `safeParse` |
|
|
259
|
-
| Ajv compiled |
|
|
268
|
+
| TypeSea interpreted `check()` | 405,590 |
|
|
269
|
+
| TypeSea compiled safe `check()` | 2,107,460 |
|
|
270
|
+
| TypeSea compiled unsafe `check()` | 3,186,702 |
|
|
271
|
+
| TypeSea compiled unchecked `check()` | 3,509,673 |
|
|
272
|
+
| Zod `safeParse` | 85,355 |
|
|
273
|
+
| Valibot `safeParse` | 788,870 |
|
|
274
|
+
| Ajv compiled | 29,951,403 |
|
|
260
275
|
|
|
261
276
|
The safe compiled path stays close to Ajv while retaining TypeSea hostile-input
|
|
262
277
|
semantics: descriptor-based property reads, symbol/non-enumerable strict-key
|
|
@@ -275,37 +290,57 @@ grouped under the `t` table.
|
|
|
275
290
|
|
|
276
291
|
| Area | Entry points |
|
|
277
292
|
| --- | --- |
|
|
278
|
-
| Scalar guards | `t.unknown`, `t.never`, `t.string`, `t.number`, `t.bigint`, `t.symbol`, `t.boolean` |
|
|
279
|
-
|
|
|
280
|
-
|
|
|
293
|
+
| Scalar guards | `t.unknown`, `t.never`, `t.string`, `t.number`, `t.date`, `t.bigint`, `t.symbol`, `t.boolean`, `t.null`, `t.undefined`, `t.void` |
|
|
294
|
+
| String checks | `.min`, `.max`, `.length`, `.nonempty`, `.regex`, `.startsWith`, `.endsWith`, `.includes`, `.uuid`, `.email`, `.url`, `.isoDate`, `.isoDateTime`, `.ulid`, `.ipv4`, `.ipv6` |
|
|
295
|
+
| Number checks | `.int`, `.finite`, `.safe`, `.gte`, `.lte`, `.min`, `.max`, `.gt`, `.lt`, `.multipleOf`, `.positive`, `.nonnegative`, `.negative`, `.nonpositive` |
|
|
296
|
+
| Date checks | `.min`, `.max` |
|
|
297
|
+
| Literal and containers | `t.literal`, `t.enum`, `t.array`, `t.tuple`, tuple rest, `t.record`, `t.map`, `t.set`, `t.json` |
|
|
298
|
+
| Array checks | `.min`, `.max`, `.length`, `.nonempty` |
|
|
299
|
+
| Objects | `t.object`, `t.strictObject`, `extend`, `safeExtend`, `merge`, `pick`, `omit`, `partial`, `deepPartial`, `required`, `strict`, `passthrough`, `strip`, `catchall` |
|
|
300
|
+
| Runtime object contracts | `t.instanceOf`, `t.property`, `guard.property` |
|
|
281
301
|
| Composition | `t.union`, `t.discriminatedUnion`, `t.intersect`, `guard.intersect` |
|
|
282
|
-
| Presence wrappers | `t.optional`, `t.undefinedable`, `t.nullable` |
|
|
302
|
+
| Presence wrappers | `t.optional`, `t.undefinedable`, `t.nullable`, `t.nullish` |
|
|
283
303
|
| Dynamic contracts | `t.lazy`, `t.refine` |
|
|
284
304
|
|
|
285
305
|
### Decoders
|
|
286
306
|
|
|
287
307
|
| Area | Entry points |
|
|
288
308
|
| --- | --- |
|
|
289
|
-
| Sync decoders | `t.decoder`, `t.transform`, `t.pipe`, `t.coerce` |
|
|
309
|
+
| Sync decoders | `t.decoder`, `t.transform`, `t.pipe`, `t.default`, `t.defaultValue`, `t.prefault`, `t.catch`, `t.codec`, `t.coerce`, `t.string.trim()`, `t.string.toLowerCase()`, `t.string.toUpperCase()` |
|
|
290
310
|
| Async decoders | `t.asyncDecoder`, `t.asyncRefine`, `t.asyncTransform`, `t.asyncPipe` |
|
|
291
311
|
|
|
292
312
|
### Execution & Export
|
|
293
313
|
|
|
294
314
|
| Area | Entry points |
|
|
295
315
|
| --- | --- |
|
|
296
|
-
| Guard methods | `guard.is()`, `guard.check()`, `guard.graph()` |
|
|
316
|
+
| Guard methods | `guard.is()`, `guard.check()`, `guard.checkFirst()`, `guard.graph()` |
|
|
297
317
|
| Generated validators | `compile`, `emitAotModule` |
|
|
298
318
|
| JSON Schema | `toJsonSchema` |
|
|
319
|
+
| Messages | `formatIssue`, `formatIssues`, `flattenIssues`, `withMessages` |
|
|
299
320
|
|
|
300
321
|
### Messages & Adapters
|
|
301
322
|
|
|
302
323
|
| Area | Entry points |
|
|
303
324
|
| --- | --- |
|
|
304
|
-
| Messages / i18n | `formatIssue`, `formatIssues`, `withMessages`, `defineMessages` |
|
|
325
|
+
| Messages / i18n | `formatIssue`, `formatIssues`, `flattenIssues`, `withMessages`, `defineMessages` |
|
|
305
326
|
| tRPC | `toTrpcParser`, `toAsyncTrpcParser` |
|
|
306
327
|
| Fastify | `toFastifyRouteSchema`, `toFastifyValidatorCompiler` |
|
|
307
328
|
| React Hook Form | `toReactHookFormResolver` |
|
|
308
329
|
|
|
330
|
+
Adapters accept compiled guards too. Compile once at startup, then pass the
|
|
331
|
+
compiled guard into parser or validator-compiler adapters so framework hot paths
|
|
332
|
+
reuse the generated predicate.
|
|
333
|
+
|
|
334
|
+
```ts
|
|
335
|
+
const FastUser = compile(User);
|
|
336
|
+
const trpcParser = toTrpcParser(FastUser);
|
|
337
|
+
const fastifyCompiler = toFastifyValidatorCompiler(FastUser);
|
|
338
|
+
|
|
339
|
+
// Trusted normalized data only: trades hostile-input hardening for direct reads.
|
|
340
|
+
const UnsafeUser = compile(User, { mode: "unsafe" });
|
|
341
|
+
const internalParser = toTrpcParser(UnsafeUser);
|
|
342
|
+
```
|
|
343
|
+
|
|
309
344
|
> [!TIP]
|
|
310
345
|
> Match the inference alias to the source kind: `Infer<>` for guards,
|
|
311
346
|
> `InferDecoder<>` for decoders, `InferAsyncDecoder<>` for async decoders.
|
|
@@ -326,6 +361,11 @@ Deliberate, documented, and pinned by tests:
|
|
|
326
361
|
| `__proto__`, `constructor` keys | validated as plain own keys, no pollution |
|
|
327
362
|
| Sparse array holes | read as `undefined` without executing accessors |
|
|
328
363
|
| Strict object extras | rejected via `Reflect.ownKeys` — including symbol keys and non-enumerable properties |
|
|
364
|
+
| `catchall` extras | unknown own keys are descriptor-read and validated by the catchall schema |
|
|
365
|
+
| `strip()` | validation-only alias for accepting extras; TypeSea does not clone stripped output |
|
|
366
|
+
| `t.date` | accepts valid JavaScript `Date` objects; `.min` and `.max` compare epoch milliseconds without reading user-overridable Date methods |
|
|
367
|
+
| `t.map`, `t.set`, `t.instanceOf` | runtime-only contracts; JSON Schema and AOT export reject them instead of weakening semantics |
|
|
368
|
+
| `property` | validates own data properties only; getter-backed properties are rejected |
|
|
329
369
|
| Global-flag regexes | cloned at construction; `lastIndex` reset before every test |
|
|
330
370
|
| UUID | accepts RFC 9562 versions 1–8 plus the nil UUID |
|
|
331
371
|
| Cyclic input values | validate finitely via (value × schema) active-pair tracking |
|
|
@@ -373,6 +413,7 @@ npm run check:consumer # tarball install + runtime/type smoke in a temp project
|
|
|
373
413
|
npm run bench -- --run # benchmark smoke
|
|
374
414
|
npm run pack:dry # package contents dry run
|
|
375
415
|
npm run release:check # the full pre-publish gate (everything above)
|
|
416
|
+
npm run release:publish # npm publish with provenance and ignored lifecycle scripts
|
|
376
417
|
```
|
|
377
418
|
|
|
378
419
|
`npm run release:check` runs the same gate expected before publishing:
|
|
@@ -380,6 +421,16 @@ typecheck, lint, tests, build, docs smoke, dist policy, public API snapshot,
|
|
|
380
421
|
package contents, consumer install, benchmark smoke, and pack dry run.
|
|
381
422
|
CI executes it on Node 20.19, 22, and 24; releases publish with npm provenance.
|
|
382
423
|
|
|
424
|
+
Release path:
|
|
425
|
+
|
|
426
|
+
1. Push a `vX.Y.Z` tag or run the GitHub `Release` workflow with that tag.
|
|
427
|
+
2. The release workflow verifies that the tag matches `package.json`.
|
|
428
|
+
3. Publishing happens from the GitHub `Publish` workflow through `npm run release:publish`, which expands to `npm publish --provenance --access public --ignore-scripts`.
|
|
429
|
+
|
|
430
|
+
Local publishing with `NPM_TOKEN` is reserved for manual recovery releases. It
|
|
431
|
+
must still run `npm run release:check` first, and it cannot attach GitHub OIDC
|
|
432
|
+
provenance.
|
|
433
|
+
|
|
383
434
|
> [!NOTE]
|
|
384
435
|
> Benchmark comparison packages (Zod, Valibot, Ajv) are dev dependencies only —
|
|
385
436
|
> package policy rejects them from every runtime dependency field. The
|
|
@@ -393,6 +444,18 @@ CI executes it on Node 20.19, 22, and 24; releases publish with npm provenance.
|
|
|
393
444
|
- [Documentation site](https://feralthedogg.github.io/TypeSea/)
|
|
394
445
|
- [API reference](docs/api.md)
|
|
395
446
|
- [Engine notes](docs/engine-notes.md)
|
|
447
|
+
- [Security policy](https://github.com/Feralthedogg/TypeSea/blob/main/SECURITY.md)
|
|
448
|
+
|
|
449
|
+
---
|
|
450
|
+
|
|
451
|
+
## Migration Notes
|
|
452
|
+
|
|
453
|
+
### 0.3.0 to 0.3.1
|
|
454
|
+
|
|
455
|
+
No application code changes are required. `0.3.1` is a release-hardening patch:
|
|
456
|
+
it tightens manual release tag handling, documents npm provenance expectations,
|
|
457
|
+
adds a security policy, and verifies that npm exposes the published version after
|
|
458
|
+
the GitHub publish workflow completes.
|
|
396
459
|
|
|
397
460
|
---
|
|
398
461
|
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
TypeSea supports the latest published minor line. Security fixes are released as
|
|
6
|
+
patch versions whenever a fix can be shipped without changing the public API.
|
|
7
|
+
|
|
8
|
+
| Version | Supported |
|
|
9
|
+
| --- | --- |
|
|
10
|
+
| 0.3.x | yes |
|
|
11
|
+
| 0.2.x | no |
|
|
12
|
+
|
|
13
|
+
## Reporting A Vulnerability
|
|
14
|
+
|
|
15
|
+
Please report security issues through GitHub Security Advisories for
|
|
16
|
+
`Feralthedogg/TypeSea`. If that is unavailable, open a GitHub issue with the
|
|
17
|
+
minimum public detail needed to start coordination and mark the title as a
|
|
18
|
+
security report.
|
|
19
|
+
|
|
20
|
+
Useful reports include:
|
|
21
|
+
|
|
22
|
+
- affected TypeSea version
|
|
23
|
+
- minimal schema and input needed to reproduce the issue
|
|
24
|
+
- whether the issue affects `safe`, `unsafe`, `unchecked`, AOT, JSON Schema, or
|
|
25
|
+
an adapter
|
|
26
|
+
- expected verdict and actual verdict
|
|
27
|
+
- generated source or stack output that helps reproduce the issue
|
|
28
|
+
|
|
29
|
+
## Security Boundary
|
|
30
|
+
|
|
31
|
+
The default validation mode is `safe`. It is the mode intended for hostile
|
|
32
|
+
boundary data. Safe mode avoids user getter execution, treats prototype-backed
|
|
33
|
+
data as untrusted, handles `__proto__` and `constructor` keys with
|
|
34
|
+
null-prototype lookups, checks strict-object symbol and non-enumerable extras,
|
|
35
|
+
and returns explicit `Result` values for expected failures.
|
|
36
|
+
|
|
37
|
+
`unsafe` and `unchecked` are performance escape hatches for trusted,
|
|
38
|
+
already-normalized data. They may execute getters, may accept prototype-backed
|
|
39
|
+
values, and may relax strict-object extra-key guarantees. Do not use these modes
|
|
40
|
+
on public input boundaries unless a separate normalization step has already
|
|
41
|
+
converted the input into plain owned data.
|
|
42
|
+
|
|
43
|
+
`compile()` uses `new Function` by design. If a deployment forbids dynamic code
|
|
44
|
+
generation through Content Security Policy, use normal guards or
|
|
45
|
+
`emitAotModule()` instead.
|
|
46
|
+
|
|
47
|
+
## Release Integrity
|
|
48
|
+
|
|
49
|
+
The package is expected to have zero runtime, peer, optional, and bundled
|
|
50
|
+
dependencies. Release checks verify package contents, public API drift, docs,
|
|
51
|
+
tests, consumer install smoke, benchmarks, and dist policy before publishing.
|
|
52
|
+
Normal releases should go through GitHub Releases so npm provenance is attached.
|
package/dist/aot/index.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { type Result } from "../result/index.js";
|
|
|
7
7
|
* @details AOT helpers serialize only portable data because standalone modules cannot close
|
|
8
8
|
* over runtime side tables.
|
|
9
9
|
*/
|
|
10
|
-
export type AotIssueCode = "unsupported_aot_lazy" | "unsupported_aot_refine" | "unsupported_aot_symbol_literal";
|
|
10
|
+
export type AotIssueCode = "unsupported_aot_lazy" | "unsupported_aot_refine" | "unsupported_aot_date" | "unsupported_aot_runtime_object" | "unsupported_aot_symbol_literal";
|
|
11
11
|
/**
|
|
12
12
|
* @brief aot issue.
|
|
13
13
|
* @details AOT helpers serialize only portable data because standalone modules cannot close
|
package/dist/aot/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aot/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ1D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAClB,sBAAsB,GACtB,wBAAwB,GACxB,gCAAgC,CAAC;AAEvC;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;CAC1C;AAYD;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACrC,MAAM,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC,CAsBxC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/aot/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAQ1D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAClB,sBAAsB,GACtB,wBAAwB,GACxB,sBAAsB,GACtB,gCAAgC,GAChC,gCAAgC,CAAC;AAEvC;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACrB,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,WAAW,GAAG,SAAS,CAAC;CAC1C;AAYD;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACtC;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CACzB,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC/B,OAAO,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,GACrC,MAAM,CAAC,SAAS,EAAE,SAAS,QAAQ,EAAE,CAAC,CAsBxC"}
|
package/dist/aot/index.js
CHANGED
|
@@ -124,17 +124,32 @@ function scanAotSchema(schema, path, issues, seen) {
|
|
|
124
124
|
pushIssue(path, issues, "unsupported_aot_symbol_literal", "AOT modules cannot preserve symbol literal identity");
|
|
125
125
|
}
|
|
126
126
|
return;
|
|
127
|
+
case SchemaTag.Date:
|
|
128
|
+
pushIssue(path, issues, "unsupported_aot_date", "AOT modules cannot preserve JavaScript Date object validation yet");
|
|
129
|
+
return;
|
|
127
130
|
case SchemaTag.Array:
|
|
128
131
|
scanAotSchema(schema.item, path.concat("items"), issues, seen);
|
|
129
132
|
return;
|
|
130
133
|
case SchemaTag.Tuple:
|
|
131
134
|
scanSchemaArray(schema.items, path, issues, seen);
|
|
135
|
+
if (schema.rest !== undefined) {
|
|
136
|
+
scanAotSchema(schema.rest, path.concat("rest"), issues, seen);
|
|
137
|
+
}
|
|
132
138
|
return;
|
|
133
139
|
case SchemaTag.Record:
|
|
134
140
|
scanAotSchema(schema.value, path.concat("additionalProperties"), issues, seen);
|
|
135
141
|
return;
|
|
142
|
+
case SchemaTag.Map:
|
|
143
|
+
case SchemaTag.Set:
|
|
144
|
+
case SchemaTag.InstanceOf:
|
|
145
|
+
case SchemaTag.Property:
|
|
146
|
+
pushIssue(path, issues, "unsupported_aot_runtime_object", "AOT modules cannot preserve JavaScript runtime object contracts yet");
|
|
147
|
+
return;
|
|
136
148
|
case SchemaTag.Object:
|
|
137
149
|
scanObjectEntries(schema.entries, path, issues, seen);
|
|
150
|
+
if (schema.catchall !== undefined) {
|
|
151
|
+
scanAotSchema(schema.catchall, path.concat("additionalProperties"), issues, seen);
|
|
152
|
+
}
|
|
138
153
|
return;
|
|
139
154
|
case SchemaTag.Union:
|
|
140
155
|
scanSchemaArray(schema.options, path, issues, seen);
|
|
@@ -216,14 +231,16 @@ function emitModuleSource(bundle) {
|
|
|
216
231
|
JSON.stringify(bundle.strings),
|
|
217
232
|
";const d=function(){return false;};",
|
|
218
233
|
"const m=function(){return;};",
|
|
234
|
+
"const mf=function(){return;};",
|
|
219
235
|
"const sk=function(v,ks){if(typeof v!==\"object\"||v===null||Array.isArray(v))return false;const ps=Reflect.ownKeys(v);for(let i=0;i<ps.length;i+=1){const key=ps[i];if(typeof key!==\"string\"||!ks.includes(key))return false;}return true;};",
|
|
220
|
-
"const __typesea=(function(l,r,k,u,d,m,sk){",
|
|
236
|
+
"const __typesea=(function(l,r,k,u,d,m,mf,sk){",
|
|
221
237
|
bundle.source,
|
|
222
|
-
"})(l,r,k,u,d,m,sk);",
|
|
238
|
+
"})(l,r,k,u,d,m,mf,sk);",
|
|
223
239
|
"export function is(value){return __typesea.is(value);}",
|
|
224
240
|
"export function check(value){return __typesea.result(value);}",
|
|
241
|
+
"export function checkFirst(value){return __typesea.first(value);}",
|
|
225
242
|
"export function assert(value){const result=check(value);if(!result.ok){const error=new Error(\"TypeSea assertion failed\");Object.defineProperty(error,\"issues\",{configurable:false,enumerable:true,value:result.error,writable:false});throw error;}}",
|
|
226
|
-
"export default Object.freeze({is,check,assert});",
|
|
243
|
+
"export default Object.freeze({is,check,checkFirst,assert});",
|
|
227
244
|
""
|
|
228
245
|
].join("");
|
|
229
246
|
}
|
|
@@ -246,10 +263,12 @@ function emitDeclarationSource() {
|
|
|
246
263
|
" | { readonly ok: false; readonly error: readonly AotIssue[] };",
|
|
247
264
|
"export declare function is(value: unknown): boolean;",
|
|
248
265
|
"export declare function check<TValue = unknown>(value: TValue): AotCheckResult<TValue>;",
|
|
266
|
+
"export declare function checkFirst<TValue = unknown>(value: TValue): AotCheckResult<TValue>;",
|
|
249
267
|
"export declare function assert(value: unknown): void;",
|
|
250
268
|
"declare const guard: {",
|
|
251
269
|
" readonly is: typeof is;",
|
|
252
270
|
" readonly check: typeof check;",
|
|
271
|
+
" readonly checkFirst: typeof checkFirst;",
|
|
253
272
|
" readonly assert: typeof assert;",
|
|
254
273
|
"};",
|
|
255
274
|
"export default guard;",
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
|
5
5
|
* with stable metadata.
|
|
6
6
|
*/
|
|
7
|
-
import { BaseGuard, type Guard, type Infer, type Presence } from "../guard/index.js";
|
|
8
|
-
import type { DiscriminatedUnionCases, InferTuple, TupleShape, UnionInput } from "./types.js";
|
|
7
|
+
import { ArrayGuard, BaseGuard, type Guard, type Infer, type Presence } from "../guard/index.js";
|
|
8
|
+
import type { DiscriminatedUnionCases, InferTuple, InferTupleWithRest, TupleShape, UnionInput } from "./types.js";
|
|
9
9
|
/**
|
|
10
10
|
* @brief Build an array guard.
|
|
11
11
|
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
|
@@ -13,7 +13,7 @@ import type { DiscriminatedUnionCases, InferTuple, TupleShape, UnionInput } from
|
|
|
13
13
|
* @param item Guard used for each logical array slot.
|
|
14
14
|
* @returns Fresh array guard.
|
|
15
15
|
*/
|
|
16
|
-
export declare function array<TGuard extends Guard<unknown, Presence>>(item: TGuard):
|
|
16
|
+
export declare function array<TGuard extends Guard<unknown, Presence>>(item: TGuard): ArrayGuard<Infer<TGuard>>;
|
|
17
17
|
/**
|
|
18
18
|
* @brief Build a fixed-length tuple guard.
|
|
19
19
|
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
|
@@ -23,6 +23,7 @@ export declare function array<TGuard extends Guard<unknown, Presence>>(item: TGu
|
|
|
23
23
|
* @throws TypeError when shape is not an array-like tuple input.
|
|
24
24
|
*/
|
|
25
25
|
export declare function tuple<const TShape extends TupleShape>(shape: TShape): BaseGuard<InferTuple<TShape>>;
|
|
26
|
+
export declare function tuple<const TShape extends TupleShape, TRest extends Guard<unknown, Presence>>(shape: TShape, rest: TRest): BaseGuard<InferTupleWithRest<TShape, TRest>>;
|
|
26
27
|
/**
|
|
27
28
|
* @brief Build a string-keyed record guard.
|
|
28
29
|
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
|
@@ -31,6 +32,8 @@ export declare function tuple<const TShape extends TupleShape>(shape: TShape): B
|
|
|
31
32
|
* @returns Fresh record guard.
|
|
32
33
|
*/
|
|
33
34
|
export declare function record<TGuard extends Guard<unknown, Presence>>(value: TGuard): BaseGuard<Readonly<Record<string, Infer<TGuard>>>>;
|
|
35
|
+
export declare function map<TKey extends Guard<unknown, Presence>, TValue extends Guard<unknown, Presence>>(key: TKey, value: TValue): BaseGuard<ReadonlyMap<Infer<TKey>, Infer<TValue>>>;
|
|
36
|
+
export declare function set<TItem extends Guard<unknown, Presence>>(item: TItem): BaseGuard<ReadonlySet<Infer<TItem>>>;
|
|
34
37
|
/**
|
|
35
38
|
* @brief Build a union guard from one or more guards.
|
|
36
39
|
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composite.d.ts","sourceRoot":"","sources":["../../src/builders/composite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EACH,SAAS,EACT,KAAK,KAAK,EACV,KAAK,KAAK,EACV,KAAK,QAAQ,EAChB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,KAAK,EACR,uBAAuB,EACvB,UAAU,EACV,UAAU,EACV,UAAU,EACb,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACzD,IAAI,EAAE,MAAM,GACb,
|
|
1
|
+
{"version":3,"file":"composite.d.ts","sourceRoot":"","sources":["../../src/builders/composite.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EACH,UAAU,EACV,SAAS,EACT,KAAK,KAAK,EACV,KAAK,KAAK,EACV,KAAK,QAAQ,EAChB,MAAM,mBAAmB,CAAC;AAM3B,OAAO,KAAK,EACR,uBAAuB,EACvB,UAAU,EACV,kBAAkB,EAClB,UAAU,EACV,UAAU,EACb,MAAM,YAAY,CAAC;AAEpB;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACzD,IAAI,EAAE,MAAM,GACb,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAM3B;AAED;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,CAAC,MAAM,SAAS,UAAU,EACjD,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAEjC,wBAAgB,KAAK,CACjB,KAAK,CAAC,MAAM,SAAS,UAAU,EAC/B,KAAK,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAEtC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,KAAK,GACZ,SAAS,CAAC,kBAAkB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AA4BhD;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC1D,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAKpD;AAED,wBAAgB,GAAG,CACf,IAAI,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACrC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAEvC,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAMpD;AAED,wBAAgB,GAAG,CAAC,KAAK,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACtD,IAAI,EAAE,KAAK,GACZ,SAAS,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAKtC;AAED;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,CAAC,OAAO,SAAS,UAAU,EAClD,GAAG,MAAM,EAAE,OAAO,GACnB,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAiBnC;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACrB,KAAK,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACtC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAEvC,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAMzC;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,CAAC,IAAI,SAAS,MAAM,EACzB,KAAK,CAAC,MAAM,SAAS,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,EAEvE,GAAG,EAAE,IAAI,EACT,KAAK,EAAE,MAAM,GAAG,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,GACtD,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,CAiCxC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* with stable metadata.
|
|
6
6
|
*/
|
|
7
7
|
import { PresenceTag, SchemaTag } from "../kind/index.js";
|
|
8
|
-
import { BaseGuard } from "../guard/index.js";
|
|
8
|
+
import { ArrayGuard, BaseGuard } from "../guard/index.js";
|
|
9
9
|
import { isRecord, readGuardSchema } from "../internal/index.js";
|
|
10
10
|
/**
|
|
11
11
|
* @brief Build an array guard.
|
|
@@ -15,20 +15,13 @@ import { isRecord, readGuardSchema } from "../internal/index.js";
|
|
|
15
15
|
* @returns Fresh array guard.
|
|
16
16
|
*/
|
|
17
17
|
export function array(item) {
|
|
18
|
-
return new
|
|
18
|
+
return new ArrayGuard({
|
|
19
19
|
tag: SchemaTag.Array,
|
|
20
|
-
item: readGuardSchema(item, "array item")
|
|
20
|
+
item: readGuardSchema(item, "array item"),
|
|
21
|
+
checks: []
|
|
21
22
|
});
|
|
22
23
|
}
|
|
23
|
-
|
|
24
|
-
* @brief Build a fixed-length tuple guard.
|
|
25
|
-
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
|
26
|
-
* with stable metadata.
|
|
27
|
-
* @param shape Ordered guard list for tuple indexes.
|
|
28
|
-
* @returns Fresh tuple guard preserving item order.
|
|
29
|
-
* @throws TypeError when shape is not an array-like tuple input.
|
|
30
|
-
*/
|
|
31
|
-
export function tuple(shape) {
|
|
24
|
+
export function tuple(shape, rest) {
|
|
32
25
|
const rawShape = shape;
|
|
33
26
|
if (!Array.isArray(rawShape)) {
|
|
34
27
|
throw new TypeError("tuple shape must be an array");
|
|
@@ -44,7 +37,10 @@ export function tuple(shape) {
|
|
|
44
37
|
}
|
|
45
38
|
return new BaseGuard({
|
|
46
39
|
tag: SchemaTag.Tuple,
|
|
47
|
-
items
|
|
40
|
+
items,
|
|
41
|
+
rest: rest === undefined
|
|
42
|
+
? undefined
|
|
43
|
+
: readGuardSchema(rest, "tuple rest")
|
|
48
44
|
});
|
|
49
45
|
}
|
|
50
46
|
/**
|
|
@@ -60,6 +56,19 @@ export function record(value) {
|
|
|
60
56
|
value: readGuardSchema(value, "record value")
|
|
61
57
|
});
|
|
62
58
|
}
|
|
59
|
+
export function map(key, value) {
|
|
60
|
+
return new BaseGuard({
|
|
61
|
+
tag: SchemaTag.Map,
|
|
62
|
+
key: readGuardSchema(key, "map key"),
|
|
63
|
+
value: readGuardSchema(value, "map value")
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export function set(item) {
|
|
67
|
+
return new BaseGuard({
|
|
68
|
+
tag: SchemaTag.Set,
|
|
69
|
+
item: readGuardSchema(item, "set item")
|
|
70
|
+
});
|
|
71
|
+
}
|
|
63
72
|
/**
|
|
64
73
|
* @brief Build a union guard from one or more guards.
|
|
65
74
|
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
package/dist/builders/index.d.ts
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* @details This barrel keeps public import paths stable while implementation files remain
|
|
5
5
|
* split by responsibility.
|
|
6
6
|
*/
|
|
7
|
-
export { array, discriminatedUnion, intersect, record, tuple, union } from "./composite.js";
|
|
8
|
-
export { lazy, nullable, optional, refine, undefinedable } from "./modifier.js";
|
|
9
|
-
export { ObjectGuard, extend, object, omit, partial, pick, strictObject, type InferObject, type MergeObjectShapes, type ObjectGuardMode, type ObjectShape, type OmitObjectShape, type PartialObjectShape, type PickObjectShape } from "./object/index.js";
|
|
10
|
-
export { bigintGuard, literal, neverGuard, symbolGuard, unknownGuard } from "./scalar.js";
|
|
7
|
+
export { array, discriminatedUnion, intersect, map, record, set, tuple, union } from "./composite.js";
|
|
8
|
+
export { lazy, nullable, nullish, optional, refine, undefinedable } from "./modifier.js";
|
|
9
|
+
export { ObjectGuard, catchall, deepPartial, extend, merge, object, omit, partial, passthrough, pick, required, safeExtend, strict, strictObject, strip, type DeepPartialObjectShape, type DeepPartialValue, type InferObject, type MaskSelectedKeys, type MergeObjectShapes, type ObjectKeyMask, type ObjectGuardMode, type ObjectShape, type OmitObjectShape, type OmitObjectShapeByMask, type PartialObjectShape, type PickObjectShape, type PickObjectShapeByMask, type RequiredObjectShape } from "./object/index.js";
|
|
10
|
+
export { bigintGuard, booleanGuard, dateGuard, enumValues, enumValues as enum, literal, neverGuard, nullGuard, numberGuard, symbolGuard, stringGuard, unknownGuard, undefinedGuard, voidGuard, type EnumValues } from "./scalar.js";
|
|
11
|
+
export { instanceOf, json, property, type InstanceConstructor, type JsonValue } from "./runtime.js";
|
|
11
12
|
export { t } from "./table.js";
|
|
12
|
-
export type { InferTuple, TupleShape } from "./types.js";
|
|
13
|
+
export type { InferTuple, InferTupleWithRest, TupleShape } from "./types.js";
|
|
13
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builders/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACH,KAAK,EACL,kBAAkB,EAClB,SAAS,EACT,MAAM,EACN,KAAK,EACL,KAAK,EACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACH,IAAI,EACJ,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,aAAa,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,WAAW,EACX,MAAM,EACN,MAAM,EACN,IAAI,EACJ,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builders/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACH,KAAK,EACL,kBAAkB,EAClB,SAAS,EACT,GAAG,EACH,MAAM,EACN,GAAG,EACH,KAAK,EACL,KAAK,EACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACH,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,MAAM,EACN,aAAa,EAChB,MAAM,eAAe,CAAC;AACvB,OAAO,EACH,WAAW,EACX,QAAQ,EACR,WAAW,EACX,MAAM,EACN,KAAK,EACL,MAAM,EACN,IAAI,EACJ,OAAO,EACP,WAAW,EACX,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,MAAM,EACN,YAAY,EACZ,KAAK,EACL,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,WAAW,EACX,YAAY,EACZ,SAAS,EACT,UAAU,EACV,UAAU,IAAI,IAAI,EAClB,OAAO,EACP,UAAU,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,WAAW,EACX,YAAY,EACZ,cAAc,EACd,SAAS,EACT,KAAK,UAAU,EAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACH,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,CAAC,EAAE,MAAM,YAAY,CAAC;AAC/B,YAAY,EACR,UAAU,EACV,kBAAkB,EAClB,UAAU,EACb,MAAM,YAAY,CAAC"}
|
package/dist/builders/index.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* @details This barrel keeps public import paths stable while implementation files remain
|
|
5
5
|
* split by responsibility.
|
|
6
6
|
*/
|
|
7
|
-
export { array, discriminatedUnion, intersect, record, tuple, union } from "./composite.js";
|
|
8
|
-
export { lazy, nullable, optional, refine, undefinedable } from "./modifier.js";
|
|
9
|
-
export { ObjectGuard, extend, object, omit, partial, pick, strictObject } from "./object/index.js";
|
|
10
|
-
export { bigintGuard, literal, neverGuard, symbolGuard, unknownGuard } from "./scalar.js";
|
|
7
|
+
export { array, discriminatedUnion, intersect, map, record, set, tuple, union } from "./composite.js";
|
|
8
|
+
export { lazy, nullable, nullish, optional, refine, undefinedable } from "./modifier.js";
|
|
9
|
+
export { ObjectGuard, catchall, deepPartial, extend, merge, object, omit, partial, passthrough, pick, required, safeExtend, strict, strictObject, strip } from "./object/index.js";
|
|
10
|
+
export { bigintGuard, booleanGuard, dateGuard, enumValues, enumValues as enum, literal, neverGuard, nullGuard, numberGuard, symbolGuard, stringGuard, unknownGuard, undefinedGuard, voidGuard } from "./scalar.js";
|
|
11
|
+
export { instanceOf, json, property } from "./runtime.js";
|
|
11
12
|
export { t } from "./table.js";
|
|
@@ -29,6 +29,12 @@ export declare function undefinedable<TGuard extends Guard<unknown, Presence>>(g
|
|
|
29
29
|
* @returns Fresh nullable guard preserving original presence.
|
|
30
30
|
*/
|
|
31
31
|
export declare function nullable<TGuard extends Guard<unknown, Presence>>(guard: TGuard): BaseGuard<GuardValue<TGuard> | null, GuardPresence<TGuard>>;
|
|
32
|
+
/**
|
|
33
|
+
* @brief Allow null, undefined, and absent object keys.
|
|
34
|
+
* @param guard Guard to wrap.
|
|
35
|
+
* @returns Fresh optional guard whose value domain also includes null.
|
|
36
|
+
*/
|
|
37
|
+
export declare function nullish<TGuard extends Guard<unknown, Presence>>(guard: TGuard): BaseGuard<GuardValue<TGuard> | null, "optional">;
|
|
32
38
|
/**
|
|
33
39
|
* @brief Resolve recursive schemas once and reuse the frozen schema handle.
|
|
34
40
|
* @details Builder helpers normalize user-facing fluent calls into immutable schema nodes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modifier.d.ts","sourceRoot":"","sources":["../../src/builders/modifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACH,SAAS,EACT,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,QAAQ,EAChB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC5D,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAK3C;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACjE,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAKlE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC5D,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAK7D;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACxD,GAAG,EAAE,MAAM,MAAM,GAClB,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAgB1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC1D,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,OAAO,EAC5C,IAAI,EAAE,MAAM,GACb,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAkBtD"}
|
|
1
|
+
{"version":3,"file":"modifier.d.ts","sourceRoot":"","sources":["../../src/builders/modifier.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACH,SAAS,EACT,KAAK,KAAK,EACV,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,QAAQ,EAChB,MAAM,mBAAmB,CAAC;AAI3B;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC5D,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC,CAK3C;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACjE,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAKlE;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC5D,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAK7D;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC3D,KAAK,EAAE,MAAM,GACd,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,UAAU,CAAC,CAQlD;AAED;;;;;;;GAOG;AACH,wBAAgB,IAAI,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EACxD,GAAG,EAAE,MAAM,MAAM,GAClB,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAgB1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,MAAM,SAAS,KAAK,CAAC,OAAO,EAAE,QAAQ,CAAC,EAC1D,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,OAAO,EAC5C,IAAI,EAAE,MAAM,GACb,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,CAkBtD"}
|