@hydranium/cli 1.0.0-next.244 → 1.0.0-next.246

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 (2) hide show
  1. package/README.md +73 -225
  2. package/package.json +21 -10
package/README.md CHANGED
@@ -1,261 +1,109 @@
1
1
  # `@hydranium/cli`
2
2
 
3
- The headless tool surface of the [Hydranium](https://github.com/eclipse-emfcloud/hydranium)
4
- framework, published as the `hydranium-cli` binary.
5
-
6
- Install it if you are building a Hydranium language. `init` scaffolds a complete project from one
7
- invocation; the other twelve subcommands drive an already-built head from a shell or a CI step —
8
- grammar introspection, headless validation, transfer-model codegen, memory measurement, and
9
- operations against a spawned data-server.
3
+ The `hydranium-cli` binary of the
4
+ [Hydranium](https://github.com/eclipse-emfcloud/hydranium) framework. You
5
+ install it when you build a Hydranium language: `init` scaffolds the project,
6
+ and the other commands drive your built head from a shell or a CI step.
10
7
 
11
8
  ## What it gives you
12
9
 
13
- - **`init`** — a buildable project (starter grammar, `create<Name>Services` DI wiring, an LSP +
14
- data-server launch, `langium-config.json`, build scripts) from one command, or from a wizard that
15
- echoes the flags it composed.
16
- - **CI gates that need no editor** — `validate` exits non-zero on a diagnostic; `lint-grammar`
17
- checks that every concrete cross-reference target carries a name property and that each language
18
- declares an entry rule.
19
- - **Grammar introspection** — `reflect` (type hierarchy, terminals, every cross-reference target;
20
- Markdown or `--json`) and `model-docs` (a navigable Markdown model reference for your own docs).
21
- - **Codegen** — `generate-transfer-model` turns a Langium-generated AST into a serializable transfer
22
- model, once or in `--watch`.
23
- - **Memory and profiling** — `measure-memory`, `ast-ground-truth`, and the memlab-based
24
- `analyze-heap`.
25
- - **Data-server operations** — `projects`, `query`, `save` and `watch` spawn a data-server child and
26
- speak its protocol, printing JSON / NDJSON a script can pipe.
10
+ - Scaffold a buildable language project with one `init` command, or answer a
11
+ wizard that echoes the command it composed.
12
+ - Fail a CI step on a diagnostic or a grammar-convention violation, with no
13
+ editor running.
14
+ - Dump your grammar's reflection, or write a Markdown model reference for your
15
+ own docs.
16
+ - Generate the serializable transfer model from Langium's generated AST.
17
+ - Measure model-store memory and analyze a V8 heap snapshot.
18
+ - List, read, save and watch documents through a spawned data server, printing
19
+ JSON a script can pipe.
27
20
 
28
21
  ## Install
29
22
 
30
- `init` needs no install at all:
23
+ `init` needs no install:
31
24
 
32
25
  ```bash
33
26
  npx @hydranium/cli init ./my-lang --name MyLang
34
27
  ```
35
28
 
36
- For the subcommands you run repeatedly, add it to the project it inspects, or install it globally:
29
+ For the commands you run repeatedly, add it to the project it inspects, or
30
+ install it globally:
37
31
 
38
32
  ```bash
39
33
  npm install --save-dev @hydranium/cli
40
34
  npm install --global @hydranium/cli
41
35
  ```
42
36
 
43
- The framework edges are **peer dependencies** — `@hydranium/core`, `@hydranium/data-server`,
44
- `@hydranium/langium`, `@hydranium/protocol` and `vscode-jsonrpc` — so the CLI runs the same physical
45
- copies as the head it inspects (`init` itself needs none of them). The memlab packages
46
- `analyze-heap` loads are **optional peer dependencies**, so installing this package pulls no browser:
47
- run `npm install @memlab/core @memlab/heap-analysis` (heavy, ~86 MB) before the first
48
- `analyze-heap`. Every other subcommand works without them.
49
-
50
- ## Subcommands
51
-
52
- `hydranium-cli --help` lists them; `hydranium-cli <command> --help` prints one command's own flags.
53
-
54
- Most subcommands take `--services <module>`: an ESM module exporting a zero-arg
55
- `createServices(): { shared }` thunk — normally your build's `./lib/services.js`. The head wires its
56
- own filesystem inside, so the CLI boots it with no arguments.
57
-
58
- To run the head from its TypeScript source instead, register a loader with `--import <specifier>`
59
- (repeatable), which the CLI passes as Node's own `--import` to the process that imports the head:
60
- `npx hydranium-cli reflect --import tsx --services ./src/services.ts`. A package name resolves from
61
- the directory the command runs in, as Node's flag does; a path, absolute or relative, is resolved
62
- against that directory and passed on as a file URL, so Windows paths work too. Node's built-in type
63
- stripping is not enough on its own: it neither maps a head's `./x.js` imports to their `.ts` sources
64
- nor accepts the namespaces Langium generates.
65
-
66
- **Scaffolding**
67
-
68
- - `init <target-dir>` — scaffold a new language project. See the section below.
69
-
70
- **Grammar and workspace** (`--services <module>`)
71
-
72
- - `reflect` — dump the grammar/AST reflection: type hierarchy, per-language terminals and entry
73
- rule, every cross-reference target. `--json`, `--out-file <file>`.
74
- - `lint-grammar` — check the grammar against framework conventions; non-zero exit on a violation.
75
- `--name-property <p>` (repeatable), `--strict`, `--json`.
76
- - `model-docs` — emit a navigable Markdown model reference on stdout, or into `--out-file <file>`.
77
- - `validate <workspace>` — build a workspace headlessly and report its diagnostics; non-zero exit on
78
- any error. `--strict` (also fail on warnings), `--json`, `--out-file <file>`.
79
- - `measure-memory <workspace>` — measure model-store memory in an `--expose-gc` child.
80
- `--edits <N>`, `--edit-docs <N>`, `--churn-suffix <ext>`, `--settle <ms>`, `--snapshot`,
81
- `--snapshot-path <p>`, `--profile <dims>`, `--session-out <dir>`, `--json`.
82
- - `ast-ground-truth <workspace>` — tally the live model's AST nodes by `$type`, the ground truth
83
- `analyze-heap --validate` checks a snapshot against. `--out-file <file>`.
84
-
85
- All six also take `--log-level <off|error|warn|info|debug|trace>`, which sets the threshold for the
86
- head the subcommand boots — not for the CLI itself. It reaches the head through the child's
87
- environment, so a head that binds a logger of its own decides what the flag means to it.
88
-
89
- The three `<workspace>` commands resolve that argument to an existing directory before they start —
90
- a filesystem path or a `file:` URI — and exit 2 naming it when it reaches none. Without that a CI
91
- step whose path has rotted builds nothing, reports whatever documents the head contributes
92
- independently of the workspace, and exits 0; the count is a property of the head, so it can be
93
- plausibly non-zero and cannot be read as the tell.
94
-
95
- **Codegen**
96
-
97
- - `generate-transfer-model` — generate a transfer-model TypeScript file from a Langium AST.
98
- `--ast-file`, `--augmentation-file` and `--out-file` are required, and may come from
99
- `--config <path>` instead; `--langium-config <path>` derives `--ast-file` from that config's `out`
100
- directory. `--watch` regenerates on change, and the output-naming flags (`--element-type-name`,
101
- `--terminals-name`, `--terminals-source-name`, `--skip-type-alias`, `--skip-terminal`,
102
- `--regen-command`) tune the emitted file.
103
-
104
- **Heap analysis**
105
-
106
- - `analyze-heap <snapshot>` — Langium-aware V8 heap-snapshot analysis. Its flags (`--out-file`,
107
- `--json`, `--diff`, `--validate <gt.json>`, `--renderer`, and the drill-down tuning flags) are
108
- declared alongside every other subcommand's, so an unrecognised one is rejected rather than
109
- ignored.
110
-
111
- **Child-process heap ceiling** (`HYDRANIUM_CLI_MAX_OLD_SPACE_MB`)
112
-
113
- Subcommands that spawn a child — `analyze-heap`, `measure-memory`, `validate`, `lint-grammar`,
114
- `reflect`, `model-docs`, `ast-ground-truth` — give it `--max-old-space-size=8192` on a machine with
115
- no cgroup memory limit, and **no ceiling at all when there is one**. A ceiling above the limit lets
116
- V8 grow past it without collecting hard, so the kernel kills the container rather than the child
117
- reporting a heap error.
118
-
119
- Under a limit, Node derives its own ceiling from that limit, which is a fraction of it — so a
120
- roomy container gives a child less than the same machine would unconstrained. Set
121
- `HYDRANIUM_CLI_MAX_OLD_SPACE_MB` to state a ceiling in MiB; it wins in a container too. `0` means
122
- "let Node decide". A value below 256, or one carrying a unit suffix, is reported and ignored rather
123
- than passed on.
124
-
125
- **Data-server operations** (`--server "<cmd> [args...]"`)
126
-
127
- These spawn a data-server child and talk to it over its protocol. All four also take `--cwd <dir>`
128
- and `--log-level <off|error|warn|info|debug|trace>`.
129
-
130
- `--server` has to name an entry that puts the **data** protocol on stdio, which for a scaffolded
131
- project is `lib/data-server-main.js` — `init` emits it, and the `<project-id>-data-server` bin key
132
- points at it. `lib/main.js` is the editor entry: stdio there carries LSP and the data head is a
133
- socket whose port is published over the LSP connection, so pointing `--server` at it answers
134
- `Unhandled method data-server/getProjects` (or, without `--stdio`, exits on "Connection input stream
135
- is not set"). Pass the workspace as the entry's own argument rather than through `--cwd`: `--cwd`
136
- re-roots the child, so a relative entry path would resolve against the workspace — the parser
137
- refuses that combination by name rather than letting the child fail on a bare module-not-found.
138
- An absolute entry path works with `--cwd`.
37
+ | Peer | Range |
38
+ | ------------------------ | ------------- |
39
+ | `@hydranium/core` | `^1.0.0-next` |
40
+ | `@hydranium/data-server` | `^1.0.0-next` |
41
+ | `@hydranium/langium` | `^1.0.0-next` |
42
+ | `@hydranium/protocol` | `^1.0.0-next` |
43
+ | `@memlab/core` | `^2.0.3` |
44
+ | `@memlab/heap-analysis` | `^2.0.3` |
45
+ | `vscode-jsonrpc` | `^9.0.0` |
46
+
47
+ The two memlab packages are optional peers that only `analyze-heap` loads:
48
+ install them with `npm install @memlab/core @memlab/heap-analysis` before its
49
+ first run.
50
+
51
+ ## Commands
52
+
53
+ `hydranium-cli --help` lists the commands, and `hydranium-cli <command> --help`
54
+ lists each command's flags.
55
+
56
+ - **Scaffolding.** `init` writes a project you can build right away.
57
+ - **Grammar and workspace.** Boot your built head to reflect its grammar, lint
58
+ it, write a model reference, validate a workspace, or count its AST nodes.
59
+ - **Codegen.** `generate-transfer-model` turns the AST into a transfer model,
60
+ once or on watch.
61
+ - **Memory.** Measure a workspace's model-store memory, and analyze a heap
62
+ snapshot.
63
+ - **Data server.** Spawn your data head and list projects, or query, save or
64
+ watch a document.
65
+
66
+ The commands that boot your head take `--services <module>`. That is an ESM
67
+ module exporting a zero-arg `createServices()` that returns `{ shared }`,
68
+ normally your build's `./lib/services.js`. To run the head from its TypeScript
69
+ source instead, register a loader with `--import`:
70
+ `npx hydranium-cli reflect --import tsx --services ./src/services.ts`.
71
+
72
+ The data-server commands take `--server "<cmd> [args...]"`. Point it at the
73
+ data head's stdio entry, `lib/data-server-main.js` in a scaffolded project, not
74
+ at the editor entry `lib/main.js`, whose stdio carries LSP. Pass the workspace
75
+ as the entry's argument rather than through `--cwd`:
139
76
 
140
77
  ```bash
141
78
  hydranium-cli projects --server "node ./lib/data-server-main.js ./models"
142
79
  ```
143
80
 
144
- - `projects` — list the projects the server exposes, one JSON envelope per line.
145
- - `query --uri <uri>` — print that document's envelope as a single JSON line.
146
- - `save --uri <uri> --content <text|@file>` — update and persist the document; an `@`-prefixed value
147
- reads the content from a file. `--client-id <id>`. This is the only writing subcommand, and it
148
- spawns a data server of its own: a workspace has a **single writer**, so pointing it at one an
149
- editor already has open is two writers and the later write wins. Neither process will see a
150
- half-written file, but nothing serialises them either, so a lost write is the documented
151
- outcome rather than a defect — the guarantee, its one exception and what it does not cover are
152
- in [Status: one process writes a workspace](../../docs/adopting/status.md#one-process-writes-a-workspace).
153
- - `watch --uri <uri>` — subscribe to document updates and print events as NDJSON until Ctrl-C.
154
- `--client-id <id>`.
81
+ `save` spawns a data server of its own, and a workspace has one writer. Saving
82
+ into a workspace an editor has open makes two writers, and one write is lost.
155
83
 
156
- ## `init` in detail
157
-
158
- `init` writes a project you can build immediately, and it writes **only inside the target
159
- directory** — it refuses a non-empty directory without `--force`, and it never edits a surrounding
160
- manifest (a root `workspaces` entry and dependency pins are printed, not added). It also does
161
- **not** run `npm install` or `langium generate`; both are printed as next steps.
162
-
163
- Project options are position-free:
164
-
165
- - `<target-dir>` and `--name <Name>` are required. `--name` is the PascalCase **project** name and
166
- drives the shared generated symbols (`<Name>AstReflection`, `<Name>GeneratedSharedModule`).
167
- - `--heads <list>` picks the protocol heads from `lsp`, `data`, `glsp`; default `lsp,data`. `lsp` is
168
- mandatory — it owns the workspace, the build pipeline and the shared tier the others read through.
169
- - `--monorepo` scaffolds a member of the surrounding npm workspace, `--scope <@scope>` sets the npm
170
- scope, `--public` drops the emitted `"private": true`, `--force` allows a non-empty directory.
171
- `--monorepo` also prints the exact pins, `langium` and the LSP stack among them, for the root's
172
- `devDependencies`: npm installs a root's own dependencies at the top of the tree, so another
173
- member's version cannot leave this package on a copy the framework does not share.
174
-
175
- The emitted manifest carries `files` (`lib`, `src`, `syntaxes`), a derived `description` and
176
- `keywords`, and an empty `author` for you to fill. It is `"private": true` unless you pass
177
- `--public`, because it also declares `"license": "UNLICENSED"` — a scaffold cannot pick a licence for
178
- your project, and a package that grants no rights has no business being publishable to a public
179
- registry. Choose a licence, then pass `--public`. The wizard asks this on every run rather than
180
- letting a default settle it. `files` is not cosmetic: without it npm falls back
181
- to the `.gitignore` the scaffold also writes, which ignores `lib/` — so a publish would ship `main`
182
- and omit the `bin` targets beside it, and succeed. There is deliberately no `repository`: a scaffold
183
- cannot know yours, and tooling follows that field rather than merely displaying it.
184
-
185
- There is one `bin` key per executable entry — `<project-id>` for `src/main.ts`, plus
186
- `<project-id>-data-server` for `src/data-server-main.ts` when `data` is in `--heads`. Both sources
187
- begin with a `#!` line, because npm sets the exec bit on a linked target without adding one: a
188
- first line that is anything else is handed to the shell.
189
-
190
- Grammar options are **repeatable and order-scoped**: each applies to the `--grammar` it follows.
191
-
192
- - `--grammar <Name>` — the PascalCase grammar name; pass it once per grammar. Defaults to `--name`.
193
- - `--extensions <list>` — comma-separated file extensions for that grammar, leading dot optional;
194
- accumulates. Defaults to the kebab-cased grammar name.
195
- - `--language-id <id>` — override that grammar's derived routing key.
196
- - `--diagram` — scaffold a GLSP diagram for that grammar; requires `glsp` in `--heads`.
197
-
198
- Leave `--name` off on an interactive terminal and `init` prompts instead, then echoes the command it
199
- composed before running it — so the wizard is a way to reach an `init` command line, not an
200
- alternative to one. Without a TTY a missing `--name` stays an error, so CI never hangs.
201
-
202
- ```bash
203
- # Scaffold, install, build
204
- npx @hydranium/cli init ./my-lang --name MyLang
205
- cd my-lang
206
- npm install
207
- npm run build # langium generate + tsc, into lib/
208
- npm test # the scaffolded DI-composition test
209
-
210
- # A model to work on: the starter grammar's nodes, one referencing the other
211
- mkdir models
212
- printf 'node Start -> End\nnode End\n' > models/first.my-lang
213
-
214
- # The editor entry: LSP on stdio, every other head on a published socket
215
- node lib/main.js --stdio
216
-
217
- # The data head alone, on stdio — the entry the four --server subcommands spawn
218
- hydranium-cli projects --server "node ./lib/data-server-main.js ./models"
219
-
220
- # Drive the rest of the CLI against the built factory
221
- npx hydranium-cli reflect --services ./lib/services.js
222
- npx hydranium-cli lint-grammar --services ./lib/services.js
223
- npx hydranium-cli validate --services ./lib/services.js ./models
224
- npx hydranium-cli model-docs --services ./lib/services.js --out-file model-reference.md
225
-
226
- # Several grammars, three heads, one of them with a diagram
227
- npx @hydranium/cli init ./order-flow --name OrderFlow --heads lsp,data,glsp \
228
- --grammar Domain --grammar Process --diagram \
229
- --grammar Layout --extensions diagram
230
- ```
231
-
232
- The scaffold wires only the framework defaults. The seams a real language customizes are in
233
- [Adopting Hydranium](../../docs/ADOPTING.md).
84
+ Commands that spawn a child give it a heap ceiling; set
85
+ `HYDRANIUM_CLI_MAX_OLD_SPACE_MB` to state your own in MiB.
234
86
 
235
87
  ## Entry points
236
88
 
237
- This package declares a two-key `exports` map — the root barrel and the CLI
238
- binary — plus a `main` and a `bin`. The binary key names the file, `./lib/cli.js`:
239
- a consumer that spawns the binary resolves it by specifier, and `bin` offers a
240
- shim on `PATH` rather than a path.
241
-
242
- | Entry | Kind | Contents |
243
- | ---------------- | ------ | -------------------------------- |
244
- | `hydranium-cli` | `bin` | The binary — all 13 subcommands. |
245
- | `@hydranium/cli` | `main` | Programmatic API (see below). |
89
+ | Subpath | Use it for | Runs in |
90
+ | ---------------- | ---------------------------------------------------------------------------- | ------- |
91
+ | `hydranium-cli` | The binary (`bin`). | Node |
92
+ | `.` | Spawn a data server and get a typed proxy; run the codegen as a function. | Node |
93
+ | `./lib/cli.js` | Resolve the binary's file by specifier, to spawn it from a script or a test. | Node |
246
94
 
247
- The programmatic surface is the part of the CLI worth calling from your own scripts and tests rather
248
- than through argv: `spawnDataServer` / `withDataServer` (spawn a data-server child and get a typed
249
- proxy, with teardown), `generateTransferModel` / `watchTransferModel` (the codegen, as a function),
250
- and the `runProjects` / `runQuery` / `runSave` / `runWatch` command bodies.
95
+ The subpaths need a TypeScript `moduleResolution` that reads `exports`
96
+ (`NodeNext` or `Bundler`); see *Requirements* in
97
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
251
98
 
252
99
  ## Status
253
100
 
254
- Alpha — pre-v0, published as a `1.0.0-next` prerelease on every merge to `main`. The subcommand
255
- surface and the programmatic API are both still moving. See the [repository README](../../README.md)
256
- for the current status and known limitations.
101
+ Alpha: every release is a prerelease that may break the API, so pin an exact
102
+ version. Guides and known limitations:
103
+ [Adopting Hydranium](https://github.com/eclipse-emfcloud/hydranium/blob/main/docs/ADOPTING.md).
257
104
 
258
105
  ## License
259
106
 
260
107
  `MIT` — see this package's [`LICENSE`](./LICENSE), and the repository
261
- [`NOTICE.md`](../../NOTICE.md) for third-party notices.
108
+ [`NOTICE.md`](https://github.com/eclipse-emfcloud/hydranium/blob/main/NOTICE.md)
109
+ for third-party notices.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydranium/cli",
3
- "version": "1.0.0-next.244",
3
+ "version": "1.0.0-next.246",
4
4
  "description": "Build-time codegen tools + data-server subcommands for the hydranium framework.",
5
5
  "keywords": [
6
6
  "cli",
@@ -69,20 +69,30 @@
69
69
  "ts-morph": "^25.0.0"
70
70
  },
71
71
  "devDependencies": {
72
- "@hydranium/core": "1.0.0-next.244",
73
- "@hydranium/data-server": "1.0.0-next.244",
74
- "@hydranium/langium": "1.0.0-next.244",
75
- "@hydranium/protocol": "1.0.0-next.244",
72
+ "@eclipse-glsp/graph": "2.7.0",
73
+ "@eclipse-glsp/server": "2.7.0",
74
+ "@hydranium/core": "1.0.0-next.246",
75
+ "@hydranium/data-server": "1.0.0-next.246",
76
+ "@hydranium/glsp-server": "1.0.0-next.246",
77
+ "@hydranium/langium": "1.0.0-next.246",
78
+ "@hydranium/protocol": "1.0.0-next.246",
79
+ "@types/node": "^22.0.0",
80
+ "inversify": "6.2.2",
81
+ "langium": "4.3.1",
82
+ "langium-cli": "4.3.0",
83
+ "reflect-metadata": "0.2.2",
76
84
  "rimraf": "^5.0.0",
77
85
  "typescript": "^7.0.2",
86
+ "vitest": "^4.0.0",
78
87
  "vscode-jsonrpc": "9.0.0",
79
- "vscode-languageserver": "10.0.1"
88
+ "vscode-languageserver": "10.0.1",
89
+ "vscode-languageserver-protocol": "3.18.1"
80
90
  },
81
91
  "peerDependencies": {
82
- "@hydranium/core": "1.0.0-next.244",
83
- "@hydranium/data-server": "1.0.0-next.244",
84
- "@hydranium/langium": "1.0.0-next.244",
85
- "@hydranium/protocol": "1.0.0-next.244",
92
+ "@hydranium/core": "1.0.0-next.246",
93
+ "@hydranium/data-server": "1.0.0-next.246",
94
+ "@hydranium/langium": "1.0.0-next.246",
95
+ "@hydranium/protocol": "1.0.0-next.246",
86
96
  "@memlab/core": "^2.0.3",
87
97
  "@memlab/heap-analysis": "^2.0.3",
88
98
  "vscode-jsonrpc": "^9.0.0"
@@ -98,6 +108,7 @@
98
108
  "engines": {
99
109
  "node": ">=22.13"
100
110
  },
111
+ "//devDependencies": "Every package an `init` scaffold declares, other than this one, is declared here, whether or not `src` uses it: the scaffold-compiles test compiles and runs scaffolds inside this package, so their imports and tools resolve through these declarations. `check:init-provenance` holds this list and its versions to the scaffold's manifest.",
101
112
  "//exports": "Two keys, and the SHORT list is the point: `files` ships the whole compiled tree, so without a map every `lib/commands/*.js`, every internal helper and `lib/testing/echo-server.js` is deep-importable the moment this publishes, and semver then applies to all of it. `.` is the library barrel (the data-server subcommands an adopter calls as functions). `./lib/cli.js` is the BINARY ARTEFACT, and it is declared because a consumer that spawns the CLI resolves it BY SPECIFIER — `createRequire(import.meta.url).resolve('@hydranium/cli/lib/cli.js')` — to get the path npx would run; `bin` gives a shim on PATH, not a path, so dropping this key breaks that resolution and the failure surfaces as \"hydranium-cli is not built\", naming the wrong cause. `heap-analysis/` needs no key even though `files` ships it — `analyze-heap` reaches the analyzer through a `new URL(..., import.meta.url)` file URL, which `exports` does not gate, and the package's own tests reach it relatively. `./testing` is deliberately absent: `echo-server` is a spawnable stdio fixture, not a reusable export.",
102
113
  "//memlab": "@memlab/core and @memlab/heap-analysis are OPTIONAL PEER dependencies, not optionalDependencies, and the distinction is the whole point: npm installs optionalDependencies BY DEFAULT, both memlab packages pin puppeteer exactly, and puppeteer's postinstall downloads a Chrome binary — so every adopter of this CLI paid ~86 MB and a browser download for the one subcommand almost none of them run, and the download can fail and be walked past as a warning. An optional peer is not auto-installed, so `analyze-heap` documents `npm install @memlab/core @memlab/heap-analysis` as the opt-in and every other subcommand is unaffected. Taken pre-publish deliberately: after publish the install shape is what adopters already have.",
103
114
  "//peerDependencies": "`vscode-jsonrpc` takes a caret, so the framework shares the transport the LSP connection resolves, which an `init` scaffold pins: each `vscode-languageserver-protocol` release pins its transport exactly, so an exact peer would name a copy a fresh install rarely holds. The caret excludes 8.x, so a tree whose top holds GLSP's copy fails the peer with a named ERESOLVE warning, an error under `--strict-peer-deps`, rather than resolving silently. No peer reaches a NESTED copy, such as GLSP's or one the LSP packages nest. The wire compares message types and `ResponseError`s by copy identity, so the framework sends typed messages by method name and recognises errors with `isResponseError` rather than `instanceof`.",