@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,112 @@
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 { logLevelEnv } from '../log-level.js';
10
+ import { spawnDataServer } from '../spawn-data-server.js';
11
+ /**
12
+ * Wait for the handle's premature-death rejection, and swallow it once the watch
13
+ * is being torn down.
14
+ *
15
+ * `watch` ends on SIGINT, which a shell delivers to the whole process group, so
16
+ * the child dies of the same keystroke. Its `unwatchModelDocument` round trip can
17
+ * then never be answered, leaving the loop pending and the child's exit the only
18
+ * settled outcome — so unfiltered, every clean Ctrl-C is reported as
19
+ * `exited before the request completed (… signal=SIGINT)`. Resolving instead
20
+ * also settles the race the loop can no longer settle.
21
+ *
22
+ * The check waits a turn of the event loop rather than reading `aborted` in the
23
+ * rejection's own turn: the child's death and this process's own SIGINT are
24
+ * delivered together and their order is the kernel's to choose. A genuine
25
+ * mid-watch crash pays that one turn before it is reported.
26
+ */
27
+ async function resolveOnceShuttingDown(whenTerminated, signal) {
28
+ if (!whenTerminated) {
29
+ return new Promise(() => undefined);
30
+ }
31
+ try {
32
+ await whenTerminated;
33
+ }
34
+ catch (err) {
35
+ await new Promise(resolve => setTimeout(resolve, 0));
36
+ if (signal?.aborted) {
37
+ return;
38
+ }
39
+ throw err;
40
+ }
41
+ }
42
+ /**
43
+ * Wire SIGINT to abort the given controller. Returns a function that
44
+ * un-wires the listener — call it once the subcommand exits so future
45
+ * SIGINTs don't trigger an already-aborted controller.
46
+ */
47
+ export function wireSigintAbort(controller) {
48
+ const handler = () => controller.abort();
49
+ process.once('SIGINT', handler);
50
+ return () => process.removeListener('SIGINT', handler);
51
+ }
52
+ export async function runWatch(options) {
53
+ const write = options.write ?? ((line) => process.stdout.write(line));
54
+ const clientId = options.clientId ?? 'hydranium-cli';
55
+ // Local client: filters by URI (so multiple watchers on the same wire
56
+ // don't cross-pollinate) and writes each event as one JSON line.
57
+ // `onProjectsChanged` and `onDocumentSaved` are no-ops here — `watch`
58
+ // streams build-phase update events. Project lifecycle and persistence
59
+ // events are out of band for the CLI's per-URI update view.
60
+ const localClient = {
61
+ onDocumentUpdated(event) {
62
+ if (event.document.uri !== options.uri) {
63
+ return;
64
+ }
65
+ write(`${JSON.stringify(event)}\n`);
66
+ },
67
+ onDocumentSaved() {
68
+ // Persistence is out of band for the per-URI update view.
69
+ },
70
+ onProjectsChanged() {
71
+ // Project lifecycle is out of band for the per-URI update view.
72
+ }
73
+ };
74
+ // One body for both paths: a test handle that returned before the race would
75
+ // leave the premature-death branch it stands in for uncoverable.
76
+ const handle = options.__handleForTest ??
77
+ spawnDataServer({
78
+ command: options.serverCommand,
79
+ args: options.serverArgs,
80
+ cwd: options.cwd,
81
+ env: options.logLevel ? logLevelEnv(options.logLevel) : undefined
82
+ }, localClient);
83
+ options.__handleForTest?.bindClient(localClient);
84
+ try {
85
+ // Race the subscription loop against the child's premature death so a mid-watch
86
+ // server crash exits with a clear message instead of hanging until Ctrl-C. Guard
87
+ // the loop's late rejection (an unwatch write to a dead stream) so it does not
88
+ // surface as an unhandled rejection when the death wins the race.
89
+ const loop = runWatchOnce(handle.server, options.uri, clientId, options.signal);
90
+ void loop.catch(() => undefined);
91
+ await Promise.race([loop, resolveOnceShuttingDown(handle.whenTerminated, options.signal)]);
92
+ }
93
+ finally {
94
+ await handle.shutdown();
95
+ }
96
+ }
97
+ async function runWatchOnce(server, uri, clientId, signal) {
98
+ await server.watchModelDocument({ uri, clientId });
99
+ try {
100
+ await new Promise(resolve => {
101
+ if (signal?.aborted) {
102
+ resolve();
103
+ return;
104
+ }
105
+ signal?.addEventListener('abort', () => resolve(), { once: true });
106
+ });
107
+ }
108
+ finally {
109
+ await server.unwatchModelDocument({ uri, clientId });
110
+ }
111
+ }
112
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AA6D1D;;;;;;;;;;;;;;;GAeG;AACH,KAAK,UAAU,uBAAuB,CAAC,cAA0C,EAAE,MAA+B;IAC/G,IAAI,CAAC,cAAc,EAAE,CAAC;QACnB,OAAO,IAAI,OAAO,CAAO,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IACD,IAAI,CAAC;QACF,MAAM,cAAc,CAAC;IACxB,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACrB,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QAC3D,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACnB,OAAO;QACV,CAAC;QACD,MAAM,GAAG,CAAC;IACb,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,UAA2B;IACxD,MAAM,OAAO,GAAG,GAAS,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAA4B;IACxD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9E,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,eAAe,CAAC;IAErD,sEAAsE;IACtE,iEAAiE;IACjE,sEAAsE;IACtE,uEAAuE;IACvE,4DAA4D;IAC5D,MAAM,WAAW,GAAwC;QACtD,iBAAiB,CAAC,KAAoD;YACnE,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,KAAK,OAAO,CAAC,GAAG,EAAE,CAAC;gBACtC,OAAO;YACV,CAAC;YACD,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,CAAC;QACD,eAAe;YACZ,0DAA0D;QAC7D,CAAC;QACD,iBAAiB;YACd,gEAAgE;QACnE,CAAC;KACH,CAAC;IAEF,6EAA6E;IAC7E,iEAAiE;IACjE,MAAM,MAAM,GACT,OAAO,CAAC,eAAe;QACvB,eAAe,CACZ;YACG,OAAO,EAAE,OAAO,CAAC,aAAa;YAC9B,IAAI,EAAE,OAAO,CAAC,UAAU;YACxB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS;SACnE,EACD,WAAW,CACb,CAAC;IACL,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,CAAC;QACF,gFAAgF;QAChF,iFAAiF;QACjF,+EAA+E;QAC/E,kEAAkE;QAClE,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAChF,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACjC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,uBAAuB,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC9F,CAAC;YAAS,CAAC;QACR,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,YAAY,CACxB,MAAgG,EAChG,GAAW,EACX,QAAgB,EAChB,MAA+B;IAE/B,MAAM,MAAM,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC;QACF,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;YAC/B,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACnB,OAAO,EAAE,CAAC;gBACV,OAAO;YACV,CAAC;YACD,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACN,CAAC;YAAS,CAAC;QACR,MAAM,MAAM,CAAC,oBAAoB,CAAC,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;IACxD,CAAC;AACJ,CAAC"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,16 @@
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 * from './commands/generate-transfer-model.js';
10
+ export * from './commands/projects.js';
11
+ export * from './commands/query.js';
12
+ export * from './commands/save.js';
13
+ export * from './commands/watch.js';
14
+ export * from './package-name.js';
15
+ export * from './spawn-data-server.js';
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,cAAc,uCAAuC,CAAC;AACtD,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC"}
package/lib/index.js ADDED
@@ -0,0 +1,16 @@
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 * from './commands/generate-transfer-model.js';
10
+ export * from './commands/projects.js';
11
+ export * from './commands/query.js';
12
+ export * from './commands/save.js';
13
+ export * from './commands/watch.js';
14
+ export * from './package-name.js';
15
+ export * from './spawn-data-server.js';
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,cAAc,uCAAuC,CAAC;AACtD,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,39 @@
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 LogThreshold } from '@hydranium/protocol';
10
+ /**
11
+ * Validate a raw `--log-level` argument into a {@link LogThreshold}. Throws on
12
+ * an unrecognised value so the CLI's top-level `catch` surfaces a clean error
13
+ * and exits non-zero (mirroring how the other option parsers fail fast). Use
14
+ * for the argv-supplied value; the resolved threshold is handed to
15
+ * {@link logLevelEnv} to target the spawned server.
16
+ */
17
+ export declare function parseLogLevelOption(raw: string): LogThreshold;
18
+ /**
19
+ * Build the environment override that targets *only the spawned server's* log
20
+ * threshold. Passed to `spawnDataServer` as `env`, it sets the same
21
+ * `HYDRANIUM_LOG_LEVEL` variable the server reads at startup — the CLI's own
22
+ * logging is unaffected, unlike an ambient `HYDRANIUM_LOG_LEVEL=…` that the
23
+ * child would inherit alongside the parent. The server owns *how* log level
24
+ * works; this only routes the CLI's request onto the channel it already reads.
25
+ *
26
+ * **The variable is read by `LspLogger`'s constructor**, which is bound on the
27
+ * `Logger` slot by `createLspServerSharedModule`. A server that overrides that
28
+ * slot with a logger of its own therefore decides for itself whether this flag
29
+ * means anything — which is the intended seam, not a gap. A server composing no
30
+ * head module at all binds `@hydranium/core`'s `NoopLogger` and stays silent
31
+ * regardless, so the flag is inert against it.
32
+ *
33
+ * Output lands on the spawned server's **stderr**, which
34
+ * `spawnDataServer` inherits to the user by default. It deliberately does
35
+ * not go to stdout: that is the JSON-RPC channel, so a log line there would
36
+ * corrupt the very request this flag was set to diagnose.
37
+ */
38
+ export declare function logLevelEnv(level: LogThreshold): Record<string, string>;
39
+ //# sourceMappingURL=log-level.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-level.d.ts","sourceRoot":"","sources":["../src/log-level.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAqD,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAE3G;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAM7D;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEvE"}
@@ -0,0 +1,47 @@
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 { DEFAULT_LOG_LEVEL_ENV, LEVEL_ORDER, parseLogLevel } from '@hydranium/protocol';
10
+ /**
11
+ * Validate a raw `--log-level` argument into a {@link LogThreshold}. Throws on
12
+ * an unrecognised value so the CLI's top-level `catch` surfaces a clean error
13
+ * and exits non-zero (mirroring how the other option parsers fail fast). Use
14
+ * for the argv-supplied value; the resolved threshold is handed to
15
+ * {@link logLevelEnv} to target the spawned server.
16
+ */
17
+ export function parseLogLevelOption(raw) {
18
+ const level = parseLogLevel(raw);
19
+ if (!level) {
20
+ throw new Error(`Invalid --log-level: ${raw} (expected one of: ${Object.keys(LEVEL_ORDER).join(', ')})`);
21
+ }
22
+ return level;
23
+ }
24
+ /**
25
+ * Build the environment override that targets *only the spawned server's* log
26
+ * threshold. Passed to `spawnDataServer` as `env`, it sets the same
27
+ * `HYDRANIUM_LOG_LEVEL` variable the server reads at startup — the CLI's own
28
+ * logging is unaffected, unlike an ambient `HYDRANIUM_LOG_LEVEL=…` that the
29
+ * child would inherit alongside the parent. The server owns *how* log level
30
+ * works; this only routes the CLI's request onto the channel it already reads.
31
+ *
32
+ * **The variable is read by `LspLogger`'s constructor**, which is bound on the
33
+ * `Logger` slot by `createLspServerSharedModule`. A server that overrides that
34
+ * slot with a logger of its own therefore decides for itself whether this flag
35
+ * means anything — which is the intended seam, not a gap. A server composing no
36
+ * head module at all binds `@hydranium/core`'s `NoopLogger` and stays silent
37
+ * regardless, so the flag is inert against it.
38
+ *
39
+ * Output lands on the spawned server's **stderr**, which
40
+ * `spawnDataServer` inherits to the user by default. It deliberately does
41
+ * not go to stdout: that is the JSON-RPC channel, so a log line there would
42
+ * corrupt the very request this flag was set to diagnose.
43
+ */
44
+ export function logLevelEnv(level) {
45
+ return { [DEFAULT_LOG_LEVEL_ENV]: level };
46
+ }
47
+ //# sourceMappingURL=log-level.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-level.js","sourceRoot":"","sources":["../src/log-level.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,aAAa,EAAqB,MAAM,qBAAqB,CAAC;AAE3G;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC5C,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,sBAAsB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5G,CAAC;IACD,OAAO,KAAK,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,WAAW,CAAC,KAAmB;IAC5C,OAAO,EAAE,CAAC,qBAAqB,CAAC,EAAE,KAAK,EAAE,CAAC;AAC7C,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
+ /**
10
+ * Validates against the npm package-name grammar (scoped or unscoped,
11
+ * lowercase, etc.).
12
+ *
13
+ * Published on this barrel with no caller inside the framework: it is
14
+ * scaffolding vocabulary for a generator that composes package names of its
15
+ * own, which is a job an adopter does in its own repository. It lives on the
16
+ * CLI rather than on the wire-contract package because a package name has no
17
+ * wire meaning and a client bundle should not carry the pattern.
18
+ */
19
+ export declare const NPM_PACKAGE_NAME_REGEX: RegExp;
20
+ /**
21
+ * Convert an npm package name to a Pascal-case identifier. The optional scope
22
+ * prefix is dropped; remaining segments separated by `-`, `.`, or `~` are
23
+ * Pascal-cased and concatenated.
24
+ *
25
+ * `'@my-org/foo-bar'` → `'FooBar'`
26
+ *
27
+ * The inverse direction of the `kebab` derivation the scaffolder itself runs:
28
+ * that one starts from a PascalCase project name and produces the package id,
29
+ * this one recovers an identifier from a package name that already exists.
30
+ * Same outside-reader constraint as {@link NPM_PACKAGE_NAME_REGEX}.
31
+ */
32
+ export declare function packageNameToId(input: string): string;
33
+ //# sourceMappingURL=package-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-name.d.ts","sourceRoot":"","sources":["../src/package-name.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,QAAoF,CAAC;AAExH;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGrD"}
@@ -0,0 +1,37 @@
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 { toPascal } from '@hydranium/protocol';
10
+ /**
11
+ * Validates against the npm package-name grammar (scoped or unscoped,
12
+ * lowercase, etc.).
13
+ *
14
+ * Published on this barrel with no caller inside the framework: it is
15
+ * scaffolding vocabulary for a generator that composes package names of its
16
+ * own, which is a job an adopter does in its own repository. It lives on the
17
+ * CLI rather than on the wire-contract package because a package name has no
18
+ * wire meaning and a client bundle should not carry the pattern.
19
+ */
20
+ export const NPM_PACKAGE_NAME_REGEX = /^(?:(?:@(?:[a-z0-9-*~][a-z0-9-*._~]*)?\/[a-z0-9-._~])|[a-z0-9-~])[a-z0-9-._~]*$/;
21
+ /**
22
+ * Convert an npm package name to a Pascal-case identifier. The optional scope
23
+ * prefix is dropped; remaining segments separated by `-`, `.`, or `~` are
24
+ * Pascal-cased and concatenated.
25
+ *
26
+ * `'@my-org/foo-bar'` → `'FooBar'`
27
+ *
28
+ * The inverse direction of the `kebab` derivation the scaffolder itself runs:
29
+ * that one starts from a PascalCase project name and produces the package id,
30
+ * this one recovers an identifier from a package name that already exists.
31
+ * Same outside-reader constraint as {@link NPM_PACKAGE_NAME_REGEX}.
32
+ */
33
+ export function packageNameToId(input) {
34
+ const unscoped = input.split('/').at(-1);
35
+ return unscoped.split(/[~.-]/).map(toPascal).join('');
36
+ }
37
+ //# sourceMappingURL=package-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-name.js","sourceRoot":"","sources":["../src/package-name.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,iFAAiF,CAAC;AAExH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC;IAC1C,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,102 @@
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 TransferDiagnostic, type TransferElement } from '@hydranium/protocol';
10
+ import { type DataClientProtocol, type DataServerProtocol } from '@hydranium/protocol/data';
11
+ import { type ChildProcess } from 'node:child_process';
12
+ import { type MessageConnection } from 'vscode-jsonrpc/node';
13
+ /**
14
+ * Options for {@link spawnDataServer}. `command` is the binary or script
15
+ * path; `args` are the command-line arguments passed to it. The adopter's
16
+ * server is expected to bootstrap a `DataServer` against the supplied
17
+ * MessageConnection and call `connection.listen()` so its stdin/stdout
18
+ * carry the JSON-RPC stream.
19
+ *
20
+ * `shutdown()` disposes the JSON-RPC connection and waits for the child
21
+ * to exit with a configurable timeout. Subcommands that take a SIGINT
22
+ * (e.g. `watch`) call shutdown on the cleanup path so the child doesn't
23
+ * stay orphaned.
24
+ */
25
+ export interface SpawnDataServerOptions {
26
+ readonly command: string;
27
+ readonly args?: readonly string[];
28
+ /**
29
+ * Working directory for the spawned child. Default: current cwd.
30
+ * Useful when the child resolves model files relative to a workspace
31
+ * root that differs from where the CLI was invoked.
32
+ */
33
+ readonly cwd?: string;
34
+ /**
35
+ * Additional environment variables for the child. Merged on top of
36
+ * `process.env`. Default: no overrides.
37
+ */
38
+ readonly env?: Readonly<Record<string, string | undefined>>;
39
+ /**
40
+ * Where to pipe the child's stderr. Default: inherited from the
41
+ * parent (visible to the user). Set to `'ignore'` for quiet
42
+ * scripted use; set to `'pipe'` to capture for assertion in tests.
43
+ */
44
+ readonly stderr?: 'inherit' | 'ignore' | 'pipe';
45
+ }
46
+ /**
47
+ * Lifecycle handle for a spawned data-server. Owns the child process,
48
+ * the JSON-RPC connection, and the typed protocol proxy. Always pair
49
+ * {@link spawnDataServer} with {@link DataServerHandle.shutdown} (in a
50
+ * `try`/`finally` or equivalent) so the child doesn't outlive the CLI
51
+ * invocation.
52
+ */
53
+ export interface DataServerHandle<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic> {
54
+ /** Typed server proxy — the consumer-facing surface for protocol calls. */
55
+ readonly server: DataServerProtocol<TTransfer, TDiagnostic>;
56
+ /** Raw child process — for stderr piping in tests; do not write to stdin/stdout directly. */
57
+ readonly child: ChildProcess;
58
+ /** vscode-jsonrpc connection — for callers wanting fine-grained lifecycle control. */
59
+ readonly connection: MessageConnection;
60
+ /**
61
+ * Rejects when the child fails to start (e.g. `ENOENT` for a missing
62
+ * command) or exits before {@link DataServerHandle.shutdown} is
63
+ * requested — i.e. a premature death that would otherwise leave an
64
+ * in-flight RPC hanging forever. Never resolves. Race a protocol call
65
+ * against it (see {@link withDataServer}) to fail fast with a clear
66
+ * message instead of hanging or crashing on an unhandled `'error'`
67
+ * event. Always internally handled, so ignoring it never triggers an
68
+ * unhandled-rejection crash.
69
+ */
70
+ readonly whenTerminated: Promise<never>;
71
+ /**
72
+ * Tear down the connection + wait for the child to exit. Resolves
73
+ * once the child has terminated (gracefully or via SIGTERM). Safe
74
+ * to call multiple times.
75
+ */
76
+ shutdown(timeoutMs?: number): Promise<void>;
77
+ }
78
+ /**
79
+ * Spawn a data-server subprocess and wire a typed proxy over its
80
+ * stdio JSON-RPC. The function returns once the connection is
81
+ * listening; protocol calls are queued behind the underlying
82
+ * MessageConnection's ordering guarantees.
83
+ *
84
+ * Supplying `localClient` registers its `DataClientProtocol` methods as
85
+ * inbound-notification handlers on the connection — the data-server's
86
+ * `data-server/onDocumentUpdated` notifications dispatch to
87
+ * `localClient.onDocumentUpdated`. Subcommands like `watch` use this to
88
+ * stream events; subcommands like `projects` / `query` / `save` pass
89
+ * no localClient.
90
+ */
91
+ export declare function spawnDataServer<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic>(options: SpawnDataServerOptions, localClient?: DataClientProtocol<TTransfer, TDiagnostic>): DataServerHandle<TTransfer, TDiagnostic>;
92
+ /**
93
+ * Spawn a data-server, run `use` against its typed proxy, and always shut the
94
+ * child down afterwards. The `use` call is raced against
95
+ * {@link DataServerHandle.whenTerminated}, so a spawn failure or a premature child
96
+ * exit rejects with a clear message instead of hanging on an RPC that can never be
97
+ * answered. This is the one-shot counterpart the `projects` / `query` / `save`
98
+ * subcommands compose; `watch` races its own long-running loop against
99
+ * `whenTerminated` directly.
100
+ */
101
+ export declare function withDataServer<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic, R>(options: SpawnDataServerOptions, use: (server: DataServerProtocol<TTransfer, TDiagnostic>, handle: DataServerHandle<TTransfer, TDiagnostic>) => Promise<R>, localClient?: DataClientProtocol<TTransfer, TDiagnostic>): Promise<R>;
102
+ //# sourceMappingURL=spawn-data-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-data-server.d.ts","sourceRoot":"","sources":["../src/spawn-data-server.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,EAAkB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACpG,OAAO,EAGJ,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACzB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAqE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAEhI;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,sBAAsB;IACpC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC5D;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;CAClD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,GAAG,kBAAkB;IAC7H,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAC5D,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,sFAAsF;IACtF,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC;IACvC;;;;;;;;;OASG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,EAC3H,OAAO,EAAE,sBAAsB,EAC/B,WAAW,CAAC,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,GACxD,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,CAqH1C;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,EAAE,CAAC,EAC9G,OAAO,EAAE,sBAAsB,EAC/B,GAAG,EAAE,CAAC,MAAM,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,gBAAgB,CAAC,SAAS,EAAE,WAAW,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,EACzH,WAAW,CAAC,EAAE,kBAAkB,CAAC,SAAS,EAAE,WAAW,CAAC,GACxD,OAAO,CAAC,CAAC,CAAC,CAYZ"}
@@ -0,0 +1,154 @@
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 { createRpcProxy } from '@hydranium/protocol';
10
+ import { DATA_CLIENT_PROTOCOL_METHODS, DATA_SERVER_WIRE_PREFIX } from '@hydranium/protocol/data';
11
+ import { spawn } from 'node:child_process';
12
+ import { StreamMessageReader, StreamMessageWriter, createMessageConnection } from 'vscode-jsonrpc/node';
13
+ /**
14
+ * Spawn a data-server subprocess and wire a typed proxy over its
15
+ * stdio JSON-RPC. The function returns once the connection is
16
+ * listening; protocol calls are queued behind the underlying
17
+ * MessageConnection's ordering guarantees.
18
+ *
19
+ * Supplying `localClient` registers its `DataClientProtocol` methods as
20
+ * inbound-notification handlers on the connection — the data-server's
21
+ * `data-server/onDocumentUpdated` notifications dispatch to
22
+ * `localClient.onDocumentUpdated`. Subcommands like `watch` use this to
23
+ * stream events; subcommands like `projects` / `query` / `save` pass
24
+ * no localClient.
25
+ */
26
+ export function spawnDataServer(options, localClient) {
27
+ const child = spawn(options.command, [...(options.args ?? [])], {
28
+ cwd: options.cwd,
29
+ env: options.env ? { ...process.env, ...options.env } : process.env,
30
+ stdio: ['pipe', 'pipe', options.stderr ?? 'inherit']
31
+ });
32
+ if (!child.stdin || !child.stdout) {
33
+ // Mirrors the synchronous failure-to-create-pipes case Node surfaces
34
+ // when stdio isn't 'pipe' on either end. We always request 'pipe'
35
+ // for stdin/stdout, so this is defensive only.
36
+ //
37
+ // Worded for whoever passed the command, not for whoever wrote this
38
+ // function: the reachable way to arrive here is a `--server` value that
39
+ // does not start, and naming the internal spawner told that reader
40
+ // nothing they could act on.
41
+ child.kill();
42
+ throw new Error(`Could not start the data server: the command '${options.command}' provided no stdin/stdout pipe. ` +
43
+ 'Check that --server names a runnable command, and that its own entry path resolves from --cwd.');
44
+ }
45
+ // Guard stdin against writes that flush after the child has died (spawn failure
46
+ // or a premature exit). vscode-jsonrpc queues a message write on `setImmediate`;
47
+ // if the child's stdin is destroyed by the time it flushes, Node's `write` errors
48
+ // and vscode-jsonrpc orphans that write-queue rejection (it surfaces transport
49
+ // errors only via `onError`, which we consume separately) — an unhandled
50
+ // rejection. Reporting the destroyed write as a silent success drops the doomed
51
+ // message; the child's death is already reported cleanly via `whenTerminated`.
52
+ const stdin = child.stdin;
53
+ const originalWrite = stdin.write.bind(stdin);
54
+ stdin.write = ((...writeArgs) => {
55
+ if (!stdin.destroyed) {
56
+ return originalWrite(...writeArgs);
57
+ }
58
+ const callback = writeArgs.find((arg) => typeof arg === 'function');
59
+ callback?.(null);
60
+ return true;
61
+ });
62
+ const reader = new StreamMessageReader(child.stdout);
63
+ const writer = new StreamMessageWriter(child.stdin);
64
+ const connection = createMessageConnection(reader, writer);
65
+ // Consume transport error / close so a child that dies mid-stream (its stdout
66
+ // closing, a write landing on a torn-down stdin) is observed here rather than
67
+ // escaping as an unhandled error — the death is reported via `whenTerminated`.
68
+ connection.onError(() => undefined);
69
+ connection.onClose(() => undefined);
70
+ connection.listen();
71
+ // One typed proxy over the data-server protocol; when a `localClient` is
72
+ // supplied its `on*` notification handlers are bound inbound on the same
73
+ // connection (skipped when absent — subcommands like `projects`/`query`).
74
+ const server = createRpcProxy(connection, {
75
+ methodNamespace: DATA_SERVER_WIRE_PREFIX,
76
+ localTarget: localClient,
77
+ localMethods: DATA_CLIENT_PROTOCOL_METHODS
78
+ });
79
+ // A premature child death (spawn `ENOENT`, a crash, or an exit before we asked
80
+ // for one) rejects `whenTerminated` so a racing RPC fails fast instead of
81
+ // hanging on a request that can never be answered. `terminating` gates it so an
82
+ // expected `shutdown()` exit does NOT reject. The `void .catch` guarantees the
83
+ // promise is always handled — an ignored failure can never crash the process
84
+ // with an unhandled 'error' event / rejection.
85
+ let terminating = false;
86
+ const whenTerminated = new Promise((_, reject) => {
87
+ child.once('error', error => {
88
+ if (!terminating) {
89
+ reject(new Error(`data-server process failed to start (command='${options.command}'): ${error.message}`));
90
+ }
91
+ });
92
+ child.once('exit', (code, signal) => {
93
+ if (!terminating) {
94
+ reject(new Error(`data-server process exited before the request completed ` +
95
+ `(command='${options.command}', code=${code ?? 'null'}, signal=${signal ?? 'null'}).`));
96
+ }
97
+ });
98
+ });
99
+ void whenTerminated.catch(() => undefined);
100
+ let shutdownPromise;
101
+ const shutdown = (timeoutMs = 5_000) => {
102
+ if (shutdownPromise) {
103
+ return shutdownPromise;
104
+ }
105
+ terminating = true;
106
+ shutdownPromise = new Promise(resolve => {
107
+ const finalize = () => {
108
+ connection.dispose();
109
+ resolve();
110
+ };
111
+ if (child.exitCode !== null || child.signalCode !== null) {
112
+ finalize();
113
+ return;
114
+ }
115
+ const onExit = () => {
116
+ clearTimeout(killTimer);
117
+ finalize();
118
+ };
119
+ child.once('exit', onExit);
120
+ // Polite exit first — most servers handle SIGTERM by closing
121
+ // their JSON-RPC connection and returning from `connection.listen()`.
122
+ child.kill('SIGTERM');
123
+ const killTimer = setTimeout(() => {
124
+ child.kill('SIGKILL');
125
+ }, timeoutMs);
126
+ });
127
+ return shutdownPromise;
128
+ };
129
+ return { server, child, connection, whenTerminated, shutdown };
130
+ }
131
+ /**
132
+ * Spawn a data-server, run `use` against its typed proxy, and always shut the
133
+ * child down afterwards. The `use` call is raced against
134
+ * {@link DataServerHandle.whenTerminated}, so a spawn failure or a premature child
135
+ * exit rejects with a clear message instead of hanging on an RPC that can never be
136
+ * answered. This is the one-shot counterpart the `projects` / `query` / `save`
137
+ * subcommands compose; `watch` races its own long-running loop against
138
+ * `whenTerminated` directly.
139
+ */
140
+ export async function withDataServer(options, use, localClient) {
141
+ const handle = spawnDataServer(options, localClient);
142
+ const usePromise = use(handle.server, handle);
143
+ // Defensively handle `usePromise` so that if `whenTerminated` wins the race
144
+ // (the child died), the losing in-flight RPC's later rejection — e.g. a write to
145
+ // the now-destroyed stdin — does not surface as an unhandled rejection.
146
+ void usePromise.catch(() => undefined);
147
+ try {
148
+ return await Promise.race([usePromise, handle.whenTerminated]);
149
+ }
150
+ finally {
151
+ await handle.shutdown();
152
+ }
153
+ }
154
+ //# sourceMappingURL=spawn-data-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-data-server.js","sourceRoot":"","sources":["../src/spawn-data-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /********************************************************************************
3
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
4
+ *
5
+ * This program and the accompanying materials are made available under the
6
+ * terms of the MIT License which is available in the project root.
7
+ *
8
+ * SPDX-License-Identifier: MIT
9
+ ********************************************************************************/
10
+ export {};
11
+ //# sourceMappingURL=echo-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"echo-server.d.ts","sourceRoot":"","sources":["../../src/testing/echo-server.ts"],"names":[],"mappings":";AACA;;;;;;;kFAOkF"}