@graphrefly/graphrefly 0.21.0 → 0.22.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 (97) hide show
  1. package/README.md +7 -5
  2. package/dist/chunk-44HD4BTA.js +47 -0
  3. package/dist/chunk-44HD4BTA.js.map +1 -0
  4. package/dist/chunk-7TAQJHQV.js +103 -0
  5. package/dist/chunk-7TAQJHQV.js.map +1 -0
  6. package/dist/chunk-BLD3IFYF.js +6827 -0
  7. package/dist/chunk-BLD3IFYF.js.map +1 -0
  8. package/dist/{chunk-ZTCDY5NQ.js → chunk-EQUZ5NLD.js} +34 -45
  9. package/dist/chunk-EQUZ5NLD.js.map +1 -0
  10. package/dist/{chunk-VOQFK7YN.js → chunk-IR3KMOLX.js} +358 -128
  11. package/dist/chunk-IR3KMOLX.js.map +1 -0
  12. package/dist/{chunk-XWBVAO2R.js → chunk-MQBQOFDS.js} +20 -11
  13. package/dist/chunk-MQBQOFDS.js.map +1 -0
  14. package/dist/chunk-NXC35KC5.js +2417 -0
  15. package/dist/chunk-NXC35KC5.js.map +1 -0
  16. package/dist/chunk-QA3RP5NH.js +2234 -0
  17. package/dist/chunk-QA3RP5NH.js.map +1 -0
  18. package/dist/chunk-RHI3GHZW.js +115 -0
  19. package/dist/chunk-RHI3GHZW.js.map +1 -0
  20. package/dist/{chunk-7IGHIFTT.js → chunk-TH6COGOP.js} +15 -26
  21. package/dist/chunk-TH6COGOP.js.map +1 -0
  22. package/dist/compat/nestjs/index.cjs +3366 -2259
  23. package/dist/compat/nestjs/index.cjs.map +1 -1
  24. package/dist/compat/nestjs/index.d.cts +6 -4
  25. package/dist/compat/nestjs/index.d.ts +6 -4
  26. package/dist/compat/nestjs/index.js +8 -8
  27. package/dist/core/index.cjs +1611 -1218
  28. package/dist/core/index.cjs.map +1 -1
  29. package/dist/core/index.d.cts +3 -2
  30. package/dist/core/index.d.ts +3 -2
  31. package/dist/core/index.js +37 -34
  32. package/dist/extra/index.cjs +7387 -6089
  33. package/dist/extra/index.cjs.map +1 -1
  34. package/dist/extra/index.d.cts +4 -4
  35. package/dist/extra/index.d.ts +4 -4
  36. package/dist/extra/index.js +57 -30
  37. package/dist/graph/index.cjs +3107 -2216
  38. package/dist/graph/index.cjs.map +1 -1
  39. package/dist/graph/index.d.cts +5 -3
  40. package/dist/graph/index.d.ts +5 -3
  41. package/dist/graph/index.js +24 -11
  42. package/dist/graph-DFr0diXB.d.ts +1128 -0
  43. package/dist/graph-ab1yPwIB.d.cts +1128 -0
  44. package/dist/{index-8a605sg9.d.ts → index-BHm3Ba5q.d.ts} +2 -2
  45. package/dist/{index-DuN3bhtm.d.ts → index-BbYZma8G.d.ts} +1697 -586
  46. package/dist/{index-SFzE_KTa.d.cts → index-BvWfZCTt.d.cts} +1697 -586
  47. package/dist/index-C9z6rU9P.d.cts +388 -0
  48. package/dist/{index-BjtlNirP.d.cts → index-D36MAQ3f.d.ts} +4 -4
  49. package/dist/{index-VHA43cGP.d.cts → index-DLE1Sp-L.d.cts} +2 -2
  50. package/dist/{index-CgSiUouz.d.ts → index-DrJq9B1T.d.cts} +4 -4
  51. package/dist/index-DsGxLfwL.d.ts +315 -0
  52. package/dist/index-Dy04P4W3.d.cts +315 -0
  53. package/dist/index-HdJx_BjO.d.ts +388 -0
  54. package/dist/index.cjs +9781 -7878
  55. package/dist/index.cjs.map +1 -1
  56. package/dist/index.d.cts +214 -37
  57. package/dist/index.d.ts +214 -37
  58. package/dist/index.js +905 -638
  59. package/dist/index.js.map +1 -1
  60. package/dist/meta--fr9sxRM.d.cts +41 -0
  61. package/dist/meta-n3FoVWML.d.ts +41 -0
  62. package/dist/node-C5UD5MGq.d.cts +1146 -0
  63. package/dist/node-C5UD5MGq.d.ts +1146 -0
  64. package/dist/{observable-DcBwQY7t.d.ts → observable-CQRBtEbq.d.ts} +1 -1
  65. package/dist/{observable-C8Kx_O6k.d.cts → observable-DWydVy5b.d.cts} +1 -1
  66. package/dist/patterns/reactive-layout/index.cjs +3102 -2132
  67. package/dist/patterns/reactive-layout/index.cjs.map +1 -1
  68. package/dist/patterns/reactive-layout/index.d.cts +5 -3
  69. package/dist/patterns/reactive-layout/index.d.ts +5 -3
  70. package/dist/patterns/reactive-layout/index.js +5 -4
  71. package/dist/storage-Bew05Xy6.d.cts +182 -0
  72. package/dist/storage-C9fZfMfM.d.ts +182 -0
  73. package/package.json +1 -1
  74. package/dist/chunk-2UDLYZHT.js +0 -2117
  75. package/dist/chunk-2UDLYZHT.js.map +0 -1
  76. package/dist/chunk-4MQ2J6IG.js +0 -1631
  77. package/dist/chunk-4MQ2J6IG.js.map +0 -1
  78. package/dist/chunk-7IGHIFTT.js.map +0 -1
  79. package/dist/chunk-DOSLSFKL.js +0 -162
  80. package/dist/chunk-DOSLSFKL.js.map +0 -1
  81. package/dist/chunk-ECN37NVS.js +0 -6227
  82. package/dist/chunk-ECN37NVS.js.map +0 -1
  83. package/dist/chunk-G66H6ZRK.js +0 -111
  84. package/dist/chunk-G66H6ZRK.js.map +0 -1
  85. package/dist/chunk-VOQFK7YN.js.map +0 -1
  86. package/dist/chunk-WZ2Z2CRV.js +0 -32
  87. package/dist/chunk-WZ2Z2CRV.js.map +0 -1
  88. package/dist/chunk-XWBVAO2R.js.map +0 -1
  89. package/dist/chunk-ZTCDY5NQ.js.map +0 -1
  90. package/dist/graph-KsTe57nI.d.cts +0 -750
  91. package/dist/graph-mILUUqW8.d.ts +0 -750
  92. package/dist/index-B2SvPEbc.d.ts +0 -257
  93. package/dist/index-BHfg_Ez3.d.ts +0 -629
  94. package/dist/index-Bc_diYYJ.d.cts +0 -629
  95. package/dist/index-UudxGnzc.d.cts +0 -257
  96. package/dist/meta-BnG7XAaE.d.cts +0 -778
  97. package/dist/meta-BnG7XAaE.d.ts +0 -778
@@ -4,6 +4,7 @@ import {
4
4
  DIRTY,
5
5
  ERROR,
6
6
  PAUSE,
7
+ RESOLVED,
7
8
  RESUME,
8
9
  batch,
9
10
  derived,
@@ -11,7 +12,7 @@ import {
11
12
  producer,
12
13
  state,
13
14
  wallClockNs
14
- } from "./chunk-4MQ2J6IG.js";
15
+ } from "./chunk-QA3RP5NH.js";
15
16
 
16
17
  // src/extra/observable.ts
17
18
  import { Observable } from "rxjs";
@@ -103,9 +104,6 @@ import { resolve as resolvePath } from "path";
103
104
  function sourceOpts(opts) {
104
105
  return { describeKind: "producer", ...opts };
105
106
  }
106
- function operatorOpts(opts) {
107
- return { describeKind: "operator", ...opts };
108
- }
109
107
  function escapeRegexChar(ch) {
110
108
  return /[\\^$+?.()|[\]{}]/.test(ch) ? `\\${ch}` : ch;
111
109
  }
@@ -135,20 +133,28 @@ function matchesAnyPattern(path, patterns) {
135
133
  return false;
136
134
  }
137
135
  function wrapSubscribeHook(inner, before) {
138
- const wrapper = node([inner], ([val]) => val, {
139
- describeKind: "operator",
140
- initial: inner.get()
141
- });
136
+ const wrapper = node(
137
+ [inner],
138
+ (data, a) => {
139
+ const batch0 = data[0];
140
+ if (batch0 == null || batch0.length === 0) {
141
+ a.down([[RESOLVED]]);
142
+ return;
143
+ }
144
+ for (const v of batch0) a.emit(v);
145
+ },
146
+ { describeKind: "derived", initial: inner.cache }
147
+ );
142
148
  const origSubscribe = wrapper.subscribe.bind(wrapper);
143
- wrapper.subscribe = (sink, hints) => {
149
+ wrapper.subscribe = (sink, actor) => {
144
150
  before(sink);
145
- return origSubscribe(sink, hints);
151
+ return origSubscribe(sink, actor);
146
152
  };
147
153
  return wrapper;
148
154
  }
149
155
  function fromTimer(ms, opts) {
150
156
  const { signal, period, ...rest } = opts ?? {};
151
- return producer((_d, a) => {
157
+ return producer((a) => {
152
158
  let done = false;
153
159
  let count = 0;
154
160
  let t;
@@ -161,8 +167,8 @@ function fromTimer(ms, opts) {
161
167
  };
162
168
  const finish = () => {
163
169
  if (done) return;
164
- a.emit(count++);
165
170
  if (period != null) {
171
+ a.emit(count++);
166
172
  iv = setInterval(() => {
167
173
  if (done) return;
168
174
  a.emit(count++);
@@ -170,7 +176,8 @@ function fromTimer(ms, opts) {
170
176
  } else {
171
177
  done = true;
172
178
  signal?.removeEventListener("abort", onAbort);
173
- queueMicrotask(() => a.down([[COMPLETE]]));
179
+ a.emit(count++);
180
+ a.down([[COMPLETE]]);
174
181
  }
175
182
  };
176
183
  const onAbort = () => {
@@ -193,7 +200,7 @@ function fromCron(expr, opts) {
193
200
  const tickMs = tickOpt ?? 6e4;
194
201
  const emitDate = output === "date";
195
202
  return producer(
196
- (_d, a) => {
203
+ (a) => {
197
204
  let lastFiredKey = -1;
198
205
  const check = () => {
199
206
  const now = /* @__PURE__ */ new Date();
@@ -212,7 +219,7 @@ function fromCron(expr, opts) {
212
219
  }
213
220
  function fromEvent(target, type, opts) {
214
221
  const { capture, passive, once, ...rest } = opts ?? {};
215
- return producer((_d, a) => {
222
+ return producer((a) => {
216
223
  const handler = (e) => {
217
224
  a.emit(e);
218
225
  };
@@ -231,7 +238,7 @@ function fromFSWatch(paths, opts) {
231
238
  const excludePatterns = (exclude ?? ["**/node_modules/**", "**/.git/**", "**/dist/**"]).map(
232
239
  globToRegExp
233
240
  );
234
- return producer((_d, a) => {
241
+ return producer((a) => {
235
242
  const pending = /* @__PURE__ */ new Map();
236
243
  const watchers = [];
237
244
  let stopped = false;
@@ -315,7 +322,7 @@ function fromFSWatch(paths, opts) {
315
322
  }, sourceOpts(rest));
316
323
  }
317
324
  function fromIter(iterable, opts) {
318
- return producer((_d, a) => {
325
+ return producer((a) => {
319
326
  let cancelled = false;
320
327
  try {
321
328
  for (const x of iterable) {
@@ -336,7 +343,7 @@ function isThenable(x) {
336
343
  }
337
344
  function fromPromise(p, opts) {
338
345
  const { signal, ...rest } = opts ?? {};
339
- return producer((_d, a) => {
346
+ return producer((a) => {
340
347
  let settled = false;
341
348
  const onAbort = () => {
342
349
  if (settled) return;
@@ -371,7 +378,7 @@ function fromPromise(p, opts) {
371
378
  }
372
379
  function fromAsyncIter(iterable, opts) {
373
380
  const { signal: outerSignal, ...rest } = opts ?? {};
374
- return producer((_d, a) => {
381
+ return producer((a) => {
375
382
  const ac = new AbortController();
376
383
  const onOuterAbort = () => ac.abort(outerSignal?.reason);
377
384
  if (outerSignal?.aborted) {
@@ -388,18 +395,18 @@ function fromAsyncIter(iterable, opts) {
388
395
  (step) => {
389
396
  if (cancelled || signal.aborted) return;
390
397
  if (step.done) {
391
- queueMicrotask(() => a.down([[COMPLETE]]));
398
+ a.down([[COMPLETE]]);
392
399
  return;
393
400
  }
394
401
  a.emit(step.value);
395
- queueMicrotask(pump);
402
+ pump();
396
403
  },
397
404
  (e) => {
398
405
  if (!cancelled && !signal.aborted) a.down([[ERROR, e]]);
399
406
  }
400
407
  );
401
408
  };
402
- queueMicrotask(pump);
409
+ pump();
403
410
  return () => {
404
411
  cancelled = true;
405
412
  outerSignal?.removeEventListener("abort", onOuterAbort);
@@ -409,7 +416,7 @@ function fromAsyncIter(iterable, opts) {
409
416
  }, sourceOpts(rest));
410
417
  }
411
418
  function isNode(x) {
412
- return x != null && typeof x.subscribe === "function" && typeof x.get === "function";
419
+ return x != null && typeof x === "object" && "cache" in x && typeof x.subscribe === "function";
413
420
  }
414
421
  function fromAny(input, opts) {
415
422
  if (isNode(input)) {
@@ -433,7 +440,7 @@ function of(...values) {
433
440
  return fromIter(values, void 0);
434
441
  }
435
442
  function empty(opts) {
436
- return producer((_d, a) => {
443
+ return producer((a) => {
437
444
  a.down([[COMPLETE]]);
438
445
  return void 0;
439
446
  }, sourceOpts(opts));
@@ -442,58 +449,64 @@ function never(opts) {
442
449
  return producer(() => void 0, sourceOpts(opts));
443
450
  }
444
451
  function throwError(err, opts) {
445
- return producer((_d, a) => {
452
+ return producer((a) => {
446
453
  a.down([[ERROR, err]]);
447
454
  return void 0;
448
455
  }, sourceOpts(opts));
449
456
  }
450
457
  function forEach(source, fn, opts) {
451
- const inner = node([source], () => void 0, {
452
- describeKind: "effect",
453
- ...opts,
454
- onMessage(msg, _i, _a) {
455
- if (msg[0] === DATA) {
456
- fn(msg[1]);
457
- return true;
458
+ const inner = node(
459
+ [source],
460
+ (data, _actions) => {
461
+ const batch0 = data[0];
462
+ if (batch0 != null && batch0.length > 0) {
463
+ for (const v of batch0) fn(v);
458
464
  }
459
- return false;
460
- }
461
- });
465
+ },
466
+ { describeKind: "effect", ...opts }
467
+ );
462
468
  return inner.subscribe(() => {
463
469
  });
464
470
  }
465
471
  function toArray(source, opts) {
466
- const acc = [];
467
- return node([source], () => void 0, {
468
- ...operatorOpts(opts),
469
- completeWhenDepsComplete: false,
470
- onMessage(msg, _i, a) {
471
- if (msg[0] === DATA) {
472
- acc.push(msg[1]);
473
- return true;
472
+ return node(
473
+ [source],
474
+ (data, actions, ctx) => {
475
+ if (!ctx.store.buf) ctx.store.buf = [];
476
+ const buf = ctx.store.buf;
477
+ const batch0 = data[0];
478
+ if (batch0 != null && batch0.length > 0) {
479
+ for (const v of batch0) buf.push(v);
474
480
  }
475
- if (msg[0] === COMPLETE) {
476
- a.emit([...acc]);
477
- a.down([[COMPLETE]]);
478
- return true;
481
+ if (ctx.terminalDeps[0] === true) {
482
+ actions.emit([...buf]);
483
+ actions.down([[COMPLETE]]);
484
+ return;
479
485
  }
480
- return false;
486
+ if (batch0 == null || batch0.length === 0) {
487
+ actions.down([[RESOLVED]]);
488
+ }
489
+ },
490
+ {
491
+ describeKind: "derived",
492
+ completeWhenDepsComplete: false,
493
+ ...opts
481
494
  }
482
- });
495
+ );
483
496
  }
484
497
  function share(source, opts) {
485
498
  return producer(
486
- (_d, a) => source.subscribe((msgs) => {
499
+ (a) => source.subscribe((msgs) => {
487
500
  a.down(msgs);
488
501
  }),
489
- { ...sourceOpts(opts), initial: source.get() }
502
+ { ...sourceOpts(opts), initial: source.cache }
490
503
  );
491
504
  }
492
505
  function replay(source, bufferSize, opts) {
493
506
  if (bufferSize < 1) throw new RangeError("replay expects bufferSize >= 1");
494
507
  const buf = [];
495
508
  const inner = producer(
496
- (_d, a) => source.subscribe((msgs) => {
509
+ (a) => source.subscribe((msgs) => {
497
510
  for (const m of msgs) {
498
511
  if (m[0] === DATA) {
499
512
  buf.push(m[1]);
@@ -502,7 +515,7 @@ function replay(source, bufferSize, opts) {
502
515
  }
503
516
  a.down(msgs);
504
517
  }),
505
- { ...sourceOpts(opts), initial: source.get() }
518
+ { ...sourceOpts(opts), initial: source.cache }
506
519
  );
507
520
  return wrapSubscribeHook(inner, (sink) => {
508
521
  for (const v of buf) {
@@ -516,35 +529,52 @@ function cached(source, opts) {
516
529
  function firstValueFrom(source) {
517
530
  return new Promise((resolve, reject) => {
518
531
  let settled = false;
519
- const unsub = source.subscribe((msgs) => {
532
+ let shouldUnsub = false;
533
+ let unsub;
534
+ unsub = source.subscribe((msgs) => {
520
535
  for (const m of msgs) {
521
536
  if (settled) return;
522
537
  if (m[0] === DATA) {
523
538
  settled = true;
524
539
  resolve(m[1]);
525
- queueMicrotask(() => unsub());
540
+ if (unsub) {
541
+ unsub();
542
+ unsub = void 0;
543
+ } else shouldUnsub = true;
526
544
  return;
527
545
  }
528
546
  if (m[0] === ERROR) {
529
547
  settled = true;
530
548
  reject(m[1]);
531
- queueMicrotask(() => unsub());
549
+ if (unsub) {
550
+ unsub();
551
+ unsub = void 0;
552
+ } else shouldUnsub = true;
532
553
  return;
533
554
  }
534
555
  if (m[0] === COMPLETE) {
535
556
  settled = true;
536
557
  reject(new Error("completed without DATA"));
537
- queueMicrotask(() => unsub());
558
+ if (unsub) {
559
+ unsub();
560
+ unsub = void 0;
561
+ } else shouldUnsub = true;
538
562
  return;
539
563
  }
540
564
  }
541
565
  });
566
+ if (shouldUnsub) {
567
+ unsub?.();
568
+ unsub = void 0;
569
+ }
542
570
  });
543
571
  }
544
572
  function firstWhere(source, predicate) {
545
573
  return new Promise((resolve, reject) => {
546
574
  let settled = false;
547
- const unsub = source.subscribe((msgs) => {
575
+ let shouldUnsub = false;
576
+ let unsub;
577
+ unsub = source.subscribe((msgs) => {
548
578
  for (const m of msgs) {
549
579
  if (settled) return;
550
580
  if (m[0] === DATA) {
@@ -552,24 +582,37 @@ function firstWhere(source, predicate) {
552
582
  if (predicate(v)) {
553
583
  settled = true;
554
584
  resolve(v);
555
- queueMicrotask(() => unsub());
585
+ if (unsub) {
586
+ unsub();
587
+ unsub = void 0;
588
+ } else shouldUnsub = true;
556
589
  return;
557
590
  }
558
591
  }
559
592
  if (m[0] === ERROR) {
560
593
  settled = true;
561
594
  reject(m[1]);
562
- queueMicrotask(() => unsub());
595
+ if (unsub) {
596
+ unsub();
597
+ unsub = void 0;
598
+ } else shouldUnsub = true;
563
599
  return;
564
600
  }
565
601
  if (m[0] === COMPLETE) {
566
602
  settled = true;
567
603
  reject(new Error("completed without matching value"));
568
- queueMicrotask(() => unsub());
604
+ if (unsub) {
605
+ unsub();
606
+ unsub = void 0;
607
+ } else shouldUnsub = true;
569
608
  return;
570
609
  }
571
610
  }
572
611
  });
612
+ if (shouldUnsub) {
613
+ unsub?.();
614
+ unsub = void 0;
615
+ }
573
616
  });
574
617
  }
575
618
  var shareReplay = replay;
@@ -582,16 +625,16 @@ function reactiveCounter(cap) {
582
625
  return {
583
626
  node: counter,
584
627
  increment() {
585
- const current = counter.get() ?? 0;
628
+ const current = counter.cache ?? 0;
586
629
  if (current >= cap) return false;
587
630
  counter.down([[DIRTY], [DATA, current + 1]]);
588
631
  return true;
589
632
  },
590
633
  get() {
591
- return counter.get() ?? 0;
634
+ return counter.cache ?? 0;
592
635
  },
593
636
  atCap() {
594
- return (counter.get() ?? 0) >= cap;
637
+ return (counter.cache ?? 0) >= cap;
595
638
  }
596
639
  };
597
640
  }
@@ -641,103 +684,290 @@ function createWatermarkController(sendUp, opts) {
641
684
  }
642
685
 
643
686
  // src/extra/reactive-log.ts
687
+ var NativeLogBackend = class {
688
+ _version = 0;
689
+ _maxSize;
690
+ _buf;
691
+ _head = 0;
692
+ _size = 0;
693
+ constructor(initial, maxSize) {
694
+ if (maxSize !== void 0 && maxSize < 1) {
695
+ throw new RangeError("maxSize must be >= 1");
696
+ }
697
+ this._maxSize = maxSize;
698
+ if (maxSize !== void 0) {
699
+ this._buf = new Array(maxSize);
700
+ if (initial && initial.length > 0) {
701
+ const take = Math.min(initial.length, maxSize);
702
+ const start = initial.length - take;
703
+ for (let i = 0; i < take; i++) {
704
+ this._buf[i] = initial[start + i];
705
+ }
706
+ this._size = take;
707
+ }
708
+ } else {
709
+ this._buf = initial ? [...initial] : [];
710
+ this._size = this._buf.length;
711
+ }
712
+ }
713
+ get version() {
714
+ return this._version;
715
+ }
716
+ get size() {
717
+ return this._size;
718
+ }
719
+ at(index) {
720
+ if (!Number.isInteger(index)) return void 0;
721
+ const i = index >= 0 ? index : this._size + index;
722
+ if (i < 0 || i >= this._size) return void 0;
723
+ if (this._maxSize !== void 0) {
724
+ return this._buf[(this._head + i) % this._maxSize];
725
+ }
726
+ return this._buf[i];
727
+ }
728
+ append(value) {
729
+ this._rawAppend(value);
730
+ this._version += 1;
731
+ }
732
+ appendMany(values) {
733
+ if (values.length === 0) return;
734
+ const start = this._maxSize !== void 0 && values.length > this._maxSize ? values.length - this._maxSize : 0;
735
+ for (let i = start; i < values.length; i++) {
736
+ this._rawAppend(values[i]);
737
+ }
738
+ this._version += 1;
739
+ }
740
+ clear() {
741
+ if (this._size === 0) return 0;
742
+ const n = this._size;
743
+ if (this._maxSize === void 0) {
744
+ this._buf.length = 0;
745
+ } else {
746
+ for (let i = 0; i < n; i++) {
747
+ this._buf[(this._head + i) % this._maxSize] = void 0;
748
+ }
749
+ }
750
+ this._head = 0;
751
+ this._size = 0;
752
+ this._version += 1;
753
+ return n;
754
+ }
755
+ trimHead(n) {
756
+ if (!Number.isInteger(n) || n < 0) {
757
+ throw new RangeError(`trimHead: n must be a non-negative integer (got ${n})`);
758
+ }
759
+ if (n === 0 || this._size === 0) return 0;
760
+ const removed = Math.min(n, this._size);
761
+ if (this._maxSize === void 0) {
762
+ this._buf.splice(0, removed);
763
+ } else {
764
+ for (let i = 0; i < removed; i++) {
765
+ this._buf[(this._head + i) % this._maxSize] = void 0;
766
+ }
767
+ this._head = (this._head + removed) % this._maxSize;
768
+ }
769
+ this._size -= removed;
770
+ this._version += 1;
771
+ return removed;
772
+ }
773
+ slice(start, stop) {
774
+ if (!Number.isInteger(start) || start < 0) {
775
+ throw new RangeError(`slice: start must be a non-negative integer (got ${start})`);
776
+ }
777
+ if (stop !== void 0 && (!Number.isInteger(stop) || stop < 0)) {
778
+ throw new RangeError(`slice: stop must be a non-negative integer or undefined (got ${stop})`);
779
+ }
780
+ const end = stop === void 0 ? this._size : Math.min(Math.max(stop, 0), this._size);
781
+ const s = Math.min(start, this._size);
782
+ if (s >= end) return [];
783
+ const len = end - s;
784
+ if (this._maxSize === void 0) {
785
+ return this._buf.slice(s, end);
786
+ }
787
+ const out = new Array(len);
788
+ for (let i = 0; i < len; i++) {
789
+ out[i] = this._buf[(this._head + s + i) % this._maxSize];
790
+ }
791
+ return out;
792
+ }
793
+ tail(n) {
794
+ if (!Number.isInteger(n) || n < 0) {
795
+ throw new RangeError(`tail: n must be a non-negative integer (got ${n})`);
796
+ }
797
+ if (n === 0 || this._size === 0) return [];
798
+ const take = Math.min(n, this._size);
799
+ return this.slice(this._size - take, this._size);
800
+ }
801
+ toArray() {
802
+ if (this._maxSize === void 0) {
803
+ return [...this._buf];
804
+ }
805
+ const out = new Array(this._size);
806
+ for (let i = 0; i < this._size; i++) {
807
+ out[i] = this._buf[(this._head + i) % this._maxSize];
808
+ }
809
+ return out;
810
+ }
811
+ /** Internal append without version bump — used by `appendMany`. */
812
+ _rawAppend(value) {
813
+ if (this._maxSize === void 0) {
814
+ this._buf.push(value);
815
+ this._size = this._buf.length;
816
+ return;
817
+ }
818
+ if (this._size < this._maxSize) {
819
+ this._buf[(this._head + this._size) % this._maxSize] = value;
820
+ this._size += 1;
821
+ } else {
822
+ this._buf[this._head] = value;
823
+ this._head = (this._head + 1) % this._maxSize;
824
+ }
825
+ }
826
+ };
644
827
  function keepaliveDerived(n) {
645
828
  return n.subscribe(() => {
646
829
  });
647
830
  }
831
+ var DEFAULT_VIEW_CACHE_MAX = 64;
648
832
  function reactiveLog(initial, options = {}) {
649
- const { name, maxSize } = options;
650
- if (maxSize !== void 0 && maxSize < 1) {
651
- throw new RangeError("maxSize must be >= 1");
652
- }
653
- const buf = initial ? [...initial] : [];
654
- if (maxSize !== void 0 && buf.length > maxSize) {
655
- buf.splice(0, buf.length - maxSize);
656
- }
657
- const entries = state(buf.length > 0 ? [...buf] : [], {
833
+ const { name, maxSize, versioning, backend: userBackend } = options;
834
+ const backend = userBackend ?? new NativeLogBackend(initial, maxSize);
835
+ const entries = state(backend.toArray(), {
658
836
  name,
659
837
  describeKind: "state",
660
- equals: (a, b) => a === b
838
+ equals: (a, b) => a === b,
839
+ ...versioning != null ? { versioning } : {}
661
840
  });
662
841
  function pushSnapshot() {
663
- const snapshot = [...buf];
842
+ const snapshot = backend.toArray();
664
843
  batch(() => {
665
844
  entries.down([[DIRTY]]);
666
845
  entries.down([[DATA, snapshot]]);
667
846
  });
668
847
  }
669
- function trimBuf() {
670
- if (maxSize !== void 0 && buf.length > maxSize) {
671
- buf.splice(0, buf.length - maxSize);
848
+ const tailCache = /* @__PURE__ */ new Map();
849
+ const sliceCache = /* @__PURE__ */ new Map();
850
+ function sliceKey(start, stop) {
851
+ return `${start}:${stop === void 0 ? "END" : stop}`;
852
+ }
853
+ function evictOldestIfFull(cache) {
854
+ if (cache.size < DEFAULT_VIEW_CACHE_MAX) return;
855
+ const first = cache.keys().next();
856
+ if (first.done) return;
857
+ const oldest = cache.get(first.value);
858
+ if (oldest !== void 0) oldest.dispose();
859
+ cache.delete(first.value);
860
+ }
861
+ function wrapMutation(op) {
862
+ const prev = backend.version;
863
+ try {
864
+ return op();
865
+ } finally {
866
+ if (backend.version !== prev) pushSnapshot();
672
867
  }
673
868
  }
674
- const bundle = {
869
+ return {
675
870
  entries,
871
+ get size() {
872
+ return backend.size;
873
+ },
874
+ at(index) {
875
+ return backend.at(index);
876
+ },
676
877
  append(value) {
677
- buf.push(value);
678
- trimBuf();
679
- pushSnapshot();
878
+ wrapMutation(() => backend.append(value));
680
879
  },
681
880
  appendMany(values) {
682
881
  if (values.length === 0) return;
683
- buf.push(...values);
684
- trimBuf();
685
- pushSnapshot();
882
+ wrapMutation(() => backend.appendMany(values));
686
883
  },
687
884
  clear() {
688
- if (buf.length === 0) return;
689
- buf.length = 0;
690
- pushSnapshot();
885
+ wrapMutation(() => backend.clear());
691
886
  },
692
887
  trimHead(n) {
693
- if (n < 0) {
694
- throw new RangeError("n must be >= 0");
888
+ wrapMutation(() => backend.trimHead(n));
889
+ },
890
+ tail(n) {
891
+ if (!Number.isInteger(n) || n < 0) {
892
+ throw new RangeError(`tail: n must be a non-negative integer (got ${n})`);
695
893
  }
696
- if (n === 0) return;
697
- if (n >= buf.length) {
698
- if (buf.length === 0) return;
699
- buf.length = 0;
700
- } else {
701
- buf.splice(0, n);
894
+ const hit = tailCache.get(n);
895
+ if (hit !== void 0) {
896
+ tailCache.delete(n);
897
+ tailCache.set(n, hit);
898
+ return hit.node;
702
899
  }
703
- pushSnapshot();
900
+ evictOldestIfFull(tailCache);
901
+ const node_ = derived(
902
+ [entries],
903
+ ([s]) => {
904
+ const list = s;
905
+ if (n === 0 || list.length === 0) return [];
906
+ return list.slice(Math.max(0, list.length - n));
907
+ },
908
+ { initial: backend.tail(n), describeKind: "derived" }
909
+ );
910
+ const dispose = keepaliveDerived(node_);
911
+ tailCache.set(n, { node: node_, dispose });
912
+ return node_;
704
913
  },
705
- tail(n) {
706
- if (n < 0) {
707
- throw new RangeError("n must be >= 0");
914
+ slice(start, stop) {
915
+ if (!Number.isInteger(start) || start < 0) {
916
+ throw new RangeError(`slice: start must be a non-negative integer (got ${start})`);
917
+ }
918
+ if (stop !== void 0 && (!Number.isInteger(stop) || stop < 0)) {
919
+ throw new RangeError(
920
+ `slice: stop must be a non-negative integer or undefined (got ${stop})`
921
+ );
922
+ }
923
+ const key = sliceKey(start, stop);
924
+ const hit = sliceCache.get(key);
925
+ if (hit !== void 0) {
926
+ sliceCache.delete(key);
927
+ sliceCache.set(key, hit);
928
+ return hit.node;
708
929
  }
709
- const e = entries.get();
710
- const init = n === 0 ? [] : e.slice(Math.max(0, e.length - n));
711
- const out = derived(
930
+ evictOldestIfFull(sliceCache);
931
+ const node_ = derived(
712
932
  [entries],
713
933
  ([s]) => {
714
934
  const list = s;
715
- return n === 0 ? [] : list.slice(Math.max(0, list.length - n));
935
+ return stop === void 0 ? list.slice(start) : list.slice(start, stop);
716
936
  },
717
- { initial: init, describeKind: "derived" }
937
+ { initial: backend.slice(start, stop), describeKind: "derived" }
718
938
  );
719
- keepaliveDerived(out);
720
- return out;
939
+ const dispose = keepaliveDerived(node_);
940
+ sliceCache.set(key, { node: node_, dispose });
941
+ return node_;
942
+ },
943
+ disposeTail(n) {
944
+ const hit = tailCache.get(n);
945
+ if (hit === void 0) return false;
946
+ hit.dispose();
947
+ tailCache.delete(n);
948
+ return true;
949
+ },
950
+ disposeSlice(start, stop) {
951
+ const key = sliceKey(start, stop);
952
+ const hit = sliceCache.get(key);
953
+ if (hit === void 0) return false;
954
+ hit.dispose();
955
+ sliceCache.delete(key);
956
+ return true;
957
+ },
958
+ disposeAllViews() {
959
+ for (const entry of tailCache.values()) entry.dispose();
960
+ tailCache.clear();
961
+ for (const entry of sliceCache.values()) entry.dispose();
962
+ sliceCache.clear();
963
+ },
964
+ dispose() {
965
+ for (const entry of tailCache.values()) entry.dispose();
966
+ tailCache.clear();
967
+ for (const entry of sliceCache.values()) entry.dispose();
968
+ sliceCache.clear();
721
969
  }
722
970
  };
723
- return bundle;
724
- }
725
- function logSlice(log, start, stop) {
726
- if (start < 0) {
727
- throw new RangeError("start must be >= 0");
728
- }
729
- const e = log.entries.get();
730
- const init = stop === void 0 ? e.slice(start) : e.slice(start, stop);
731
- const out = derived(
732
- [log.entries],
733
- ([s]) => {
734
- const list = s;
735
- return stop === void 0 ? list.slice(start) : list.slice(start, stop);
736
- },
737
- { initial: init, describeKind: "derived" }
738
- );
739
- keepaliveDerived(out);
740
- return out;
741
971
  }
742
972
 
743
973
  export {
@@ -770,7 +1000,7 @@ export {
770
1000
  keepalive,
771
1001
  reactiveCounter,
772
1002
  createWatermarkController,
773
- reactiveLog,
774
- logSlice
1003
+ NativeLogBackend,
1004
+ reactiveLog
775
1005
  };
776
- //# sourceMappingURL=chunk-VOQFK7YN.js.map
1006
+ //# sourceMappingURL=chunk-IR3KMOLX.js.map