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
@@ -25,6 +25,11 @@ export declare const SchemaTag: {
25
25
  readonly BigInt: 19;
26
26
  readonly Symbol: 20;
27
27
  readonly Intersection: 21;
28
+ readonly Date: 22;
29
+ readonly Map: 23;
30
+ readonly Set: 24;
31
+ readonly InstanceOf: 25;
32
+ readonly Property: 26;
28
33
  };
29
34
  export type SchemaTag = (typeof SchemaTag)[keyof typeof SchemaTag];
30
35
  /**
@@ -52,14 +57,34 @@ export declare const StringCheckTag: {
52
57
  readonly Max: 2;
53
58
  readonly Regex: 3;
54
59
  readonly Uuid: 4;
60
+ readonly Email: 5;
61
+ readonly Url: 6;
62
+ readonly IsoDate: 7;
63
+ readonly IsoDateTime: 8;
64
+ readonly Ulid: 9;
65
+ readonly Ipv4: 10;
66
+ readonly Ipv6: 11;
55
67
  };
56
68
  export type StringCheckTag = (typeof StringCheckTag)[keyof typeof StringCheckTag];
57
69
  export declare const NumberCheckTag: {
58
70
  readonly Integer: 1;
59
71
  readonly Gte: 2;
60
72
  readonly Lte: 3;
73
+ readonly Gt: 4;
74
+ readonly Lt: 5;
75
+ readonly MultipleOf: 6;
61
76
  };
62
77
  export type NumberCheckTag = (typeof NumberCheckTag)[keyof typeof NumberCheckTag];
78
+ export declare const DateCheckTag: {
79
+ readonly Min: 1;
80
+ readonly Max: 2;
81
+ };
82
+ export type DateCheckTag = (typeof DateCheckTag)[keyof typeof DateCheckTag];
83
+ export declare const ArrayCheckTag: {
84
+ readonly Min: 1;
85
+ readonly Max: 2;
86
+ };
87
+ export type ArrayCheckTag = (typeof ArrayCheckTag)[keyof typeof ArrayCheckTag];
63
88
  /**
64
89
  * @brief IR node tags with reserved numeric ranges by node family.
65
90
  * @details Sparse ranges make graph dumps easier to scan and leave room for
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kind/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;CAsBZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEnE;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE,eAAO,MAAM,cAAc;;;;;CAKjB,CAAC;AAEX,MAAM,MAAM,cAAc,GACtB,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAEzD,eAAO,MAAM,cAAc;;;;CAIjB,CAAC;AAEX,MAAM,MAAM,cAAc,GACtB,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAEzD;;;;GAIG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCV,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/kind/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BZ,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAEnE;;;;GAIG;AACH,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAE/E;;;;GAIG;AACH,eAAO,MAAM,WAAW;;;CAGd,CAAC;AAEX,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC;AAEzE,eAAO,MAAM,cAAc;;;;;;;;;;;;CAYjB,CAAC;AAEX,MAAM,MAAM,cAAc,GACtB,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAEzD,eAAO,MAAM,cAAc;;;;;;;CAOjB,CAAC;AAEX,MAAM,MAAM,cAAc,GACtB,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC;AAEzD,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,MAAM,MAAM,YAAY,GACpB,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAErD,eAAO,MAAM,aAAa;;;CAGhB,CAAC;AAEX,MAAM,MAAM,aAAa,GACrB,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCV,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,OAAO,CAAC,CAAC,MAAM,OAAO,OAAO,CAAC,CAAC"}
@@ -24,7 +24,12 @@ export const SchemaTag = {
24
24
  Never: 18,
25
25
  BigInt: 19,
26
26
  Symbol: 20,
27
- Intersection: 21
27
+ Intersection: 21,
28
+ Date: 22,
29
+ Map: 23,
30
+ Set: 24,
31
+ InstanceOf: 25,
32
+ Property: 26
28
33
  };
29
34
  /**
30
35
  * @brief Object unknown-key policy tags.
@@ -48,12 +53,30 @@ export const StringCheckTag = {
48
53
  Min: 1,
49
54
  Max: 2,
50
55
  Regex: 3,
51
- Uuid: 4
56
+ Uuid: 4,
57
+ Email: 5,
58
+ Url: 6,
59
+ IsoDate: 7,
60
+ IsoDateTime: 8,
61
+ Ulid: 9,
62
+ Ipv4: 10,
63
+ Ipv6: 11
52
64
  };
53
65
  export const NumberCheckTag = {
54
66
  Integer: 1,
55
67
  Gte: 2,
56
- Lte: 3
68
+ Lte: 3,
69
+ Gt: 4,
70
+ Lt: 5,
71
+ MultipleOf: 6
72
+ };
73
+ export const DateCheckTag = {
74
+ Min: 1,
75
+ Max: 2
76
+ };
77
+ export const ArrayCheckTag = {
78
+ Min: 1,
79
+ Max: 2
57
80
  };
58
81
  /**
59
82
  * @brief IR node tags with reserved numeric ranges by node family.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lower/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAEH,KAAK,KAAK,EAIb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE/D;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAOjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lower/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAEH,KAAK,KAAK,EAIb,MAAM,gBAAgB,CAAC;AAExB,OAAO,EASH,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAE5B;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAOjD"}
@@ -1,7 +1,7 @@
1
1
  import { NumberCheckTag, PresenceTag, SchemaTag, StringCheckTag } from "../kind/index.js";
2
2
  import { GraphBuilder } from "../ir/index.js";
3
3
  import { optimizeGraph } from "../optimize/index.js";
4
- import { UUID_PATTERN } from "../schema/index.js";
4
+ import { EMAIL_PATTERN, IPV4_PATTERN, IPV6_PATTERN, ISO_DATETIME_PATTERN, ISO_DATE_PATTERN, ULID_PATTERN, URL_PATTERN, UUID_PATTERN } from "../schema/index.js";
5
5
  /**
6
6
  * @brief Convert one schema root into a Sea-of-Nodes predicate graph.
7
7
  * @details The graph always starts with a single input parameter and ends in a
@@ -38,6 +38,8 @@ function lowerPredicate(builder, schema, value) {
38
38
  return lowerString(builder, schema, value);
39
39
  case SchemaTag.Number:
40
40
  return lowerNumber(builder, schema, value);
41
+ case SchemaTag.Date:
42
+ return builder.schemaCheck(value, schema);
41
43
  case SchemaTag.BigInt:
42
44
  return builder.isBigInt(value);
43
45
  case SchemaTag.Symbol:
@@ -54,9 +56,12 @@ function lowerPredicate(builder, schema, value) {
54
56
  */
55
57
  return builder.and([
56
58
  builder.isArray(value),
57
- builder.arrayEvery(value, schema.item, lowerChildGraph(schema.item))
59
+ builder.arrayEvery(value, schema.item, schema.checks, lowerChildGraph(schema.item))
58
60
  ]);
59
61
  case SchemaTag.Tuple:
62
+ if (schema.rest !== undefined) {
63
+ return builder.schemaCheck(value, schema);
64
+ }
60
65
  return builder.and([
61
66
  builder.isArray(value),
62
67
  builder.tupleItems(value, schema.items, lowerChildGraphs(schema.items))
@@ -66,6 +71,11 @@ function lowerPredicate(builder, schema, value) {
66
71
  builder.isObject(value),
67
72
  builder.recordEvery(value, schema.value, lowerChildGraph(schema.value))
68
73
  ]);
74
+ case SchemaTag.Map:
75
+ case SchemaTag.Set:
76
+ case SchemaTag.InstanceOf:
77
+ case SchemaTag.Property:
78
+ return builder.schemaCheck(value, schema);
69
79
  case SchemaTag.Object:
70
80
  return lowerObject(builder, schema, value);
71
81
  case SchemaTag.Union:
@@ -135,6 +145,27 @@ function lowerString(builder, schema, value) {
135
145
  case StringCheckTag.Uuid:
136
146
  tests.push(builder.regex(value, UUID_PATTERN, "uuid"));
137
147
  break;
148
+ case StringCheckTag.Email:
149
+ tests.push(builder.regex(value, EMAIL_PATTERN, "email"));
150
+ break;
151
+ case StringCheckTag.Url:
152
+ tests.push(builder.regex(value, URL_PATTERN, "url"));
153
+ break;
154
+ case StringCheckTag.IsoDate:
155
+ tests.push(builder.regex(value, ISO_DATE_PATTERN, "iso_date"));
156
+ break;
157
+ case StringCheckTag.IsoDateTime:
158
+ tests.push(builder.regex(value, ISO_DATETIME_PATTERN, "iso_datetime"));
159
+ break;
160
+ case StringCheckTag.Ulid:
161
+ tests.push(builder.regex(value, ULID_PATTERN, "ulid"));
162
+ break;
163
+ case StringCheckTag.Ipv4:
164
+ tests.push(builder.regex(value, IPV4_PATTERN, "ipv4"));
165
+ break;
166
+ case StringCheckTag.Ipv6:
167
+ tests.push(builder.regex(value, IPV6_PATTERN, "ipv6"));
168
+ break;
138
169
  }
139
170
  }
140
171
  return builder.and(tests);
@@ -167,6 +198,18 @@ function lowerNumber(builder, schema, value) {
167
198
  case NumberCheckTag.Lte:
168
199
  tests.push(builder.lte(value, builder.constant(check.value)));
169
200
  break;
201
+ case NumberCheckTag.Gt:
202
+ tests.push(builder.not(builder.lte(value, builder.constant(check.value))));
203
+ break;
204
+ case NumberCheckTag.Lt:
205
+ tests.push(builder.not(builder.gte(value, builder.constant(check.value))));
206
+ break;
207
+ case NumberCheckTag.MultipleOf:
208
+ tests.push(builder.schemaCheck(value, {
209
+ tag: SchemaTag.Number,
210
+ checks: [check]
211
+ }));
212
+ break;
170
213
  }
171
214
  }
172
215
  return builder.and(tests);
@@ -182,7 +225,7 @@ function lowerNumber(builder, schema, value) {
182
225
  * @returns Node id for the object-shape predicate.
183
226
  */
184
227
  function lowerObject(builder, schema, value) {
185
- return builder.objectShape(value, lowerObjectShapeEntries(schema.entries), schema.keys, schema.mode);
228
+ return builder.objectShape(value, lowerObjectShapeEntries(schema.entries), schema.keys, schema.mode, schema.catchall, schema.catchall === undefined ? undefined : lowerChildGraph(schema.catchall));
186
229
  }
187
230
  /**
188
231
  * @brief Lower and optimize a child schema before embedding it in a parent node.
@@ -355,6 +398,8 @@ function schemaUnionMask(schema) {
355
398
  return UnionMask.String;
356
399
  case SchemaTag.Number:
357
400
  return UnionMask.Number;
401
+ case SchemaTag.Date:
402
+ return UnionMask.Object;
358
403
  case SchemaTag.BigInt:
359
404
  return UnionMask.BigInt;
360
405
  case SchemaTag.Symbol:
@@ -368,6 +413,10 @@ function schemaUnionMask(schema) {
368
413
  return UnionMask.Array;
369
414
  case SchemaTag.Object:
370
415
  case SchemaTag.Record:
416
+ case SchemaTag.Map:
417
+ case SchemaTag.Set:
418
+ case SchemaTag.InstanceOf:
419
+ case SchemaTag.Property:
371
420
  case SchemaTag.DiscriminatedUnion:
372
421
  return UnionMask.Object;
373
422
  case SchemaTag.Optional:
@@ -48,6 +48,15 @@ export interface IssueMessageOptions {
48
48
  readonly catalog: IssueMessageCatalog | undefined;
49
49
  readonly pathFormatter: ((path: readonly PathSegment[]) => string) | undefined;
50
50
  }
51
+ /**
52
+ * @brief Zod-style flattened message view.
53
+ * @details Root issues go into formErrors. Field issues are grouped by the
54
+ * first path segment so form adapters can attach messages to top-level fields.
55
+ */
56
+ export interface FlattenedIssueMessages {
57
+ readonly formErrors: readonly string[];
58
+ readonly fieldErrors: Readonly<Record<string, readonly string[]>>;
59
+ }
51
60
  /**
52
61
  * @brief Freeze a user catalog after validating its keys and templates.
53
62
  * @details Message helpers keep structured issues separate from human-readable formatting
@@ -74,6 +83,15 @@ export declare function formatIssue(issue: Issue, options?: Partial<IssueMessage
74
83
  * @returns Frozen list of rendered messages aligned with the input issue order.
75
84
  */
76
85
  export declare function formatIssues(issues: readonly Issue[], options?: Partial<IssueMessageOptions>): readonly string[];
86
+ /**
87
+ * @brief Flatten issues into root and top-level field message buckets.
88
+ * @param issues Issue list returned by check-like APIs.
89
+ * @param options Optional locale, catalog, and path formatter.
90
+ * @returns Frozen flattened message object.
91
+ * @details This mirrors the practical shape of Zod's `error.flatten()` without
92
+ * changing TypeSea's allocation-free boolean path or array-based diagnostics.
93
+ */
94
+ export declare function flattenIssues(issues: readonly Issue[], options?: Partial<IssueMessageOptions>): FlattenedIssueMessages;
77
95
  /**
78
96
  * @brief Attach rendered messages to every issue in a failed check result.
79
97
  * @details Successful results are returned unchanged. Failed results are copied
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/message/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,WAAW,EACnB,MAAM,mBAAmB,CAAC;AAG3B;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,mBAAmB,KAC3B,MAAM,CAAC;AAEZ;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,qBAAqB,CAAC;AAElE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACrC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC,CACpD,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,aAAa,EAChB,CAAC,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,CAAC,GAC1C,SAAS,CAAC;CACnB;AAaD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAEhF;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACvB,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,MAAM,CAOR;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CACxB,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,SAAS,MAAM,EAAE,CAWnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAC/B,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,WAAW,CAAC,MAAM,CAAC,CAoBrB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/message/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,WAAW,EACnB,MAAM,mBAAmB,CAAC;AAG3B;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,IAAI,CAAC;AAExC;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAChC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,mBAAmB,KAC3B,MAAM,CAAC;AAEZ;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,qBAAqB,CAAC;AAElE;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACrC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC,CACpD,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,aAAa,EAChB,CAAC,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,KAAK,MAAM,CAAC,GAC1C,SAAS,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACnC,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;CACrE;AAaD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,mBAAmB,CAEhF;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACvB,KAAK,EAAE,KAAK,EACZ,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,MAAM,CAOR;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CACxB,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,SAAS,MAAM,EAAE,CAWnB;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CACzB,MAAM,EAAE,SAAS,KAAK,EAAE,EACxB,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,sBAAsB,CA4BxB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAC/B,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAC3B,OAAO,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACvC,WAAW,CAAC,MAAM,CAAC,CAoBrB"}
@@ -46,6 +46,44 @@ export function formatIssues(issues, options) {
46
46
  }
47
47
  return Object.freeze(messages);
48
48
  }
49
+ /**
50
+ * @brief Flatten issues into root and top-level field message buckets.
51
+ * @param issues Issue list returned by check-like APIs.
52
+ * @param options Optional locale, catalog, and path formatter.
53
+ * @returns Frozen flattened message object.
54
+ * @details This mirrors the practical shape of Zod's `error.flatten()` without
55
+ * changing TypeSea's allocation-free boolean path or array-based diagnostics.
56
+ */
57
+ export function flattenIssues(issues, options) {
58
+ const copied = copyIssueArray(issues);
59
+ const config = readOptions(options);
60
+ const formErrors = [];
61
+ const fieldErrors = Object.create(null);
62
+ for (let index = 0; index < copied.length; index += 1) {
63
+ const issue = copied[index];
64
+ if (issue === undefined) {
65
+ continue;
66
+ }
67
+ const message = renderIssue(issue, config);
68
+ const first = issue.path[0];
69
+ if (first === undefined) {
70
+ formErrors.push(message);
71
+ continue;
72
+ }
73
+ const key = String(first);
74
+ const bucket = fieldErrors[key];
75
+ if (bucket === undefined) {
76
+ fieldErrors[key] = [message];
77
+ }
78
+ else {
79
+ bucket.push(message);
80
+ }
81
+ }
82
+ return Object.freeze({
83
+ formErrors: Object.freeze(formErrors),
84
+ fieldErrors: freezeFieldErrors(fieldErrors)
85
+ });
86
+ }
49
87
  /**
50
88
  * @brief Attach rendered messages to every issue in a failed check result.
51
89
  * @details Successful results are returned unchanged. Failed results are copied
@@ -90,6 +128,21 @@ function renderIssue(issue, options) {
90
128
  }
91
129
  return renderTemplate(defaultCatalogs[options.locale][issue.code], issue, context);
92
130
  }
131
+ /**
132
+ * @brief Freeze flattened field-error buckets.
133
+ * @param value Mutable field-error table.
134
+ * @returns Frozen table with frozen message arrays.
135
+ */
136
+ function freezeFieldErrors(value) {
137
+ const keys = Object.keys(value);
138
+ for (let index = 0; index < keys.length; index += 1) {
139
+ const key = keys[index];
140
+ if (key !== undefined) {
141
+ Object.freeze(value[key]);
142
+ }
143
+ }
144
+ return Object.freeze(value);
145
+ }
93
146
  /**
94
147
  * @brief Build the stable template context for one issue.
95
148
  * @details Missing expected or actual fields become `"unknown"` so templates
@@ -275,12 +328,16 @@ function isRecord(value) {
275
328
  const enCatalog = Object.freeze({
276
329
  expected_string: "Expected string at {path}; received {actual}.",
277
330
  expected_number: "Expected number at {path}; received {actual}.",
331
+ expected_date: "Expected valid Date at {path}; received {actual}.",
278
332
  expected_bigint: "Expected bigint at {path}; received {actual}.",
279
333
  expected_symbol: "Expected symbol at {path}; received {actual}.",
280
334
  expected_boolean: "Expected boolean at {path}; received {actual}.",
281
335
  expected_never: "Expected never at {path}; received {actual}.",
282
336
  expected_literal: "Expected literal {expected} at {path}; received {actual}.",
283
337
  expected_array: "Expected array at {path}; received {actual}.",
338
+ expected_map: "Expected Map at {path}; received {actual}.",
339
+ expected_set: "Expected Set at {path}; received {actual}.",
340
+ expected_instance: "Expected instance of {expected} at {path}; received {actual}.",
284
341
  expected_tuple: "Expected tuple at {path}; received {actual}.",
285
342
  expected_tuple_length: "Expected tuple {expected} at {path}; received {actual}.",
286
343
  expected_object: "Expected object at {path}; received {actual}.",
@@ -291,6 +348,9 @@ const enCatalog = Object.freeze({
291
348
  expected_pattern: "Expected pattern {expected} at {path}; received {actual}.",
292
349
  expected_gte: "Expected value {expected} at {path}; received {actual}.",
293
350
  expected_lte: "Expected value {expected} at {path}; received {actual}.",
351
+ expected_gt: "Expected value {expected} at {path}; received {actual}.",
352
+ expected_lt: "Expected value {expected} at {path}; received {actual}.",
353
+ expected_multiple_of: "Expected value {expected} at {path}; received {actual}.",
294
354
  expected_required_key: "Expected required key at {path}; received {actual}.",
295
355
  expected_union: "Expected union at {path}; received {actual}.",
296
356
  expected_discriminant: "Expected discriminant {expected} at {path}; received {actual}.",
@@ -306,12 +366,16 @@ const enCatalog = Object.freeze({
306
366
  const koCatalog = Object.freeze({
307
367
  expected_string: "{path}에서 문자열이 필요하지만 {actual}을 받았습니다.",
308
368
  expected_number: "{path}에서 숫자가 필요하지만 {actual}을 받았습니다.",
369
+ expected_date: "{path}에서 유효한 Date가 필요하지만 {actual}을 받았습니다.",
309
370
  expected_bigint: "{path}에서 bigint가 필요하지만 {actual}을 받았습니다.",
310
371
  expected_symbol: "{path}에서 symbol이 필요하지만 {actual}을 받았습니다.",
311
372
  expected_boolean: "{path}에서 boolean이 필요하지만 {actual}을 받았습니다.",
312
373
  expected_never: "{path}에서 never가 필요하지만 {actual}을 받았습니다.",
313
374
  expected_literal: "{path}에서 literal {expected}이 필요하지만 {actual}을 받았습니다.",
314
375
  expected_array: "{path}에서 배열이 필요하지만 {actual}을 받았습니다.",
376
+ expected_map: "{path}에서 Map이 필요하지만 {actual}을 받았습니다.",
377
+ expected_set: "{path}에서 Set이 필요하지만 {actual}을 받았습니다.",
378
+ expected_instance: "{path}에서 {expected} 인스턴스가 필요하지만 {actual}을 받았습니다.",
315
379
  expected_tuple: "{path}에서 튜플이 필요하지만 {actual}을 받았습니다.",
316
380
  expected_tuple_length: "{path}에서 튜플 {expected}이 필요하지만 {actual}을 받았습니다.",
317
381
  expected_object: "{path}에서 객체가 필요하지만 {actual}을 받았습니다.",
@@ -322,6 +386,9 @@ const koCatalog = Object.freeze({
322
386
  expected_pattern: "{path}에서 패턴 {expected}이 필요하지만 {actual}을 받았습니다.",
323
387
  expected_gte: "{path}에서 값 {expected}이 필요하지만 {actual}을 받았습니다.",
324
388
  expected_lte: "{path}에서 값 {expected}이 필요하지만 {actual}을 받았습니다.",
389
+ expected_gt: "{path}에서 값 {expected}이 필요하지만 {actual}을 받았습니다.",
390
+ expected_lt: "{path}에서 값 {expected}이 필요하지만 {actual}을 받았습니다.",
391
+ expected_multiple_of: "{path}에서 값 {expected}이 필요하지만 {actual}을 받았습니다.",
325
392
  expected_required_key: "{path}에 필수 키가 필요하지만 {actual}입니다.",
326
393
  expected_union: "{path}에서 유니온 값이 필요하지만 {actual}을 받았습니다.",
327
394
  expected_discriminant: "{path}에서 discriminant {expected}이 필요하지만 {actual}을 받았습니다.",
@@ -100,12 +100,16 @@ function specializeChildDomains(node, nodes) {
100
100
  }
101
101
  case NodeTag.ObjectShape: {
102
102
  const entries = specializeObjectShapeEntries(node.entries);
103
- if (entries === node.entries) {
103
+ const catchallGraph = node.catchallGraph === undefined
104
+ ? undefined
105
+ : specializeDomains(node.catchallGraph);
106
+ if (entries === node.entries && catchallGraph === node.catchallGraph) {
104
107
  return node;
105
108
  }
106
109
  return {
107
110
  ...node,
108
- entries
111
+ entries,
112
+ catchallGraph
109
113
  };
110
114
  }
111
115
  case NodeTag.UnionDispatch: {
@@ -1 +1 @@
1
- {"version":3,"file":"map-node.d.ts","sourceRoot":"","sources":["../../src/optimize/map-node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACR,SAAS,EACT,MAAM,EACT,MAAM,gBAAgB,CAAC;AAExB;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACtB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,YAAY,EACnB,EAAE,EAAE,MAAM,GACX,SAAS,CAuOX"}
1
+ {"version":3,"file":"map-node.d.ts","sourceRoot":"","sources":["../../src/optimize/map-node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACR,SAAS,EACT,MAAM,EACT,MAAM,gBAAgB,CAAC;AAExB;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACtB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,YAAY,EACnB,EAAE,EAAE,MAAM,GACX,SAAS,CA0OX"}
@@ -137,6 +137,7 @@ export function mapNodeIds(node, mapId, id) {
137
137
  deps: [value],
138
138
  value,
139
139
  item: node.item,
140
+ checks: node.checks,
140
141
  itemGraph: node.itemGraph
141
142
  };
142
143
  }
@@ -186,6 +187,8 @@ export function mapNodeIds(node, mapId, id) {
186
187
  entries: node.entries,
187
188
  keys: node.keys,
188
189
  mode: node.mode,
190
+ catchall: node.catchall,
191
+ catchallGraph: node.catchallGraph,
189
192
  allRequired: node.allRequired
190
193
  };
191
194
  }
@@ -75,9 +75,19 @@ function schemaRequiresTrackingInner(schema, seen) {
75
75
  case SchemaTag.Array:
76
76
  return schemaRequiresTrackingInner(schema.item, seen);
77
77
  case SchemaTag.Tuple:
78
- return schemaArrayRequiresTracking(schema.items, seen);
78
+ return schemaArrayRequiresTracking(schema.items, seen) ||
79
+ (schema.rest !== undefined &&
80
+ schemaRequiresTrackingInner(schema.rest, seen));
79
81
  case SchemaTag.Record:
80
82
  return schemaRequiresTrackingInner(schema.value, seen);
83
+ case SchemaTag.Map:
84
+ return schemaRequiresTrackingInner(schema.key, seen) ||
85
+ schemaRequiresTrackingInner(schema.value, seen);
86
+ case SchemaTag.Set:
87
+ return schemaRequiresTrackingInner(schema.item, seen);
88
+ case SchemaTag.Property:
89
+ return schemaRequiresTrackingInner(schema.base, seen) ||
90
+ schemaRequiresTrackingInner(schema.value, seen);
81
91
  case SchemaTag.Object:
82
92
  for (let index = 0; index < schema.entries.length; index += 1) {
83
93
  const entry = schema.entries[index];
@@ -112,6 +122,8 @@ function schemaRequiresTrackingInner(schema, seen) {
112
122
  case SchemaTag.Never:
113
123
  case SchemaTag.String:
114
124
  case SchemaTag.Number:
125
+ case SchemaTag.Date:
126
+ case SchemaTag.InstanceOf:
115
127
  case SchemaTag.BigInt:
116
128
  case SchemaTag.Symbol:
117
129
  case SchemaTag.Boolean:
@@ -1 +1 @@
1
- {"version":3,"file":"predicate.d.ts","sourceRoot":"","sources":["../../src/plan/predicate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACR,KAAK,EAIR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAGH,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAKH,KAAK,eAAe,EACvB,MAAM,sBAAsB,CAAC;AAI9B;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GACf,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC3C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,GACvB,OAAO,CAcT;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACjC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,GACvB,OAAO,CAaT"}
1
+ {"version":3,"file":"predicate.d.ts","sourceRoot":"","sources":["../../src/plan/predicate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,KAAK,EACR,KAAK,EAIR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAIH,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAKH,KAAK,eAAe,EACvB,MAAM,sBAAsB,CAAC;AAI9B;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,GACf,OAAO,CAET;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC3C,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,GACvB,OAAO,CAcT;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACjC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,GACvB,OAAO,CAaT"}
@@ -4,7 +4,7 @@
4
4
  * @details Plan helpers keep schema-specialized execution aligned with optimized IR while
5
5
  * preserving interpreter parity.
6
6
  */
7
- import { NodeTag, ObjectModeTag, PresenceTag, SchemaTag } from "../kind/index.js";
7
+ import { ArrayCheckTag, NodeTag, ObjectModeTag, PresenceTag, SchemaTag } from "../kind/index.js";
8
8
  import { resolveLazySchema, schemaCanAcceptUndefined } from "../schema/index.js";
9
9
  import { isArrayIndexKey } from "../evaluate/shared.js";
10
10
  import { enterValidation, leaveValidation, makeValidationState } from "../evaluate/state.js";
@@ -141,7 +141,7 @@ function evaluateGraphNode(graph, node, input, values, seen, epoch, state) {
141
141
  case NodeTag.StrictKeys:
142
142
  return testStrictKeys(evaluateNode(graph, node.object, input, values, seen, epoch, state), node.keys);
143
143
  case NodeTag.ArrayEvery:
144
- return testArrayEvery(evaluateNode(graph, node.value, input, values, seen, epoch, state), node.item, node.itemGraph, state);
144
+ return testArrayEvery(evaluateNode(graph, node.value, input, values, seen, epoch, state), node.item, node.checks, node.itemGraph, state);
145
145
  case NodeTag.TupleItems:
146
146
  return testTupleItems(evaluateNode(graph, node.value, input, values, seen, epoch, state), node.itemGraphs, state);
147
147
  case NodeTag.RecordEvery:
@@ -204,10 +204,13 @@ function evaluateOr(graph, ids, input, values, seen, epoch, state) {
204
204
  * @param state Shared recursion and cycle state.
205
205
  * @returns True when every relevant slot satisfies `itemGraph`.
206
206
  */
207
- function testArrayEvery(value, item, itemGraph, state) {
207
+ function testArrayEvery(value, item, checks, itemGraph, state) {
208
208
  if (!Array.isArray(value)) {
209
209
  return false;
210
210
  }
211
+ if (!testArrayLengthChecks(value.length, checks)) {
212
+ return false;
213
+ }
211
214
  if (schemaCanAcceptUndefined(item)) {
212
215
  /*
213
216
  * The graph alone cannot reveal whether holes are valid. The retained
@@ -225,6 +228,33 @@ function testArrayEvery(value, item, itemGraph, state) {
225
228
  }
226
229
  return true;
227
230
  }
231
+ /**
232
+ * @brief Test array length checks attached to an ArrayEvery node.
233
+ * @param length Runtime array length.
234
+ * @param checks Normalized length check vector.
235
+ * @returns True when every bound accepts the length.
236
+ */
237
+ function testArrayLengthChecks(length, checks) {
238
+ for (let index = 0; index < checks.length; index += 1) {
239
+ const check = checks[index];
240
+ if (check === undefined) {
241
+ return false;
242
+ }
243
+ switch (check.tag) {
244
+ case ArrayCheckTag.Min:
245
+ if (length < check.value) {
246
+ return false;
247
+ }
248
+ break;
249
+ case ArrayCheckTag.Max:
250
+ if (length > check.value) {
251
+ return false;
252
+ }
253
+ break;
254
+ }
255
+ }
256
+ return true;
257
+ }
228
258
  /**
229
259
  * @brief test present array indexes.
230
260
  * @details Holes are skipped only after the caller proved that undefined passes
@@ -1 +1 @@
1
- {"version":3,"file":"schema-predicate.d.ts","sourceRoot":"","sources":["../../src/plan/schema-predicate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,OAAO,EAKH,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,KACrB,OAAO,CAAC;AAEb;;;;GAIG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,oBAAoB,GAC/B,OAAO,CAoDT"}
1
+ {"version":3,"file":"schema-predicate.d.ts","sourceRoot":"","sources":["../../src/plan/schema-predicate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAYH,KAAK,MAAM,EACd,MAAM,oBAAoB,CAAC;AAa5B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,KACrB,OAAO,CAAC;AAEb;;;;GAIG;AACH,wBAAgB,mBAAmB,CAC/B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,oBAAoB,GAC/B,OAAO,CA8DT"}