@lsproxy/cli 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +167 -0
- package/dist/apply.d.ts +139 -0
- package/dist/apply.d.ts.map +1 -0
- package/dist/apply.js +325 -0
- package/dist/apply.js.map +1 -0
- package/dist/build-commands.d.ts +6 -0
- package/dist/build-commands.d.ts.map +1 -0
- package/dist/build-commands.js +111 -0
- package/dist/build-commands.js.map +1 -0
- package/dist/cli.d.ts +30 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +207 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/move-file.d.ts +13 -0
- package/dist/commands/move-file.d.ts.map +1 -0
- package/dist/commands/move-file.js +84 -0
- package/dist/commands/move-file.js.map +1 -0
- package/dist/commands/move-symbol.d.ts +70 -0
- package/dist/commands/move-symbol.d.ts.map +1 -0
- package/dist/commands/move-symbol.js +154 -0
- package/dist/commands/move-symbol.js.map +1 -0
- package/dist/commands/query.d.ts +14 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +46 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/rename.d.ts +14 -0
- package/dist/commands/rename.d.ts.map +1 -0
- package/dist/commands/rename.js +42 -0
- package/dist/commands/rename.js.map +1 -0
- package/dist/connect.d.ts +10 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +63 -0
- package/dist/connect.js.map +1 -0
- package/dist/discover.d.ts +17 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +46 -0
- package/dist/discover.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/io.d.ts +76 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +150 -0
- package/dist/io.js.map +1 -0
- package/dist/session.d.ts +89 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +286 -0
- package/dist/session.js.map +1 -0
- package/dist/zod-to-commander.d.ts +11 -0
- package/dist/zod-to-commander.d.ts.map +1 -0
- package/dist/zod-to-commander.js +351 -0
- package/dist/zod-to-commander.js.map +1 -0
- package/package.json +65 -0
package/dist/io.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI I/O helpers.
|
|
3
|
+
*
|
|
4
|
+
* Convention: **stdout is reserved for command output** (human summary or, with
|
|
5
|
+
* `--json`, a single JSON document). All progress/diagnostic chatter goes to
|
|
6
|
+
* **stderr** so piped `--json` consumers get clean input.
|
|
7
|
+
*/
|
|
8
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
9
|
+
import { dirname, isAbsolute, relative, resolve, sep } from 'node:path';
|
|
10
|
+
/**
|
|
11
|
+
* Resolve a path's longest EXISTING ancestor through `realpath`, then rejoin the
|
|
12
|
+
* non-existing tail. This makes containment checks symlink-aware even for
|
|
13
|
+
* destinations that do not exist yet (e.g. a move target): if any existing
|
|
14
|
+
* ancestor is a symlink escaping `--root`, the canonical path reflects it, while
|
|
15
|
+
* a not-yet-created leaf cannot be `realpath`'d directly (it would throw).
|
|
16
|
+
*
|
|
17
|
+
* Walks up to a fixed-point so a chain like `root/link -> /tmp/ext` + `ext/sub`
|
|
18
|
+
* is fully canonicalized via the first existing ancestor.
|
|
19
|
+
*/
|
|
20
|
+
function canonicalize(absPath) {
|
|
21
|
+
let existing = absPath;
|
|
22
|
+
const tail = [];
|
|
23
|
+
while (!existsSync(existing)) {
|
|
24
|
+
const parent = dirname(existing);
|
|
25
|
+
if (parent === existing)
|
|
26
|
+
break; // reached filesystem root
|
|
27
|
+
tail.unshift(existing.slice(parent.length + 1));
|
|
28
|
+
existing = parent;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const real = realpathSync(existing);
|
|
32
|
+
return tail.length ? resolve(real, ...tail) : real;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// realpath can still fail on permission errors; fall back to the lexical path.
|
|
36
|
+
return absPath;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Test whether an absolute path is contained within `root`, resolving symlinks
|
|
41
|
+
* in both the candidate and the root before comparing. A lexical-only check
|
|
42
|
+
* accepts `root/link/x` where `root/link -> /tmp/external`; canonicalizing the
|
|
43
|
+
* existing ancestors closes that escape.
|
|
44
|
+
*/
|
|
45
|
+
export function isInsideRoot(absPath, root) {
|
|
46
|
+
const realRoot = canonicalize(resolve(root));
|
|
47
|
+
const realPath = canonicalize(absPath);
|
|
48
|
+
return realPath === realRoot || realPath.startsWith(realRoot + sep);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a file-path argument against the project `--root` and enforce that it
|
|
52
|
+
* stays inside that root.
|
|
53
|
+
*
|
|
54
|
+
* This is the single base both the server (spawn cwd / `rootUri`) and the file
|
|
55
|
+
* arguments share — they MUST agree. Relative args are resolved against `root`
|
|
56
|
+
* (NOT `process.cwd()`), so running the CLI from an unrelated directory (e.g. a
|
|
57
|
+
* different git worktree of the same project) cannot silently operate on the
|
|
58
|
+
* wrong checkout. Absolute args are used as-is.
|
|
59
|
+
*
|
|
60
|
+
* Unless `allowOutsideRoot` is set, any resolved path outside `root` is rejected
|
|
61
|
+
* (error + non-zero exit, no changes) — defense-in-depth against the wrong-repo
|
|
62
|
+
* incident relative-cwd resolution caused. Containment is symlink-aware (see
|
|
63
|
+
* {@link isInsideRoot}).
|
|
64
|
+
*/
|
|
65
|
+
export function resolvePathArg(arg, flags) {
|
|
66
|
+
const root = resolve(flags.root);
|
|
67
|
+
const abs = isAbsolute(arg) ? resolve(arg) : resolve(root, arg);
|
|
68
|
+
if (!flags.allowOutsideRoot && !isInsideRoot(abs, root)) {
|
|
69
|
+
fail(`refusing: ${abs} is outside --root ${root}`, flags.json);
|
|
70
|
+
}
|
|
71
|
+
return abs;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Refuse a SERVER-RETURNED set of edit/resource targets that escape `--root`.
|
|
75
|
+
*
|
|
76
|
+
* The input-path guard ({@link resolvePathArg}) only validates CLI arguments;
|
|
77
|
+
* a language server can return a {@link WorkspaceEdit} whose URIs/resource ops
|
|
78
|
+
* point outside the project. Applying that unguarded would let a server
|
|
79
|
+
* modify, rename, or delete an external file — bypassing the `--root` safety
|
|
80
|
+
* guarantee. Every command routes server edits through this pre-flight check
|
|
81
|
+
* (via `apply.ts`), so all three inherit the boundary.
|
|
82
|
+
*
|
|
83
|
+
* Throws (rather than `fail()`/exit) so it composes inside the apply pipeline
|
|
84
|
+
* and is unit-testable; callers surface the message verbatim.
|
|
85
|
+
*/
|
|
86
|
+
export function assertTargetsInsideRoot(targets, flags) {
|
|
87
|
+
if (flags.allowOutsideRoot)
|
|
88
|
+
return;
|
|
89
|
+
const root = resolve(flags.root);
|
|
90
|
+
for (const abs of targets) {
|
|
91
|
+
if (!isInsideRoot(abs, root)) {
|
|
92
|
+
throw new Error(`refusing server edit: ${abs} is outside --root ${root} (pass --allow-outside-root to permit)`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Parse `line:col` (1-based, editor style) into a 1-based position. */
|
|
97
|
+
export function parseLineCol(input) {
|
|
98
|
+
const m = /^(\d+):(\d+)$/.exec(input.trim());
|
|
99
|
+
if (!m)
|
|
100
|
+
throw new Error(`Invalid position "${input}" — expected line:col (1-based), e.g. 12:7`);
|
|
101
|
+
const line = Number(m[1]);
|
|
102
|
+
const character = Number(m[2]);
|
|
103
|
+
if (line < 1 || character < 1)
|
|
104
|
+
throw new Error(`Position is 1-based; got "${input}"`);
|
|
105
|
+
return { line, character };
|
|
106
|
+
}
|
|
107
|
+
/** Convert a 1-based editor position to the 0-based position LSP expects. */
|
|
108
|
+
export function toLspPosition(p) {
|
|
109
|
+
return { line: p.line - 1, character: p.character - 1 };
|
|
110
|
+
}
|
|
111
|
+
export function fail(message, json) {
|
|
112
|
+
if (json)
|
|
113
|
+
process.stdout.write(JSON.stringify({ ok: false, error: message }) + '\n');
|
|
114
|
+
else
|
|
115
|
+
process.stderr.write(`error: ${message}\n`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
/** Render a list of applied/planned changes for human output. */
|
|
119
|
+
export function summarizeChanges(changes, root, dryRun) {
|
|
120
|
+
// Use path.relative so the root prefix is stripped with the platform
|
|
121
|
+
// separator (a hardcoded '/' left Windows paths un-shortened). Fall back to
|
|
122
|
+
// the absolute path for anything that resolves outside root.
|
|
123
|
+
const resolvedRoot = resolve(root);
|
|
124
|
+
const rel = (p) => relative(resolvedRoot, p) || p;
|
|
125
|
+
const lines = [];
|
|
126
|
+
const verb = dryRun ? 'would change' : 'changed';
|
|
127
|
+
const totalEdits = changes.reduce((n, c) => n + (c.editCount ?? 0), 0);
|
|
128
|
+
lines.push(`${dryRun ? '[dry-run] ' : ''}${changes.length} file(s) ${verb}, ${totalEdits} text edit(s)`);
|
|
129
|
+
for (const c of changes) {
|
|
130
|
+
if (c.kind === 'edit')
|
|
131
|
+
lines.push(` edit ${c.editCount}\t${rel(c.path)}`);
|
|
132
|
+
else if (c.kind === 'create')
|
|
133
|
+
lines.push(` create \t${rel(c.path)}`);
|
|
134
|
+
else if (c.kind === 'delete')
|
|
135
|
+
lines.push(` delete \t${rel(c.path)}`);
|
|
136
|
+
else if (c.kind === 'rename')
|
|
137
|
+
lines.push(` rename \t${rel(c.path)} -> ${rel(c.toPath ?? '')}`);
|
|
138
|
+
}
|
|
139
|
+
return lines.join('\n');
|
|
140
|
+
}
|
|
141
|
+
/** Emit the result, either as JSON (stdout) or a human summary. */
|
|
142
|
+
export function emitResult(op, changes, flags, extra = {}) {
|
|
143
|
+
if (flags.json) {
|
|
144
|
+
process.stdout.write(JSON.stringify({ ok: true, op, dryRun: flags.dryRun, changes, ...extra }) + '\n');
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
process.stdout.write(summarizeChanges(changes, flags.root, flags.dryRun) + '\n');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=io.js.map
|
package/dist/io.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"io.js","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin session wrapper around `@lspeasy/client` for one-shot refactor commands.
|
|
3
|
+
*
|
|
4
|
+
* Encapsulates the proven recipe: spawn the language server, connect (which
|
|
5
|
+
* performs the `initialize` / `initialized` handshake with a generous set of
|
|
6
|
+
* client capabilities), open an anchor file, wait for the project to index,
|
|
7
|
+
* then run a request with a single null-result retry.
|
|
8
|
+
*
|
|
9
|
+
* All diagnostic logging goes to **stderr** so that `--json` output on stdout
|
|
10
|
+
* stays machine-parseable.
|
|
11
|
+
*/
|
|
12
|
+
import { LSPClient } from '@lspeasy/client';
|
|
13
|
+
import { type ServerCapabilities, type Transport } from '@lspeasy/core';
|
|
14
|
+
import type { WorkspaceEdit } from './apply.js';
|
|
15
|
+
export interface SessionOptions {
|
|
16
|
+
/** Server launch command, e.g. `typescript-language-server --stdio`. Required unless `transport` is supplied. */
|
|
17
|
+
serverCommand?: string;
|
|
18
|
+
/** Absolute project root directory. */
|
|
19
|
+
root: string;
|
|
20
|
+
/** languageId for textDocument/didOpen (e.g. 'typescript', 'rust'). */
|
|
21
|
+
languageId?: string;
|
|
22
|
+
/** Milliseconds to wait for the server to index before the first request. */
|
|
23
|
+
indexWaitMs?: number;
|
|
24
|
+
/** Emit `[lspeasy] …` progress lines to stderr. */
|
|
25
|
+
verbose?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Pre-built transport to use instead of spawning a server process.
|
|
28
|
+
*
|
|
29
|
+
* When supplied, `serverCommand` is ignored and no child process is spawned.
|
|
30
|
+
* Used by the proxy path to reuse all downstream session logic unchanged.
|
|
31
|
+
*/
|
|
32
|
+
transport?: Transport;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* An ordered queue of edits the server pushed via `workspace/applyEdit`.
|
|
36
|
+
*
|
|
37
|
+
* A server implementing `executeCommand` may send MORE THAN ONE sequential
|
|
38
|
+
* applyEdit request for a single command. The old "single field" capture
|
|
39
|
+
* overwrote earlier edits while still acking each `applied: true`, silently
|
|
40
|
+
* dropping every edit but the last. This queue preserves them all in arrival
|
|
41
|
+
* order; {@link drain} returns and clears the batch.
|
|
42
|
+
*/
|
|
43
|
+
export declare class CapturedEdits {
|
|
44
|
+
private edits;
|
|
45
|
+
/** Record an edit the server pushed (handler must NOT drop it). */
|
|
46
|
+
push(edit: WorkspaceEdit): void;
|
|
47
|
+
/** Return all captured edits in order and reset the queue. */
|
|
48
|
+
drain(): WorkspaceEdit[];
|
|
49
|
+
}
|
|
50
|
+
export declare class RefactorSession {
|
|
51
|
+
private readonly opts;
|
|
52
|
+
private proc?;
|
|
53
|
+
private client?;
|
|
54
|
+
/**
|
|
55
|
+
* Edits pushed by the server via `workspace/applyEdit`, in arrival order. A
|
|
56
|
+
* server implementing `executeCommand` may send MORE THAN ONE sequential
|
|
57
|
+
* applyEdit; we queue them all (rather than overwriting) so none is dropped
|
|
58
|
+
* after the server was told `applied: true`.
|
|
59
|
+
*/
|
|
60
|
+
private readonly capturedEdits;
|
|
61
|
+
constructor(opts: SessionOptions);
|
|
62
|
+
private log;
|
|
63
|
+
/** Spawn the server (or reuse a pre-built transport) and complete the LSP handshake. */
|
|
64
|
+
start(): Promise<void>;
|
|
65
|
+
/** Notify the server that an anchor file is open. */
|
|
66
|
+
open(anchorFile: string): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Run a request immediately and retry with exponential backoff while the
|
|
69
|
+
* server returns null (i.e. it is still indexing). Gives up after
|
|
70
|
+
* `indexWaitMs` total elapsed time and returns null.
|
|
71
|
+
*
|
|
72
|
+
* Initial retry delay: 250 ms, doubling each round, capped at 5 s per
|
|
73
|
+
* attempt. The first attempt is always immediate so fast servers pay no
|
|
74
|
+
* extra latency at all.
|
|
75
|
+
*/
|
|
76
|
+
requestWithRetry<R>(run: () => Promise<R | null | undefined>): Promise<R | null>;
|
|
77
|
+
/**
|
|
78
|
+
* Drain ALL edits pushed by the server via `workspace/applyEdit` since the
|
|
79
|
+
* last drain, in arrival order. Returns an empty array if none were pushed.
|
|
80
|
+
* Callers apply them in order so a multi-applyEdit command is fully honored.
|
|
81
|
+
*/
|
|
82
|
+
takeCapturedEdits(): WorkspaceEdit[];
|
|
83
|
+
get lsp(): LSPClient;
|
|
84
|
+
get capabilities(): ServerCapabilities;
|
|
85
|
+
private requireClient;
|
|
86
|
+
/** Shut down the client and kill the server process. */
|
|
87
|
+
stop(): Promise<void>;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAKL,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,iHAAiH;IACjH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mDAAmD;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAwFD;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAAuB;IACpC,mEAAmE;IACnE,IAAI,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAE9B;IACD,8DAA8D;IAC9D,KAAK,IAAI,aAAa,EAAE,CAIvB;CACF;AAgCD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,OAAO,CAAC,IAAI,CAAC,CAAiC;IAC9C,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B;;;;;OAKG;IACH,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuB;IAErD,YAAY,IAAI,EAAE,cAAc,EAO/B;IAED,OAAO,CAAC,GAAG;IAIX,wFAAwF;IAClF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CA8C3B;IAED,qDAAqD;IAC/C,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAW5C;IAED;;;;;;;;OAQG;IACG,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAarF;IAED;;;;OAIG;IACH,iBAAiB,IAAI,aAAa,EAAE,CAEnC;IAED,IAAI,GAAG,IAAI,SAAS,CAEnB;IAED,IAAI,YAAY,IAAI,kBAAkB,CAErC;IAED,OAAO,CAAC,aAAa;IAKrB,wDAAwD;IAClD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAO1B;CACF"}
|
package/dist/session.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin session wrapper around `@lspeasy/client` for one-shot refactor commands.
|
|
3
|
+
*
|
|
4
|
+
* Encapsulates the proven recipe: spawn the language server, connect (which
|
|
5
|
+
* performs the `initialize` / `initialized` handshake with a generous set of
|
|
6
|
+
* client capabilities), open an anchor file, wait for the project to index,
|
|
7
|
+
* then run a request with a single null-result retry.
|
|
8
|
+
*
|
|
9
|
+
* All diagnostic logging goes to **stderr** so that `--json` output on stdout
|
|
10
|
+
* stays machine-parseable.
|
|
11
|
+
*/
|
|
12
|
+
import { spawn } from 'node:child_process';
|
|
13
|
+
import { readFileSync } from 'node:fs';
|
|
14
|
+
import { basename, resolve } from 'node:path';
|
|
15
|
+
import { pathToFileURL } from 'node:url';
|
|
16
|
+
import { LSPClient } from '@lspeasy/client';
|
|
17
|
+
import { NullLogger, tokenizeCommand } from '@lspeasy/core';
|
|
18
|
+
import { StdioTransport } from '@lspeasy/core/node';
|
|
19
|
+
// Advertise the full set of capabilities the CLI can dispatch so servers do
|
|
20
|
+
// not gate their ServerCapabilities on a narrow client declaration. Each entry
|
|
21
|
+
// corresponds to a ClientCapability path used by getCapabilityForRequestMethod;
|
|
22
|
+
// a missing entry silently suppresses the matching command from the command tree.
|
|
23
|
+
const CLIENT_CAPABILITIES = {
|
|
24
|
+
textDocument: {
|
|
25
|
+
synchronization: { dynamicRegistration: false },
|
|
26
|
+
// Navigation
|
|
27
|
+
definition: { dynamicRegistration: false },
|
|
28
|
+
declaration: { dynamicRegistration: false },
|
|
29
|
+
typeDefinition: { dynamicRegistration: false },
|
|
30
|
+
implementation: { dynamicRegistration: false },
|
|
31
|
+
references: { dynamicRegistration: false },
|
|
32
|
+
documentHighlight: { dynamicRegistration: false },
|
|
33
|
+
documentSymbol: { dynamicRegistration: false },
|
|
34
|
+
// Hover / completion / signature
|
|
35
|
+
hover: { dynamicRegistration: false },
|
|
36
|
+
completion: { dynamicRegistration: false },
|
|
37
|
+
signatureHelp: { dynamicRegistration: false },
|
|
38
|
+
// Refactor / actions / rename
|
|
39
|
+
rename: { dynamicRegistration: false, prepareSupport: true },
|
|
40
|
+
codeAction: {
|
|
41
|
+
dynamicRegistration: false,
|
|
42
|
+
codeActionLiteralSupport: {
|
|
43
|
+
codeActionKind: {
|
|
44
|
+
valueSet: [
|
|
45
|
+
'',
|
|
46
|
+
'quickfix',
|
|
47
|
+
'refactor',
|
|
48
|
+
'refactor.extract',
|
|
49
|
+
'refactor.inline',
|
|
50
|
+
'refactor.move',
|
|
51
|
+
'refactor.rewrite',
|
|
52
|
+
'source',
|
|
53
|
+
'source.organizeImports',
|
|
54
|
+
'source.fixAll'
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
resolveSupport: { properties: ['edit'] },
|
|
59
|
+
dataSupport: true
|
|
60
|
+
},
|
|
61
|
+
codeLens: { dynamicRegistration: false },
|
|
62
|
+
// Formatting
|
|
63
|
+
formatting: { dynamicRegistration: false },
|
|
64
|
+
rangeFormatting: { dynamicRegistration: false },
|
|
65
|
+
onTypeFormatting: { dynamicRegistration: false },
|
|
66
|
+
// Semantic tokens — needed for servers to advertise semanticTokensProvider
|
|
67
|
+
semanticTokens: {
|
|
68
|
+
dynamicRegistration: false,
|
|
69
|
+
requests: { full: { delta: true }, range: true },
|
|
70
|
+
tokenTypes: [],
|
|
71
|
+
tokenModifiers: [],
|
|
72
|
+
formats: ['relative'],
|
|
73
|
+
overlappingTokenSupport: false,
|
|
74
|
+
multilineTokenSupport: false
|
|
75
|
+
},
|
|
76
|
+
// Hierarchy / navigation
|
|
77
|
+
callHierarchy: { dynamicRegistration: false },
|
|
78
|
+
typeHierarchy: { dynamicRegistration: false },
|
|
79
|
+
selectionRange: { dynamicRegistration: false },
|
|
80
|
+
foldingRange: { dynamicRegistration: false },
|
|
81
|
+
linkedEditingRange: { dynamicRegistration: false },
|
|
82
|
+
// Lenses / hints
|
|
83
|
+
inlayHint: { dynamicRegistration: false, resolveSupport: { properties: [] } },
|
|
84
|
+
inlineValue: { dynamicRegistration: false },
|
|
85
|
+
// Diagnostics / misc
|
|
86
|
+
diagnostic: { dynamicRegistration: false },
|
|
87
|
+
colorProvider: { dynamicRegistration: false },
|
|
88
|
+
documentLink: { dynamicRegistration: false },
|
|
89
|
+
moniker: { dynamicRegistration: false }
|
|
90
|
+
},
|
|
91
|
+
workspace: {
|
|
92
|
+
applyEdit: true,
|
|
93
|
+
executeCommand: { dynamicRegistration: false },
|
|
94
|
+
symbol: { dynamicRegistration: false },
|
|
95
|
+
workspaceEdit: {
|
|
96
|
+
documentChanges: true,
|
|
97
|
+
resourceOperations: ['create', 'rename', 'delete']
|
|
98
|
+
},
|
|
99
|
+
fileOperations: { dynamicRegistration: false, willRename: true }
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
103
|
+
/**
|
|
104
|
+
* An ordered queue of edits the server pushed via `workspace/applyEdit`.
|
|
105
|
+
*
|
|
106
|
+
* A server implementing `executeCommand` may send MORE THAN ONE sequential
|
|
107
|
+
* applyEdit request for a single command. The old "single field" capture
|
|
108
|
+
* overwrote earlier edits while still acking each `applied: true`, silently
|
|
109
|
+
* dropping every edit but the last. This queue preserves them all in arrival
|
|
110
|
+
* order; {@link drain} returns and clears the batch.
|
|
111
|
+
*/
|
|
112
|
+
export class CapturedEdits {
|
|
113
|
+
edits = [];
|
|
114
|
+
/** Record an edit the server pushed (handler must NOT drop it). */
|
|
115
|
+
push(edit) {
|
|
116
|
+
this.edits.push(edit);
|
|
117
|
+
}
|
|
118
|
+
/** Return all captured edits in order and reset the queue. */
|
|
119
|
+
drain() {
|
|
120
|
+
const out = this.edits;
|
|
121
|
+
this.edits = [];
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Logger that routes everything to **stderr**, keeping stdout clean for the
|
|
127
|
+
* CLI's own output (critical for `--json`).
|
|
128
|
+
*/
|
|
129
|
+
class StderrLogger {
|
|
130
|
+
error(message, ...args) {
|
|
131
|
+
this.write('error', message, args);
|
|
132
|
+
}
|
|
133
|
+
warn(message, ...args) {
|
|
134
|
+
this.write('warn', message, args);
|
|
135
|
+
}
|
|
136
|
+
info(message, ...args) {
|
|
137
|
+
this.write('info', message, args);
|
|
138
|
+
}
|
|
139
|
+
debug(message, ...args) {
|
|
140
|
+
this.write('debug', message, args);
|
|
141
|
+
}
|
|
142
|
+
trace(message, ...args) {
|
|
143
|
+
this.write('trace', message, args);
|
|
144
|
+
}
|
|
145
|
+
write(level, message, args) {
|
|
146
|
+
const extra = args.length ? ' ' + args.map((a) => JSON.stringify(a)).join(' ') : '';
|
|
147
|
+
process.stderr.write(`[lsp:${level}] ${message}${extra}\n`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
export class RefactorSession {
|
|
151
|
+
opts;
|
|
152
|
+
proc;
|
|
153
|
+
client;
|
|
154
|
+
/**
|
|
155
|
+
* Edits pushed by the server via `workspace/applyEdit`, in arrival order. A
|
|
156
|
+
* server implementing `executeCommand` may send MORE THAN ONE sequential
|
|
157
|
+
* applyEdit; we queue them all (rather than overwriting) so none is dropped
|
|
158
|
+
* after the server was told `applied: true`.
|
|
159
|
+
*/
|
|
160
|
+
capturedEdits = new CapturedEdits();
|
|
161
|
+
constructor(opts) {
|
|
162
|
+
this.opts = {
|
|
163
|
+
indexWaitMs: 15000,
|
|
164
|
+
verbose: false,
|
|
165
|
+
languageId: 'plaintext',
|
|
166
|
+
...opts
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
log(msg) {
|
|
170
|
+
if (this.opts.verbose)
|
|
171
|
+
process.stderr.write(`[lspeasy] ${msg}\n`);
|
|
172
|
+
}
|
|
173
|
+
/** Spawn the server (or reuse a pre-built transport) and complete the LSP handshake. */
|
|
174
|
+
async start() {
|
|
175
|
+
// Derive the workspace root URI + folders from --root so the server indexes
|
|
176
|
+
// the right project (rootUri:null is fragile for non-tsserver servers).
|
|
177
|
+
const rootDir = resolve(this.opts.root);
|
|
178
|
+
const rootUri = pathToFileURL(rootDir).href;
|
|
179
|
+
let transport;
|
|
180
|
+
if (this.opts.transport) {
|
|
181
|
+
transport = this.opts.transport;
|
|
182
|
+
this.log(`using pre-built transport (proxy)`);
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
const [cmd, ...args] = tokenizeCommand(this.opts.serverCommand ?? '');
|
|
186
|
+
if (!cmd)
|
|
187
|
+
throw new Error('Empty --server command');
|
|
188
|
+
this.log(`spawning: ${this.opts.serverCommand} (cwd ${this.opts.root})`);
|
|
189
|
+
const proc = spawn(cmd, args, { cwd: this.opts.root });
|
|
190
|
+
this.proc = proc;
|
|
191
|
+
proc.on('error', (e) => {
|
|
192
|
+
process.stderr.write(`[lspeasy] server spawn error: ${e.message}\n`);
|
|
193
|
+
});
|
|
194
|
+
transport = new StdioTransport({ input: proc.stdout, output: proc.stdin });
|
|
195
|
+
}
|
|
196
|
+
const client = new LSPClient({
|
|
197
|
+
name: 'lspeasy-cli',
|
|
198
|
+
version: '0.1.0',
|
|
199
|
+
capabilities: CLIENT_CAPABILITIES,
|
|
200
|
+
rootUri,
|
|
201
|
+
workspaceFolders: [{ uri: rootUri, name: basename(rootDir) }],
|
|
202
|
+
initializationOptions: { languageId: this.opts.languageId },
|
|
203
|
+
// Keep stdout clean; route the SDK's own logging to stderr (or silence it).
|
|
204
|
+
logger: this.opts.verbose ? new StderrLogger() : new NullLogger()
|
|
205
|
+
});
|
|
206
|
+
this.client = client;
|
|
207
|
+
// Intercept server-pushed edits (tsserver's refactor.move applies this way).
|
|
208
|
+
// Queue every pushed edit in order — a server may send several sequential
|
|
209
|
+
// applyEdit requests for one command, and acking `applied:true` for an edit
|
|
210
|
+
// we then dropped would be a lie that loses changes.
|
|
211
|
+
client.onRequest('workspace/applyEdit', (params) => {
|
|
212
|
+
this.capturedEdits.push(params.edit);
|
|
213
|
+
return { applied: true };
|
|
214
|
+
});
|
|
215
|
+
await client.connect(transport);
|
|
216
|
+
this.log('connected (initialize/initialized handshake complete)');
|
|
217
|
+
}
|
|
218
|
+
/** Notify the server that an anchor file is open. */
|
|
219
|
+
async open(anchorFile) {
|
|
220
|
+
const client = this.requireClient();
|
|
221
|
+
await client.sendNotification('textDocument/didOpen', {
|
|
222
|
+
textDocument: {
|
|
223
|
+
uri: pathToFileURL(anchorFile).href,
|
|
224
|
+
languageId: this.opts.languageId,
|
|
225
|
+
version: 1,
|
|
226
|
+
text: readFileSync(anchorFile, 'utf8')
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
this.log(`didOpen ${anchorFile}`);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Run a request immediately and retry with exponential backoff while the
|
|
233
|
+
* server returns null (i.e. it is still indexing). Gives up after
|
|
234
|
+
* `indexWaitMs` total elapsed time and returns null.
|
|
235
|
+
*
|
|
236
|
+
* Initial retry delay: 250 ms, doubling each round, capped at 5 s per
|
|
237
|
+
* attempt. The first attempt is always immediate so fast servers pay no
|
|
238
|
+
* extra latency at all.
|
|
239
|
+
*/
|
|
240
|
+
async requestWithRetry(run) {
|
|
241
|
+
const deadline = Date.now() + this.opts.indexWaitMs;
|
|
242
|
+
let delay = 250;
|
|
243
|
+
while (true) {
|
|
244
|
+
const res = await run();
|
|
245
|
+
if (res !== null && res !== undefined)
|
|
246
|
+
return res;
|
|
247
|
+
const remaining = deadline - Date.now();
|
|
248
|
+
if (remaining <= 0)
|
|
249
|
+
return null;
|
|
250
|
+
const wait = Math.min(delay, remaining);
|
|
251
|
+
this.log(`null result — retrying in ${wait}ms (${remaining}ms remaining)`);
|
|
252
|
+
await sleep(wait);
|
|
253
|
+
delay = Math.min(delay * 2, 5000);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Drain ALL edits pushed by the server via `workspace/applyEdit` since the
|
|
258
|
+
* last drain, in arrival order. Returns an empty array if none were pushed.
|
|
259
|
+
* Callers apply them in order so a multi-applyEdit command is fully honored.
|
|
260
|
+
*/
|
|
261
|
+
takeCapturedEdits() {
|
|
262
|
+
return this.capturedEdits.drain();
|
|
263
|
+
}
|
|
264
|
+
get lsp() {
|
|
265
|
+
return this.requireClient();
|
|
266
|
+
}
|
|
267
|
+
get capabilities() {
|
|
268
|
+
return this.requireClient().getServerCapabilities() ?? {};
|
|
269
|
+
}
|
|
270
|
+
requireClient() {
|
|
271
|
+
if (!this.client)
|
|
272
|
+
throw new Error('Session not started — call start() first');
|
|
273
|
+
return this.client;
|
|
274
|
+
}
|
|
275
|
+
/** Shut down the client and kill the server process. */
|
|
276
|
+
async stop() {
|
|
277
|
+
try {
|
|
278
|
+
await this.client?.disconnect();
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
/* ignore shutdown races */
|
|
282
|
+
}
|
|
283
|
+
this.proc?.kill();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import type { GlobalFlags } from './io.js';
|
|
4
|
+
import type { RefactorSession } from './session.js';
|
|
5
|
+
import { type AppliedChange } from './apply.js';
|
|
6
|
+
export type ArgPattern = 'file-position-newname' | 'file-position' | 'file-range' | 'file' | 'query' | 'raw';
|
|
7
|
+
export declare function detectArgPattern(schema: z.ZodType<unknown>): ArgPattern;
|
|
8
|
+
export declare function marshalParams(pattern: ArgPattern, positional: string[], opts: Record<string, unknown>, flags: GlobalFlags): unknown;
|
|
9
|
+
export declare function printAppliedChanges(changes: AppliedChange[], method: string, dryRun: boolean, json: boolean): void;
|
|
10
|
+
export declare function zodToCommander(method: string, schema: z.ZodType<unknown>, session: RefactorSession, flags: GlobalFlags): Command;
|
|
11
|
+
//# sourceMappingURL=zod-to-commander.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-commander.d.ts","sourceRoot":"","sources":["../src/zod-to-commander.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,OAAO,EAIL,KAAK,aAAa,EAEnB,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,UAAU,GAClB,uBAAuB,GACvB,eAAe,GACf,YAAY,GACZ,MAAM,GACN,OAAO,GACP,KAAK,CAAC;AAsHV,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,UAAU,CAUvE;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,UAAU,EACnB,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,EAAE,WAAW,GACjB,OAAO,CAwCT;AA8BD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EAAE,EACxB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EACf,IAAI,EAAE,OAAO,GACZ,IAAI,CAeN;AAoBD,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAC1B,OAAO,EAAE,eAAe,EACxB,KAAK,EAAE,WAAW,GACjB,OAAO,CA4JT"}
|