Skip to content

del-wang/echorpc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

26 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

EchoRPC

Bidirectional JSON-RPC 2.0 over WebSocket β€” TypeScript & Python.

Note: This project is under active development. APIs may change before v1.0.

# TypeScript
pnpm add echorpc

# Python
pip install echorpc

Features

  • Bidirectional RPC β€” server and client can call each other's methods
  • Pub/Sub β€” fire-and-forget notifications via publish / subscribe
  • Batch requests β€” multiple calls per frame, results returned in order
  • Auth β€” token validated during HTTP upgrade
  • Heartbeat β€” ping/pong with auto-disconnect on timeout
  • Auto-reconnect β€” exponential backoff, handlers and subscriptions preserved
  • Broadcast β€” send to all connections, filter by role, or exclude specific peers

Python

Server

from echorpc import EchoServer

server = EchoServer(port=9100, auth_handler=lambda p: p["token"] == "secret")

# Define a command that clients can call
@server.command("add")
def add(params):
    return {"sum": params["a"] + params["b"]}

# Listen for events from clients
@server.event("chat")
async def on_chat(data):
    print("on_chat", data)

await server.start()

Client

from echorpc import EchoClient

client = EchoClient("ws://localhost:9100", token="secret")

# Let the server call you back
client.register("double", lambda p: p["x"] * 2)

# Subscribe to events
client.subscribe("chat", lambda data: print(data))

await client.connect()

# Call a server command
result = await client.request("add", {"a": 1, "b": 2})

# Publish event to the server
await client.publish("chat", {"text": "hello"})

# Send multiple calls at once
results = await client.batch_request([
    ("add", {"a": 1, "b": 2}),
    ("add", {"a": 3, "b": 4}),
])

TypeScript

Server

import { EchoServer } from "echorpc";

const server = new EchoServer({
  port: 9100,
  authHandler: (p) => p.token === "secret",
});

// Define a command that clients can call
server.register("add", (p: { a: number; b: number }) => ({
  sum: p.a + p.b,
}));

// Listen for events from clients
server.subscribe("chat", async (data) => {
  console.log("chat", data);
});

await server.start();

Client (Node.js)

import WebSocket from "ws";
import { EchoClient } from "echorpc";

const client = new EchoClient("ws://localhost:9100", {
  token: "secret",
  WebSocket,
});

// Let the server call you back
client.register("double", (p) => p.x * 2);

// Subscribe to events
client.subscribe("chat", (data) => console.log(data));

await client.connect();

// Call a server command
const result = await client.request("add", { a: 1, b: 2 });

// Publish event to the server
client.publish("chat", { text: "hello" });

// Send multiple calls at once
const results = await client.batchRequest([
  ["add", { a: 1, b: 2 }],
  ["add", { a: 3, b: 4 }],
]);

Client (Browser)

No WebSocket import needed β€” uses the native one.

import { EchoClient } from "echorpc";

const client = new EchoClient("ws://localhost:9100", { token: "secret" });
await client.connect();

Error Codes

Code Name Meaning
-32700 Parse error Invalid JSON
-32601 Method not found No such method
-32603 Internal error Handler threw
-32001 Not connected No active connection
-32002 Timeout Request timed out
-32003 Auth failed Authentication rejected

License

MIT License Β© 2026-PRESENT Del Wang

About

🐚 Bidirectional JSON-RPC 2.0 over WebSocket β€” TypeScript & Python.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors