connect

tcmts.cli.lsp.connect · #hzduggq2 · term · runs on the server

uses Buffer

Content-Length framed JSON-RPC over a pair of streams.

import type { Json, Message } from "#codebase/tcmts/cli/lsp";

export function connect(input: NodeJS.ReadableStream, output: NodeJS.WritableStream, onMessage: (m: Message) => void) {
  let buf = Buffer.alloc(0);
  input.on("data", (chunk: Buffer) => {
    buf = Buffer.concat([buf, chunk]);
    for (;;) {
      const sep = buf.indexOf("\r\n\r\n");
      if (sep < 0) return;
      const len = Number(/content-length:\s*(\d+)/i.exec(buf.subarray(0, sep).toString("ascii"))?.[1]);
      if (buf.length < sep + 4 + len) return;
      const body = buf.subarray(sep + 4, sep + 4 + len).toString("utf8");
      buf = buf.subarray(sep + 4 + len);
      onMessage(JSON.parse(body) as Message);
    }
  });
  return (m: Json) => {
    const body = Buffer.from(JSON.stringify({ jsonrpc: "2.0", ...m }), "utf8");
    output.write(`Content-Length: ${body.length}\r\n\r\n`);
    output.write(body);
  };
}

uses

used by