actions/compile_action_registry.ts

Shared registration loop for action-dispatcher endpoints.

create_rpc_endpoint (HTTP RPC) and register_action_ws (WebSocket) both build a Map<method, RpcAction> from a list of action specs and gate the build on the same registry-time invariants:

  1. Auth-shape biconditional — per assert_route_auth_acting_biconditional in http/auth_shape.ts: `auth.actor !== 'none' ⟺ input declares acting?: ActingActor`. Fires for every spec with non-null auth.
  2. Rate-limit / account axisrate_limit: 'account' | 'both' requires auth.account === 'required'; without an account on the request there is no key for the per-account bucket.
  3. JSON-RPC §4.2 wire validityrequest_response specs whose handler will reach the dispatch map must not use z.null() for input (the wire format forbids "params": null; use z.void() for parameterless methods).
  4. Duplicate method names — JSON-RPC keys on method, so every spec in the array must declare a unique method regardless of kind / handler presence.

Pre-consolidation each dispatcher inlined these checks; the comment in actions/register_action_ws.ts literally said "mirrors the HTTP RPC registration check" but nothing kept them mirrored. Centralizing the loop closes the most likely future drift surface.

view source

Declarations
#

2 declarations

ActionRegistryCompileResult
#

actions/compile_action_registry.ts view source

ActionRegistryCompileResult import type {ActionRegistryCompileResult} from '@fuzdev/fuz_app/actions/compile_action_registry.js';

Result returned by compile_action_registry.

action_map

Method → RpcAction lookup for dispatch. Only request_response specs with a handler land here — kind-polymorphic input arrays (the WebSocket dispatcher's actions: ReadonlyArray<Action>) pass remote_notification / handler-less specs through unchanged.

type Map<string, RpcAction>

compile_action_registry
#

actions/compile_action_registry.ts view source

(actions: readonly Action<{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<...>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }>[], ctx_label: string): ActionRegistryCompileResult import {compile_action_registry} from '@fuzdev/fuz_app/actions/compile_action_registry.js';

Validate registry-time invariants and build the dispatcher's method → action lookup.

actions

polymorphic action array; HTTP RPC passes RpcAction[] (narrower), WebSocket passes Action[] (kind-polymorphic — handler-less notification specs are accepted)

type readonly Action<{ method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ....

ctx_label

per-spec error-message prefix, e.g. 'RPC action' or 'WS action'. Combined with the spec method as ${ctx_label} "${method}".

type string

returns

ActionRegistryCompileResult

throws

  • Error - on biconditional violation, rate-limit/account-axis mismatch, JSON-RPC null-input, or duplicate method.

Depends on
#

Imported by
#