/** * `call(name, opts)` — call-only Flow sugar with invoke contract on the bag. * * Same species as `flow` + internal trigger; contracts live here (not on `flow()`). */ import { stampBoundaryContract, type BoundaryContract, type InferBoundaryErrors, type InferBoundaryIn, type InferBoundaryOut, } from "./boundary-contract.ts"; import { flow, type FlowDef, type FlowErrorMap, type FlowHandler, type FlowOptions, } from "./flow.ts"; import { internal } from "./triggers.ts"; /** Options for {@link call} — boundary contract + flow runtime + `do`. */ export type CallOptions< I = unknown, O = unknown, E extends FlowErrorMap = FlowErrorMap, > = BoundaryContract & Omit, "do"> & { readonly do: FlowHandler; }; type InferCallIn = Opts extends { readonly in: unknown } ? InferBoundaryIn : Opts extends { readonly do: FlowHandler } ? I : unknown; type InferCallOut = Opts extends { readonly out: unknown } ? InferBoundaryOut : Opts extends { readonly do: FlowHandler } ? O : unknown; /** * Define a call-only Flow with its invoke contract on the same bag. * * @param name - Stable Manifest / `fx.call` name * @param options - Contract + runtime + `do` */ export function call>( name: string, options: Opts & { readonly name?: never }, ): FlowDef, InferCallOut, InferBoundaryErrors> { if (typeof name !== "string" || name.trim().length === 0) { throw new TypeError("call(name, opts): name is required"); } const { in: inSchema, out: outSchema, errors, breaking, do: handler, ...runtime } = options as CallOptions; const def = flow(name, { ...runtime, do: handler as FlowHandler, }) as FlowDef, InferCallOut, InferBoundaryErrors>; const stamped = stampBoundaryContract({ in: inSchema, out: outSchema, errors, breaking, }); def.in = stamped.in; def.out = stamped.out; def.errors = stamped.errors as InferBoundaryErrors | undefined; def.breaking = stamped.breaking; // Mark as internal / call-only exposure (addressable trigger kind). const triggers = def.triggers as import("./triggers.ts").Trigger[]; triggers.push(internal); (def as { $trigger: typeof internal }).$trigger = internal; return def; }