actions/ws_endpoint_spec.ts

WsEndpointSpec — the canonical WebSocket endpoint declaration consumed by create_app_server's ws_endpoints option (mirror of RpcEndpointSpec for HTTP RPC).

Lives in its own module so both server/app_server.ts (which mounts endpoints from these specs) and http/surface.ts (which threads the resolved spec list into surface generation) can import it without a cycle between the two.

Declarations
#

view source

WsEndpointSpec
#

actions/ws_endpoint_spec.ts view source

WsEndpointSpec

Declarative description of a WebSocket endpoint to be auto-mounted by create_app_server.

Single source of truth for mount + surface — the same array drives register_ws_endpoint-style upgrade wiring AND the surface.ws_endpoints slot emitted into AppSurface, so consumers cannot drift their declared actions from what dispatch actually serves.

path

Hono mount path (e.g. /api/ws).

type string

allowed_origins

Origin allowlist regexes — typically parsed via parse_allowed_origins. Passed straight to verify_request_source on upgrade.

type ReadonlyArray<RegExp>

actions

The actions registered on this endpoint. Spread protocol_actions from actions/protocol.ts first to complete the disconnect-detection + per-request cancel pairing with the frontend client.

type ReadonlyArray<Action>

required_roles

Roles permitted to upgrade — any-of disjunction. Omit (or pass []) to skip the upgrade-time role gate; per-action auth on each spec still applies at dispatch time via perform_action. Pass [ROLE_ADMIN] for a zap-style admin-only WS endpoint.

type ReadonlyArray<RoleName>

transport

Existing transport to register connections with. Auto-created when omitted. Either way the mounted transport is reachable on AppServer.ws_endpoints[path] for broadcast / fan-out.

heartbeat

Server-side heartbeat policy. Default-on (60s receive-silence timeout). Set false only when an upstream stack (TCP keepalive, Cloudflare idle timeout) already owns disconnect detection.

type boolean | ServerHeartbeatOptions

artificial_delay

Optional per-message delay for testing loading states.

type number

on_socket_open

Called once per socket after transport.add_connection but before the first message dispatches. See RegisterActionWsOptions.on_socket_open.

type (ctx: SocketOpenContext) => void | Promise<void>

on_socket_close

Called once per socket on close, before transport.remove_connection. See RegisterActionWsOptions.on_socket_close.

type (ctx: SocketCloseContext) => void | Promise<void>

auth_guard

Default true — auto-composes create_ws_auth_guard + create_ws_logout_closer against this endpoint's transport and appends them to deps.audit.on_event_chain. Wiring is deduped by transport reference identity (WeakSet<BackendWebsocketTransport>), so two WsEndpointSpecs sharing the exact same instance get a single pair of listeners.

Shared-transport OR-semantics. When multiple WsEndpointSpecs share one transport, the guard is wired iff any of those specs has auth_guard !== false. To opt out for a shared transport, every sibling spec must pass auth_guard: false. The default is "fail safe" — easier to enable than disable, and predictable regardless of spec order.

Reference-identity dedupe means wrapped or proxied transports dedupe as separate entries — a consumer threading every transport through a tracing / DI / metrics shim will get a fresh pair of listeners per shimmed reference, even when the underlying transport is the same. If you wrap or proxy, set `auth_guard: false on the duplicate WsEndpointSpec`s and compose create_ws_auth_guard / create_ws_logout_closer against the underlying transport once.

Set false when a consumer needs to compose their own callback from scratch — or to opt out of the auto-wiring entirely.

NOTE: does NOT close sockets on role_grant_revoke — that omission is deliberate (per-connection role tracking is out of scope). A user whose admin role is revoked keeps their socket open; the next message gets forbidden from the per-message authorization phase. Consumers wanting role-revoke disconnection use extra_audit_handlers.

type boolean

extra_audit_handlers

Extra audit-event handlers appended to deps.audit.on_event_chain AFTER the standard auth_guard wiring (when enabled). By the time these run, the standard guards may have already closed sockets. Use for role-revoke disconnection, custom analytics, etc.

Never deduped — consumer-owned; pass the same handler twice and it fires twice.

type ReadonlyArray<AuditEventHandler>