Skip to content

Quick Start

This page walks you from zero to a running pipeline. If you haven’t installed Actioneer yet, see Installation.

An action is any object with a setup(builder) method. Inside setup, you describe your pipeline by chaining .do() calls on the builder. Each step is an activity that receives a shared context object.

import {ActionBuilder, ActionRunner} from "@gesslar/actioneer"
class MyAction {
setup(builder) {
builder
.do("prepare", ctx => { ctx.count = 0; return ctx })
.do("work", ctx => { ctx.count += 1; return ctx })
.do("finalise", ctx => { return ctx.count })
}
}

The operation for each activity reads from and mutates ctx, then returns it so the updated context flows to the next step — return nothing and the next step receives undefined. Whatever the final activity returns becomes the pipeline’s result.

Wrap your action in an ActionBuilder, hand it to an ActionRunner, and call run() with an initial context:

const builder = new ActionBuilder(new MyAction())
const runner = new ActionRunner(builder)
const result = await runner.run({})
console.log(result) // 1

run() executes the pipeline once and returns the final context value. If any activity throws, run() rejects — wrap it in try/catch to handle errors.

To process many inputs at once, use pipe() with an array of contexts and a concurrency limit:

const builder = new ActionBuilder(new MyAction())
const runner = new ActionRunner(builder)
// Run up to 4 contexts concurrently
const results = await runner.pipe([{}, {}, {}], 4)
// pipe() returns SETTLED results — it never throws on individual failures
results.forEach(result => {
if (result.status === "fulfilled") {
console.log("Count:", result.value)
} else {
console.error("Error:", result.reason)
}
})

Unlike run(), pipe() returns an array of settlement objects ({status: "fulfilled", value} or {status: "rejected", reason}), so a single failing context never blows up the whole batch. See run() vs pipe() for the full comparison.

The done() callback runs after every activity completes — even on error — much like finally. On success its return value becomes the final result (on error it receives the error and the pipeline still rejects), which makes it ideal for cleanup or shaping output:

class MyAction {
setup(builder) {
builder
.do("step1", ctx => { ctx.a = 1; return ctx })
.do("step2", ctx => { ctx.b = 2; return ctx })
.done(ctx => ({total: ctx.a + ctx.b}))
}
}
const runner = new ActionRunner(new ActionBuilder(new MyAction()))
console.log(await runner.run({})) // { total: 3 }

See Finalizing with done() for the details.

  • Core Concepts — the mental model behind actions, contexts, and activities.
  • Activity Modes — loops, conditionals, and parallel sections with WHILE, UNTIL, IF, BREAK, CONTINUE, and SPLIT.
  • Lifecycle Hooks — run code before and after activities.