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.
Files changed (301) hide show
  1. package/CHANGELOG.md +85 -6
  2. package/README.md +143 -28
  3. package/dist/adapters/index.d.ts +50 -8
  4. package/dist/adapters/index.d.ts.map +1 -1
  5. package/dist/adapters/index.js +169 -48
  6. package/dist/aot/index.d.ts +19 -3
  7. package/dist/aot/index.d.ts.map +1 -1
  8. package/dist/aot/index.js +115 -17
  9. package/dist/async/index.d.ts +28 -56
  10. package/dist/async/index.d.ts.map +1 -1
  11. package/dist/async/index.js +94 -37
  12. package/dist/builders/composite.d.ts +43 -9
  13. package/dist/builders/composite.d.ts.map +1 -1
  14. package/dist/builders/composite.js +100 -17
  15. package/dist/builders/index.d.ts +8 -5
  16. package/dist/builders/index.d.ts.map +1 -1
  17. package/dist/builders/index.js +7 -4
  18. package/dist/builders/modifier.d.ts +36 -5
  19. package/dist/builders/modifier.d.ts.map +1 -1
  20. package/dist/builders/modifier.js +52 -5
  21. package/dist/builders/object/guard.d.ts +72 -24
  22. package/dist/builders/object/guard.d.ts.map +1 -1
  23. package/dist/builders/object/guard.js +139 -29
  24. package/dist/builders/object/index.d.ts +4 -2
  25. package/dist/builders/object/index.d.ts.map +1 -1
  26. package/dist/builders/object/index.js +3 -1
  27. package/dist/builders/object/schema.d.ts +88 -11
  28. package/dist/builders/object/schema.d.ts.map +1 -1
  29. package/dist/builders/object/schema.js +290 -23
  30. package/dist/builders/object/types.d.ts +20 -31
  31. package/dist/builders/object/types.d.ts.map +1 -1
  32. package/dist/builders/object/types.js +2 -0
  33. package/dist/builders/runtime.d.ts +40 -0
  34. package/dist/builders/runtime.d.ts.map +1 -0
  35. package/dist/builders/runtime.js +150 -0
  36. package/dist/builders/scalar.d.ts +49 -9
  37. package/dist/builders/scalar.d.ts.map +1 -1
  38. package/dist/builders/scalar.js +87 -9
  39. package/dist/builders/table.d.ts +35 -5
  40. package/dist/builders/table.d.ts.map +1 -1
  41. package/dist/builders/table.js +35 -5
  42. package/dist/builders/types.d.ts +20 -4
  43. package/dist/builders/types.d.ts.map +1 -1
  44. package/dist/builders/types.js +2 -0
  45. package/dist/compile/check-composite.d.ts +25 -2
  46. package/dist/compile/check-composite.d.ts.map +1 -1
  47. package/dist/compile/check-composite.js +699 -27
  48. package/dist/compile/check-scalar.d.ts +88 -0
  49. package/dist/compile/check-scalar.d.ts.map +1 -1
  50. package/dist/compile/check-scalar.js +570 -3
  51. package/dist/compile/check.d.ts +12 -0
  52. package/dist/compile/check.d.ts.map +1 -1
  53. package/dist/compile/check.js +62 -3
  54. package/dist/compile/context.d.ts +47 -9
  55. package/dist/compile/context.d.ts.map +1 -1
  56. package/dist/compile/context.js +53 -8
  57. package/dist/compile/first.d.ts +26 -0
  58. package/dist/compile/first.d.ts.map +1 -0
  59. package/dist/compile/first.js +850 -0
  60. package/dist/compile/graph-predicate.d.ts +4 -2
  61. package/dist/compile/graph-predicate.d.ts.map +1 -1
  62. package/dist/compile/graph-predicate.js +2272 -165
  63. package/dist/compile/guard.d.ts +16 -24
  64. package/dist/compile/guard.d.ts.map +1 -1
  65. package/dist/compile/guard.js +202 -72
  66. package/dist/compile/index.d.ts +3 -1
  67. package/dist/compile/index.d.ts.map +1 -1
  68. package/dist/compile/index.js +2 -0
  69. package/dist/compile/issue.d.ts +110 -0
  70. package/dist/compile/issue.d.ts.map +1 -1
  71. package/dist/compile/issue.js +184 -1
  72. package/dist/compile/names.d.ts +12 -2
  73. package/dist/compile/names.d.ts.map +1 -1
  74. package/dist/compile/names.js +19 -3
  75. package/dist/compile/predicate.d.ts +24 -0
  76. package/dist/compile/predicate.d.ts.map +1 -1
  77. package/dist/compile/predicate.js +287 -10
  78. package/dist/compile/runtime.d.ts +100 -13
  79. package/dist/compile/runtime.d.ts.map +1 -1
  80. package/dist/compile/runtime.js +56 -6
  81. package/dist/compile/source.d.ts +10 -2
  82. package/dist/compile/source.d.ts.map +1 -1
  83. package/dist/compile/source.js +385 -26
  84. package/dist/compile/types.d.ts +22 -0
  85. package/dist/compile/types.d.ts.map +1 -1
  86. package/dist/compile/types.js +2 -0
  87. package/dist/decoder/index.d.ts +92 -46
  88. package/dist/decoder/index.d.ts.map +1 -1
  89. package/dist/decoder/index.js +266 -39
  90. package/dist/evaluate/check-composite.d.ts +111 -2
  91. package/dist/evaluate/check-composite.d.ts.map +1 -1
  92. package/dist/evaluate/check-composite.js +343 -8
  93. package/dist/evaluate/check-scalar.d.ts +25 -0
  94. package/dist/evaluate/check-scalar.d.ts.map +1 -1
  95. package/dist/evaluate/check-scalar.js +124 -3
  96. package/dist/evaluate/check.d.ts +7 -0
  97. package/dist/evaluate/check.d.ts.map +1 -1
  98. package/dist/evaluate/check.js +62 -4
  99. package/dist/evaluate/index.d.ts +2 -0
  100. package/dist/evaluate/index.d.ts.map +1 -1
  101. package/dist/evaluate/index.js +2 -0
  102. package/dist/evaluate/issue.d.ts +11 -1
  103. package/dist/evaluate/issue.d.ts.map +1 -1
  104. package/dist/evaluate/issue.js +15 -1
  105. package/dist/evaluate/predicate.d.ts +16 -5
  106. package/dist/evaluate/predicate.d.ts.map +1 -1
  107. package/dist/evaluate/predicate.js +20 -5
  108. package/dist/evaluate/shared.d.ts +78 -13
  109. package/dist/evaluate/shared.d.ts.map +1 -1
  110. package/dist/evaluate/shared.js +101 -8
  111. package/dist/evaluate/state.d.ts +35 -13
  112. package/dist/evaluate/state.d.ts.map +1 -1
  113. package/dist/evaluate/state.js +35 -2
  114. package/dist/guard/array.d.ts +48 -0
  115. package/dist/guard/array.d.ts.map +1 -0
  116. package/dist/guard/array.js +84 -0
  117. package/dist/guard/base.d.ts +111 -31
  118. package/dist/guard/base.d.ts.map +1 -1
  119. package/dist/guard/base.js +165 -32
  120. package/dist/guard/date.d.ts +34 -0
  121. package/dist/guard/date.d.ts.map +1 -0
  122. package/dist/guard/date.js +60 -0
  123. package/dist/guard/error.d.ts +10 -5
  124. package/dist/guard/error.d.ts.map +1 -1
  125. package/dist/guard/error.js +10 -5
  126. package/dist/guard/index.d.ts +4 -0
  127. package/dist/guard/index.d.ts.map +1 -1
  128. package/dist/guard/index.js +4 -0
  129. package/dist/guard/number.d.ts +86 -11
  130. package/dist/guard/number.d.ts.map +1 -1
  131. package/dist/guard/number.js +159 -11
  132. package/dist/guard/props.d.ts +27 -3
  133. package/dist/guard/props.d.ts.map +1 -1
  134. package/dist/guard/props.js +27 -3
  135. package/dist/guard/read.d.ts +115 -10
  136. package/dist/guard/read.d.ts.map +1 -1
  137. package/dist/guard/read.js +185 -10
  138. package/dist/guard/registry.d.ts +12 -2
  139. package/dist/guard/registry.d.ts.map +1 -1
  140. package/dist/guard/registry.js +15 -3
  141. package/dist/guard/string.d.ts +115 -13
  142. package/dist/guard/string.d.ts.map +1 -1
  143. package/dist/guard/string.js +250 -13
  144. package/dist/guard/types.d.ts +110 -40
  145. package/dist/guard/types.d.ts.map +1 -1
  146. package/dist/guard/types.js +2 -0
  147. package/dist/index.d.ts +5 -5
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +4 -4
  150. package/dist/internal/index.d.ts +42 -6
  151. package/dist/internal/index.d.ts.map +1 -1
  152. package/dist/internal/index.js +51 -8
  153. package/dist/ir/builder.d.ts +17 -127
  154. package/dist/ir/builder.d.ts.map +1 -1
  155. package/dist/ir/builder.js +80 -137
  156. package/dist/ir/freeze.d.ts +4 -0
  157. package/dist/ir/freeze.d.ts.map +1 -1
  158. package/dist/ir/freeze.js +66 -0
  159. package/dist/ir/index.d.ts +3 -1
  160. package/dist/ir/index.d.ts.map +1 -1
  161. package/dist/ir/index.js +2 -0
  162. package/dist/ir/regexp.d.ts +2 -0
  163. package/dist/ir/regexp.d.ts.map +1 -1
  164. package/dist/ir/regexp.js +2 -0
  165. package/dist/ir/types.d.ts +94 -56
  166. package/dist/ir/types.d.ts.map +1 -1
  167. package/dist/ir/types.js +2 -0
  168. package/dist/ir/validate.d.ts +8 -1
  169. package/dist/ir/validate.d.ts.map +1 -1
  170. package/dist/ir/validate.js +511 -61
  171. package/dist/issue/index.d.ts +42 -10
  172. package/dist/issue/index.d.ts.map +1 -1
  173. package/dist/issue/index.js +65 -11
  174. package/dist/json-schema/emit-combinator.d.ts +44 -4
  175. package/dist/json-schema/emit-combinator.d.ts.map +1 -1
  176. package/dist/json-schema/emit-combinator.js +44 -4
  177. package/dist/json-schema/emit-composite.d.ts +16 -2
  178. package/dist/json-schema/emit-composite.d.ts.map +1 -1
  179. package/dist/json-schema/emit-composite.js +81 -13
  180. package/dist/json-schema/emit-scalar.d.ts +26 -3
  181. package/dist/json-schema/emit-scalar.d.ts.map +1 -1
  182. package/dist/json-schema/emit-scalar.js +124 -10
  183. package/dist/json-schema/emit-types.d.ts +11 -1
  184. package/dist/json-schema/emit-types.d.ts.map +1 -1
  185. package/dist/json-schema/emit-types.js +2 -0
  186. package/dist/json-schema/emit.d.ts +12 -1
  187. package/dist/json-schema/emit.d.ts.map +1 -1
  188. package/dist/json-schema/emit.js +23 -3
  189. package/dist/json-schema/freeze.d.ts +13 -2
  190. package/dist/json-schema/freeze.d.ts.map +1 -1
  191. package/dist/json-schema/freeze.js +41 -8
  192. package/dist/json-schema/index.d.ts +16 -2
  193. package/dist/json-schema/index.d.ts.map +1 -1
  194. package/dist/json-schema/index.js +23 -3
  195. package/dist/json-schema/issue.d.ts +4 -1
  196. package/dist/json-schema/issue.d.ts.map +1 -1
  197. package/dist/json-schema/issue.js +4 -1
  198. package/dist/json-schema/read.d.ts +24 -3
  199. package/dist/json-schema/read.d.ts.map +1 -1
  200. package/dist/json-schema/read.js +59 -12
  201. package/dist/json-schema/types.d.ts +45 -16
  202. package/dist/json-schema/types.d.ts.map +1 -1
  203. package/dist/json-schema/types.js +2 -0
  204. package/dist/kind/index.d.ts +40 -28
  205. package/dist/kind/index.d.ts.map +1 -1
  206. package/dist/kind/index.js +41 -13
  207. package/dist/lower/index.d.ts +6 -1
  208. package/dist/lower/index.d.ts.map +1 -1
  209. package/dist/lower/index.js +462 -46
  210. package/dist/message/index.d.ts +64 -10
  211. package/dist/message/index.d.ts.map +1 -1
  212. package/dist/message/index.js +155 -17
  213. package/dist/optimize/algebraic.d.ts +54 -0
  214. package/dist/optimize/algebraic.d.ts.map +1 -0
  215. package/dist/optimize/algebraic.js +314 -0
  216. package/dist/optimize/compact.d.ts +8 -1
  217. package/dist/optimize/compact.d.ts.map +1 -1
  218. package/dist/optimize/compact.js +13 -2
  219. package/dist/optimize/domain.d.ts +16 -0
  220. package/dist/optimize/domain.d.ts.map +1 -0
  221. package/dist/optimize/domain.js +619 -0
  222. package/dist/optimize/fold-boolean.d.ts +17 -2
  223. package/dist/optimize/fold-boolean.d.ts.map +1 -1
  224. package/dist/optimize/fold-boolean.js +59 -14
  225. package/dist/optimize/fold-common.d.ts +43 -8
  226. package/dist/optimize/fold-common.d.ts.map +1 -1
  227. package/dist/optimize/fold-common.js +37 -6
  228. package/dist/optimize/fold-constraints.d.ts +33 -0
  229. package/dist/optimize/fold-constraints.d.ts.map +1 -0
  230. package/dist/optimize/fold-constraints.js +484 -0
  231. package/dist/optimize/fold-scalar.d.ts +98 -13
  232. package/dist/optimize/fold-scalar.d.ts.map +1 -1
  233. package/dist/optimize/fold-scalar.js +98 -13
  234. package/dist/optimize/fold.d.ts +8 -1
  235. package/dist/optimize/fold.d.ts.map +1 -1
  236. package/dist/optimize/fold.js +22 -2
  237. package/dist/optimize/index.d.ts +9 -1
  238. package/dist/optimize/index.d.ts.map +1 -1
  239. package/dist/optimize/index.js +18 -3
  240. package/dist/optimize/map-node.d.ts +3 -1
  241. package/dist/optimize/map-node.d.ts.map +1 -1
  242. package/dist/optimize/map-node.js +48 -3
  243. package/dist/optimize/peephole.d.ts +16 -0
  244. package/dist/optimize/peephole.d.ts.map +1 -0
  245. package/dist/optimize/peephole.js +254 -0
  246. package/dist/optimize/remap.d.ts +2 -0
  247. package/dist/optimize/remap.d.ts.map +1 -1
  248. package/dist/optimize/remap.js +2 -0
  249. package/dist/optimize/rewrite.d.ts +13 -8
  250. package/dist/optimize/rewrite.d.ts.map +1 -1
  251. package/dist/optimize/rewrite.js +13 -8
  252. package/dist/plan/cache.d.ts +9 -3
  253. package/dist/plan/cache.d.ts.map +1 -1
  254. package/dist/plan/cache.js +34 -6
  255. package/dist/plan/index.d.ts +2 -0
  256. package/dist/plan/index.d.ts.map +1 -1
  257. package/dist/plan/index.js +2 -0
  258. package/dist/plan/predicate.d.ts +2 -0
  259. package/dist/plan/predicate.d.ts.map +1 -1
  260. package/dist/plan/predicate.js +298 -29
  261. package/dist/plan/schema-predicate.d.ts +6 -0
  262. package/dist/plan/schema-predicate.d.ts.map +1 -1
  263. package/dist/plan/schema-predicate.js +382 -19
  264. package/dist/plan/types.d.ts +2 -0
  265. package/dist/plan/types.d.ts.map +1 -1
  266. package/dist/plan/types.js +2 -0
  267. package/dist/result/index.d.ts +19 -5
  268. package/dist/result/index.d.ts.map +1 -1
  269. package/dist/result/index.js +10 -2
  270. package/dist/schema/common.d.ts +69 -6
  271. package/dist/schema/common.d.ts.map +1 -1
  272. package/dist/schema/common.js +104 -10
  273. package/dist/schema/freeze.d.ts +4 -0
  274. package/dist/schema/freeze.d.ts.map +1 -1
  275. package/dist/schema/freeze.js +40 -0
  276. package/dist/schema/index.d.ts +5 -2
  277. package/dist/schema/index.d.ts.map +1 -1
  278. package/dist/schema/index.js +4 -1
  279. package/dist/schema/lazy.d.ts +4 -0
  280. package/dist/schema/lazy.d.ts.map +1 -1
  281. package/dist/schema/lazy.js +4 -0
  282. package/dist/schema/literal.d.ts +7 -1
  283. package/dist/schema/literal.d.ts.map +1 -1
  284. package/dist/schema/literal.js +7 -1
  285. package/dist/schema/types.d.ts +109 -100
  286. package/dist/schema/types.d.ts.map +1 -1
  287. package/dist/schema/types.js +13 -2
  288. package/dist/schema/undefined.d.ts +17 -0
  289. package/dist/schema/undefined.d.ts.map +1 -0
  290. package/dist/schema/undefined.js +77 -0
  291. package/dist/schema/validate.d.ts +8 -1
  292. package/dist/schema/validate.d.ts.map +1 -1
  293. package/dist/schema/validate.js +255 -57
  294. package/docs/api.md +128 -8
  295. package/docs/assets/benchmark-headline.svg +163 -0
  296. package/docs/engine-notes.md +62 -15
  297. package/docs/index.html +1340 -702
  298. package/docs/ko/api.md +375 -0
  299. package/docs/ko/engine-notes.md +156 -0
  300. package/docs/ko/readme.md +378 -0
  301. package/package.json +66 -65
@@ -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 is schema value.
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 is schema value inner.
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 is schema record.
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
- switch (value["tag"]) {
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["checks"]);
75
+ return isStringChecks(readOwnDataProperty(value, "checks"));
51
76
  case SchemaTag.Number:
52
- return isNumberChecks(value["checks"]);
53
- case SchemaTag.Literal:
54
- return isLiteralValue(value["value"]);
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["item"], state);
87
+ return isSchemaValueInner(readOwnDataProperty(value, "item"), state) &&
88
+ isArrayChecks(readOwnDataProperty(value, "checks"));
57
89
  case SchemaTag.Tuple:
58
- return isSchemaArray(value["items"], state);
90
+ return isSchemaArray(readOwnDataProperty(value, "items"), state) &&
91
+ isOptionalSchemaValue(readOwnDataProperty(value, "rest"), state);
59
92
  case SchemaTag.Record:
60
- return isSchemaValueInner(value["value"], state);
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["options"], state);
109
+ return isSchemaArray(readOwnDataProperty(value, "options"), state);
65
110
  case SchemaTag.Intersection:
66
- return isSchemaValueInner(value["left"], state) &&
67
- isSchemaValueInner(value["right"], state);
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["inner"], state);
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["brand"] === "string" &&
76
- isSchemaValueInner(value["inner"], state);
120
+ return typeof readOwnDataProperty(value, "brand") === "string" &&
121
+ isSchemaValueInner(readOwnDataProperty(value, "inner"), state);
77
122
  case SchemaTag.Lazy:
78
- return typeof value["get"] === "function";
123
+ return typeof readOwnDataProperty(value, "get") === "function";
79
124
  case SchemaTag.Refine:
80
- return typeof value["name"] === "string" &&
81
- typeof value["predicate"] === "function" &&
82
- isSchemaValueInner(value["inner"], state);
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 is string checks.
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["tag"]) {
157
+ switch (readOwnDataProperty(check, "tag")) {
100
158
  case StringCheckTag.Min:
101
159
  case StringCheckTag.Max: {
102
- const bound = check["value"];
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
- if (!isPlainRegExp(check["regex"]) || typeof check["name"] !== "string") {
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 is number checks.
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["tag"]) {
207
+ switch (readOwnDataProperty(check, "tag")) {
134
208
  case NumberCheckTag.Integer:
135
209
  break;
136
210
  case NumberCheckTag.Gte:
137
- case NumberCheckTag.Lte: {
138
- const bound = check["value"];
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 is schema array.
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 is object schema value.
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
- if (value["mode"] !== ObjectModeTag.Passthrough &&
169
- value["mode"] !== ObjectModeTag.Strict) {
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["entries"];
173
- const keys = value["keys"];
174
- const keyLookup = value["keyLookup"];
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
- seen.push(entry["key"]);
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 is discriminated union schema value.
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["cases"];
200
- const key = value["key"];
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) || typeof unionCase["literal"] !== "string" ||
208
- includesString(literals, unionCase["literal"]) ||
209
- !isSchemaValueInner(unionCase["schema"], state) ||
210
- !caseRequiresDiscriminant(unionCase["schema"], key, unionCase["literal"])) {
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(unionCase["literal"]);
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 unwrap case object schema.
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 requires literal.
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) {