@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/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
- 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)) return;
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
- if (bucket.tombstoneCount >= length >> 1) {
75
- this.compactBucket(bucket);
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 >= length >> 1) {
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.queue.enqueue(() => {
459
- const updatedKeys = this.coalescer.getUpdatedKeys();
460
- if (this.keyHandlers.size === 0) {
461
- this.coalescer.clearUpdatedKeys();
462
- return;
463
- }
464
- if (updatedKeys.size * 2 < this.keyHandlers.size) {
465
- for (const key of updatedKeys.values()) {
466
- const handlers = this.keyHandlers.get(key);
467
- if (handlers) {
468
- for (const handler of handlers) {
469
- handler();
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
- for (const handlers of this.keyHandlers.values()) {
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 && 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) {
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
  };