npm install @rotorsoft/act
import { act, 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({ Incremented: (event, state) => ({ count: state.count + event.data.amount }) })
.on("increment", z.object({ by: z.number() }))
.emit((action, state) => ["Incremented", { amount: action.by }])
.build();
const app = act().with(Counter).build();
await app.do("increment", { stream: "counter1", actor: { id: "1", name: "User" } }, { by: 1 });
console.log(await app.load(Counter, "counter1"));
Every state change is a pure function of previous state and events. Immutability and replayability by design.
Model your domain as composable, strongly-typed state machines. No classes, just functions and data.
Type safety and inference everywhere. Catch errors at compile time, not at runtime.
Reactions let you build event-driven flows and side effects with ease.
Production-ready Postgres adapter for scalable, persistent event storage. Switch between in-memory and Postgres with a single line of code.
Minimal and dependency-light. No codegen, no runtime bloat, and a tiny bundle size.