@graphrefly/graphrefly 0.6.0 → 0.8.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-HP7OKEOE.js → chunk-A2AJJOSJ.js} +3 -3
  3. package/dist/chunk-A2AJJOSJ.js.map +1 -0
  4. package/dist/{chunk-CP6MNKAA.js → chunk-E7OH6ZAZ.js} +10 -4
  5. package/dist/{chunk-CP6MNKAA.js.map → chunk-E7OH6ZAZ.js.map} +1 -1
  6. package/dist/chunk-LR2CLSEF.js +106 -0
  7. package/dist/chunk-LR2CLSEF.js.map +1 -0
  8. package/dist/{chunk-5X3LAO3B.js → chunk-QTZSBQGJ.js} +79 -20
  9. package/dist/chunk-QTZSBQGJ.js.map +1 -0
  10. package/dist/{chunk-V3UACY6A.js → chunk-TZLX4KIT.js} +790 -203
  11. package/dist/chunk-TZLX4KIT.js.map +1 -0
  12. package/dist/{chunk-QW7H3ICI.js → chunk-UCW3VWMN.js} +4 -4
  13. package/dist/{chunk-6W5SGIGB.js → chunk-WYI7YW54.js} +142 -30
  14. package/dist/chunk-WYI7YW54.js.map +1 -0
  15. package/dist/chunk-WZ2Z2CRV.js +32 -0
  16. package/dist/chunk-WZ2Z2CRV.js.map +1 -0
  17. package/dist/{chunk-Z4Y4FMQN.js → chunk-XCZPGOVP.js} +7 -7
  18. package/dist/{chunk-KWXPDASV.js → chunk-YWTP2XRJ.js} +2 -2
  19. package/dist/compat/nestjs/index.cjs +268 -61
  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 +163 -35
  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 +892 -221
  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 +268 -61
  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-DqTICAY2.d.cts} +69 -12
  40. package/dist/{graph-D18qmsNm.d.ts → graph-X9uwnD_z.d.ts} +69 -12
  41. package/dist/{index-C3BMRmmp.d.cts → index-3U0WxdD-.d.cts} +3 -3
  42. package/dist/{index-Bk_idZm1.d.cts → index-BP1t_38S.d.cts} +406 -61
  43. package/dist/{index-BtK55IE2.d.ts → index-BPCeYDS4.d.ts} +4 -2
  44. package/dist/{index-Bvy_6CaN.d.ts → index-BVG5pjin.d.ts} +50 -5
  45. package/dist/{index-C5mqLhMX.d.cts → index-BYEgosAX.d.cts} +50 -5
  46. package/dist/{index-D_geH2Bm.d.cts → index-BYa2YMat.d.cts} +3 -3
  47. package/dist/{index-CP_QvbWu.d.ts → index-DLO8wnYU.d.ts} +3 -3
  48. package/dist/{index-B7eOdgEx.d.ts → index-DMv1Etbi.d.ts} +3 -3
  49. package/dist/{index-BvhgZRHK.d.cts → index-DbwgQ4Cw.d.cts} +4 -2
  50. package/dist/{index-B2jmzVxL.d.ts → index-a5gHmH5b.d.ts} +406 -61
  51. package/dist/index.cjs +2966 -1790
  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 +385 -20
  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 +268 -61
  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-BfX6bOSZ.d.cts} +2 -2
  65. package/dist/{reactive-log-ohLmTXoZ.d.ts → reactive-log-RhgIog2Z.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-UCW3VWMN.js.map} +0 -0
  74. /package/dist/{chunk-Z4Y4FMQN.js.map → chunk-XCZPGOVP.js.map} +0 -0
  75. /package/dist/{chunk-KWXPDASV.js.map → chunk-YWTP2XRJ.js.map} +0 -0
@@ -32,7 +32,10 @@ import {
32
32
  toArray,
33
33
  toMessages$,
34
34
  toObservable
35
- } from "./chunk-KWXPDASV.js";
35
+ } from "./chunk-YWTP2XRJ.js";
36
+ import {
37
+ ResettableTimer
38
+ } from "./chunk-WZ2Z2CRV.js";
36
39
  import {
37
40
  COMPLETE,
38
41
  DATA,
@@ -56,7 +59,7 @@ import {
56
59
  producer,
57
60
  state,
58
61
  wallClockNs
59
- } from "./chunk-5X3LAO3B.js";
62
+ } from "./chunk-QTZSBQGJ.js";
60
63
 
61
64
  // src/extra/index.ts
62
65
  var extra_exports = {};
@@ -68,11 +71,14 @@ __export(extra_exports, {
68
71
  NS_PER_MS: () => NS_PER_MS,
69
72
  NS_PER_SEC: () => NS_PER_SEC,
70
73
  SqliteCheckpointAdapter: () => SqliteCheckpointAdapter,
74
+ TimeoutError: () => TimeoutError,
71
75
  audit: () => audit,
72
76
  buffer: () => buffer,
73
77
  bufferCount: () => bufferCount,
74
78
  bufferTime: () => bufferTime,
79
+ cache: () => cache,
75
80
  cached: () => cached,
81
+ cascadingCache: () => cascadingCache,
76
82
  catchError: () => catchError,
77
83
  checkpointNodeValue: () => checkpointNodeValue,
78
84
  checkpointToRedis: () => checkpointToRedis,
@@ -97,6 +103,7 @@ __export(extra_exports, {
97
103
  escapeRegexChar: () => escapeRegexChar,
98
104
  exhaustMap: () => exhaustMap,
99
105
  exponential: () => exponential,
106
+ fallback: () => fallback,
100
107
  fibonacci: () => fibonacci,
101
108
  filter: () => filter,
102
109
  find: () => find,
@@ -109,6 +116,7 @@ __export(extra_exports, {
109
116
  fromCSV: () => fromCSV,
110
117
  fromClickHouseWatch: () => fromClickHouseWatch,
111
118
  fromCron: () => fromCron,
119
+ fromDrizzle: () => fromDrizzle,
112
120
  fromEvent: () => fromEvent,
113
121
  fromFSWatch: () => fromFSWatch,
114
122
  fromGitHook: () => fromGitHook,
@@ -117,10 +125,12 @@ __export(extra_exports, {
117
125
  fromIDBTransaction: () => fromIDBTransaction,
118
126
  fromIter: () => fromIter,
119
127
  fromKafka: () => fromKafka,
128
+ fromKysely: () => fromKysely,
120
129
  fromMCP: () => fromMCP,
121
130
  fromNATS: () => fromNATS,
122
131
  fromNDJSON: () => fromNDJSON,
123
132
  fromOTel: () => fromOTel,
133
+ fromPrisma: () => fromPrisma,
124
134
  fromPrometheus: () => fromPrometheus,
125
135
  fromPromise: () => fromPromise,
126
136
  fromPulsar: () => fromPulsar,
@@ -138,6 +148,7 @@ __export(extra_exports, {
138
148
  last: () => last,
139
149
  linear: () => linear,
140
150
  logSlice: () => logSlice,
151
+ lru: () => lru,
141
152
  map: () => map,
142
153
  matchesAnyPattern: () => matchesAnyPattern,
143
154
  matchesCron: () => matchesCron,
@@ -187,6 +198,7 @@ __export(extra_exports, {
187
198
  throttle: () => throttle,
188
199
  throttleTime: () => throttleTime,
189
200
  throwError: () => throwError,
201
+ tieredStorage: () => tieredStorage,
190
202
  timeout: () => timeout,
191
203
  toArray: () => toArray,
192
204
  toCSV: () => toCSV,
@@ -344,14 +356,7 @@ function retry(source, opts) {
344
356
  let stopped = false;
345
357
  let prevDelay = null;
346
358
  let unsub;
347
- let timer;
348
- let timerGen = 0;
349
- function cancelTimer() {
350
- if (timer !== void 0) {
351
- clearTimeout(timer);
352
- timer = void 0;
353
- }
354
- }
359
+ const timer = new ResettableTimer();
355
360
  function disconnectUpstream() {
356
361
  unsub?.();
357
362
  unsub = void 0;
@@ -367,20 +372,18 @@ function retry(source, opts) {
367
372
  const delayNs = coerceDelayNs(raw === void 0 ? null : raw);
368
373
  prevDelay = delayNs;
369
374
  attempt += 1;
370
- timerGen += 1;
371
- const gen = timerGen;
372
375
  disconnectUpstream();
373
376
  const delayMs = delayNs > 0 ? delayNs / NS_PER_MS : 1;
374
- timer = setTimeout(() => {
375
- timer = void 0;
376
- if (stopped || gen !== timerGen) return;
377
+ timer.start(delayMs, () => {
378
+ if (stopped) return;
377
379
  connect();
378
- }, delayMs);
380
+ });
379
381
  }
380
382
  function connect() {
381
- cancelTimer();
383
+ timer.cancel();
382
384
  disconnectUpstream();
383
385
  unsub = source.subscribe((msgs) => {
386
+ if (stopped) return;
384
387
  for (const m of msgs) {
385
388
  const t = m[0];
386
389
  if (t === DIRTY) a.down([[DIRTY]]);
@@ -402,8 +405,7 @@ function retry(source, opts) {
402
405
  connect();
403
406
  return () => {
404
407
  stopped = true;
405
- timerGen += 1;
406
- cancelTimer();
408
+ timer.cancel();
407
409
  disconnectUpstream();
408
410
  };
409
411
  },
@@ -583,14 +585,7 @@ function rateLimiter(source, maxEvents, windowNs) {
583
585
  (_d, a) => {
584
586
  const times = [];
585
587
  const pending = [];
586
- let timer;
587
- let timerGen = 0;
588
- function cancelTimer() {
589
- if (timer !== void 0) {
590
- clearTimeout(timer);
591
- timer = void 0;
592
- }
593
- }
588
+ const timer = new ResettableTimer();
594
589
  function prune(now) {
595
590
  const boundary = now - windowNs;
596
591
  while (times.length > 0 && times[0] <= boundary) times.shift();
@@ -604,15 +599,10 @@ function rateLimiter(source, maxEvents, windowNs) {
604
599
  a.emit(pending.shift());
605
600
  } else {
606
601
  const oldest = times[0];
607
- cancelTimer();
608
- timerGen += 1;
609
- const gen = timerGen;
610
602
  const delayNs = Math.max(0, oldest + windowNs - monotonicNs());
611
- timer = setTimeout(() => {
612
- timer = void 0;
613
- if (gen !== timerGen) return;
603
+ timer.start(delayNs / NS_PER_MS, () => {
614
604
  tryEmit();
615
- }, delayNs / NS_PER_MS);
605
+ });
616
606
  return;
617
607
  }
618
608
  }
@@ -626,14 +616,12 @@ function rateLimiter(source, maxEvents, windowNs) {
626
616
  tryEmit();
627
617
  } else if (t === RESOLVED) a.down([[RESOLVED]]);
628
618
  else if (t === COMPLETE) {
629
- timerGen += 1;
630
- cancelTimer();
619
+ timer.cancel();
631
620
  pending.length = 0;
632
621
  times.length = 0;
633
622
  a.down([[COMPLETE]]);
634
623
  } else if (t === ERROR) {
635
- timerGen += 1;
636
- cancelTimer();
624
+ timer.cancel();
637
625
  pending.length = 0;
638
626
  times.length = 0;
639
627
  a.down([m]);
@@ -641,8 +629,7 @@ function rateLimiter(source, maxEvents, windowNs) {
641
629
  }
642
630
  });
643
631
  return () => {
644
- timerGen += 1;
645
- cancelTimer();
632
+ timer.cancel();
646
633
  unsub();
647
634
  };
648
635
  },
@@ -703,8 +690,160 @@ function withStatus(src, options) {
703
690
  error: out.meta.error
704
691
  };
705
692
  }
693
+ var TimeoutError = class extends Error {
694
+ name = "TimeoutError";
695
+ constructor(ns) {
696
+ super(`Timed out after ${ns / NS_PER_MS}ms`);
697
+ }
698
+ };
699
+ function isNode(x) {
700
+ return x != null && typeof x.subscribe === "function" && typeof x.get === "function";
701
+ }
702
+ function fallback(source, fb) {
703
+ return producer(
704
+ (_d, a) => {
705
+ let fallbackUnsub;
706
+ let sourceUnsub;
707
+ sourceUnsub = source.subscribe((msgs) => {
708
+ for (const m of msgs) {
709
+ const t = m[0];
710
+ if (t === DIRTY) a.down([[DIRTY]]);
711
+ else if (t === DATA) a.emit(m[1]);
712
+ else if (t === RESOLVED) a.down([[RESOLVED]]);
713
+ else if (t === COMPLETE) a.down([[COMPLETE]]);
714
+ else if (t === ERROR) {
715
+ sourceUnsub?.();
716
+ if (isNode(fb)) {
717
+ fallbackUnsub = fb.subscribe((fMsgs) => {
718
+ a.down(fMsgs);
719
+ });
720
+ const cur = fb.get();
721
+ if (cur !== void 0) a.down([[DATA, cur]]);
722
+ } else {
723
+ a.emit(fb);
724
+ a.down([[COMPLETE]]);
725
+ }
726
+ return;
727
+ } else if (t === TEARDOWN) {
728
+ fallbackUnsub?.();
729
+ a.down([m]);
730
+ return;
731
+ } else a.down([m]);
732
+ }
733
+ });
734
+ return () => {
735
+ sourceUnsub?.();
736
+ fallbackUnsub?.();
737
+ };
738
+ },
739
+ {
740
+ ...operatorOpts(),
741
+ initial: source.get()
742
+ }
743
+ );
744
+ }
745
+ function timeout(source, timeoutNs) {
746
+ if (timeoutNs <= 0) throw new RangeError("timeoutNs must be > 0");
747
+ return producer(
748
+ (_d, a) => {
749
+ let stopped = false;
750
+ const timer = new ResettableTimer();
751
+ function startTimer() {
752
+ const delayMs = timeoutNs / NS_PER_MS;
753
+ timer.start(delayMs, () => {
754
+ if (stopped) return;
755
+ stopped = true;
756
+ unsub();
757
+ a.down([[ERROR, new TimeoutError(timeoutNs)]]);
758
+ });
759
+ }
760
+ const unsub = source.subscribe((msgs) => {
761
+ for (const m of msgs) {
762
+ if (stopped) return;
763
+ const t = m[0];
764
+ if (t === DIRTY) a.down([[DIRTY]]);
765
+ else if (t === DATA) {
766
+ startTimer();
767
+ a.emit(m[1]);
768
+ } else if (t === RESOLVED) a.down([[RESOLVED]]);
769
+ else if (t === COMPLETE) {
770
+ timer.cancel();
771
+ stopped = true;
772
+ a.down([[COMPLETE]]);
773
+ return;
774
+ } else if (t === ERROR) {
775
+ timer.cancel();
776
+ stopped = true;
777
+ a.down([m]);
778
+ return;
779
+ } else if (t === TEARDOWN) {
780
+ timer.cancel();
781
+ stopped = true;
782
+ a.down([m]);
783
+ return;
784
+ } else a.down([m]);
785
+ }
786
+ });
787
+ startTimer();
788
+ return () => {
789
+ stopped = true;
790
+ timer.cancel();
791
+ unsub();
792
+ };
793
+ },
794
+ {
795
+ ...operatorOpts(),
796
+ initial: source.get()
797
+ }
798
+ );
799
+ }
800
+ function cache(source, ttlNs) {
801
+ if (ttlNs <= 0) throw new RangeError("ttlNs must be > 0");
802
+ let cachedValue;
803
+ let cachedAt = 0;
804
+ let hasCached = false;
805
+ return producer(
806
+ (_d, a) => {
807
+ if (hasCached && monotonicNs() - cachedAt < ttlNs) {
808
+ a.down([[DATA, cachedValue]]);
809
+ }
810
+ const unsub = source.subscribe((msgs) => {
811
+ for (const m of msgs) {
812
+ const t = m[0];
813
+ if (t === DATA) {
814
+ cachedValue = m[1];
815
+ cachedAt = monotonicNs();
816
+ hasCached = true;
817
+ a.emit(cachedValue);
818
+ } else if (t === DIRTY) a.down([[DIRTY]]);
819
+ else if (t === RESOLVED) a.down([[RESOLVED]]);
820
+ else if (t === COMPLETE) a.down([[COMPLETE]]);
821
+ else if (t === ERROR) a.down([m]);
822
+ else a.down([m]);
823
+ }
824
+ });
825
+ return unsub;
826
+ },
827
+ {
828
+ ...operatorOpts(),
829
+ resubscribable: true,
830
+ initial: source.get()
831
+ }
832
+ );
833
+ }
706
834
 
707
835
  // src/extra/adapters.ts
836
+ function createSinkErrorHandler(userHandler) {
837
+ const errorsNode = state(null);
838
+ const handler = (err) => {
839
+ userHandler?.(err);
840
+ try {
841
+ errorsNode.down([[DATA, err]]);
842
+ } catch {
843
+ }
844
+ };
845
+ return { errorsNode, handler };
846
+ }
708
847
  function sourceOpts(opts) {
709
848
  return { describeKind: "producer", ...opts };
710
849
  }
@@ -1455,6 +1594,7 @@ function toKafka(source, kafkaProducer, topic, opts) {
1455
1594
  onTransportError,
1456
1595
  ...rest
1457
1596
  } = opts ?? {};
1597
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
1458
1598
  const inner = node([source], () => void 0, {
1459
1599
  describeKind: "effect",
1460
1600
  ...rest,
@@ -1466,7 +1606,7 @@ function toKafka(source, kafkaProducer, topic, opts) {
1466
1606
  try {
1467
1607
  serialized = serialize(value);
1468
1608
  } catch (err) {
1469
- onTransportError?.({
1609
+ handler({
1470
1610
  stage: "serialize",
1471
1611
  error: err instanceof Error ? err : new Error(String(err)),
1472
1612
  value
@@ -1477,7 +1617,7 @@ function toKafka(source, kafkaProducer, topic, opts) {
1477
1617
  topic,
1478
1618
  messages: [{ key, value: Buffer.from(serialized) }]
1479
1619
  }).catch((err) => {
1480
- onTransportError?.({
1620
+ handler({
1481
1621
  stage: "send",
1482
1622
  error: err instanceof Error ? err : new Error(String(err)),
1483
1623
  value
@@ -1488,8 +1628,15 @@ function toKafka(source, kafkaProducer, topic, opts) {
1488
1628
  return false;
1489
1629
  }
1490
1630
  });
1491
- return inner.subscribe(() => {
1631
+ const unsub = inner.subscribe(() => {
1492
1632
  });
1633
+ return {
1634
+ dispose: () => {
1635
+ unsub();
1636
+ errorsNode.down([[TEARDOWN]]);
1637
+ },
1638
+ errors: errorsNode
1639
+ };
1493
1640
  }
1494
1641
  function fromRedisStream(client, key, opts) {
1495
1642
  const {
@@ -1554,6 +1701,7 @@ function toRedisStream(source, client, key, opts) {
1554
1701
  onTransportError,
1555
1702
  ...rest
1556
1703
  } = opts ?? {};
1704
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
1557
1705
  const inner = node([source], () => void 0, {
1558
1706
  describeKind: "effect",
1559
1707
  ...rest,
@@ -1564,7 +1712,7 @@ function toRedisStream(source, client, key, opts) {
1564
1712
  try {
1565
1713
  fields = serialize(value);
1566
1714
  } catch (err) {
1567
- onTransportError?.({
1715
+ handler({
1568
1716
  stage: "serialize",
1569
1717
  error: err instanceof Error ? err : new Error(String(err)),
1570
1718
  value
@@ -1573,7 +1721,7 @@ function toRedisStream(source, client, key, opts) {
1573
1721
  }
1574
1722
  const send = maxLen !== void 0 ? client.xadd(key, "MAXLEN", "~", String(maxLen), "*", ...fields) : client.xadd(key, "*", ...fields);
1575
1723
  void send.catch((err) => {
1576
- onTransportError?.({
1724
+ handler({
1577
1725
  stage: "send",
1578
1726
  error: err instanceof Error ? err : new Error(String(err)),
1579
1727
  value
@@ -1584,8 +1732,15 @@ function toRedisStream(source, client, key, opts) {
1584
1732
  return false;
1585
1733
  }
1586
1734
  });
1587
- return inner.subscribe(() => {
1735
+ const unsub = inner.subscribe(() => {
1588
1736
  });
1737
+ return {
1738
+ dispose: () => {
1739
+ unsub();
1740
+ errorsNode.down([[TEARDOWN]]);
1741
+ },
1742
+ errors: errorsNode
1743
+ };
1589
1744
  }
1590
1745
  function fromCSV(source, opts) {
1591
1746
  const {
@@ -1812,6 +1967,7 @@ function toPulsar(source, pulsarProducer, opts) {
1812
1967
  onTransportError,
1813
1968
  ...rest
1814
1969
  } = opts ?? {};
1970
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
1815
1971
  const inner = node([source], () => void 0, {
1816
1972
  describeKind: "effect",
1817
1973
  ...rest,
@@ -1822,7 +1978,7 @@ function toPulsar(source, pulsarProducer, opts) {
1822
1978
  try {
1823
1979
  data = serialize(value);
1824
1980
  } catch (err) {
1825
- onTransportError?.({
1981
+ handler({
1826
1982
  stage: "serialize",
1827
1983
  error: err instanceof Error ? err : new Error(String(err)),
1828
1984
  value
@@ -1834,7 +1990,7 @@ function toPulsar(source, pulsarProducer, opts) {
1834
1990
  partitionKey: keyExtractor?.(value),
1835
1991
  properties: propertiesExtractor?.(value)
1836
1992
  }).catch((err) => {
1837
- onTransportError?.({
1993
+ handler({
1838
1994
  stage: "send",
1839
1995
  error: err instanceof Error ? err : new Error(String(err)),
1840
1996
  value
@@ -1845,8 +2001,15 @@ function toPulsar(source, pulsarProducer, opts) {
1845
2001
  return false;
1846
2002
  }
1847
2003
  });
1848
- return inner.subscribe(() => {
2004
+ const unsub = inner.subscribe(() => {
1849
2005
  });
2006
+ return {
2007
+ dispose: () => {
2008
+ unsub();
2009
+ errorsNode.down([[TEARDOWN]]);
2010
+ },
2011
+ errors: errorsNode
2012
+ };
1850
2013
  }
1851
2014
  function fromNATS(client, subject, opts) {
1852
2015
  const decoder = new TextDecoder();
@@ -1902,6 +2065,7 @@ function toNATS(source, client, subject, opts) {
1902
2065
  onTransportError,
1903
2066
  ...rest
1904
2067
  } = opts ?? {};
2068
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
1905
2069
  const inner = node([source], () => void 0, {
1906
2070
  describeKind: "effect",
1907
2071
  ...rest,
@@ -1912,7 +2076,7 @@ function toNATS(source, client, subject, opts) {
1912
2076
  try {
1913
2077
  data = serialize(value);
1914
2078
  } catch (err) {
1915
- onTransportError?.({
2079
+ handler({
1916
2080
  stage: "serialize",
1917
2081
  error: err instanceof Error ? err : new Error(String(err)),
1918
2082
  value
@@ -1922,7 +2086,7 @@ function toNATS(source, client, subject, opts) {
1922
2086
  try {
1923
2087
  client.publish(subject, data);
1924
2088
  } catch (err) {
1925
- onTransportError?.({
2089
+ handler({
1926
2090
  stage: "send",
1927
2091
  error: err instanceof Error ? err : new Error(String(err)),
1928
2092
  value
@@ -1933,8 +2097,15 @@ function toNATS(source, client, subject, opts) {
1933
2097
  return false;
1934
2098
  }
1935
2099
  });
1936
- return inner.subscribe(() => {
2100
+ const unsub = inner.subscribe(() => {
1937
2101
  });
2102
+ return {
2103
+ dispose: () => {
2104
+ unsub();
2105
+ errorsNode.down([[TEARDOWN]]);
2106
+ },
2107
+ errors: errorsNode
2108
+ };
1938
2109
  }
1939
2110
  function fromRabbitMQ(channel, queue, opts) {
1940
2111
  const {
@@ -1996,6 +2167,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
1996
2167
  onTransportError,
1997
2168
  ...rest
1998
2169
  } = opts ?? {};
2170
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
1999
2171
  const inner = node([source], () => void 0, {
2000
2172
  describeKind: "effect",
2001
2173
  ...rest,
@@ -2006,7 +2178,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
2006
2178
  try {
2007
2179
  routingKey = routingKeyExtractor(value);
2008
2180
  } catch (err) {
2009
- onTransportError?.({
2181
+ handler({
2010
2182
  stage: "routing_key",
2011
2183
  error: err instanceof Error ? err : new Error(String(err)),
2012
2184
  value
@@ -2017,7 +2189,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
2017
2189
  try {
2018
2190
  content = serialize(value);
2019
2191
  } catch (err) {
2020
- onTransportError?.({
2192
+ handler({
2021
2193
  stage: "serialize",
2022
2194
  error: err instanceof Error ? err : new Error(String(err)),
2023
2195
  value
@@ -2027,7 +2199,7 @@ function toRabbitMQ(source, channel, exchange, opts) {
2027
2199
  try {
2028
2200
  channel.publish(exchange, routingKey, content);
2029
2201
  } catch (err) {
2030
- onTransportError?.({
2202
+ handler({
2031
2203
  stage: "send",
2032
2204
  error: err instanceof Error ? err : new Error(String(err)),
2033
2205
  value
@@ -2038,8 +2210,15 @@ function toRabbitMQ(source, channel, exchange, opts) {
2038
2210
  return false;
2039
2211
  }
2040
2212
  });
2041
- return inner.subscribe(() => {
2213
+ const unsub = inner.subscribe(() => {
2042
2214
  });
2215
+ return {
2216
+ dispose: () => {
2217
+ unsub();
2218
+ errorsNode.down([[TEARDOWN]]);
2219
+ },
2220
+ errors: errorsNode
2221
+ };
2043
2222
  }
2044
2223
  function toFile(source, writer, opts) {
2045
2224
  const {
@@ -2051,8 +2230,10 @@ function toFile(source, writer, opts) {
2051
2230
  mode: _mode,
2052
2231
  ...rest
2053
2232
  } = opts ?? {};
2233
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2054
2234
  let buffer2 = [];
2055
2235
  let timer;
2236
+ let disposed = false;
2056
2237
  const doFlush = () => {
2057
2238
  if (buffer2.length === 0) return;
2058
2239
  const chunk = buffer2.join("");
@@ -2060,7 +2241,7 @@ function toFile(source, writer, opts) {
2060
2241
  try {
2061
2242
  writer.write(chunk);
2062
2243
  } catch (err) {
2063
- onTransportError?.({
2244
+ handler({
2064
2245
  stage: "send",
2065
2246
  error: err instanceof Error ? err : new Error(String(err)),
2066
2247
  value: chunk
@@ -2068,7 +2249,7 @@ function toFile(source, writer, opts) {
2068
2249
  }
2069
2250
  };
2070
2251
  const scheduleFlush = () => {
2071
- if (flushIntervalMs > 0 && timer === void 0) {
2252
+ if (flushIntervalMs > 0 && timer === void 0 && !disposed) {
2072
2253
  timer = setTimeout(() => {
2073
2254
  timer = void 0;
2074
2255
  doFlush();
@@ -2086,7 +2267,7 @@ function toFile(source, writer, opts) {
2086
2267
  try {
2087
2268
  line = serialize(value);
2088
2269
  } catch (err) {
2089
- onTransportError?.({
2270
+ handler({
2090
2271
  stage: "serialize",
2091
2272
  error: err instanceof Error ? err : new Error(String(err)),
2092
2273
  value
@@ -2101,7 +2282,7 @@ function toFile(source, writer, opts) {
2101
2282
  try {
2102
2283
  writer.write(line);
2103
2284
  } catch (err) {
2104
- onTransportError?.({
2285
+ handler({
2105
2286
  stage: "send",
2106
2287
  error: err instanceof Error ? err : new Error(String(err)),
2107
2288
  value
@@ -2110,7 +2291,7 @@ function toFile(source, writer, opts) {
2110
2291
  }
2111
2292
  return true;
2112
2293
  }
2113
- if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
2294
+ if (messageTier(msg[0]) >= 3) {
2114
2295
  doFlush();
2115
2296
  }
2116
2297
  return false;
@@ -2119,18 +2300,25 @@ function toFile(source, writer, opts) {
2119
2300
  const unsub = inner.subscribe(() => {
2120
2301
  });
2121
2302
  const dispose = () => {
2303
+ if (disposed) return;
2304
+ disposed = true;
2122
2305
  if (timer !== void 0) {
2123
2306
  clearTimeout(timer);
2124
2307
  timer = void 0;
2125
2308
  }
2126
2309
  doFlush();
2127
- writer.end();
2310
+ try {
2311
+ writer.end();
2312
+ } catch {
2313
+ }
2128
2314
  unsub();
2315
+ errorsNode.down([[TEARDOWN]]);
2129
2316
  };
2130
2317
  return {
2131
2318
  dispose,
2319
+ errors: errorsNode,
2132
2320
  flush: async () => {
2133
- doFlush();
2321
+ if (!disposed) doFlush();
2134
2322
  }
2135
2323
  };
2136
2324
  }
@@ -2181,25 +2369,29 @@ function toClickHouse(source, client, table, opts) {
2181
2369
  onTransportError,
2182
2370
  ...rest
2183
2371
  } = opts ?? {};
2372
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2184
2373
  let buffer2 = [];
2185
2374
  let timer;
2186
- let lastFlush = Promise.resolve();
2375
+ let disposed = false;
2376
+ const inFlight = /* @__PURE__ */ new Set();
2187
2377
  const doFlush = () => {
2188
2378
  if (buffer2.length === 0) return Promise.resolve();
2189
2379
  const batch2 = buffer2;
2190
2380
  buffer2 = [];
2191
2381
  try {
2192
2382
  const p = client.insert({ table, values: batch2, format }).catch((err) => {
2193
- onTransportError?.({
2383
+ handler({
2194
2384
  stage: "send",
2195
2385
  error: err instanceof Error ? err : new Error(String(err)),
2196
2386
  value: batch2
2197
2387
  });
2388
+ }).finally(() => {
2389
+ inFlight.delete(p);
2198
2390
  });
2199
- lastFlush = p;
2391
+ inFlight.add(p);
2200
2392
  return p;
2201
2393
  } catch (err) {
2202
- onTransportError?.({
2394
+ handler({
2203
2395
  stage: "send",
2204
2396
  error: err instanceof Error ? err : new Error(String(err)),
2205
2397
  value: batch2
@@ -2208,7 +2400,7 @@ function toClickHouse(source, client, table, opts) {
2208
2400
  }
2209
2401
  };
2210
2402
  const scheduleFlush = () => {
2211
- if (timer === void 0) {
2403
+ if (timer === void 0 && !disposed) {
2212
2404
  timer = setTimeout(() => {
2213
2405
  timer = void 0;
2214
2406
  doFlush();
@@ -2224,7 +2416,7 @@ function toClickHouse(source, client, table, opts) {
2224
2416
  try {
2225
2417
  buffer2.push(transform(value));
2226
2418
  } catch (err) {
2227
- onTransportError?.({
2419
+ handler({
2228
2420
  stage: "serialize",
2229
2421
  error: err instanceof Error ? err : new Error(String(err)),
2230
2422
  value
@@ -2235,7 +2427,7 @@ function toClickHouse(source, client, table, opts) {
2235
2427
  else scheduleFlush();
2236
2428
  return true;
2237
2429
  }
2238
- if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
2430
+ if (messageTier(msg[0]) >= 3) {
2239
2431
  doFlush();
2240
2432
  }
2241
2433
  return false;
@@ -2244,16 +2436,24 @@ function toClickHouse(source, client, table, opts) {
2244
2436
  const unsub = inner.subscribe(() => {
2245
2437
  });
2246
2438
  const dispose = () => {
2439
+ if (disposed) return;
2440
+ disposed = true;
2247
2441
  if (timer !== void 0) {
2248
2442
  clearTimeout(timer);
2249
2443
  timer = void 0;
2250
2444
  }
2251
2445
  doFlush();
2252
2446
  unsub();
2447
+ errorsNode.down([[TEARDOWN]]);
2253
2448
  };
2254
2449
  return {
2255
2450
  dispose,
2256
- flush: () => doFlush().then(() => lastFlush)
2451
+ errors: errorsNode,
2452
+ flush: () => {
2453
+ const p = disposed ? Promise.resolve() : doFlush();
2454
+ return p.then(() => Promise.all(inFlight)).then(() => {
2455
+ });
2456
+ }
2257
2457
  };
2258
2458
  }
2259
2459
  function toS3(source, client, bucket, opts) {
@@ -2270,10 +2470,12 @@ function toS3(source, client, bucket, opts) {
2270
2470
  onTransportError,
2271
2471
  ...rest
2272
2472
  } = opts ?? {};
2473
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2273
2474
  let buffer2 = [];
2274
2475
  let timer;
2275
2476
  let seq = 0;
2276
- let lastFlush = Promise.resolve();
2477
+ let disposed = false;
2478
+ const inFlight = /* @__PURE__ */ new Set();
2277
2479
  const doFlush = () => {
2278
2480
  if (buffer2.length === 0) return Promise.resolve();
2279
2481
  const batch2 = buffer2;
@@ -2286,16 +2488,18 @@ function toS3(source, client, bucket, opts) {
2286
2488
  try {
2287
2489
  const p = client.putObject({ Bucket: bucket, Key: key, Body: body, ContentType: contentType }).then(() => {
2288
2490
  }).catch((err) => {
2289
- onTransportError?.({
2491
+ handler({
2290
2492
  stage: "send",
2291
2493
  error: err instanceof Error ? err : new Error(String(err)),
2292
2494
  value: batch2
2293
2495
  });
2496
+ }).finally(() => {
2497
+ inFlight.delete(p);
2294
2498
  });
2295
- lastFlush = p;
2499
+ inFlight.add(p);
2296
2500
  return p;
2297
2501
  } catch (err) {
2298
- onTransportError?.({
2502
+ handler({
2299
2503
  stage: "send",
2300
2504
  error: err instanceof Error ? err : new Error(String(err)),
2301
2505
  value: batch2
@@ -2304,7 +2508,7 @@ function toS3(source, client, bucket, opts) {
2304
2508
  }
2305
2509
  };
2306
2510
  const scheduleFlush = () => {
2307
- if (timer === void 0) {
2511
+ if (timer === void 0 && !disposed) {
2308
2512
  timer = setTimeout(() => {
2309
2513
  timer = void 0;
2310
2514
  doFlush();
@@ -2320,7 +2524,7 @@ function toS3(source, client, bucket, opts) {
2320
2524
  try {
2321
2525
  buffer2.push(transform(value));
2322
2526
  } catch (err) {
2323
- onTransportError?.({
2527
+ handler({
2324
2528
  stage: "serialize",
2325
2529
  error: err instanceof Error ? err : new Error(String(err)),
2326
2530
  value
@@ -2331,7 +2535,7 @@ function toS3(source, client, bucket, opts) {
2331
2535
  else scheduleFlush();
2332
2536
  return true;
2333
2537
  }
2334
- if (msg[0] === COMPLETE || msg[0] === TEARDOWN) {
2538
+ if (messageTier(msg[0]) >= 3) {
2335
2539
  doFlush();
2336
2540
  }
2337
2541
  return false;
@@ -2340,16 +2544,24 @@ function toS3(source, client, bucket, opts) {
2340
2544
  const unsub = inner.subscribe(() => {
2341
2545
  });
2342
2546
  const dispose = () => {
2547
+ if (disposed) return;
2548
+ disposed = true;
2343
2549
  if (timer !== void 0) {
2344
2550
  clearTimeout(timer);
2345
2551
  timer = void 0;
2346
2552
  }
2347
2553
  doFlush();
2348
2554
  unsub();
2555
+ errorsNode.down([[TEARDOWN]]);
2349
2556
  };
2350
2557
  return {
2351
2558
  dispose,
2352
- flush: () => doFlush().then(() => lastFlush)
2559
+ errors: errorsNode,
2560
+ flush: () => {
2561
+ const p = disposed ? Promise.resolve() : doFlush();
2562
+ return p.then(() => Promise.all(inFlight)).then(() => {
2563
+ });
2564
+ }
2353
2565
  };
2354
2566
  }
2355
2567
  function toPostgres(source, client, table, opts) {
@@ -2361,6 +2573,7 @@ function toPostgres(source, client, table, opts) {
2361
2573
  onTransportError,
2362
2574
  ...rest
2363
2575
  } = opts ?? {};
2576
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2364
2577
  const inner = node([source], () => void 0, {
2365
2578
  describeKind: "effect",
2366
2579
  ...rest,
@@ -2371,7 +2584,7 @@ function toPostgres(source, client, table, opts) {
2371
2584
  try {
2372
2585
  query = toSQL(value, table);
2373
2586
  } catch (err) {
2374
- onTransportError?.({
2587
+ handler({
2375
2588
  stage: "serialize",
2376
2589
  error: err instanceof Error ? err : new Error(String(err)),
2377
2590
  value
@@ -2379,7 +2592,7 @@ function toPostgres(source, client, table, opts) {
2379
2592
  return true;
2380
2593
  }
2381
2594
  void client.query(query.sql, query.params).catch((err) => {
2382
- onTransportError?.({
2595
+ handler({
2383
2596
  stage: "send",
2384
2597
  error: err instanceof Error ? err : new Error(String(err)),
2385
2598
  value
@@ -2390,11 +2603,19 @@ function toPostgres(source, client, table, opts) {
2390
2603
  return false;
2391
2604
  }
2392
2605
  });
2393
- return inner.subscribe(() => {
2606
+ const unsub = inner.subscribe(() => {
2394
2607
  });
2608
+ return {
2609
+ dispose: () => {
2610
+ unsub();
2611
+ errorsNode.down([[TEARDOWN]]);
2612
+ },
2613
+ errors: errorsNode
2614
+ };
2395
2615
  }
2396
2616
  function toMongo(source, collection, opts) {
2397
2617
  const { toDocument = (v) => v, onTransportError, ...rest } = opts ?? {};
2618
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2398
2619
  const inner = node([source], () => void 0, {
2399
2620
  describeKind: "effect",
2400
2621
  ...rest,
@@ -2405,7 +2626,7 @@ function toMongo(source, collection, opts) {
2405
2626
  try {
2406
2627
  doc = toDocument(value);
2407
2628
  } catch (err) {
2408
- onTransportError?.({
2629
+ handler({
2409
2630
  stage: "serialize",
2410
2631
  error: err instanceof Error ? err : new Error(String(err)),
2411
2632
  value
@@ -2413,7 +2634,7 @@ function toMongo(source, collection, opts) {
2413
2634
  return true;
2414
2635
  }
2415
2636
  void collection.insertOne(doc).catch((err) => {
2416
- onTransportError?.({
2637
+ handler({
2417
2638
  stage: "send",
2418
2639
  error: err instanceof Error ? err : new Error(String(err)),
2419
2640
  value
@@ -2424,8 +2645,15 @@ function toMongo(source, collection, opts) {
2424
2645
  return false;
2425
2646
  }
2426
2647
  });
2427
- return inner.subscribe(() => {
2648
+ const unsub = inner.subscribe(() => {
2428
2649
  });
2650
+ return {
2651
+ dispose: () => {
2652
+ unsub();
2653
+ errorsNode.down([[TEARDOWN]]);
2654
+ },
2655
+ errors: errorsNode
2656
+ };
2429
2657
  }
2430
2658
  function toLoki(source, client, opts) {
2431
2659
  const {
@@ -2435,6 +2663,7 @@ function toLoki(source, client, opts) {
2435
2663
  onTransportError,
2436
2664
  ...rest
2437
2665
  } = opts ?? {};
2666
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2438
2667
  const inner = node([source], () => void 0, {
2439
2668
  describeKind: "effect",
2440
2669
  ...rest,
@@ -2445,7 +2674,7 @@ function toLoki(source, client, opts) {
2445
2674
  try {
2446
2675
  line = toLine(value);
2447
2676
  } catch (err) {
2448
- onTransportError?.({
2677
+ handler({
2449
2678
  stage: "serialize",
2450
2679
  error: err instanceof Error ? err : new Error(String(err)),
2451
2680
  value
@@ -2456,7 +2685,7 @@ function toLoki(source, client, opts) {
2456
2685
  try {
2457
2686
  streamLabels = toLabels ? { ...labels, ...toLabels(value) } : labels;
2458
2687
  } catch (err) {
2459
- onTransportError?.({
2688
+ handler({
2460
2689
  stage: "serialize",
2461
2690
  error: err instanceof Error ? err : new Error(String(err)),
2462
2691
  value
@@ -2465,7 +2694,7 @@ function toLoki(source, client, opts) {
2465
2694
  }
2466
2695
  const ts = `${wallClockNs()}`;
2467
2696
  void client.push({ streams: [{ stream: streamLabels, values: [[ts, line]] }] }).catch((err) => {
2468
- onTransportError?.({
2697
+ handler({
2469
2698
  stage: "send",
2470
2699
  error: err instanceof Error ? err : new Error(String(err)),
2471
2700
  value
@@ -2476,11 +2705,19 @@ function toLoki(source, client, opts) {
2476
2705
  return false;
2477
2706
  }
2478
2707
  });
2479
- return inner.subscribe(() => {
2708
+ const unsub = inner.subscribe(() => {
2480
2709
  });
2710
+ return {
2711
+ dispose: () => {
2712
+ unsub();
2713
+ errorsNode.down([[TEARDOWN]]);
2714
+ },
2715
+ errors: errorsNode
2716
+ };
2481
2717
  }
2482
2718
  function toTempo(source, client, opts) {
2483
2719
  const { toResourceSpans = (v) => [v], onTransportError, ...rest } = opts ?? {};
2720
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2484
2721
  const inner = node([source], () => void 0, {
2485
2722
  describeKind: "effect",
2486
2723
  ...rest,
@@ -2491,7 +2728,7 @@ function toTempo(source, client, opts) {
2491
2728
  try {
2492
2729
  spans = toResourceSpans(value);
2493
2730
  } catch (err) {
2494
- onTransportError?.({
2731
+ handler({
2495
2732
  stage: "serialize",
2496
2733
  error: err instanceof Error ? err : new Error(String(err)),
2497
2734
  value
@@ -2499,7 +2736,7 @@ function toTempo(source, client, opts) {
2499
2736
  return true;
2500
2737
  }
2501
2738
  void client.push({ resourceSpans: spans }).catch((err) => {
2502
- onTransportError?.({
2739
+ handler({
2503
2740
  stage: "send",
2504
2741
  error: err instanceof Error ? err : new Error(String(err)),
2505
2742
  value
@@ -2510,15 +2747,22 @@ function toTempo(source, client, opts) {
2510
2747
  return false;
2511
2748
  }
2512
2749
  });
2513
- return inner.subscribe(() => {
2750
+ const unsub = inner.subscribe(() => {
2514
2751
  });
2752
+ return {
2753
+ dispose: () => {
2754
+ unsub();
2755
+ errorsNode.down([[TEARDOWN]]);
2756
+ },
2757
+ errors: errorsNode
2758
+ };
2515
2759
  }
2516
2760
  function checkpointToS3(graph, client, bucket, opts) {
2517
2761
  const { prefix = "checkpoints/", debounceMs, compactEvery, onError } = opts ?? {};
2518
2762
  const adapter = {
2519
- save(data) {
2763
+ save(_key, data) {
2520
2764
  const ms = Math.floor(wallClockNs() / 1e6);
2521
- const key = `${prefix}${graph.name}/checkpoint-${ms}.json`;
2765
+ const s3Key = `${prefix}${graph.name}/checkpoint-${ms}.json`;
2522
2766
  let body;
2523
2767
  try {
2524
2768
  body = JSON.stringify(data);
@@ -2528,7 +2772,7 @@ function checkpointToS3(graph, client, bucket, opts) {
2528
2772
  }
2529
2773
  void client.putObject({
2530
2774
  Bucket: bucket,
2531
- Key: key,
2775
+ Key: s3Key,
2532
2776
  Body: body,
2533
2777
  ContentType: "application/json"
2534
2778
  }).catch((err) => onError?.(err));
@@ -2538,9 +2782,9 @@ function checkpointToS3(graph, client, bucket, opts) {
2538
2782
  }
2539
2783
  function checkpointToRedis(graph, client, opts) {
2540
2784
  const { prefix = "graphrefly:checkpoint:", debounceMs, compactEvery, onError } = opts ?? {};
2541
- const key = `${prefix}${graph.name}`;
2785
+ const redisKey = `${prefix}${graph.name}`;
2542
2786
  const adapter = {
2543
- save(data) {
2787
+ save(_key, data) {
2544
2788
  let body;
2545
2789
  try {
2546
2790
  body = JSON.stringify(data);
@@ -2548,7 +2792,7 @@ function checkpointToRedis(graph, client, opts) {
2548
2792
  onError?.(err);
2549
2793
  return;
2550
2794
  }
2551
- void client.set(key, body).catch((err) => onError?.(err));
2795
+ void client.set(redisKey, body).catch((err) => onError?.(err));
2552
2796
  }
2553
2797
  };
2554
2798
  return graph.autoCheckpoint(adapter, { debounceMs, compactEvery, onError });
@@ -2586,8 +2830,67 @@ function toSqlite(source, db, table, opts) {
2586
2830
  params: [JSON.stringify(v)]
2587
2831
  }),
2588
2832
  onTransportError,
2833
+ batchInsert = false,
2834
+ maxBatchSize = 1e3,
2835
+ flushIntervalMs = 0,
2589
2836
  ...rest
2590
2837
  } = opts ?? {};
2838
+ const { errorsNode, handler } = createSinkErrorHandler(onTransportError);
2839
+ const pendingInserts = [];
2840
+ let flushing = false;
2841
+ let disposed = false;
2842
+ let timer;
2843
+ function flushTransaction() {
2844
+ if (pendingInserts.length === 0 || flushing) return;
2845
+ flushing = true;
2846
+ try {
2847
+ db.query("BEGIN", []);
2848
+ } catch (err) {
2849
+ flushing = false;
2850
+ handler({
2851
+ stage: "send",
2852
+ error: err instanceof Error ? err : new Error(String(err)),
2853
+ value: void 0
2854
+ });
2855
+ return;
2856
+ }
2857
+ const batch2 = pendingInserts.splice(0);
2858
+ let firstError;
2859
+ for (const q of batch2) {
2860
+ try {
2861
+ db.query(q.sql, q.params);
2862
+ } catch (err) {
2863
+ firstError = err instanceof Error ? err : new Error(String(err));
2864
+ break;
2865
+ }
2866
+ }
2867
+ if (firstError) {
2868
+ try {
2869
+ db.query("ROLLBACK", []);
2870
+ } catch {
2871
+ }
2872
+ handler({ stage: "send", error: firstError, value: void 0 });
2873
+ } else {
2874
+ try {
2875
+ db.query("COMMIT", []);
2876
+ } catch (err) {
2877
+ handler({
2878
+ stage: "send",
2879
+ error: err instanceof Error ? err : new Error(String(err)),
2880
+ value: void 0
2881
+ });
2882
+ }
2883
+ }
2884
+ flushing = false;
2885
+ }
2886
+ const scheduleFlush = () => {
2887
+ if (batchInsert && flushIntervalMs > 0 && timer === void 0 && !disposed) {
2888
+ timer = setTimeout(() => {
2889
+ timer = void 0;
2890
+ flushTransaction();
2891
+ }, flushIntervalMs);
2892
+ }
2893
+ };
2591
2894
  const inner = node([source], () => void 0, {
2592
2895
  describeKind: "effect",
2593
2896
  ...rest,
@@ -2598,29 +2901,339 @@ function toSqlite(source, db, table, opts) {
2598
2901
  try {
2599
2902
  query = toSQL(value, table);
2600
2903
  } catch (err) {
2601
- onTransportError?.({
2904
+ handler({
2602
2905
  stage: "serialize",
2603
2906
  error: err instanceof Error ? err : new Error(String(err)),
2604
2907
  value
2605
2908
  });
2606
2909
  return true;
2607
2910
  }
2608
- try {
2609
- db.query(query.sql, query.params);
2610
- } catch (err) {
2611
- onTransportError?.({
2612
- stage: "send",
2613
- error: err instanceof Error ? err : new Error(String(err)),
2614
- value
2615
- });
2911
+ if (batchInsert) {
2912
+ pendingInserts.push(query);
2913
+ if (pendingInserts.length >= maxBatchSize) flushTransaction();
2914
+ else scheduleFlush();
2915
+ } else {
2916
+ try {
2917
+ db.query(query.sql, query.params);
2918
+ } catch (err) {
2919
+ handler({
2920
+ stage: "send",
2921
+ error: err instanceof Error ? err : new Error(String(err)),
2922
+ value
2923
+ });
2924
+ }
2616
2925
  }
2617
2926
  return true;
2618
2927
  }
2928
+ if (batchInsert && messageTier(msg[0]) >= 3) {
2929
+ flushTransaction();
2930
+ }
2619
2931
  return false;
2620
2932
  }
2621
2933
  });
2622
- return inner.subscribe(() => {
2934
+ const unsub = inner.subscribe(() => {
2623
2935
  });
2936
+ const dispose = () => {
2937
+ if (disposed) return;
2938
+ disposed = true;
2939
+ if (timer !== void 0) {
2940
+ clearTimeout(timer);
2941
+ timer = void 0;
2942
+ }
2943
+ if (batchInsert) flushTransaction();
2944
+ unsub();
2945
+ errorsNode.down([[TEARDOWN]]);
2946
+ };
2947
+ return {
2948
+ dispose,
2949
+ errors: errorsNode,
2950
+ flush: batchInsert ? async () => {
2951
+ if (!disposed) flushTransaction();
2952
+ } : void 0
2953
+ };
2954
+ }
2955
+ function fromPrisma(model, opts) {
2956
+ const { args, mapRow = (r) => r, ...rest } = opts ?? {};
2957
+ return producer(
2958
+ (_d, a) => {
2959
+ let active = true;
2960
+ void model.findMany(args).then((rows) => {
2961
+ if (!active) return;
2962
+ const mapped = rows.map(mapRow);
2963
+ batch(() => {
2964
+ for (const item of mapped) {
2965
+ a.emit(item);
2966
+ }
2967
+ });
2968
+ a.down([[COMPLETE]]);
2969
+ }).catch((err) => {
2970
+ if (!active) return;
2971
+ try {
2972
+ a.down([[ERROR, err instanceof Error ? err : new Error(String(err))]]);
2973
+ } catch {
2974
+ }
2975
+ });
2976
+ return () => {
2977
+ active = false;
2978
+ };
2979
+ },
2980
+ { ...rest, describeKind: "producer", completeWhenDepsComplete: false }
2981
+ );
2982
+ }
2983
+ function fromDrizzle(query, opts) {
2984
+ const { mapRow = (r) => r, ...rest } = opts ?? {};
2985
+ return producer(
2986
+ (_d, a) => {
2987
+ let active = true;
2988
+ void query.execute().then((rows) => {
2989
+ if (!active) return;
2990
+ const mapped = rows.map(mapRow);
2991
+ batch(() => {
2992
+ for (const item of mapped) {
2993
+ a.emit(item);
2994
+ }
2995
+ });
2996
+ a.down([[COMPLETE]]);
2997
+ }).catch((err) => {
2998
+ if (!active) return;
2999
+ try {
3000
+ a.down([[ERROR, err instanceof Error ? err : new Error(String(err))]]);
3001
+ } catch {
3002
+ }
3003
+ });
3004
+ return () => {
3005
+ active = false;
3006
+ };
3007
+ },
3008
+ { ...rest, describeKind: "producer", completeWhenDepsComplete: false }
3009
+ );
3010
+ }
3011
+ function fromKysely(query, opts) {
3012
+ const { mapRow = (r) => r, ...rest } = opts ?? {};
3013
+ return producer(
3014
+ (_d, a) => {
3015
+ let active = true;
3016
+ void query.execute().then((rows) => {
3017
+ if (!active) return;
3018
+ const mapped = rows.map(mapRow);
3019
+ batch(() => {
3020
+ for (const item of mapped) {
3021
+ a.emit(item);
3022
+ }
3023
+ });
3024
+ a.down([[COMPLETE]]);
3025
+ }).catch((err) => {
3026
+ if (!active) return;
3027
+ try {
3028
+ a.down([[ERROR, err instanceof Error ? err : new Error(String(err))]]);
3029
+ } catch {
3030
+ }
3031
+ });
3032
+ return () => {
3033
+ active = false;
3034
+ };
3035
+ },
3036
+ { ...rest, describeKind: "producer", completeWhenDepsComplete: false }
3037
+ );
3038
+ }
3039
+
3040
+ // src/extra/cascading-cache.ts
3041
+ function lru() {
3042
+ const map2 = /* @__PURE__ */ new Map();
3043
+ let head = null;
3044
+ let tail = null;
3045
+ function unlink(n) {
3046
+ if (n.prev) n.prev.next = n.next;
3047
+ else head = n.next;
3048
+ if (n.next) n.next.prev = n.prev;
3049
+ else tail = n.prev;
3050
+ n.prev = null;
3051
+ n.next = null;
3052
+ }
3053
+ function pushFront(n) {
3054
+ n.next = head;
3055
+ n.prev = null;
3056
+ if (head) head.prev = n;
3057
+ head = n;
3058
+ if (tail === null) tail = n;
3059
+ }
3060
+ return {
3061
+ insert(key) {
3062
+ if (map2.has(key)) {
3063
+ this.touch(key);
3064
+ return;
3065
+ }
3066
+ const n = { key, prev: null, next: null };
3067
+ map2.set(key, n);
3068
+ pushFront(n);
3069
+ },
3070
+ touch(key) {
3071
+ const n = map2.get(key);
3072
+ if (!n) return;
3073
+ unlink(n);
3074
+ pushFront(n);
3075
+ },
3076
+ delete(key) {
3077
+ const n = map2.get(key);
3078
+ if (!n) return;
3079
+ unlink(n);
3080
+ map2.delete(key);
3081
+ },
3082
+ evict(count) {
3083
+ const victims = [];
3084
+ for (let i = 0; i < count && tail !== null; i++) {
3085
+ const n = tail;
3086
+ victims.push(n.key);
3087
+ unlink(n);
3088
+ map2.delete(n.key);
3089
+ }
3090
+ return victims;
3091
+ },
3092
+ size() {
3093
+ return map2.size;
3094
+ }
3095
+ };
3096
+ }
3097
+ function cascadingCache(tiers, opts) {
3098
+ const entries = /* @__PURE__ */ new Map();
3099
+ const maxSize = opts?.maxSize ?? 0;
3100
+ const policy = maxSize > 0 ? opts?.eviction ?? lru() : null;
3101
+ const writeThrough = opts?.writeThrough ?? false;
3102
+ function promote(key, value, hitTierIndex) {
3103
+ for (let i = 0; i < hitTierIndex; i++) {
3104
+ const tier = tiers[i];
3105
+ if (tier.save) tier.save(key, value);
3106
+ }
3107
+ }
3108
+ function cascade(key, nd) {
3109
+ for (let tierIndex = 0; tierIndex < tiers.length; tierIndex++) {
3110
+ let result;
3111
+ try {
3112
+ result = tiers[tierIndex].load(key);
3113
+ } catch {
3114
+ continue;
3115
+ }
3116
+ if (result != null) {
3117
+ nd.down([[DATA, result]]);
3118
+ promote(key, result, tierIndex);
3119
+ return;
3120
+ }
3121
+ }
3122
+ }
3123
+ function evictIfNeeded() {
3124
+ if (!policy || maxSize <= 0) return;
3125
+ while (policy.size() >= maxSize) {
3126
+ const victims = policy.evict(1);
3127
+ if (victims.length === 0) break;
3128
+ for (const key of victims) {
3129
+ const nd = entries.get(key);
3130
+ if (nd) {
3131
+ const value = nd.get();
3132
+ if (value !== void 0) {
3133
+ for (let i = tiers.length - 1; i >= 0; i--) {
3134
+ if (tiers[i].save) {
3135
+ tiers[i].save(key, value);
3136
+ for (let j = 0; j < i; j++) {
3137
+ if (tiers[j].clear) tiers[j].clear(key);
3138
+ }
3139
+ break;
3140
+ }
3141
+ }
3142
+ }
3143
+ nd.down([[TEARDOWN]]);
3144
+ }
3145
+ entries.delete(key);
3146
+ }
3147
+ }
3148
+ }
3149
+ return {
3150
+ load(key) {
3151
+ const existing = entries.get(key);
3152
+ if (existing) {
3153
+ policy?.touch(key);
3154
+ return existing;
3155
+ }
3156
+ if (policy && maxSize > 0 && policy.size() >= maxSize) {
3157
+ evictIfNeeded();
3158
+ }
3159
+ const nd = state(void 0);
3160
+ entries.set(key, nd);
3161
+ if (policy) {
3162
+ policy.insert(key);
3163
+ }
3164
+ cascade(key, nd);
3165
+ return nd;
3166
+ },
3167
+ save(key, value) {
3168
+ if (writeThrough) {
3169
+ for (const tier of tiers) {
3170
+ if (tier.save) tier.save(key, value);
3171
+ }
3172
+ } else if (tiers[0]?.save) {
3173
+ tiers[0].save(key, value);
3174
+ }
3175
+ const existing = entries.get(key);
3176
+ if (existing) {
3177
+ existing.down([[DATA, value]]);
3178
+ policy?.touch(key);
3179
+ } else {
3180
+ if (policy && maxSize > 0 && policy.size() >= maxSize) {
3181
+ evictIfNeeded();
3182
+ }
3183
+ const nd = state(value);
3184
+ entries.set(key, nd);
3185
+ if (policy) {
3186
+ policy.insert(key);
3187
+ }
3188
+ }
3189
+ },
3190
+ invalidate(key) {
3191
+ const existing = entries.get(key);
3192
+ if (existing) {
3193
+ cascade(key, existing);
3194
+ }
3195
+ },
3196
+ delete(key) {
3197
+ policy?.delete(key);
3198
+ const nd = entries.get(key);
3199
+ if (nd) nd.down([[TEARDOWN]]);
3200
+ entries.delete(key);
3201
+ for (const tier of tiers) {
3202
+ if (tier.clear) tier.clear(key);
3203
+ }
3204
+ },
3205
+ has(key) {
3206
+ return entries.has(key);
3207
+ },
3208
+ get size() {
3209
+ return entries.size;
3210
+ }
3211
+ };
3212
+ }
3213
+ function adapterToTier(adapter) {
3214
+ return {
3215
+ load: (key) => adapter.load(key),
3216
+ save: (key, value) => adapter.save(key, value),
3217
+ clear: (key) => adapter.clear(key)
3218
+ };
3219
+ }
3220
+ function tieredStorage(adapters, opts) {
3221
+ const inner = cascadingCache(adapters.map(adapterToTier), {
3222
+ maxSize: opts?.maxSize,
3223
+ eviction: opts?.eviction,
3224
+ writeThrough: true
3225
+ });
3226
+ return {
3227
+ load: (key) => inner.load(key),
3228
+ save: (key, value) => inner.save(key, value),
3229
+ invalidate: (key) => inner.invalidate(key),
3230
+ delete: (key) => inner.delete(key),
3231
+ has: (key) => inner.has(key),
3232
+ get size() {
3233
+ return inner.size;
3234
+ },
3235
+ cache: inner
3236
+ };
2624
3237
  }
2625
3238
 
2626
3239
  // src/extra/checkpoint.ts
@@ -2643,60 +3256,61 @@ function sortJsonValue(value) {
2643
3256
  }
2644
3257
  return out;
2645
3258
  }
2646
- function warnNonJsonValues(data) {
2647
- for (const [path, node2] of Object.entries(data.nodes)) {
2648
- const v = node2.value;
2649
- if (v === void 0 || v === null) continue;
2650
- if (typeof v === "function" || typeof v === "symbol" || typeof v === "bigint") {
2651
- console.warn(
2652
- `checkpoint: node "${path}" has non-JSON-serializable value (${typeof v}); it will be lost on round-trip`
2653
- );
2654
- }
2655
- }
2656
- }
2657
- function stableSnapshotJson(data) {
2658
- warnNonJsonValues(data);
3259
+ function stableJsonString(data) {
2659
3260
  return `${JSON.stringify(sortJsonValue(data), void 0, 0)}
2660
3261
  `;
2661
3262
  }
2662
3263
  var MemoryCheckpointAdapter = class {
2663
- #data = null;
2664
- save(data) {
2665
- this.#data = JSON.parse(JSON.stringify(data));
3264
+ #data = /* @__PURE__ */ new Map();
3265
+ save(key, data) {
3266
+ this.#data.set(key, JSON.parse(JSON.stringify(data)));
2666
3267
  }
2667
- load() {
2668
- return this.#data === null ? null : JSON.parse(JSON.stringify(this.#data));
3268
+ load(key) {
3269
+ const v = this.#data.get(key);
3270
+ return v === void 0 ? null : JSON.parse(JSON.stringify(v));
3271
+ }
3272
+ clear(key) {
3273
+ this.#data.delete(key);
2669
3274
  }
2670
3275
  };
2671
3276
  var DictCheckpointAdapter = class {
2672
3277
  #storage;
2673
- #key;
2674
- constructor(storage, key = "graphrefly_checkpoint") {
3278
+ constructor(storage) {
2675
3279
  this.#storage = storage;
2676
- this.#key = key;
2677
3280
  }
2678
- save(data) {
2679
- this.#storage[this.#key] = JSON.parse(JSON.stringify(data));
3281
+ save(key, data) {
3282
+ this.#storage[key] = JSON.parse(JSON.stringify(data));
3283
+ }
3284
+ load(key) {
3285
+ const raw = this.#storage[key];
3286
+ return raw === void 0 ? null : JSON.parse(JSON.stringify(raw));
2680
3287
  }
2681
- load() {
2682
- const raw = this.#storage[this.#key];
2683
- return raw !== null && typeof raw === "object" && !Array.isArray(raw) ? JSON.parse(JSON.stringify(raw)) : null;
3288
+ clear(key) {
3289
+ delete this.#storage[key];
2684
3290
  }
2685
3291
  };
2686
3292
  var FileCheckpointAdapter = class {
2687
- #path;
2688
- constructor(path) {
2689
- this.#path = path;
3293
+ #dir;
3294
+ constructor(dir) {
3295
+ this.#dir = dir;
2690
3296
  }
2691
- save(data) {
2692
- const dir = dirname(this.#path);
2693
- mkdirSync(dir, { recursive: true });
2694
- const payload = stableSnapshotJson(data);
2695
- const base = basename(this.#path);
3297
+ #pathFor(key) {
3298
+ const safeName = key.replace(
3299
+ /[^a-zA-Z0-9_-]/g,
3300
+ (c) => `%${c.charCodeAt(0).toString(16).padStart(2, "0")}`
3301
+ );
3302
+ return join(this.#dir, `${safeName}.json`);
3303
+ }
3304
+ save(key, data) {
3305
+ mkdirSync(this.#dir, { recursive: true });
3306
+ const filePath = this.#pathFor(key);
3307
+ const payload = stableJsonString(data);
3308
+ const base = basename(filePath);
3309
+ const dir = dirname(filePath);
2696
3310
  const tmp = join(dir, `.${base}.${randomBytes(8).toString("hex")}.tmp`);
2697
3311
  try {
2698
3312
  writeFileSync(tmp, payload, "utf8");
2699
- renameSync(tmp, this.#path);
3313
+ renameSync(tmp, filePath);
2700
3314
  } catch (e) {
2701
3315
  try {
2702
3316
  unlinkSync(tmp);
@@ -2705,36 +3319,42 @@ var FileCheckpointAdapter = class {
2705
3319
  throw e;
2706
3320
  }
2707
3321
  }
2708
- load() {
3322
+ load(key) {
2709
3323
  try {
2710
- const text = readFileSync(this.#path, "utf8").trim();
3324
+ const text = readFileSync(this.#pathFor(key), "utf8").trim();
2711
3325
  if (!text) return null;
2712
- const data = JSON.parse(text);
2713
- return data !== null && typeof data === "object" && !Array.isArray(data) ? data : null;
3326
+ return JSON.parse(text);
2714
3327
  } catch {
2715
3328
  return null;
2716
3329
  }
2717
3330
  }
3331
+ clear(key) {
3332
+ try {
3333
+ unlinkSync(this.#pathFor(key));
3334
+ } catch (e) {
3335
+ if (e.code !== "ENOENT") throw e;
3336
+ }
3337
+ }
2718
3338
  };
2719
3339
  var SqliteCheckpointAdapter = class {
2720
3340
  #db;
2721
- #key;
2722
- constructor(path, key = "graphrefly_checkpoint") {
3341
+ constructor(path) {
2723
3342
  this.#db = new DatabaseSync(path);
2724
- this.#key = key;
2725
3343
  this.#db.exec(
2726
3344
  `CREATE TABLE IF NOT EXISTS graphrefly_checkpoint (k TEXT PRIMARY KEY, v TEXT NOT NULL)`
2727
3345
  );
2728
3346
  }
2729
- save(data) {
2730
- const payload = stableSnapshotJson(data).trimEnd();
2731
- this.#db.prepare(`INSERT OR REPLACE INTO graphrefly_checkpoint (k, v) VALUES (?, ?)`).run(this.#key, payload);
3347
+ save(key, data) {
3348
+ const payload = stableJsonString(data).trimEnd();
3349
+ this.#db.prepare(`INSERT OR REPLACE INTO graphrefly_checkpoint (k, v) VALUES (?, ?)`).run(key, payload);
2732
3350
  }
2733
- load() {
2734
- const row = this.#db.prepare(`SELECT v FROM graphrefly_checkpoint WHERE k = ?`).get(this.#key);
3351
+ load(key) {
3352
+ const row = this.#db.prepare(`SELECT v FROM graphrefly_checkpoint WHERE k = ?`).get(key);
2735
3353
  if (row === void 0 || typeof row.v !== "string" || row.v.trim() === "") return null;
2736
- const parsed = JSON.parse(row.v);
2737
- return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
3354
+ return JSON.parse(row.v);
3355
+ }
3356
+ clear(key) {
3357
+ this.#db.prepare(`DELETE FROM graphrefly_checkpoint WHERE k = ?`).run(key);
2738
3358
  }
2739
3359
  /** Close the underlying SQLite connection (safe to call more than once). */
2740
3360
  close() {
@@ -2745,10 +3365,10 @@ var SqliteCheckpointAdapter = class {
2745
3365
  }
2746
3366
  };
2747
3367
  function saveGraphCheckpoint(graph, adapter) {
2748
- adapter.save(graph.snapshot());
3368
+ adapter.save(graph.name, graph.snapshot());
2749
3369
  }
2750
3370
  function restoreGraphCheckpoint(graph, adapter) {
2751
- const data = adapter.load();
3371
+ const data = adapter.load(graph.name);
2752
3372
  if (data === null) return false;
2753
3373
  graph.restore(data);
2754
3374
  return true;
@@ -4154,48 +4774,6 @@ function audit(source, ms, opts) {
4154
4774
  }
4155
4775
  });
4156
4776
  }
4157
- function timeout(source, ms, opts) {
4158
- const { with: withPayload, ...timeoutNodeOpts } = opts ?? {};
4159
- let timer;
4160
- const err = withPayload ?? new Error("timeout");
4161
- function arm(a) {
4162
- clearTimeout(timer);
4163
- timer = setTimeout(() => {
4164
- timer = void 0;
4165
- a.down([[ERROR, err]]);
4166
- }, ms);
4167
- }
4168
- return node(
4169
- [source],
4170
- ([_v], a) => {
4171
- arm(a);
4172
- return () => clearTimeout(timer);
4173
- },
4174
- {
4175
- ...operatorOpts2(timeoutNodeOpts),
4176
- completeWhenDepsComplete: false,
4177
- onMessage(msg, _i, a) {
4178
- const t = msg[0];
4179
- if (t === DATA) {
4180
- arm(a);
4181
- a.down([msg]);
4182
- return true;
4183
- }
4184
- if (t === COMPLETE || t === ERROR) {
4185
- clearTimeout(timer);
4186
- a.down([msg]);
4187
- return true;
4188
- }
4189
- if (t === DIRTY || t === RESOLVED) {
4190
- a.down([msg]);
4191
- return true;
4192
- }
4193
- a.down([msg]);
4194
- return true;
4195
- }
4196
- }
4197
- );
4198
- }
4199
4777
  function buffer(source, notifier, opts) {
4200
4778
  const buf = [];
4201
4779
  return node([source, notifier], () => void 0, {
@@ -5565,6 +6143,10 @@ export {
5565
6143
  tokenTracker,
5566
6144
  rateLimiter,
5567
6145
  withStatus,
6146
+ TimeoutError,
6147
+ fallback,
6148
+ timeout,
6149
+ cache,
5568
6150
  fromWebSocket,
5569
6151
  fromWebhook,
5570
6152
  fromHTTP,
@@ -5604,6 +6186,12 @@ export {
5604
6186
  checkpointToRedis,
5605
6187
  fromSqlite,
5606
6188
  toSqlite,
6189
+ fromPrisma,
6190
+ fromDrizzle,
6191
+ fromKysely,
6192
+ lru,
6193
+ cascadingCache,
6194
+ tieredStorage,
5607
6195
  MemoryCheckpointAdapter,
5608
6196
  DictCheckpointAdapter,
5609
6197
  FileCheckpointAdapter,
@@ -5647,7 +6235,6 @@ export {
5647
6235
  throttle,
5648
6236
  sample,
5649
6237
  audit,
5650
- timeout,
5651
6238
  buffer,
5652
6239
  bufferCount,
5653
6240
  windowCount,
@@ -5678,4 +6265,4 @@ export {
5678
6265
  workerSelf,
5679
6266
  extra_exports
5680
6267
  };
5681
- //# sourceMappingURL=chunk-V3UACY6A.js.map
6268
+ //# sourceMappingURL=chunk-TZLX4KIT.js.map