actions/broadcast_api.ts view source
BroadcastApi Loose base shape for a broadcast API. Consumers typically declare a
stricter per-method interface (e.g. BackendActionsApi) and pin it via
the type parameter on create_broadcast_api.
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.
4 declarations
actions/broadcast_api.ts view source
BroadcastApi Loose base shape for a broadcast API. Consumers typically declare a
stricter per-method interface (e.g. BackendActionsApi) and pin it via
the type parameter on 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.
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.
optionsTApi actions/broadcast_api.ts view source
CreateBroadcastApiOptions Options for create_broadcast_api.
peerThe peer holding the transport registry used for sends.
specsNotification 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.
ReadonlyArray<ActionSpecUnion>logLogger for validation/send errors. Defaults to a [broadcast] namespace.
LoggerType | nullshould_deliverOptional 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.
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.