@rotorsoft/act 0.26.0 → 0.27.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
@@ -309,7 +309,7 @@ var InMemoryStream = class {
309
309
  _error = "";
310
310
  _leased_by = void 0;
311
311
  _leased_until = void 0;
312
- get is_avaliable() {
312
+ get is_available() {
313
313
  return !this._blocked && (!this._leased_until || this._leased_until <= /* @__PURE__ */ new Date());
314
314
  }
315
315
  get at() {
@@ -376,6 +376,17 @@ var InMemoryStream = class {
376
376
  };
377
377
  }
378
378
  }
379
+ /**
380
+ * Reset this stream's watermark and state for replay.
381
+ */
382
+ reset() {
383
+ this._at = -1;
384
+ this._retry = 0;
385
+ this._blocked = false;
386
+ this._error = "";
387
+ this._leased_by = void 0;
388
+ this._leased_until = void 0;
389
+ }
379
390
  };
380
391
  var InMemoryStore = class {
381
392
  // stored events
@@ -503,7 +514,7 @@ var InMemoryStore = class {
503
514
  async claim(lagging, leading, by, millis) {
504
515
  await sleep();
505
516
  const available = [...this._streams.values()].filter(
506
- (s) => s.is_avaliable && (s.at < 0 || this._events.some(
517
+ (s) => s.is_available && (s.at < 0 || this._events.some(
507
518
  (e) => e.id > s.at && e.name !== SNAP_EVENT && (!s.source || RegExp(s.source).test(e.stream))
508
519
  ))
509
520
  );
@@ -566,6 +577,24 @@ var InMemoryStore = class {
566
577
  await sleep();
567
578
  return leases.map((l) => this._streams.get(l.stream)?.block(l, l.error)).filter((l) => !!l);
568
579
  }
580
+ /**
581
+ * Reset watermarks for the given streams to -1, clearing retry, blocked,
582
+ * error, and lease state so they can be replayed from the beginning.
583
+ * @param streams - Stream names to reset.
584
+ * @returns Count of streams that were actually reset.
585
+ */
586
+ async reset(streams) {
587
+ await sleep();
588
+ let count = 0;
589
+ for (const name of streams) {
590
+ const s = this._streams.get(name);
591
+ if (s) {
592
+ s.reset();
593
+ count++;
594
+ }
595
+ }
596
+ return count;
597
+ }
569
598
  };
570
599
 
571
600
  // src/ports.ts
@@ -747,7 +776,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
747
776
  if (!stream) throw new Error("Missing target stream");
748
777
  payload = skipValidation ? payload : validate(action2, payload, me.actions[action2]);
749
778
  const snapshot = await load(me, stream);
750
- const expected = expectedVersion || snapshot.event?.version;
779
+ const expected = expectedVersion ?? snapshot.event?.version;
751
780
  logger2.trace(
752
781
  payload,
753
782
  `\u{1F535} ${stream}.${action2}${typeof expected === "number" ? `.${expected}` : ""}`
@@ -806,7 +835,7 @@ async function action(me, action2, target, payload, reactingTo, skipValidation =
806
835
  );
807
836
  } catch (error) {
808
837
  if (error.name === "ERR_CONCURRENCY") {
809
- void cache().invalidate(stream);
838
+ await cache().invalidate(stream);
810
839
  }
811
840
  throw error;
812
841
  }
@@ -1657,7 +1686,11 @@ function registerState(state2, states, actions, events) {
1657
1686
  patch: mergedPatch,
1658
1687
  on: { ...existing.on, ...state2.on },
1659
1688
  given: { ...existing.given, ...state2.given },
1660
- snap: state2.snap || existing.snap
1689
+ snap: state2.snap && existing.snap && state2.snap !== existing.snap ? (() => {
1690
+ throw new Error(
1691
+ `Duplicate snap strategy for state "${state2.name}"`
1692
+ );
1693
+ })() : state2.snap || existing.snap
1661
1694
  };
1662
1695
  states.set(state2.name, merged);
1663
1696
  for (const name of Object.keys(merged.actions)) {
@@ -1772,19 +1805,22 @@ function act(states = /* @__PURE__ */ new Map(), registry = {
1772
1805
  maxRetries: options?.maxRetries ?? 3
1773
1806
  }
1774
1807
  };
1775
- const name = handler.name || `${String(event)}_${registry.events[event].reactions.size}`;
1776
- registry.events[event].reactions.set(name, reaction);
1808
+ if (!handler.name)
1809
+ throw new Error(
1810
+ `Reaction handler for "${String(event)}" must be a named function`
1811
+ );
1812
+ registry.events[event].reactions.set(handler.name, reaction);
1777
1813
  return {
1778
1814
  ...builder,
1779
1815
  to(resolver) {
1780
- registry.events[event].reactions.set(name, {
1816
+ registry.events[event].reactions.set(handler.name, {
1781
1817
  ...reaction,
1782
1818
  resolver: typeof resolver === "string" ? { target: resolver } : resolver
1783
1819
  });
1784
1820
  return builder;
1785
1821
  },
1786
1822
  void() {
1787
- registry.events[event].reactions.set(name, {
1823
+ registry.events[event].reactions.set(handler.name, {
1788
1824
  ...reaction,
1789
1825
  resolver: _void_
1790
1826
  });
@@ -1837,20 +1873,23 @@ function _projection(target, events) {
1837
1873
  }
1838
1874
  };
1839
1875
  const register = events[event];
1840
- const name = handler.name || `${event}_${register.reactions.size}`;
1841
- register.reactions.set(name, reaction);
1876
+ if (!handler.name)
1877
+ throw new Error(
1878
+ `Projection handler for "${event}" must be a named function`
1879
+ );
1880
+ register.reactions.set(handler.name, reaction);
1842
1881
  const nextBuilder = _projection(target, events);
1843
1882
  return {
1844
1883
  ...nextBuilder,
1845
1884
  to(resolver) {
1846
- register.reactions.set(name, {
1885
+ register.reactions.set(handler.name, {
1847
1886
  ...reaction,
1848
1887
  resolver: typeof resolver === "string" ? { target: resolver } : resolver
1849
1888
  });
1850
1889
  return nextBuilder;
1851
1890
  },
1852
1891
  void() {
1853
- register.reactions.set(name, {
1892
+ register.reactions.set(handler.name, {
1854
1893
  ...reaction,
1855
1894
  resolver: _void_
1856
1895
  });
@@ -1917,19 +1956,22 @@ function slice(states = /* @__PURE__ */ new Map(), actions = {}, events = {}, pr
1917
1956
  maxRetries: options?.maxRetries ?? 3
1918
1957
  }
1919
1958
  };
1920
- const name = handler.name || `${String(event)}_${events[event].reactions.size}`;
1921
- events[event].reactions.set(name, reaction);
1959
+ if (!handler.name)
1960
+ throw new Error(
1961
+ `Reaction handler for "${String(event)}" must be a named function`
1962
+ );
1963
+ events[event].reactions.set(handler.name, reaction);
1922
1964
  return {
1923
1965
  ...builder,
1924
1966
  to(resolver) {
1925
- events[event].reactions.set(name, {
1967
+ events[event].reactions.set(handler.name, {
1926
1968
  ...reaction,
1927
1969
  resolver: typeof resolver === "string" ? { target: resolver } : resolver
1928
1970
  });
1929
1971
  return builder;
1930
1972
  },
1931
1973
  void() {
1932
- events[event].reactions.set(name, {
1974
+ events[event].reactions.set(handler.name, {
1933
1975
  ...reaction,
1934
1976
  resolver: _void_
1935
1977
  });