Skip to main content
Version: Current

state

@rotorsoft/act-root


@rotorsoft/act-root / act/src / state

Function: state()

state<TName, TState>(entry): StateBuilder<TState, TName>

Defined in: libs/act/src/builders/state-builder.ts:82

Creates a new state definition with event sourcing capabilities.

States are the core building blocks of Act. Each state represents a consistency boundary (aggregate) that processes actions, emits events, and maintains its own state through event patches (reducers). States use event sourcing to maintain a complete audit trail and enable time-travel capabilities.

The state builder provides a fluent API for defining:

  1. Initial state via .init()
  2. Event types via .emits() — all events default to passthrough (({ data }) => data)
  3. Custom event reducers via .patch() (optional — only for events that need custom logic)
  4. Actions (commands) via .on() → .emit() — pass an event name string for passthrough
  5. Business rules: preconditions via .requires()
  6. Snapshotting strategy via .snap()

Type Parameters​

TName​

TName extends string

TState​

TState extends Schema

Zod schema type defining the shape of the state

Parameters​

entry​

StateEntry<TName, TState>

Single-key record mapping state name to Zod schema (e.g., { Counter: z.object({ count: z.number() }) })

Returns​

StateBuilder<TState, TName>

A StateBuilder instance for fluent API configuration

Example​

Basic counter state (with custom patch)

import { state } from "@rotorsoft/act";
import { z } from "zod";

const Counter = state({ Counter: z.object({ count: z.number() }) })
.init(() => ({ count: 0 }))
.emits({
Incremented: z.object({ amount: z.number() })
})
.patch({ // optional — only for events needing custom reducers
Incremented: ({ data }, state) => ({ count: state.count + data.amount })
})
.on({ increment: z.object({ by: z.number() }) })
.emit((action) => ["Incremented", { amount: action.by }])
.build();

See​