Skip to content

ridit-jangra/Relay

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@ridit/relay

One port. Any language. Monaco-ready LSP bridge.

@ridit/relay multiplexes any number of language servers over a single WebSocket port using path-based routing. Drop it into any Monaco editor project and get completions, hover, diagnostics, go-to-definition, references, signature help, formatting, and code lenses — wired automatically.

ws://127.0.0.1:9721/python      → pylsp / pyright
ws://127.0.0.1:9721/typescript  → typescript-language-server
ws://127.0.0.1:9721/rust        → rust-analyzer

Why

The standard approach to Monaco + LSP is monaco-languageclient — but it pulls in vscode-languageclient and the full VSCode extension host model just to wire up completions. That's hundreds of kilobytes of VSCode abstractions built for a different runtime, bolted onto Monaco as an afterthought.

Relay uses only the primitives it actually needs — vscode-ws-jsonrpc for WebSocket framing and vscode-languageserver-protocol for LSP message types — then talks directly to Monaco's provider APIs. No extension host, no VSCode shims, no adapter layers.

It was extracted from Meridia — a from-scratch code editor — where we needed LSP that fit the stack instead of fighting it. If you're building an editor or any Monaco-based tool, relay gives you full LSP integration without the overhead.


Install

npm install @ridit/relay
# or
bun add @ridit/relay

Monaco is a peer dependency — install it separately if you haven't:

npm install monaco-editor

Usage

Server (Node / Bun)

import { Server } from "@ridit/relay";

const server = new Server();

server.register({
  command: "pyright-langserver",
  args: ["--stdio"],
  languageId: "python",
});

server.register({
  command: "typescript-language-server",
  args: ["--stdio"],
  languageId: "typescript",
});

await server.start(9721);

Client (Browser)

import * as monaco from "monaco-editor";
import { Client } from "@ridit/relay";

const editor = monaco.editor.create(document.getElementById("app")!, {
  automaticLayout: true,
});

const model = monaco.editor.createModel(
  "print('hello')",
  "python",
  monaco.Uri.file("/workspace/main.py"), // real path required
);

editor.setModel(model);

const client = new Client(monaco);
client.register({ languageId: "python" });
await client.start("/workspace");

Windows: pass the workspace path with backslashes — "C:\\workspace".


What gets wired automatically

Once client.start() is called, relay registers the following Monaco providers for each language:

Feature Provider
Completions registerCompletionItemProvider
Hover registerHoverProvider
Diagnostics setModelMarkers via publishDiagnostics
Go to Definition registerDefinitionProvider
Find References registerReferenceProvider
Signature Help registerSignatureHelpProvider
Formatting registerDocumentFormattingEditProvider
Code Lenses registerCodeLensProvider (with usage counts)

API

new Server()

server.register(def: LspServerDefinition): this
server.start(port?: number): Promise<void>   // default: 9721

LspServerDefinition

{
  command: string;       // binary name or full path
  languageId: string;    // e.g. "python", "typescript"
  args?: string[];       // e.g. ["--stdio"]
  cwd?: string;          // working directory override
}

new Client(monaco)

client.register(def: LspClientDefinition): this
client.start(workspacePath?: string, port?: number): Promise<void>
client.format_model(model: monaco.editor.ITextModel): Promise<boolean>
client.updateWorkspaceRoot(folderPath: string): Promise<void>
client.dispose(): Promise<void>

LspClientDefinition

{
  languageId: string;     // must match server registration
  extensions?: string[];  // file extensions to match, e.g. ["py", "pyw"]
}

Windows notes

On Windows, npm-installed language servers are .cmd wrappers. Relay resolves these automatically — pass the bare binary name and it will find the right executable:

server.register({
  command: "pyright-langserver",
  languageId: "python",
  args: ["--stdio"],
});

License

MIT

About

One port. Any language. Monaco-ready LSP bridge.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors