@graphrefly/graphrefly 0.6.0 → 0.7.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.
Files changed (75) hide show
  1. package/README.md +30 -14
  2. package/dist/{chunk-5X3LAO3B.js → chunk-3EVXOI5C.js} +50 -5
  3. package/dist/chunk-3EVXOI5C.js.map +1 -0
  4. package/dist/chunk-47YJEZUJ.js +106 -0
  5. package/dist/chunk-47YJEZUJ.js.map +1 -0
  6. package/dist/{chunk-6W5SGIGB.js → chunk-BLCXEMAD.js} +129 -25
  7. package/dist/chunk-BLCXEMAD.js.map +1 -0
  8. package/dist/{chunk-QW7H3ICI.js → chunk-FGLZ5QID.js} +4 -4
  9. package/dist/{chunk-CP6MNKAA.js → chunk-ISGMZ2T3.js} +10 -4
  10. package/dist/{chunk-CP6MNKAA.js.map → chunk-ISGMZ2T3.js.map} +1 -1
  11. package/dist/{chunk-HP7OKEOE.js → chunk-L4J2K2RT.js} +3 -3
  12. package/dist/chunk-L4J2K2RT.js.map +1 -0
  13. package/dist/{chunk-V3UACY6A.js → chunk-ONLYF6GA.js} +790 -203
  14. package/dist/chunk-ONLYF6GA.js.map +1 -0
  15. package/dist/{chunk-Z4Y4FMQN.js → chunk-OSR3G3DP.js} +7 -7
  16. package/dist/{chunk-KWXPDASV.js → chunk-PEBORXRA.js} +2 -2
  17. package/dist/chunk-WZ2Z2CRV.js +32 -0
  18. package/dist/chunk-WZ2Z2CRV.js.map +1 -0
  19. package/dist/compat/nestjs/index.cjs +226 -41
  20. package/dist/compat/nestjs/index.cjs.map +1 -1
  21. package/dist/compat/nestjs/index.d.cts +4 -4
  22. package/dist/compat/nestjs/index.d.ts +4 -4
  23. package/dist/compat/nestjs/index.js +8 -7
  24. package/dist/core/index.cjs +134 -20
  25. package/dist/core/index.cjs.map +1 -1
  26. package/dist/core/index.d.cts +2 -2
  27. package/dist/core/index.d.ts +2 -2
  28. package/dist/core/index.js +10 -4
  29. package/dist/extra/index.cjs +863 -206
  30. package/dist/extra/index.cjs.map +1 -1
  31. package/dist/extra/index.d.cts +4 -4
  32. package/dist/extra/index.d.ts +4 -4
  33. package/dist/extra/index.js +22 -3
  34. package/dist/graph/index.cjs +226 -41
  35. package/dist/graph/index.cjs.map +1 -1
  36. package/dist/graph/index.d.cts +3 -3
  37. package/dist/graph/index.d.ts +3 -3
  38. package/dist/graph/index.js +4 -4
  39. package/dist/{graph-CL_ZDAj9.d.cts → graph-B3BoJjcb.d.cts} +58 -7
  40. package/dist/{graph-D18qmsNm.d.ts → graph-CmiUuhaN.d.ts} +58 -7
  41. package/dist/{index-B7eOdgEx.d.ts → index-Bf2X1YSI.d.ts} +3 -3
  42. package/dist/{index-BvhgZRHK.d.cts → index-Bl7hJcc3.d.cts} +4 -2
  43. package/dist/{index-Bvy_6CaN.d.ts → index-BrgtEG-C.d.ts} +47 -4
  44. package/dist/{index-D_geH2Bm.d.cts → index-BsuKSs4L.d.cts} +3 -3
  45. package/dist/{index-BtK55IE2.d.ts → index-CsUq2rrK.d.ts} +4 -2
  46. package/dist/{index-C3BMRmmp.d.cts → index-D0cx-Yht.d.cts} +3 -3
  47. package/dist/{index-Bk_idZm1.d.cts → index-D1hgSTzr.d.cts} +406 -61
  48. package/dist/{index-C5mqLhMX.d.cts → index-D8NIq6om.d.cts} +47 -4
  49. package/dist/{index-CP_QvbWu.d.ts → index-DFFNKYig.d.ts} +3 -3
  50. package/dist/{index-B2jmzVxL.d.ts → index-Pm68AYPh.d.ts} +406 -61
  51. package/dist/index.cjs +2929 -1775
  52. package/dist/index.cjs.map +1 -1
  53. package/dist/index.d.cts +112 -14
  54. package/dist/index.d.ts +112 -14
  55. package/dist/index.js +392 -27
  56. package/dist/index.js.map +1 -1
  57. package/dist/{meta-BsF6Sag9.d.cts → meta-BJEU8fYz.d.cts} +31 -4
  58. package/dist/{meta-BsF6Sag9.d.ts → meta-BJEU8fYz.d.ts} +31 -4
  59. package/dist/patterns/reactive-layout/index.cjs +226 -41
  60. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  61. package/dist/patterns/reactive-layout/index.d.cts +3 -3
  62. package/dist/patterns/reactive-layout/index.d.ts +3 -3
  63. package/dist/patterns/reactive-layout/index.js +4 -4
  64. package/dist/{reactive-log-BfvfNWQh.d.cts → reactive-log-CAXzJ7hw.d.cts} +2 -2
  65. package/dist/{reactive-log-ohLmTXoZ.d.ts → reactive-log-DwNhOe0g.d.ts} +2 -2
  66. package/package.json +29 -18
  67. package/dist/chunk-5X3LAO3B.js.map +0 -1
  68. package/dist/chunk-6W5SGIGB.js.map +0 -1
  69. package/dist/chunk-HP7OKEOE.js.map +0 -1
  70. package/dist/chunk-O3PI7W45.js +0 -68
  71. package/dist/chunk-O3PI7W45.js.map +0 -1
  72. package/dist/chunk-V3UACY6A.js.map +0 -1
  73. /package/dist/{chunk-QW7H3ICI.js.map → chunk-FGLZ5QID.js.map} +0 -0
  74. /package/dist/{chunk-Z4Y4FMQN.js.map → chunk-OSR3G3DP.js.map} +0 -0
  75. /package/dist/{chunk-KWXPDASV.js.map → chunk-PEBORXRA.js.map} +0 -0
@@ -27,11 +27,14 @@ __export(extra_exports, {
27
27
  NS_PER_MS: () => NS_PER_MS,
28
28
  NS_PER_SEC: () => NS_PER_SEC,
29
29
  SqliteCheckpointAdapter: () => SqliteCheckpointAdapter,
30
+ TimeoutError: () => TimeoutError,
30
31
  audit: () => audit,
31
32
  buffer: () => buffer,
32
33
  bufferCount: () => bufferCount,
33
34
  bufferTime: () => bufferTime,
35
+ cache: () => cache,
34
36
  cached: () => cached,
37
+ cascadingCache: () => cascadingCache,
35
38
  catchError: () => catchError,
36
39
  checkpointNodeValue: () => checkpointNodeValue,
37
40
  checkpointToRedis: () => checkpointToRedis,
@@ -56,6 +59,7 @@ __export(extra_exports, {
56
59
  escapeRegexChar: () => escapeRegexChar,
57
60
  exhaustMap: () => exhaustMap,
58
61
  exponential: () => exponential,
62
+ fallback: () => fallback,
59
63
  fibonacci: () => fibonacci,
60
64
  filter: () => filter,
61
65
  find: () => find,
@@ -68,6 +72,7 @@ __export(extra_exports, {
68
72
  fromCSV: () => fromCSV,
69
73
  fromClickHouseWatch: () => fromClickHouseWatch,
70
74
  fromCron: () => fromCron,
75
+ fromDrizzle: () => fromDrizzle,
71
76
  fromEvent: () => fromEvent,
72
77
  fromFSWatch: () => fromFSWatch,
73
78
  fromGitHook: () => fromGitHook,
@@ -76,10 +81,12 @@ __export(extra_exports, {
76
81
  fromIDBTransaction: () => fromIDBTransaction,
77
82
  fromIter: () => fromIter,
78
83
  fromKafka: () => fromKafka,
84
+ fromKysely: () => fromKysely,
79
85
  fromMCP: () => fromMCP,
80
86
  fromNATS: () => fromNATS,
81
87
  fromNDJSON: () => fromNDJSON,
82
88
  fromOTel: () => fromOTel,
89
+ fromPrisma: () => fromPrisma,
83
90
  fromPrometheus: () => fromPrometheus,
84
91
  fromPromise: () => fromPromise,
85
92
  fromPulsar: () => fromPulsar,
@@ -97,6 +104,7 @@ __export(extra_exports, {
97
104
  last: () => last,
98
105
  linear: () => linear,
99
106
  logSlice: () => logSlice,
107
+ lru: () => lru,
100
108
  map: () => map,
101
109
  matchesAnyPattern: () => matchesAnyPattern,
102
110
  matchesCron: () => matchesCron,
@@ -146,6 +154,7 @@ __export(extra_exports, {
146
154
  throttle: () => throttle,
147
155
  throttleTime: () => throttleTime,
148
156
  throwError: () => throwError,
157
+ tieredStorage: () => tieredStorage,
149
158
  timeout: () => timeout,
150
159
  toArray: () => toArray,
151
160
  toCSV: () => toCSV,
@@ -330,10 +339,14 @@ function partitionForBatch(messages) {
330
339
  }
331
340
  return { immediate, deferred, terminal };
332
341
  }
333
- function emitWithBatch(emit, messages, phase = 2) {
342
+ function emitWithBatch(emit, messages, phase = 2, options) {
334
343
  if (messages.length === 0) {
335
344
  return;
336
345
  }
346
+ if (options?.strategy === "sequential") {
347
+ _emitSequential(emit, messages, phase);
348
+ return;
349
+ }
337
350
  const queue = phase === 3 ? pendingPhase3 : pendingPhase2;
338
351
  if (messages.length === 1) {
339
352
  const t = messages[0][0];
@@ -374,6 +387,29 @@ function emitWithBatch(emit, messages, phase = 2) {
374
387
  }
375
388
  }
376
389
  }
390
+ function _emitSequential(emit, messages, phase = 2) {
391
+ const dataQueue = phase === 3 ? pendingPhase3 : pendingPhase2;
392
+ for (const msg of messages) {
393
+ const tier = messageTier(msg[0]);
394
+ if (tier === 2) {
395
+ if (isBatching()) {
396
+ const m = msg;
397
+ dataQueue.push(() => emit([m]));
398
+ } else {
399
+ emit([msg]);
400
+ }
401
+ } else if (tier >= 3) {
402
+ if (isBatching()) {
403
+ const m = msg;
404
+ pendingPhase3.push(() => emit([m]));
405
+ } else {
406
+ emit([msg]);
407
+ }
408
+ } else {
409
+ emit([msg]);
410
+ }
411
+ }
412
+ }
377
413
 
378
414
  // src/core/clock.ts
379
415
  function monotonicNs() {
@@ -572,6 +608,7 @@ var NodeImpl = class {
572
608
  _producerStarted = false;
573
609
  _connecting = false;
574
610
  _manualEmitUsed = false;
611
+ _hasEmittedData = false;
575
612
  _sinkCount = 0;
576
613
  _singleDepSinkCount = 0;
577
614
  // --- Object/collection state ---
@@ -858,6 +895,7 @@ var NodeImpl = class {
858
895
  this._cleanup = void 0;
859
896
  cleanupFn?.();
860
897
  this._cached = void 0;
898
+ this._hasEmittedData = false;
861
899
  this._lastDepValues = void 0;
862
900
  }
863
901
  this._status = statusAfterMessage(this._status, m);
@@ -867,6 +905,7 @@ var NodeImpl = class {
867
905
  if (t === TEARDOWN) {
868
906
  if (this._opts.resetOnTeardown) {
869
907
  this._cached = void 0;
908
+ this._hasEmittedData = false;
870
909
  }
871
910
  const teardownCleanup = this._cleanup;
872
911
  this._cleanup = void 0;
@@ -897,7 +936,16 @@ var NodeImpl = class {
897
936
  }
898
937
  _emitAutoValue(value) {
899
938
  const wasDirty = this._status === "dirty";
900
- const unchanged = this._equals(this._cached, value);
939
+ let unchanged;
940
+ try {
941
+ unchanged = this._hasEmittedData && this._equals(this._cached, value);
942
+ } catch (eqErr) {
943
+ const eqMsg = eqErr instanceof Error ? eqErr.message : String(eqErr);
944
+ const wrapped = new Error(`Node "${this.name}": equals threw: ${eqMsg}`, { cause: eqErr });
945
+ this._downInternal([[ERROR, wrapped]]);
946
+ return;
947
+ }
948
+ this._hasEmittedData = true;
901
949
  if (unchanged) {
902
950
  this._downInternal(wasDirty ? [[RESOLVED]] : [[DIRTY], [RESOLVED]]);
903
951
  return;
@@ -944,7 +992,9 @@ var NodeImpl = class {
944
992
  if (out === void 0) return;
945
993
  this._emitAutoValue(out);
946
994
  } catch (err) {
947
- this._downInternal([[ERROR, err]]);
995
+ const errMsg = err instanceof Error ? err.message : String(err);
996
+ const wrapped = new Error(`Node "${this.name}": fn threw: ${errMsg}`, { cause: err });
997
+ this._downInternal([[ERROR, wrapped]]);
948
998
  }
949
999
  }
950
1000
  _onDepDirty(index) {
@@ -979,7 +1029,11 @@ var NodeImpl = class {
979
1029
  try {
980
1030
  if (this._onMessage(msg, index, this._actions)) continue;
981
1031
  } catch (err) {
982
- this._downInternal([[ERROR, err]]);
1032
+ const errMsg = err instanceof Error ? err.message : String(err);
1033
+ const wrapped = new Error(`Node "${this.name}": onMessage threw: ${errMsg}`, {
1034
+ cause: err
1035
+ });
1036
+ this._downInternal([[ERROR, wrapped]]);
983
1037
  return;
984
1038
  }
985
1039
  }
@@ -1194,6 +1248,34 @@ function resolveBackoffPreset(name) {
1194
1248
  );
1195
1249
  }
1196
1250
 
1251
+ // src/core/timer.ts
1252
+ var ResettableTimer = class {
1253
+ _timer;
1254
+ _gen = 0;
1255
+ /** Schedule callback after delayMs. Cancels any pending timer. */
1256
+ start(delayMs, callback) {
1257
+ this.cancel();
1258
+ this._gen += 1;
1259
+ const gen = this._gen;
1260
+ this._timer = setTimeout(() => {
1261
+ this._timer = void 0;
1262
+ if (gen !== this._gen) return;
1263
+ callback();
1264
+ }, delayMs);
1265
+ }
1266
+ /** Cancel the pending timer (if any). */
1267
+ cancel() {
1268
+ if (this._timer !== void 0) {
1269
+ clearTimeout(this._timer);
1270
+ this._timer = void 0;
1271
+ }
1272
+ }
1273
+ /** Whether a timer is currently pending. */
1274
+ get pending() {
1275
+ return this._timer !== void 0;
1276
+ }
1277
+ };
1278
+
1197
1279
  // src/extra/resilience.ts
1198
1280
  function operatorOpts(opts) {
1199
1281
  return { describeKind: "operator", ...opts };
@@ -1223,14 +1305,7 @@ function retry(source, opts) {
1223
1305
  let stopped = false;
1224
1306
  let prevDelay = null;
1225
1307
  let unsub;
1226
- let timer;
1227
- let timerGen = 0;
1228
- function cancelTimer() {
1229
- if (timer !== void 0) {
1230
- clearTimeout(timer);
1231
- timer = void 0;
1232
- }
1233
- }
1308
+ const timer = new ResettableTimer();
1234
1309
  function disconnectUpstream() {
1235
1310
  unsub?.();
1236
1311
  unsub = void 0;
@@ -1246,20 +1321,18 @@ function retry(source, opts) {
1246
1321
  const delayNs = coerceDelayNs(raw === void 0 ? null : raw);
1247
1322
  prevDelay = delayNs;
1248
1323
  attempt += 1;
1249
- timerGen += 1;
1250
- const gen = timerGen;
1251
1324
  disconnectUpstream();
1252
1325
  const delayMs = delayNs > 0 ? delayNs / NS_PER_MS : 1;
1253
- timer = setTimeout(() => {
1254
- timer = void 0;
1255
- if (stopped || gen !== timerGen) return;
1326
+ timer.start(delayMs, () => {
1327
+ if (stopped) return;
1256
1328
  connect();
1257
- }, delayMs);
1329
+ });
1258
1330
  }
1259
1331
  function connect() {
1260
- cancelTimer();
1332
+ timer.cancel();
1261
1333
  disconnectUpstream();
1262
1334
  unsub = source.subscribe((msgs) => {
1335
+ if (stopped) return;
1263
1336
  for (const m of msgs) {
1264
1337
  const t = m[0];
1265
1338
  if (t === DIRTY) a.down([[DIRTY]]);
@@ -1281,8 +1354,7 @@ function retry(source, opts) {
1281
1354
  connect();
1282
1355
  return () => {
1283
1356
  stopped = true;
1284
- timerGen += 1;
1285
- cancelTimer();
1357
+ timer.cancel();
1286
1358
  disconnectUpstream();
1287
1359
  };
1288
1360
  },
@@ -1462,14 +1534,7 @@ function rateLimiter(source, maxEvents, windowNs) {
1462
1534
  (_d, a) => {
1463
1535
  const times = [];
1464
1536
  const pending = [];
1465
- let timer;
1466
- let timerGen = 0;
1467
- function cancelTimer() {
1468
- if (timer !== void 0) {
1469
- clearTimeout(timer);
1470
- timer = void 0;
1471
- }
1472
- }
1537
+ const timer = new ResettableTimer();
1473
1538
  function prune(now) {
1474
1539
  const boundary = now - windowNs;
1475
1540
  while (times.length > 0 && times[0] <= boundary) times.shift();
@@ -1483,15 +1548,10 @@ function rateLimiter(source, maxEvents, windowNs) {
1483
1548
  a.emit(pending.shift());
1484
1549
  } else {
1485
1550
  const oldest = times[0];
1486
- cancelTimer();
1487
- timerGen += 1;
1488
- const gen = timerGen;
1489
1551
  const delayNs = Math.max(0, oldest + windowNs - monotonicNs());
1490
- timer = setTimeout(() => {
1491
- timer = void 0;
1492
- if (gen !== timerGen) return;
1552
+ timer.start(delayNs / NS_PER_MS, () => {
1493
1553
  tryEmit();
1494
- }, delayNs / NS_PER_MS);
1554
+ });
1495
1555
  return;
1496
1556
  }
1497
1557
  }
@@ -1505,14 +1565,12 @@ function rateLimiter(source, maxEvents, windowNs) {
1505
1565
  tryEmit();
1506
1566
  } else if (t === RESOLVED) a.down([[RESOLVED]]);
1507
1567
  else if (t === COMPLETE) {
1508
- timerGen += 1;
1509
- cancelTimer();
1568
+ timer.cancel();
1510
1569
  pending.length = 0;
1511
1570
  times.length = 0;
1512
1571
  a.down([[COMPLETE]]);
1513
1572
  } else if (t === ERROR) {
1514
- timerGen += 1;
1515
- cancelTimer();
1573
+ timer.cancel();
1516
1574
  pending.length = 0;
1517
1575
  times.length = 0;
1518
1576
  a.down([m]);
@@ -1520,8 +1578,7 @@ function rateLimiter(source, maxEvents, windowNs) {
1520
1578
  }
1521
1579
  });
1522
1580
  return () => {
1523
- timerGen += 1;
1524
- cancelTimer();
1581
+ timer.cancel();
1525
1582
  unsub();
1526
1583
  };
1527
1584
  },
@@ -1582,6 +1639,147 @@ function withStatus(src, options) {
1582
1639
  error: out.meta.error
1583
1640
  };
1584
1641
  }
1642
+ var TimeoutError = class extends Error {
1643
+ name = "TimeoutError";
1644
+ constructor(ns) {
1645
+ super(`Timed out after ${ns / NS_PER_MS}ms`);
1646
+ }
1647
+ };
1648
+ function isNode(x) {
1649
+ return x != null && typeof x.subscribe === "function" && typeof x.get === "function";
1650
+ }
1651
+ function fallback(source, fb) {
1652
+ return producer(
1653
+ (_d, a) => {
1654
+ let fallbackUnsub;
1655
+ let sourceUnsub;
1656
+ sourceUnsub = source.subscribe((msgs) => {
1657
+ for (const m of msgs) {
1658
+ const t = m[0];
1659
+ if (t === DIRTY) a.down([[DIRTY]]);
1660
+ else if (t === DATA) a.emit(m[1]);
1661
+ else if (t === RESOLVED) a.down([[RESOLVED]]);
1662
+ else if (t === COMPLETE) a.down([[COMPLETE]]);
1663
+ else if (t === ERROR) {
1664
+ sourceUnsub?.();
1665
+ if (isNode(fb)) {
1666
+ fallbackUnsub = fb.subscribe((fMsgs) => {
1667
+ a.down(fMsgs);
1668
+ });
1669
+ const cur = fb.get();
1670
+ if (cur !== void 0) a.down([[DATA, cur]]);
1671
+ } else {
1672
+ a.emit(fb);
1673
+ a.down([[COMPLETE]]);
1674
+ }
1675
+ return;
1676
+ } else if (t === TEARDOWN) {
1677
+ fallbackUnsub?.();
1678
+ a.down([m]);
1679
+ return;
1680
+ } else a.down([m]);
1681
+ }
1682
+ });
1683
+ return () => {
1684
+ sourceUnsub?.();
1685
+ fallbackUnsub?.();
1686
+ };
1687
+ },
1688
+ {
1689
+ ...operatorOpts(),
1690
+ initial: source.get()
1691
+ }
1692
+ );
1693
+ }
1694
+ function timeout(source, timeoutNs) {
1695
+ if (timeoutNs <= 0) throw new RangeError("timeoutNs must be > 0");
1696
+ return producer(
1697
+ (_d, a) => {
1698
+ let stopped = false;
1699
+ const timer = new ResettableTimer();
1700
+ function startTimer() {
1701
+ const delayMs = timeoutNs / NS_PER_MS;
1702
+ timer.start(delayMs, () => {
1703
+ if (stopped) return;
1704
+ stopped = true;
1705
+ unsub();
1706
+ a.down([[ERROR, new TimeoutError(timeoutNs)]]);
1707
+ });
1708
+ }
1709
+ const unsub = source.subscribe((msgs) => {
1710
+ for (const m of msgs) {
1711
+ if (stopped) return;
1712
+ const t = m[0];
1713
+ if (t === DIRTY) a.down([[DIRTY]]);
1714
+ else if (t === DATA) {
1715
+ startTimer();
1716
+ a.emit(m[1]);
1717
+ } else if (t === RESOLVED) a.down([[RESOLVED]]);
1718
+ else if (t === COMPLETE) {
1719
+ timer.cancel();
1720
+ stopped = true;
1721
+ a.down([[COMPLETE]]);
1722
+ return;
1723
+ } else if (t === ERROR) {
1724
+ timer.cancel();
1725
+ stopped = true;
1726
+ a.down([m]);
1727
+ return;
1728
+ } else if (t === TEARDOWN) {
1729
+ timer.cancel();
1730
+ stopped = true;
1731
+ a.down([m]);
1732
+ return;
1733
+ } else a.down([m]);
1734
+ }
1735
+ });
1736
+ startTimer();
1737
+ return () => {
1738
+ stopped = true;
1739
+ timer.cancel();
1740
+ unsub();
1741
+ };
1742
+ },
1743
+ {
1744
+ ...operatorOpts(),
1745
+ initial: source.get()
1746
+ }
1747
+ );
1748
+ }
1749
+ function cache(source, ttlNs) {
1750
+ if (ttlNs <= 0) throw new RangeError("ttlNs must be > 0");
1751
+ let cachedValue;
1752
+ let cachedAt = 0;
1753
+ let hasCached = false;
1754
+ return producer(
1755
+ (_d, a) => {
1756
+ if (hasCached && monotonicNs() - cachedAt < ttlNs) {
1757
+ a.down([[DATA, cachedValue]]);
1758
+ }
1759
+ const unsub = source.subscribe((msgs) => {
1760
+ for (const m of msgs) {
1761
+ const t = m[0];
1762
+ if (t === DATA) {
1763
+ cachedValue = m[1];
1764
+ cachedAt = monotonicNs();
1765
+ hasCached = true;
1766
+ a.emit(cachedValue);
1767
+ } else if (t === DIRTY) a.down([[DIRTY]]);
1768
+ else if (t === RESOLVED) a.down([[RESOLVED]]);
1769
+ else if (t === COMPLETE) a.down([[COMPLETE]]);
1770
+ else if (t === ERROR) a.down([m]);
1771
+ else a.down([m]);
1772
+ }
1773
+ });
1774
+ return unsub;
1775
+ },
1776
+ {
1777
+ ...operatorOpts(),
1778
+ resubscribable: true,
1779
+ initial: source.get()
1780
+ }
1781
+ );
1782
+ }
1585
1783
 
1586
1784
  // src/extra/sources.ts
1587
1785
  var import_node_fs = require("fs");
@@ -1939,11 +2137,11 @@ function fromAsyncIter(iterable, opts) {
1939
2137
  };
1940
2138
  }, sourceOpts(rest));
1941
2139
  }
1942
- function isNode(x) {
2140
+ function isNode2(x) {
1943
2141
  return x != null && typeof x.subscribe === "function" && typeof x.get === "function";
1944
2142
  }
1945
2143
  function fromAny(input, opts) {
1946
- if (isNode(input)) {
2144
+ if (isNode2(input)) {
1947
2145
  return input;
1948
2146
  }
1949
2147
  if (isThenable(input)) {
@@ -2075,6 +2273,17 @@ function firstValueFrom(source) {
2075
2273
  var shareReplay = replay;
2076
2274
 
2077
2275
  // src/extra/adapters.ts
2276
+ function createSinkErrorHandler(userHandler) {
2277
+ const errorsNode = state(null);
2278
+ const handler = (err) => {
2279
+ userHandler?.(err);
2280
+ try {
2281
+ errorsNode.down([[DATA, err]]);
2282
+ } catch {
2283
+ }
2284
+ };
2285
+ return { errorsNode, handler };
2286
+ }
2078
2287
  function sourceOpts2(opts) {
2079
2288
  return { describeKind: "producer", ...opts };
2080
2289
  }
@@ -2825,6 +3034,7 @@ function toKafka(source, kafkaProducer, topic, opts) {
2825
3034
  onTransportError,
2826
3035
  ...rest
2827
3036
  } = opts ?? {};
3037
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2828
3038
  const inner = node([source], () => void 0, {
2829
3039
  describeKind: "effect",
2830
3040
  ...rest,
@@ -2836,7 +3046,7 @@ function toKafka(source, kafkaProducer, topic, opts) {
2836
3046
  try {
2837
3047
  serialized = serialize(value);
2838
3048
  } catch (err) {
2839
- onTransportError?.({
3049
+ handler({
2840
3050
  stage: "serialize",
2841
3051
  error: err instanceof Error ? err : new Error(String(err)),
2842
3052
  value
@@ -2847,7 +3057,7 @@ function toKafka(source, kafkaProducer, topic, opts) {
2847
3057
  topic,
2848
3058
  messages: [{ key, value: Buffer.from(serialized) }]
2849
3059
  }).catch((err) => {
2850
- onTransportError?.({
3060
+ handler({
2851
3061
  stage: "send",
2852
3062
  error: err instanceof Error ? err : new Error(String(err)),
2853
3063
  value
@@ -2858,8 +3068,15 @@ function toKafka(source, kafkaProducer, topic, opts) {
2858
3068
  return false;
2859
3069
  }
2860
3070
  });
2861
- return inner.subscribe(() => {
3071
+ const unsub = inner.subscribe(() => {
2862
3072
  });
3073
+ return {
3074
+ dispose: () => {
3075
+ unsub();
3076
+ errorsNode.down([[TEARDOWN]]);
3077
+ },
3078
+ errors: errorsNode
3079
+ };
2863
3080
  }
2864
3081
  function fromRedisStream(client, key, opts) {
2865
3082
  const {
@@ -2924,6 +3141,7 @@ function toRedisStream(source, client, key, opts) {
2924
3141
  onTransportError,
2925
3142
  ...rest
2926
3143
  } = opts ?? {};
3144
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2927
3145
  const inner = node([source], () => void 0, {
2928
3146
  describeKind: "effect",
2929
3147
  ...rest,
@@ -2934,7 +3152,7 @@ function toRedisStream(source, client, key, opts) {
2934
3152
  try {
2935
3153
  fields = serialize(value);
2936
3154
  } catch (err) {
2937
- onTransportError?.({
3155
+ handler({
2938
3156
  stage: "serialize",
2939
3157
  error: err instanceof Error ? err : new Error(String(err)),
2940
3158
  value
@@ -2943,7 +3161,7 @@ function toRedisStream(source, client, key, opts) {
2943
3161
  }
2944
3162
  const send = maxLen !== void 0 ? client.xadd(key, "MAXLEN", "~", String(maxLen), "*", ...fields) : client.xadd(key, "*", ...fields);
2945
3163
  void send.catch((err) => {
2946
- onTransportError?.({
3164
+ handler({
2947
3165
  stage: "send",
2948
3166
  error: err instanceof Error ? err : new Error(String(err)),
2949
3167
  value
@@ -2954,8 +3172,15 @@ function toRedisStream(source, client, key, opts) {
2954
3172
  return false;
2955
3173
  }
2956
3174
  });
2957
- return inner.subscribe(() => {
3175
+ const unsub = inner.subscribe(() => {
2958
3176
  });
3177
+ return {
3178
+ dispose: () => {
3179
+ unsub();
3180
+ errorsNode.down([[TEARDOWN]]);
3181
+ },
3182
+ errors: errorsNode
3183
+ };
2959
3184
  }
2960
3185
  function fromCSV(source, opts) {
2961
3186
  const {
@@ -3182,6 +3407,7 @@ function toPulsar(source, pulsarProducer, opts) {
3182
3407
  onTransportError,
3183
3408
  ...rest
3184
3409
  } = opts ?? {};
3410
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3185
3411
  const inner = node([source], () => void 0, {
3186
3412
  describeKind: "effect",
3187
3413
  ...rest,
@@ -3192,7 +3418,7 @@ function toPulsar(source, pulsarProducer, opts) {
3192
3418
  try {
3193
3419
  data = serialize(value);
3194
3420
  } catch (err) {
3195
- onTransportError?.({
3421
+ handler({
3196
3422
  stage: "serialize",
3197
3423
  error: err instanceof Error ? err : new Error(String(err)),
3198
3424
  value
@@ -3204,7 +3430,7 @@ function toPulsar(source, pulsarProducer, opts) {
3204
3430
  partitionKey: keyExtractor?.(value),
3205
3431
  properties: propertiesExtractor?.(value)
3206
3432
  }).catch((err) => {
3207
- onTransportError?.({
3433
+ handler({
3208
3434
  stage: "send",
3209
3435
  error: err instanceof Error ? err : new Error(String(err)),
3210
3436
  value
@@ -3215,8 +3441,15 @@ function toPulsar(source, pulsarProducer, opts) {
3215
3441
  return false;
3216
3442
  }
3217
3443
  });
3218
- return inner.subscribe(() => {
3444
+ const unsub = inner.subscribe(() => {
3219
3445
  });
3446
+ return {
3447
+ dispose: () => {
3448
+ unsub();
3449
+ errorsNode.down([[TEARDOWN]]);
3450
+ },
3451
+ errors: errorsNode
3452
+ };
3220
3453
  }
3221
3454
  function fromNATS(client, subject, opts) {
3222
3455
  const decoder = new TextDecoder();
@@ -3272,6 +3505,7 @@ function toNATS(source, client, subject, opts) {
3272
3505
  onTransportError,
3273
3506
  ...rest
3274
3507
  } = opts ?? {};
3508
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3275
3509
  const inner = node([source], () => void 0, {
3276
3510
  describeKind: "effect",
3277
3511
  ...rest,
@@ -3282,7 +3516,7 @@ function toNATS(source, client, subject, opts) {
3282
3516
  try {
3283
3517
  data = serialize(value);
3284
3518
  } catch (err) {
3285
- onTransportError?.({
3519
+ handler({
3286
3520
  stage: "serialize",
3287
3521
  error: err instanceof Error ? err : new Error(String(err)),
3288
3522
  value
@@ -3292,7 +3526,7 @@ function toNATS(source, client, subject, opts) {
3292
3526
  try {
3293
3527
  client.publish(subject, data);
3294
3528
  } catch (err) {
3295
- onTransportError?.({
3529
+ handler({
3296
3530
  stage: "send",
3297
3531
  error: err instanceof Error ? err : new Error(String(err)),
3298
3532
  value
@@ -3303,8 +3537,15 @@ function toNATS(source, client, subject, opts) {
3303
3537
  return false;
3304
3538
  }
3305
3539
  });
3306
- return inner.subscribe(() => {
3540
+ const unsub = inner.subscribe(() => {
3307
3541
  });
3542
+ return {
3543
+ dispose: () => {
3544
+ unsub();
3545
+ errorsNode.down([[TEARDOWN]]);
3546
+ },
3547
+ errors: errorsNode
3548
+ };
3308
3549
  }
3309
3550
  function fromRabbitMQ(channel, queue, opts) {
3310
3551
  const {
@@ -3366,6 +3607,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
3366
3607
  onTransportError,
3367
3608
  ...rest
3368
3609
  } = opts ?? {};
3610
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3369
3611
  const inner = node([source], () => void 0, {
3370
3612
  describeKind: "effect",
3371
3613
  ...rest,
@@ -3376,7 +3618,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
3376
3618
  try {
3377
3619
  routingKey = routingKeyExtractor(value);
3378
3620
  } catch (err) {
3379
- onTransportError?.({
3621
+ handler({
3380
3622
  stage: "routing_key",
3381
3623
  error: err instanceof Error ? err : new Error(String(err)),
3382
3624
  value
@@ -3387,7 +3629,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
3387
3629
  try {
3388
3630
  content = serialize(value);
3389
3631
  } catch (err) {
3390
- onTransportError?.({
3632
+ handler({
3391
3633
  stage: "serialize",
3392
3634
  error: err instanceof Error ? err : new Error(String(err)),
3393
3635
  value
@@ -3397,7 +3639,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
3397
3639
  try {
3398
3640
  channel.publish(exchange, routingKey, content);
3399
3641
  } catch (err) {
3400
- onTransportError?.({
3642
+ handler({
3401
3643
  stage: "send",
3402
3644
  error: err instanceof Error ? err : new Error(String(err)),
3403
3645
  value
@@ -3408,8 +3650,15 @@ function toRabbitMQ(source, channel, exchange, opts) {
3408
3650
  return false;
3409
3651
  }
3410
3652
  });
3411
- return inner.subscribe(() => {
3653
+ const unsub = inner.subscribe(() => {
3412
3654
  });
3655
+ return {
3656
+ dispose: () => {
3657
+ unsub();
3658
+ errorsNode.down([[TEARDOWN]]);
3659
+ },
3660
+ errors: errorsNode
3661
+ };
3413
3662
  }
3414
3663
  function toFile(source, writer, opts) {
3415
3664
  const {
@@ -3421,8 +3670,10 @@ function toFile(source, writer, opts) {
3421
3670
  mode: _mode,
3422
3671
  ...rest
3423
3672
  } = opts ?? {};
3673
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3424
3674
  let buffer2 = [];
3425
3675
  let timer;
3676
+ let disposed = false;
3426
3677
  const doFlush = () => {
3427
3678
  if (buffer2.length === 0) return;
3428
3679
  const chunk = buffer2.join("");
@@ -3430,7 +3681,7 @@ function toFile(source, writer, opts) {
3430
3681
  try {
3431
3682
  writer.write(chunk);
3432
3683
  } catch (err) {
3433
- onTransportError?.({
3684
+ handler({
3434
3685
  stage: "send",
3435
3686
  error: err instanceof Error ? err : new Error(String(err)),
3436
3687
  value: chunk
@@ -3438,7 +3689,7 @@ function toFile(source, writer, opts) {
3438
3689
  }
3439
3690
  };
3440
3691
  const scheduleFlush = () => {
3441
- if (flushIntervalMs > 0 && timer === void 0) {
3692
+ if (flushIntervalMs > 0 && timer === void 0 && !disposed) {
3442
3693
  timer = setTimeout(() => {
3443
3694
  timer = void 0;
3444
3695
  doFlush();
@@ -3456,7 +3707,7 @@ function toFile(source, writer, opts) {
3456
3707
  try {
3457
3708
  line = serialize(value);
3458
3709
  } catch (err) {
3459
- onTransportError?.({
3710
+ handler({
3460
3711
  stage: "serialize",
3461
3712
  error: err instanceof Error ? err : new Error(String(err)),
3462
3713
  value
@@ -3471,7 +3722,7 @@ function toFile(source, writer, opts) {
3471
3722
  try {
3472
3723
  writer.write(line);
3473
3724
  } catch (err) {
3474
- onTransportError?.({
3725
+ handler({
3475
3726
  stage: "send",
3476
3727
  error: err instanceof Error ? err : new Error(String(err)),
3477
3728
  value
@@ -3480,7 +3731,7 @@ function toFile(source, writer, opts) {
3480
3731
  }
3481
3732
  return true;
3482
3733
  }
3483
- if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
3734
+ if (messageTier(msg[0]) >= 3) {
3484
3735
  doFlush();
3485
3736
  }
3486
3737
  return false;
@@ -3489,18 +3740,25 @@ function toFile(source, writer, opts) {
3489
3740
  const unsub = inner.subscribe(() => {
3490
3741
  });
3491
3742
  const dispose = () => {
3743
+ if (disposed) return;
3744
+ disposed = true;
3492
3745
  if (timer !== void 0) {
3493
3746
  clearTimeout(timer);
3494
3747
  timer = void 0;
3495
3748
  }
3496
3749
  doFlush();
3497
- writer.end();
3750
+ try {
3751
+ writer.end();
3752
+ } catch {
3753
+ }
3498
3754
  unsub();
3755
+ errorsNode.down([[TEARDOWN]]);
3499
3756
  };
3500
3757
  return {
3501
3758
  dispose,
3759
+ errors: errorsNode,
3502
3760
  flush: async () => {
3503
- doFlush();
3761
+ if (!disposed) doFlush();
3504
3762
  }
3505
3763
  };
3506
3764
  }
@@ -3551,25 +3809,29 @@ function toClickHouse(source, client, table, opts) {
3551
3809
  onTransportError,
3552
3810
  ...rest
3553
3811
  } = opts ?? {};
3812
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3554
3813
  let buffer2 = [];
3555
3814
  let timer;
3556
- let lastFlush = Promise.resolve();
3815
+ let disposed = false;
3816
+ const inFlight = /* @__PURE__ */ new Set();
3557
3817
  const doFlush = () => {
3558
3818
  if (buffer2.length === 0) return Promise.resolve();
3559
3819
  const batch2 = buffer2;
3560
3820
  buffer2 = [];
3561
3821
  try {
3562
3822
  const p = client.insert({ table, values: batch2, format }).catch((err) => {
3563
- onTransportError?.({
3823
+ handler({
3564
3824
  stage: "send",
3565
3825
  error: err instanceof Error ? err : new Error(String(err)),
3566
3826
  value: batch2
3567
3827
  });
3828
+ }).finally(() => {
3829
+ inFlight.delete(p);
3568
3830
  });
3569
- lastFlush = p;
3831
+ inFlight.add(p);
3570
3832
  return p;
3571
3833
  } catch (err) {
3572
- onTransportError?.({
3834
+ handler({
3573
3835
  stage: "send",
3574
3836
  error: err instanceof Error ? err : new Error(String(err)),
3575
3837
  value: batch2
@@ -3578,7 +3840,7 @@ function toClickHouse(source, client, table, opts) {
3578
3840
  }
3579
3841
  };
3580
3842
  const scheduleFlush = () => {
3581
- if (timer === void 0) {
3843
+ if (timer === void 0 && !disposed) {
3582
3844
  timer = setTimeout(() => {
3583
3845
  timer = void 0;
3584
3846
  doFlush();
@@ -3594,7 +3856,7 @@ function toClickHouse(source, client, table, opts) {
3594
3856
  try {
3595
3857
  buffer2.push(transform(value));
3596
3858
  } catch (err) {
3597
- onTransportError?.({
3859
+ handler({
3598
3860
  stage: "serialize",
3599
3861
  error: err instanceof Error ? err : new Error(String(err)),
3600
3862
  value
@@ -3605,7 +3867,7 @@ function toClickHouse(source, client, table, opts) {
3605
3867
  else scheduleFlush();
3606
3868
  return true;
3607
3869
  }
3608
- if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
3870
+ if (messageTier(msg[0]) >= 3) {
3609
3871
  doFlush();
3610
3872
  }
3611
3873
  return false;
@@ -3614,16 +3876,24 @@ function toClickHouse(source, client, table, opts) {
3614
3876
  const unsub = inner.subscribe(() => {
3615
3877
  });
3616
3878
  const dispose = () => {
3879
+ if (disposed) return;
3880
+ disposed = true;
3617
3881
  if (timer !== void 0) {
3618
3882
  clearTimeout(timer);
3619
3883
  timer = void 0;
3620
3884
  }
3621
3885
  doFlush();
3622
3886
  unsub();
3887
+ errorsNode.down([[TEARDOWN]]);
3623
3888
  };
3624
3889
  return {
3625
3890
  dispose,
3626
- flush: () => doFlush().then(() => lastFlush)
3891
+ errors: errorsNode,
3892
+ flush: () => {
3893
+ const p = disposed ? Promise.resolve() : doFlush();
3894
+ return p.then(() => Promise.all(inFlight)).then(() => {
3895
+ });
3896
+ }
3627
3897
  };
3628
3898
  }
3629
3899
  function toS3(source, client, bucket, opts) {
@@ -3640,10 +3910,12 @@ function toS3(source, client, bucket, opts) {
3640
3910
  onTransportError,
3641
3911
  ...rest
3642
3912
  } = opts ?? {};
3913
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3643
3914
  let buffer2 = [];
3644
3915
  let timer;
3645
3916
  let seq = 0;
3646
- let lastFlush = Promise.resolve();
3917
+ let disposed = false;
3918
+ const inFlight = /* @__PURE__ */ new Set();
3647
3919
  const doFlush = () => {
3648
3920
  if (buffer2.length === 0) return Promise.resolve();
3649
3921
  const batch2 = buffer2;
@@ -3656,16 +3928,18 @@ function toS3(source, client, bucket, opts) {
3656
3928
  try {
3657
3929
  const p = client.putObject({ Bucket: bucket, Key: key, Body: body, ContentType: contentType }).then(() => {
3658
3930
  }).catch((err) => {
3659
- onTransportError?.({
3931
+ handler({
3660
3932
  stage: "send",
3661
3933
  error: err instanceof Error ? err : new Error(String(err)),
3662
3934
  value: batch2
3663
3935
  });
3936
+ }).finally(() => {
3937
+ inFlight.delete(p);
3664
3938
  });
3665
- lastFlush = p;
3939
+ inFlight.add(p);
3666
3940
  return p;
3667
3941
  } catch (err) {
3668
- onTransportError?.({
3942
+ handler({
3669
3943
  stage: "send",
3670
3944
  error: err instanceof Error ? err : new Error(String(err)),
3671
3945
  value: batch2
@@ -3674,7 +3948,7 @@ function toS3(source, client, bucket, opts) {
3674
3948
  }
3675
3949
  };
3676
3950
  const scheduleFlush = () => {
3677
- if (timer === void 0) {
3951
+ if (timer === void 0 && !disposed) {
3678
3952
  timer = setTimeout(() => {
3679
3953
  timer = void 0;
3680
3954
  doFlush();
@@ -3690,7 +3964,7 @@ function toS3(source, client, bucket, opts) {
3690
3964
  try {
3691
3965
  buffer2.push(transform(value));
3692
3966
  } catch (err) {
3693
- onTransportError?.({
3967
+ handler({
3694
3968
  stage: "serialize",
3695
3969
  error: err instanceof Error ? err : new Error(String(err)),
3696
3970
  value
@@ -3701,7 +3975,7 @@ function toS3(source, client, bucket, opts) {
3701
3975
  else scheduleFlush();
3702
3976
  return true;
3703
3977
  }
3704
- if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
3978
+ if (messageTier(msg[0]) >= 3) {
3705
3979
  doFlush();
3706
3980
  }
3707
3981
  return false;
@@ -3710,16 +3984,24 @@ function toS3(source, client, bucket, opts) {
3710
3984
  const unsub = inner.subscribe(() => {
3711
3985
  });
3712
3986
  const dispose = () => {
3987
+ if (disposed) return;
3988
+ disposed = true;
3713
3989
  if (timer !== void 0) {
3714
3990
  clearTimeout(timer);
3715
3991
  timer = void 0;
3716
3992
  }
3717
3993
  doFlush();
3718
3994
  unsub();
3995
+ errorsNode.down([[TEARDOWN]]);
3719
3996
  };
3720
3997
  return {
3721
3998
  dispose,
3722
- flush: () => doFlush().then(() => lastFlush)
3999
+ errors: errorsNode,
4000
+ flush: () => {
4001
+ const p = disposed ? Promise.resolve() : doFlush();
4002
+ return p.then(() => Promise.all(inFlight)).then(() => {
4003
+ });
4004
+ }
3723
4005
  };
3724
4006
  }
3725
4007
  function toPostgres(source, client, table, opts) {
@@ -3731,6 +4013,7 @@ function toPostgres(source, client, table, opts) {
3731
4013
  onTransportError,
3732
4014
  ...rest
3733
4015
  } = opts ?? {};
4016
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3734
4017
  const inner = node([source], () => void 0, {
3735
4018
  describeKind: "effect",
3736
4019
  ...rest,
@@ -3741,7 +4024,7 @@ function toPostgres(source, client, table, opts) {
3741
4024
  try {
3742
4025
  query = toSQL(value, table);
3743
4026
  } catch (err) {
3744
- onTransportError?.({
4027
+ handler({
3745
4028
  stage: "serialize",
3746
4029
  error: err instanceof Error ? err : new Error(String(err)),
3747
4030
  value
@@ -3749,7 +4032,7 @@ function toPostgres(source, client, table, opts) {
3749
4032
  return true;
3750
4033
  }
3751
4034
  void client.query(query.sql, query.params).catch((err) => {
3752
- onTransportError?.({
4035
+ handler({
3753
4036
  stage: "send",
3754
4037
  error: err instanceof Error ? err : new Error(String(err)),
3755
4038
  value
@@ -3760,11 +4043,19 @@ function toPostgres(source, client, table, opts) {
3760
4043
  return false;
3761
4044
  }
3762
4045
  });
3763
- return inner.subscribe(() => {
4046
+ const unsub = inner.subscribe(() => {
3764
4047
  });
4048
+ return {
4049
+ dispose: () => {
4050
+ unsub();
4051
+ errorsNode.down([[TEARDOWN]]);
4052
+ },
4053
+ errors: errorsNode
4054
+ };
3765
4055
  }
3766
4056
  function toMongo(source, collection, opts) {
3767
4057
  const { toDocument = (v) => v, onTransportError, ...rest } = opts ?? {};
4058
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3768
4059
  const inner = node([source], () => void 0, {
3769
4060
  describeKind: "effect",
3770
4061
  ...rest,
@@ -3775,7 +4066,7 @@ function toMongo(source, collection, opts) {
3775
4066
  try {
3776
4067
  doc = toDocument(value);
3777
4068
  } catch (err) {
3778
- onTransportError?.({
4069
+ handler({
3779
4070
  stage: "serialize",
3780
4071
  error: err instanceof Error ? err : new Error(String(err)),
3781
4072
  value
@@ -3783,7 +4074,7 @@ function toMongo(source, collection, opts) {
3783
4074
  return true;
3784
4075
  }
3785
4076
  void collection.insertOne(doc).catch((err) => {
3786
- onTransportError?.({
4077
+ handler({
3787
4078
  stage: "send",
3788
4079
  error: err instanceof Error ? err : new Error(String(err)),
3789
4080
  value
@@ -3794,8 +4085,15 @@ function toMongo(source, collection, opts) {
3794
4085
  return false;
3795
4086
  }
3796
4087
  });
3797
- return inner.subscribe(() => {
4088
+ const unsub = inner.subscribe(() => {
3798
4089
  });
4090
+ return {
4091
+ dispose: () => {
4092
+ unsub();
4093
+ errorsNode.down([[TEARDOWN]]);
4094
+ },
4095
+ errors: errorsNode
4096
+ };
3799
4097
  }
3800
4098
  function toLoki(source, client, opts) {
3801
4099
  const {
@@ -3805,6 +4103,7 @@ function toLoki(source, client, opts) {
3805
4103
  onTransportError,
3806
4104
  ...rest
3807
4105
  } = opts ?? {};
4106
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3808
4107
  const inner = node([source], () => void 0, {
3809
4108
  describeKind: "effect",
3810
4109
  ...rest,
@@ -3815,7 +4114,7 @@ function toLoki(source, client, opts) {
3815
4114
  try {
3816
4115
  line = toLine(value);
3817
4116
  } catch (err) {
3818
- onTransportError?.({
4117
+ handler({
3819
4118
  stage: "serialize",
3820
4119
  error: err instanceof Error ? err : new Error(String(err)),
3821
4120
  value
@@ -3826,7 +4125,7 @@ function toLoki(source, client, opts) {
3826
4125
  try {
3827
4126
  streamLabels = toLabels ? { ...labels, ...toLabels(value) } : labels;
3828
4127
  } catch (err) {
3829
- onTransportError?.({
4128
+ handler({
3830
4129
  stage: "serialize",
3831
4130
  error: err instanceof Error ? err : new Error(String(err)),
3832
4131
  value
@@ -3835,7 +4134,7 @@ function toLoki(source, client, opts) {
3835
4134
  }
3836
4135
  const ts = `${wallClockNs()}`;
3837
4136
  void client.push({ streams: [{ stream: streamLabels, values: [[ts, line]] }] }).catch((err) => {
3838
- onTransportError?.({
4137
+ handler({
3839
4138
  stage: "send",
3840
4139
  error: err instanceof Error ? err : new Error(String(err)),
3841
4140
  value
@@ -3846,11 +4145,19 @@ function toLoki(source, client, opts) {
3846
4145
  return false;
3847
4146
  }
3848
4147
  });
3849
- return inner.subscribe(() => {
4148
+ const unsub = inner.subscribe(() => {
3850
4149
  });
4150
+ return {
4151
+ dispose: () => {
4152
+ unsub();
4153
+ errorsNode.down([[TEARDOWN]]);
4154
+ },
4155
+ errors: errorsNode
4156
+ };
3851
4157
  }
3852
4158
  function toTempo(source, client, opts) {
3853
4159
  const { toResourceSpans = (v) => [v], onTransportError, ...rest } = opts ?? {};
4160
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
3854
4161
  const inner = node([source], () => void 0, {
3855
4162
  describeKind: "effect",
3856
4163
  ...rest,
@@ -3861,7 +4168,7 @@ function toTempo(source, client, opts) {
3861
4168
  try {
3862
4169
  spans = toResourceSpans(value);
3863
4170
  } catch (err) {
3864
- onTransportError?.({
4171
+ handler({
3865
4172
  stage: "serialize",
3866
4173
  error: err instanceof Error ? err : new Error(String(err)),
3867
4174
  value
@@ -3869,7 +4176,7 @@ function toTempo(source, client, opts) {
3869
4176
  return true;
3870
4177
  }
3871
4178
  void client.push({ resourceSpans: spans }).catch((err) => {
3872
- onTransportError?.({
4179
+ handler({
3873
4180
  stage: "send",
3874
4181
  error: err instanceof Error ? err : new Error(String(err)),
3875
4182
  value
@@ -3880,15 +4187,22 @@ function toTempo(source, client, opts) {
3880
4187
  return false;
3881
4188
  }
3882
4189
  });
3883
- return inner.subscribe(() => {
4190
+ const unsub = inner.subscribe(() => {
3884
4191
  });
4192
+ return {
4193
+ dispose: () => {
4194
+ unsub();
4195
+ errorsNode.down([[TEARDOWN]]);
4196
+ },
4197
+ errors: errorsNode
4198
+ };
3885
4199
  }
3886
4200
  function checkpointToS3(graph, client, bucket, opts) {
3887
4201
  const { prefix = "checkpoints/", debounceMs, compactEvery, onError } = opts ?? {};
3888
4202
  const adapter = {
3889
- save(data) {
4203
+ save(_key, data) {
3890
4204
  const ms = Math.floor(wallClockNs() / 1e6);
3891
- const key = `${prefix}${graph.name}/checkpoint-${ms}.json`;
4205
+ const s3Key = `${prefix}${graph.name}/checkpoint-${ms}.json`;
3892
4206
  let body;
3893
4207
  try {
3894
4208
  body = JSON.stringify(data);
@@ -3898,7 +4212,7 @@ function checkpointToS3(graph, client, bucket, opts) {
3898
4212
  }
3899
4213
  void client.putObject({
3900
4214
  Bucket: bucket,
3901
- Key: key,
4215
+ Key: s3Key,
3902
4216
  Body: body,
3903
4217
  ContentType: "application/json"
3904
4218
  }).catch((err) => onError?.(err));
@@ -3908,9 +4222,9 @@ function checkpointToS3(graph, client, bucket, opts) {
3908
4222
  }
3909
4223
  function checkpointToRedis(graph, client, opts) {
3910
4224
  const { prefix = "graphrefly:checkpoint:", debounceMs, compactEvery, onError } = opts ?? {};
3911
- const key = `${prefix}${graph.name}`;
4225
+ const redisKey = `${prefix}${graph.name}`;
3912
4226
  const adapter = {
3913
- save(data) {
4227
+ save(_key, data) {
3914
4228
  let body;
3915
4229
  try {
3916
4230
  body = JSON.stringify(data);
@@ -3918,7 +4232,7 @@ function checkpointToRedis(graph, client, opts) {
3918
4232
  onError?.(err);
3919
4233
  return;
3920
4234
  }
3921
- void client.set(key, body).catch((err) => onError?.(err));
4235
+ void client.set(redisKey, body).catch((err) => onError?.(err));
3922
4236
  }
3923
4237
  };
3924
4238
  return graph.autoCheckpoint(adapter, { debounceMs, compactEvery, onError });
@@ -3956,8 +4270,67 @@ function toSqlite(source, db, table, opts) {
3956
4270
  params: [JSON.stringify(v)]
3957
4271
  }),
3958
4272
  onTransportError,
4273
+ batchInsert = false,
4274
+ maxBatchSize = 1e3,
4275
+ flushIntervalMs = 0,
3959
4276
  ...rest
3960
4277
  } = opts ?? {};
4278
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
4279
+ const pendingInserts = [];
4280
+ let flushing = false;
4281
+ let disposed = false;
4282
+ let timer;
4283
+ function flushTransaction() {
4284
+ if (pendingInserts.length === 0 || flushing) return;
4285
+ flushing = true;
4286
+ try {
4287
+ db.query("BEGIN", []);
4288
+ } catch (err) {
4289
+ flushing = false;
4290
+ handler({
4291
+ stage: "send",
4292
+ error: err instanceof Error ? err : new Error(String(err)),
4293
+ value: void 0
4294
+ });
4295
+ return;
4296
+ }
4297
+ const batch2 = pendingInserts.splice(0);
4298
+ let firstError;
4299
+ for (const q of batch2) {
4300
+ try {
4301
+ db.query(q.sql, q.params);
4302
+ } catch (err) {
4303
+ firstError = err instanceof Error ? err : new Error(String(err));
4304
+ break;
4305
+ }
4306
+ }
4307
+ if (firstError) {
4308
+ try {
4309
+ db.query("ROLLBACK", []);
4310
+ } catch {
4311
+ }
4312
+ handler({ stage: "send", error: firstError, value: void 0 });
4313
+ } else {
4314
+ try {
4315
+ db.query("COMMIT", []);
4316
+ } catch (err) {
4317
+ handler({
4318
+ stage: "send",
4319
+ error: err instanceof Error ? err : new Error(String(err)),
4320
+ value: void 0
4321
+ });
4322
+ }
4323
+ }
4324
+ flushing = false;
4325
+ }
4326
+ const scheduleFlush = () => {
4327
+ if (batchInsert && flushIntervalMs > 0 && timer === void 0 && !disposed) {
4328
+ timer = setTimeout(() => {
4329
+ timer = void 0;
4330
+ flushTransaction();
4331
+ }, flushIntervalMs);
4332
+ }
4333
+ };
3961
4334
  const inner = node([source], () => void 0, {
3962
4335
  describeKind: "effect",
3963
4336
  ...rest,
@@ -3968,29 +4341,140 @@ function toSqlite(source, db, table, opts) {
3968
4341
  try {
3969
4342
  query = toSQL(value, table);
3970
4343
  } catch (err) {
3971
- onTransportError?.({
4344
+ handler({
3972
4345
  stage: "serialize",
3973
4346
  error: err instanceof Error ? err : new Error(String(err)),
3974
4347
  value
3975
4348
  });
3976
4349
  return true;
3977
4350
  }
3978
- try {
3979
- db.query(query.sql, query.params);
3980
- } catch (err) {
3981
- onTransportError?.({
3982
- stage: "send",
3983
- error: err instanceof Error ? err : new Error(String(err)),
3984
- value
3985
- });
4351
+ if (batchInsert) {
4352
+ pendingInserts.push(query);
4353
+ if (pendingInserts.length >= maxBatchSize) flushTransaction();
4354
+ else scheduleFlush();
4355
+ } else {
4356
+ try {
4357
+ db.query(query.sql, query.params);
4358
+ } catch (err) {
4359
+ handler({
4360
+ stage: "send",
4361
+ error: err instanceof Error ? err : new Error(String(err)),
4362
+ value
4363
+ });
4364
+ }
3986
4365
  }
3987
4366
  return true;
3988
4367
  }
4368
+ if (batchInsert && messageTier(msg[0]) >= 3) {
4369
+ flushTransaction();
4370
+ }
3989
4371
  return false;
3990
4372
  }
3991
4373
  });
3992
- return inner.subscribe(() => {
4374
+ const unsub = inner.subscribe(() => {
3993
4375
  });
4376
+ const dispose = () => {
4377
+ if (disposed) return;
4378
+ disposed = true;
4379
+ if (timer !== void 0) {
4380
+ clearTimeout(timer);
4381
+ timer = void 0;
4382
+ }
4383
+ if (batchInsert) flushTransaction();
4384
+ unsub();
4385
+ errorsNode.down([[TEARDOWN]]);
4386
+ };
4387
+ return {
4388
+ dispose,
4389
+ errors: errorsNode,
4390
+ flush: batchInsert ? async () => {
4391
+ if (!disposed) flushTransaction();
4392
+ } : void 0
4393
+ };
4394
+ }
4395
+ function fromPrisma(model, opts) {
4396
+ const { args, mapRow = (r) => r, ...rest } = opts ?? {};
4397
+ return producer(
4398
+ (_d, a) => {
4399
+ let active = true;
4400
+ void model.findMany(args).then((rows) => {
4401
+ if (!active) return;
4402
+ const mapped = rows.map(mapRow);
4403
+ batch(() => {
4404
+ for (const item of mapped) {
4405
+ a.emit(item);
4406
+ }
4407
+ });
4408
+ a.down([[COMPLETE]]);
4409
+ }).catch((err) => {
4410
+ if (!active) return;
4411
+ try {
4412
+ a.down([[ERROR, err instanceof Error ? err : new Error(String(err))]]);
4413
+ } catch {
4414
+ }
4415
+ });
4416
+ return () => {
4417
+ active = false;
4418
+ };
4419
+ },
4420
+ { ...rest, describeKind: "producer", completeWhenDepsComplete: false }
4421
+ );
4422
+ }
4423
+ function fromDrizzle(query, opts) {
4424
+ const { mapRow = (r) => r, ...rest } = opts ?? {};
4425
+ return producer(
4426
+ (_d, a) => {
4427
+ let active = true;
4428
+ void query.execute().then((rows) => {
4429
+ if (!active) return;
4430
+ const mapped = rows.map(mapRow);
4431
+ batch(() => {
4432
+ for (const item of mapped) {
4433
+ a.emit(item);
4434
+ }
4435
+ });
4436
+ a.down([[COMPLETE]]);
4437
+ }).catch((err) => {
4438
+ if (!active) return;
4439
+ try {
4440
+ a.down([[ERROR, err instanceof Error ? err : new Error(String(err))]]);
4441
+ } catch {
4442
+ }
4443
+ });
4444
+ return () => {
4445
+ active = false;
4446
+ };
4447
+ },
4448
+ { ...rest, describeKind: "producer", completeWhenDepsComplete: false }
4449
+ );
4450
+ }
4451
+ function fromKysely(query, opts) {
4452
+ const { mapRow = (r) => r, ...rest } = opts ?? {};
4453
+ return producer(
4454
+ (_d, a) => {
4455
+ let active = true;
4456
+ void query.execute().then((rows) => {
4457
+ if (!active) return;
4458
+ const mapped = rows.map(mapRow);
4459
+ batch(() => {
4460
+ for (const item of mapped) {
4461
+ a.emit(item);
4462
+ }
4463
+ });
4464
+ a.down([[COMPLETE]]);
4465
+ }).catch((err) => {
4466
+ if (!active) return;
4467
+ try {
4468
+ a.down([[ERROR, err instanceof Error ? err : new Error(String(err))]]);
4469
+ } catch {
4470
+ }
4471
+ });
4472
+ return () => {
4473
+ active = false;
4474
+ };
4475
+ },
4476
+ { ...rest, describeKind: "producer", completeWhenDepsComplete: false }
4477
+ );
3994
4478
  }
3995
4479
 
3996
4480
  // src/extra/backpressure.ts
@@ -4037,6 +4521,205 @@ function createWatermarkController(sendUp, opts) {
4037
4521
  };
4038
4522
  }
4039
4523
 
4524
+ // src/extra/cascading-cache.ts
4525
+ function lru() {
4526
+ const map2 = /* @__PURE__ */ new Map();
4527
+ let head = null;
4528
+ let tail = null;
4529
+ function unlink(n) {
4530
+ if (n.prev) n.prev.next = n.next;
4531
+ else head = n.next;
4532
+ if (n.next) n.next.prev = n.prev;
4533
+ else tail = n.prev;
4534
+ n.prev = null;
4535
+ n.next = null;
4536
+ }
4537
+ function pushFront(n) {
4538
+ n.next = head;
4539
+ n.prev = null;
4540
+ if (head) head.prev = n;
4541
+ head = n;
4542
+ if (tail === null) tail = n;
4543
+ }
4544
+ return {
4545
+ insert(key) {
4546
+ if (map2.has(key)) {
4547
+ this.touch(key);
4548
+ return;
4549
+ }
4550
+ const n = { key, prev: null, next: null };
4551
+ map2.set(key, n);
4552
+ pushFront(n);
4553
+ },
4554
+ touch(key) {
4555
+ const n = map2.get(key);
4556
+ if (!n) return;
4557
+ unlink(n);
4558
+ pushFront(n);
4559
+ },
4560
+ delete(key) {
4561
+ const n = map2.get(key);
4562
+ if (!n) return;
4563
+ unlink(n);
4564
+ map2.delete(key);
4565
+ },
4566
+ evict(count) {
4567
+ const victims = [];
4568
+ for (let i = 0; i < count && tail !== null; i++) {
4569
+ const n = tail;
4570
+ victims.push(n.key);
4571
+ unlink(n);
4572
+ map2.delete(n.key);
4573
+ }
4574
+ return victims;
4575
+ },
4576
+ size() {
4577
+ return map2.size;
4578
+ }
4579
+ };
4580
+ }
4581
+ function cascadingCache(tiers, opts) {
4582
+ const entries = /* @__PURE__ */ new Map();
4583
+ const maxSize = opts?.maxSize ?? 0;
4584
+ const policy = maxSize > 0 ? opts?.eviction ?? lru() : null;
4585
+ const writeThrough = opts?.writeThrough ?? false;
4586
+ function promote(key, value, hitTierIndex) {
4587
+ for (let i = 0; i < hitTierIndex; i++) {
4588
+ const tier = tiers[i];
4589
+ if (tier.save) tier.save(key, value);
4590
+ }
4591
+ }
4592
+ function cascade(key, nd) {
4593
+ for (let tierIndex = 0; tierIndex < tiers.length; tierIndex++) {
4594
+ let result;
4595
+ try {
4596
+ result = tiers[tierIndex].load(key);
4597
+ } catch {
4598
+ continue;
4599
+ }
4600
+ if (result != null) {
4601
+ nd.down([[DATA, result]]);
4602
+ promote(key, result, tierIndex);
4603
+ return;
4604
+ }
4605
+ }
4606
+ }
4607
+ function evictIfNeeded() {
4608
+ if (!policy || maxSize <= 0) return;
4609
+ while (policy.size() >= maxSize) {
4610
+ const victims = policy.evict(1);
4611
+ if (victims.length === 0) break;
4612
+ for (const key of victims) {
4613
+ const nd = entries.get(key);
4614
+ if (nd) {
4615
+ const value = nd.get();
4616
+ if (value !== void 0) {
4617
+ for (let i = tiers.length - 1; i >= 0; i--) {
4618
+ if (tiers[i].save) {
4619
+ tiers[i].save(key, value);
4620
+ for (let j = 0; j < i; j++) {
4621
+ if (tiers[j].clear) tiers[j].clear(key);
4622
+ }
4623
+ break;
4624
+ }
4625
+ }
4626
+ }
4627
+ nd.down([[TEARDOWN]]);
4628
+ }
4629
+ entries.delete(key);
4630
+ }
4631
+ }
4632
+ }
4633
+ return {
4634
+ load(key) {
4635
+ const existing = entries.get(key);
4636
+ if (existing) {
4637
+ policy?.touch(key);
4638
+ return existing;
4639
+ }
4640
+ if (policy && maxSize > 0 && policy.size() >= maxSize) {
4641
+ evictIfNeeded();
4642
+ }
4643
+ const nd = state(void 0);
4644
+ entries.set(key, nd);
4645
+ if (policy) {
4646
+ policy.insert(key);
4647
+ }
4648
+ cascade(key, nd);
4649
+ return nd;
4650
+ },
4651
+ save(key, value) {
4652
+ if (writeThrough) {
4653
+ for (const tier of tiers) {
4654
+ if (tier.save) tier.save(key, value);
4655
+ }
4656
+ } else if (tiers[0]?.save) {
4657
+ tiers[0].save(key, value);
4658
+ }
4659
+ const existing = entries.get(key);
4660
+ if (existing) {
4661
+ existing.down([[DATA, value]]);
4662
+ policy?.touch(key);
4663
+ } else {
4664
+ if (policy && maxSize > 0 && policy.size() >= maxSize) {
4665
+ evictIfNeeded();
4666
+ }
4667
+ const nd = state(value);
4668
+ entries.set(key, nd);
4669
+ if (policy) {
4670
+ policy.insert(key);
4671
+ }
4672
+ }
4673
+ },
4674
+ invalidate(key) {
4675
+ const existing = entries.get(key);
4676
+ if (existing) {
4677
+ cascade(key, existing);
4678
+ }
4679
+ },
4680
+ delete(key) {
4681
+ policy?.delete(key);
4682
+ const nd = entries.get(key);
4683
+ if (nd) nd.down([[TEARDOWN]]);
4684
+ entries.delete(key);
4685
+ for (const tier of tiers) {
4686
+ if (tier.clear) tier.clear(key);
4687
+ }
4688
+ },
4689
+ has(key) {
4690
+ return entries.has(key);
4691
+ },
4692
+ get size() {
4693
+ return entries.size;
4694
+ }
4695
+ };
4696
+ }
4697
+ function adapterToTier(adapter) {
4698
+ return {
4699
+ load: (key) => adapter.load(key),
4700
+ save: (key, value) => adapter.save(key, value),
4701
+ clear: (key) => adapter.clear(key)
4702
+ };
4703
+ }
4704
+ function tieredStorage(adapters, opts) {
4705
+ const inner = cascadingCache(adapters.map(adapterToTier), {
4706
+ maxSize: opts?.maxSize,
4707
+ eviction: opts?.eviction,
4708
+ writeThrough: true
4709
+ });
4710
+ return {
4711
+ load: (key) => inner.load(key),
4712
+ save: (key, value) => inner.save(key, value),
4713
+ invalidate: (key) => inner.invalidate(key),
4714
+ delete: (key) => inner.delete(key),
4715
+ has: (key) => inner.has(key),
4716
+ get size() {
4717
+ return inner.size;
4718
+ },
4719
+ cache: inner
4720
+ };
4721
+ }
4722
+
4040
4723
  // src/extra/checkpoint.ts
4041
4724
  var import_node_crypto2 = require("crypto");
4042
4725
  var import_node_fs2 = require("fs");
@@ -4057,60 +4740,61 @@ function sortJsonValue(value) {
4057
4740
  }
4058
4741
  return out;
4059
4742
  }
4060
- function warnNonJsonValues(data) {
4061
- for (const [path, node2] of Object.entries(data.nodes)) {
4062
- const v = node2.value;
4063
- if (v === void 0 || v === null) continue;
4064
- if (typeof v === "function" || typeof v === "symbol" || typeof v === "bigint") {
4065
- console.warn(
4066
- `checkpoint: node "${path}" has non-JSON-serializable value (${typeof v}); it will be lost on round-trip`
4067
- );
4068
- }
4069
- }
4070
- }
4071
- function stableSnapshotJson(data) {
4072
- warnNonJsonValues(data);
4743
+ function stableJsonString(data) {
4073
4744
  return `${JSON.stringify(sortJsonValue(data), void 0, 0)}
4074
4745
  `;
4075
4746
  }
4076
4747
  var MemoryCheckpointAdapter = class {
4077
- #data = null;
4078
- save(data) {
4079
- this.#data = JSON.parse(JSON.stringify(data));
4748
+ #data = /* @__PURE__ */ new Map();
4749
+ save(key, data) {
4750
+ this.#data.set(key, JSON.parse(JSON.stringify(data)));
4751
+ }
4752
+ load(key) {
4753
+ const v = this.#data.get(key);
4754
+ return v === void 0 ? null : JSON.parse(JSON.stringify(v));
4080
4755
  }
4081
- load() {
4082
- return this.#data === null ? null : JSON.parse(JSON.stringify(this.#data));
4756
+ clear(key) {
4757
+ this.#data.delete(key);
4083
4758
  }
4084
4759
  };
4085
4760
  var DictCheckpointAdapter = class {
4086
4761
  #storage;
4087
- #key;
4088
- constructor(storage, key = "graphrefly_checkpoint") {
4762
+ constructor(storage) {
4089
4763
  this.#storage = storage;
4090
- this.#key = key;
4091
4764
  }
4092
- save(data) {
4093
- this.#storage[this.#key] = JSON.parse(JSON.stringify(data));
4765
+ save(key, data) {
4766
+ this.#storage[key] = JSON.parse(JSON.stringify(data));
4767
+ }
4768
+ load(key) {
4769
+ const raw = this.#storage[key];
4770
+ return raw === void 0 ? null : JSON.parse(JSON.stringify(raw));
4094
4771
  }
4095
- load() {
4096
- const raw = this.#storage[this.#key];
4097
- return raw !== null && typeof raw === "object" && !Array.isArray(raw) ? JSON.parse(JSON.stringify(raw)) : null;
4772
+ clear(key) {
4773
+ delete this.#storage[key];
4098
4774
  }
4099
4775
  };
4100
4776
  var FileCheckpointAdapter = class {
4101
- #path;
4102
- constructor(path) {
4103
- this.#path = path;
4104
- }
4105
- save(data) {
4106
- const dir = (0, import_node_path2.dirname)(this.#path);
4107
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
4108
- const payload = stableSnapshotJson(data);
4109
- const base = (0, import_node_path2.basename)(this.#path);
4777
+ #dir;
4778
+ constructor(dir) {
4779
+ this.#dir = dir;
4780
+ }
4781
+ #pathFor(key) {
4782
+ const safeName = key.replace(
4783
+ /[^a-zA-Z0-9_-]/g,
4784
+ (c) => `%${c.charCodeAt(0).toString(16).padStart(2, "0")}`
4785
+ );
4786
+ return (0, import_node_path2.join)(this.#dir, `${safeName}.json`);
4787
+ }
4788
+ save(key, data) {
4789
+ (0, import_node_fs2.mkdirSync)(this.#dir, { recursive: true });
4790
+ const filePath = this.#pathFor(key);
4791
+ const payload = stableJsonString(data);
4792
+ const base = (0, import_node_path2.basename)(filePath);
4793
+ const dir = (0, import_node_path2.dirname)(filePath);
4110
4794
  const tmp = (0, import_node_path2.join)(dir, `.${base}.${(0, import_node_crypto2.randomBytes)(8).toString("hex")}.tmp`);
4111
4795
  try {
4112
4796
  (0, import_node_fs2.writeFileSync)(tmp, payload, "utf8");
4113
- (0, import_node_fs2.renameSync)(tmp, this.#path);
4797
+ (0, import_node_fs2.renameSync)(tmp, filePath);
4114
4798
  } catch (e) {
4115
4799
  try {
4116
4800
  (0, import_node_fs2.unlinkSync)(tmp);
@@ -4119,36 +4803,42 @@ var FileCheckpointAdapter = class {
4119
4803
  throw e;
4120
4804
  }
4121
4805
  }
4122
- load() {
4806
+ load(key) {
4123
4807
  try {
4124
- const text = (0, import_node_fs2.readFileSync)(this.#path, "utf8").trim();
4808
+ const text = (0, import_node_fs2.readFileSync)(this.#pathFor(key), "utf8").trim();
4125
4809
  if (!text) return null;
4126
- const data = JSON.parse(text);
4127
- return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
4810
+ return JSON.parse(text);
4128
4811
  } catch {
4129
4812
  return null;
4130
4813
  }
4131
4814
  }
4815
+ clear(key) {
4816
+ try {
4817
+ (0, import_node_fs2.unlinkSync)(this.#pathFor(key));
4818
+ } catch (e) {
4819
+ if (e.code !== "ENOENT") throw e;
4820
+ }
4821
+ }
4132
4822
  };
4133
4823
  var SqliteCheckpointAdapter = class {
4134
4824
  #db;
4135
- #key;
4136
- constructor(path, key = "graphrefly_checkpoint") {
4825
+ constructor(path) {
4137
4826
  this.#db = new import_node_sqlite.DatabaseSync(path);
4138
- this.#key = key;
4139
4827
  this.#db.exec(
4140
4828
  `CREATE TABLE IF NOT EXISTS graphrefly_checkpoint (k TEXT PRIMARY KEY, v TEXT NOT NULL)`
4141
4829
  );
4142
4830
  }
4143
- save(data) {
4144
- const payload = stableSnapshotJson(data).trimEnd();
4145
- this.#db.prepare(`INSERT OR REPLACE INTO graphrefly_checkpoint (k, v) VALUES (?, ?)`).run(this.#key, payload);
4831
+ save(key, data) {
4832
+ const payload = stableJsonString(data).trimEnd();
4833
+ this.#db.prepare(`INSERT OR REPLACE INTO graphrefly_checkpoint (k, v) VALUES (?, ?)`).run(key, payload);
4146
4834
  }
4147
- load() {
4148
- const row = this.#db.prepare(`SELECT v FROM graphrefly_checkpoint WHERE k = ?`).get(this.#key);
4835
+ load(key) {
4836
+ const row = this.#db.prepare(`SELECT v FROM graphrefly_checkpoint WHERE k = ?`).get(key);
4149
4837
  if (row === void 0 || typeof row.v !== "string" || row.v.trim() === "") return null;
4150
- const parsed = JSON.parse(row.v);
4151
- return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
4838
+ return JSON.parse(row.v);
4839
+ }
4840
+ clear(key) {
4841
+ this.#db.prepare(`DELETE FROM graphrefly_checkpoint WHERE k = ?`).run(key);
4152
4842
  }
4153
4843
  /** Close the underlying SQLite connection (safe to call more than once). */
4154
4844
  close() {
@@ -4159,10 +4849,10 @@ var SqliteCheckpointAdapter = class {
4159
4849
  }
4160
4850
  };
4161
4851
  function saveGraphCheckpoint(graph, adapter) {
4162
- adapter.save(graph.snapshot());
4852
+ adapter.save(graph.name, graph.snapshot());
4163
4853
  }
4164
4854
  function restoreGraphCheckpoint(graph, adapter) {
4165
- const data = adapter.load();
4855
+ const data = adapter.load(graph.name);
4166
4856
  if (data === null) return false;
4167
4857
  graph.restore(data);
4168
4858
  return true;
@@ -6027,48 +6717,6 @@ function audit(source, ms, opts) {
6027
6717
  }
6028
6718
  });
6029
6719
  }
6030
- function timeout(source, ms, opts) {
6031
- const { with: withPayload, ...timeoutNodeOpts } = opts ?? {};
6032
- let timer;
6033
- const err = withPayload ?? new Error("timeout");
6034
- function arm(a) {
6035
- clearTimeout(timer);
6036
- timer = setTimeout(() => {
6037
- timer = void 0;
6038
- a.down([[ERROR, err]]);
6039
- }, ms);
6040
- }
6041
- return node(
6042
- [source],
6043
- ([_v], a) => {
6044
- arm(a);
6045
- return () => clearTimeout(timer);
6046
- },
6047
- {
6048
- ...operatorOpts3(timeoutNodeOpts),
6049
- completeWhenDepsComplete: false,
6050
- onMessage(msg, _i, a) {
6051
- const t = msg[0];
6052
- if (t === DATA) {
6053
- arm(a);
6054
- a.down([msg]);
6055
- return true;
6056
- }
6057
- if (t === COMPLETE || t === ERROR) {
6058
- clearTimeout(timer);
6059
- a.down([msg]);
6060
- return true;
6061
- }
6062
- if (t === DIRTY || t === RESOLVED) {
6063
- a.down([msg]);
6064
- return true;
6065
- }
6066
- a.down([msg]);
6067
- return true;
6068
- }
6069
- }
6070
- );
6071
- }
6072
6720
  function buffer(source, notifier, opts) {
6073
6721
  const buf = [];
6074
6722
  return node([source, notifier], () => void 0, {
@@ -7625,11 +8273,14 @@ function workerSelf(target, opts) {
7625
8273
  NS_PER_MS,
7626
8274
  NS_PER_SEC,
7627
8275
  SqliteCheckpointAdapter,
8276
+ TimeoutError,
7628
8277
  audit,
7629
8278
  buffer,
7630
8279
  bufferCount,
7631
8280
  bufferTime,
8281
+ cache,
7632
8282
  cached,
8283
+ cascadingCache,
7633
8284
  catchError,
7634
8285
  checkpointNodeValue,
7635
8286
  checkpointToRedis,
@@ -7654,6 +8305,7 @@ function workerSelf(target, opts) {
7654
8305
  escapeRegexChar,
7655
8306
  exhaustMap,
7656
8307
  exponential,
8308
+ fallback,
7657
8309
  fibonacci,
7658
8310
  filter,
7659
8311
  find,
@@ -7666,6 +8318,7 @@ function workerSelf(target, opts) {
7666
8318
  fromCSV,
7667
8319
  fromClickHouseWatch,
7668
8320
  fromCron,
8321
+ fromDrizzle,
7669
8322
  fromEvent,
7670
8323
  fromFSWatch,
7671
8324
  fromGitHook,
@@ -7674,10 +8327,12 @@ function workerSelf(target, opts) {
7674
8327
  fromIDBTransaction,
7675
8328
  fromIter,
7676
8329
  fromKafka,
8330
+ fromKysely,
7677
8331
  fromMCP,
7678
8332
  fromNATS,
7679
8333
  fromNDJSON,
7680
8334
  fromOTel,
8335
+ fromPrisma,
7681
8336
  fromPrometheus,
7682
8337
  fromPromise,
7683
8338
  fromPulsar,
@@ -7695,6 +8350,7 @@ function workerSelf(target, opts) {
7695
8350
  last,
7696
8351
  linear,
7697
8352
  logSlice,
8353
+ lru,
7698
8354
  map,
7699
8355
  matchesAnyPattern,
7700
8356
  matchesCron,
@@ -7744,6 +8400,7 @@ function workerSelf(target, opts) {
7744
8400
  throttle,
7745
8401
  throttleTime,
7746
8402
  throwError,
8403
+ tieredStorage,
7747
8404
  timeout,
7748
8405
  toArray,
7749
8406
  toCSV,