ActionBuilder
@rotorsoft/act-root / act/src / ActionBuilder
Type Alias: ActionBuilder<TState, TEvents, TActions, TName>
ActionBuilder<
TState,TEvents,TActions,TName> =object
Defined in: libs/act/src/builders/state-builder.ts:137
Builder interface for defining actions (commands) on a state.
Actions represent user/system intents to modify state. Each action is validated against a schema, can have business rule invariants, and must emit one or more events.
Seeโ
state for complete usage examples
Type Parametersโ
TStateโ
TState extends Schema
State schema type
TEventsโ
TEvents extends Schemas
Event schemas type
TActionsโ
TActions extends Schemas
Action schemas type
TNameโ
TName extends string = string
State name literal type
Propertiesโ
buildโ
build: () =>
State<TState,TEvents,TActions,TName>
Defined in: libs/act/src/builders/state-builder.ts:368
Finalizes and builds the state definition.
Call this method after defining all actions, invariants, and patches to create the complete State object that can be registered with Act.
Returnsโ
State<TState, TEvents, TActions, TName>
The complete strongly-typed State definition
Exampleโ
const Counter = state({ Counter: schema })
.init(() => ({ count: 0 }))
.emits({ Incremented: z.object({ amount: z.number() }) })
.patch({ Incremented: ({ data }, state) => ({ count: state.count + data.amount }) })
.on({ increment: z.object({ by: z.number() }) })
.emit((action) => ["Incremented", { amount: action.by }])
.build(); // Returns State<TState, TEvents, TActions, TName>
onโ
on: <
TKey,TNewActions>(entry) =>object
Defined in: libs/act/src/builders/state-builder.ts:182
Defines an action (command) that can be executed on this state.
Actions represent intents to change state - they should be named in imperative form (e.g., "CreateUser", "IncrementCounter", "PlaceOrder"). Actions are validated against their schema and must emit at least one event.
Pass a { ActionName: schema } record โ use shorthand { ActionName }
when the variable name matches the action name. The key becomes the
action name, the value the Zod schema.
Type Parametersโ
TKeyโ
TKey extends string
Action name (string literal type)
TNewActionsโ
TNewActions extends Schema
Action payload schema type
Parametersโ
entryโ
ActionEntry<TKey, TNewActions>
Single-key record { ActionName: schema }
Returnsโ
An object with .given() and .emit() for further configuration
emitโ
emit: {(
handler):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>; (eventName):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>; }
Defines the action handler that emits events. Same two overloads as
the post-.given() form above:
- Function โ receives
(action, snapshot)and returns one or more[EventName, data]tuples (orundefined). - String โ passthrough: the action payload becomes the event
data directly. Must reference an event declared in
.emits().
The two overloads are kept separate (rather than merged into a
handler | string union) so that TS contextual typing of the
function alternative isn't degraded by considering the string
branch โ under the union form TState could collapse to its
Schema constraint inside the callback.
Call Signatureโ
(
handler):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>
Parametersโ
handlerโ
ActionHandler<TState, TEvents, { [P in string]: TNewActions }, TKey>
Returnsโ
ActionBuilder<TState, TEvents, TActions & { [P in string]: TNewActions }, TName>
Call Signatureโ
(
eventName):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>
Parametersโ
eventNameโ
keyof TEvents & string
Returnsโ
ActionBuilder<TState, TEvents, TActions & { [P in string]: TNewActions }, TName>
Examplesโ
.emit("Incremented")
.emit((action) => ["Incremented", { amount: action.by }])
.emit((action) => [
["Incremented", { amount: action.by }],
["LogUpdated", { message: `Incremented by ${action.by}` }]
])
givenโ
given: (
rules) =>object
Adds business rule invariants that must hold before the action can execute.
Invariants are checked after loading the current state but before emitting events.
Each invariant should return true or an error message string. All invariants
must pass for the action to succeed.
Parametersโ
rulesโ
Invariant<TState>[]
Array of invariant functions
Returnsโ
An object with .emit() to finalize the action
emitโ
emit: {(
handler):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>; (eventName):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>; }
Defines the action handler that emits events.
The handler receives the action payload and current state snapshot, and must return one or more events to emit. Events are applied to state via the patch handlers defined earlier.
Pass a string event name for passthrough: the action payload becomes the event data directly.
Call Signatureโ
(
handler):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>
Custom handler โ receives (action, snapshot) and returns one
or more [EventName, data] tuples (or undefined).
Parametersโ
handlerโ
ActionHandler<TState, TEvents, { [P in string]: TNewActions }, TKey>
Returnsโ
ActionBuilder<TState, TEvents, TActions & { [P in string]: TNewActions }, TName>
Call Signatureโ
(
eventName):ActionBuilder<TState,TEvents,TActions&{ [P in string]: TNewActions },TName>
Passthrough โ the action payload becomes the event data
directly. Must reference an event declared in .emits().
Parametersโ
eventNameโ
keyof TEvents & string
Returnsโ
ActionBuilder<TState, TEvents, TActions & { [P in string]: TNewActions }, TName>
Paramโ
Function that returns events to emit, or event name string for passthrough
Returnsโ
The ActionBuilder for chaining more actions
Examplesโ
.emit((action, snapshot) => {
const newBalance = snapshot.state.balance + action.amount;
return ["Deposited", { amount: action.amount, newBalance }];
})
.emit("TicketAssigned")
Exampleโ
.given([
(_, snap) => snap.state.status === "active" || "Must be active",
(target, snap) => snap.state.ownerId === target.actor.id || "Not authorized"
])
Examplesโ
.on({ increment: z.object({ by: z.number() }) })
.emit((action) => ["Incremented", { amount: action.by }])
.on({ withdraw: z.object({ amount: z.number() }) })
.given([
(_, snap) => snap.state.balance >= 0 || "Account closed",
(_, snap, action) => snap.state.balance >= action.amount || "Insufficient funds"
])
.emit((action) => ["Withdrawn", { amount: action.amount }])
const OpenTicket = z.object({ title: z.string() });
.on({ OpenTicket })
.emit((action) => ["TicketOpened", { title: action.title }])
snapโ
snap: (
snap) =>ActionBuilder<TState,TEvents,TActions,TName>
Defined in: libs/act/src/builders/state-builder.ts:346
Defines a snapshotting strategy to optimize state reconstruction.
Snapshots store the current state at a point in time, allowing faster state loading
by avoiding replaying all events from the beginning. The snap function is called
after each event is applied and should return true when a snapshot should be taken.
Parametersโ
snapโ
(snapshot) => boolean
Predicate function that returns true when a snapshot should be taken
Returnsโ
ActionBuilder<TState, TEvents, TActions, TName>
The ActionBuilder for chaining
Examplesโ
.snap((snapshot) => snapshot.patches >= 10)
.snap((snapshot) => {
const estimatedSize = JSON.stringify(snapshot.state).length;
return estimatedSize > 10000 || snapshot.patches >= 50;
})
.snap((snapshot) => {
const hoursSinceLastSnapshot = snapshot.patches * 0.1; // Estimate
return hoursSinceLastSnapshot >= 24;
})