@rotorsoft/act 0.7.0 → 0.9.0
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 -1
- package/dist/@types/act-builder.d.ts +35 -223
- package/dist/@types/act-builder.d.ts.map +1 -1
- package/dist/@types/act.d.ts +13 -10
- package/dist/@types/act.d.ts.map +1 -1
- package/dist/@types/index.d.ts +1 -0
- package/dist/@types/index.d.ts.map +1 -1
- package/dist/@types/merge.d.ts +38 -0
- package/dist/@types/merge.d.ts.map +1 -0
- package/dist/@types/slice-builder.d.ts +107 -0
- package/dist/@types/slice-builder.d.ts.map +1 -0
- package/dist/@types/state-builder.d.ts +9 -9
- package/dist/@types/state-builder.d.ts.map +1 -1
- package/dist/@types/types/action.d.ts +47 -2
- package/dist/@types/types/action.d.ts.map +1 -1
- package/dist/@types/types/reaction.d.ts +1 -1
- package/dist/@types/types/reaction.d.ts.map +1 -1
- package/dist/index.cjs +165 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +163 -108
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
* Fluent builder for composing event-sourced applications.
|
|
6
6
|
*/
|
|
7
7
|
import { Act } from "./act.js";
|
|
8
|
-
import
|
|
8
|
+
import { type Slice } from "./slice-builder.js";
|
|
9
|
+
import type { Committed, Dispatcher, EventRegister, ReactionOptions, ReactionResolver, Registry, Schema, SchemaRegister, Schemas, Snapshot, State } from "./types/index.js";
|
|
9
10
|
/**
|
|
10
11
|
* Fluent builder interface for composing event-sourced applications.
|
|
11
12
|
*
|
|
12
13
|
* Provides a chainable API for:
|
|
13
|
-
* - Registering states via `.with()`
|
|
14
|
+
* - Registering states or slices via `.with()`
|
|
14
15
|
* - Defining event reactions via `.on()` → `.do()` → `.to()` or `.void()`
|
|
15
16
|
* - Building the orchestrator via `.build()`
|
|
16
17
|
*
|
|
@@ -21,41 +22,33 @@ import type { EventRegister, ReactionHandler, ReactionOptions, ReactionResolver,
|
|
|
21
22
|
* @see {@link act} for usage examples
|
|
22
23
|
* @see {@link Act} for the built orchestrator API
|
|
23
24
|
*/
|
|
24
|
-
export type ActBuilder<S extends SchemaRegister<A>, E extends Schemas, A extends Schemas> = {
|
|
25
|
+
export type ActBuilder<S extends SchemaRegister<A>, E extends Schemas, A extends Schemas, M extends Record<string, Schema> = {}> = {
|
|
25
26
|
/**
|
|
26
|
-
* Registers a state definition with the builder.
|
|
27
|
+
* Registers a state definition or a slice with the builder.
|
|
27
28
|
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* State names, action names, and event names must be unique across the application
|
|
29
|
+
* When receiving a State, it registers the state's actions and events.
|
|
30
|
+
* When receiving a Slice, it merges all the slice's states and reactions.
|
|
31
|
+
* State names, action names, and event names must be unique across the application
|
|
32
|
+
* (partial states with the same name are merged automatically).
|
|
31
33
|
*
|
|
32
|
-
* @
|
|
33
|
-
* @template EX - Event schemas type for this state
|
|
34
|
-
* @template AX - Action schemas type for this state
|
|
35
|
-
* @param state - The state definition to register
|
|
36
|
-
* @returns The builder with updated type information for chaining
|
|
34
|
+
* @throws {Error} If duplicate action or event names are detected
|
|
37
35
|
*
|
|
38
|
-
* @
|
|
39
|
-
*
|
|
40
|
-
* @example Register single state
|
|
36
|
+
* @example Register a state
|
|
41
37
|
* ```typescript
|
|
42
|
-
* const app = act()
|
|
43
|
-
* .with(Counter)
|
|
44
|
-
* .build();
|
|
38
|
+
* const app = act().with(Counter).build();
|
|
45
39
|
* ```
|
|
46
40
|
*
|
|
47
|
-
* @example Register
|
|
41
|
+
* @example Register a slice
|
|
48
42
|
* ```typescript
|
|
49
|
-
* const
|
|
50
|
-
*
|
|
51
|
-
* .with(Order)
|
|
52
|
-
* .with(Inventory)
|
|
53
|
-
* .build();
|
|
43
|
+
* const CounterSlice = slice().with(Counter).on("Incremented").do(log).void().build();
|
|
44
|
+
* const app = act().with(CounterSlice).build();
|
|
54
45
|
* ```
|
|
55
46
|
*/
|
|
56
|
-
with: <SX extends Schema, EX extends Schemas, AX extends Schemas>(state: State<SX, EX, AX>) => ActBuilder<S & {
|
|
47
|
+
with: (<SX extends Schema, EX extends Schemas, AX extends Schemas, NX extends string = string>(state: State<SX, EX, AX, NX>) => ActBuilder<S & {
|
|
57
48
|
[K in keyof AX]: SX;
|
|
58
|
-
}, E & EX, A & AX
|
|
49
|
+
}, E & EX, A & AX, M & {
|
|
50
|
+
[K in NX]: SX;
|
|
51
|
+
}>) & (<SX extends SchemaRegister<AX>, EX extends Schemas, AX extends Schemas, MX extends Record<string, Schema>>(slice: Slice<SX, EX, AX, MX>) => ActBuilder<S & SX, E & EX, A & AX, M & MX>);
|
|
59
52
|
/**
|
|
60
53
|
* Begins defining a reaction to a specific event.
|
|
61
54
|
*
|
|
@@ -93,128 +86,34 @@ export type ActBuilder<S extends SchemaRegister<A>, E extends Schemas, A extends
|
|
|
93
86
|
* @param options.blockOnError - Block this stream if handler fails (default: true)
|
|
94
87
|
* @param options.maxRetries - Maximum retry attempts on failure (default: 3)
|
|
95
88
|
* @returns The builder with `.to()` and `.void()` methods for routing configuration
|
|
96
|
-
*
|
|
97
|
-
* @example Side effect only (void)
|
|
98
|
-
* ```typescript
|
|
99
|
-
* .on("UserCreated")
|
|
100
|
-
* .do(async (event) => {
|
|
101
|
-
* await analytics.track("user_created", event.data);
|
|
102
|
-
* })
|
|
103
|
-
* .void()
|
|
104
|
-
* ```
|
|
105
|
-
*
|
|
106
|
-
* @example Trigger another action
|
|
107
|
-
* ```typescript
|
|
108
|
-
* .on("OrderPlaced")
|
|
109
|
-
* .do(async (event) => {
|
|
110
|
-
* return ["reduceStock", { amount: event.data.items.length }];
|
|
111
|
-
* })
|
|
112
|
-
* .to("inventory-1")
|
|
113
|
-
* ```
|
|
114
|
-
*
|
|
115
|
-
* @example With retry configuration
|
|
116
|
-
* ```typescript
|
|
117
|
-
* .on("PaymentProcessed")
|
|
118
|
-
* .do(async (event) => {
|
|
119
|
-
* await externalAPI.notify(event.data);
|
|
120
|
-
* }, {
|
|
121
|
-
* blockOnError: false, // Don't block on failure
|
|
122
|
-
* maxRetries: 5 // Retry up to 5 times
|
|
123
|
-
* })
|
|
124
|
-
* .void()
|
|
125
|
-
* ```
|
|
126
89
|
*/
|
|
127
|
-
do: (handler:
|
|
90
|
+
do: (handler: (event: Committed<E, K>, stream: string, app: Dispatcher<A>) => Promise<Snapshot<E, Schema> | void>, options?: Partial<ReactionOptions>) => ActBuilder<S, E, A, M> & {
|
|
128
91
|
/**
|
|
129
92
|
* Routes the reaction to a specific target stream.
|
|
130
93
|
*
|
|
131
|
-
* Use this when the reaction triggers an action on a specific state instance.
|
|
132
|
-
* You can provide either a static stream name (string) or a resolver function
|
|
133
|
-
* that dynamically determines the target based on the event.
|
|
134
|
-
*
|
|
135
94
|
* @param resolver - Target stream name (string) or resolver function
|
|
136
95
|
* @returns The builder for chaining
|
|
137
|
-
*
|
|
138
|
-
* @example Static target stream
|
|
139
|
-
* ```typescript
|
|
140
|
-
* .on("OrderPlaced")
|
|
141
|
-
* .do(async (event) => ["reduceStock", { amount: 10 }])
|
|
142
|
-
* .to("inventory-main")
|
|
143
|
-
* ```
|
|
144
|
-
*
|
|
145
|
-
* @example Dynamic target based on event data
|
|
146
|
-
* ```typescript
|
|
147
|
-
* .on("OrderPlaced")
|
|
148
|
-
* .do(async (event) => ["reduceStock", { amount: 10 }])
|
|
149
|
-
* .to((event) => ({
|
|
150
|
-
* target: `inventory-${event.data.warehouseId}`
|
|
151
|
-
* }))
|
|
152
|
-
* ```
|
|
153
|
-
*
|
|
154
|
-
* @example Source and target routing
|
|
155
|
-
* ```typescript
|
|
156
|
-
* .on("UserLoggedIn")
|
|
157
|
-
* .do(async (event) => ["incrementCount", {}])
|
|
158
|
-
* .to(({ stream }) => ({
|
|
159
|
-
* source: stream, // React to events from this user stream
|
|
160
|
-
* target: `stats-${stream}` // Update corresponding stats stream
|
|
161
|
-
* }))
|
|
162
|
-
* ```
|
|
163
96
|
*/
|
|
164
|
-
to: (resolver: ReactionResolver<E, K> | string) => ActBuilder<S, E, A>;
|
|
97
|
+
to: (resolver: ReactionResolver<E, K> | string) => ActBuilder<S, E, A, M>;
|
|
165
98
|
/**
|
|
166
99
|
* Marks the reaction as void (side-effect only, no target stream).
|
|
167
100
|
*
|
|
168
|
-
* Use this when the reaction doesn't trigger any actions - it only performs
|
|
169
|
-
* side effects like logging, sending notifications, or updating external systems.
|
|
170
|
-
*
|
|
171
101
|
* @returns The builder for chaining
|
|
172
|
-
*
|
|
173
|
-
* @example
|
|
174
|
-
* ```typescript
|
|
175
|
-
* .on("UserCreated")
|
|
176
|
-
* .do(async (event) => {
|
|
177
|
-
* await sendEmail(event.data.email, "Welcome!");
|
|
178
|
-
* await logger.info("User created", event.data);
|
|
179
|
-
* })
|
|
180
|
-
* .void() // No target stream
|
|
181
|
-
* ```
|
|
182
102
|
*/
|
|
183
|
-
void: () => ActBuilder<S, E, A>;
|
|
103
|
+
void: () => ActBuilder<S, E, A, M>;
|
|
184
104
|
};
|
|
185
105
|
};
|
|
186
106
|
/**
|
|
187
107
|
* Builds and returns the Act orchestrator instance.
|
|
188
108
|
*
|
|
189
|
-
* This finalizes the builder configuration and creates the orchestrator that
|
|
190
|
-
* can execute actions, load state, and process reactions.
|
|
191
|
-
*
|
|
192
109
|
* @param drainLimit - Deprecated parameter, no longer used
|
|
193
110
|
* @returns The Act orchestrator instance
|
|
194
111
|
*
|
|
195
|
-
* @example
|
|
196
|
-
* ```typescript
|
|
197
|
-
* const app = act()
|
|
198
|
-
* .with(Counter)
|
|
199
|
-
* .with(User)
|
|
200
|
-
* .on("UserCreated")
|
|
201
|
-
* .do(sendWelcomeEmail)
|
|
202
|
-
* .void()
|
|
203
|
-
* .build();
|
|
204
|
-
*
|
|
205
|
-
* // Now use the app
|
|
206
|
-
* await app.do("createUser", target, payload);
|
|
207
|
-
* await app.drain();
|
|
208
|
-
* ```
|
|
209
|
-
*
|
|
210
112
|
* @see {@link Act} for available orchestrator methods
|
|
211
113
|
*/
|
|
212
|
-
build: (drainLimit?: number) => Act<S, E, A>;
|
|
114
|
+
build: (drainLimit?: number) => Act<S, E, A, M>;
|
|
213
115
|
/**
|
|
214
116
|
* The registered event schemas and their reaction maps.
|
|
215
|
-
*
|
|
216
|
-
* This is an internal registry maintained by the builder. Generally, you don't
|
|
217
|
-
* need to access this directly.
|
|
218
117
|
*/
|
|
219
118
|
readonly events: EventRegister<E>;
|
|
220
119
|
};
|
|
@@ -227,8 +126,8 @@ export type ActBuilder<S extends SchemaRegister<A>, E extends Schemas, A extends
|
|
|
227
126
|
* - Processing reactions (event handlers)
|
|
228
127
|
* - Coordinating event-driven workflows
|
|
229
128
|
*
|
|
230
|
-
* Use the fluent API to register states with `.with()`, define event
|
|
231
|
-
* and build the orchestrator with `.build()`.
|
|
129
|
+
* Use the fluent API to register states or slices with `.with()`, define event
|
|
130
|
+
* reactions with `.on()`, and build the orchestrator with `.build()`.
|
|
232
131
|
*
|
|
233
132
|
* @template S - State schema register type
|
|
234
133
|
* @template E - Event schemas type
|
|
@@ -251,115 +150,28 @@ export type ActBuilder<S extends SchemaRegister<A>, E extends Schemas, A extends
|
|
|
251
150
|
* const app = act()
|
|
252
151
|
* .with(Counter)
|
|
253
152
|
* .build();
|
|
254
|
-
*
|
|
255
|
-
* // Execute action
|
|
256
|
-
* await app.do("increment",
|
|
257
|
-
* { stream: "counter1", actor: { id: "user1", name: "Alice" } },
|
|
258
|
-
* { by: 5 }
|
|
259
|
-
* );
|
|
260
|
-
*
|
|
261
|
-
* // Load current state
|
|
262
|
-
* const snapshot = await app.load(Counter, "counter1");
|
|
263
|
-
* console.log(snapshot.state.count); // 5
|
|
264
153
|
* ```
|
|
265
154
|
*
|
|
266
|
-
* @example Application with
|
|
155
|
+
* @example Application with slices (vertical slice architecture)
|
|
267
156
|
* ```typescript
|
|
268
|
-
*
|
|
269
|
-
* .init((data) => data)
|
|
270
|
-
* .emits({ UserCreated: z.object({ name: z.string(), email: z.string() }) })
|
|
271
|
-
* .patch({ UserCreated: (event) => event.data })
|
|
272
|
-
* .on("createUser", z.object({ name: z.string(), email: z.string() }))
|
|
273
|
-
* .emit((action) => ["UserCreated", action])
|
|
274
|
-
* .build();
|
|
275
|
-
*
|
|
276
|
-
* const app = act()
|
|
277
|
-
* .with(User)
|
|
278
|
-
* .on("UserCreated")
|
|
279
|
-
* .do(async (event) => {
|
|
280
|
-
* // Send welcome email
|
|
281
|
-
* await sendEmail(event.data.email, "Welcome!");
|
|
282
|
-
* logger.info(`Sent welcome email to ${event.data.email}`);
|
|
283
|
-
* })
|
|
284
|
-
* .void() // No target stream, just side effects
|
|
285
|
-
* .build();
|
|
286
|
-
*
|
|
287
|
-
* // Create user (triggers email sending via reaction)
|
|
288
|
-
* await app.do("createUser",
|
|
289
|
-
* { stream: "user-123", actor: { id: "admin", name: "Admin" } },
|
|
290
|
-
* { name: "Alice", email: "alice@example.com" }
|
|
291
|
-
* );
|
|
292
|
-
*
|
|
293
|
-
* // Process reactions
|
|
294
|
-
* await app.drain();
|
|
295
|
-
* ```
|
|
296
|
-
*
|
|
297
|
-
* @example Multi-state application with event correlation
|
|
298
|
-
* ```typescript
|
|
299
|
-
* const Order = state("Order", z.object({ items: z.array(z.string()), total: z.number() }))
|
|
300
|
-
* .init((data) => data)
|
|
301
|
-
* .emits({ OrderPlaced: z.object({ items: z.array(z.string()), total: z.number() }) })
|
|
302
|
-
* .patch({ OrderPlaced: (event) => event.data })
|
|
303
|
-
* .on("placeOrder", z.object({ items: z.array(z.string()), total: z.number() }))
|
|
304
|
-
* .emit((action) => ["OrderPlaced", action])
|
|
305
|
-
* .build();
|
|
157
|
+
* import { act, slice, state } from "@rotorsoft/act";
|
|
306
158
|
*
|
|
307
|
-
* const
|
|
308
|
-
* .
|
|
309
|
-
* .
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
* .emit((action) => ["StockReduced", { amount: action.amount }])
|
|
313
|
-
* .build();
|
|
314
|
-
*
|
|
315
|
-
* const app = act()
|
|
316
|
-
* .with(Order)
|
|
317
|
-
* .with(Inventory)
|
|
318
|
-
* .on("OrderPlaced")
|
|
319
|
-
* .do(async (event) => {
|
|
320
|
-
* // Reduce inventory for each item
|
|
321
|
-
* return ["reduceStock", { amount: event.data.items.length }];
|
|
322
|
-
* })
|
|
323
|
-
* .to("inventory-1") // Target specific inventory stream
|
|
324
|
-
* .build();
|
|
325
|
-
*
|
|
326
|
-
* await app.do("placeOrder",
|
|
327
|
-
* { stream: "order-1", actor: { id: "user1", name: "Alice" } },
|
|
328
|
-
* { items: ["item1", "item2"], total: 100 }
|
|
329
|
-
* );
|
|
330
|
-
*
|
|
331
|
-
* // Process reaction (reduces inventory)
|
|
332
|
-
* await app.drain();
|
|
333
|
-
* ```
|
|
334
|
-
*
|
|
335
|
-
* @example Partial state definitions (same name, merged via .with())
|
|
336
|
-
* ```typescript
|
|
337
|
-
* const TicketCreation = state("Ticket", TicketSchema)
|
|
338
|
-
* .init(() => initialTicket)
|
|
339
|
-
* .emits({ TicketOpened: ..., TicketClosed: ... })
|
|
340
|
-
* .patch({ TicketOpened: ..., TicketClosed: ... })
|
|
341
|
-
* .on("OpenTicket", ...).emit(...)
|
|
342
|
-
* .on("CloseTicket", ...).emit(...)
|
|
343
|
-
* .build();
|
|
344
|
-
*
|
|
345
|
-
* const TicketMessaging = state("Ticket", TicketSchema)
|
|
346
|
-
* .init(() => initialTicket)
|
|
347
|
-
* .emits({ MessageAdded: ... })
|
|
348
|
-
* .patch({ MessageAdded: ... })
|
|
349
|
-
* .on("AddMessage", ...).emit(...)
|
|
159
|
+
* const CounterSlice = slice()
|
|
160
|
+
* .with(Counter)
|
|
161
|
+
* .on("Incremented")
|
|
162
|
+
* .do(async (event) => { console.log("incremented!"); })
|
|
163
|
+
* .void()
|
|
350
164
|
* .build();
|
|
351
165
|
*
|
|
352
|
-
* // Partials with same name are merged automatically
|
|
353
166
|
* const app = act()
|
|
354
|
-
* .with(
|
|
355
|
-
* .with(TicketMessaging)
|
|
167
|
+
* .with(CounterSlice)
|
|
356
168
|
* .build();
|
|
357
169
|
* ```
|
|
358
170
|
*
|
|
359
171
|
* @see {@link ActBuilder} for available builder methods
|
|
360
172
|
* @see {@link Act} for orchestrator API methods
|
|
361
173
|
* @see {@link state} for defining states
|
|
362
|
-
* @see {@link
|
|
174
|
+
* @see {@link slice} for defining slices
|
|
363
175
|
*/
|
|
364
|
-
export declare function act<S extends SchemaRegister<A> = {}, E extends Schemas = {}, A extends Schemas = {}>(states?: Map<string, State<any, any, any>>, registry?: Registry<S, E, A>): ActBuilder<S, E, A>;
|
|
176
|
+
export declare function act<S extends SchemaRegister<A> = {}, E extends Schemas = {}, A extends Schemas = {}, M extends Record<string, Schema> = {}>(states?: Map<string, State<any, any, any>>, registry?: Registry<S, E, A>): ActBuilder<S, E, A, M>;
|
|
365
177
|
//# sourceMappingURL=act-builder.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"act-builder.d.ts","sourceRoot":"","sources":["../../src/act-builder.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"act-builder.d.ts","sourceRoot":"","sources":["../../src/act-builder.ts"],"names":[],"mappings":"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"}
|
package/dist/@types/act.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ import type { Committed, Drain, DrainOptions, Lease, Query, Registry, Schema, Sc
|
|
|
23
23
|
* @template E Schemas for events
|
|
24
24
|
* @template A Schemas for actions
|
|
25
25
|
*/
|
|
26
|
-
export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A extends Schemas> {
|
|
26
|
+
export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A extends Schemas, M extends Record<string, Schema> = Record<string, never>> {
|
|
27
27
|
readonly registry: Registry<S, E, A>;
|
|
28
28
|
private readonly _states;
|
|
29
29
|
private _emitter;
|
|
@@ -156,34 +156,36 @@ export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A exten
|
|
|
156
156
|
* @see {@link Snapshot} for return value structure
|
|
157
157
|
* @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}
|
|
158
158
|
*/
|
|
159
|
-
do<K extends keyof A>(action: K, target: Target, payload: Readonly<A[K]>, reactingTo?: Committed<E, keyof E>, skipValidation?: boolean): Promise<Snapshot<S[K], E>[]>;
|
|
159
|
+
do<K extends keyof A>(action: K, target: Target, payload: Readonly<A[K]>, reactingTo?: Committed<E, string & keyof E>, skipValidation?: boolean): Promise<Snapshot<S[K], E>[]>;
|
|
160
160
|
/**
|
|
161
161
|
* Loads the current state snapshot for a specific stream.
|
|
162
162
|
*
|
|
163
163
|
* Reconstructs the current state by replaying events from the event store.
|
|
164
164
|
* Uses snapshots when available to optimize loading performance.
|
|
165
165
|
*
|
|
166
|
+
* Accepts either a State definition object or a state name string. When
|
|
167
|
+
* using a string, the merged state (from partial states registered via
|
|
168
|
+
* `.with()`) is resolved by name.
|
|
169
|
+
*
|
|
166
170
|
* @template SX - State schema type
|
|
167
171
|
* @template EX - Event schemas type
|
|
168
172
|
* @template AX - Action schemas type
|
|
169
|
-
* @param state - The state definition to load
|
|
173
|
+
* @param state - The state definition or state name to load
|
|
170
174
|
* @param stream - The stream ID (state instance identifier)
|
|
171
175
|
* @param callback - Optional callback invoked with the loaded snapshot
|
|
172
176
|
* @returns The current state snapshot for the stream
|
|
173
177
|
*
|
|
174
|
-
* @example Load
|
|
178
|
+
* @example Load by state definition
|
|
175
179
|
* ```typescript
|
|
176
180
|
* const snapshot = await app.load(Counter, "counter-1");
|
|
177
181
|
* console.log(snapshot.state.count); // Current count
|
|
178
|
-
* console.log(snapshot.version); // Number of events applied
|
|
179
182
|
* console.log(snapshot.patches); // Events since last snapshot
|
|
180
183
|
* ```
|
|
181
184
|
*
|
|
182
|
-
* @example
|
|
185
|
+
* @example Load by state name (useful with partial states)
|
|
183
186
|
* ```typescript
|
|
184
|
-
* const snapshot = await app.load(
|
|
185
|
-
*
|
|
186
|
-
* });
|
|
187
|
+
* const snapshot = await app.load("Ticket", "ticket-123");
|
|
188
|
+
* console.log(snapshot.state.title); // Merged state from all partials
|
|
187
189
|
* ```
|
|
188
190
|
*
|
|
189
191
|
* @example Load multiple states
|
|
@@ -197,6 +199,7 @@ export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A exten
|
|
|
197
199
|
* @see {@link Snapshot} for snapshot structure
|
|
198
200
|
*/
|
|
199
201
|
load<SX extends Schema, EX extends Schemas, AX extends Schemas>(state: State<SX, EX, AX>, stream: string, callback?: (snapshot: Snapshot<SX, EX>) => void): Promise<Snapshot<SX, EX>>;
|
|
202
|
+
load<K extends keyof M & string>(name: K, stream: string, callback?: (snapshot: Snapshot<M[K], E>) => void): Promise<Snapshot<M[K], E>>;
|
|
200
203
|
/**
|
|
201
204
|
* Queries the event store for events matching a filter.
|
|
202
205
|
*
|
|
@@ -356,7 +359,7 @@ export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A exten
|
|
|
356
359
|
* @see {@link correlate} for dynamic stream discovery
|
|
357
360
|
* @see {@link start_correlations} for automatic correlation
|
|
358
361
|
*/
|
|
359
|
-
drain
|
|
362
|
+
drain({ streamLimit, eventLimit, leaseMillis, }?: DrainOptions): Promise<Drain<E>>;
|
|
360
363
|
/**
|
|
361
364
|
* Discovers and registers new streams dynamically based on reaction resolvers.
|
|
362
365
|
*
|
package/dist/@types/act.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/act.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,SAAS,EACT,KAAK,EACL,YAAY,EACZ,KAAK,EACL,KAAK,EAEL,QAAQ,EACR,MAAM,EACN,cAAc,EACd,OAAO,EACP,QAAQ,EACR,KAAK,EACL,MAAM,EACP,MAAM,kBAAkB,CAAC;AAI1B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,GAAG,CACd,CAAC,SAAS,cAAc,CAAC,CAAC,CAAC,EAC3B,CAAC,SAAS,OAAO,EACjB,CAAC,SAAS,OAAO;
|
|
1
|
+
{"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/act.ts"],"names":[],"mappings":"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"}
|
package/dist/@types/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./act-builder.js";
|
|
|
8
8
|
export * from "./act.js";
|
|
9
9
|
export * from "./config.js";
|
|
10
10
|
export * from "./ports.js";
|
|
11
|
+
export * from "./slice-builder.js";
|
|
11
12
|
export * from "./state-builder.js";
|
|
12
13
|
export * from "./types/index.js";
|
|
13
14
|
export * from "./utils.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB;;;;GAIG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,CAAC;AAEtB;;;;GAIG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module merge
|
|
3
|
+
* @category Builders
|
|
4
|
+
*
|
|
5
|
+
* Shared utilities for merging partial states across builders.
|
|
6
|
+
*/
|
|
7
|
+
import { type ZodType } from "zod";
|
|
8
|
+
import type { Schema, State } from "./types/index.js";
|
|
9
|
+
/**
|
|
10
|
+
* Unwraps wrapper types (ZodOptional, ZodNullable, ZodDefault, ZodReadonly)
|
|
11
|
+
* to find the base type name, e.g. `z.string().optional()` -> `"ZodString"`.
|
|
12
|
+
*/
|
|
13
|
+
export declare function baseTypeName(zodType: ZodType): string;
|
|
14
|
+
/**
|
|
15
|
+
* Merges two Zod schemas. If both are ZodObject instances, checks for
|
|
16
|
+
* overlapping shape keys with incompatible base types (throws descriptive
|
|
17
|
+
* error), then merges via `.extend()`. Falls back to keeping existing
|
|
18
|
+
* schema if either is not a ZodObject.
|
|
19
|
+
*/
|
|
20
|
+
export declare function mergeSchemas(existing: ZodType, incoming: ZodType, stateName: string): ZodType;
|
|
21
|
+
/**
|
|
22
|
+
* Merges two init functions by spreading both results together.
|
|
23
|
+
* Each partial only provides its own defaults.
|
|
24
|
+
*/
|
|
25
|
+
export declare function mergeInits<S extends Schema>(existing: () => Readonly<S>, incoming: () => Readonly<S>): () => Readonly<S>;
|
|
26
|
+
/**
|
|
27
|
+
* Registers a state into a states map and action/event registries,
|
|
28
|
+
* merging with existing same-name states (partial state support).
|
|
29
|
+
*/
|
|
30
|
+
export declare function registerState(state: State<any, any, any>, states: Map<string, State<any, any, any>>, actions: Record<string, any>, events: Record<string, any>): void;
|
|
31
|
+
export declare const _this_: ({ stream }: {
|
|
32
|
+
stream: string;
|
|
33
|
+
}) => {
|
|
34
|
+
source: string;
|
|
35
|
+
target: string;
|
|
36
|
+
};
|
|
37
|
+
export declare const _void_: () => undefined;
|
|
38
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/merge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAMrD;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,OAAO,EACjB,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAkBT;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,QAAQ,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,EAC3B,QAAQ,EAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,GAC1B,MAAM,QAAQ,CAAC,CAAC,CAAC,CAEnB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC3B,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EACzC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC1B,IAAI,CAoDN;AAGD,eAAO,MAAM,MAAM,GAAI,YAAY;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;;;CAGnD,CAAC;AAGH,eAAO,MAAM,MAAM,iBAAkB,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Committed, Dispatcher, EventRegister, ReactionOptions, ReactionResolver, Schema, SchemaRegister, Schemas, Snapshot, State } from "./types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* A self-contained functional slice grouping partial states with their
|
|
4
|
+
* scoped reactions. Slices are composed into an Act orchestrator via
|
|
5
|
+
* `act().with(slice)`.
|
|
6
|
+
*
|
|
7
|
+
* @template S - Schema register for states
|
|
8
|
+
* @template E - Event schemas from this slice's states
|
|
9
|
+
* @template A - Action schemas from this slice's states
|
|
10
|
+
* @template M - Map of state names to state schemas
|
|
11
|
+
*/
|
|
12
|
+
export type Slice<S extends SchemaRegister<A>, E extends Schemas, A extends Schemas, M extends Record<string, Schema> = {}> = {
|
|
13
|
+
readonly _tag: "Slice";
|
|
14
|
+
readonly states: Map<string, State<any, any, any>>;
|
|
15
|
+
readonly events: EventRegister<E>;
|
|
16
|
+
/** @internal phantom field for type-level state schema tracking */
|
|
17
|
+
readonly _S?: S;
|
|
18
|
+
/** @internal phantom field for type-level state name tracking */
|
|
19
|
+
readonly _M?: M;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Type guard for distinguishing Slice from State objects.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isSlice(x: any): x is Slice<any, any, any, any>;
|
|
25
|
+
/**
|
|
26
|
+
* Fluent builder interface for composing functional slices.
|
|
27
|
+
*
|
|
28
|
+
* Provides a chainable API for registering states and defining reactions,
|
|
29
|
+
* scoped to the slice's own events. Include all states whose actions your
|
|
30
|
+
* handlers need via `.with()` — the `app` parameter in `.do()` handlers
|
|
31
|
+
* is typed with every action registered in the slice.
|
|
32
|
+
*
|
|
33
|
+
* @template S - Schema register for states
|
|
34
|
+
* @template E - Event schemas
|
|
35
|
+
* @template A - Action schemas
|
|
36
|
+
* @template M - Map of state names to state schemas
|
|
37
|
+
*/
|
|
38
|
+
export type SliceBuilder<S extends SchemaRegister<A>, E extends Schemas, A extends Schemas, M extends Record<string, Schema> = {}> = {
|
|
39
|
+
/**
|
|
40
|
+
* Registers a partial 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
|
+
with: <SX extends Schema, EX extends Schemas, AX extends Schemas, NX extends string = string>(state: State<SX, EX, AX, NX>) => SliceBuilder<S & {
|
|
47
|
+
[K in keyof AX]: SX;
|
|
48
|
+
}, E & EX, A & AX, M & {
|
|
49
|
+
[K in NX]: SX;
|
|
50
|
+
}>;
|
|
51
|
+
/**
|
|
52
|
+
* Begins defining a reaction scoped to this slice's events.
|
|
53
|
+
*/
|
|
54
|
+
on: <K extends keyof E>(event: K) => {
|
|
55
|
+
do: (handler: (event: Committed<E, K>, stream: string, app: Dispatcher<A>) => Promise<Snapshot<E, Schema> | void>, options?: Partial<ReactionOptions>) => SliceBuilder<S, E, A, M> & {
|
|
56
|
+
to: (resolver: ReactionResolver<E, K> | string) => SliceBuilder<S, E, A, M>;
|
|
57
|
+
void: () => SliceBuilder<S, E, A, M>;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Builds and returns the Slice data structure.
|
|
62
|
+
*/
|
|
63
|
+
build: () => Slice<S, E, A, M>;
|
|
64
|
+
/**
|
|
65
|
+
* The registered event schemas and their reaction maps.
|
|
66
|
+
*/
|
|
67
|
+
readonly events: EventRegister<E>;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Creates a new slice builder for composing partial states with scoped reactions.
|
|
71
|
+
*
|
|
72
|
+
* Slices enable vertical slice architecture by grouping related states and
|
|
73
|
+
* reactions into self-contained feature modules. Reactions defined in a slice
|
|
74
|
+
* are type-scoped to events from that slice's states only.
|
|
75
|
+
*
|
|
76
|
+
* Include all states whose actions your handlers dispatch via `.with()`.
|
|
77
|
+
* When multiple slices share the same state, duplicates are merged
|
|
78
|
+
* automatically at `act().with(slice)` composition time.
|
|
79
|
+
*
|
|
80
|
+
* @example Single-state slice with typed dispatch
|
|
81
|
+
* ```typescript
|
|
82
|
+
* const CounterSlice = slice()
|
|
83
|
+
* .with(Counter)
|
|
84
|
+
* .on("Incremented")
|
|
85
|
+
* .do(async (event, _stream, app) => {
|
|
86
|
+
* await app.do("reset", target, {});
|
|
87
|
+
* })
|
|
88
|
+
* .void()
|
|
89
|
+
* .build();
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @example Cross-state dispatch (include both states)
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const CreationSlice = slice()
|
|
95
|
+
* .with(TicketCreation)
|
|
96
|
+
* .with(TicketOperations) // handler can dispatch AssignTicket
|
|
97
|
+
* .on("TicketOpened").do(async (event, _stream, app) => {
|
|
98
|
+
* await app.do("AssignTicket", target, payload, event);
|
|
99
|
+
* })
|
|
100
|
+
* .build();
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @see {@link SliceBuilder} for builder methods
|
|
104
|
+
* @see {@link Slice} for the output type
|
|
105
|
+
*/
|
|
106
|
+
export declare function slice<S extends SchemaRegister<A> = {}, E extends Schemas = {}, A extends Schemas = {}, M extends Record<string, Schema> = {}>(states?: Map<string, State<any, any, any>>, actions?: Record<string, any>, events?: EventRegister<E>): SliceBuilder<S, E, A, M>;
|
|
107
|
+
//# sourceMappingURL=slice-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slice-builder.d.ts","sourceRoot":"","sources":["../../src/slice-builder.ts"],"names":[],"mappings":"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"}
|