JSON-RPC 2.0 implementation over WebSockets for Node.js and browser with bidirectional communication support
npx @tessl/cli install tessl/npm-rpc-websockets@10.0.0RPC WebSockets is a comprehensive JSON-RPC 2.0 implementation over WebSockets for Node.js and browser environments. It enables bidirectional real-time communication between clients and servers with support for RPC method calls, event subscriptions, and notifications.
npm install rpc-websocketsFor Node.js environments:
import { Client, Server, createError } from "rpc-websockets";For browser environments (Server and createError not available):
import { Client } from "rpc-websockets";CommonJS (Node.js):
const { Client, Server, createError } = require("rpc-websockets");import { Client } from "rpc-websockets";
// Create and connect to WebSocket RPC server
const client = new Client("ws://localhost:8080");
// Wait for connection
client.on("open", async () => {
// Call RPC method
const result = await client.call("sum", [5, 3]);
console.log(result); // 8
// Subscribe to events
await client.subscribe("feedUpdated");
client.on("feedUpdated", (data) => {
console.log("Feed updated:", data);
});
// Send notification
await client.notify("userAction", { action: "click", element: "button" });
});import { Server } from "rpc-websockets";
// Create WebSocket RPC server
const server = new Server({ port: 8080 });
// Register RPC methods
server.register("sum", (params) => {
return params[0] + params[1];
});
// Create and emit events
server.event("feedUpdated");
server.emit("feedUpdated", { timestamp: Date.now() });
// Register protected method requiring authentication
server.register("getSecretData", () => {
return { secret: "confidential data" };
}).protected();RPC WebSockets is built around several key components:
Full-featured JSON-RPC 2.0 client for both Node.js and browser environments with automatic reconnection, event subscriptions, and authentication support.
class Client extends CommonClient {
constructor(
address?: string,
options?: IWSClientAdditionalOptions & NodeWebSocketTypeOptions,
generate_request_id?: (method: string, params: object | Array<any>) => number | string
);
}
interface IWSClientAdditionalOptions {
autoconnect?: boolean;
reconnect?: boolean;
reconnect_interval?: number;
max_reconnects?: number;
}JSON-RPC 2.0 server implementation with method registration, event management, namespace support, and authentication middleware.
class Server extends EventEmitter {
wss: InstanceType<typeof WebSocketServer>;
constructor(
options: NodeWebSocket.ServerOptions,
dataPack?: DataPack<object, string>
);
register(
name: string,
fn: (params: IRPCMethodParams, socket_id: string) => void,
ns?: string
): IMethod;
event(name: string, ns?: string): IEvent;
}Pluggable data encoding and decoding system for custom serialization formats beyond the default JSON implementation.
interface DataPack<T, R extends string | ArrayBufferLike | Blob | ArrayBufferView> {
encode(value: T): R;
decode(value: R): T;
}
class DefaultDataPack implements DataPack<Object, string> {
encode(value: Object): string;
decode(value: string): Object;
}Standalone utility functions for error handling and JSON-RPC compliance. Note: Available in Node.js environments only.
/**
* Creates a JSON-RPC 2.0-compliant error
* @param code - JSON-RPC error code (e.g., -32700 for parse error, -32600 for invalid request)
* @param details - optional additional error details
* @returns JSON-RPC error object with code, message, and optional data
*/
function createError(code: number, details?: string): IRPCError;Usage Example:
import { createError } from "rpc-websockets";
// Create a custom error
const error = createError(-32001, "Custom application error");
// Result: { code: -32001, message: "Server error", data: "Custom application error" }
// Create a standard JSON-RPC error
const parseError = createError(-32700);
// Result: { code: -32700, message: "Parse error" }WebSocket factory functions for advanced use cases and custom implementations.
/**
* Node.js WebSocket factory function
* Creates WebSocket instances optimized for Node.js environments
*/
function WebSocket(address: string, options: IWSClientAdditionalOptions): ICommonWebSocket;Usage Example:
import { WebSocket, CommonClient } from "rpc-websockets";
// Create a custom client with the Node.js WebSocket factory
const customClient = new CommonClient(
WebSocket,
"ws://localhost:8080",
{ reconnect: false }
);Note: The browser build exports a different WebSocket factory optimized for browser environments. Most users should use the Client class directly instead of these factory functions.
interface IRPCMethodParams {
[x: string]: any;
}
interface IWSRequestParams {
[x: string]: any;
[x: number]: any;
}
interface IQueue {
[x: number | string]: IQueueElement;
}
interface IQueueElement {
promise: [
Parameters<ConstructorParameters<typeof Promise>[0]>[0],
Parameters<ConstructorParameters<typeof Promise>[0]>[1]
];
timeout?: ReturnType<typeof setTimeout>;
}
interface IMethod {
public(): void;
protected(): void;
}
interface IEvent {
public(): void;
protected(): void;
}
interface IRPCError {
code: number;
message: string;
data?: string;
}
interface ICommonWebSocket {
send: (
data: Parameters<BrowserWebSocketType["send"]>[0],
optionsOrCallback: ((error?: Error) => void) | Parameters<NodeWebSocketType["send"]>[1],
callback?: (error?: Error) => void
) => void;
close: (code?: number, reason?: string) => void;
addEventListener<K extends keyof WebSocketEventMap>(
type: K,
listener: (ev: WebSocketEventMap[K]) => any,
options?: boolean | AddEventListenerOptions
): void;
}
interface ICommonWebSocketFactory {
(address: string, options: IWSClientAdditionalOptions): ICommonWebSocket;
}
type NodeWebSocketTypeOptions = NodeWebSocket.ClientOptions;
type BrowserWebSocketType = InstanceType<typeof WebSocket>;
type NodeWebSocketType = InstanceType<typeof NodeWebSocket>;