@rotorsoft/act 0.36.0 → 0.38.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.js CHANGED
@@ -15,6 +15,9 @@ import {
15
15
  ZodEmpty
16
16
  } from "./chunk-AGWZY6YT.js";
17
17
 
18
+ // src/ports.ts
19
+ import { AsyncLocalStorage } from "async_hooks";
20
+
18
21
  // src/adapters/console-logger.ts
19
22
  var LEVEL_VALUES = {
20
23
  fatal: 60,
@@ -803,6 +806,7 @@ var InMemoryStore = class {
803
806
  };
804
807
 
805
808
  // src/ports.ts
809
+ var scoped = new AsyncLocalStorage();
806
810
  var ExitCodes = ["ERROR", "EXIT"];
807
811
  var adapters = /* @__PURE__ */ new Map();
808
812
  function port(injector) {
@@ -822,11 +826,17 @@ var log = port(function log2(adapter) {
822
826
  pretty: cfg.env !== "production"
823
827
  });
824
828
  });
825
- var store = port(function store2(adapter) {
826
- return adapter || new InMemoryStore();
829
+ var _store = port(function store(adapter) {
830
+ return adapter ?? new InMemoryStore();
831
+ });
832
+ var store2 = ((adapter) => {
833
+ return scoped.getStore()?.store ?? _store(adapter);
827
834
  });
828
- var cache = port(function cache2(adapter) {
829
- return adapter || new InMemoryCache();
835
+ var _cache = port(function cache(adapter) {
836
+ return adapter ?? new InMemoryCache();
837
+ });
838
+ var cache2 = ((adapter) => {
839
+ return scoped.getStore()?.cache ?? _cache(adapter);
830
840
  });
831
841
  var disposers = [];
832
842
  async function disposeAndExit(code = "EXIT") {
@@ -956,7 +966,7 @@ async function scanStreamHeads(streams) {
956
966
  let maxId = -1;
957
967
  let version = -1;
958
968
  let lastEventName = "";
959
- await store().query(
969
+ await store2().query(
960
970
  (e) => {
961
971
  if (e.name === TOMBSTONE_EVENT || maxId !== -1) return;
962
972
  maxId = e.id;
@@ -973,7 +983,7 @@ async function scanStreamHeads(streams) {
973
983
  async function partitionBySafety(streamInfo, reactiveEventsSize, skipped) {
974
984
  if (reactiveEventsSize === 0) return [...streamInfo.keys()];
975
985
  const pendingSet = /* @__PURE__ */ new Set();
976
- await store().query_streams((position) => {
986
+ await store2().query_streams((position) => {
977
987
  const sourceRe = position.source ? RegExp(position.source) : void 0;
978
988
  for (const [stream, info] of streamInfo) {
979
989
  if ((!sourceRe || sourceRe.test(stream)) && position.at < info.maxId) {
@@ -1044,13 +1054,13 @@ async function truncateAndWarmCache(guarded, seedStates, guardEvents, correlatio
1044
1054
  }
1045
1055
  };
1046
1056
  });
1047
- const truncated = await store().truncate(truncTargets);
1057
+ const truncated = await store2().truncate(truncTargets);
1048
1058
  await Promise.all(
1049
1059
  guarded.map(async (stream) => {
1050
1060
  const entry = truncated.get(stream);
1051
1061
  const state2 = seedStates.get(stream);
1052
1062
  if (state2 && entry) {
1053
- await cache().set(stream, {
1063
+ await cache2().set(stream, {
1054
1064
  state: state2,
1055
1065
  version: entry.committed.version,
1056
1066
  event_id: entry.committed.id,
@@ -1058,7 +1068,7 @@ async function truncateAndWarmCache(guarded, seedStates, guardEvents, correlatio
1058
1068
  snaps: 1
1059
1069
  });
1060
1070
  } else {
1061
- await cache().invalidate(stream);
1071
+ await cache2().invalidate(stream);
1062
1072
  }
1063
1073
  })
1064
1074
  );
@@ -1093,7 +1103,7 @@ var CorrelateCycle = class {
1093
1103
  async init() {
1094
1104
  if (this._initialized) return;
1095
1105
  this._initialized = true;
1096
- const { watermark } = await store().subscribe([...this.staticTargets]);
1106
+ const { watermark } = await store2().subscribe([...this.staticTargets]);
1097
1107
  this._checkpoint = watermark;
1098
1108
  this.onInit?.();
1099
1109
  for (const { stream } of this.staticTargets) {
@@ -1112,7 +1122,7 @@ var CorrelateCycle = class {
1112
1122
  const after = Math.max(this._checkpoint, query.after || -1);
1113
1123
  const correlated = /* @__PURE__ */ new Map();
1114
1124
  let last_id = after;
1115
- await store().query(
1125
+ await store2().query(
1116
1126
  (event) => {
1117
1127
  last_id = event.id;
1118
1128
  const register = this.registry.events[event.name];
@@ -1317,6 +1327,43 @@ var DrainController = class {
1317
1327
  }
1318
1328
  };
1319
1329
 
1330
+ // src/internal/event-versions.ts
1331
+ var VERSION_SUFFIX = /^(.+?)_v(\d+)$/;
1332
+ function parse(name) {
1333
+ const m = name.match(VERSION_SUFFIX);
1334
+ if (m) {
1335
+ const v = Number.parseInt(m[2], 10);
1336
+ if (v >= 2) return { base: m[1], version: v };
1337
+ }
1338
+ return { base: name, version: 1 };
1339
+ }
1340
+ function deprecatedEventNames(names) {
1341
+ const groups = /* @__PURE__ */ new Map();
1342
+ for (const name of names) {
1343
+ const { base, version } = parse(name);
1344
+ const list = groups.get(base);
1345
+ if (list) list.push({ version, name });
1346
+ else groups.set(base, [{ version, name }]);
1347
+ }
1348
+ const deprecated = /* @__PURE__ */ new Set();
1349
+ for (const list of groups.values()) {
1350
+ if (list.length < 2) continue;
1351
+ list.sort((a, b) => b.version - a.version);
1352
+ for (let i = 1; i < list.length; i++) deprecated.add(list[i].name);
1353
+ }
1354
+ return deprecated;
1355
+ }
1356
+ function currentVersionOf(deprecatedName, allNames) {
1357
+ const target = parse(deprecatedName);
1358
+ let highest;
1359
+ for (const name of allNames) {
1360
+ const { base, version } = parse(name);
1361
+ if (base !== target.base) continue;
1362
+ if (!highest || version > highest.version) highest = { version, name };
1363
+ }
1364
+ return highest && highest.version > target.version ? highest.name : void 0;
1365
+ }
1366
+
1320
1367
  // src/internal/merge.ts
1321
1368
  import { ZodObject } from "zod";
1322
1369
  function baseTypeName(zodType) {
@@ -1595,12 +1642,12 @@ var SettleLoop = class {
1595
1642
  };
1596
1643
 
1597
1644
  // src/internal/drain.ts
1598
- var claim = (lagging, leading, by, millis) => store().claim(lagging, leading, by, millis);
1645
+ var claim = (lagging, leading, by, millis) => store2().claim(lagging, leading, by, millis);
1599
1646
  async function fetch(leased, eventLimit) {
1600
1647
  return Promise.all(
1601
1648
  leased.map(async ({ stream, source, at, lagging }) => {
1602
1649
  const events = [];
1603
- await store().query((e) => events.push(e), {
1650
+ await store2().query((e) => events.push(e), {
1604
1651
  stream: source,
1605
1652
  after: at,
1606
1653
  limit: eventLimit
@@ -1609,9 +1656,9 @@ async function fetch(leased, eventLimit) {
1609
1656
  })
1610
1657
  );
1611
1658
  }
1612
- var ack = (leases) => store().ack(leases);
1613
- var block = (leases) => store().block(leases);
1614
- var subscribe = (streams) => store().subscribe(streams);
1659
+ var ack = (leases) => store2().ack(leases);
1660
+ var block = (leases) => store2().block(leases);
1661
+ var subscribe = (streams) => store2().subscribe(streams);
1615
1662
 
1616
1663
  // src/internal/event-sourcing.ts
1617
1664
  import { randomUUID as randomUUID3 } from "crypto";
@@ -1619,7 +1666,7 @@ import { patch } from "@rotorsoft/act-patch";
1619
1666
  async function snap(snapshot) {
1620
1667
  try {
1621
1668
  const { id, stream, name, meta, version } = snapshot.event;
1622
- await store().commit(
1669
+ await store2().commit(
1623
1670
  stream,
1624
1671
  [{ name: SNAP_EVENT, data: snapshot.state }],
1625
1672
  {
@@ -1635,7 +1682,7 @@ async function snap(snapshot) {
1635
1682
  }
1636
1683
  async function tombstone(stream, expectedVersion, correlation) {
1637
1684
  try {
1638
- const [committed] = await store().commit(
1685
+ const [committed] = await store2().commit(
1639
1686
  stream,
1640
1687
  [{ name: TOMBSTONE_EVENT, data: {} }],
1641
1688
  { correlation, causation: {} },
@@ -1649,7 +1696,7 @@ async function tombstone(stream, expectedVersion, correlation) {
1649
1696
  }
1650
1697
  async function load(me, stream, callback, asOf) {
1651
1698
  const timeTravel = !!asOf && Object.values(asOf).some((v) => v !== void 0);
1652
- const cached = timeTravel ? void 0 : await cache().get(stream);
1699
+ const cached = timeTravel ? void 0 : await cache2().get(stream);
1653
1700
  const cache_hit = !!cached;
1654
1701
  let state2 = cached?.state ?? (me.init ? me.init() : {});
1655
1702
  let patches = cached?.patches ?? 0;
@@ -1657,7 +1704,7 @@ async function load(me, stream, callback, asOf) {
1657
1704
  let version = cached?.version ?? -1;
1658
1705
  let replayed = 0;
1659
1706
  let event;
1660
- await store().query(
1707
+ await store2().query(
1661
1708
  (e) => {
1662
1709
  event = e;
1663
1710
  version = e.version;
@@ -1692,7 +1739,7 @@ async function load(me, stream, callback, asOf) {
1692
1739
  }
1693
1740
  );
1694
1741
  if (replayed > 0 && !timeTravel && event) {
1695
- await cache().set(stream, {
1742
+ await cache2().set(stream, {
1696
1743
  state: state2,
1697
1744
  version,
1698
1745
  event_id: event.id,
@@ -1729,6 +1776,20 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1729
1776
  return [snapshot];
1730
1777
  }
1731
1778
  const tuples = Array.isArray(result[0]) ? result : [result];
1779
+ const deprecated = me._deprecated;
1780
+ if (deprecated && deprecated.size > 0) {
1781
+ const me_ = me;
1782
+ const warned = me_._warned ?? (me_._warned = /* @__PURE__ */ new Set());
1783
+ for (const [name] of tuples) {
1784
+ const evt = name;
1785
+ if (deprecated.has(evt) && !warned.has(evt)) {
1786
+ warned.add(evt);
1787
+ log().warn(
1788
+ `Action "${String(action2)}" emitted deprecated event "${evt}". A newer version exists in the registry \u2014 update the action's .emit() to target the current version. (warned once per process)`
1789
+ );
1790
+ }
1791
+ }
1792
+ }
1732
1793
  const emitted = tuples.map(([name, data]) => ({
1733
1794
  name,
1734
1795
  data: skipValidation ? data : validate(name, data, me.events[name])
@@ -1751,7 +1812,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1751
1812
  };
1752
1813
  let committed;
1753
1814
  try {
1754
- committed = await store().commit(
1815
+ committed = await store2().commit(
1755
1816
  stream,
1756
1817
  emitted,
1757
1818
  meta,
@@ -1763,7 +1824,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1763
1824
  );
1764
1825
  } catch (error) {
1765
1826
  if (error instanceof ConcurrencyError) {
1766
- await cache().invalidate(stream);
1827
+ await cache2().invalidate(stream);
1767
1828
  }
1768
1829
  throw error;
1769
1830
  }
@@ -1785,7 +1846,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
1785
1846
  });
1786
1847
  const last = snapshots.at(-1);
1787
1848
  const snapped = me.snap?.(last);
1788
- cache().set(stream, {
1849
+ cache2().set(stream, {
1789
1850
  state: last.state,
1790
1851
  version: last.event.version,
1791
1852
  event_id: last.event.id,
@@ -1980,6 +2041,7 @@ var Act = class {
1980
2041
  this.registry = registry;
1981
2042
  this._states = _states;
1982
2043
  this._batch_handlers = batchHandlers;
2044
+ this._scoped = options.scoped ? (fn) => scoped.run(options.scoped, fn) : (fn) => fn();
1983
2045
  this._es = buildEs(this._logger);
1984
2046
  this._cd = buildDrain(this._logger);
1985
2047
  this._handle = buildHandle({
@@ -2025,7 +2087,7 @@ var Act = class {
2025
2087
  },
2026
2088
  options.settleDebounceMs ?? DEFAULT_SETTLE_DEBOUNCE_MS
2027
2089
  );
2028
- this._notify_disposer = this._wireNotify();
2090
+ this._notify_disposer = this._wireNotify(options.scoped?.store ?? store2());
2029
2091
  dispose(async () => {
2030
2092
  this._emitter.removeAllListeners();
2031
2093
  this.stop_correlations();
@@ -2094,6 +2156,11 @@ var Act = class {
2094
2156
  _event_to_state;
2095
2157
  /** Logger resolved at construction time (after user port configuration) */
2096
2158
  _logger = log();
2159
+ /** Wraps a public-method body so internal `store()`/`cache()` resolve to the
2160
+ * per-Act ports (ACT-501). No-op when the Act is unscoped — so the singleton
2161
+ * path keeps reading fresh `store()`/`cache()` per call, which matters for
2162
+ * tests that dispose and re-seed mid-suite. */
2163
+ _scoped;
2097
2164
  /** Pre-bound IAct methods reused across drain cycles. Only `do` varies per
2098
2165
  * payload (it captures the triggering event for reactingTo auto-inject). */
2099
2166
  _bound_do = this.do.bind(this);
@@ -2109,9 +2176,8 @@ var Act = class {
2109
2176
  * subscription was made). Errors during subscription are logged but
2110
2177
  * never thrown — `notify` is a hint, not a contract.
2111
2178
  */
2112
- async _wireNotify() {
2179
+ async _wireNotify(s) {
2113
2180
  if (this._reactive_events.size === 0) return void 0;
2114
- const s = store();
2115
2181
  if (!s.notify) return void 0;
2116
2182
  try {
2117
2183
  return await s.notify((notification) => {
@@ -2215,35 +2281,39 @@ var Act = class {
2215
2281
  * @see {@link ValidationError}, {@link InvariantError}, {@link ConcurrencyError}
2216
2282
  */
2217
2283
  async do(action2, target, payload, reactingTo, skipValidation = false) {
2218
- const snapshots = await this._es.action(
2219
- this.registry.actions[action2],
2220
- action2,
2221
- target,
2222
- payload,
2223
- reactingTo,
2224
- skipValidation
2225
- );
2226
- if (this._reactive_events.size > 0) {
2227
- for (const snap2 of snapshots) {
2228
- if (snap2.event?.name && this._reactive_events.has(snap2.event.name)) {
2229
- this._drain.arm();
2230
- break;
2284
+ return this._scoped(async () => {
2285
+ const snapshots = await this._es.action(
2286
+ this.registry.actions[action2],
2287
+ action2,
2288
+ target,
2289
+ payload,
2290
+ reactingTo,
2291
+ skipValidation
2292
+ );
2293
+ if (this._reactive_events.size > 0) {
2294
+ for (const snap2 of snapshots) {
2295
+ if (snap2.event?.name && this._reactive_events.has(snap2.event.name)) {
2296
+ this._drain.arm();
2297
+ break;
2298
+ }
2231
2299
  }
2232
2300
  }
2233
- }
2234
- this.emit("committed", snapshots);
2235
- return snapshots;
2301
+ this.emit("committed", snapshots);
2302
+ return snapshots;
2303
+ });
2236
2304
  }
2237
2305
  async load(stateOrName, stream, callback, asOf) {
2238
- let merged;
2239
- if (typeof stateOrName === "string") {
2240
- const found = this._states.get(stateOrName);
2241
- if (!found) throw new Error(`State "${stateOrName}" not found`);
2242
- merged = found;
2243
- } else {
2244
- merged = this._states.get(stateOrName.name) || stateOrName;
2245
- }
2246
- return await this._es.load(merged, stream, callback, asOf);
2306
+ return this._scoped(async () => {
2307
+ let merged;
2308
+ if (typeof stateOrName === "string") {
2309
+ const found = this._states.get(stateOrName);
2310
+ if (!found) throw new Error(`State "${stateOrName}" not found`);
2311
+ merged = found;
2312
+ } else {
2313
+ merged = this._states.get(stateOrName.name) || stateOrName;
2314
+ }
2315
+ return await this._es.load(merged, stream, callback, asOf);
2316
+ });
2247
2317
  }
2248
2318
  /**
2249
2319
  * Queries the event store for events matching a filter.
@@ -2292,14 +2362,16 @@ var Act = class {
2292
2362
  * @see {@link query_array} for loading events into memory
2293
2363
  */
2294
2364
  async query(query, callback) {
2295
- let first;
2296
- let last;
2297
- const count = await store().query((e) => {
2298
- if (!first) first = e;
2299
- last = e;
2300
- callback?.(e);
2301
- }, query);
2302
- return { first, last, count };
2365
+ return this._scoped(async () => {
2366
+ let first;
2367
+ let last;
2368
+ const count = await store2().query((e) => {
2369
+ if (!first) first = e;
2370
+ last = e;
2371
+ callback?.(e);
2372
+ }, query);
2373
+ return { first, last, count };
2374
+ });
2303
2375
  }
2304
2376
  /**
2305
2377
  * Queries the event store and returns all matching events in memory.
@@ -2328,9 +2400,11 @@ var Act = class {
2328
2400
  * @see {@link query} for large result sets
2329
2401
  */
2330
2402
  async query_array(query) {
2331
- const events = [];
2332
- await store().query((e) => events.push(e), query);
2333
- return events;
2403
+ return this._scoped(async () => {
2404
+ const events = [];
2405
+ await store2().query((e) => events.push(e), query);
2406
+ return events;
2407
+ });
2334
2408
  }
2335
2409
  /**
2336
2410
  * Processes pending reactions by draining uncommitted events from the event store.
@@ -2370,7 +2444,7 @@ var Act = class {
2370
2444
  * @see {@link start_correlations} for automatic correlation
2371
2445
  */
2372
2446
  async drain(options = {}) {
2373
- return this._drain.drain(options);
2447
+ return this._scoped(() => this._drain.drain(options));
2374
2448
  }
2375
2449
  /**
2376
2450
  * Discovers and registers new streams dynamically based on reaction resolvers.
@@ -2418,7 +2492,7 @@ var Act = class {
2418
2492
  * @see {@link stop_correlations} to stop automatic correlation
2419
2493
  */
2420
2494
  async correlate(query = { after: -1, limit: 10 }) {
2421
- return this._correlate.correlate(query);
2495
+ return this._scoped(() => this._correlate.correlate(query));
2422
2496
  }
2423
2497
  /**
2424
2498
  * Starts automatic periodic correlation worker for discovering new streams.
@@ -2539,9 +2613,11 @@ var Act = class {
2539
2613
  * @see {@link settle} for the debounced full-catch-up loop
2540
2614
  */
2541
2615
  async reset(streams) {
2542
- const count = await store().reset(streams);
2543
- if (count > 0 && this._reactive_events.size > 0) this._drain.arm();
2544
- return count;
2616
+ return this._scoped(async () => {
2617
+ const count = await store2().reset(streams);
2618
+ if (count > 0 && this._reactive_events.size > 0) this._drain.arm();
2619
+ return count;
2620
+ });
2545
2621
  }
2546
2622
  /**
2547
2623
  * Bulk-update scheduling priority for streams matching `filter`.
@@ -2582,7 +2658,7 @@ var Act = class {
2582
2658
  * @see {@link claim} for how priority biases scheduling
2583
2659
  */
2584
2660
  async prioritize(filter, priority) {
2585
- return store().prioritize(filter, priority);
2661
+ return this._scoped(() => store2().prioritize(filter, priority));
2586
2662
  }
2587
2663
  /**
2588
2664
  * Close the books — guard, archive, truncate, and optionally restart streams.
@@ -2619,16 +2695,18 @@ var Act = class {
2619
2695
  */
2620
2696
  async close(targets) {
2621
2697
  if (!targets.length) return { truncated: /* @__PURE__ */ new Map(), skipped: [] };
2622
- await this.correlate({ limit: 1e3 });
2623
- const result = await runCloseCycle(targets, {
2624
- reactiveEventsSize: this._reactive_events.size,
2625
- eventToState: this._event_to_state,
2626
- load: this._es.load,
2627
- tombstone: this._es.tombstone,
2628
- logger: this._logger
2698
+ return this._scoped(async () => {
2699
+ await this.correlate({ limit: 1e3 });
2700
+ const result = await runCloseCycle(targets, {
2701
+ reactiveEventsSize: this._reactive_events.size,
2702
+ eventToState: this._event_to_state,
2703
+ load: this._es.load,
2704
+ tombstone: this._es.tombstone,
2705
+ logger: this._logger
2706
+ });
2707
+ this.emit("closed", result);
2708
+ return result;
2629
2709
  });
2630
- this.emit("closed", result);
2631
- return result;
2632
2710
  }
2633
2711
  /**
2634
2712
  * Debounced, non-blocking correlate→drain cycle.
@@ -2682,6 +2760,41 @@ function act() {
2682
2760
  };
2683
2761
  const pendingProjections = [];
2684
2762
  const batchHandlers = /* @__PURE__ */ new Map();
2763
+ let _built = false;
2764
+ const finalizeDeprecations = () => {
2765
+ const deprecationSummary = [];
2766
+ for (const state2 of states.values()) {
2767
+ const eventNames = Object.keys(state2.events);
2768
+ const deprecated = deprecatedEventNames(eventNames);
2769
+ if (deprecated.size === 0) continue;
2770
+ state2._deprecated = deprecated;
2771
+ for (const name of deprecated) {
2772
+ const current = currentVersionOf(name, eventNames);
2773
+ deprecationSummary.push({
2774
+ stateName: state2.name,
2775
+ deprecated: name,
2776
+ current
2777
+ });
2778
+ }
2779
+ for (const [actionName, handler] of Object.entries(state2.on)) {
2780
+ const staticTarget = handler?._staticEmit;
2781
+ if (staticTarget && deprecated.has(staticTarget)) {
2782
+ const current = currentVersionOf(staticTarget, eventNames);
2783
+ throw new Error(
2784
+ `Action "${actionName}" in state "${state2.name}" emits deprecated event "${staticTarget}". A newer version exists: "${current}". Update the .emit() call to target the current version. The reducer (.patch) for "${staticTarget}" stays as-is \u2014 historical events still need it.`
2785
+ );
2786
+ }
2787
+ }
2788
+ }
2789
+ if (deprecationSummary.length > 0) {
2790
+ const list = deprecationSummary.map(
2791
+ (d) => `"${d.deprecated}" (current: "${d.current}", state: "${d.stateName}")`
2792
+ ).join(", ");
2793
+ log().info(
2794
+ `Act registered ${deprecationSummary.length} deprecated event(s): ${list}. These are legacy versions kept for the read path. Consider truncating closed streams via app.close() when feasible to reduce historical event load. See docs/docs/architecture/event-schema-evolution.md.`
2795
+ );
2796
+ }
2797
+ };
2685
2798
  const builder = {
2686
2799
  withState: (state2) => {
2687
2800
  registerState(state2, states, registry.actions, registry.events);
@@ -2725,9 +2838,13 @@ function act() {
2725
2838
  }
2726
2839
  }),
2727
2840
  build: (options) => {
2728
- for (const proj of pendingProjections) {
2729
- mergeProjection(proj, registry.events);
2730
- registerBatchHandler(proj, batchHandlers);
2841
+ if (!_built) {
2842
+ for (const proj of pendingProjections) {
2843
+ mergeProjection(proj, registry.events);
2844
+ registerBatchHandler(proj, batchHandlers);
2845
+ }
2846
+ finalizeDeprecations();
2847
+ _built = true;
2731
2848
  }
2732
2849
  return new Act(
2733
2850
  registry,
@@ -2915,10 +3032,10 @@ function action_builder(state2) {
2915
3032
  function emit(handler) {
2916
3033
  if (typeof handler === "string") {
2917
3034
  const eventName = handler;
2918
- internal.on[action2] = (payload) => [
2919
- eventName,
2920
- payload
2921
- ];
3035
+ const emitFn = Object.assign((payload) => [eventName, payload], {
3036
+ _staticEmit: eventName
3037
+ });
3038
+ internal.on[action2] = emitFn;
2922
3039
  } else {
2923
3040
  internal.on[action2] = handler;
2924
3041
  }
@@ -2962,7 +3079,7 @@ export {
2962
3079
  ValidationError,
2963
3080
  ZodEmpty,
2964
3081
  act,
2965
- cache,
3082
+ cache2 as cache,
2966
3083
  config,
2967
3084
  dispose,
2968
3085
  disposeAndExit,
@@ -2970,10 +3087,11 @@ export {
2970
3087
  log,
2971
3088
  port,
2972
3089
  projection,
3090
+ scoped,
2973
3091
  sleep,
2974
3092
  slice,
2975
3093
  state,
2976
- store,
3094
+ store2 as store,
2977
3095
  validate
2978
3096
  };
2979
3097
  //# sourceMappingURL=index.js.map