actions/action_codegen.ts

Declarations
#

31 declarations

view source

ACTION_METHOD_ENUM_KINDS_ALL
#

ActionMethodEnumKind
#

compose_gen_file
#

actions/action_codegen.ts view source

(input: { origin_path: string; imports: ImportBuilder; blocks: readonly string[]; }): string

Wrap the per-*.gen.ts boilerplate (banner + imports.build() + blocks join + template literal) into one call. Returns the full file body as a string ready to return from a Gen function.

Each consumer producer collapses to one compose_gen_file call wrapping the helper invocations.

input

type { origin_path: string; imports: ImportBuilder; blocks: readonly string[]; }

returns

string

examples

export const gen: Gen = ({origin_path}) => { const imports = new ImportBuilder(); return compose_gen_file({ origin_path, imports, blocks: [ generate_action_specs_record(all_action_specs, imports), generate_action_inputs_outputs(all_action_specs, imports), generate_action_event_datas(all_action_specs, imports), ], }); };

Empty blocks ('') are filtered out so helpers that short-circuit on empty spec sets don't introduce stray double blank lines.

create_banner
#

create_namespace_qualifier
#

actions/action_codegen.ts view source

(sources: readonly SpecSource[], imports: ImportBuilder): { qualify_spec: (spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; ... 8 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string; all_specs: readonly ({ ...; } | ... 1 more ... | { ...; })[]; }

Multi-source consumer helper. Takes a list of {ns, module, specs} rows, registers import * as ns from module for each on imports, builds the method_to_ns lookup with duplicate-method detection, and returns {qualify_spec, all_specs} ready to thread through the high-level helpers.

Closes the per-file boilerplate gap that kept tx + visiones on hand-rolled template strings even after qualify_spec? landed in API review II — the per-call callback wasn't enough; the import dance + dup-check was the real boilerplate.

sources

type readonly SpecSource[]

imports

returns

{ qualify_spec: (spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; output: ZodType<...>; ... 6 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string; all_specs: rea...

throws

  • Error - if two sources contain the same method name (same-method

examples

const sources = [ {ns: 'tx_specs', module: './action_specs.js', specs: all_tx_action_specs}, {ns: 'admin_specs', module: '@fuzdev/fuz_app/auth/admin_action_specs.js', specs: all_admin_action_specs}, ]; export const gen: Gen = ({origin_path}) => { const imports = new ImportBuilder(); const {qualify_spec, all_specs} = create_namespace_qualifier(sources, imports); return compose_gen_file({ origin_path, imports, blocks: [ generate_action_specs_record(all_specs, imports, {qualify_spec}), generate_action_inputs_outputs(all_specs, imports, {qualify_spec}), ], }); };

DEFAULT_COLLECTIONS_PATH
#

DEFAULT_METATYPES_PATH
#

DEFAULT_SPECS_MODULE
#

generate_action_event_datas
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the ActionEventDatas interface — one ActionEvent*Data variant per method, parameterized by the spec's kind: - request_responseActionEventRequestResponseData<method, input, output> - remote_notificationActionEventRemoteNotificationData<method, input> - local_callActionEventLocalCallData<method, input, output>

Adds the per-kind data type imports (only the kinds that appear in specs).

specs

type readonly ({ 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; } | { ...; } ...

imports

options?

type { same_file?: boolean | undefined; collections_path?: string | undefined; include_protocol_actions?: boolean | undefined; } | undefined
optional

returns

string

generate_action_inputs_outputs
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit ActionInputs + ActionOutputs runtime consts and matching interfaces. The runtime consts reference specs.{method}_action_spec.input / .output; the interfaces use z.infer.

Adds import {z} from 'zod'; and the * as specs namespace import.

specs

type readonly ({ 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; } | { ...; } ...

imports

options?

type { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string)...
optional

returns

string

generate_action_method_enum_block
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options: { ...; }): string

Emit a single named z.enum([...]) + z.infer block for an arbitrary spec subset. Lower-level escape hatch from generate_action_method_enums — for cross-product or domain-specific enums the built-in discriminator doesn't cover.

Mirrors the built-in helper's contract: protocol actions filtered by default, empty subsets return '' (skip rather than emit z.enum([])), zod import registered idempotently only when at least one method qualifies.

The cross-product space is open-ended; rather than grow the ActionMethodEnumKind discriminator one cross-product at a time, callers own the subset shape — name, jsdoc, predicate.

specs

type readonly ({ 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; } | { ...; } ...

imports

options

type { name: string; jsdoc: string; predicate: (spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => boolean; include_p...

returns

string

generate_action_method_enums
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit one or more z.enum([...]) declarations for action method names — ActionMethod, RequestResponseActionMethod, RemoteNotificationActionMethod, LocalCallActionMethod, FrontendActionMethod, BackendActionMethod, FrontendRequestResponseMethod, BackendRequestResponseMethod, BroadcastActionMethod. Pairs each runtime const with a z.infer type alias under the same identifier.

Protocol-action methods (heartbeat, cancel) are filtered out by default — pass include_protocol_actions: true if a consumer genuinely wants them on their typed surface. Empty kinds are skipped so the helper never emits z.enum([]) (zod runtime-throws on that).

Adds import {z} from 'zod'; to imports only when at least one block is emitted (idempotent).

For genuinely cross-product enums the discriminator doesn't cover, use generate_action_method_enum_block — caller owns the predicate, name, and jsdoc.

specs

type readonly ({ 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; } | { ...; } ...

imports

options?

type { emit?: ReadonlySet<ActionMethodEnumKind> | undefined; include_protocol_actions?: boolean | undefined; } | undefined
optional

returns

string

generate_action_specs_record
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the ActionSpecs runtime const + interface + the `action_specs: Array<ActionSpecUnion> value bundling every spec. Adds the * as specs` namespace import + the ActionSpecUnion type import.

specs

type readonly ({ 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; } | { ...; } ...

imports

options?

type { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string)...
optional

returns

string

generate_actions_api_method_signature
#

actions/action_codegen.ts view source

(spec: { 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; } | { ...; } | { ...; }, imports: ImportBuilder, options?: { ...; } | undefined): string

Generates one method line of the typed FrontendActionsApi interface for a single spec. Encapsulates the input/options/return-type signature shape so the surface evolves in one place when fields like signal or transport_name are added to per-call options.

Async methods (request_response, remote_notification, async local_call) get an optional second options?: RpcClientCallOptions arg ({signal?, transport_name?, queue?}) and a Promise<Result<...>> return type. Sync local_call methods omit the options arg — signal can't cooperatively interrupt a synchronous handler and there's no transport to select. remote_notification is async because create_remote_notification_method returns a Promise that resolves to a Result<{value: void}> (success) or Result<{error}> (transport send failure). Earlier emit shapes declared notifications as => void — regenerate consumer typed clients to pick up the corrected return.

Registers exactly the imports the emitted line references on imports: ActionInputs (when the spec has input), ActionOutputs (always), RpcClientCallOptions (async only), and Result + JsonrpcErrorObject (any return shape that wraps the value in Result<{value}, {error}> — every async method, plus sync local_call when `sync_returns_value: false). Mirrors the leaf-level pattern get_handler_return_type` already follows so wrappers no longer pre-register imports a per-spec emit might not actually use.

Optional-input detection. The emitted parameter is input?: (caller may omit the argument) when either (a) the schema accepts undefinedz.optional(z.strictObject(...)) and similar wrappers — or (b) the schema accepts the empty object {} — `z.strictObject({acting: ActingActor})` and other all-optional-fields strict objects. The second probe mirrors the dispatcher's HTTP convention (raw_params ?? {} for non-z.void() schemas in actions/action_rpc.ts / http/route_spec.ts): if a request with no params reaches the handler, this is the value the schema is asked to validate. A schema with required fields fails both probes and stays input: (required at the typed surface). Refinements and transforms run as part of safeParse, so their accept/reject decisions feed into the optional/required choice naturally.

spec

type { 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; } | { ...; } | { ...; }

imports

options?

type { sync_returns_value?: boolean | undefined; collections_path?: string | undefined; } | undefined
optional

returns

string

one line like foo: (input: ActionInputs['foo'], options?: RpcClientCallOptions) => Promise<Result<...>>;

generate_backend_action_handlers_map
#

actions/action_codegen.ts view source

(imports: ImportBuilder, options?: { type_name?: string | undefined; method_enum_name?: string | undefined; context_type?: string | undefined; collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined): string

Emit the BackendActionHandlers mapped type — one entry per BackendRequestResponseMethod, each (input, ctx) => output | Promise<output>. Replaces the hand-maintained Exclude<> + parallel mapped-type pattern (zzz had this at zzz/src/lib/server/zzz_action_handlers.ts:42-66).

The context type is consumer-defined (e.g. zzz's ZzzHandlerContext). Pass context_type to name it; the helper assumes it's importable or defined in the emitted module's scope (consumer's responsibility).

Adds ActionInputs / ActionOutputs type imports from collections_path and the BackendRequestResponseMethod import from metatypes_path.

imports

options?

type { type_name?: string | undefined; method_enum_name?: string | undefined; context_type?: string | undefined; collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined
optional

returns

string

generate_backend_actions_api
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit BOTH the typed BackendActionsApi interface AND the broadcast_action_specs runtime array. The interface is shaped for create_broadcast_api: backend-initiated remote_notification methods, each (input) => Promise<void>. The array bundles the matching specs as a ReadonlyArray<ActionSpecUnion>.

Filter: kind === 'remote_notification' && initiator !== 'frontend', additionally excluding methods that are the target of another spec's streams field. Streams targets (e.g. completion_progress, ollama_progress) are request-scoped notifications invoked via ctx.notify inside their parent handler — they're never callable through the broadcast API. The discriminator is ActionSpec.streams, not a manual exclusion list.

Adds the * as specs namespace import (from specs_module), the ActionInputs type import (from collections_path), and the ActionSpecUnion type import.

Method signature shape today is (input) => Promise<void> — matches the fire-and-forget runtime of create_broadcast_api. Generalizing per-kind via generate_actions_api_method_signature is deferred until a second backend runtime constructor lands.

specs

type readonly ({ 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; } | { ...; } ...

imports

options?

type { specs_module?: string | undefined; collections_path?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; ... 8 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string) | undefined; include_protocol_a...
optional

returns

string

generate_frontend_action_handlers
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the FrontendActionHandlers interface — wraps generate_phase_handlers with the TypedActionEvent action-event type and standard 1-tab per-method indentation. Pairs with generate_typed_action_event_alias (emits the matching TypedActionEvent alias) — call both in the same gen producer.

specs

type readonly ({ 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; } | { ...; } ...

imports

options?

type { collections_path?: string | undefined; include_protocol_actions?: boolean | undefined; } | undefined
optional

returns

string

generate_frontend_actions_api
#

actions/action_codegen.ts view source

(specs: readonly ({ 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; } | { ...; } | { ...; })[], imports: ImportBuilder, options?: { ...; } | undefined): string

Emit the FrontendActionsApi interface — one method signature per spec via generate_actions_api_method_signature. Optionally filter the spec set (e.g. omit additional methods alongside the default protocol-action filter) via method_filter.

Imports are registered by the leaf generate_actions_api_method_signature per emitted line — only what the spec set actually references shows up on imports. A spec set with no async methods skips RpcClientCallOptions; one with no inputs skips ActionInputs; sync local_call methods with sync_returns_value: true (the default) skip Result / JsonrpcErrorObject.

The interface name is fixed at FrontendActionsApi — the symmetric counterpart of BackendActionsApi. Earlier consumer-named variants (MyActionsApi, VisionesActionsApi) were retired in API review III to make the side-of-the-wire intent visible at every call site. If a consumer needs a different name they hand-roll the interface (the helper's job is the standard symmetric shape).

specs

type readonly ({ 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; } | { ...; } ...

imports

options?

type { method_filter?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => boolean) | undefined; collections_path?: ...
optional

returns

string

generate_phase_handlers
#

actions/action_codegen.ts view source

(spec: { 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; } | { ...; } | { ...; }, executor: "frontend" | "backend", imports: ImportBuilder, options?: { ...; } | undefined): string

Generates the phase handlers for an action spec using the unified ActionEvent type with the new phase/step type parameters.

Returns '' when the spec contributes no phases on the given executor side (e.g. a backend-only local_call asked for 'frontend'). Upstream wrappers compose blocks with .filter(Boolean) so empty entries are dropped from the generated handler map. The earlier shape was ${method}?: never, which read as "calling this here is a type error" but in practice produced useless rows on FrontendActionHandlers for methods that don't belong on this side at all — drop the row instead so the typed surface only carries methods the executor actually handles.

spec

type { 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; } | { ...; } | { ...; }

executor

type "frontend" | "backend"

imports

options?

type { action_event_type?: string | undefined; collections_path?: string | undefined; } | undefined
optional

returns

string

generate_typed_action_event_alias
#

actions/action_codegen.ts view source

(imports: ImportBuilder, options?: { collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined): string

Emit the fixed-shape TypedActionEvent alias used by FrontendActionHandlers to narrow ActionEvent.data against the consumer's generated ActionEventDatas map. Registers the four fuz_app type imports it needs (ActionEvent, ActionEventPhase, ActionEventStep, ActionEventDatas) plus the ActionMethod type import — sourced from collections_path and metatypes_path respectively.

Pair with generate_action_method_enums (emits ActionMethod into metatypes_path) and generate_action_event_datas (emits ActionEventDatas into collections_path).

imports

options?

type { collections_path?: string | undefined; metatypes_path?: string | undefined; } | undefined
optional

returns

string

get_executor_phases
#

actions/action_codegen.ts view source

(spec: { 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; } | { ...; } | { ...; }, executor: "frontend" | "backend"): ("send_request" | ... 7 more ... | "execute")[]

Phases an executor can handle for the given spec — kind + initiator → set of phases.

spec

type { 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; } | { ...; } | { ...; }

executor

type "frontend" | "backend"

returns

("send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute")[]

get_handler_return_type
#

actions/action_codegen.ts view source

(spec: { 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; } | { ...; } | { ...; }, phase: "send_request" | ... 7 more ... | "execute", imports: ImportBuilder, collections_path?: string): string

Gets the handler return type for a specific phase and spec. Adds an ActionOutputs import (from collections_path) when the phase carries an output (request_response receive_request, local_call execute).

spec

type { 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; } | { ...; } | { ...; }

phase

type "send_request" | "receive_request" | "send_response" | "receive_response" | "send_error" | "receive_error" | "send" | "receive" | "execute"

imports

collections_path

type string
default DEFAULT_COLLECTIONS_PATH

returns

string

ImportBuilder
#

actions/action_codegen.ts view source

Manages imports for generated code, building them on demand. Automatically optimizes type-only imports to use import type syntax.

Why this matters: - import type statements are completely removed during compilation - Mixed imports like import { type A, B } cannot be safely removed - This ensures optimal tree-shaking and smaller bundle sizes

examples

const imports = new ImportBuilder(); imports.add_types('./types.js', 'Foo', 'Bar'); imports.add('./utils.js', 'helper'); imports.add_type('./utils.js', 'HelperOptions'); imports.add('./action_specs.js', '* as specs'); // Generates: // import type {Foo, Bar} from './types.js'; // import {helper, type HelperOptions} from './utils.js'; // import * as specs from './action_specs.js';

imports

type Map<string, Map<string, ImportItem>>

add

Add a value import. Accepts * as ns strings as namespace imports.

type (from: string, what: string): this

from
type string
what
type string
returns this

this for chaining

add_type

Add a type-only import.

type (from: string, what: string): this

from
type string
what
type string
returns this

this for chaining

add_many

type (from: string, ...items: string[]): this

from
type string
items
type string[]
returns this

add_types

type (from: string, ...items: string[]): this

from
type string
items
type string[]
returns this

build

Generate the import statements. When every import from a module is a type, emits import type {…} so the whole statement disappears at compile time.

type (): string

returns string

has_imports

type (): boolean

returns boolean

preview

Build the same statement list as build without joining — for inspection in tests.

type (): string[]

returns string[]

clear

Clear all imports.

type (): this

returns this

this for chaining

is_protocol_action_method
#

actions/action_codegen.ts view source

(method: string): method is "heartbeat" | "cancel"

Type predicate for filtering protocol-action methods out of a typed FrontendActionsApi method_filter. Avoids the (... as never) cast required to call Array.prototype.includes on the readonly tuple at narrow string types.

method

type string

returns

boolean

examples

generate_frontend_actions_api(specs, imports, { method_filter: (s) => !is_protocol_action_method(s.method), });

PROTOCOL_ACTION_METHODS
#

actions/action_codegen.ts view source

readonly ["heartbeat", "cancel"]

Method names of fuz_app's protocol actions — heartbeat (auth-aware client liveness probe) and cancel (request-scoped abort signal). Consumers spread this list when filtering backend request_response methods so the dispatcher-owned protocol actions don't show up in BackendRequestResponseMethod / handler maps. Pairs with protocol_actions / protocol_action_specs from actions/protocol.ts (the runtime bundles).

ProtocolActionMethod
#

resolve_spec_qualifier
#

actions/action_codegen.ts view source

(imports: ImportBuilder, options?: { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; ... 8 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string) | undefined; } | undefined): (spec: { ...; } | ... 1 more ... | { ...; }) => string

Resolve a per-spec identifier qualifier with the standard default-vs-callback dance. When qualify_spec is set, returns the caller's callback verbatim and registers no imports — the caller owns its namespace setup (the multi-source case where specs come from several modules). Otherwise, registers * as specs from specs_module (defaulting to './action_specs.js') on imports and returns (spec) => 'specs.' + to_action_spec_identifier(spec.method).

Used internally by every multi-source-aware helper in this module (generate_action_specs_record, generate_action_inputs_outputs, generate_backend_actions_api); exported so consumers writing their own codegen helpers can reuse the same defaulting + import-registration behavior instead of reimplementing it.

imports

options?

type { specs_module?: string | undefined; qualify_spec?: ((spec: { method: string; initiator: "frontend" | "backend" | "both"; side_effects: boolean; input: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>; ... 7 more ...; rate_limit?: "both" | ... 2 more ... | undefined; } | { ...; } | { ...; }) => string)...
optional

returns

(spec: { 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; } | { ...; } | {...

SpecSource
#

actions/action_codegen.ts view source

SpecSource

One source in a multi-source consumer's namespace map. ns is the local alias used inside the generated file; module is the import path; specs is the runtime spec array. create_namespace_qualifier consumes a list of these.

ns

type string

module

type string

specs

type ReadonlyArray<ActionSpecUnion>

to_action_spec_identifier
#

to_action_spec_input_identifier
#

to_action_spec_output_identifier
#

Depends on
#