@rtcsvc/server
v1.1.14
Published
Node + browser SDK: register a service channel and answer client requests over WebRTC
Maintainers
Readme
@rtcsvc/server
Node + browser SDK for rtcsvc: register a service channel on the gateway and answer client requests over a peer-to-peer WebRTC DataChannel.
The gateway only authenticates and relays WebRTC signalling — request/response
traffic, pub/sub and broadcast flow peer-to-peer, encoded with
datapack. This server is the WebRTC
offerer and owns the RPC data channel. Servers also form an inter-server
mesh so pub/sub and broadcast fan out across every server of a service.
Install
npm install @rtcsvc/serverRuns in Node >= 20 and modern browsers (ES2022, WebSocket, RTCPeerConnection).
In Node, the optional peer dependencies ws and node-rtc-connection are used
for the WebSocket control plane and WebRTC data plane respectively. Install them
alongside this package:
npm install @rtcsvc/server ws node-rtc-connectionIn the browser, the native WebSocket and RTCPeerConnection APIs are used —
no additional dependencies are needed.
Usage
import { Event, Request, ServiceServer, Status } from "@rtcsvc/server";
import { STRING } from "datapack";
const server = new ServiceServer({
gatewayUrl: "wss://gateway.example.com/ws",
projectId: "proj_...", // from the admin console
secretKey: "sk_...", // the project's secret key
serviceName: "chat", // service name within the project (auto-created there if missing)
});
// Request/reply route — payload + response are datapack schemas.
server.use(
"echo",
{ text: STRING }, // request schema
{ text: STRING }, // response schema
(req, res) => {
res.send({ text: req.payload.text });
},
{ description: "Echo text back to the caller." },
);
// Pub/sub: declare an event type, optionally subscribe.
server.useEvent(
"chat",
{ text: STRING },
(payload, publisher) => {
console.log(`from ${publisher.id} (${publisher.role}):`, payload.text);
},
{ description: "Chat messages broadcast to subscribers." },
);
server.on("registered", (serviceName, connId) => console.log("registered", serviceName, connId));
await server.start();
// Fan out to topic subscribers across the mesh (data is packed per the
// schema registered with useEvent):
server.publish("chat", { text: "hello" });
// Fan out to every client of every server:
server.broadcast("chat", { text: "hello everyone" });Decorator-style handlers
You can also register request routes and event subscribers with Nest-style method decorators:
const ReqHello = { name: STRING } as const;
const ResHello = { text: STRING } as const;
const RoomEvent = { text: STRING } as const;
class HelloController {
@Request("hello", {
description: "abc",
requestSchema: ReqHello,
responseSchema: ResHello,
})
hello(req, res) {
res.send({ text: `hello ${req.payload.name}` });
}
@Event("room", {
description: "Room messages.",
payloadSchema: RoomEvent,
})
onRoom(payload, publisher) {
console.log(`from ${publisher.id}: ${payload.text}`);
}
}
server.registerController(new HelloController());Decorators store route metadata only; pass an already constructed controller
instance to registerController() so your own constructor dependencies work
normally. The decorator works with TypeScript 5 standard decorators and legacy
experimentalDecorators.
API
new ServiceServer(options)—{ gatewayUrl, projectId, secretKey, serviceName, reconnect?, webSocketHeaders?, debug? }. The server registersserviceNameinsideprojectId; the sameserviceNamemay exist in another project. In Node, the SDK sends browser-like WebSocket headers by default;webSocketHeaderscan override or extend them..use(type, requestSchema, responseSchema, handler, metadata?)— register a request route..registerController(instance)— register methods decorated with@Request(...)or@Event(...)..useEvent(type, payloadSchema, handlerOrMetadata?, metadata?)— register an event type (and optionally subscribe).metadatamay be a string or{ description }; descriptions are reflected by#schema..subscribe(topic, cb)/.unsubscribe(topic, cb?)— server-side topic subscription..publish(type, data)— publish to topic subscribers across the mesh (datapacked per the event schema)..broadcast(type, data)— deliver to every client of every server..sendTo(connId, payload)— directed message to a single connection..start()/.stop()— connect to / disconnect from the gateway..on(event, cb)— lifecycle events:registered,peer,connect,disconnect,error,close,reconnecting,reconnect,reconnectfailed.
Inside a handler, res.setStatus(code), res.setSession(patch) and
res.send(data) shape the reply; Status holds the common status codes.
License
MIT
