@rotorsoft/act 0.6.28 → 0.6.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ports.ts","../src/types/errors.ts","../src/utils.ts","../src/config.ts","../src/types/schemas.ts","../src/types/index.ts","../src/adapters/InMemoryStore.ts","../src/signals.ts","../src/act.ts","../src/event-sourcing.ts","../src/act-builder.ts","../src/state-builder.ts"],"sourcesContent":["import { pino } from \"pino\";\nimport { InMemoryStore } from \"./adapters/InMemoryStore.js\";\nimport { config } from \"./config.js\";\nimport type {\n Disposable,\n Disposer,\n Fetch,\n Lease,\n LogLevel,\n Schemas,\n Store,\n} from \"./types/index.js\";\n\n/**\n * Port and adapter utilities for logging, store management, and resource disposal.\n *\n * Provides singleton store and logger instances, and helpers for resource lifecycle management.\n *\n * - Use `store()` to get or inject the event store (in-memory or persistent).\n * - Use `logger` for structured logging.\n * - Use `dispose()` to register resource disposers for graceful shutdown.\n *\n * @module ports\n */\n\n/**\n * List of exit codes for process termination.\n */\nexport const ExitCodes = [\"ERROR\", \"EXIT\"] as const;\n\n/**\n * Type for allowed exit codes.\n */\nexport type ExitCode = (typeof ExitCodes)[number];\n\n/**\n * Singleton logger instance (Pino).\n *\n * Use for structured logging throughout your application.\n *\n * @example\n * logger.info(\"Application started\");\n */\nexport const logger = pino({\n transport:\n config().env !== \"production\"\n ? {\n target: \"pino-pretty\",\n options: {\n ignore: \"pid,hostname\",\n singleLine: config().logSingleLine,\n colorize: true,\n },\n }\n : undefined,\n level: config().logLevel,\n});\n\n/**\n * Helper to create a singleton port (adapter) with optional injection.\n *\n * @param injector The function that creates the port/adapter\n * @returns A function to get or inject the singleton instance\n *\n * @example\n * const store = port((adapter) => adapter || new InMemoryStore());\n * const myStore = store();\n */\ntype Injector<Port extends Disposable> = (adapter?: Port) => Port;\nconst adapters = new Map<string, Disposable>();\nexport function port<Port extends Disposable>(injector: Injector<Port>) {\n return function (adapter?: Port): Port {\n if (!adapters.has(injector.name)) {\n const injected = injector(adapter);\n adapters.set(injector.name, injected);\n logger.info(`🔌 injected ${injector.name}:${injected.constructor.name}`);\n }\n return adapters.get(injector.name) as Port;\n };\n}\n\nconst disposers: Disposer[] = [];\nexport async function disposeAndExit(code: ExitCode = \"EXIT\"): Promise<void> {\n // ignore when errors are caught in production\n if (code === \"ERROR\" && config().env === \"production\") return;\n\n await Promise.all(disposers.map((disposer) => disposer()));\n await Promise.all(\n [...adapters.values()].reverse().map(async (adapter) => {\n await adapter.dispose();\n logger.info(`🔌 disposed ${adapter.constructor.name}`);\n })\n );\n adapters.clear();\n config().env !== \"test\" && process.exit(code === \"ERROR\" ? 1 : 0);\n}\n\n/**\n * Registers resource disposers that are triggered on process exit.\n *\n * @param disposer The disposer function to register\n * @returns A function that triggers all registered disposers and terminates the process\n *\n * @example\n * dispose(async () => { await myResource.close(); });\n */\nexport function dispose(\n disposer?: Disposer\n): (code?: ExitCode) => Promise<void> {\n disposer && disposers.push(disposer);\n return disposeAndExit;\n}\n\n/**\n * Special event name for snapshot events in the event store.\n */\nexport const SNAP_EVENT = \"__snapshot__\";\n\n/**\n * Singleton event store port. By default, uses the in-memory store.\n *\n * You can inject a persistent store (e.g., Postgres) by calling `store(myAdapter)`.\n *\n * @example\n * const myStore = store();\n * const customStore = store(new MyCustomStore());\n */\nexport const store = port(function store(adapter?: Store) {\n return adapter || new InMemoryStore();\n});\n\n/**\n * Tracer builder for logging fetches, leases, etc.\n */\nexport function build_tracer(logLevel: LogLevel): {\n fetched: <E extends Schemas>(fetched: Fetch<E>) => void;\n correlated: (leases: Lease[]) => void;\n leased: (leases: Lease[]) => void;\n acked: (leases: Lease[]) => void;\n blocked: (leases: Array<Lease & { error: string }>) => void;\n} {\n if (logLevel === \"trace\") {\n return {\n fetched: <E extends Schemas>(fetched: Fetch<E>) => {\n const data = Object.fromEntries(\n fetched.map(({ stream, source, events }) => {\n const key = source ? `${stream}<-${source}` : stream;\n const value = Object.fromEntries(\n events.map(({ id, stream, name }) => [id, { [stream]: name }])\n );\n return [key, value];\n })\n );\n logger.trace(data, \"⚡️ fetch\");\n },\n correlated: (leases: Lease[]) => {\n const data = leases.map(({ stream }) => stream).join(\" \");\n logger.trace(`⚡️ correlate ${data}`);\n },\n leased: (leases: Lease[]) => {\n const data = Object.fromEntries(\n leases.map(({ stream, at, retry }) => [stream, { at, retry }])\n );\n logger.trace(data, \"⚡️ lease\");\n },\n acked: (leases: Lease[]) => {\n const data = Object.fromEntries(\n leases.map(({ stream, at, retry }) => [stream, { at, retry }])\n );\n logger.trace(data, \"⚡️ ack\");\n },\n blocked: (leases: Array<Lease & { error: string }>) => {\n const data = Object.fromEntries(\n leases.map(({ stream, at, retry, error }) => [\n stream,\n { at, retry, error },\n ])\n );\n logger.trace(data, \"⚡️ block\");\n },\n };\n } else {\n return {\n fetched: () => {},\n correlated: () => {},\n leased: () => {},\n acked: () => {},\n blocked: () => {},\n };\n }\n}\n","import type { Message, Schema, Schemas, Snapshot, Target } from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n} as const;\n\n/**\n * Thrown when a payload fails schema validation.\n * @param target - The name of the target being validated (e.g., event, action).\n * @param payload - The invalid payload.\n * @param details - Additional validation error details.\n * @example\n * throw new ValidationError('event', payload, zodError);\n */\nexport class ValidationError extends Error {\n constructor(\n public readonly target: string,\n public readonly payload: any,\n public readonly details: any\n ) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n }\n}\n\n/**\n * Thrown when a state invariant is violated after an action or event.\n * @param name - The name of the invariant or action.\n * @param payload - The state or payload that failed the invariant.\n * @param target - The target context (e.g., stream, actor).\n * @param description - Description of the invariant.\n * @example\n * throw new InvariantError('balanceNonNegative', state, target, 'Balance must be >= 0');\n */\nexport class InvariantError<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n K extends keyof A,\n> extends Error {\n constructor(\n readonly action: K,\n readonly payload: Readonly<A[K]>,\n readonly target: Target,\n readonly snapshot: Snapshot<S, E>,\n readonly description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n }\n}\n\n/**\n * Thrown when an optimistic concurrency check fails during event commit.\n * @param lastVersion - The last known version in the stream.\n * @param events - The events being committed.\n * @param expectedVersion - The expected version for the commit.\n * @example\n * throw new ConcurrencyError(2, events, 1);\n */\nexport class ConcurrencyError extends Error {\n constructor(\n public readonly stream: string,\n public readonly lastVersion: number,\n public readonly events: Message<Schemas, keyof Schemas>[],\n public readonly expectedVersion: number\n ) {\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}.${JSON.stringify(e.data)}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n }\n}\n","import { type ZodError, type ZodType, prettifyError } from \"zod\";\nimport { config } from \"./config.js\";\nimport type { Patch, Schema } from \"./types/index.js\";\nimport { ValidationError } from \"./types/index.js\";\n\n/** These objects are copied instead of deep merged */\nconst UNMERGEABLES = [\n RegExp,\n Date,\n Array,\n Map,\n Set,\n WeakMap,\n WeakSet,\n ArrayBuffer,\n SharedArrayBuffer,\n DataView,\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float32Array,\n Float64Array,\n];\n\nconst is_mergeable = (value: any): boolean =>\n !!value &&\n typeof value === \"object\" &&\n !UNMERGEABLES.some((t) => value instanceof t);\n\n/**\n * @module utils\n * @category Utilities\n * Utility functions for patching state, validation, extending objects, and async helpers.\n *\n * - Use `patch()` to immutably update state with patches.\n * - Use `validate()` to validate payloads against Zod schemas.\n * - Use `extend()` to merge and validate configuration objects.\n * - Use `sleep()` for async delays.\n */\n\n/**\n * Immutably copies state with patches recursively.\n *\n * Keys with `undefined` or `null` values in patch are deleted.\n *\n * @param original The original state object\n * @param patches The patches to merge\n * @returns A new patched state\n *\n * @example\n * const newState = patch(oldState, { count: 5 });\n */\nexport const patch = <S extends Schema>(\n original: Readonly<S>,\n patches: Readonly<Patch<S>>\n): Readonly<S> => {\n const copy = {} as Record<string, any>;\n Object.keys({ ...original, ...patches }).forEach((key) => {\n const patched_value = patches[key as keyof typeof patches];\n const original_value = original[key as keyof typeof original];\n const patched = patches && key in patches;\n const deleted =\n patched &&\n (typeof patched_value === \"undefined\" || patched_value === null);\n const value = patched && !deleted ? patched_value : original_value;\n !deleted &&\n (copy[key] = is_mergeable(value)\n ? patch(original_value || {}, patched_value || {})\n : value);\n });\n return copy as S;\n};\n\n/**\n * Validates a payload against a Zod schema, throwing a ValidationError on failure.\n *\n * @param target The name of the target (for error reporting)\n * @param payload The payload to validate\n * @param schema (Optional) The Zod schema to validate against\n * @returns The validated payload\n * @throws ValidationError if validation fails\n *\n * @example\n * const valid = validate(\"User\", userPayload, userSchema);\n */\nexport const validate = <S>(\n target: string,\n payload: Readonly<S>,\n schema?: ZodType<S>\n): Readonly<S> => {\n try {\n return schema ? schema.parse(payload) : payload;\n } catch (error) {\n if (error instanceof Error && error.name === \"ZodError\") {\n throw new ValidationError(\n target,\n payload,\n prettifyError(error as ZodError)\n );\n }\n throw new ValidationError(target, payload, error);\n }\n};\n\n/**\n * Extends the target payload with the source payload after validating the source.\n *\n * @param source The source object to validate and merge\n * @param schema The Zod schema for the source\n * @param target (Optional) The target object to extend\n * @returns The merged and validated object\n *\n * @example\n * const config = extend(envConfig, configSchema, defaultConfig);\n */\nexport const extend = <\n S extends Record<string, unknown>,\n T extends Record<string, unknown>,\n>(\n source: Readonly<S>,\n schema: ZodType<S>,\n target?: Readonly<T>\n): Readonly<S & T> => {\n const value = validate(\"config\", source, schema);\n return Object.assign(target || {}, value) as Readonly<S & T>;\n};\n\n/**\n * Async helper to pause execution for a given number of milliseconds.\n *\n * @param ms (Optional) Milliseconds to sleep (defaults to config().sleepMs)\n * @returns Promise that resolves after the delay\n *\n * @example\n * await sleep(1000); // sleep for 1 second\n */\nexport async function sleep(ms?: number) {\n return new Promise((resolve) => setTimeout(resolve, ms ?? config().sleepMs));\n}\n","/**\n * @packageDocumentation\n * Configuration utilities for Act Framework environment, logging, and package metadata.\n *\n * Provides type-safe configuration loading and validation using Zod schemas.\n *\n * @module config\n */\nimport * as fs from \"node:fs\";\nimport { z } from \"zod\";\nimport {\n Environment,\n Environments,\n LogLevel,\n LogLevels,\n} from \"./types/index.js\";\nimport { extend } from \"./utils.js\";\n\n/**\n * Zod schema for validating package.json metadata.\n * @internal\n */\nexport const PackageSchema = z.object({\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string().min(1).optional(),\n author: z\n .object({ name: z.string().min(1), email: z.string().optional() })\n .optional()\n .or(z.string().min(1))\n .optional(),\n license: z.string().min(1).optional(),\n dependencies: z.record(z.string(), z.string()).optional(),\n});\n\n/**\n * Type representing the validated package.json metadata.\n */\nexport type Package = z.infer<typeof PackageSchema>;\n\n/**\n * Loads and parses the local package.json file as a Package object.\n * @returns The parsed and validated package metadata.\n * @internal\n */\nconst getPackage = (): Package => {\n const pkg = fs.readFileSync(\"package.json\");\n return JSON.parse(pkg.toString()) as Package;\n};\n\n/**\n * Zod schema for the full Act Framework configuration object.\n * Includes package metadata, environment, logging, and timing options.\n * @internal\n */\nconst BaseSchema = PackageSchema.extend({\n env: z.enum(Environments),\n logLevel: z.enum(LogLevels),\n logSingleLine: z.boolean(),\n sleepMs: z.number().int().min(0).max(5000),\n});\n\n/**\n * Type representing the validated Act Framework configuration object.\n */\nexport type Config = z.infer<typeof BaseSchema>;\n\nconst { NODE_ENV, LOG_LEVEL, LOG_SINGLE_LINE, SLEEP_MS } = process.env;\n\nconst env = (NODE_ENV || \"development\") as Environment;\nconst logLevel = (LOG_LEVEL ||\n (NODE_ENV === \"test\"\n ? \"error\"\n : NODE_ENV === \"production\"\n ? \"info\"\n : \"trace\")) as LogLevel;\nconst logSingleLine = (LOG_SINGLE_LINE || \"true\") === \"true\";\nconst sleepMs = parseInt(NODE_ENV === \"test\" ? \"0\" : (SLEEP_MS ?? \"100\"));\n\nconst pkg = getPackage();\n\n/**\n * Returns the current Act Framework configuration, validated and type-safe.\n *\n * Merges package.json metadata with environment, logging, and timing options.\n * @returns The validated configuration object.\n * @example\n * ```ts\n * const cfg = config();\n * console.log(cfg.env, cfg.logLevel);\n * ```\n */\nexport const config = (): Config => {\n return extend({ ...pkg, env, logLevel, logSingleLine, sleepMs }, BaseSchema);\n};\n","import { z, ZodObject, ZodRawShape } from \"zod\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n","/**\n * @packageDocumentation\n * @module act/adapters\n * In-memory event store adapter for the Act Framework.\n *\n * This adapter implements the Store interface and is suitable for development, testing, and demonstration purposes.\n * All data is stored in memory and lost on process exit.\n *\n * @category Adapters\n */\nimport { SNAP_EVENT } from \"../ports.js\";\nimport { ConcurrencyError } from \"../types/errors.js\";\nimport type {\n Committed,\n EventMeta,\n Lease,\n Message,\n Query,\n Schemas,\n Store,\n} from \"../types/index.js\";\nimport { sleep } from \"../utils.js\";\n\n/**\n * @internal\n * Represents an in-memory stream for event processing and leasing.\n */\nclass InMemoryStream {\n private _at = -1;\n private _retry = -1;\n private _blocked = false;\n private _error = \"\";\n private _leased_by: string | undefined = undefined;\n private _leased_until: Date | undefined = undefined;\n\n constructor(\n readonly stream: string,\n readonly source: string | undefined\n ) {}\n\n get is_avaliable() {\n return (\n !this._blocked &&\n (!this._leased_until || this._leased_until <= new Date())\n );\n }\n\n get at() {\n return this._at;\n }\n\n /**\n * Attempt to lease this stream for processing.\n * @param lease - The lease request.\n * @param millis - Lease duration in milliseconds.\n * @returns The granted lease or undefined if blocked.\n */\n lease(lease: Lease, millis: number): Lease | undefined {\n if (this.is_avaliable) {\n if (millis > 0) {\n this._leased_by = lease.by;\n this._leased_until = new Date(Date.now() + millis);\n this._retry = this._retry + 1;\n }\n return {\n stream: this.stream,\n source: this.source,\n at: lease.at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n };\n }\n }\n\n /**\n * Acknowledge completion of processing for this stream.\n * @param lease - The lease request.\n */\n ack(lease: Lease) {\n if (this._leased_by === lease.by) {\n this._leased_by = undefined;\n this._leased_until = undefined;\n this._at = lease.at;\n this._retry = -1;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n };\n }\n }\n\n /**\n * Block a stream for processing after failing to process and reaching max retries with blocking enabled.\n * @param lease - The lease request.\n * @param error Blocked error message.\n */\n block(lease: Lease, error: string) {\n if (this._leased_by === lease.by) {\n this._blocked = true;\n this._error = error;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: this._leased_by,\n retry: this._retry,\n error: this._error,\n lagging: lease.lagging,\n };\n }\n }\n}\n\n/**\n * @category Adapters\n * @see Store\n *\n * In-memory implementation of the Store interface.\n *\n * Suitable for development, testing, and demonstration. Not for production use.\n * All events and streams are stored in memory and lost on process exit.\n *\n * @example\n * const store = new InMemoryStore();\n * await store.commit('streamA', [{ name: 'event', data: {} }], meta);\n */\nexport class InMemoryStore implements Store {\n // stored events\n private _events: Committed<Schemas, keyof Schemas>[] = [];\n // stored stream positions and other metadata\n private _streams: Map<string, InMemoryStream> = new Map();\n\n /**\n * Dispose of the store and clear all events.\n * @returns Promise that resolves when disposal is complete.\n */\n async dispose() {\n await sleep();\n this._events.length = 0;\n }\n\n /**\n * Seed the store with initial data (no-op for in-memory).\n * @returns Promise that resolves when seeding is complete.\n */\n async seed() {\n await sleep();\n }\n\n /**\n * Drop all data from the store.\n * @returns Promise that resolves when the store is cleared.\n */\n async drop() {\n await sleep();\n this._events.length = 0;\n this._streams = new Map();\n }\n\n private in_query<E extends Schemas>(query: Query, e: Committed<E, keyof E>) {\n if (query.stream && !RegExp(`^${query.stream}$`).test(e.stream))\n return false;\n if (query.names && !query.names.includes(e.name as string)) return false;\n if (query.correlation && e.meta?.correlation !== query.correlation)\n return false;\n if (e.name === SNAP_EVENT && !query.with_snaps) return false;\n return true;\n }\n\n /**\n * Query events in the store, optionally filtered by query options.\n * @param callback - Function to call for each event.\n * @param query - Optional query options.\n * @returns The number of events processed.\n */\n async query<E extends Schemas>(\n callback: (event: Committed<E, keyof E>) => void,\n query?: Query\n ) {\n await sleep();\n let count = 0;\n if (query?.backward) {\n let i = (query?.before || this._events.length) - 1;\n while (i >= 0) {\n const e = this._events[i--];\n if (query && !this.in_query(query, e)) continue;\n if (query?.created_before && e.created >= query.created_before)\n continue;\n if (query.after && e.id <= query.after) break;\n if (query.created_after && e.created <= query.created_after) break;\n callback(e as Committed<E, keyof E>);\n count++;\n if (query?.limit && count >= query.limit) break;\n }\n } else {\n let i = (query?.after ?? -1) + 1;\n while (i < this._events.length) {\n const e = this._events[i++];\n if (query && !this.in_query(query, e)) continue;\n if (query?.created_after && e.created <= query.created_after) continue;\n if (query?.before && e.id >= query.before) break;\n if (query?.created_before && e.created >= query.created_before) break;\n callback(e as Committed<E, keyof E>);\n count++;\n if (query?.limit && count >= query.limit) break;\n }\n }\n return count;\n }\n\n /**\n * Commit one or more events to a stream.\n * @param stream - The stream name.\n * @param msgs - The events/messages to commit.\n * @param meta - Event metadata.\n * @param expectedVersion - Optional optimistic concurrency check.\n * @returns The committed events with metadata.\n * @throws ConcurrencyError if expectedVersion does not match.\n */\n async commit<E extends Schemas>(\n stream: string,\n msgs: Message<E, keyof E>[],\n meta: EventMeta,\n expectedVersion?: number\n ) {\n await sleep();\n const instance = this._events.filter((e) => e.stream === stream); // ignore state events, this is a production optimization\n if (\n typeof expectedVersion === \"number\" &&\n instance.length - 1 !== expectedVersion\n ) {\n throw new ConcurrencyError(\n stream,\n instance.length - 1,\n msgs as Message<Schemas, keyof Schemas>[],\n expectedVersion\n );\n }\n\n let version = instance.length;\n return msgs.map(({ name, data }) => {\n const committed: Committed<E, keyof E> = {\n id: this._events.length,\n stream,\n version,\n created: new Date(),\n name,\n data,\n meta,\n };\n this._events.push(committed as Committed<Schemas, keyof Schemas>);\n version++;\n return committed;\n });\n }\n\n /**\n * Polls the store for unblocked streams needing processing, ordered by lease watermark ascending.\n * @param lagging - Max number of streams to poll in ascending order.\n * @param leading - Max number of streams to poll in descending order.\n * @returns The polled streams.\n */\n async poll(lagging: number, leading: number) {\n await sleep();\n const a = [...this._streams.values()]\n .filter((s) => s.is_avaliable)\n .sort((a, b) => a.at - b.at)\n .slice(0, lagging)\n .map(({ stream, source, at }) => ({\n stream,\n source,\n at,\n lagging: true,\n }));\n const b = [...this._streams.values()]\n .filter((s) => s.is_avaliable)\n .sort((a, b) => b.at - a.at)\n .slice(0, leading)\n .map(({ stream, source, at }) => ({\n stream,\n source,\n at,\n lagging: false,\n }));\n return [...a, ...b];\n }\n\n /**\n * Lease streams for processing (e.g., for distributed consumers).\n * @param leases - Lease requests for streams, including end-of-lease watermark, lease holder, and source stream.\n * @param leaseMilis - Lease duration in milliseconds.\n * @returns Granted leases.\n */\n async lease(leases: Lease[], millis: number) {\n await sleep();\n return leases\n .map((l) => {\n if (!this._streams.has(l.stream)) {\n // store new correlations\n this._streams.set(l.stream, new InMemoryStream(l.stream, l.source));\n }\n return this._streams.get(l.stream)?.lease(l, millis);\n })\n .filter((l) => !!l);\n }\n\n /**\n * Acknowledge completion of processing for leased streams.\n * @param leases - Leases to acknowledge, including last processed watermark and lease holder.\n */\n async ack(leases: Lease[]) {\n await sleep();\n return leases\n .map((l) => this._streams.get(l.stream)?.ack(l))\n .filter((l) => !!l);\n }\n\n /**\n * Block a stream for processing after failing to process and reaching max retries with blocking enabled.\n * @param leases - Leases to block, including lease holder and last error message.\n * @returns Blocked leases.\n */\n async block(leases: Array<Lease & { error: string }>) {\n await sleep();\n return leases\n .map((l) => this._streams.get(l.stream)?.block(l, l.error))\n .filter((l) => !!l);\n }\n}\n","import { disposeAndExit, logger } from \"./ports.js\";\n\n// exit on signals\nprocess.once(\"SIGINT\", async (arg?: any) => {\n logger.info(arg, \"SIGINT\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"SIGTERM\", async (arg?: any) => {\n logger.info(arg, \"SIGTERM\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"uncaughtException\", async (arg?: any) => {\n logger.error(arg, \"Uncaught Exception\");\n await disposeAndExit(\"ERROR\");\n});\nprocess.once(\"unhandledRejection\", async (arg?: any) => {\n logger.error(arg, \"Unhandled Rejection\");\n await disposeAndExit(\"ERROR\");\n});\n","import { randomUUID } from \"crypto\";\nimport EventEmitter from \"events\";\nimport { config } from \"./config.js\";\nimport * as es from \"./event-sourcing.js\";\nimport { build_tracer, dispose, logger, store } from \"./ports.js\";\nimport type {\n Committed,\n Drain,\n DrainOptions,\n Lease,\n Query,\n ReactionPayload,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"./types/index.js\";\n\nconst tracer = build_tracer(config().logLevel);\n\n/**\n * @category Orchestrator\n * @see Store\n *\n * Main orchestrator for event-sourced state machines and workflows.\n *\n * It manages the lifecycle of actions, reactions, and event streams, providing APIs for loading state, executing actions, querying events, and draining reactions.\n *\n * ## Usage\n *\n * ```typescript\n * const app = new Act(registry, 100);\n * await app.do(\"increment\", { stream: \"counter1\", actor }, { by: 1 });\n * const snapshot = await app.load(Counter, \"counter1\");\n * await app.drain();\n * ```\n *\n * - Register event listeners with `.on(\"committed\", ...)` and `.on(\"acked\", ...)` to react to lifecycle events.\n * - Use `.query()` to analyze event streams for analytics or debugging.\n *\n * @template S SchemaRegister for state\n * @template E Schemas for events\n * @template A Schemas for actions\n */\nexport class Act<\n S extends SchemaRegister<A>,\n E extends Schemas,\n A extends Schemas,\n> {\n private _emitter = new EventEmitter();\n private _drain_locked = false;\n private _drain_lag2lead_ratio = 0.5;\n private _correlation_interval: NodeJS.Timeout | undefined = undefined;\n\n /**\n * Emit a lifecycle event (internal use, but can be used for custom listeners).\n *\n * @param event The event name (\"committed\", \"acked\", or \"blocked\")\n * @param args The event payload\n * @returns true if the event had listeners, false otherwise\n */\n emit(event: \"committed\", args: Snapshot<S, E>[]): boolean;\n emit(event: \"acked\", args: Lease[]): boolean;\n emit(event: \"blocked\", args: Array<Lease & { error: string }>): boolean;\n emit(event: string, args: any): boolean {\n return this._emitter.emit(event, args);\n }\n\n /**\n * Register a listener for a lifecycle event (\"committed\", \"acked\", or \"blocked\").\n *\n * @param event The event name\n * @param listener The callback function\n * @returns this (for chaining)\n */\n on(event: \"committed\", listener: (args: Snapshot<S, E>[]) => void): this;\n on(event: \"acked\", listener: (args: Lease[]) => void): this;\n on(\n event: \"blocked\",\n listener: (args: Array<Lease & { error: string }>) => void\n ): this;\n on(event: string, listener: (args: any) => void): this {\n this._emitter.on(event, listener);\n return this;\n }\n\n /**\n * Remove a listener for a lifecycle event.\n *\n * @param event The event name\n * @param listener The callback function\n * @returns this (for chaining)\n */\n off(event: \"committed\", listener: (args: Snapshot<S, E>[]) => void): this;\n off(event: \"acked\", listener: (args: Lease[]) => void): this;\n off(\n event: \"blocked\",\n listener: (args: Array<Lease & { error: string }>) => void\n ): this;\n off(event: string, listener: (args: any) => void): this {\n this._emitter.off(event, listener);\n return this;\n }\n\n /**\n * Create a new Act orchestrator.\n *\n * @param registry The registry of state, event, and action schemas\n */\n constructor(public readonly registry: Registry<S, E, A>) {\n dispose(() => {\n this._emitter.removeAllListeners();\n this.stop_correlations();\n return Promise.resolve();\n });\n }\n\n /**\n * Executes an action (command) against a state machine, emitting and committing the resulting event(s).\n *\n * @template K The type of action to execute\n * @param action The action name (key of the action schema)\n * @param target The target (stream and actor) for the action\n * @param payload The action payload (validated against the schema)\n * @param reactingTo (Optional) The event this action is reacting to\n * @param skipValidation (Optional) If true, skips schema validation (not recommended)\n * @returns The snapshot of the committed event\n *\n * @example\n * await app.do(\"increment\", { stream: \"counter1\", actor }, { by: 1 });\n */\n async do<K extends keyof A>(\n action: K,\n target: Target,\n payload: Readonly<A[K]>,\n reactingTo?: Committed<E, keyof E>,\n skipValidation = false\n ) {\n const snapshots = await es.action(\n this.registry.actions[action],\n action,\n target,\n payload,\n // @ts-expect-error type lost\n reactingTo,\n skipValidation\n );\n this.emit(\"committed\", snapshots as Snapshot<S, E>[]);\n return snapshots;\n }\n\n /**\n * Loads the current state snapshot for a given state machine and stream.\n *\n * @template SX The type of state\n * @template EX The type of events\n * @template AX The type of actions\n * @param state The state machine definition\n * @param stream The stream (instance) to load\n * @param callback (Optional) Callback to receive the loaded snapshot\n * @returns The snapshot of the loaded state\n *\n * @example\n * const snapshot = await app.load(Counter, \"counter1\");\n */\n async load<SX extends Schema, EX extends Schemas, AX extends Schemas>(\n state: State<SX, EX, AX>,\n stream: string,\n callback?: (snapshot: Snapshot<SX, EX>) => void\n ): Promise<Snapshot<SX, EX>> {\n return await es.load(state, stream, callback);\n }\n\n /**\n * Query the event store for events matching a filter.\n *\n * @param query The query filter (e.g., by stream, event name, or time range)\n * @param callback (Optional) Callback for each event found\n * @returns An object with the first and last event found, and the total count\n *\n * @example\n * const { count } = await app.query({ stream: \"counter1\" }, (event) => console.log(event));\n */\n async query(\n query: Query,\n callback?: (event: Committed<E, keyof E>) => void\n ): Promise<{\n first?: Committed<E, keyof E>;\n last?: Committed<E, keyof E>;\n count: number;\n }> {\n let first: Committed<E, keyof E> | undefined = undefined,\n last: Committed<E, keyof E> | undefined = undefined;\n const count = await store().query<E>((e) => {\n !first && (first = e);\n last = e;\n callback && callback(e);\n }, query);\n return { first, last, count };\n }\n\n /**\n * Query the event store for events matching a filter.\n * Use this version with caution, as it return events in memory.\n *\n * @param query The query filter (e.g., by stream, event name, or time range)\n * @returns The matching events\n *\n * @example\n * const { count } = await app.query({ stream: \"counter1\" }, (event) => console.log(event));\n */\n async query_array(query: Query): Promise<Committed<E, keyof E>[]> {\n const events: Committed<E, keyof E>[] = [];\n await store().query<E>((e) => events.push(e), query);\n return events;\n }\n\n /**\n * Handles leased reactions.\n *\n * This is called by the main `drain` loop after fetching new events.\n * It handles reactions, supporting retries, blocking, and error handling.\n *\n * @internal\n * @param lease The lease to handle\n * @param payloads The reactions to handle\n * @returns The lease with results\n */\n private async handle<E extends Schemas>(\n lease: Lease,\n payloads: ReactionPayload<E>[]\n ): Promise<{\n readonly lease: Lease;\n readonly handled: number;\n readonly at: number;\n readonly error?: string;\n readonly block?: boolean;\n }> {\n // no payloads, just advance the lease\n if (payloads.length === 0) return { lease, handled: 0, at: lease.at };\n\n const stream = lease.stream;\n let at = payloads.at(0)!.event.id,\n handled = 0;\n\n lease.retry > 0 &&\n logger.warn(`Retrying ${stream}@${at} (${lease.retry}).`);\n\n for (const payload of payloads) {\n const { event, handler, options } = payload;\n try {\n await handler(event, stream); // the actual reaction\n at = event.id;\n handled++;\n } catch (error) {\n logger.error(error);\n const block = lease.retry >= options.maxRetries && options.blockOnError;\n block &&\n logger.error(`Blocking ${stream} after ${lease.retry} retries.`);\n return {\n lease,\n handled,\n at,\n // only report error when nothing was handled\n error: handled === 0 ? (error as Error).message : undefined,\n block,\n };\n }\n }\n return { lease, handled, at };\n }\n\n /**\n * Drains and processes events from the store, triggering reactions and updating state.\n *\n * This is typically called in a background loop or after committing new events.\n *\n * @returns The number of events drained and processed\n *\n * @example\n * await app.drain();\n */\n async drain<E extends Schemas>({\n streamLimit = 10,\n eventLimit = 10,\n leaseMillis = 10_000,\n }: DrainOptions = {}): Promise<Drain<E>> {\n if (!this._drain_locked) {\n try {\n this._drain_locked = true;\n const lagging = Math.ceil(streamLimit * this._drain_lag2lead_ratio);\n const leading = streamLimit - lagging;\n const polled = await store().poll(lagging, leading);\n const fetched = await Promise.all(\n polled.map(async ({ stream, source, at, lagging }) => {\n const events = await this.query_array({\n stream: source,\n after: at,\n limit: eventLimit,\n });\n return { stream, source, at, lagging, events } as const;\n })\n );\n if (fetched.length) {\n tracer.fetched(fetched);\n\n const leases = new Map<\n string,\n { lease: Lease; lagging: boolean; payloads: ReactionPayload<E>[] }\n >();\n\n // compute fetch window max event id\n const fetch_window_at = fetched.reduce(\n (max, { at, events }) => Math.max(max, events.at(-1)?.id || at),\n 0\n );\n\n fetched.forEach(({ stream, lagging, events }) => {\n const payloads = events.flatMap((event) => {\n const register = this.registry.events[event.name] || [];\n return [...register.reactions.values()]\n .filter((reaction) => {\n const resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n return resolved && resolved.target === stream;\n })\n .map((reaction) => ({ ...reaction, event }));\n });\n leases.set(stream, {\n lease: {\n stream,\n by: randomUUID(),\n at: events.at(-1)?.id || fetch_window_at, // ff when no matching events\n retry: 0,\n lagging,\n },\n // @ts-expect-error indexed by key\n payloads,\n });\n });\n\n const leased = await store().lease(\n [...leases.values()].map(({ lease }) => lease),\n leaseMillis\n );\n tracer.leased(leased);\n\n const handled = await Promise.all(\n leased.map((lease) =>\n this.handle(lease, leases.get(lease.stream)!.payloads)\n )\n );\n\n // adaptive drain ratio based on handled events, favors frontier with highest pressure (clamped between 20% and 80%)\n const [lagging_handled, leading_handled] = handled.reduce(\n ([lagging_handled, leading_handled], { lease, handled }) => [\n lagging_handled + (lease.lagging ? handled : 0),\n leading_handled + (lease.lagging ? 0 : handled),\n ],\n [0, 0]\n );\n const lagging_avg = lagging > 0 ? lagging_handled / lagging : 0;\n const leading_avg = leading > 0 ? leading_handled / leading : 0;\n const total = lagging_avg + leading_avg;\n this._drain_lag2lead_ratio =\n total > 0 ? Math.max(0.2, Math.min(0.8, lagging_avg / total)) : 0.5;\n\n const acked = await store().ack(\n handled\n .filter(({ error }) => !error)\n .map(({ at, lease }) => ({ ...lease, at }))\n );\n if (acked.length) {\n tracer.acked(acked);\n this.emit(\"acked\", acked);\n }\n\n const blocked = await store().block(\n handled\n .filter(({ block }) => block)\n .map(({ lease, error }) => ({ ...lease, error: error! }))\n );\n if (blocked.length) {\n tracer.blocked(blocked);\n this.emit(\"blocked\", blocked);\n }\n\n // @ts-expect-error key\n return { fetched, leased, acked, blocked };\n }\n } catch (error) {\n logger.error(error);\n } finally {\n this._drain_locked = false;\n }\n }\n\n return { fetched: [], leased: [], acked: [], blocked: [] };\n }\n\n /**\n * Correlates streams using reaction resolvers.\n * @param query - The query filter (e.g., by stream, event name, or starting point).\n * @returns The leases of newly correlated streams, and the last seen event ID.\n */\n async correlate(\n query: Query = { after: -1, limit: 10 }\n ): Promise<{ leased: Lease[]; last_id: number }> {\n const correlated = new Map<string, ReactionPayload<E>[]>();\n let last_id = query.after || -1;\n await store().query<E>((event) => {\n last_id = event.id;\n const register = this.registry.events[event.name];\n // skip events with no registered reactions\n if (register) {\n for (const reaction of register.reactions.values()) {\n const resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n resolved &&\n (\n correlated.get(resolved.target) ||\n correlated.set(resolved.target, []).get(resolved.target)!\n ).push({ ...reaction, source: resolved.source, event });\n }\n }\n }, query);\n if (correlated.size) {\n const leases = [...correlated.entries()].map(([stream, payloads]) => ({\n stream,\n // TODO: by convention, the first defined source wins (this can be tricky)\n source: payloads.find((p) => p.source)?.source || undefined,\n by: randomUUID(),\n at: 0,\n retry: 0,\n lagging: true,\n payloads,\n }));\n // register leases with 0ms lease timeout (just to tag the new streams)\n const leased = await store().lease(leases, 0);\n leased.length && tracer.correlated(leased);\n return { leased, last_id };\n }\n return { leased: [], last_id };\n }\n\n /**\n * Starts correlation worker that identifies and registers new streams using reaction resolvers.\n *\n * Enables \"dynamic reactions\", allowing streams to be auto-discovered based on event content.\n * - Uses a correlation sliding window over the event stream to identify new streams.\n * - Once registered, these streams are picked up by the main `drain` loop.\n * - Users should have full control over their correlation strategy.\n * - The starting point keeps increasing with each new batch of events.\n * - Users are responsible for storing the last seen event ID.\n *\n * @param query - The query filter (e.g., by stream, event name, or starting point).\n * @param frequency - The frequency of correlation checks (in milliseconds).\n * @param callback - Callback to report stats (new strems, last seen event ID, etc.).\n * @returns true if the correlation worker started, false otherwise (already started).\n */\n start_correlations(\n query: Query = {},\n frequency = 10_000,\n callback?: (leased: Lease[]) => void\n ): boolean {\n if (this._correlation_interval) return false;\n\n const limit = query.limit || 100;\n let after = query.after || -1;\n this._correlation_interval = setInterval(\n () =>\n this.correlate({ ...query, after, limit })\n .then((result) => {\n after = result.last_id;\n if (callback && result.leased.length) callback(result.leased);\n })\n .catch(console.error),\n frequency\n );\n return true;\n }\n\n stop_correlations() {\n if (this._correlation_interval) {\n clearInterval(this._correlation_interval);\n this._correlation_interval = undefined;\n }\n }\n}\n","/**\n * @module event-sourcing\n * @category Event Sourcing\n *\n * Utilities for event sourcing, snapshotting, and event store interaction.\n */\n\nimport { randomUUID } from \"crypto\";\nimport { logger, SNAP_EVENT, store } from \"./ports.js\";\nimport { InvariantError } from \"./types/errors.js\";\nimport type {\n Committed,\n Emitted,\n EventMeta,\n Schema,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"./types/index.js\";\nimport { patch, validate } from \"./utils.js\";\n\n/**\n * Event sourcing utilities for snapshotting, loading, and committing actions/events.\n * Used internally by Act and state machines.\n */\n\n/**\n * Saves a snapshot of the state to the store.\n *\n * Snapshots are used to optimize state reconstruction for aggregates with long event streams.\n *\n * @template S The type of state\n * @template E The type of events\n * @param snapshot The snapshot to save\n * @returns Promise that resolves when the snapshot is saved\n *\n * @example\n * await snap(snapshot);\n */\nexport async function snap<S extends Schema, E extends Schemas>(\n snapshot: Snapshot<S, E>\n): Promise<void> {\n try {\n const { id, stream, name, meta, version } = snapshot.event!;\n const snapped = await store().commit(\n stream,\n [{ name: SNAP_EVENT, data: snapshot.state }],\n {\n correlation: meta.correlation,\n causation: { event: { id, name: name as string, stream } },\n },\n version // IMPORTANT! - state events are committed right after the snapshot event\n );\n logger.trace(snapped, \"🟠 snap\");\n } catch (error) {\n logger.error(error);\n }\n}\n\n/**\n * Loads a snapshot of the state from the store by replaying events and applying patches.\n *\n * @template S The type of state\n * @template E The type of events\n * @template A The type of actions\n * @param me The state machine definition\n * @param stream The stream (instance) to load\n * @param callback (Optional) Callback to receive the loaded snapshot as it is built\n * @returns The snapshot of the loaded state\n *\n * @example\n * const snapshot = await load(Counter, \"counter1\");\n */\nexport async function load<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n>(\n me: State<S, E, A>,\n stream: string,\n callback?: (snapshot: Snapshot<S, E>) => void\n): Promise<Snapshot<S, E>> {\n let state = me.init ? me.init() : ({} as S);\n let patches = 0;\n let snaps = 0;\n let event: Committed<E, string> | undefined;\n await store().query(\n (e) => {\n event = e as Committed<E, string>;\n if (e.name === SNAP_EVENT) {\n state = e.data as S;\n snaps++;\n patches = 0;\n } else if (me.patch[e.name]) {\n state = patch(state, me.patch[e.name](event, state));\n patches++;\n }\n callback && callback({ event, state, patches, snaps });\n },\n { stream, with_snaps: true }\n );\n logger.trace(state as object, `🟢 load ${stream}`);\n return { event, state, patches, snaps };\n}\n\n/**\n * Executes an action and emits an event to be committed by the store.\n *\n * This function validates the action, applies business invariants, emits events, and commits them to the event store.\n *\n * @template S The type of state\n * @template E The type of events\n * @template A The type of actionSchemas\n * @template K The type of action to execute\n * @param me The state machine definition\n * @param action The action to execute\n * @param target The target (stream, actor, etc.)\n * @param payload The payload of the action\n * @param reactingTo (Optional) The event that the action is reacting to\n * @param skipValidation (Optional) Whether to skip validation (not recommended)\n * @returns The snapshot of the committed event\n *\n * @example\n * const snapshot = await action(Counter, \"increment\", { stream: \"counter1\", actor }, { by: 1 });\n */\nexport async function action<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n K extends keyof A,\n>(\n me: State<S, E, A>,\n action: K,\n target: Target,\n payload: Readonly<A[K]>,\n reactingTo?: Committed<Schemas, keyof Schemas>,\n skipValidation = false\n): Promise<Snapshot<S, E>[]> {\n const { stream, expectedVersion, actor } = target;\n if (!stream) throw new Error(\"Missing target stream\");\n\n payload = skipValidation\n ? payload\n : validate(action as string, payload, me.actions[action]);\n\n const snapshot = await load(me, stream);\n const expected = expectedVersion || snapshot.event?.version;\n\n logger.trace(\n payload as object,\n `🔵 ${stream}.${action as string}${typeof expected === \"number\" ? `.${expected}` : \"\"}`\n );\n\n if (me.given) {\n const invariants = me.given[action] || [];\n invariants.forEach(({ valid, description }) => {\n if (!valid(snapshot.state, actor))\n throw new InvariantError(\n action,\n payload,\n target,\n snapshot,\n description\n );\n });\n }\n\n const result = me.on[action](payload, snapshot, target);\n if (!result) return [snapshot];\n\n // An empty array means no events were emitted\n if (Array.isArray(result) && result.length === 0) {\n return [snapshot];\n }\n\n const tuples = Array.isArray(result[0])\n ? (result as Emitted<E>[]) // array of tuples\n : ([result] as Emitted<E>[]); // single tuple\n\n const emitted = tuples.map(([name, data]) => ({\n name,\n data: skipValidation\n ? data\n : validate(name as string, data, me.events[name]),\n }));\n\n const meta: EventMeta = {\n correlation: reactingTo?.meta.correlation || randomUUID(),\n causation: {\n action: {\n name: action as string,\n ...target,\n // payload: TODO: flag to include action payload in metadata\n // not included by default to avoid large payloads\n },\n event: reactingTo\n ? {\n id: reactingTo.id,\n name: reactingTo.name,\n stream: reactingTo.stream,\n }\n : undefined,\n },\n };\n\n logger.trace(\n emitted.map((e) => e.data),\n `🔴 commit ${stream}.${emitted.map((e) => e.name).join(\", \")}`\n );\n\n const committed = await store().commit(\n stream,\n emitted,\n meta,\n // TODO: review reactions not enforcing expected version\n reactingTo ? undefined : expected\n );\n\n let { state, patches } = snapshot;\n const snapshots = committed.map((event) => {\n state = patch(state, me.patch[event.name](event, state));\n patches++;\n return { event, state, patches, snaps: snapshot.snaps };\n });\n\n // fire and forget snaps\n const last = snapshots.at(-1)!;\n me.snap && me.snap(last) && void snap(last);\n\n return snapshots;\n}\n","/**\n * @module act-builder\n * @category Builders\n *\n * Fluent builder for composing event-sourced applications.\n */\nimport { Act } from \"./act.js\";\nimport type {\n EventRegister,\n Reaction,\n ReactionHandler,\n ReactionOptions,\n ReactionResolver,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"./types/index.js\";\n\n// resolves the event stream as source and target (default)\nconst _this_ = ({ stream }: { stream: string }) => ({\n source: stream,\n target: stream,\n});\n// resolves to nothing\nconst _void_ = () => undefined;\n\n/**\n * Fluent builder for composing event-sourced state machines with actions and reactions.\n *\n * Provides a chainable API for registering states, events, and reaction handlers, enabling you to declaratively build complex, reactive applications.\n *\n * @template S SchemaRegister for state\n * @template E Schemas for events\n * @template A Schemas for actions\n *\n * @example\n * const app = act()\n * .with(Counter)\n * .on(\"Incremented\").do(async (event) => { ... })\n * .to(() => \"OtherStream\")\n * .build();\n */\nexport type ActBuilder<\n S extends SchemaRegister<A>,\n E extends Schemas,\n A extends Schemas,\n> = {\n /**\n * Register a state machine with the builder.\n *\n * @template SX The type of state\n * @template EX The type of events\n * @template AX The type of actions\n * @param state The state machine to add\n * @returns The builder (for chaining)\n */\n with: <SX extends Schema, EX extends Schemas, AX extends Schemas>(\n state: State<SX, EX, AX>\n ) => ActBuilder<S & { [K in keyof AX]: SX }, E & EX, A & AX>;\n /**\n * Register a reaction handler for a given event.\n *\n * @template K The event name\n * @param event The event to react to\n * @returns An object with .do(handler) to register the handler\n */\n on: <K extends keyof E>(\n event: K\n ) => {\n /**\n * Register a reaction handler for the event.\n *\n * @param handler The reaction handler function\n * @param options (Optional) Reaction options (retries, blocking, etc.)\n * @returns The builder (for chaining), with .to(resolver) and .void() for advanced routing\n */\n do: (\n handler: ReactionHandler<E, K>,\n options?: Partial<ReactionOptions>\n ) => ActBuilder<S, E, A> & {\n /**\n * Route the reaction to a specific target and optionally source streams (resolver function).\n * @param resolver The resolver function or target stream name (all sources) as a shorthand\n * @returns The builder (for chaining)\n */\n to: (resolver: ReactionResolver<E, K> | string) => ActBuilder<S, E, A>;\n /**\n * Mark the reaction as void (no routing).\n * @returns The builder (for chaining)\n */\n void: () => ActBuilder<S, E, A>;\n };\n };\n /**\n * Build the application and return an Act orchestrator.\n *\n * @param drainLimit (Optional) The maximum number of events to drain per cycle (default: 10)\n * @returns The Act orchestrator instance\n */\n build: (drainLimit?: number) => Act<S, E, A>;\n /**\n * The registered event schemas and reaction maps.\n */\n readonly events: EventRegister<E>;\n};\n\n/* eslint-disable @typescript-eslint/no-empty-object-type */\n\n/**\n * Creates an ActBuilder instance for composing event-sourced applications.\n *\n * Use this function to start building your application by chaining `.with()`, `.on()`, and `.build()` calls.\n *\n * @template S The type of state\n * @template E The type of events\n * @template A The type of actions\n * @returns An ActBuilder instance\n *\n * @example\n * const app = act()\n * .with(Counter)\n * .on(\"Incremented\").do(async (event) => { ... })\n * .build();\n */\nexport function act<\n // @ts-expect-error empty schema\n S extends SchemaRegister<A> = {},\n E extends Schemas = {},\n A extends Schemas = {},\n>(\n states: Set<string> = new Set(),\n registry: Registry<S, E, A> = {\n actions: {} as any,\n events: {} as any,\n }\n): ActBuilder<S, E, A> {\n const builder: ActBuilder<S, E, A> = {\n /**\n * Adds a state to the builder.\n *\n * @template SX The type of state\n * @template EX The type of events\n * @template AX The type of actions\n * @param state The state to add\n * @returns The builder\n */\n with: <SX extends Schema, EX extends Schemas, AX extends Schemas>(\n state: State<SX, EX, AX>\n ) => {\n if (!states.has(state.name)) {\n states.add(state.name);\n for (const name of Object.keys(state.actions)) {\n if (registry.actions[name])\n throw new Error(`Duplicate action \"${name}\"`);\n // @ts-expect-error indexed access\n registry.actions[name] = state;\n }\n for (const name of Object.keys(state.events)) {\n if (registry.events[name])\n throw new Error(`Duplicate event \"${name}\"`);\n // @ts-expect-error indexed access\n registry.events[name] = {\n schema: state.events[name],\n reactions: new Map(),\n };\n }\n }\n return act<S & { [K in keyof AX]: SX }, E & EX, A & AX>(\n states,\n registry as unknown as Registry<\n S & { [K in keyof AX]: SX },\n E & EX,\n A & AX\n >\n );\n },\n /**\n * Adds a reaction to an event.\n *\n * @template K The type of event\n * @param event The event to add a reaction to\n * @returns The builder\n */\n on: <K extends keyof E>(event: K) => ({\n do: (\n handler: ReactionHandler<E, K>,\n options?: Partial<ReactionOptions>\n ) => {\n const reaction: Reaction<E, K> = {\n handler,\n resolver: _this_,\n options: {\n blockOnError: options?.blockOnError ?? true,\n maxRetries: options?.maxRetries ?? 3,\n },\n };\n registry.events[event].reactions.set(handler.name, reaction);\n return {\n ...builder,\n to(resolver: ReactionResolver<E, K> | string) {\n registry.events[event].reactions.set(handler.name, {\n ...reaction,\n resolver:\n typeof resolver === \"string\" ? { target: resolver } : resolver,\n });\n return builder;\n },\n void() {\n registry.events[event].reactions.set(handler.name, {\n ...reaction,\n resolver: _void_,\n });\n return builder;\n },\n };\n },\n }),\n build: () => new Act<S, E, A>(registry),\n events: registry.events,\n };\n return builder;\n}\n","/**\n * @module state-builder\n * @category Builders\n *\n * Fluent interface for defining a strongly-typed state machine using Zod schemas.\n */\nimport { ZodType } from \"zod\";\nimport {\n ActionHandler,\n ActionHandlers,\n GivenHandlers,\n Invariant,\n PatchHandlers,\n Schema,\n Schemas,\n Snapshot,\n State,\n ZodTypes,\n} from \"./types/index.js\";\n\n/* eslint-disable @typescript-eslint/no-empty-object-type */\nexport type StateBuilder<S extends Schema> = {\n /**\n * Define the initial state for the state machine.\n * @param init Function returning the initial state\n * @returns An object with .emits() to declare event types\n */\n init: (init: () => Readonly<S>) => {\n /**\n * Declare the event types the state machine can emit.\n * @param events Zod schemas for each event\n * @returns An object with .patch() to define event handlers\n */\n emits: <E extends Schemas>(\n events: ZodTypes<E>\n ) => {\n /**\n * Define how each event updates state.\n * @param patch Event handler functions\n * @returns An ActionBuilder for defining actions\n */\n patch: (patch: PatchHandlers<S, E>) => ActionBuilder<S, E, {}>;\n };\n };\n};\n\nexport type ActionBuilder<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n> = {\n /**\n * Define an action for the state machine.\n * @param action The action name\n * @param schema The Zod schema for the action payload\n * @returns An object with .given() and .emit() for further configuration\n */\n on: <K extends string, AX extends Schema>(\n action: K,\n schema: ZodType<AX>\n ) => {\n /**\n * Constrain the action with invariants (business rules).\n * @param rules Array of invariants\n * @returns An object with .emit() to finalize the action\n */\n given: (rules: Invariant<S>[]) => {\n /**\n * Finalize the action by providing the event emission handler.\n * @param handler The action handler function\n * @returns The ActionBuilder for chaining\n */\n emit: (\n handler: ActionHandler<S, E, { [P in K]: AX }, K>\n ) => ActionBuilder<S, E, A & { [P in K]: AX }>;\n };\n /**\n * Finalize the action by providing the event emission handler.\n * @param handler The action handler function\n * @returns The ActionBuilder for chaining\n */\n emit: (\n handler: ActionHandler<S, E, { [P in K]: AX }, K>\n ) => ActionBuilder<S, E, A & { [P in K]: AX }>;\n };\n /**\n * Define a snapshotting strategy to reduce recomputations.\n * @param snap Function that determines when to snapshot\n * @returns The ActionBuilder for chaining\n */\n snap: (snap: (snapshot: Snapshot<S, E>) => boolean) => ActionBuilder<S, E, A>;\n /**\n * Finalize and build the state machine definition.\n * @returns The strongly-typed State definition\n */\n build: () => State<S, E, A>;\n};\n\n/**\n * Fluent interface for defining a strongly-typed state machine using Zod schemas.\n *\n * This builder helps you model a system where:\n * - You start by defining the state schema with `state(name, zodSchema)`\n * - Then, provide the initial state using `.init(() => defaultState)`\n * - Declare the event types your system can emit using `.emits({ ... })`\n * - Define how emitted events update state with `.patch({ ... })`\n * - Define actions using `.on(\"actionName\", actionSchema)`\n * - Optionally constrain the action with `.given([...invariants])`\n * - Then finalize the action behavior with `.emit(handler)`\n * - (Optional) Define a `.snap(snapshot => boolean)` function to reduce recomputations\n * - Finalize the state machine definition using `.build()`\n *\n * @template S The type of state\n *\n * @example\n * const machine = state(\"machine\", myStateSchema)\n * .init(() => ({ count: 0 }))\n * .emits({ Incremented: z.object({ amount: z.number() }) })\n * .patch({\n * Incremented: (event, state) => ({ count: state.count + event.amount })\n * })\n * .on(\"increment\", z.object({ by: z.number() }))\n * .given([{ description: \"must be positive\", valid: (s, a) => a?.by > 0 }])\n * .emit((action, state) => ({ type: \"Incremented\", amount: action.by }))\n * .build();\n */\nexport function state<S extends Schema>(\n name: string,\n state: ZodType<S>\n): StateBuilder<S> {\n return {\n init(init: () => Readonly<S>) {\n return {\n emits<E extends Schema>(events: ZodTypes<E>) {\n return {\n patch(patch: PatchHandlers<S, E>) {\n return action_builder<S, E, {}>({\n events,\n actions: {},\n state,\n name,\n init,\n patch,\n on: {},\n });\n },\n };\n },\n };\n },\n };\n}\n\nfunction action_builder<S extends Schema, E extends Schemas, A extends Schemas>(\n state: State<S, E, A>\n): ActionBuilder<S, E, A> {\n return {\n on<K extends string, AX extends Schema>(action: K, schema: ZodType<AX>) {\n if (action in state.actions)\n throw new Error(`Duplicate action \"${action}\"`);\n\n type NewA = A & { [P in K]: AX };\n const actions = { ...state.actions, [action]: schema } as ZodTypes<NewA>;\n const on = { ...state.on } as ActionHandlers<S, E, NewA>;\n const _given = { ...state.given } as GivenHandlers<S, NewA>;\n\n function given(rules: Invariant<S>[]) {\n _given[action] = rules;\n return { emit };\n }\n\n function emit(handler: ActionHandler<S, E, NewA, K>) {\n on[action] = handler;\n return action_builder<S, E, NewA>({\n ...state,\n actions,\n on,\n given: _given,\n });\n }\n\n return { given, emit };\n },\n\n snap(snap: (snapshot: Snapshot<S, E>) => boolean) {\n return action_builder<S, E, A>({ ...state, snap });\n },\n\n build(): State<S, E, A> {\n return state;\n },\n };\n}\n"],"mappings":"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","names":["action","z","z","pkg","a","b","store","logLevel","stream","randomUUID","state","action","action","state","lagging","randomUUID","lagging_handled","leading_handled","handled","state","state","patch","action","snap"]}
1
+ {"version":3,"sources":["../src/ports.ts","../src/types/errors.ts","../src/utils.ts","../src/config.ts","../src/types/schemas.ts","../src/types/index.ts","../src/adapters/InMemoryStore.ts","../src/signals.ts","../src/act.ts","../src/event-sourcing.ts","../src/act-builder.ts","../src/state-builder.ts"],"sourcesContent":["import { pino } from \"pino\";\nimport { InMemoryStore } from \"./adapters/InMemoryStore.js\";\nimport { config } from \"./config.js\";\nimport type {\n Disposable,\n Disposer,\n Fetch,\n Lease,\n LogLevel,\n Schemas,\n Store,\n} from \"./types/index.js\";\n\n/**\n * Port and adapter utilities for logging, store management, and resource disposal.\n *\n * Provides singleton store and logger instances, and helpers for resource lifecycle management.\n *\n * - Use `store()` to get or inject the event store (in-memory or persistent).\n * - Use `logger` for structured logging.\n * - Use `dispose()` to register resource disposers for graceful shutdown.\n *\n * @module ports\n */\n\n/**\n * List of exit codes for process termination.\n */\nexport const ExitCodes = [\"ERROR\", \"EXIT\"] as const;\n\n/**\n * Type for allowed exit codes.\n */\nexport type ExitCode = (typeof ExitCodes)[number];\n\n/**\n * Singleton logger instance (Pino).\n *\n * Use for structured logging throughout your application.\n *\n * @example\n * logger.info(\"Application started\");\n */\nexport const logger = pino({\n transport:\n config().env !== \"production\"\n ? {\n target: \"pino-pretty\",\n options: {\n ignore: \"pid,hostname\",\n singleLine: config().logSingleLine,\n colorize: true,\n },\n }\n : undefined,\n level: config().logLevel,\n});\n\n/**\n * Helper to create a singleton port (adapter) with optional injection.\n *\n * @param injector The function that creates the port/adapter\n * @returns A function to get or inject the singleton instance\n *\n * @example\n * const store = port((adapter) => adapter || new InMemoryStore());\n * const myStore = store();\n */\ntype Injector<Port extends Disposable> = (adapter?: Port) => Port;\nconst adapters = new Map<string, Disposable>();\nexport function port<Port extends Disposable>(injector: Injector<Port>) {\n return function (adapter?: Port): Port {\n if (!adapters.has(injector.name)) {\n const injected = injector(adapter);\n adapters.set(injector.name, injected);\n logger.info(`🔌 injected ${injector.name}:${injected.constructor.name}`);\n }\n return adapters.get(injector.name) as Port;\n };\n}\n\nconst disposers: Disposer[] = [];\nexport async function disposeAndExit(code: ExitCode = \"EXIT\"): Promise<void> {\n // ignore when errors are caught in production\n if (code === \"ERROR\" && config().env === \"production\") return;\n\n await Promise.all(disposers.map((disposer) => disposer()));\n await Promise.all(\n [...adapters.values()].reverse().map(async (adapter) => {\n await adapter.dispose();\n logger.info(`🔌 disposed ${adapter.constructor.name}`);\n })\n );\n adapters.clear();\n config().env !== \"test\" && process.exit(code === \"ERROR\" ? 1 : 0);\n}\n\n/**\n * Registers resource cleanup functions for graceful shutdown.\n *\n * Disposers are called automatically when the process exits (SIGINT, SIGTERM)\n * or when manually triggered. They execute in reverse registration order,\n * allowing proper cleanup of dependent resources.\n *\n * Act automatically disposes registered stores and adapters. Use this function\n * to register additional cleanup for your own resources (database connections,\n * file handles, timers, etc.).\n *\n * @param disposer - Async function to call during cleanup\n * @returns Function to manually trigger disposal and exit\n *\n * @example Register custom resource cleanup\n * ```typescript\n * import { dispose } from \"@rotorsoft/act\";\n *\n * const redis = createRedisClient();\n *\n * dispose(async () => {\n * console.log(\"Closing Redis connection...\");\n * await redis.quit();\n * });\n *\n * // On SIGINT/SIGTERM, Redis will be cleaned up automatically\n * ```\n *\n * @example Multiple disposers in order\n * ```typescript\n * import { dispose } from \"@rotorsoft/act\";\n *\n * const db = connectDatabase();\n * dispose(async () => {\n * console.log(\"Closing database...\");\n * await db.close();\n * });\n *\n * const cache = connectCache();\n * dispose(async () => {\n * console.log(\"Closing cache...\");\n * await cache.disconnect();\n * });\n *\n * // On exit: cache closes first, then database\n * ```\n *\n * @example Manual cleanup trigger\n * ```typescript\n * import { dispose } from \"@rotorsoft/act\";\n *\n * const shutdown = dispose(async () => {\n * await cleanup();\n * });\n *\n * // Manually trigger cleanup and exit\n * process.on(\"SIGUSR2\", async () => {\n * console.log(\"Manual shutdown requested\");\n * await shutdown(\"EXIT\");\n * });\n * ```\n *\n * @example With error handling\n * ```typescript\n * import { dispose } from \"@rotorsoft/act\";\n *\n * dispose(async () => {\n * try {\n * await expensiveCleanup();\n * } catch (error) {\n * console.error(\"Cleanup failed:\", error);\n * // Error doesn't prevent other disposers from running\n * }\n * });\n * ```\n *\n * @see {@link Disposer} for disposer function type\n * @see {@link Disposable} for disposable interface\n */\nexport function dispose(\n disposer?: Disposer\n): (code?: ExitCode) => Promise<void> {\n disposer && disposers.push(disposer);\n return disposeAndExit;\n}\n\n/**\n * Special event name for snapshot events in the event store.\n */\nexport const SNAP_EVENT = \"__snapshot__\";\n\n/**\n * Gets or injects the singleton event store.\n *\n * By default, Act uses an in-memory store suitable for development and testing.\n * For production, inject a persistent store like PostgresStore before building\n * your application.\n *\n * **Important:** Store injection must happen before creating any Act instances.\n * Once set, the store cannot be changed without restarting the application.\n *\n * @param adapter - Optional store implementation to inject\n * @returns The singleton store instance\n *\n * @example Using default in-memory store\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n *\n * const currentStore = store(); // Returns InMemoryStore\n * ```\n *\n * @example Injecting PostgreSQL store\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n * import { PostgresStore } from \"@rotorsoft/act-pg\";\n *\n * // Inject before building your app\n * store(new PostgresStore({\n * host: \"localhost\",\n * port: 5432,\n * database: \"myapp\",\n * user: \"postgres\",\n * password: \"secret\",\n * schema: \"public\",\n * table: \"events\"\n * }));\n *\n * // Now build your app - it will use PostgreSQL\n * const app = act()\n * .with(Counter)\n * .build();\n * ```\n *\n * @example With environment-based configuration\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n * import { PostgresStore } from \"@rotorsoft/act-pg\";\n *\n * if (process.env.NODE_ENV === \"production\") {\n * store(new PostgresStore({\n * host: process.env.DB_HOST,\n * port: parseInt(process.env.DB_PORT || \"5432\"),\n * database: process.env.DB_NAME,\n * user: process.env.DB_USER,\n * password: process.env.DB_PASSWORD\n * }));\n * }\n * // Development uses default in-memory store\n * ```\n *\n * @example Testing with fresh store\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n *\n * beforeEach(async () => {\n * // Reset store between tests\n * await store().seed();\n * });\n *\n * afterAll(async () => {\n * // Cleanup\n * await store().drop();\n * });\n * ```\n *\n * @see {@link Store} for the store interface\n * @see {@link InMemoryStore} for the default implementation\n * @see {@link PostgresStore} for production use\n */\nexport const store = port(function store(adapter?: Store) {\n return adapter || new InMemoryStore();\n});\n\n/**\n * Tracer builder for logging fetches, leases, etc.\n */\nexport function build_tracer(logLevel: LogLevel): {\n fetched: <E extends Schemas>(fetched: Fetch<E>) => void;\n correlated: (leases: Lease[]) => void;\n leased: (leases: Lease[]) => void;\n acked: (leases: Lease[]) => void;\n blocked: (leases: Array<Lease & { error: string }>) => void;\n} {\n if (logLevel === \"trace\") {\n return {\n fetched: <E extends Schemas>(fetched: Fetch<E>) => {\n const data = Object.fromEntries(\n fetched.map(({ stream, source, events }) => {\n const key = source ? `${stream}<-${source}` : stream;\n const value = Object.fromEntries(\n events.map(({ id, stream, name }) => [id, { [stream]: name }])\n );\n return [key, value];\n })\n );\n logger.trace(data, \"⚡️ fetch\");\n },\n correlated: (leases: Lease[]) => {\n const data = leases.map(({ stream }) => stream).join(\" \");\n logger.trace(`⚡️ correlate ${data}`);\n },\n leased: (leases: Lease[]) => {\n const data = Object.fromEntries(\n leases.map(({ stream, at, retry }) => [stream, { at, retry }])\n );\n logger.trace(data, \"⚡️ lease\");\n },\n acked: (leases: Lease[]) => {\n const data = Object.fromEntries(\n leases.map(({ stream, at, retry }) => [stream, { at, retry }])\n );\n logger.trace(data, \"⚡️ ack\");\n },\n blocked: (leases: Array<Lease & { error: string }>) => {\n const data = Object.fromEntries(\n leases.map(({ stream, at, retry, error }) => [\n stream,\n { at, retry, error },\n ])\n );\n logger.trace(data, \"⚡️ block\");\n },\n };\n } else {\n return {\n fetched: () => {},\n correlated: () => {},\n leased: () => {},\n acked: () => {},\n blocked: () => {},\n };\n }\n}\n","import type { Message, Schema, Schemas, Snapshot, Target } from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n constructor(\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string,\n /** The invalid payload that failed validation */\n public readonly payload: any,\n /** Zod validation error details */\n public readonly details: any\n ) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template S - State schema type\n * @template E - Event schemas type\n * @template A - Action schemas type\n * @template K - Action name\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n K extends keyof A,\n> extends Error {\n constructor(\n /** The action that was attempted */\n readonly action: K,\n /** The action payload that was provided */\n readonly payload: Readonly<A[K]>,\n /** The target stream and actor context */\n readonly target: Target,\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<S, E>,\n /** Human-readable description of why the invariant failed */\n readonly description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n constructor(\n /** The stream that had the concurrent modification */\n public readonly stream: string,\n /** The actual current version in the store */\n public readonly lastVersion: number,\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[],\n /** The version number that was expected */\n public readonly expectedVersion: number\n ) {\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}.${JSON.stringify(e.data)}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n }\n}\n","import { type ZodError, type ZodType, prettifyError } from \"zod\";\nimport { config } from \"./config.js\";\nimport type { Patch, Schema } from \"./types/index.js\";\nimport { ValidationError } from \"./types/index.js\";\n\n/** These objects are copied instead of deep merged */\nconst UNMERGEABLES = [\n RegExp,\n Date,\n Array,\n Map,\n Set,\n WeakMap,\n WeakSet,\n ArrayBuffer,\n SharedArrayBuffer,\n DataView,\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float32Array,\n Float64Array,\n];\n\nconst is_mergeable = (value: any): boolean =>\n !!value &&\n typeof value === \"object\" &&\n !UNMERGEABLES.some((t) => value instanceof t);\n\n/**\n * @module utils\n * @category Utilities\n * Utility functions for patching state, validation, extending objects, and async helpers.\n *\n * - Use `patch()` to immutably update state with patches.\n * - Use `validate()` to validate payloads against Zod schemas.\n * - Use `extend()` to merge and validate configuration objects.\n * - Use `sleep()` for async delays.\n */\n\n/**\n * Immutably applies patches to a state object, creating a new copy.\n *\n * This function performs deep merging for plain objects while preserving\n * immutability. Special types (Arrays, Dates, Maps, etc.) are replaced\n * entirely rather than merged. Setting a property to `undefined` or `null`\n * removes it from the resulting object.\n *\n * Used internally by the framework to apply event patches to state, but\n * can also be used directly for state transformations.\n *\n * **Merging rules:**\n * - Plain objects: Deep merge recursively\n * - Arrays, Dates, RegExp, Maps, Sets, TypedArrays: Replace entirely\n * - `undefined` or `null` values: Delete the property\n * - Primitives: Replace with patch value\n *\n * @param original - The original state object to patch\n * @param patches - The patches to apply (partial state)\n * @returns A new state object with patches applied\n *\n * @example Simple property update\n * ```typescript\n * import { patch } from \"@rotorsoft/act\";\n *\n * const state = { count: 0, name: \"Alice\" };\n * const updated = patch(state, { count: 5 });\n * // Result: { count: 5, name: \"Alice\" }\n * // Original unchanged: { count: 0, name: \"Alice\" }\n * ```\n *\n * @example Nested object patching\n * ```typescript\n * const state = {\n * user: { id: 1, name: \"Alice\", email: \"alice@example.com\" },\n * settings: { theme: \"dark\" }\n * };\n *\n * const updated = patch(state, {\n * user: { email: \"newemail@example.com\" }\n * });\n * // Result: {\n * // user: { id: 1, name: \"Alice\", email: \"newemail@example.com\" },\n * // settings: { theme: \"dark\" }\n * // }\n * ```\n *\n * @example Property deletion\n * ```typescript\n * const state = { count: 5, temp: \"value\", flag: true };\n *\n * const updated = patch(state, {\n * temp: undefined, // Delete temp\n * flag: null // Delete flag\n * });\n * // Result: { count: 5 }\n * ```\n *\n * @example Array replacement (not merged)\n * ```typescript\n * const state = { items: [1, 2, 3], meta: { count: 3 } };\n *\n * const updated = patch(state, {\n * items: [4, 5] // Arrays are replaced, not merged\n * });\n * // Result: { items: [4, 5], meta: { count: 3 } }\n * ```\n *\n * @example In event handlers\n * ```typescript\n * import { state } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const Counter = state(\"Counter\", z.object({ count: z.number() }))\n * .init(() => ({ count: 0 }))\n * .emits({ Incremented: z.object({ by: z.number() }) })\n * .patch({\n * Incremented: (event, state) => {\n * // patch() is called internally here\n * return { count: state.count + event.data.by };\n * }\n * });\n * ```\n *\n * @see {@link Patch} for the patch type definition\n */\nexport const patch = <S extends Schema>(\n original: Readonly<S>,\n patches: Readonly<Patch<S>>\n): Readonly<S> => {\n const copy = {} as Record<string, any>;\n Object.keys({ ...original, ...patches }).forEach((key) => {\n const patched_value = patches[key as keyof typeof patches];\n const original_value = original[key as keyof typeof original];\n const patched = patches && key in patches;\n const deleted =\n patched &&\n (typeof patched_value === \"undefined\" || patched_value === null);\n const value = patched && !deleted ? patched_value : original_value;\n !deleted &&\n (copy[key] = is_mergeable(value)\n ? patch(original_value || {}, patched_value || {})\n : value);\n });\n return copy as S;\n};\n\n/**\n * Validates a payload against a Zod schema.\n *\n * This is the primary validation function used throughout the Act framework.\n * It parses the payload using the provided Zod schema and throws a\n * {@link ValidationError} with detailed error information if validation fails.\n *\n * When no schema is provided, the payload is returned as-is without validation.\n * This allows for optional validation in the framework.\n *\n * The framework automatically calls this function when:\n * - Actions are invoked via `app.do()`\n * - Events are emitted from action handlers\n * - States are initialized\n *\n * @param target - Name of the target being validated (used in error messages)\n * @param payload - The data to validate\n * @param schema - Optional Zod schema to validate against\n * @returns The validated and type-safe payload\n * @throws {@link ValidationError} if validation fails with detailed error info\n *\n * @example Basic validation\n * ```typescript\n * import { validate } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const UserSchema = z.object({\n * email: z.string().email(),\n * age: z.number().min(0)\n * });\n *\n * const user = validate(\"User\", { email: \"alice@example.com\", age: 30 }, UserSchema);\n * // Returns: { email: \"alice@example.com\", age: 30 }\n * ```\n *\n * @example Handling validation errors\n * ```typescript\n * import { validate, ValidationError } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const schema = z.object({\n * email: z.string().email(),\n * age: z.number().min(18)\n * });\n *\n * try {\n * validate(\"User\", { email: \"invalid\", age: 15 }, schema);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Target:\", error.target); // \"User\"\n * console.error(\"Payload:\", error.payload); // { email: \"invalid\", age: 15 }\n * console.error(\"Details:\", error.details); // Prettified Zod errors\n * // Details shows: email must be valid, age must be >= 18\n * }\n * }\n * ```\n *\n * @example Optional validation\n * ```typescript\n * // When schema is undefined, payload is returned as-is\n * const data = validate(\"Data\", { any: \"value\" });\n * // Returns: { any: \"value\" } without validation\n * ```\n *\n * @example In action definitions\n * ```typescript\n * import { state } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const Counter = state(\"Counter\", z.object({ count: z.number() }))\n * .init(() => ({ count: 0 }))\n * .emits({ Incremented: z.object({ by: z.number().positive() }) })\n * .on(\"increment\", z.object({ by: z.number() }))\n * .emit((action) => {\n * // validate() is called automatically before this runs\n * // action.by is guaranteed to be a number\n * return [\"Incremented\", { by: action.by }];\n * })\n * .build();\n * ```\n *\n * @example Custom validation in application code\n * ```typescript\n * import { validate } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const ConfigSchema = z.object({\n * apiKey: z.string().min(32),\n * timeout: z.number().positive(),\n * retries: z.number().int().min(0).max(10)\n * });\n *\n * function loadConfig(raw: unknown) {\n * return validate(\"AppConfig\", raw, ConfigSchema);\n * }\n * ```\n *\n * @see {@link ValidationError} for error handling\n * @see {@link https://zod.dev | Zod documentation} for schema definition\n */\nexport const validate = <S>(\n target: string,\n payload: Readonly<S>,\n schema?: ZodType<S>\n): Readonly<S> => {\n try {\n return schema ? schema.parse(payload) : payload;\n } catch (error) {\n if (error instanceof Error && error.name === \"ZodError\") {\n throw new ValidationError(\n target,\n payload,\n prettifyError(error as ZodError)\n );\n }\n throw new ValidationError(target, payload, error);\n }\n};\n\n/**\n * Validates and merges configuration objects.\n *\n * This function first validates the source object against a Zod schema using\n * {@link validate}, then merges it with an optional target object. The source\n * properties override target properties in the result.\n *\n * Primarily used for configuration management where you want to:\n * 1. Define default configuration values\n * 2. Load environment-specific overrides\n * 3. Validate the final configuration\n *\n * The framework uses this internally for the {@link config} function.\n *\n * @template S - Source object type (must be a record)\n * @template T - Target object type (must be a record)\n * @param source - The source object to validate and use as overrides\n * @param schema - Zod schema to validate the source against\n * @param target - Optional target object with default values\n * @returns Merged object with validated source overriding target\n * @throws {@link ValidationError} if source fails schema validation\n *\n * @example Basic configuration merging\n * ```typescript\n * import { extend } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const ConfigSchema = z.object({\n * host: z.string(),\n * port: z.number(),\n * debug: z.boolean()\n * });\n *\n * const defaults = { host: \"localhost\", port: 3000, debug: false };\n * const overrides = { port: 8080, debug: true };\n *\n * const config = extend(overrides, ConfigSchema, defaults);\n * // Result: { host: \"localhost\", port: 8080, debug: true }\n * ```\n *\n * @example Environment-based configuration\n * ```typescript\n * import { extend } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const DbConfigSchema = z.object({\n * host: z.string(),\n * port: z.number(),\n * database: z.string(),\n * user: z.string(),\n * password: z.string()\n * });\n *\n * const defaults = {\n * host: \"localhost\",\n * port: 5432,\n * database: \"myapp_dev\",\n * user: \"postgres\",\n * password: \"dev\"\n * };\n *\n * const envConfig = {\n * host: process.env.DB_HOST || \"localhost\",\n * port: parseInt(process.env.DB_PORT || \"5432\"),\n * database: process.env.DB_NAME || \"myapp_dev\",\n * user: process.env.DB_USER || \"postgres\",\n * password: process.env.DB_PASSWORD || \"dev\"\n * };\n *\n * // Validates environment config and merges with defaults\n * const dbConfig = extend(envConfig, DbConfigSchema, defaults);\n * ```\n *\n * @example Framework usage\n * ```typescript\n * // This is how Act's config() function uses extend internally:\n * import { extend } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const BaseSchema = z.object({\n * env: z.enum([\"development\", \"test\", \"staging\", \"production\"]),\n * logLevel: z.enum([\"fatal\", \"error\", \"warn\", \"info\", \"debug\", \"trace\"]),\n * sleepMs: z.number().int().min(0).max(5000)\n * });\n *\n * const packageData = { name: \"my-app\", version: \"1.0.0\" };\n * const runtimeConfig = { env: \"production\", logLevel: \"info\", sleepMs: 100 };\n *\n * const config = extend(\n * { ...packageData, ...runtimeConfig },\n * BaseSchema,\n * packageData\n * );\n * ```\n *\n * @example With validation error handling\n * ```typescript\n * import { extend, ValidationError } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const schema = z.object({\n * apiKey: z.string().min(32),\n * timeout: z.number().positive()\n * });\n *\n * try {\n * const config = extend(\n * { apiKey: \"short\", timeout: -1 },\n * schema\n * );\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Invalid configuration:\", error.details);\n * }\n * }\n * ```\n *\n * @see {@link validate} for validation details\n * @see {@link config} for framework configuration\n * @see {@link ValidationError} for error handling\n */\nexport const extend = <\n S extends Record<string, unknown>,\n T extends Record<string, unknown>,\n>(\n source: Readonly<S>,\n schema: ZodType<S>,\n target?: Readonly<T>\n): Readonly<S & T> => {\n const value = validate(\"config\", source, schema);\n return Object.assign(target || {}, value) as Readonly<S & T>;\n};\n\n/**\n * Pauses async execution for a specified duration.\n *\n * This is a simple async utility for adding delays in your code. When called\n * without arguments, it uses the configured sleep duration from `config().sleepMs`,\n * which defaults to 100ms in development and 0ms in test environments.\n *\n * The framework uses this internally in store adapters to simulate I/O delays\n * in the {@link InMemoryStore}.\n *\n * **Note:** In test environments (NODE_ENV=test), the default sleep duration is\n * 0ms to keep tests fast.\n *\n * @param ms - Optional duration in milliseconds (defaults to config().sleepMs)\n * @returns Promise that resolves after the specified delay\n *\n * @example Using default sleep duration\n * ```typescript\n * import { sleep } from \"@rotorsoft/act\";\n *\n * async function processWithDelay() {\n * console.log(\"Starting...\");\n * await sleep(); // Uses config().sleepMs (100ms in dev, 0ms in test)\n * console.log(\"Continued after delay\");\n * }\n * ```\n *\n * @example Custom sleep duration\n * ```typescript\n * import { sleep } from \"@rotorsoft/act\";\n *\n * async function retryWithBackoff(fn: () => Promise<void>, retries = 3) {\n * for (let i = 0; i < retries; i++) {\n * try {\n * await fn();\n * return;\n * } catch (error) {\n * if (i < retries - 1) {\n * const delay = Math.pow(2, i) * 1000; // Exponential backoff\n * console.log(`Retrying in ${delay}ms...`);\n * await sleep(delay);\n * } else {\n * throw error;\n * }\n * }\n * }\n * }\n * ```\n *\n * @example Rate limiting\n * ```typescript\n * import { sleep } from \"@rotorsoft/act\";\n *\n * async function processItems(items: string[]) {\n * for (const item of items) {\n * await processItem(item);\n * await sleep(500); // 500ms between items\n * }\n * }\n * ```\n *\n * @example Framework internal usage\n * ```typescript\n * // InMemoryStore uses sleep to simulate async I/O\n * class InMemoryStore implements Store {\n * async query(...) {\n * await sleep(); // Simulate database latency\n * // ... query logic\n * }\n *\n * async commit(...) {\n * await sleep(); // Simulate write latency\n * // ... commit logic\n * }\n * }\n * ```\n *\n * @example Configuring default sleep duration\n * ```bash\n * # Set custom default sleep duration via environment variable\n * SLEEP_MS=50 npm start\n *\n * # In tests, it's automatically 0\n * NODE_ENV=test npm test\n * ```\n *\n * @see {@link config} for sleep duration configuration\n */\nexport async function sleep(ms?: number) {\n return new Promise((resolve) => setTimeout(resolve, ms ?? config().sleepMs));\n}\n","/**\n * @packageDocumentation\n * Configuration utilities for Act Framework environment, logging, and package metadata.\n *\n * Provides type-safe configuration loading and validation using Zod schemas.\n *\n * @module config\n */\nimport * as fs from \"node:fs\";\nimport { z } from \"zod\";\nimport {\n Environment,\n Environments,\n LogLevel,\n LogLevels,\n} from \"./types/index.js\";\nimport { extend } from \"./utils.js\";\n\n/**\n * Zod schema for validating package.json metadata.\n * @internal\n */\nexport const PackageSchema = z.object({\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string().min(1).optional(),\n author: z\n .object({ name: z.string().min(1), email: z.string().optional() })\n .optional()\n .or(z.string().min(1))\n .optional(),\n license: z.string().min(1).optional(),\n dependencies: z.record(z.string(), z.string()).optional(),\n});\n\n/**\n * Type representing the validated package.json metadata.\n */\nexport type Package = z.infer<typeof PackageSchema>;\n\n/**\n * Loads and parses the local package.json file as a Package object.\n * @returns The parsed and validated package metadata.\n * @internal\n */\nconst getPackage = (): Package => {\n const pkg = fs.readFileSync(\"package.json\");\n return JSON.parse(pkg.toString()) as Package;\n};\n\n/**\n * Zod schema for the full Act Framework configuration object.\n * Includes package metadata, environment, logging, and timing options.\n * @internal\n */\nconst BaseSchema = PackageSchema.extend({\n env: z.enum(Environments),\n logLevel: z.enum(LogLevels),\n logSingleLine: z.boolean(),\n sleepMs: z.number().int().min(0).max(5000),\n});\n\n/**\n * Type representing the validated Act Framework configuration object.\n */\nexport type Config = z.infer<typeof BaseSchema>;\n\nconst { NODE_ENV, LOG_LEVEL, LOG_SINGLE_LINE, SLEEP_MS } = process.env;\n\nconst env = (NODE_ENV || \"development\") as Environment;\nconst logLevel = (LOG_LEVEL ||\n (NODE_ENV === \"test\"\n ? \"error\"\n : NODE_ENV === \"production\"\n ? \"info\"\n : \"trace\")) as LogLevel;\nconst logSingleLine = (LOG_SINGLE_LINE || \"true\") === \"true\";\nconst sleepMs = parseInt(NODE_ENV === \"test\" ? \"0\" : (SLEEP_MS ?? \"100\"));\n\nconst pkg = getPackage();\n\n/**\n * Gets the current Act Framework configuration.\n *\n * Configuration is loaded from package.json and environment variables, providing\n * type-safe access to application metadata and runtime settings.\n *\n * **Environment Variables:**\n * - `NODE_ENV`: \"development\" | \"test\" | \"staging\" | \"production\" (default: \"development\")\n * - `LOG_LEVEL`: \"fatal\" | \"error\" | \"warn\" | \"info\" | \"debug\" | \"trace\"\n * - `LOG_SINGLE_LINE`: \"true\" | \"false\" (default: \"true\")\n * - `SLEEP_MS`: Milliseconds for sleep utility (default: 100, 0 for tests)\n *\n * **Defaults by environment:**\n * - test: logLevel=\"error\", sleepMs=0\n * - production: logLevel=\"info\"\n * - development: logLevel=\"trace\"\n *\n * @returns The validated configuration object\n *\n * @example Basic usage\n * ```typescript\n * import { config } from \"@rotorsoft/act\";\n *\n * const cfg = config();\n * console.log(`App: ${cfg.name} v${cfg.version}`);\n * console.log(`Environment: ${cfg.env}`);\n * console.log(`Log level: ${cfg.logLevel}`);\n * ```\n *\n * @example Environment-specific behavior\n * ```typescript\n * import { config } from \"@rotorsoft/act\";\n *\n * const cfg = config();\n *\n * if (cfg.env === \"production\") {\n * // Use PostgreSQL in production\n * store(new PostgresStore(prodConfig));\n * } else {\n * // Use in-memory store for dev/test\n * store(new InMemoryStore());\n * }\n * ```\n *\n * @example Adjusting log levels\n * ```typescript\n * // Set via environment variable:\n * // LOG_LEVEL=debug npm start\n *\n * // Or check in code:\n * const cfg = config();\n * if (cfg.logLevel === \"trace\") {\n * logger.trace(\"Detailed debugging enabled\");\n * }\n * ```\n *\n * @see {@link Config} for configuration type\n * @see {@link Package} for package.json metadata\n */\nexport const config = (): Config => {\n return extend({ ...pkg, env, logLevel, logSingleLine, sleepMs }, BaseSchema);\n};\n","import { z, ZodObject, ZodRawShape } from \"zod\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n","/**\n * @packageDocumentation\n * @module act/adapters\n * In-memory event store adapter for the Act Framework.\n *\n * This adapter implements the Store interface and is suitable for development, testing, and demonstration purposes.\n * All data is stored in memory and lost on process exit.\n *\n * @category Adapters\n */\nimport { SNAP_EVENT } from \"../ports.js\";\nimport { ConcurrencyError } from \"../types/errors.js\";\nimport type {\n Committed,\n EventMeta,\n Lease,\n Message,\n Query,\n Schemas,\n Store,\n} from \"../types/index.js\";\nimport { sleep } from \"../utils.js\";\n\n/**\n * @internal\n * Represents an in-memory stream for event processing and leasing.\n */\nclass InMemoryStream {\n private _at = -1;\n private _retry = -1;\n private _blocked = false;\n private _error = \"\";\n private _leased_by: string | undefined = undefined;\n private _leased_until: Date | undefined = undefined;\n\n constructor(\n readonly stream: string,\n readonly source: string | undefined\n ) {}\n\n get is_avaliable() {\n return (\n !this._blocked &&\n (!this._leased_until || this._leased_until <= new Date())\n );\n }\n\n get at() {\n return this._at;\n }\n\n /**\n * Attempt to lease this stream for processing.\n * @param lease - The lease request.\n * @param millis - Lease duration in milliseconds.\n * @returns The granted lease or undefined if blocked.\n */\n lease(lease: Lease, millis: number): Lease | undefined {\n if (this.is_avaliable) {\n if (millis > 0) {\n this._leased_by = lease.by;\n this._leased_until = new Date(Date.now() + millis);\n this._retry = this._retry + 1;\n }\n return {\n stream: this.stream,\n source: this.source,\n at: lease.at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n };\n }\n }\n\n /**\n * Acknowledge completion of processing for this stream.\n * @param lease - The lease request.\n */\n ack(lease: Lease) {\n if (this._leased_by === lease.by) {\n this._leased_by = undefined;\n this._leased_until = undefined;\n this._at = lease.at;\n this._retry = -1;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: lease.by,\n retry: this._retry,\n lagging: lease.lagging,\n };\n }\n }\n\n /**\n * Block a stream for processing after failing to process and reaching max retries with blocking enabled.\n * @param lease - The lease request.\n * @param error Blocked error message.\n */\n block(lease: Lease, error: string) {\n if (this._leased_by === lease.by) {\n this._blocked = true;\n this._error = error;\n return {\n stream: this.stream,\n source: this.source,\n at: this._at,\n by: this._leased_by,\n retry: this._retry,\n error: this._error,\n lagging: lease.lagging,\n };\n }\n }\n}\n\n/**\n * In-memory event store implementation.\n *\n * This is the default store used by Act when no other store is injected.\n * It stores all events in memory and is suitable for:\n * - Development and prototyping\n * - Unit and integration testing\n * - Demonstrations and examples\n *\n * **Not suitable for production** - all data is lost when the process exits.\n * Use {@link PostgresStore} for production deployments.\n *\n * The in-memory store provides:\n * - Full {@link Store} interface implementation\n * - Optimistic concurrency control\n * - Stream leasing for distributed processing simulation\n * - Snapshot support\n * - Fast performance (no I/O overhead)\n *\n * @example Using in tests\n * ```typescript\n * import { store } from \"@rotorsoft/act\";\n *\n * describe(\"Counter\", () => {\n * beforeEach(async () => {\n * // Reset store between tests\n * await store().seed();\n * });\n *\n * it(\"increments\", async () => {\n * await app.do(\"increment\", target, { by: 5 });\n * const snapshot = await app.load(Counter, \"counter-1\");\n * expect(snapshot.state.count).toBe(5);\n * });\n * });\n * ```\n *\n * @example Explicit instantiation\n * ```typescript\n * import { InMemoryStore } from \"@rotorsoft/act\";\n *\n * const testStore = new InMemoryStore();\n * await testStore.seed();\n *\n * // Use for specific test scenarios\n * await testStore.commit(\"test-stream\", events, meta);\n * ```\n *\n * @example Querying events\n * ```typescript\n * const events: any[] = [];\n * await store().query(\n * (event) => events.push(event),\n * { stream: \"test-stream\" }\n * );\n * console.log(`Found ${events.length} events`);\n * ```\n *\n * @see {@link Store} for the interface definition\n * @see {@link PostgresStore} for production use\n * @see {@link store} for injecting stores\n *\n * @category Adapters\n */\nexport class InMemoryStore implements Store {\n // stored events\n private _events: Committed<Schemas, keyof Schemas>[] = [];\n // stored stream positions and other metadata\n private _streams: Map<string, InMemoryStream> = new Map();\n\n /**\n * Dispose of the store and clear all events.\n * @returns Promise that resolves when disposal is complete.\n */\n async dispose() {\n await sleep();\n this._events.length = 0;\n }\n\n /**\n * Seed the store with initial data (no-op for in-memory).\n * @returns Promise that resolves when seeding is complete.\n */\n async seed() {\n await sleep();\n }\n\n /**\n * Drop all data from the store.\n * @returns Promise that resolves when the store is cleared.\n */\n async drop() {\n await sleep();\n this._events.length = 0;\n this._streams = new Map();\n }\n\n private in_query<E extends Schemas>(query: Query, e: Committed<E, keyof E>) {\n if (query.stream && !RegExp(`^${query.stream}$`).test(e.stream))\n return false;\n if (query.names && !query.names.includes(e.name as string)) return false;\n if (query.correlation && e.meta?.correlation !== query.correlation)\n return false;\n if (e.name === SNAP_EVENT && !query.with_snaps) return false;\n return true;\n }\n\n /**\n * Query events in the store, optionally filtered by query options.\n * @param callback - Function to call for each event.\n * @param query - Optional query options.\n * @returns The number of events processed.\n */\n async query<E extends Schemas>(\n callback: (event: Committed<E, keyof E>) => void,\n query?: Query\n ) {\n await sleep();\n let count = 0;\n if (query?.backward) {\n let i = (query?.before || this._events.length) - 1;\n while (i >= 0) {\n const e = this._events[i--];\n if (query && !this.in_query(query, e)) continue;\n if (query?.created_before && e.created >= query.created_before)\n continue;\n if (query.after && e.id <= query.after) break;\n if (query.created_after && e.created <= query.created_after) break;\n callback(e as Committed<E, keyof E>);\n count++;\n if (query?.limit && count >= query.limit) break;\n }\n } else {\n let i = (query?.after ?? -1) + 1;\n while (i < this._events.length) {\n const e = this._events[i++];\n if (query && !this.in_query(query, e)) continue;\n if (query?.created_after && e.created <= query.created_after) continue;\n if (query?.before && e.id >= query.before) break;\n if (query?.created_before && e.created >= query.created_before) break;\n callback(e as Committed<E, keyof E>);\n count++;\n if (query?.limit && count >= query.limit) break;\n }\n }\n return count;\n }\n\n /**\n * Commit one or more events to a stream.\n * @param stream - The stream name.\n * @param msgs - The events/messages to commit.\n * @param meta - Event metadata.\n * @param expectedVersion - Optional optimistic concurrency check.\n * @returns The committed events with metadata.\n * @throws ConcurrencyError if expectedVersion does not match.\n */\n async commit<E extends Schemas>(\n stream: string,\n msgs: Message<E, keyof E>[],\n meta: EventMeta,\n expectedVersion?: number\n ) {\n await sleep();\n const instance = this._events.filter((e) => e.stream === stream); // ignore state events, this is a production optimization\n if (\n typeof expectedVersion === \"number\" &&\n instance.length - 1 !== expectedVersion\n ) {\n throw new ConcurrencyError(\n stream,\n instance.length - 1,\n msgs as Message<Schemas, keyof Schemas>[],\n expectedVersion\n );\n }\n\n let version = instance.length;\n return msgs.map(({ name, data }) => {\n const committed: Committed<E, keyof E> = {\n id: this._events.length,\n stream,\n version,\n created: new Date(),\n name,\n data,\n meta,\n };\n this._events.push(committed as Committed<Schemas, keyof Schemas>);\n version++;\n return committed;\n });\n }\n\n /**\n * Polls the store for unblocked streams needing processing, ordered by lease watermark ascending.\n * @param lagging - Max number of streams to poll in ascending order.\n * @param leading - Max number of streams to poll in descending order.\n * @returns The polled streams.\n */\n async poll(lagging: number, leading: number) {\n await sleep();\n const a = [...this._streams.values()]\n .filter((s) => s.is_avaliable)\n .sort((a, b) => a.at - b.at)\n .slice(0, lagging)\n .map(({ stream, source, at }) => ({\n stream,\n source,\n at,\n lagging: true,\n }));\n const b = [...this._streams.values()]\n .filter((s) => s.is_avaliable)\n .sort((a, b) => b.at - a.at)\n .slice(0, leading)\n .map(({ stream, source, at }) => ({\n stream,\n source,\n at,\n lagging: false,\n }));\n return [...a, ...b];\n }\n\n /**\n * Lease streams for processing (e.g., for distributed consumers).\n * @param leases - Lease requests for streams, including end-of-lease watermark, lease holder, and source stream.\n * @param leaseMilis - Lease duration in milliseconds.\n * @returns Granted leases.\n */\n async lease(leases: Lease[], millis: number) {\n await sleep();\n return leases\n .map((l) => {\n if (!this._streams.has(l.stream)) {\n // store new correlations\n this._streams.set(l.stream, new InMemoryStream(l.stream, l.source));\n }\n return this._streams.get(l.stream)?.lease(l, millis);\n })\n .filter((l) => !!l);\n }\n\n /**\n * Acknowledge completion of processing for leased streams.\n * @param leases - Leases to acknowledge, including last processed watermark and lease holder.\n */\n async ack(leases: Lease[]) {\n await sleep();\n return leases\n .map((l) => this._streams.get(l.stream)?.ack(l))\n .filter((l) => !!l);\n }\n\n /**\n * Block a stream for processing after failing to process and reaching max retries with blocking enabled.\n * @param leases - Leases to block, including lease holder and last error message.\n * @returns Blocked leases.\n */\n async block(leases: Array<Lease & { error: string }>) {\n await sleep();\n return leases\n .map((l) => this._streams.get(l.stream)?.block(l, l.error))\n .filter((l) => !!l);\n }\n}\n","import { disposeAndExit, logger } from \"./ports.js\";\n\n// exit on signals\nprocess.once(\"SIGINT\", async (arg?: any) => {\n logger.info(arg, \"SIGINT\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"SIGTERM\", async (arg?: any) => {\n logger.info(arg, \"SIGTERM\");\n await disposeAndExit(\"EXIT\");\n});\nprocess.once(\"uncaughtException\", async (arg?: any) => {\n logger.error(arg, \"Uncaught Exception\");\n await disposeAndExit(\"ERROR\");\n});\nprocess.once(\"unhandledRejection\", async (arg?: any) => {\n logger.error(arg, \"Unhandled Rejection\");\n await disposeAndExit(\"ERROR\");\n});\n","import { randomUUID } from \"crypto\";\nimport EventEmitter from \"events\";\nimport { config } from \"./config.js\";\nimport * as es from \"./event-sourcing.js\";\nimport { build_tracer, dispose, logger, store } from \"./ports.js\";\nimport type {\n Committed,\n Drain,\n DrainOptions,\n Lease,\n Query,\n ReactionPayload,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"./types/index.js\";\n\nconst tracer = build_tracer(config().logLevel);\n\n/**\n * @category Orchestrator\n * @see Store\n *\n * Main orchestrator for event-sourced state machines and workflows.\n *\n * It manages the lifecycle of actions, reactions, and event streams, providing APIs for loading state, executing actions, querying events, and draining reactions.\n *\n * ## Usage\n *\n * ```typescript\n * const app = new Act(registry, 100);\n * await app.do(\"increment\", { stream: \"counter1\", actor }, { by: 1 });\n * const snapshot = await app.load(Counter, \"counter1\");\n * await app.drain();\n * ```\n *\n * - Register event listeners with `.on(\"committed\", ...)` and `.on(\"acked\", ...)` to react to lifecycle events.\n * - Use `.query()` to analyze event streams for analytics or debugging.\n *\n * @template S SchemaRegister for state\n * @template E Schemas for events\n * @template A Schemas for actions\n */\nexport class Act<\n S extends SchemaRegister<A>,\n E extends Schemas,\n A extends Schemas,\n> {\n private _emitter = new EventEmitter();\n private _drain_locked = false;\n private _drain_lag2lead_ratio = 0.5;\n private _correlation_interval: NodeJS.Timeout | undefined = undefined;\n\n /**\n * Emit a lifecycle event (internal use, but can be used for custom listeners).\n *\n * @param event The event name (\"committed\", \"acked\", or \"blocked\")\n * @param args The event payload\n * @returns true if the event had listeners, false otherwise\n */\n emit(event: \"committed\", args: Snapshot<S, E>[]): boolean;\n emit(event: \"acked\", args: Lease[]): boolean;\n emit(event: \"blocked\", args: Array<Lease & { error: string }>): boolean;\n emit(event: string, args: any): boolean {\n return this._emitter.emit(event, args);\n }\n\n /**\n * Register a listener for a lifecycle event (\"committed\", \"acked\", or \"blocked\").\n *\n * @param event The event name\n * @param listener The callback function\n * @returns this (for chaining)\n */\n on(event: \"committed\", listener: (args: Snapshot<S, E>[]) => void): this;\n on(event: \"acked\", listener: (args: Lease[]) => void): this;\n on(\n event: \"blocked\",\n listener: (args: Array<Lease & { error: string }>) => void\n ): this;\n on(event: string, listener: (args: any) => void): this {\n this._emitter.on(event, listener);\n return this;\n }\n\n /**\n * Remove a listener for a lifecycle event.\n *\n * @param event The event name\n * @param listener The callback function\n * @returns this (for chaining)\n */\n off(event: \"committed\", listener: (args: Snapshot<S, E>[]) => void): this;\n off(event: \"acked\", listener: (args: Lease[]) => void): this;\n off(\n event: \"blocked\",\n listener: (args: Array<Lease & { error: string }>) => void\n ): this;\n off(event: string, listener: (args: any) => void): this {\n this._emitter.off(event, listener);\n return this;\n }\n\n /**\n * Create a new Act orchestrator.\n *\n * @param registry The registry of state, event, and action schemas\n */\n constructor(public readonly registry: Registry<S, E, A>) {\n dispose(() => {\n this._emitter.removeAllListeners();\n this.stop_correlations();\n return Promise.resolve();\n });\n }\n\n /**\n * Executes an action on a state instance, committing resulting events.\n *\n * This is the primary method for modifying state. It:\n * 1. Validates the action payload against the schema\n * 2. Loads the current state snapshot\n * 3. Checks invariants (business rules)\n * 4. Executes the action handler to generate events\n * 5. Applies events to create new state\n * 6. Commits events to the store with optimistic concurrency control\n *\n * @template K - Action name from registered actions\n * @param action - The name of the action to execute\n * @param target - Target specification with stream ID and actor context\n * @param payload - Action payload matching the action's schema\n * @param reactingTo - Optional event that triggered this action (for correlation)\n * @param skipValidation - Skip schema validation (use carefully, for performance)\n * @returns Array of snapshots for all affected states (usually one)\n *\n * @throws {ValidationError} If payload doesn't match action schema\n * @throws {InvariantError} If business rules are violated\n * @throws {ConcurrencyError} If another process modified the stream\n *\n * @example Basic action execution\n * ```typescript\n * const snapshots = await app.do(\n * \"increment\",\n * {\n * stream: \"counter-1\",\n * actor: { id: \"user1\", name: \"Alice\" }\n * },\n * { by: 5 }\n * );\n *\n * console.log(snapshots[0].state.count); // Current count after increment\n * ```\n *\n * @example With error handling\n * ```typescript\n * try {\n * await app.do(\n * \"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Business rule violated:\", error.description);\n * } else if (error instanceof ConcurrencyError) {\n * console.error(\"Concurrent modification detected, retry...\");\n * } else if (error instanceof ValidationError) {\n * console.error(\"Invalid payload:\", error.details);\n * }\n * }\n * ```\n *\n * @example Reaction triggering another action\n * ```typescript\n * const app = act()\n * .with(Order)\n * .with(Inventory)\n * .on(\"OrderPlaced\")\n * .do(async (event, context) => {\n * // This action is triggered by an event\n * const result = await context.app.do(\n * \"reduceStock\",\n * {\n * stream: \"inventory-1\",\n * actor: event.meta.causation.action.actor\n * },\n * { amount: event.data.items.length },\n * event // Pass event for correlation tracking\n * );\n * return result;\n * })\n * .to(\"inventory-1\")\n * .build();\n * ```\n *\n * @see {@link Target} for target structure\n * @see {@link Snapshot} for return value structure\n * @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}\n */\n async do<K extends keyof A>(\n action: K,\n target: Target,\n payload: Readonly<A[K]>,\n reactingTo?: Committed<E, keyof E>,\n skipValidation = false\n ) {\n const snapshots = await es.action(\n this.registry.actions[action],\n action,\n target,\n payload,\n // @ts-expect-error type lost\n reactingTo,\n skipValidation\n );\n this.emit(\"committed\", snapshots as Snapshot<S, E>[]);\n return snapshots;\n }\n\n /**\n * Loads the current state snapshot for a specific stream.\n *\n * Reconstructs the current state by replaying events from the event store.\n * Uses snapshots when available to optimize loading performance.\n *\n * @template SX - State schema type\n * @template EX - Event schemas type\n * @template AX - Action schemas type\n * @param state - The state definition to load\n * @param stream - The stream ID (state instance identifier)\n * @param callback - Optional callback invoked with the loaded snapshot\n * @returns The current state snapshot for the stream\n *\n * @example Load current state\n * ```typescript\n * const snapshot = await app.load(Counter, \"counter-1\");\n * console.log(snapshot.state.count); // Current count\n * console.log(snapshot.version); // Number of events applied\n * console.log(snapshot.patches); // Events since last snapshot\n * ```\n *\n * @example With callback\n * ```typescript\n * const snapshot = await app.load(User, \"user-123\", (snap) => {\n * console.log(\"Loaded user:\", snap.state.name);\n * });\n * ```\n *\n * @example Load multiple states\n * ```typescript\n * const [user, account] = await Promise.all([\n * app.load(User, \"user-123\"),\n * app.load(BankAccount, \"account-456\")\n * ]);\n * ```\n *\n * @see {@link Snapshot} for snapshot structure\n */\n async load<SX extends Schema, EX extends Schemas, AX extends Schemas>(\n state: State<SX, EX, AX>,\n stream: string,\n callback?: (snapshot: Snapshot<SX, EX>) => void\n ): Promise<Snapshot<SX, EX>> {\n return await es.load(state, stream, callback);\n }\n\n /**\n * Queries the event store for events matching a filter.\n *\n * Use this for analyzing event streams, generating reports, or debugging.\n * The callback is invoked for each matching event, and the method returns\n * summary information (first event, last event, total count).\n *\n * For small result sets, consider using {@link query_array} instead.\n *\n * @param query - The query filter\n * @param query.stream - Filter by stream ID\n * @param query.name - Filter by event name\n * @param query.after - Filter events after this event ID\n * @param query.before - Filter events before this event ID\n * @param query.created_after - Filter events after this timestamp\n * @param query.created_before - Filter events before this timestamp\n * @param query.limit - Maximum number of events to return\n * @param callback - Optional callback invoked for each matching event\n * @returns Object with first event, last event, and total count\n *\n * @example Query all events for a stream\n * ```typescript\n * const { first, last, count } = await app.query(\n * { stream: \"counter-1\" },\n * (event) => console.log(event.name, event.data)\n * );\n * console.log(`Found ${count} events from ${first?.id} to ${last?.id}`);\n * ```\n *\n * @example Query specific event types\n * ```typescript\n * const { count } = await app.query(\n * { name: \"UserCreated\", limit: 100 },\n * (event) => {\n * console.log(\"User created:\", event.data.email);\n * }\n * );\n * ```\n *\n * @example Query events in time range\n * ```typescript\n * const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);\n * const { count } = await app.query({\n * created_after: yesterday,\n * stream: \"user-123\"\n * });\n * console.log(`User had ${count} events in last 24 hours`);\n * ```\n *\n * @see {@link query_array} for loading events into memory\n */\n async query(\n query: Query,\n callback?: (event: Committed<E, keyof E>) => void\n ): Promise<{\n first?: Committed<E, keyof E>;\n last?: Committed<E, keyof E>;\n count: number;\n }> {\n let first: Committed<E, keyof E> | undefined = undefined,\n last: Committed<E, keyof E> | undefined = undefined;\n const count = await store().query<E>((e) => {\n !first && (first = e);\n last = e;\n callback && callback(e);\n }, query);\n return { first, last, count };\n }\n\n /**\n * Queries the event store and returns all matching events in memory.\n *\n * **Use with caution** - this loads all results into memory. For large result sets,\n * use {@link query} with a callback instead to process events incrementally.\n *\n * @param query - The query filter (same as {@link query})\n * @returns Array of all matching events\n *\n * @example Load all events for a stream\n * ```typescript\n * const events = await app.query_array({ stream: \"counter-1\" });\n * console.log(`Loaded ${events.length} events`);\n * events.forEach(event => console.log(event.name, event.data));\n * ```\n *\n * @example Get recent events\n * ```typescript\n * const recent = await app.query_array({\n * stream: \"user-123\",\n * limit: 10\n * });\n * ```\n *\n * @see {@link query} for large result sets\n */\n async query_array(query: Query): Promise<Committed<E, keyof E>[]> {\n const events: Committed<E, keyof E>[] = [];\n await store().query<E>((e) => events.push(e), query);\n return events;\n }\n\n /**\n * Handles leased reactions.\n *\n * This is called by the main `drain` loop after fetching new events.\n * It handles reactions, supporting retries, blocking, and error handling.\n *\n * @internal\n * @param lease The lease to handle\n * @param payloads The reactions to handle\n * @returns The lease with results\n */\n private async handle<E extends Schemas>(\n lease: Lease,\n payloads: ReactionPayload<E>[]\n ): Promise<{\n readonly lease: Lease;\n readonly handled: number;\n readonly at: number;\n readonly error?: string;\n readonly block?: boolean;\n }> {\n // no payloads, just advance the lease\n if (payloads.length === 0) return { lease, handled: 0, at: lease.at };\n\n const stream = lease.stream;\n let at = payloads.at(0)!.event.id,\n handled = 0;\n\n lease.retry > 0 &&\n logger.warn(`Retrying ${stream}@${at} (${lease.retry}).`);\n\n for (const payload of payloads) {\n const { event, handler, options } = payload;\n try {\n await handler(event, stream); // the actual reaction\n at = event.id;\n handled++;\n } catch (error) {\n logger.error(error);\n const block = lease.retry >= options.maxRetries && options.blockOnError;\n block &&\n logger.error(`Blocking ${stream} after ${lease.retry} retries.`);\n return {\n lease,\n handled,\n at,\n // only report error when nothing was handled\n error: handled === 0 ? (error as Error).message : undefined,\n block,\n };\n }\n }\n return { lease, handled, at };\n }\n\n /**\n * Processes pending reactions by draining uncommitted events from the event store.\n *\n * The drain process:\n * 1. Polls the store for streams with uncommitted events\n * 2. Leases streams to prevent concurrent processing\n * 3. Fetches events for each leased stream\n * 4. Executes matching reaction handlers\n * 5. Acknowledges successful reactions or blocks failing ones\n *\n * Drain uses a dual-frontier strategy to balance processing of new streams (lagging)\n * vs active streams (leading). The ratio adapts based on event pressure.\n *\n * Call this method periodically in a background loop, or after committing events.\n *\n * @param options - Drain configuration options\n * @param options.streamLimit - Maximum number of streams to process per cycle (default: 10)\n * @param options.eventLimit - Maximum events to fetch per stream (default: 10)\n * @param options.leaseMillis - Lease duration in milliseconds (default: 10000)\n * @returns Drain statistics with fetched, leased, acked, and blocked counts\n *\n * @example Basic drain loop\n * ```typescript\n * // Process reactions after each action\n * await app.do(\"createUser\", target, payload);\n * await app.drain();\n * ```\n *\n * @example Background drain worker\n * ```typescript\n * setInterval(async () => {\n * try {\n * const result = await app.drain({\n * streamLimit: 20,\n * eventLimit: 50\n * });\n * if (result.acked.length) {\n * console.log(`Processed ${result.acked.length} streams`);\n * }\n * } catch (error) {\n * console.error(\"Drain error:\", error);\n * }\n * }, 5000); // Every 5 seconds\n * ```\n *\n * @example With lifecycle listeners\n * ```typescript\n * app.on(\"acked\", (leases) => {\n * console.log(`Acknowledged ${leases.length} streams`);\n * });\n *\n * app.on(\"blocked\", (blocked) => {\n * console.error(`Blocked ${blocked.length} streams due to errors`);\n * blocked.forEach(({ stream, error }) => {\n * console.error(`Stream ${stream}: ${error}`);\n * });\n * });\n *\n * await app.drain();\n * ```\n *\n * @see {@link correlate} for dynamic stream discovery\n * @see {@link start_correlations} for automatic correlation\n */\n async drain<E extends Schemas>({\n streamLimit = 10,\n eventLimit = 10,\n leaseMillis = 10_000,\n }: DrainOptions = {}): Promise<Drain<E>> {\n if (!this._drain_locked) {\n try {\n this._drain_locked = true;\n const lagging = Math.ceil(streamLimit * this._drain_lag2lead_ratio);\n const leading = streamLimit - lagging;\n const polled = await store().poll(lagging, leading);\n const fetched = await Promise.all(\n polled.map(async ({ stream, source, at, lagging }) => {\n const events = await this.query_array({\n stream: source,\n after: at,\n limit: eventLimit,\n });\n return { stream, source, at, lagging, events } as const;\n })\n );\n if (fetched.length) {\n tracer.fetched(fetched);\n\n const leases = new Map<\n string,\n { lease: Lease; lagging: boolean; payloads: ReactionPayload<E>[] }\n >();\n\n // compute fetch window max event id\n const fetch_window_at = fetched.reduce(\n (max, { at, events }) => Math.max(max, events.at(-1)?.id || at),\n 0\n );\n\n fetched.forEach(({ stream, lagging, events }) => {\n const payloads = events.flatMap((event) => {\n const register = this.registry.events[event.name] || [];\n return [...register.reactions.values()]\n .filter((reaction) => {\n const resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n return resolved && resolved.target === stream;\n })\n .map((reaction) => ({ ...reaction, event }));\n });\n leases.set(stream, {\n lease: {\n stream,\n by: randomUUID(),\n at: events.at(-1)?.id || fetch_window_at, // ff when no matching events\n retry: 0,\n lagging,\n },\n // @ts-expect-error indexed by key\n payloads,\n });\n });\n\n const leased = await store().lease(\n [...leases.values()].map(({ lease }) => lease),\n leaseMillis\n );\n tracer.leased(leased);\n\n const handled = await Promise.all(\n leased.map((lease) =>\n this.handle(lease, leases.get(lease.stream)!.payloads)\n )\n );\n\n // adaptive drain ratio based on handled events, favors frontier with highest pressure (clamped between 20% and 80%)\n const [lagging_handled, leading_handled] = handled.reduce(\n ([lagging_handled, leading_handled], { lease, handled }) => [\n lagging_handled + (lease.lagging ? handled : 0),\n leading_handled + (lease.lagging ? 0 : handled),\n ],\n [0, 0]\n );\n const lagging_avg = lagging > 0 ? lagging_handled / lagging : 0;\n const leading_avg = leading > 0 ? leading_handled / leading : 0;\n const total = lagging_avg + leading_avg;\n this._drain_lag2lead_ratio =\n total > 0 ? Math.max(0.2, Math.min(0.8, lagging_avg / total)) : 0.5;\n\n const acked = await store().ack(\n handled\n .filter(({ error }) => !error)\n .map(({ at, lease }) => ({ ...lease, at }))\n );\n if (acked.length) {\n tracer.acked(acked);\n this.emit(\"acked\", acked);\n }\n\n const blocked = await store().block(\n handled\n .filter(({ block }) => block)\n .map(({ lease, error }) => ({ ...lease, error: error! }))\n );\n if (blocked.length) {\n tracer.blocked(blocked);\n this.emit(\"blocked\", blocked);\n }\n\n // @ts-expect-error key\n return { fetched, leased, acked, blocked };\n }\n } catch (error) {\n logger.error(error);\n } finally {\n this._drain_locked = false;\n }\n }\n\n return { fetched: [], leased: [], acked: [], blocked: [] };\n }\n\n /**\n * Discovers and registers new streams dynamically based on reaction resolvers.\n *\n * Correlation enables \"dynamic reactions\" where target streams are determined at runtime\n * based on event content. For example, you might create a stats stream for each user\n * when they perform certain actions.\n *\n * This method scans events matching the query and identifies new target streams based\n * on reaction resolvers. It then registers these streams so they'll be picked up by\n * the next drain cycle.\n *\n * @param query - Query filter to scan for new correlations\n * @param query.after - Start scanning after this event ID (default: -1)\n * @param query.limit - Maximum events to scan (default: 10)\n * @returns Object with newly leased streams and last scanned event ID\n *\n * @example Manual correlation\n * ```typescript\n * // Scan for new streams\n * const { leased, last_id } = await app.correlate({ after: 0, limit: 100 });\n * console.log(`Found ${leased.length} new streams`);\n *\n * // Save last_id for next scan\n * await saveCheckpoint(last_id);\n * ```\n *\n * @example Dynamic stream creation\n * ```typescript\n * const app = act()\n * .with(User)\n * .with(UserStats)\n * .on(\"UserLoggedIn\")\n * .do(async (event) => [\"incrementLoginCount\", {}])\n * .to((event) => ({\n * target: `stats-${event.stream}` // Dynamic target per user\n * }))\n * .build();\n *\n * // Discover stats streams as users log in\n * await app.correlate();\n * ```\n *\n * @see {@link start_correlations} for automatic periodic correlation\n * @see {@link stop_correlations} to stop automatic correlation\n */\n async correlate(\n query: Query = { after: -1, limit: 10 }\n ): Promise<{ leased: Lease[]; last_id: number }> {\n const correlated = new Map<string, ReactionPayload<E>[]>();\n let last_id = query.after || -1;\n await store().query<E>((event) => {\n last_id = event.id;\n const register = this.registry.events[event.name];\n // skip events with no registered reactions\n if (register) {\n for (const reaction of register.reactions.values()) {\n const resolved =\n typeof reaction.resolver === \"function\"\n ? reaction.resolver(event)\n : reaction.resolver;\n resolved &&\n (\n correlated.get(resolved.target) ||\n correlated.set(resolved.target, []).get(resolved.target)!\n ).push({ ...reaction, source: resolved.source, event });\n }\n }\n }, query);\n if (correlated.size) {\n const leases = [...correlated.entries()].map(([stream, payloads]) => ({\n stream,\n // TODO: by convention, the first defined source wins (this can be tricky)\n source: payloads.find((p) => p.source)?.source || undefined,\n by: randomUUID(),\n at: 0,\n retry: 0,\n lagging: true,\n payloads,\n }));\n // register leases with 0ms lease timeout (just to tag the new streams)\n const leased = await store().lease(leases, 0);\n leased.length && tracer.correlated(leased);\n return { leased, last_id };\n }\n return { leased: [], last_id };\n }\n\n /**\n * Starts automatic periodic correlation worker for discovering new streams.\n *\n * The correlation worker runs in the background, scanning for new events and identifying\n * new target streams based on reaction resolvers. It maintains a sliding window that\n * advances with each scan, ensuring all events are eventually correlated.\n *\n * This is useful for dynamic stream creation patterns where you don't know all streams\n * upfront - they're discovered as events arrive.\n *\n * **Note:** Only one correlation worker can run at a time per Act instance.\n *\n * @param query - Query filter for correlation scans\n * @param query.after - Initial starting point (default: -1, start from beginning)\n * @param query.limit - Events to scan per cycle (default: 100)\n * @param frequency - Correlation frequency in milliseconds (default: 10000)\n * @param callback - Optional callback invoked with newly discovered streams\n * @returns `true` if worker started, `false` if already running\n *\n * @example Start automatic correlation\n * ```typescript\n * // Start correlation worker scanning every 5 seconds\n * app.start_correlations(\n * { after: 0, limit: 100 },\n * 5000,\n * (leased) => {\n * console.log(`Discovered ${leased.length} new streams`);\n * }\n * );\n *\n * // Later, stop it\n * app.stop_correlations();\n * ```\n *\n * @example With checkpoint persistence\n * ```typescript\n * // Load last checkpoint\n * const lastId = await loadCheckpoint();\n *\n * app.start_correlations(\n * { after: lastId, limit: 100 },\n * 10000,\n * async (leased) => {\n * // Save checkpoint for next restart\n * if (leased.length) {\n * const maxId = Math.max(...leased.map(l => l.at));\n * await saveCheckpoint(maxId);\n * }\n * }\n * );\n * ```\n *\n * @see {@link correlate} for manual one-time correlation\n * @see {@link stop_correlations} to stop the worker\n */\n start_correlations(\n query: Query = {},\n frequency = 10_000,\n callback?: (leased: Lease[]) => void\n ): boolean {\n if (this._correlation_interval) return false;\n\n const limit = query.limit || 100;\n let after = query.after || -1;\n this._correlation_interval = setInterval(\n () =>\n this.correlate({ ...query, after, limit })\n .then((result) => {\n after = result.last_id;\n if (callback && result.leased.length) callback(result.leased);\n })\n .catch(console.error),\n frequency\n );\n return true;\n }\n\n /**\n * Stops the automatic correlation worker.\n *\n * Call this to stop the background correlation worker started by {@link start_correlations}.\n * This is automatically called when the Act instance is disposed.\n *\n * @example\n * ```typescript\n * // Start correlation\n * app.start_correlations();\n *\n * // Later, stop it\n * app.stop_correlations();\n * ```\n *\n * @see {@link start_correlations}\n */\n stop_correlations() {\n if (this._correlation_interval) {\n clearInterval(this._correlation_interval);\n this._correlation_interval = undefined;\n }\n }\n}\n","/**\n * @module event-sourcing\n * @category Event Sourcing\n *\n * Utilities for event sourcing, snapshotting, and event store interaction.\n */\n\nimport { randomUUID } from \"crypto\";\nimport { logger, SNAP_EVENT, store } from \"./ports.js\";\nimport { InvariantError } from \"./types/errors.js\";\nimport type {\n Committed,\n Emitted,\n EventMeta,\n Schema,\n Schemas,\n Snapshot,\n State,\n Target,\n} from \"./types/index.js\";\nimport { patch, validate } from \"./utils.js\";\n\n/**\n * Event sourcing utilities for snapshotting, loading, and committing actions/events.\n * Used internally by Act and state machines.\n */\n\n/**\n * Saves a snapshot of the state to the store.\n *\n * Snapshots are used to optimize state reconstruction for aggregates with long event streams.\n *\n * @template S The type of state\n * @template E The type of events\n * @param snapshot The snapshot to save\n * @returns Promise that resolves when the snapshot is saved\n *\n * @example\n * await snap(snapshot);\n */\nexport async function snap<S extends Schema, E extends Schemas>(\n snapshot: Snapshot<S, E>\n): Promise<void> {\n try {\n const { id, stream, name, meta, version } = snapshot.event!;\n const snapped = await store().commit(\n stream,\n [{ name: SNAP_EVENT, data: snapshot.state }],\n {\n correlation: meta.correlation,\n causation: { event: { id, name: name as string, stream } },\n },\n version // IMPORTANT! - state events are committed right after the snapshot event\n );\n logger.trace(snapped, \"🟠 snap\");\n } catch (error) {\n logger.error(error);\n }\n}\n\n/**\n * Loads a snapshot of the state from the store by replaying events and applying patches.\n *\n * @template S The type of state\n * @template E The type of events\n * @template A The type of actions\n * @param me The state machine definition\n * @param stream The stream (instance) to load\n * @param callback (Optional) Callback to receive the loaded snapshot as it is built\n * @returns The snapshot of the loaded state\n *\n * @example\n * const snapshot = await load(Counter, \"counter1\");\n */\nexport async function load<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n>(\n me: State<S, E, A>,\n stream: string,\n callback?: (snapshot: Snapshot<S, E>) => void\n): Promise<Snapshot<S, E>> {\n let state = me.init ? me.init() : ({} as S);\n let patches = 0;\n let snaps = 0;\n let event: Committed<E, string> | undefined;\n await store().query(\n (e) => {\n event = e as Committed<E, string>;\n if (e.name === SNAP_EVENT) {\n state = e.data as S;\n snaps++;\n patches = 0;\n } else if (me.patch[e.name]) {\n state = patch(state, me.patch[e.name](event, state));\n patches++;\n }\n callback && callback({ event, state, patches, snaps });\n },\n { stream, with_snaps: true }\n );\n logger.trace(state as object, `🟢 load ${stream}`);\n return { event, state, patches, snaps };\n}\n\n/**\n * Executes an action and emits an event to be committed by the store.\n *\n * This function validates the action, applies business invariants, emits events, and commits them to the event store.\n *\n * @template S The type of state\n * @template E The type of events\n * @template A The type of actionSchemas\n * @template K The type of action to execute\n * @param me The state machine definition\n * @param action The action to execute\n * @param target The target (stream, actor, etc.)\n * @param payload The payload of the action\n * @param reactingTo (Optional) The event that the action is reacting to\n * @param skipValidation (Optional) Whether to skip validation (not recommended)\n * @returns The snapshot of the committed event\n *\n * @example\n * const snapshot = await action(Counter, \"increment\", { stream: \"counter1\", actor }, { by: 1 });\n */\nexport async function action<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n K extends keyof A,\n>(\n me: State<S, E, A>,\n action: K,\n target: Target,\n payload: Readonly<A[K]>,\n reactingTo?: Committed<Schemas, keyof Schemas>,\n skipValidation = false\n): Promise<Snapshot<S, E>[]> {\n const { stream, expectedVersion, actor } = target;\n if (!stream) throw new Error(\"Missing target stream\");\n\n payload = skipValidation\n ? payload\n : validate(action as string, payload, me.actions[action]);\n\n const snapshot = await load(me, stream);\n const expected = expectedVersion || snapshot.event?.version;\n\n logger.trace(\n payload as object,\n `🔵 ${stream}.${action as string}${typeof expected === \"number\" ? `.${expected}` : \"\"}`\n );\n\n if (me.given) {\n const invariants = me.given[action] || [];\n invariants.forEach(({ valid, description }) => {\n if (!valid(snapshot.state, actor))\n throw new InvariantError(\n action,\n payload,\n target,\n snapshot,\n description\n );\n });\n }\n\n const result = me.on[action](payload, snapshot, target);\n if (!result) return [snapshot];\n\n // An empty array means no events were emitted\n if (Array.isArray(result) && result.length === 0) {\n return [snapshot];\n }\n\n const tuples = Array.isArray(result[0])\n ? (result as Emitted<E>[]) // array of tuples\n : ([result] as Emitted<E>[]); // single tuple\n\n const emitted = tuples.map(([name, data]) => ({\n name,\n data: skipValidation\n ? data\n : validate(name as string, data, me.events[name]),\n }));\n\n const meta: EventMeta = {\n correlation: reactingTo?.meta.correlation || randomUUID(),\n causation: {\n action: {\n name: action as string,\n ...target,\n // payload: TODO: flag to include action payload in metadata\n // not included by default to avoid large payloads\n },\n event: reactingTo\n ? {\n id: reactingTo.id,\n name: reactingTo.name,\n stream: reactingTo.stream,\n }\n : undefined,\n },\n };\n\n logger.trace(\n emitted.map((e) => e.data),\n `🔴 commit ${stream}.${emitted.map((e) => e.name).join(\", \")}`\n );\n\n const committed = await store().commit(\n stream,\n emitted,\n meta,\n // TODO: review reactions not enforcing expected version\n reactingTo ? undefined : expected\n );\n\n let { state, patches } = snapshot;\n const snapshots = committed.map((event) => {\n state = patch(state, me.patch[event.name](event, state));\n patches++;\n return { event, state, patches, snaps: snapshot.snaps };\n });\n\n // fire and forget snaps\n const last = snapshots.at(-1)!;\n me.snap && me.snap(last) && void snap(last);\n\n return snapshots;\n}\n","/**\n * @module act-builder\n * @category Builders\n *\n * Fluent builder for composing event-sourced applications.\n */\nimport { Act } from \"./act.js\";\nimport type {\n EventRegister,\n Reaction,\n ReactionHandler,\n ReactionOptions,\n ReactionResolver,\n Registry,\n Schema,\n SchemaRegister,\n Schemas,\n State,\n} from \"./types/index.js\";\n\n// resolves the event stream as source and target (default)\nconst _this_ = ({ stream }: { stream: string }) => ({\n source: stream,\n target: stream,\n});\n// resolves to nothing\nconst _void_ = () => undefined;\n\n/**\n * Fluent builder interface for composing event-sourced applications.\n *\n * Provides a chainable API for:\n * - Registering states via `.with()`\n * - Defining event reactions via `.on()` → `.do()` → `.to()` or `.void()`\n * - Building the orchestrator via `.build()`\n *\n * @template S - Schema register for states (maps action names to state schemas)\n * @template E - Event schemas (maps event names to event data schemas)\n * @template A - Action schemas (maps action names to action payload schemas)\n *\n * @see {@link act} for usage examples\n * @see {@link Act} for the built orchestrator API\n */\nexport type ActBuilder<\n S extends SchemaRegister<A>,\n E extends Schemas,\n A extends Schemas,\n> = {\n /**\n * Registers a state definition with the builder.\n *\n * States define aggregates that process actions and emit events. Each state\n * registration adds its actions and events to the orchestrator's registry.\n * State names, action names, and event names must be unique across the application.\n *\n * @template SX - State schema type\n * @template EX - Event schemas type for this state\n * @template AX - Action schemas type for this state\n * @param state - The state definition to register\n * @returns The builder with updated type information for chaining\n *\n * @throws {Error} If a state with duplicate action or event names is registered\n *\n * @example Register single state\n * ```typescript\n * const app = act()\n * .with(Counter)\n * .build();\n * ```\n *\n * @example Register multiple states\n * ```typescript\n * const app = act()\n * .with(User)\n * .with(Order)\n * .with(Inventory)\n * .build();\n * ```\n */\n with: <SX extends Schema, EX extends Schemas, AX extends Schemas>(\n state: State<SX, EX, AX>\n ) => ActBuilder<S & { [K in keyof AX]: SX }, E & EX, A & AX>;\n /**\n * Begins defining a reaction to a specific event.\n *\n * Reactions are event handlers that respond to state changes. They can trigger\n * additional actions, update external systems, or perform side effects. Reactions\n * are processed asynchronously during drain cycles.\n *\n * @template K - Event name (must be a registered event)\n * @param event - The event name to react to\n * @returns An object with `.do()` method to define the reaction handler\n *\n * @example\n * ```typescript\n * const app = act()\n * .with(User)\n * .on(\"UserCreated\") // React to UserCreated events\n * .do(async (event) => {\n * await sendWelcomeEmail(event.data.email);\n * })\n * .void()\n * .build();\n * ```\n */\n on: <K extends keyof E>(\n event: K\n ) => {\n /**\n * Defines the reaction handler function for the event.\n *\n * The handler receives the committed event and can:\n * - Perform side effects (send emails, call APIs, etc.)\n * - Return an action tuple `[actionName, payload]` to trigger another action\n * - Return `void` or `undefined` for side-effect-only reactions\n *\n * @param handler - The reaction handler function\n * @param options - Optional reaction configuration\n * @param options.blockOnError - Block this stream if handler fails (default: true)\n * @param options.maxRetries - Maximum retry attempts on failure (default: 3)\n * @returns The builder with `.to()` and `.void()` methods for routing configuration\n *\n * @example Side effect only (void)\n * ```typescript\n * .on(\"UserCreated\")\n * .do(async (event) => {\n * await analytics.track(\"user_created\", event.data);\n * })\n * .void()\n * ```\n *\n * @example Trigger another action\n * ```typescript\n * .on(\"OrderPlaced\")\n * .do(async (event) => {\n * return [\"reduceStock\", { amount: event.data.items.length }];\n * })\n * .to(\"inventory-1\")\n * ```\n *\n * @example With retry configuration\n * ```typescript\n * .on(\"PaymentProcessed\")\n * .do(async (event) => {\n * await externalAPI.notify(event.data);\n * }, {\n * blockOnError: false, // Don't block on failure\n * maxRetries: 5 // Retry up to 5 times\n * })\n * .void()\n * ```\n */\n do: (\n handler: ReactionHandler<E, K>,\n options?: Partial<ReactionOptions>\n ) => ActBuilder<S, E, A> & {\n /**\n * Routes the reaction to a specific target stream.\n *\n * Use this when the reaction triggers an action on a specific state instance.\n * You can provide either a static stream name (string) or a resolver function\n * that dynamically determines the target based on the event.\n *\n * @param resolver - Target stream name (string) or resolver function\n * @returns The builder for chaining\n *\n * @example Static target stream\n * ```typescript\n * .on(\"OrderPlaced\")\n * .do(async (event) => [\"reduceStock\", { amount: 10 }])\n * .to(\"inventory-main\")\n * ```\n *\n * @example Dynamic target based on event data\n * ```typescript\n * .on(\"OrderPlaced\")\n * .do(async (event) => [\"reduceStock\", { amount: 10 }])\n * .to((event) => ({\n * target: `inventory-${event.data.warehouseId}`\n * }))\n * ```\n *\n * @example Source and target routing\n * ```typescript\n * .on(\"UserLoggedIn\")\n * .do(async (event) => [\"incrementCount\", {}])\n * .to(({ stream }) => ({\n * source: stream, // React to events from this user stream\n * target: `stats-${stream}` // Update corresponding stats stream\n * }))\n * ```\n */\n to: (resolver: ReactionResolver<E, K> | string) => ActBuilder<S, E, A>;\n /**\n * Marks the reaction as void (side-effect only, no target stream).\n *\n * Use this when the reaction doesn't trigger any actions - it only performs\n * side effects like logging, sending notifications, or updating external systems.\n *\n * @returns The builder for chaining\n *\n * @example\n * ```typescript\n * .on(\"UserCreated\")\n * .do(async (event) => {\n * await sendEmail(event.data.email, \"Welcome!\");\n * await logger.info(\"User created\", event.data);\n * })\n * .void() // No target stream\n * ```\n */\n void: () => ActBuilder<S, E, A>;\n };\n };\n /**\n * Builds and returns the Act orchestrator instance.\n *\n * This finalizes the builder configuration and creates the orchestrator that\n * can execute actions, load state, and process reactions.\n *\n * @param drainLimit - Deprecated parameter, no longer used\n * @returns The Act orchestrator instance\n *\n * @example\n * ```typescript\n * const app = act()\n * .with(Counter)\n * .with(User)\n * .on(\"UserCreated\")\n * .do(sendWelcomeEmail)\n * .void()\n * .build();\n *\n * // Now use the app\n * await app.do(\"createUser\", target, payload);\n * await app.drain();\n * ```\n *\n * @see {@link Act} for available orchestrator methods\n */\n build: (drainLimit?: number) => Act<S, E, A>;\n /**\n * The registered event schemas and their reaction maps.\n *\n * This is an internal registry maintained by the builder. Generally, you don't\n * need to access this directly.\n */\n readonly events: EventRegister<E>;\n};\n\n/* eslint-disable @typescript-eslint/no-empty-object-type */\n\n/**\n * Creates a new Act orchestrator builder for composing event-sourced applications.\n *\n * The Act orchestrator is responsible for:\n * - Managing state instances (aggregates)\n * - Executing actions and committing events\n * - Processing reactions (event handlers)\n * - Coordinating event-driven workflows\n *\n * Use the fluent API to register states with `.with()`, define event reactions with `.on()`,\n * and build the orchestrator with `.build()`.\n *\n * @template S - State schema register type\n * @template E - Event schemas type\n * @template A - Action schemas type\n * @returns An ActBuilder instance for fluent API configuration\n *\n * @example Basic application with single state\n * ```typescript\n * import { act, state } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const Counter = state(\"Counter\", z.object({ count: z.number() }))\n * .init(() => ({ count: 0 }))\n * .emits({ Incremented: z.object({ amount: z.number() }) })\n * .patch({ Incremented: (event, state) => ({ count: state.count + event.data.amount }) })\n * .on(\"increment\", z.object({ by: z.number() }))\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * .build();\n *\n * const app = act()\n * .with(Counter)\n * .build();\n *\n * // Execute action\n * await app.do(\"increment\",\n * { stream: \"counter1\", actor: { id: \"user1\", name: \"Alice\" } },\n * { by: 5 }\n * );\n *\n * // Load current state\n * const snapshot = await app.load(Counter, \"counter1\");\n * console.log(snapshot.state.count); // 5\n * ```\n *\n * @example Application with reactions\n * ```typescript\n * const User = state(\"User\", z.object({ name: z.string(), email: z.string() }))\n * .init((data) => data)\n * .emits({ UserCreated: z.object({ name: z.string(), email: z.string() }) })\n * .patch({ UserCreated: (event) => event.data })\n * .on(\"createUser\", z.object({ name: z.string(), email: z.string() }))\n * .emit((action) => [\"UserCreated\", action])\n * .build();\n *\n * const app = act()\n * .with(User)\n * .on(\"UserCreated\")\n * .do(async (event) => {\n * // Send welcome email\n * await sendEmail(event.data.email, \"Welcome!\");\n * logger.info(`Sent welcome email to ${event.data.email}`);\n * })\n * .void() // No target stream, just side effects\n * .build();\n *\n * // Create user (triggers email sending via reaction)\n * await app.do(\"createUser\",\n * { stream: \"user-123\", actor: { id: \"admin\", name: \"Admin\" } },\n * { name: \"Alice\", email: \"alice@example.com\" }\n * );\n *\n * // Process reactions\n * await app.drain();\n * ```\n *\n * @example Multi-state application with event correlation\n * ```typescript\n * const Order = state(\"Order\", z.object({ items: z.array(z.string()), total: z.number() }))\n * .init((data) => data)\n * .emits({ OrderPlaced: z.object({ items: z.array(z.string()), total: z.number() }) })\n * .patch({ OrderPlaced: (event) => event.data })\n * .on(\"placeOrder\", z.object({ items: z.array(z.string()), total: z.number() }))\n * .emit((action) => [\"OrderPlaced\", action])\n * .build();\n *\n * const Inventory = state(\"Inventory\", z.object({ stock: z.number() }))\n * .init(() => ({ stock: 100 }))\n * .emits({ StockReduced: z.object({ amount: z.number() }) })\n * .patch({ StockReduced: (event, state) => ({ stock: state.stock - event.data.amount }) })\n * .on(\"reduceStock\", z.object({ amount: z.number() }))\n * .emit((action) => [\"StockReduced\", { amount: action.amount }])\n * .build();\n *\n * const app = act()\n * .with(Order)\n * .with(Inventory)\n * .on(\"OrderPlaced\")\n * .do(async (event) => {\n * // Reduce inventory for each item\n * return [\"reduceStock\", { amount: event.data.items.length }];\n * })\n * .to(\"inventory-1\") // Target specific inventory stream\n * .build();\n *\n * await app.do(\"placeOrder\",\n * { stream: \"order-1\", actor: { id: \"user1\", name: \"Alice\" } },\n * { items: [\"item1\", \"item2\"], total: 100 }\n * );\n *\n * // Process reaction (reduces inventory)\n * await app.drain();\n * ```\n *\n * @see {@link ActBuilder} for available builder methods\n * @see {@link Act} for orchestrator API methods\n * @see {@link state} for defining states\n * @see {@link https://rotorsoft.github.io/act-root/docs/intro | Documentation}\n */\nexport function act<\n // @ts-expect-error empty schema\n S extends SchemaRegister<A> = {},\n E extends Schemas = {},\n A extends Schemas = {},\n>(\n states: Set<string> = new Set(),\n registry: Registry<S, E, A> = {\n actions: {} as any,\n events: {} as any,\n }\n): ActBuilder<S, E, A> {\n const builder: ActBuilder<S, E, A> = {\n /**\n * Adds a state to the builder.\n *\n * @template SX The type of state\n * @template EX The type of events\n * @template AX The type of actions\n * @param state The state to add\n * @returns The builder\n */\n with: <SX extends Schema, EX extends Schemas, AX extends Schemas>(\n state: State<SX, EX, AX>\n ) => {\n if (!states.has(state.name)) {\n states.add(state.name);\n for (const name of Object.keys(state.actions)) {\n if (registry.actions[name])\n throw new Error(`Duplicate action \"${name}\"`);\n // @ts-expect-error indexed access\n registry.actions[name] = state;\n }\n for (const name of Object.keys(state.events)) {\n if (registry.events[name])\n throw new Error(`Duplicate event \"${name}\"`);\n // @ts-expect-error indexed access\n registry.events[name] = {\n schema: state.events[name],\n reactions: new Map(),\n };\n }\n }\n return act<S & { [K in keyof AX]: SX }, E & EX, A & AX>(\n states,\n registry as unknown as Registry<\n S & { [K in keyof AX]: SX },\n E & EX,\n A & AX\n >\n );\n },\n /**\n * Adds a reaction to an event.\n *\n * @template K The type of event\n * @param event The event to add a reaction to\n * @returns The builder\n */\n on: <K extends keyof E>(event: K) => ({\n do: (\n handler: ReactionHandler<E, K>,\n options?: Partial<ReactionOptions>\n ) => {\n const reaction: Reaction<E, K> = {\n handler,\n resolver: _this_,\n options: {\n blockOnError: options?.blockOnError ?? true,\n maxRetries: options?.maxRetries ?? 3,\n },\n };\n registry.events[event].reactions.set(handler.name, reaction);\n return {\n ...builder,\n to(resolver: ReactionResolver<E, K> | string) {\n registry.events[event].reactions.set(handler.name, {\n ...reaction,\n resolver:\n typeof resolver === \"string\" ? { target: resolver } : resolver,\n });\n return builder;\n },\n void() {\n registry.events[event].reactions.set(handler.name, {\n ...reaction,\n resolver: _void_,\n });\n return builder;\n },\n };\n },\n }),\n build: () => new Act<S, E, A>(registry),\n events: registry.events,\n };\n return builder;\n}\n","/**\n * @module state-builder\n * @category Builders\n *\n * Fluent interface for defining a strongly-typed state machine using Zod schemas.\n */\nimport { ZodType } from \"zod\";\nimport {\n ActionHandler,\n ActionHandlers,\n GivenHandlers,\n Invariant,\n PatchHandlers,\n Schema,\n Schemas,\n Snapshot,\n State,\n ZodTypes,\n} from \"./types/index.js\";\n\n/* eslint-disable @typescript-eslint/no-empty-object-type */\n/**\n * Builder interface for defining a state with event sourcing.\n *\n * Provides a fluent API to configure the initial state, event types,\n * and event handlers (reducers) before moving to action configuration.\n *\n * @template S - State schema type\n *\n * @see {@link state} for usage examples\n * @see {@link ActionBuilder} for action configuration\n */\nexport type StateBuilder<S extends Schema> = {\n /**\n * Defines the initial state for new state instances.\n *\n * The init function is called when a new stream is created (first event).\n * It can accept initial data or return a default state.\n *\n * @param init - Function returning the initial state\n * @returns A builder with `.emits()` to declare event types\n *\n * @example\n * ```typescript\n * .init(() => ({ count: 0, created: new Date() }))\n * ```\n *\n * @example With initial data\n * ```typescript\n * .init((data) => ({ ...data, createdAt: new Date() }))\n * ```\n */\n init: (init: () => Readonly<S>) => {\n /**\n * Declares the event types that this state can emit.\n *\n * Events represent facts that have happened - they should be named in past tense.\n * Each event is defined with a Zod schema for type safety and runtime validation.\n *\n * @template E - Event schemas type\n * @param events - Object mapping event names to Zod schemas\n * @returns A builder with `.patch()` to define event handlers\n *\n * @example\n * ```typescript\n * .emits({\n * Incremented: z.object({ amount: z.number() }),\n * Decremented: z.object({ amount: z.number() }),\n * Reset: z.object({})\n * })\n * ```\n */\n emits: <E extends Schemas>(\n events: ZodTypes<E>\n ) => {\n /**\n * Defines how each event updates (patches) the state.\n *\n * Patch handlers are reducers - pure functions that take an event and current state,\n * and return the changes to apply. Return partial state objects; unchanged fields\n * are preserved automatically.\n *\n * @param patch - Object mapping event names to patch handler functions\n * @returns An ActionBuilder for defining actions\n *\n * @example\n * ```typescript\n * .patch({\n * Incremented: (event, state) => ({ count: state.count + event.data.amount }),\n * Decremented: (event, state) => ({ count: state.count - event.data.amount }),\n * Reset: () => ({ count: 0 })\n * })\n * ```\n */\n patch: (patch: PatchHandlers<S, E>) => ActionBuilder<S, E, {}>;\n };\n };\n};\n\n/**\n * Builder interface for defining actions (commands) on a state.\n *\n * Actions represent user/system intents to modify state. Each action is validated\n * against a schema, can have business rule invariants, and must emit one or more events.\n *\n * @template S - State schema type\n * @template E - Event schemas type\n * @template A - Action schemas type\n *\n * @see {@link state} for complete usage examples\n */\nexport type ActionBuilder<\n S extends Schema,\n E extends Schemas,\n A extends Schemas,\n> = {\n /**\n * Defines an action (command) that can be executed on this state.\n *\n * Actions represent intents to change state - they should be named in imperative form\n * (e.g., \"createUser\", \"incrementCounter\", \"placeOrder\"). Actions are validated against\n * their schema and must emit at least one event.\n *\n * @template K - Action name (string literal type)\n * @template AX - Action payload schema type\n * @param action - The action name (should be unique within this state)\n * @param schema - Zod schema for the action payload\n * @returns An object with `.given()` and `.emit()` for further configuration\n *\n * @example Simple action without invariants\n * ```typescript\n * .on(\"increment\", z.object({ by: z.number() }))\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * ```\n *\n * @example Action with business rules\n * ```typescript\n * .on(\"withdraw\", z.object({ amount: z.number() }))\n * .given([\n * (_, snap) => snap.state.balance >= 0 || \"Account closed\",\n * (_, snap, action) => snap.state.balance >= action.amount || \"Insufficient funds\"\n * ])\n * .emit((action) => [\"Withdrawn\", { amount: action.amount }])\n * ```\n *\n * @example Action emitting multiple events\n * ```typescript\n * .on(\"completeOrder\", z.object({ orderId: z.string() }))\n * .emit((action) => [\n * [\"OrderCompleted\", { orderId: action.orderId }],\n * [\"InventoryReserved\", { orderId: action.orderId }],\n * [\"PaymentProcessed\", { orderId: action.orderId }]\n * ])\n * ```\n */\n on: <K extends string, AX extends Schema>(\n action: K,\n schema: ZodType<AX>\n ) => {\n /**\n * Adds business rule invariants that must hold before the action can execute.\n *\n * Invariants are checked after loading the current state but before emitting events.\n * Each invariant should return `true` or an error message string. All invariants\n * must pass for the action to succeed.\n *\n * @param rules - Array of invariant functions\n * @returns An object with `.emit()` to finalize the action\n *\n * @example\n * ```typescript\n * .given([\n * (_, snap) => snap.state.status === \"active\" || \"Must be active\",\n * (target, snap) => snap.state.ownerId === target.actor.id || \"Not authorized\"\n * ])\n * ```\n */\n given: (rules: Invariant<S>[]) => {\n /**\n * Defines the action handler that emits events.\n *\n * The handler receives the action payload and current state snapshot,\n * and must return one or more events to emit. Events are applied to state\n * via the patch handlers defined earlier.\n *\n * @param handler - Function that returns events to emit\n * @returns The ActionBuilder for chaining more actions\n *\n * @example\n * ```typescript\n * .emit((action, snapshot) => {\n * const newBalance = snapshot.state.balance + action.amount;\n * return [\"Deposited\", { amount: action.amount, newBalance }];\n * })\n * ```\n */\n emit: (\n handler: ActionHandler<S, E, { [P in K]: AX }, K>\n ) => ActionBuilder<S, E, A & { [P in K]: AX }>;\n };\n /**\n * Defines the action handler that emits events.\n *\n * The handler receives the action payload and current state snapshot,\n * and must return one or more events to emit. Return a single event as\n * `[\"EventName\", data]` or multiple events as an array of event tuples.\n *\n * @param handler - Function that returns events to emit\n * @returns The ActionBuilder for chaining more actions\n *\n * @example Single event\n * ```typescript\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * ```\n *\n * @example Multiple events\n * ```typescript\n * .emit((action) => [\n * [\"Incremented\", { amount: action.by }],\n * [\"LogUpdated\", { message: `Incremented by ${action.by}` }]\n * ])\n * ```\n *\n * @example Conditional events\n * ```typescript\n * .emit((action, snapshot) => {\n * if (snapshot.state.count + action.by >= 100) {\n * return [\n * [\"Incremented\", { amount: action.by }],\n * [\"MilestoneReached\", { milestone: 100 }]\n * ];\n * }\n * return [\"Incremented\", { amount: action.by }];\n * })\n * ```\n */\n emit: (\n handler: ActionHandler<S, E, { [P in K]: AX }, K>\n ) => ActionBuilder<S, E, A & { [P in K]: AX }>;\n };\n /**\n * Defines a snapshotting strategy to optimize state reconstruction.\n *\n * Snapshots store the current state at a point in time, allowing faster state loading\n * by avoiding replaying all events from the beginning. The snap function is called\n * after each event is applied and should return `true` when a snapshot should be taken.\n *\n * @param snap - Predicate function that returns true when a snapshot should be taken\n * @returns The ActionBuilder for chaining\n *\n * @example Snapshot every 10 events\n * ```typescript\n * .snap((snapshot) => snapshot.patches >= 10)\n * ```\n *\n * @example Snapshot based on state size\n * ```typescript\n * .snap((snapshot) => {\n * const estimatedSize = JSON.stringify(snapshot.state).length;\n * return estimatedSize > 10000 || snapshot.patches >= 50;\n * })\n * ```\n *\n * @example Time-based snapshotting\n * ```typescript\n * .snap((snapshot) => {\n * const hoursSinceLastSnapshot = snapshot.patches * 0.1; // Estimate\n * return hoursSinceLastSnapshot >= 24;\n * })\n * ```\n */\n snap: (snap: (snapshot: Snapshot<S, E>) => boolean) => ActionBuilder<S, E, A>;\n /**\n * Finalizes and builds the state definition.\n *\n * Call this method after defining all actions, invariants, and patches to create\n * the complete State object that can be registered with Act.\n *\n * @returns The complete strongly-typed State definition\n *\n * @example\n * ```typescript\n * const Counter = state(\"Counter\", schema)\n * .init(() => ({ count: 0 }))\n * .emits({ Incremented: z.object({ amount: z.number() }) })\n * .patch({ Incremented: (event, state) => ({ count: state.count + event.data.amount }) })\n * .on(\"increment\", z.object({ by: z.number() }))\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * .build(); // Returns State<S, E, A>\n * ```\n */\n build: () => State<S, E, A>;\n};\n\n/**\n * Creates a new state definition with event sourcing capabilities.\n *\n * States are the core building blocks of Act. Each state represents a consistency\n * boundary (aggregate) that processes actions, emits events, and maintains its own\n * state through event patches (reducers). States use event sourcing to maintain a\n * complete audit trail and enable time-travel capabilities.\n *\n * The state builder provides a fluent API for defining:\n * 1. Initial state via `.init()`\n * 2. Event types via `.emits()`\n * 3. Event handlers (reducers) via `.patch()`\n * 4. Actions (commands) via `.on()` → `.emit()`\n * 5. Business rules (invariants) via `.given()`\n * 6. Snapshotting strategy via `.snap()`\n *\n * @template S - Zod schema type defining the shape of the state\n * @param name - Unique identifier for this state type (e.g., \"Counter\", \"User\", \"Order\")\n * @param state - Zod schema defining the structure of the state\n * @returns A StateBuilder instance for fluent API configuration\n *\n * @example Basic counter state\n * ```typescript\n * import { state } from \"@rotorsoft/act\";\n * import { z } from \"zod\";\n *\n * const Counter = state(\"Counter\", z.object({ count: z.number() }))\n * .init(() => ({ count: 0 }))\n * .emits({\n * Incremented: z.object({ amount: z.number() })\n * })\n * .patch({\n * Incremented: (event, state) => ({ count: state.count + event.data.amount })\n * })\n * .on(\"increment\", z.object({ by: z.number() }))\n * .emit((action) => [\"Incremented\", { amount: action.by }])\n * .build();\n * ```\n *\n * @example State with multiple events and invariants\n * ```typescript\n * const BankAccount = state(\"BankAccount\", z.object({\n * balance: z.number(),\n * currency: z.string(),\n * status: z.enum([\"open\", \"closed\"])\n * }))\n * .init(() => ({ balance: 0, currency: \"USD\", status: \"open\" }))\n * .emits({\n * Deposited: z.object({ amount: z.number() }),\n * Withdrawn: z.object({ amount: z.number() }),\n * Closed: z.object({})\n * })\n * .patch({\n * Deposited: (event, state) => ({ balance: state.balance + event.data.amount }),\n * Withdrawn: (event, state) => ({ balance: state.balance - event.data.amount }),\n * Closed: () => ({ status: \"closed\", balance: 0 })\n * })\n * .on(\"deposit\", z.object({ amount: z.number() }))\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Account must be open\"\n * ])\n * .emit((action) => [\"Deposited\", { amount: action.amount }])\n * .on(\"withdraw\", z.object({ amount: z.number() }))\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Account must be open\",\n * (_, snap, action) =>\n * snap.state.balance >= action.amount || \"Insufficient funds\"\n * ])\n * .emit((action) => [\"Withdrawn\", { amount: action.amount }])\n * .on(\"close\", z.object({}))\n * .given([\n * (_, snap) => snap.state.status === \"open\" || \"Already closed\",\n * (_, snap) => snap.state.balance === 0 || \"Balance must be zero\"\n * ])\n * .emit(() => [\"Closed\", {}])\n * .build();\n * ```\n *\n * @example State with snapshotting\n * ```typescript\n * const User = state(\"User\", z.object({\n * name: z.string(),\n * email: z.string(),\n * loginCount: z.number()\n * }))\n * .init((data) => ({ ...data, loginCount: 0 }))\n * .emits({\n * UserCreated: z.object({ name: z.string(), email: z.string() }),\n * UserLoggedIn: z.object({})\n * })\n * .patch({\n * UserCreated: (event) => event.data,\n * UserLoggedIn: (_, state) => ({ loginCount: state.loginCount + 1 })\n * })\n * .on(\"createUser\", z.object({ name: z.string(), email: z.string() }))\n * .emit((action) => [\"UserCreated\", action])\n * .on(\"login\", z.object({}))\n * .emit(() => [\"UserLoggedIn\", {}])\n * .snap((snap) => snap.patches >= 10) // Snapshot every 10 events\n * .build();\n * ```\n *\n * @see {@link StateBuilder} for available builder methods\n * @see {@link ActionBuilder} for action configuration methods\n * @see {@link https://rotorsoft.github.io/act-root/docs/intro | Getting Started Guide}\n * @see {@link https://rotorsoft.github.io/act-root/docs/examples/calculator | Calculator Example}\n */\nexport function state<S extends Schema>(\n name: string,\n state: ZodType<S>\n): StateBuilder<S> {\n return {\n init(init: () => Readonly<S>) {\n return {\n emits<E extends Schema>(events: ZodTypes<E>) {\n return {\n patch(patch: PatchHandlers<S, E>) {\n return action_builder<S, E, {}>({\n events,\n actions: {},\n state,\n name,\n init,\n patch,\n on: {},\n });\n },\n };\n },\n };\n },\n };\n}\n\nfunction action_builder<S extends Schema, E extends Schemas, A extends Schemas>(\n state: State<S, E, A>\n): ActionBuilder<S, E, A> {\n return {\n on<K extends string, AX extends Schema>(action: K, schema: ZodType<AX>) {\n if (action in state.actions)\n throw new Error(`Duplicate action \"${action}\"`);\n\n type NewA = A & { [P in K]: AX };\n const actions = { ...state.actions, [action]: schema } as ZodTypes<NewA>;\n const on = { ...state.on } as ActionHandlers<S, E, NewA>;\n const _given = { ...state.given } as GivenHandlers<S, NewA>;\n\n function given(rules: Invariant<S>[]) {\n _given[action] = rules;\n return { emit };\n }\n\n function emit(handler: ActionHandler<S, E, NewA, K>) {\n on[action] = handler;\n return action_builder<S, E, NewA>({\n ...state,\n actions,\n on,\n given: _given,\n });\n }\n\n return { given, emit };\n },\n\n snap(snap: (snapshot: Snapshot<S, E>) => boolean) {\n return action_builder<S, E, A>({ ...state, snap });\n },\n\n build(): State<S, E, A> {\n return state;\n },\n };\n}\n"],"mappings":"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","names":["action","z","z","pkg","a","b","store","logLevel","stream","randomUUID","state","action","action","state","lagging","randomUUID","lagging_handled","leading_handled","handled","state","state","patch","action","snap"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rotorsoft/act",
3
3
  "type": "module",
4
- "version": "0.6.28",
4
+ "version": "0.6.29",
5
5
  "description": "act core library",
6
6
  "author": "rotorsoft",
7
7
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "pino": "^10.1.0",
33
+ "pino": "^10.1.1",
34
34
  "pino-pretty": "^13.1.3",
35
35
  "zod": "^4.3.5"
36
36
  },