Creating a workflow
This page declares the state of a workflow and the workflow itself, and registers it with the bus. Each time a workflow is started, a new instance of its state is created. Every step of the workflow receives the state, and changes it by returning the fields to update.
Declaring the state
The state is a class that extends WorkflowState. Give it a static NAME and a $name that's unique among all your workflow states, since the persistence stores each workflow's state under it. The class is constructed with no arguments.
import { WorkflowState } from '@node-ts/bus-core'
export class FulfilmentWorkflowState extends WorkflowState {
// Unique among all of your workflow states
static NAME = 'my-app/store/fulfilment-workflow-state'
$name = FulfilmentWorkflowState.NAME
// The workflow's own fields
itemId: string
customerId: string
status: 'shipping-item' | 'emailing-receipt' | 'complete'
shippedAt?: Date
}Declaring the workflow
With functions, defineWorkflow(State) returns a workflow that startedBy and when add handlers to. As a class, extend Workflow and map messages to its methods by name in configureWorkflow.
export const fulfilmentWorkflow = defineWorkflow(FulfilmentWorkflowState)
// Handlers are added with startedBy and when
.startedBy(ItemPurchased, ({ itemId, customerId }) => ({
itemId,
customerId
}))export class FulfilmentWorkflow extends Workflow<FulfilmentWorkflowState> {
configureWorkflow(
mapper: WorkflowMapper<FulfilmentWorkflowState, FulfilmentWorkflow>
): void {
mapper.withState(FulfilmentWorkflowState).startedBy(ItemPurchased, 'start')
}
start({ itemId, customerId }: ItemPurchased) {
return { itemId, customerId }
}
}A function workflow reaches its dependencies through closures and needs no container. A class workflow is constructed with no arguments, or resolved from a container when the bus has one.
Type a class workflow's mapper with the class itself, as WorkflowMapper<FulfilmentWorkflowState, FulfilmentWorkflow>. The compiler then checks every handler name against the method it names: the method must be public, accept the message it's mapped to, and return changes to the state with no fields that aren't in it.
Registering the workflow
Register the workflow with withWorkflow(). The bus needs message types for the workflow state as well as its messages, so generate them from the file that declares the state too. initialize() checks that every workflow state has an entry.
const bus = Bus.configure()
// Generated from the messages and the workflow state
.withMessageTypes(messageTypes)
.withWorkflow(fulfilmentWorkflow)
.build()Without withPersistence(), workflow state is kept in memory, which is only suitable for development. See Persistence for durable options.
See also
- Starting a workflow
defineWorkflowandWorkflowin the API reference