@oimdb/core 1.3.0 → 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 -49
- package/dist/index.d.cts +430 -9
- package/dist/index.d.ts +430 -9
- package/dist/index.js +997 -49
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28,35 +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))
|
|
54
|
+
if (bucket.indexByHandler.has(handler)) {
|
|
55
|
+
return () => {
|
|
56
|
+
this.off(event, handler);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
57
59
|
const index = bucket.handlers.length;
|
|
58
60
|
bucket.handlers.push(handler);
|
|
59
61
|
bucket.indexByHandler.set(handler, index);
|
|
62
|
+
return () => {
|
|
63
|
+
this.off(event, handler);
|
|
64
|
+
};
|
|
60
65
|
}
|
|
61
66
|
emit(event, payload) {
|
|
62
67
|
const bucket = this.buckets[event];
|
|
@@ -71,10 +76,11 @@ var OIMEventEmitter = class {
|
|
|
71
76
|
}
|
|
72
77
|
bucket.isEmitting--;
|
|
73
78
|
if (bucket.isEmitting === 0 && bucket.tombstoneCount > 0) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
} else if (length === bucket.tombstoneCount) {
|
|
79
|
+
const currentLength = bucket.handlers.length;
|
|
80
|
+
if (bucket.tombstoneCount === currentLength) {
|
|
77
81
|
delete this.buckets[event];
|
|
82
|
+
} else if (bucket.tombstoneCount >= currentLength >> 1) {
|
|
83
|
+
this.compactBucket(bucket);
|
|
78
84
|
}
|
|
79
85
|
}
|
|
80
86
|
}
|
|
@@ -88,10 +94,10 @@ var OIMEventEmitter = class {
|
|
|
88
94
|
bucket.indexByHandler.delete(handler);
|
|
89
95
|
if (bucket.isEmitting === 0) {
|
|
90
96
|
const length = bucket.handlers.length;
|
|
91
|
-
if (bucket.tombstoneCount
|
|
92
|
-
this.compactBucket(bucket);
|
|
93
|
-
} else if (length === bucket.tombstoneCount) {
|
|
97
|
+
if (bucket.tombstoneCount === length) {
|
|
94
98
|
delete this.buckets[event];
|
|
99
|
+
} else if (bucket.tombstoneCount >= length >> 1) {
|
|
100
|
+
this.compactBucket(bucket);
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
}
|
|
@@ -453,34 +459,50 @@ var EOIMUpdateEventCoalescerEventType = /* @__PURE__ */ ((EOIMUpdateEventCoalesc
|
|
|
453
459
|
// src/core/OIMUpdateEventEmitter.ts
|
|
454
460
|
var OIMUpdateEventEmitter = class {
|
|
455
461
|
constructor(opts) {
|
|
462
|
+
this.keyHandlersBeforeFlush = /* @__PURE__ */ new Map();
|
|
456
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;
|
|
457
469
|
this.handleHasChanges = () => {
|
|
458
|
-
this.
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
} else {
|
|
474
|
-
for (const [key, handlers] of this.keyHandlers) {
|
|
475
|
-
if (updatedKeys.has(key)) {
|
|
476
|
-
for (const handler of handlers) {
|
|
477
|
-
handler();
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
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) {
|
|
482
482
|
this.coalescer.clearUpdatedKeys();
|
|
483
|
-
|
|
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
|
+
}
|
|
484
506
|
};
|
|
485
507
|
this.coalescer = opts.coalescer;
|
|
486
508
|
this.coalescer.emitter.on(
|
|
@@ -489,11 +511,90 @@ var OIMUpdateEventEmitter = class {
|
|
|
489
511
|
);
|
|
490
512
|
this.queue = opts.queue;
|
|
491
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
|
+
}
|
|
492
590
|
destroy() {
|
|
591
|
+
if (this.isDestroyed) return;
|
|
592
|
+
this.isDestroyed = true;
|
|
493
593
|
this.coalescer.emitter.off(
|
|
494
594
|
0 /* HAS_CHANGES */,
|
|
495
595
|
this.handleHasChanges
|
|
496
596
|
);
|
|
597
|
+
this.keyHandlersBeforeFlush.clear();
|
|
497
598
|
this.keyHandlers.clear();
|
|
498
599
|
}
|
|
499
600
|
/**
|
|
@@ -501,9 +602,9 @@ var OIMUpdateEventEmitter = class {
|
|
|
501
602
|
*/
|
|
502
603
|
getMetrics() {
|
|
503
604
|
let totalHandlers = 0;
|
|
504
|
-
|
|
605
|
+
this.keyHandlers.forEach((handlers) => {
|
|
505
606
|
totalHandlers += handlers.size;
|
|
506
|
-
}
|
|
607
|
+
});
|
|
507
608
|
return {
|
|
508
609
|
totalKeys: this.keyHandlers.size,
|
|
509
610
|
totalHandlers,
|
|
@@ -515,13 +616,32 @@ var OIMUpdateEventEmitter = class {
|
|
|
515
616
|
* Check if there are any active subscriptions
|
|
516
617
|
*/
|
|
517
618
|
hasSubscriptions() {
|
|
518
|
-
return this.keyHandlers.size > 0;
|
|
619
|
+
return this.keyHandlers.size > 0 || this.keyHandlersBeforeFlush.size > 0;
|
|
519
620
|
}
|
|
520
621
|
/**
|
|
521
622
|
* Get the number of handlers for a specific key
|
|
522
623
|
*/
|
|
523
624
|
getHandlerCount(key) {
|
|
524
|
-
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
|
+
}
|
|
525
645
|
}
|
|
526
646
|
subscribeOnKey(key, handler) {
|
|
527
647
|
let handlers = this.keyHandlers.get(key);
|
|
@@ -561,6 +681,30 @@ var OIMUpdateEventEmitter = class {
|
|
|
561
681
|
}
|
|
562
682
|
};
|
|
563
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
|
+
}
|
|
564
708
|
unsubscribeFromKeys(keys, handler) {
|
|
565
709
|
for (const key of keys) {
|
|
566
710
|
this.unsubscribeFromKey(key, handler);
|
|
@@ -655,15 +799,19 @@ var OIMDBSettings = class {
|
|
|
655
799
|
* This constant is exported so users can create their own indexes and pass them to coalescers.
|
|
656
800
|
*/
|
|
657
801
|
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
802
|
+
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY = "__flushingKeys__";
|
|
658
803
|
|
|
659
804
|
// src/core/OIMUpdateEventCoalescer.ts
|
|
660
805
|
var OIMUpdateEventCoalescer = class {
|
|
661
|
-
constructor(index) {
|
|
806
|
+
constructor(index, flushingIndex) {
|
|
662
807
|
this.emitter = new OIMEventEmitter();
|
|
663
808
|
this.hasEmittedChanges = false;
|
|
664
809
|
this.updatedKeysIndex = index ?? new OIMIndexManualSetBased({
|
|
665
810
|
store: new OIMIndexStoreMapDrivenSetBased()
|
|
666
811
|
});
|
|
812
|
+
this.flushingUpdatedKeysIndex = flushingIndex ?? new OIMIndexManualSetBased({
|
|
813
|
+
store: new OIMIndexStoreMapDrivenSetBased()
|
|
814
|
+
});
|
|
667
815
|
if (!this.updatedKeysIndex.hasKey(OIMDBSettings.UPDATED_KEYS_INDEX_KEY)) {
|
|
668
816
|
this.updatedKeysIndex.setPks(
|
|
669
817
|
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
@@ -679,6 +827,18 @@ var OIMUpdateEventCoalescer = class {
|
|
|
679
827
|
OIMDBSettings.UPDATED_KEYS_INDEX_KEY
|
|
680
828
|
);
|
|
681
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
|
+
}
|
|
682
842
|
/**
|
|
683
843
|
* Clear all updated keys and reset the changed state
|
|
684
844
|
*/
|
|
@@ -694,6 +854,12 @@ var OIMUpdateEventCoalescer = class {
|
|
|
694
854
|
void 0
|
|
695
855
|
);
|
|
696
856
|
}
|
|
857
|
+
clearFlushingUpdatedKeys() {
|
|
858
|
+
this.flushingUpdatedKeysIndex.setPks(
|
|
859
|
+
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY,
|
|
860
|
+
[]
|
|
861
|
+
);
|
|
862
|
+
}
|
|
697
863
|
/**
|
|
698
864
|
* Add keys to the updated set and emit HAS_CHANGES event if needed
|
|
699
865
|
*/
|
|
@@ -769,6 +935,8 @@ var OIMReactiveIndexSetBased = class {
|
|
|
769
935
|
return this.index.getMetrics();
|
|
770
936
|
}
|
|
771
937
|
destroy() {
|
|
938
|
+
this.updateEventEmitter.destroy();
|
|
939
|
+
this.coalescer.destroy();
|
|
772
940
|
this.index.destroy();
|
|
773
941
|
}
|
|
774
942
|
};
|
|
@@ -810,10 +978,16 @@ var OIMReactiveIndexArrayBased = class {
|
|
|
810
978
|
return this.index.getMetrics();
|
|
811
979
|
}
|
|
812
980
|
destroy() {
|
|
981
|
+
this.updateEventEmitter.destroy();
|
|
982
|
+
this.coalescer.destroy();
|
|
813
983
|
this.index.destroy();
|
|
814
984
|
}
|
|
815
985
|
};
|
|
816
986
|
|
|
987
|
+
// src/abstract/OIMObjectStore.ts
|
|
988
|
+
var OIMObjectStore = class {
|
|
989
|
+
};
|
|
990
|
+
|
|
817
991
|
// src/core/OIMPkSelectorFactory.ts
|
|
818
992
|
var OIMPkSelectorFactory = class {
|
|
819
993
|
createIdSelector() {
|
|
@@ -871,6 +1045,9 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
871
1045
|
getAllPks() {
|
|
872
1046
|
return Array.from(this.entities.keys());
|
|
873
1047
|
}
|
|
1048
|
+
destroy() {
|
|
1049
|
+
this.clear();
|
|
1050
|
+
}
|
|
874
1051
|
};
|
|
875
1052
|
|
|
876
1053
|
// src/core/OIMEntityUpdaterFactory.ts
|
|
@@ -968,6 +1145,10 @@ var OIMCollection = class {
|
|
|
968
1145
|
this.store.setOneByPk(pk, entity);
|
|
969
1146
|
}
|
|
970
1147
|
}
|
|
1148
|
+
destroy() {
|
|
1149
|
+
this.store.destroy();
|
|
1150
|
+
this.emitter.offAll();
|
|
1151
|
+
}
|
|
971
1152
|
};
|
|
972
1153
|
|
|
973
1154
|
// src/core/OIMUpdateEventCoalescerCollection.ts
|
|
@@ -1008,6 +1189,143 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1008
1189
|
queue
|
|
1009
1190
|
});
|
|
1010
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
|
+
}
|
|
1011
1329
|
};
|
|
1012
1330
|
|
|
1013
1331
|
// src/core/OIMReactiveIndexManualSetBased.ts
|
|
@@ -1134,7 +1452,54 @@ var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased
|
|
|
1134
1452
|
var OIMRICollection = class extends OIMReactiveCollection {
|
|
1135
1453
|
constructor(queue, opts) {
|
|
1136
1454
|
super(queue, opts.collectionOpts);
|
|
1137
|
-
this.indexes = opts.indexes;
|
|
1455
|
+
this.indexes = opts.indexes || {};
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
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();
|
|
1138
1503
|
}
|
|
1139
1504
|
};
|
|
1140
1505
|
|
|
@@ -1168,6 +1533,8 @@ var OIMEventQueue = class {
|
|
|
1168
1533
|
constructor(options = {}) {
|
|
1169
1534
|
this.emitter = new OIMEventEmitter();
|
|
1170
1535
|
this.queue = [];
|
|
1536
|
+
this.isFlushing = false;
|
|
1537
|
+
this.pendingSchedule = false;
|
|
1171
1538
|
this.scheduler = options.scheduler;
|
|
1172
1539
|
if (this.scheduler) {
|
|
1173
1540
|
this.flushBound = () => this.flush();
|
|
@@ -1183,7 +1550,12 @@ var OIMEventQueue = class {
|
|
|
1183
1550
|
*/
|
|
1184
1551
|
enqueue(fn) {
|
|
1185
1552
|
this.queue.push(fn);
|
|
1186
|
-
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) {
|
|
1187
1559
|
this.scheduler.schedule();
|
|
1188
1560
|
}
|
|
1189
1561
|
}
|
|
@@ -1193,6 +1565,8 @@ var OIMEventQueue = class {
|
|
|
1193
1565
|
*/
|
|
1194
1566
|
flush() {
|
|
1195
1567
|
if (this.queue.length === 0) return;
|
|
1568
|
+
this.scheduler?.cancel();
|
|
1569
|
+
this.isFlushing = true;
|
|
1196
1570
|
this.emitter.emit(1 /* BEFORE_FLUSH */, void 0);
|
|
1197
1571
|
const currentQueue = this.queue.slice();
|
|
1198
1572
|
this.queue.length = 0;
|
|
@@ -1200,6 +1574,13 @@ var OIMEventQueue = class {
|
|
|
1200
1574
|
currentQueue[i]();
|
|
1201
1575
|
}
|
|
1202
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
|
+
}
|
|
1203
1584
|
}
|
|
1204
1585
|
/**
|
|
1205
1586
|
* Get the current number of queued functions.
|
|
@@ -1267,7 +1648,7 @@ var OIMIndexComparatorFactory = class {
|
|
|
1267
1648
|
if (existingSet.size !== newSet.size || existingSet.size !== existingPks.length) {
|
|
1268
1649
|
return false;
|
|
1269
1650
|
}
|
|
1270
|
-
for (const pk of existingSet) {
|
|
1651
|
+
for (const pk of Array.from(existingSet)) {
|
|
1271
1652
|
if (!newSet.has(pk)) {
|
|
1272
1653
|
return false;
|
|
1273
1654
|
}
|
|
@@ -1333,6 +1714,270 @@ var OIMMap2Keys = class {
|
|
|
1333
1714
|
}
|
|
1334
1715
|
};
|
|
1335
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
|
+
|
|
1336
1981
|
// src/core/event-queue-scheduler/OIMEventQueueSchedulerAnimationFrame.ts
|
|
1337
1982
|
var OIMEventQueueSchedulerAnimationFrame = class extends OIMEventQueueScheduler {
|
|
1338
1983
|
constructor() {
|
|
@@ -1501,17 +2146,310 @@ var OIMEventQueueSchedulerFactory = class {
|
|
|
1501
2146
|
return new OIMEventQueueSchedulerImmediate();
|
|
1502
2147
|
}
|
|
1503
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
|
+
};
|
|
1504
2431
|
export {
|
|
1505
2432
|
EOIMCollectionEventType,
|
|
2433
|
+
EOIMComputedEventType,
|
|
2434
|
+
EOIMEffectPhase,
|
|
1506
2435
|
EOIMEventQueueEventType,
|
|
1507
2436
|
EOIMEventQueueSchedulerEventType,
|
|
1508
2437
|
EOIMIndexEventType,
|
|
2438
|
+
EOIMObjectEventType,
|
|
1509
2439
|
EOIMUpdateEventCoalescerEventType,
|
|
1510
2440
|
OIMCollection,
|
|
2441
|
+
OIMCollectionChangedFieldsWrapper,
|
|
1511
2442
|
OIMCollectionStore,
|
|
1512
2443
|
OIMCollectionStoreMapDriven,
|
|
1513
2444
|
OIMComparatorFactory,
|
|
2445
|
+
OIMComputed,
|
|
1514
2446
|
OIMDBSettings,
|
|
2447
|
+
OIMEffect,
|
|
2448
|
+
OIMEffectDependencyComputed,
|
|
2449
|
+
OIMEffectDependencyKeyed,
|
|
2450
|
+
OIMEffectDependencyKeyedCollection,
|
|
2451
|
+
OIMEffectDependencyKeyedIndex,
|
|
2452
|
+
OIMEffectDependencyKeyedObject,
|
|
1515
2453
|
OIMEntityUpdaterFactory,
|
|
1516
2454
|
OIMEventEmitter,
|
|
1517
2455
|
OIMEventQueue,
|
|
@@ -1524,6 +2462,7 @@ export {
|
|
|
1524
2462
|
OIMIndexArrayBased,
|
|
1525
2463
|
OIMIndexComparatorFactory,
|
|
1526
2464
|
OIMIndexManualArrayBased,
|
|
2465
|
+
OIMIndexManualOrderedArrayBased,
|
|
1527
2466
|
OIMIndexManualSetBased,
|
|
1528
2467
|
OIMIndexSetBased,
|
|
1529
2468
|
OIMIndexStoreArrayBased,
|
|
@@ -1531,6 +2470,11 @@ export {
|
|
|
1531
2470
|
OIMIndexStoreMapDrivenSetBased,
|
|
1532
2471
|
OIMIndexStoreSetBased,
|
|
1533
2472
|
OIMMap2Keys,
|
|
2473
|
+
OIMObject,
|
|
2474
|
+
OIMObjectStore,
|
|
2475
|
+
OIMObjectStoreMapDriven,
|
|
2476
|
+
OIMObjectStoreRecordDriven,
|
|
2477
|
+
OIMOrderedListIndexCommandStreamWrapper,
|
|
1534
2478
|
OIMPkSelectorFactory,
|
|
1535
2479
|
OIMRICollection,
|
|
1536
2480
|
OIMReactiveCollection,
|
|
@@ -1538,8 +2482,12 @@ export {
|
|
|
1538
2482
|
OIMReactiveIndexManualArrayBased,
|
|
1539
2483
|
OIMReactiveIndexManualSetBased,
|
|
1540
2484
|
OIMReactiveIndexSetBased,
|
|
2485
|
+
OIMReactiveObject,
|
|
1541
2486
|
OIMUpdateEventCoalescer,
|
|
1542
2487
|
OIMUpdateEventCoalescerCollection,
|
|
2488
|
+
OIMUpdateEventCoalescerComputed,
|
|
1543
2489
|
OIMUpdateEventCoalescerIndex,
|
|
2490
|
+
OIMUpdateEventCoalescerManual,
|
|
2491
|
+
OIMUpdateEventCoalescerObject,
|
|
1544
2492
|
OIMUpdateEventEmitter
|
|
1545
2493
|
};
|