@suaveplan/network-transport-websockets - WebSocket client utilities: typed message framing, connection lifecycle, heartbeat, backpressure queue, and injectable transport adapters
Summary
WebSocket client utilities with typed message framing, connection lifecycle management, heartbeat, backpressure queue, and injectable transport adapters.
Documentation tree
- adapters — (no submodules)
- native-adapter — (no submodules)
- client — (no submodules)
- client — (no submodules)
- heartbeat — (no submodules)
- heartbeat — (no submodules)
- queue — (no submodules)
- queue — (no submodules)
- otel — (no submodules)
- otel — (no submodules)
- plugin — (no submodules)
- plugin — (no submodules)
- transport — (no submodules)
- transport — (no submodules)
- types — (no submodules)
- common — (no submodules)
- error-codes — Frozen error-code registry for the
@suaveplan/network-transport-websocketspackage. Centralises every failure classif…
- native-adapter — (no submodules)- client — (no submodules)- client — (no submodules)- heartbeat — (no submodules)- heartbeat — (no submodules)- queue — (no submodules)- queue — (no submodules)- otel — (no submodules)- otel — (no submodules)- plugin — (no submodules)- plugin — (no submodules)- transport — (no submodules)- transport — (no submodules)- types — (no submodules)- common — (no submodules)- error-codes — Frozen error-code registry for the
@suaveplan/network-transport-websocketspackage. Centralises every failure classif… - native-adapter — (no submodules)- client — (no submodules)- client — (no submodules)- heartbeat — (no submodules)- heartbeat — (no submodules)- queue — (no submodules)- queue — (no submodules)- otel — (no submodules)- otel — (no submodules)- plugin — (no submodules)- plugin — (no submodules)- transport — (no submodules)- transport — (no submodules)- types — (no submodules)- common — (no submodules)- error-codes — Frozen error-code registry for the
@suaveplan/network-transport-websocketspackage. Centralises every failure classif… - native-adapter — (no submodules)- client — (no submodules) - client — (no submodules)- heartbeat — (no submodules) - heartbeat — (no submodules)- queue — (no submodules) - queue — (no submodules)- otel — (no submodules) - otel — (no submodules)- plugin — (no submodules) - plugin — (no submodules)- transport — (no submodules) - transport — (no submodules)- types — (no submodules) - common — (no submodules)- error-codes — Frozen error-code registry for the
@suaveplan/network-transport-websocketspackage. Centralises every failure classif…
Purpose
@suaveplan/network-transport-websockets provides a robust, enterprise-grade WebSocket client for browser and Node.js environments. It handles connection establishment, automatic reconnection with exponential backoff, heartbeat/ping-pong keepalive, a bounded message queue for backpressure, and channel-based message multiplexing over a single WebSocket connection. All timing is injectable via a Clock interface for deterministic testing.
Features
- Connection lifecycle — connect, disconnect, and state tracking (
disconnected|connecting|connected|reconnecting|closed) - Automatic reconnect — configurable exponential backoff with max attempts and capped delay
- Heartbeat — configurable ping interval and pong timeout; disconnects on missed pong
- Message queue — bounded queue that drops oldest messages when full, with rejections for dropped items
- Channel multiplexing — subscribe to named channels and receive typed messages
- Injectable adapter — swap the native WebSocket transport for custom implementations (tests, mocks, alternate runtimes)
- Injectable clock — drive timers deterministically in tests using
FakeClock - Event bus integration — emits
websocket:connectedandwebsocket:disconnectedevents - AbortSignal support — cancel
connect()andsend()viaAbortSignal - Structured errors — all errors use
@suaveplan/errorwith stableWS.*error codes
Usage
Basic Example
import { createWebSocketClient } from "@suaveplan/network-transport-websockets";
const client = createWebSocketClient({
url: "wss://example.com/socket",
heartbeat: { enabled: true, intervalMs: 30000, timeoutMs: 10000 },
reconnect: { enabled: true, maxAttempts: 5, initialDelayMs: 1000, maxDelayMs: 30000 },
});
await client.connect();
client.subscribe("chat", (msg, meta) => {
console.log(`[${meta.channel}] ${msg}`);
});
await client.send({ type: "chat", channel: "chat", payload: { text: "hello" } });
client.disconnect();
Advanced Example
import { createWebSocketClient } from "@suaveplan/network-transport-websockets";
const client = createWebSocketClient({
url: "wss://example.com/socket",
clock: fakeClock, // injectable for tests
adapter: customAdapter, // custom WebSocket transport
eventBus: appEventBus, // emit connection events
maxQueueSize: 100,
serialization: "json",
});
client.on("connect", () => console.log("connected"));
client.on("disconnect", ({ code, reason }) => console.log("disconnected", code, reason));
client.on("reconnect", ({ attempt }) => console.log("reconnecting, attempt", attempt));
const ctrl = new AbortController();
await client.connect(ctrl.signal);
// Send with abort support
await client.send({ type: "ping", payload: null }, ctrl.signal);
API Reference
See the per-module documentation in src/:
src/core/client/—createWebSocketClient,WebSocketClient, connection lifecyclesrc/core/heartbeat/—createHeartbeat,HeartbeatControllersrc/core/queue/—MessageQueue, bounded message queuesrc/adapters/—nativeWebSocketAdapter,WebSocketAdaptercontractsrc/types/—WebSocketClientOptions,WebSocketMessage,MessageMeta,Clocksrc/error-codes.ts—WS_CODESandWsError
Implementation Notes
The client uses private fields for all internal state and exposes a minimal public API. The native adapter wraps the global WebSocket with safe close() handling for reserved close codes. The heartbeat controller is fully decoupled from the client and can be tested in isolation. All timer-based behavior uses an injectable Clock so tests can advance time deterministically without real waits.