@astrale-os/kernel-dsl 0.2.0-beta.8 → 0.2.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 (321) hide show
  1. package/dist/v1/addressing/class-key.js +5 -4
  2. package/dist/v1/addressing/method-key.js +3 -2
  3. package/dist/v1/addressing/patterns.d.ts +0 -5
  4. package/dist/v1/addressing/patterns.js +5 -5
  5. package/dist/v1/builder/callable/authoring.d.ts +87 -41
  6. package/dist/v1/builder/callable/authoring.js +29 -14
  7. package/dist/v1/builder/class/authoring.d.ts +311 -36
  8. package/dist/v1/builder/class/authoring.js +3 -4
  9. package/dist/v1/builder/class/property.d.ts +16 -8
  10. package/dist/v1/builder/class/property.js +21 -5
  11. package/dist/v1/builder/core/authoring.d.ts +28 -13
  12. package/dist/v1/builder/core/authoring.js +22 -2
  13. package/dist/v1/builder/index.d.ts +9 -8
  14. package/dist/v1/builder/index.js +2 -2
  15. package/dist/v1/builder/lowering/callable.d.ts +3 -1
  16. package/dist/v1/builder/lowering/callable.js +43 -51
  17. package/dist/v1/builder/lowering/class.d.ts +7 -0
  18. package/dist/v1/builder/lowering/class.js +79 -29
  19. package/dist/v1/builder/lowering/core.d.ts +3 -2
  20. package/dist/v1/builder/lowering/core.js +9 -6
  21. package/dist/v1/builder/lowering/policy.d.ts +8 -1
  22. package/dist/v1/builder/lowering/policy.js +35 -0
  23. package/dist/v1/builder/lowering/schema/capture.js +9 -4
  24. package/dist/v1/builder/lowering/schema/compile.d.ts +2 -2
  25. package/dist/v1/builder/lowering/schema/compile.js +15 -2
  26. package/dist/v1/builder/lowering/schema/context.d.ts +11 -8
  27. package/dist/v1/builder/lowering/schema/context.js +59 -29
  28. package/dist/v1/builder/lowering/schema/ownership.d.ts +3 -3
  29. package/dist/v1/builder/lowering/schema/ownership.js +2 -1
  30. package/dist/v1/builder/lowering/value/compile.js +14 -4
  31. package/dist/v1/builder/lowering/value/zod.d.ts +7 -6
  32. package/dist/v1/builder/lowering/value/zod.js +16 -7
  33. package/dist/v1/builder/lowering/view.d.ts +4 -3
  34. package/dist/v1/builder/lowering/view.js +2 -14
  35. package/dist/v1/builder/policy/authoring.d.ts +23 -6
  36. package/dist/v1/builder/policy/authoring.js +35 -8
  37. package/dist/v1/builder/schema/define.d.ts +8 -5
  38. package/dist/v1/builder/schema/diagnostic.d.ts +1 -1
  39. package/dist/v1/builder/schema/handle.d.ts +2 -1
  40. package/dist/v1/builder/schema/input.d.ts +9 -1
  41. package/dist/v1/builder/schema/projection/callable.d.ts +51 -0
  42. package/dist/v1/builder/schema/projection/callable.js +1 -0
  43. package/dist/v1/builder/schema/projection/class.d.ts +89 -0
  44. package/dist/v1/builder/schema/projection/class.js +1 -0
  45. package/dist/v1/builder/schema/projection/core-input.d.ts +32 -0
  46. package/dist/v1/builder/schema/projection/core-input.js +1 -0
  47. package/dist/v1/builder/schema/projection/domain.d.ts +59 -0
  48. package/dist/v1/builder/schema/projection/domain.js +1 -0
  49. package/dist/v1/builder/schema/projection/identity.d.ts +39 -0
  50. package/dist/v1/builder/schema/projection/identity.js +1 -0
  51. package/dist/v1/builder/schema/projection/model.d.ts +59 -0
  52. package/dist/v1/builder/schema/projection/model.js +1 -0
  53. package/dist/v1/builder/schema/projection/property.d.ts +32 -0
  54. package/dist/v1/builder/schema/projection/property.js +1 -0
  55. package/dist/v1/builder/schema/projection/resolved-class.d.ts +76 -0
  56. package/dist/v1/builder/schema/projection/resolved-class.js +1 -0
  57. package/dist/v1/builder/schema/projection.d.ts +4 -258
  58. package/dist/v1/builder/value/full-match.js +6 -3
  59. package/dist/v1/builder/value/path.d.ts +2 -2
  60. package/dist/v1/builder/value/path.js +2 -2
  61. package/dist/v1/builder/view/authoring.d.ts +6 -14
  62. package/dist/v1/builder/view/authoring.js +13 -5
  63. package/dist/v1/bundle/structure.d.ts +2 -1
  64. package/dist/v1/compiled/admission/accept.d.ts +1 -1
  65. package/dist/v1/compiled/admission/accept.js +11 -814
  66. package/dist/v1/compiled/admission/closure.d.ts +3 -0
  67. package/dist/v1/compiled/admission/closure.js +173 -0
  68. package/dist/v1/compiled/admission/diagnostic.d.ts +7 -0
  69. package/dist/v1/compiled/admission/diagnostic.js +13 -0
  70. package/dist/v1/compiled/admission/revision.js +9 -1
  71. package/dist/v1/compiled/admission/semantics/cardinality.d.ts +5 -0
  72. package/dist/v1/compiled/admission/semantics/cardinality.js +113 -0
  73. package/dist/v1/compiled/admission/semantics/class.d.ts +5 -0
  74. package/dist/v1/compiled/admission/semantics/class.js +125 -0
  75. package/dist/v1/compiled/admission/semantics/context.d.ts +60 -0
  76. package/dist/v1/compiled/admission/semantics/context.js +81 -0
  77. package/dist/v1/compiled/admission/semantics/core.d.ts +35 -0
  78. package/dist/v1/compiled/admission/semantics/core.js +123 -0
  79. package/dist/v1/compiled/admission/semantics/edge.d.ts +8 -0
  80. package/dist/v1/compiled/admission/semantics/edge.js +89 -0
  81. package/dist/v1/compiled/admission/semantics/policy/admit.d.ts +4 -0
  82. package/dist/v1/compiled/admission/semantics/policy/admit.js +63 -0
  83. package/dist/v1/compiled/admission/semantics/policy/callable.d.ts +5 -0
  84. package/dist/v1/compiled/admission/semantics/policy/callable.js +72 -0
  85. package/dist/v1/compiled/admission/semantics/policy/contracts.d.ts +24 -0
  86. package/dist/v1/compiled/admission/semantics/policy/contracts.js +45 -0
  87. package/dist/v1/compiled/admission/semantics/policy/equality.d.ts +8 -0
  88. package/dist/v1/compiled/admission/semantics/policy/equality.js +27 -0
  89. package/dist/v1/compiled/admission/semantics/policy/measure.d.ts +9 -0
  90. package/dist/v1/compiled/admission/semantics/policy/measure.js +81 -0
  91. package/dist/v1/compiled/admission/semantics/policy/parity.d.ts +4 -0
  92. package/dist/v1/compiled/admission/semantics/policy/parity.js +139 -0
  93. package/dist/v1/compiled/admission/semantics/policy/pattern.d.ts +8 -0
  94. package/dist/v1/compiled/admission/semantics/policy/pattern.js +78 -0
  95. package/dist/v1/compiled/admission/semantics/policy/typing.d.ts +28 -0
  96. package/dist/v1/compiled/admission/semantics/policy/typing.js +206 -0
  97. package/dist/v1/compiled/admission/semantics/policy/variants.d.ts +10 -0
  98. package/dist/v1/compiled/admission/semantics/policy/variants.js +65 -0
  99. package/dist/v1/compiled/admission/semantics.d.ts +1 -1
  100. package/dist/v1/compiled/admission/semantics.js +8 -1078
  101. package/dist/v1/compiled/admission/wire/callable.d.ts +6 -0
  102. package/dist/v1/compiled/admission/wire/callable.js +90 -0
  103. package/dist/v1/compiled/admission/wire/class.d.ts +4 -0
  104. package/dist/v1/compiled/admission/wire/class.js +133 -0
  105. package/dist/v1/compiled/admission/wire/core.d.ts +5 -0
  106. package/dist/v1/compiled/admission/wire/core.js +32 -0
  107. package/dist/v1/compiled/admission/wire/dependency.d.ts +14 -0
  108. package/dist/v1/compiled/admission/wire/dependency.js +43 -0
  109. package/dist/v1/compiled/admission/wire/entry.d.ts +5 -0
  110. package/dist/v1/compiled/admission/wire/entry.js +100 -0
  111. package/dist/v1/compiled/admission/wire/pattern.d.ts +12 -0
  112. package/dist/v1/compiled/admission/wire/pattern.js +111 -0
  113. package/dist/v1/compiled/admission/wire/policy.d.ts +10 -0
  114. package/dist/v1/compiled/admission/wire/policy.js +189 -0
  115. package/dist/v1/compiled/admission/wire/program.d.ts +4 -0
  116. package/dist/v1/compiled/admission/wire/program.js +52 -0
  117. package/dist/v1/compiled/admission/wire/property.d.ts +4 -0
  118. package/dist/v1/compiled/admission/wire/property.js +74 -0
  119. package/dist/v1/compiled/admission/wire/reference.d.ts +8 -0
  120. package/dist/v1/compiled/admission/wire/reference.js +33 -0
  121. package/dist/v1/compiled/admission/wire/value.d.ts +29 -0
  122. package/dist/v1/compiled/admission/wire/value.js +98 -0
  123. package/dist/v1/compiled/admission/wire/view.d.ts +3 -0
  124. package/dist/v1/compiled/admission/wire/view.js +17 -0
  125. package/dist/v1/compiled/compiler/compile.js +43 -11
  126. package/dist/v1/compiled/generated.d.ts +10 -0
  127. package/dist/v1/compiled/generated.js +15 -0
  128. package/dist/v1/compiled/loader/load.d.ts +5 -0
  129. package/dist/v1/compiled/loader/load.js +18 -4
  130. package/dist/v1/compiled/model/schema.d.ts +16 -7
  131. package/dist/v1/domain/create.js +18 -28
  132. package/dist/v1/domain/model/domain.d.ts +0 -1
  133. package/dist/v1/domain/model/input.d.ts +3 -0
  134. package/dist/v1/domain/projection/classes.js +13 -41
  135. package/dist/v1/domain/validation/create.d.ts +2 -0
  136. package/dist/v1/domain/validation/create.js +12 -0
  137. package/dist/v1/index.d.ts +5 -2
  138. package/dist/v1/index.js +3 -1
  139. package/dist/v1/language/callable/composition.d.ts +27 -0
  140. package/dist/v1/language/callable/composition.js +52 -0
  141. package/dist/v1/language/callable/executable.d.ts +6 -0
  142. package/dist/v1/language/callable/executable.js +4 -0
  143. package/dist/v1/language/callable/model/callable.d.ts +34 -9
  144. package/dist/v1/language/callable/model/callable.js +3 -1
  145. package/dist/v1/language/callable/resolved.d.ts +23 -8
  146. package/dist/v1/language/class/facets.d.ts +5 -2
  147. package/dist/v1/language/class/inheritance.d.ts +12 -0
  148. package/dist/v1/language/class/inheritance.js +25 -0
  149. package/dist/v1/language/class/lifetime.d.ts +17 -0
  150. package/dist/v1/language/class/lifetime.js +26 -0
  151. package/dist/v1/language/class/model/class.d.ts +8 -4
  152. package/dist/v1/language/class/model/property.d.ts +4 -2
  153. package/dist/v1/language/class/property-values.js +5 -2
  154. package/dist/v1/language/class/resolved.d.ts +25 -15
  155. package/dist/v1/language/core/model/core.d.ts +7 -1
  156. package/dist/v1/language/core/resolved.d.ts +6 -2
  157. package/dist/v1/language/definition/metadata.d.ts +8 -0
  158. package/dist/v1/language/definition/metadata.js +12 -0
  159. package/dist/v1/language/index.d.ts +9 -0
  160. package/dist/v1/language/index.js +6 -0
  161. package/dist/v1/language/policy/analysis/branches.d.ts +4 -3
  162. package/dist/v1/language/policy/analysis/branches.js +54 -12
  163. package/dist/v1/language/policy/analysis/budgets.js +1 -1
  164. package/dist/v1/language/policy/analysis/checks.d.ts +28 -0
  165. package/dist/v1/language/policy/analysis/checks.js +80 -0
  166. package/dist/v1/language/policy/index.d.ts +1 -0
  167. package/dist/v1/language/policy/index.js +1 -0
  168. package/dist/v1/language/policy/model/policy.d.ts +71 -5
  169. package/dist/v1/language/policy/model/policy.js +52 -1
  170. package/dist/v1/language/policy/normalization/normalize.d.ts +12 -1
  171. package/dist/v1/language/policy/normalization/normalize.js +178 -44
  172. package/dist/v1/language/state/index.d.ts +3 -0
  173. package/dist/v1/language/state/index.js +1 -0
  174. package/dist/v1/language/state/machine.d.ts +28 -0
  175. package/dist/v1/language/state/machine.js +40 -0
  176. package/dist/v1/language/state/topology.d.ts +14 -0
  177. package/dist/v1/language/state/topology.js +69 -0
  178. package/dist/v1/language/value/compile/fields.d.ts +1 -1
  179. package/dist/v1/language/value/compile/load.d.ts +4 -2
  180. package/dist/v1/language/value/compile/load.js +22 -1
  181. package/dist/v1/language/value/compile/model.d.ts +16 -1
  182. package/dist/v1/language/value/evaluate/assertions.d.ts +2 -0
  183. package/dist/v1/language/value/evaluate/assertions.js +13 -0
  184. package/dist/v1/language/value/evaluate/evaluator.js +111 -28
  185. package/dist/v1/language/value/evaluate/preparation.d.ts +10 -1
  186. package/dist/v1/language/value/evaluate/preparation.js +17 -26
  187. package/dist/v1/language/value/evaluate/program.js +1 -1
  188. package/dist/v1/language/value/evaluate/validate.d.ts +6 -2
  189. package/dist/v1/language/value/evaluate/validate.js +18 -11
  190. package/dist/v1/language/value/inclusion/includes.d.ts +9 -0
  191. package/dist/v1/language/value/inclusion/includes.js +777 -0
  192. package/dist/v1/language/value/model/blob.d.ts +31 -0
  193. package/dist/v1/language/value/model/blob.js +90 -0
  194. package/dist/v1/language/value/model/instant.d.ts +0 -2
  195. package/dist/v1/language/value/model/instant.js +1 -1
  196. package/dist/v1/language/value/model/schema.d.ts +2 -1
  197. package/dist/v1/language/value/model/schema.js +1 -5
  198. package/dist/v1/language/value/ordering.d.ts +2 -0
  199. package/dist/v1/language/value/ordering.js +4 -8
  200. package/dist/v1/language/value/profile/json.validate.js +1 -1
  201. package/dist/v1/language/value/profile/rules.js +48 -12
  202. package/dist/v1/language/value/reference/registry.d.ts +2 -1
  203. package/dist/v1/language/value/regexp/ast.js +3 -64
  204. package/dist/v1/language/value/regexp/compile.d.ts +32 -3
  205. package/dist/v1/language/value/regexp/compile.js +117 -21
  206. package/dist/v1/language/value/regexp/matcher.d.ts +6 -3
  207. package/dist/v1/language/value/regexp/matcher.js +185 -28
  208. package/dist/v1/language/value/regexp/syntax.d.ts +12 -1
  209. package/dist/v1/language/value/regexp/syntax.js +14 -2
  210. package/dist/v1/language/value/regexp/unicode.d.ts +32 -0
  211. package/dist/v1/language/value/regexp/unicode.js +139 -0
  212. package/dist/v1/language/value/syntax/full-match.js +8 -5
  213. package/dist/v1/language/value/syntax/node-path/validate.js +4 -6
  214. package/dist/v1/language/view/model/view.d.ts +2 -4
  215. package/dist/v1/language/view/resolved.d.ts +2 -2
  216. package/dist/v1/schema/analysis/class.d.ts +36 -6
  217. package/dist/v1/schema/analysis/class.js +31 -66
  218. package/dist/v1/schema/canonical/revision.d.ts +2 -1
  219. package/dist/v1/schema/canonical/revision.js +4 -1
  220. package/dist/v1/schema/compatibility/api.d.ts +3 -0
  221. package/dist/v1/schema/compatibility/api.js +2 -0
  222. package/dist/v1/schema/compatibility/comparators/callables.d.ts +39 -0
  223. package/dist/v1/schema/compatibility/comparators/callables.js +101 -0
  224. package/dist/v1/schema/compatibility/comparators/classes.d.ts +47 -0
  225. package/dist/v1/schema/compatibility/comparators/classes.js +160 -0
  226. package/dist/v1/schema/compatibility/comparators/index.d.ts +12 -0
  227. package/dist/v1/schema/compatibility/comparators/index.js +53 -0
  228. package/dist/v1/schema/compatibility/comparators/members.d.ts +4 -0
  229. package/dist/v1/schema/compatibility/comparators/members.js +49 -0
  230. package/dist/v1/schema/compatibility/comparators/values.d.ts +5 -0
  231. package/dist/v1/schema/compatibility/comparators/values.js +37 -0
  232. package/dist/v1/schema/compatibility/compare.d.ts +5 -0
  233. package/dist/v1/schema/compatibility/compare.js +23 -0
  234. package/dist/v1/schema/compatibility/context.d.ts +19 -0
  235. package/dist/v1/schema/compatibility/context.js +49 -0
  236. package/dist/v1/schema/compatibility/coordinate.d.ts +40 -0
  237. package/dist/v1/schema/compatibility/coordinate.js +38 -0
  238. package/dist/v1/schema/compatibility/diff.d.ts +12 -0
  239. package/dist/v1/schema/compatibility/diff.js +39 -0
  240. package/dist/v1/schema/compatibility/evidence.d.ts +16 -0
  241. package/dist/v1/schema/compatibility/evidence.js +62 -0
  242. package/dist/v1/schema/compatibility/fields.d.ts +194 -0
  243. package/dist/v1/schema/compatibility/fields.js +94 -0
  244. package/dist/v1/schema/compatibility/index.d.ts +6 -0
  245. package/dist/v1/schema/compatibility/index.js +3 -0
  246. package/dist/v1/schema/compatibility/meaning/footprint.d.ts +7 -0
  247. package/dist/v1/schema/compatibility/meaning/footprint.js +59 -0
  248. package/dist/v1/schema/compatibility/meaning/index.d.ts +3 -0
  249. package/dist/v1/schema/compatibility/meaning/index.js +16 -0
  250. package/dist/v1/schema/compatibility/model.d.ts +131 -0
  251. package/dist/v1/schema/compatibility/model.js +1 -0
  252. package/dist/v1/schema/compatibility/references.d.ts +38 -0
  253. package/dist/v1/schema/compatibility/references.js +149 -0
  254. package/dist/v1/schema/compatibility/report.d.ts +27 -0
  255. package/dist/v1/schema/compatibility/report.js +100 -0
  256. package/dist/v1/schema/compatibility/scope.d.ts +36 -0
  257. package/dist/v1/schema/compatibility/scope.js +110 -0
  258. package/dist/v1/schema/compatibility/structure/index.d.ts +3 -0
  259. package/dist/v1/schema/compatibility/structure/index.js +40 -0
  260. package/dist/v1/schema/compatibility/structure/inheritance.d.ts +7 -0
  261. package/dist/v1/schema/compatibility/structure/inheritance.js +68 -0
  262. package/dist/v1/schema/compatibility/structure/requirements.d.ts +7 -0
  263. package/dist/v1/schema/compatibility/structure/requirements.js +97 -0
  264. package/dist/v1/schema/compatibility/subjects.d.ts +39 -0
  265. package/dist/v1/schema/compatibility/subjects.js +143 -0
  266. package/dist/v1/schema/compatibility/versioning/index.d.ts +8 -0
  267. package/dist/v1/schema/compatibility/versioning/index.js +50 -0
  268. package/dist/v1/schema/compatibility/versioning/members.d.ts +12 -0
  269. package/dist/v1/schema/compatibility/versioning/members.js +47 -0
  270. package/dist/v1/schema/compatibility/versioning/surface.d.ts +11 -0
  271. package/dist/v1/schema/compatibility/versioning/surface.js +61 -0
  272. package/dist/v1/schema/diagnostic.d.ts +1 -1
  273. package/dist/v1/schema/fingerprint.d.ts +2 -0
  274. package/dist/v1/schema/fingerprint.js +1 -0
  275. package/dist/v1/schema/index.d.ts +4 -3
  276. package/dist/v1/schema/index.js +2 -1
  277. package/dist/v1/schema/model/schema.d.ts +8 -11
  278. package/dist/v1/schema/normalization/domain.js +57 -13
  279. package/dist/v1/schema/resolution/definition.index.d.ts +1 -2
  280. package/dist/v1/schema/resolution/definition.index.js +0 -3
  281. package/dist/v1/schema/resolution/domain.d.ts +4 -1
  282. package/dist/v1/schema/resolution/domain.js +26 -18
  283. package/dist/v1/schema/resolution/origins.d.ts +28 -5
  284. package/dist/v1/schema/resolution/origins.js +68 -31
  285. package/dist/v1/schema/validation/callable.d.ts +4 -0
  286. package/dist/v1/schema/validation/callable.js +39 -0
  287. package/dist/v1/schema/validation/class.d.ts +10 -0
  288. package/dist/v1/schema/validation/class.js +79 -60
  289. package/dist/v1/schema/validation/core.js +83 -55
  290. package/dist/v1/schema/validation/domain.d.ts +2 -1
  291. package/dist/v1/schema/validation/domain.js +2 -0
  292. package/dist/v1/schema/validation/domain.structure.d.ts +0 -2
  293. package/dist/v1/schema/validation/domain.structure.js +214 -171
  294. package/dist/v1/schema/validation/policy/budgets.js +36 -6
  295. package/dist/v1/schema/validation/policy/context.js +5 -16
  296. package/dist/v1/schema/validation/policy/objects.d.ts +4 -0
  297. package/dist/v1/schema/validation/policy/objects.js +71 -0
  298. package/dist/v1/schema/validation/policy/references.js +16 -4
  299. package/dist/v1/schema/validation/policy/typing.d.ts +2 -0
  300. package/dist/v1/schema/validation/policy/typing.js +55 -7
  301. package/dist/v1/schema/validation/policy/uses.js +73 -99
  302. package/dist/v1/schema/validation/value-api.d.ts +2 -0
  303. package/dist/v1/schema/validation/value-api.js +1 -0
  304. package/dist/v1/schema/validation/value.js +7 -1
  305. package/dist/v1/schema/validation/view.js +14 -9
  306. package/dist/value/accept.d.ts +9 -0
  307. package/dist/value/accept.js +106 -7
  308. package/dist/value/canonical.d.ts +3 -0
  309. package/dist/value/canonical.js +22 -6
  310. package/dist/value/immutable.optimization.d.ts +15 -0
  311. package/dist/value/immutable.optimization.js +34 -0
  312. package/dist/value/index.d.ts +1 -1
  313. package/dist/value/index.js +1 -1
  314. package/dist/value/json.d.ts +1 -1
  315. package/dist/value/json.js +1 -1
  316. package/dist/value/limits.d.ts +1 -1
  317. package/dist/value/unicode.d.ts +4 -1
  318. package/dist/value/unicode.js +28 -0
  319. package/package.json +20 -5
  320. package/dist/v1/schema/compatibility/meaning.d.ts +0 -29
  321. package/dist/v1/schema/compatibility/meaning.js +0 -605
@@ -0,0 +1,31 @@
1
+ import type { JsonSchemaObject } from './schema.js';
2
+ declare const BLOB_SCHEMA: unique symbol;
3
+ /** The portable value read from a blob-kind Node property. */
4
+ export interface BlobRef {
5
+ readonly digest: `sha256:${string}`;
6
+ readonly mediaType: string;
7
+ readonly size: number;
8
+ }
9
+ /** An uploader-bound receipt is the only ordinary write input for a blob property. */
10
+ export type BlobReceipt = string & {
11
+ readonly __brand: 'BlobReceipt';
12
+ };
13
+ /** Type-only marker; the serialized schema remains ordinary JSON. */
14
+ export interface BlobSchema extends JsonSchemaObject {
15
+ readonly [BLOB_SCHEMA]: true;
16
+ }
17
+ export interface BlobOptions {
18
+ /** Required property-level bound, in bytes. */
19
+ readonly maxBytes: number;
20
+ /** Omission admits any canonical artifact media type. */
21
+ readonly mediaTypes?: readonly string[];
22
+ }
23
+ export declare const BLOB_VALUE_KIND: 'blob';
24
+ /** Build the one canonical V1 schema shape for a blob-valued Node property. */
25
+ export declare function blob(options: BlobOptions): BlobSchema;
26
+ /** Marker recognition on an already admitted V1 value schema. */
27
+ export declare function isBlobValueSchema(input: unknown): input is BlobSchema;
28
+ /** Exact canonical artifact media type, including ordered token parameters. */
29
+ export declare function canonicalMediaType(input: string): string;
30
+ export declare function isCanonicalBlobRef(input: unknown): input is BlobRef;
31
+ export {};
@@ -0,0 +1,90 @@
1
+ export const BLOB_VALUE_KIND = 'blob';
2
+ const BLOB_DIGEST_PATTERN = 'sha256:[0-9a-f]{64}';
3
+ const BLOB_MEDIA_TYPE_PATTERN = "[a-z0-9!#$%&'*+.^_`|~-]+/[a-z0-9!#$%&'*+.^_`|~-]+(;[a-z0-9!#$%&'*+.^_`|~-]+=[!#$%&'*+.^_`|~0-9A-Za-z-]+)*";
4
+ const TOKEN = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/u;
5
+ const DIGEST = /^sha256:[0-9a-f]{64}$/u;
6
+ /** Build the one canonical V1 schema shape for a blob-valued Node property. */
7
+ export function blob(options) {
8
+ if (!Number.isSafeInteger(options?.maxBytes) || options.maxBytes < 1) {
9
+ throw new TypeError('Blob maxBytes must be a positive safe integer.');
10
+ }
11
+ let mediaTypes;
12
+ if (options.mediaTypes !== undefined) {
13
+ if (!Array.isArray(options.mediaTypes) || options.mediaTypes.length === 0) {
14
+ throw new TypeError('Blob mediaTypes must be a non-empty list.');
15
+ }
16
+ mediaTypes = [...new Set(options.mediaTypes.map(canonicalMediaType))].sort();
17
+ }
18
+ return Object.freeze({
19
+ type: 'object',
20
+ 'x-astrale-value-kind': BLOB_VALUE_KIND,
21
+ properties: {
22
+ digest: { type: 'string', fullMatch: BLOB_DIGEST_PATTERN },
23
+ mediaType: mediaTypes === undefined
24
+ ? { type: 'string', fullMatch: BLOB_MEDIA_TYPE_PATTERN }
25
+ : { enum: mediaTypes },
26
+ size: { type: 'integer', minimum: 0, maximum: options.maxBytes },
27
+ },
28
+ required: ['digest', 'mediaType', 'size'],
29
+ additionalProperties: false,
30
+ });
31
+ }
32
+ /** Marker recognition on an already admitted V1 value schema. */
33
+ export function isBlobValueSchema(input) {
34
+ return (input !== null &&
35
+ typeof input === 'object' &&
36
+ !Array.isArray(input) &&
37
+ input['x-astrale-value-kind'] === BLOB_VALUE_KIND);
38
+ }
39
+ /** Exact canonical artifact media type, including ordered token parameters. */
40
+ export function canonicalMediaType(input) {
41
+ if (typeof input !== 'string')
42
+ throw new TypeError('Blob media type is invalid.');
43
+ const [essence, ...parametersInput] = input.split(';');
44
+ const [rawType, rawSubtype, ...extra] = essence.trim().split('/');
45
+ if (rawType === undefined ||
46
+ rawSubtype === undefined ||
47
+ extra.length !== 0 ||
48
+ !TOKEN.test(rawType) ||
49
+ !TOKEN.test(rawSubtype)) {
50
+ throw new TypeError('Blob media type is invalid.');
51
+ }
52
+ const parameters = parametersInput.map((part) => {
53
+ const separator = part.indexOf('=');
54
+ if (separator <= 0)
55
+ throw new TypeError('Blob media type parameter is invalid.');
56
+ const name = part.slice(0, separator).trim().toLowerCase();
57
+ const value = part.slice(separator + 1).trim();
58
+ if (!TOKEN.test(name) || !TOKEN.test(value)) {
59
+ throw new TypeError('Blob media type parameter is invalid.');
60
+ }
61
+ return [name, value];
62
+ });
63
+ parameters.sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0));
64
+ if (new Set(parameters.map(([name]) => name)).size !== parameters.length) {
65
+ throw new TypeError('Blob media type parameters are duplicated.');
66
+ }
67
+ return parameters.reduce((result, [name, value]) => `${result};${name}=${value}`, `${rawType.toLowerCase()}/${rawSubtype.toLowerCase()}`);
68
+ }
69
+ export function isCanonicalBlobRef(input) {
70
+ if (input === null || typeof input !== 'object' || Array.isArray(input))
71
+ return false;
72
+ const value = input;
73
+ if (Object.keys(value).length !== 3 ||
74
+ !Object.hasOwn(value, 'digest') ||
75
+ !Object.hasOwn(value, 'mediaType') ||
76
+ !Object.hasOwn(value, 'size') ||
77
+ typeof value.digest !== 'string' ||
78
+ !DIGEST.test(value.digest) ||
79
+ typeof value.mediaType !== 'string' ||
80
+ !Number.isSafeInteger(value.size) ||
81
+ value.size < 0) {
82
+ return false;
83
+ }
84
+ try {
85
+ return canonicalMediaType(value.mediaType) === value.mediaType;
86
+ }
87
+ catch {
88
+ return false;
89
+ }
90
+ }
@@ -1,6 +1,4 @@
1
1
  /** Exact portable UTC millisecond Instant used by the V1 value-schema dialect. */
2
- /** Canonical value-language annotation for an Instant string. */
3
- export declare const INSTANT_VALUE_KIND: 'instant';
4
2
  export declare const instant: Readonly<{
5
3
  readonly type: 'string';
6
4
  readonly 'x-astrale-value-kind': 'instant';
@@ -1,6 +1,6 @@
1
1
  /** Exact portable UTC millisecond Instant used by the V1 value-schema dialect. */
2
2
  /** Canonical value-language annotation for an Instant string. */
3
- export const INSTANT_VALUE_KIND = 'instant';
3
+ const INSTANT_VALUE_KIND = 'instant';
4
4
  export const instant = Object.freeze({
5
5
  type: 'string',
6
6
  'x-astrale-value-kind': INSTANT_VALUE_KIND,
@@ -21,5 +21,6 @@ export interface PathAnnotation {
21
21
  readonly cardinality: 'one';
22
22
  readonly accepts: readonly ClassRef[];
23
23
  }
24
- export declare const VALUE_SCHEMA_CONTEXTS: readonly ['property-facet', 'callable-input', 'callable-output'];
24
+ declare const VALUE_SCHEMA_CONTEXTS: readonly ['property-facet', 'callable-input', 'callable-output'];
25
25
  export type ValueSchemaContext = (typeof VALUE_SCHEMA_CONTEXTS)[number];
26
+ export {};
@@ -4,8 +4,4 @@ export const JSON_SCHEMA_DIALECT = 'https://json-schema.org/draft/2020-12/schema
4
4
  export const VALUE_SCHEMA_DIALECT = 'https://schemas.astrale.ai/dsl/v1/value-schema';
5
5
  /** Required vocabulary carried by the V1 value-schema dialect. */
6
6
  export const VALUE_SCHEMA_VOCABULARY = 'https://schemas.astrale.ai/dsl/v1/value-schema/vocabulary';
7
- export const VALUE_SCHEMA_CONTEXTS = [
8
- 'property-facet',
9
- 'callable-input',
10
- 'callable-output',
11
- ];
7
+ const VALUE_SCHEMA_CONTEXTS = ['property-facet', 'callable-input', 'callable-output'];
@@ -1,4 +1,5 @@
1
1
  import type { ValueProgram } from './compile/model.js';
2
+ import type { CompiledInstanceSchema } from './evaluate/types.js';
2
3
  import type { JsonSchema } from './model/schema.js';
3
4
  import type { ValueSchemaRegistry } from './reference/registry.js';
4
5
  export type OrderingKind = 'boolean' | 'number' | 'string' | 'instant';
@@ -11,3 +12,4 @@ export type OrderingKind = 'boolean' | 'number' | 'string' | 'instant';
11
12
  export declare function classifyOrdering(contract: JsonSchema, registry: ValueSchemaRegistry): OrderingKind | undefined;
12
13
  /** Recompute the scalar ordering classification from one admitted portable value program. */
13
14
  export declare function classifyValueProgramOrdering(program: ValueProgram): OrderingKind | undefined;
15
+ export declare function classifyPreparedOrdering(compiled: CompiledInstanceSchema): OrderingKind | undefined;
@@ -18,17 +18,13 @@ export function classifyOrdering(contract, registry) {
18
18
  const prepared = prepareValueSchema(contract, registry, '');
19
19
  if (!prepared.compiled)
20
20
  return undefined;
21
- const candidates = new OrderingClassifier(prepared.value).classify(prepared.value.root);
22
- if (candidates.size !== 1)
23
- return undefined;
24
- const [kind] = candidates;
25
- return kind === 'boolean' || kind === 'number' || kind === 'string' || kind === 'instant'
26
- ? kind
27
- : undefined;
21
+ return classifyPreparedOrdering(prepared.value);
28
22
  }
29
23
  /** Recompute the scalar ordering classification from one admitted portable value program. */
30
24
  export function classifyValueProgramOrdering(program) {
31
- const compiled = loadValueProgram(program);
25
+ return classifyPreparedOrdering(loadValueProgram(program));
26
+ }
27
+ export function classifyPreparedOrdering(compiled) {
32
28
  const candidates = new OrderingClassifier(compiled).classify(compiled.root);
33
29
  if (candidates.size !== 1)
34
30
  return undefined;
@@ -1,4 +1,4 @@
1
- import { accept as acceptJsonValue, BoundaryError as JsonBoundaryError, } from '@astrale-os/kernel-dsl/value';
1
+ import { acceptForRead as acceptJsonValue, BoundaryError as JsonBoundaryError, } from '@astrale-os/kernel-dsl/value';
2
2
  import { diagnostic } from '../../validation/diagnostic.js';
3
3
  export function validateCanonicalJsonDomain(value, pointer) {
4
4
  try {
@@ -1,8 +1,9 @@
1
1
  import { json } from '@astrale-os/kernel-dsl/value';
2
2
  import { diagnostic } from '../../validation/diagnostic.js';
3
+ import { blob, BLOB_VALUE_KIND } from '../model/blob.js';
3
4
  import { isValueObject as isJsonObject } from '../model/object.js';
4
5
  import { VALUE_SCHEMA_DIALECT } from '../model/schema.js';
5
- import { isIRegexp } from '../regexp/syntax.js';
6
+ import { refuseIRegexp, stateBudgetMessage } from '../regexp/syntax.js';
6
7
  import { walkSchema } from '../syntax/walk.js';
7
8
  import { FORBIDDEN_DYNAMIC_KEYWORDS, STANDARD_SCHEMA_KEYWORDS } from './vocabulary.js';
8
9
  export function validateSchemaProfile(schema, context, pointer) {
@@ -28,19 +29,50 @@ export function validateSchemaProfile(schema, context, pointer) {
28
29
  diagnostics.push(diagnostic('VS_RESOURCE_ID', `${currentPointer}/$id`, '$id is forbidden in an embedded V1 value schema.'));
29
30
  }
30
31
  validateSemanticSets(location.schema, currentPointer, diagnostics);
31
- validateValueKind(location.schema, currentPointer, diagnostics);
32
+ validateValueKind(location.schema, context, location.depth, currentPointer, diagnostics);
32
33
  validateRegexes(location.schema, currentPointer, diagnostics);
33
34
  });
34
- void context;
35
35
  return diagnostics;
36
36
  }
37
- function validateValueKind(schema, pointer, diagnostics) {
37
+ function validateValueKind(schema, context, depth, pointer, diagnostics) {
38
38
  if (!Object.hasOwn(schema, 'x-astrale-value-kind'))
39
39
  return;
40
- if (schema['x-astrale-value-kind'] !== 'instant' || schema.type !== 'string') {
40
+ if (schema['x-astrale-value-kind'] === BLOB_VALUE_KIND) {
41
+ if (context !== 'property-facet' || depth !== 0 || !isCanonicalBlobSchema(schema)) {
42
+ diagnostics.push(diagnostic('VS_VALUE_KIND', `${pointer}/x-astrale-value-kind`, 'blob must be the exact schema.values.blob output at the root of a Node property.'));
43
+ }
44
+ }
45
+ else if (schema['x-astrale-value-kind'] !== 'instant' || schema.type !== 'string') {
41
46
  diagnostics.push(diagnostic('VS_VALUE_KIND', `${pointer}/x-astrale-value-kind`, 'x-astrale-value-kind is exactly instant and requires type string at the same schema location.'));
42
47
  }
43
48
  }
49
+ function isCanonicalBlobSchema(input) {
50
+ const properties = input.properties;
51
+ if (!isJsonObject(properties))
52
+ return false;
53
+ const size = properties.size;
54
+ const mediaType = properties.mediaType;
55
+ if (!isJsonObject(size) || !isJsonObject(mediaType))
56
+ return false;
57
+ const maxBytes = size.maximum;
58
+ if (typeof maxBytes !== 'number' || !Number.isSafeInteger(maxBytes) || maxBytes < 1) {
59
+ return false;
60
+ }
61
+ const mediaTypes = mediaType.enum;
62
+ if (mediaTypes !== undefined && (!Array.isArray(mediaTypes) || !mediaTypes.every(isString))) {
63
+ return false;
64
+ }
65
+ try {
66
+ return (json.serialize(input) ===
67
+ json.serialize(blob({ maxBytes, ...(mediaTypes === undefined ? {} : { mediaTypes }) })));
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ }
73
+ function isString(input) {
74
+ return typeof input === 'string';
75
+ }
44
76
  function validateSemanticSets(schema, pointer, diagnostics) {
45
77
  if (Array.isArray(schema.type)) {
46
78
  rejectPrimitiveDuplicates(schema.type, `${pointer}/type`, 'type', diagnostics);
@@ -63,20 +95,24 @@ function validateRegexes(schema, pointer, diagnostics) {
63
95
  if (Object.hasOwn(schema, 'fullMatch') && typeof schema.fullMatch !== 'string') {
64
96
  diagnostics.push(diagnostic('VS_META_SCHEMA', `${pointer}/fullMatch`, 'fullMatch must be an I-Regexp source string.'));
65
97
  }
66
- if (typeof schema.fullMatch === 'string' && !isIRegexp(schema.fullMatch)) {
67
- diagnostics.push(diagnostic('VS_REGEX_PORTABLE', `${pointer}/fullMatch`, 'fullMatch must satisfy the complete RFC 9485 I-Regexp syntax.'));
98
+ if (typeof schema.fullMatch === 'string') {
99
+ portableRegex(schema.fullMatch, `${pointer}/fullMatch`, 'fullMatch', 'fullMatch must satisfy the complete RFC 9485 I-Regexp syntax.', diagnostics);
68
100
  }
69
- if (typeof schema.pattern === 'string' && !isIRegexp(schema.pattern)) {
70
- diagnostics.push(diagnostic('VS_REGEX_PORTABLE', `${pointer}/pattern`, 'pattern must satisfy the complete RFC 9485 I-Regexp syntax.'));
101
+ if (typeof schema.pattern === 'string') {
102
+ portableRegex(schema.pattern, `${pointer}/pattern`, 'pattern', 'pattern must satisfy the complete RFC 9485 I-Regexp syntax.', diagnostics);
71
103
  }
72
104
  if (isJsonObject(schema.patternProperties)) {
73
105
  for (const pattern of Object.keys(schema.patternProperties)) {
74
- if (!isIRegexp(pattern)) {
75
- diagnostics.push(diagnostic('VS_REGEX_PORTABLE', `${pointer}/patternProperties/${escapeToken(pattern)}`, 'patternProperties keys must satisfy RFC 9485 I-Regexp syntax.'));
76
- }
106
+ portableRegex(pattern, `${pointer}/patternProperties/${escapeToken(pattern)}`, 'A patternProperties key', 'patternProperties keys must satisfy RFC 9485 I-Regexp syntax.', diagnostics);
77
107
  }
78
108
  }
79
109
  }
110
+ function portableRegex(source, pointer, subject, syntax, diagnostics) {
111
+ const refusal = refuseIRegexp(source);
112
+ if (refusal === undefined)
113
+ return;
114
+ diagnostics.push(diagnostic('VS_REGEX_PORTABLE', pointer, refusal === 'syntax' ? syntax : stateBudgetMessage(subject)));
115
+ }
80
116
  function rejectPrimitiveDuplicates(values, pointer, name, diagnostics) {
81
117
  const seen = new Set();
82
118
  for (const value of values) {
@@ -1,6 +1,6 @@
1
1
  import type { ClassRef } from '../../../addressing/index.js';
2
2
  import type { JsonSchema } from '../model/schema.js';
3
- export interface ValueSchemaDependency {
3
+ interface ValueSchemaDependency {
4
4
  readonly origin: string;
5
5
  readonly revision: `sha256:${string}`;
6
6
  }
@@ -22,3 +22,4 @@ export interface ValueSchemaRegistry {
22
22
  readonly transitiveDependencies: readonly ValueSchemaDomainRegistry[];
23
23
  readonly graphNodePath: JsonSchema;
24
24
  }
25
+ export {};
@@ -1,11 +1,8 @@
1
- const CATEGORY = /^(?:L[lmotu]?|M[cen]?|N[dlo]?|P[cdfios]?|Z[lps]?|S[ckmo]?|C[cfno]?)$/u;
1
+ import { categoryRanges, complement, mergeRanges } from './unicode.js';
2
+ const CATEGORY = /^(?:L[lmotu]?|M[cen]?|N[dlo]?|P[cdefios]?|Z[lps]?|S[ckmo]?|C[cfno]?)$/u;
2
3
  const MAX_CODE_POINTS = 4096;
3
4
  const MAX_NESTING = 32;
4
5
  const MAX_REPEAT = 1000;
5
- const SCALAR_RANGES = [
6
- [0, 0xd7ff],
7
- [0xe000, 0x10ffff],
8
- ];
9
6
  const DOT_RANGES = [
10
7
  [0, 9],
11
8
  [11, 12],
@@ -200,7 +197,7 @@ class Parser {
200
197
  if (this.peek() !== '\\')
201
198
  return undefined;
202
199
  const escaped = this.peek(1);
203
- if (escaped === undefined || !'()*+-.?[\\]^nrt{}'.includes(escaped))
200
+ if (escaped === undefined || !'()*+-.?[\\]^nrt{|}'.includes(escaped))
204
201
  return undefined;
205
202
  this.index += 2;
206
203
  const value = escaped === 'n' ? '\n' : escaped === 'r' ? '\r' : escaped === 't' ? '\t' : escaped;
@@ -237,68 +234,10 @@ class Parser {
237
234
  return this.characters[this.index + offset];
238
235
  }
239
236
  }
240
- const categories = new Map();
241
- function categoryRanges(category) {
242
- const retained = categories.get(category);
243
- if (retained !== undefined)
244
- return retained;
245
- const expression = new RegExp(`^\\p{${category}}$`, 'u');
246
- const output = [];
247
- let start;
248
- let previous = -2;
249
- for (const [minimum, maximum] of SCALAR_RANGES) {
250
- for (let scalar = minimum; scalar <= maximum; scalar++) {
251
- if (!expression.test(String.fromCodePoint(scalar)))
252
- continue;
253
- if (start === undefined)
254
- start = scalar;
255
- else if (scalar !== previous + 1) {
256
- output.push([start, previous]);
257
- start = scalar;
258
- }
259
- previous = scalar;
260
- }
261
- }
262
- if (start !== undefined)
263
- output.push([start, previous]);
264
- const frozen = Object.freeze(output.map((range) => Object.freeze(range)));
265
- categories.set(category, frozen);
266
- return frozen;
267
- }
268
237
  function singleton(value) {
269
238
  const scalar = value.codePointAt(0);
270
239
  return scalar === undefined ? [] : [[scalar, scalar]];
271
240
  }
272
- function mergeRanges(input) {
273
- const sorted = [...input].sort((left, right) => left[0] - right[0] || left[1] - right[1]);
274
- const output = [];
275
- for (const range of sorted) {
276
- const previous = output.at(-1);
277
- if (previous === undefined || range[0] > previous[1] + 1)
278
- output.push([range[0], range[1]]);
279
- else
280
- output[output.length - 1] = [previous[0], Math.max(previous[1], range[1])];
281
- }
282
- return output;
283
- }
284
- function complement(input) {
285
- const output = [];
286
- for (const [minimum, maximum] of SCALAR_RANGES) {
287
- let cursor = minimum;
288
- for (const [start, end] of input) {
289
- if (end < minimum || start > maximum)
290
- continue;
291
- if (start > cursor)
292
- output.push([cursor, Math.min(start - 1, maximum)]);
293
- cursor = Math.max(cursor, end + 1);
294
- if (cursor > maximum)
295
- break;
296
- }
297
- if (cursor <= maximum)
298
- output.push([cursor, maximum]);
299
- }
300
- return output;
301
- }
302
241
  function isNormalCharacter(value) {
303
242
  const code = value.codePointAt(0);
304
243
  return (code !== undefined &&
@@ -1,3 +1,32 @@
1
- import type { Pattern } from '../compile/model.js';
2
- /** Compile one admitted I-Regexp AST to portable Thompson-NFA data. */
3
- export declare function compilePattern(source: string): Pattern;
1
+ import type { Pattern, RunPattern } from '../compile/model.js';
2
+ import type { Expression } from './ast.js';
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.
14
+ */
15
+ export declare class PatternComplexityError extends RangeError {
16
+ readonly limit: number;
17
+ constructor(limit?: number);
18
+ }
19
+ /** Compile scalar sequences as counted runs; preserve the NFA for branching expressions. */
20
+ export declare function compilePattern(source: string): Pattern | RunPattern;
21
+ /**
22
+ * 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.
24
+ */
25
+ export declare function withinStateBudget(expression: Expression): boolean;
26
+ /**
27
+ * The number of states `Builder` builds for an expression, computed from the AST alone: `states`
28
+ * in `proofs/Regexp.lean`, where `compile_size` proves it exact. Nesting and counts are bounded by
29
+ * the parser, so the count stays finite; it is exact up to `Number.MAX_SAFE_INTEGER`, and above it
30
+ * every rounding keeps it above the budget.
31
+ */
32
+ export declare function states(expression: Expression): number;
@@ -1,9 +1,34 @@
1
1
  import { parseIRegexp } from './ast.js';
2
- /** Compile one admitted I-Regexp AST to portable Thompson-NFA data. */
2
+ /**
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.
7
+ */
8
+ export const MAX_STATES = 10_000;
9
+ /**
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.
13
+ */
14
+ export class PatternComplexityError extends RangeError {
15
+ limit;
16
+ constructor(limit = MAX_STATES) {
17
+ super(`Cannot compile an I-Regexp machine of more than ${limit} states.`);
18
+ this.limit = limit;
19
+ this.name = 'PatternComplexityError';
20
+ }
21
+ }
22
+ /** Compile scalar sequences as counted runs; preserve the NFA for branching expressions. */
3
23
  export function compilePattern(source) {
4
24
  const expression = parseIRegexp(source);
5
25
  if (expression === undefined)
6
26
  throw new TypeError('Cannot compile an invalid I-Regexp source.');
27
+ const runs = scalarRuns(expression);
28
+ if (runs !== undefined)
29
+ return Object.freeze({ source, runs });
30
+ if (states(expression) > MAX_STATES)
31
+ throw new PatternComplexityError();
7
32
  const builder = new Builder();
8
33
  const fragment = builder.expression(expression);
9
34
  builder.states[fragment.end].accepting = true;
@@ -13,9 +38,77 @@ export function compilePattern(source) {
13
38
  states: Object.freeze(builder.states.map(freezeState)),
14
39
  });
15
40
  }
41
+ /**
42
+ * 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
+ */
45
+ export function withinStateBudget(expression) {
46
+ return scalarRuns(expression) !== undefined || states(expression) <= MAX_STATES;
47
+ }
48
+ /**
49
+ * The number of states `Builder` builds for an expression, computed from the AST alone: `states`
50
+ * in `proofs/Regexp.lean`, where `compile_size` proves it exact. Nesting and counts are bounded by
51
+ * the parser, so the count stays finite; it is exact up to `Number.MAX_SAFE_INTEGER`, and above it
52
+ * every rounding keeps it above the budget.
53
+ */
54
+ export function states(expression) {
55
+ const [only, ...others] = expression.alternatives;
56
+ if (only !== undefined && others.length === 0)
57
+ return sequenceStates(only);
58
+ return expression.alternatives.reduce((total, sequence) => total + sequenceStates(sequence), 2);
59
+ }
60
+ function sequenceStates({ pieces }) {
61
+ if (pieces.length === 0)
62
+ return 2;
63
+ return pieces.reduce((total, piece) => total + pieceStates(piece), 0);
64
+ }
65
+ /** `pieceStates`: `minimum` copies, then a star, or a shared end and the optional copies. */
66
+ function pieceStates({ atom, minimum, maximum }) {
67
+ const copy = atom.kind === 'ranges' ? 2 : states(atom.expression);
68
+ if (maximum === undefined)
69
+ return minimum * copy + (copy + 2);
70
+ return ((minimum === 0 ? 2 : minimum * copy) +
71
+ (maximum === minimum ? 0 : 1 + (maximum - minimum) * copy));
72
+ }
73
+ function scalarRuns(expression) {
74
+ if (expression.alternatives.length !== 1)
75
+ return undefined;
76
+ const pieces = expression.alternatives[0].pieces;
77
+ let counted = false;
78
+ for (let index = 0; index < pieces.length; index++) {
79
+ const piece = pieces[index];
80
+ if (piece.atom.kind !== 'ranges' ||
81
+ (index !== pieces.length - 1 && piece.minimum !== piece.maximum))
82
+ return undefined;
83
+ if (piece.maximum !== undefined && piece.maximum > 1)
84
+ counted = true;
85
+ }
86
+ if (!counted)
87
+ return undefined;
88
+ const runs = [];
89
+ for (const piece of pieces) {
90
+ if (piece.atom.kind !== 'ranges')
91
+ return undefined;
92
+ runs.push(Object.freeze({
93
+ ranges: freezeRanges(piece.atom.ranges),
94
+ minimum: piece.minimum,
95
+ ...(piece.maximum === undefined ? {} : { maximum: piece.maximum }),
96
+ }));
97
+ }
98
+ return Object.freeze(runs);
99
+ }
100
+ function freezeRanges(ranges) {
101
+ if (Object.isFrozen(ranges))
102
+ return ranges;
103
+ for (const range of ranges)
104
+ Object.freeze(range);
105
+ return Object.freeze(ranges);
106
+ }
16
107
  class Builder {
17
108
  states = [];
18
109
  expression(expression) {
110
+ if (expression.alternatives.length === 1)
111
+ return this.sequence(expression.alternatives[0]);
19
112
  const start = this.state();
20
113
  const end = this.state();
21
114
  for (const alternative of expression.alternatives) {
@@ -26,22 +119,34 @@ class Builder {
26
119
  return { start, end };
27
120
  }
28
121
  sequence(sequence) {
29
- let output = this.empty();
30
- for (const piece of sequence.pieces)
31
- output = this.concat(output, this.piece(piece));
32
- return output;
122
+ let output;
123
+ for (const piece of sequence.pieces) {
124
+ const fragment = this.piece(piece);
125
+ output = output === undefined ? fragment : this.concat(output, fragment);
126
+ }
127
+ return output ?? this.empty();
33
128
  }
34
129
  piece(piece) {
35
- let output = this.empty();
130
+ let output;
36
131
  for (let index = 0; index < piece.minimum; index++) {
37
- output = this.concat(output, this.atom(piece.atom));
132
+ const fragment = this.atom(piece.atom);
133
+ output = output === undefined ? fragment : this.concat(output, fragment);
38
134
  }
39
- if (piece.maximum === undefined)
40
- return this.concat(output, this.star(piece.atom));
135
+ if (piece.maximum === undefined) {
136
+ const repeated = this.star(piece.atom);
137
+ return output === undefined ? repeated : this.concat(output, repeated);
138
+ }
139
+ if (piece.maximum === piece.minimum)
140
+ return output ?? this.empty();
141
+ output ??= this.empty();
142
+ const end = this.state();
41
143
  for (let index = piece.minimum; index < piece.maximum; index++) {
42
- output = this.concat(output, this.optional(piece.atom));
144
+ // A shorter repetition exits the whole suffix, rather than skipping arbitrary copies.
145
+ this.epsilon(output.end, end);
146
+ output = this.concat(output, this.atom(piece.atom));
43
147
  }
44
- return output;
148
+ this.epsilon(output.end, end);
149
+ return { start: output.start, end };
45
150
  }
46
151
  atom(atom) {
47
152
  if (atom.kind === 'expression')
@@ -51,15 +156,6 @@ class Builder {
51
156
  this.states[start].transitions.push({ to: end, ranges: atom.ranges });
52
157
  return { start, end };
53
158
  }
54
- optional(atom) {
55
- const start = this.state();
56
- const end = this.state();
57
- const child = this.atom(atom);
58
- this.epsilon(start, end);
59
- this.epsilon(start, child.start);
60
- this.epsilon(child.end, end);
61
- return { start, end };
62
- }
63
159
  star(atom) {
64
160
  const start = this.state();
65
161
  const end = this.state();
@@ -90,7 +186,7 @@ class Builder {
90
186
  function freezeState(state) {
91
187
  return Object.freeze({
92
188
  epsilon: Object.freeze(state.epsilon),
93
- transitions: Object.freeze(state.transitions.map((transition) => Object.freeze({ to: transition.to, ranges: Object.freeze(transition.ranges) }))),
189
+ transitions: Object.freeze(state.transitions.map((transition) => Object.freeze({ to: transition.to, ranges: freezeRanges(transition.ranges) }))),
94
190
  ...(state.accepting === true ? { accepting: true } : {}),
95
191
  });
96
192
  }
@@ -1,7 +1,10 @@
1
- import type { Pattern } from '../compile/model.js';
1
+ import type { Pattern, RunPattern } from '../compile/model.js';
2
2
  export interface IRegexpMatcher {
3
3
  test(value: string): boolean;
4
4
  matches(value: string): boolean;
5
5
  }
6
- /** Load portable NFA data without a regex engine or dynamic compilation. */
7
- export declare function loadPattern(pattern: Pattern): IRegexpMatcher;
6
+ /**
7
+ * Load the portable counted-run or Thompson NFA executor for search and whole-string matching.
8
+ * Scratch belongs to one invocation: no match-result cache, shared mutable cursor or DFA expansion.
9
+ */
10
+ export declare function loadPattern(pattern: Pattern | RunPattern): IRegexpMatcher;