4.3 KiB
4.3 KiB
Tasks: enterprise-websocket-gateway
Change ID: enterprise-websocket-gateway
Package: @suaveplan/websocket-gateway
Target path: api/framework/websocket-gateway
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/logger, @suaveplan/events, @suaveplan/rate-limiter, @suaveplan/api
1. Scaffold
- Create
api/framework/websocket-gateway/with all subdirs per layout. package.jsonv0.0.0,"sideEffects": false, subpath exports.tsconfig.jsonextendinglibrary-node.json.vitest.config.tsviacreateTestConfig().- Scripts:
lint,typecheck,test,test:coverage,build,docs:check,bench.
2. Types and errors
src/types/common.ts— all interfaces and types listed in proposal.src/types/common.md(≥200 words, both examples).src/errors/ws-errors.ts— 6-code union, metadata,registerWsGatewayErrorCodes().ws-errors.test.tsandws-errors.md.
3. Connection
WsConnectionclass:id(UUID),userId,tenantId,topics: Set<string>, outboundsendQueue(bounded ring buffer of sizesendQueueSize).subscribe(topic)/unsubscribe(topic).send(message)— enqueue; drop oldest + incrementws.queue_drops_totalif full.close()— flush queue, callws.close().connection.test.ts: subscribe/unsubscribe, send queued, queue-full drops oldest, close flushes.connection.md.
4. Heartbeat
HeartbeatManager: sends ping everyheartbeatIntervalMs; schedulespingTimeoutMsdeadline per connection; on pong received, cancel deadline; on deadline exceeded, close connection.- Injectable
Clockfor testability. heartbeat.test.ts: pong received cancels deadline, deadline exceeded closes connection.heartbeat.md.
5. WS Router
WsRouter: registerson(type: string, handler: WsMessageHandler)handlers; routes inbound messages bymessage.type.WsMessageEnvelopeSchema(Zod) validates every inbound message; invalid →WsGatewayError(WS_INVALID_MESSAGE).ws-router.test.ts: known type routed, unknown type → error, invalid envelope → error.ws-router.md.
6. Gateway
createWebSocketGateway(options):- Maintains
connections: Map<string, WsConnection>. handleUpgrade(app, path)— registers Hono WebSocket route.- On connect: auth via
options.authenticate; max-connections check; createWsConnection; start heartbeat; emitws:connectedevent. - On message: rate-limit check; validate + route via
WsRouter. - On disconnect: remove from map; stop heartbeat; emit
ws:disconnectedevent. publish(topic, message)— fan out to all connections subscribed to topic.broadcast(message)— fan out to all connections.close()— close all connections gracefully.
- Maintains
- OTel:
ws.connections_activegauge updated on connect/disconnect; counters + histograms on message receive/send. gateway.test.ts(≤500 lines): connect + auth, auth failure closes ws, max-connections rejects, publish to topic, broadcast, rate-limited message dropped.gateway.md.
7. Hono adapter
createHonoWsAdapter(gateway: WebSocketGateway): (app: HonoApp, path: string) => void— wraps HonoupgradeWebSocket; bridges native ws events to gateway lifecycle.hono-ws-adapter.test.ts: upgrade handled, message forwarded.hono-ws-adapter.md.
8. Benchmarks (src/__benchmarks__/ws-gateway.bench.ts)
ws_message_routing: route 10 000 messages throughWsRouterwith 5 registered handlers.ws_publish_100_connections:publish()to a topic with 100 subscribers.
9. Integration tests (tests/integration.test.ts)
- Start a real Hono server + WebSocket gateway; connect N clients; send messages; assert routing + heartbeat + disconnect.
10. Docs and publish
- All co-located
.mdfiles (≥200 words, both examples, API reference). - Root
README.md. bunx turbo lint typecheck test --filter=@suaveplan/websocket-gateway— green.bunx turbo test:coverage --filter=@suaveplan/websocket-gateway— 100%.bun scripts/publish.ts --package @suaveplan/websocket-gateway.- Archive →
openspec/archive/2026-04-24-enterprise-websocket-gateway/.