typesea 0.2.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 (157) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +45 -11
  3. package/dist/aot/index.d.ts +1 -1
  4. package/dist/aot/index.d.ts.map +1 -1
  5. package/dist/aot/index.js +22 -3
  6. package/dist/builders/composite.d.ts +6 -3
  7. package/dist/builders/composite.d.ts.map +1 -1
  8. package/dist/builders/composite.js +22 -13
  9. package/dist/builders/index.d.ts +6 -5
  10. package/dist/builders/index.d.ts.map +1 -1
  11. package/dist/builders/index.js +5 -4
  12. package/dist/builders/modifier.d.ts +6 -0
  13. package/dist/builders/modifier.d.ts.map +1 -1
  14. package/dist/builders/modifier.js +14 -0
  15. package/dist/builders/object/guard.d.ts +54 -2
  16. package/dist/builders/object/guard.d.ts.map +1 -1
  17. package/dist/builders/object/guard.js +117 -7
  18. package/dist/builders/object/index.d.ts +2 -2
  19. package/dist/builders/object/index.d.ts.map +1 -1
  20. package/dist/builders/object/index.js +1 -1
  21. package/dist/builders/object/schema.d.ts +33 -2
  22. package/dist/builders/object/schema.d.ts.map +1 -1
  23. package/dist/builders/object/schema.js +198 -8
  24. package/dist/builders/object/types.d.ts +15 -0
  25. package/dist/builders/object/types.d.ts.map +1 -1
  26. package/dist/builders/runtime.d.ts +40 -0
  27. package/dist/builders/runtime.d.ts.map +1 -0
  28. package/dist/builders/runtime.js +150 -0
  29. package/dist/builders/scalar.d.ts +20 -1
  30. package/dist/builders/scalar.d.ts.map +1 -1
  31. package/dist/builders/scalar.js +54 -1
  32. package/dist/builders/table.d.ts +31 -5
  33. package/dist/builders/table.d.ts.map +1 -1
  34. package/dist/builders/table.js +31 -5
  35. package/dist/builders/types.d.ts +6 -0
  36. package/dist/builders/types.d.ts.map +1 -1
  37. package/dist/compile/check-composite.d.ts +3 -1
  38. package/dist/compile/check-composite.d.ts.map +1 -1
  39. package/dist/compile/check-composite.js +143 -11
  40. package/dist/compile/check-scalar.d.ts +10 -0
  41. package/dist/compile/check-scalar.d.ts.map +1 -1
  42. package/dist/compile/check-scalar.js +138 -2
  43. package/dist/compile/check.d.ts.map +1 -1
  44. package/dist/compile/check.js +25 -3
  45. package/dist/compile/context.d.ts.map +1 -1
  46. package/dist/compile/context.js +2 -0
  47. package/dist/compile/first.d.ts +26 -0
  48. package/dist/compile/first.d.ts.map +1 -0
  49. package/dist/compile/first.js +850 -0
  50. package/dist/compile/graph-predicate.d.ts.map +1 -1
  51. package/dist/compile/graph-predicate.js +389 -18
  52. package/dist/compile/guard.d.ts +2 -1
  53. package/dist/compile/guard.d.ts.map +1 -1
  54. package/dist/compile/guard.js +54 -8
  55. package/dist/compile/predicate.d.ts.map +1 -1
  56. package/dist/compile/predicate.js +156 -5
  57. package/dist/compile/runtime.d.ts +20 -1
  58. package/dist/compile/runtime.d.ts.map +1 -1
  59. package/dist/compile/runtime.js +31 -0
  60. package/dist/compile/source.d.ts.map +1 -1
  61. package/dist/compile/source.js +27 -3
  62. package/dist/compile/types.d.ts +2 -0
  63. package/dist/compile/types.d.ts.map +1 -1
  64. package/dist/decoder/index.d.ts +60 -0
  65. package/dist/decoder/index.d.ts.map +1 -1
  66. package/dist/decoder/index.js +164 -1
  67. package/dist/evaluate/check-composite.d.ts +52 -2
  68. package/dist/evaluate/check-composite.d.ts.map +1 -1
  69. package/dist/evaluate/check-composite.js +193 -6
  70. package/dist/evaluate/check-scalar.d.ts +9 -0
  71. package/dist/evaluate/check-scalar.d.ts.map +1 -1
  72. package/dist/evaluate/check-scalar.js +92 -3
  73. package/dist/evaluate/check.d.ts.map +1 -1
  74. package/dist/evaluate/check.js +19 -4
  75. package/dist/evaluate/shared.d.ts +19 -0
  76. package/dist/evaluate/shared.d.ts.map +1 -1
  77. package/dist/evaluate/shared.js +35 -0
  78. package/dist/guard/array.d.ts +48 -0
  79. package/dist/guard/array.d.ts.map +1 -0
  80. package/dist/guard/array.js +84 -0
  81. package/dist/guard/base.d.ts +32 -2
  82. package/dist/guard/base.d.ts.map +1 -1
  83. package/dist/guard/base.js +74 -3
  84. package/dist/guard/date.d.ts +34 -0
  85. package/dist/guard/date.d.ts.map +1 -0
  86. package/dist/guard/date.js +60 -0
  87. package/dist/guard/index.d.ts +2 -0
  88. package/dist/guard/index.d.ts.map +1 -1
  89. package/dist/guard/index.js +2 -0
  90. package/dist/guard/number.d.ts +60 -0
  91. package/dist/guard/number.d.ts.map +1 -1
  92. package/dist/guard/number.js +129 -0
  93. package/dist/guard/read.d.ts +53 -1
  94. package/dist/guard/read.d.ts.map +1 -1
  95. package/dist/guard/read.js +102 -0
  96. package/dist/guard/string.d.ts +82 -0
  97. package/dist/guard/string.d.ts.map +1 -1
  98. package/dist/guard/string.js +213 -0
  99. package/dist/guard/types.d.ts +18 -0
  100. package/dist/guard/types.d.ts.map +1 -1
  101. package/dist/index.d.ts +4 -4
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +4 -4
  104. package/dist/ir/builder.d.ts +3 -3
  105. package/dist/ir/builder.d.ts.map +1 -1
  106. package/dist/ir/builder.js +5 -2
  107. package/dist/ir/freeze.js +7 -0
  108. package/dist/ir/types.d.ts +4 -1
  109. package/dist/ir/types.d.ts.map +1 -1
  110. package/dist/ir/validate.d.ts.map +1 -1
  111. package/dist/ir/validate.js +35 -1
  112. package/dist/issue/index.d.ts +1 -1
  113. package/dist/issue/index.d.ts.map +1 -1
  114. package/dist/issue/index.js +4 -0
  115. package/dist/json-schema/emit-composite.d.ts +6 -2
  116. package/dist/json-schema/emit-composite.d.ts.map +1 -1
  117. package/dist/json-schema/emit-composite.js +66 -12
  118. package/dist/json-schema/emit-scalar.d.ts.map +1 -1
  119. package/dist/json-schema/emit-scalar.js +54 -1
  120. package/dist/json-schema/emit.d.ts.map +1 -1
  121. package/dist/json-schema/emit.js +11 -2
  122. package/dist/json-schema/types.d.ts +7 -1
  123. package/dist/json-schema/types.d.ts.map +1 -1
  124. package/dist/kind/index.d.ts +25 -0
  125. package/dist/kind/index.d.ts.map +1 -1
  126. package/dist/kind/index.js +26 -3
  127. package/dist/lower/index.d.ts.map +1 -1
  128. package/dist/lower/index.js +52 -3
  129. package/dist/message/index.d.ts +18 -0
  130. package/dist/message/index.d.ts.map +1 -1
  131. package/dist/message/index.js +67 -0
  132. package/dist/optimize/domain.js +6 -2
  133. package/dist/optimize/map-node.d.ts.map +1 -1
  134. package/dist/optimize/map-node.js +3 -0
  135. package/dist/plan/cache.js +13 -1
  136. package/dist/plan/predicate.d.ts.map +1 -1
  137. package/dist/plan/predicate.js +33 -3
  138. package/dist/plan/schema-predicate.d.ts.map +1 -1
  139. package/dist/plan/schema-predicate.js +267 -8
  140. package/dist/schema/freeze.js +22 -0
  141. package/dist/schema/index.d.ts +2 -2
  142. package/dist/schema/index.d.ts.map +1 -1
  143. package/dist/schema/index.js +1 -1
  144. package/dist/schema/types.d.ts +89 -4
  145. package/dist/schema/types.d.ts.map +1 -1
  146. package/dist/schema/types.js +8 -1
  147. package/dist/schema/undefined.d.ts.map +1 -1
  148. package/dist/schema/undefined.js +5 -0
  149. package/dist/schema/validate.d.ts.map +1 -1
  150. package/dist/schema/validate.js +111 -4
  151. package/docs/api.md +71 -8
  152. package/docs/engine-notes.md +4 -0
  153. package/docs/index.html +1340 -722
  154. package/docs/ko/api.md +375 -0
  155. package/docs/ko/engine-notes.md +156 -0
  156. package/docs/ko/readme.md +378 -0
  157. package/package.json +3 -2
@@ -4,7 +4,7 @@
4
4
  * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
5
5
  * stable across runtime and AOT emission.
6
6
  */
7
- import { ObjectModeTag, PresenceTag, SchemaTag } from "../kind/index.js";
7
+ import { ArrayCheckTag, ObjectModeTag, PresenceTag, SchemaTag } from "../kind/index.js";
8
8
  import { schemaCanAcceptUndefined } from "../schema/index.js";
9
9
  import { pushLiteral, stringRef } from "./context.js";
10
10
  import { emitIssue, emitIssueAtSegment, emitIssueAtTwoSegments, emitIssueExprAtSegment } from "./issue.js";
@@ -22,10 +22,11 @@ import { stringLiteral } from "./names.js";
22
22
  * @param emitChild Fallback emitter for non-leaf child validators.
23
23
  * @returns JavaScript source for array diagnostics.
24
24
  */
25
- export function emitArrayCheck(item, value, path, issues, context, emitChild) {
25
+ export function emitArrayCheck(schema, value, path, issues, context, emitChild) {
26
26
  if (isUnsafeMode(context)) {
27
- return emitUnsafeArrayCheck(item, value, path, issues, context, emitChild);
27
+ return emitUnsafeArrayCheck(schema, value, path, issues, context, emitChild);
28
28
  }
29
+ const item = schema.item;
29
30
  const itemValue = "av";
30
31
  const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, "i", issues, context);
31
32
  const missingLeaf = itemLeaf === undefined
@@ -53,6 +54,7 @@ export function emitArrayCheck(item, value, path, issues, context, emitChild) {
53
54
  */
54
55
  return [
55
56
  `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_array", "array", `a(${value})`)}return;}`,
57
+ emitArrayLengthIssues(schema, value, path, issues),
56
58
  `const xs=Object.getOwnPropertyNames(${value});`,
57
59
  "for(let xi=0;xi<xs.length;xi+=1){",
58
60
  "const key=xs[xi];",
@@ -65,6 +67,7 @@ export function emitArrayCheck(item, value, path, issues, context, emitChild) {
65
67
  }
66
68
  return [
67
69
  `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_array", "array", `a(${value})`)}return;}`,
70
+ emitArrayLengthIssues(schema, value, path, issues),
68
71
  `for(let i=0;i<${value}.length;i+=1){`,
69
72
  `const d=gp(${value},i);`,
70
73
  `if(d===undefined){${missingCheck}}else if(!h.call(d,"value")){${emitIssueAtSegment(issues, path, "i", "expected_array", "data property", stringLiteral("accessor"))}}else{${presentCheck}}`,
@@ -118,7 +121,8 @@ export function emitTupleCheck(items, value, path, issues, context, emitChild) {
118
121
  * @brief Execute emit unsafe array check.
119
122
  * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
120
123
  */
121
- function emitUnsafeArrayCheck(item, value, path, issues, context, emitChild) {
124
+ function emitUnsafeArrayCheck(schema, value, path, issues, context, emitChild) {
125
+ const item = schema.item;
122
126
  const itemValue = "av";
123
127
  const itemLeaf = emitLeafCheckAtSegment(item, itemValue, path, "i", issues, context);
124
128
  let itemCheck;
@@ -132,11 +136,67 @@ function emitUnsafeArrayCheck(item, value, path, issues, context, emitChild) {
132
136
  const parts = [
133
137
  `if(!Array.isArray(${value})){${emitIssue(issues, path, "expected_array", "array", `a(${value})`)}return;}`
134
138
  ];
139
+ parts.push(emitArrayLengthIssues(schema, value, path, issues));
135
140
  if (itemCheck !== "") {
136
141
  parts.push(`for(let i=0;i<${value}.length;i+=1){`, `const ${itemValue}=${value}[i];`, itemCheck, "}");
137
142
  }
138
143
  return parts.join("");
139
144
  }
145
+ /**
146
+ * @brief Emit root-level array length diagnostics.
147
+ * @param schema Array schema with normalized checks.
148
+ * @param value Generated expression for the candidate array.
149
+ * @param path Generated expression for the current diagnostic path.
150
+ * @param issues Generated expression for the issue buffer.
151
+ * @returns JavaScript source that appends zero or more length issues.
152
+ */
153
+ function emitArrayLengthIssues(schema, value, path, issues) {
154
+ const chunks = [];
155
+ const checks = schema.checks;
156
+ for (let index = 0; index < checks.length; index += 1) {
157
+ const check = checks[index];
158
+ if (check === undefined) {
159
+ continue;
160
+ }
161
+ switch (check.tag) {
162
+ case ArrayCheckTag.Min:
163
+ chunks.push(`if(${value}.length<${String(check.value)}){${emitIssue(issues, path, "expected_min_length", `length >= ${String(check.value)}`, `"length "+String(${value}.length)`)}}`);
164
+ break;
165
+ case ArrayCheckTag.Max:
166
+ chunks.push(`if(${value}.length>${String(check.value)}){${emitIssue(issues, path, "expected_max_length", `length <= ${String(check.value)}`, `"length "+String(${value}.length)`)}}`);
167
+ break;
168
+ }
169
+ }
170
+ return chunks.join("");
171
+ }
172
+ /**
173
+ * @brief Emit one-segment array length diagnostics.
174
+ * @param schema Array schema with normalized checks.
175
+ * @param value Generated expression for the candidate array.
176
+ * @param path Generated expression for the current diagnostic path.
177
+ * @param segmentExpression Generated path segment for the array field.
178
+ * @param issues Generated expression for the issue buffer.
179
+ * @returns JavaScript source that appends zero or more length issues.
180
+ */
181
+ function emitArrayLengthIssuesAtSegment(schema, value, path, segmentExpression, issues) {
182
+ const chunks = [];
183
+ const checks = schema.checks;
184
+ for (let index = 0; index < checks.length; index += 1) {
185
+ const check = checks[index];
186
+ if (check === undefined) {
187
+ continue;
188
+ }
189
+ switch (check.tag) {
190
+ case ArrayCheckTag.Min:
191
+ chunks.push(`if(${value}.length<${String(check.value)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_min_length", `length >= ${String(check.value)}`, `"length "+String(${value}.length)`)}}`);
192
+ break;
193
+ case ArrayCheckTag.Max:
194
+ chunks.push(`if(${value}.length>${String(check.value)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_max_length", `length <= ${String(check.value)}`, `"length "+String(${value}.length)`)}}`);
195
+ break;
196
+ }
197
+ }
198
+ return chunks.join("");
199
+ }
140
200
  /**
141
201
  * @brief Execute emit unsafe tuple check.
142
202
  * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
@@ -181,10 +241,11 @@ function emitUnsafeTupleCheck(items, value, path, issues, context, emitChild) {
181
241
  * @param context Shared code-generation context.
182
242
  * @returns JavaScript source, or undefined when the caller must fall back.
183
243
  */
184
- function emitArrayCheckAtSegment(item, value, path, segmentExpression, issues, context) {
244
+ function emitArrayCheckAtSegment(schema, value, path, segmentExpression, issues, context) {
185
245
  if (isUnsafeMode(context)) {
186
- return emitUnsafeArrayCheckAtSegment(item, value, path, segmentExpression, issues, context);
246
+ return emitUnsafeArrayCheckAtSegment(schema, value, path, segmentExpression, issues, context);
187
247
  }
248
+ const item = schema.item;
188
249
  const itemValue = "av";
189
250
  const itemLeaf = emitLeafCheckAtTwoSegments(item, itemValue, path, segmentExpression, "i", issues, context);
190
251
  const missingLeaf = itemLeaf === undefined
@@ -203,6 +264,7 @@ function emitArrayCheckAtSegment(item, value, path, segmentExpression, issues, c
203
264
  */
204
265
  return [
205
266
  `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_array", "array", `a(${value})`)}}else{`,
267
+ emitArrayLengthIssuesAtSegment(schema, value, path, segmentExpression, issues),
206
268
  `const xs=Object.getOwnPropertyNames(${value});`,
207
269
  "for(let xi=0;xi<xs.length;xi+=1){",
208
270
  "const key=xs[xi];",
@@ -216,6 +278,7 @@ function emitArrayCheckAtSegment(item, value, path, segmentExpression, issues, c
216
278
  }
217
279
  return [
218
280
  `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_array", "array", `a(${value})`)}}else{`,
281
+ emitArrayLengthIssuesAtSegment(schema, value, path, segmentExpression, issues),
219
282
  `for(let i=0;i<${value}.length;i+=1){`,
220
283
  `const vd=gp(${value},i);`,
221
284
  `if(vd===undefined){${missingLeaf}}else if(!h.call(vd,"value")){${emitIssueAtTwoSegments(issues, path, segmentExpression, "i", "expected_array", "data property", stringLiteral("accessor"))}}else{${presentCheck}}`,
@@ -263,7 +326,8 @@ function emitTupleCheckAtSegment(items, value, path, segmentExpression, issues,
263
326
  * @brief Execute emit unsafe array check at segment.
264
327
  * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
265
328
  */
266
- function emitUnsafeArrayCheckAtSegment(item, value, path, segmentExpression, issues, context) {
329
+ function emitUnsafeArrayCheckAtSegment(schema, value, path, segmentExpression, issues, context) {
330
+ const item = schema.item;
267
331
  const itemLeaf = emitLeafCheckAtTwoSegments(item, "av", path, segmentExpression, "i", issues, context);
268
332
  if (itemLeaf === undefined) {
269
333
  return undefined;
@@ -271,9 +335,11 @@ function emitUnsafeArrayCheckAtSegment(item, value, path, segmentExpression, iss
271
335
  const parts = [
272
336
  `if(!Array.isArray(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_array", "array", `a(${value})`)}}`
273
337
  ];
338
+ parts.push("else{", emitArrayLengthIssuesAtSegment(schema, value, path, segmentExpression, issues));
274
339
  if (itemLeaf !== "") {
275
- parts.push("else{", `for(let i=0;i<${value}.length;i+=1){`, `const av=${value}[i];`, itemLeaf, "}", "}");
340
+ parts.push(`for(let i=0;i<${value}.length;i+=1){`, `const av=${value}[i];`, itemLeaf, "}");
276
341
  }
342
+ parts.push("}");
277
343
  return parts.join("");
278
344
  }
279
345
  /**
@@ -441,11 +507,50 @@ export function emitObjectCheck(schema, value, path, issues, context, emitChild)
441
507
  parts.push(`if(h.call(${value},${key})){const d=gp(${value},${key});if(d===undefined||!h.call(d,"value")){${emitIssueAtSegment(issues, path, key, "expected_object", "data property", stringLiteral("accessor"))}}else{${presentCheck}}}`);
442
508
  }
443
509
  }
444
- if (schema.mode === ObjectModeTag.Strict) {
510
+ if (schema.catchall !== undefined) {
511
+ parts.push(emitObjectCatchallCheck(schema, value, path, issues, context, emitChild));
512
+ }
513
+ else if (schema.mode === ObjectModeTag.Strict) {
445
514
  parts.push(`const xs=Object.getOwnPropertyNames(${value});const xn=xs.length;for(let i=0;i<xn;i+=1){const key=xs[i];if(!(${safeKeyMembershipExpression("key", keyExpressions)})){${emitIssueAtSegment(issues, path, "key", "unrecognized_key", "known key", stringLiteral("extra key"))}}}const ys=Object.getOwnPropertySymbols(${value});const yn=ys.length;for(let i=0;i<yn;i+=1){const key=ys[i];if(key!==undefined){${emitIssueAtSegment(issues, path, "String(key)", "unrecognized_key", "known key", stringLiteral("extra key"))}}}`);
446
515
  }
447
516
  return parts.join("");
448
517
  }
518
+ /**
519
+ * @brief Emit diagnostic collection for object catchall keys.
520
+ */
521
+ function emitObjectCatchallCheck(schema, value, path, issues, context, emitChild) {
522
+ const catchall = schema.catchall;
523
+ if (catchall === undefined) {
524
+ return "";
525
+ }
526
+ const child = emitChild(catchall, context);
527
+ const membership = safeKeyMembershipExpression("key", objectKeyExpressions(schema, context));
528
+ return [
529
+ `const cx=Reflect.ownKeys(${value});`,
530
+ "const cn=cx.length;",
531
+ "for(let ci=0;ci<cn;ci+=1){",
532
+ "const key=cx[ci];",
533
+ `if(typeof key==="string"&&(${membership}))continue;`,
534
+ "const pk=typeof key===\"string\"?key:String(key);",
535
+ `const cd=gp(${value},key);`,
536
+ `if(cd===undefined||!h.call(cd,"value")){${emitIssueAtSegment(issues, path, "pk", "expected_object", "data property", stringLiteral("accessor"))}}else{`,
537
+ `${path}.push(pk);${child}(cd.value,${path},${issues});${path}.pop();`,
538
+ "}}"
539
+ ].join("");
540
+ }
541
+ /**
542
+ * @brief Convert object schema keys into side-table source expressions.
543
+ */
544
+ function objectKeyExpressions(schema, context) {
545
+ const keys = new Array(schema.keys.length);
546
+ for (let index = 0; index < schema.keys.length; index += 1) {
547
+ const key = schema.keys[index];
548
+ if (key !== undefined) {
549
+ keys[index] = stringRef(context, key);
550
+ }
551
+ }
552
+ return keys;
553
+ }
449
554
  /**
450
555
  * @brief Execute emit unsafe object check.
451
556
  * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
@@ -475,7 +580,10 @@ function emitUnsafeObjectCheck(schema, value, path, issues, context, emitChild)
475
580
  }
476
581
  parts.push("}");
477
582
  }
478
- if (schema.mode === ObjectModeTag.Strict && !isUncheckedMode(context)) {
583
+ if (schema.catchall !== undefined) {
584
+ parts.push(emitUnsafeObjectCatchallCheck(schema, value, path, issues, context, emitChild));
585
+ }
586
+ else if (schema.mode === ObjectModeTag.Strict && !isUncheckedMode(context)) {
479
587
  const keys = new Array(schema.entries.length);
480
588
  for (let index = 0; index < schema.entries.length; index += 1) {
481
589
  const entry = schema.entries[index];
@@ -487,6 +595,27 @@ function emitUnsafeObjectCheck(schema, value, path, issues, context, emitChild)
487
595
  }
488
596
  return parts.join("");
489
597
  }
598
+ /**
599
+ * @brief Emit unsafe diagnostic collection for object catchall keys.
600
+ */
601
+ function emitUnsafeObjectCatchallCheck(schema, value, path, issues, context, emitChild) {
602
+ const catchall = schema.catchall;
603
+ if (catchall === undefined) {
604
+ return "";
605
+ }
606
+ const child = emitChild(catchall, context);
607
+ const membership = unsafeKeyMembershipExpression("key", schema.keys);
608
+ return [
609
+ `const cx=Reflect.ownKeys(${value});`,
610
+ "const cn=cx.length;",
611
+ "for(let ci=0;ci<cn;ci+=1){",
612
+ "const key=cx[ci];",
613
+ `if(typeof key==="string"&&(${membership}))continue;`,
614
+ "const pk=typeof key===\"string\"?key:String(key);",
615
+ `${path}.push(pk);${child}(${value}[key],${path},${issues});${path}.pop();`,
616
+ "}"
617
+ ].join("");
618
+ }
490
619
  /**
491
620
  * @brief Execute emit object field check.
492
621
  * @details Code generation helpers keep emitted JavaScript shape stable across runtime and AOT paths.
@@ -510,8 +639,11 @@ function emitObjectFieldCheck(schema, value, path, segmentExpression, issues, co
510
639
  function emitCompositeCheckAtSegment(schema, value, path, segmentExpression, issues, context) {
511
640
  switch (schema.tag) {
512
641
  case SchemaTag.Array:
513
- return emitArrayCheckAtSegment(schema.item, value, path, segmentExpression, issues, context);
642
+ return emitArrayCheckAtSegment(schema, value, path, segmentExpression, issues, context);
514
643
  case SchemaTag.Tuple:
644
+ if (schema.rest !== undefined) {
645
+ return undefined;
646
+ }
515
647
  return emitTupleCheckAtSegment(schema.items, value, path, segmentExpression, issues, context);
516
648
  case SchemaTag.Record:
517
649
  return emitRecordCheckAtSegment(schema.value, value, path, segmentExpression, issues, context);
@@ -21,6 +21,16 @@ import type { EmitContext } from "./types.js";
21
21
  export declare function emitStringCheck(schema: Extract<Schema, {
22
22
  readonly tag: typeof SchemaTag.String;
23
23
  }>, value: string, path: string, issues: string, context: EmitContext): string;
24
+ /**
25
+ * @brief Emit Date diagnostics.
26
+ * @param value Generated expression for the candidate value.
27
+ * @param path Generated expression for the current diagnostic path.
28
+ * @param issues Generated expression for the issue buffer.
29
+ * @returns JavaScript source for root Date diagnostics.
30
+ */
31
+ export declare function emitDateCheck(schema: Extract<Schema, {
32
+ readonly tag: typeof SchemaTag.Date;
33
+ }>, value: string, path: string, issues: string): string;
24
34
  /**
25
35
  * @brief emit leaf check at one appended path segment.
26
36
  * @details This path is used by object-field diagnostics to avoid building a
@@ -1 +1 @@
1
- {"version":3,"file":"check-scalar.d.ts","sourceRoot":"","sources":["../../src/compile/check-scalar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAEH,SAAS,EAEZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEH,KAAK,YAAY,EACjB,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAe5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC3B,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,SAAS,CAAC,MAAM,CAAA;CAAE,CAAC,EAClE,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,CAgDR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CAkFpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAC3C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CAqEpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,sBAAsB,EAAE,MAAM,EAC9B,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CAsFpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mCAAmC,CAC/C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,sBAAsB,EAAE,MAAM,EAC9B,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CA4EpB;AA4MD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC3B,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,SAAS,CAAC,MAAM,CAAA;CAAE,CAAC,EAClE,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACf,MAAM,CAmDR;AA+KD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,CAaR"}
1
+ {"version":3,"file":"check-scalar.d.ts","sourceRoot":"","sources":["../../src/compile/check-scalar.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAGH,SAAS,EAEZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EASH,KAAK,YAAY,EACjB,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAe5B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC3B,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,SAAS,CAAC,MAAM,CAAA;CAAE,CAAC,EAClE,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,CAqER;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,SAAS,CAAC,IAAI,CAAA;CAAE,CAAC,EAChE,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACf,MAAM,CAgDR;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CA8FpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,+BAA+B,CAC3C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,iBAAiB,EAAE,MAAM,EACzB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CA8EpB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACtC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,sBAAsB,EAAE,MAAM,EAC9B,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CAmGpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mCAAmC,CAC/C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,sBAAsB,EAAE,MAAM,EAC9B,uBAAuB,EAAE,MAAM,EAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,GAAG,SAAS,CAsFpB;AA6WD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC3B,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,SAAS,CAAC,MAAM,CAAA;CAAE,CAAC,EAClE,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACf,MAAM,CA8ER;AA8OD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,WAAW,GACrB,MAAM,CAaR"}
@@ -4,8 +4,8 @@
4
4
  * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
5
5
  * stable across runtime and AOT emission.
6
6
  */
7
- import { NumberCheckTag, SchemaTag, StringCheckTag } from "../kind/index.js";
8
- import { UUID_PATTERN } from "../schema/index.js";
7
+ import { DateCheckTag, NumberCheckTag, SchemaTag, StringCheckTag } from "../kind/index.js";
8
+ import { EMAIL_PATTERN, IPV4_PATTERN, IPV6_PATTERN, ISO_DATETIME_PATTERN, ISO_DATE_PATTERN, ULID_PATTERN, URL_PATTERN, UUID_PATTERN } from "../schema/index.js";
9
9
  import { pushLiteral } from "./context.js";
10
10
  import { emitIssue, emitIssueAtSegment, emitIssueAtTwoSegments, emitIssueExpr, emitIssueExprAtSegment, emitIssueExprAtTwoSegments, emitPatternIssueAtSegment, emitPatternIssueAtTwoSegments, emitPatternIssue } from "./issue.js";
11
11
  import { stringLiteral } from "./names.js";
@@ -48,10 +48,63 @@ export function emitStringCheck(schema, value, path, issues, context) {
48
48
  case StringCheckTag.Uuid:
49
49
  parts.push(emitPatternIssue(value, path, issues, UUID_PATTERN, "uuid", context));
50
50
  break;
51
+ case StringCheckTag.Email:
52
+ parts.push(emitPatternIssue(value, path, issues, EMAIL_PATTERN, "email", context));
53
+ break;
54
+ case StringCheckTag.Url:
55
+ parts.push(emitPatternIssue(value, path, issues, URL_PATTERN, "url", context));
56
+ break;
57
+ case StringCheckTag.IsoDate:
58
+ parts.push(emitPatternIssue(value, path, issues, ISO_DATE_PATTERN, "iso_date", context));
59
+ break;
60
+ case StringCheckTag.IsoDateTime:
61
+ parts.push(emitPatternIssue(value, path, issues, ISO_DATETIME_PATTERN, "iso_datetime", context));
62
+ break;
63
+ case StringCheckTag.Ulid:
64
+ parts.push(emitPatternIssue(value, path, issues, ULID_PATTERN, "ulid", context));
65
+ break;
66
+ case StringCheckTag.Ipv4:
67
+ parts.push(emitPatternIssue(value, path, issues, IPV4_PATTERN, "ipv4", context));
68
+ break;
69
+ case StringCheckTag.Ipv6:
70
+ parts.push(emitPatternIssue(value, path, issues, IPV6_PATTERN, "ipv6", context));
71
+ break;
51
72
  }
52
73
  }
53
74
  return parts.join("");
54
75
  }
76
+ /**
77
+ * @brief Emit Date diagnostics.
78
+ * @param value Generated expression for the candidate value.
79
+ * @param path Generated expression for the current diagnostic path.
80
+ * @param issues Generated expression for the issue buffer.
81
+ * @returns JavaScript source for root Date diagnostics.
82
+ */
83
+ export function emitDateCheck(schema, value, path, issues) {
84
+ const invalid = `!dg(${value})`;
85
+ const checks = schema.checks;
86
+ if (checks.length === 0) {
87
+ return `if(${invalid}){${emitIssue(issues, path, "expected_date", "valid Date", `a(${value})`)}}`;
88
+ }
89
+ const parts = [`if(${invalid}){${emitIssue(issues, path, "expected_date", "valid Date", `a(${value})`)}}else{`];
90
+ for (let index = 0; index < checks.length; index += 1) {
91
+ const check = checks[index];
92
+ if (check === undefined) {
93
+ continue;
94
+ }
95
+ const actual = `new Date(dt(${value})).toISOString()`;
96
+ switch (check.tag) {
97
+ case DateCheckTag.Min:
98
+ parts.push(`if(dt(${value})<${String(check.value)}){${emitIssue(issues, path, "expected_gte", `>= ${new Date(check.value).toISOString()}`, actual)}}`);
99
+ break;
100
+ case DateCheckTag.Max:
101
+ parts.push(`if(dt(${value})>${String(check.value)}){${emitIssue(issues, path, "expected_lte", `<= ${new Date(check.value).toISOString()}`, actual)}}`);
102
+ break;
103
+ }
104
+ }
105
+ parts.push("}");
106
+ return parts.join("");
107
+ }
55
108
  /**
56
109
  * @brief emit leaf check at one appended path segment.
57
110
  * @details This path is used by object-field diagnostics to avoid building a
@@ -74,6 +127,11 @@ export function emitLeafCheckAtSegment(schema, value, path, segmentExpression, i
74
127
  return emitStringCheckAtSegment(schema, value, path, segmentExpression, issues, context);
75
128
  case SchemaTag.Number:
76
129
  return emitNumberCheckAtSegment(schema, value, path, segmentExpression, issues);
130
+ case SchemaTag.Date:
131
+ if (schema.checks.length !== 0) {
132
+ return undefined;
133
+ }
134
+ return `if(!dg(${value})){${emitIssueAtSegment(issues, path, segmentExpression, "expected_date", "valid Date", `a(${value})`)}}`;
77
135
  case SchemaTag.BigInt:
78
136
  return `if(typeof ${value}!=="bigint"){${emitIssueAtSegment(issues, path, segmentExpression, "expected_bigint", "bigint", `a(${value})`)}}`;
79
137
  case SchemaTag.Symbol:
@@ -114,6 +172,8 @@ export function emitUndefinedLeafCheckAtSegment(schema, path, segmentExpression,
114
172
  return emitIssueAtSegment(issues, path, segmentExpression, "expected_string", "string", stringLiteral("undefined"));
115
173
  case SchemaTag.Number:
116
174
  return emitIssueAtSegment(issues, path, segmentExpression, "expected_number", "number", stringLiteral("undefined"));
175
+ case SchemaTag.Date:
176
+ return emitIssueAtSegment(issues, path, segmentExpression, "expected_date", "valid Date", stringLiteral("undefined"));
117
177
  case SchemaTag.BigInt:
118
178
  return emitIssueAtSegment(issues, path, segmentExpression, "expected_bigint", "bigint", stringLiteral("undefined"));
119
179
  case SchemaTag.Symbol:
@@ -149,6 +209,11 @@ export function emitLeafCheckAtTwoSegments(schema, value, path, firstSegmentExpr
149
209
  return emitStringCheckAtTwoSegments(schema, value, path, firstSegmentExpression, secondSegmentExpression, issues, context);
150
210
  case SchemaTag.Number:
151
211
  return emitNumberCheckAtTwoSegments(schema, value, path, firstSegmentExpression, secondSegmentExpression, issues);
212
+ case SchemaTag.Date:
213
+ if (schema.checks.length !== 0) {
214
+ return undefined;
215
+ }
216
+ return `if(!dg(${value})){${emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_date", "valid Date", `a(${value})`)}}`;
152
217
  case SchemaTag.BigInt:
153
218
  return `if(typeof ${value}!=="bigint"){${emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_bigint", "bigint", `a(${value})`)}}`;
154
219
  case SchemaTag.Symbol:
@@ -185,6 +250,8 @@ export function emitUndefinedLeafCheckAtTwoSegments(schema, path, firstSegmentEx
185
250
  return emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_string", "string", stringLiteral("undefined"));
186
251
  case SchemaTag.Number:
187
252
  return emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_number", "number", stringLiteral("undefined"));
253
+ case SchemaTag.Date:
254
+ return emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_date", "valid Date", stringLiteral("undefined"));
188
255
  case SchemaTag.BigInt:
189
256
  return emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_bigint", "bigint", stringLiteral("undefined"));
190
257
  case SchemaTag.Symbol:
@@ -239,6 +306,27 @@ function emitStringCheckAtSegment(schema, value, path, segmentExpression, issues
239
306
  case StringCheckTag.Uuid:
240
307
  parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, UUID_PATTERN, "uuid", context));
241
308
  break;
309
+ case StringCheckTag.Email:
310
+ parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, EMAIL_PATTERN, "email", context));
311
+ break;
312
+ case StringCheckTag.Url:
313
+ parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, URL_PATTERN, "url", context));
314
+ break;
315
+ case StringCheckTag.IsoDate:
316
+ parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, ISO_DATE_PATTERN, "iso_date", context));
317
+ break;
318
+ case StringCheckTag.IsoDateTime:
319
+ parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, ISO_DATETIME_PATTERN, "iso_datetime", context));
320
+ break;
321
+ case StringCheckTag.Ulid:
322
+ parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, ULID_PATTERN, "ulid", context));
323
+ break;
324
+ case StringCheckTag.Ipv4:
325
+ parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, IPV4_PATTERN, "ipv4", context));
326
+ break;
327
+ case StringCheckTag.Ipv6:
328
+ parts.push(emitPatternIssueAtSegment(value, path, segmentExpression, issues, IPV6_PATTERN, "ipv6", context));
329
+ break;
242
330
  }
243
331
  }
244
332
  parts.push("}");
@@ -283,6 +371,27 @@ function emitStringCheckAtTwoSegments(schema, value, path, firstSegmentExpressio
283
371
  case StringCheckTag.Uuid:
284
372
  parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, UUID_PATTERN, "uuid", context));
285
373
  break;
374
+ case StringCheckTag.Email:
375
+ parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, EMAIL_PATTERN, "email", context));
376
+ break;
377
+ case StringCheckTag.Url:
378
+ parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, URL_PATTERN, "url", context));
379
+ break;
380
+ case StringCheckTag.IsoDate:
381
+ parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, ISO_DATE_PATTERN, "iso_date", context));
382
+ break;
383
+ case StringCheckTag.IsoDateTime:
384
+ parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, ISO_DATETIME_PATTERN, "iso_datetime", context));
385
+ break;
386
+ case StringCheckTag.Ulid:
387
+ parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, ULID_PATTERN, "ulid", context));
388
+ break;
389
+ case StringCheckTag.Ipv4:
390
+ parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, IPV4_PATTERN, "ipv4", context));
391
+ break;
392
+ case StringCheckTag.Ipv6:
393
+ parts.push(emitPatternIssueAtTwoSegments(value, path, firstSegmentExpression, secondSegmentExpression, issues, IPV6_PATTERN, "ipv6", context));
394
+ break;
286
395
  }
287
396
  }
288
397
  parts.push("}");
@@ -322,6 +431,15 @@ export function emitNumberCheck(schema, value, path, issues) {
322
431
  case NumberCheckTag.Lte:
323
432
  parts.push(`if(${value}>${String(check.value)}){${emitIssue(issues, path, "expected_lte", `<= ${String(check.value)}`, `String(${value})`)}}`);
324
433
  break;
434
+ case NumberCheckTag.Gt:
435
+ parts.push(`if(${value}<=${String(check.value)}){${emitIssue(issues, path, "expected_gt", `> ${String(check.value)}`, `String(${value})`)}}`);
436
+ break;
437
+ case NumberCheckTag.Lt:
438
+ parts.push(`if(${value}>=${String(check.value)}){${emitIssue(issues, path, "expected_lt", `< ${String(check.value)}`, `String(${value})`)}}`);
439
+ break;
440
+ case NumberCheckTag.MultipleOf:
441
+ parts.push(`if(${value}%${String(check.value)}!==0){${emitIssue(issues, path, "expected_multiple_of", `multiple of ${String(check.value)}`, `String(${value})`)}}`);
442
+ break;
325
443
  }
326
444
  }
327
445
  return parts.join("");
@@ -364,6 +482,15 @@ function emitNumberCheckAtSegment(schema, value, path, segmentExpression, issues
364
482
  case NumberCheckTag.Lte:
365
483
  parts.push(`if(${value}>${String(check.value)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_lte", `<= ${String(check.value)}`, `String(${value})`)}}`);
366
484
  break;
485
+ case NumberCheckTag.Gt:
486
+ parts.push(`if(${value}<=${String(check.value)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_gt", `> ${String(check.value)}`, `String(${value})`)}}`);
487
+ break;
488
+ case NumberCheckTag.Lt:
489
+ parts.push(`if(${value}>=${String(check.value)}){${emitIssueAtSegment(issues, path, segmentExpression, "expected_lt", `< ${String(check.value)}`, `String(${value})`)}}`);
490
+ break;
491
+ case NumberCheckTag.MultipleOf:
492
+ parts.push(`if(${value}%${String(check.value)}!==0){${emitIssueAtSegment(issues, path, segmentExpression, "expected_multiple_of", `multiple of ${String(check.value)}`, `String(${value})`)}}`);
493
+ break;
367
494
  }
368
495
  }
369
496
  parts.push("}");
@@ -404,6 +531,15 @@ function emitNumberCheckAtTwoSegments(schema, value, path, firstSegmentExpressio
404
531
  case NumberCheckTag.Lte:
405
532
  parts.push(`if(${value}>${String(check.value)}){${emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_lte", `<= ${String(check.value)}`, `String(${value})`)}}`);
406
533
  break;
534
+ case NumberCheckTag.Gt:
535
+ parts.push(`if(${value}<=${String(check.value)}){${emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_gt", `> ${String(check.value)}`, `String(${value})`)}}`);
536
+ break;
537
+ case NumberCheckTag.Lt:
538
+ parts.push(`if(${value}>=${String(check.value)}){${emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_lt", `< ${String(check.value)}`, `String(${value})`)}}`);
539
+ break;
540
+ case NumberCheckTag.MultipleOf:
541
+ parts.push(`if(${value}%${String(check.value)}!==0){${emitIssueAtTwoSegments(issues, path, firstSegmentExpression, secondSegmentExpression, "expected_multiple_of", `multiple of ${String(check.value)}`, `String(${value})`)}}`);
542
+ break;
407
543
  }
408
544
  }
409
545
  parts.push("}");
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/compile/check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAgBjD,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAkB9E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAU/D"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/compile/check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAiBjD,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAkB9E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAU/D"}
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { SchemaTag } from "../kind/index.js";
8
8
  import { emitArrayCheck, emitDiscriminatedUnionCheck, emitObjectCheck, emitRecordCheck, emitTupleCheck } from "./check-composite.js";
9
- import { emitLiteralCheck, emitNumberCheck, emitStringCheck } from "./check-scalar.js";
9
+ import { emitDateCheck, emitLiteralCheck, emitNumberCheck, emitStringCheck } from "./check-scalar.js";
10
10
  import { pushSchema } from "./context.js";
11
11
  import { emitIssue } from "./issue.js";
12
12
  import { emitUnion } from "./predicate.js";
@@ -77,6 +77,8 @@ function emitCheckBody(schema, value, path, issues, context) {
77
77
  return emitStringCheck(schema, value, path, issues, context);
78
78
  case SchemaTag.Number:
79
79
  return emitNumberCheck(schema, value, path, issues);
80
+ case SchemaTag.Date:
81
+ return emitDateCheck(schema, value, path, issues);
80
82
  case SchemaTag.BigInt:
81
83
  return `if(typeof ${value}!=="bigint"){${emitIssue(issues, path, "expected_bigint", "bigint", `a(${value})`)}}`;
82
84
  case SchemaTag.Symbol:
@@ -86,11 +88,19 @@ function emitCheckBody(schema, value, path, issues, context) {
86
88
  case SchemaTag.Literal:
87
89
  return emitLiteralCheck(schema.value, value, path, issues, context);
88
90
  case SchemaTag.Array:
89
- return emitArrayCheck(schema.item, value, path, issues, context, emitCheckFunction);
91
+ return emitArrayCheck(schema, value, path, issues, context, emitCheckFunction);
90
92
  case SchemaTag.Tuple:
93
+ if (schema.rest !== undefined) {
94
+ return emitDynamicCheck(schema, value, path, issues, context);
95
+ }
91
96
  return emitTupleCheck(schema.items, value, path, issues, context, emitCheckFunction);
92
97
  case SchemaTag.Record:
93
98
  return emitRecordCheck(schema.value, value, path, issues, context, emitCheckFunction);
99
+ case SchemaTag.Map:
100
+ case SchemaTag.Set:
101
+ case SchemaTag.InstanceOf:
102
+ case SchemaTag.Property:
103
+ return emitDynamicCheck(schema, value, path, issues, context);
94
104
  case SchemaTag.Object:
95
105
  return emitObjectCheck(schema, value, path, issues, context, emitCheckFunction);
96
106
  case SchemaTag.Union:
@@ -116,9 +126,21 @@ function emitCheckBody(schema, value, path, issues, context) {
116
126
  * inlined into generated source. The `m` helper calls the interpreter
117
127
  * diagnostic path through the dynamic schema side table.
118
128
  */
119
- return `m(${String(pushSchema(context, schema))},${value},${path},${issues});`;
129
+ return emitDynamicCheck(schema, value, path, issues, context);
120
130
  }
121
131
  }
132
+ /**
133
+ * @brief Emit a diagnostic fallback call for runtime-only schema nodes.
134
+ * @param schema Schema captured in the dynamic side table.
135
+ * @param value Generated candidate value expression.
136
+ * @param path Generated path expression.
137
+ * @param issues Generated issue buffer expression.
138
+ * @param context Shared emission context.
139
+ * @returns JavaScript source delegating diagnostics to the interpreter.
140
+ */
141
+ function emitDynamicCheck(schema, value, path, issues, context) {
142
+ return `m(${String(pushSchema(context, schema))},${value},${path},${issues});`;
143
+ }
122
144
  /**
123
145
  * @brief emit check call.
124
146
  * @details Generated-source helpers keep the side-table ABI and JavaScript source shape
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/compile/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAchE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAI7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAIjF;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAatE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAItE"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/compile/context.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAgBhE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,CAI7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIrE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAIjF;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAatE;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAItE"}
@@ -24,6 +24,8 @@ export function createEmitContext(mode) {
24
24
  functionNames: new Map(),
25
25
  checkFunctions: [],
26
26
  checkFunctionNames: new Map(),
27
+ firstFunctions: [],
28
+ firstFunctionNames: new Map(),
27
29
  stringIndexes: new Map()
28
30
  };
29
31
  }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @file first.ts
3
+ * @brief First-fault diagnostic validator function table emitter.
4
+ * @details Generated first-fault helpers return one frozen issue immediately,
5
+ * keeping hot rejection diagnostics out of the full issue collector.
6
+ */
7
+ import { type Schema } from "../schema/index.js";
8
+ import type { EmitContext } from "./types.js";
9
+ /**
10
+ * @brief Emit or reuse a first-fault diagnostic function.
11
+ * @details Each schema identity maps to one generated first-fault function so
12
+ * recursive and shared schemas keep stable function identities in source.
13
+ * @param schema Schema whose first diagnostic should be emitted.
14
+ * @param context Shared code-generation context.
15
+ * @returns Generated first-fault function name.
16
+ */
17
+ export declare function emitFirstFunction(schema: Schema, context: EmitContext): string;
18
+ /**
19
+ * @brief Emit all first-fault diagnostic functions.
20
+ * @details Generated functions return undefined on success or one frozen issue
21
+ * on failure. They never allocate an issue array.
22
+ * @param context Shared code-generation context with accumulated sources.
23
+ * @returns Concatenated JavaScript function declarations.
24
+ */
25
+ export declare function emitFirstFunctions(context: EmitContext): string;
26
+ //# sourceMappingURL=first.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"first.d.ts","sourceRoot":"","sources":["../../src/compile/first.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAYH,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAS5B,OAAO,KAAK,EAAE,WAAW,EAAkB,MAAM,YAAY,CAAC;AAE9D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAc9E;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAS/D"}