@rotorsoft/act 1.32.21 → 1.32.23

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 (33) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/@types/act.d.ts +1 -2
  3. package/dist/@types/act.d.ts.map +1 -1
  4. package/dist/@types/adapters/in-memory-store.d.ts +18 -16
  5. package/dist/@types/adapters/in-memory-store.d.ts.map +1 -1
  6. package/dist/@types/builders/act-builder.d.ts.map +1 -1
  7. package/dist/@types/internal/audit.d.ts +1 -4
  8. package/dist/@types/internal/audit.d.ts.map +1 -1
  9. package/dist/@types/internal/config.d.ts +3 -9
  10. package/dist/@types/internal/config.d.ts.map +1 -1
  11. package/dist/@types/internal/correlate-cycle.d.ts +1 -11
  12. package/dist/@types/internal/correlate-cycle.d.ts.map +1 -1
  13. package/dist/@types/internal/defer-timer.d.ts +0 -5
  14. package/dist/@types/internal/defer-timer.d.ts.map +1 -1
  15. package/dist/@types/internal/drain-cycle.d.ts +3 -5
  16. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  17. package/dist/@types/internal/index.d.ts +1 -1
  18. package/dist/@types/internal/index.d.ts.map +1 -1
  19. package/dist/@types/types/ports.d.ts +10 -10
  20. package/dist/@types/types/ports.d.ts.map +1 -1
  21. package/dist/@types/utils.d.ts +3 -2
  22. package/dist/@types/utils.d.ts.map +1 -1
  23. package/dist/{chunk-QOSQI3CA.js → chunk-OG5O36AJ.js} +50 -141
  24. package/dist/chunk-OG5O36AJ.js.map +1 -0
  25. package/dist/index.cjs +75 -191
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.js +27 -52
  28. package/dist/index.js.map +1 -1
  29. package/dist/test/index.cjs +49 -140
  30. package/dist/test/index.cjs.map +1 -1
  31. package/dist/test/index.js +1 -1
  32. package/package.json +1 -1
  33. package/dist/chunk-QOSQI3CA.js.map +0 -1
@@ -478,8 +478,7 @@ var InMemoryStream = class {
478
478
  // in-process backoff, this is durable store state shared across workers.
479
479
  _deferred_at = void 0;
480
480
  // Work mark: highest event id observed to resolve to this target.
481
- // `undefined` means UNKNOWN — the row predates the mark, so `claim` falls
482
- // back to the legacy has-work probe rather than treating it as "no work".
481
+ // `undefined` means the row was never correlated, so `claim` skips it.
483
482
  _correlated_at = void 0;
484
483
  constructor(stream, source, priority = 0, lane = DEFAULT_LANE) {
485
484
  this.stream = stream;
@@ -682,12 +681,6 @@ var InMemoryStore = class {
682
681
  _correlators = /* @__PURE__ */ new Map();
683
682
  // last committed version per stream — O(1) replacement for filter-on-commit
684
683
  _stream_versions = /* @__PURE__ */ new Map();
685
- // max non-snapshot event id per stream — drives the has-work probe in
686
- // claim(): an O(1) lookup for a literal source, and the per-stream max
687
- // that a pattern source scans, without touching the full event log.
688
- _max_event_id_by_stream = /* @__PURE__ */ new Map();
689
- // global max non-snapshot event id — fast pre-check for source-less streams in claim()
690
- _max_non_snap_event_id = -1;
691
684
  // stream → (event_id → cloned sensitive payload). Two-level so `forget_pii`
692
685
  // is O(1) — drop the inner Map for the stream and the wipe is done — mirroring
693
686
  // the `DELETE WHERE stream = ?` scope that durable adapters get from their
@@ -699,10 +692,17 @@ var InMemoryStore = class {
699
692
  this._next_id = 0;
700
693
  this._correlated_at = -1;
701
694
  this._stream_versions.clear();
702
- this._max_event_id_by_stream.clear();
703
- this._max_non_snap_event_id = -1;
704
695
  this._pii.clear();
705
696
  }
697
+ // Stores a cloned copy, so caller-side mutation can't reach it.
698
+ _put_pii(stream, id, pii) {
699
+ let per_stream = this._pii.get(stream);
700
+ if (!per_stream) {
701
+ per_stream = /* @__PURE__ */ new Map();
702
+ this._pii.set(stream, per_stream);
703
+ }
704
+ per_stream.set(id, structuredClone(pii));
705
+ }
706
706
  // First index whose event id is greater than `after`. `_events` stays
707
707
  // sorted ascending by id (append-only commits; deletions preserve
708
708
  // order), so id-bounded scans binary-search their start instead of
@@ -822,7 +822,6 @@ var InMemoryStore = class {
822
822
  );
823
823
  }
824
824
  let version = current_version + 1;
825
- let last_non_snap_id = -1;
826
825
  const committed = msgs.map(({ name, data, pii }) => {
827
826
  const c = {
828
827
  id: this._next_id++,
@@ -834,23 +833,11 @@ var InMemoryStore = class {
834
833
  meta
835
834
  };
836
835
  this._events.push(c);
837
- if (pii != null) {
838
- let per_stream = this._pii.get(stream);
839
- if (!per_stream) {
840
- per_stream = /* @__PURE__ */ new Map();
841
- this._pii.set(stream, per_stream);
842
- }
843
- per_stream.set(c.id, structuredClone(pii));
844
- }
845
- if (name !== SNAP_EVENT) last_non_snap_id = c.id;
836
+ if (pii != null) this._put_pii(stream, c.id, pii);
846
837
  version++;
847
838
  return this._with_pii(c);
848
839
  });
849
840
  this._stream_versions.set(stream, version - 1);
850
- if (last_non_snap_id >= 0) {
851
- this._max_event_id_by_stream.set(stream, last_non_snap_id);
852
- this._max_non_snap_event_id = last_non_snap_id;
853
- }
854
841
  return committed;
855
842
  }
856
843
  /**
@@ -992,25 +979,19 @@ var InMemoryStore = class {
992
979
  */
993
980
  async defer(input, deferred_at) {
994
981
  await sleep();
995
- let count = 0;
996
- if (Array.isArray(input)) {
997
- for (const name of new Set(input)) {
998
- const s = this._streams.get(name);
999
- if (s) {
1000
- s.defer(deferred_at);
1001
- count++;
1002
- }
1003
- }
1004
- } else {
1005
- const matches = this._filter_predicate(input);
1006
- for (const s of this._streams.values()) {
1007
- if (matches(s)) {
1008
- s.defer(deferred_at);
1009
- count++;
1010
- }
1011
- }
1012
- }
1013
- return count;
982
+ const selected = this._select(input);
983
+ for (const s of selected) s.defer(deferred_at);
984
+ return selected.length;
985
+ }
986
+ /**
987
+ * The streams named by `input`: an explicit list (de-duplicated, so a
988
+ * repeated name counts once, matching the SQL adapters' set-based
989
+ * `stream = ANY(...)`; unknown names are skipped) or a {@link StreamFilter}.
990
+ */
991
+ _select(input) {
992
+ if (Array.isArray(input))
993
+ return [...new Set(input)].map((name) => this._streams.get(name)).filter((s) => s !== void 0);
994
+ return [...this._streams.values()].filter(this._filter_predicate(input));
1014
995
  }
1015
996
  /**
1016
997
  * Build a predicate from a {@link StreamFilter}. Compiled regexes are
@@ -1046,37 +1027,10 @@ var InMemoryStore = class {
1046
1027
  */
1047
1028
  async reset(input) {
1048
1029
  await sleep();
1049
- let count = 0;
1050
- if (Array.isArray(input)) {
1051
- for (const name of new Set(input)) {
1052
- const s = this._streams.get(name);
1053
- if (s) {
1054
- s.reset();
1055
- count++;
1056
- }
1057
- }
1058
- } else {
1059
- const matches = this._filter_predicate(input);
1060
- for (const s of this._streams.values()) {
1061
- if (matches(s)) {
1062
- s.reset();
1063
- count++;
1064
- }
1065
- }
1066
- }
1067
- return count;
1030
+ const selected = this._select(input);
1031
+ for (const s of selected) s.reset();
1032
+ return selected.length;
1068
1033
  }
1069
- /**
1070
- * Clear the blocked flag (and retry / error / lease) on the matched
1071
- * streams without touching the watermark. Streams that aren't blocked
1072
- * at call time are silently skipped. Accepts either an explicit list
1073
- * of names or a {@link StreamFilter}. The filter form always restricts
1074
- * to blocked streams — passing `blocked: false` matches nothing.
1075
- * See {@link Store.unblock}.
1076
- *
1077
- * @param input - Stream names or a filter selecting the streams to unblock.
1078
- * @returns Count of streams that were actually flipped (were blocked).
1079
- */
1080
1034
  /**
1081
1035
  * Wipe the sensitive-data payload for every event on the stream — see
1082
1036
  * {@link Store.forget_pii}. O(1) drop of the stream's inner Map; the size of
@@ -1092,21 +1046,23 @@ var InMemoryStore = class {
1092
1046
  this._pii.delete(stream);
1093
1047
  return count;
1094
1048
  }
1049
+ /**
1050
+ * Clear the blocked flag (and retry / error / lease) on the matched
1051
+ * streams without touching the watermark. Streams that aren't blocked
1052
+ * at call time are silently skipped. Accepts either an explicit list
1053
+ * of names or a {@link StreamFilter}. The filter form always restricts
1054
+ * to blocked streams — passing `blocked: false` matches nothing.
1055
+ * See {@link Store.unblock}.
1056
+ *
1057
+ * @param input - Stream names or a filter selecting the streams to unblock.
1058
+ * @returns Count of streams that were actually flipped (were blocked).
1059
+ */
1095
1060
  async unblock(input) {
1096
1061
  await sleep();
1097
- let count = 0;
1098
- if (Array.isArray(input)) {
1099
- for (const name of input) {
1100
- const s = this._streams.get(name);
1101
- if (s?.unblock()) count++;
1102
- }
1103
- } else {
1104
- const matches = this._filter_predicate({ ...input, blocked: true });
1105
- for (const s of this._streams.values()) {
1106
- if (matches(s) && s.unblock()) count++;
1107
- }
1108
- }
1109
- return count;
1062
+ const selected = this._select(
1063
+ Array.isArray(input) ? input : { ...input, blocked: true }
1064
+ );
1065
+ return selected.filter((s) => s.unblock()).length;
1110
1066
  }
1111
1067
  /**
1112
1068
  * Bulk-update priority of streams matching `filter`. Mirrors
@@ -1119,16 +1075,9 @@ var InMemoryStore = class {
1119
1075
  */
1120
1076
  async prioritize(filter, priority) {
1121
1077
  await sleep();
1122
- const matches = this._filter_predicate(filter);
1123
- let count = 0;
1124
- for (const s of this._streams.values()) {
1125
- if (!matches(s)) continue;
1126
- if (s.priority !== priority) {
1127
- s.set_priority(priority);
1128
- count++;
1129
- }
1130
- }
1131
- return count;
1078
+ const changed = this._select(filter).filter((s) => s.priority !== priority);
1079
+ for (const s of changed) s.set_priority(priority);
1080
+ return changed.length;
1132
1081
  }
1133
1082
  /**
1134
1083
  * Streams registered subscription positions to the callback, ordered by
@@ -1139,10 +1088,8 @@ var InMemoryStore = class {
1139
1088
  await sleep();
1140
1089
  const limit = query?.limit ?? 100;
1141
1090
  const after = query?.after;
1142
- const blocked = query?.blocked;
1143
1091
  const source_matches = query?.source_matches;
1144
- const stream_re = query?.stream !== void 0 && !query.stream_exact ? new RegExp(query.stream) : void 0;
1145
- const source_re = query?.source !== void 0 && !query.source_exact ? new RegExp(query.source) : void 0;
1092
+ const matches = this._filter_predicate(query ?? {});
1146
1093
  const reverse_cache = /* @__PURE__ */ new Map();
1147
1094
  const reverse_match = (source) => {
1148
1095
  let re = reverse_cache.get(source);
@@ -1156,20 +1103,10 @@ var InMemoryStore = class {
1156
1103
  let count = 0;
1157
1104
  for (const s of sorted) {
1158
1105
  if (after !== void 0 && s.stream <= after) continue;
1159
- if (query?.stream !== void 0) {
1160
- if (query.stream_exact ? s.stream !== query.stream : !stream_re.test(s.stream))
1161
- continue;
1162
- }
1163
- if (query?.source !== void 0) {
1164
- if (s.source === void 0) continue;
1165
- if (query.source_exact ? s.source !== query.source : !source_re.test(s.source))
1166
- continue;
1167
- }
1106
+ if (!matches(s)) continue;
1168
1107
  if (source_matches !== void 0) {
1169
1108
  if (s.source && !reverse_match(s.source)) continue;
1170
1109
  }
1171
- if (blocked !== void 0 && s.blocked !== blocked) continue;
1172
- if (query?.lane !== void 0 && s.lane !== query.lane) continue;
1173
1110
  if (count >= limit) break;
1174
1111
  callback({
1175
1112
  stream: s.stream,
@@ -1200,10 +1137,7 @@ var InMemoryStore = class {
1200
1137
  * Scope rules:
1201
1138
  * - Array `input` — explicit stream names, regardless of subscription.
1202
1139
  * - Filter `input` — `stream`/`stream_exact` match against event-bearing
1203
- * stream names; `source`/`source_exact`/`blocked` require a
1204
- * corresponding subscription in `_streams` (those are subscription
1205
- * concepts, not event concepts). Empty filter `{}` matches every
1206
- * event-bearing stream.
1140
+ * stream names. Empty filter `{}` matches every event-bearing stream.
1207
1141
  */
1208
1142
  async query_stats(input, options) {
1209
1143
  await sleep();
@@ -1309,7 +1243,6 @@ var InMemoryStore = class {
1309
1243
  return false;
1310
1244
  });
1311
1245
  this._stream_versions.delete(stream);
1312
- this._max_event_id_by_stream.delete(stream);
1313
1246
  this._pii.delete(stream);
1314
1247
  const event = {
1315
1248
  id: this._next_id++,
@@ -1322,15 +1255,8 @@ var InMemoryStore = class {
1322
1255
  };
1323
1256
  this._events.push(event);
1324
1257
  this._stream_versions.set(stream, 0);
1325
- if (event.name !== SNAP_EVENT) {
1326
- this._max_event_id_by_stream.set(stream, event.id);
1327
- }
1328
1258
  result.set(stream, { deleted, committed: event });
1329
1259
  }
1330
- let max = -1;
1331
- for (const id of this._max_event_id_by_stream.values())
1332
- if (id > max) max = id;
1333
- this._max_non_snap_event_id = max;
1334
1260
  return result;
1335
1261
  }
1336
1262
  /**
@@ -1351,8 +1277,6 @@ var InMemoryStore = class {
1351
1277
  const prev_next_id = this._next_id;
1352
1278
  const prev_streams = this._streams;
1353
1279
  const prev_stream_versions = this._stream_versions;
1354
- const prev_max_event_id_by_stream = this._max_event_id_by_stream;
1355
- const prev_max_non_snap_event_id = this._max_non_snap_event_id;
1356
1280
  const prev_pii = this._pii;
1357
1281
  const prev_correlated_at = this._correlated_at;
1358
1282
  const prev_correlators = new Map(
@@ -1364,8 +1288,6 @@ var InMemoryStore = class {
1364
1288
  this._next_id = 0;
1365
1289
  this._streams = /* @__PURE__ */ new Map();
1366
1290
  this._stream_versions = /* @__PURE__ */ new Map();
1367
- this._max_event_id_by_stream = /* @__PURE__ */ new Map();
1368
- this._max_non_snap_event_id = -1;
1369
1291
  this._pii = /* @__PURE__ */ new Map();
1370
1292
  try {
1371
1293
  await driver(async (event) => {
@@ -1373,19 +1295,8 @@ var InMemoryStore = class {
1373
1295
  const { pii, ...rest } = event;
1374
1296
  const committed = { ...rest, id };
1375
1297
  this._events.push(committed);
1376
- if (pii != null) {
1377
- let per_stream = this._pii.get(event.stream);
1378
- if (!per_stream) {
1379
- per_stream = /* @__PURE__ */ new Map();
1380
- this._pii.set(event.stream, per_stream);
1381
- }
1382
- per_stream.set(id, structuredClone(pii));
1383
- }
1298
+ if (pii != null) this._put_pii(event.stream, id, pii);
1384
1299
  this._stream_versions.set(event.stream, event.version);
1385
- if (event.name !== SNAP_EVENT) {
1386
- this._max_event_id_by_stream.set(event.stream, id);
1387
- this._max_non_snap_event_id = id;
1388
- }
1389
1300
  return id;
1390
1301
  });
1391
1302
  } catch (err) {
@@ -1393,8 +1304,6 @@ var InMemoryStore = class {
1393
1304
  this._next_id = prev_next_id;
1394
1305
  this._streams = prev_streams;
1395
1306
  this._stream_versions = prev_stream_versions;
1396
- this._max_event_id_by_stream = prev_max_event_id_by_stream;
1397
- this._max_non_snap_event_id = prev_max_non_snap_event_id;
1398
1307
  this._pii = prev_pii;
1399
1308
  this._correlated_at = prev_correlated_at;
1400
1309
  this._correlators = prev_correlators;