# @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](./src/adapters/native-adapter.md) — _(no submodules)_ - [native-adapter](./src/adapters/native-adapter.md) — _(no submodules)_ - [client](./src/core/client/client.md) — _(no submodules)_ - [client](./src/core/client/client.md) — _(no submodules)_ - [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_ - [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_ - [queue](./src/core/queue/queue.md) — _(no submodules)_ - [queue](./src/core/queue/queue.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_ - [plugin](./src/plugin/plugin.md) — _(no submodules)_ - [plugin](./src/plugin/plugin.md) — _(no submodules)_ - [transport](./src/transport/transport.md) — _(no submodules)_ - [transport](./src/transport/transport.md) — _(no submodules)_ - [types](./src/types/common.md) — _(no submodules)_ - [common](./src/types/common.md) — _(no submodules)_ - [error-codes](./src/error-codes.md) — Frozen error-code registry for the `@suaveplan/network-transport-websockets` package. Centralises every failure classif… - [native-adapter](./src/adapters/native-adapter.md) — _(no submodules)_- [client](./src/core/client/client.md) — _(no submodules)_- [client](./src/core/client/client.md) — _(no submodules)_- [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_- [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_- [queue](./src/core/queue/queue.md) — _(no submodules)_- [queue](./src/core/queue/queue.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_- [common](./src/types/common.md) — _(no submodules)_- [error-codes](./src/error-codes.md) — Frozen error-code registry for the `@suaveplan/network-transport-websockets` package. Centralises every failure classif… - [native-adapter](./src/adapters/native-adapter.md) — _(no submodules)_- [client](./src/core/client/client.md) — _(no submodules)_- [client](./src/core/client/client.md) — _(no submodules)_- [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_- [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_- [queue](./src/core/queue/queue.md) — _(no submodules)_- [queue](./src/core/queue/queue.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_- [common](./src/types/common.md) — _(no submodules)_- [error-codes](./src/error-codes.md) — Frozen error-code registry for the `@suaveplan/network-transport-websockets` package. Centralises every failure classif… - [native-adapter](./src/adapters/native-adapter.md) — _(no submodules)_- [client](./src/core/client/client.md) — _(no submodules)_- [client](./src/core/client/client.md) — _(no submodules)_- [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_- [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_- [queue](./src/core/queue/queue.md) — _(no submodules)_- [queue](./src/core/queue/queue.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_- [common](./src/types/common.md) — _(no submodules)_- [error-codes](./src/error-codes.md) — Frozen error-code registry for the `@suaveplan/network-transport-websockets` package. Centralises every failure classif… - [native-adapter](./src/adapters/native-adapter.md) — _(no submodules)_- [client](./src/core/client/client.md) — _(no submodules)_ - [client](./src/core/client/client.md) — _(no submodules)_- [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_ - [heartbeat](./src/core/heartbeat/heartbeat.md) — _(no submodules)_- [queue](./src/core/queue/queue.md) — _(no submodules)_ - [queue](./src/core/queue/queue.md) — _(no submodules)_- [otel](./src/otel/otel.md) — _(no submodules)_ - [otel](./src/otel/otel.md) — _(no submodules)_- [plugin](./src/plugin/plugin.md) — _(no submodules)_ - [plugin](./src/plugin/plugin.md) — _(no submodules)_- [transport](./src/transport/transport.md) — _(no submodules)_ - [transport](./src/transport/transport.md) — _(no submodules)_- [types](./src/types/common.md) — _(no submodules)_ - [common](./src/types/common.md) — _(no submodules)_- [error-codes](./src/error-codes.md) — Frozen error-code registry for the `@suaveplan/network-transport-websockets` package. 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:connected` and `websocket:disconnected` events - **AbortSignal support** — cancel `connect()` and `send()` via `AbortSignal` - **Structured errors** — all errors use `@suaveplan/error` with stable `WS.*` error codes ## Usage ### Basic Example ```ts 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 ```ts 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 lifecycle - `src/core/heartbeat/` — `createHeartbeat`, `HeartbeatController` - `src/core/queue/` — `MessageQueue`, bounded message queue - `src/adapters/` — `nativeWebSocketAdapter`, `WebSocketAdapter` contract - `src/types/` — `WebSocketClientOptions`, `WebSocketMessage`, `MessageMeta`, `Clock` - `src/error-codes.ts` — `WS_CODES` and `WsError` ## 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.