Files
pi-lsp/src/daemonClient.ts

73 lines
2.2 KiB
TypeScript

// Daemon Client - High-level helpers used by cli.ts and index.ts to send
// LSP work to the long-lived daemon. The first call autospawns the
// daemon; subsequent calls reuse it.
//
// Why Not One Persistent Socket - For now we open a fresh connection per
// request. The cost is negligible (Unix socket, same machine) compared to
// the LSP request itself, and it keeps client code stateless.
import {
buildLaunchContext,
sendOnce,
type DaemonResponse,
} from "./daemonProtocol.ts";
// Unwrap - Throws on { ok: false }, returns result on { ok: true }. All
// callers want the result-or-throw shape, so we centralize it.
function unwrap(resp: DaemonResponse): unknown {
if (resp.ok) return resp.result;
throw new Error(resp.error);
}
// Send LSP Request - Forwards an arbitrary LSP method to the daemon. The
// daemon injects textDocument.uri from `file`, so callers omit it.
export async function daemonRequest(
file: string,
method: string,
params: Record<string, unknown>,
): Promise<unknown> {
return unwrap(
await sendOnce({
op: "request",
file,
method,
params,
launch: buildLaunchContext(),
}),
);
}
// Wait For Diagnostics - Diagnostics arrive as a notification, not a
// response, so the daemon has a dedicated op that awaits the next publish.
export async function daemonDiagnostics(
file: string,
timeoutMs = 1500,
): Promise<unknown> {
return unwrap(
await sendOnce({
op: "diagnostics",
file,
timeoutMs,
launch: buildLaunchContext(),
}),
);
}
// Status - Lists currently-cached LSP servers (id, root, opened files,
// idle time). Useful for `pi-lsp daemon status`.
export async function daemonStatus(): Promise<unknown> {
return unwrap(await sendOnce({ op: "status" }));
}
// Shutdown - Asks the daemon to dispose all LspClients and exit.
export async function daemonShutdown(): Promise<unknown> {
return unwrap(await sendOnce({ op: "shutdown" }));
}
// Destroy Server - Kills running LspClient entries matching a server ID,
// or all entries if no ID is given. Entries can respawn on next request.
export async function daemonDestroyServer(
serverId?: string,
): Promise<unknown> {
return unwrap(await sendOnce({ op: "destroy_server", serverId }));
}