@oimdb/core 1.3.1 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +148 -0
- package/dist/index.cjs +1018 -53
- package/dist/index.d.cts +426 -6
- package/dist/index.d.ts +426 -6
- package/dist/index.js +997 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28,39 +28,40 @@ var OIMEventEmitter = class {
|
|
|
28
28
|
}
|
|
29
29
|
return bucket;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Compacts the handlers array by removing null entries (tombstones) left by handler removal.
|
|
33
|
+
* Rebuilds the indexByHandler map with updated indices and resets the tombstone count.
|
|
34
|
+
* This reduces array fragmentation and improves iteration performance.
|
|
35
|
+
*/
|
|
31
36
|
compactBucket(bucket) {
|
|
32
37
|
const handlers = bucket.handlers;
|
|
33
38
|
const length = handlers.length;
|
|
34
39
|
const newHandlers = [];
|
|
35
40
|
bucket.indexByHandler.clear();
|
|
36
|
-
if (bucket.tombstoneCount < length >> 2) {
|
|
37
|
-
newHandlers.length = length - bucket.tombstoneCount;
|
|
38
|
-
}
|
|
39
|
-
let writeIndex = 0;
|
|
40
41
|
for (let i = 0; i < length; i++) {
|
|
41
42
|
const handler = handlers[i];
|
|
42
43
|
if (handler) {
|
|
43
|
-
|
|
44
|
+
const writeIndex = newHandlers.length;
|
|
45
|
+
newHandlers.push(handler);
|
|
44
46
|
bucket.indexByHandler.set(handler, writeIndex);
|
|
45
|
-
writeIndex++;
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
if (newHandlers.length !== writeIndex) {
|
|
49
|
-
newHandlers.length = writeIndex;
|
|
50
|
-
}
|
|
51
49
|
bucket.handlers = newHandlers;
|
|
52
50
|
bucket.tombstoneCount = 0;
|
|
53
51
|
}
|
|
54
52
|
on(event, handler) {
|
|
55
53
|
const bucket = this.getOrCreateBucket(event);
|
|
56
|
-
if (bucket.indexByHandler.has(handler))
|
|
57
|
-
return
|
|
54
|
+
if (bucket.indexByHandler.has(handler)) {
|
|
55
|
+
return () => {
|
|
56
|
+
this.off(event, handler);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
58
59
|
const index = bucket.handlers.length;
|
|
59
60
|
bucket.handlers.push(handler);
|
|
60
|
-
bucket.indexByHandler.set(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
bucket.indexByHandler.set(handler, index);
|
|
62
|
+
return () => {
|
|
63
|
+
this.off(event, handler);
|
|
64
|
+
};
|
|
64
65
|
}
|
|
65
66
|
emit(event, payload) {
|
|
66
67
|
const bucket = this.buckets[event];
|
|
@@ -75,10 +76,11 @@ var OIMEventEmitter = class {
|
|
|
75
76
|
}
|
|
76
77
|
bucket.isEmitting--;
|
|
77
78
|
if (bucket.isEmitting === 0 && bucket.tombstoneCount > 0) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
} else if (length === bucket.tombstoneCount) {
|
|
79
|
+
const currentLength = bucket.handlers.length;
|
|
80
|
+
if (bucket.tombstoneCount === currentLength) {
|
|
81
81
|
delete this.buckets[event];
|
|
82
|
+
} else if (bucket.tombstoneCount >= currentLength >> 1) {
|
|
83
|
+
this.compactBucket(bucket);
|
|
82
84
|
}
|
|
83
85
|
}
|
|
84
86
|
}
|
|
@@ -92,10 +94,10 @@ var OIMEventEmitter = class {
|
|
|
92
94
|
bucket.indexByHandler.delete(handler);
|
|
93
95
|
if (bucket.isEmitting === 0) {
|
|
94
96
|
const length = bucket.handlers.length;
|
|
95
|
-
if (bucket.tombstoneCount
|
|
96
|
-
this.compactBucket(bucket);
|
|
97
|
-
} else if (length === bucket.tombstoneCount) {
|
|
97
|
+
if (bucket.tombstoneCount === length) {
|
|
98
98
|
delete this.buckets[event];
|
|
99
|
+
} else if (bucket.tombstoneCount >= length >> 1) {
|
|
100
|
+
this.compactBucket(bucket);
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
}
|
|
@@ -457,34 +459,50 @@ var EOIMUpdateEventCoalescerEventType = /* @__PURE__ */ ((EOIMUpdateEventCoalesc
|
|
|
457
459
|
// src/core/OIMUpdateEventEmitter.ts
|
|
458
460
|
var OIMUpdateEventEmitter = class {
|
|
459
461
|
constructor(opts) {
|
|
462
|
+
this.keyHandlersBeforeFlush = /* @__PURE__ */ new Map();
|
|
460
463
|
this.keyHandlers = /* @__PURE__ */ new Map();
|
|
464
|
+
this.isDestroyed = false;
|
|
465
|
+
this.isDispatching = false;
|
|
466
|
+
this.isInPrePhase = false;
|
|
467
|
+
this.hasPendingDuringPrePhase = false;
|
|
468
|
+
this.isFlushEnqueued = false;
|
|
461
469
|
this.handleHasChanges = () => {
|
|
462
|
-
this.
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
} else {
|
|
478
|
-
for (const [key, handlers] of this.keyHandlers) {
|
|
479
|
-
if (updatedKeys.has(key)) {
|
|
480
|
-
for (const handler of handlers) {
|
|
481
|
-
handler();
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
}
|
|
470
|
+
if (this.isDispatching && this.isInPrePhase) {
|
|
471
|
+
this.hasPendingDuringPrePhase = true;
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
if (this.isFlushEnqueued) return;
|
|
475
|
+
this.isFlushEnqueued = true;
|
|
476
|
+
this.queue.enqueue(this.onFlush);
|
|
477
|
+
};
|
|
478
|
+
// Stable handler reference to avoid allocating a new closure on every HAS_CHANGES.
|
|
479
|
+
this.onFlush = () => {
|
|
480
|
+
this.isFlushEnqueued = false;
|
|
481
|
+
if (this.isDestroyed) {
|
|
486
482
|
this.coalescer.clearUpdatedKeys();
|
|
487
|
-
|
|
483
|
+
this.coalescer.clearFlushingUpdatedKeys();
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
if (this.keyHandlers.size === 0 && this.keyHandlersBeforeFlush.size === 0) {
|
|
487
|
+
this.coalescer.clearUpdatedKeys();
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const makeHandlerSnapshot = (handlers) => {
|
|
491
|
+
const snapshot = [];
|
|
492
|
+
handlers.forEach((h) => snapshot.push(h));
|
|
493
|
+
return snapshot;
|
|
494
|
+
};
|
|
495
|
+
try {
|
|
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
|
+
}
|
|
488
506
|
};
|
|
489
507
|
this.coalescer = opts.coalescer;
|
|
490
508
|
this.coalescer.emitter.on(
|
|
@@ -493,11 +511,90 @@ var OIMUpdateEventEmitter = class {
|
|
|
493
511
|
);
|
|
494
512
|
this.queue = opts.queue;
|
|
495
513
|
}
|
|
514
|
+
/**
|
|
515
|
+
* Helps to run computed values etc.
|
|
516
|
+
*/
|
|
517
|
+
runPrePhaseDrain(makeHandlerSnapshot) {
|
|
518
|
+
const allKeysForNormalPhase = /* @__PURE__ */ new Set();
|
|
519
|
+
let hasMorePreWork = true;
|
|
520
|
+
while (hasMorePreWork) {
|
|
521
|
+
this.coalescer.markUpdatedKeysAsFlushing();
|
|
522
|
+
const flushingKeys = this.coalescer.getFlushingUpdatedKeys();
|
|
523
|
+
flushingKeys.forEach((key) => allKeysForNormalPhase.add(key));
|
|
524
|
+
try {
|
|
525
|
+
if (this.keyHandlersBeforeFlush.size > 0) {
|
|
526
|
+
if (flushingKeys.size * 2 < this.keyHandlersBeforeFlush.size) {
|
|
527
|
+
flushingKeys.forEach((key) => {
|
|
528
|
+
if (this.isDestroyed) return;
|
|
529
|
+
const handlers = this.keyHandlersBeforeFlush.get(key);
|
|
530
|
+
if (!handlers || handlers.size === 0) return;
|
|
531
|
+
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
532
|
+
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
533
|
+
if (this.isDestroyed) return;
|
|
534
|
+
const handler = handlerSnapshot[i];
|
|
535
|
+
if (handlers.has(handler)) handler();
|
|
536
|
+
}
|
|
537
|
+
});
|
|
538
|
+
} else {
|
|
539
|
+
this.keyHandlersBeforeFlush.forEach((handlers, key) => {
|
|
540
|
+
if (this.isDestroyed) return;
|
|
541
|
+
if (!flushingKeys.has(key)) return;
|
|
542
|
+
if (!handlers || handlers.size === 0) return;
|
|
543
|
+
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
544
|
+
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
545
|
+
if (this.isDestroyed) return;
|
|
546
|
+
const handler = handlerSnapshot[i];
|
|
547
|
+
if (handlers.has(handler)) handler();
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
} finally {
|
|
553
|
+
this.coalescer.clearFlushingUpdatedKeys();
|
|
554
|
+
}
|
|
555
|
+
const nextHasMorePreWork = this.hasPendingDuringPrePhase || this.coalescer.getUpdatedKeys().size > 0;
|
|
556
|
+
this.hasPendingDuringPrePhase = false;
|
|
557
|
+
hasMorePreWork = nextHasMorePreWork;
|
|
558
|
+
}
|
|
559
|
+
return allKeysForNormalPhase;
|
|
560
|
+
}
|
|
561
|
+
runHandlersPhase(allKeysForNormalPhase, makeHandlerSnapshot) {
|
|
562
|
+
if (this.keyHandlers.size === 0 || allKeysForNormalPhase.size === 0)
|
|
563
|
+
return;
|
|
564
|
+
if (allKeysForNormalPhase.size * 2 < this.keyHandlers.size) {
|
|
565
|
+
allKeysForNormalPhase.forEach((key) => {
|
|
566
|
+
if (this.isDestroyed) return;
|
|
567
|
+
const handlers = this.keyHandlers.get(key);
|
|
568
|
+
if (!handlers || handlers.size === 0) return;
|
|
569
|
+
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
570
|
+
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
571
|
+
if (this.isDestroyed) return;
|
|
572
|
+
const handler = handlerSnapshot[i];
|
|
573
|
+
if (handlers.has(handler)) handler();
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
} else {
|
|
577
|
+
this.keyHandlers.forEach((handlers, key) => {
|
|
578
|
+
if (this.isDestroyed) return;
|
|
579
|
+
if (!allKeysForNormalPhase.has(key)) return;
|
|
580
|
+
if (!handlers || handlers.size === 0) return;
|
|
581
|
+
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
582
|
+
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
583
|
+
if (this.isDestroyed) return;
|
|
584
|
+
const handler = handlerSnapshot[i];
|
|
585
|
+
if (handlers.has(handler)) handler();
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
}
|
|
496
590
|
destroy() {
|
|
591
|
+
if (this.isDestroyed) return;
|
|
592
|
+
this.isDestroyed = true;
|
|
497
593
|
this.coalescer.emitter.off(
|
|
498
594
|
0 /* HAS_CHANGES */,
|
|
499
595
|
this.handleHasChanges
|
|
500
596
|
);
|
|
597
|
+
this.keyHandlersBeforeFlush.clear();
|
|
501
598
|
this.keyHandlers.clear();
|
|
502
599
|
}
|
|
503
600
|
/**
|
|
@@ -505,9 +602,9 @@ var OIMUpdateEventEmitter = class {
|
|
|
505
602
|
*/
|
|
506
603
|
getMetrics() {
|
|
507
604
|
let totalHandlers = 0;
|
|
508
|
-
|
|
605
|
+
this.keyHandlers.forEach((handlers) => {
|
|
509
606
|
totalHandlers += handlers.size;
|
|
510
|
-
}
|
|
607
|
+
});
|
|
511
608
|
return {
|
|
512
609
|
totalKeys: this.keyHandlers.size,
|
|
513
610
|
totalHandlers,
|
|
@@ -519,13 +616,32 @@ var OIMUpdateEventEmitter = class {
|
|
|
519
616
|
* Check if there are any active subscriptions
|
|
520
617
|
*/
|
|
521
618
|
hasSubscriptions() {
|
|
522
|
-
return this.keyHandlers.size > 0;
|
|
619
|
+
return this.keyHandlers.size > 0 || this.keyHandlersBeforeFlush.size > 0;
|
|
523
620
|
}
|
|
524
621
|
/**
|
|
525
622
|
* Get the number of handlers for a specific key
|
|
526
623
|
*/
|
|
527
624
|
getHandlerCount(key) {
|
|
528
|
-
return this.keyHandlers.get(key)?.size ?? 0;
|
|
625
|
+
return (this.keyHandlers.get(key)?.size ?? 0) + (this.keyHandlersBeforeFlush.get(key)?.size ?? 0);
|
|
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
|
+
}
|
|
529
645
|
}
|
|
530
646
|
subscribeOnKey(key, handler) {
|
|
531
647
|
let handlers = this.keyHandlers.get(key);
|
|
@@ -565,6 +681,30 @@ var OIMUpdateEventEmitter = class {
|
|
|
565
681
|
}
|
|
566
682
|
};
|
|
567
683
|
}
|
|
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
|
+
}
|
|
568
708
|
unsubscribeFromKeys(keys, handler) {
|
|
569
709
|
for (const key of keys) {
|
|
570
710
|
this.unsubscribeFromKey(key, handler);
|
|
@@ -659,15 +799,19 @@ var OIMDBSettings = class {
|
|
|
659
799
|
* This constant is exported so users can create their own indexes and pass them to coalescers.
|
|
660
800
|
*/
|
|
661
801
|
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
802
|
+
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY = "__flushingKeys__";
|
|
662
803
|
|
|
663
804
|
// src/core/OIMUpdateEventCoalescer.ts
|
|
664
805
|
var OIMUpdateEventCoalescer = class {
|
|
665
|
-
constructor(index) {
|
|
806
|
+
constructor(index, flushingIndex) {
|
|
666
807
|
this.emitter = new OIMEventEmitter();
|
|
667
808
|
this.hasEmittedChanges = false;
|
|
668
809
|
this.updatedKeysIndex = index ?? new OIMIndexManualSetBased({
|
|
669
810
|
store: new OIMIndexStoreMapDrivenSetBased()
|
|
670
811
|
});
|
|
812
|
+
this.flushingUpdatedKeysIndex = flushingIndex ?? new OIMIndexManualSetBased({
|
|
813
|
+
store: new OIMIndexStoreMapDrivenSetBased()
|
|
814
|
+
});
|
|
671
815
|
if (!this.updatedKeysIndex.hasKey(OIMDBSettings.UPDATED_KEYS_INDEX_KEY)) {
|
|
672
816
|
this.updatedKeysIndex.setPks(
|
|
673
817
|
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
@@ -683,6 +827,18 @@ var OIMUpdateEventCoalescer = class {
|
|
|
683
827
|
OIMDBSettings.UPDATED_KEYS_INDEX_KEY
|
|
684
828
|
);
|
|
685
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
|
+
}
|
|
686
842
|
/**
|
|
687
843
|
* Clear all updated keys and reset the changed state
|
|
688
844
|
*/
|
|
@@ -698,6 +854,12 @@ var OIMUpdateEventCoalescer = class {
|
|
|
698
854
|
void 0
|
|
699
855
|
);
|
|
700
856
|
}
|
|
857
|
+
clearFlushingUpdatedKeys() {
|
|
858
|
+
this.flushingUpdatedKeysIndex.setPks(
|
|
859
|
+
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY,
|
|
860
|
+
[]
|
|
861
|
+
);
|
|
862
|
+
}
|
|
701
863
|
/**
|
|
702
864
|
* Add keys to the updated set and emit HAS_CHANGES event if needed
|
|
703
865
|
*/
|
|
@@ -773,6 +935,8 @@ var OIMReactiveIndexSetBased = class {
|
|
|
773
935
|
return this.index.getMetrics();
|
|
774
936
|
}
|
|
775
937
|
destroy() {
|
|
938
|
+
this.updateEventEmitter.destroy();
|
|
939
|
+
this.coalescer.destroy();
|
|
776
940
|
this.index.destroy();
|
|
777
941
|
}
|
|
778
942
|
};
|
|
@@ -814,10 +978,16 @@ var OIMReactiveIndexArrayBased = class {
|
|
|
814
978
|
return this.index.getMetrics();
|
|
815
979
|
}
|
|
816
980
|
destroy() {
|
|
981
|
+
this.updateEventEmitter.destroy();
|
|
982
|
+
this.coalescer.destroy();
|
|
817
983
|
this.index.destroy();
|
|
818
984
|
}
|
|
819
985
|
};
|
|
820
986
|
|
|
987
|
+
// src/abstract/OIMObjectStore.ts
|
|
988
|
+
var OIMObjectStore = class {
|
|
989
|
+
};
|
|
990
|
+
|
|
821
991
|
// src/core/OIMPkSelectorFactory.ts
|
|
822
992
|
var OIMPkSelectorFactory = class {
|
|
823
993
|
createIdSelector() {
|
|
@@ -875,6 +1045,9 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
875
1045
|
getAllPks() {
|
|
876
1046
|
return Array.from(this.entities.keys());
|
|
877
1047
|
}
|
|
1048
|
+
destroy() {
|
|
1049
|
+
this.clear();
|
|
1050
|
+
}
|
|
878
1051
|
};
|
|
879
1052
|
|
|
880
1053
|
// src/core/OIMEntityUpdaterFactory.ts
|
|
@@ -972,6 +1145,10 @@ var OIMCollection = class {
|
|
|
972
1145
|
this.store.setOneByPk(pk, entity);
|
|
973
1146
|
}
|
|
974
1147
|
}
|
|
1148
|
+
destroy() {
|
|
1149
|
+
this.store.destroy();
|
|
1150
|
+
this.emitter.offAll();
|
|
1151
|
+
}
|
|
975
1152
|
};
|
|
976
1153
|
|
|
977
1154
|
// src/core/OIMUpdateEventCoalescerCollection.ts
|
|
@@ -1012,6 +1189,143 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1012
1189
|
queue
|
|
1013
1190
|
});
|
|
1014
1191
|
}
|
|
1192
|
+
destroy() {
|
|
1193
|
+
this.updateEventEmitter.destroy();
|
|
1194
|
+
this.coalescer.destroy();
|
|
1195
|
+
super.destroy();
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
// src/core/OIMObjectStoreRecordDriven.ts
|
|
1200
|
+
var OIMObjectStoreRecordDriven = class extends OIMObjectStore {
|
|
1201
|
+
constructor(initial) {
|
|
1202
|
+
super();
|
|
1203
|
+
this.properties = Object.assign(/* @__PURE__ */ Object.create(null), initial ?? {});
|
|
1204
|
+
}
|
|
1205
|
+
setProperty(key, value) {
|
|
1206
|
+
this.properties[key] = value;
|
|
1207
|
+
}
|
|
1208
|
+
merge(draft) {
|
|
1209
|
+
Object.assign(this.properties, draft);
|
|
1210
|
+
}
|
|
1211
|
+
delete(key) {
|
|
1212
|
+
delete this.properties[key];
|
|
1213
|
+
}
|
|
1214
|
+
get(key) {
|
|
1215
|
+
return this.properties[key];
|
|
1216
|
+
}
|
|
1217
|
+
getAll() {
|
|
1218
|
+
return { ...this.properties };
|
|
1219
|
+
}
|
|
1220
|
+
clear() {
|
|
1221
|
+
this.properties = /* @__PURE__ */ Object.create(null);
|
|
1222
|
+
}
|
|
1223
|
+
count() {
|
|
1224
|
+
return Object.keys(this.properties).length;
|
|
1225
|
+
}
|
|
1226
|
+
keys() {
|
|
1227
|
+
return Object.keys(this.properties);
|
|
1228
|
+
}
|
|
1229
|
+
values() {
|
|
1230
|
+
return Object.values(this.properties);
|
|
1231
|
+
}
|
|
1232
|
+
entries() {
|
|
1233
|
+
return Object.entries(this.properties);
|
|
1234
|
+
}
|
|
1235
|
+
destroy() {
|
|
1236
|
+
this.clear();
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
|
|
1240
|
+
// src/enum/EOIMObjectEventType.ts
|
|
1241
|
+
var EOIMObjectEventType = /* @__PURE__ */ ((EOIMObjectEventType2) => {
|
|
1242
|
+
EOIMObjectEventType2[EOIMObjectEventType2["UPDATE"] = 0] = "UPDATE";
|
|
1243
|
+
return EOIMObjectEventType2;
|
|
1244
|
+
})(EOIMObjectEventType || {});
|
|
1245
|
+
|
|
1246
|
+
// src/core/OIMObject.ts
|
|
1247
|
+
var OIMObject = class {
|
|
1248
|
+
constructor(opts) {
|
|
1249
|
+
this.emitter = new OIMEventEmitter();
|
|
1250
|
+
this.store = opts?.store ?? new OIMObjectStoreRecordDriven();
|
|
1251
|
+
}
|
|
1252
|
+
setProperty(key, value) {
|
|
1253
|
+
this.store.setProperty(key, value);
|
|
1254
|
+
this.emitter.emit(0 /* UPDATE */, { keys: [key] });
|
|
1255
|
+
}
|
|
1256
|
+
merge(draft) {
|
|
1257
|
+
this.store.merge(draft);
|
|
1258
|
+
this.emitter.emit(0 /* UPDATE */, {
|
|
1259
|
+
keys: Object.keys(draft)
|
|
1260
|
+
});
|
|
1261
|
+
}
|
|
1262
|
+
delete(key) {
|
|
1263
|
+
this.store.delete(key);
|
|
1264
|
+
this.emitter.emit(0 /* UPDATE */, { keys: [key] });
|
|
1265
|
+
}
|
|
1266
|
+
get(key) {
|
|
1267
|
+
return this.store.get(key);
|
|
1268
|
+
}
|
|
1269
|
+
getAll() {
|
|
1270
|
+
return this.store.getAll();
|
|
1271
|
+
}
|
|
1272
|
+
clear() {
|
|
1273
|
+
this.store.clear();
|
|
1274
|
+
this.emitter.emit(0 /* UPDATE */, { keys: [] });
|
|
1275
|
+
}
|
|
1276
|
+
count() {
|
|
1277
|
+
return this.store.count();
|
|
1278
|
+
}
|
|
1279
|
+
keys() {
|
|
1280
|
+
return this.store.keys();
|
|
1281
|
+
}
|
|
1282
|
+
values() {
|
|
1283
|
+
return this.store.values();
|
|
1284
|
+
}
|
|
1285
|
+
entries() {
|
|
1286
|
+
return this.store.entries();
|
|
1287
|
+
}
|
|
1288
|
+
destroy() {
|
|
1289
|
+
this.store.destroy();
|
|
1290
|
+
this.emitter.offAll();
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
|
|
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
|
+
// src/core/OIMReactiveObject.ts
|
|
1315
|
+
var OIMReactiveObject = class extends OIMObject {
|
|
1316
|
+
constructor(queue, opts) {
|
|
1317
|
+
super(opts);
|
|
1318
|
+
this.coalescer = new OIMUpdateEventCoalescerObject(this.emitter);
|
|
1319
|
+
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
1320
|
+
coalescer: this.coalescer,
|
|
1321
|
+
queue
|
|
1322
|
+
});
|
|
1323
|
+
}
|
|
1324
|
+
destroy() {
|
|
1325
|
+
this.updateEventEmitter.destroy();
|
|
1326
|
+
this.coalescer.destroy();
|
|
1327
|
+
super.destroy();
|
|
1328
|
+
}
|
|
1015
1329
|
};
|
|
1016
1330
|
|
|
1017
1331
|
// src/core/OIMReactiveIndexManualSetBased.ts
|
|
@@ -1142,6 +1456,53 @@ var OIMRICollection = class extends OIMReactiveCollection {
|
|
|
1142
1456
|
}
|
|
1143
1457
|
};
|
|
1144
1458
|
|
|
1459
|
+
// src/core/OIMObjectStoreMapDriven.ts
|
|
1460
|
+
var OIMObjectStoreMapDriven = class extends OIMObjectStore {
|
|
1461
|
+
constructor() {
|
|
1462
|
+
super(...arguments);
|
|
1463
|
+
this.properties = /* @__PURE__ */ new Map();
|
|
1464
|
+
}
|
|
1465
|
+
setProperty(key, value) {
|
|
1466
|
+
this.properties.set(key, value);
|
|
1467
|
+
}
|
|
1468
|
+
merge(draft) {
|
|
1469
|
+
for (const key in draft) {
|
|
1470
|
+
if (!Object.prototype.hasOwnProperty.call(draft, key)) continue;
|
|
1471
|
+
this.properties.set(
|
|
1472
|
+
key,
|
|
1473
|
+
draft[key]
|
|
1474
|
+
);
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
delete(key) {
|
|
1478
|
+
this.properties.delete(key);
|
|
1479
|
+
}
|
|
1480
|
+
get(key) {
|
|
1481
|
+
return this.properties.get(key);
|
|
1482
|
+
}
|
|
1483
|
+
getAll() {
|
|
1484
|
+
return Object.fromEntries(this.properties.entries());
|
|
1485
|
+
}
|
|
1486
|
+
clear() {
|
|
1487
|
+
this.properties.clear();
|
|
1488
|
+
}
|
|
1489
|
+
count() {
|
|
1490
|
+
return this.properties.size;
|
|
1491
|
+
}
|
|
1492
|
+
keys() {
|
|
1493
|
+
return Array.from(this.properties.keys());
|
|
1494
|
+
}
|
|
1495
|
+
values() {
|
|
1496
|
+
return Array.from(this.properties.values());
|
|
1497
|
+
}
|
|
1498
|
+
entries() {
|
|
1499
|
+
return Array.from(this.properties.entries());
|
|
1500
|
+
}
|
|
1501
|
+
destroy() {
|
|
1502
|
+
this.properties.clear();
|
|
1503
|
+
}
|
|
1504
|
+
};
|
|
1505
|
+
|
|
1145
1506
|
// src/core/OIMComparatorFactory.ts
|
|
1146
1507
|
var OIMComparatorFactory = class {
|
|
1147
1508
|
createShallowComparator() {
|
|
@@ -1172,6 +1533,8 @@ var OIMEventQueue = class {
|
|
|
1172
1533
|
constructor(options = {}) {
|
|
1173
1534
|
this.emitter = new OIMEventEmitter();
|
|
1174
1535
|
this.queue = [];
|
|
1536
|
+
this.isFlushing = false;
|
|
1537
|
+
this.pendingSchedule = false;
|
|
1175
1538
|
this.scheduler = options.scheduler;
|
|
1176
1539
|
if (this.scheduler) {
|
|
1177
1540
|
this.flushBound = () => this.flush();
|
|
@@ -1187,7 +1550,12 @@ var OIMEventQueue = class {
|
|
|
1187
1550
|
*/
|
|
1188
1551
|
enqueue(fn) {
|
|
1189
1552
|
this.queue.push(fn);
|
|
1190
|
-
if (this.scheduler
|
|
1553
|
+
if (!this.scheduler) return;
|
|
1554
|
+
if (this.isFlushing) {
|
|
1555
|
+
this.pendingSchedule = true;
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
if (this.queue.length === 1) {
|
|
1191
1559
|
this.scheduler.schedule();
|
|
1192
1560
|
}
|
|
1193
1561
|
}
|
|
@@ -1197,6 +1565,8 @@ var OIMEventQueue = class {
|
|
|
1197
1565
|
*/
|
|
1198
1566
|
flush() {
|
|
1199
1567
|
if (this.queue.length === 0) return;
|
|
1568
|
+
this.scheduler?.cancel();
|
|
1569
|
+
this.isFlushing = true;
|
|
1200
1570
|
this.emitter.emit(1 /* BEFORE_FLUSH */, void 0);
|
|
1201
1571
|
const currentQueue = this.queue.slice();
|
|
1202
1572
|
this.queue.length = 0;
|
|
@@ -1204,6 +1574,13 @@ var OIMEventQueue = class {
|
|
|
1204
1574
|
currentQueue[i]();
|
|
1205
1575
|
}
|
|
1206
1576
|
this.emitter.emit(0 /* AFTER_FLUSH */, void 0);
|
|
1577
|
+
this.isFlushing = false;
|
|
1578
|
+
if (this.scheduler && this.pendingSchedule && this.queue.length > 0) {
|
|
1579
|
+
this.pendingSchedule = false;
|
|
1580
|
+
this.scheduler.schedule();
|
|
1581
|
+
} else {
|
|
1582
|
+
this.pendingSchedule = false;
|
|
1583
|
+
}
|
|
1207
1584
|
}
|
|
1208
1585
|
/**
|
|
1209
1586
|
* Get the current number of queued functions.
|
|
@@ -1271,7 +1648,7 @@ var OIMIndexComparatorFactory = class {
|
|
|
1271
1648
|
if (existingSet.size !== newSet.size || existingSet.size !== existingPks.length) {
|
|
1272
1649
|
return false;
|
|
1273
1650
|
}
|
|
1274
|
-
for (const pk of existingSet) {
|
|
1651
|
+
for (const pk of Array.from(existingSet)) {
|
|
1275
1652
|
if (!newSet.has(pk)) {
|
|
1276
1653
|
return false;
|
|
1277
1654
|
}
|
|
@@ -1337,6 +1714,270 @@ var OIMMap2Keys = class {
|
|
|
1337
1714
|
}
|
|
1338
1715
|
};
|
|
1339
1716
|
|
|
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
|
+
// src/modules/wrapper/collection/OIMCollectionChangedFieldsWrapper.ts
|
|
1731
|
+
var OIMCollectionChangedFieldsWrapper = class {
|
|
1732
|
+
constructor(queue, collection, opts) {
|
|
1733
|
+
this.changedFieldsByPk = /* @__PURE__ */ new Map();
|
|
1734
|
+
this.changedPksByField = /* @__PURE__ */ new Map();
|
|
1735
|
+
this.collection = collection;
|
|
1736
|
+
this.selectPk = opts?.selectPk ?? (() => {
|
|
1737
|
+
throw new Error(
|
|
1738
|
+
`[OIMCollectionChangedFieldsWrapper]: selectPk was not provided. Use upsertOneByPk(...) or pass opts.selectPk.`
|
|
1739
|
+
);
|
|
1740
|
+
});
|
|
1741
|
+
this.changedPksCoalescer = new OIMUpdateEventCoalescerManual();
|
|
1742
|
+
this.changedPksEventEmitter = new OIMUpdateEventEmitter({
|
|
1743
|
+
coalescer: this.changedPksCoalescer,
|
|
1744
|
+
queue
|
|
1745
|
+
});
|
|
1746
|
+
this.changedFieldsCoalescer = new OIMUpdateEventCoalescerManual();
|
|
1747
|
+
this.changedFieldsEventEmitter = new OIMUpdateEventEmitter({
|
|
1748
|
+
coalescer: this.changedFieldsCoalescer,
|
|
1749
|
+
queue
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
upsertOneByPk(pk, patch) {
|
|
1753
|
+
this.trackPatch(pk, patch);
|
|
1754
|
+
this.collection.upsertOneByPk(pk, patch);
|
|
1755
|
+
}
|
|
1756
|
+
upsertOne(entity) {
|
|
1757
|
+
const pk = this.selectPk(entity);
|
|
1758
|
+
this.trackPatch(pk, entity);
|
|
1759
|
+
this.collection.upsertOne(entity);
|
|
1760
|
+
}
|
|
1761
|
+
upsertMany(entities) {
|
|
1762
|
+
for (const entity of entities) {
|
|
1763
|
+
const pk = this.selectPk(entity);
|
|
1764
|
+
this.trackPatch(pk, entity);
|
|
1765
|
+
}
|
|
1766
|
+
this.collection.upsertMany(entities);
|
|
1767
|
+
}
|
|
1768
|
+
getChangedFieldsByPk(pk) {
|
|
1769
|
+
return this.changedFieldsByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
1770
|
+
}
|
|
1771
|
+
consumeChangedFieldsByPk(pk) {
|
|
1772
|
+
const existing = this.changedFieldsByPk.get(pk);
|
|
1773
|
+
if (!existing) return /* @__PURE__ */ new Set();
|
|
1774
|
+
this.changedFieldsByPk.delete(pk);
|
|
1775
|
+
return existing;
|
|
1776
|
+
}
|
|
1777
|
+
getChangedPksByField(field) {
|
|
1778
|
+
return this.changedPksByField.get(field) ?? /* @__PURE__ */ new Set();
|
|
1779
|
+
}
|
|
1780
|
+
consumeChangedPksByField(field) {
|
|
1781
|
+
const existing = this.changedPksByField.get(field);
|
|
1782
|
+
if (!existing) return /* @__PURE__ */ new Set();
|
|
1783
|
+
this.changedPksByField.delete(field);
|
|
1784
|
+
return existing;
|
|
1785
|
+
}
|
|
1786
|
+
clear() {
|
|
1787
|
+
this.changedFieldsByPk.clear();
|
|
1788
|
+
this.changedPksByField.clear();
|
|
1789
|
+
}
|
|
1790
|
+
destroy() {
|
|
1791
|
+
this.changedPksEventEmitter.destroy();
|
|
1792
|
+
this.changedFieldsEventEmitter.destroy();
|
|
1793
|
+
this.changedPksCoalescer.destroy();
|
|
1794
|
+
this.changedFieldsCoalescer.destroy();
|
|
1795
|
+
this.clear();
|
|
1796
|
+
}
|
|
1797
|
+
trackPatch(pk, patch) {
|
|
1798
|
+
if (pk === void 0 || pk === null || pk === "") {
|
|
1799
|
+
throw new Error(
|
|
1800
|
+
`[OIMCollectionChangedFieldsWrapper]: PK is required to track changes.`
|
|
1801
|
+
);
|
|
1802
|
+
}
|
|
1803
|
+
const keys = Object.keys(patch);
|
|
1804
|
+
if (keys.length === 0) return;
|
|
1805
|
+
let pkFields = this.changedFieldsByPk.get(pk);
|
|
1806
|
+
if (!pkFields) {
|
|
1807
|
+
pkFields = /* @__PURE__ */ new Set();
|
|
1808
|
+
this.changedFieldsByPk.set(pk, pkFields);
|
|
1809
|
+
}
|
|
1810
|
+
for (const key of keys) {
|
|
1811
|
+
pkFields.add(key);
|
|
1812
|
+
let fieldPks = this.changedPksByField.get(key);
|
|
1813
|
+
if (!fieldPks) {
|
|
1814
|
+
fieldPks = /* @__PURE__ */ new Set();
|
|
1815
|
+
this.changedPksByField.set(key, fieldPks);
|
|
1816
|
+
}
|
|
1817
|
+
fieldPks.add(pk);
|
|
1818
|
+
}
|
|
1819
|
+
this.changedPksCoalescer.markUpdatedKeys([pk]);
|
|
1820
|
+
this.changedFieldsCoalescer.markUpdatedKeys(keys);
|
|
1821
|
+
}
|
|
1822
|
+
};
|
|
1823
|
+
|
|
1824
|
+
// src/modules/wrapper/index/OIMIndexManualOrderedArrayBased.ts
|
|
1825
|
+
var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
1826
|
+
clear(key) {
|
|
1827
|
+
if (key === void 0) {
|
|
1828
|
+
const keys = this.getKeys();
|
|
1829
|
+
if (keys.length > 0) {
|
|
1830
|
+
this.store.clear();
|
|
1831
|
+
this.emitUpdate(Array.from(keys));
|
|
1832
|
+
}
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
if (this.store.getOneByKey(key) !== void 0) {
|
|
1836
|
+
this.store.removeOneByKey(key);
|
|
1837
|
+
this.emitUpdate([key]);
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
1840
|
+
push(key, itemKey) {
|
|
1841
|
+
const list = this.getOrCreateList(key);
|
|
1842
|
+
const index = list.length;
|
|
1843
|
+
list.push(itemKey);
|
|
1844
|
+
this.emitUpdate([key]);
|
|
1845
|
+
return index;
|
|
1846
|
+
}
|
|
1847
|
+
insertAt(key, index, itemKey) {
|
|
1848
|
+
const list = this.getOrCreateList(key);
|
|
1849
|
+
const safeIndex = Math.max(0, Math.min(index, list.length));
|
|
1850
|
+
list.splice(safeIndex, 0, itemKey);
|
|
1851
|
+
this.emitUpdate([key]);
|
|
1852
|
+
}
|
|
1853
|
+
removeAt(key, index) {
|
|
1854
|
+
const list = this.store.getOneByKey(key);
|
|
1855
|
+
if (!list) return void 0;
|
|
1856
|
+
if (index < 0 || index >= list.length) return void 0;
|
|
1857
|
+
const [removed] = list.splice(index, 1);
|
|
1858
|
+
if (list.length === 0) {
|
|
1859
|
+
this.store.removeOneByKey(key);
|
|
1860
|
+
}
|
|
1861
|
+
this.emitUpdate([key]);
|
|
1862
|
+
return removed;
|
|
1863
|
+
}
|
|
1864
|
+
move(key, fromIndex, toIndex) {
|
|
1865
|
+
const list = this.store.getOneByKey(key);
|
|
1866
|
+
if (!list) return void 0;
|
|
1867
|
+
if (fromIndex < 0 || fromIndex >= list.length) return void 0;
|
|
1868
|
+
if (toIndex < 0 || toIndex >= list.length) return void 0;
|
|
1869
|
+
if (fromIndex === toIndex) return list[fromIndex];
|
|
1870
|
+
const [itemKey] = list.splice(fromIndex, 1);
|
|
1871
|
+
if (itemKey === void 0) return void 0;
|
|
1872
|
+
list.splice(toIndex, 0, itemKey);
|
|
1873
|
+
this.emitUpdate([key]);
|
|
1874
|
+
return itemKey;
|
|
1875
|
+
}
|
|
1876
|
+
reset(key, itemKeys) {
|
|
1877
|
+
if (itemKeys.length === 0) {
|
|
1878
|
+
if (this.store.getOneByKey(key) !== void 0) {
|
|
1879
|
+
this.store.removeOneByKey(key);
|
|
1880
|
+
this.emitUpdate([key]);
|
|
1881
|
+
}
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
this.store.setOneByKey(key, Array.from(itemKeys));
|
|
1885
|
+
this.emitUpdate([key]);
|
|
1886
|
+
}
|
|
1887
|
+
getOrCreateList(key) {
|
|
1888
|
+
let list = this.store.getOneByKey(key);
|
|
1889
|
+
if (!list) {
|
|
1890
|
+
list = [];
|
|
1891
|
+
this.store.setOneByKey(key, list);
|
|
1892
|
+
}
|
|
1893
|
+
return list;
|
|
1894
|
+
}
|
|
1895
|
+
};
|
|
1896
|
+
|
|
1897
|
+
// src/modules/wrapper/index/OIMOrderedListIndexCommandStreamWrapper.ts
|
|
1898
|
+
var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
1899
|
+
constructor(queue, index) {
|
|
1900
|
+
this.commandsByKey = /* @__PURE__ */ new Map();
|
|
1901
|
+
this.coalescer = new OIMUpdateEventCoalescerManual();
|
|
1902
|
+
this.commandsEventEmitter = new OIMUpdateEventEmitter({
|
|
1903
|
+
coalescer: this.coalescer,
|
|
1904
|
+
queue
|
|
1905
|
+
});
|
|
1906
|
+
this.index = index ?? new OIMIndexManualOrderedArrayBased();
|
|
1907
|
+
}
|
|
1908
|
+
getPksByKey(key) {
|
|
1909
|
+
return this.index.getPksByKey(key);
|
|
1910
|
+
}
|
|
1911
|
+
hasKey(key) {
|
|
1912
|
+
return this.index.hasKey(key);
|
|
1913
|
+
}
|
|
1914
|
+
getKeys() {
|
|
1915
|
+
return this.index.getKeys();
|
|
1916
|
+
}
|
|
1917
|
+
push(key, itemKey) {
|
|
1918
|
+
const index = this.index.push(key, itemKey);
|
|
1919
|
+
this.appendCommand(key, { type: "add", key: itemKey, index });
|
|
1920
|
+
}
|
|
1921
|
+
removeAt(key, index) {
|
|
1922
|
+
const itemKey = this.index.removeAt(key, index);
|
|
1923
|
+
if (itemKey === void 0) return;
|
|
1924
|
+
this.appendCommand(key, { type: "remove", key: itemKey, index });
|
|
1925
|
+
}
|
|
1926
|
+
move(key, fromIndex, toIndex) {
|
|
1927
|
+
const itemKey = this.index.move(key, fromIndex, toIndex);
|
|
1928
|
+
if (itemKey === void 0) return;
|
|
1929
|
+
this.appendCommand(key, {
|
|
1930
|
+
type: "move",
|
|
1931
|
+
key: itemKey,
|
|
1932
|
+
fromIndex,
|
|
1933
|
+
toIndex
|
|
1934
|
+
});
|
|
1935
|
+
}
|
|
1936
|
+
reset(key, keys) {
|
|
1937
|
+
this.index.reset(key, keys);
|
|
1938
|
+
this.appendCommand(key, { type: "reset", keys });
|
|
1939
|
+
}
|
|
1940
|
+
/**
|
|
1941
|
+
* Read-only peek at buffered commands without clearing them.
|
|
1942
|
+
*/
|
|
1943
|
+
getBufferedCommands(key) {
|
|
1944
|
+
return this.commandsByKey.get(key) ?? [];
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Drain buffered commands for a key, preserving order.
|
|
1948
|
+
* Intended usage: call inside a `commandsEventEmitter.subscribeOnKey(key, ...)` handler.
|
|
1949
|
+
*/
|
|
1950
|
+
consumeCommands(key) {
|
|
1951
|
+
const cmds = this.commandsByKey.get(key);
|
|
1952
|
+
if (!cmds || cmds.length === 0) return [];
|
|
1953
|
+
this.commandsByKey.delete(key);
|
|
1954
|
+
return cmds;
|
|
1955
|
+
}
|
|
1956
|
+
clear(key) {
|
|
1957
|
+
if (key === void 0) {
|
|
1958
|
+
this.index.destroy();
|
|
1959
|
+
this.commandsByKey.clear();
|
|
1960
|
+
return;
|
|
1961
|
+
}
|
|
1962
|
+
this.index.clear(key);
|
|
1963
|
+
this.commandsByKey.delete(key);
|
|
1964
|
+
}
|
|
1965
|
+
destroy() {
|
|
1966
|
+
this.commandsEventEmitter.destroy();
|
|
1967
|
+
this.coalescer.destroy();
|
|
1968
|
+
this.clear();
|
|
1969
|
+
}
|
|
1970
|
+
appendCommand(key, cmd) {
|
|
1971
|
+
let cmds = this.commandsByKey.get(key);
|
|
1972
|
+
if (!cmds) {
|
|
1973
|
+
cmds = [];
|
|
1974
|
+
this.commandsByKey.set(key, cmds);
|
|
1975
|
+
}
|
|
1976
|
+
cmds.push(cmd);
|
|
1977
|
+
this.coalescer.markUpdatedKeys([key]);
|
|
1978
|
+
}
|
|
1979
|
+
};
|
|
1980
|
+
|
|
1340
1981
|
// src/core/event-queue-scheduler/OIMEventQueueSchedulerAnimationFrame.ts
|
|
1341
1982
|
var OIMEventQueueSchedulerAnimationFrame = class extends OIMEventQueueScheduler {
|
|
1342
1983
|
constructor() {
|
|
@@ -1505,17 +2146,310 @@ var OIMEventQueueSchedulerFactory = class {
|
|
|
1505
2146
|
return new OIMEventQueueSchedulerImmediate();
|
|
1506
2147
|
}
|
|
1507
2148
|
};
|
|
2149
|
+
|
|
2150
|
+
// src/modules/effect/core/OIMEffect.ts
|
|
2151
|
+
var OIMEffect = class {
|
|
2152
|
+
constructor(queue, opts) {
|
|
2153
|
+
this.unsubscribers = [];
|
|
2154
|
+
this.isDestroyed = false;
|
|
2155
|
+
this.isInFlush = false;
|
|
2156
|
+
this.hasRunInThisFlush = false;
|
|
2157
|
+
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
|
+
this.runTask = () => {
|
|
2167
|
+
this.isScheduled = false;
|
|
2168
|
+
if (this.isDestroyed) return;
|
|
2169
|
+
this.runOnce();
|
|
2170
|
+
};
|
|
2171
|
+
this.invalidate = () => {
|
|
2172
|
+
if (this.isDestroyed) return;
|
|
2173
|
+
this.onInvalidate?.();
|
|
2174
|
+
if (this.isInFlush) {
|
|
2175
|
+
if (this.hasRunInThisFlush) return;
|
|
2176
|
+
this.hasRunInThisFlush = true;
|
|
2177
|
+
this.runOnce();
|
|
2178
|
+
return;
|
|
2179
|
+
}
|
|
2180
|
+
if (this.isScheduled) return;
|
|
2181
|
+
this.isScheduled = true;
|
|
2182
|
+
this.queue.enqueue(this.runTask);
|
|
2183
|
+
};
|
|
2184
|
+
this.queue = queue;
|
|
2185
|
+
this.phase = opts.phase;
|
|
2186
|
+
this.onInvalidate = opts.onInvalidate;
|
|
2187
|
+
this.run = opts.run;
|
|
2188
|
+
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
|
+
for (const dep of this.deps) {
|
|
2198
|
+
this.unsubscribers.push(dep.subscribe(this.phase, this.invalidate));
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2201
|
+
destroy() {
|
|
2202
|
+
if (this.isDestroyed) return;
|
|
2203
|
+
this.isDestroyed = true;
|
|
2204
|
+
for (const unsubscribe of this.unsubscribers) unsubscribe();
|
|
2205
|
+
this.unsubscribers = [];
|
|
2206
|
+
this.queue.emitter.off(
|
|
2207
|
+
1 /* BEFORE_FLUSH */,
|
|
2208
|
+
this.handleQueueBeforeFlush
|
|
2209
|
+
);
|
|
2210
|
+
this.queue.emitter.off(
|
|
2211
|
+
0 /* AFTER_FLUSH */,
|
|
2212
|
+
this.handleQueueAfterFlush
|
|
2213
|
+
);
|
|
2214
|
+
}
|
|
2215
|
+
runOnce() {
|
|
2216
|
+
if (this.isDestroyed) return;
|
|
2217
|
+
this.run();
|
|
2218
|
+
}
|
|
2219
|
+
};
|
|
2220
|
+
|
|
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
|
+
// src/modules/computed/enum/EOIMComputedEventType.ts
|
|
2229
|
+
var EOIMComputedEventType = /* @__PURE__ */ ((EOIMComputedEventType2) => {
|
|
2230
|
+
EOIMComputedEventType2["UPDATE"] = "update";
|
|
2231
|
+
return EOIMComputedEventType2;
|
|
2232
|
+
})(EOIMComputedEventType || {});
|
|
2233
|
+
|
|
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
|
+
// src/modules/computed/core/OIMComputed.ts
|
|
2258
|
+
var OIMComputed = class {
|
|
2259
|
+
constructor(queue, opts) {
|
|
2260
|
+
this.emitter = new OIMEventEmitter();
|
|
2261
|
+
this.hasValue = false;
|
|
2262
|
+
this.isDirty = true;
|
|
2263
|
+
this.isInFlush = false;
|
|
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;
|
|
2274
|
+
this.compute = opts.compute;
|
|
2275
|
+
this.compare = opts.compare ?? Object.is;
|
|
2276
|
+
this.deps = opts.deps ?? [];
|
|
2277
|
+
this.coalescer = new OIMUpdateEventCoalescerComputed(
|
|
2278
|
+
this.emitter
|
|
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
|
|
2291
|
+
);
|
|
2292
|
+
this.effect = new OIMEffect(this.queue, {
|
|
2293
|
+
deps: this.deps,
|
|
2294
|
+
phase: "pre" /* PRE */,
|
|
2295
|
+
onInvalidate: () => {
|
|
2296
|
+
this.isDirty = true;
|
|
2297
|
+
},
|
|
2298
|
+
run: () => {
|
|
2299
|
+
if (this.isInFlush) {
|
|
2300
|
+
if (this.hasRecomputedInThisFlush) return;
|
|
2301
|
+
this.hasRecomputedInThisFlush = true;
|
|
2302
|
+
}
|
|
2303
|
+
this.recomputeAndEmitIfChanged();
|
|
2304
|
+
}
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
get() {
|
|
2308
|
+
this.recomputeAndEmitIfChanged();
|
|
2309
|
+
return this.value;
|
|
2310
|
+
}
|
|
2311
|
+
getIfReady() {
|
|
2312
|
+
return this.hasValue ? this.value : void 0;
|
|
2313
|
+
}
|
|
2314
|
+
destroy() {
|
|
2315
|
+
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
|
+
this.updateEventEmitter.destroy();
|
|
2325
|
+
this.coalescer.destroy();
|
|
2326
|
+
this.emitter.offAll();
|
|
2327
|
+
}
|
|
2328
|
+
recomputeAndEmitIfChanged() {
|
|
2329
|
+
if (!this.isDirty) return;
|
|
2330
|
+
const prev = this.value;
|
|
2331
|
+
const hadPrev = this.hasValue;
|
|
2332
|
+
const next = this.compute();
|
|
2333
|
+
this.value = next;
|
|
2334
|
+
this.hasValue = true;
|
|
2335
|
+
this.isDirty = false;
|
|
2336
|
+
const changed = !hadPrev || !this.compare(prev, next);
|
|
2337
|
+
if (!changed) return;
|
|
2338
|
+
this.emitter.emit("update" /* UPDATE */, {
|
|
2339
|
+
keys: ["value"]
|
|
2340
|
+
});
|
|
2341
|
+
}
|
|
2342
|
+
};
|
|
2343
|
+
|
|
2344
|
+
// src/modules/effect/core/OIMEffectDependencyKeyed.ts
|
|
2345
|
+
function isReadonlyArray(value) {
|
|
2346
|
+
return Array.isArray(value);
|
|
2347
|
+
}
|
|
2348
|
+
var OIMEffectDependencyKeyed = class {
|
|
2349
|
+
constructor(updateEventEmitter, keyOrKeys) {
|
|
2350
|
+
this.updateEventEmitter = updateEventEmitter;
|
|
2351
|
+
if (isReadonlyArray(keyOrKeys)) {
|
|
2352
|
+
this.keys = keyOrKeys;
|
|
2353
|
+
} else {
|
|
2354
|
+
this.key = keyOrKeys;
|
|
2355
|
+
}
|
|
2356
|
+
}
|
|
2357
|
+
subscribe(phase, onInvalidate) {
|
|
2358
|
+
const isPre = phase === "pre" /* PRE */;
|
|
2359
|
+
if (this.keys !== void 0) {
|
|
2360
|
+
return isPre ? this.updateEventEmitter.subscribeOnKeysBeforeFlush(
|
|
2361
|
+
this.keys,
|
|
2362
|
+
onInvalidate
|
|
2363
|
+
) : this.updateEventEmitter.subscribeOnKeys(
|
|
2364
|
+
this.keys,
|
|
2365
|
+
onInvalidate
|
|
2366
|
+
);
|
|
2367
|
+
}
|
|
2368
|
+
if (this.key === void 0) return () => {
|
|
2369
|
+
};
|
|
2370
|
+
return isPre ? this.updateEventEmitter.subscribeOnKeyBeforeFlush(
|
|
2371
|
+
this.key,
|
|
2372
|
+
onInvalidate
|
|
2373
|
+
) : this.updateEventEmitter.subscribeOnKey(this.key, onInvalidate);
|
|
2374
|
+
}
|
|
2375
|
+
};
|
|
2376
|
+
|
|
2377
|
+
// src/modules/effect/core/OIMEffectDependencyKeyedObject.ts
|
|
2378
|
+
var OIMEffectDependencyKeyedObject = class {
|
|
2379
|
+
constructor(object, keyOrKeys) {
|
|
2380
|
+
this.dep = new OIMEffectDependencyKeyed(
|
|
2381
|
+
object.updateEventEmitter,
|
|
2382
|
+
keyOrKeys
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2385
|
+
subscribe(phase, onInvalidate) {
|
|
2386
|
+
return this.dep.subscribe(phase, onInvalidate);
|
|
2387
|
+
}
|
|
2388
|
+
};
|
|
2389
|
+
|
|
2390
|
+
// src/modules/effect/core/OIMEffectDependencyKeyedCollection.ts
|
|
2391
|
+
var OIMEffectDependencyKeyedCollection = class {
|
|
2392
|
+
constructor(collection, pkOrPks) {
|
|
2393
|
+
this.dep = new OIMEffectDependencyKeyed(
|
|
2394
|
+
collection.updateEventEmitter,
|
|
2395
|
+
pkOrPks
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
subscribe(phase, onInvalidate) {
|
|
2399
|
+
return this.dep.subscribe(phase, onInvalidate);
|
|
2400
|
+
}
|
|
2401
|
+
};
|
|
2402
|
+
|
|
2403
|
+
// src/modules/effect/core/OIMEffectDependencyKeyedIndex.ts
|
|
2404
|
+
var OIMEffectDependencyKeyedIndex = class {
|
|
2405
|
+
constructor(index, keyOrKeys) {
|
|
2406
|
+
this.dep = new OIMEffectDependencyKeyed(
|
|
2407
|
+
index.updateEventEmitter,
|
|
2408
|
+
keyOrKeys
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
subscribe(phase, onInvalidate) {
|
|
2412
|
+
return this.dep.subscribe(phase, onInvalidate);
|
|
2413
|
+
}
|
|
2414
|
+
};
|
|
2415
|
+
|
|
2416
|
+
// src/modules/effect/core/OIMEffectDependencyComputed.ts
|
|
2417
|
+
var OIMEffectDependencyComputed = class {
|
|
2418
|
+
constructor(computed) {
|
|
2419
|
+
this.computed = computed;
|
|
2420
|
+
}
|
|
2421
|
+
subscribe(phase, onInvalidate) {
|
|
2422
|
+
if (phase === "pre" /* PRE */) {
|
|
2423
|
+
return this.computed.emitter.on("update", onInvalidate);
|
|
2424
|
+
}
|
|
2425
|
+
return this.computed.updateEventEmitter.subscribeOnKey(
|
|
2426
|
+
"value",
|
|
2427
|
+
onInvalidate
|
|
2428
|
+
);
|
|
2429
|
+
}
|
|
2430
|
+
};
|
|
1508
2431
|
export {
|
|
1509
2432
|
EOIMCollectionEventType,
|
|
2433
|
+
EOIMComputedEventType,
|
|
2434
|
+
EOIMEffectPhase,
|
|
1510
2435
|
EOIMEventQueueEventType,
|
|
1511
2436
|
EOIMEventQueueSchedulerEventType,
|
|
1512
2437
|
EOIMIndexEventType,
|
|
2438
|
+
EOIMObjectEventType,
|
|
1513
2439
|
EOIMUpdateEventCoalescerEventType,
|
|
1514
2440
|
OIMCollection,
|
|
2441
|
+
OIMCollectionChangedFieldsWrapper,
|
|
1515
2442
|
OIMCollectionStore,
|
|
1516
2443
|
OIMCollectionStoreMapDriven,
|
|
1517
2444
|
OIMComparatorFactory,
|
|
2445
|
+
OIMComputed,
|
|
1518
2446
|
OIMDBSettings,
|
|
2447
|
+
OIMEffect,
|
|
2448
|
+
OIMEffectDependencyComputed,
|
|
2449
|
+
OIMEffectDependencyKeyed,
|
|
2450
|
+
OIMEffectDependencyKeyedCollection,
|
|
2451
|
+
OIMEffectDependencyKeyedIndex,
|
|
2452
|
+
OIMEffectDependencyKeyedObject,
|
|
1519
2453
|
OIMEntityUpdaterFactory,
|
|
1520
2454
|
OIMEventEmitter,
|
|
1521
2455
|
OIMEventQueue,
|
|
@@ -1528,6 +2462,7 @@ export {
|
|
|
1528
2462
|
OIMIndexArrayBased,
|
|
1529
2463
|
OIMIndexComparatorFactory,
|
|
1530
2464
|
OIMIndexManualArrayBased,
|
|
2465
|
+
OIMIndexManualOrderedArrayBased,
|
|
1531
2466
|
OIMIndexManualSetBased,
|
|
1532
2467
|
OIMIndexSetBased,
|
|
1533
2468
|
OIMIndexStoreArrayBased,
|
|
@@ -1535,6 +2470,11 @@ export {
|
|
|
1535
2470
|
OIMIndexStoreMapDrivenSetBased,
|
|
1536
2471
|
OIMIndexStoreSetBased,
|
|
1537
2472
|
OIMMap2Keys,
|
|
2473
|
+
OIMObject,
|
|
2474
|
+
OIMObjectStore,
|
|
2475
|
+
OIMObjectStoreMapDriven,
|
|
2476
|
+
OIMObjectStoreRecordDriven,
|
|
2477
|
+
OIMOrderedListIndexCommandStreamWrapper,
|
|
1538
2478
|
OIMPkSelectorFactory,
|
|
1539
2479
|
OIMRICollection,
|
|
1540
2480
|
OIMReactiveCollection,
|
|
@@ -1542,8 +2482,12 @@ export {
|
|
|
1542
2482
|
OIMReactiveIndexManualArrayBased,
|
|
1543
2483
|
OIMReactiveIndexManualSetBased,
|
|
1544
2484
|
OIMReactiveIndexSetBased,
|
|
2485
|
+
OIMReactiveObject,
|
|
1545
2486
|
OIMUpdateEventCoalescer,
|
|
1546
2487
|
OIMUpdateEventCoalescerCollection,
|
|
2488
|
+
OIMUpdateEventCoalescerComputed,
|
|
1547
2489
|
OIMUpdateEventCoalescerIndex,
|
|
2490
|
+
OIMUpdateEventCoalescerManual,
|
|
2491
|
+
OIMUpdateEventCoalescerObject,
|
|
1548
2492
|
OIMUpdateEventEmitter
|
|
1549
2493
|
};
|