@kronos-ts/eventsourcing 0.1.4 → 0.2.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/index.d.ts CHANGED
@@ -12,5 +12,6 @@ export { type SnapshotPolicy, type EvolutionResult, afterEvents, whenSourcingTim
12
12
  export { type Snapshot, type SnapshotStore, createInMemorySnapshotStore, } from "./snapshot-store.js";
13
13
  export { createInterceptingEventStore } from "./intercepting-event-store.js";
14
14
  export { load, STATE_MANAGER_KEY } from "./load.js";
15
+ export { schedule, scheduleAfter, cancelSchedule, EVENT_SCHEDULER_KEY, type ScheduleFunction, type ScheduleAfterFunction, } from "./schedule.js";
15
16
  export { append, BUFFERED_EVENTS_KEY, SOURCING_INFOS_KEY, STATE_CACHE_KEY, STATE_MODULES_KEY, } from "./append.js";
16
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EACtB,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,KAAK,iBAAiB,EACtB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,KAAK,eAAe,EACpB,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,KAAK,qBAAqB,EAC1B,2BAA2B,GAC5B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAE3F,OAAO,EACL,KAAK,WAAW,EAChB,0BAA0B,EAC1B,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAC5E,YAAY,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAA;AAElF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,WAAW,EACX,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAG5E,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EACL,MAAM,EACN,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EACtB,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,KAAK,iBAAiB,EACtB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,KAAK,eAAe,EACpB,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EACL,KAAK,UAAU,EACf,KAAK,cAAc,GACpB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,KAAK,qBAAqB,EAC1B,2BAA2B,GAC5B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAE3F,OAAO,EACL,KAAK,WAAW,EAChB,0BAA0B,EAC1B,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAC5E,YAAY,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAA;AAElF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,WAAW,EACX,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,2BAA2B,GAC5B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAG5E,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EACL,QAAQ,EACR,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,MAAM,EACN,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAA"}
package/dist/index.js CHANGED
@@ -12,5 +12,6 @@ export { createInMemorySnapshotStore, } from "./snapshot-store.js";
12
12
  export { createInterceptingEventStore } from "./intercepting-event-store.js";
13
13
  // Module-level handler helpers (Plan 04-01 / HDL-02 / D-42)
14
14
  export { load, STATE_MANAGER_KEY } from "./load.js";
15
+ export { schedule, scheduleAfter, cancelSchedule, EVENT_SCHEDULER_KEY, } from "./schedule.js";
15
16
  export { append, BUFFERED_EVENTS_KEY, SOURCING_INFOS_KEY, STATE_CACHE_KEY, STATE_MODULES_KEY, } from "./append.js";
16
17
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAEL,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAEL,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAGN,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAEL,2BAA2B,GAC5B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAmD,MAAM,2BAA2B,CAAA;AAE3F,OAAO,EAEL,0BAA0B,EAC1B,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAG5E,OAAO,EAGL,WAAW,EACX,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAGL,2BAA2B,GAC5B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAE5E,4DAA4D;AAC5D,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EACL,MAAM,EACN,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,QAAQ,EACR,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAEL,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EAEL,eAAe,GAChB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAGN,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAEL,2BAA2B,GAC5B,MAAM,8BAA8B,CAAA;AAErC,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EAAmD,MAAM,2BAA2B,CAAA;AAE3F,OAAO,EAEL,0BAA0B,EAC1B,wBAAwB,EACxB,gBAAgB,GACjB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAG5E,OAAO,EAGL,WAAW,EACX,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAGL,2BAA2B,GAC5B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAA;AAE5E,4DAA4D;AAC5D,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EACL,QAAQ,EACR,aAAa,EACb,cAAc,EACd,mBAAmB,GAGpB,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,MAAM,EACN,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAMjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGzD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;KAAE,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAClG,CAAC,CAAC,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACvD;AAMD,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,CACJ,MAAM,EAAE,GAAG,EACX,EAAE,EAAE,GAAG,KACJ,OAAO,CAAC;QACX,KAAK,EAAE,GAAG,CAAA;QACV,YAAY,EAAE;YAAE,QAAQ,EAAE,aAAa,CAAC;YAAC,cAAc,EAAE,MAAM,CAAA;SAAE,CAAA;KAClE,CAAC,CAAA;CACH,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,gBAAgB,CAA+B,CAAA;AAE3F;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,EAAE,YAqBD,CAAA"}
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAMjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAGzD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;KAAE,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAClG,CAAC,CAAC,EAAE,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACvD;AAMD,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,CACJ,MAAM,EAAE,GAAG,EACX,EAAE,EAAE,GAAG,KACJ,OAAO,CAAC;QACX,KAAK,EAAE,GAAG,CAAA;QACV,YAAY,EAAE;YAAE,QAAQ,EAAE,aAAa,CAAC;YAAC,cAAc,EAAE,MAAM,CAAA;SAAE,CAAA;KAClE,CAAC,CAAA;CACH,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,gBAAgB,CAA+B,CAAA;AAuB3F;;;;;;GAMG;AACH,eAAO,MAAM,IAAI,EAAE,YAqBD,CAAA"}
package/dist/load.js CHANGED
@@ -6,6 +6,28 @@ import { STATE_CACHE_KEY, STATE_MODULES_KEY, SOURCING_INFOS_KEY } from "./append
6
6
  * Written by handling modules + processors at handler-invocation entry (D-44).
7
7
  */
8
8
  export const STATE_MANAGER_KEY = resourceKey("stateManager");
9
+ /**
10
+ * Stable cache key for a state id. State ids are typically objects
11
+ * (e.g. `{ ticketId }`), and `String({...})` collapses every object to
12
+ * `"[object Object]"` — which would make two different ids of the same module
13
+ * share a cache entry within a UoW and return each other's state. Serialize
14
+ * structurally instead, with sorted keys (so id construction order is
15
+ * irrelevant) and bigint support. Primitive ids serialize to a unique string
16
+ * too, so this is strictly safer than `String(id)`.
17
+ */
18
+ function stableIdKey(id) {
19
+ return JSON.stringify(id, (_key, value) => {
20
+ if (typeof value === "bigint")
21
+ return `${value}n`;
22
+ if (value && typeof value === "object" && !Array.isArray(value)) {
23
+ const sorted = {};
24
+ for (const k of Object.keys(value).sort())
25
+ sorted[k] = value[k];
26
+ return sorted;
27
+ }
28
+ return value;
29
+ });
30
+ }
9
31
  /**
10
32
  * Plan 04-01 (HDL-02 / D-42): module-level load.
11
33
  *
@@ -21,7 +43,7 @@ export const load = (async (module, id) => {
21
43
  if (!stateManager)
22
44
  throw new Error("No state manager configured");
23
45
  const cache = computeIfAbsent(STATE_CACHE_KEY, () => new Map());
24
- const cacheKey = `${module.name}:${String(id)}`;
46
+ const cacheKey = `${module.name}:${stableIdKey(id)}`;
25
47
  if (!cache.has(cacheKey)) {
26
48
  cache.set(cacheKey, stateManager.load(module, id));
27
49
  const modules = computeIfAbsent(STATE_MODULES_KEY, () => new Map());
package/dist/load.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"load.js","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AACjE,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,kBAAkB,GACnB,MAAM,uCAAuC,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AA4BpF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAkC,WAAW,CAAC,cAAc,CAAC,CAAA;AAE3F;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAiB,CAAC,KAAK,EAAK,MAAwB,EAAE,EAAW,EAAc,EAAE;IAChG,MAAM,KAAK,GAAG,sBAAsB,CAAC,QAAQ,EAAE,CAAA;IAC/C,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACvD,MAAM,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAiC,CAAA;IAClG,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAEjE,MAAM,KAAK,GAAG,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAA;IAC/D,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC,EAAE,CAAA;IAC/C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAA;QAClD,MAAM,OAAO,GAAG,eAAe,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAA;QACnE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IACvC,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;IACzC,MAAM,UAAU,GAAG,MAGlB,CAAA;IACD,MAAM,KAAK,GAAG,eAAe,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3D,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;IACnC,OAAO,UAAU,CAAC,KAAU,CAAA;AAC9B,CAAC,CAAiB,CAAA"}
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../src/load.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AACjE,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,kBAAkB,GACnB,MAAM,uCAAuC,CAAA;AAE9C,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AA4BpF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAkC,WAAW,CAAC,cAAc,CAAC,CAAA;AAE3F;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,EAAW;IAC9B,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QACxC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,GAAG,KAAK,GAAG,CAAA;QACjD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChE,MAAM,MAAM,GAA4B,EAAE,CAAA;YAC1C,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE;gBAAE,MAAM,CAAC,CAAC,CAAC,GAAI,KAAiC,CAAC,CAAC,CAAC,CAAA;YAC5F,OAAO,MAAM,CAAA;QACf,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,IAAI,GAAiB,CAAC,KAAK,EAAK,MAAwB,EAAE,EAAW,EAAc,EAAE;IAChG,MAAM,KAAK,GAAG,sBAAsB,CAAC,QAAQ,EAAE,CAAA;IAC/C,IAAI,KAAK,KAAK,SAAS;QAAE,MAAM,IAAI,kBAAkB,EAAE,CAAA;IACvD,MAAM,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAiC,CAAA;IAClG,IAAI,CAAC,YAAY;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAA;IAEjE,MAAM,KAAK,GAAG,eAAe,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAA;IAC/D,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,WAAW,CAAC,EAAE,CAAC,EAAE,CAAA;IACpD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAA;QAClD,MAAM,OAAO,GAAG,eAAe,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAA;QACnE,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;IACvC,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAA;IACzC,MAAM,UAAU,GAAG,MAGlB,CAAA;IACD,MAAM,KAAK,GAAG,eAAe,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3D,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;IACnC,OAAO,UAAU,CAAC,KAAU,CAAA;AAC9B,CAAC,CAAiB,CAAA"}
@@ -0,0 +1,50 @@
1
+ import { type Metadata, type ResourceKey } from "@kronos-ts/common";
2
+ import type { z } from "zod";
3
+ import type { EventDescriptor, EventScheduler, ScheduleToken, CancelResult } from "@kronos-ts/messaging";
4
+ /**
5
+ * Resource key for the event scheduler component.
6
+ * Written by handling modules + processors at handler-invocation entry,
7
+ * exactly like {@link STATE_MANAGER_KEY} — so the {@link schedule} helper
8
+ * resolves the framework-configured scheduler from the active UnitOfWork.
9
+ */
10
+ export declare const EVENT_SCHEDULER_KEY: ResourceKey<EventScheduler>;
11
+ /** Schedule an event for future append from inside a handler. */
12
+ export interface ScheduleFunction {
13
+ <P extends z.ZodType>(event: EventDescriptor<P>, payload: z.infer<P>, at: Date): Promise<ScheduleToken>;
14
+ <P extends z.ZodType>(event: EventDescriptor<P>, payload: z.infer<P>, at: Date, metadata: Metadata): Promise<ScheduleToken>;
15
+ }
16
+ /**
17
+ * Schedule {@link event} to be appended at {@link at}.
18
+ *
19
+ * The same one-call ergonomics as {@link append}/{@link send}: pass the event
20
+ * descriptor + payload and the helper builds the {@link EventMessage} (tags,
21
+ * metadata, identifier) and hands it to the configured {@link EventScheduler}.
22
+ * No need to fetch the scheduler or construct a message by hand.
23
+ *
24
+ * Must be called from inside a UnitOfWork (throws otherwise). The schedule
25
+ * participates in the active transaction — if the handler's UoW rolls back,
26
+ * nothing is scheduled; if it commits, the event is durably scheduled and will
27
+ * fire at or after `at` unless cancelled. Metadata defaults to the UoW
28
+ * metadata, so correlation/causation lineage carries onto the fired event.
29
+ *
30
+ * Returns a {@link ScheduleToken} — persist it (e.g. in state via an event) to
31
+ * {@link cancelSchedule} later. That is the deadline/process-manager pattern.
32
+ */
33
+ export declare const schedule: ScheduleFunction;
34
+ /** Schedule an event a fixed delay from now, from inside a handler. */
35
+ export interface ScheduleAfterFunction {
36
+ <P extends z.ZodType>(event: EventDescriptor<P>, payload: z.infer<P>, delayMs: number): Promise<ScheduleToken>;
37
+ <P extends z.ZodType>(event: EventDescriptor<P>, payload: z.infer<P>, delayMs: number, metadata: Metadata): Promise<ScheduleToken>;
38
+ }
39
+ /**
40
+ * Convenience wrapper over {@link schedule}: fire `delayMs` milliseconds from
41
+ * now instead of at an absolute {@link Date}.
42
+ */
43
+ export declare const scheduleAfter: ScheduleAfterFunction;
44
+ /**
45
+ * Attempt to cancel a previously {@link schedule}d event from inside a handler.
46
+ * UoW-aware: joins the active transaction, so cancelling then throwing does not
47
+ * leave the schedule cancelled. See {@link CancelResult} for outcomes.
48
+ */
49
+ export declare const cancelSchedule: (token: ScheduleToken) => Promise<CancelResult>;
50
+ //# sourceMappingURL=schedule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../src/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,QAAQ,EAAe,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpG,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EACd,aAAa,EACb,YAAY,EACb,MAAM,sBAAsB,CAAA;AAE7B;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,cAAc,CAAiC,CAAA;AAE7F,iEAAiE;AACjE,MAAM,WAAW,gBAAgB;IAC/B,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IACvG,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAClB,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EACnB,EAAE,EAAE,IAAI,EACR,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,aAAa,CAAC,CAAA;CAC1B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,QAAQ,EAAE,gBAoBD,CAAA;AAEtB,uEAAuE;AACvE,MAAM,WAAW,qBAAqB;IACpC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;IAC9G,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAClB,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,EACzB,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,QAAQ,GACjB,OAAO,CAAC,aAAa,CAAC,CAAA;CAC1B;AAED;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,qBAKiF,CAAA;AAE7G;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAU,OAAO,aAAa,KAAG,OAAO,CAAC,YAAY,CAK/E,CAAA"}
@@ -0,0 +1,60 @@
1
+ import { generateIdentifier, resourceKey } from "@kronos-ts/common";
2
+ import { requireInvocationPhase } from "@kronos-ts/messaging/processing-state";
3
+ /**
4
+ * Resource key for the event scheduler component.
5
+ * Written by handling modules + processors at handler-invocation entry,
6
+ * exactly like {@link STATE_MANAGER_KEY} — so the {@link schedule} helper
7
+ * resolves the framework-configured scheduler from the active UnitOfWork.
8
+ */
9
+ export const EVENT_SCHEDULER_KEY = resourceKey("eventScheduler");
10
+ /**
11
+ * Schedule {@link event} to be appended at {@link at}.
12
+ *
13
+ * The same one-call ergonomics as {@link append}/{@link send}: pass the event
14
+ * descriptor + payload and the helper builds the {@link EventMessage} (tags,
15
+ * metadata, identifier) and hands it to the configured {@link EventScheduler}.
16
+ * No need to fetch the scheduler or construct a message by hand.
17
+ *
18
+ * Must be called from inside a UnitOfWork (throws otherwise). The schedule
19
+ * participates in the active transaction — if the handler's UoW rolls back,
20
+ * nothing is scheduled; if it commits, the event is durably scheduled and will
21
+ * fire at or after `at` unless cancelled. Metadata defaults to the UoW
22
+ * metadata, so correlation/causation lineage carries onto the fired event.
23
+ *
24
+ * Returns a {@link ScheduleToken} — persist it (e.g. in state via an event) to
25
+ * {@link cancelSchedule} later. That is the deadline/process-manager pattern.
26
+ */
27
+ export const schedule = (async (event, payload, at, metadata) => {
28
+ const state = requireInvocationPhase(); // D-43 mutator guard
29
+ const scheduler = state.resources.get(EVENT_SCHEDULER_KEY.symbol);
30
+ if (!scheduler)
31
+ throw new Error("No event scheduler configured");
32
+ const eventMessage = {
33
+ identifier: generateIdentifier(),
34
+ name: event.name,
35
+ version: event.version,
36
+ payload,
37
+ metadata: metadata ?? state.metadata,
38
+ timestamp: Date.now(),
39
+ tags: event.tags ? event.tags(payload) : [],
40
+ };
41
+ return scheduler.schedule(eventMessage, at);
42
+ });
43
+ /**
44
+ * Convenience wrapper over {@link schedule}: fire `delayMs` milliseconds from
45
+ * now instead of at an absolute {@link Date}.
46
+ */
47
+ export const scheduleAfter = ((event, payload, delayMs, metadata) => schedule(event, payload, new Date(Date.now() + delayMs), metadata));
48
+ /**
49
+ * Attempt to cancel a previously {@link schedule}d event from inside a handler.
50
+ * UoW-aware: joins the active transaction, so cancelling then throwing does not
51
+ * leave the schedule cancelled. See {@link CancelResult} for outcomes.
52
+ */
53
+ export const cancelSchedule = async (token) => {
54
+ const state = requireInvocationPhase(); // D-43 mutator guard
55
+ const scheduler = state.resources.get(EVENT_SCHEDULER_KEY.symbol);
56
+ if (!scheduler)
57
+ throw new Error("No event scheduler configured");
58
+ return scheduler.cancel(token);
59
+ };
60
+ //# sourceMappingURL=schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../src/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAiB,WAAW,EAAoB,MAAM,mBAAmB,CAAA;AACpG,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAU9E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAgC,WAAW,CAAC,gBAAgB,CAAC,CAAA;AAa7F;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAqB,CAAC,KAAK,EAC9C,KAAyB,EACzB,OAAmB,EACnB,EAAQ,EACR,QAAmB,EACK,EAAE;IAC1B,MAAM,KAAK,GAAG,sBAAsB,EAAE,CAAA,CAAC,qBAAqB;IAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,CAA+B,CAAA;IAC/F,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IAEhE,MAAM,YAAY,GAAiB;QACjC,UAAU,EAAE,kBAAkB,EAAE;QAChC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,OAAO;QACP,QAAQ,EAAE,QAAQ,IAAI,KAAK,CAAC,QAAQ;QACpC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE;KAC5C,CAAA;IACD,OAAO,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;AAC7C,CAAC,CAAqB,CAAA;AAatB;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAA0B,CAAC,CACnD,KAA2B,EAC3B,OAAgB,EAChB,OAAe,EACf,QAAmB,EACnB,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,EAAE,QAAoB,CAAC,CAA0B,CAAA;AAE7G;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,KAAoB,EAAyB,EAAE;IAClF,MAAM,KAAK,GAAG,sBAAsB,EAAE,CAAA,CAAC,qBAAqB;IAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,CAA+B,CAAA;IAC/F,IAAI,CAAC,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;IAChE,OAAO,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAChC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kronos-ts/eventsourcing",
3
- "version": "0.1.4",
3
+ "version": "0.2.0",
4
4
  "description": "Event sourcing for Kronos — dynamic-consistency-boundary event store with load/append.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -47,12 +47,12 @@
47
47
  }
48
48
  },
49
49
  "dependencies": {
50
- "@kronos-ts/common": "0.1.0",
51
- "@kronos-ts/messaging": "0.1.0",
52
- "@kronos-ts/modelling": "0.1.0",
50
+ "@kronos-ts/common": "0.1.1",
51
+ "@kronos-ts/messaging": "0.5.0",
52
+ "@kronos-ts/modelling": "0.2.3",
53
53
  "zod": "^4.3.6"
54
54
  },
55
55
  "devDependencies": {
56
- "@kronos-ts/app": "0.1.0"
56
+ "@kronos-ts/app": "0.3.3"
57
57
  }
58
58
  }
package/src/index.ts CHANGED
@@ -64,6 +64,14 @@ export { createInterceptingEventStore } from "./intercepting-event-store.js"
64
64
 
65
65
  // Module-level handler helpers (Plan 04-01 / HDL-02 / D-42)
66
66
  export { load, STATE_MANAGER_KEY } from "./load.js"
67
+ export {
68
+ schedule,
69
+ scheduleAfter,
70
+ cancelSchedule,
71
+ EVENT_SCHEDULER_KEY,
72
+ type ScheduleFunction,
73
+ type ScheduleAfterFunction,
74
+ } from "./schedule.js"
67
75
  export {
68
76
  append,
69
77
  BUFFERED_EVENTS_KEY,
package/src/load.ts CHANGED
@@ -39,6 +39,27 @@ type StateManagerLike = {
39
39
  */
40
40
  export const STATE_MANAGER_KEY: ResourceKey<StateManagerLike> = resourceKey("stateManager")
41
41
 
42
+ /**
43
+ * Stable cache key for a state id. State ids are typically objects
44
+ * (e.g. `{ ticketId }`), and `String({...})` collapses every object to
45
+ * `"[object Object]"` — which would make two different ids of the same module
46
+ * share a cache entry within a UoW and return each other's state. Serialize
47
+ * structurally instead, with sorted keys (so id construction order is
48
+ * irrelevant) and bigint support. Primitive ids serialize to a unique string
49
+ * too, so this is strictly safer than `String(id)`.
50
+ */
51
+ function stableIdKey(id: unknown): string {
52
+ return JSON.stringify(id, (_key, value) => {
53
+ if (typeof value === "bigint") return `${value}n`
54
+ if (value && typeof value === "object" && !Array.isArray(value)) {
55
+ const sorted: Record<string, unknown> = {}
56
+ for (const k of Object.keys(value).sort()) sorted[k] = (value as Record<string, unknown>)[k]
57
+ return sorted
58
+ }
59
+ return value
60
+ })
61
+ }
62
+
42
63
  /**
43
64
  * Plan 04-01 (HDL-02 / D-42): module-level load.
44
65
  *
@@ -53,7 +74,7 @@ export const load: LoadFunction = (async <S>(module: { name: string }, id: unkno
53
74
  if (!stateManager) throw new Error("No state manager configured")
54
75
 
55
76
  const cache = computeIfAbsent(STATE_CACHE_KEY, () => new Map())
56
- const cacheKey = `${module.name}:${String(id)}`
77
+ const cacheKey = `${module.name}:${stableIdKey(id)}`
57
78
  if (!cache.has(cacheKey)) {
58
79
  cache.set(cacheKey, stateManager.load(module, id))
59
80
  const modules = computeIfAbsent(STATE_MODULES_KEY, () => new Map())
@@ -0,0 +1,102 @@
1
+ import { generateIdentifier, type Metadata, resourceKey, type ResourceKey } from "@kronos-ts/common"
2
+ import { requireInvocationPhase } from "@kronos-ts/messaging/processing-state"
3
+ import type { z } from "zod"
4
+ import type {
5
+ EventDescriptor,
6
+ EventMessage,
7
+ EventScheduler,
8
+ ScheduleToken,
9
+ CancelResult,
10
+ } from "@kronos-ts/messaging"
11
+
12
+ /**
13
+ * Resource key for the event scheduler component.
14
+ * Written by handling modules + processors at handler-invocation entry,
15
+ * exactly like {@link STATE_MANAGER_KEY} — so the {@link schedule} helper
16
+ * resolves the framework-configured scheduler from the active UnitOfWork.
17
+ */
18
+ export const EVENT_SCHEDULER_KEY: ResourceKey<EventScheduler> = resourceKey("eventScheduler")
19
+
20
+ /** Schedule an event for future append from inside a handler. */
21
+ export interface ScheduleFunction {
22
+ <P extends z.ZodType>(event: EventDescriptor<P>, payload: z.infer<P>, at: Date): Promise<ScheduleToken>
23
+ <P extends z.ZodType>(
24
+ event: EventDescriptor<P>,
25
+ payload: z.infer<P>,
26
+ at: Date,
27
+ metadata: Metadata,
28
+ ): Promise<ScheduleToken>
29
+ }
30
+
31
+ /**
32
+ * Schedule {@link event} to be appended at {@link at}.
33
+ *
34
+ * The same one-call ergonomics as {@link append}/{@link send}: pass the event
35
+ * descriptor + payload and the helper builds the {@link EventMessage} (tags,
36
+ * metadata, identifier) and hands it to the configured {@link EventScheduler}.
37
+ * No need to fetch the scheduler or construct a message by hand.
38
+ *
39
+ * Must be called from inside a UnitOfWork (throws otherwise). The schedule
40
+ * participates in the active transaction — if the handler's UoW rolls back,
41
+ * nothing is scheduled; if it commits, the event is durably scheduled and will
42
+ * fire at or after `at` unless cancelled. Metadata defaults to the UoW
43
+ * metadata, so correlation/causation lineage carries onto the fired event.
44
+ *
45
+ * Returns a {@link ScheduleToken} — persist it (e.g. in state via an event) to
46
+ * {@link cancelSchedule} later. That is the deadline/process-manager pattern.
47
+ */
48
+ export const schedule: ScheduleFunction = (async <P extends z.ZodType>(
49
+ event: EventDescriptor<P>,
50
+ payload: z.infer<P>,
51
+ at: Date,
52
+ metadata?: Metadata,
53
+ ): Promise<ScheduleToken> => {
54
+ const state = requireInvocationPhase() // D-43 mutator guard
55
+ const scheduler = state.resources.get(EVENT_SCHEDULER_KEY.symbol) as EventScheduler | undefined
56
+ if (!scheduler) throw new Error("No event scheduler configured")
57
+
58
+ const eventMessage: EventMessage = {
59
+ identifier: generateIdentifier(),
60
+ name: event.name,
61
+ version: event.version,
62
+ payload,
63
+ metadata: metadata ?? state.metadata,
64
+ timestamp: Date.now(),
65
+ tags: event.tags ? event.tags(payload) : [],
66
+ }
67
+ return scheduler.schedule(eventMessage, at)
68
+ }) as ScheduleFunction
69
+
70
+ /** Schedule an event a fixed delay from now, from inside a handler. */
71
+ export interface ScheduleAfterFunction {
72
+ <P extends z.ZodType>(event: EventDescriptor<P>, payload: z.infer<P>, delayMs: number): Promise<ScheduleToken>
73
+ <P extends z.ZodType>(
74
+ event: EventDescriptor<P>,
75
+ payload: z.infer<P>,
76
+ delayMs: number,
77
+ metadata: Metadata,
78
+ ): Promise<ScheduleToken>
79
+ }
80
+
81
+ /**
82
+ * Convenience wrapper over {@link schedule}: fire `delayMs` milliseconds from
83
+ * now instead of at an absolute {@link Date}.
84
+ */
85
+ export const scheduleAfter: ScheduleAfterFunction = ((
86
+ event: EventDescriptor<any>,
87
+ payload: unknown,
88
+ delayMs: number,
89
+ metadata?: Metadata,
90
+ ) => schedule(event, payload, new Date(Date.now() + delayMs), metadata as Metadata)) as ScheduleAfterFunction
91
+
92
+ /**
93
+ * Attempt to cancel a previously {@link schedule}d event from inside a handler.
94
+ * UoW-aware: joins the active transaction, so cancelling then throwing does not
95
+ * leave the schedule cancelled. See {@link CancelResult} for outcomes.
96
+ */
97
+ export const cancelSchedule = async (token: ScheduleToken): Promise<CancelResult> => {
98
+ const state = requireInvocationPhase() // D-43 mutator guard
99
+ const scheduler = state.resources.get(EVENT_SCHEDULER_KEY.symbol) as EventScheduler | undefined
100
+ if (!scheduler) throw new Error("No event scheduler configured")
101
+ return scheduler.cancel(token)
102
+ }