@fainthit/reserve-client
v1.0.0
Published
JavaScript client for the reserve protocol. It works in browsers and Node.js.
Readme
@fainthit/reserve-client-js
JavaScript client for the reserve protocol. It works in browsers and Node.js.
Install
npm install @fainthit/reserve-client-jsBasic usage
import { ReserveClient } from "@fainthit/reserve-client-js";
const client = new ReserveClient({
url: "ws://localhost:3000",
name: "door-a",
});
client.on("connected", () => {
console.log("connected", client.token);
});
client.on("door.open", ({ duration }) => {
console.log("open door", duration);
});
client.send("device.ready", { ok: true });Node.js usage
Node.js 22+ usually has a global WebSocket. If your runtime does not, pass a
WebSocket implementation.
import WebSocket from "ws";
import { ReserveClient } from "@fainthit/reserve-client-js";
const client = new ReserveClient({
url: "ws://localhost:3000",
name: "device-a",
WebSocket,
});Constructor
new ReserveClient(options)Options:
{
url: string;
name?: string;
token?: string;
reconnectInterval?: number;
autoConnect?: boolean;
WebSocket?: WebSocketConstructor;
pingInterval?: number;
pingTimeout?: number;
retryInterval?: number;
}Defaults:
autoConnect = true
reconnectInterval = 1000
pingInterval = 10000
pingTimeout = 5000
retryInterval = 5000token is kept in memory only. The client updates client.token after
helloAck. Store it yourself only if your application needs that behavior.
Events
connected
client.on("connected", () => {});Emitted after the first successful helloAck.
reconnected
client.on("reconnected", () => {});Emitted after a later successful helloAck using the current in-memory token.
disconnected
client.on("disconnected", (reason) => {});Emitted when a connected socket closes, errors, or heartbeat times out. The
client automatically reconnects while opened is true.
helloAck
client.on("helloAck", (token) => {});Emitted whenever the server accepts the session.
error
client.on("error", (error) => {});Emitted when decoding, connection, or socket sending fails.
channel events
Incoming server messages are emitted by channel name.
client.on("game.start", (...data) => {});channel: null frames are sync fillers. They are ACKed but not emitted.
Methods
send
Send a reliable message to the server.
client.send(channel, ...data);Example:
client.send("sensor.trigger", { id: "button-a" });Aliases:
client.sendMessage(channel, ...data);
client.sendChannel(channel, ...data);connect
Open a connection manually.
const client = new ReserveClient({
url: "ws://localhost:3000",
autoConnect: false,
});
await client.connect();close
Close the client and stop automatic reconnect.
client.close();Public state
client.name?: string;
client.token?: string;
client.connected: boolean;
client.opened: boolean;
client.delay: number;delay is reserved for heartbeat latency tracking.
Reliability
Every msg frame has a 32-bit sequence key and must be ACKed. If no ACK arrives,
the client retries the same frame with the same key. Duplicate incoming messages
are ACKed again without re-emitting the channel event.
The dedupe window is 32 messages. If sync is lost, the client sends unsynced.
If the server sends reset, the client clears pending messages and restarts
sequence keys from 0.
