@hydranium/cli 1.0.0-next.10

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 (267) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +240 -0
  3. package/heap-analysis/analyze-heap.mjs +798 -0
  4. package/heap-analysis/heap/core/aggregate.mjs +152 -0
  5. package/heap-analysis/heap/core/bucket-label.mjs +23 -0
  6. package/heap-analysis/heap/core/cutpoints.mjs +51 -0
  7. package/heap-analysis/heap/core/diff.mjs +56 -0
  8. package/heap-analysis/heap/core/format.mjs +47 -0
  9. package/heap-analysis/heap/core/holders.mjs +80 -0
  10. package/heap-analysis/heap/core/load.mjs +46 -0
  11. package/heap-analysis/heap/core/report.mjs +68 -0
  12. package/heap-analysis/heap/core/strings.mjs +80 -0
  13. package/heap-analysis/heap/langium/concepts.mjs +230 -0
  14. package/heap-analysis/heap/langium/glsp.classifier.mjs +80 -0
  15. package/heap-analysis/heap/langium/langium.classifier.mjs +203 -0
  16. package/heap-analysis/heap/renderer/renderer.mjs +122 -0
  17. package/lib/cli-version.d.ts +21 -0
  18. package/lib/cli-version.d.ts.map +1 -0
  19. package/lib/cli-version.js +30 -0
  20. package/lib/cli-version.js.map +1 -0
  21. package/lib/cli.d.ts +11 -0
  22. package/lib/cli.d.ts.map +1 -0
  23. package/lib/cli.js +135 -0
  24. package/lib/cli.js.map +1 -0
  25. package/lib/commands/analyze-heap-args.d.ts +46 -0
  26. package/lib/commands/analyze-heap-args.d.ts.map +1 -0
  27. package/lib/commands/analyze-heap-args.js +174 -0
  28. package/lib/commands/analyze-heap-args.js.map +1 -0
  29. package/lib/commands/analyze-heap.d.ts +37 -0
  30. package/lib/commands/analyze-heap.d.ts.map +1 -0
  31. package/lib/commands/analyze-heap.js +63 -0
  32. package/lib/commands/analyze-heap.js.map +1 -0
  33. package/lib/commands/ast-ground-truth-args.d.ts +23 -0
  34. package/lib/commands/ast-ground-truth-args.d.ts.map +1 -0
  35. package/lib/commands/ast-ground-truth-args.js +47 -0
  36. package/lib/commands/ast-ground-truth-args.js.map +1 -0
  37. package/lib/commands/ast-ground-truth-driver.d.ts +10 -0
  38. package/lib/commands/ast-ground-truth-driver.d.ts.map +1 -0
  39. package/lib/commands/ast-ground-truth-driver.js +72 -0
  40. package/lib/commands/ast-ground-truth-driver.js.map +1 -0
  41. package/lib/commands/ast-ground-truth.d.ts +31 -0
  42. package/lib/commands/ast-ground-truth.d.ts.map +1 -0
  43. package/lib/commands/ast-ground-truth.js +36 -0
  44. package/lib/commands/ast-ground-truth.js.map +1 -0
  45. package/lib/commands/generate-transfer-model-args.d.ts +38 -0
  46. package/lib/commands/generate-transfer-model-args.d.ts.map +1 -0
  47. package/lib/commands/generate-transfer-model-args.js +183 -0
  48. package/lib/commands/generate-transfer-model-args.js.map +1 -0
  49. package/lib/commands/generate-transfer-model-config.d.ts +32 -0
  50. package/lib/commands/generate-transfer-model-config.d.ts.map +1 -0
  51. package/lib/commands/generate-transfer-model-config.js +122 -0
  52. package/lib/commands/generate-transfer-model-config.js.map +1 -0
  53. package/lib/commands/generate-transfer-model.d.ts +110 -0
  54. package/lib/commands/generate-transfer-model.d.ts.map +1 -0
  55. package/lib/commands/generate-transfer-model.js +587 -0
  56. package/lib/commands/generate-transfer-model.js.map +1 -0
  57. package/lib/commands/harness-args.d.ts +198 -0
  58. package/lib/commands/harness-args.d.ts.map +1 -0
  59. package/lib/commands/harness-args.js +339 -0
  60. package/lib/commands/harness-args.js.map +1 -0
  61. package/lib/commands/headless-harness.d.ts +97 -0
  62. package/lib/commands/headless-harness.d.ts.map +1 -0
  63. package/lib/commands/headless-harness.js +121 -0
  64. package/lib/commands/headless-harness.js.map +1 -0
  65. package/lib/commands/init-args.d.ts +81 -0
  66. package/lib/commands/init-args.d.ts.map +1 -0
  67. package/lib/commands/init-args.js +250 -0
  68. package/lib/commands/init-args.js.map +1 -0
  69. package/lib/commands/init-prompt.d.ts +66 -0
  70. package/lib/commands/init-prompt.d.ts.map +1 -0
  71. package/lib/commands/init-prompt.js +71 -0
  72. package/lib/commands/init-prompt.js.map +1 -0
  73. package/lib/commands/init-templates.d.ts +42 -0
  74. package/lib/commands/init-templates.d.ts.map +1 -0
  75. package/lib/commands/init-templates.js +1902 -0
  76. package/lib/commands/init-templates.js.map +1 -0
  77. package/lib/commands/init-wizard.d.ts +65 -0
  78. package/lib/commands/init-wizard.d.ts.map +1 -0
  79. package/lib/commands/init-wizard.js +302 -0
  80. package/lib/commands/init-wizard.js.map +1 -0
  81. package/lib/commands/init-workspace.d.ts +168 -0
  82. package/lib/commands/init-workspace.d.ts.map +1 -0
  83. package/lib/commands/init-workspace.js +372 -0
  84. package/lib/commands/init-workspace.js.map +1 -0
  85. package/lib/commands/init.d.ts +273 -0
  86. package/lib/commands/init.d.ts.map +1 -0
  87. package/lib/commands/init.js +303 -0
  88. package/lib/commands/init.js.map +1 -0
  89. package/lib/commands/lint-grammar-args.d.ts +23 -0
  90. package/lib/commands/lint-grammar-args.d.ts.map +1 -0
  91. package/lib/commands/lint-grammar-args.js +63 -0
  92. package/lib/commands/lint-grammar-args.js.map +1 -0
  93. package/lib/commands/lint-grammar-driver.d.ts +10 -0
  94. package/lib/commands/lint-grammar-driver.d.ts.map +1 -0
  95. package/lib/commands/lint-grammar-driver.js +72 -0
  96. package/lib/commands/lint-grammar-driver.js.map +1 -0
  97. package/lib/commands/lint-grammar-report.d.ts +24 -0
  98. package/lib/commands/lint-grammar-report.d.ts.map +1 -0
  99. package/lib/commands/lint-grammar-report.js +65 -0
  100. package/lib/commands/lint-grammar-report.js.map +1 -0
  101. package/lib/commands/lint-grammar.d.ts +33 -0
  102. package/lib/commands/lint-grammar.d.ts.map +1 -0
  103. package/lib/commands/lint-grammar.js +42 -0
  104. package/lib/commands/lint-grammar.js.map +1 -0
  105. package/lib/commands/measure-memory-args.d.ts +23 -0
  106. package/lib/commands/measure-memory-args.d.ts.map +1 -0
  107. package/lib/commands/measure-memory-args.js +106 -0
  108. package/lib/commands/measure-memory-args.js.map +1 -0
  109. package/lib/commands/measure-memory-driver.d.ts +10 -0
  110. package/lib/commands/measure-memory-driver.d.ts.map +1 -0
  111. package/lib/commands/measure-memory-driver.js +110 -0
  112. package/lib/commands/measure-memory-driver.js.map +1 -0
  113. package/lib/commands/measure-memory.d.ts +68 -0
  114. package/lib/commands/measure-memory.d.ts.map +1 -0
  115. package/lib/commands/measure-memory.js +100 -0
  116. package/lib/commands/measure-memory.js.map +1 -0
  117. package/lib/commands/model-docs-args.d.ts +23 -0
  118. package/lib/commands/model-docs-args.d.ts.map +1 -0
  119. package/lib/commands/model-docs-args.js +53 -0
  120. package/lib/commands/model-docs-args.js.map +1 -0
  121. package/lib/commands/model-docs-driver.d.ts +10 -0
  122. package/lib/commands/model-docs-driver.d.ts.map +1 -0
  123. package/lib/commands/model-docs-driver.js +61 -0
  124. package/lib/commands/model-docs-driver.js.map +1 -0
  125. package/lib/commands/model-docs-report.d.ts +18 -0
  126. package/lib/commands/model-docs-report.d.ts.map +1 -0
  127. package/lib/commands/model-docs-report.js +123 -0
  128. package/lib/commands/model-docs-report.js.map +1 -0
  129. package/lib/commands/model-docs.d.ts +30 -0
  130. package/lib/commands/model-docs.d.ts.map +1 -0
  131. package/lib/commands/model-docs.js +37 -0
  132. package/lib/commands/model-docs.js.map +1 -0
  133. package/lib/commands/projects-args.d.ts +25 -0
  134. package/lib/commands/projects-args.d.ts.map +1 -0
  135. package/lib/commands/projects-args.js +49 -0
  136. package/lib/commands/projects-args.js.map +1 -0
  137. package/lib/commands/projects.d.ts +45 -0
  138. package/lib/commands/projects.d.ts.map +1 -0
  139. package/lib/commands/projects.js +39 -0
  140. package/lib/commands/projects.js.map +1 -0
  141. package/lib/commands/query-args.d.ts +25 -0
  142. package/lib/commands/query-args.d.ts.map +1 -0
  143. package/lib/commands/query-args.js +46 -0
  144. package/lib/commands/query-args.js.map +1 -0
  145. package/lib/commands/query.d.ts +32 -0
  146. package/lib/commands/query.d.ts.map +1 -0
  147. package/lib/commands/query.js +29 -0
  148. package/lib/commands/query.js.map +1 -0
  149. package/lib/commands/reflect-args.d.ts +23 -0
  150. package/lib/commands/reflect-args.d.ts.map +1 -0
  151. package/lib/commands/reflect-args.js +59 -0
  152. package/lib/commands/reflect-args.js.map +1 -0
  153. package/lib/commands/reflect-driver.d.ts +10 -0
  154. package/lib/commands/reflect-driver.d.ts.map +1 -0
  155. package/lib/commands/reflect-driver.js +66 -0
  156. package/lib/commands/reflect-driver.js.map +1 -0
  157. package/lib/commands/reflect-report.d.ts +20 -0
  158. package/lib/commands/reflect-report.d.ts.map +1 -0
  159. package/lib/commands/reflect-report.js +127 -0
  160. package/lib/commands/reflect-report.js.map +1 -0
  161. package/lib/commands/reflect.d.ts +30 -0
  162. package/lib/commands/reflect.d.ts.map +1 -0
  163. package/lib/commands/reflect.js +38 -0
  164. package/lib/commands/reflect.js.map +1 -0
  165. package/lib/commands/save-args.d.ts +26 -0
  166. package/lib/commands/save-args.d.ts.map +1 -0
  167. package/lib/commands/save-args.js +59 -0
  168. package/lib/commands/save-args.js.map +1 -0
  169. package/lib/commands/save.d.ts +38 -0
  170. package/lib/commands/save.d.ts.map +1 -0
  171. package/lib/commands/save.js +48 -0
  172. package/lib/commands/save.js.map +1 -0
  173. package/lib/commands/validate-args.d.ts +23 -0
  174. package/lib/commands/validate-args.d.ts.map +1 -0
  175. package/lib/commands/validate-args.js +60 -0
  176. package/lib/commands/validate-args.js.map +1 -0
  177. package/lib/commands/validate-driver.d.ts +10 -0
  178. package/lib/commands/validate-driver.d.ts.map +1 -0
  179. package/lib/commands/validate-driver.js +72 -0
  180. package/lib/commands/validate-driver.js.map +1 -0
  181. package/lib/commands/validate-report.d.ts +30 -0
  182. package/lib/commands/validate-report.d.ts.map +1 -0
  183. package/lib/commands/validate-report.js +87 -0
  184. package/lib/commands/validate-report.js.map +1 -0
  185. package/lib/commands/validate.d.ts +34 -0
  186. package/lib/commands/validate.d.ts.map +1 -0
  187. package/lib/commands/validate.js +41 -0
  188. package/lib/commands/validate.js.map +1 -0
  189. package/lib/commands/watch-args.d.ts +26 -0
  190. package/lib/commands/watch-args.d.ts.map +1 -0
  191. package/lib/commands/watch-args.js +59 -0
  192. package/lib/commands/watch-args.js.map +1 -0
  193. package/lib/commands/watch.d.ts +75 -0
  194. package/lib/commands/watch.d.ts.map +1 -0
  195. package/lib/commands/watch.js +112 -0
  196. package/lib/commands/watch.js.map +1 -0
  197. package/lib/index.d.ts +16 -0
  198. package/lib/index.d.ts.map +1 -0
  199. package/lib/index.js +16 -0
  200. package/lib/index.js.map +1 -0
  201. package/lib/log-level.d.ts +39 -0
  202. package/lib/log-level.d.ts.map +1 -0
  203. package/lib/log-level.js +47 -0
  204. package/lib/log-level.js.map +1 -0
  205. package/lib/package-name.d.ts +33 -0
  206. package/lib/package-name.d.ts.map +1 -0
  207. package/lib/package-name.js +37 -0
  208. package/lib/package-name.js.map +1 -0
  209. package/lib/spawn-data-server.d.ts +102 -0
  210. package/lib/spawn-data-server.d.ts.map +1 -0
  211. package/lib/spawn-data-server.js +154 -0
  212. package/lib/spawn-data-server.js.map +1 -0
  213. package/lib/testing/echo-server.d.ts +11 -0
  214. package/lib/testing/echo-server.d.ts.map +1 -0
  215. package/lib/testing/echo-server.js +79 -0
  216. package/lib/testing/echo-server.js.map +1 -0
  217. package/package.json +105 -0
  218. package/src/cli-version.ts +32 -0
  219. package/src/cli.ts +139 -0
  220. package/src/commands/analyze-heap-args.ts +184 -0
  221. package/src/commands/analyze-heap.ts +76 -0
  222. package/src/commands/ast-ground-truth-args.ts +63 -0
  223. package/src/commands/ast-ground-truth-driver.ts +81 -0
  224. package/src/commands/ast-ground-truth.ts +49 -0
  225. package/src/commands/generate-transfer-model-args.ts +203 -0
  226. package/src/commands/generate-transfer-model-config.ts +128 -0
  227. package/src/commands/generate-transfer-model.ts +716 -0
  228. package/src/commands/harness-args.ts +429 -0
  229. package/src/commands/headless-harness.ts +165 -0
  230. package/src/commands/init-args.ts +273 -0
  231. package/src/commands/init-prompt.ts +149 -0
  232. package/src/commands/init-templates.ts +2037 -0
  233. package/src/commands/init-wizard.ts +378 -0
  234. package/src/commands/init-workspace.ts +442 -0
  235. package/src/commands/init.ts +554 -0
  236. package/src/commands/lint-grammar-args.ts +79 -0
  237. package/src/commands/lint-grammar-driver.ts +83 -0
  238. package/src/commands/lint-grammar-report.ts +74 -0
  239. package/src/commands/lint-grammar.ts +57 -0
  240. package/src/commands/measure-memory-args.ts +123 -0
  241. package/src/commands/measure-memory-driver.ts +128 -0
  242. package/src/commands/measure-memory.ts +143 -0
  243. package/src/commands/model-docs-args.ts +69 -0
  244. package/src/commands/model-docs-driver.ts +68 -0
  245. package/src/commands/model-docs-report.ts +133 -0
  246. package/src/commands/model-docs.ts +48 -0
  247. package/src/commands/projects-args.ts +62 -0
  248. package/src/commands/projects.ts +76 -0
  249. package/src/commands/query-args.ts +61 -0
  250. package/src/commands/query.ts +58 -0
  251. package/src/commands/reflect-args.ts +75 -0
  252. package/src/commands/reflect-driver.ts +76 -0
  253. package/src/commands/reflect-report.ts +138 -0
  254. package/src/commands/reflect.ts +51 -0
  255. package/src/commands/save-args.ts +74 -0
  256. package/src/commands/save.ts +84 -0
  257. package/src/commands/validate-args.ts +76 -0
  258. package/src/commands/validate-driver.ts +84 -0
  259. package/src/commands/validate-report.ts +95 -0
  260. package/src/commands/validate.ts +58 -0
  261. package/src/commands/watch-args.ts +74 -0
  262. package/src/commands/watch.ts +185 -0
  263. package/src/index.ts +16 -0
  264. package/src/log-level.ts +49 -0
  265. package/src/package-name.ts +39 -0
  266. package/src/spawn-data-server.ts +247 -0
  267. package/src/testing/echo-server.ts +93 -0
@@ -0,0 +1,230 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ /*
11
+ * Concept-classification engine: shared heap-node helpers, the primitive / plain
12
+ * fallback (V8/JS universals, no language vocabulary), and `composeClassifiers`,
13
+ * which folds a set of ConceptClassifier contributions into the `classify` /
14
+ * `isAnchorConcept` / `conceptGroup` / `grammarTypes` the analyzer consumes.
15
+ *
16
+ * The engine knows no model vocabulary of its own — Langium and GLSP knowledge
17
+ * live in classifier contributions loaded by default, exactly the contract an
18
+ * adopter's `--classifier` file uses.
19
+ */
20
+
21
+ /**
22
+ * @typedef {Object} ConceptClassifier
23
+ * @property {(node: import('@memlab/core').IHeapNode) => (string|undefined)} classify
24
+ * Map a heap node to a concept label, or `undefined` to defer to the next
25
+ * classifier / the engine fallback. Receives only `object`-typed nodes
26
+ * (primitives are the engine's baseline).
27
+ * @property {string[]} [anchorConcepts] Concept labels this classifier owns as
28
+ * exclusive-retained attribution anchors.
29
+ * @property {string[]} [grammarTypes] `$type`s from a meta-grammar that appear in
30
+ * the heap but not an adopter document model (e.g. Langium's own grammar AST).
31
+ * @property {(label: string) => boolean} [isAnchor] Predicate for prefix-based
32
+ * anchors (e.g. `AST node:*`); supplements `anchorConcepts`.
33
+ * @property {Record<string, string>} [descriptions] One-line explanations keyed by
34
+ * root group (first label segment, e.g. `GModel`, `CST`), shown under that
35
+ * group's heading in the hierarchical breakdown.
36
+ *
37
+ * A label is a `:`-delimited HIERARCHY PATH (`L1:L2:L3`, see {@link parseLabelPath}):
38
+ * the first segment is the display group and the analyzer aggregates at every
39
+ * prefix, so a classifier never declares a group — it just mints a path. Each
40
+ * segment must be `:`-free (spaces are fine); ≤3 levels is the readability
41
+ * convention, but aggregation is depth-agnostic and never truncates.
42
+ */
43
+
44
+ /** Property-name set of a node's own named properties. */
45
+ export function propertySet(node) {
46
+ const set = new Set();
47
+ for (const edge of node.references) {
48
+ if (edge.type === 'property' && !edge.is_index && edge.name_or_index !== '__proto__') {
49
+ set.add(edge.name_or_index);
50
+ }
51
+ }
52
+ return set;
53
+ }
54
+
55
+ /** Value of a string-valued property edge (e.g. the `$type` element kind). */
56
+ export function stringProp(node, name) {
57
+ for (const edge of node.references) {
58
+ if (edge.type === 'property' && edge.name_or_index === name) {
59
+ const target = edge.toNode;
60
+ if (target && (target.type === 'string' || target.type === 'concatenated string')) {
61
+ return target.name;
62
+ }
63
+ return undefined;
64
+ }
65
+ }
66
+ return undefined;
67
+ }
68
+
69
+ /** True when a property set contains every named property. */
70
+ export const has = (set, ...names) => names.every(name => set.has(name));
71
+
72
+ /**
73
+ * Follow a property edge to its target object and read a string property off it
74
+ * (one hop of dereference). Used where a discriminator lives on a referenced node
75
+ * rather than inline — e.g. a leaf CST node's token type is `_tokenType.name`.
76
+ */
77
+ export function derefStringProp(node, edgeName, prop) {
78
+ for (const edge of node.references) {
79
+ if (edge.type === 'property' && edge.name_or_index === edgeName && edge.toNode) {
80
+ return stringProp(edge.toNode, prop);
81
+ }
82
+ }
83
+ return undefined;
84
+ }
85
+
86
+ /**
87
+ * Read a discriminator property (e.g. `$type`/`type`) as a usable label segment.
88
+ * A concatenated/sliced string value cannot be materialized by memlab — it
89
+ * surfaces as a placeholder like `(concatenated string)`; treat any such
90
+ * unreadable value (and a missing one) as `unknown` rather than leaking the
91
+ * placeholder into a concept label.
92
+ */
93
+ export function readableType(node, name = 'type') {
94
+ const value = stringProp(node, name);
95
+ return value && !value.startsWith('(') ? value : 'unknown';
96
+ }
97
+
98
+ /**
99
+ * Split a `:`-delimited label into its hierarchy segments: the first segment is
100
+ * the display group and each deeper segment a drill-down level. ≤3 levels is the
101
+ * convention, but parsing is depth-agnostic — it never truncates, so an adopter
102
+ * that emits a deeper path simply gets a deeper tree (and a `:`-free label is a
103
+ * 1-level leaf, which is always valid). Empty/blank → a single `(unknown)`
104
+ * segment so callers always get a non-empty group.
105
+ */
106
+ export function parseLabelPath(label) {
107
+ const trimmed = (label ?? '').trim();
108
+ return trimmed ? trimmed.split(':') : ['(unknown)'];
109
+ }
110
+
111
+ /**
112
+ * Aggregate labelled buckets into a hierarchy keyed by the `:`-delimited label
113
+ * path. EVERY prefix accumulates, so a label `A:B:C` adds its sizes to nodes `A`,
114
+ * `A→B` and `A→B→C`; a parent's sizes are therefore exactly the sum of its
115
+ * descendants' leaf buckets (the reconciliation invariant the report relies on).
116
+ * Each tree node is `{ sizes: {count, shallow, exclusive, overlapping}, children:
117
+ * Map<segment, node> }`. No concept is hardcoded — the tree shape is whatever the
118
+ * labels imply.
119
+ *
120
+ * @param {Iterable<[string, {count: number, shallow: number, retainedOverlapping: number}]>} buckets
121
+ * `[label, byBucket-entry]` pairs (the shallow/overlapping/count view per label).
122
+ * @param {(label: string) => number} exclusiveOf exclusive-retained bytes for a label.
123
+ * @returns {Map<string, {sizes: object, children: Map}>} the L1 group → subtree map.
124
+ */
125
+ export function buildHierarchy(buckets, exclusiveOf) {
126
+ const root = new Map();
127
+ const ensure = (map, segment) => {
128
+ let node = map.get(segment);
129
+ if (!node) {
130
+ node = { sizes: { count: 0, shallow: 0, exclusive: 0, overlapping: 0 }, children: new Map() };
131
+ map.set(segment, node);
132
+ }
133
+ return node;
134
+ };
135
+ for (const [label, entry] of buckets) {
136
+ const exclusive = exclusiveOf(label);
137
+ let level = root;
138
+ for (const segment of parseLabelPath(label)) {
139
+ const node = ensure(level, segment);
140
+ node.sizes.count += entry.count;
141
+ node.sizes.shallow += entry.shallow;
142
+ node.sizes.exclusive += exclusive;
143
+ node.sizes.overlapping += entry.retainedOverlapping;
144
+ level = node.children;
145
+ }
146
+ }
147
+ return root;
148
+ }
149
+
150
+ /** Engine baseline for non-`object` heap nodes — V8/JS universals, no vocabulary. */
151
+ function classifyPrimitive(type) {
152
+ switch (type) {
153
+ case 'string':
154
+ return 'string';
155
+ case 'concatenated string':
156
+ return 'string (concatenated)';
157
+ case 'sliced string':
158
+ return 'string (sliced)';
159
+ case 'number':
160
+ return 'boxed number';
161
+ case 'closure':
162
+ return 'closure';
163
+ case 'code':
164
+ case 'compiled code':
165
+ return 'code';
166
+ case 'array':
167
+ return 'array (backing)';
168
+ case 'hidden':
169
+ return 'hidden';
170
+ case 'synthetic':
171
+ return 'synthetic (roots)';
172
+ case 'native':
173
+ return 'native';
174
+ default:
175
+ return `(${type})`;
176
+ }
177
+ }
178
+
179
+ /** Engine fallback for an `object` node no classifier claimed. */
180
+ function classifyObjectFallback(node) {
181
+ if (node.name && node.name !== 'Object') {
182
+ return `class:${node.name}`;
183
+ }
184
+ return propertySet(node).size === 0 ? 'empty object {}' : 'other Object shape';
185
+ }
186
+
187
+ /**
188
+ * Fold a set of {@link ConceptClassifier} contributions into the classification
189
+ * functions the analyzer consumes. Contributions are tried in order — first
190
+ * non-`undefined` `classify` wins — with the engine's primitive handling before
191
+ * them and its `class:<name>` / `other Object shape` fallback after. Anchors are
192
+ * the union of every contribution's `anchorConcepts` plus any `isAnchor`
193
+ * predicate; `grammarTypes` is the union of all contributions' grammar `$type`s.
194
+ *
195
+ * `conceptGroup` is structural, NOT contributed: a label's group is the first
196
+ * segment of its `:`-delimited path (see {@link parseLabelPath}). Since
197
+ * classifiers mint the label, the first segment IS the display group — there is
198
+ * no alias/rename layer to keep in sync.
199
+ *
200
+ * @param {ConceptClassifier[]} contributions
201
+ */
202
+ export function composeClassifiers(contributions) {
203
+ const anchorSet = new Set(contributions.flatMap(contribution => contribution.anchorConcepts ?? []));
204
+ const grammarTypes = new Set(contributions.flatMap(contribution => contribution.grammarTypes ?? []));
205
+ // Merge group descriptions; earlier contributions win (adopter overrides default),
206
+ // so apply defaults first and the earlier contributions last.
207
+ const descriptions = Object.assign({}, ...[...contributions].reverse().map(contribution => contribution.descriptions ?? {}));
208
+
209
+ const classify = node => {
210
+ if (node.type !== 'object') {
211
+ return classifyPrimitive(node.type);
212
+ }
213
+ for (const contribution of contributions) {
214
+ const label = contribution.classify(node);
215
+ if (label !== undefined) {
216
+ return label;
217
+ }
218
+ }
219
+ return classifyObjectFallback(node);
220
+ };
221
+
222
+ const isAnchorConcept = label => anchorSet.has(label) || contributions.some(contribution => contribution.isAnchor?.(label) === true);
223
+
224
+ // The display group is structural: the first segment of the label path.
225
+ const conceptGroup = label => parseLabelPath(label)[0];
226
+
227
+ const describe = group => descriptions[group];
228
+
229
+ return { classify, isAnchorConcept, conceptGroup, grammarTypes, describe };
230
+ }
@@ -0,0 +1,80 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ /*
11
+ * GLSP GModel concept classifier — a default contribution for heads with a
12
+ * `@hydranium/glsp-server` diagram layer. GModel elements are class instances
13
+ * from `@eclipse-glsp/graph` (GGraph/GNode/GEdge/GLabel/GCompartment/…), each
14
+ * carrying a `type` string and the shared own-prop set
15
+ * {type,id,children,cssClasses}. So this mirrors CST (recognise by constructor)
16
+ * and AST (sub-label by the discriminator) at once: a GModel instance →
17
+ * `GModel:<type>` (the field is `type`, NOT `$type`).
18
+ *
19
+ * The `type` string is itself hierarchical by GLSP convention
20
+ * (`<kind>:<subtype>`), so the label becomes a 3-level path
21
+ * `GModel:<kind>:<subtype>` that the analyzer drills into (group `GModel`, then
22
+ * by kind `node`/`edge`/`comp`/`label`/`graph`, then by subtype). A flat `type`
23
+ * (`graph`, `label`) is simply a 2-level leaf — never wrong.
24
+ *
25
+ * The element vocabulary is framework-fixed (`@eclipse-glsp/graph`), so it ships
26
+ * as a default rather than behind discovery. On a non-GLSP heap it matches
27
+ * nothing and is inert. Only leaf option bags (`layoutOptions`/`args`) are plain
28
+ * objects — negligible mass — so no plain-object predicate is needed; the
29
+ * structural fallback catches any GModel subtype a head adds beyond this set.
30
+ */
31
+
32
+ import { has, propertySet, readableType } from './concepts.mjs';
33
+
34
+ /** `@eclipse-glsp/graph` element classes — the framework-fixed GModel vocabulary. */
35
+ const GMODEL_CTORS = new Set([
36
+ 'GGraph',
37
+ 'GNode',
38
+ 'GEdge',
39
+ 'GLabel',
40
+ 'GCompartment',
41
+ 'GPort',
42
+ 'GForeignObjectElement',
43
+ 'GHtmlRoot',
44
+ 'GIssueMarker'
45
+ ]);
46
+
47
+ /** @type {import('./concepts.mjs').ConceptClassifier} */
48
+ export const glspClassifier = {
49
+ classify(node) {
50
+ if (node.type !== 'object') {
51
+ return undefined;
52
+ }
53
+ const { name } = node;
54
+ if (name && GMODEL_CTORS.has(name)) {
55
+ return `GModel:${readableType(node)}`;
56
+ }
57
+ // Recognise any GModel element by its shared own-prop shape
58
+ // {type,id,children,cssClasses}, regardless of constructor name. A bundled
59
+ // server renames the classes (`_GLabel`) and heads add their own
60
+ // subclasses (`_AttributeCompartment`), so a name allow-list misses most
61
+ // of a real diagram — the structural signature is what holds. The shape is
62
+ // GLSP-specific, and Langium runs first, so only unclassified objects reach
63
+ // this check (no risk of stealing a model node).
64
+ if (has(propertySet(node), 'type', 'id', 'children', 'cssClasses')) {
65
+ return `GModel:${readableType(node)}`;
66
+ }
67
+ return undefined;
68
+ },
69
+
70
+ // Matches the raw per-node labels (exclusive-retained attribution anchors)
71
+ // and the bare group (`GModel`, retainer-path selection).
72
+ isAnchor(label) {
73
+ return label.startsWith('GModel');
74
+ },
75
+
76
+ descriptions: {
77
+ GModel:
78
+ 'GLSP graphical-model elements for the open diagrams (nodes, edges, labels, ports, compartments). Sub-levels are the GLSP `type`, itself a `<kind>:<subtype>` path.'
79
+ }
80
+ };
@@ -0,0 +1,203 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ /*
11
+ * Generic Langium/LSP concept classifier — the default contribution every run
12
+ * loads. Its `classify(node)` returns a Langium concept label or `undefined` to
13
+ * defer to the next classifier / the engine fallback. Recognises class instances
14
+ * by constructor and plain objects by their property-name set; AST nodes and
15
+ * descriptions are sub-labelled by `$type` / element kind so the report can
16
+ * break down by element. No application-specific vocabulary — heads contribute
17
+ * their own classifier alongside this one.
18
+ */
19
+
20
+ import { derefStringProp, has, propertySet, stringProp } from './concepts.mjs';
21
+
22
+ /** Concepts that own memory and act as exclusive-retained attribution anchors.
23
+ * (CST/AST node/AstNodeDescription are matched by prefix in `isAnchor`.) */
24
+ const ANCHOR_CONCEPTS = ['Range', 'Position', 'DocumentSegment', 'MultiMap', 'Map', 'LangiumDocument', 'ParseResult', 'Reference'];
25
+
26
+ /**
27
+ * CST node constructors → their role, so CST drills down like AST
28
+ * (`CST:leaf`/`CST:composite`/`CST:root`/`CST:container`). Generic Langium names,
29
+ * no language coupling. A bundled server may prefix `_`, hence the lookup strips
30
+ * a leading underscore.
31
+ */
32
+ const CST_ROLE = {
33
+ LeafCstNodeImpl: 'leaf',
34
+ CompositeCstNodeImpl: 'composite',
35
+ RootCstNodeImpl: 'root',
36
+ CstNodeContainer: 'container'
37
+ };
38
+
39
+ /**
40
+ * AST node $types from Langium's OWN grammar language. These appear in a
41
+ * language-server heap (the parsed .langium grammar) but never in an adopter's
42
+ * document model, so a `--validate` cross-check treats them as expected
43
+ * snapshot-only rather than a discrepancy. Generic Langium, not app-specific.
44
+ */
45
+ const LANGIUM_GRAMMAR_TYPES = [
46
+ 'Grammar',
47
+ 'GrammarImport',
48
+ 'AbstractRule',
49
+ 'ParserRule',
50
+ 'TerminalRule',
51
+ 'InfixRule',
52
+ 'Type',
53
+ 'Interface',
54
+ 'AbstractType',
55
+ 'Action',
56
+ 'Alternatives',
57
+ 'Group',
58
+ 'UnorderedGroup',
59
+ 'Assignment',
60
+ 'RuleCall',
61
+ 'CrossReference',
62
+ 'Keyword',
63
+ 'RegexToken',
64
+ 'TerminalAlternatives',
65
+ 'TerminalGroup',
66
+ 'TerminalRuleCall',
67
+ 'CharacterRange',
68
+ 'NegatedToken',
69
+ 'UntilToken',
70
+ 'Wildcard',
71
+ 'EndOfFile',
72
+ 'SimpleType',
73
+ 'ReferenceType',
74
+ 'ArrayType',
75
+ 'UnionType',
76
+ 'TypeAttribute',
77
+ 'ParameterReference',
78
+ 'ReturnType',
79
+ 'NamedArgument',
80
+ 'Parameter',
81
+ 'Conjunction',
82
+ 'Disjunction',
83
+ 'Negation',
84
+ 'BooleanLiteral',
85
+ 'NumberLiteral',
86
+ 'StringLiteral'
87
+ ];
88
+
89
+ /** @type {import('./concepts.mjs').ConceptClassifier} */
90
+ export const langiumClassifier = {
91
+ classify(node) {
92
+ const { type, name } = node;
93
+ if (type !== 'object') {
94
+ return undefined; // primitives are the engine's baseline
95
+ }
96
+
97
+ // Class instances: recognised by constructor name.
98
+ if (name && name !== 'Object') {
99
+ const cstRole = CST_ROLE[name.startsWith('_') ? name.slice(1) : name];
100
+ if (cstRole) {
101
+ // A leaf is a single token; sub-label by its token type
102
+ // (`_tokenType.name` — `ID`, `STRING`, or the keyword text), so the
103
+ // CST breakdown shows which tokens dominate (e.g. trivia vs identifiers).
104
+ if (cstRole === 'leaf') {
105
+ const token = derefStringProp(node, '_tokenType', 'name')?.trim();
106
+ if (!token) {
107
+ return 'CST:leaf';
108
+ }
109
+ // Token names are either identifier-like (terminals `ID`/`STRING`,
110
+ // keywords `name`/`value`) or punctuation (`:`/`{`/`;`). Bucket
111
+ // punctuation together: per-mark counts are noise, and a literal `:`
112
+ // would corrupt the `:`-delimited label path (and `>` the ` > `
113
+ // display) if embedded as a segment.
114
+ return /^[A-Za-z_][\w-]*$/.test(token) ? `CST:leaf:${token}` : 'CST:leaf:(punctuation)';
115
+ }
116
+ return `CST:${cstRole}`;
117
+ }
118
+ // Any class whose name ends in AstNodeDescription is a description wrapper;
119
+ // the prefix is the scope layer (Local, Global, ...). Labelled
120
+ // `AstNodeDescription:<layer>` so it nests under the description family at
121
+ // L2 (the bases sit at `AstNodeDescription:base:<kind>`). Generic: no app names.
122
+ if (name.endsWith('AstNodeDescription')) {
123
+ const layer = name.slice(0, -'AstNodeDescription'.length) || 'base';
124
+ return `AstNodeDescription:${layer}`;
125
+ }
126
+ // Index manager is an attribution anchor but keeps its real name; Map/MultiMap
127
+ // stay their own names too (referrer edges show which are the scope index).
128
+ if (name.endsWith('IndexManager') || name === 'MultiMap' || name === 'Map') {
129
+ return name;
130
+ }
131
+ return undefined; // defer (engine → class:<name>, or a later classifier)
132
+ }
133
+
134
+ // Plain object literal: classify by property-name set.
135
+ const props = propertySet(node);
136
+ if (props.size === 0) {
137
+ // A Position {line,character} whose numeric fields are inline SMIs has NO
138
+ // property edges on the heap, so it looks empty. Recover it from an
139
+ // incoming Range `start`/`end` edge — otherwise the millions of Range
140
+ // endpoints misbucket as 'empty object {}' (the biggest single
141
+ // misclassification on a large workspace).
142
+ for (const edge of node.referrers) {
143
+ if (edge.type === 'property' && (edge.name_or_index === 'start' || edge.name_or_index === 'end')) {
144
+ return 'Position';
145
+ }
146
+ }
147
+ return undefined; // defer → engine 'empty object {}'
148
+ }
149
+ if (props.has('$type')) {
150
+ return `AST node:${stringProp(node, '$type') ?? 'unknown'}`;
151
+ }
152
+ if (props.size === 2 && has(props, 'start', 'end')) {
153
+ return 'Range';
154
+ }
155
+ if (has(props, 'line', 'character')) {
156
+ return 'Position';
157
+ }
158
+ if (has(props, 'parseResult', 'uri') || has(props, 'localSymbols', 'parseResult', 'uri')) {
159
+ return 'LangiumDocument';
160
+ }
161
+ if (has(props, 'value', 'lexerErrors', 'parserErrors')) {
162
+ return 'ParseResult';
163
+ }
164
+ if (has(props, 'name', 'nameSegment', 'documentUri', 'node', 'selectionSegment')) {
165
+ // The base description payload carries `type` = the described node's element
166
+ // kind. Labelled `AstNodeDescription:base:<kind>` so it nests under the
167
+ // description family: L2 `base` aggregates all payloads (alongside the L2
168
+ // scope-wrapper layers above), L3 `<kind>` is the per-element-kind split.
169
+ return `AstNodeDescription:base:${stringProp(node, 'type') ?? 'unknown'}`;
170
+ }
171
+ if (has(props, '$refText', 'ref')) {
172
+ return 'Reference';
173
+ }
174
+ if (has(props, 'range') && props.size <= 3) {
175
+ return 'DocumentSegment';
176
+ }
177
+ return undefined; // defer → engine 'other Object shape'
178
+ },
179
+
180
+ anchorConcepts: ANCHOR_CONCEPTS,
181
+ grammarTypes: LANGIUM_GRAMMAR_TYPES,
182
+
183
+ // Matches both the raw per-node labels (`AST node:Class`, used as exclusive-
184
+ // retained attribution anchors) and the bare group (`AST node`, used to pick
185
+ // top concepts for the retainer-path sample). `AstNodeDescription` prefix
186
+ // already covers the group and every layer/base path.
187
+ isAnchor(label) {
188
+ return (
189
+ label.startsWith('AST node') || label.startsWith('AstNodeDescription') || label.startsWith('CST') || label.endsWith('IndexManager')
190
+ );
191
+ },
192
+
193
+ descriptions: {
194
+ 'AST node':
195
+ 'Parsed abstract-syntax-tree nodes, split by `$type` (includes the Langium grammar AST since the parsed grammar shares the heap).',
196
+ AstNodeDescription:
197
+ 'Scope-index entries. `base` is the payload (one per exported symbol, split by element kind); `Local`/`Global`/… are thin per-scope-layer wrappers that delegate to a base.',
198
+ CST: 'Concrete-syntax-tree nodes: `leaf` = a token (sub-split by token type — `ID`, `STRING`, keyword text, with all punctuation bucketed as `(punctuation)`), `composite` = a grammar rule, `root` = a document root, `container` = a child-node array.',
199
+ Range: 'LSP text ranges (`start`/`end` Position pairs) attached to CST nodes and document segments.',
200
+ Position:
201
+ 'LSP `{line, character}` endpoints of Ranges (their numeric fields are inline, so they carry no heap properties of their own).'
202
+ }
203
+ };
@@ -0,0 +1,122 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ /*
11
+ * Renderer (browser) heap classification — the `--renderer` mode's counterpart to
12
+ * the Langium/GLSP classifiers. A renderer `.heapsnapshot` (from CDP
13
+ * `HeapProfiler.takeHeapSnapshot`, the `browser-heap` artefact) has NO Langium
14
+ * structure; its leak vocabulary is the DOM: detached DOM subtrees and the JS
15
+ * that retains them (event listeners, closures, arrays). So this classifier
16
+ * buckets by that vocabulary and lets the SAME report machinery (exclusive
17
+ * retained, holders, retainer paths) do the work — a retainer path to a
18
+ * `Detached DOM` concept IS the listener-retainer analysis.
19
+ *
20
+ * Unlike a normal ConceptClassifier contribution, this cannot be composed through
21
+ * `composeClassifiers`: DOM nodes are `native`-typed, and the engine short-circuits
22
+ * every non-`object` node to its primitive bucket BEFORE contributions run. So the
23
+ * renderer mode installs a dedicated `classify` that intercepts `native`/DOM nodes
24
+ * itself and delegates everything else to the engine baseline (the JS/V8 universals
25
+ * — strings, arrays, closures — which a renderer heap has just like any other).
26
+ */
27
+
28
+ import { composeClassifiers } from '../langium/concepts.mjs';
29
+
30
+ const DETACHED_PREFIX = 'Detached ';
31
+ const SYSTEM_PREFIX = 'system';
32
+ /** Object-node class names V8 uses for a registered DOM event listener. */
33
+ const EVENT_LISTENER_NAMES = new Set(['V8EventListener', 'EventListener']);
34
+
35
+ /**
36
+ * A clean, single-segment DOM key for a heap node name. V8 names a DOM element by
37
+ * its markup or by its class (`HTMLDivElement`, `Text`). The raw markup breaks the
38
+ * report: the `<…>` is eaten as literal HTML by a Markdown renderer, an inline
39
+ * `style` attribute's `:` collides with the label-path separator, and a `|` would
40
+ * break the table column. So an element descriptor is normalised to a CSS selector
41
+ * — dropping the `style`/`data-*` soup, which also collapses near-duplicate rows —
42
+ * and any residual `:`/`|`/`<`/`>`/`"` is stripped. A plain class name passes
43
+ * through, and V8's trailing ` / <url>` suffix is dropped.
44
+ */
45
+ function domClass(name) {
46
+ const raw = (name || 'native').split(' / ')[0].trim() || 'native';
47
+ const element = raw.match(/^<([a-zA-Z][\w-]*)([^>]*)>$/);
48
+ let key = raw;
49
+ if (element) {
50
+ const tag = element[1].toLowerCase();
51
+ const id = (element[2].match(/\bid="([^"]*)"/) ?? ['', ''])[1].trim();
52
+ const classes = (element[2].match(/\bclass="([^"]*)"/) ?? ['', ''])[1].trim();
53
+ const idSel = id ? `#${id}` : '';
54
+ const classSel = classes ? `.${classes.split(/\s+/).filter(Boolean).join('.')}` : '';
55
+ key = `${tag}${idSel}${classSel}`;
56
+ }
57
+ return (
58
+ key
59
+ .replace(/[:|<>"]/g, ' ')
60
+ .replace(/\s+/g, ' ')
61
+ .trim()
62
+ .slice(0, 80) || 'native'
63
+ );
64
+ }
65
+
66
+ /** The subtype of a V8 `system` native (`system / Context` → `Context`; bare `system` → `(other)`). */
67
+ function nativeSubtype(name) {
68
+ const slash = name.indexOf('/');
69
+ return slash >= 0 ? name.slice(slash + 1).trim() || '(other)' : '(other)';
70
+ }
71
+
72
+ const RENDERER_DESCRIPTIONS = {
73
+ 'Detached DOM':
74
+ "DOM nodes no longer in the document tree but still retained by JS — the classic browser leak. Follow each concept's retainer path to the listener / closure / array holding it; that holder is the lever.",
75
+ 'DOM node':
76
+ 'Live DOM nodes still attached to the document, grouped by element class. Growth across a session (vs a stable baseline) points at accumulating UI.',
77
+ 'V8 native':
78
+ 'V8-internal native allocations (`system / Context`, `system / JSArrayBufferData`, …) — NOT DOM. Renderer memory held by the engine (contexts, ArrayBuffer backing stores), grouped by system subtype.',
79
+ 'Event listener':
80
+ 'Registered DOM event listeners (V8EventListener). A listener retaining a detached subtree is a leak; a rising count is the other classic tell.'
81
+ };
82
+
83
+ /**
84
+ * Build the renderer classification functions in the shape the analyzer consumes
85
+ * ({@link composeClassifiers}'s return), intercepting `native`/DOM + event-listener
86
+ * nodes and delegating the rest to the engine baseline (no Langium/GLSP vocabulary).
87
+ */
88
+ export function rendererClassifiers() {
89
+ const baseline = composeClassifiers([]);
90
+ const classify = node => {
91
+ if (node.type === 'native') {
92
+ const name = node.name || '';
93
+ if (name.startsWith(DETACHED_PREFIX)) {
94
+ return `Detached DOM:${domClass(name.slice(DETACHED_PREFIX.length))}`;
95
+ }
96
+ // V8-internal native allocations (`system / Context`, `system / JSArrayBufferData`,
97
+ // …) are NOT DOM — bucket them apart so `DOM node` reflects real elements.
98
+ if (name === SYSTEM_PREFIX || name.startsWith(`${SYSTEM_PREFIX} `) || name.startsWith(`${SYSTEM_PREFIX}/`)) {
99
+ return `V8 native:${nativeSubtype(name)}`;
100
+ }
101
+ return `DOM node:${domClass(name)}`;
102
+ }
103
+ if (node.type === 'object' && EVENT_LISTENER_NAMES.has(node.name)) {
104
+ return 'Event listener';
105
+ }
106
+ return baseline.classify(node);
107
+ };
108
+ // Anchor the DOM concepts AND the per-constructor `class:<Name>` buckets: a renderer
109
+ // heap has no curated model, so class instances (widgets, models, caches, framework
110
+ // objects) are the meaningful attribution anchors. Without this the ~1/5 of the heap
111
+ // that is the JS object graph shows 0 exclusive retained (attributed up to GC roots);
112
+ // anchoring per-class turns it into a "which constructor retains the most" view.
113
+ const isAnchorConcept = label =>
114
+ label.startsWith('Detached DOM') ||
115
+ label.startsWith('DOM node') ||
116
+ label.startsWith('V8 native') ||
117
+ label === 'Event listener' ||
118
+ label === 'class' ||
119
+ label.startsWith('class:');
120
+ const describe = group => RENDERER_DESCRIPTIONS[group];
121
+ return { classify, isAnchorConcept, conceptGroup: baseline.conceptGroup, grammarTypes: new Set(), describe };
122
+ }
@@ -0,0 +1,21 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+ /**
10
+ * The version of the running binary.
11
+ *
12
+ * Read from the manifest rather than emitted as a constant at build time: a
13
+ * generated constant is a second copy of a number the manifest already carries,
14
+ * and nothing goes red while the two disagree.
15
+ *
16
+ * Throws rather than reporting `unknown`: every caller turns the number into a
17
+ * claim someone else acts on — a pinned dependency range, a version in a bug
18
+ * report — where a placeholder is worse than a failure.
19
+ */
20
+ export declare function readCliVersion(): string;
21
+ //# sourceMappingURL=cli-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-version.d.ts","sourceRoot":"","sources":["../src/cli-version.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAOlF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAMvC"}