typesea 0.1.0 → 0.2.0
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 +67 -6
- package/README.md +98 -17
- package/dist/adapters/index.d.ts +50 -8
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +169 -48
- package/dist/aot/index.d.ts +18 -2
- package/dist/aot/index.d.ts.map +1 -1
- package/dist/aot/index.js +93 -14
- package/dist/async/index.d.ts +28 -56
- package/dist/async/index.d.ts.map +1 -1
- package/dist/async/index.js +94 -37
- package/dist/builders/composite.d.ts +37 -6
- package/dist/builders/composite.d.ts.map +1 -1
- package/dist/builders/composite.js +84 -10
- package/dist/builders/index.d.ts +2 -0
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +2 -0
- package/dist/builders/modifier.d.ts +30 -5
- package/dist/builders/modifier.d.ts.map +1 -1
- package/dist/builders/modifier.js +38 -5
- package/dist/builders/object/guard.d.ts +18 -22
- package/dist/builders/object/guard.d.ts.map +1 -1
- package/dist/builders/object/guard.js +26 -26
- package/dist/builders/object/index.d.ts +2 -0
- package/dist/builders/object/index.d.ts.map +1 -1
- package/dist/builders/object/index.js +2 -0
- package/dist/builders/object/schema.d.ts +55 -9
- package/dist/builders/object/schema.d.ts.map +1 -1
- package/dist/builders/object/schema.js +92 -15
- package/dist/builders/object/types.d.ts +5 -31
- package/dist/builders/object/types.d.ts.map +1 -1
- package/dist/builders/object/types.js +2 -0
- package/dist/builders/scalar.d.ts +29 -8
- package/dist/builders/scalar.d.ts.map +1 -1
- package/dist/builders/scalar.js +33 -8
- package/dist/builders/table.d.ts +4 -0
- package/dist/builders/table.d.ts.map +1 -1
- package/dist/builders/table.js +4 -0
- package/dist/builders/types.d.ts +14 -4
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/builders/types.js +2 -0
- package/dist/compile/check-composite.d.ts +22 -1
- package/dist/compile/check-composite.d.ts.map +1 -1
- package/dist/compile/check-composite.js +564 -24
- package/dist/compile/check-scalar.d.ts +78 -0
- package/dist/compile/check-scalar.d.ts.map +1 -1
- package/dist/compile/check-scalar.js +432 -1
- package/dist/compile/check.d.ts +12 -0
- package/dist/compile/check.d.ts.map +1 -1
- package/dist/compile/check.js +37 -0
- package/dist/compile/context.d.ts +47 -9
- package/dist/compile/context.d.ts.map +1 -1
- package/dist/compile/context.js +51 -8
- package/dist/compile/graph-predicate.d.ts +4 -2
- package/dist/compile/graph-predicate.d.ts.map +1 -1
- package/dist/compile/graph-predicate.js +1907 -171
- package/dist/compile/guard.d.ts +15 -24
- package/dist/compile/guard.d.ts.map +1 -1
- package/dist/compile/guard.js +158 -74
- package/dist/compile/index.d.ts +3 -1
- package/dist/compile/index.d.ts.map +1 -1
- package/dist/compile/index.js +2 -0
- package/dist/compile/issue.d.ts +110 -0
- package/dist/compile/issue.d.ts.map +1 -1
- package/dist/compile/issue.js +184 -1
- package/dist/compile/names.d.ts +12 -2
- package/dist/compile/names.d.ts.map +1 -1
- package/dist/compile/names.js +19 -3
- package/dist/compile/predicate.d.ts +24 -0
- package/dist/compile/predicate.d.ts.map +1 -1
- package/dist/compile/predicate.js +131 -5
- package/dist/compile/runtime.d.ts +80 -12
- package/dist/compile/runtime.d.ts.map +1 -1
- package/dist/compile/runtime.js +25 -6
- package/dist/compile/source.d.ts +10 -2
- package/dist/compile/source.d.ts.map +1 -1
- package/dist/compile/source.js +361 -26
- package/dist/compile/types.d.ts +20 -0
- package/dist/compile/types.d.ts.map +1 -1
- package/dist/compile/types.js +2 -0
- package/dist/decoder/index.d.ts +32 -46
- package/dist/decoder/index.d.ts.map +1 -1
- package/dist/decoder/index.js +102 -38
- package/dist/evaluate/check-composite.d.ts +59 -0
- package/dist/evaluate/check-composite.d.ts.map +1 -1
- package/dist/evaluate/check-composite.js +151 -3
- package/dist/evaluate/check-scalar.d.ts +16 -0
- package/dist/evaluate/check-scalar.d.ts.map +1 -1
- package/dist/evaluate/check-scalar.js +32 -0
- package/dist/evaluate/check.d.ts +7 -0
- package/dist/evaluate/check.d.ts.map +1 -1
- package/dist/evaluate/check.js +43 -0
- package/dist/evaluate/index.d.ts +2 -0
- package/dist/evaluate/index.d.ts.map +1 -1
- package/dist/evaluate/index.js +2 -0
- package/dist/evaluate/issue.d.ts +11 -1
- package/dist/evaluate/issue.d.ts.map +1 -1
- package/dist/evaluate/issue.js +15 -1
- package/dist/evaluate/predicate.d.ts +16 -5
- package/dist/evaluate/predicate.d.ts.map +1 -1
- package/dist/evaluate/predicate.js +20 -5
- package/dist/evaluate/shared.d.ts +59 -13
- package/dist/evaluate/shared.d.ts.map +1 -1
- package/dist/evaluate/shared.js +66 -8
- package/dist/evaluate/state.d.ts +35 -13
- package/dist/evaluate/state.d.ts.map +1 -1
- package/dist/evaluate/state.js +35 -2
- package/dist/guard/base.d.ts +79 -29
- package/dist/guard/base.d.ts.map +1 -1
- package/dist/guard/base.js +91 -29
- package/dist/guard/error.d.ts +10 -5
- package/dist/guard/error.d.ts.map +1 -1
- package/dist/guard/error.js +10 -5
- 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 +26 -11
- package/dist/guard/number.d.ts.map +1 -1
- package/dist/guard/number.js +30 -11
- package/dist/guard/props.d.ts +27 -3
- package/dist/guard/props.d.ts.map +1 -1
- package/dist/guard/props.js +27 -3
- package/dist/guard/read.d.ts +62 -9
- package/dist/guard/read.d.ts.map +1 -1
- package/dist/guard/read.js +83 -10
- package/dist/guard/registry.d.ts +12 -2
- package/dist/guard/registry.d.ts.map +1 -1
- package/dist/guard/registry.js +15 -3
- package/dist/guard/string.d.ts +33 -13
- package/dist/guard/string.d.ts.map +1 -1
- package/dist/guard/string.js +37 -13
- package/dist/guard/types.d.ts +92 -40
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/guard/types.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/index.d.ts +42 -6
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +51 -8
- package/dist/ir/builder.d.ts +16 -126
- package/dist/ir/builder.d.ts.map +1 -1
- package/dist/ir/builder.js +77 -137
- package/dist/ir/freeze.d.ts +4 -0
- package/dist/ir/freeze.d.ts.map +1 -1
- package/dist/ir/freeze.js +59 -0
- package/dist/ir/index.d.ts +3 -1
- package/dist/ir/index.d.ts.map +1 -1
- package/dist/ir/index.js +2 -0
- package/dist/ir/regexp.d.ts +2 -0
- package/dist/ir/regexp.d.ts.map +1 -1
- package/dist/ir/regexp.js +2 -0
- package/dist/ir/types.d.ts +90 -55
- package/dist/ir/types.d.ts.map +1 -1
- package/dist/ir/types.js +2 -0
- package/dist/ir/validate.d.ts +8 -1
- package/dist/ir/validate.d.ts.map +1 -1
- package/dist/ir/validate.js +477 -61
- package/dist/issue/index.d.ts +41 -9
- package/dist/issue/index.d.ts.map +1 -1
- package/dist/issue/index.js +61 -11
- package/dist/json-schema/emit-combinator.d.ts +44 -4
- package/dist/json-schema/emit-combinator.d.ts.map +1 -1
- package/dist/json-schema/emit-combinator.js +44 -4
- package/dist/json-schema/emit-composite.d.ts +10 -0
- package/dist/json-schema/emit-composite.d.ts.map +1 -1
- package/dist/json-schema/emit-composite.js +15 -1
- package/dist/json-schema/emit-scalar.d.ts +26 -3
- package/dist/json-schema/emit-scalar.d.ts.map +1 -1
- package/dist/json-schema/emit-scalar.js +70 -9
- package/dist/json-schema/emit-types.d.ts +11 -1
- package/dist/json-schema/emit-types.d.ts.map +1 -1
- package/dist/json-schema/emit-types.js +2 -0
- package/dist/json-schema/emit.d.ts +12 -1
- package/dist/json-schema/emit.d.ts.map +1 -1
- package/dist/json-schema/emit.js +12 -1
- package/dist/json-schema/freeze.d.ts +13 -2
- package/dist/json-schema/freeze.d.ts.map +1 -1
- package/dist/json-schema/freeze.js +41 -8
- package/dist/json-schema/index.d.ts +16 -2
- package/dist/json-schema/index.d.ts.map +1 -1
- package/dist/json-schema/index.js +23 -3
- package/dist/json-schema/issue.d.ts +4 -1
- package/dist/json-schema/issue.d.ts.map +1 -1
- package/dist/json-schema/issue.js +4 -1
- package/dist/json-schema/read.d.ts +24 -3
- package/dist/json-schema/read.d.ts.map +1 -1
- package/dist/json-schema/read.js +59 -12
- package/dist/json-schema/types.d.ts +38 -15
- package/dist/json-schema/types.d.ts.map +1 -1
- package/dist/json-schema/types.js +2 -0
- package/dist/kind/index.d.ts +15 -28
- package/dist/kind/index.d.ts.map +1 -1
- package/dist/kind/index.js +15 -10
- package/dist/lower/index.d.ts +6 -1
- package/dist/lower/index.d.ts.map +1 -1
- package/dist/lower/index.js +411 -44
- package/dist/message/index.d.ts +46 -10
- package/dist/message/index.d.ts.map +1 -1
- package/dist/message/index.js +88 -17
- package/dist/optimize/algebraic.d.ts +54 -0
- package/dist/optimize/algebraic.d.ts.map +1 -0
- package/dist/optimize/algebraic.js +314 -0
- package/dist/optimize/compact.d.ts +8 -1
- package/dist/optimize/compact.d.ts.map +1 -1
- package/dist/optimize/compact.js +13 -2
- package/dist/optimize/domain.d.ts +16 -0
- package/dist/optimize/domain.d.ts.map +1 -0
- package/dist/optimize/domain.js +615 -0
- package/dist/optimize/fold-boolean.d.ts +17 -2
- package/dist/optimize/fold-boolean.d.ts.map +1 -1
- package/dist/optimize/fold-boolean.js +59 -14
- package/dist/optimize/fold-common.d.ts +43 -8
- package/dist/optimize/fold-common.d.ts.map +1 -1
- package/dist/optimize/fold-common.js +37 -6
- package/dist/optimize/fold-constraints.d.ts +33 -0
- package/dist/optimize/fold-constraints.d.ts.map +1 -0
- package/dist/optimize/fold-constraints.js +484 -0
- package/dist/optimize/fold-scalar.d.ts +98 -13
- package/dist/optimize/fold-scalar.d.ts.map +1 -1
- package/dist/optimize/fold-scalar.js +98 -13
- package/dist/optimize/fold.d.ts +8 -1
- package/dist/optimize/fold.d.ts.map +1 -1
- package/dist/optimize/fold.js +22 -2
- package/dist/optimize/index.d.ts +9 -1
- package/dist/optimize/index.d.ts.map +1 -1
- package/dist/optimize/index.js +18 -3
- package/dist/optimize/map-node.d.ts +3 -1
- package/dist/optimize/map-node.d.ts.map +1 -1
- package/dist/optimize/map-node.js +45 -3
- package/dist/optimize/peephole.d.ts +16 -0
- package/dist/optimize/peephole.d.ts.map +1 -0
- package/dist/optimize/peephole.js +254 -0
- package/dist/optimize/remap.d.ts +2 -0
- package/dist/optimize/remap.d.ts.map +1 -1
- package/dist/optimize/remap.js +2 -0
- package/dist/optimize/rewrite.d.ts +13 -8
- package/dist/optimize/rewrite.d.ts.map +1 -1
- package/dist/optimize/rewrite.js +13 -8
- package/dist/plan/cache.d.ts +9 -3
- package/dist/plan/cache.d.ts.map +1 -1
- package/dist/plan/cache.js +21 -5
- package/dist/plan/index.d.ts +2 -0
- package/dist/plan/index.d.ts.map +1 -1
- package/dist/plan/index.js +2 -0
- package/dist/plan/predicate.d.ts +2 -0
- package/dist/plan/predicate.d.ts.map +1 -1
- package/dist/plan/predicate.js +268 -29
- package/dist/plan/schema-predicate.d.ts +6 -0
- package/dist/plan/schema-predicate.d.ts.map +1 -1
- package/dist/plan/schema-predicate.js +117 -13
- package/dist/plan/types.d.ts +2 -0
- package/dist/plan/types.d.ts.map +1 -1
- package/dist/plan/types.js +2 -0
- package/dist/result/index.d.ts +19 -5
- package/dist/result/index.d.ts.map +1 -1
- package/dist/result/index.js +10 -2
- package/dist/schema/common.d.ts +69 -6
- package/dist/schema/common.d.ts.map +1 -1
- package/dist/schema/common.js +104 -10
- package/dist/schema/freeze.d.ts +4 -0
- package/dist/schema/freeze.d.ts.map +1 -1
- package/dist/schema/freeze.js +18 -0
- package/dist/schema/index.d.ts +3 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +3 -0
- package/dist/schema/lazy.d.ts +4 -0
- package/dist/schema/lazy.d.ts.map +1 -1
- package/dist/schema/lazy.js +4 -0
- package/dist/schema/literal.d.ts +7 -1
- package/dist/schema/literal.d.ts.map +1 -1
- package/dist/schema/literal.js +7 -1
- package/dist/schema/types.d.ts +20 -96
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +5 -1
- package/dist/schema/undefined.d.ts +17 -0
- package/dist/schema/undefined.d.ts.map +1 -0
- package/dist/schema/undefined.js +72 -0
- package/dist/schema/validate.d.ts +8 -1
- package/dist/schema/validate.d.ts.map +1 -1
- package/dist/schema/validate.js +146 -55
- package/docs/api.md +57 -0
- package/docs/assets/benchmark-headline.svg +163 -0
- package/docs/engine-notes.md +58 -15
- package/docs/index.html +130 -110
- package/package.json +65 -65
package/dist/adapters/index.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { isAsyncDecoderValue } from "../async/index.js";
|
|
2
2
|
import { isDecoderValue } from "../decoder/index.js";
|
|
3
3
|
import { TypeSeaAssertionError } from "../guard/index.js";
|
|
4
|
+
import { isConstructedGuard } from "../guard/registry.js";
|
|
4
5
|
import { formatIssue } from "../message/index.js";
|
|
5
6
|
import { toJsonSchema } from "../json-schema/index.js";
|
|
6
7
|
import { isSchemaValue } from "../schema/index.js";
|
|
7
8
|
/**
|
|
8
9
|
* @brief to trpc parser.
|
|
10
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
11
|
+
* adding framework dependencies.
|
|
9
12
|
*/
|
|
10
13
|
export function toTrpcParser(source) {
|
|
11
14
|
readSyncAdapterSource(source, "tRPC parser source");
|
|
@@ -21,6 +24,8 @@ export function toTrpcParser(source) {
|
|
|
21
24
|
}
|
|
22
25
|
/**
|
|
23
26
|
* @brief to async trpc parser.
|
|
27
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
28
|
+
* adding framework dependencies.
|
|
24
29
|
*/
|
|
25
30
|
export function toAsyncTrpcParser(source) {
|
|
26
31
|
readAsyncAdapterSource(source, "async tRPC parser source");
|
|
@@ -36,6 +41,8 @@ export function toAsyncTrpcParser(source) {
|
|
|
36
41
|
}
|
|
37
42
|
/**
|
|
38
43
|
* @brief to fastify route schema.
|
|
44
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
45
|
+
* adding framework dependencies.
|
|
39
46
|
*/
|
|
40
47
|
export function toFastifyRouteSchema(guard, options) {
|
|
41
48
|
const part = readFastifyPart(options);
|
|
@@ -52,6 +59,8 @@ export function toFastifyRouteSchema(guard, options) {
|
|
|
52
59
|
}
|
|
53
60
|
/**
|
|
54
61
|
* @brief to fastify validator compiler.
|
|
62
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
63
|
+
* adding framework dependencies.
|
|
55
64
|
*/
|
|
56
65
|
export function toFastifyValidatorCompiler(source) {
|
|
57
66
|
const readSource = readFastifyValidatorCompilerSource(source);
|
|
@@ -72,6 +81,8 @@ export function toFastifyValidatorCompiler(source) {
|
|
|
72
81
|
}
|
|
73
82
|
/**
|
|
74
83
|
* @brief to react hook form resolver.
|
|
84
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
85
|
+
* adding framework dependencies.
|
|
75
86
|
*/
|
|
76
87
|
export function toReactHookFormResolver(source, options) {
|
|
77
88
|
const config = readReactHookFormOptions(options);
|
|
@@ -91,7 +102,13 @@ export function toReactHookFormResolver(source, options) {
|
|
|
91
102
|
};
|
|
92
103
|
}
|
|
93
104
|
/**
|
|
94
|
-
* @brief
|
|
105
|
+
* @brief Run a synchronous adapter source against one submitted value.
|
|
106
|
+
* @param source Guard or decoder selected for the adapter call.
|
|
107
|
+
* @param value Framework payload being validated.
|
|
108
|
+
* @returns TypeSea Result produced by the selected source.
|
|
109
|
+
* @details Decoders already own their result shape. Guard-like values are first
|
|
110
|
+
* normalized through readGuard so structural receivers cannot smuggle inherited
|
|
111
|
+
* schema or check fields into adapter execution.
|
|
95
112
|
*/
|
|
96
113
|
function decodeSyncSource(source, value) {
|
|
97
114
|
if (isDecoderValue(source)) {
|
|
@@ -101,7 +118,13 @@ function decodeSyncSource(source, value) {
|
|
|
101
118
|
return guard.check(value);
|
|
102
119
|
}
|
|
103
120
|
/**
|
|
104
|
-
* @brief
|
|
121
|
+
* @brief Run a possibly asynchronous adapter source.
|
|
122
|
+
* @param source Guard, decoder, or async decoder selected for the adapter call.
|
|
123
|
+
* @param value Framework payload being validated.
|
|
124
|
+
* @returns Promise resolving to a TypeSea Result.
|
|
125
|
+
* @details The ordering keeps native async decoders on their own private runner
|
|
126
|
+
* path while preserving the same hardened guard normalization used by sync
|
|
127
|
+
* adapters.
|
|
105
128
|
*/
|
|
106
129
|
async function decodeAsyncSource(source, value) {
|
|
107
130
|
if (isAsyncDecoderValue(source)) {
|
|
@@ -114,21 +137,36 @@ async function decodeAsyncSource(source, value) {
|
|
|
114
137
|
return guard.check(value);
|
|
115
138
|
}
|
|
116
139
|
/**
|
|
117
|
-
* @brief
|
|
140
|
+
* @brief Normalize a guard-like adapter source.
|
|
141
|
+
* @param value Candidate adapter source.
|
|
142
|
+
* @param label Message prefix for TypeError diagnostics.
|
|
143
|
+
* @returns Guard object safe to call through the adapter layer.
|
|
144
|
+
* @throws TypeError when schema or check are not valid guard fields.
|
|
145
|
+
* @details Constructed guards use registry identity. Structural guard support is
|
|
146
|
+
* limited to own data `schema` and `check` slots so adapter entry points do not
|
|
147
|
+
* execute prototype getters supplied by a framework payload or plugin wrapper.
|
|
118
148
|
*/
|
|
119
149
|
function readGuard(value, label) {
|
|
150
|
+
if (isConstructedGuard(value)) {
|
|
151
|
+
return value;
|
|
152
|
+
}
|
|
120
153
|
if (!isRecord(value)) {
|
|
121
154
|
throw new TypeError(`${label} must be a TypeSea guard or decoder`);
|
|
122
155
|
}
|
|
123
156
|
const guard = value;
|
|
124
|
-
const schema = value
|
|
125
|
-
|
|
157
|
+
const schema = readOwnDataProperty(value, "schema");
|
|
158
|
+
const check = readOwnDataProperty(value, "check");
|
|
159
|
+
if (!isSchemaValue(schema) || typeof check !== "function") {
|
|
126
160
|
throw new TypeError(`${label} must be a TypeSea guard or decoder`);
|
|
127
161
|
}
|
|
128
162
|
return guard;
|
|
129
163
|
}
|
|
130
164
|
/**
|
|
131
|
-
* @brief
|
|
165
|
+
* @brief Validate a source accepted by sync-only adapters.
|
|
166
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
167
|
+
* adding framework dependencies.
|
|
168
|
+
* @param source Candidate guard or decoder.
|
|
169
|
+
* @param label Message prefix for TypeError diagnostics.
|
|
132
170
|
*/
|
|
133
171
|
function readSyncAdapterSource(source, label) {
|
|
134
172
|
if (isDecoderValue(source)) {
|
|
@@ -137,8 +175,11 @@ function readSyncAdapterSource(source, label) {
|
|
|
137
175
|
readGuard(source, label);
|
|
138
176
|
}
|
|
139
177
|
/**
|
|
140
|
-
* @brief
|
|
141
|
-
* @details
|
|
178
|
+
* @brief Normalize Fastify validator sources into a route selector.
|
|
179
|
+
* @details A single source applies to all route parts. A source map is copied
|
|
180
|
+
* into a null-prototype table so route selection cannot observe later prototype
|
|
181
|
+
* mutations or inherited body/querystring/params/headers fields.
|
|
182
|
+
* @param source Guard, decoder, or route-part source table supplied by the user.
|
|
142
183
|
* @returns Source selector used by the Fastify compiler callback.
|
|
143
184
|
*/
|
|
144
185
|
function readFastifyValidatorCompilerSource(source) {
|
|
@@ -149,10 +190,15 @@ function readFastifyValidatorCompilerSource(source) {
|
|
|
149
190
|
if (!isRecord(source)) {
|
|
150
191
|
throw new TypeError("Fastify validator source must be a TypeSea guard, decoder, or route map");
|
|
151
192
|
}
|
|
152
|
-
|
|
193
|
+
/*
|
|
194
|
+
* Route maps are copied once before Fastify requests per-route validators.
|
|
195
|
+
* Later route selection reads the hardened copy, not caller-controlled
|
|
196
|
+
* prototype state.
|
|
197
|
+
*/
|
|
198
|
+
const sourceMap = readFastifyCompilerMap(source);
|
|
153
199
|
return (route) => {
|
|
154
200
|
const part = readFastifyRouteHttpPart(route);
|
|
155
|
-
const selected =
|
|
201
|
+
const selected = sourceMap[part];
|
|
156
202
|
if (selected === undefined) {
|
|
157
203
|
throw new TypeError(`Fastify validator source is missing ${part}`);
|
|
158
204
|
}
|
|
@@ -160,46 +206,79 @@ function readFastifyValidatorCompilerSource(source) {
|
|
|
160
206
|
};
|
|
161
207
|
}
|
|
162
208
|
/**
|
|
163
|
-
* @brief is guard
|
|
164
|
-
* @details Performs the same structural guard check as `readGuard` without
|
|
209
|
+
* @brief Test whether a value is usable as a guard source.
|
|
210
|
+
* @details Performs the same structural guard check as `readGuard` without
|
|
211
|
+
* throwing, which lets the Fastify source normalizer distinguish a single guard
|
|
212
|
+
* from a route-part map.
|
|
213
|
+
* @param value Candidate source.
|
|
165
214
|
* @returns True when the value is a TypeSea guard object.
|
|
166
215
|
*/
|
|
167
216
|
function isGuardValue(value) {
|
|
217
|
+
if (isConstructedGuard(value)) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
168
220
|
if (!isRecord(value)) {
|
|
169
221
|
return false;
|
|
170
222
|
}
|
|
171
|
-
const
|
|
172
|
-
|
|
223
|
+
const schema = readOwnDataProperty(value, "schema");
|
|
224
|
+
const check = readOwnDataProperty(value, "check");
|
|
225
|
+
return isSchemaValue(schema) && typeof check === "function";
|
|
173
226
|
}
|
|
174
227
|
/**
|
|
175
|
-
* @brief
|
|
176
|
-
* @details Validates every present route-part source before Fastify starts
|
|
177
|
-
*
|
|
228
|
+
* @brief Copy and validate a Fastify route-part source map.
|
|
229
|
+
* @details Validates every present route-part source before Fastify starts
|
|
230
|
+
* compiling routes. The returned table is a frozen null-prototype copy owned by
|
|
231
|
+
* TypeSea.
|
|
232
|
+
* @param source Route-part source table supplied by the user.
|
|
233
|
+
* @returns Frozen null-prototype map containing only own data-property sources.
|
|
234
|
+
* @post Accessor properties are rejected without executing getters.
|
|
178
235
|
*/
|
|
179
236
|
function readFastifyCompilerMap(source) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
237
|
+
/*
|
|
238
|
+
* Null prototype prevents inherited body/querystring/params/headers slots
|
|
239
|
+
* from becoming validator sources during route selection.
|
|
240
|
+
*/
|
|
241
|
+
const target = Object.create(null);
|
|
242
|
+
readOptionalFastifyCompilerPart(source, target, "body");
|
|
243
|
+
readOptionalFastifyCompilerPart(source, target, "querystring");
|
|
244
|
+
readOptionalFastifyCompilerPart(source, target, "params");
|
|
245
|
+
readOptionalFastifyCompilerPart(source, target, "headers");
|
|
246
|
+
return Object.freeze(target);
|
|
184
247
|
}
|
|
185
248
|
/**
|
|
186
|
-
* @brief
|
|
187
|
-
* @details
|
|
188
|
-
*
|
|
249
|
+
* @brief Copy one optional Fastify route-part source.
|
|
250
|
+
* @details Copies one own data-property source without consulting prototype
|
|
251
|
+
* state. Missing parts stay undefined so route selection can fail with the
|
|
252
|
+
* concrete missing part later.
|
|
253
|
+
* @param source User supplied route-part source table.
|
|
254
|
+
* @param target Hardened lookup receiving validated sources.
|
|
255
|
+
* @param part Fastify HTTP part to copy.
|
|
256
|
+
* @post Malformed present sources throw TypeError before the compiler is returned.
|
|
189
257
|
*/
|
|
190
|
-
function readOptionalFastifyCompilerPart(source, part) {
|
|
191
|
-
|
|
258
|
+
function readOptionalFastifyCompilerPart(source, target, part) {
|
|
259
|
+
/*
|
|
260
|
+
* getOwnPropertyDescriptor observes own metadata without reading the value
|
|
261
|
+
* through the prototype chain or invoking an accessor getter.
|
|
262
|
+
*/
|
|
263
|
+
const descriptor = Object.getOwnPropertyDescriptor(source, part);
|
|
264
|
+
if (descriptor === undefined) {
|
|
192
265
|
return;
|
|
193
266
|
}
|
|
194
|
-
|
|
267
|
+
if (!Object.prototype.hasOwnProperty.call(descriptor, "value")) {
|
|
268
|
+
throw new TypeError(`Fastify validator source for ${part} must be a data property`);
|
|
269
|
+
}
|
|
270
|
+
const partSource = descriptor.value;
|
|
195
271
|
if (partSource === undefined) {
|
|
196
272
|
throw new TypeError(`Fastify validator source for ${part} must be defined`);
|
|
197
273
|
}
|
|
198
274
|
readSyncAdapterSource(partSource, `Fastify validator source for ${part}`);
|
|
275
|
+
target[part] = partSource;
|
|
199
276
|
}
|
|
200
277
|
/**
|
|
201
|
-
* @brief
|
|
202
|
-
* @details Converts Fastify's route descriptor slot into TypeSea's closed part
|
|
278
|
+
* @brief Normalize Fastify route metadata into a supported HTTP part.
|
|
279
|
+
* @details Converts Fastify's route descriptor slot into TypeSea's closed part
|
|
280
|
+
* union so one validator source is never silently reused for a different part.
|
|
281
|
+
* @param route Fastify validator route descriptor.
|
|
203
282
|
* @returns Validated Fastify HTTP part.
|
|
204
283
|
*/
|
|
205
284
|
function readFastifyRouteHttpPart(route) {
|
|
@@ -214,7 +293,11 @@ function readFastifyRouteHttpPart(route) {
|
|
|
214
293
|
}
|
|
215
294
|
}
|
|
216
295
|
/**
|
|
217
|
-
* @brief
|
|
296
|
+
* @brief Validate a source accepted by async-capable adapters.
|
|
297
|
+
* @param source Candidate guard, decoder, or async decoder.
|
|
298
|
+
* @param label Message prefix for TypeError diagnostics.
|
|
299
|
+
* @details Async decoders and sync decoders already prove identity through
|
|
300
|
+
* private registries. Guard-like values still pass through readGuard.
|
|
218
301
|
*/
|
|
219
302
|
function readAsyncAdapterSource(source, label) {
|
|
220
303
|
if (isAsyncDecoderValue(source) || isDecoderValue(source)) {
|
|
@@ -223,7 +306,11 @@ function readAsyncAdapterSource(source, label) {
|
|
|
223
306
|
readGuard(source, label);
|
|
224
307
|
}
|
|
225
308
|
/**
|
|
226
|
-
* @brief
|
|
309
|
+
* @brief Resolve the Fastify route part used for JSON Schema output.
|
|
310
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
311
|
+
* adding framework dependencies.
|
|
312
|
+
* @param options Optional Fastify route schema options.
|
|
313
|
+
* @returns The selected HTTP part, defaulting to body.
|
|
227
314
|
*/
|
|
228
315
|
function readFastifyPart(options) {
|
|
229
316
|
if (options?.part === undefined) {
|
|
@@ -240,8 +327,10 @@ function readFastifyPart(options) {
|
|
|
240
327
|
}
|
|
241
328
|
}
|
|
242
329
|
/**
|
|
243
|
-
* @brief
|
|
244
|
-
* @details Copies only JSON Schema exporter options out of the adapter options
|
|
330
|
+
* @brief Extract JSON Schema exporter options from Fastify options.
|
|
331
|
+
* @details Copies only JSON Schema exporter options out of the adapter options
|
|
332
|
+
* object. The returned object avoids exact-optional undefined fields.
|
|
333
|
+
* @param options Optional Fastify route schema options.
|
|
245
334
|
* @returns Partial JSON Schema options without exact-optional undefined slots.
|
|
246
335
|
*/
|
|
247
336
|
function readFastifyJsonSchemaOptions(options) {
|
|
@@ -255,7 +344,12 @@ function readFastifyJsonSchemaOptions(options) {
|
|
|
255
344
|
return output;
|
|
256
345
|
}
|
|
257
346
|
/**
|
|
258
|
-
* @brief
|
|
347
|
+
* @brief Normalize React Hook Form resolver options.
|
|
348
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
349
|
+
* adding framework dependencies.
|
|
350
|
+
* @param options Optional resolver options.
|
|
351
|
+
* @returns Required options object used by the resolver.
|
|
352
|
+
* @throws TypeError when options are not object-like.
|
|
259
353
|
*/
|
|
260
354
|
function readReactHookFormOptions(options) {
|
|
261
355
|
if (options === undefined) {
|
|
@@ -271,7 +365,12 @@ function readReactHookFormOptions(options) {
|
|
|
271
365
|
};
|
|
272
366
|
}
|
|
273
367
|
/**
|
|
274
|
-
* @brief issues
|
|
368
|
+
* @brief Convert TypeSea issues into React Hook Form field errors.
|
|
369
|
+
* @param issues Frozen TypeSea issue vector.
|
|
370
|
+
* @param options Message formatting options.
|
|
371
|
+
* @returns Frozen nested FieldErrors-compatible object.
|
|
372
|
+
* @details React Hook Form resolves nested fields by object traversal, so
|
|
373
|
+
* TypeSea paths are inserted as nested branches rather than flat dotted keys.
|
|
275
374
|
*/
|
|
276
375
|
function issuesToReactHookFormErrors(issues, options) {
|
|
277
376
|
const errors = makeReactHookFormErrorBranch();
|
|
@@ -285,19 +384,21 @@ function issuesToReactHookFormErrors(issues, options) {
|
|
|
285
384
|
return freezeReactHookFormErrors(errors);
|
|
286
385
|
}
|
|
287
386
|
/**
|
|
288
|
-
* @brief
|
|
289
|
-
* @details
|
|
387
|
+
* @brief Allocate one mutable React Hook Form error branch.
|
|
388
|
+
* @details Null prototype branches keep field names such as `constructor` or
|
|
389
|
+
* `__proto__` from colliding with inherited object members.
|
|
290
390
|
* @returns Mutable branch owned by the caller.
|
|
291
391
|
*/
|
|
292
392
|
function makeReactHookFormErrorBranch() {
|
|
293
393
|
return Object.create(null);
|
|
294
394
|
}
|
|
295
395
|
/**
|
|
296
|
-
* @brief
|
|
297
|
-
* @details
|
|
298
|
-
*
|
|
299
|
-
* @param
|
|
300
|
-
* @param
|
|
396
|
+
* @brief Insert one TypeSea issue into a nested React Hook Form tree.
|
|
397
|
+
* @details Existing leaf errors are preserved because React Hook Form reports
|
|
398
|
+
* the first error for a field by default.
|
|
399
|
+
* @param errors Mutable root branch receiving the leaf error when absent.
|
|
400
|
+
* @param issue Issue whose path is converted into branch keys.
|
|
401
|
+
* @param options Message options used only when a leaf is created.
|
|
301
402
|
* @post Existing first errors are preserved to match React Hook Form resolver behavior.
|
|
302
403
|
*/
|
|
303
404
|
function insertReactHookFormIssue(errors, issue, options) {
|
|
@@ -337,7 +438,7 @@ function insertReactHookFormIssue(errors, issue, options) {
|
|
|
337
438
|
/**
|
|
338
439
|
* @brief react hook form path key.
|
|
339
440
|
* @details Converts one TypeSea path segment into the object key React Hook Form traverses.
|
|
340
|
-
* @param segment
|
|
441
|
+
* @param segment Path segment from a TypeSea issue.
|
|
341
442
|
* @returns Stable string key for object or array-index lookup.
|
|
342
443
|
*/
|
|
343
444
|
function reactHookFormPathKey(segment) {
|
|
@@ -346,7 +447,7 @@ function reactHookFormPathKey(segment) {
|
|
|
346
447
|
/**
|
|
347
448
|
* @brief freeze react hook form errors.
|
|
348
449
|
* @details Recursively freezes the null-prototype tree after all issues have been inserted.
|
|
349
|
-
* @param errors
|
|
450
|
+
* @param errors Mutable branch that becomes immutable before publication.
|
|
350
451
|
* @returns Frozen React Hook Form error tree.
|
|
351
452
|
*/
|
|
352
453
|
function freezeReactHookFormErrors(errors) {
|
|
@@ -364,7 +465,7 @@ function freezeReactHookFormErrors(errors) {
|
|
|
364
465
|
return Object.freeze(errors);
|
|
365
466
|
}
|
|
366
467
|
/**
|
|
367
|
-
* @brief
|
|
468
|
+
* @brief Test whether a React Hook Form node is an internal branch.
|
|
368
469
|
* @details Distinguishes internal branch objects from frozen leaf error objects.
|
|
369
470
|
* @param value Candidate branch or leaf error value.
|
|
370
471
|
* @returns True when value is a null-prototype branch object.
|
|
@@ -381,16 +482,36 @@ function isReactHookFormErrorBranch(value) {
|
|
|
381
482
|
*/
|
|
382
483
|
const rootIssuePath = Object.freeze(["root"]);
|
|
383
484
|
/**
|
|
384
|
-
* @brief
|
|
485
|
+
* @brief Check record.
|
|
486
|
+
* @details This helper keeps a local invariant explicit at the module boundary.
|
|
385
487
|
*/
|
|
386
488
|
function isRecord(value) {
|
|
387
489
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
388
490
|
}
|
|
389
491
|
/**
|
|
390
|
-
* @brief
|
|
492
|
+
* @brief Read one own data slot from an adapter input object.
|
|
493
|
+
* @details Adapter shapes stay local so TypeSea diagnostics can be translated without
|
|
494
|
+
* adding framework dependencies.
|
|
495
|
+
* @param value Object being normalized.
|
|
496
|
+
* @param key Field name or symbol.
|
|
497
|
+
* @returns Stored field value, or undefined when absent.
|
|
498
|
+
*/
|
|
499
|
+
function readOwnDataProperty(value, key) {
|
|
500
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
501
|
+
if (descriptor === undefined ||
|
|
502
|
+
!Object.prototype.hasOwnProperty.call(descriptor, "value")) {
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
505
|
+
return descriptor.value;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* @brief Shared immutable success errors object for React Hook Form.
|
|
509
|
+
* @details Reusing this object avoids allocating a fresh empty tree on every
|
|
510
|
+
* successful resolver call.
|
|
391
511
|
*/
|
|
392
512
|
const emptyErrors = Object.freeze({});
|
|
393
513
|
/**
|
|
394
|
-
* @brief
|
|
514
|
+
* @brief Shared immutable values object used when resolver validation fails.
|
|
515
|
+
* @details React Hook Form expects failed resolvers to return no accepted values.
|
|
395
516
|
*/
|
|
396
517
|
const emptyValues = Object.freeze({});
|
package/dist/aot/index.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
import type { CompileMode } from "../compile/index.js";
|
|
1
2
|
import type { Guard, Presence } from "../guard/index.js";
|
|
2
3
|
import type { PathSegment } from "../issue/index.js";
|
|
3
4
|
import { type Result } from "../result/index.js";
|
|
4
5
|
/**
|
|
5
6
|
* @brief aot issue code.
|
|
7
|
+
* @details AOT helpers serialize only portable data because standalone modules cannot close
|
|
8
|
+
* over runtime side tables.
|
|
6
9
|
*/
|
|
7
10
|
export type AotIssueCode = "unsupported_aot_lazy" | "unsupported_aot_refine" | "unsupported_aot_symbol_literal";
|
|
8
11
|
/**
|
|
9
12
|
* @brief aot issue.
|
|
13
|
+
* @details AOT helpers serialize only portable data because standalone modules cannot close
|
|
14
|
+
* over runtime side tables.
|
|
10
15
|
*/
|
|
11
16
|
export interface AotIssue {
|
|
12
17
|
readonly path: readonly PathSegment[];
|
|
@@ -15,19 +20,30 @@ export interface AotIssue {
|
|
|
15
20
|
}
|
|
16
21
|
/**
|
|
17
22
|
* @brief aot compile options.
|
|
23
|
+
* @details AOT helpers serialize only portable data because standalone modules cannot close
|
|
24
|
+
* over runtime side tables.
|
|
18
25
|
*/
|
|
19
26
|
export interface AotCompileOptions {
|
|
20
27
|
readonly name: string | undefined;
|
|
28
|
+
readonly mode: CompileMode | undefined;
|
|
21
29
|
}
|
|
22
30
|
/**
|
|
23
|
-
* @brief
|
|
31
|
+
* @brief Source pair emitted for ahead-of-time validation.
|
|
32
|
+
* @details `source` is the JavaScript module body; `declarationSource` is the
|
|
33
|
+
* companion TypeScript declaration used by package consumers.
|
|
24
34
|
*/
|
|
25
35
|
export interface AotModule {
|
|
26
36
|
readonly source: string;
|
|
27
37
|
readonly declarationSource: string;
|
|
28
38
|
}
|
|
29
39
|
/**
|
|
30
|
-
* @brief
|
|
40
|
+
* @brief Emit a standalone validator module for a guard schema.
|
|
41
|
+
* @param guard Guard whose schema is exported.
|
|
42
|
+
* @param options Optional function name and compile mode.
|
|
43
|
+
* @returns Result carrying source text, or closed issues for unsupported schema nodes.
|
|
44
|
+
* @details AOT output cannot close over runtime side tables. The schema is
|
|
45
|
+
* scanned before code emission so lazy, refine, and symbol-literal constructs
|
|
46
|
+
* fail as explicit issues instead of producing partially faithful source.
|
|
31
47
|
*/
|
|
32
48
|
export declare function emitAotModule(guard: Guard<unknown, Presence>, options?: Partial<AotCompileOptions>): Result<AotModule, readonly AotIssue[]>;
|
|
33
49
|
//# sourceMappingURL=index.d.ts.map
|
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,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
|
|
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"}
|