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).
stringallowed_origins
Origin allowlist regexes — typically parsed via parse_allowed_origins. Passed straight to verify_request_source on upgrade.
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.
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.
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.
boolean | ServerHeartbeatOptionsartificial_delay
Optional per-message delay for testing loading states.
numberon_socket_open
Called once per socket after transport.add_connection but before
the first message dispatches. See
RegisterActionWsOptions.on_socket_open.
(ctx: SocketOpenContext) => void | Promise<void>on_socket_close
Called once per socket on close, before transport.remove_connection.
See RegisterActionWsOptions.on_socket_close.
(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.
booleanextra_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.
ReadonlyArray<AuditEventHandler>