Quick Start
This guide walks you through building a complete workflow from scratch.
Installation
npm install wooks @wooksjs/event-wfStep 1: Create the App
Every workflow app starts with createWfApp. The generic parameter defines the context type — the shared state that all steps in a workflow can read and modify.
import { createWfApp, useWfState } from '@wooksjs/event-wf'
import { useRouteParams } from '@wooksjs/event-core'
// Define the shape of your workflow context
interface OrderContext {
items: string[]
total: number
discount: number
status: string
}
const app = createWfApp<OrderContext>()Step 2: Define Steps
Steps are the building blocks. Each step has an id and a handler function.
// A simple step that calculates the total
app.step('calculate-total', {
handler: (ctx) => {
ctx.total = ctx.items.length * 10 // $10 per item
},
})
// A parametric step — the discount percentage comes from the step id
app.step('apply-discount/:percent', {
handler: (ctx) => {
const percent = Number(useRouteParams().get('percent'))
ctx.discount = ctx.total * (percent / 100)
ctx.total -= ctx.discount
},
})
// A step that uses the composable API
app.step('finalize', {
handler: () => {
const { ctx } = useWfState()
const context = ctx<OrderContext>()
context.status = context.total > 0 ? 'ready' : 'empty'
},
})Note how apply-discount/:percent uses route-style parameters — when called as apply-discount/15, the percent parameter resolves to "15".
Step 3: Define a Flow
A flow is a schema that wires steps together. It's just an array — the engine executes steps in order.
app.flow('process-order', [
'calculate-total',
{
condition: 'total > 50', // only apply discount for orders over $50
steps: ['apply-discount/10'],
},
'finalize',
])Step 4: Run It
const output = await app.start('process-order', {
items: ['shirt', 'pants', 'shoes', 'jacket', 'hat', 'belt'],
total: 0,
discount: 0,
status: '',
})
console.log(output.finished) // true
console.log(output.state.context)
// { items: [...], total: 54, discount: 6, status: 'ready' }The second argument to start() is the initial context. Every step in the flow reads and mutates this same object.
What Just Happened?
calculate-totalsettotalto 60 (6 items × $10)- The condition
total > 50was true, soapply-discount/10ran and subtracted 10% ($6) finalizesetstatusto'ready'
The output includes the full final state under output.state.context, and output.finished tells you whether the workflow completed or paused for input.
Next Steps
- Steps — handlers, parametric routing, composables, string handlers
- Flows — conditions, loops, subflows, break/continue
- Input & Resume — pause workflows for user input, resume later
