@rotorsoft/act 0.33.1 → 0.33.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.
Files changed (38) hide show
  1. package/README.md +1 -1
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/@types/act.d.ts +25 -31
  4. package/dist/@types/act.d.ts.map +1 -1
  5. package/dist/@types/adapters/console-logger.d.ts +2 -0
  6. package/dist/@types/adapters/console-logger.d.ts.map +1 -1
  7. package/dist/@types/adapters/in-memory-cache.d.ts +7 -1
  8. package/dist/@types/adapters/in-memory-cache.d.ts.map +1 -1
  9. package/dist/@types/builders/state-builder.d.ts +2 -2
  10. package/dist/@types/builders/state-builder.d.ts.map +1 -1
  11. package/dist/@types/config.d.ts +0 -1
  12. package/dist/@types/config.d.ts.map +1 -1
  13. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  14. package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
  15. package/dist/@types/internal/index.d.ts +2 -2
  16. package/dist/@types/internal/index.d.ts.map +1 -1
  17. package/dist/@types/ports.d.ts.map +1 -1
  18. package/dist/@types/types/action.d.ts +6 -6
  19. package/dist/@types/types/action.d.ts.map +1 -1
  20. package/dist/@types/types/errors.d.ts +19 -19
  21. package/dist/@types/types/errors.d.ts.map +1 -1
  22. package/dist/@types/types/ports.d.ts +11 -10
  23. package/dist/@types/types/ports.d.ts.map +1 -1
  24. package/dist/@types/types/registry.d.ts +13 -4
  25. package/dist/@types/types/registry.d.ts.map +1 -1
  26. package/dist/@types/types/schemas.d.ts +19 -19
  27. package/dist/@types/types/schemas.d.ts.map +1 -1
  28. package/dist/@types/utils.d.ts.map +1 -1
  29. package/dist/{chunk-IDEYGKT4.js → chunk-AWT7TU22.js} +9 -9
  30. package/dist/{chunk-IDEYGKT4.js.map → chunk-AWT7TU22.js.map} +1 -1
  31. package/dist/index.cjs +57 -53
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.js +45 -41
  34. package/dist/index.js.map +1 -1
  35. package/dist/types/index.cjs +7 -7
  36. package/dist/types/index.cjs.map +1 -1
  37. package/dist/types/index.js +1 -1
  38. package/package.json +2 -2
@@ -1,4 +1,4 @@
1
- import { z, ZodObject, ZodRawShape } from "zod";
1
+ import { ZodObject, ZodRawShape, z } from "zod";
2
2
  /**
3
3
  * @packageDocumentation
4
4
  * @module act/types
@@ -12,16 +12,16 @@ export declare const ZodEmpty: z.ZodRecord<z.ZodString, z.ZodNever>;
12
12
  /**
13
13
  * Zod schema for an actor (user, system, etc.).
14
14
  */
15
- export declare const ActorSchema: z.ZodReadonly<z.ZodObject<{
15
+ export declare const ActorSchema: z.ZodReadonly<ZodObject<{
16
16
  id: z.ZodString;
17
17
  name: z.ZodString;
18
18
  }, z.core.$loose>>;
19
19
  /**
20
20
  * Zod schema for a target (stream and actor info).
21
21
  */
22
- export declare const TargetSchema: z.ZodReadonly<z.ZodObject<{
22
+ export declare const TargetSchema: z.ZodReadonly<ZodObject<{
23
23
  stream: z.ZodString;
24
- actor: z.ZodReadonly<z.ZodObject<{
24
+ actor: z.ZodReadonly<ZodObject<{
25
25
  id: z.ZodString;
26
26
  name: z.ZodString;
27
27
  }, z.core.$loose>>;
@@ -30,7 +30,7 @@ export declare const TargetSchema: z.ZodReadonly<z.ZodObject<{
30
30
  /**
31
31
  * Zod schema for causation event metadata.
32
32
  */
33
- export declare const CausationEventSchema: z.ZodObject<{
33
+ export declare const CausationEventSchema: ZodObject<{
34
34
  id: z.ZodNumber;
35
35
  name: z.ZodString;
36
36
  stream: z.ZodString;
@@ -38,20 +38,20 @@ export declare const CausationEventSchema: z.ZodObject<{
38
38
  /**
39
39
  * Zod schema for event metadata (correlation and causation).
40
40
  */
41
- export declare const EventMetaSchema: z.ZodReadonly<z.ZodObject<{
41
+ export declare const EventMetaSchema: z.ZodReadonly<ZodObject<{
42
42
  correlation: z.ZodString;
43
- causation: z.ZodObject<{
44
- action: z.ZodOptional<z.ZodIntersection<z.ZodReadonly<z.ZodObject<{
43
+ causation: ZodObject<{
44
+ action: z.ZodOptional<z.ZodIntersection<z.ZodReadonly<ZodObject<{
45
45
  stream: z.ZodString;
46
- actor: z.ZodReadonly<z.ZodObject<{
46
+ actor: z.ZodReadonly<ZodObject<{
47
47
  id: z.ZodString;
48
48
  name: z.ZodString;
49
49
  }, z.core.$loose>>;
50
50
  expectedVersion: z.ZodOptional<z.ZodNumber>;
51
- }, z.core.$loose>>, z.ZodObject<{
51
+ }, z.core.$loose>>, ZodObject<{
52
52
  name: z.ZodString;
53
53
  }, z.core.$strip>>>;
54
- event: z.ZodOptional<z.ZodObject<{
54
+ event: z.ZodOptional<ZodObject<{
55
55
  id: z.ZodNumber;
56
56
  name: z.ZodString;
57
57
  stream: z.ZodString;
@@ -61,25 +61,25 @@ export declare const EventMetaSchema: z.ZodReadonly<z.ZodObject<{
61
61
  /**
62
62
  * Zod schema for committed event metadata (id, stream, version, created, meta).
63
63
  */
64
- export declare const CommittedMetaSchema: z.ZodReadonly<z.ZodObject<{
64
+ export declare const CommittedMetaSchema: z.ZodReadonly<ZodObject<{
65
65
  id: z.ZodNumber;
66
66
  stream: z.ZodString;
67
67
  version: z.ZodNumber;
68
68
  created: z.ZodDate;
69
- meta: z.ZodReadonly<z.ZodObject<{
69
+ meta: z.ZodReadonly<ZodObject<{
70
70
  correlation: z.ZodString;
71
- causation: z.ZodObject<{
72
- action: z.ZodOptional<z.ZodIntersection<z.ZodReadonly<z.ZodObject<{
71
+ causation: ZodObject<{
72
+ action: z.ZodOptional<z.ZodIntersection<z.ZodReadonly<ZodObject<{
73
73
  stream: z.ZodString;
74
- actor: z.ZodReadonly<z.ZodObject<{
74
+ actor: z.ZodReadonly<ZodObject<{
75
75
  id: z.ZodString;
76
76
  name: z.ZodString;
77
77
  }, z.core.$loose>>;
78
78
  expectedVersion: z.ZodOptional<z.ZodNumber>;
79
- }, z.core.$loose>>, z.ZodObject<{
79
+ }, z.core.$loose>>, ZodObject<{
80
80
  name: z.ZodString;
81
81
  }, z.core.$strip>>>;
82
- event: z.ZodOptional<z.ZodObject<{
82
+ event: z.ZodOptional<ZodObject<{
83
83
  id: z.ZodNumber;
84
84
  name: z.ZodString;
85
85
  stream: z.ZodString;
@@ -101,7 +101,7 @@ export type StateSchema = Readonly<{
101
101
  /**
102
102
  * Query options for event store queries.
103
103
  */
104
- export declare const QuerySchema: z.ZodReadonly<z.ZodObject<{
104
+ export declare const QuerySchema: z.ZodReadonly<ZodObject<{
105
105
  stream: z.ZodOptional<z.ZodString>;
106
106
  names: z.ZodOptional<z.ZodArray<z.ZodString>>;
107
107
  before: z.ZodOptional<z.ZodNumber>;
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/types/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAEhD;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,QAAQ,sCAAkC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,WAAW;;;kBAMX,CAAC;AAEd;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;kBAOZ,CAAC;AAEd;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;iBAI/B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;kBAQf,CAAC;AAEd;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;kBAQnB,CAAC;AAEd;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC;IAClE,KAAK,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;CAC/B,CAAC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;kBAcX,CAAC"}
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/types/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAEhD;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,QAAQ,sCAAkC,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,WAAW;;;kBAMX,CAAC;AAEd;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;;;kBAOZ,CAAC;AAEd;;GAEG;AACH,eAAO,MAAM,oBAAoB;;;;iBAI/B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;kBAQf,CAAC;AAEd;;GAEG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;kBAQnB,CAAC;AAEd;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC;IACjE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,WAAW,CAAC,GAAG,OAAO,QAAQ,CAAC,CAAC;IAClE,KAAK,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;CAC/B,CAAC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;kBAcX,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,OAAO,EAAiB,MAAM,KAAK,CAAC;AAI5D;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EACxB,QAAQ,MAAM,EACd,SAAS,QAAQ,CAAC,CAAC,CAAC,EACpB,SAAS,OAAO,CAAC,CAAC,CAAC,KAClB,QAAQ,CAAC,CAAC,CASZ,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,GACjB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjC,QAAQ,QAAQ,CAAC,CAAC,CAAC,EACnB,QAAQ,OAAO,CAAC,CAAC,CAAC,EAClB,SAAS,QAAQ,CAAC,CAAC,CAAC,KACnB,QAAQ,CAAC,CAAC,GAAG,CAAC,CAGhB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,oBAEtC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,KAAK,CAAC;AAI5D;;;;;;;;;GASG;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EACxB,QAAQ,MAAM,EACd,SAAS,QAAQ,CAAC,CAAC,CAAC,EACpB,SAAS,OAAO,CAAC,CAAC,CAAC,KAClB,QAAQ,CAAC,CAAC,CASZ,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,GACjB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAEjC,QAAQ,QAAQ,CAAC,CAAC,CAAC,EACnB,QAAQ,OAAO,CAAC,CAAC,CAAC,EAClB,SAAS,QAAQ,CAAC,CAAC,CAAC,KACnB,QAAQ,CAAC,CAAC,GAAG,CAAC,CAGhB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,oBAEtC"}
@@ -25,13 +25,6 @@ var InvariantError = class extends Error {
25
25
  this.name = Errors.InvariantError;
26
26
  }
27
27
  };
28
- var StreamClosedError = class extends Error {
29
- constructor(stream) {
30
- super(`Stream "${stream}" is closed (tombstoned)`);
31
- this.stream = stream;
32
- this.name = Errors.StreamClosedError;
33
- }
34
- };
35
28
  var ConcurrencyError = class extends Error {
36
29
  constructor(stream, lastVersion, events, expectedVersion) {
37
30
  super(
@@ -46,6 +39,13 @@ var ConcurrencyError = class extends Error {
46
39
  this.name = Errors.ConcurrencyError;
47
40
  }
48
41
  };
42
+ var StreamClosedError = class extends Error {
43
+ constructor(stream) {
44
+ super(`Stream "${stream}" is closed (tombstoned)`);
45
+ this.stream = stream;
46
+ this.name = Errors.StreamClosedError;
47
+ }
48
+ };
49
49
 
50
50
  // src/types/schemas.ts
51
51
  import { z } from "zod";
@@ -112,8 +112,8 @@ export {
112
112
  Errors,
113
113
  ValidationError,
114
114
  InvariantError,
115
- StreamClosedError,
116
115
  ConcurrencyError,
116
+ StreamClosedError,
117
117
  ZodEmpty,
118
118
  ActorSchema,
119
119
  TargetSchema,
@@ -124,4 +124,4 @@ export {
124
124
  Environments,
125
125
  LogLevels
126
126
  };
127
- //# sourceMappingURL=chunk-IDEYGKT4.js.map
127
+ //# sourceMappingURL=chunk-AWT7TU22.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/errors.ts","../src/types/schemas.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n constructor(\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string,\n /** The invalid payload that failed validation */\n public readonly payload: any,\n /** Zod validation error details */\n public readonly details: any\n ) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n constructor(\n /** The action that was attempted */\n readonly action: TKey,\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>,\n /** The target stream and actor context */\n readonly target: Target<TActor>,\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>,\n /** Human-readable description of why the invariant failed */\n readonly description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n constructor(\n /** The stream that is closed */\n public readonly stream: string\n ) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n }\n}\n\nexport class ConcurrencyError extends Error {\n constructor(\n /** The stream that had the concurrent modification */\n public readonly stream: string,\n /** The actual current version in the store */\n public readonly lastVersion: number,\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[],\n /** The version number that was expected */\n public readonly expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n }\n}\n","import { z, ZodObject, ZodRawShape } from \"zod\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/types/errors.ts","../src/types/schemas.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n constructor(\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string,\n /** The invalid payload that failed validation */\n public readonly payload: any,\n /** Zod validation error details */\n public readonly details: any\n ) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n constructor(\n /** The action that was attempted */\n readonly action: TKey,\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>,\n /** The target stream and actor context */\n readonly target: Target<TActor>,\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>,\n /** Human-readable description of why the invariant failed */\n readonly description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n constructor(\n /** The stream that had the concurrent modification */\n public readonly stream: string,\n /** The actual current version in the store */\n public readonly lastVersion: number,\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[],\n /** The version number that was expected */\n public readonly expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n }\n}\n\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n constructor(\n /** The stream that is closed */\n public readonly stream: string\n ) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n }\n}\n","import { ZodObject, ZodRawShape, z } from \"zod\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -123,8 +123,10 @@ var ConsoleLogger = class _ConsoleLogger {
123
123
  this.debug = threshold <= 20 ? write.bind(this, "debug", 20) : noop;
124
124
  this.trace = threshold <= 10 ? write.bind(this, "trace", 10) : noop;
125
125
  }
126
+ /** No-op — `console.log` has no resources to release. */
126
127
  async dispose() {
127
128
  }
129
+ /** @inheritDoc */
128
130
  child(bindings) {
129
131
  return new _ConsoleLogger({
130
132
  level: this.level,
@@ -249,21 +251,27 @@ var InMemoryCache = class {
249
251
  constructor(options) {
250
252
  this._entries = new LruMap(options?.maxSize ?? 1e3);
251
253
  }
254
+ /** @inheritDoc */
252
255
  async get(stream) {
253
256
  return this._entries.get(stream);
254
257
  }
258
+ /** @inheritDoc */
255
259
  async set(stream, entry) {
256
260
  this._entries.set(stream, entry);
257
261
  }
262
+ /** @inheritDoc */
258
263
  async invalidate(stream) {
259
264
  this._entries.delete(stream);
260
265
  }
266
+ /** @inheritDoc */
261
267
  async clear() {
262
268
  this._entries.clear();
263
269
  }
270
+ /** @inheritDoc */
264
271
  async dispose() {
265
272
  this._entries.clear();
266
273
  }
274
+ /** Current number of entries held by the LRU. */
267
275
  get size() {
268
276
  return this._entries.size;
269
277
  }
@@ -296,13 +304,6 @@ var InvariantError = class extends Error {
296
304
  this.name = Errors.InvariantError;
297
305
  }
298
306
  };
299
- var StreamClosedError = class extends Error {
300
- constructor(stream) {
301
- super(`Stream "${stream}" is closed (tombstoned)`);
302
- this.stream = stream;
303
- this.name = Errors.StreamClosedError;
304
- }
305
- };
306
307
  var ConcurrencyError = class extends Error {
307
308
  constructor(stream, lastVersion, events, expectedVersion) {
308
309
  super(
@@ -317,6 +318,13 @@ var ConcurrencyError = class extends Error {
317
318
  this.name = Errors.ConcurrencyError;
318
319
  }
319
320
  };
321
+ var StreamClosedError = class extends Error {
322
+ constructor(stream) {
323
+ super(`Stream "${stream}" is closed (tombstoned)`);
324
+ this.stream = stream;
325
+ this.name = Errors.StreamClosedError;
326
+ }
327
+ };
320
328
 
321
329
  // src/utils.ts
322
330
  var import_zod3 = require("zod");
@@ -906,7 +914,7 @@ var InMemoryStore = class {
906
914
  var ExitCodes = ["ERROR", "EXIT"];
907
915
  var adapters = /* @__PURE__ */ new Map();
908
916
  function port(injector) {
909
- return function(adapter) {
917
+ return (adapter) => {
910
918
  if (!adapters.has(injector.name)) {
911
919
  const injected = injector(adapter);
912
920
  adapters.set(injector.name, injected);
@@ -972,7 +980,7 @@ process.once("unhandledRejection", async (arg) => {
972
980
  });
973
981
 
974
982
  // src/act.ts
975
- var import_events = __toESM(require("events"), 1);
983
+ var import_node_events = __toESM(require("events"), 1);
976
984
 
977
985
  // src/internal/build-classify.ts
978
986
  function classifyRegistry(registry, states) {
@@ -1006,7 +1014,7 @@ function classifyRegistry(registry, states) {
1006
1014
  }
1007
1015
 
1008
1016
  // src/internal/close-cycle.ts
1009
- var import_crypto = require("crypto");
1017
+ var import_node_crypto = require("crypto");
1010
1018
  async function runCloseCycle(targets, deps) {
1011
1019
  const targetMap = new Map(targets.map((t) => [t.stream, t]));
1012
1020
  const streams = [...targetMap.keys()];
@@ -1018,7 +1026,7 @@ async function runCloseCycle(targets, deps) {
1018
1026
  skipped
1019
1027
  );
1020
1028
  if (!safe.length) return { truncated: /* @__PURE__ */ new Map(), skipped };
1021
- const correlation = (0, import_crypto.randomUUID)();
1029
+ const correlation = (0, import_node_crypto.randomUUID)();
1022
1030
  const { guarded, guardEvents } = await guardWithTombstones(
1023
1031
  safe,
1024
1032
  streamInfo,
@@ -1275,7 +1283,7 @@ var CorrelateCycle = class {
1275
1283
  };
1276
1284
 
1277
1285
  // src/internal/drain-cycle.ts
1278
- var import_crypto2 = require("crypto");
1286
+ var import_node_crypto2 = require("crypto");
1279
1287
 
1280
1288
  // src/internal/drain-ratio.ts
1281
1289
  var RATIO_MIN = 0.2;
@@ -1297,7 +1305,7 @@ function computeLagLeadRatio(handled, lagging, leading) {
1297
1305
 
1298
1306
  // src/internal/drain-cycle.ts
1299
1307
  async function runDrainCycle(ops, registry, batchHandlers, handle, handleBatch, lagging, leading, eventLimit, leaseMillis) {
1300
- const leased = await ops.claim(lagging, leading, (0, import_crypto2.randomUUID)(), leaseMillis);
1308
+ const leased = await ops.claim(lagging, leading, (0, import_node_crypto2.randomUUID)(), leaseMillis);
1301
1309
  if (!leased.length) return void 0;
1302
1310
  const fetched = await ops.fetch(leased, eventLimit);
1303
1311
  const fetchMap = /* @__PURE__ */ new Map();
@@ -1698,8 +1706,8 @@ var block = (leases) => store().block(leases);
1698
1706
  var subscribe = (streams) => store().subscribe(streams);
1699
1707
 
1700
1708
  // src/internal/event-sourcing.ts
1709
+ var import_node_crypto3 = require("crypto");
1701
1710
  var import_act_patch = require("@rotorsoft/act-patch");
1702
- var import_crypto3 = require("crypto");
1703
1711
  async function snap(snapshot) {
1704
1712
  try {
1705
1713
  const { id, stream, name, meta, version } = snapshot.event;
@@ -1759,7 +1767,7 @@ async function load(me, stream, callback, asOf) {
1759
1767
  `Skipping unknown event "${String(e.name)}" on stream "${stream}" (id=${e.id}) \u2014 no reducer in state "${me.name}"`
1760
1768
  );
1761
1769
  }
1762
- callback && callback({
1770
+ callback?.({
1763
1771
  event,
1764
1772
  state: state2,
1765
1773
  version,
@@ -1818,7 +1826,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1818
1826
  data: skipValidation ? data : validate(name, data, me.events[name])
1819
1827
  }));
1820
1828
  const meta = {
1821
- correlation: reactingTo?.meta.correlation || (0, import_crypto3.randomUUID)(),
1829
+ correlation: reactingTo?.meta.correlation || (0, import_node_crypto3.randomUUID)(),
1822
1830
  causation: {
1823
1831
  action: {
1824
1832
  name: action2,
@@ -1868,7 +1876,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1868
1876
  };
1869
1877
  });
1870
1878
  const last = snapshots.at(-1);
1871
- const snapped = me.snap && me.snap(last);
1879
+ const snapped = me.snap?.(last);
1872
1880
  cache().set(stream, {
1873
1881
  state: last.state,
1874
1882
  version: last.event.version,
@@ -2049,6 +2057,17 @@ function buildDrain(logger) {
2049
2057
  var DEFAULT_MAX_SUBSCRIBED_STREAMS = 1e3;
2050
2058
  var DEFAULT_SETTLE_DEBOUNCE_MS = 10;
2051
2059
  var Act = class {
2060
+ /**
2061
+ * Create a new Act orchestrator. Prefer the {@link act} builder over
2062
+ * direct construction — `act()...build()` wires the registry, merges
2063
+ * partial states, and collects batch handlers from registered slices
2064
+ * and projections in one pass.
2065
+ *
2066
+ * @param registry Schemas for every event and action across registered states
2067
+ * @param _states Merged map of state name → state definition
2068
+ * @param batchHandlers Static-target projection batch handlers (target → handler)
2069
+ * @param options Tuning knobs — see {@link ActOptions}
2070
+ */
2052
2071
  constructor(registry, _states = /* @__PURE__ */ new Map(), batchHandlers = /* @__PURE__ */ new Map(), options = {}) {
2053
2072
  this.registry = registry;
2054
2073
  this._states = _states;
@@ -2105,7 +2124,7 @@ var Act = class {
2105
2124
  return Promise.resolve();
2106
2125
  });
2107
2126
  }
2108
- _emitter = new import_events.default();
2127
+ _emitter = new import_node_events.default();
2109
2128
  /** Event names with at least one registered reaction (computed at build time) */
2110
2129
  _reactive_events;
2111
2130
  /** Drain pipeline driver: armed flag, concurrency lock, adaptive ratio. */
@@ -2136,12 +2155,6 @@ var Act = class {
2136
2155
  this._emitter.off(event, listener);
2137
2156
  return this;
2138
2157
  }
2139
- /**
2140
- * Create a new Act orchestrator.
2141
- *
2142
- * @param registry The registry of state, event, and action schemas
2143
- * @param states Map of state names to their (potentially merged) state definitions
2144
- */
2145
2158
  /** Batch handlers for static-target projections (target → handler) */
2146
2159
  _batch_handlers;
2147
2160
  /** Event-sourcing handlers, optionally wrapped with trace decorators */
@@ -2287,14 +2300,9 @@ var Act = class {
2287
2300
  *
2288
2301
  * For small result sets, consider using {@link query_array} instead.
2289
2302
  *
2290
- * @param query - The query filter
2291
- * @param query.stream - Filter by stream ID
2292
- * @param query.name - Filter by event name
2293
- * @param query.after - Filter events after this event ID
2294
- * @param query.before - Filter events before this event ID
2295
- * @param query.created_after - Filter events after this timestamp
2296
- * @param query.created_before - Filter events before this timestamp
2297
- * @param query.limit - Maximum number of events to return
2303
+ * @param query - Filter criteria — see {@link Query} for available fields
2304
+ * (`stream`, `name`, `after`, `before`, `created_after`, `created_before`,
2305
+ * `limit`, `with_snaps`, `stream_exact`)
2298
2306
  * @param callback - Optional callback invoked for each matching event
2299
2307
  * @returns Object with first event, last event, and total count
2300
2308
  *
@@ -2330,11 +2338,12 @@ var Act = class {
2330
2338
  * @see {@link query_array} for loading events into memory
2331
2339
  */
2332
2340
  async query(query, callback) {
2333
- let first = void 0, last = void 0;
2341
+ let first;
2342
+ let last;
2334
2343
  const count = await store().query((e) => {
2335
- !first && (first = e);
2344
+ if (!first) first = e;
2336
2345
  last = e;
2337
- callback && callback(e);
2346
+ callback?.(e);
2338
2347
  }, query);
2339
2348
  return { first, last, count };
2340
2349
  }
@@ -2385,10 +2394,8 @@ var Act = class {
2385
2394
  * Call `correlate()` before `drain()` to discover target streams. For a higher-level
2386
2395
  * API that handles debouncing, correlation, and signaling automatically, use {@link settle}.
2387
2396
  *
2388
- * @param options - Drain configuration options
2389
- * @param options.streamLimit - Maximum number of streams to process per cycle (default: 10)
2390
- * @param options.eventLimit - Maximum events to fetch per stream (default: 10)
2391
- * @param options.leaseMillis - Lease duration in milliseconds (default: 10000)
2397
+ * @param options - Drain configuration — see {@link DrainOptions} for fields
2398
+ * (`streamLimit`, `eventLimit`, `leaseMillis`).
2392
2399
  * @returns Drain statistics with fetched, leased, acked, and blocked counts
2393
2400
  *
2394
2401
  * @example In tests and scripts
@@ -2423,8 +2430,8 @@ var Act = class {
2423
2430
  * the next drain cycle.
2424
2431
  *
2425
2432
  * @param query - Query filter to scan for new correlations
2426
- * @param query.after - Start scanning after this event ID (default: -1)
2427
- * @param query.limit - Maximum events to scan (default: 10)
2433
+ * @param query - Scan filter see {@link Query} for fields (typically
2434
+ * `{ after: <event-id>, limit: <count> }`)
2428
2435
  * @returns Object with newly leased streams and last scanned event ID
2429
2436
  *
2430
2437
  * @example Manual correlation
@@ -2471,9 +2478,8 @@ var Act = class {
2471
2478
  *
2472
2479
  * **Note:** Only one correlation worker can run at a time per Act instance.
2473
2480
  *
2474
- * @param query - Query filter for correlation scans
2475
- * @param query.after - Initial starting point (default: -1, start from beginning)
2476
- * @param query.limit - Events to scan per cycle (default: 100)
2481
+ * @param query - Query filter for correlation scans — see {@link Query}
2482
+ * (typically `{ after: -1, limit: 100 }`)
2477
2483
  * @param frequency - Correlation frequency in milliseconds (default: 10000)
2478
2484
  * @param callback - Optional callback invoked with newly discovered streams
2479
2485
  * @returns `true` if worker started, `false` if already running
@@ -2640,14 +2646,11 @@ var Act = class {
2640
2646
  * fully catches up paginated streams (e.g. after `reset()` on a long
2641
2647
  * projection) without forcing callers to loop.
2642
2648
  *
2643
- * @param options - Settle configuration options
2644
- * @param options.debounceMs - Debounce window in milliseconds (default: 10)
2645
- * @param options.correlate - Query filter for correlation scans (default: `{ after: -1, limit: 100 }`)
2646
- * @param options.maxPasses - Cap on correlate→drain loops (default: `Infinity`).
2647
- * Early-exit on no-progress means the cap only matters in pathological cases.
2648
- * @param options.streamLimit - Maximum streams per drain cycle (default: 10)
2649
- * @param options.eventLimit - Maximum events per stream (default: 10)
2650
- * @param options.leaseMillis - Lease duration in milliseconds (default: 10000)
2649
+ * @param options - Settle configuration — see {@link SettleOptions} for fields:
2650
+ * `debounceMs` (default 10), `correlate` (default `{ after: -1, limit: 100 }`),
2651
+ * `maxPasses` (default `Infinity` kill-switch for runaway loops),
2652
+ * `streamLimit` (default 10), `eventLimit` (default 10),
2653
+ * `leaseMillis` (default 10000).
2651
2654
  *
2652
2655
  * @example API mutations
2653
2656
  * ```typescript
@@ -2910,7 +2913,8 @@ function action_builder(state2) {
2910
2913
  throw new Error(`Duplicate action "${action2}"`);
2911
2914
  internal.actions[action2] = schema;
2912
2915
  function given(rules) {
2913
- (internal.given ??= {})[action2] = rules;
2916
+ internal.given ??= {};
2917
+ internal.given[action2] = rules;
2914
2918
  return { emit };
2915
2919
  }
2916
2920
  function emit(handler) {