actions/broadcast_api.ts

Backend-initiated broadcast notification plumbing — generic across consumers.

Builds a typed {method_name: (input) => Promise<void>} object from a list of action specs. Each call validates input against the spec, wraps it in a JSON-RPC notification, and either broadcasts to every connection or fans out with a per-connection ACL predicate.

Counterpart to register_action_ws: that handles request-scoped dispatch (frontend-initiated), this handles broadcast (backend-initiated). Together they cover the two primitives fuz_app consumers share. Request-scoped streaming (completion_progress, tx_apply events) stays on ctx.notify inside a handler — it's socket-scoped, not broadcast.

Extracted from zzz's backend_actions_api.ts to stop the pattern from drifting across zzz, tx, and undying.

Declarations
#

4 declarations

view source

BroadcastApi
#

create_broadcast_api
#

actions/broadcast_api.ts view source

<TApi extends object>(options: CreateBroadcastApiOptions): TApi

Builds a typed broadcast API from a set of action specs.

For each spec, adds a method keyed by spec.method that: - Validates input against the spec's Zod schema (logs and returns on failure) - Creates a JSON-RPC notification from the validated input - Broadcasts via the peer (filtered by should_deliver when supplied)

Silently returns when no transport is ready (e.g. before any clients connect). Errors during send are logged but never thrown — broadcasts are fire-and-forget from the handler's perspective.

Typed consumer surface

Consumers declare an explicit interface and pin it via the type parameter:

export interface BackendActionsApi { filer_change: (input: ActionInputs['filer_change']) => Promise<void>; workspace_changed: (input: ActionInputs['workspace_changed']) => Promise<void>; } const api = create_broadcast_api<BackendActionsApi>({ peer: backend.peer, specs: [filer_change_action_spec, workspace_changed_action_spec], });

The cast is unchecked — callers must keep the interface and the specs array in sync. Codegen (action_collections.gen.ts) is a natural fit if the consumer already generates per-method type maps.

options

returns

TApi

CreateBroadcastApiOptions
#

actions/broadcast_api.ts view source

CreateBroadcastApiOptions

peer

The peer holding the transport registry used for sends.

specs

Notification specs to expose as broadcast methods. Typically the remote_notification specs whose initiator is backend (or both). Other kinds are accepted — the helper only uses spec.method and spec.input — but the typical use is notifications.

type ReadonlyArray<ActionSpecUnion>

log

Logger for validation/send errors. Defaults to a [broadcast] namespace.

type LoggerType | null

should_deliver

Optional per-connection ACL predicate. When set, the broadcast fans out via the transport's broadcast_filtered (feature-detected) — each connection's identity is checked before the message is sent. When unset, the transport broadcasts unfiltered via transport.send.

Requires a transport that implements FilterableBroadcastTransport (today: only BackendWebsocketTransport). If set and the active transport is not filterable, the send is skipped and an error logged.

ShouldDeliverFn
#

actions/broadcast_api.ts view source

ShouldDeliverFn

Per-connection delivery predicate for subscription ACLs.

Called once per connection for every broadcast send. Returning false skips that connection. Keep it fast — this runs in the broadcast hot path.

input is the already-validated payload (matches the spec's input schema); method is the action method name.

Depends on
#

Imported by
#