@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/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
- newHandlers[writeIndex] = handler;
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
- handler,
62
- index
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
- if (bucket.tombstoneCount >= length >> 1) {
79
- this.compactBucket(bucket);
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 >= length >> 1) {
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.queue.enqueue(() => {
463
- const updatedKeys = this.coalescer.getUpdatedKeys();
464
- if (this.keyHandlers.size === 0) {
465
- this.coalescer.clearUpdatedKeys();
466
- return;
467
- }
468
- if (updatedKeys.size * 2 < this.keyHandlers.size) {
469
- for (const key of updatedKeys.values()) {
470
- const handlers = this.keyHandlers.get(key);
471
- if (handlers) {
472
- for (const handler of handlers) {
473
- handler();
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
- for (const handlers of this.keyHandlers.values()) {
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 && this.queue.length === 1) {
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
  };