@astrale-os/kernel-dsl 1.0.0-beta.2 → 1.0.0-beta.20

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 (307) hide show
  1. package/dist/v1/addressing/class-key.js +3 -3
  2. package/dist/v1/addressing/definition-ref.js +21 -37
  3. package/dist/v1/addressing/domain-dependency.d.ts +0 -6
  4. package/dist/v1/addressing/domain-dependency.js +1 -6
  5. package/dist/v1/addressing/key.d.ts +4 -1
  6. package/dist/v1/addressing/key.js +23 -3
  7. package/dist/v1/addressing/ordering.d.ts +2 -0
  8. package/dist/v1/addressing/ordering.js +4 -0
  9. package/dist/v1/addressing/patterns.d.ts +1 -1
  10. package/dist/v1/addressing/patterns.js +2 -6
  11. package/dist/v1/builder/callable/authoring.d.ts +11 -5
  12. package/dist/v1/builder/callable/authoring.js +2 -0
  13. package/dist/v1/builder/class/authoring.d.ts +94 -224
  14. package/dist/v1/builder/class/authoring.js +31 -33
  15. package/dist/v1/builder/class/handle.d.ts +27 -0
  16. package/dist/v1/builder/class/handle.js +1 -0
  17. package/dist/v1/builder/class/input.d.ts +159 -0
  18. package/dist/v1/builder/class/projection.d.ts +129 -0
  19. package/dist/v1/builder/class/projection.js +1 -0
  20. package/dist/v1/builder/class/property.d.ts +3 -9
  21. package/dist/v1/builder/class/property.js +1 -0
  22. package/dist/v1/builder/core/authoring.d.ts +1 -1
  23. package/dist/v1/builder/index.d.ts +5 -2
  24. package/dist/v1/builder/lowering/callable.js +1 -0
  25. package/dist/v1/builder/lowering/class.d.ts +9 -1
  26. package/dist/v1/builder/lowering/class.js +62 -17
  27. package/dist/v1/builder/lowering/policy.js +2 -0
  28. package/dist/v1/builder/lowering/property-keys.d.ts +27 -0
  29. package/dist/v1/builder/lowering/property-keys.js +108 -0
  30. package/dist/v1/builder/lowering/schema/compile.js +11 -6
  31. package/dist/v1/builder/lowering/schema/context.d.ts +9 -1
  32. package/dist/v1/builder/lowering/schema/context.js +36 -4
  33. package/dist/v1/builder/lowering/schema/lifetime.d.ts +11 -0
  34. package/dist/v1/builder/lowering/schema/lifetime.js +55 -0
  35. package/dist/v1/builder/lowering/value/path.d.ts +1 -1
  36. package/dist/v1/builder/lowering/value/path.js +2 -4
  37. package/dist/v1/builder/lowering/value/zod.js +1 -3
  38. package/dist/v1/builder/policy/authoring.d.ts +85 -5
  39. package/dist/v1/builder/policy/authoring.js +107 -68
  40. package/dist/v1/builder/schema/define.d.ts +0 -1
  41. package/dist/v1/builder/schema/diagnostic.d.ts +3 -2
  42. package/dist/v1/builder/schema/diagnostic.js +5 -10
  43. package/dist/v1/builder/schema/input.d.ts +1 -1
  44. package/dist/v1/builder/schema/projection/callable.d.ts +7 -5
  45. package/dist/v1/builder/schema/projection/class.d.ts +118 -15
  46. package/dist/v1/builder/schema/projection/core-input.d.ts +2 -1
  47. package/dist/v1/builder/schema/projection/identity.d.ts +2 -1
  48. package/dist/v1/builder/schema/projection/model.d.ts +4 -2
  49. package/dist/v1/builder/schema/projection/property.d.ts +1 -1
  50. package/dist/v1/builder/schema/projection/resolved-class.d.ts +2 -1
  51. package/dist/v1/builder/schema/projection.d.ts +1 -1
  52. package/dist/v1/builder/value/full-match.d.ts +0 -1
  53. package/dist/v1/builder/value/full-match.js +0 -1
  54. package/dist/v1/builder/value/path-metadata.d.ts +1 -1
  55. package/dist/v1/builder/value/path.d.ts +1 -1
  56. package/dist/v1/bundle/codec.js +11 -13
  57. package/dist/v1/bundle/diagnostic.d.ts +2 -0
  58. package/dist/v1/bundle/diagnostic.js +9 -7
  59. package/dist/v1/bundle/model.js +1 -1
  60. package/dist/v1/bundle/structure.js +4 -6
  61. package/dist/v1/compiled/admission/accept.js +4 -10
  62. package/dist/v1/compiled/admission/closure.js +2 -2
  63. package/dist/v1/compiled/admission/diagnostic.d.ts +1 -1
  64. package/dist/v1/compiled/admission/diagnostic.js +1 -3
  65. package/dist/v1/compiled/admission/revision.d.ts +9 -1
  66. package/dist/v1/compiled/admission/revision.js +6 -3
  67. package/dist/v1/compiled/admission/semantics/class.d.ts +4 -1
  68. package/dist/v1/compiled/admission/semantics/class.js +37 -12
  69. package/dist/v1/compiled/admission/semantics/core.d.ts +1 -24
  70. package/dist/v1/compiled/admission/semantics/core.js +56 -24
  71. package/dist/v1/compiled/admission/semantics/edge.d.ts +2 -4
  72. package/dist/v1/compiled/admission/semantics/edge.js +6 -65
  73. package/dist/v1/compiled/admission/semantics/policy/callable.js +0 -2
  74. package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +5 -20
  75. package/dist/v1/compiled/admission/semantics/policy/contracts.js +8 -21
  76. package/dist/v1/compiled/admission/semantics/policy/parity.js +40 -43
  77. package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +4 -1
  78. package/dist/v1/compiled/admission/semantics/policy/pattern.js +4 -16
  79. package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +2 -24
  80. package/dist/v1/compiled/admission/semantics/policy/typing.js +19 -201
  81. package/dist/v1/compiled/admission/wire/callable.js +11 -1
  82. package/dist/v1/compiled/admission/wire/class.js +73 -21
  83. package/dist/v1/compiled/admission/wire/policy.d.ts +4 -3
  84. package/dist/v1/compiled/admission/wire/policy.js +8 -7
  85. package/dist/v1/compiled/compiler/compile.js +8 -8
  86. package/dist/v1/compiled/diagnostic.js +2 -3
  87. package/dist/v1/compiled/loader/load.d.ts +3 -2
  88. package/dist/v1/compiled/loader/load.js +11 -45
  89. package/dist/v1/domain/create.js +5 -6
  90. package/dist/v1/domain/model/domain.d.ts +2 -7
  91. package/dist/v1/domain/model/input.d.ts +2 -1
  92. package/dist/v1/domain/namespace/member-collection.js +4 -6
  93. package/dist/v1/domain/projection/classes.js +4 -1
  94. package/dist/v1/domain/validation/create.d.ts +6 -3
  95. package/dist/v1/domain/validation/create.js +21 -69
  96. package/dist/v1/index.d.ts +2 -1
  97. package/dist/v1/language/.spec/schemas/draft-2020-12.schema.json +462 -0
  98. package/dist/v1/language/.spec/schemas/value-schema.schema.json +22 -0
  99. package/dist/v1/language/callable/admission.d.ts +15 -0
  100. package/dist/v1/language/callable/admission.js +43 -0
  101. package/dist/v1/language/callable/model/callable.d.ts +10 -0
  102. package/dist/v1/language/callable/resolved.d.ts +16 -3
  103. package/dist/v1/language/class/inheritance.d.ts +36 -5
  104. package/dist/v1/language/class/inheritance.js +87 -1
  105. package/dist/v1/language/class/lifetime.d.ts +50 -11
  106. package/dist/v1/language/class/lifetime.js +89 -20
  107. package/dist/v1/language/class/model/class.d.ts +45 -9
  108. package/dist/v1/language/class/model/edge.d.ts +31 -2
  109. package/dist/v1/language/class/model/property.d.ts +16 -7
  110. package/dist/v1/language/class/property-values.js +2 -4
  111. package/dist/v1/language/class/unique.d.ts +143 -0
  112. package/dist/v1/language/class/unique.js +264 -0
  113. package/dist/v1/language/core/facts.d.ts +85 -0
  114. package/dist/v1/language/core/facts.js +116 -0
  115. package/dist/v1/language/definition/metadata.d.ts +5 -0
  116. package/dist/v1/language/definition/metadata.js +7 -0
  117. package/dist/v1/language/freeze.d.ts +5 -0
  118. package/dist/v1/{schema/canonical → language}/freeze.js +4 -0
  119. package/dist/v1/language/index.d.ts +7 -2
  120. package/dist/v1/language/index.js +5 -1
  121. package/dist/v1/language/limits.d.ts +64 -0
  122. package/dist/v1/language/limits.js +60 -0
  123. package/dist/v1/language/policy/analysis/branches.d.ts +8 -0
  124. package/dist/v1/language/policy/analysis/branches.js +2 -1
  125. package/dist/v1/language/policy/analysis/budgets.d.ts +45 -12
  126. package/dist/v1/language/policy/analysis/budgets.js +133 -19
  127. package/dist/v1/language/policy/analysis/checks.js +3 -2
  128. package/dist/v1/language/policy/analysis/typing.d.ts +51 -0
  129. package/dist/v1/language/policy/analysis/typing.js +455 -0
  130. package/dist/v1/language/policy/model/policy.d.ts +49 -9
  131. package/dist/v1/language/policy/model/policy.js +14 -0
  132. package/dist/v1/language/policy/normalization/normalize.d.ts +6 -6
  133. package/dist/v1/language/policy/normalization/normalize.js +22 -21
  134. package/dist/v1/language/validation/diagnostic.d.ts +15 -1
  135. package/dist/v1/language/validation/diagnostic.js +21 -0
  136. package/dist/v1/language/validation/rule.d.ts +45 -0
  137. package/dist/v1/language/validation/rule.js +109 -0
  138. package/dist/v1/language/value/compile/fields.js +4 -8
  139. package/dist/v1/language/value/evaluate/program.d.ts +2 -1
  140. package/dist/v1/language/value/evaluate/program.js +2 -2
  141. package/dist/v1/language/value/evaluate/validate.d.ts +2 -2
  142. package/dist/v1/language/value/evaluate/validate.js +6 -2
  143. package/dist/v1/language/value/evaluate/validity.optimization.d.ts +14 -0
  144. package/dist/v1/language/value/evaluate/validity.optimization.js +342 -0
  145. package/dist/v1/language/value/inclusion/arrays.d.ts +3 -0
  146. package/dist/v1/language/value/inclusion/arrays.js +85 -0
  147. package/dist/v1/language/value/inclusion/assertions.d.ts +18 -0
  148. package/dist/v1/language/value/inclusion/assertions.js +29 -0
  149. package/dist/v1/language/value/inclusion/combinators.d.ts +3 -0
  150. package/dist/v1/language/value/inclusion/combinators.js +67 -0
  151. package/dist/v1/language/value/inclusion/equivalence.d.ts +4 -0
  152. package/dist/v1/language/value/inclusion/equivalence.js +74 -0
  153. package/dist/v1/language/value/inclusion/evidence.d.ts +34 -0
  154. package/dist/v1/language/value/inclusion/evidence.js +138 -0
  155. package/dist/v1/language/value/inclusion/includes.d.ts +17 -0
  156. package/dist/v1/language/value/inclusion/includes.js +25 -719
  157. package/dist/v1/language/value/inclusion/keywords.d.ts +5 -0
  158. package/dist/v1/language/value/inclusion/keywords.js +31 -0
  159. package/dist/v1/language/value/inclusion/kinds.d.ts +17 -0
  160. package/dist/v1/language/value/inclusion/kinds.js +57 -0
  161. package/dist/v1/language/value/inclusion/location.d.ts +24 -0
  162. package/dist/v1/language/value/inclusion/location.js +63 -0
  163. package/dist/v1/language/value/inclusion/numbers.d.ts +3 -0
  164. package/dist/v1/language/value/inclusion/numbers.js +41 -0
  165. package/dist/v1/language/value/inclusion/objects.d.ts +3 -0
  166. package/dist/v1/language/value/inclusion/objects.js +190 -0
  167. package/dist/v1/language/value/inclusion/strings.d.ts +3 -0
  168. package/dist/v1/language/value/inclusion/strings.js +29 -0
  169. package/dist/v1/language/value/inclusion/types.d.ts +3 -0
  170. package/dist/v1/language/value/inclusion/types.js +11 -0
  171. package/dist/v1/language/value/ordering.d.ts +14 -0
  172. package/dist/v1/language/value/ordering.js +86 -9
  173. package/dist/v1/language/value/profile/canonicalize.js +6 -5
  174. package/dist/v1/language/value/profile/json.validate.d.ts +3 -1
  175. package/dist/v1/language/value/profile/json.validate.js +3 -2
  176. package/dist/v1/language/value/profile/meta-schema.compiled.js +4 -1
  177. package/dist/v1/language/value/profile/rules.js +17 -43
  178. package/dist/v1/language/value/profile/validate.js +1 -10
  179. package/dist/v1/language/value/profile/vocabulary.d.ts +35 -2
  180. package/dist/v1/language/value/profile/vocabulary.js +52 -5
  181. package/dist/v1/language/value/reference/closure.js +3 -4
  182. package/dist/v1/language/value/reference/recursion.js +2 -22
  183. package/dist/v1/language/value/reference/registry.index.d.ts +2 -0
  184. package/dist/v1/language/value/reference/registry.index.js +33 -16
  185. package/dist/v1/language/value/regexp/ast.js +6 -7
  186. package/dist/v1/language/value/regexp/compile.d.ts +5 -11
  187. package/dist/v1/language/value/regexp/compile.js +14 -12
  188. package/dist/v1/language/value/regexp/syntax.js +3 -2
  189. package/dist/v1/language/value/syntax/keywords.d.ts +3 -3
  190. package/dist/v1/language/value/syntax/keywords.js +4 -20
  191. package/dist/v1/language/value/syntax/node-path/validate.js +2 -3
  192. package/dist/v1/language/value/syntax/pointer.d.ts +2 -0
  193. package/dist/v1/language/value/syntax/pointer.js +5 -2
  194. package/dist/v1/language/value/syntax/walk.d.ts +2 -0
  195. package/dist/v1/language/value/syntax/walk.js +19 -20
  196. package/dist/v1/schema/.spec/schemas/domain-schema.schema.json +2519 -0
  197. package/dist/v1/schema/admission/accept.js +3 -14
  198. package/dist/v1/schema/admission/callable.d.ts +21 -0
  199. package/dist/v1/schema/admission/callable.js +96 -0
  200. package/dist/v1/schema/analysis/class.js +33 -15
  201. package/dist/v1/schema/canonical/revision.js +4 -4
  202. package/dist/v1/schema/compatibility/api.d.ts +2 -1
  203. package/dist/v1/schema/compatibility/api.js +1 -0
  204. package/dist/v1/schema/compatibility/comparators/callables.js +1 -1
  205. package/dist/v1/schema/compatibility/comparators/classes.d.ts +9 -4
  206. package/dist/v1/schema/compatibility/comparators/classes.js +29 -8
  207. package/dist/v1/schema/compatibility/comparators/index.d.ts +1 -1
  208. package/dist/v1/schema/compatibility/comparators/members.js +1 -1
  209. package/dist/v1/schema/compatibility/comparators/values.js +2 -2
  210. package/dist/v1/schema/compatibility/coordinate.js +3 -3
  211. package/dist/v1/schema/compatibility/diff.js +2 -4
  212. package/dist/v1/schema/compatibility/extension.d.ts +11 -0
  213. package/dist/v1/schema/compatibility/extension.js +22 -0
  214. package/dist/v1/schema/compatibility/fields.d.ts +20 -4
  215. package/dist/v1/schema/compatibility/fields.js +13 -3
  216. package/dist/v1/schema/compatibility/meaning/footprint.js +16 -50
  217. package/dist/v1/schema/compatibility/model.d.ts +17 -5
  218. package/dist/v1/schema/compatibility/report.js +1 -1
  219. package/dist/v1/schema/compatibility/scope.d.ts +2 -0
  220. package/dist/v1/schema/compatibility/scope.js +4 -1
  221. package/dist/v1/schema/compatibility/structure/index.js +6 -4
  222. package/dist/v1/schema/compatibility/structure/requirements.js +57 -58
  223. package/dist/v1/schema/compatibility/versioning/index.js +1 -1
  224. package/dist/v1/schema/compatibility/versioning/surface.d.ts +1 -1
  225. package/dist/v1/schema/compatibility/versioning/surface.js +30 -2
  226. package/dist/v1/schema/compatibility/walk.d.ts +17 -0
  227. package/dist/v1/schema/compatibility/walk.js +41 -0
  228. package/dist/v1/schema/diagnostic.d.ts +17 -3
  229. package/dist/v1/schema/diagnostic.js +14 -11
  230. package/dist/v1/schema/index.d.ts +10 -1
  231. package/dist/v1/schema/index.js +4 -0
  232. package/dist/v1/schema/model/schema.d.ts +20 -1
  233. package/dist/v1/schema/model/schema.js +1 -1
  234. package/dist/v1/schema/normalization/domain.d.ts +2 -0
  235. package/dist/v1/schema/normalization/domain.js +29 -9
  236. package/dist/v1/schema/resolution/closure.js +2 -1
  237. package/dist/v1/schema/resolution/context.js +13 -13
  238. package/dist/v1/schema/resolution/domain.d.ts +5 -0
  239. package/dist/v1/schema/resolution/domain.js +2 -2
  240. package/dist/v1/schema/resolution/origins.js +3 -2
  241. package/dist/v1/schema/rule.d.ts +26 -0
  242. package/dist/v1/schema/rule.js +440 -0
  243. package/dist/v1/schema/validation/callable.d.ts +35 -2
  244. package/dist/v1/schema/validation/callable.js +65 -9
  245. package/dist/v1/schema/validation/class.d.ts +6 -2
  246. package/dist/v1/schema/validation/class.js +127 -104
  247. package/dist/v1/schema/validation/core.js +90 -168
  248. package/dist/v1/schema/validation/domain.js +4 -13
  249. package/dist/v1/schema/validation/domain.json-schema.d.ts +15 -0
  250. package/dist/v1/schema/validation/domain.json-schema.js +197 -0
  251. package/dist/v1/schema/validation/domain.route.d.ts +6 -1
  252. package/dist/v1/schema/validation/domain.route.js +18 -0
  253. package/dist/v1/schema/validation/domain.structure.d.ts +7780 -0
  254. package/dist/v1/schema/validation/domain.structure.js +398 -147
  255. package/dist/v1/schema/validation/json.json-schema.d.ts +40 -0
  256. package/dist/v1/schema/validation/json.json-schema.js +46 -0
  257. package/dist/v1/schema/validation/policy/budgets.d.ts +33 -2
  258. package/dist/v1/schema/validation/policy/budgets.js +87 -121
  259. package/dist/v1/schema/validation/policy/context.d.ts +6 -5
  260. package/dist/v1/schema/validation/policy/context.js +7 -10
  261. package/dist/v1/schema/validation/policy/objects.d.ts +1 -1
  262. package/dist/v1/schema/validation/policy/objects.js +6 -14
  263. package/dist/v1/schema/validation/policy/references.js +11 -27
  264. package/dist/v1/schema/validation/policy/typing.d.ts +3 -18
  265. package/dist/v1/schema/validation/policy/typing.js +22 -356
  266. package/dist/v1/schema/validation/policy/uses.d.ts +40 -3
  267. package/dist/v1/schema/validation/policy/uses.js +66 -89
  268. package/dist/v1/schema/validation/policy/validate.js +5 -5
  269. package/dist/v1/schema/validation/value-api.d.ts +22 -0
  270. package/dist/v1/schema/validation/value-api.js +34 -1
  271. package/dist/v1/schema/validation/value.d.ts +3 -0
  272. package/dist/v1/schema/validation/value.js +9 -17
  273. package/dist/v1/schema/validation/value.json-schema.d.ts +49 -0
  274. package/dist/v1/schema/validation/value.json-schema.js +137 -0
  275. package/dist/v1/schema/validation/view.js +4 -8
  276. package/dist/value/canonical.d.ts +6 -0
  277. package/dist/value/canonical.js +36 -0
  278. package/dist/value/decode.d.ts +7 -0
  279. package/dist/value/decode.js +159 -9
  280. package/dist/value/index.d.ts +1 -1
  281. package/dist/value/json.d.ts +2 -2
  282. package/dist/value/json.js +2 -2
  283. package/dist/value/types.d.ts +6 -0
  284. package/dist/value/unicode.d.ts +2 -1
  285. package/dist/value/unicode.js +2 -0
  286. package/package.json +8 -1
  287. package/dist/v1/builder/lowering/core-properties.d.ts +0 -10
  288. package/dist/v1/builder/lowering/core-properties.js +0 -76
  289. package/dist/v1/compiled/admission/semantics/cardinality.d.ts +0 -5
  290. package/dist/v1/compiled/admission/semantics/cardinality.js +0 -113
  291. package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +0 -8
  292. package/dist/v1/compiled/admission/semantics/policy/equality.js +0 -27
  293. package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +0 -9
  294. package/dist/v1/compiled/admission/semantics/policy/measure.js +0 -81
  295. package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +0 -10
  296. package/dist/v1/compiled/admission/semantics/policy/variants.js +0 -65
  297. package/dist/v1/language/class/index.d.ts +0 -8
  298. package/dist/v1/language/class/index.js +0 -1
  299. package/dist/v1/language/core/index.d.ts +0 -2
  300. package/dist/v1/language/value/index.d.ts +0 -11
  301. package/dist/v1/language/value/index.js +0 -8
  302. package/dist/v1/schema/canonical/domain.d.ts +0 -3
  303. package/dist/v1/schema/canonical/domain.digest.d.ts +0 -3
  304. package/dist/v1/schema/canonical/domain.digest.js +0 -5
  305. package/dist/v1/schema/canonical/domain.js +0 -5
  306. package/dist/v1/schema/canonical/freeze.d.ts +0 -1
  307. /package/dist/v1/{language/core/index.js → builder/class/input.js} +0 -0
@@ -7,10 +7,11 @@ const TYPE_RANK = new Map(TYPE_ORDER.map((name, index) => [name, index]));
7
7
  const encoder = new TextEncoder();
8
8
  /** Canonicalizes syntax without rewriting the schema's algebra. Validate first. */
9
9
  export function canonicalizeValueSchema(schema, context, registry) {
10
+ void context;
10
11
  void registry;
11
- return canonicalizeSchema(schema, true, context);
12
+ return canonicalizeSchema(schema, true);
12
13
  }
13
- function canonicalizeSchema(schema, root, context) {
14
+ function canonicalizeSchema(schema, root) {
14
15
  if (typeof schema === 'boolean')
15
16
  return schema;
16
17
  const result = {};
@@ -39,17 +40,17 @@ function canonicalizeSchema(schema, root, context) {
39
40
  result[keyword] = canonicalizePathAnnotation(value);
40
41
  }
41
42
  else if (SCHEMA_SINGLE_KEYWORDS.has(keyword) && isJsonSchema(value)) {
42
- result[keyword] = canonicalizeSchema(value, false, context);
43
+ result[keyword] = canonicalizeSchema(value, false);
43
44
  }
44
45
  else if (SCHEMA_ARRAY_KEYWORDS.has(keyword) && Array.isArray(value)) {
45
- result[keyword] = value.map((entry) => isJsonSchema(entry) ? canonicalizeSchema(entry, false, context) : canonicalizeJson(entry));
46
+ result[keyword] = value.map((entry) => isJsonSchema(entry) ? canonicalizeSchema(entry, false) : canonicalizeJson(entry));
46
47
  }
47
48
  else if (SCHEMA_MAP_KEYWORDS.has(keyword) && isJsonObject(value)) {
48
49
  const schemas = {};
49
50
  for (const name of Object.keys(value).sort()) {
50
51
  const entry = value[name];
51
52
  schemas[name] = isJsonSchema(entry)
52
- ? canonicalizeSchema(entry, false, context)
53
+ ? canonicalizeSchema(entry, false)
53
54
  : canonicalizeJson(entry);
54
55
  }
55
56
  result[keyword] = schemas;
@@ -1,2 +1,4 @@
1
+ import { type Options } from '@astrale-os/kernel-dsl/value';
1
2
  import type { Diagnostic } from '../../validation/diagnostic.js';
2
- export declare function validateCanonicalJsonDomain(value: unknown, pointer: string): readonly Diagnostic[];
3
+ /** Whether `value` is a portable JSON Value, within the portable limits `options` overrides. */
4
+ export declare function validateCanonicalJsonDomain(value: unknown, pointer: string, options?: Options): readonly Diagnostic[];
@@ -1,8 +1,9 @@
1
1
  import { acceptForRead as acceptJsonValue, BoundaryError as JsonBoundaryError, } from '@astrale-os/kernel-dsl/value';
2
2
  import { diagnostic } from '../../validation/diagnostic.js';
3
- export function validateCanonicalJsonDomain(value, pointer) {
3
+ /** Whether `value` is a portable JSON Value, within the portable limits `options` overrides. */
4
+ export function validateCanonicalJsonDomain(value, pointer, options) {
4
5
  try {
5
- acceptJsonValue(value);
6
+ acceptJsonValue(value, options);
6
7
  return [];
7
8
  }
8
9
  catch (error) {
@@ -4,7 +4,7 @@
4
4
  "use strict";
5
5
  export const validate = validate20;
6
6
  export default validate20;
7
- const schema31 = { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.astrale.ai/dsl/v1/value-schema", "$vocabulary": {}, "allOf": [{ "$ref": "https://json-schema.org/draft/2020-12/schema" }], "properties": { "fullMatch": { "type": "string" }, "x-astrale-path": { "type": "object" } } };
7
+ const schema31 = { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://schemas.astrale.ai/dsl/v1/value-schema", "$dynamicAnchor": "meta", "$vocabulary": { "https://json-schema.org/draft/2020-12/vocab/core": true, "https://json-schema.org/draft/2020-12/vocab/applicator": true, "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, "https://json-schema.org/draft/2020-12/vocab/validation": true, "https://json-schema.org/draft/2020-12/vocab/meta-data": true, "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, "https://json-schema.org/draft/2020-12/vocab/content": true, "https://schemas.astrale.ai/dsl/v1/value-schema/vocabulary": true }, "title": "Astrale V1 value schema", "$comment": "The meta-schema of the V1 value-schema dialect: Draft 2020-12 and the required Astrale vocabulary (fullMatch, x-astrale-path, x-astrale-value-kind). Its $dynamicAnchor extends Draft 2020-12 at every subschema, not only the root. The rules of the profile beyond it are published as schema.values.RULES.", "allOf": [{ "$ref": "https://json-schema.org/draft/2020-12/schema" }], "properties": { "fullMatch": { "type": "string" }, "x-astrale-path": { "type": "object" } } };
8
8
  const schema0 = { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://json-schema.org/draft/2020-12/schema", "$vocabulary": { "https://json-schema.org/draft/2020-12/vocab/core": true, "https://json-schema.org/draft/2020-12/vocab/applicator": true, "https://json-schema.org/draft/2020-12/vocab/unevaluated": true, "https://json-schema.org/draft/2020-12/vocab/validation": true, "https://json-schema.org/draft/2020-12/vocab/meta-data": true, "https://json-schema.org/draft/2020-12/vocab/format-annotation": true, "https://json-schema.org/draft/2020-12/vocab/content": true }, "$dynamicAnchor": "meta", "title": "Core and Validation specifications meta-schema", "allOf": [{ "$ref": "meta/core" }, { "$ref": "meta/applicator" }, { "$ref": "meta/unevaluated" }, { "$ref": "meta/validation" }, { "$ref": "meta/meta-data" }, { "$ref": "meta/format-annotation" }, { "$ref": "meta/content" }], "type": ["object", "boolean"], "$comment": "This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.", "properties": { "definitions": { "$comment": "\"definitions\" has been replaced by \"$defs\".", "type": "object", "additionalProperties": { "$dynamicRef": "#meta" }, "deprecated": true, "default": {} }, "dependencies": { "$comment": "\"dependencies\" has been split and replaced by \"dependentSchemas\" and \"dependentRequired\" in order to serve their differing semantics.", "type": "object", "additionalProperties": { "anyOf": [{ "$dynamicRef": "#meta" }, { "$ref": "meta/validation#/$defs/stringArray" }] }, "deprecated": true, "default": {} }, "$recursiveAnchor": { "$comment": "\"$recursiveAnchor\" has been replaced by \"$dynamicAnchor\".", "$ref": "meta/core#/$defs/anchorString", "deprecated": true }, "$recursiveRef": { "$comment": "\"$recursiveRef\" has been replaced by \"$dynamicRef\".", "$ref": "meta/core#/$defs/uriReferenceString", "deprecated": true } } };
9
9
  const schema23 = { "type": "array", "items": { "type": "string" }, "uniqueItems": true, "default": [] };
10
10
  const schema5 = { "type": "string", "pattern": "^[A-Za-z_][-A-Za-z0-9._]*$" };
@@ -2042,6 +2042,9 @@ function validate20(data, { instancePath = "", parentData, parentDataProperty, r
2042
2042
  if (evaluated0.dynamicItems) {
2043
2043
  evaluated0.items = undefined;
2044
2044
  }
2045
+ if (!dynamicAnchors.meta) {
2046
+ dynamicAnchors.meta = validate20;
2047
+ }
2045
2048
  if (!(validate0(data, { instancePath, parentData, parentDataProperty, rootData, dynamicAnchors }))) {
2046
2049
  vErrors = vErrors === null ? validate0.errors : vErrors.concat(validate0.errors);
2047
2050
  errors = vErrors.length;
@@ -4,8 +4,11 @@ import { blob, BLOB_VALUE_KIND } from '../model/blob.js';
4
4
  import { isValueObject as isJsonObject } from '../model/object.js';
5
5
  import { VALUE_SCHEMA_DIALECT } from '../model/schema.js';
6
6
  import { refuseIRegexp, stateBudgetMessage } from '../regexp/syntax.js';
7
+ import { escapePointerToken } from '../syntax/pointer.js';
7
8
  import { walkSchema } from '../syntax/walk.js';
8
- import { FORBIDDEN_DYNAMIC_KEYWORDS, STANDARD_SCHEMA_KEYWORDS } from './vocabulary.js';
9
+ import { FORBIDDEN_KEYWORDS, VALUE_KEYWORDS } from './vocabulary.js';
10
+ const KEYWORDS = new Set(VALUE_KEYWORDS);
11
+ const FORBIDDEN = new Set(FORBIDDEN_KEYWORDS);
9
12
  export function validateSchemaProfile(schema, context, pointer) {
10
13
  const diagnostics = [];
11
14
  walkSchema(schema, (location) => {
@@ -13,11 +16,11 @@ export function validateSchemaProfile(schema, context, pointer) {
13
16
  return;
14
17
  const currentPointer = `${pointer}${location.pointer}`;
15
18
  for (const keyword of Object.keys(location.schema)) {
16
- if (!STANDARD_SCHEMA_KEYWORDS.has(keyword)) {
17
- diagnostics.push(diagnostic('VS_KEYWORD_CLOSED', `${currentPointer}/${escapeToken(keyword)}`, `Keyword ${keyword} is outside the closed V1 Draft 2020-12 vocabulary.`));
19
+ if (!KEYWORDS.has(keyword)) {
20
+ diagnostics.push(diagnostic('VS_KEYWORD_CLOSED', `${currentPointer}/${escapePointerToken(keyword)}`, `Keyword ${keyword} is outside the closed V1 Draft 2020-12 vocabulary.`));
18
21
  }
19
- if (FORBIDDEN_DYNAMIC_KEYWORDS.has(keyword)) {
20
- diagnostics.push(diagnostic('VS_DYNAMIC_FORBIDDEN', `${currentPointer}/${escapeToken(keyword)}`, `Keyword ${keyword} is forbidden by V1.`));
22
+ if (FORBIDDEN.has(keyword)) {
23
+ diagnostics.push(diagnostic('VS_DYNAMIC_FORBIDDEN', `${currentPointer}/${escapePointerToken(keyword)}`, `Keyword ${keyword} is forbidden by V1.`));
21
24
  }
22
25
  }
23
26
  if (Object.hasOwn(location.schema, '$schema')) {
@@ -28,7 +31,11 @@ export function validateSchemaProfile(schema, context, pointer) {
28
31
  if (Object.hasOwn(location.schema, '$id')) {
29
32
  diagnostics.push(diagnostic('VS_RESOURCE_ID', `${currentPointer}/$id`, '$id is forbidden in an embedded V1 value schema.'));
30
33
  }
31
- validateSemanticSets(location.schema, currentPointer, diagnostics);
34
+ // The dialect refuses a repeated type, required or dependentRequired entry; it lets an enum
35
+ // repeat a value.
36
+ if (Array.isArray(location.schema.enum)) {
37
+ rejectCanonicalDuplicates(location.schema.enum, `${currentPointer}/enum`, diagnostics);
38
+ }
32
39
  validateValueKind(location.schema, context, location.depth, currentPointer, diagnostics);
33
40
  validateRegexes(location.schema, currentPointer, diagnostics);
34
41
  });
@@ -73,28 +80,8 @@ function isCanonicalBlobSchema(input) {
73
80
  function isString(input) {
74
81
  return typeof input === 'string';
75
82
  }
76
- function validateSemanticSets(schema, pointer, diagnostics) {
77
- if (Array.isArray(schema.type)) {
78
- rejectPrimitiveDuplicates(schema.type, `${pointer}/type`, 'type', diagnostics);
79
- }
80
- if (Array.isArray(schema.required)) {
81
- rejectPrimitiveDuplicates(schema.required, `${pointer}/required`, 'required', diagnostics);
82
- }
83
- if (Array.isArray(schema.enum)) {
84
- rejectCanonicalDuplicates(schema.enum, `${pointer}/enum`, 'enum', diagnostics);
85
- }
86
- if (isJsonObject(schema.dependentRequired)) {
87
- for (const [name, dependencies] of Object.entries(schema.dependentRequired)) {
88
- if (Array.isArray(dependencies)) {
89
- rejectPrimitiveDuplicates(dependencies, `${pointer}/dependentRequired/${escapeToken(name)}`, 'dependentRequired', diagnostics);
90
- }
91
- }
92
- }
93
- }
83
+ /** The dialect refuses a fullMatch that is not a string, at every location. */
94
84
  function validateRegexes(schema, pointer, diagnostics) {
95
- if (Object.hasOwn(schema, 'fullMatch') && typeof schema.fullMatch !== 'string') {
96
- diagnostics.push(diagnostic('VS_META_SCHEMA', `${pointer}/fullMatch`, 'fullMatch must be an I-Regexp source string.'));
97
- }
98
85
  if (typeof schema.fullMatch === 'string') {
99
86
  portableRegex(schema.fullMatch, `${pointer}/fullMatch`, 'fullMatch', 'fullMatch must satisfy the complete RFC 9485 I-Regexp syntax.', diagnostics);
100
87
  }
@@ -103,7 +90,7 @@ function validateRegexes(schema, pointer, diagnostics) {
103
90
  }
104
91
  if (isJsonObject(schema.patternProperties)) {
105
92
  for (const pattern of Object.keys(schema.patternProperties)) {
106
- portableRegex(pattern, `${pointer}/patternProperties/${escapeToken(pattern)}`, 'A patternProperties key', 'patternProperties keys must satisfy RFC 9485 I-Regexp syntax.', diagnostics);
93
+ portableRegex(pattern, `${pointer}/patternProperties/${escapePointerToken(pattern)}`, 'A patternProperties key', 'patternProperties keys must satisfy RFC 9485 I-Regexp syntax.', diagnostics);
107
94
  }
108
95
  }
109
96
  }
@@ -113,17 +100,7 @@ function portableRegex(source, pointer, subject, syntax, diagnostics) {
113
100
  return;
114
101
  diagnostics.push(diagnostic('VS_REGEX_PORTABLE', pointer, refusal === 'syntax' ? syntax : stateBudgetMessage(subject)));
115
102
  }
116
- function rejectPrimitiveDuplicates(values, pointer, name, diagnostics) {
117
- const seen = new Set();
118
- for (const value of values) {
119
- if (seen.has(value)) {
120
- diagnostics.push(diagnostic('VS_META_SCHEMA', pointer, `${name} is a duplicate-free semantic set.`));
121
- return;
122
- }
123
- seen.add(value);
124
- }
125
- }
126
- function rejectCanonicalDuplicates(values, pointer, name, diagnostics) {
103
+ function rejectCanonicalDuplicates(values, pointer, diagnostics) {
127
104
  const seen = new Set();
128
105
  for (const value of values) {
129
106
  let key;
@@ -134,12 +111,9 @@ function rejectCanonicalDuplicates(values, pointer, name, diagnostics) {
134
111
  continue;
135
112
  }
136
113
  if (seen.has(key)) {
137
- diagnostics.push(diagnostic('VS_META_SCHEMA', pointer, `${name} rejects canonically equal duplicates.`));
114
+ diagnostics.push(diagnostic('VS_META_SCHEMA', pointer, 'enum rejects canonically equal duplicates.'));
138
115
  return;
139
116
  }
140
117
  seen.add(key);
141
118
  }
142
119
  }
143
- function escapeToken(value) {
144
- return value.replaceAll('~', '~0').replaceAll('/', '~1');
145
- }
@@ -1,4 +1,4 @@
1
- import { compareUnicode } from '../../../addressing/ordering.js';
1
+ import { orderAndDeduplicate } from '../../validation/diagnostic.js';
2
2
  import { collectResourceClosure } from '../reference/closure.js';
3
3
  import { validateProductiveRecursion } from '../reference/recursion.js';
4
4
  import { hasNodeDefinition, indexRegistry } from '../reference/registry.index.js';
@@ -28,12 +28,3 @@ export function validateValueSchema(schema, context, registry, pointer = '') {
28
28
  diagnostics.push(...validateProductiveRecursion(closure.resources, closure.resolutions));
29
29
  return orderAndDeduplicate(diagnostics);
30
30
  }
31
- function orderAndDeduplicate(diagnostics) {
32
- const unique = new Map();
33
- for (const value of diagnostics) {
34
- unique.set(`${value.pointer}\u0000${value.code}\u0000${value.ref ?? ''}\u0000${value.message}`, value);
35
- }
36
- return [...unique.values()].sort((left, right) => compareUnicode(left.pointer, right.pointer) ||
37
- compareUnicode(left.code, right.code) ||
38
- compareUnicode(left.message, right.message));
39
- }
@@ -1,2 +1,35 @@
1
- export declare const STANDARD_SCHEMA_KEYWORDS: Set<string>;
2
- export declare const FORBIDDEN_DYNAMIC_KEYWORDS: Set<string>;
1
+ declare const keywords: readonly ['$anchor', '$comment', '$defs', '$dynamicAnchor', '$dynamicRef', '$id', '$ref', '$schema', '$vocabulary', 'additionalProperties', 'allOf', 'anyOf', 'const', 'contains', 'contentEncoding', 'contentMediaType', 'contentSchema', 'default', 'dependentRequired', 'dependentSchemas', 'deprecated', 'description', 'else', 'enum', 'examples', 'exclusiveMaximum', 'exclusiveMinimum', 'format', 'fullMatch', 'if', 'items', 'maxContains', 'maxItems', 'maxLength', 'maxProperties', 'maximum', 'minContains', 'minItems', 'minLength', 'minProperties', 'minimum', 'multipleOf', 'not', 'oneOf', 'pattern', 'patternProperties', 'prefixItems', 'properties', 'propertyNames', 'readOnly', 'required', 'then', 'title', 'type', 'unevaluatedItems', 'unevaluatedProperties', 'uniqueItems', 'writeOnly', 'x-astrale-path', 'x-astrale-value-kind'];
2
+ export type ValueKeyword = (typeof keywords)[number];
3
+ /**
4
+ * The closed V1 vocabulary: every keyword a value schema may name, the Astrale profile's included
5
+ * (`fullMatch`, `x-astrale-path`, `x-astrale-value-kind`). Any other keyword is refused
6
+ * (`VS_KEYWORD_CLOSED`). Other rules restrict some of these: the forbidden keywords never appear,
7
+ * `$id` never, `$schema` only at the root. Frozen and Unicode-ordered.
8
+ */
9
+ export declare const VALUE_KEYWORDS: readonly ValueKeyword[];
10
+ /** The keywords of the vocabulary refused wherever they appear (`VS_DYNAMIC_FORBIDDEN`). */
11
+ export declare const FORBIDDEN_KEYWORDS: readonly ValueKeyword[];
12
+ /**
13
+ * The keywords whose value holds subschemas, by its shape: one schema, an array of schemas, or an
14
+ * object of named schemas. A value schema's locations are its root and the subschemas these hold.
15
+ */
16
+ export declare const SUBSCHEMA_KEYWORDS: {
17
+ readonly single: readonly ValueKeyword[];
18
+ readonly array: readonly ValueKeyword[];
19
+ readonly map: readonly ValueKeyword[];
20
+ };
21
+ /** A value kind a schema declares with `x-astrale-value-kind`, because no JSON type gives it. */
22
+ export interface DeclaredValueKind {
23
+ /** The JSON type of its values, which the schema states beside the declaration. */
24
+ readonly type: 'string' | 'object';
25
+ /**
26
+ * Where a schema may declare it: at any location of any value schema, or only as the whole
27
+ * schema of a Node Property that is neither automatic nor a State Property.
28
+ */
29
+ readonly placement: 'any' | 'node-property';
30
+ /** The kind, in one plain sentence. */
31
+ readonly statement: string;
32
+ }
33
+ /** The value kinds `x-astrale-value-kind` declares; it admits no other value. */
34
+ export declare const DECLARED_VALUE_KINDS: Readonly<Record<'instant' | 'blob', DeclaredValueKind>>;
35
+ export {};
@@ -1,4 +1,4 @@
1
- export const STANDARD_SCHEMA_KEYWORDS = new Set([
1
+ const keywords = [
2
2
  '$anchor',
3
3
  '$comment',
4
4
  '$defs',
@@ -31,15 +31,15 @@ export const STANDARD_SCHEMA_KEYWORDS = new Set([
31
31
  'if',
32
32
  'items',
33
33
  'maxContains',
34
- 'maximum',
35
34
  'maxItems',
36
35
  'maxLength',
37
36
  'maxProperties',
37
+ 'maximum',
38
38
  'minContains',
39
- 'minimum',
40
39
  'minItems',
41
40
  'minLength',
42
41
  'minProperties',
42
+ 'minimum',
43
43
  'multipleOf',
44
44
  'not',
45
45
  'oneOf',
@@ -59,10 +59,57 @@ export const STANDARD_SCHEMA_KEYWORDS = new Set([
59
59
  'writeOnly',
60
60
  'x-astrale-path',
61
61
  'x-astrale-value-kind',
62
- ]);
63
- export const FORBIDDEN_DYNAMIC_KEYWORDS = new Set([
62
+ ];
63
+ /**
64
+ * The closed V1 vocabulary: every keyword a value schema may name, the Astrale profile's included
65
+ * (`fullMatch`, `x-astrale-path`, `x-astrale-value-kind`). Any other keyword is refused
66
+ * (`VS_KEYWORD_CLOSED`). Other rules restrict some of these: the forbidden keywords never appear,
67
+ * `$id` never, `$schema` only at the root. Frozen and Unicode-ordered.
68
+ */
69
+ export const VALUE_KEYWORDS = Object.freeze(keywords);
70
+ /** The keywords of the vocabulary refused wherever they appear (`VS_DYNAMIC_FORBIDDEN`). */
71
+ export const FORBIDDEN_KEYWORDS = Object.freeze([
64
72
  '$anchor',
65
73
  '$dynamicAnchor',
66
74
  '$dynamicRef',
67
75
  '$vocabulary',
68
76
  ]);
77
+ /**
78
+ * The keywords whose value holds subschemas, by its shape: one schema, an array of schemas, or an
79
+ * object of named schemas. A value schema's locations are its root and the subschemas these hold.
80
+ */
81
+ export const SUBSCHEMA_KEYWORDS = Object.freeze({
82
+ single: Object.freeze([
83
+ 'additionalProperties',
84
+ 'contains',
85
+ 'contentSchema',
86
+ 'else',
87
+ 'if',
88
+ 'items',
89
+ 'not',
90
+ 'propertyNames',
91
+ 'then',
92
+ 'unevaluatedItems',
93
+ 'unevaluatedProperties',
94
+ ]),
95
+ array: Object.freeze(['allOf', 'anyOf', 'oneOf', 'prefixItems']),
96
+ map: Object.freeze([
97
+ '$defs',
98
+ 'dependentSchemas',
99
+ 'patternProperties',
100
+ 'properties',
101
+ ]),
102
+ });
103
+ /** The value kinds `x-astrale-value-kind` declares; it admits no other value. */
104
+ export const DECLARED_VALUE_KINDS = Object.freeze({
105
+ instant: Object.freeze({
106
+ type: 'string',
107
+ placement: 'any',
108
+ statement: 'A UTC instant written YYYY-MM-DDTHH:mm:ss.sssZ, in the years 0000 to 9999, whose text order is its chronological order.',
109
+ }),
110
+ blob: Object.freeze({
111
+ type: 'object',
112
+ placement: 'node-property',
113
+ statement: 'The Ref of stored contents, its digest, media type and size: the schema is exactly a values.blob output, and the Property is written with an upload receipt.',
114
+ }),
115
+ });
@@ -36,10 +36,9 @@ export function collectResourceClosure(schema, context, index, pointer) {
36
36
  const target = result.resolved.resource;
37
37
  if (resources.has(target.key))
38
38
  return;
39
- const registered = {
40
- ...target,
41
- diagnosticPointer: `${pointer}/registry/graphNodePath`,
42
- };
39
+ // The graph NodePath resource is no part of the schema: what it holds is reported at the
40
+ // $ref that names it.
41
+ const registered = { ...target, diagnosticPointer: refPointer };
43
42
  resources.set(target.key, registered);
44
43
  queue.push(registered);
45
44
  });
@@ -1,8 +1,7 @@
1
1
  import { diagnostic } from '../../validation/diagnostic.js';
2
2
  import { isValueObject as isJsonObject } from '../model/object.js';
3
- import { SCHEMA_ARRAY_KEYWORDS, SCHEMA_MAP_KEYWORDS, SCHEMA_SINGLE_KEYWORDS, } from '../syntax/keywords.js';
4
3
  import { appendPointer } from '../syntax/pointer.js';
5
- import { isJsonSchema, walkSchema } from '../syntax/walk.js';
4
+ import { forEachSubschema, walkSchema } from '../syntax/walk.js';
6
5
  import { locationKey } from './closure.js';
7
6
  export const CONSUMING_SCHEMA_KEYWORDS = new Set([
8
7
  'additionalProperties',
@@ -43,26 +42,7 @@ export function validateProductiveRecursion(resources, resolutions) {
43
42
  for (const [keyword, value] of Object.entries(location.schema)) {
44
43
  if (!NON_CONSUMING_SCHEMA_KEYWORDS.has(keyword))
45
44
  continue;
46
- const keywordPointer = appendPointer(location.pointer, keyword);
47
- if (SCHEMA_SINGLE_KEYWORDS.has(keyword) && isJsonSchema(value)) {
48
- outgoing.add(locationKey(resource.key, keywordPointer));
49
- continue;
50
- }
51
- if (SCHEMA_ARRAY_KEYWORDS.has(keyword) && Array.isArray(value)) {
52
- value.forEach((entry, index) => {
53
- if (isJsonSchema(entry)) {
54
- outgoing.add(locationKey(resource.key, appendPointer(keywordPointer, index)));
55
- }
56
- });
57
- continue;
58
- }
59
- if (SCHEMA_MAP_KEYWORDS.has(keyword) && isJsonObject(value)) {
60
- for (const [name, entry] of Object.entries(value)) {
61
- if (isJsonSchema(entry)) {
62
- outgoing.add(locationKey(resource.key, appendPointer(keywordPointer, name)));
63
- }
64
- }
65
- }
45
+ forEachSubschema(keyword, value, appendPointer(location.pointer, keyword), (_, at) => outgoing.add(locationKey(resource.key, at)));
66
46
  }
67
47
  });
68
48
  }
@@ -5,6 +5,8 @@ export interface RegistryIndex {
5
5
  readonly registry: ValueSchemaRegistry;
6
6
  readonly domains: ReadonlyMap<string, ValueSchemaDomainRegistry>;
7
7
  readonly dependenciesByOwner: ReadonlyMap<string, ReadonlyMap<string, string>>;
8
+ /** The `definitionRefIndex` of each Node Definition its own Domain lists. */
9
+ readonly nodeDefinitions: ReadonlySet<string>;
8
10
  }
9
11
  export declare function indexRegistry(registry: ValueSchemaRegistry, pointer: string): {
10
12
  readonly index: RegistryIndex;
@@ -4,11 +4,21 @@ import { diagnostic } from '../../validation/diagnostic.js';
4
4
  import { isValueObject as isJsonObject } from '../model/object.js';
5
5
  import { JSON_SCHEMA_DIALECT } from '../model/schema.js';
6
6
  import { GRAPH_NODE_PATH_SCHEMA_ID } from '../syntax/node-path/schema.js';
7
+ // A registry is an immutable value, and every value schema of a Domain is validated against the
8
+ // same one: an index that admitted it without a diagnostic is reused, so the closure is indexed
9
+ // once per registry rather than once per value schema.
10
+ const admittedIndexes = new WeakMap();
7
11
  export function indexRegistry(registry, pointer) {
12
+ const admitted = admittedIndexes.get(registry);
13
+ if (admitted !== undefined)
14
+ return { index: admitted, diagnostics: [] };
8
15
  const diagnostics = [];
9
16
  const domains = new Map();
10
17
  domains.set(registry.current.origin, registry.current);
11
- validateDomainRegistry(registry.current, `${pointer}/registry/current`, false, diagnostics);
18
+ // The registry is the closure the Kernel builds for the schema at `pointer`, not a document: a
19
+ // fault of one of its entries is a fault of the closure that schema is checked with, reported
20
+ // there, the entry named in the message.
21
+ validateDomainRegistry(registry.current, 'current', false, pointer, diagnostics);
12
22
  const dependencies = [
13
23
  ...registry.directDependencies.map((domain) => ({ domain, lane: 'directDependencies' })),
14
24
  ...registry.transitiveDependencies.map((domain) => ({
@@ -17,10 +27,9 @@ export function indexRegistry(registry, pointer) {
17
27
  })),
18
28
  ];
19
29
  dependencies.forEach(({ domain, lane }, index) => {
20
- const domainPointer = `${pointer}/registry/${lane}/${index}`;
21
- validateDomainRegistry(domain, domainPointer, true, diagnostics);
30
+ validateDomainRegistry(domain, `${lane}/${index}`, true, pointer, diagnostics);
22
31
  if (domain.origin === registry.current.origin || domains.has(domain.origin)) {
23
- diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', domainPointer, `Registry origin ${domain.origin} is duplicated in the exact closure.`));
32
+ diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', pointer, `Registry origin ${domain.origin} is duplicated in the exact closure, at ${lane}/${index}.`));
24
33
  return;
25
34
  }
26
35
  domains.set(domain.origin, domain);
@@ -31,36 +40,44 @@ export function indexRegistry(registry, pointer) {
31
40
  dependenciesByOwner.set(domain.origin, pins);
32
41
  for (const dependency of domain.dependencies) {
33
42
  const target = domains.get(dependency.origin);
43
+ // The schema at `pointer` cannot be judged without the closure it may reference.
34
44
  if (target === undefined || target.revision !== dependency.revision) {
35
- diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', `${pointer}/registry/${domain.origin}/dependencies`, `Registry closure is missing exact ${dependency.origin}@${dependency.revision} required by ${domain.origin}.`));
45
+ diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', pointer, `Registry closure is missing exact ${dependency.origin}@${dependency.revision} required by ${domain.origin}.`));
36
46
  }
37
47
  }
38
48
  }
39
- validateGraphNodePathResource(registry.graphNodePath, `${pointer}/registry/graphNodePath`, diagnostics);
40
- return { index: { registry, domains, dependenciesByOwner }, diagnostics };
49
+ const nodeDefinitions = new Set();
50
+ for (const domain of domains.values()) {
51
+ for (const ref of domain.nodeDefinitions) {
52
+ if (ref.origin === domain.origin)
53
+ nodeDefinitions.add(definitionRefIndex(ref));
54
+ }
55
+ }
56
+ validateGraphNodePathResource(registry.graphNodePath, pointer, diagnostics);
57
+ const index = { registry, domains, dependenciesByOwner, nodeDefinitions };
58
+ if (diagnostics.length === 0)
59
+ admittedIndexes.set(registry, index);
60
+ return { index, diagnostics };
41
61
  }
42
62
  export function isOriginVisibleFrom(index, ownerOrigin, targetOrigin) {
43
63
  return (ownerOrigin === targetOrigin ||
44
64
  index.dependenciesByOwner.get(ownerOrigin)?.has(targetOrigin) === true);
45
65
  }
46
66
  export function hasNodeDefinition(index, ref, ownerOrigin) {
47
- if (!isOriginVisibleFrom(index, ownerOrigin, ref.origin))
48
- return false;
49
- return (index.domains
50
- .get(ref.origin)
51
- ?.nodeDefinitions.some((candidate) => definitionRefIndex(candidate) === definitionRefIndex(ref)) === true);
67
+ return (isOriginVisibleFrom(index, ownerOrigin, ref.origin) &&
68
+ index.nodeDefinitions.has(definitionRefIndex(ref)));
52
69
  }
53
- function validateDomainRegistry(domain, pointer, revisionRequired, diagnostics) {
70
+ function validateDomainRegistry(domain, entry, revisionRequired, pointer, diagnostics) {
54
71
  if (!DOMAIN_ORIGIN_PATTERN.test(domain.origin)) {
55
- diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', `${pointer}/origin`, 'Registry origin is invalid.'));
72
+ diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', pointer, `Registry origin is invalid, at ${entry}.`));
56
73
  }
57
74
  if ((revisionRequired && domain.revision === undefined) ||
58
75
  (domain.revision !== undefined && !DOMAIN_REVISION_PATTERN.test(domain.revision))) {
59
- diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', `${pointer}/revision`, 'A dependency-closure registry entry requires its exact sha256 revision.'));
76
+ diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', pointer, `A dependency-closure registry entry requires its exact sha256 revision, at ${entry}.`));
60
77
  }
61
78
  for (const ref of domain.nodeDefinitions) {
62
79
  if (ref.origin !== domain.origin) {
63
- diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', `${pointer}/nodeDefinitions`, 'A registry domain can list only its own Node Definitions.'));
80
+ diagnostics.push(diagnostic('VS_REFERENCE_RESOLUTION', pointer, `A registry domain can list only its own Node Definitions, at ${entry}.`));
64
81
  }
65
82
  }
66
83
  }
@@ -1,8 +1,7 @@
1
+ import { limits } from '../../limits.js';
1
2
  import { categoryRanges, complement, mergeRanges } from './unicode.js';
2
3
  const CATEGORY = /^(?:L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|Z[lps]?|S[ckmo]?|C[cfno]?)$/u;
3
- const MAX_CODE_POINTS = 4096;
4
- const MAX_NESTING = 32;
5
- const MAX_REPEAT = 1000;
4
+ const { maxCodePoints, maxNesting, maxRepeat } = limits.regexp;
6
5
  const DOT_RANGES = [
7
6
  [0, 9],
8
7
  [11, 12],
@@ -14,7 +13,7 @@ export function parseIRegexp(source) {
14
13
  if (!isUnicodeScalarString(source) || source === '[^]')
15
14
  return undefined;
16
15
  const characters = Array.from(source);
17
- if (characters.length > MAX_CODE_POINTS)
16
+ if (characters.length > maxCodePoints)
18
17
  return undefined;
19
18
  const parser = new Parser(characters);
20
19
  const expression = parser.expression(undefined, 0);
@@ -30,7 +29,7 @@ class Parser {
30
29
  return this.index === this.characters.length;
31
30
  }
32
31
  expression(stop, depth) {
33
- if (depth > MAX_NESTING)
32
+ if (depth > maxNesting)
34
33
  return undefined;
35
34
  const alternatives = [];
36
35
  const first = this.sequence(stop, depth);
@@ -112,14 +111,14 @@ class Parser {
112
111
  quantifier() {
113
112
  this.index++;
114
113
  const minimum = this.integer();
115
- if (minimum === undefined || minimum > MAX_REPEAT)
114
+ if (minimum === undefined || minimum > maxRepeat)
116
115
  return undefined;
117
116
  let maximum = minimum;
118
117
  if (this.peek() === ',') {
119
118
  this.index++;
120
119
  maximum = this.integer();
121
120
  }
122
- if ((maximum !== undefined && (maximum > MAX_REPEAT || maximum < minimum)) ||
121
+ if ((maximum !== undefined && (maximum > maxRepeat || maximum < minimum)) ||
123
122
  this.peek() !== '}') {
124
123
  return undefined;
125
124
  }
@@ -1,16 +1,9 @@
1
1
  import type { Pattern, RunPattern } from '../compile/model.js';
2
2
  import type { Expression } from './ast.js';
3
3
  /**
4
- * The most states the machine of one I-Regexp may have (`limits.regexp.maxStates`), an
5
- * implementation limit as RFC 9485 §8 allows. Counted repetitions are expanded copy by copy, so the
6
- * parser's bounds on length, nesting and counts alone admit machines of billions of states. The
7
- * counted-run form never expands, so it is not subject to this budget.
8
- */
9
- export declare const MAX_STATES = 10000;
10
- /**
11
- * Thrown when an I-Regexp source compiles to a machine of more than `MAX_STATES` states. A short
12
- * branching source such as `(a{0,1000}){0,60}b` would unroll to ~120k states and cost seconds per
13
- * validated value (P1-I-01); it is refused before any state is built.
4
+ * Thrown when an I-Regexp source compiles to a machine of more than `limits.regexp.maxStates`
5
+ * states. A short branching source such as `(a{0,1000}){0,60}b` would unroll to ~120k states and
6
+ * cost seconds per validated value (P1-I-01); it is refused before any state is built.
14
7
  */
15
8
  export declare class PatternComplexityError extends RangeError {
16
9
  readonly limit: number;
@@ -20,7 +13,8 @@ export declare class PatternComplexityError extends RangeError {
20
13
  export declare function compilePattern(source: string): Pattern | RunPattern;
21
14
  /**
22
15
  * Whether a parsed I-Regexp compiles within the state budget: as counted runs, which never expand,
23
- * or as a machine of at most `MAX_STATES` states, counted from the AST before anything is built.
16
+ * or as a machine of at most `limits.regexp.maxStates` states, counted from the AST before anything
17
+ * is built.
24
18
  */
25
19
  export declare function withinStateBudget(expression: Expression): boolean;
26
20
  /**
@@ -1,19 +1,20 @@
1
+ import { limits } from '../../limits.js';
1
2
  import { parseIRegexp } from './ast.js';
2
3
  /**
3
- * The most states the machine of one I-Regexp may have (`limits.regexp.maxStates`), an
4
- * implementation limit as RFC 9485 §8 allows. Counted repetitions are expanded copy by copy, so the
5
- * parser's bounds on length, nesting and counts alone admit machines of billions of states. The
6
- * counted-run form never expands, so it is not subject to this budget.
4
+ * The most states the machine of one I-Regexp may have, an implementation limit as RFC 9485 §8
5
+ * allows. Counted repetitions are expanded copy by copy, so the parser's bounds on length, nesting
6
+ * and counts alone admit machines of billions of states. The counted-run form never expands, so it
7
+ * is not subject to this budget.
7
8
  */
8
- export const MAX_STATES = 10_000;
9
+ const { maxStates } = limits.regexp;
9
10
  /**
10
- * Thrown when an I-Regexp source compiles to a machine of more than `MAX_STATES` states. A short
11
- * branching source such as `(a{0,1000}){0,60}b` would unroll to ~120k states and cost seconds per
12
- * validated value (P1-I-01); it is refused before any state is built.
11
+ * Thrown when an I-Regexp source compiles to a machine of more than `limits.regexp.maxStates`
12
+ * states. A short branching source such as `(a{0,1000}){0,60}b` would unroll to ~120k states and
13
+ * cost seconds per validated value (P1-I-01); it is refused before any state is built.
13
14
  */
14
15
  export class PatternComplexityError extends RangeError {
15
16
  limit;
16
- constructor(limit = MAX_STATES) {
17
+ constructor(limit = maxStates) {
17
18
  super(`Cannot compile an I-Regexp machine of more than ${limit} states.`);
18
19
  this.limit = limit;
19
20
  this.name = 'PatternComplexityError';
@@ -27,7 +28,7 @@ export function compilePattern(source) {
27
28
  const runs = scalarRuns(expression);
28
29
  if (runs !== undefined)
29
30
  return Object.freeze({ source, runs });
30
- if (states(expression) > MAX_STATES)
31
+ if (states(expression) > maxStates)
31
32
  throw new PatternComplexityError();
32
33
  const builder = new Builder();
33
34
  const fragment = builder.expression(expression);
@@ -40,10 +41,11 @@ export function compilePattern(source) {
40
41
  }
41
42
  /**
42
43
  * Whether a parsed I-Regexp compiles within the state budget: as counted runs, which never expand,
43
- * or as a machine of at most `MAX_STATES` states, counted from the AST before anything is built.
44
+ * or as a machine of at most `limits.regexp.maxStates` states, counted from the AST before anything
45
+ * is built.
44
46
  */
45
47
  export function withinStateBudget(expression) {
46
- return scalarRuns(expression) !== undefined || states(expression) <= MAX_STATES;
48
+ return scalarRuns(expression) !== undefined || states(expression) <= maxStates;
47
49
  }
48
50
  /**
49
51
  * The number of states `Builder` builds for an expression, computed from the AST alone: `states`