@rotorsoft/act 0.6.28 → 0.6.30

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.
@@ -72,44 +72,179 @@ export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A exten
72
72
  */
73
73
  constructor(registry: Registry<S, E, A>);
74
74
  /**
75
- * Executes an action (command) against a state machine, emitting and committing the resulting event(s).
75
+ * Executes an action on a state instance, committing resulting events.
76
76
  *
77
- * @template K The type of action to execute
78
- * @param action The action name (key of the action schema)
79
- * @param target The target (stream and actor) for the action
80
- * @param payload The action payload (validated against the schema)
81
- * @param reactingTo (Optional) The event this action is reacting to
82
- * @param skipValidation (Optional) If true, skips schema validation (not recommended)
83
- * @returns The snapshot of the committed event
77
+ * This is the primary method for modifying state. It:
78
+ * 1. Validates the action payload against the schema
79
+ * 2. Loads the current state snapshot
80
+ * 3. Checks invariants (business rules)
81
+ * 4. Executes the action handler to generate events
82
+ * 5. Applies events to create new state
83
+ * 6. Commits events to the store with optimistic concurrency control
84
84
  *
85
- * @example
86
- * await app.do("increment", { stream: "counter1", actor }, { by: 1 });
85
+ * @template K - Action name from registered actions
86
+ * @param action - The name of the action to execute
87
+ * @param target - Target specification with stream ID and actor context
88
+ * @param payload - Action payload matching the action's schema
89
+ * @param reactingTo - Optional event that triggered this action (for correlation)
90
+ * @param skipValidation - Skip schema validation (use carefully, for performance)
91
+ * @returns Array of snapshots for all affected states (usually one)
92
+ *
93
+ * @throws {ValidationError} If payload doesn't match action schema
94
+ * @throws {InvariantError} If business rules are violated
95
+ * @throws {ConcurrencyError} If another process modified the stream
96
+ *
97
+ * @example Basic action execution
98
+ * ```typescript
99
+ * const snapshots = await app.do(
100
+ * "increment",
101
+ * {
102
+ * stream: "counter-1",
103
+ * actor: { id: "user1", name: "Alice" }
104
+ * },
105
+ * { by: 5 }
106
+ * );
107
+ *
108
+ * console.log(snapshots[0].state.count); // Current count after increment
109
+ * ```
110
+ *
111
+ * @example With error handling
112
+ * ```typescript
113
+ * try {
114
+ * await app.do(
115
+ * "withdraw",
116
+ * { stream: "account-123", actor: { id: "user1", name: "Alice" } },
117
+ * { amount: 1000 }
118
+ * );
119
+ * } catch (error) {
120
+ * if (error instanceof InvariantError) {
121
+ * console.error("Business rule violated:", error.description);
122
+ * } else if (error instanceof ConcurrencyError) {
123
+ * console.error("Concurrent modification detected, retry...");
124
+ * } else if (error instanceof ValidationError) {
125
+ * console.error("Invalid payload:", error.details);
126
+ * }
127
+ * }
128
+ * ```
129
+ *
130
+ * @example Reaction triggering another action
131
+ * ```typescript
132
+ * const app = act()
133
+ * .with(Order)
134
+ * .with(Inventory)
135
+ * .on("OrderPlaced")
136
+ * .do(async (event, context) => {
137
+ * // This action is triggered by an event
138
+ * const result = await context.app.do(
139
+ * "reduceStock",
140
+ * {
141
+ * stream: "inventory-1",
142
+ * actor: event.meta.causation.action.actor
143
+ * },
144
+ * { amount: event.data.items.length },
145
+ * event // Pass event for correlation tracking
146
+ * );
147
+ * return result;
148
+ * })
149
+ * .to("inventory-1")
150
+ * .build();
151
+ * ```
152
+ *
153
+ * @see {@link Target} for target structure
154
+ * @see {@link Snapshot} for return value structure
155
+ * @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}
87
156
  */
88
157
  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>[]>;
89
158
  /**
90
- * Loads the current state snapshot for a given state machine and stream.
159
+ * Loads the current state snapshot for a specific stream.
91
160
  *
92
- * @template SX The type of state
93
- * @template EX The type of events
94
- * @template AX The type of actions
95
- * @param state The state machine definition
96
- * @param stream The stream (instance) to load
97
- * @param callback (Optional) Callback to receive the loaded snapshot
98
- * @returns The snapshot of the loaded state
161
+ * Reconstructs the current state by replaying events from the event store.
162
+ * Uses snapshots when available to optimize loading performance.
99
163
  *
100
- * @example
101
- * const snapshot = await app.load(Counter, "counter1");
164
+ * @template SX - State schema type
165
+ * @template EX - Event schemas type
166
+ * @template AX - Action schemas type
167
+ * @param state - The state definition to load
168
+ * @param stream - The stream ID (state instance identifier)
169
+ * @param callback - Optional callback invoked with the loaded snapshot
170
+ * @returns The current state snapshot for the stream
171
+ *
172
+ * @example Load current state
173
+ * ```typescript
174
+ * const snapshot = await app.load(Counter, "counter-1");
175
+ * console.log(snapshot.state.count); // Current count
176
+ * console.log(snapshot.version); // Number of events applied
177
+ * console.log(snapshot.patches); // Events since last snapshot
178
+ * ```
179
+ *
180
+ * @example With callback
181
+ * ```typescript
182
+ * const snapshot = await app.load(User, "user-123", (snap) => {
183
+ * console.log("Loaded user:", snap.state.name);
184
+ * });
185
+ * ```
186
+ *
187
+ * @example Load multiple states
188
+ * ```typescript
189
+ * const [user, account] = await Promise.all([
190
+ * app.load(User, "user-123"),
191
+ * app.load(BankAccount, "account-456")
192
+ * ]);
193
+ * ```
194
+ *
195
+ * @see {@link Snapshot} for snapshot structure
102
196
  */
103
197
  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>>;
104
198
  /**
105
- * Query the event store for events matching a filter.
199
+ * Queries the event store for events matching a filter.
106
200
  *
107
- * @param query The query filter (e.g., by stream, event name, or time range)
108
- * @param callback (Optional) Callback for each event found
109
- * @returns An object with the first and last event found, and the total count
201
+ * Use this for analyzing event streams, generating reports, or debugging.
202
+ * The callback is invoked for each matching event, and the method returns
203
+ * summary information (first event, last event, total count).
110
204
  *
111
- * @example
112
- * const { count } = await app.query({ stream: "counter1" }, (event) => console.log(event));
205
+ * For small result sets, consider using {@link query_array} instead.
206
+ *
207
+ * @param query - The query filter
208
+ * @param query.stream - Filter by stream ID
209
+ * @param query.name - Filter by event name
210
+ * @param query.after - Filter events after this event ID
211
+ * @param query.before - Filter events before this event ID
212
+ * @param query.created_after - Filter events after this timestamp
213
+ * @param query.created_before - Filter events before this timestamp
214
+ * @param query.limit - Maximum number of events to return
215
+ * @param callback - Optional callback invoked for each matching event
216
+ * @returns Object with first event, last event, and total count
217
+ *
218
+ * @example Query all events for a stream
219
+ * ```typescript
220
+ * const { first, last, count } = await app.query(
221
+ * { stream: "counter-1" },
222
+ * (event) => console.log(event.name, event.data)
223
+ * );
224
+ * console.log(`Found ${count} events from ${first?.id} to ${last?.id}`);
225
+ * ```
226
+ *
227
+ * @example Query specific event types
228
+ * ```typescript
229
+ * const { count } = await app.query(
230
+ * { name: "UserCreated", limit: 100 },
231
+ * (event) => {
232
+ * console.log("User created:", event.data.email);
233
+ * }
234
+ * );
235
+ * ```
236
+ *
237
+ * @example Query events in time range
238
+ * ```typescript
239
+ * const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
240
+ * const { count } = await app.query({
241
+ * created_after: yesterday,
242
+ * stream: "user-123"
243
+ * });
244
+ * console.log(`User had ${count} events in last 24 hours`);
245
+ * ```
246
+ *
247
+ * @see {@link query_array} for loading events into memory
113
248
  */
114
249
  query(query: Query, callback?: (event: Committed<E, keyof E>) => void): Promise<{
115
250
  first?: Committed<E, keyof E>;
@@ -117,14 +252,30 @@ export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A exten
117
252
  count: number;
118
253
  }>;
119
254
  /**
120
- * Query the event store for events matching a filter.
121
- * Use this version with caution, as it return events in memory.
255
+ * Queries the event store and returns all matching events in memory.
122
256
  *
123
- * @param query The query filter (e.g., by stream, event name, or time range)
124
- * @returns The matching events
257
+ * **Use with caution** - this loads all results into memory. For large result sets,
258
+ * use {@link query} with a callback instead to process events incrementally.
125
259
  *
126
- * @example
127
- * const { count } = await app.query({ stream: "counter1" }, (event) => console.log(event));
260
+ * @param query - The query filter (same as {@link query})
261
+ * @returns Array of all matching events
262
+ *
263
+ * @example Load all events for a stream
264
+ * ```typescript
265
+ * const events = await app.query_array({ stream: "counter-1" });
266
+ * console.log(`Loaded ${events.length} events`);
267
+ * events.forEach(event => console.log(event.name, event.data));
268
+ * ```
269
+ *
270
+ * @example Get recent events
271
+ * ```typescript
272
+ * const recent = await app.query_array({
273
+ * stream: "user-123",
274
+ * limit: 10
275
+ * });
276
+ * ```
277
+ *
278
+ * @see {@link query} for large result sets
128
279
  */
129
280
  query_array(query: Query): Promise<Committed<E, keyof E>[]>;
130
281
  /**
@@ -140,41 +291,192 @@ export declare class Act<S extends SchemaRegister<A>, E extends Schemas, A exten
140
291
  */
141
292
  private handle;
142
293
  /**
143
- * Drains and processes events from the store, triggering reactions and updating state.
294
+ * Processes pending reactions by draining uncommitted events from the event store.
144
295
  *
145
- * This is typically called in a background loop or after committing new events.
296
+ * The drain process:
297
+ * 1. Polls the store for streams with uncommitted events
298
+ * 2. Leases streams to prevent concurrent processing
299
+ * 3. Fetches events for each leased stream
300
+ * 4. Executes matching reaction handlers
301
+ * 5. Acknowledges successful reactions or blocks failing ones
146
302
  *
147
- * @returns The number of events drained and processed
303
+ * Drain uses a dual-frontier strategy to balance processing of new streams (lagging)
304
+ * vs active streams (leading). The ratio adapts based on event pressure.
148
305
  *
149
- * @example
306
+ * Call this method periodically in a background loop, or after committing events.
307
+ *
308
+ * @param options - Drain configuration options
309
+ * @param options.streamLimit - Maximum number of streams to process per cycle (default: 10)
310
+ * @param options.eventLimit - Maximum events to fetch per stream (default: 10)
311
+ * @param options.leaseMillis - Lease duration in milliseconds (default: 10000)
312
+ * @returns Drain statistics with fetched, leased, acked, and blocked counts
313
+ *
314
+ * @example Basic drain loop
315
+ * ```typescript
316
+ * // Process reactions after each action
317
+ * await app.do("createUser", target, payload);
150
318
  * await app.drain();
319
+ * ```
320
+ *
321
+ * @example Background drain worker
322
+ * ```typescript
323
+ * setInterval(async () => {
324
+ * try {
325
+ * const result = await app.drain({
326
+ * streamLimit: 20,
327
+ * eventLimit: 50
328
+ * });
329
+ * if (result.acked.length) {
330
+ * console.log(`Processed ${result.acked.length} streams`);
331
+ * }
332
+ * } catch (error) {
333
+ * console.error("Drain error:", error);
334
+ * }
335
+ * }, 5000); // Every 5 seconds
336
+ * ```
337
+ *
338
+ * @example With lifecycle listeners
339
+ * ```typescript
340
+ * app.on("acked", (leases) => {
341
+ * console.log(`Acknowledged ${leases.length} streams`);
342
+ * });
343
+ *
344
+ * app.on("blocked", (blocked) => {
345
+ * console.error(`Blocked ${blocked.length} streams due to errors`);
346
+ * blocked.forEach(({ stream, error }) => {
347
+ * console.error(`Stream ${stream}: ${error}`);
348
+ * });
349
+ * });
350
+ *
351
+ * await app.drain();
352
+ * ```
353
+ *
354
+ * @see {@link correlate} for dynamic stream discovery
355
+ * @see {@link start_correlations} for automatic correlation
151
356
  */
152
357
  drain<E extends Schemas>({ streamLimit, eventLimit, leaseMillis, }?: DrainOptions): Promise<Drain<E>>;
153
358
  /**
154
- * Correlates streams using reaction resolvers.
155
- * @param query - The query filter (e.g., by stream, event name, or starting point).
156
- * @returns The leases of newly correlated streams, and the last seen event ID.
359
+ * Discovers and registers new streams dynamically based on reaction resolvers.
360
+ *
361
+ * Correlation enables "dynamic reactions" where target streams are determined at runtime
362
+ * based on event content. For example, you might create a stats stream for each user
363
+ * when they perform certain actions.
364
+ *
365
+ * This method scans events matching the query and identifies new target streams based
366
+ * on reaction resolvers. It then registers these streams so they'll be picked up by
367
+ * the next drain cycle.
368
+ *
369
+ * @param query - Query filter to scan for new correlations
370
+ * @param query.after - Start scanning after this event ID (default: -1)
371
+ * @param query.limit - Maximum events to scan (default: 10)
372
+ * @returns Object with newly leased streams and last scanned event ID
373
+ *
374
+ * @example Manual correlation
375
+ * ```typescript
376
+ * // Scan for new streams
377
+ * const { leased, last_id } = await app.correlate({ after: 0, limit: 100 });
378
+ * console.log(`Found ${leased.length} new streams`);
379
+ *
380
+ * // Save last_id for next scan
381
+ * await saveCheckpoint(last_id);
382
+ * ```
383
+ *
384
+ * @example Dynamic stream creation
385
+ * ```typescript
386
+ * const app = act()
387
+ * .with(User)
388
+ * .with(UserStats)
389
+ * .on("UserLoggedIn")
390
+ * .do(async (event) => ["incrementLoginCount", {}])
391
+ * .to((event) => ({
392
+ * target: `stats-${event.stream}` // Dynamic target per user
393
+ * }))
394
+ * .build();
395
+ *
396
+ * // Discover stats streams as users log in
397
+ * await app.correlate();
398
+ * ```
399
+ *
400
+ * @see {@link start_correlations} for automatic periodic correlation
401
+ * @see {@link stop_correlations} to stop automatic correlation
157
402
  */
158
403
  correlate(query?: Query): Promise<{
159
404
  leased: Lease[];
160
405
  last_id: number;
161
406
  }>;
162
407
  /**
163
- * Starts correlation worker that identifies and registers new streams using reaction resolvers.
164
- *
165
- * Enables "dynamic reactions", allowing streams to be auto-discovered based on event content.
166
- * - Uses a correlation sliding window over the event stream to identify new streams.
167
- * - Once registered, these streams are picked up by the main `drain` loop.
168
- * - Users should have full control over their correlation strategy.
169
- * - The starting point keeps increasing with each new batch of events.
170
- * - Users are responsible for storing the last seen event ID.
171
- *
172
- * @param query - The query filter (e.g., by stream, event name, or starting point).
173
- * @param frequency - The frequency of correlation checks (in milliseconds).
174
- * @param callback - Callback to report stats (new strems, last seen event ID, etc.).
175
- * @returns true if the correlation worker started, false otherwise (already started).
408
+ * Starts automatic periodic correlation worker for discovering new streams.
409
+ *
410
+ * The correlation worker runs in the background, scanning for new events and identifying
411
+ * new target streams based on reaction resolvers. It maintains a sliding window that
412
+ * advances with each scan, ensuring all events are eventually correlated.
413
+ *
414
+ * This is useful for dynamic stream creation patterns where you don't know all streams
415
+ * upfront - they're discovered as events arrive.
416
+ *
417
+ * **Note:** Only one correlation worker can run at a time per Act instance.
418
+ *
419
+ * @param query - Query filter for correlation scans
420
+ * @param query.after - Initial starting point (default: -1, start from beginning)
421
+ * @param query.limit - Events to scan per cycle (default: 100)
422
+ * @param frequency - Correlation frequency in milliseconds (default: 10000)
423
+ * @param callback - Optional callback invoked with newly discovered streams
424
+ * @returns `true` if worker started, `false` if already running
425
+ *
426
+ * @example Start automatic correlation
427
+ * ```typescript
428
+ * // Start correlation worker scanning every 5 seconds
429
+ * app.start_correlations(
430
+ * { after: 0, limit: 100 },
431
+ * 5000,
432
+ * (leased) => {
433
+ * console.log(`Discovered ${leased.length} new streams`);
434
+ * }
435
+ * );
436
+ *
437
+ * // Later, stop it
438
+ * app.stop_correlations();
439
+ * ```
440
+ *
441
+ * @example With checkpoint persistence
442
+ * ```typescript
443
+ * // Load last checkpoint
444
+ * const lastId = await loadCheckpoint();
445
+ *
446
+ * app.start_correlations(
447
+ * { after: lastId, limit: 100 },
448
+ * 10000,
449
+ * async (leased) => {
450
+ * // Save checkpoint for next restart
451
+ * if (leased.length) {
452
+ * const maxId = Math.max(...leased.map(l => l.at));
453
+ * await saveCheckpoint(maxId);
454
+ * }
455
+ * }
456
+ * );
457
+ * ```
458
+ *
459
+ * @see {@link correlate} for manual one-time correlation
460
+ * @see {@link stop_correlations} to stop the worker
176
461
  */
177
462
  start_correlations(query?: Query, frequency?: number, callback?: (leased: Lease[]) => void): boolean;
463
+ /**
464
+ * Stops the automatic correlation worker.
465
+ *
466
+ * Call this to stop the background correlation worker started by {@link start_correlations}.
467
+ * This is automatically called when the Act instance is disposed.
468
+ *
469
+ * @example
470
+ * ```typescript
471
+ * // Start correlation
472
+ * app.start_correlations();
473
+ *
474
+ * // Later, stop it
475
+ * app.stop_correlations();
476
+ * ```
477
+ *
478
+ * @see {@link start_correlations}
479
+ */
178
480
  stop_correlations(): void;
179
481
  }
180
482
  //# sourceMappingURL=act.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/act.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/act.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,67 @@
1
1
  import type { Committed, EventMeta, Lease, Message, Query, Schemas, Store } from "../types/index.js";
2
2
  /**
3
- * @category Adapters
4
- * @see Store
3
+ * In-memory event store implementation.
4
+ *
5
+ * This is the default store used by Act when no other store is injected.
6
+ * It stores all events in memory and is suitable for:
7
+ * - Development and prototyping
8
+ * - Unit and integration testing
9
+ * - Demonstrations and examples
10
+ *
11
+ * **Not suitable for production** - all data is lost when the process exits.
12
+ * Use {@link PostgresStore} for production deployments.
13
+ *
14
+ * The in-memory store provides:
15
+ * - Full {@link Store} interface implementation
16
+ * - Optimistic concurrency control
17
+ * - Stream leasing for distributed processing simulation
18
+ * - Snapshot support
19
+ * - Fast performance (no I/O overhead)
20
+ *
21
+ * @example Using in tests
22
+ * ```typescript
23
+ * import { store } from "@rotorsoft/act";
24
+ *
25
+ * describe("Counter", () => {
26
+ * beforeEach(async () => {
27
+ * // Reset store between tests
28
+ * await store().seed();
29
+ * });
5
30
  *
6
- * In-memory implementation of the Store interface.
31
+ * it("increments", async () => {
32
+ * await app.do("increment", target, { by: 5 });
33
+ * const snapshot = await app.load(Counter, "counter-1");
34
+ * expect(snapshot.state.count).toBe(5);
35
+ * });
36
+ * });
37
+ * ```
7
38
  *
8
- * Suitable for development, testing, and demonstration. Not for production use.
9
- * All events and streams are stored in memory and lost on process exit.
39
+ * @example Explicit instantiation
40
+ * ```typescript
41
+ * import { InMemoryStore } from "@rotorsoft/act";
10
42
  *
11
- * @example
12
- * const store = new InMemoryStore();
13
- * await store.commit('streamA', [{ name: 'event', data: {} }], meta);
43
+ * const testStore = new InMemoryStore();
44
+ * await testStore.seed();
45
+ *
46
+ * // Use for specific test scenarios
47
+ * await testStore.commit("test-stream", events, meta);
48
+ * ```
49
+ *
50
+ * @example Querying events
51
+ * ```typescript
52
+ * const events: any[] = [];
53
+ * await store().query(
54
+ * (event) => events.push(event),
55
+ * { stream: "test-stream" }
56
+ * );
57
+ * console.log(`Found ${events.length} events`);
58
+ * ```
59
+ *
60
+ * @see {@link Store} for the interface definition
61
+ * @see {@link PostgresStore} for production use
62
+ * @see {@link store} for injecting stores
63
+ *
64
+ * @category Adapters
14
65
  */
15
66
  export declare class InMemoryStore implements Store {
16
67
  private _events;
@@ -1 +1 @@
1
- {"version":3,"file":"InMemoryStore.d.ts","sourceRoot":"","sources":["../../../src/adapters/InMemoryStore.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,KAAK,EACL,OAAO,EACP,KAAK,EACN,MAAM,mBAAmB,CAAC;AAkG3B;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,YAAW,KAAK;IAEzC,OAAO,CAAC,OAAO,CAA2C;IAE1D,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;IACG,OAAO;IAKb;;;OAGG;IACG,IAAI;IAIV;;;OAGG;IACG,IAAI;IAMV,OAAO,CAAC,QAAQ;IAUhB;;;;;OAKG;IACG,KAAK,CAAC,CAAC,SAAS,OAAO,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,EAChD,KAAK,CAAC,EAAE,KAAK;IAiCf;;;;;;;;OAQG;IACG,MAAM,CAAC,CAAC,SAAS,OAAO,EAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,EAC3B,IAAI,EAAE,SAAS,EACf,eAAe,CAAC,EAAE,MAAM;IAiC1B;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;IAyB3C;;;;;OAKG;IACG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM;IAa3C;;;OAGG;IACG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE;;;;;;;;IAOzB;;;;OAIG;IACG,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;;;;;;;;;CAMrD"}
1
+ {"version":3,"file":"InMemoryStore.d.ts","sourceRoot":"","sources":["../../../src/adapters/InMemoryStore.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,KAAK,EACL,OAAO,EACP,KAAK,EACL,OAAO,EACP,KAAK,EACN,MAAM,mBAAmB,CAAC;AAkG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,qBAAa,aAAc,YAAW,KAAK;IAEzC,OAAO,CAAC,OAAO,CAA2C;IAE1D,OAAO,CAAC,QAAQ,CAA0C;IAE1D;;;OAGG;IACG,OAAO;IAKb;;;OAGG;IACG,IAAI;IAIV;;;OAGG;IACG,IAAI;IAMV,OAAO,CAAC,QAAQ;IAUhB;;;;;OAKG;IACG,KAAK,CAAC,CAAC,SAAS,OAAO,EAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,EAChD,KAAK,CAAC,EAAE,KAAK;IAiCf;;;;;;;;OAQG;IACG,MAAM,CAAC,CAAC,SAAS,OAAO,EAC5B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,OAAO,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,EAC3B,IAAI,EAAE,SAAS,EACf,eAAe,CAAC,EAAE,MAAM;IAiC1B;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;;;;;;IAyB3C;;;;;OAKG;IACG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM;IAa3C;;;OAGG;IACG,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE;;;;;;;;IAOzB;;;;OAIG;IACG,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;;;;;;;;;CAMrD"}
@@ -55,15 +55,63 @@ declare const BaseSchema: z.ZodObject<{
55
55
  */
56
56
  export type Config = z.infer<typeof BaseSchema>;
57
57
  /**
58
- * Returns the current Act Framework configuration, validated and type-safe.
58
+ * Gets the current Act Framework configuration.
59
+ *
60
+ * Configuration is loaded from package.json and environment variables, providing
61
+ * type-safe access to application metadata and runtime settings.
62
+ *
63
+ * **Environment Variables:**
64
+ * - `NODE_ENV`: "development" | "test" | "staging" | "production" (default: "development")
65
+ * - `LOG_LEVEL`: "fatal" | "error" | "warn" | "info" | "debug" | "trace"
66
+ * - `LOG_SINGLE_LINE`: "true" | "false" (default: "true")
67
+ * - `SLEEP_MS`: Milliseconds for sleep utility (default: 100, 0 for tests)
68
+ *
69
+ * **Defaults by environment:**
70
+ * - test: logLevel="error", sleepMs=0
71
+ * - production: logLevel="info"
72
+ * - development: logLevel="trace"
73
+ *
74
+ * @returns The validated configuration object
75
+ *
76
+ * @example Basic usage
77
+ * ```typescript
78
+ * import { config } from "@rotorsoft/act";
59
79
  *
60
- * Merges package.json metadata with environment, logging, and timing options.
61
- * @returns The validated configuration object.
62
- * @example
63
- * ```ts
64
80
  * const cfg = config();
65
- * console.log(cfg.env, cfg.logLevel);
81
+ * console.log(`App: ${cfg.name} v${cfg.version}`);
82
+ * console.log(`Environment: ${cfg.env}`);
83
+ * console.log(`Log level: ${cfg.logLevel}`);
66
84
  * ```
85
+ *
86
+ * @example Environment-specific behavior
87
+ * ```typescript
88
+ * import { config } from "@rotorsoft/act";
89
+ *
90
+ * const cfg = config();
91
+ *
92
+ * if (cfg.env === "production") {
93
+ * // Use PostgreSQL in production
94
+ * store(new PostgresStore(prodConfig));
95
+ * } else {
96
+ * // Use in-memory store for dev/test
97
+ * store(new InMemoryStore());
98
+ * }
99
+ * ```
100
+ *
101
+ * @example Adjusting log levels
102
+ * ```typescript
103
+ * // Set via environment variable:
104
+ * // LOG_LEVEL=debug npm start
105
+ *
106
+ * // Or check in code:
107
+ * const cfg = config();
108
+ * if (cfg.logLevel === "trace") {
109
+ * logger.trace("Detailed debugging enabled");
110
+ * }
111
+ * ```
112
+ *
113
+ * @see {@link Config} for configuration type
114
+ * @see {@link Package} for package.json metadata
67
115
  */
68
116
  export declare const config: () => Config;
69
117
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;iBAWxB,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAYpD;;;;GAIG;AACH,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKd,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAgBhD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,QAAO,MAEzB,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB;;;GAGG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;iBAWxB,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAYpD;;;;GAIG;AACH,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKd,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAgBhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,eAAO,MAAM,MAAM,QAAO,MAEzB,CAAC"}