@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,303 @@
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
+ import * as fs from 'node:fs';
10
+ import * as path from 'node:path';
11
+ import { buildInitTemplates, readFrameworkVersion, UNPUBLISHED_FRAMEWORK_VERSION } from './init-templates.js';
12
+ import { createNodeWorkspaceProbe, detectWorkspace } from './init-workspace.js';
13
+ /**
14
+ * The protocol heads a scaffold can start, in composition order.
15
+ *
16
+ * `lsp` is mandatory rather than optional: it owns the workspace, the build
17
+ * pipeline and the shared service tier every other head reads through, so a
18
+ * project without it has nothing for `data` or `glsp` to serve.
19
+ */
20
+ export const INIT_HEADS = ['lsp', 'data', 'glsp'];
21
+ /** The heads a scaffold emits when `--heads` is not given. */
22
+ export const DEFAULT_INIT_HEADS = ['lsp', 'data'];
23
+ /** True for a string naming one of {@link INIT_HEADS}. */
24
+ export function isInitHead(value) {
25
+ return INIT_HEADS.includes(value);
26
+ }
27
+ /**
28
+ * A standalone, unscoped, unpublishable package — what `init` emits without the
29
+ * packaging flags.
30
+ *
31
+ * `private` defaults to TRUE because the manifest also declares `license:
32
+ * "UNLICENSED"`, and a package that grants no rights while being publishable to
33
+ * a public registry asserts two contradictory things about itself. npm pairs
34
+ * those two keys for exactly this reason. The scaffold cannot pick a licence for
35
+ * a stranger's project, so it withholds publication instead of granting rights
36
+ * nobody chose; `--public` is the opt-out for a project that has picked one.
37
+ */
38
+ export const STANDALONE_PACKAGING = { private: true };
39
+ /** Kebab-case a PascalCase/camelCase name. */
40
+ export function kebab(name) {
41
+ return name.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
42
+ }
43
+ /** True for a PascalCase identifier legal as a generated TypeScript symbol prefix. */
44
+ function isPascalIdentifier(value) {
45
+ return /^[A-Za-z][A-Za-z0-9]*$/.test(value);
46
+ }
47
+ /** Strip a leading dot and reject an extension that is empty or dotted through. */
48
+ function normalizeExtension(value, grammar) {
49
+ const extension = value.replace(/^\./, '');
50
+ if (extension.length === 0) {
51
+ throw new Error(`Invalid extension '${value}' for grammar '${grammar}': an extension cannot be empty.`);
52
+ }
53
+ return extension;
54
+ }
55
+ /**
56
+ * Resolve one grammar's names.
57
+ *
58
+ * `qualify` comes from the project rather than the grammar: a lone grammar
59
+ * whose name matches the project keeps the bare project id, but as soon as
60
+ * there are several every id is qualified, so the set reads consistently
61
+ * instead of one member being special.
62
+ */
63
+ function resolveGrammar(spec, projectId, qualify, diagram) {
64
+ if (!isPascalIdentifier(spec.name)) {
65
+ throw new Error(`Invalid --grammar '${spec.name}': must be a PascalCase identifier (letters and digits, starting with a letter), e.g. 'Domain'.`);
66
+ }
67
+ const grammarId = kebab(spec.name);
68
+ const extensions = (spec.extensions ?? [grammarId]).map(extension => normalizeExtension(extension, spec.name));
69
+ if (extensions.length === 0) {
70
+ throw new Error(`Invalid --extensions for grammar '${spec.name}': at least one extension is required.`);
71
+ }
72
+ return {
73
+ grammar: spec.name,
74
+ grammarId,
75
+ languageId: spec.languageId ?? (qualify || grammarId !== projectId ? `${projectId}-${grammarId}` : projectId),
76
+ extensions,
77
+ entryRule: `${spec.name}Model`,
78
+ nodeRule: `${spec.name}Node`,
79
+ diagram
80
+ };
81
+ }
82
+ /**
83
+ * Resolve which grammars get a diagram.
84
+ *
85
+ * With the `glsp` head on and nothing marked, a lone grammar is unambiguous and
86
+ * is taken as the diagram's; with several it is a real choice, so it is required
87
+ * rather than guessed — binding a diagram to the wrong grammar surfaces much
88
+ * later as references resolving against the wrong scope.
89
+ */
90
+ function resolveDiagrams(specs, heads) {
91
+ const marked = specs.map(spec => spec.diagram === true);
92
+ if (!heads.includes('glsp')) {
93
+ const named = specs.filter(spec => spec.diagram === true).map(spec => spec.name);
94
+ if (named.length > 0) {
95
+ throw new Error(`--diagram was given for ${named.join(', ')} but the head set is '${heads.join(',')}'. ` +
96
+ "Add 'glsp' to --heads, since the emitted dependencies follow the head set.");
97
+ }
98
+ return marked;
99
+ }
100
+ if (marked.some(Boolean)) {
101
+ return marked;
102
+ }
103
+ if (specs.length === 1) {
104
+ return [true];
105
+ }
106
+ throw new Error(`--heads includes 'glsp' but no grammar carries --diagram. Mark the one the diagram edits: ` +
107
+ `${specs.map(spec => spec.name).join(', ')}.`);
108
+ }
109
+ /** Validate the head set: known names only, and `lsp` present. */
110
+ function resolveHeads(heads) {
111
+ const resolved = heads === undefined || heads.length === 0 ? DEFAULT_INIT_HEADS : heads;
112
+ const unknown = resolved.filter(head => !isInitHead(head));
113
+ if (unknown.length > 0) {
114
+ throw new Error(`Unknown head(s) '${unknown.join(', ')}': expected one of ${INIT_HEADS.join(', ')}.`);
115
+ }
116
+ if (!resolved.includes('lsp')) {
117
+ throw new Error("--heads must include 'lsp': it owns the workspace, the build pipeline and the shared service tier the other heads read through.");
118
+ }
119
+ // De-duplicated and put back in composition order, so the order the heads
120
+ // were named in does not change the emitted project.
121
+ return INIT_HEADS.filter(head => resolved.includes(head));
122
+ }
123
+ /**
124
+ * Reject the collisions that would otherwise surface as a confusing generator
125
+ * or runtime failure rather than as a bad invocation.
126
+ *
127
+ * The extension check is the one worth having: Langium routes documents to a
128
+ * language BY extension, so two grammars claiming `.foo` is not a name clash
129
+ * but a silent mis-route of every `.foo` file to whichever language registered
130
+ * first.
131
+ */
132
+ function assertNoCollisions(grammars) {
133
+ const byGrammarId = new Map();
134
+ const byLanguageId = new Map();
135
+ const byExtension = new Map();
136
+ for (const grammar of grammars) {
137
+ const clashingName = byGrammarId.get(grammar.grammarId);
138
+ if (clashingName !== undefined) {
139
+ throw new Error(`Duplicate grammar '${grammar.grammar}': it resolves to the same file as '${clashingName}'.`);
140
+ }
141
+ byGrammarId.set(grammar.grammarId, grammar.grammar);
142
+ const clashingLanguage = byLanguageId.get(grammar.languageId);
143
+ if (clashingLanguage !== undefined) {
144
+ throw new Error(`Duplicate language id '${grammar.languageId}': claimed by both '${clashingLanguage}' and '${grammar.grammar}'.`);
145
+ }
146
+ byLanguageId.set(grammar.languageId, grammar.grammar);
147
+ for (const extension of grammar.extensions) {
148
+ const clashingExtension = byExtension.get(extension);
149
+ if (clashingExtension !== undefined) {
150
+ throw new Error(`File extension '.${extension}' is claimed by both '${clashingExtension}' and '${grammar.grammar}'. ` +
151
+ 'Langium routes documents by extension, so each grammar needs its own.');
152
+ }
153
+ byExtension.set(extension, grammar.grammar);
154
+ }
155
+ }
156
+ }
157
+ /**
158
+ * Derive the whole scaffold description from `--name` plus the collected
159
+ * grammars. Throws on a name that is not a valid PascalCase identifier — both
160
+ * project and grammar names become prefixes of generated TypeScript symbols.
161
+ *
162
+ * With no grammars given, one is synthesised from the project name, which is
163
+ * the single-language starter shape.
164
+ */
165
+ export function resolveInitComposition(name, grammars = [], heads, packaging = STANDALONE_PACKAGING) {
166
+ if (!isPascalIdentifier(name)) {
167
+ throw new Error(`Invalid --name '${name}': must be a PascalCase identifier (letters and digits, starting with a letter), e.g. 'Bookstore'.`);
168
+ }
169
+ const projectId = kebab(name);
170
+ if (packaging.scope !== undefined && !/^@[a-z0-9][a-z0-9._-]*$/.test(packaging.scope)) {
171
+ throw new Error(`Invalid --scope '${packaging.scope}': an npm scope starts with '@', e.g. '@acme'.`);
172
+ }
173
+ const resolvedHeads = resolveHeads(heads);
174
+ const specs = grammars.length > 0 ? grammars : [{ name }];
175
+ const diagrams = resolveDiagrams(specs, resolvedHeads);
176
+ const resolved = specs.map((spec, index) => resolveGrammar(spec, projectId, specs.length > 1, diagrams[index]));
177
+ assertNoCollisions(resolved);
178
+ return { name, projectId, heads: resolvedHeads, grammars: resolved, packaging, frameworkVersion: readFrameworkVersion() };
179
+ }
180
+ /**
181
+ * Plan the files a scaffold emits — every template rendered for this
182
+ * composition. Pure over its input → unit-testable without touching disk;
183
+ * {@link runInit} is the thin IO wrapper.
184
+ */
185
+ export function planInitFiles(composition) {
186
+ return buildInitTemplates(composition);
187
+ }
188
+ /** True when `dir` exists and contains at least one entry. */
189
+ export function isNonEmptyDir(dir) {
190
+ return fs.existsSync(dir) && fs.statSync(dir).isDirectory() && fs.readdirSync(dir).length > 0;
191
+ }
192
+ /**
193
+ * Resolve the packaging tier for a target directory, running workspace
194
+ * detection when `--monorepo` asked for it.
195
+ *
196
+ * Exported because the `init`-provenance gate re-runs the reference example's
197
+ * recorded invocation and must reach the same composition `runInit` would: a
198
+ * second copy of these rules there would drift from these, and the gate exists
199
+ * precisely to catch drift.
200
+ */
201
+ export function resolveInitPackaging(targetDir, options) {
202
+ if (options.monorepo !== true) {
203
+ return { scope: options.scope, private: options.public !== true };
204
+ }
205
+ const detection = detectWorkspace(targetDir, options.probe ?? createNodeWorkspaceProbe());
206
+ if (detection === undefined) {
207
+ throw new Error(`--monorepo was given but no ancestor of '${path.resolve(targetDir)}' has a package.json declaring 'workspaces'. ` +
208
+ 'Scaffold without it for a standalone project.');
209
+ }
210
+ return {
211
+ scope: options.scope,
212
+ private: options.public !== true,
213
+ // The scope and the publishability deliberately do NOT fall back to what
214
+ // detection found: the emitted package name stays a function of the argv
215
+ // alone, which is what lets the wizard's echoed command reproduce the
216
+ // scaffold anywhere. Detection only supplies the wizard's DEFAULT answer.
217
+ workspace: {
218
+ targetPath: detection.targetPath,
219
+ baseTsconfig: detection.baseTsconfig,
220
+ baseCompilerOptions: detection.baseCompilerOptions,
221
+ printWidth: detection.printWidth,
222
+ eslintConfig: detection.eslintConfig
223
+ }
224
+ };
225
+ }
226
+ /**
227
+ * Scaffold a new Hydranium language project end-to-end: one starter grammar per
228
+ * `--grammar`, `create<Name>Services` DI wiring, a launcher for each head in
229
+ * `--heads`, `langium-config.json`, `package.json`, and scripts. Does NOT run `npm install`
230
+ * or `langium generate` — those are printed as next steps, so the command stays
231
+ * offline and side-effect-free beyond the files it writes. Refuses a non-empty
232
+ * target directory unless `force`.
233
+ */
234
+ export function runInit(options) {
235
+ const write = options.write ?? ((line) => process.stdout.write(line));
236
+ const targetDir = path.resolve(options.targetDir);
237
+ const detection = options.monorepo ? detectWorkspace(targetDir, options.probe ?? createNodeWorkspaceProbe()) : undefined;
238
+ const composition = resolveInitComposition(options.name, options.grammars, options.heads, resolveInitPackaging(targetDir, options));
239
+ if (!options.force && isNonEmptyDir(targetDir)) {
240
+ throw new Error(`Target directory '${targetDir}' is not empty. Pass --force to scaffold into it anyway.`);
241
+ }
242
+ const files = planInitFiles(composition);
243
+ if (options.__writeFilesForTest) {
244
+ options.__writeFilesForTest(targetDir, files);
245
+ }
246
+ else {
247
+ for (const file of files) {
248
+ const absolute = path.join(targetDir, file.path);
249
+ fs.mkdirSync(path.dirname(absolute), { recursive: true });
250
+ fs.writeFileSync(absolute, file.content, 'utf-8');
251
+ }
252
+ }
253
+ const grammarList = composition.grammars.map(grammar => (grammar.diagram ? `${grammar.grammar} (diagram)` : grammar.grammar)).join(', ');
254
+ write(`Scaffolded ${composition.name} (${files.length} files, heads: ${composition.heads.join(',')}, ` +
255
+ `${composition.grammars.length} grammar(s): ${grammarList}) into ${targetDir}\n`);
256
+ if (detection !== undefined) {
257
+ write('\n');
258
+ write(`Workspace root: ${detection.rootDir}\n`);
259
+ if (detection.baseTsconfig !== undefined) {
260
+ write(` tsconfig.json extends ${detection.baseTsconfig}, minus the options it inherits unchanged.\n`);
261
+ }
262
+ else {
263
+ write(' No root tsconfig carries compilerOptions, so the emitted one stands alone.\n');
264
+ }
265
+ write(" .gitignore holds `syntaxes/` only — the workspace root's covers the rest.\n");
266
+ if (detection.printWidth !== undefined) {
267
+ write(` Sources wrapped at ${detection.printWidth} columns, from ${detection.rootDir}'s prettier config.\n`);
268
+ }
269
+ if (detection.eslintConfig !== undefined) {
270
+ write(` A lint script was added — ${detection.eslintConfig} says this repo lints. Adjust it if your invocation differs.\n`);
271
+ }
272
+ // Printed rather than applied: `init` writes inside the target directory
273
+ // and nowhere else, so a scaffold can never surprise-edit a manifest that
274
+ // is under review, mid-rebase, or simply not the caller's to change.
275
+ if (detection.coveredBy === undefined) {
276
+ write(` Add this to "workspaces" in ${path.join(detection.rootDir, 'package.json')}:\n`);
277
+ write(` "${detection.targetPath}"\n`);
278
+ }
279
+ else {
280
+ write(` Already covered by the "${detection.coveredBy}" workspaces entry — no root manifest change needed.\n`);
281
+ }
282
+ if (composition.packaging.scope === undefined && detection.scope !== undefined) {
283
+ write(` Sibling packages all use the "${detection.scope}" scope; pass --scope ${detection.scope} to match them.\n`);
284
+ }
285
+ }
286
+ write('\n');
287
+ write('Next steps:\n');
288
+ write(` cd ${options.targetDir}\n`);
289
+ // The warning is conditional on the pins this scaffold actually carries — see
290
+ // `UNPUBLISHED_FRAMEWORK_VERSION`.
291
+ write(composition.frameworkVersion === UNPUBLISHED_FRAMEWORK_VERSION
292
+ ? ' npm install # 404s until @hydranium/* is published — see README\n'
293
+ : ' npm install\n');
294
+ write(' npm run build # langium generate + tsc\n');
295
+ write(' npm test # the scaffolded DI-composition test\n');
296
+ // `npx`, not a bare invocation: `@hydranium/cli` is a devDependency of the
297
+ // scaffold, so the binary is on PATH inside an npm script and nowhere else.
298
+ write(' npx hydranium-cli reflect --services ./lib/services.js\n');
299
+ write('\n');
300
+ write('The emitted sources carry no license header — run your own header tool if\n');
301
+ write('your repo gates them. See the README section on that.\n');
302
+ }
303
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
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
+ import { type UsageError } from './harness-args.js';
10
+ import { type LintGrammarCommandOptions } from './lint-grammar.js';
11
+ /**
12
+ * Every flag `lint-grammar` accepts, derived from the sets the parser is handed
13
+ * so the list cannot claim a flag the parser would reject. `--services` is
14
+ * consumed by the shared harness parser itself, so it is in neither set.
15
+ */
16
+ export declare const LINT_GRAMMAR_FLAGS: readonly string[];
17
+ /** The subset that takes a value, so `--help` in a value position reads as data. */
18
+ export declare const LINT_GRAMMAR_VALUE_FLAGS: readonly string[];
19
+ /** The `--help` text, as data, held to {@link LINT_GRAMMAR_FLAGS} by a test. */
20
+ export declare const LINT_GRAMMAR_HELP: readonly string[];
21
+ export declare function parseLintGrammarArgs(args: string[], onError?: UsageError): LintGrammarCommandOptions;
22
+ export declare function runLintGrammarCommand(args: string[]): Promise<void>;
23
+ //# sourceMappingURL=lint-grammar-args.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-grammar-args.d.ts","sourceRoot":"","sources":["../../src/commands/lint-grammar-args.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EASJ,KAAK,UAAU,EACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAkB,KAAK,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAMnF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAA8E,CAAC;AAE/H,oFAAoF;AACpF,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAA+D,CAAC;AAEtH,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAkB9C,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,UAA0B,GAAG,yBAAyB,CAanH;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMnE"}
@@ -0,0 +1,63 @@
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
+ import { exitWithUsage, helpRequested, LOG_LEVEL_FLAG, logLevelHelpLine, logLevelOption, parseHarnessArgs, printHelp, SERVICES_FLAG } from './harness-args.js';
10
+ import { runLintGrammar } from './lint-grammar.js';
11
+ const VALUE_FLAGS = [LOG_LEVEL_FLAG];
12
+ const BOOL_FLAGS = ['--strict', '--json'];
13
+ const REPEATABLE_VALUE_FLAGS = ['--name-property'];
14
+ /**
15
+ * Every flag `lint-grammar` accepts, derived from the sets the parser is handed
16
+ * so the list cannot claim a flag the parser would reject. `--services` is
17
+ * consumed by the shared harness parser itself, so it is in neither set.
18
+ */
19
+ export const LINT_GRAMMAR_FLAGS = [SERVICES_FLAG, ...REPEATABLE_VALUE_FLAGS, ...VALUE_FLAGS, ...BOOL_FLAGS];
20
+ /** The subset that takes a value, so `--help` in a value position reads as data. */
21
+ export const LINT_GRAMMAR_VALUE_FLAGS = [SERVICES_FLAG, ...REPEATABLE_VALUE_FLAGS, ...VALUE_FLAGS];
22
+ /** The `--help` text, as data, held to {@link LINT_GRAMMAR_FLAGS} by a test. */
23
+ export const LINT_GRAMMAR_HELP = [
24
+ 'Usage: hydranium-cli lint-grammar --services <module> [--name-property <p>]... [--strict] [--json] [--log-level <lvl>]',
25
+ '',
26
+ "Check a head's grammar against the framework's conventions — a CI gate: the",
27
+ 'process exits non-zero when a violation is found. Read-only: no workspace is',
28
+ 'built (the grammar is static once the head registers its language), so',
29
+ '`lint-grammar` takes no `<workspace>`. Checks that every concrete cross-reference',
30
+ 'target carries a name property (else references cannot resolve) and that each',
31
+ 'language declares an entry rule. `<module>` is an ESM module exporting a',
32
+ 'zero-arg `createServices(): { shared }` thunk. Needs @hydranium/core.',
33
+ '',
34
+ 'Options:',
35
+ ' --services <module> ESM module exporting `createServices(): { shared }` (required).',
36
+ ' --name-property <p> Property that satisfies the nameability convention',
37
+ ' (repeatable). Default: name.',
38
+ ' --strict Also fail (non-zero exit) on warnings, not only errors.',
39
+ ' --json Emit the raw JSON result instead of the human report.',
40
+ logLevelHelpLine(23)
41
+ ];
42
+ export function parseLintGrammarArgs(args, onError = exitWithUsage) {
43
+ const { servicesModule, options, values } = parseHarnessArgs(args, 'lint-grammar', VALUE_FLAGS, BOOL_FLAGS, {
44
+ requireWorkspace: false,
45
+ repeatableValueFlags: REPEATABLE_VALUE_FLAGS,
46
+ onError
47
+ });
48
+ return {
49
+ servicesModule,
50
+ nameProperties: values['--name-property'],
51
+ strict: options['--strict'] === 'true',
52
+ json: options['--json'] === 'true',
53
+ logLevel: logLevelOption(options[LOG_LEVEL_FLAG])
54
+ };
55
+ }
56
+ export function runLintGrammarCommand(args) {
57
+ if (helpRequested(args, LINT_GRAMMAR_VALUE_FLAGS)) {
58
+ printHelp(LINT_GRAMMAR_HELP);
59
+ return Promise.resolve();
60
+ }
61
+ return runLintGrammar(parseLintGrammarArgs(args));
62
+ }
63
+ //# sourceMappingURL=lint-grammar-args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-grammar-args.js","sourceRoot":"","sources":["../../src/commands/lint-grammar-args.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EACJ,aAAa,EACb,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,aAAa,EAEf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAkC,MAAM,mBAAmB,CAAC;AAEnF,MAAM,WAAW,GAAG,CAAC,cAAc,CAAU,CAAC;AAC9C,MAAM,UAAU,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAU,CAAC;AACnD,MAAM,sBAAsB,GAAG,CAAC,iBAAiB,CAAU,CAAC;AAE5D;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAsB,CAAC,aAAa,EAAE,GAAG,sBAAsB,EAAE,GAAG,WAAW,EAAE,GAAG,UAAU,CAAC,CAAC;AAE/H,oFAAoF;AACpF,MAAM,CAAC,MAAM,wBAAwB,GAAsB,CAAC,aAAa,EAAE,GAAG,sBAAsB,EAAE,GAAG,WAAW,CAAC,CAAC;AAEtH,gFAAgF;AAChF,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IACjD,wHAAwH;IACxH,EAAE;IACF,6EAA6E;IAC7E,8EAA8E;IAC9E,wEAAwE;IACxE,mFAAmF;IACnF,+EAA+E;IAC/E,0EAA0E;IAC1E,uEAAuE;IACvE,EAAE;IACF,UAAU;IACV,0FAA0F;IAC1F,6EAA6E;IAC7E,uDAAuD;IACvD,kFAAkF;IAClF,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,UAAU,oBAAoB,CAAC,IAAc,EAAE,UAAsB,aAAa;IACrF,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC,IAAI,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE;QACzG,gBAAgB,EAAE,KAAK;QACvB,oBAAoB,EAAE,sBAAsB;QAC5C,OAAO;KACT,CAAC,CAAC;IACH,OAAO;QACJ,cAAc;QACd,cAAc,EAAE,MAAM,CAAC,iBAAiB,CAAC;QACzC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,KAAK,MAAM;QACtC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,MAAM;QAClC,QAAQ,EAAE,cAAc,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;KACnD,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAc;IACjD,IAAI,aAAa,CAAC,IAAI,EAAE,wBAAwB,CAAC,EAAE,CAAC;QACjD,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAC7B,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5B,CAAC;IACD,OAAO,cAAc,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,10 @@
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
+ export {};
10
+ //# sourceMappingURL=lint-grammar-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-grammar-driver.d.ts","sourceRoot":"","sources":["../../src/commands/lint-grammar-driver.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF"}
@@ -0,0 +1,72 @@
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
+ * Spawned child of the `lint-grammar` subcommand. Launched by the parent with
11
+ * `node <this> --services <module> [--name-property <p>]... [--json] [--strict]`.
12
+ * It dynamic-imports the head's services module, runs the framework's
13
+ * `lintGrammar`, prints the report (human or `--json`) and exits with the gate
14
+ * code (non-zero on errors; `--strict` also fails on warnings). Never imported —
15
+ * only spawned.
16
+ */
17
+ import { loadHeadlessContext } from './headless-harness.js';
18
+ import { formatLintReport, lintExitCode } from './lint-grammar-report.js';
19
+ function parseArgs(argv) {
20
+ const parsed = { nameProperties: [], json: false, strict: false };
21
+ for (let index = 0; index < argv.length; index += 1) {
22
+ const flag = argv[index];
23
+ const next = () => {
24
+ const value = argv[index + 1];
25
+ if (value === undefined) {
26
+ console.error(`Missing value for ${flag}`);
27
+ process.exit(1);
28
+ }
29
+ index += 1;
30
+ return value;
31
+ };
32
+ switch (flag) {
33
+ case '--services':
34
+ parsed.servicesModule = next();
35
+ break;
36
+ case '--name-property':
37
+ parsed.nameProperties.push(next());
38
+ break;
39
+ case '--json':
40
+ parsed.json = true;
41
+ break;
42
+ case '--strict':
43
+ parsed.strict = true;
44
+ break;
45
+ default:
46
+ console.error(`Unknown option: ${flag}`);
47
+ process.exit(1);
48
+ }
49
+ }
50
+ return parsed;
51
+ }
52
+ async function main(argv) {
53
+ const args = parseArgs(argv);
54
+ if (!args.servicesModule) {
55
+ console.error('lint-grammar-driver: --services <module> is required.');
56
+ process.exit(1);
57
+ }
58
+ const { createServices, coreNode } = await loadHeadlessContext(args.servicesModule);
59
+ const result = coreNode.lintGrammar({
60
+ createServices,
61
+ nameProperties: args.nameProperties.length ? args.nameProperties : undefined
62
+ });
63
+ console.log(formatLintReport(result, { json: args.json }));
64
+ return lintExitCode(result, args.strict);
65
+ }
66
+ main(process.argv.slice(2))
67
+ .then(code => process.exit(code))
68
+ .catch((error) => {
69
+ console.error(error instanceof Error ? error.message : String(error));
70
+ process.exit(1);
71
+ });
72
+ //# sourceMappingURL=lint-grammar-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-grammar-driver.js","sourceRoot":"","sources":["../../src/commands/lint-grammar-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
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
+ import type { GrammarLintResult } from '@hydranium/core/node';
10
+ /**
11
+ * The exit code for a lint run: non-zero blocks the CI gate. Errors always fail;
12
+ * `strict` additionally fails on warnings.
13
+ */
14
+ export declare function lintExitCode(result: GrammarLintResult, strict?: boolean): number;
15
+ /**
16
+ * Render a grammar-convention lint result for the terminal. `json` emits the raw
17
+ * {@link GrammarLintResult} (the machine-readable CI contract); the default is a
18
+ * human report — one `severity [rule] message` line per finding — closing with
19
+ * the {@link summaryLine} tally.
20
+ */
21
+ export declare function formatLintReport(result: GrammarLintResult, options?: {
22
+ json?: boolean;
23
+ }): string;
24
+ //# sourceMappingURL=lint-grammar-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-grammar-report.d.ts","sourceRoot":"","sources":["../../src/commands/lint-grammar-report.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAO9D;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,EAAE,MAAM,UAAQ,GAAG,MAAM,CAQ9E;AAwBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAapG"}
@@ -0,0 +1,65 @@
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
+ /** `s` when `count !== 1`, else empty. */
10
+ function plural(count) {
11
+ return count === 1 ? '' : 's';
12
+ }
13
+ /**
14
+ * The exit code for a lint run: non-zero blocks the CI gate. Errors always fail;
15
+ * `strict` additionally fails on warnings.
16
+ */
17
+ export function lintExitCode(result, strict = false) {
18
+ if (result.counts.error > 0) {
19
+ return 1;
20
+ }
21
+ if (strict && result.counts.warning > 0) {
22
+ return 1;
23
+ }
24
+ return 0;
25
+ }
26
+ /** One-line severity tally, or the clean-grammar message. */
27
+ function summaryLine(result) {
28
+ const { error, warning } = result.counts;
29
+ if (error + warning === 0) {
30
+ // "target type", not "target": the tally counts distinct TYPES reachable
31
+ // as a cross-reference target, not cross-reference properties. Several
32
+ // references can share one target type, so the bare word reads as though
33
+ // the lint had missed the rest.
34
+ return `No grammar-convention problems found (${result.checkedReferenceTargets} reference target type${plural(result.checkedReferenceTargets)} checked).`;
35
+ }
36
+ const parts = [];
37
+ if (error) {
38
+ parts.push(`${error} error${plural(error)}`);
39
+ }
40
+ if (warning) {
41
+ parts.push(`${warning} warning${plural(warning)}`);
42
+ }
43
+ return `${parts.join(', ')}.`;
44
+ }
45
+ /**
46
+ * Render a grammar-convention lint result for the terminal. `json` emits the raw
47
+ * {@link GrammarLintResult} (the machine-readable CI contract); the default is a
48
+ * human report — one `severity [rule] message` line per finding — closing with
49
+ * the {@link summaryLine} tally.
50
+ */
51
+ export function formatLintReport(result, options = {}) {
52
+ if (options.json) {
53
+ return JSON.stringify(result, undefined, 2);
54
+ }
55
+ const lines = [];
56
+ for (const finding of result.findings) {
57
+ lines.push(` ${finding.severity.padEnd(7)} [${finding.rule}] ${finding.message}`);
58
+ }
59
+ if (result.findings.length > 0) {
60
+ lines.push('');
61
+ }
62
+ lines.push(summaryLine(result));
63
+ return lines.join('\n');
64
+ }
65
+ //# sourceMappingURL=lint-grammar-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lint-grammar-report.js","sourceRoot":"","sources":["../../src/commands/lint-grammar-report.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAMlF,0CAA0C;AAC1C,SAAS,MAAM,CAAC,KAAa;IAC1B,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAyB,EAAE,MAAM,GAAG,KAAK;IACnE,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,CAAC;IACZ,CAAC;IACD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,CAAC;IACZ,CAAC;IACD,OAAO,CAAC,CAAC;AACZ,CAAC;AAED,6DAA6D;AAC7D,SAAS,WAAW,CAAC,MAAyB;IAC3C,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,IAAI,KAAK,GAAG,OAAO,KAAK,CAAC,EAAE,CAAC;QACzB,yEAAyE;QACzE,uEAAuE;QACvE,yEAAyE;QACzE,gCAAgC;QAChC,OAAO,yCAAyC,MAAM,CAAC,uBAAuB,yBAAyB,MAAM,CAC1G,MAAM,CAAC,uBAAuB,CAChC,YAAY,CAAC;IACjB,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,EAAE,CAAC;QACT,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,WAAW,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AACjC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAyB,EAAE,UAA8B,EAAE;IACzF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAC/C,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAChC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,33 @@
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
+ import { type DriverSpawnOptions } from './headless-harness.js';
10
+ /** Options for the {@link runLintGrammar} subcommand. */
11
+ export interface LintGrammarCommandOptions extends DriverSpawnOptions {
12
+ /** ESM module exporting a zero-arg `createServices(): { shared }` thunk. */
13
+ readonly servicesModule: string;
14
+ /** Property names that satisfy the nameability convention. Empty → the framework default `name`. */
15
+ readonly nameProperties?: readonly string[];
16
+ /** Emit the raw JSON result instead of the human report. */
17
+ readonly json?: boolean;
18
+ /** Also fail (non-zero exit) on warnings, not only errors. */
19
+ readonly strict?: boolean;
20
+ }
21
+ /** Build the argv the driver child parses. Pure → unit-testable. */
22
+ export declare function buildLintGrammarDriverArgs(options: LintGrammarCommandOptions): string[];
23
+ /**
24
+ * Headless grammar-convention lint — a CI gate that checks a head's grammar against
25
+ * the framework's expectations (nameable cross-reference targets, an entry rule) and
26
+ * exits non-zero when a violation is found (`--strict` also fails on warnings).
27
+ * Read-only: no workspace is built (the reflection is static once the head registers
28
+ * its language), so this subcommand takes only `--services` and the name-property
29
+ * overrides. The work runs in a spawned child that dynamic-imports the head's
30
+ * `createServices` module, keeping the binary language-agnostic.
31
+ */
32
+ export declare function runLintGrammar(options: LintGrammarCommandOptions): Promise<void>;
33
+ //# sourceMappingURL=lint-grammar.d.ts.map