@oimdb/core 1.4.0 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +369 -50
- package/dist/index.cjs +1409 -712
- package/dist/index.d.cts +387 -273
- package/dist/index.d.ts +387 -273
- package/dist/index.js +1397 -703
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,6 +15,11 @@ var OIMEventEmitter = class {
|
|
|
15
15
|
constructor() {
|
|
16
16
|
this.buckets = {};
|
|
17
17
|
}
|
|
18
|
+
hasHandlers(event) {
|
|
19
|
+
const bucket = this.buckets[event];
|
|
20
|
+
if (!bucket) return false;
|
|
21
|
+
return bucket.indexByHandler.size > 0;
|
|
22
|
+
}
|
|
18
23
|
getOrCreateBucket(event) {
|
|
19
24
|
let bucket = this.buckets[event];
|
|
20
25
|
if (!bucket) {
|
|
@@ -297,6 +302,12 @@ var OIMIndexSetBased = class {
|
|
|
297
302
|
emitUpdate(keys) {
|
|
298
303
|
this.emitter.emit(0 /* UPDATE */, { keys });
|
|
299
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Emit update event for a single key (fast-path override point).
|
|
307
|
+
*/
|
|
308
|
+
emitUpdateOne(key) {
|
|
309
|
+
this.emitUpdate([key]);
|
|
310
|
+
}
|
|
300
311
|
};
|
|
301
312
|
|
|
302
313
|
// src/core/OIMIndexStoreMapDrivenArrayBased.ts
|
|
@@ -446,45 +457,34 @@ var OIMIndexArrayBased = class {
|
|
|
446
457
|
emitUpdate(keys) {
|
|
447
458
|
this.emitter.emit(0 /* UPDATE */, { keys });
|
|
448
459
|
}
|
|
460
|
+
/**
|
|
461
|
+
* Emit update event for a single key (fast-path override point).
|
|
462
|
+
*/
|
|
463
|
+
emitUpdateOne(key) {
|
|
464
|
+
this.emitUpdate([key]);
|
|
465
|
+
}
|
|
449
466
|
};
|
|
450
467
|
|
|
451
|
-
// src/enum/
|
|
452
|
-
var
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
})(EOIMUpdateEventCoalescerEventType || {});
|
|
468
|
+
// src/enum/EOIMEventQueueEventType.ts
|
|
469
|
+
var EOIMEventQueueEventType = /* @__PURE__ */ ((EOIMEventQueueEventType2) => {
|
|
470
|
+
EOIMEventQueueEventType2[EOIMEventQueueEventType2["AFTER_FLUSH"] = 0] = "AFTER_FLUSH";
|
|
471
|
+
EOIMEventQueueEventType2[EOIMEventQueueEventType2["BEFORE_FLUSH"] = 1] = "BEFORE_FLUSH";
|
|
472
|
+
return EOIMEventQueueEventType2;
|
|
473
|
+
})(EOIMEventQueueEventType || {});
|
|
458
474
|
|
|
459
475
|
// src/core/OIMUpdateEventEmitter.ts
|
|
460
476
|
var OIMUpdateEventEmitter = class {
|
|
461
|
-
constructor(
|
|
462
|
-
this.keyHandlersBeforeFlush = /* @__PURE__ */ new Map();
|
|
477
|
+
constructor(queue, deliveryMode = "queue") {
|
|
463
478
|
this.keyHandlers = /* @__PURE__ */ new Map();
|
|
464
|
-
this.isDestroyed = false;
|
|
465
|
-
this.isDispatching = false;
|
|
466
|
-
this.isInPrePhase = false;
|
|
467
|
-
this.hasPendingDuringPrePhase = false;
|
|
468
479
|
this.isFlushEnqueued = false;
|
|
469
|
-
this.
|
|
470
|
-
|
|
471
|
-
this.hasPendingDuringPrePhase = true;
|
|
472
|
-
return;
|
|
473
|
-
}
|
|
474
|
-
if (this.isFlushEnqueued) return;
|
|
475
|
-
this.isFlushEnqueued = true;
|
|
476
|
-
this.queue.enqueue(this.onFlush);
|
|
477
|
-
};
|
|
480
|
+
this.updatedKeys = /* @__PURE__ */ new Set();
|
|
481
|
+
this.isAfterFlushDeliveryScheduled = false;
|
|
478
482
|
// Stable handler reference to avoid allocating a new closure on every HAS_CHANGES.
|
|
479
483
|
this.onFlush = () => {
|
|
480
484
|
this.isFlushEnqueued = false;
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
this.
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
if (this.keyHandlers.size === 0 && this.keyHandlersBeforeFlush.size === 0) {
|
|
487
|
-
this.coalescer.clearUpdatedKeys();
|
|
485
|
+
this.dequeueFlush = void 0;
|
|
486
|
+
if (this.keyHandlers.size === 0) {
|
|
487
|
+
this.updatedKeys.clear();
|
|
488
488
|
return;
|
|
489
489
|
}
|
|
490
490
|
const makeHandlerSnapshot = (handlers) => {
|
|
@@ -492,95 +492,133 @@ var OIMUpdateEventEmitter = class {
|
|
|
492
492
|
handlers.forEach((h) => snapshot.push(h));
|
|
493
493
|
return snapshot;
|
|
494
494
|
};
|
|
495
|
-
|
|
496
|
-
this.isDispatching = true;
|
|
497
|
-
this.isInPrePhase = true;
|
|
498
|
-
this.hasPendingDuringPrePhase = false;
|
|
499
|
-
const allKeysForNormalPhase = this.runPrePhaseDrain(makeHandlerSnapshot);
|
|
500
|
-
this.isInPrePhase = false;
|
|
501
|
-
this.runHandlersPhase(allKeysForNormalPhase, makeHandlerSnapshot);
|
|
502
|
-
} finally {
|
|
503
|
-
this.isInPrePhase = false;
|
|
504
|
-
this.isDispatching = false;
|
|
505
|
-
}
|
|
495
|
+
this.runSinglePass(makeHandlerSnapshot);
|
|
506
496
|
};
|
|
507
|
-
this.
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
this.
|
|
511
|
-
|
|
512
|
-
this.queue =
|
|
497
|
+
this.onAfterFlush = () => {
|
|
498
|
+
if (!this.isAfterFlushDeliveryScheduled) return;
|
|
499
|
+
this.isAfterFlushDeliveryScheduled = false;
|
|
500
|
+
this.deliverImmediate();
|
|
501
|
+
};
|
|
502
|
+
this.queue = queue;
|
|
503
|
+
this.deliveryMode = deliveryMode;
|
|
504
|
+
if (this.deliveryMode === "after_flush") {
|
|
505
|
+
this.unsubscribeAfterFlushDelivery = this.queue.emitter.on(
|
|
506
|
+
0 /* AFTER_FLUSH */,
|
|
507
|
+
this.onAfterFlush
|
|
508
|
+
);
|
|
509
|
+
}
|
|
513
510
|
}
|
|
514
511
|
/**
|
|
515
|
-
*
|
|
512
|
+
* Mark keys as updated and schedule delivery.
|
|
513
|
+
*
|
|
514
|
+
* If there are no subscriptions, this is a no-op and does not allocate or retain keys.
|
|
516
515
|
*/
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
516
|
+
markUpdatedKeys(keys) {
|
|
517
|
+
if (keys.length === 0) return;
|
|
518
|
+
if (this.deliveryMode === "queue" && this.queue.isInFlush) {
|
|
519
|
+
throw new Error(
|
|
520
|
+
"OIMUpdateEventEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
if (this.keyHandlers.size === 0) return;
|
|
524
|
+
let didAddAny = false;
|
|
525
|
+
for (let i = 0; i < keys.length; i++) {
|
|
526
|
+
const key = keys[i];
|
|
527
|
+
const handlers = this.keyHandlers.get(key);
|
|
528
|
+
if (!handlers || handlers.size === 0) continue;
|
|
529
|
+
this.updatedKeys.add(key);
|
|
530
|
+
didAddAny = true;
|
|
531
|
+
}
|
|
532
|
+
if (!didAddAny) return;
|
|
533
|
+
if (this.deliveryMode === "immediate") {
|
|
534
|
+
this.deliverImmediate();
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
if (this.deliveryMode === "after_flush") {
|
|
538
|
+
this.isAfterFlushDeliveryScheduled = true;
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
if (this.isFlushEnqueued) return;
|
|
542
|
+
this.isFlushEnqueued = true;
|
|
543
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
544
|
+
}
|
|
545
|
+
markUpdatedKey(key) {
|
|
546
|
+
if (this.deliveryMode === "queue" && this.queue.isInFlush) {
|
|
547
|
+
throw new Error(
|
|
548
|
+
"OIMUpdateEventEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
549
|
+
);
|
|
550
|
+
}
|
|
551
|
+
if (this.keyHandlers.size === 0) return;
|
|
552
|
+
const handlers = this.keyHandlers.get(key);
|
|
553
|
+
if (!handlers || handlers.size === 0) return;
|
|
554
|
+
this.updatedKeys.add(key);
|
|
555
|
+
if (this.deliveryMode === "immediate") {
|
|
556
|
+
this.deliverImmediate();
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
if (this.deliveryMode === "after_flush") {
|
|
560
|
+
this.isAfterFlushDeliveryScheduled = true;
|
|
561
|
+
return;
|
|
558
562
|
}
|
|
559
|
-
return
|
|
563
|
+
if (this.isFlushEnqueued) return;
|
|
564
|
+
this.isFlushEnqueued = true;
|
|
565
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
560
566
|
}
|
|
561
|
-
|
|
562
|
-
if (this.
|
|
567
|
+
markAllUpdated() {
|
|
568
|
+
if (this.deliveryMode === "queue" && this.queue.isInFlush) {
|
|
569
|
+
throw new Error(
|
|
570
|
+
"OIMUpdateEventEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
571
|
+
);
|
|
572
|
+
}
|
|
573
|
+
if (this.keyHandlers.size === 0) return;
|
|
574
|
+
this.keyHandlers.forEach((_handlers, key) => {
|
|
575
|
+
this.updatedKeys.add(key);
|
|
576
|
+
});
|
|
577
|
+
if (this.deliveryMode === "immediate") {
|
|
578
|
+
this.deliverImmediate();
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
if (this.deliveryMode === "after_flush") {
|
|
582
|
+
this.isAfterFlushDeliveryScheduled = true;
|
|
563
583
|
return;
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
584
|
+
}
|
|
585
|
+
if (this.isFlushEnqueued) return;
|
|
586
|
+
this.isFlushEnqueued = true;
|
|
587
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
588
|
+
}
|
|
589
|
+
deliverImmediate() {
|
|
590
|
+
const makeHandlerSnapshot = (handlers) => {
|
|
591
|
+
const snapshot = [];
|
|
592
|
+
handlers.forEach((h) => snapshot.push(h));
|
|
593
|
+
return snapshot;
|
|
594
|
+
};
|
|
595
|
+
this.runSinglePass(makeHandlerSnapshot);
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Deliver updated keys and notify handlers once.
|
|
599
|
+
* Re-entrant updates during delivery are forbidden and will throw in markUpdatedKeys().
|
|
600
|
+
*/
|
|
601
|
+
runSinglePass(makeHandlerSnapshot) {
|
|
602
|
+
if (this.updatedKeys.size === 0) return;
|
|
603
|
+
const flushingKeys = this.updatedKeys;
|
|
604
|
+
this.updatedKeys = /* @__PURE__ */ new Set();
|
|
605
|
+
if (this.keyHandlers.size === 0 || flushingKeys.size === 0) return;
|
|
606
|
+
if (flushingKeys.size * 2 < this.keyHandlers.size) {
|
|
607
|
+
flushingKeys.forEach((key) => {
|
|
567
608
|
const handlers = this.keyHandlers.get(key);
|
|
568
609
|
if (!handlers || handlers.size === 0) return;
|
|
569
610
|
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
570
611
|
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
571
|
-
if (this.isDestroyed) return;
|
|
572
612
|
const handler = handlerSnapshot[i];
|
|
573
613
|
if (handlers.has(handler)) handler();
|
|
574
614
|
}
|
|
575
615
|
});
|
|
576
616
|
} else {
|
|
577
617
|
this.keyHandlers.forEach((handlers, key) => {
|
|
578
|
-
if (
|
|
579
|
-
if (!allKeysForNormalPhase.has(key)) return;
|
|
618
|
+
if (!flushingKeys.has(key)) return;
|
|
580
619
|
if (!handlers || handlers.size === 0) return;
|
|
581
620
|
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
582
621
|
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
583
|
-
if (this.isDestroyed) return;
|
|
584
622
|
const handler = handlerSnapshot[i];
|
|
585
623
|
if (handlers.has(handler)) handler();
|
|
586
624
|
}
|
|
@@ -588,14 +626,17 @@ var OIMUpdateEventEmitter = class {
|
|
|
588
626
|
}
|
|
589
627
|
}
|
|
590
628
|
destroy() {
|
|
591
|
-
if (this.
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
629
|
+
if (this.dequeueFlush) {
|
|
630
|
+
this.dequeueFlush();
|
|
631
|
+
this.dequeueFlush = void 0;
|
|
632
|
+
}
|
|
633
|
+
if (this.unsubscribeAfterFlushDelivery) {
|
|
634
|
+
this.unsubscribeAfterFlushDelivery();
|
|
635
|
+
this.unsubscribeAfterFlushDelivery = void 0;
|
|
636
|
+
}
|
|
637
|
+
this.keyHandlers.forEach((handlers) => handlers.clear());
|
|
598
638
|
this.keyHandlers.clear();
|
|
639
|
+
this.updatedKeys.clear();
|
|
599
640
|
}
|
|
600
641
|
/**
|
|
601
642
|
* Get performance metrics for monitoring and debugging
|
|
@@ -616,32 +657,13 @@ var OIMUpdateEventEmitter = class {
|
|
|
616
657
|
* Check if there are any active subscriptions
|
|
617
658
|
*/
|
|
618
659
|
hasSubscriptions() {
|
|
619
|
-
return this.keyHandlers.size > 0
|
|
660
|
+
return this.keyHandlers.size > 0;
|
|
620
661
|
}
|
|
621
662
|
/**
|
|
622
663
|
* Get the number of handlers for a specific key
|
|
623
664
|
*/
|
|
624
665
|
getHandlerCount(key) {
|
|
625
|
-
return
|
|
626
|
-
}
|
|
627
|
-
subscribeOnKeyBeforeFlush(key, handler) {
|
|
628
|
-
let handlers = this.keyHandlersBeforeFlush.get(key);
|
|
629
|
-
if (!handlers) {
|
|
630
|
-
handlers = /* @__PURE__ */ new Set();
|
|
631
|
-
this.keyHandlersBeforeFlush.set(key, handlers);
|
|
632
|
-
}
|
|
633
|
-
handlers.add(handler);
|
|
634
|
-
return () => {
|
|
635
|
-
this.unsubscribeFromKeyBeforeFlush(key, handler);
|
|
636
|
-
};
|
|
637
|
-
}
|
|
638
|
-
unsubscribeFromKeyBeforeFlush(key, handler) {
|
|
639
|
-
const handlers = this.keyHandlersBeforeFlush.get(key);
|
|
640
|
-
if (!handlers) return;
|
|
641
|
-
handlers.delete(handler);
|
|
642
|
-
if (handlers.size === 0) {
|
|
643
|
-
this.keyHandlersBeforeFlush.delete(key);
|
|
644
|
-
}
|
|
666
|
+
return this.keyHandlers.get(key)?.size ?? 0;
|
|
645
667
|
}
|
|
646
668
|
subscribeOnKey(key, handler) {
|
|
647
669
|
let handlers = this.keyHandlers.get(key);
|
|
@@ -660,6 +682,15 @@ var OIMUpdateEventEmitter = class {
|
|
|
660
682
|
handlers.delete(handler);
|
|
661
683
|
if (handlers.size === 0) {
|
|
662
684
|
this.keyHandlers.delete(key);
|
|
685
|
+
this.updatedKeys.delete(key);
|
|
686
|
+
}
|
|
687
|
+
if (this.keyHandlers.size === 0) {
|
|
688
|
+
this.updatedKeys.clear();
|
|
689
|
+
if (this.dequeueFlush) {
|
|
690
|
+
this.dequeueFlush();
|
|
691
|
+
this.dequeueFlush = void 0;
|
|
692
|
+
}
|
|
693
|
+
this.isFlushEnqueued = false;
|
|
663
694
|
}
|
|
664
695
|
}
|
|
665
696
|
subscribeOnKeys(keys, handler) {
|
|
@@ -681,30 +712,6 @@ var OIMUpdateEventEmitter = class {
|
|
|
681
712
|
}
|
|
682
713
|
};
|
|
683
714
|
}
|
|
684
|
-
subscribeOnKeysBeforeFlush(keys, handler) {
|
|
685
|
-
const subscribedKeys = [];
|
|
686
|
-
for (const key of keys) {
|
|
687
|
-
let handlers = this.keyHandlersBeforeFlush.get(key);
|
|
688
|
-
if (!handlers) {
|
|
689
|
-
handlers = /* @__PURE__ */ new Set();
|
|
690
|
-
this.keyHandlersBeforeFlush.set(key, handlers);
|
|
691
|
-
}
|
|
692
|
-
if (!handlers.has(handler)) {
|
|
693
|
-
handlers.add(handler);
|
|
694
|
-
subscribedKeys.push(key);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
return () => {
|
|
698
|
-
for (const key of subscribedKeys) {
|
|
699
|
-
this.unsubscribeFromKeyBeforeFlush(key, handler);
|
|
700
|
-
}
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
unsubscribeFromKeysBeforeFlush(keys, handler) {
|
|
704
|
-
for (const key of keys) {
|
|
705
|
-
this.unsubscribeFromKeyBeforeFlush(key, handler);
|
|
706
|
-
}
|
|
707
|
-
}
|
|
708
715
|
unsubscribeFromKeys(keys, handler) {
|
|
709
716
|
for (const key of keys) {
|
|
710
717
|
this.unsubscribeFromKey(key, handler);
|
|
@@ -712,203 +719,11 @@ var OIMUpdateEventEmitter = class {
|
|
|
712
719
|
}
|
|
713
720
|
};
|
|
714
721
|
|
|
715
|
-
// src/core/OIMIndexManualSetBased.ts
|
|
716
|
-
var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
717
|
-
constructor(options = {}) {
|
|
718
|
-
super(options);
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Set primary keys for a specific index key, replacing any existing values.
|
|
722
|
-
* Uses optional comparator to skip updates if PKs haven't actually changed.
|
|
723
|
-
*/
|
|
724
|
-
setPks(key, pks) {
|
|
725
|
-
const hasChanges = this.setPksWithComparison(key, new Set(pks));
|
|
726
|
-
if (hasChanges) {
|
|
727
|
-
this.emitUpdate([key]);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
/**
|
|
731
|
-
* Add primary keys to a specific index key
|
|
732
|
-
*/
|
|
733
|
-
addPks(key, pks) {
|
|
734
|
-
if (pks.length === 0) return;
|
|
735
|
-
let pksSet = this.store.getOneByKey(key);
|
|
736
|
-
if (!pksSet) {
|
|
737
|
-
pksSet = /* @__PURE__ */ new Set();
|
|
738
|
-
this.store.setOneByKey(key, pksSet);
|
|
739
|
-
}
|
|
740
|
-
let hasChanges = false;
|
|
741
|
-
for (const pk of pks) {
|
|
742
|
-
if (!pksSet.has(pk)) {
|
|
743
|
-
pksSet.add(pk);
|
|
744
|
-
hasChanges = true;
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
if (hasChanges) {
|
|
748
|
-
this.store.setOneByKey(key, pksSet);
|
|
749
|
-
this.emitUpdate([key]);
|
|
750
|
-
}
|
|
751
|
-
}
|
|
752
|
-
/**
|
|
753
|
-
* Remove primary keys from a specific index key
|
|
754
|
-
*/
|
|
755
|
-
removePks(key, pks) {
|
|
756
|
-
if (pks.length === 0) return;
|
|
757
|
-
const pksSet = this.store.getOneByKey(key);
|
|
758
|
-
if (!pksSet) return;
|
|
759
|
-
let hasChanges = false;
|
|
760
|
-
for (const pk of pks) {
|
|
761
|
-
if (pksSet.delete(pk)) {
|
|
762
|
-
hasChanges = true;
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
if (pksSet.size === 0) {
|
|
766
|
-
this.store.removeOneByKey(key);
|
|
767
|
-
hasChanges = true;
|
|
768
|
-
} else if (hasChanges) {
|
|
769
|
-
this.store.setOneByKey(key, pksSet);
|
|
770
|
-
}
|
|
771
|
-
if (hasChanges) {
|
|
772
|
-
this.emitUpdate([key]);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
/**
|
|
776
|
-
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
777
|
-
*/
|
|
778
|
-
clear(key) {
|
|
779
|
-
if (key === void 0) {
|
|
780
|
-
const allKeys = this.store.getAllKeys();
|
|
781
|
-
if (allKeys.length > 0) {
|
|
782
|
-
this.store.clear();
|
|
783
|
-
this.emitUpdate(allKeys);
|
|
784
|
-
}
|
|
785
|
-
} else {
|
|
786
|
-
if (this.store.getOneByKey(key) !== void 0) {
|
|
787
|
-
this.store.removeOneByKey(key);
|
|
788
|
-
this.emitUpdate([key]);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
};
|
|
793
|
-
|
|
794
|
-
// src/const/OIMDBSettings.ts
|
|
795
|
-
var OIMDBSettings = class {
|
|
796
|
-
};
|
|
797
|
-
/**
|
|
798
|
-
* Fixed key used in the manual index to store updated keys set in coalescers.
|
|
799
|
-
* This constant is exported so users can create their own indexes and pass them to coalescers.
|
|
800
|
-
*/
|
|
801
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
802
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY = "__flushingKeys__";
|
|
803
|
-
|
|
804
|
-
// src/core/OIMUpdateEventCoalescer.ts
|
|
805
|
-
var OIMUpdateEventCoalescer = class {
|
|
806
|
-
constructor(index, flushingIndex) {
|
|
807
|
-
this.emitter = new OIMEventEmitter();
|
|
808
|
-
this.hasEmittedChanges = false;
|
|
809
|
-
this.updatedKeysIndex = index ?? new OIMIndexManualSetBased({
|
|
810
|
-
store: new OIMIndexStoreMapDrivenSetBased()
|
|
811
|
-
});
|
|
812
|
-
this.flushingUpdatedKeysIndex = flushingIndex ?? new OIMIndexManualSetBased({
|
|
813
|
-
store: new OIMIndexStoreMapDrivenSetBased()
|
|
814
|
-
});
|
|
815
|
-
if (!this.updatedKeysIndex.hasKey(OIMDBSettings.UPDATED_KEYS_INDEX_KEY)) {
|
|
816
|
-
this.updatedKeysIndex.setPks(
|
|
817
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
818
|
-
[]
|
|
819
|
-
);
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
/**
|
|
823
|
-
* Get the set of keys that have been updated since last clear
|
|
824
|
-
*/
|
|
825
|
-
getUpdatedKeys() {
|
|
826
|
-
return this.updatedKeysIndex.getPksByKey(
|
|
827
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY
|
|
828
|
-
);
|
|
829
|
-
}
|
|
830
|
-
getFlushingUpdatedKeys() {
|
|
831
|
-
return this.flushingUpdatedKeysIndex.getPksByKey(
|
|
832
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY
|
|
833
|
-
);
|
|
834
|
-
}
|
|
835
|
-
markUpdatedKeysAsFlushing() {
|
|
836
|
-
this.flushingUpdatedKeysIndex.setPks(
|
|
837
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY,
|
|
838
|
-
Array.from(this.getUpdatedKeys())
|
|
839
|
-
);
|
|
840
|
-
this.clearUpdatedKeys();
|
|
841
|
-
}
|
|
842
|
-
/**
|
|
843
|
-
* Clear all updated keys and reset the changed state
|
|
844
|
-
*/
|
|
845
|
-
clearUpdatedKeys() {
|
|
846
|
-
this.emitter.emit(
|
|
847
|
-
1 /* BEFORE_FLUSH */,
|
|
848
|
-
void 0
|
|
849
|
-
);
|
|
850
|
-
this.updatedKeysIndex.setPks(OIMDBSettings.UPDATED_KEYS_INDEX_KEY, []);
|
|
851
|
-
this.hasEmittedChanges = false;
|
|
852
|
-
this.emitter.emit(
|
|
853
|
-
2 /* AFTER_FLUSH */,
|
|
854
|
-
void 0
|
|
855
|
-
);
|
|
856
|
-
}
|
|
857
|
-
clearFlushingUpdatedKeys() {
|
|
858
|
-
this.flushingUpdatedKeysIndex.setPks(
|
|
859
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY,
|
|
860
|
-
[]
|
|
861
|
-
);
|
|
862
|
-
}
|
|
863
|
-
/**
|
|
864
|
-
* Add keys to the updated set and emit HAS_CHANGES event if needed
|
|
865
|
-
*/
|
|
866
|
-
addUpdatedKeys(keys) {
|
|
867
|
-
this.updatedKeysIndex.addPks(
|
|
868
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
869
|
-
keys
|
|
870
|
-
);
|
|
871
|
-
if (!this.hasEmittedChanges) {
|
|
872
|
-
this.hasEmittedChanges = true;
|
|
873
|
-
this.emitter.emit(
|
|
874
|
-
0 /* HAS_CHANGES */,
|
|
875
|
-
void 0
|
|
876
|
-
);
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
};
|
|
880
|
-
|
|
881
|
-
// src/core/OIMUpdateEventCoalescerIndex.ts
|
|
882
|
-
var OIMUpdateEventCoalescerIndex = class extends OIMUpdateEventCoalescer {
|
|
883
|
-
constructor(indexEmitter) {
|
|
884
|
-
super();
|
|
885
|
-
this.indexEmitter = indexEmitter;
|
|
886
|
-
/**
|
|
887
|
-
* When the index is updated, we keep track of the updated keys.
|
|
888
|
-
*/
|
|
889
|
-
this.handleUpdate = (payload) => {
|
|
890
|
-
this.addUpdatedKeys(payload.keys);
|
|
891
|
-
};
|
|
892
|
-
this.indexEmitter.on(0 /* UPDATE */, this.handleUpdate);
|
|
893
|
-
}
|
|
894
|
-
destroy() {
|
|
895
|
-
this.indexEmitter.off(0 /* UPDATE */, this.handleUpdate);
|
|
896
|
-
this.emitter.offAll();
|
|
897
|
-
this.clearUpdatedKeys();
|
|
898
|
-
}
|
|
899
|
-
};
|
|
900
|
-
|
|
901
722
|
// src/abstract/OIMReactiveIndexSetBased.ts
|
|
902
723
|
var OIMReactiveIndexSetBased = class {
|
|
903
|
-
constructor(queue,
|
|
904
|
-
this.
|
|
905
|
-
this.
|
|
906
|
-
this.index.emitter
|
|
907
|
-
);
|
|
908
|
-
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
909
|
-
coalescer: this.coalescer,
|
|
910
|
-
queue
|
|
911
|
-
});
|
|
724
|
+
constructor(queue, createIndex) {
|
|
725
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue);
|
|
726
|
+
this.index = createIndex(this.updateEmitter);
|
|
912
727
|
}
|
|
913
728
|
getPksByKey(key) {
|
|
914
729
|
return this.index.getPksByKey(key);
|
|
@@ -934,24 +749,38 @@ var OIMReactiveIndexSetBased = class {
|
|
|
934
749
|
getMetrics() {
|
|
935
750
|
return this.index.getMetrics();
|
|
936
751
|
}
|
|
752
|
+
subscribeOnKey(key, handler) {
|
|
753
|
+
return this.updateEmitter.subscribeOnKey(key, handler);
|
|
754
|
+
}
|
|
755
|
+
subscribeOnKeys(keys, handler) {
|
|
756
|
+
return this.updateEmitter.subscribeOnKeys(keys, handler);
|
|
757
|
+
}
|
|
758
|
+
unsubscribeFromKey(key, handler) {
|
|
759
|
+
this.updateEmitter.unsubscribeFromKey(key, handler);
|
|
760
|
+
}
|
|
761
|
+
unsubscribeFromKeys(keys, handler) {
|
|
762
|
+
this.updateEmitter.unsubscribeFromKeys(keys, handler);
|
|
763
|
+
}
|
|
764
|
+
hasSubscriptions() {
|
|
765
|
+
return this.updateEmitter.hasSubscriptions();
|
|
766
|
+
}
|
|
767
|
+
getHandlerCount(key) {
|
|
768
|
+
return this.updateEmitter.getHandlerCount(key);
|
|
769
|
+
}
|
|
770
|
+
getSubscriptionMetrics() {
|
|
771
|
+
return this.updateEmitter.getMetrics();
|
|
772
|
+
}
|
|
937
773
|
destroy() {
|
|
938
|
-
this.
|
|
939
|
-
this.coalescer.destroy();
|
|
774
|
+
this.updateEmitter.destroy();
|
|
940
775
|
this.index.destroy();
|
|
941
776
|
}
|
|
942
777
|
};
|
|
943
778
|
|
|
944
779
|
// src/abstract/OIMReactiveIndexArrayBased.ts
|
|
945
780
|
var OIMReactiveIndexArrayBased = class {
|
|
946
|
-
constructor(queue,
|
|
947
|
-
this.
|
|
948
|
-
this.
|
|
949
|
-
this.index.emitter
|
|
950
|
-
);
|
|
951
|
-
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
952
|
-
coalescer: this.coalescer,
|
|
953
|
-
queue
|
|
954
|
-
});
|
|
781
|
+
constructor(queue, createIndex) {
|
|
782
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue);
|
|
783
|
+
this.index = createIndex(this.updateEmitter);
|
|
955
784
|
}
|
|
956
785
|
getPksByKey(key) {
|
|
957
786
|
return this.index.getPksByKey(key);
|
|
@@ -977,9 +806,29 @@ var OIMReactiveIndexArrayBased = class {
|
|
|
977
806
|
getMetrics() {
|
|
978
807
|
return this.index.getMetrics();
|
|
979
808
|
}
|
|
809
|
+
subscribeOnKey(key, handler) {
|
|
810
|
+
return this.updateEmitter.subscribeOnKey(key, handler);
|
|
811
|
+
}
|
|
812
|
+
subscribeOnKeys(keys, handler) {
|
|
813
|
+
return this.updateEmitter.subscribeOnKeys(keys, handler);
|
|
814
|
+
}
|
|
815
|
+
unsubscribeFromKey(key, handler) {
|
|
816
|
+
this.updateEmitter.unsubscribeFromKey(key, handler);
|
|
817
|
+
}
|
|
818
|
+
unsubscribeFromKeys(keys, handler) {
|
|
819
|
+
this.updateEmitter.unsubscribeFromKeys(keys, handler);
|
|
820
|
+
}
|
|
821
|
+
hasSubscriptions() {
|
|
822
|
+
return this.updateEmitter.hasSubscriptions();
|
|
823
|
+
}
|
|
824
|
+
getHandlerCount(key) {
|
|
825
|
+
return this.updateEmitter.getHandlerCount(key);
|
|
826
|
+
}
|
|
827
|
+
getSubscriptionMetrics() {
|
|
828
|
+
return this.updateEmitter.getMetrics();
|
|
829
|
+
}
|
|
980
830
|
destroy() {
|
|
981
|
-
this.
|
|
982
|
-
this.coalescer.destroy();
|
|
831
|
+
this.updateEmitter.destroy();
|
|
983
832
|
this.index.destroy();
|
|
984
833
|
}
|
|
985
834
|
};
|
|
@@ -1151,47 +1000,131 @@ var OIMCollection = class {
|
|
|
1151
1000
|
}
|
|
1152
1001
|
};
|
|
1153
1002
|
|
|
1154
|
-
// src/core/OIMUpdateEventCoalescerCollection.ts
|
|
1155
|
-
var OIMUpdateEventCoalescerCollection = class extends OIMUpdateEventCoalescer {
|
|
1156
|
-
constructor(collectionEmitter) {
|
|
1157
|
-
super();
|
|
1158
|
-
this.collectionEmitter = collectionEmitter;
|
|
1159
|
-
/**
|
|
1160
|
-
* When the collection is updated, we keep track of the updated pks.
|
|
1161
|
-
*/
|
|
1162
|
-
this.handleUpdate = (payload) => {
|
|
1163
|
-
this.addUpdatedKeys(payload.pks);
|
|
1164
|
-
};
|
|
1165
|
-
this.collectionEmitter.on(
|
|
1166
|
-
0 /* UPDATE */,
|
|
1167
|
-
this.handleUpdate
|
|
1168
|
-
);
|
|
1169
|
-
}
|
|
1170
|
-
destroy() {
|
|
1171
|
-
this.collectionEmitter.off(
|
|
1172
|
-
0 /* UPDATE */,
|
|
1173
|
-
this.handleUpdate
|
|
1174
|
-
);
|
|
1175
|
-
this.emitter.offAll();
|
|
1176
|
-
this.clearUpdatedKeys();
|
|
1177
|
-
}
|
|
1178
|
-
};
|
|
1179
|
-
|
|
1180
1003
|
// src/core/OIMReactiveCollection.ts
|
|
1181
1004
|
var OIMReactiveCollection = class extends OIMCollection {
|
|
1182
1005
|
constructor(queue, opts) {
|
|
1183
1006
|
super(opts);
|
|
1184
|
-
this.
|
|
1185
|
-
|
|
1007
|
+
this.anyUpdateHandlers = /* @__PURE__ */ new Set();
|
|
1008
|
+
this.pendingAnyUpdatePks = /* @__PURE__ */ new Set();
|
|
1009
|
+
this.isAnyUpdateClearPending = false;
|
|
1010
|
+
this.isAnyUpdateScheduled = false;
|
|
1011
|
+
this.runAnyUpdate = () => {
|
|
1012
|
+
if (!this.isAnyUpdateScheduled) return;
|
|
1013
|
+
this.isAnyUpdateScheduled = false;
|
|
1014
|
+
this.dequeueAnyUpdate = void 0;
|
|
1015
|
+
const pks = this.isAnyUpdateClearPending ? [] : Array.from(this.pendingAnyUpdatePks);
|
|
1016
|
+
this.pendingAnyUpdatePks.clear();
|
|
1017
|
+
this.isAnyUpdateClearPending = false;
|
|
1018
|
+
const snapshot = Array.from(this.anyUpdateHandlers);
|
|
1019
|
+
for (let i = 0; i < snapshot.length; i++) snapshot[i](pks);
|
|
1020
|
+
};
|
|
1021
|
+
this.queue = queue;
|
|
1022
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue, "queue");
|
|
1023
|
+
}
|
|
1024
|
+
subscribeOnKey(pk, handler) {
|
|
1025
|
+
return this.updateEmitter.subscribeOnKey(pk, handler);
|
|
1026
|
+
}
|
|
1027
|
+
subscribeOnKeys(pks, handler) {
|
|
1028
|
+
return this.updateEmitter.subscribeOnKeys(pks, handler);
|
|
1029
|
+
}
|
|
1030
|
+
unsubscribeFromKey(pk, handler) {
|
|
1031
|
+
this.updateEmitter.unsubscribeFromKey(pk, handler);
|
|
1032
|
+
}
|
|
1033
|
+
unsubscribeFromKeys(pks, handler) {
|
|
1034
|
+
this.updateEmitter.unsubscribeFromKeys(pks, handler);
|
|
1035
|
+
}
|
|
1036
|
+
destroySubscriptions() {
|
|
1037
|
+
this.updateEmitter.destroy();
|
|
1038
|
+
}
|
|
1039
|
+
hasSubscriptions() {
|
|
1040
|
+
return this.updateEmitter.hasSubscriptions();
|
|
1041
|
+
}
|
|
1042
|
+
getHandlerCount(pk) {
|
|
1043
|
+
return this.updateEmitter.getHandlerCount(pk);
|
|
1044
|
+
}
|
|
1045
|
+
getMetrics() {
|
|
1046
|
+
return this.updateEmitter.getMetrics();
|
|
1047
|
+
}
|
|
1048
|
+
subscribeOnAnyUpdate(handler) {
|
|
1049
|
+
this.anyUpdateHandlers.add(handler);
|
|
1050
|
+
return () => {
|
|
1051
|
+
this.anyUpdateHandlers.delete(handler);
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
upsertOneByPk(pk, entity) {
|
|
1055
|
+
this.upsertOneWithoutNotificationsByPk(pk, entity);
|
|
1056
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1057
|
+
this.trackAnyUpdatePk(pk);
|
|
1058
|
+
}
|
|
1059
|
+
upsertOne(entity) {
|
|
1060
|
+
const pk = this.upsertOneWithoutNotifications(entity);
|
|
1061
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1062
|
+
this.trackAnyUpdatePk(pk);
|
|
1063
|
+
}
|
|
1064
|
+
upsertMany(entities) {
|
|
1065
|
+
const pks = entities.map(
|
|
1066
|
+
(entity) => this.upsertOneWithoutNotifications(entity)
|
|
1186
1067
|
);
|
|
1187
|
-
this.
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1068
|
+
this.updateEmitter.markUpdatedKeys(pks);
|
|
1069
|
+
this.trackAnyUpdatePks(pks);
|
|
1070
|
+
}
|
|
1071
|
+
removeOne(entity) {
|
|
1072
|
+
const pk = this.selectPk(entity);
|
|
1073
|
+
this.store.removeOneByPk(pk);
|
|
1074
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1075
|
+
this.trackAnyUpdatePk(pk);
|
|
1076
|
+
}
|
|
1077
|
+
removeMany(entities) {
|
|
1078
|
+
const pks = entities.map(this.selectPk);
|
|
1079
|
+
this.store.removeManyByPks(pks);
|
|
1080
|
+
this.updateEmitter.markUpdatedKeys(pks);
|
|
1081
|
+
this.trackAnyUpdatePks(pks);
|
|
1082
|
+
}
|
|
1083
|
+
removeOneByPk(pk) {
|
|
1084
|
+
this.store.removeOneByPk(pk);
|
|
1085
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1086
|
+
this.trackAnyUpdatePk(pk);
|
|
1087
|
+
}
|
|
1088
|
+
removeManyByPks(pks) {
|
|
1089
|
+
this.store.removeManyByPks(pks);
|
|
1090
|
+
this.updateEmitter.markUpdatedKeys(pks);
|
|
1091
|
+
this.trackAnyUpdatePks(pks);
|
|
1092
|
+
}
|
|
1093
|
+
clear() {
|
|
1094
|
+
this.store.clear();
|
|
1095
|
+
this.updateEmitter.markAllUpdated();
|
|
1096
|
+
this.trackAnyUpdateClear();
|
|
1097
|
+
}
|
|
1098
|
+
trackAnyUpdatePk(pk) {
|
|
1099
|
+
if (this.anyUpdateHandlers.size === 0) return;
|
|
1100
|
+
this.pendingAnyUpdatePks.add(pk);
|
|
1101
|
+
this.ensureAnyUpdateEnqueued();
|
|
1102
|
+
}
|
|
1103
|
+
trackAnyUpdatePks(pks) {
|
|
1104
|
+
if (this.anyUpdateHandlers.size === 0) return;
|
|
1105
|
+
for (let i = 0; i < pks.length; i++)
|
|
1106
|
+
this.pendingAnyUpdatePks.add(pks[i]);
|
|
1107
|
+
this.ensureAnyUpdateEnqueued();
|
|
1108
|
+
}
|
|
1109
|
+
trackAnyUpdateClear() {
|
|
1110
|
+
if (this.anyUpdateHandlers.size === 0) return;
|
|
1111
|
+
this.isAnyUpdateClearPending = true;
|
|
1112
|
+
this.pendingAnyUpdatePks.clear();
|
|
1113
|
+
this.ensureAnyUpdateEnqueued();
|
|
1114
|
+
}
|
|
1115
|
+
ensureAnyUpdateEnqueued() {
|
|
1116
|
+
if (this.isAnyUpdateScheduled) return;
|
|
1117
|
+
this.isAnyUpdateScheduled = true;
|
|
1118
|
+
this.dequeueAnyUpdate = this.queue.enqueue(this.runAnyUpdate);
|
|
1191
1119
|
}
|
|
1192
1120
|
destroy() {
|
|
1193
|
-
this.
|
|
1194
|
-
this.
|
|
1121
|
+
this.updateEmitter.destroy();
|
|
1122
|
+
if (this.dequeueAnyUpdate) {
|
|
1123
|
+
this.dequeueAnyUpdate();
|
|
1124
|
+
this.dequeueAnyUpdate = void 0;
|
|
1125
|
+
}
|
|
1126
|
+
this.anyUpdateHandlers.clear();
|
|
1127
|
+
this.pendingAnyUpdatePks.clear();
|
|
1195
1128
|
super.destroy();
|
|
1196
1129
|
}
|
|
1197
1130
|
};
|
|
@@ -1291,50 +1224,142 @@ var OIMObject = class {
|
|
|
1291
1224
|
}
|
|
1292
1225
|
};
|
|
1293
1226
|
|
|
1294
|
-
// src/core/OIMUpdateEventCoalescerObject.ts
|
|
1295
|
-
var OIMUpdateEventCoalescerObject = class extends OIMUpdateEventCoalescer {
|
|
1296
|
-
constructor(objectEmitter) {
|
|
1297
|
-
super();
|
|
1298
|
-
this.objectEmitter = objectEmitter;
|
|
1299
|
-
/**
|
|
1300
|
-
* When the object is updated, we keep track of the updated keys.
|
|
1301
|
-
*/
|
|
1302
|
-
this.handleUpdate = (payload) => {
|
|
1303
|
-
this.addUpdatedKeys(payload.keys);
|
|
1304
|
-
};
|
|
1305
|
-
this.objectEmitter.on(0 /* UPDATE */, this.handleUpdate);
|
|
1306
|
-
}
|
|
1307
|
-
destroy() {
|
|
1308
|
-
this.objectEmitter.off(0 /* UPDATE */, this.handleUpdate);
|
|
1309
|
-
this.emitter.offAll();
|
|
1310
|
-
this.clearUpdatedKeys();
|
|
1311
|
-
}
|
|
1312
|
-
};
|
|
1313
|
-
|
|
1314
1227
|
// src/core/OIMReactiveObject.ts
|
|
1315
1228
|
var OIMReactiveObject = class extends OIMObject {
|
|
1316
1229
|
constructor(queue, opts) {
|
|
1317
1230
|
super(opts);
|
|
1318
|
-
this.
|
|
1319
|
-
this.
|
|
1320
|
-
|
|
1321
|
-
queue
|
|
1231
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue, "queue");
|
|
1232
|
+
this.emitter.on(0 /* UPDATE */, (payload) => {
|
|
1233
|
+
this.updateEmitter.markUpdatedKeys(payload.keys);
|
|
1322
1234
|
});
|
|
1323
1235
|
}
|
|
1236
|
+
subscribeOnKey(key, handler) {
|
|
1237
|
+
return this.updateEmitter.subscribeOnKey(key, handler);
|
|
1238
|
+
}
|
|
1239
|
+
subscribeOnKeys(keys, handler) {
|
|
1240
|
+
return this.updateEmitter.subscribeOnKeys(keys, handler);
|
|
1241
|
+
}
|
|
1242
|
+
unsubscribeFromKey(key, handler) {
|
|
1243
|
+
this.updateEmitter.unsubscribeFromKey(key, handler);
|
|
1244
|
+
}
|
|
1245
|
+
unsubscribeFromKeys(keys, handler) {
|
|
1246
|
+
this.updateEmitter.unsubscribeFromKeys(keys, handler);
|
|
1247
|
+
}
|
|
1248
|
+
hasSubscriptions() {
|
|
1249
|
+
return this.updateEmitter.hasSubscriptions();
|
|
1250
|
+
}
|
|
1251
|
+
getHandlerCount(key) {
|
|
1252
|
+
return this.updateEmitter.getHandlerCount(key);
|
|
1253
|
+
}
|
|
1254
|
+
getMetrics() {
|
|
1255
|
+
return this.updateEmitter.getMetrics();
|
|
1256
|
+
}
|
|
1324
1257
|
destroy() {
|
|
1325
|
-
this.
|
|
1326
|
-
this.coalescer.destroy();
|
|
1258
|
+
this.updateEmitter.destroy();
|
|
1327
1259
|
super.destroy();
|
|
1328
1260
|
}
|
|
1329
1261
|
};
|
|
1330
1262
|
|
|
1263
|
+
// src/core/OIMIndexManualSetBased.ts
|
|
1264
|
+
var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
1265
|
+
constructor(options = {}) {
|
|
1266
|
+
super(options);
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Set primary keys for a specific index key, replacing any existing values.
|
|
1270
|
+
* Uses optional comparator to skip updates if PKs haven't actually changed.
|
|
1271
|
+
*/
|
|
1272
|
+
setPks(key, pks) {
|
|
1273
|
+
const hasChanges = this.setPksWithComparison(key, new Set(pks));
|
|
1274
|
+
if (hasChanges) {
|
|
1275
|
+
this.emitUpdateOne(key);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* Add primary keys to a specific index key
|
|
1280
|
+
*/
|
|
1281
|
+
addPks(key, pks) {
|
|
1282
|
+
if (pks.length === 0) return;
|
|
1283
|
+
let pksSet = this.store.getOneByKey(key);
|
|
1284
|
+
if (!pksSet) {
|
|
1285
|
+
pksSet = /* @__PURE__ */ new Set();
|
|
1286
|
+
this.store.setOneByKey(key, pksSet);
|
|
1287
|
+
}
|
|
1288
|
+
let hasChanges = false;
|
|
1289
|
+
for (const pk of pks) {
|
|
1290
|
+
if (!pksSet.has(pk)) {
|
|
1291
|
+
pksSet.add(pk);
|
|
1292
|
+
hasChanges = true;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
if (hasChanges) {
|
|
1296
|
+
this.store.setOneByKey(key, pksSet);
|
|
1297
|
+
this.emitUpdateOne(key);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
/**
|
|
1301
|
+
* Remove primary keys from a specific index key
|
|
1302
|
+
*/
|
|
1303
|
+
removePks(key, pks) {
|
|
1304
|
+
if (pks.length === 0) return;
|
|
1305
|
+
const pksSet = this.store.getOneByKey(key);
|
|
1306
|
+
if (!pksSet) return;
|
|
1307
|
+
let hasChanges = false;
|
|
1308
|
+
for (const pk of pks) {
|
|
1309
|
+
if (pksSet.delete(pk)) {
|
|
1310
|
+
hasChanges = true;
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
if (pksSet.size === 0) {
|
|
1314
|
+
this.store.removeOneByKey(key);
|
|
1315
|
+
hasChanges = true;
|
|
1316
|
+
} else if (hasChanges) {
|
|
1317
|
+
this.store.setOneByKey(key, pksSet);
|
|
1318
|
+
}
|
|
1319
|
+
if (hasChanges) {
|
|
1320
|
+
this.emitUpdateOne(key);
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
/**
|
|
1324
|
+
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
1325
|
+
*/
|
|
1326
|
+
clear(key) {
|
|
1327
|
+
if (key === void 0) {
|
|
1328
|
+
const allKeys = this.store.getAllKeys();
|
|
1329
|
+
if (allKeys.length > 0) {
|
|
1330
|
+
this.store.clear();
|
|
1331
|
+
this.emitUpdate(allKeys);
|
|
1332
|
+
}
|
|
1333
|
+
} else {
|
|
1334
|
+
if (this.store.getOneByKey(key) !== void 0) {
|
|
1335
|
+
this.store.removeOneByKey(key);
|
|
1336
|
+
this.emitUpdateOne(key);
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1331
1342
|
// src/core/OIMReactiveIndexManualSetBased.ts
|
|
1343
|
+
var OIMIndexManualSetBasedReactive = class extends OIMIndexManualSetBased {
|
|
1344
|
+
constructor(updateEmitter, opts) {
|
|
1345
|
+
super(opts);
|
|
1346
|
+
this.updateEmitter = updateEmitter;
|
|
1347
|
+
}
|
|
1348
|
+
emitUpdate(keys) {
|
|
1349
|
+
this.updateEmitter.markUpdatedKeys(keys);
|
|
1350
|
+
}
|
|
1351
|
+
emitUpdateOne(key) {
|
|
1352
|
+
this.updateEmitter.markUpdatedKey(key);
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1332
1355
|
var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
1333
1356
|
constructor(queue, opts) {
|
|
1334
|
-
super(queue,
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1357
|
+
super(queue, (updateEmitter) => {
|
|
1358
|
+
return new OIMIndexManualSetBasedReactive(
|
|
1359
|
+
updateEmitter,
|
|
1360
|
+
opts?.indexOptions
|
|
1361
|
+
);
|
|
1362
|
+
});
|
|
1338
1363
|
}
|
|
1339
1364
|
setPks(key, pks) {
|
|
1340
1365
|
this.index.setPks(key, pks);
|
|
@@ -1362,7 +1387,7 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1362
1387
|
setPks(key, pks) {
|
|
1363
1388
|
const hasChanges = this.setPksWithComparison(key, pks);
|
|
1364
1389
|
if (hasChanges) {
|
|
1365
|
-
this.
|
|
1390
|
+
this.emitUpdateOne(key);
|
|
1366
1391
|
}
|
|
1367
1392
|
}
|
|
1368
1393
|
/**
|
|
@@ -1385,7 +1410,7 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1385
1410
|
}
|
|
1386
1411
|
if (hasChanges) {
|
|
1387
1412
|
this.store.setOneByKey(key, Array.from(pksSet));
|
|
1388
|
-
this.
|
|
1413
|
+
this.emitUpdateOne(key);
|
|
1389
1414
|
}
|
|
1390
1415
|
}
|
|
1391
1416
|
/**
|
|
@@ -1404,7 +1429,7 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1404
1429
|
} else {
|
|
1405
1430
|
this.store.setOneByKey(key, filtered);
|
|
1406
1431
|
}
|
|
1407
|
-
this.
|
|
1432
|
+
this.emitUpdateOne(key);
|
|
1408
1433
|
}
|
|
1409
1434
|
}
|
|
1410
1435
|
/**
|
|
@@ -1420,19 +1445,33 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1420
1445
|
} else {
|
|
1421
1446
|
if (this.store.getOneByKey(key) !== void 0) {
|
|
1422
1447
|
this.store.removeOneByKey(key);
|
|
1423
|
-
this.
|
|
1448
|
+
this.emitUpdateOne(key);
|
|
1424
1449
|
}
|
|
1425
1450
|
}
|
|
1426
1451
|
}
|
|
1427
1452
|
};
|
|
1428
1453
|
|
|
1429
1454
|
// src/core/OIMReactiveIndexManualArrayBased.ts
|
|
1455
|
+
var OIMIndexManualArrayBasedReactive = class extends OIMIndexManualArrayBased {
|
|
1456
|
+
constructor(updateEmitter, opts) {
|
|
1457
|
+
super(opts);
|
|
1458
|
+
this.updateEmitter = updateEmitter;
|
|
1459
|
+
}
|
|
1460
|
+
emitUpdate(keys) {
|
|
1461
|
+
this.updateEmitter.markUpdatedKeys(keys);
|
|
1462
|
+
}
|
|
1463
|
+
emitUpdateOne(key) {
|
|
1464
|
+
this.updateEmitter.markUpdatedKey(key);
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1430
1467
|
var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased {
|
|
1431
1468
|
constructor(queue, opts) {
|
|
1432
|
-
super(queue,
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1469
|
+
super(queue, (updateEmitter) => {
|
|
1470
|
+
return new OIMIndexManualArrayBasedReactive(
|
|
1471
|
+
updateEmitter,
|
|
1472
|
+
opts?.indexOptions
|
|
1473
|
+
);
|
|
1474
|
+
});
|
|
1436
1475
|
}
|
|
1437
1476
|
setPks(key, pks) {
|
|
1438
1477
|
this.index.setPks(key, pks);
|
|
@@ -1521,20 +1560,12 @@ var OIMComparatorFactory = class {
|
|
|
1521
1560
|
}
|
|
1522
1561
|
};
|
|
1523
1562
|
|
|
1524
|
-
// src/enum/EOIMEventQueueEventType.ts
|
|
1525
|
-
var EOIMEventQueueEventType = /* @__PURE__ */ ((EOIMEventQueueEventType2) => {
|
|
1526
|
-
EOIMEventQueueEventType2[EOIMEventQueueEventType2["AFTER_FLUSH"] = 0] = "AFTER_FLUSH";
|
|
1527
|
-
EOIMEventQueueEventType2[EOIMEventQueueEventType2["BEFORE_FLUSH"] = 1] = "BEFORE_FLUSH";
|
|
1528
|
-
return EOIMEventQueueEventType2;
|
|
1529
|
-
})(EOIMEventQueueEventType || {});
|
|
1530
|
-
|
|
1531
1563
|
// src/core/OIMEventQueue.ts
|
|
1532
1564
|
var OIMEventQueue = class {
|
|
1533
1565
|
constructor(options = {}) {
|
|
1534
1566
|
this.emitter = new OIMEventEmitter();
|
|
1535
|
-
this.
|
|
1567
|
+
this.tasks = /* @__PURE__ */ new Set();
|
|
1536
1568
|
this.isFlushing = false;
|
|
1537
|
-
this.pendingSchedule = false;
|
|
1538
1569
|
this.scheduler = options.scheduler;
|
|
1539
1570
|
if (this.scheduler) {
|
|
1540
1571
|
this.flushBound = () => this.flush();
|
|
@@ -1545,62 +1576,76 @@ var OIMEventQueue = class {
|
|
|
1545
1576
|
}
|
|
1546
1577
|
}
|
|
1547
1578
|
/**
|
|
1548
|
-
*
|
|
1549
|
-
*
|
|
1579
|
+
* Enqueue a one-shot task to be executed on the next flush.
|
|
1580
|
+
* Returns a dequeue function that can be called to cancel the task before it runs.
|
|
1550
1581
|
*/
|
|
1551
1582
|
enqueue(fn) {
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1583
|
+
let isActive = true;
|
|
1584
|
+
const task = () => {
|
|
1585
|
+
if (!isActive) return;
|
|
1586
|
+
fn();
|
|
1587
|
+
};
|
|
1588
|
+
this.tasks.add(task);
|
|
1589
|
+
this.ensureScheduled();
|
|
1590
|
+
return () => {
|
|
1591
|
+
if (!isActive) return;
|
|
1592
|
+
isActive = false;
|
|
1593
|
+
this.tasks.delete(task);
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
get isInFlush() {
|
|
1597
|
+
return this.isFlushing;
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Dequeue (cancel) a previously enqueued task by its dequeue function.
|
|
1601
|
+
*/
|
|
1602
|
+
dequeue(dequeueFn) {
|
|
1603
|
+
dequeueFn();
|
|
1561
1604
|
}
|
|
1562
1605
|
/**
|
|
1563
|
-
* Execute all
|
|
1564
|
-
*
|
|
1606
|
+
* Execute all pending tasks.
|
|
1607
|
+
*
|
|
1608
|
+
* This flush drains until the queue is empty. If tasks enqueue more tasks, they will be
|
|
1609
|
+
* executed within the same flush.
|
|
1565
1610
|
*/
|
|
1566
1611
|
flush() {
|
|
1567
|
-
if (this.queue.length === 0) return;
|
|
1568
1612
|
this.scheduler?.cancel();
|
|
1569
1613
|
this.isFlushing = true;
|
|
1570
1614
|
this.emitter.emit(1 /* BEFORE_FLUSH */, void 0);
|
|
1571
|
-
const
|
|
1572
|
-
this.
|
|
1573
|
-
for (let i = 0; i <
|
|
1574
|
-
|
|
1615
|
+
const snapshot = Array.from(this.tasks);
|
|
1616
|
+
this.tasks.clear();
|
|
1617
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
1618
|
+
snapshot[i]();
|
|
1575
1619
|
}
|
|
1576
|
-
this.emitter.emit(0 /* AFTER_FLUSH */, void 0);
|
|
1577
1620
|
this.isFlushing = false;
|
|
1578
|
-
|
|
1579
|
-
this.pendingSchedule = false;
|
|
1580
|
-
this.scheduler.schedule();
|
|
1581
|
-
} else {
|
|
1582
|
-
this.pendingSchedule = false;
|
|
1583
|
-
}
|
|
1621
|
+
this.emitter.emit(0 /* AFTER_FLUSH */, void 0);
|
|
1584
1622
|
}
|
|
1585
1623
|
/**
|
|
1586
1624
|
* Get the current number of queued functions.
|
|
1587
1625
|
*/
|
|
1588
1626
|
get length() {
|
|
1589
|
-
return this.
|
|
1627
|
+
return this.tasks.size;
|
|
1590
1628
|
}
|
|
1591
1629
|
/**
|
|
1592
1630
|
* Check if the queue is empty.
|
|
1593
1631
|
*/
|
|
1594
1632
|
get isEmpty() {
|
|
1595
|
-
return this.
|
|
1633
|
+
return this.tasks.size === 0;
|
|
1596
1634
|
}
|
|
1597
1635
|
/**
|
|
1598
1636
|
* Clear the queue without executing functions and cancel any scheduled flush.
|
|
1599
1637
|
*/
|
|
1600
1638
|
clear() {
|
|
1601
|
-
this.
|
|
1639
|
+
this.tasks.clear();
|
|
1602
1640
|
this.scheduler?.cancel();
|
|
1603
1641
|
}
|
|
1642
|
+
ensureScheduled() {
|
|
1643
|
+
if (!this.scheduler) return;
|
|
1644
|
+
if (this.isFlushing) return;
|
|
1645
|
+
if (this.tasks.size === 1) {
|
|
1646
|
+
this.scheduler.schedule();
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1604
1649
|
/**
|
|
1605
1650
|
* Clean up scheduler subscription when queue is no longer needed.
|
|
1606
1651
|
*/
|
|
@@ -1714,56 +1759,75 @@ var OIMMap2Keys = class {
|
|
|
1714
1759
|
}
|
|
1715
1760
|
};
|
|
1716
1761
|
|
|
1717
|
-
// src/modules/wrapper/OIMUpdateEventCoalescerManual.ts
|
|
1718
|
-
var OIMUpdateEventCoalescerManual = class extends OIMUpdateEventCoalescer {
|
|
1719
|
-
markUpdatedKeys(keys) {
|
|
1720
|
-
if (keys.length === 0) return;
|
|
1721
|
-
this.addUpdatedKeys(keys);
|
|
1722
|
-
}
|
|
1723
|
-
destroy() {
|
|
1724
|
-
this.emitter.offAll();
|
|
1725
|
-
this.updatedKeysIndex.destroy();
|
|
1726
|
-
this.flushingUpdatedKeysIndex.destroy();
|
|
1727
|
-
}
|
|
1728
|
-
};
|
|
1729
|
-
|
|
1730
1762
|
// src/modules/wrapper/collection/OIMCollectionChangedFieldsWrapper.ts
|
|
1731
1763
|
var OIMCollectionChangedFieldsWrapper = class {
|
|
1732
1764
|
constructor(queue, collection, opts) {
|
|
1765
|
+
this.isInWrite = false;
|
|
1766
|
+
this.lastEntitySnapshotByPk = /* @__PURE__ */ new Map();
|
|
1733
1767
|
this.changedFieldsByPk = /* @__PURE__ */ new Map();
|
|
1734
1768
|
this.changedPksByField = /* @__PURE__ */ new Map();
|
|
1769
|
+
this.onAfterFlush = () => {
|
|
1770
|
+
this.clear();
|
|
1771
|
+
};
|
|
1772
|
+
this.onCollectionUpdate = (payload) => {
|
|
1773
|
+
if (this.isInWrite) return;
|
|
1774
|
+
if (payload.pks.length === 0) return;
|
|
1775
|
+
for (let i = 0; i < payload.pks.length; i++) {
|
|
1776
|
+
const pk = payload.pks[i];
|
|
1777
|
+
this.trackExternalMutationByPk(pk);
|
|
1778
|
+
}
|
|
1779
|
+
};
|
|
1735
1780
|
this.collection = collection;
|
|
1736
1781
|
this.selectPk = opts?.selectPk ?? (() => {
|
|
1737
1782
|
throw new Error(
|
|
1738
1783
|
`[OIMCollectionChangedFieldsWrapper]: selectPk was not provided. Use upsertOneByPk(...) or pass opts.selectPk.`
|
|
1739
1784
|
);
|
|
1740
1785
|
});
|
|
1741
|
-
this.
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
this.
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1786
|
+
this.changedPksEventEmitter = new OIMUpdateEventEmitter(
|
|
1787
|
+
queue,
|
|
1788
|
+
"after_flush"
|
|
1789
|
+
);
|
|
1790
|
+
this.changedFieldsEventEmitter = new OIMUpdateEventEmitter(queue, "after_flush");
|
|
1791
|
+
this.unsubscribeAfterFlush = queue.emitter.on(
|
|
1792
|
+
0 /* AFTER_FLUSH */,
|
|
1793
|
+
this.onAfterFlush
|
|
1794
|
+
);
|
|
1795
|
+
const maybeReactive = collection;
|
|
1796
|
+
this.unsubscribeFromCollectionEmitter = maybeReactive.subscribeOnAnyUpdate ? maybeReactive.subscribeOnAnyUpdate((pks) => {
|
|
1797
|
+
this.onCollectionUpdate({
|
|
1798
|
+
pks
|
|
1799
|
+
});
|
|
1800
|
+
}) : collection.emitter.on(
|
|
1801
|
+
0 /* UPDATE */,
|
|
1802
|
+
this.onCollectionUpdate
|
|
1803
|
+
);
|
|
1751
1804
|
}
|
|
1752
1805
|
upsertOneByPk(pk, patch) {
|
|
1753
|
-
this.
|
|
1754
|
-
|
|
1806
|
+
this.withWrite(() => {
|
|
1807
|
+
this.trackPatch(pk, patch);
|
|
1808
|
+
this.collection.upsertOneByPk(pk, patch);
|
|
1809
|
+
});
|
|
1810
|
+
this.updateEntitySnapshot(pk);
|
|
1755
1811
|
}
|
|
1756
1812
|
upsertOne(entity) {
|
|
1757
|
-
|
|
1758
|
-
this.trackPatch(pk, entity);
|
|
1759
|
-
this.collection.upsertOne(entity);
|
|
1760
|
-
}
|
|
1761
|
-
upsertMany(entities) {
|
|
1762
|
-
for (const entity of entities) {
|
|
1813
|
+
this.withWrite(() => {
|
|
1763
1814
|
const pk = this.selectPk(entity);
|
|
1764
1815
|
this.trackPatch(pk, entity);
|
|
1765
|
-
|
|
1766
|
-
|
|
1816
|
+
this.collection.upsertOne(entity);
|
|
1817
|
+
});
|
|
1818
|
+
this.updateEntitySnapshot(this.selectPk(entity));
|
|
1819
|
+
}
|
|
1820
|
+
upsertMany(entities) {
|
|
1821
|
+
const pks = [];
|
|
1822
|
+
this.withWrite(() => {
|
|
1823
|
+
for (const entity of entities) {
|
|
1824
|
+
const pk = this.selectPk(entity);
|
|
1825
|
+
pks.push(pk);
|
|
1826
|
+
this.trackPatch(pk, entity);
|
|
1827
|
+
}
|
|
1828
|
+
this.collection.upsertMany(entities);
|
|
1829
|
+
});
|
|
1830
|
+
for (let i = 0; i < pks.length; i++) this.updateEntitySnapshot(pks[i]);
|
|
1767
1831
|
}
|
|
1768
1832
|
getChangedFieldsByPk(pk) {
|
|
1769
1833
|
return this.changedFieldsByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
@@ -1771,8 +1835,7 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1771
1835
|
consumeChangedFieldsByPk(pk) {
|
|
1772
1836
|
const existing = this.changedFieldsByPk.get(pk);
|
|
1773
1837
|
if (!existing) return /* @__PURE__ */ new Set();
|
|
1774
|
-
|
|
1775
|
-
return existing;
|
|
1838
|
+
return new Set(existing);
|
|
1776
1839
|
}
|
|
1777
1840
|
getChangedPksByField(field) {
|
|
1778
1841
|
return this.changedPksByField.get(field) ?? /* @__PURE__ */ new Set();
|
|
@@ -1780,8 +1843,7 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1780
1843
|
consumeChangedPksByField(field) {
|
|
1781
1844
|
const existing = this.changedPksByField.get(field);
|
|
1782
1845
|
if (!existing) return /* @__PURE__ */ new Set();
|
|
1783
|
-
|
|
1784
|
-
return existing;
|
|
1846
|
+
return new Set(existing);
|
|
1785
1847
|
}
|
|
1786
1848
|
clear() {
|
|
1787
1849
|
this.changedFieldsByPk.clear();
|
|
@@ -1790,18 +1852,60 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1790
1852
|
destroy() {
|
|
1791
1853
|
this.changedPksEventEmitter.destroy();
|
|
1792
1854
|
this.changedFieldsEventEmitter.destroy();
|
|
1793
|
-
this.
|
|
1794
|
-
this.
|
|
1855
|
+
this.unsubscribeAfterFlush();
|
|
1856
|
+
this.unsubscribeFromCollectionEmitter();
|
|
1795
1857
|
this.clear();
|
|
1796
1858
|
}
|
|
1797
|
-
|
|
1798
|
-
if (
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
);
|
|
1859
|
+
withWrite(fn) {
|
|
1860
|
+
if (this.isInWrite) {
|
|
1861
|
+
fn();
|
|
1862
|
+
return;
|
|
1802
1863
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1864
|
+
this.isInWrite = true;
|
|
1865
|
+
try {
|
|
1866
|
+
fn();
|
|
1867
|
+
} finally {
|
|
1868
|
+
this.isInWrite = false;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
trackExternalMutationByPk(pk) {
|
|
1872
|
+
const prev = this.lastEntitySnapshotByPk.get(pk);
|
|
1873
|
+
const next = this.collection.getOneByPk(pk);
|
|
1874
|
+
const changedKeys = this.diffChangedKeys(prev, next);
|
|
1875
|
+
this.updateEntitySnapshot(pk);
|
|
1876
|
+
if (changedKeys.length > 0) {
|
|
1877
|
+
this.trackChangedKeys(pk, changedKeys);
|
|
1878
|
+
} else {
|
|
1879
|
+
this.changedPksEventEmitter.markUpdatedKeys([pk]);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
diffChangedKeys(prev, next) {
|
|
1883
|
+
if (!prev && !next) return [];
|
|
1884
|
+
if (!prev && next) return Object.keys(next);
|
|
1885
|
+
if (prev && !next) return Object.keys(prev);
|
|
1886
|
+
const prevObj = prev;
|
|
1887
|
+
const nextObj = next;
|
|
1888
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1889
|
+
Object.keys(prevObj).forEach((k) => keys.add(k));
|
|
1890
|
+
Object.keys(nextObj).forEach((k) => keys.add(k));
|
|
1891
|
+
const changed = [];
|
|
1892
|
+
keys.forEach((k) => {
|
|
1893
|
+
if (prevObj[k] !== nextObj[k])
|
|
1894
|
+
changed.push(k);
|
|
1895
|
+
});
|
|
1896
|
+
return changed;
|
|
1897
|
+
}
|
|
1898
|
+
updateEntitySnapshot(pk) {
|
|
1899
|
+
const entity = this.collection.getOneByPk(pk);
|
|
1900
|
+
if (!entity) {
|
|
1901
|
+
this.lastEntitySnapshotByPk.delete(pk);
|
|
1902
|
+
return;
|
|
1903
|
+
}
|
|
1904
|
+
this.lastEntitySnapshotByPk.set(pk, {
|
|
1905
|
+
...entity
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
trackChangedKeys(pk, keys) {
|
|
1805
1909
|
let pkFields = this.changedFieldsByPk.get(pk);
|
|
1806
1910
|
if (!pkFields) {
|
|
1807
1911
|
pkFields = /* @__PURE__ */ new Set();
|
|
@@ -1816,8 +1920,18 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1816
1920
|
}
|
|
1817
1921
|
fieldPks.add(pk);
|
|
1818
1922
|
}
|
|
1819
|
-
this.
|
|
1820
|
-
this.
|
|
1923
|
+
this.changedPksEventEmitter.markUpdatedKeys([pk]);
|
|
1924
|
+
this.changedFieldsEventEmitter.markUpdatedKeys(keys);
|
|
1925
|
+
}
|
|
1926
|
+
trackPatch(pk, patch) {
|
|
1927
|
+
if (pk === void 0 || pk === null || pk === "") {
|
|
1928
|
+
throw new Error(
|
|
1929
|
+
`[OIMCollectionChangedFieldsWrapper]: PK is required to track changes.`
|
|
1930
|
+
);
|
|
1931
|
+
}
|
|
1932
|
+
const keys = Object.keys(patch);
|
|
1933
|
+
if (keys.length === 0) return;
|
|
1934
|
+
this.trackChangedKeys(pk, keys);
|
|
1821
1935
|
}
|
|
1822
1936
|
};
|
|
1823
1937
|
|
|
@@ -1897,13 +2011,33 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1897
2011
|
// src/modules/wrapper/index/OIMOrderedListIndexCommandStreamWrapper.ts
|
|
1898
2012
|
var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
1899
2013
|
constructor(queue, index) {
|
|
2014
|
+
this.isInWrite = false;
|
|
1900
2015
|
this.commandsByKey = /* @__PURE__ */ new Map();
|
|
1901
|
-
this.
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
2016
|
+
this.onAfterFlush = () => {
|
|
2017
|
+
this.commandsByKey.clear();
|
|
2018
|
+
};
|
|
2019
|
+
this.onIndexUpdate = (payload) => {
|
|
2020
|
+
if (this.isInWrite) return;
|
|
2021
|
+
if (payload.keys.length === 0) return;
|
|
2022
|
+
for (let i = 0; i < payload.keys.length; i++) {
|
|
2023
|
+
const key = payload.keys[i];
|
|
2024
|
+
const list = this.index.getPksByKey(key);
|
|
2025
|
+
this.appendCommand(key, { type: "set", keys: Array.from(list) });
|
|
2026
|
+
}
|
|
2027
|
+
};
|
|
2028
|
+
this.commandsEventEmitter = new OIMUpdateEventEmitter(
|
|
2029
|
+
queue,
|
|
2030
|
+
"after_flush"
|
|
2031
|
+
);
|
|
1906
2032
|
this.index = index ?? new OIMIndexManualOrderedArrayBased();
|
|
2033
|
+
this.unsubscribeAfterFlush = queue.emitter.on(
|
|
2034
|
+
0 /* AFTER_FLUSH */,
|
|
2035
|
+
this.onAfterFlush
|
|
2036
|
+
);
|
|
2037
|
+
this.unsubscribeFromIndexEmitter = this.index.emitter.on(
|
|
2038
|
+
0 /* UPDATE */,
|
|
2039
|
+
this.onIndexUpdate
|
|
2040
|
+
);
|
|
1907
2041
|
}
|
|
1908
2042
|
getPksByKey(key) {
|
|
1909
2043
|
return this.index.getPksByKey(key);
|
|
@@ -1915,27 +2049,35 @@ var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
|
1915
2049
|
return this.index.getKeys();
|
|
1916
2050
|
}
|
|
1917
2051
|
push(key, itemKey) {
|
|
1918
|
-
|
|
1919
|
-
|
|
2052
|
+
this.withWrite(() => {
|
|
2053
|
+
const index = this.index.push(key, itemKey);
|
|
2054
|
+
this.appendCommand(key, { type: "add", key: itemKey, index });
|
|
2055
|
+
});
|
|
1920
2056
|
}
|
|
1921
2057
|
removeAt(key, index) {
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
2058
|
+
this.withWrite(() => {
|
|
2059
|
+
const itemKey = this.index.removeAt(key, index);
|
|
2060
|
+
if (itemKey === void 0) return;
|
|
2061
|
+
this.appendCommand(key, { type: "remove", key: itemKey, index });
|
|
2062
|
+
});
|
|
1925
2063
|
}
|
|
1926
2064
|
move(key, fromIndex, toIndex) {
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
2065
|
+
this.withWrite(() => {
|
|
2066
|
+
const itemKey = this.index.move(key, fromIndex, toIndex);
|
|
2067
|
+
if (itemKey === void 0) return;
|
|
2068
|
+
this.appendCommand(key, {
|
|
2069
|
+
type: "move",
|
|
2070
|
+
key: itemKey,
|
|
2071
|
+
fromIndex,
|
|
2072
|
+
toIndex
|
|
2073
|
+
});
|
|
1934
2074
|
});
|
|
1935
2075
|
}
|
|
1936
|
-
|
|
1937
|
-
this.
|
|
1938
|
-
|
|
2076
|
+
set(key, keys) {
|
|
2077
|
+
this.withWrite(() => {
|
|
2078
|
+
this.index.reset(key, keys);
|
|
2079
|
+
this.appendCommand(key, { type: "set", keys });
|
|
2080
|
+
});
|
|
1939
2081
|
}
|
|
1940
2082
|
/**
|
|
1941
2083
|
* Read-only peek at buffered commands without clearing them.
|
|
@@ -1950,8 +2092,7 @@ var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
|
1950
2092
|
consumeCommands(key) {
|
|
1951
2093
|
const cmds = this.commandsByKey.get(key);
|
|
1952
2094
|
if (!cmds || cmds.length === 0) return [];
|
|
1953
|
-
|
|
1954
|
-
return cmds;
|
|
2095
|
+
return cmds.slice();
|
|
1955
2096
|
}
|
|
1956
2097
|
clear(key) {
|
|
1957
2098
|
if (key === void 0) {
|
|
@@ -1964,17 +2105,38 @@ var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
|
1964
2105
|
}
|
|
1965
2106
|
destroy() {
|
|
1966
2107
|
this.commandsEventEmitter.destroy();
|
|
1967
|
-
this.
|
|
2108
|
+
this.unsubscribeAfterFlush();
|
|
2109
|
+
this.unsubscribeFromIndexEmitter();
|
|
1968
2110
|
this.clear();
|
|
1969
2111
|
}
|
|
2112
|
+
withWrite(fn) {
|
|
2113
|
+
if (this.isInWrite) {
|
|
2114
|
+
fn();
|
|
2115
|
+
return;
|
|
2116
|
+
}
|
|
2117
|
+
this.isInWrite = true;
|
|
2118
|
+
try {
|
|
2119
|
+
fn();
|
|
2120
|
+
} finally {
|
|
2121
|
+
this.isInWrite = false;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
1970
2124
|
appendCommand(key, cmd) {
|
|
1971
2125
|
let cmds = this.commandsByKey.get(key);
|
|
1972
2126
|
if (!cmds) {
|
|
1973
2127
|
cmds = [];
|
|
1974
2128
|
this.commandsByKey.set(key, cmds);
|
|
1975
2129
|
}
|
|
1976
|
-
|
|
1977
|
-
|
|
2130
|
+
if (cmd.type === "set") {
|
|
2131
|
+
cmds.length = 0;
|
|
2132
|
+
cmds.push(cmd);
|
|
2133
|
+
} else if (cmds.length > 0 && cmds[0].type === "set") {
|
|
2134
|
+
const setCmd = cmds[0];
|
|
2135
|
+
setCmd.keys = Array.from(this.index.getPksByKey(key));
|
|
2136
|
+
} else {
|
|
2137
|
+
cmds.push(cmd);
|
|
2138
|
+
}
|
|
2139
|
+
this.commandsEventEmitter.markUpdatedKeys([key]);
|
|
1978
2140
|
}
|
|
1979
2141
|
};
|
|
1980
2142
|
|
|
@@ -2147,159 +2309,160 @@ var OIMEventQueueSchedulerFactory = class {
|
|
|
2147
2309
|
}
|
|
2148
2310
|
};
|
|
2149
2311
|
|
|
2312
|
+
// src/const/OIMDBSettings.ts
|
|
2313
|
+
var OIMDBSettings = class {
|
|
2314
|
+
};
|
|
2315
|
+
/**
|
|
2316
|
+
* Fixed key used in the manual index to store updated keys set in coalescers.
|
|
2317
|
+
* This constant is exported so users can create their own indexes and pass them to coalescers.
|
|
2318
|
+
*/
|
|
2319
|
+
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
2320
|
+
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY = "__flushingKeys__";
|
|
2321
|
+
|
|
2322
|
+
// src/modules/effect/core/OIMEffectDependencyComputed.ts
|
|
2323
|
+
var OIMEffectDependencyComputed = class {
|
|
2324
|
+
constructor(computed) {
|
|
2325
|
+
this.computed = computed;
|
|
2326
|
+
}
|
|
2327
|
+
subscribe(onUpdate) {
|
|
2328
|
+
return this.computed.emitter.on("update", onUpdate);
|
|
2329
|
+
}
|
|
2330
|
+
};
|
|
2331
|
+
|
|
2150
2332
|
// src/modules/effect/core/OIMEffect.ts
|
|
2151
2333
|
var OIMEffect = class {
|
|
2152
|
-
constructor(
|
|
2153
|
-
this.
|
|
2154
|
-
this.
|
|
2155
|
-
this.
|
|
2156
|
-
this.
|
|
2334
|
+
constructor(runtime, opts) {
|
|
2335
|
+
this.sourceDeps = [];
|
|
2336
|
+
this.computedDeps = [];
|
|
2337
|
+
this.sourceUnsubscribers = [];
|
|
2338
|
+
this.computedUnsubscribers = [];
|
|
2339
|
+
this.isResubscribeEnqueued = false;
|
|
2340
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2157
2341
|
this.isScheduled = false;
|
|
2158
|
-
this.handleQueueBeforeFlush = () => {
|
|
2159
|
-
this.isInFlush = true;
|
|
2160
|
-
this.hasRunInThisFlush = false;
|
|
2161
|
-
};
|
|
2162
|
-
this.handleQueueAfterFlush = () => {
|
|
2163
|
-
this.isInFlush = false;
|
|
2164
|
-
this.hasRunInThisFlush = false;
|
|
2165
|
-
};
|
|
2166
2342
|
this.runTask = () => {
|
|
2167
2343
|
this.isScheduled = false;
|
|
2168
|
-
|
|
2344
|
+
this.dequeueScheduled = void 0;
|
|
2169
2345
|
this.runOnce();
|
|
2170
2346
|
};
|
|
2171
|
-
this.
|
|
2172
|
-
|
|
2173
|
-
this.
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
this.
|
|
2177
|
-
this.runOnce();
|
|
2178
|
-
return;
|
|
2347
|
+
this.onSourceInvalidate = () => {
|
|
2348
|
+
this.onUpdate?.();
|
|
2349
|
+
if (!this.isTemporarilyUnsubscribedForFlush) {
|
|
2350
|
+
this.isTemporarilyUnsubscribedForFlush = true;
|
|
2351
|
+
this.unsubscribeFromSourceDeps();
|
|
2352
|
+
this.ensureResubscribeAfterFlush();
|
|
2179
2353
|
}
|
|
2180
2354
|
if (this.isScheduled) return;
|
|
2181
2355
|
this.isScheduled = true;
|
|
2182
|
-
this.
|
|
2356
|
+
this.dequeueScheduled = this.runtime.schedule(this.runTask);
|
|
2183
2357
|
};
|
|
2184
|
-
this.
|
|
2185
|
-
|
|
2186
|
-
|
|
2358
|
+
this.onComputedInvalidate = () => {
|
|
2359
|
+
this.onUpdate?.();
|
|
2360
|
+
if (this.isScheduled) return;
|
|
2361
|
+
this.isScheduled = true;
|
|
2362
|
+
this.dequeueScheduled = this.runtime.schedule(this.runTask);
|
|
2363
|
+
};
|
|
2364
|
+
this.onAfterFlush = () => {
|
|
2365
|
+
if (!this.isResubscribeEnqueued) return;
|
|
2366
|
+
this.isResubscribeEnqueued = false;
|
|
2367
|
+
this.dequeueResubscribe = void 0;
|
|
2368
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2369
|
+
if (this.sourceUnsubscribers.length === 0) {
|
|
2370
|
+
for (const dep of this.sourceDeps) {
|
|
2371
|
+
this.sourceUnsubscribers.push(
|
|
2372
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2373
|
+
);
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
this.runtime = runtime;
|
|
2378
|
+
this.onUpdate = opts.onUpdate;
|
|
2187
2379
|
this.run = opts.run;
|
|
2188
2380
|
this.deps = opts.deps ?? [];
|
|
2189
|
-
this.queue.emitter.on(
|
|
2190
|
-
1 /* BEFORE_FLUSH */,
|
|
2191
|
-
this.handleQueueBeforeFlush
|
|
2192
|
-
);
|
|
2193
|
-
this.queue.emitter.on(
|
|
2194
|
-
0 /* AFTER_FLUSH */,
|
|
2195
|
-
this.handleQueueAfterFlush
|
|
2196
|
-
);
|
|
2197
2381
|
for (const dep of this.deps) {
|
|
2198
|
-
|
|
2382
|
+
if (dep instanceof OIMEffectDependencyComputed) {
|
|
2383
|
+
this.computedDeps.push(dep);
|
|
2384
|
+
} else {
|
|
2385
|
+
this.sourceDeps.push(dep);
|
|
2386
|
+
}
|
|
2199
2387
|
}
|
|
2388
|
+
this.subscribeToDeps();
|
|
2200
2389
|
}
|
|
2201
2390
|
destroy() {
|
|
2202
|
-
if (this.
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
this.
|
|
2207
|
-
|
|
2208
|
-
this.
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
);
|
|
2391
|
+
if (this.dequeueScheduled) {
|
|
2392
|
+
this.dequeueScheduled();
|
|
2393
|
+
this.dequeueScheduled = void 0;
|
|
2394
|
+
}
|
|
2395
|
+
this.unsubscribeFromAllDeps();
|
|
2396
|
+
if (this.dequeueResubscribe) {
|
|
2397
|
+
this.dequeueResubscribe();
|
|
2398
|
+
this.dequeueResubscribe = void 0;
|
|
2399
|
+
}
|
|
2400
|
+
this.isResubscribeEnqueued = false;
|
|
2401
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2214
2402
|
}
|
|
2215
2403
|
runOnce() {
|
|
2216
|
-
if (this.isDestroyed) return;
|
|
2217
2404
|
this.run();
|
|
2218
2405
|
}
|
|
2406
|
+
subscribeToDeps() {
|
|
2407
|
+
if (this.sourceUnsubscribers.length > 0 || this.computedUnsubscribers.length > 0)
|
|
2408
|
+
return;
|
|
2409
|
+
for (const dep of this.sourceDeps) {
|
|
2410
|
+
this.sourceUnsubscribers.push(
|
|
2411
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2412
|
+
);
|
|
2413
|
+
}
|
|
2414
|
+
for (const dep of this.computedDeps) {
|
|
2415
|
+
this.computedUnsubscribers.push(
|
|
2416
|
+
dep.subscribe(this.onComputedInvalidate)
|
|
2417
|
+
);
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
unsubscribeFromSourceDeps() {
|
|
2421
|
+
if (this.sourceUnsubscribers.length === 0) return;
|
|
2422
|
+
for (const unsubscribe of this.sourceUnsubscribers) unsubscribe();
|
|
2423
|
+
this.sourceUnsubscribers = [];
|
|
2424
|
+
}
|
|
2425
|
+
unsubscribeFromAllDeps() {
|
|
2426
|
+
this.unsubscribeFromSourceDeps();
|
|
2427
|
+
if (this.computedUnsubscribers.length === 0) return;
|
|
2428
|
+
for (const unsubscribe of this.computedUnsubscribers) unsubscribe();
|
|
2429
|
+
this.computedUnsubscribers = [];
|
|
2430
|
+
}
|
|
2431
|
+
ensureResubscribeAfterFlush() {
|
|
2432
|
+
if (this.isResubscribeEnqueued) return;
|
|
2433
|
+
this.isResubscribeEnqueued = true;
|
|
2434
|
+
this.dequeueResubscribe = this.runtime.scheduleAfterFlush(
|
|
2435
|
+
this.onAfterFlush
|
|
2436
|
+
);
|
|
2437
|
+
}
|
|
2219
2438
|
};
|
|
2220
2439
|
|
|
2221
|
-
// src/modules/effect/enum/EOIMEffectPhase.ts
|
|
2222
|
-
var EOIMEffectPhase = /* @__PURE__ */ ((EOIMEffectPhase2) => {
|
|
2223
|
-
EOIMEffectPhase2["PRE"] = "pre";
|
|
2224
|
-
EOIMEffectPhase2["HANDLERS"] = "handlers";
|
|
2225
|
-
return EOIMEffectPhase2;
|
|
2226
|
-
})(EOIMEffectPhase || {});
|
|
2227
|
-
|
|
2228
2440
|
// src/modules/computed/enum/EOIMComputedEventType.ts
|
|
2229
2441
|
var EOIMComputedEventType = /* @__PURE__ */ ((EOIMComputedEventType2) => {
|
|
2230
2442
|
EOIMComputedEventType2["UPDATE"] = "update";
|
|
2231
2443
|
return EOIMComputedEventType2;
|
|
2232
2444
|
})(EOIMComputedEventType || {});
|
|
2233
2445
|
|
|
2234
|
-
// src/modules/computed/core/OIMUpdateEventCoalescerComputed.ts
|
|
2235
|
-
var OIMUpdateEventCoalescerComputed = class extends OIMUpdateEventCoalescer {
|
|
2236
|
-
constructor(computedEmitter) {
|
|
2237
|
-
super();
|
|
2238
|
-
this.computedEmitter = computedEmitter;
|
|
2239
|
-
this.handleUpdate = (payload) => {
|
|
2240
|
-
this.addUpdatedKeys(payload.keys);
|
|
2241
|
-
};
|
|
2242
|
-
this.computedEmitter.on(
|
|
2243
|
-
"update" /* UPDATE */,
|
|
2244
|
-
this.handleUpdate
|
|
2245
|
-
);
|
|
2246
|
-
}
|
|
2247
|
-
destroy() {
|
|
2248
|
-
this.computedEmitter.off(
|
|
2249
|
-
"update" /* UPDATE */,
|
|
2250
|
-
this.handleUpdate
|
|
2251
|
-
);
|
|
2252
|
-
this.emitter.offAll();
|
|
2253
|
-
this.clearUpdatedKeys();
|
|
2254
|
-
}
|
|
2255
|
-
};
|
|
2256
|
-
|
|
2257
2446
|
// src/modules/computed/core/OIMComputed.ts
|
|
2258
2447
|
var OIMComputed = class {
|
|
2259
|
-
constructor(
|
|
2448
|
+
constructor(runtime, opts) {
|
|
2260
2449
|
this.emitter = new OIMEventEmitter();
|
|
2261
2450
|
this.hasValue = false;
|
|
2262
2451
|
this.isDirty = true;
|
|
2263
|
-
this.
|
|
2264
|
-
this.hasRecomputedInThisFlush = false;
|
|
2265
|
-
this.handleQueueBeforeFlush = () => {
|
|
2266
|
-
this.isInFlush = true;
|
|
2267
|
-
this.hasRecomputedInThisFlush = false;
|
|
2268
|
-
};
|
|
2269
|
-
this.handleQueueAfterFlush = () => {
|
|
2270
|
-
this.isInFlush = false;
|
|
2271
|
-
this.hasRecomputedInThisFlush = false;
|
|
2272
|
-
};
|
|
2273
|
-
this.queue = queue;
|
|
2452
|
+
this.runtime = runtime;
|
|
2274
2453
|
this.compute = opts.compute;
|
|
2275
2454
|
this.compare = opts.compare ?? Object.is;
|
|
2276
2455
|
this.deps = opts.deps ?? [];
|
|
2277
|
-
this.
|
|
2278
|
-
this.
|
|
2279
|
-
|
|
2280
|
-
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
2281
|
-
coalescer: this.coalescer,
|
|
2282
|
-
queue: this.queue
|
|
2283
|
-
});
|
|
2284
|
-
this.queue.emitter.on(
|
|
2285
|
-
1 /* BEFORE_FLUSH */,
|
|
2286
|
-
this.handleQueueBeforeFlush
|
|
2287
|
-
);
|
|
2288
|
-
this.queue.emitter.on(
|
|
2289
|
-
0 /* AFTER_FLUSH */,
|
|
2290
|
-
this.handleQueueAfterFlush
|
|
2456
|
+
this.updateEventEmitter = new OIMUpdateEventEmitter(
|
|
2457
|
+
this.runtime.queue,
|
|
2458
|
+
"immediate"
|
|
2291
2459
|
);
|
|
2292
|
-
this.effect = new OIMEffect(this.
|
|
2460
|
+
this.effect = new OIMEffect(this.runtime, {
|
|
2293
2461
|
deps: this.deps,
|
|
2294
|
-
|
|
2295
|
-
onInvalidate: () => {
|
|
2462
|
+
onUpdate: () => {
|
|
2296
2463
|
this.isDirty = true;
|
|
2297
2464
|
},
|
|
2298
2465
|
run: () => {
|
|
2299
|
-
if (this.isInFlush) {
|
|
2300
|
-
if (this.hasRecomputedInThisFlush) return;
|
|
2301
|
-
this.hasRecomputedInThisFlush = true;
|
|
2302
|
-
}
|
|
2303
2466
|
this.recomputeAndEmitIfChanged();
|
|
2304
2467
|
}
|
|
2305
2468
|
});
|
|
@@ -2313,16 +2476,7 @@ var OIMComputed = class {
|
|
|
2313
2476
|
}
|
|
2314
2477
|
destroy() {
|
|
2315
2478
|
this.effect.destroy();
|
|
2316
|
-
this.queue.emitter.off(
|
|
2317
|
-
1 /* BEFORE_FLUSH */,
|
|
2318
|
-
this.handleQueueBeforeFlush
|
|
2319
|
-
);
|
|
2320
|
-
this.queue.emitter.off(
|
|
2321
|
-
0 /* AFTER_FLUSH */,
|
|
2322
|
-
this.handleQueueAfterFlush
|
|
2323
|
-
);
|
|
2324
2479
|
this.updateEventEmitter.destroy();
|
|
2325
|
-
this.coalescer.destroy();
|
|
2326
2480
|
this.emitter.offAll();
|
|
2327
2481
|
}
|
|
2328
2482
|
recomputeAndEmitIfChanged() {
|
|
@@ -2338,6 +2492,7 @@ var OIMComputed = class {
|
|
|
2338
2492
|
this.emitter.emit("update" /* UPDATE */, {
|
|
2339
2493
|
keys: ["value"]
|
|
2340
2494
|
});
|
|
2495
|
+
this.updateEventEmitter.markUpdatedKey("value");
|
|
2341
2496
|
}
|
|
2342
2497
|
};
|
|
2343
2498
|
|
|
@@ -2346,31 +2501,21 @@ function isReadonlyArray(value) {
|
|
|
2346
2501
|
return Array.isArray(value);
|
|
2347
2502
|
}
|
|
2348
2503
|
var OIMEffectDependencyKeyed = class {
|
|
2349
|
-
constructor(
|
|
2350
|
-
this.
|
|
2504
|
+
constructor(subscription, keyOrKeys) {
|
|
2505
|
+
this.subscription = subscription;
|
|
2351
2506
|
if (isReadonlyArray(keyOrKeys)) {
|
|
2352
2507
|
this.keys = keyOrKeys;
|
|
2353
2508
|
} else {
|
|
2354
2509
|
this.key = keyOrKeys;
|
|
2355
2510
|
}
|
|
2356
2511
|
}
|
|
2357
|
-
subscribe(
|
|
2358
|
-
const isPre = phase === "pre" /* PRE */;
|
|
2512
|
+
subscribe(onUpdate) {
|
|
2359
2513
|
if (this.keys !== void 0) {
|
|
2360
|
-
return
|
|
2361
|
-
this.keys,
|
|
2362
|
-
onInvalidate
|
|
2363
|
-
) : this.updateEventEmitter.subscribeOnKeys(
|
|
2364
|
-
this.keys,
|
|
2365
|
-
onInvalidate
|
|
2366
|
-
);
|
|
2514
|
+
return this.subscription.subscribeOnKeys(this.keys, onUpdate);
|
|
2367
2515
|
}
|
|
2368
2516
|
if (this.key === void 0) return () => {
|
|
2369
2517
|
};
|
|
2370
|
-
return
|
|
2371
|
-
this.key,
|
|
2372
|
-
onInvalidate
|
|
2373
|
-
) : this.updateEventEmitter.subscribeOnKey(this.key, onInvalidate);
|
|
2518
|
+
return this.subscription.subscribeOnKey(this.key, onUpdate);
|
|
2374
2519
|
}
|
|
2375
2520
|
};
|
|
2376
2521
|
|
|
@@ -2378,12 +2523,12 @@ var OIMEffectDependencyKeyed = class {
|
|
|
2378
2523
|
var OIMEffectDependencyKeyedObject = class {
|
|
2379
2524
|
constructor(object, keyOrKeys) {
|
|
2380
2525
|
this.dep = new OIMEffectDependencyKeyed(
|
|
2381
|
-
object
|
|
2526
|
+
object,
|
|
2382
2527
|
keyOrKeys
|
|
2383
2528
|
);
|
|
2384
2529
|
}
|
|
2385
|
-
subscribe(
|
|
2386
|
-
return this.dep.subscribe(
|
|
2530
|
+
subscribe(onUpdate) {
|
|
2531
|
+
return this.dep.subscribe(onUpdate);
|
|
2387
2532
|
}
|
|
2388
2533
|
};
|
|
2389
2534
|
|
|
@@ -2391,12 +2536,12 @@ var OIMEffectDependencyKeyedObject = class {
|
|
|
2391
2536
|
var OIMEffectDependencyKeyedCollection = class {
|
|
2392
2537
|
constructor(collection, pkOrPks) {
|
|
2393
2538
|
this.dep = new OIMEffectDependencyKeyed(
|
|
2394
|
-
collection
|
|
2539
|
+
collection,
|
|
2395
2540
|
pkOrPks
|
|
2396
2541
|
);
|
|
2397
2542
|
}
|
|
2398
|
-
subscribe(
|
|
2399
|
-
return this.dep.subscribe(
|
|
2543
|
+
subscribe(onUpdate) {
|
|
2544
|
+
return this.dep.subscribe(onUpdate);
|
|
2400
2545
|
}
|
|
2401
2546
|
};
|
|
2402
2547
|
|
|
@@ -2404,44 +2549,591 @@ var OIMEffectDependencyKeyedCollection = class {
|
|
|
2404
2549
|
var OIMEffectDependencyKeyedIndex = class {
|
|
2405
2550
|
constructor(index, keyOrKeys) {
|
|
2406
2551
|
this.dep = new OIMEffectDependencyKeyed(
|
|
2407
|
-
index
|
|
2552
|
+
index,
|
|
2408
2553
|
keyOrKeys
|
|
2409
2554
|
);
|
|
2410
2555
|
}
|
|
2411
|
-
subscribe(
|
|
2412
|
-
return this.dep.subscribe(
|
|
2556
|
+
subscribe(onUpdate) {
|
|
2557
|
+
return this.dep.subscribe(onUpdate);
|
|
2413
2558
|
}
|
|
2414
2559
|
};
|
|
2415
2560
|
|
|
2416
|
-
// src/modules/
|
|
2417
|
-
var
|
|
2418
|
-
constructor(
|
|
2419
|
-
this.
|
|
2561
|
+
// src/modules/selector/core/OIMSelector.ts
|
|
2562
|
+
var OIMSelector = class {
|
|
2563
|
+
constructor(runtime, sourceDeps, computedDeps = []) {
|
|
2564
|
+
this.runtime = runtime;
|
|
2565
|
+
this.sourceDeps = sourceDeps;
|
|
2566
|
+
this.computedDeps = computedDeps;
|
|
2567
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
2568
|
+
this.sourceUnsubscribers = [];
|
|
2569
|
+
this.computedUnsubscribers = [];
|
|
2570
|
+
this.isResubscribeEnqueued = false;
|
|
2571
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2572
|
+
this.isDeliveryEnqueued = false;
|
|
2573
|
+
this.hasLastValue = false;
|
|
2574
|
+
this.onSourceInvalidate = () => {
|
|
2575
|
+
if (this.listeners.size === 0) return;
|
|
2576
|
+
if (!this.isTemporarilyUnsubscribedForFlush) {
|
|
2577
|
+
this.isTemporarilyUnsubscribedForFlush = true;
|
|
2578
|
+
this.unsubscribeFromSourceDeps();
|
|
2579
|
+
this.ensureResubscribeAfterFlush();
|
|
2580
|
+
}
|
|
2581
|
+
if (this.isDeliveryEnqueued) return;
|
|
2582
|
+
this.isDeliveryEnqueued = true;
|
|
2583
|
+
this.dequeueDelivery = this.runtime.schedule(this.deliver);
|
|
2584
|
+
};
|
|
2585
|
+
this.onComputedInvalidate = () => {
|
|
2586
|
+
if (this.listeners.size === 0) return;
|
|
2587
|
+
if (this.isDeliveryEnqueued) return;
|
|
2588
|
+
this.isDeliveryEnqueued = true;
|
|
2589
|
+
this.dequeueDelivery = this.runtime.schedule(this.deliver);
|
|
2590
|
+
};
|
|
2591
|
+
this.deliver = () => {
|
|
2592
|
+
this.isDeliveryEnqueued = false;
|
|
2593
|
+
this.dequeueDelivery = void 0;
|
|
2594
|
+
if (this.listeners.size === 0) return;
|
|
2595
|
+
const next = this.getValue();
|
|
2596
|
+
if (this.hasLastValue && this.areEqual(this.lastValue, next)) return;
|
|
2597
|
+
this.setLastValue(next);
|
|
2598
|
+
const snapshot = Array.from(this.listeners);
|
|
2599
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
2600
|
+
const listener = snapshot[i];
|
|
2601
|
+
if (this.listeners.has(listener)) listener(next);
|
|
2602
|
+
}
|
|
2603
|
+
};
|
|
2604
|
+
this.onAfterFlush = () => {
|
|
2605
|
+
if (!this.isResubscribeEnqueued) return;
|
|
2606
|
+
this.isResubscribeEnqueued = false;
|
|
2607
|
+
this.dequeueResubscribe = void 0;
|
|
2608
|
+
if (this.listeners.size === 0) return;
|
|
2609
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2610
|
+
if (this.sourceUnsubscribers.length === 0) {
|
|
2611
|
+
for (const dep of this.sourceDeps) {
|
|
2612
|
+
this.sourceUnsubscribers.push(
|
|
2613
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2614
|
+
);
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
};
|
|
2618
|
+
}
|
|
2619
|
+
get queue() {
|
|
2620
|
+
return this.runtime.queue;
|
|
2621
|
+
}
|
|
2622
|
+
/**
|
|
2623
|
+
* Start watching this selector. The callback is called immediately with the current value,
|
|
2624
|
+
* then coalesced and delivered on `queue.flush()` when the selector invalidates.
|
|
2625
|
+
*/
|
|
2626
|
+
watch(onValue) {
|
|
2627
|
+
this.listeners.add(onValue);
|
|
2628
|
+
if (this.listeners.size === 1) {
|
|
2629
|
+
this.subscribeToDeps();
|
|
2630
|
+
}
|
|
2631
|
+
const current = this.getValue();
|
|
2632
|
+
this.setLastValue(current);
|
|
2633
|
+
onValue(current);
|
|
2634
|
+
return () => {
|
|
2635
|
+
this.listeners.delete(onValue);
|
|
2636
|
+
if (this.listeners.size > 0) return;
|
|
2637
|
+
this.unsubscribeFromAllDeps();
|
|
2638
|
+
if (this.dequeueResubscribe) {
|
|
2639
|
+
this.dequeueResubscribe();
|
|
2640
|
+
this.dequeueResubscribe = void 0;
|
|
2641
|
+
}
|
|
2642
|
+
this.isResubscribeEnqueued = false;
|
|
2643
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2644
|
+
if (this.dequeueDelivery) {
|
|
2645
|
+
this.dequeueDelivery();
|
|
2646
|
+
this.dequeueDelivery = void 0;
|
|
2647
|
+
}
|
|
2648
|
+
this.isDeliveryEnqueued = false;
|
|
2649
|
+
this.hasLastValue = false;
|
|
2650
|
+
};
|
|
2420
2651
|
}
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2652
|
+
areEqual(prev, next) {
|
|
2653
|
+
return Object.is(prev, next);
|
|
2654
|
+
}
|
|
2655
|
+
setLastValue(value) {
|
|
2656
|
+
this.lastValue = value;
|
|
2657
|
+
this.hasLastValue = true;
|
|
2658
|
+
}
|
|
2659
|
+
subscribeToDeps() {
|
|
2660
|
+
if (this.sourceUnsubscribers.length > 0 || this.computedUnsubscribers.length > 0)
|
|
2661
|
+
return;
|
|
2662
|
+
for (const dep of this.sourceDeps) {
|
|
2663
|
+
this.sourceUnsubscribers.push(
|
|
2664
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2665
|
+
);
|
|
2424
2666
|
}
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2667
|
+
for (const dep of this.computedDeps) {
|
|
2668
|
+
this.computedUnsubscribers.push(
|
|
2669
|
+
dep.subscribe(this.onComputedInvalidate)
|
|
2670
|
+
);
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
unsubscribeFromSourceDeps() {
|
|
2674
|
+
if (this.sourceUnsubscribers.length === 0) return;
|
|
2675
|
+
for (const unsub of this.sourceUnsubscribers) unsub();
|
|
2676
|
+
this.sourceUnsubscribers = [];
|
|
2677
|
+
}
|
|
2678
|
+
unsubscribeFromAllDeps() {
|
|
2679
|
+
this.unsubscribeFromSourceDeps();
|
|
2680
|
+
if (this.computedUnsubscribers.length === 0) return;
|
|
2681
|
+
for (const unsub of this.computedUnsubscribers) unsub();
|
|
2682
|
+
this.computedUnsubscribers = [];
|
|
2683
|
+
}
|
|
2684
|
+
ensureResubscribeAfterFlush() {
|
|
2685
|
+
if (this.isResubscribeEnqueued) return;
|
|
2686
|
+
this.isResubscribeEnqueued = true;
|
|
2687
|
+
this.dequeueResubscribe = this.runtime.scheduleAfterFlush(
|
|
2688
|
+
this.onAfterFlush
|
|
2428
2689
|
);
|
|
2429
2690
|
}
|
|
2430
2691
|
};
|
|
2692
|
+
|
|
2693
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyUpdateEventEmitterKey.ts
|
|
2694
|
+
var OIMSelectorSourceDependencyUpdateEventEmitterKey = class {
|
|
2695
|
+
constructor(subscription, key) {
|
|
2696
|
+
this.subscription = subscription;
|
|
2697
|
+
this.key = key;
|
|
2698
|
+
}
|
|
2699
|
+
subscribe(onUpdate) {
|
|
2700
|
+
return this.subscription.subscribeOnKey(this.key, onUpdate);
|
|
2701
|
+
}
|
|
2702
|
+
};
|
|
2703
|
+
|
|
2704
|
+
// src/modules/selector/core/OIMCollectionByPkSelector.ts
|
|
2705
|
+
var OIMCollectionByPkSelector = class extends OIMSelector {
|
|
2706
|
+
constructor(runtime, collection, pk) {
|
|
2707
|
+
super(runtime, [
|
|
2708
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
2709
|
+
collection,
|
|
2710
|
+
pk
|
|
2711
|
+
)
|
|
2712
|
+
]);
|
|
2713
|
+
this.collection = collection;
|
|
2714
|
+
this.pk = pk;
|
|
2715
|
+
}
|
|
2716
|
+
getValue() {
|
|
2717
|
+
return this.collection.getOneByPk(this.pk);
|
|
2718
|
+
}
|
|
2719
|
+
};
|
|
2720
|
+
|
|
2721
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyUpdateEventEmitterKeys.ts
|
|
2722
|
+
var OIMSelectorSourceDependencyUpdateEventEmitterKeys = class {
|
|
2723
|
+
constructor(subscription, keys) {
|
|
2724
|
+
this.subscription = subscription;
|
|
2725
|
+
this.keys = keys;
|
|
2726
|
+
}
|
|
2727
|
+
subscribe(onUpdate) {
|
|
2728
|
+
return this.subscription.subscribeOnKeys(this.keys, onUpdate);
|
|
2729
|
+
}
|
|
2730
|
+
};
|
|
2731
|
+
|
|
2732
|
+
// src/modules/selector/core/OIMCollectionByPksSelector.ts
|
|
2733
|
+
var OIMCollectionByPksSelector = class extends OIMSelector {
|
|
2734
|
+
constructor(runtime, collection, pks) {
|
|
2735
|
+
super(runtime, [
|
|
2736
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
2737
|
+
collection,
|
|
2738
|
+
pks
|
|
2739
|
+
)
|
|
2740
|
+
]);
|
|
2741
|
+
this.collection = collection;
|
|
2742
|
+
this.pks = pks;
|
|
2743
|
+
}
|
|
2744
|
+
getValue() {
|
|
2745
|
+
return this.pks.map((pk) => this.collection.getOneByPk(pk));
|
|
2746
|
+
}
|
|
2747
|
+
areEqual(prev, next) {
|
|
2748
|
+
if (prev === next) return true;
|
|
2749
|
+
if (prev.length !== next.length) return false;
|
|
2750
|
+
for (let i = 0; i < prev.length; i++) {
|
|
2751
|
+
if (prev[i] !== next[i]) return false;
|
|
2752
|
+
}
|
|
2753
|
+
return true;
|
|
2754
|
+
}
|
|
2755
|
+
};
|
|
2756
|
+
|
|
2757
|
+
// src/modules/selector/core/OIMObjectValueByKeySelector.ts
|
|
2758
|
+
var OIMObjectValueByKeySelector = class extends OIMSelector {
|
|
2759
|
+
constructor(runtime, obj, key) {
|
|
2760
|
+
super(runtime, [
|
|
2761
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
2762
|
+
obj,
|
|
2763
|
+
key
|
|
2764
|
+
)
|
|
2765
|
+
]);
|
|
2766
|
+
this.obj = obj;
|
|
2767
|
+
this.key = key;
|
|
2768
|
+
}
|
|
2769
|
+
getValue() {
|
|
2770
|
+
return this.obj.get(this.key);
|
|
2771
|
+
}
|
|
2772
|
+
};
|
|
2773
|
+
|
|
2774
|
+
// src/modules/selector/core/OIMObjectValuesByKeysSelector.ts
|
|
2775
|
+
var OIMObjectValuesByKeysSelector = class extends OIMSelector {
|
|
2776
|
+
constructor(runtime, obj, keys) {
|
|
2777
|
+
super(runtime, [
|
|
2778
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
2779
|
+
obj,
|
|
2780
|
+
keys
|
|
2781
|
+
)
|
|
2782
|
+
]);
|
|
2783
|
+
this.obj = obj;
|
|
2784
|
+
this.keys = keys;
|
|
2785
|
+
}
|
|
2786
|
+
getValue() {
|
|
2787
|
+
return this.keys.map((k) => this.obj.get(k));
|
|
2788
|
+
}
|
|
2789
|
+
areEqual(prev, next) {
|
|
2790
|
+
if (prev === next) return true;
|
|
2791
|
+
if (prev.length !== next.length) return false;
|
|
2792
|
+
for (let i = 0; i < prev.length; i++) {
|
|
2793
|
+
if (prev[i] !== next[i]) return false;
|
|
2794
|
+
}
|
|
2795
|
+
return true;
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
2798
|
+
|
|
2799
|
+
// src/modules/selector/core/OIMIndexPksByKeySetBasedSelector.ts
|
|
2800
|
+
var OIMIndexPksByKeySetBasedSelector = class extends OIMSelector {
|
|
2801
|
+
constructor(runtime, reactiveIndex, key) {
|
|
2802
|
+
super(runtime, [
|
|
2803
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
2804
|
+
reactiveIndex,
|
|
2805
|
+
key
|
|
2806
|
+
)
|
|
2807
|
+
]);
|
|
2808
|
+
this.reactiveIndex = reactiveIndex;
|
|
2809
|
+
this.key = key;
|
|
2810
|
+
}
|
|
2811
|
+
getValue() {
|
|
2812
|
+
return this.reactiveIndex.getPksByKey(this.key);
|
|
2813
|
+
}
|
|
2814
|
+
};
|
|
2815
|
+
|
|
2816
|
+
// src/modules/selector/core/OIMIndexPksByKeyArrayBasedSelector.ts
|
|
2817
|
+
var OIMIndexPksByKeyArrayBasedSelector = class extends OIMSelector {
|
|
2818
|
+
constructor(runtime, reactiveIndex, key) {
|
|
2819
|
+
super(runtime, [
|
|
2820
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
2821
|
+
reactiveIndex,
|
|
2822
|
+
key
|
|
2823
|
+
)
|
|
2824
|
+
]);
|
|
2825
|
+
this.reactiveIndex = reactiveIndex;
|
|
2826
|
+
this.key = key;
|
|
2827
|
+
}
|
|
2828
|
+
getValue() {
|
|
2829
|
+
return this.reactiveIndex.getPksByKey(this.key);
|
|
2830
|
+
}
|
|
2831
|
+
areEqual(prev, next) {
|
|
2832
|
+
if (prev === next) return true;
|
|
2833
|
+
if (prev.length !== next.length) return false;
|
|
2834
|
+
for (let i = 0; i < prev.length; i++)
|
|
2835
|
+
if (prev[i] !== next[i]) return false;
|
|
2836
|
+
return true;
|
|
2837
|
+
}
|
|
2838
|
+
};
|
|
2839
|
+
|
|
2840
|
+
// src/modules/selector/core/OIMIndexPksByKeysSetBasedSelector.ts
|
|
2841
|
+
var OIMIndexPksByKeysSetBasedSelector = class extends OIMSelector {
|
|
2842
|
+
constructor(runtime, reactiveIndex, keys) {
|
|
2843
|
+
super(runtime, [
|
|
2844
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
2845
|
+
reactiveIndex,
|
|
2846
|
+
keys
|
|
2847
|
+
)
|
|
2848
|
+
]);
|
|
2849
|
+
this.reactiveIndex = reactiveIndex;
|
|
2850
|
+
this.keys = keys;
|
|
2851
|
+
}
|
|
2852
|
+
getValue() {
|
|
2853
|
+
return this.keys.map((key) => Array.from(this.reactiveIndex.getPksByKey(key))).flat();
|
|
2854
|
+
}
|
|
2855
|
+
areEqual(prev, next) {
|
|
2856
|
+
if (prev === next) return true;
|
|
2857
|
+
if (prev.length !== next.length) return false;
|
|
2858
|
+
for (let i = 0; i < prev.length; i++)
|
|
2859
|
+
if (prev[i] !== next[i]) return false;
|
|
2860
|
+
return true;
|
|
2861
|
+
}
|
|
2862
|
+
};
|
|
2863
|
+
|
|
2864
|
+
// src/modules/selector/core/OIMIndexPksByKeysArrayBasedSelector.ts
|
|
2865
|
+
var OIMIndexPksByKeysArrayBasedSelector = class extends OIMSelector {
|
|
2866
|
+
constructor(runtime, reactiveIndex, keys) {
|
|
2867
|
+
super(runtime, [
|
|
2868
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
2869
|
+
reactiveIndex,
|
|
2870
|
+
keys
|
|
2871
|
+
)
|
|
2872
|
+
]);
|
|
2873
|
+
this.reactiveIndex = reactiveIndex;
|
|
2874
|
+
this.keys = keys;
|
|
2875
|
+
}
|
|
2876
|
+
getValue() {
|
|
2877
|
+
return this.keys.map((key) => this.reactiveIndex.getPksByKey(key)).flat();
|
|
2878
|
+
}
|
|
2879
|
+
areEqual(prev, next) {
|
|
2880
|
+
if (prev === next) return true;
|
|
2881
|
+
if (prev.length !== next.length) return false;
|
|
2882
|
+
for (let i = 0; i < prev.length; i++)
|
|
2883
|
+
if (prev[i] !== next[i]) return false;
|
|
2884
|
+
return true;
|
|
2885
|
+
}
|
|
2886
|
+
};
|
|
2887
|
+
|
|
2888
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyEntitiesByIndexKeySetBased.ts
|
|
2889
|
+
var OIMSelectorSourceDependencyEntitiesByIndexKeySetBased = class {
|
|
2890
|
+
constructor(collection, reactiveIndex, key) {
|
|
2891
|
+
this.collection = collection;
|
|
2892
|
+
this.reactiveIndex = reactiveIndex;
|
|
2893
|
+
this.key = key;
|
|
2894
|
+
this.currentPks = [];
|
|
2895
|
+
}
|
|
2896
|
+
subscribe(onUpdate) {
|
|
2897
|
+
const resubscribeCollection = () => {
|
|
2898
|
+
const nextPks = Array.from(
|
|
2899
|
+
this.reactiveIndex.getPksByKey(this.key)
|
|
2900
|
+
);
|
|
2901
|
+
if (this.sameArray(this.currentPks, nextPks)) return;
|
|
2902
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
2903
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
2904
|
+
this.currentPks = nextPks;
|
|
2905
|
+
if (this.currentPks.length === 0) return;
|
|
2906
|
+
this.unsubscribeFromCollectionKeys = this.collection.subscribeOnKeys(this.currentPks, onUpdate);
|
|
2907
|
+
};
|
|
2908
|
+
const onIndexUpdate = () => {
|
|
2909
|
+
resubscribeCollection();
|
|
2910
|
+
onUpdate();
|
|
2911
|
+
};
|
|
2912
|
+
resubscribeCollection();
|
|
2913
|
+
const unsubscribeFromIndex = this.reactiveIndex.subscribeOnKey(
|
|
2914
|
+
this.key,
|
|
2915
|
+
onIndexUpdate
|
|
2916
|
+
);
|
|
2917
|
+
return () => {
|
|
2918
|
+
unsubscribeFromIndex();
|
|
2919
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
2920
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
2921
|
+
this.currentPks = [];
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
sameArray(a, b) {
|
|
2925
|
+
if (a === b) return true;
|
|
2926
|
+
if (a.length !== b.length) return false;
|
|
2927
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
2928
|
+
return true;
|
|
2929
|
+
}
|
|
2930
|
+
};
|
|
2931
|
+
|
|
2932
|
+
// src/modules/selector/core/OIMEntitiesByIndexKeySetBasedSelector.ts
|
|
2933
|
+
var OIMEntitiesByIndexKeySetBasedSelector = class extends OIMSelector {
|
|
2934
|
+
constructor(runtime, collection, reactiveIndex, key) {
|
|
2935
|
+
super(runtime, [
|
|
2936
|
+
new OIMSelectorSourceDependencyEntitiesByIndexKeySetBased(collection, reactiveIndex, key)
|
|
2937
|
+
]);
|
|
2938
|
+
this.collection = collection;
|
|
2939
|
+
this.reactiveIndex = reactiveIndex;
|
|
2940
|
+
this.key = key;
|
|
2941
|
+
}
|
|
2942
|
+
getValue() {
|
|
2943
|
+
const pks = Array.from(this.reactiveIndex.getPksByKey(this.key));
|
|
2944
|
+
return pks.map((pk) => this.collection.getOneByPk(pk));
|
|
2945
|
+
}
|
|
2946
|
+
areEqual(prev, next) {
|
|
2947
|
+
if (prev === next) return true;
|
|
2948
|
+
if (prev.length !== next.length) return false;
|
|
2949
|
+
for (let i = 0; i < prev.length; i++)
|
|
2950
|
+
if (prev[i] !== next[i]) return false;
|
|
2951
|
+
return true;
|
|
2952
|
+
}
|
|
2953
|
+
};
|
|
2954
|
+
|
|
2955
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyEntitiesByIndexKeyArrayBased.ts
|
|
2956
|
+
var OIMSelectorSourceDependencyEntitiesByIndexKeyArrayBased = class {
|
|
2957
|
+
constructor(collection, reactiveIndex, key) {
|
|
2958
|
+
this.collection = collection;
|
|
2959
|
+
this.reactiveIndex = reactiveIndex;
|
|
2960
|
+
this.key = key;
|
|
2961
|
+
this.currentPks = [];
|
|
2962
|
+
}
|
|
2963
|
+
subscribe(onUpdate) {
|
|
2964
|
+
const resubscribeCollection = () => {
|
|
2965
|
+
const nextPks = this.reactiveIndex.getPksByKey(this.key);
|
|
2966
|
+
if (this.sameArray(this.currentPks, nextPks)) return;
|
|
2967
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
2968
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
2969
|
+
this.currentPks = nextPks;
|
|
2970
|
+
if (this.currentPks.length === 0) return;
|
|
2971
|
+
this.unsubscribeFromCollectionKeys = this.collection.subscribeOnKeys(this.currentPks, onUpdate);
|
|
2972
|
+
};
|
|
2973
|
+
const onIndexUpdate = () => {
|
|
2974
|
+
resubscribeCollection();
|
|
2975
|
+
onUpdate();
|
|
2976
|
+
};
|
|
2977
|
+
resubscribeCollection();
|
|
2978
|
+
const unsubscribeFromIndex = this.reactiveIndex.subscribeOnKey(
|
|
2979
|
+
this.key,
|
|
2980
|
+
onIndexUpdate
|
|
2981
|
+
);
|
|
2982
|
+
return () => {
|
|
2983
|
+
unsubscribeFromIndex();
|
|
2984
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
2985
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
2986
|
+
this.currentPks = [];
|
|
2987
|
+
};
|
|
2988
|
+
}
|
|
2989
|
+
sameArray(a, b) {
|
|
2990
|
+
if (a === b) return true;
|
|
2991
|
+
if (a.length !== b.length) return false;
|
|
2992
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
2993
|
+
return true;
|
|
2994
|
+
}
|
|
2995
|
+
};
|
|
2996
|
+
|
|
2997
|
+
// src/modules/selector/core/OIMEntitiesByIndexKeyArrayBasedSelector.ts
|
|
2998
|
+
var OIMEntitiesByIndexKeyArrayBasedSelector = class extends OIMSelector {
|
|
2999
|
+
constructor(runtime, collection, reactiveIndex, key) {
|
|
3000
|
+
super(runtime, [
|
|
3001
|
+
new OIMSelectorSourceDependencyEntitiesByIndexKeyArrayBased(collection, reactiveIndex, key)
|
|
3002
|
+
]);
|
|
3003
|
+
this.collection = collection;
|
|
3004
|
+
this.reactiveIndex = reactiveIndex;
|
|
3005
|
+
this.key = key;
|
|
3006
|
+
}
|
|
3007
|
+
getValue() {
|
|
3008
|
+
const pks = this.reactiveIndex.getPksByKey(this.key);
|
|
3009
|
+
return pks.map((pk) => this.collection.getOneByPk(pk));
|
|
3010
|
+
}
|
|
3011
|
+
areEqual(prev, next) {
|
|
3012
|
+
if (prev === next) return true;
|
|
3013
|
+
if (prev.length !== next.length) return false;
|
|
3014
|
+
for (let i = 0; i < prev.length; i++)
|
|
3015
|
+
if (prev[i] !== next[i]) return false;
|
|
3016
|
+
return true;
|
|
3017
|
+
}
|
|
3018
|
+
};
|
|
3019
|
+
|
|
3020
|
+
// src/modules/computative/core/OIMComputativeRuntime.ts
|
|
3021
|
+
var OIMComputativeRuntime = class {
|
|
3022
|
+
constructor(queue) {
|
|
3023
|
+
this.queue = queue;
|
|
3024
|
+
this.isFlushScheduled = false;
|
|
3025
|
+
this.isFlushing = false;
|
|
3026
|
+
this.minLevel = Infinity;
|
|
3027
|
+
this.maxLevel = -Infinity;
|
|
3028
|
+
this.dirtyByLevel = /* @__PURE__ */ new Map();
|
|
3029
|
+
this.afterFlushTasks = /* @__PURE__ */ new Set();
|
|
3030
|
+
this.queue.emitter.on(0 /* AFTER_FLUSH */, () => {
|
|
3031
|
+
if (!this.isFlushScheduled) return;
|
|
3032
|
+
this.flush();
|
|
3033
|
+
});
|
|
3034
|
+
}
|
|
3035
|
+
/**
|
|
3036
|
+
* Schedule a one-shot task to run on the next `queue.flush()` (AFTER_FLUSH),
|
|
3037
|
+
* ordered by `level` ascending.
|
|
3038
|
+
*/
|
|
3039
|
+
schedule(task, level = 0) {
|
|
3040
|
+
let isActive = true;
|
|
3041
|
+
const wrapped = () => {
|
|
3042
|
+
if (!isActive) return;
|
|
3043
|
+
task();
|
|
3044
|
+
};
|
|
3045
|
+
let bucket = this.dirtyByLevel.get(level);
|
|
3046
|
+
if (!bucket) {
|
|
3047
|
+
bucket = /* @__PURE__ */ new Set();
|
|
3048
|
+
this.dirtyByLevel.set(level, bucket);
|
|
3049
|
+
}
|
|
3050
|
+
bucket.add(wrapped);
|
|
3051
|
+
if (level < this.minLevel) this.minLevel = level;
|
|
3052
|
+
if (level > this.maxLevel) this.maxLevel = level;
|
|
3053
|
+
if (!this.isFlushing) this.isFlushScheduled = true;
|
|
3054
|
+
return () => {
|
|
3055
|
+
if (!isActive) return;
|
|
3056
|
+
isActive = false;
|
|
3057
|
+
bucket.delete(wrapped);
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
/**
|
|
3061
|
+
* Run once at the start of the next runtime flush (i.e. after queue.flush()).
|
|
3062
|
+
* Useful for resubscribing dependencies exactly once per source flush.
|
|
3063
|
+
*/
|
|
3064
|
+
scheduleAfterFlush(task) {
|
|
3065
|
+
let isActive = true;
|
|
3066
|
+
const wrapped = () => {
|
|
3067
|
+
if (!isActive) return;
|
|
3068
|
+
task();
|
|
3069
|
+
};
|
|
3070
|
+
this.afterFlushTasks.add(wrapped);
|
|
3071
|
+
if (!this.isFlushing) this.isFlushScheduled = true;
|
|
3072
|
+
return () => {
|
|
3073
|
+
if (!isActive) return;
|
|
3074
|
+
isActive = false;
|
|
3075
|
+
this.afterFlushTasks.delete(wrapped);
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
3078
|
+
flush() {
|
|
3079
|
+
this.isFlushScheduled = false;
|
|
3080
|
+
if (this.dirtyByLevel.size === 0 && this.afterFlushTasks.size === 0)
|
|
3081
|
+
return;
|
|
3082
|
+
this.isFlushing = true;
|
|
3083
|
+
try {
|
|
3084
|
+
if (this.afterFlushTasks.size > 0) {
|
|
3085
|
+
const snapshot = Array.from(this.afterFlushTasks);
|
|
3086
|
+
this.afterFlushTasks.clear();
|
|
3087
|
+
for (let i = 0; i < snapshot.length; i++) snapshot[i]();
|
|
3088
|
+
}
|
|
3089
|
+
if (this.dirtyByLevel.size === 0) return;
|
|
3090
|
+
let level = this.minLevel;
|
|
3091
|
+
let max = this.maxLevel;
|
|
3092
|
+
while (level <= max) {
|
|
3093
|
+
for (; ; ) {
|
|
3094
|
+
const bucket = this.dirtyByLevel.get(level);
|
|
3095
|
+
if (!bucket || bucket.size === 0) break;
|
|
3096
|
+
this.dirtyByLevel.delete(level);
|
|
3097
|
+
const snapshot = Array.from(bucket);
|
|
3098
|
+
for (let i = 0; i < snapshot.length; i++) snapshot[i]();
|
|
3099
|
+
}
|
|
3100
|
+
if (this.maxLevel > max) max = this.maxLevel;
|
|
3101
|
+
level++;
|
|
3102
|
+
}
|
|
3103
|
+
} finally {
|
|
3104
|
+
this.isFlushing = false;
|
|
3105
|
+
if (this.dirtyByLevel.size === 0) {
|
|
3106
|
+
this.minLevel = Infinity;
|
|
3107
|
+
this.maxLevel = -Infinity;
|
|
3108
|
+
} else {
|
|
3109
|
+
let nextMin = Infinity;
|
|
3110
|
+
let nextMax = -Infinity;
|
|
3111
|
+
this.dirtyByLevel.forEach((_bucket, lvl) => {
|
|
3112
|
+
if (lvl < nextMin) nextMin = lvl;
|
|
3113
|
+
if (lvl > nextMax) nextMax = lvl;
|
|
3114
|
+
});
|
|
3115
|
+
this.minLevel = nextMin;
|
|
3116
|
+
this.maxLevel = nextMax;
|
|
3117
|
+
this.isFlushScheduled = true;
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
};
|
|
2431
3122
|
export {
|
|
2432
3123
|
EOIMCollectionEventType,
|
|
2433
3124
|
EOIMComputedEventType,
|
|
2434
|
-
EOIMEffectPhase,
|
|
2435
3125
|
EOIMEventQueueEventType,
|
|
2436
3126
|
EOIMEventQueueSchedulerEventType,
|
|
2437
3127
|
EOIMIndexEventType,
|
|
2438
3128
|
EOIMObjectEventType,
|
|
2439
|
-
EOIMUpdateEventCoalescerEventType,
|
|
2440
3129
|
OIMCollection,
|
|
3130
|
+
OIMCollectionByPkSelector,
|
|
3131
|
+
OIMCollectionByPksSelector,
|
|
2441
3132
|
OIMCollectionChangedFieldsWrapper,
|
|
2442
3133
|
OIMCollectionStore,
|
|
2443
3134
|
OIMCollectionStoreMapDriven,
|
|
2444
3135
|
OIMComparatorFactory,
|
|
3136
|
+
OIMComputativeRuntime,
|
|
2445
3137
|
OIMComputed,
|
|
2446
3138
|
OIMDBSettings,
|
|
2447
3139
|
OIMEffect,
|
|
@@ -2450,6 +3142,8 @@ export {
|
|
|
2450
3142
|
OIMEffectDependencyKeyedCollection,
|
|
2451
3143
|
OIMEffectDependencyKeyedIndex,
|
|
2452
3144
|
OIMEffectDependencyKeyedObject,
|
|
3145
|
+
OIMEntitiesByIndexKeyArrayBasedSelector,
|
|
3146
|
+
OIMEntitiesByIndexKeySetBasedSelector,
|
|
2453
3147
|
OIMEntityUpdaterFactory,
|
|
2454
3148
|
OIMEventEmitter,
|
|
2455
3149
|
OIMEventQueue,
|
|
@@ -2464,6 +3158,10 @@ export {
|
|
|
2464
3158
|
OIMIndexManualArrayBased,
|
|
2465
3159
|
OIMIndexManualOrderedArrayBased,
|
|
2466
3160
|
OIMIndexManualSetBased,
|
|
3161
|
+
OIMIndexPksByKeyArrayBasedSelector,
|
|
3162
|
+
OIMIndexPksByKeySetBasedSelector,
|
|
3163
|
+
OIMIndexPksByKeysArrayBasedSelector,
|
|
3164
|
+
OIMIndexPksByKeysSetBasedSelector,
|
|
2467
3165
|
OIMIndexSetBased,
|
|
2468
3166
|
OIMIndexStoreArrayBased,
|
|
2469
3167
|
OIMIndexStoreMapDrivenArrayBased,
|
|
@@ -2474,6 +3172,8 @@ export {
|
|
|
2474
3172
|
OIMObjectStore,
|
|
2475
3173
|
OIMObjectStoreMapDriven,
|
|
2476
3174
|
OIMObjectStoreRecordDriven,
|
|
3175
|
+
OIMObjectValueByKeySelector,
|
|
3176
|
+
OIMObjectValuesByKeysSelector,
|
|
2477
3177
|
OIMOrderedListIndexCommandStreamWrapper,
|
|
2478
3178
|
OIMPkSelectorFactory,
|
|
2479
3179
|
OIMRICollection,
|
|
@@ -2483,11 +3183,5 @@ export {
|
|
|
2483
3183
|
OIMReactiveIndexManualSetBased,
|
|
2484
3184
|
OIMReactiveIndexSetBased,
|
|
2485
3185
|
OIMReactiveObject,
|
|
2486
|
-
|
|
2487
|
-
OIMUpdateEventCoalescerCollection,
|
|
2488
|
-
OIMUpdateEventCoalescerComputed,
|
|
2489
|
-
OIMUpdateEventCoalescerIndex,
|
|
2490
|
-
OIMUpdateEventCoalescerManual,
|
|
2491
|
-
OIMUpdateEventCoalescerObject,
|
|
2492
|
-
OIMUpdateEventEmitter
|
|
3186
|
+
OIMSelector
|
|
2493
3187
|
};
|