2.3 KiB
Gateway lifecycle helpers
Purpose
Centralises three pieces of lifecycle plumbing the daemon needs but doesn't want inline: WS-server boot, start-completion accounting (OTel histogram + bus event), and the per-connection auth handshake. Splitting these out of gateway.ts keeps the daemon file under the 300-line cap and makes each phase independently unit-testable.
Features
bootWsServer(resolved, callbacks, signal)— calls the injected factory, invokesstart(), and translates every failure into a typedWsGatewayError(START_FAILED)with the original cause attached. Always best-effort-stops the (possibly-partially-created) server before rethrowing.recordStartCompleted(resolved, address, port, startedAt, t0, emit)— records the start-duration histogram and emits the typedws_gateway:startedevent.runAuthHandshake(resolved, socketId, handshake, now)— runs the injectedauthVerifier, normalises the resulting auth context (handles missing client-ids), audits both outcomes, raisesAUTH_REJECTEDon failure.
Usage: Basic Example
import { bootWsServer } from "@suaveplan/websocket-gateway";
const { server, address, port } = await bootWsServer(resolved, callbacks, signal);
Usage: Advanced Example
import { runAuthHandshake } from "@suaveplan/websocket-gateway";
try {
const ctx = await runAuthHandshake(resolved, socketId, handshake, Date.now());
// ctx.clientId guaranteed to be non-empty
} catch (err) {
// err is a WsGatewayError(AUTH_REJECTED); audit log has already received
// the "denied" record.
}
API Reference
bootWsServer(resolved, callbacks, signal): Promise<{server, address, port}>recordStartCompleted(resolved, address, port, startedAt, t0, emit): voidrunAuthHandshake(resolved, socketId, handshake, now): Promise<AuthContext>
Implementation Notes
bootWsServer always awaits server?.stop() before rethrowing because the WS factory may throw mid-start() after attaching internal state — letting that state leak would prevent a retry. runAuthHandshake defaults a missing ctx.clientId to the socket id so consumers that adopt async auth don't need to invent ids twice. Auditing fires on both branches because the audit log is the source of truth for "did this handshake even reach us" alerts.