--- status: draft last_updated: 2026-05-07 --- # WebSocket Client Event Target **Import**: `@alkdev/pubsub/event-target-websocket-client` **Peer dep**: none (WebSocket is a web standard) **Status**: Not yet implemented. Wraps a single `WebSocket` connection for the client (spoke) side. Bidirectional — can both send and receive events. ## `createWebSocketClientEventTarget` ```ts function createWebSocketClientEventTarget( ws: WebSocket, ): TypedEventTarget; ``` Takes an already-connected `WebSocket`. The caller is responsible for connection lifecycle (including reconnection — see below). ## Protocol WebSocket provides native message boundaries (no length-prefix needed). Each message is a JSON-serialized `EventEnvelope`: ```json { "type": "call.responded", "id": "uuid-123", "payload": { "output": 42 } } ``` ### Sending (dispatchEvent) ```ts dispatchEvent(event) { this.ws.send(JSON.stringify(event.detail)); // event.detail is the EventEnvelope { type, id, payload } return true; } ``` ### Receiving (addEventListener) ```ts ws.onmessage = (msg) => { const envelope = JSON.parse(msg.data); const topic = `${envelope.type}:${envelope.id}`; const event = new CustomEvent(topic, { detail: envelope }); // dispatch to local listeners }; ``` ## Key Properties - **Bidirectional** — `dispatchEvent` sends over WS, `addEventListener` receives from WS - **Per-connection** — one event target per WebSocket connection - **JSON framing** — WebSocket provides native message boundaries - **No native deps** — works in browsers and Node - **Envelope serialization** — sends/receives the full `EventEnvelope` JSON ## Reconnection WebSocket connections drop. On reconnect, the spoke must create a new `WebSocket` and a new `WebSocketClientEventTarget`. Reconnection logic belongs to the spoke lifecycle, not the event target. The event target itself is per-connection. A new connection means a new instance. ## Test Plan 1. **Send path** — dispatchEvent serializes envelope and calls ws.send 2. **Receive path** — ws.onmessage parses envelope, creates CustomEvent, dispatches to listeners 3. **Topic scoping** — type:id topics correctly formed from envelope 4. **Connection close** — ws.onclose propagates to listeners (error event?) 5. **Multiple listeners** — multiple addEventListener on same topic