typesea 0.1.0 → 0.3.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 +85 -6
- package/README.md +143 -28
- 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 +19 -3
- package/dist/aot/index.d.ts.map +1 -1
- package/dist/aot/index.js +115 -17
- 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 +43 -9
- package/dist/builders/composite.d.ts.map +1 -1
- package/dist/builders/composite.js +100 -17
- package/dist/builders/index.d.ts +8 -5
- package/dist/builders/index.d.ts.map +1 -1
- package/dist/builders/index.js +7 -4
- package/dist/builders/modifier.d.ts +36 -5
- package/dist/builders/modifier.d.ts.map +1 -1
- package/dist/builders/modifier.js +52 -5
- package/dist/builders/object/guard.d.ts +72 -24
- package/dist/builders/object/guard.d.ts.map +1 -1
- package/dist/builders/object/guard.js +139 -29
- package/dist/builders/object/index.d.ts +4 -2
- package/dist/builders/object/index.d.ts.map +1 -1
- package/dist/builders/object/index.js +3 -1
- package/dist/builders/object/schema.d.ts +88 -11
- package/dist/builders/object/schema.d.ts.map +1 -1
- package/dist/builders/object/schema.js +290 -23
- package/dist/builders/object/types.d.ts +20 -31
- package/dist/builders/object/types.d.ts.map +1 -1
- package/dist/builders/object/types.js +2 -0
- 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 +49 -9
- package/dist/builders/scalar.d.ts.map +1 -1
- package/dist/builders/scalar.js +87 -9
- package/dist/builders/table.d.ts +35 -5
- package/dist/builders/table.d.ts.map +1 -1
- package/dist/builders/table.js +35 -5
- package/dist/builders/types.d.ts +20 -4
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/builders/types.js +2 -0
- package/dist/compile/check-composite.d.ts +25 -2
- package/dist/compile/check-composite.d.ts.map +1 -1
- package/dist/compile/check-composite.js +699 -27
- package/dist/compile/check-scalar.d.ts +88 -0
- package/dist/compile/check-scalar.d.ts.map +1 -1
- package/dist/compile/check-scalar.js +570 -3
- package/dist/compile/check.d.ts +12 -0
- package/dist/compile/check.d.ts.map +1 -1
- package/dist/compile/check.js +62 -3
- package/dist/compile/context.d.ts +47 -9
- package/dist/compile/context.d.ts.map +1 -1
- package/dist/compile/context.js +53 -8
- 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 +4 -2
- package/dist/compile/graph-predicate.d.ts.map +1 -1
- package/dist/compile/graph-predicate.js +2272 -165
- package/dist/compile/guard.d.ts +16 -24
- package/dist/compile/guard.d.ts.map +1 -1
- package/dist/compile/guard.js +202 -72
- 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 +287 -10
- package/dist/compile/runtime.d.ts +100 -13
- package/dist/compile/runtime.d.ts.map +1 -1
- package/dist/compile/runtime.js +56 -6
- package/dist/compile/source.d.ts +10 -2
- package/dist/compile/source.d.ts.map +1 -1
- package/dist/compile/source.js +385 -26
- package/dist/compile/types.d.ts +22 -0
- package/dist/compile/types.d.ts.map +1 -1
- package/dist/compile/types.js +2 -0
- package/dist/decoder/index.d.ts +92 -46
- package/dist/decoder/index.d.ts.map +1 -1
- package/dist/decoder/index.js +266 -39
- package/dist/evaluate/check-composite.d.ts +111 -2
- package/dist/evaluate/check-composite.d.ts.map +1 -1
- package/dist/evaluate/check-composite.js +343 -8
- package/dist/evaluate/check-scalar.d.ts +25 -0
- package/dist/evaluate/check-scalar.d.ts.map +1 -1
- package/dist/evaluate/check-scalar.js +124 -3
- package/dist/evaluate/check.d.ts +7 -0
- package/dist/evaluate/check.d.ts.map +1 -1
- package/dist/evaluate/check.js +62 -4
- 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 +78 -13
- package/dist/evaluate/shared.d.ts.map +1 -1
- package/dist/evaluate/shared.js +101 -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/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 +111 -31
- package/dist/guard/base.d.ts.map +1 -1
- package/dist/guard/base.js +165 -32
- 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/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 +4 -0
- package/dist/guard/index.d.ts.map +1 -1
- package/dist/guard/index.js +4 -0
- package/dist/guard/number.d.ts +86 -11
- package/dist/guard/number.d.ts.map +1 -1
- package/dist/guard/number.js +159 -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 +115 -10
- package/dist/guard/read.d.ts.map +1 -1
- package/dist/guard/read.js +185 -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 +115 -13
- package/dist/guard/string.d.ts.map +1 -1
- package/dist/guard/string.js +250 -13
- package/dist/guard/types.d.ts +110 -40
- package/dist/guard/types.d.ts.map +1 -1
- package/dist/guard/types.js +2 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- 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 +17 -127
- package/dist/ir/builder.d.ts.map +1 -1
- package/dist/ir/builder.js +80 -137
- package/dist/ir/freeze.d.ts +4 -0
- package/dist/ir/freeze.d.ts.map +1 -1
- package/dist/ir/freeze.js +66 -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 +94 -56
- 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 +511 -61
- package/dist/issue/index.d.ts +42 -10
- package/dist/issue/index.d.ts.map +1 -1
- package/dist/issue/index.js +65 -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 +16 -2
- package/dist/json-schema/emit-composite.d.ts.map +1 -1
- package/dist/json-schema/emit-composite.js +81 -13
- 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 +124 -10
- 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 +23 -3
- 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 +45 -16
- package/dist/json-schema/types.d.ts.map +1 -1
- package/dist/json-schema/types.js +2 -0
- package/dist/kind/index.d.ts +40 -28
- package/dist/kind/index.d.ts.map +1 -1
- package/dist/kind/index.js +41 -13
- package/dist/lower/index.d.ts +6 -1
- package/dist/lower/index.d.ts.map +1 -1
- package/dist/lower/index.js +462 -46
- package/dist/message/index.d.ts +64 -10
- package/dist/message/index.d.ts.map +1 -1
- package/dist/message/index.js +155 -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 +619 -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 +48 -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 +34 -6
- 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 +298 -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 +382 -19
- 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 +40 -0
- package/dist/schema/index.d.ts +5 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +4 -1
- 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 +109 -100
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +13 -2
- package/dist/schema/undefined.d.ts +17 -0
- package/dist/schema/undefined.d.ts.map +1 -0
- package/dist/schema/undefined.js +77 -0
- package/dist/schema/validate.d.ts +8 -1
- package/dist/schema/validate.d.ts.map +1 -1
- package/dist/schema/validate.js +255 -57
- package/docs/api.md +128 -8
- package/docs/assets/benchmark-headline.svg +163 -0
- package/docs/engine-notes.md +62 -15
- package/docs/index.html +1340 -702
- package/docs/ko/api.md +375 -0
- package/docs/ko/engine-notes.md +156 -0
- package/docs/ko/readme.md +378 -0
- package/package.json +66 -65
package/dist/schema/validate.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file schema/validate.ts
|
|
3
3
|
* @brief Runtime validators for direct schema objects.
|
|
4
|
+
* @details Schema helpers enforce construction-time invariants before values reach
|
|
5
|
+
* validation, compilation, or export.
|
|
4
6
|
*/
|
|
5
|
-
import { NumberCheckTag, ObjectModeTag, PresenceTag, SchemaTag, StringCheckTag } from "../kind/index.js";
|
|
7
|
+
import { ArrayCheckTag, DateCheckTag, NumberCheckTag, ObjectModeTag, PresenceTag, SchemaTag, StringCheckTag } from "../kind/index.js";
|
|
6
8
|
import { isLiteralValue } from "./literal.js";
|
|
7
|
-
import { includesString, isObjectKeyLookup, isPlainRegExp, isRecord, isStringArray, isUnknownArray } from "./common.js";
|
|
9
|
+
import { includesString, isMissingDataProperty, isObjectKeyLookup, isPlainRegExp, isRecord, isStringArray, isUnknownArray, readOwnDataProperty } from "./common.js";
|
|
8
10
|
/**
|
|
9
|
-
* @brief
|
|
11
|
+
* @brief Validate an unknown value as a TypeSea schema tree.
|
|
12
|
+
* @param value Candidate schema object from a public boundary.
|
|
13
|
+
* @returns True when the complete tree satisfies the internal schema layout.
|
|
14
|
+
* @details This routine is intentionally stricter than normal JavaScript object
|
|
15
|
+
* access: every record and vector must be data-only so later consumers can read
|
|
16
|
+
* fields without invoking user code.
|
|
10
17
|
*/
|
|
11
18
|
export function isSchemaValue(value) {
|
|
12
19
|
return isSchemaValueInner(value, {
|
|
@@ -15,7 +22,12 @@ export function isSchemaValue(value) {
|
|
|
15
22
|
});
|
|
16
23
|
}
|
|
17
24
|
/**
|
|
18
|
-
* @brief
|
|
25
|
+
* @brief Validate one schema node with cycle protection.
|
|
26
|
+
* @details Schema helpers enforce construction-time invariants before values reach
|
|
27
|
+
* validation, compilation, or export.
|
|
28
|
+
* @param value Candidate node.
|
|
29
|
+
* @param state Recursion state shared by the root validation pass.
|
|
30
|
+
* @returns True when this node and its reachable children are well-formed.
|
|
19
31
|
*/
|
|
20
32
|
function isSchemaValueInner(value, state) {
|
|
21
33
|
if (!isRecord(value)) {
|
|
@@ -28,6 +40,10 @@ function isSchemaValueInner(value, state) {
|
|
|
28
40
|
return false;
|
|
29
41
|
}
|
|
30
42
|
state.visiting.add(value);
|
|
43
|
+
/*
|
|
44
|
+
* The node is placed in `visiting` before child traversal so recursive
|
|
45
|
+
* object graphs fail closed instead of creating an infinite walk.
|
|
46
|
+
*/
|
|
31
47
|
const valid = isSchemaRecord(value, state);
|
|
32
48
|
state.visiting.delete(value);
|
|
33
49
|
if (valid) {
|
|
@@ -36,56 +52,98 @@ function isSchemaValueInner(value, state) {
|
|
|
36
52
|
return valid;
|
|
37
53
|
}
|
|
38
54
|
/**
|
|
39
|
-
* @brief
|
|
55
|
+
* @brief Dispatch validation by schema tag.
|
|
56
|
+
* @param value Data-only record already accepted by isRecord.
|
|
57
|
+
* @param state Recursion state for child schemas.
|
|
58
|
+
* @returns True when the tag-specific payload is well-formed.
|
|
59
|
+
* @details Tag and payload fields are read through readOwnDataProperty. This
|
|
60
|
+
* preserves the rule that forged schema prototypes never participate in schema
|
|
61
|
+
* admission.
|
|
40
62
|
*/
|
|
41
63
|
function isSchemaRecord(value, state) {
|
|
42
|
-
|
|
64
|
+
const tag = readOwnDataProperty(value, "tag");
|
|
65
|
+
switch (tag) {
|
|
43
66
|
case SchemaTag.Unknown:
|
|
44
67
|
case SchemaTag.Never:
|
|
45
68
|
case SchemaTag.BigInt:
|
|
46
69
|
case SchemaTag.Symbol:
|
|
47
70
|
case SchemaTag.Boolean:
|
|
48
71
|
return true;
|
|
72
|
+
case SchemaTag.Date:
|
|
73
|
+
return isDateChecks(readOwnDataProperty(value, "checks"));
|
|
49
74
|
case SchemaTag.String:
|
|
50
|
-
return isStringChecks(value
|
|
75
|
+
return isStringChecks(readOwnDataProperty(value, "checks"));
|
|
51
76
|
case SchemaTag.Number:
|
|
52
|
-
return isNumberChecks(value
|
|
53
|
-
case SchemaTag.Literal:
|
|
54
|
-
|
|
77
|
+
return isNumberChecks(readOwnDataProperty(value, "checks"));
|
|
78
|
+
case SchemaTag.Literal: {
|
|
79
|
+
const literal = readOwnDataProperty(value, "value");
|
|
80
|
+
/*
|
|
81
|
+
* `undefined` is a legal literal payload. The sentinel distinguishes
|
|
82
|
+
* a missing `value` field from a stored undefined literal.
|
|
83
|
+
*/
|
|
84
|
+
return !isMissingDataProperty(literal) && isLiteralValue(literal);
|
|
85
|
+
}
|
|
55
86
|
case SchemaTag.Array:
|
|
56
|
-
return isSchemaValueInner(value
|
|
87
|
+
return isSchemaValueInner(readOwnDataProperty(value, "item"), state) &&
|
|
88
|
+
isArrayChecks(readOwnDataProperty(value, "checks"));
|
|
57
89
|
case SchemaTag.Tuple:
|
|
58
|
-
return isSchemaArray(value
|
|
90
|
+
return isSchemaArray(readOwnDataProperty(value, "items"), state) &&
|
|
91
|
+
isOptionalSchemaValue(readOwnDataProperty(value, "rest"), state);
|
|
59
92
|
case SchemaTag.Record:
|
|
60
|
-
return isSchemaValueInner(value
|
|
93
|
+
return isSchemaValueInner(readOwnDataProperty(value, "value"), state);
|
|
94
|
+
case SchemaTag.Map:
|
|
95
|
+
return isSchemaValueInner(readOwnDataProperty(value, "key"), state) &&
|
|
96
|
+
isSchemaValueInner(readOwnDataProperty(value, "value"), state);
|
|
97
|
+
case SchemaTag.Set:
|
|
98
|
+
return isSchemaValueInner(readOwnDataProperty(value, "item"), state);
|
|
99
|
+
case SchemaTag.InstanceOf:
|
|
100
|
+
return typeof readOwnDataProperty(value, "constructor") === "function" &&
|
|
101
|
+
typeof readOwnDataProperty(value, "name") === "string";
|
|
102
|
+
case SchemaTag.Property:
|
|
103
|
+
return typeof readOwnDataProperty(value, "key") === "string" &&
|
|
104
|
+
isSchemaValueInner(readOwnDataProperty(value, "base"), state) &&
|
|
105
|
+
isSchemaValueInner(readOwnDataProperty(value, "value"), state);
|
|
61
106
|
case SchemaTag.Object:
|
|
62
107
|
return isObjectSchemaValue(value, state);
|
|
63
108
|
case SchemaTag.Union:
|
|
64
|
-
return isSchemaArray(value
|
|
109
|
+
return isSchemaArray(readOwnDataProperty(value, "options"), state);
|
|
65
110
|
case SchemaTag.Intersection:
|
|
66
|
-
return isSchemaValueInner(value
|
|
67
|
-
isSchemaValueInner(value
|
|
111
|
+
return isSchemaValueInner(readOwnDataProperty(value, "left"), state) &&
|
|
112
|
+
isSchemaValueInner(readOwnDataProperty(value, "right"), state);
|
|
68
113
|
case SchemaTag.Optional:
|
|
69
114
|
case SchemaTag.Undefinedable:
|
|
70
115
|
case SchemaTag.Nullable:
|
|
71
|
-
return isSchemaValueInner(value
|
|
116
|
+
return isSchemaValueInner(readOwnDataProperty(value, "inner"), state);
|
|
72
117
|
case SchemaTag.DiscriminatedUnion:
|
|
73
118
|
return isDiscriminatedUnionSchemaValue(value, state);
|
|
74
119
|
case SchemaTag.Brand:
|
|
75
|
-
return typeof value
|
|
76
|
-
isSchemaValueInner(value
|
|
120
|
+
return typeof readOwnDataProperty(value, "brand") === "string" &&
|
|
121
|
+
isSchemaValueInner(readOwnDataProperty(value, "inner"), state);
|
|
77
122
|
case SchemaTag.Lazy:
|
|
78
|
-
return typeof value
|
|
123
|
+
return typeof readOwnDataProperty(value, "get") === "function";
|
|
79
124
|
case SchemaTag.Refine:
|
|
80
|
-
return typeof value
|
|
81
|
-
typeof value
|
|
82
|
-
isSchemaValueInner(value
|
|
125
|
+
return typeof readOwnDataProperty(value, "name") === "string" &&
|
|
126
|
+
typeof readOwnDataProperty(value, "predicate") === "function" &&
|
|
127
|
+
isSchemaValueInner(readOwnDataProperty(value, "inner"), state);
|
|
83
128
|
default:
|
|
84
129
|
return false;
|
|
85
130
|
}
|
|
86
131
|
}
|
|
87
132
|
/**
|
|
88
|
-
* @brief
|
|
133
|
+
* @brief Validate an optional schema payload.
|
|
134
|
+
* @param value Candidate child schema or undefined.
|
|
135
|
+
* @param state Recursion state for child schemas.
|
|
136
|
+
* @returns True when the value is absent or a valid schema.
|
|
137
|
+
*/
|
|
138
|
+
function isOptionalSchemaValue(value, state) {
|
|
139
|
+
return value === undefined || isSchemaValueInner(value, state);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* @brief Validate the check vector attached to a string schema.
|
|
143
|
+
* @param value Candidate check vector.
|
|
144
|
+
* @returns True when every check is data-only and semantically usable.
|
|
145
|
+
* @details Bounds are constrained at admission so interpreter and codegen do not
|
|
146
|
+
* need to repeat defensive numeric checks in their hot paths.
|
|
89
147
|
*/
|
|
90
148
|
function isStringChecks(value) {
|
|
91
149
|
if (!isUnknownArray(value)) {
|
|
@@ -96,21 +154,33 @@ function isStringChecks(value) {
|
|
|
96
154
|
if (!isRecord(check)) {
|
|
97
155
|
return false;
|
|
98
156
|
}
|
|
99
|
-
switch (check
|
|
157
|
+
switch (readOwnDataProperty(check, "tag")) {
|
|
100
158
|
case StringCheckTag.Min:
|
|
101
159
|
case StringCheckTag.Max: {
|
|
102
|
-
const bound = check
|
|
160
|
+
const bound = readOwnDataProperty(check, "value");
|
|
103
161
|
if (typeof bound !== "number" || !Number.isInteger(bound) || bound < 0) {
|
|
104
162
|
return false;
|
|
105
163
|
}
|
|
106
164
|
break;
|
|
107
165
|
}
|
|
108
166
|
case StringCheckTag.Regex:
|
|
109
|
-
|
|
167
|
+
/*
|
|
168
|
+
* Regex checks carry executable engine state. Only a plain
|
|
169
|
+
* RegExp plus a stable diagnostic name can enter the schema.
|
|
170
|
+
*/
|
|
171
|
+
if (!isPlainRegExp(readOwnDataProperty(check, "regex")) ||
|
|
172
|
+
typeof readOwnDataProperty(check, "name") !== "string") {
|
|
110
173
|
return false;
|
|
111
174
|
}
|
|
112
175
|
break;
|
|
113
176
|
case StringCheckTag.Uuid:
|
|
177
|
+
case StringCheckTag.Email:
|
|
178
|
+
case StringCheckTag.Url:
|
|
179
|
+
case StringCheckTag.IsoDate:
|
|
180
|
+
case StringCheckTag.IsoDateTime:
|
|
181
|
+
case StringCheckTag.Ulid:
|
|
182
|
+
case StringCheckTag.Ipv4:
|
|
183
|
+
case StringCheckTag.Ipv6:
|
|
114
184
|
break;
|
|
115
185
|
default:
|
|
116
186
|
return false;
|
|
@@ -119,7 +189,11 @@ function isStringChecks(value) {
|
|
|
119
189
|
return true;
|
|
120
190
|
}
|
|
121
191
|
/**
|
|
122
|
-
* @brief
|
|
192
|
+
* @brief Validate the check vector attached to a number schema.
|
|
193
|
+
* @details Schema helpers enforce construction-time invariants before values reach
|
|
194
|
+
* validation, compilation, or export.
|
|
195
|
+
* @param value Candidate check vector.
|
|
196
|
+
* @returns True when all numeric bounds are finite and tag-compatible.
|
|
123
197
|
*/
|
|
124
198
|
function isNumberChecks(value) {
|
|
125
199
|
if (!isUnknownArray(value)) {
|
|
@@ -130,17 +204,28 @@ function isNumberChecks(value) {
|
|
|
130
204
|
if (!isRecord(check)) {
|
|
131
205
|
return false;
|
|
132
206
|
}
|
|
133
|
-
switch (check
|
|
207
|
+
switch (readOwnDataProperty(check, "tag")) {
|
|
134
208
|
case NumberCheckTag.Integer:
|
|
135
209
|
break;
|
|
136
210
|
case NumberCheckTag.Gte:
|
|
137
|
-
case NumberCheckTag.Lte:
|
|
138
|
-
|
|
211
|
+
case NumberCheckTag.Lte:
|
|
212
|
+
case NumberCheckTag.Gt:
|
|
213
|
+
case NumberCheckTag.Lt: {
|
|
214
|
+
const bound = readOwnDataProperty(check, "value");
|
|
139
215
|
if (typeof bound !== "number" || !Number.isFinite(bound)) {
|
|
140
216
|
return false;
|
|
141
217
|
}
|
|
142
218
|
break;
|
|
143
219
|
}
|
|
220
|
+
case NumberCheckTag.MultipleOf: {
|
|
221
|
+
const divisor = readOwnDataProperty(check, "value");
|
|
222
|
+
if (typeof divisor !== "number" ||
|
|
223
|
+
!Number.isFinite(divisor) ||
|
|
224
|
+
divisor <= 0) {
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
144
229
|
default:
|
|
145
230
|
return false;
|
|
146
231
|
}
|
|
@@ -148,7 +233,72 @@ function isNumberChecks(value) {
|
|
|
148
233
|
return true;
|
|
149
234
|
}
|
|
150
235
|
/**
|
|
151
|
-
* @brief
|
|
236
|
+
* @brief Validate the check vector attached to a Date schema.
|
|
237
|
+
* @param value Candidate check vector.
|
|
238
|
+
* @returns True when every Date bound is finite epoch milliseconds.
|
|
239
|
+
*/
|
|
240
|
+
function isDateChecks(value) {
|
|
241
|
+
if (!isUnknownArray(value)) {
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
245
|
+
const check = value[index];
|
|
246
|
+
if (!isRecord(check)) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
switch (readOwnDataProperty(check, "tag")) {
|
|
250
|
+
case DateCheckTag.Min:
|
|
251
|
+
case DateCheckTag.Max: {
|
|
252
|
+
const bound = readOwnDataProperty(check, "value");
|
|
253
|
+
if (typeof bound !== "number" || !Number.isFinite(bound)) {
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
default:
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return true;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* @brief Validate the check vector attached to an array schema.
|
|
266
|
+
* @param value Candidate check vector.
|
|
267
|
+
* @returns True when every array length bound is a non-negative integer.
|
|
268
|
+
* @details Array length checks are admitted once at schema construction so
|
|
269
|
+
* interpreters and code generators can emit direct `length` comparisons later.
|
|
270
|
+
*/
|
|
271
|
+
function isArrayChecks(value) {
|
|
272
|
+
if (!isUnknownArray(value)) {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
276
|
+
const check = value[index];
|
|
277
|
+
if (!isRecord(check)) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
switch (readOwnDataProperty(check, "tag")) {
|
|
281
|
+
case ArrayCheckTag.Min:
|
|
282
|
+
case ArrayCheckTag.Max: {
|
|
283
|
+
const bound = readOwnDataProperty(check, "value");
|
|
284
|
+
if (typeof bound !== "number" || !Number.isInteger(bound) || bound < 0) {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
default:
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* @brief Validate a dense vector of child schemas.
|
|
297
|
+
* @details Schema helpers enforce construction-time invariants before values reach
|
|
298
|
+
* validation, compilation, or export.
|
|
299
|
+
* @param value Candidate schema vector.
|
|
300
|
+
* @param state Recursion state shared with the parent node.
|
|
301
|
+
* @returns True when every vector slot is a valid schema.
|
|
152
302
|
*/
|
|
153
303
|
function isSchemaArray(value, state) {
|
|
154
304
|
if (!isUnknownArray(value)) {
|
|
@@ -162,60 +312,98 @@ function isSchemaArray(value, state) {
|
|
|
162
312
|
return true;
|
|
163
313
|
}
|
|
164
314
|
/**
|
|
165
|
-
* @brief
|
|
315
|
+
* @brief Validate object-schema payload invariants.
|
|
316
|
+
* @param value Candidate object schema record.
|
|
317
|
+
* @param state Recursion state for property schemas.
|
|
318
|
+
* @returns True when entries, key order, lookup, and presence metadata agree.
|
|
319
|
+
* @details Object validation depends on three redundant views: ordered entries
|
|
320
|
+
* for stable codegen, ordered keys for strict key checks, and lookup for fast
|
|
321
|
+
* membership. Admission rejects drift between those views.
|
|
166
322
|
*/
|
|
167
323
|
function isObjectSchemaValue(value, state) {
|
|
168
|
-
|
|
169
|
-
|
|
324
|
+
const mode = readOwnDataProperty(value, "mode");
|
|
325
|
+
if (mode !== ObjectModeTag.Passthrough &&
|
|
326
|
+
mode !== ObjectModeTag.Strict) {
|
|
170
327
|
return false;
|
|
171
328
|
}
|
|
172
|
-
const entries = value
|
|
173
|
-
const keys = value
|
|
174
|
-
const keyLookup = value
|
|
329
|
+
const entries = readOwnDataProperty(value, "entries");
|
|
330
|
+
const keys = readOwnDataProperty(value, "keys");
|
|
331
|
+
const keyLookup = readOwnDataProperty(value, "keyLookup");
|
|
332
|
+
const catchall = readOwnDataProperty(value, "catchall");
|
|
175
333
|
if (!isUnknownArray(entries) || !isStringArray(keys) ||
|
|
176
334
|
!isObjectKeyLookup(keyLookup, keys) || entries.length !== keys.length) {
|
|
177
335
|
return false;
|
|
178
336
|
}
|
|
337
|
+
if (catchall !== undefined && !isSchemaValueInner(catchall, state)) {
|
|
338
|
+
return false;
|
|
339
|
+
}
|
|
179
340
|
const seen = [];
|
|
180
341
|
for (let index = 0; index < entries.length; index += 1) {
|
|
181
342
|
const entry = entries[index];
|
|
182
|
-
if (!isRecord(entry)
|
|
183
|
-
typeof entry["key"] !== "string" ||
|
|
184
|
-
entry["key"] !== keys[index] ||
|
|
185
|
-
includesString(seen, entry["key"]) ||
|
|
186
|
-
(entry["presence"] !== PresenceTag.Required &&
|
|
187
|
-
entry["presence"] !== PresenceTag.Optional) ||
|
|
188
|
-
!isSchemaValueInner(entry["schema"], state)) {
|
|
343
|
+
if (!isRecord(entry)) {
|
|
189
344
|
return false;
|
|
190
345
|
}
|
|
191
|
-
|
|
346
|
+
const key = readOwnDataProperty(entry, "key");
|
|
347
|
+
const presence = readOwnDataProperty(entry, "presence");
|
|
348
|
+
const schema = readOwnDataProperty(entry, "schema");
|
|
349
|
+
/*
|
|
350
|
+
* The entry key must match the parallel `keys` slot. That keeps emitted
|
|
351
|
+
* object code deterministic and prevents a lookup table from describing
|
|
352
|
+
* a different shape than the property graph.
|
|
353
|
+
*/
|
|
354
|
+
if (typeof key !== "string" ||
|
|
355
|
+
key !== keys[index] ||
|
|
356
|
+
includesString(seen, key) ||
|
|
357
|
+
(presence !== PresenceTag.Required &&
|
|
358
|
+
presence !== PresenceTag.Optional) ||
|
|
359
|
+
!isSchemaValueInner(schema, state)) {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
seen.push(key);
|
|
192
363
|
}
|
|
193
364
|
return true;
|
|
194
365
|
}
|
|
195
366
|
/**
|
|
196
|
-
* @brief
|
|
367
|
+
* @brief Validate discriminated-union dispatch metadata.
|
|
368
|
+
* @param value Candidate discriminated union record.
|
|
369
|
+
* @param state Recursion state for case schemas.
|
|
370
|
+
* @returns True when each case owns a unique literal and proves the tag field.
|
|
371
|
+
* @details The case schema must require the discriminant literal. Without that
|
|
372
|
+
* proof, dispatch could choose a branch before the branch actually validates the
|
|
373
|
+
* same discriminant field.
|
|
197
374
|
*/
|
|
198
375
|
function isDiscriminatedUnionSchemaValue(value, state) {
|
|
199
|
-
const cases = value
|
|
200
|
-
const key = value
|
|
376
|
+
const cases = readOwnDataProperty(value, "cases");
|
|
377
|
+
const key = readOwnDataProperty(value, "key");
|
|
201
378
|
if (typeof key !== "string" || !isUnknownArray(cases) || cases.length === 0) {
|
|
202
379
|
return false;
|
|
203
380
|
}
|
|
204
381
|
const literals = [];
|
|
205
382
|
for (let index = 0; index < cases.length; index += 1) {
|
|
206
383
|
const unionCase = cases[index];
|
|
207
|
-
if (!isRecord(unionCase)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
384
|
+
if (!isRecord(unionCase)) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
const literal = readOwnDataProperty(unionCase, "literal");
|
|
388
|
+
const schema = readOwnDataProperty(unionCase, "schema");
|
|
389
|
+
if (typeof literal !== "string" ||
|
|
390
|
+
includesString(literals, literal) ||
|
|
391
|
+
!isSchemaValueInner(schema, state) ||
|
|
392
|
+
!caseRequiresDiscriminant(schema, key, literal)) {
|
|
211
393
|
return false;
|
|
212
394
|
}
|
|
213
|
-
literals.push(
|
|
395
|
+
literals.push(literal);
|
|
214
396
|
}
|
|
215
397
|
return true;
|
|
216
398
|
}
|
|
217
399
|
/**
|
|
218
|
-
* @brief case requires discriminant.
|
|
400
|
+
* @brief Prove that one case schema requires the requested discriminant value.
|
|
401
|
+
* @details Schema helpers enforce construction-time invariants before values reach
|
|
402
|
+
* validation, compilation, or export.
|
|
403
|
+
* @param schema Case schema after structural validation.
|
|
404
|
+
* @param key Discriminant property name.
|
|
405
|
+
* @param literal Required literal value for this case.
|
|
406
|
+
* @returns True when an object case contains a required matching literal field.
|
|
219
407
|
*/
|
|
220
408
|
function caseRequiresDiscriminant(schema, key, literal) {
|
|
221
409
|
const objectSchema = unwrapCaseObjectSchema(schema);
|
|
@@ -234,7 +422,12 @@ function caseRequiresDiscriminant(schema, key, literal) {
|
|
|
234
422
|
return false;
|
|
235
423
|
}
|
|
236
424
|
/**
|
|
237
|
-
* @brief
|
|
425
|
+
* @brief Peel transparent wrappers until an object case schema is reached.
|
|
426
|
+
* @param schema Case schema.
|
|
427
|
+
* @returns The object schema used for discriminant proof, or undefined.
|
|
428
|
+
* @details Intersections and transparent wrappers can carry the object branch
|
|
429
|
+
* while still adding extra validation. Lazy and union nodes are not unwrapped
|
|
430
|
+
* here because they do not give a local, branch-stable object proof.
|
|
238
431
|
*/
|
|
239
432
|
function unwrapCaseObjectSchema(schema) {
|
|
240
433
|
switch (schema.tag) {
|
|
@@ -250,7 +443,12 @@ function unwrapCaseObjectSchema(schema) {
|
|
|
250
443
|
}
|
|
251
444
|
}
|
|
252
445
|
/**
|
|
253
|
-
* @brief schema
|
|
446
|
+
* @brief Check whether a schema forces one exact string literal.
|
|
447
|
+
* @details Schema helpers enforce construction-time invariants before values reach
|
|
448
|
+
* validation, compilation, or export.
|
|
449
|
+
* @param schema Property schema.
|
|
450
|
+
* @param literal Required literal value.
|
|
451
|
+
* @returns True when the schema cannot accept a different discriminant value.
|
|
254
452
|
*/
|
|
255
453
|
function schemaRequiresLiteral(schema, literal) {
|
|
256
454
|
switch (schema.tag) {
|