@rotorsoft/act 0.35.0 → 0.35.2
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/.tsbuildinfo +1 -0
- package/dist/@types/act.d.ts +672 -0
- package/dist/@types/act.d.ts.map +1 -0
- package/dist/@types/adapters/console-logger.d.ts +41 -0
- package/dist/@types/adapters/console-logger.d.ts.map +1 -0
- package/dist/@types/adapters/in-memory-cache.d.ts +34 -0
- package/dist/@types/adapters/in-memory-cache.d.ts.map +1 -0
- package/dist/@types/adapters/in-memory-store.d.ts +202 -0
- package/dist/@types/adapters/in-memory-store.d.ts.map +1 -0
- package/dist/@types/adapters/index.d.ts +4 -0
- package/dist/@types/adapters/index.d.ts.map +1 -0
- package/dist/@types/builders/act-builder.d.ts +160 -0
- package/dist/@types/builders/act-builder.d.ts.map +1 -0
- package/dist/@types/builders/index.d.ts +13 -0
- package/dist/@types/builders/index.d.ts.map +1 -0
- package/dist/@types/builders/projection-builder.d.ts +101 -0
- package/dist/@types/builders/projection-builder.d.ts.map +1 -0
- package/dist/@types/builders/slice-builder.d.ts +109 -0
- package/dist/@types/builders/slice-builder.d.ts.map +1 -0
- package/dist/@types/builders/state-builder.d.ts +424 -0
- package/dist/@types/builders/state-builder.d.ts.map +1 -0
- package/dist/@types/config.d.ts +119 -0
- package/dist/@types/config.d.ts.map +1 -0
- package/dist/@types/index.d.ts +14 -0
- package/dist/@types/index.d.ts.map +1 -0
- package/dist/@types/internal/build-classify.d.ts +44 -0
- package/dist/@types/internal/build-classify.d.ts.map +1 -0
- package/dist/@types/internal/close-cycle.d.ts +38 -0
- package/dist/@types/internal/close-cycle.d.ts.map +1 -0
- package/dist/@types/internal/correlate-cycle.d.ts +78 -0
- package/dist/@types/internal/correlate-cycle.d.ts.map +1 -0
- package/dist/@types/internal/drain-cycle.d.ts +113 -0
- package/dist/@types/internal/drain-cycle.d.ts.map +1 -0
- package/dist/@types/internal/drain-ratio.d.ts +26 -0
- package/dist/@types/internal/drain-ratio.d.ts.map +1 -0
- package/dist/@types/internal/drain.d.ts +41 -0
- package/dist/@types/internal/drain.d.ts.map +1 -0
- package/dist/@types/internal/event-sourcing.d.ts +96 -0
- package/dist/@types/internal/event-sourcing.d.ts.map +1 -0
- package/dist/@types/internal/index.d.ts +29 -0
- package/dist/@types/internal/index.d.ts.map +1 -0
- package/dist/@types/internal/merge.d.ts +31 -0
- package/dist/@types/internal/merge.d.ts.map +1 -0
- package/dist/@types/internal/reactions.d.ts +54 -0
- package/dist/@types/internal/reactions.d.ts.map +1 -0
- package/dist/@types/internal/settle.d.ts +60 -0
- package/dist/@types/internal/settle.d.ts.map +1 -0
- package/dist/@types/internal/tracing.d.ts +45 -0
- package/dist/@types/internal/tracing.d.ts.map +1 -0
- package/dist/@types/lru-map.d.ts +50 -0
- package/dist/@types/lru-map.d.ts.map +1 -0
- package/dist/@types/ports.d.ts +196 -0
- package/dist/@types/ports.d.ts.map +1 -0
- package/dist/@types/signals.d.ts +2 -0
- package/dist/@types/signals.d.ts.map +1 -0
- package/dist/@types/types/action.d.ts +444 -0
- package/dist/@types/types/action.d.ts.map +1 -0
- package/dist/@types/types/errors.d.ts +284 -0
- package/dist/@types/types/errors.d.ts.map +1 -0
- package/dist/@types/types/index.d.ts +39 -0
- package/dist/@types/types/index.d.ts.map +1 -0
- package/dist/@types/types/ports.d.ts +617 -0
- package/dist/@types/types/ports.d.ts.map +1 -0
- package/dist/@types/types/reaction.d.ts +314 -0
- package/dist/@types/types/reaction.d.ts.map +1 -0
- package/dist/@types/types/registry.d.ts +74 -0
- package/dist/@types/types/registry.d.ts.map +1 -0
- package/dist/@types/types/schemas.d.ts +117 -0
- package/dist/@types/types/schemas.d.ts.map +1 -0
- package/dist/@types/utils.d.ts +54 -0
- package/dist/@types/utils.d.ts.map +1 -0
- package/dist/chunk-AGWZY6YT.js +127 -0
- package/dist/chunk-AGWZY6YT.js.map +1 -0
- package/dist/index.cjs +3144 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +2975 -0
- package/dist/index.js.map +1 -0
- package/dist/types/index.cjs +166 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.js +33 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +15 -5
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { Actor, Committed, EventRegister, IAct, ReactionOptions, ReactionResolver, Schema, SchemaRegister, Schemas, Snapshot, State } from "../types/index.js";
|
|
2
|
+
import type { Projection } from "./projection-builder.js";
|
|
3
|
+
/**
|
|
4
|
+
* A self-contained functional slice grouping partial states with their
|
|
5
|
+
* scoped reactions. Slices are composed into an Act orchestrator via
|
|
6
|
+
* `act().withSlice(slice)`.
|
|
7
|
+
*
|
|
8
|
+
* @template TSchemaReg - Schema register for states
|
|
9
|
+
* @template TEvents - Event schemas from this slice's states
|
|
10
|
+
* @template TActions - Action schemas from this slice's states
|
|
11
|
+
* @template TStateMap - Map of state names to state schemas
|
|
12
|
+
* @template TActor - Actor type extending base Actor
|
|
13
|
+
*/
|
|
14
|
+
export type Slice<TSchemaReg extends SchemaRegister<TActions>, TEvents extends Schemas, TActions extends Schemas, TStateMap extends Record<string, Schema> = {}, TActor extends Actor = Actor> = {
|
|
15
|
+
readonly _tag: "Slice";
|
|
16
|
+
readonly states: Map<string, State<any, any, any>>;
|
|
17
|
+
readonly events: EventRegister<TEvents>;
|
|
18
|
+
readonly projections: ReadonlyArray<Projection<any>>;
|
|
19
|
+
/** @internal phantom field for type-level state schema tracking */
|
|
20
|
+
readonly _S?: TSchemaReg;
|
|
21
|
+
/** @internal phantom field for type-level state name tracking */
|
|
22
|
+
readonly _M?: TStateMap;
|
|
23
|
+
/** @internal phantom field for type-level actor tracking */
|
|
24
|
+
readonly _TActor?: TActor;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Fluent builder interface for composing functional slices.
|
|
28
|
+
*
|
|
29
|
+
* Provides a chainable API for registering states and projections,
|
|
30
|
+
* and defining reactions scoped to the slice's own events.
|
|
31
|
+
*
|
|
32
|
+
* @template TSchemaReg - Schema register for states
|
|
33
|
+
* @template TEvents - Event schemas
|
|
34
|
+
* @template TActions - Action schemas
|
|
35
|
+
* @template TStateMap - Map of state names to state schemas
|
|
36
|
+
* @template TActor - Actor type extending base Actor
|
|
37
|
+
*/
|
|
38
|
+
export type SliceBuilder<TSchemaReg extends SchemaRegister<TActions>, TEvents extends Schemas, TActions extends Schemas, TStateMap extends Record<string, Schema> = {}, TActor extends Actor = Actor> = {
|
|
39
|
+
/**
|
|
40
|
+
* Registers a state definition with the slice.
|
|
41
|
+
*
|
|
42
|
+
* Include every state whose actions your reaction handlers need to
|
|
43
|
+
* dispatch. Duplicate registrations (same state in multiple slices)
|
|
44
|
+
* are handled automatically at composition time.
|
|
45
|
+
*/
|
|
46
|
+
withState: <TNewState extends Schema, TNewEvents extends Schemas, TNewActions extends Schemas, TNewName extends string = string>(state: State<TNewState, TNewEvents, TNewActions, TNewName>) => SliceBuilder<TSchemaReg & {
|
|
47
|
+
[K in keyof TNewActions]: TNewState;
|
|
48
|
+
}, TEvents & TNewEvents, TActions & TNewActions, TStateMap & {
|
|
49
|
+
[K in TNewName]: TNewState;
|
|
50
|
+
}, TActor>;
|
|
51
|
+
/**
|
|
52
|
+
* Embeds a built Projection within this slice. The projection's events
|
|
53
|
+
* must be a subset of events from states already registered via
|
|
54
|
+
* `.withState()`. Projection handlers preserve their `(event, stream)`
|
|
55
|
+
* signature and do not receive the app interface.
|
|
56
|
+
*/
|
|
57
|
+
withProjection: <TNewEvents extends Schemas>(projection: [Exclude<keyof TNewEvents, keyof TEvents>] extends [never] ? Projection<TNewEvents> : never) => SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor>;
|
|
58
|
+
/**
|
|
59
|
+
* Begins defining a reaction scoped to this slice's events.
|
|
60
|
+
*/
|
|
61
|
+
on: <TKey extends keyof TEvents>(event: TKey) => {
|
|
62
|
+
do: (handler: (event: Committed<TEvents, TKey>, stream: string, app: IAct<TEvents, TActions, TActor>) => Promise<Snapshot<Schema, TEvents> | void>, options?: Partial<ReactionOptions>) => SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor> & {
|
|
63
|
+
to: (resolver: ReactionResolver<TEvents, TKey> | string) => SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor>;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Builds and returns the Slice data structure.
|
|
68
|
+
*/
|
|
69
|
+
build: () => Slice<TSchemaReg, TEvents, TActions, TStateMap, TActor>;
|
|
70
|
+
/**
|
|
71
|
+
* The registered event schemas and their reaction maps.
|
|
72
|
+
*/
|
|
73
|
+
readonly events: EventRegister<TEvents>;
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Creates a new slice builder for composing partial states with scoped reactions.
|
|
77
|
+
*
|
|
78
|
+
* Slices enable vertical slice architecture by grouping related states and
|
|
79
|
+
* reactions into self-contained feature modules. Reactions defined in a slice
|
|
80
|
+
* are type-scoped to events from that slice's states only.
|
|
81
|
+
*
|
|
82
|
+
* @example Single-state slice with typed dispatch
|
|
83
|
+
* ```typescript
|
|
84
|
+
* const CounterSlice = slice()
|
|
85
|
+
* .withState(Counter)
|
|
86
|
+
* .on("Incremented")
|
|
87
|
+
* .do(async (event, _stream, app) => {
|
|
88
|
+
* await app.do("reset", target, {});
|
|
89
|
+
* })
|
|
90
|
+
* .to("counter-target")
|
|
91
|
+
* .build();
|
|
92
|
+
* ```
|
|
93
|
+
*
|
|
94
|
+
* @example Cross-state dispatch (include both states)
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const CreationSlice = slice()
|
|
97
|
+
* .withState(TicketCreation)
|
|
98
|
+
* .withState(TicketOperations) // handler can dispatch AssignTicket
|
|
99
|
+
* .on("TicketOpened").do(async (event, _stream, app) => {
|
|
100
|
+
* await app.do("AssignTicket", target, payload, event);
|
|
101
|
+
* })
|
|
102
|
+
* .build();
|
|
103
|
+
* ```
|
|
104
|
+
*
|
|
105
|
+
* @see {@link SliceBuilder} for builder methods
|
|
106
|
+
* @see {@link Slice} for the output type
|
|
107
|
+
*/
|
|
108
|
+
export declare function slice<TSchemaReg extends SchemaRegister<TActions> = {}, TEvents extends Schemas = {}, TActions extends Schemas = {}, TStateMap extends Record<string, Schema> = {}, TActor extends Actor = Actor>(): SliceBuilder<TSchemaReg, TEvents, TActions, TStateMap, TActor>;
|
|
109
|
+
//# sourceMappingURL=slice-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slice-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/slice-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module state-builder
|
|
3
|
+
* @category Builders
|
|
4
|
+
*
|
|
5
|
+
* Fluent interface for defining a strongly-typed state machine using Zod schemas.
|
|
6
|
+
*/
|
|
7
|
+
import type { ZodType } from "zod";
|
|
8
|
+
import type { ActionHandler, Invariant, PatchHandlers, Schema, Schemas, Snapshot, State, ZodTypes } from "../types/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Builder interface for defining a state with event sourcing.
|
|
11
|
+
*
|
|
12
|
+
* Provides a fluent API to configure the initial state, event types,
|
|
13
|
+
* and event handlers (reducers) before moving to action configuration.
|
|
14
|
+
*
|
|
15
|
+
* @template TState - State schema type
|
|
16
|
+
* @template TName - State name literal type
|
|
17
|
+
*
|
|
18
|
+
* @see {@link state} for usage examples
|
|
19
|
+
* @see {@link ActionBuilder} for action configuration
|
|
20
|
+
*/
|
|
21
|
+
export type StateBuilder<TState extends Schema, TName extends string = string> = {
|
|
22
|
+
/**
|
|
23
|
+
* Defines the initial state for new state instances.
|
|
24
|
+
*
|
|
25
|
+
* The init function is called when a new stream is created (first event).
|
|
26
|
+
* It can accept initial data or return a default state.
|
|
27
|
+
*
|
|
28
|
+
* @param init - Function returning the initial state
|
|
29
|
+
* @returns A builder with `.emits()` to declare event types
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* .init(() => ({ count: 0, created: new Date() }))
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* @example With initial data
|
|
37
|
+
* ```typescript
|
|
38
|
+
* .init((data) => ({ ...data, createdAt: new Date() }))
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
init: (init: () => Readonly<TState>) => {
|
|
42
|
+
/**
|
|
43
|
+
* Declares the event types that this state can emit.
|
|
44
|
+
*
|
|
45
|
+
* Events represent facts that have happened - they should be named in past tense.
|
|
46
|
+
* Each event is defined with a Zod schema for type safety and runtime validation.
|
|
47
|
+
*
|
|
48
|
+
* @template TEvents - Event schemas type
|
|
49
|
+
* @param events - Object mapping event names to Zod schemas
|
|
50
|
+
* @returns An ActionBuilder (with optional `.patch()` to override specific reducers)
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* .emits({
|
|
55
|
+
* Incremented: z.object({ amount: z.number() }),
|
|
56
|
+
* Decremented: z.object({ amount: z.number() }),
|
|
57
|
+
* Reset: z.object({})
|
|
58
|
+
* })
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
emits: <TEvents extends Schemas>(events: ZodTypes<TEvents>) => ActionBuilder<TState, TEvents, {}, TName> & {
|
|
62
|
+
/**
|
|
63
|
+
* Overrides specific event reducers. Events without a custom patch
|
|
64
|
+
* default to passthrough: `({ data }) => data` (event data merges
|
|
65
|
+
* into state).
|
|
66
|
+
*
|
|
67
|
+
* @param patch - Partial map of event names to patch handler functions
|
|
68
|
+
* @returns An ActionBuilder for defining actions
|
|
69
|
+
*
|
|
70
|
+
* @example Only override the events that need custom logic
|
|
71
|
+
* ```typescript
|
|
72
|
+
* .emits({ TicketOpened, TicketClosed, TicketResolved })
|
|
73
|
+
* .patch({
|
|
74
|
+
* TicketOpened: ({ data }) => {
|
|
75
|
+
* const { message, messageId, userId, ...other } = data;
|
|
76
|
+
* return { ...other, userId, messages: { [messageId]: { ... } } };
|
|
77
|
+
* },
|
|
78
|
+
* })
|
|
79
|
+
* // TicketClosed and TicketResolved use passthrough
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
patch: (patch: Partial<PatchHandlers<TState, TEvents>>) => ActionBuilder<TState, TEvents, {}, TName>;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
/** Helper: a single-key record mapping a state name to its Zod schema. */
|
|
87
|
+
type StateEntry<TKey extends string = string, TState extends Schema = Schema> = {
|
|
88
|
+
[P in TKey]: ZodType<TState>;
|
|
89
|
+
};
|
|
90
|
+
/** Helper: a single-key record mapping an action name to its Zod schema. */
|
|
91
|
+
type ActionEntry<TKey extends string = string, TNewActions extends Schema = Schema> = {
|
|
92
|
+
[P in TKey]: ZodType<TNewActions>;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Builder interface for defining actions (commands) on a state.
|
|
96
|
+
*
|
|
97
|
+
* Actions represent user/system intents to modify state. Each action is validated
|
|
98
|
+
* against a schema, can have business rule invariants, and must emit one or more events.
|
|
99
|
+
*
|
|
100
|
+
* @template TState - State schema type
|
|
101
|
+
* @template TEvents - Event schemas type
|
|
102
|
+
* @template TActions - Action schemas type
|
|
103
|
+
* @template TName - State name literal type
|
|
104
|
+
*
|
|
105
|
+
* @see {@link state} for complete usage examples
|
|
106
|
+
*/
|
|
107
|
+
export type ActionBuilder<TState extends Schema, TEvents extends Schemas, TActions extends Schemas, TName extends string = string> = {
|
|
108
|
+
/**
|
|
109
|
+
* Defines an action (command) that can be executed on this state.
|
|
110
|
+
*
|
|
111
|
+
* Actions represent intents to change state - they should be named in imperative form
|
|
112
|
+
* (e.g., "CreateUser", "IncrementCounter", "PlaceOrder"). Actions are validated against
|
|
113
|
+
* their schema and must emit at least one event.
|
|
114
|
+
*
|
|
115
|
+
* Pass a `{ ActionName: schema }` record — use shorthand `{ ActionName }`
|
|
116
|
+
* when the variable name matches the action name. The key becomes the
|
|
117
|
+
* action name, the value the Zod schema.
|
|
118
|
+
*
|
|
119
|
+
* @template TKey - Action name (string literal type)
|
|
120
|
+
* @template TNewActions - Action payload schema type
|
|
121
|
+
* @param entry - Single-key record `{ ActionName: schema }`
|
|
122
|
+
* @returns An object with `.given()` and `.emit()` for further configuration
|
|
123
|
+
*
|
|
124
|
+
* @example Simple action without invariants
|
|
125
|
+
* ```typescript
|
|
126
|
+
* .on({ increment: z.object({ by: z.number() }) })
|
|
127
|
+
* .emit((action) => ["Incremented", { amount: action.by }])
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @example Action with business rules
|
|
131
|
+
* ```typescript
|
|
132
|
+
* .on({ withdraw: z.object({ amount: z.number() }) })
|
|
133
|
+
* .given([
|
|
134
|
+
* (_, snap) => snap.state.balance >= 0 || "Account closed",
|
|
135
|
+
* (_, snap, action) => snap.state.balance >= action.amount || "Insufficient funds"
|
|
136
|
+
* ])
|
|
137
|
+
* .emit((action) => ["Withdrawn", { amount: action.amount }])
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* @example Action with shorthand (variable name matches action name)
|
|
141
|
+
* ```typescript
|
|
142
|
+
* const OpenTicket = z.object({ title: z.string() });
|
|
143
|
+
* .on({ OpenTicket })
|
|
144
|
+
* .emit((action) => ["TicketOpened", { title: action.title }])
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
on: <TKey extends string, TNewActions extends Schema>(entry: ActionEntry<TKey, TNewActions>) => {
|
|
148
|
+
/**
|
|
149
|
+
* Adds business rule invariants that must hold before the action can execute.
|
|
150
|
+
*
|
|
151
|
+
* Invariants are checked after loading the current state but before emitting events.
|
|
152
|
+
* Each invariant should return `true` or an error message string. All invariants
|
|
153
|
+
* must pass for the action to succeed.
|
|
154
|
+
*
|
|
155
|
+
* @param rules - Array of invariant functions
|
|
156
|
+
* @returns An object with `.emit()` to finalize the action
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* .given([
|
|
161
|
+
* (_, snap) => snap.state.status === "active" || "Must be active",
|
|
162
|
+
* (target, snap) => snap.state.ownerId === target.actor.id || "Not authorized"
|
|
163
|
+
* ])
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
given: (rules: Invariant<TState>[]) => {
|
|
167
|
+
/**
|
|
168
|
+
* Defines the action handler that emits events.
|
|
169
|
+
*
|
|
170
|
+
* The handler receives the action payload and current state snapshot,
|
|
171
|
+
* and must return one or more events to emit. Events are applied to state
|
|
172
|
+
* via the patch handlers defined earlier.
|
|
173
|
+
*
|
|
174
|
+
* Pass a string event name for passthrough: the action payload becomes
|
|
175
|
+
* the event data directly.
|
|
176
|
+
*
|
|
177
|
+
* @param handler - Function that returns events to emit, or event name string for passthrough
|
|
178
|
+
* @returns The ActionBuilder for chaining more actions
|
|
179
|
+
*
|
|
180
|
+
* @example Custom handler
|
|
181
|
+
* ```typescript
|
|
182
|
+
* .emit((action, snapshot) => {
|
|
183
|
+
* const newBalance = snapshot.state.balance + action.amount;
|
|
184
|
+
* return ["Deposited", { amount: action.amount, newBalance }];
|
|
185
|
+
* })
|
|
186
|
+
* ```
|
|
187
|
+
*
|
|
188
|
+
* @example Passthrough (action payload = event data)
|
|
189
|
+
* ```typescript
|
|
190
|
+
* .emit("TicketAssigned")
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
emit: {
|
|
194
|
+
/** Custom handler — receives `(action, snapshot)` and returns one
|
|
195
|
+
* or more `[EventName, data]` tuples (or `undefined`). */
|
|
196
|
+
(handler: ActionHandler<TState, TEvents, {
|
|
197
|
+
[P in TKey]: TNewActions;
|
|
198
|
+
}, TKey>): ActionBuilder<TState, TEvents, TActions & {
|
|
199
|
+
[P in TKey]: TNewActions;
|
|
200
|
+
}, TName>;
|
|
201
|
+
/** Passthrough — the action payload becomes the event data
|
|
202
|
+
* directly. Must reference an event declared in `.emits()`. */
|
|
203
|
+
(eventName: keyof TEvents & string): ActionBuilder<TState, TEvents, TActions & {
|
|
204
|
+
[P in TKey]: TNewActions;
|
|
205
|
+
}, TName>;
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Defines the action handler that emits events. Same two overloads as
|
|
210
|
+
* the post-`.given()` form above:
|
|
211
|
+
*
|
|
212
|
+
* - **Function** — receives `(action, snapshot)` and returns one or
|
|
213
|
+
* more `[EventName, data]` tuples (or `undefined`).
|
|
214
|
+
* - **String** — passthrough: the action payload becomes the event
|
|
215
|
+
* data directly. Must reference an event declared in `.emits()`.
|
|
216
|
+
*
|
|
217
|
+
* The two overloads are kept separate (rather than merged into a
|
|
218
|
+
* `handler | string` union) so that TS contextual typing of the
|
|
219
|
+
* function alternative isn't degraded by considering the string
|
|
220
|
+
* branch — under the union form `TState` could collapse to its
|
|
221
|
+
* `Schema` constraint inside the callback.
|
|
222
|
+
*
|
|
223
|
+
* @example Passthrough (action payload = event data)
|
|
224
|
+
* ```typescript
|
|
225
|
+
* .emit("Incremented")
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* @example Single event
|
|
229
|
+
* ```typescript
|
|
230
|
+
* .emit((action) => ["Incremented", { amount: action.by }])
|
|
231
|
+
* ```
|
|
232
|
+
*
|
|
233
|
+
* @example Multiple events
|
|
234
|
+
* ```typescript
|
|
235
|
+
* .emit((action) => [
|
|
236
|
+
* ["Incremented", { amount: action.by }],
|
|
237
|
+
* ["LogUpdated", { message: `Incremented by ${action.by}` }]
|
|
238
|
+
* ])
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
emit: {
|
|
242
|
+
(handler: ActionHandler<TState, TEvents, {
|
|
243
|
+
[P in TKey]: TNewActions;
|
|
244
|
+
}, TKey>): ActionBuilder<TState, TEvents, TActions & {
|
|
245
|
+
[P in TKey]: TNewActions;
|
|
246
|
+
}, TName>;
|
|
247
|
+
(eventName: keyof TEvents & string): ActionBuilder<TState, TEvents, TActions & {
|
|
248
|
+
[P in TKey]: TNewActions;
|
|
249
|
+
}, TName>;
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Defines a snapshotting strategy to optimize state reconstruction.
|
|
254
|
+
*
|
|
255
|
+
* Snapshots store the current state at a point in time, allowing faster state loading
|
|
256
|
+
* by avoiding replaying all events from the beginning. The snap function is called
|
|
257
|
+
* after each event is applied and should return `true` when a snapshot should be taken.
|
|
258
|
+
*
|
|
259
|
+
* @param snap - Predicate function that returns true when a snapshot should be taken
|
|
260
|
+
* @returns The ActionBuilder for chaining
|
|
261
|
+
*
|
|
262
|
+
* @example Snapshot every 10 events
|
|
263
|
+
* ```typescript
|
|
264
|
+
* .snap((snapshot) => snapshot.patches >= 10)
|
|
265
|
+
* ```
|
|
266
|
+
*
|
|
267
|
+
* @example Snapshot based on state size
|
|
268
|
+
* ```typescript
|
|
269
|
+
* .snap((snapshot) => {
|
|
270
|
+
* const estimatedSize = JSON.stringify(snapshot.state).length;
|
|
271
|
+
* return estimatedSize > 10000 || snapshot.patches >= 50;
|
|
272
|
+
* })
|
|
273
|
+
* ```
|
|
274
|
+
*
|
|
275
|
+
* @example Time-based snapshotting
|
|
276
|
+
* ```typescript
|
|
277
|
+
* .snap((snapshot) => {
|
|
278
|
+
* const hoursSinceLastSnapshot = snapshot.patches * 0.1; // Estimate
|
|
279
|
+
* return hoursSinceLastSnapshot >= 24;
|
|
280
|
+
* })
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
snap: (snap: (snapshot: Snapshot<TState, TEvents>) => boolean) => ActionBuilder<TState, TEvents, TActions, TName>;
|
|
284
|
+
/**
|
|
285
|
+
* Finalizes and builds the state definition.
|
|
286
|
+
*
|
|
287
|
+
* Call this method after defining all actions, invariants, and patches to create
|
|
288
|
+
* the complete State object that can be registered with Act.
|
|
289
|
+
*
|
|
290
|
+
* @returns The complete strongly-typed State definition
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* const Counter = state({ Counter: schema })
|
|
295
|
+
* .init(() => ({ count: 0 }))
|
|
296
|
+
* .emits({ Incremented: z.object({ amount: z.number() }) })
|
|
297
|
+
* .patch({ Incremented: ({ data }, state) => ({ count: state.count + data.amount }) })
|
|
298
|
+
* .on({ increment: z.object({ by: z.number() }) })
|
|
299
|
+
* .emit((action) => ["Incremented", { amount: action.by }])
|
|
300
|
+
* .build(); // Returns State<TState, TEvents, TActions, TName>
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
build: () => State<TState, TEvents, TActions, TName>;
|
|
304
|
+
};
|
|
305
|
+
/**
|
|
306
|
+
* Creates a new state definition with event sourcing capabilities.
|
|
307
|
+
*
|
|
308
|
+
* States are the core building blocks of Act. Each state represents a consistency
|
|
309
|
+
* boundary (aggregate) that processes actions, emits events, and maintains its own
|
|
310
|
+
* state through event patches (reducers). States use event sourcing to maintain a
|
|
311
|
+
* complete audit trail and enable time-travel capabilities.
|
|
312
|
+
*
|
|
313
|
+
* The state builder provides a fluent API for defining:
|
|
314
|
+
* 1. Initial state via `.init()`
|
|
315
|
+
* 2. Event types via `.emits()` — all events default to passthrough (`({ data }) => data`)
|
|
316
|
+
* 3. Custom event reducers via `.patch()` (optional — only for events that need custom logic)
|
|
317
|
+
* 4. Actions (commands) via `.on()` → `.emit()` — pass an event name string for passthrough
|
|
318
|
+
* 5. Business rules (invariants) via `.given()`
|
|
319
|
+
* 6. Snapshotting strategy via `.snap()`
|
|
320
|
+
*
|
|
321
|
+
* @template TState - Zod schema type defining the shape of the state
|
|
322
|
+
* @param entry - Single-key record mapping state name to Zod schema (e.g., `{ Counter: z.object({ count: z.number() }) }`)
|
|
323
|
+
* @returns A StateBuilder instance for fluent API configuration
|
|
324
|
+
*
|
|
325
|
+
* @example Basic counter state (with custom patch)
|
|
326
|
+
* ```typescript
|
|
327
|
+
* import { state } from "@rotorsoft/act";
|
|
328
|
+
* import { z } from "zod";
|
|
329
|
+
*
|
|
330
|
+
* const Counter = state({ Counter: z.object({ count: z.number() }) })
|
|
331
|
+
* .init(() => ({ count: 0 }))
|
|
332
|
+
* .emits({
|
|
333
|
+
* Incremented: z.object({ amount: z.number() })
|
|
334
|
+
* })
|
|
335
|
+
* .patch({ // optional — only for events needing custom reducers
|
|
336
|
+
* Incremented: ({ data }, state) => ({ count: state.count + data.amount })
|
|
337
|
+
* })
|
|
338
|
+
* .on({ increment: z.object({ by: z.number() }) })
|
|
339
|
+
* .emit((action) => ["Incremented", { amount: action.by }])
|
|
340
|
+
* .build();
|
|
341
|
+
* ```
|
|
342
|
+
*
|
|
343
|
+
* @example Passthrough state (no custom patch or emit needed)
|
|
344
|
+
* ```typescript
|
|
345
|
+
* const DigitBoard = state({ DigitBoard: z.object({ digit: z.string() }) })
|
|
346
|
+
* .init(() => ({ digit: "" }))
|
|
347
|
+
* .emits({ DigitCounted: z.object({ digit: z.string() }) })
|
|
348
|
+
* // no .patch() — passthrough is the default (event data merges into state)
|
|
349
|
+
* .on({ CountDigit: z.object({ digit: z.string() }) })
|
|
350
|
+
* .emit("DigitCounted") // string passthrough — action payload becomes event data
|
|
351
|
+
* .build();
|
|
352
|
+
* ```
|
|
353
|
+
*
|
|
354
|
+
* @example State with multiple events and invariants
|
|
355
|
+
* ```typescript
|
|
356
|
+
* const BankAccount = state({ BankAccount: z.object({
|
|
357
|
+
* balance: z.number(),
|
|
358
|
+
* currency: z.string(),
|
|
359
|
+
* status: z.enum(["open", "closed"])
|
|
360
|
+
* }) })
|
|
361
|
+
* .init(() => ({ balance: 0, currency: "USD", status: "open" }))
|
|
362
|
+
* .emits({
|
|
363
|
+
* Deposited: z.object({ amount: z.number() }),
|
|
364
|
+
* Withdrawn: z.object({ amount: z.number() }),
|
|
365
|
+
* Closed: z.object({})
|
|
366
|
+
* })
|
|
367
|
+
* .patch({ // only override events needing custom logic
|
|
368
|
+
* Deposited: ({ data }, state) => ({ balance: state.balance + data.amount }),
|
|
369
|
+
* Withdrawn: ({ data }, state) => ({ balance: state.balance - data.amount }),
|
|
370
|
+
* Closed: () => ({ status: "closed", balance: 0 })
|
|
371
|
+
* })
|
|
372
|
+
* .on({ deposit: z.object({ amount: z.number() }) })
|
|
373
|
+
* .given([
|
|
374
|
+
* (_, snap) => snap.state.status === "open" || "Account must be open"
|
|
375
|
+
* ])
|
|
376
|
+
* .emit("Deposited") // passthrough — action payload { amount } becomes event data
|
|
377
|
+
* .on({ withdraw: z.object({ amount: z.number() }) })
|
|
378
|
+
* .given([
|
|
379
|
+
* (_, snap) => snap.state.status === "open" || "Account must be open",
|
|
380
|
+
* (_, snap, action) =>
|
|
381
|
+
* snap.state.balance >= action.amount || "Insufficient funds"
|
|
382
|
+
* ])
|
|
383
|
+
* .emit("Withdrawn")
|
|
384
|
+
* .on({ close: z.object({}) })
|
|
385
|
+
* .given([
|
|
386
|
+
* (_, snap) => snap.state.status === "open" || "Already closed",
|
|
387
|
+
* (_, snap) => snap.state.balance === 0 || "Balance must be zero"
|
|
388
|
+
* ])
|
|
389
|
+
* .emit("Closed")
|
|
390
|
+
* .build();
|
|
391
|
+
* ```
|
|
392
|
+
*
|
|
393
|
+
* @example State with snapshotting
|
|
394
|
+
* ```typescript
|
|
395
|
+
* const User = state({ User: z.object({
|
|
396
|
+
* name: z.string(),
|
|
397
|
+
* email: z.string(),
|
|
398
|
+
* loginCount: z.number()
|
|
399
|
+
* }) })
|
|
400
|
+
* .init((data) => ({ ...data, loginCount: 0 }))
|
|
401
|
+
* .emits({
|
|
402
|
+
* UserCreated: z.object({ name: z.string(), email: z.string() }),
|
|
403
|
+
* UserLoggedIn: z.object({})
|
|
404
|
+
* })
|
|
405
|
+
* .patch({ // only override events needing custom logic
|
|
406
|
+
* UserLoggedIn: (_, state) => ({ loginCount: state.loginCount + 1 })
|
|
407
|
+
* })
|
|
408
|
+
* // UserCreated uses passthrough — event data merges into state
|
|
409
|
+
* .on({ createUser: z.object({ name: z.string(), email: z.string() }) })
|
|
410
|
+
* .emit("UserCreated") // passthrough
|
|
411
|
+
* .on({ login: z.object({}) })
|
|
412
|
+
* .emit("UserLoggedIn")
|
|
413
|
+
* .snap((snap) => snap.patches >= 10) // Snapshot every 10 events
|
|
414
|
+
* .build();
|
|
415
|
+
* ```
|
|
416
|
+
*
|
|
417
|
+
* @see {@link StateBuilder} for available builder methods
|
|
418
|
+
* @see {@link ActionBuilder} for action configuration methods
|
|
419
|
+
* @see {@link https://rotorsoft.github.io/act-root/docs/intro | Getting Started Guide}
|
|
420
|
+
* @see {@link https://rotorsoft.github.io/act-root/docs/examples/calculator | Calculator Example}
|
|
421
|
+
*/
|
|
422
|
+
export declare function state<TName extends string, TState extends Schema>(entry: StateEntry<TName, TState>): StateBuilder<TState, TName>;
|
|
423
|
+
export {};
|
|
424
|
+
//# sourceMappingURL=state-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-builder.d.ts","sourceRoot":"","sources":["../../../src/builders/state-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Zod schema for validating package.json metadata.
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare const PackageSchema: z.ZodObject<{
|
|
7
|
+
name: z.ZodString;
|
|
8
|
+
version: z.ZodString;
|
|
9
|
+
description: z.ZodOptional<z.ZodString>;
|
|
10
|
+
author: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodObject<{
|
|
11
|
+
name: z.ZodString;
|
|
12
|
+
email: z.ZodOptional<z.ZodString>;
|
|
13
|
+
}, z.core.$strip>>, z.ZodString]>>;
|
|
14
|
+
license: z.ZodOptional<z.ZodString>;
|
|
15
|
+
dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
/**
|
|
18
|
+
* Type representing the validated package.json metadata.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export type Package = z.infer<typeof PackageSchema>;
|
|
23
|
+
/**
|
|
24
|
+
* Zod schema for the full Act Framework configuration object.
|
|
25
|
+
* Includes package metadata, environment, logging, and timing options.
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
declare const BaseSchema: z.ZodObject<{
|
|
29
|
+
name: z.ZodString;
|
|
30
|
+
version: z.ZodString;
|
|
31
|
+
description: z.ZodOptional<z.ZodString>;
|
|
32
|
+
author: z.ZodOptional<z.ZodUnion<[z.ZodOptional<z.ZodObject<{
|
|
33
|
+
name: z.ZodString;
|
|
34
|
+
email: z.ZodOptional<z.ZodString>;
|
|
35
|
+
}, z.core.$strip>>, z.ZodString]>>;
|
|
36
|
+
license: z.ZodOptional<z.ZodString>;
|
|
37
|
+
dependencies: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
38
|
+
env: z.ZodEnum<{
|
|
39
|
+
development: "development";
|
|
40
|
+
test: "test";
|
|
41
|
+
staging: "staging";
|
|
42
|
+
production: "production";
|
|
43
|
+
}>;
|
|
44
|
+
logLevel: z.ZodEnum<{
|
|
45
|
+
fatal: "fatal";
|
|
46
|
+
error: "error";
|
|
47
|
+
warn: "warn";
|
|
48
|
+
info: "info";
|
|
49
|
+
debug: "debug";
|
|
50
|
+
trace: "trace";
|
|
51
|
+
}>;
|
|
52
|
+
logSingleLine: z.ZodBoolean;
|
|
53
|
+
sleepMs: z.ZodNumber;
|
|
54
|
+
}, z.core.$strip>;
|
|
55
|
+
/**
|
|
56
|
+
* Type representing the validated Act Framework configuration object.
|
|
57
|
+
*/
|
|
58
|
+
export type Config = z.infer<typeof BaseSchema>;
|
|
59
|
+
/**
|
|
60
|
+
* Gets the current Act Framework configuration.
|
|
61
|
+
*
|
|
62
|
+
* Configuration is loaded from package.json and environment variables, providing
|
|
63
|
+
* type-safe access to application metadata and runtime settings.
|
|
64
|
+
*
|
|
65
|
+
* **Environment Variables:**
|
|
66
|
+
* - `NODE_ENV`: "development" | "test" | "staging" | "production" (default: "development")
|
|
67
|
+
* - `LOG_LEVEL`: "fatal" | "error" | "warn" | "info" | "debug" | "trace"
|
|
68
|
+
* - `LOG_SINGLE_LINE`: "true" | "false" (default: "true")
|
|
69
|
+
* - `SLEEP_MS`: Milliseconds for sleep utility (default: 100, 0 for tests)
|
|
70
|
+
*
|
|
71
|
+
* **Defaults by environment:**
|
|
72
|
+
* - test: logLevel="error", sleepMs=0
|
|
73
|
+
* - production: logLevel="info"
|
|
74
|
+
* - development: logLevel="trace"
|
|
75
|
+
*
|
|
76
|
+
* @returns The validated configuration object
|
|
77
|
+
*
|
|
78
|
+
* @example Basic usage
|
|
79
|
+
* ```typescript
|
|
80
|
+
* import { config } from "@rotorsoft/act";
|
|
81
|
+
*
|
|
82
|
+
* const cfg = config();
|
|
83
|
+
* console.log(`App: ${cfg.name} v${cfg.version}`);
|
|
84
|
+
* console.log(`Environment: ${cfg.env}`);
|
|
85
|
+
* console.log(`Log level: ${cfg.logLevel}`);
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example Environment-specific behavior
|
|
89
|
+
* ```typescript
|
|
90
|
+
* import { config } from "@rotorsoft/act";
|
|
91
|
+
*
|
|
92
|
+
* const cfg = config();
|
|
93
|
+
*
|
|
94
|
+
* if (cfg.env === "production") {
|
|
95
|
+
* // Use PostgreSQL in production
|
|
96
|
+
* store(new PostgresStore(prodConfig));
|
|
97
|
+
* } else {
|
|
98
|
+
* // Use in-memory store for dev/test
|
|
99
|
+
* store(new InMemoryStore());
|
|
100
|
+
* }
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @example Adjusting log levels
|
|
104
|
+
* ```typescript
|
|
105
|
+
* // Set via environment variable:
|
|
106
|
+
* // LOG_LEVEL=debug npm start
|
|
107
|
+
*
|
|
108
|
+
* // Or check in code:
|
|
109
|
+
* const cfg = config();
|
|
110
|
+
* if (cfg.logLevel === "trace") {
|
|
111
|
+
* logger.trace("Detailed debugging enabled");
|
|
112
|
+
* }
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @see {@link Config} for configuration type
|
|
116
|
+
*/
|
|
117
|
+
export declare const config: () => Config;
|
|
118
|
+
export {};
|
|
119
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;iBAWxB,CAAC;AAEH;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AA0CpD;;;;GAIG;AACH,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKd,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAsBhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AACH,eAAO,MAAM,MAAM,QAAO,MAwBzB,CAAC"}
|