Files
pubsub/tasks/006-websocket-client-adapter.md
glm-5.1 1306716897 Decompose architecture into atomic, dependency-ordered tasks
19 tasks covering core testing, Redis hardening, WebSocket client/server
adapters, Worker adapter, and final review gates. Iroh adapters are tracked
as a deferred placeholder blocked on the @alkdev/iroh fork.

Phases: core validation → Redis hardening → review gate → WebSocket
adapters → review gate → Worker adapter → review gate → final validation.
2026-05-08 05:50:43 +00:00

56 lines
2.6 KiB
Markdown

---
id: websocket-client-adapter
name: Implement WebSocket client event target adapter
status: pending
depends_on: [review-core-and-redis]
scope: moderate
risk: medium
impact: component
level: implementation
---
## Description
Implement the `createWebSocketClientEventTarget` adapter as specified in `docs/architecture/event-targets/websocket-client.md`.
This is a symmetric (single-connection) adapter that wraps a `WebSocket` connection for the spoke/client side. It's bidirectional — can both send and receive events. It must implement subscription forwarding using `__subscribe`/`__unsubscribe` control events per ADR-003.
Key requirements from the architecture:
- Takes an already-connected `WebSocket` (caller handles connection lifecycle)
- `dispatchEvent``ws.send(JSON.stringify(event.detail))`
- `addEventListener` → register local listener + send `__subscribe` control event on first listener for topic
- `removeEventListener` → remove local listener + send `__unsubscribe` when no listeners remain
- Subscription reference counting: `__subscribe` sent only on first `addEventListener` per topic
- Malformed JSON from server → silently ignored, log warning
- Control events (`__subscribe`, `__unsubscribe`) received from server → silently ignored
- `ws.send()` failure → error propagates to caller, no retry
## Acceptance Criteria
- [ ] `src/event-target-websocket-client.ts` exists
- [ ] Implements `createWebSocketClientEventTarget(ws: WebSocket): TypedEventTarget<TEvent>`
- [ ] `dispatchEvent` serializes envelope and calls `ws.send()`
- [ ] `addEventListener` registers local listener and sends `__subscribe` on first listener for topic
- [ ] Subscription reference counting: only one `__subscribe` per topic regardless of listener count
- [ ] `removeEventListener` removes local listener and sends `__unsubscribe` when no listeners remain
- [ ] Malformed JSON messages from server are silently ignored (logged)
- [ ] Control events received from server are silently ignored
- [ ] `ws.onmessage` parses envelope, creates `CustomEvent` with `type:id` topic, dispatches to listeners
- [ ] `ws.send()` failure propagates to caller
- [ ] No comments in source code (project convention)
- [ ] Sub-path export added to `package.json` and `tsup.config.ts`
- [ ] Barrel re-export added to `src/index.ts`
## References
- docs/architecture/event-targets/websocket-client.md
- docs/architecture/decisions/003-subscription-control-protocol.md
- src/types.ts (TypedEventTarget, TypedEvent, EventEnvelope)
## Notes
> To be filled by implementation agent
## Summary
> To be filled on completion