WorkflowBuilder
Fluent builder that compiles a workflow definition. Use createWorkflow() — do not call new WorkflowBuilder() directly.
import { createWorkflow } from 'flowyd';createWorkflow(config)
function createWorkflow(config: { name: string }): WorkflowBuilder<Record<never, never>, never>;Instantiates a WorkflowBuilder with TStates = never. Each subsequent addStep, addFork, addJoin, or addWait call widens TStates by one literal — every call is constrained to the accumulated union, so typos are compile errors.
const wf = createWorkflow({ name: 'purchase-order' });
// TStates = never initially; grows with each addStep/addFork/addJoin/addWait callThrows if name is empty or whitespace.
Call order
Methods must be called in this sequence:
defineAction()— register each action and its payload schemaaddStep()/addFork()/addJoin()/addWait()— register every statesetInitial()/setTerminal()— declare entry and exit pointsaddTransition()— wire states togetherbuild()— validate and compile
.defineAction(name, schema)
defineAction<K extends string, T>(
name: K,
schema: ZodSchema<T>,
): WorkflowBuilder<TActions & Record<K, T>, TStates>Registers an action and binds a Zod schema to its payload. Returns a new builder specialization with extended TActions — downstream calls to addTransition, dispatch, and canExecute are all typed to registered action names.
.defineAction('APPROVE', z.object({ approverId: z.string(), reason: z.string() })).addStep(id, options?)
addStep<K extends string>(id: K, options?: { label?: string }): WorkflowBuilder<TActions, TStates | K>Registers a StepState and widens TStates to include K. Becomes active on entry; waits for a dispatch to advance.
.addFork(id, options)
addFork(id: TStates, options: {
targets: [TStates, ...TStates[]];
label?: string;
}): thisRegisters a ForkState. On entry it immediately completes and activates all targets in the same engine tick. The targets array is constrained to the declared TStates union — a misspelled target is a compile error.
.addJoin(id, options)
addJoin(id: TStates, options: {
requires: [TStates, ...TStates[]];
mode: 'all' | 'any' | number;
label?: string;
}): thisRegisters a JoinState. Activates automatically when the mode threshold of requires states is satisfied. The requires array is constrained to TStates.
mode | Activates when |
|---|---|
'all' | All states in requires are completed |
'any' | At least one state in requires is completed |
number N | At least N states in requires are completed |
.addWait(id, options?)
addWait(id: TStates, options?: { externalName?: string; label?: string }): thisRegisters a WaitState. On entry its status becomes waiting (not active). Resume with inst.resolveWait(id).
externalName is documentary — it appears in snapshots and visualization but has no runtime effect.
.setInitial(id)
setInitial(id: TStates): thisMarks one state as the initial state. It becomes active when createInstance is called.
.setTerminal(ids)
setTerminal(ids: [TStates, ...TStates[]]): thisMarks one or more states as terminal. Once any terminal state is active, all subsequent dispatch calls return { success: false, reason: 'terminal-state' }.
.addTransition(def)
addTransition(def: {
from: TStates;
to: TStates;
on: keyof TActions & string;
guard?: IGuard | GuardFn;
}): thisWires a directed edge. from, to, and on are all constrained to registered IDs and action names.
guard accepts either a Guard.* factory result or an inline function (ctx: GuardContext) => boolean | Promise<boolean>.
.build()
build(): Workflow<TActions, TStates>Validates the complete definition and returns an immutable Workflow object.
Throws if:
- Any declared state was not registered via
addStep/addFork/addJoin/addWait - No initial state was set
- No terminal state was set
- A transition references an unregistered state or action
Workflow object (returned by build())
.createInstance(instanceId)
createInstance(instanceId: string): WorkflowInstance<TActions>Creates a new WorkflowInstance with the initial state set to active.
.restoreInstance(snapshot)
restoreInstance(snapshot: InstanceSnapshot): WorkflowInstance<TActions>Reconstructs a WorkflowInstance from a previously saved snapshot. Validates that snapshot.workflowName matches this workflow.
Throws if the snapshot's workflowName does not match.
.getDefinition()
getDefinition(): WorkflowDefinitionReturns the immutable compiled definition. Pass to MermaidExporter.export() or JsonGraphExporter.export().