@oimdb/core 2.1.0 → 3.0.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.cjs +488 -124
- package/dist/index.d.cts +173 -19
- package/dist/index.d.ts +173 -19
- package/dist/index.js +486 -124
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
EOIMEventQueueSchedulerEventType: () => EOIMEventQueueSchedulerEventType,
|
|
27
27
|
EOIMIndexEventType: () => EOIMIndexEventType,
|
|
28
28
|
EOIMObjectEventType: () => EOIMObjectEventType,
|
|
29
|
+
OIMCarrierKeyedEmitter: () => OIMCarrierKeyedEmitter,
|
|
29
30
|
OIMCollection: () => OIMCollection,
|
|
30
31
|
OIMCollectionByPkSelector: () => OIMCollectionByPkSelector,
|
|
31
32
|
OIMCollectionByPksSelector: () => OIMCollectionByPksSelector,
|
|
@@ -93,6 +94,7 @@ __export(index_exports, {
|
|
|
93
94
|
OIMReactiveIndexSetBased: () => OIMReactiveIndexSetBased,
|
|
94
95
|
OIMReactiveObject: () => OIMReactiveObject,
|
|
95
96
|
OIMSelector: () => OIMSelector,
|
|
97
|
+
createInPlaceEntityUpdater: () => createInPlaceEntityUpdater,
|
|
96
98
|
createOIMCollectionIndexFactory: () => createOIMCollectionIndexFactory,
|
|
97
99
|
createOIMCollectionKit: () => createOIMCollectionKit
|
|
98
100
|
});
|
|
@@ -277,10 +279,18 @@ var OIMIndex = class {
|
|
|
277
279
|
emitUpdateOne(key) {
|
|
278
280
|
this.emitUpdate([key]);
|
|
279
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Maps a bucket's slots to entities, preserving positional holes: a slot
|
|
284
|
+
* whose entity is not present yet (reserved by an index ahead of its data)
|
|
285
|
+
* or was removed yields `undefined` at its position rather than being
|
|
286
|
+
* dropped. This keeps the result aligned with `getPksByKey`, so callers can
|
|
287
|
+
* render a per-item loading/placeholder state instead of a silently shorter
|
|
288
|
+
* list.
|
|
289
|
+
*/
|
|
280
290
|
slotsToEntities(slots) {
|
|
281
291
|
const entities = [];
|
|
282
292
|
for (const slot of slots) {
|
|
283
|
-
|
|
293
|
+
entities.push(slot.item);
|
|
284
294
|
}
|
|
285
295
|
return entities;
|
|
286
296
|
}
|
|
@@ -536,12 +546,7 @@ var OIMUpdateEventEmitter = class {
|
|
|
536
546
|
this.updatedKeys.clear();
|
|
537
547
|
return;
|
|
538
548
|
}
|
|
539
|
-
|
|
540
|
-
const snapshot = [];
|
|
541
|
-
handlers.forEach((h) => snapshot.push(h));
|
|
542
|
-
return snapshot;
|
|
543
|
-
};
|
|
544
|
-
this.runSinglePass(makeHandlerSnapshot);
|
|
549
|
+
this.runSinglePass();
|
|
545
550
|
};
|
|
546
551
|
this.onAfterFlush = () => {
|
|
547
552
|
if (!this.isAfterFlushDeliveryScheduled) return;
|
|
@@ -636,18 +641,32 @@ var OIMUpdateEventEmitter = class {
|
|
|
636
641
|
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
637
642
|
}
|
|
638
643
|
deliverImmediate() {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
644
|
+
this.runSinglePass();
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Notifies all handlers for a key. The overwhelmingly common case is a
|
|
648
|
+
* single subscriber per key (one component per pk), handled without any
|
|
649
|
+
* allocation. For multiple subscribers a snapshot is taken so a handler may
|
|
650
|
+
* (un)subscribe during iteration without corrupting the walk.
|
|
651
|
+
*/
|
|
652
|
+
notifyHandlers(handlers) {
|
|
653
|
+
if (handlers.size === 1) {
|
|
654
|
+
const only = handlers.values().next().value;
|
|
655
|
+
if (only) only();
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const snapshot = [];
|
|
659
|
+
handlers.forEach((h) => snapshot.push(h));
|
|
660
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
661
|
+
const handler = snapshot[i];
|
|
662
|
+
if (handlers.has(handler)) handler();
|
|
663
|
+
}
|
|
645
664
|
}
|
|
646
665
|
/**
|
|
647
666
|
* Deliver updated keys and notify handlers once.
|
|
648
667
|
* Re-entrant updates during delivery are forbidden and will throw in markUpdatedKeys().
|
|
649
668
|
*/
|
|
650
|
-
runSinglePass(
|
|
669
|
+
runSinglePass() {
|
|
651
670
|
if (this.updatedKeys.size === 0) return;
|
|
652
671
|
const flushingKeys = this.updatedKeys;
|
|
653
672
|
this.updatedKeys = /* @__PURE__ */ new Set();
|
|
@@ -656,21 +675,13 @@ var OIMUpdateEventEmitter = class {
|
|
|
656
675
|
flushingKeys.forEach((key) => {
|
|
657
676
|
const handlers = this.keyHandlers.get(key);
|
|
658
677
|
if (!handlers || handlers.size === 0) return;
|
|
659
|
-
|
|
660
|
-
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
661
|
-
const handler = handlerSnapshot[i];
|
|
662
|
-
if (handlers.has(handler)) handler();
|
|
663
|
-
}
|
|
678
|
+
this.notifyHandlers(handlers);
|
|
664
679
|
});
|
|
665
680
|
} else {
|
|
666
681
|
this.keyHandlers.forEach((handlers, key) => {
|
|
667
682
|
if (!flushingKeys.has(key)) return;
|
|
668
683
|
if (!handlers || handlers.size === 0) return;
|
|
669
|
-
|
|
670
|
-
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
671
|
-
const handler = handlerSnapshot[i];
|
|
672
|
-
if (handlers.has(handler)) handler();
|
|
673
|
-
}
|
|
684
|
+
this.notifyHandlers(handlers);
|
|
674
685
|
});
|
|
675
686
|
}
|
|
676
687
|
}
|
|
@@ -879,17 +890,39 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
879
890
|
constructor() {
|
|
880
891
|
super(...arguments);
|
|
881
892
|
this.slots = /* @__PURE__ */ new Map();
|
|
893
|
+
// Slots reserved by indexes for PKs whose entity has not arrived yet.
|
|
894
|
+
// They carry `item: undefined` and live apart from `slots` so they do not
|
|
895
|
+
// leak into entity enumeration (getAll/getAllPks/countAll). When the entity
|
|
896
|
+
// is finally written, the reserved slot is promoted into `slots` — keeping
|
|
897
|
+
// the reference that indexes already hold, so it fills in live.
|
|
898
|
+
this.reservedSlots = /* @__PURE__ */ new Map();
|
|
882
899
|
}
|
|
883
900
|
setOneByPk(pk, entity) {
|
|
884
901
|
const slot = this.slots.get(pk);
|
|
885
902
|
if (slot) {
|
|
886
903
|
slot.item = entity;
|
|
887
904
|
return slot;
|
|
888
|
-
} else {
|
|
889
|
-
const nextSlot = { pk, item: entity };
|
|
890
|
-
this.slots.set(pk, nextSlot);
|
|
891
|
-
return nextSlot;
|
|
892
905
|
}
|
|
906
|
+
const reserved = this.reservedSlots.get(pk);
|
|
907
|
+
if (reserved) {
|
|
908
|
+
reserved.item = entity;
|
|
909
|
+
this.reservedSlots.delete(pk);
|
|
910
|
+
this.slots.set(pk, reserved);
|
|
911
|
+
return reserved;
|
|
912
|
+
}
|
|
913
|
+
const nextSlot = { pk, item: entity };
|
|
914
|
+
this.slots.set(pk, nextSlot);
|
|
915
|
+
return nextSlot;
|
|
916
|
+
}
|
|
917
|
+
getOrReserveSlotByPk(pk) {
|
|
918
|
+
const slot = this.slots.get(pk);
|
|
919
|
+
if (slot) return slot;
|
|
920
|
+
let reserved = this.reservedSlots.get(pk);
|
|
921
|
+
if (!reserved) {
|
|
922
|
+
reserved = { pk, item: void 0 };
|
|
923
|
+
this.reservedSlots.set(pk, reserved);
|
|
924
|
+
}
|
|
925
|
+
return reserved;
|
|
893
926
|
}
|
|
894
927
|
setManyByPks(pks, entities) {
|
|
895
928
|
const slots = [];
|
|
@@ -902,6 +935,12 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
902
935
|
getSlotByPk(pk) {
|
|
903
936
|
return this.slots.get(pk);
|
|
904
937
|
}
|
|
938
|
+
findSlotByPk(pk) {
|
|
939
|
+
return this.slots.get(pk) ?? this.reservedSlots.get(pk);
|
|
940
|
+
}
|
|
941
|
+
hasSubscribers(slot) {
|
|
942
|
+
return slot.subscribers !== void 0 && slot.subscribers.size > 0;
|
|
943
|
+
}
|
|
905
944
|
getSlotsByPks(pks) {
|
|
906
945
|
const result = [];
|
|
907
946
|
result.length = pks.length;
|
|
@@ -920,8 +959,21 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
920
959
|
}
|
|
921
960
|
removeOneByPk(pk) {
|
|
922
961
|
const slot = this.slots.get(pk);
|
|
923
|
-
if (slot)
|
|
924
|
-
|
|
962
|
+
if (slot) {
|
|
963
|
+
slot.item = void 0;
|
|
964
|
+
this.slots.delete(pk);
|
|
965
|
+
if (this.hasSubscribers(slot)) {
|
|
966
|
+
this.reservedSlots.set(pk, slot);
|
|
967
|
+
}
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
const reserved = this.reservedSlots.get(pk);
|
|
971
|
+
if (reserved) {
|
|
972
|
+
reserved.item = void 0;
|
|
973
|
+
if (!this.hasSubscribers(reserved)) {
|
|
974
|
+
this.reservedSlots.delete(pk);
|
|
975
|
+
}
|
|
976
|
+
}
|
|
925
977
|
}
|
|
926
978
|
removeManyByPks(pks) {
|
|
927
979
|
for (const pk of pks) {
|
|
@@ -955,16 +1007,31 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
955
1007
|
return this.slots.size;
|
|
956
1008
|
}
|
|
957
1009
|
clear() {
|
|
1010
|
+
const retained = [];
|
|
958
1011
|
for (const slot of this.slots.values()) {
|
|
959
1012
|
slot.item = void 0;
|
|
1013
|
+
if (this.hasSubscribers(slot)) retained.push(slot);
|
|
960
1014
|
}
|
|
961
1015
|
this.slots.clear();
|
|
1016
|
+
for (const slot of this.reservedSlots.values()) {
|
|
1017
|
+
slot.item = void 0;
|
|
1018
|
+
if (this.hasSubscribers(slot)) retained.push(slot);
|
|
1019
|
+
}
|
|
1020
|
+
this.reservedSlots.clear();
|
|
1021
|
+
for (const slot of retained) {
|
|
1022
|
+
this.reservedSlots.set(slot.pk, slot);
|
|
1023
|
+
}
|
|
962
1024
|
}
|
|
963
1025
|
getAllPks() {
|
|
964
1026
|
return Array.from(this.slots.keys());
|
|
965
1027
|
}
|
|
966
1028
|
destroy() {
|
|
967
1029
|
this.clear();
|
|
1030
|
+
for (const slot of this.reservedSlots.values()) {
|
|
1031
|
+
slot.subscribers?.clear();
|
|
1032
|
+
slot.subscribers = void 0;
|
|
1033
|
+
}
|
|
1034
|
+
this.reservedSlots.clear();
|
|
968
1035
|
}
|
|
969
1036
|
};
|
|
970
1037
|
|
|
@@ -1000,6 +1067,9 @@ var OIMCollection = class {
|
|
|
1000
1067
|
getSlotByPk(pk) {
|
|
1001
1068
|
return this.store.getSlotByPk(pk);
|
|
1002
1069
|
}
|
|
1070
|
+
getOrReserveSlotByPk(pk) {
|
|
1071
|
+
return this.store.getOrReserveSlotByPk(pk);
|
|
1072
|
+
}
|
|
1003
1073
|
getSlotsByPks(pks) {
|
|
1004
1074
|
return this.store.getSlotsByPks(pks);
|
|
1005
1075
|
}
|
|
@@ -1084,6 +1154,153 @@ var OIMCollection = class {
|
|
|
1084
1154
|
}
|
|
1085
1155
|
};
|
|
1086
1156
|
|
|
1157
|
+
// src/core/OIMCarrierKeyedEmitter.ts
|
|
1158
|
+
var OIMCarrierKeyedEmitter = class {
|
|
1159
|
+
constructor(queue, resolver) {
|
|
1160
|
+
// Carriers with at least one subscriber — for markAllUpdated / metrics.
|
|
1161
|
+
this.subscribedCarriers = /* @__PURE__ */ new Set();
|
|
1162
|
+
this.dirtyCarriers = /* @__PURE__ */ new Set();
|
|
1163
|
+
this.isFlushEnqueued = false;
|
|
1164
|
+
this.onFlush = () => {
|
|
1165
|
+
this.isFlushEnqueued = false;
|
|
1166
|
+
this.dequeueFlush = void 0;
|
|
1167
|
+
if (this.dirtyCarriers.size === 0) return;
|
|
1168
|
+
const flushing = this.dirtyCarriers;
|
|
1169
|
+
this.dirtyCarriers = /* @__PURE__ */ new Set();
|
|
1170
|
+
flushing.forEach((carrier) => this.notify(carrier));
|
|
1171
|
+
};
|
|
1172
|
+
this.queue = queue;
|
|
1173
|
+
this.resolver = resolver;
|
|
1174
|
+
}
|
|
1175
|
+
subscribeOnKey(key, handler) {
|
|
1176
|
+
const carrier = this.resolver.getOrReserveCarrier(key);
|
|
1177
|
+
this.addHandler(carrier, handler);
|
|
1178
|
+
return () => this.removeHandler(carrier, handler);
|
|
1179
|
+
}
|
|
1180
|
+
subscribeOnKeys(keys, handler) {
|
|
1181
|
+
const carriers = [];
|
|
1182
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1183
|
+
const carrier = this.resolver.getOrReserveCarrier(keys[i]);
|
|
1184
|
+
this.addHandler(carrier, handler);
|
|
1185
|
+
carriers.push(carrier);
|
|
1186
|
+
}
|
|
1187
|
+
return () => {
|
|
1188
|
+
for (let i = 0; i < carriers.length; i++) {
|
|
1189
|
+
this.removeHandler(carriers[i], handler);
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
unsubscribeFromKey(key, handler) {
|
|
1194
|
+
const carrier = this.resolver.findCarrier(key);
|
|
1195
|
+
if (carrier) this.removeHandler(carrier, handler);
|
|
1196
|
+
}
|
|
1197
|
+
unsubscribeFromKeys(keys, handler) {
|
|
1198
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1199
|
+
this.unsubscribeFromKey(keys[i], handler);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
addHandler(carrier, handler) {
|
|
1203
|
+
let subscribers = carrier.subscribers;
|
|
1204
|
+
if (!subscribers) {
|
|
1205
|
+
subscribers = /* @__PURE__ */ new Set();
|
|
1206
|
+
carrier.subscribers = subscribers;
|
|
1207
|
+
}
|
|
1208
|
+
subscribers.add(handler);
|
|
1209
|
+
this.subscribedCarriers.add(carrier);
|
|
1210
|
+
}
|
|
1211
|
+
removeHandler(carrier, handler) {
|
|
1212
|
+
const subscribers = carrier.subscribers;
|
|
1213
|
+
if (!subscribers) return;
|
|
1214
|
+
subscribers.delete(handler);
|
|
1215
|
+
if (subscribers.size === 0) {
|
|
1216
|
+
this.subscribedCarriers.delete(carrier);
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
/** Fast path: the writer already holds the carrier. */
|
|
1220
|
+
markUpdatedCarrier(carrier) {
|
|
1221
|
+
this.assertNotInFlush();
|
|
1222
|
+
const subscribers = carrier.subscribers;
|
|
1223
|
+
if (!subscribers || subscribers.size === 0) return;
|
|
1224
|
+
this.dirtyCarriers.add(carrier);
|
|
1225
|
+
this.scheduleFlush();
|
|
1226
|
+
}
|
|
1227
|
+
markUpdatedKey(key) {
|
|
1228
|
+
const carrier = this.resolver.findCarrier(key);
|
|
1229
|
+
if (carrier) this.markUpdatedCarrier(carrier);
|
|
1230
|
+
else this.assertNotInFlush();
|
|
1231
|
+
}
|
|
1232
|
+
markUpdatedKeys(keys) {
|
|
1233
|
+
for (let i = 0; i < keys.length; i++) this.markUpdatedKey(keys[i]);
|
|
1234
|
+
}
|
|
1235
|
+
markAllUpdated() {
|
|
1236
|
+
this.assertNotInFlush();
|
|
1237
|
+
if (this.subscribedCarriers.size === 0) return;
|
|
1238
|
+
this.subscribedCarriers.forEach(
|
|
1239
|
+
(carrier) => this.dirtyCarriers.add(carrier)
|
|
1240
|
+
);
|
|
1241
|
+
this.scheduleFlush();
|
|
1242
|
+
}
|
|
1243
|
+
hasSubscriptions() {
|
|
1244
|
+
return this.subscribedCarriers.size > 0;
|
|
1245
|
+
}
|
|
1246
|
+
getHandlerCount(key) {
|
|
1247
|
+
return this.resolver.findCarrier(key)?.subscribers?.size ?? 0;
|
|
1248
|
+
}
|
|
1249
|
+
getMetrics() {
|
|
1250
|
+
let totalHandlers = 0;
|
|
1251
|
+
this.subscribedCarriers.forEach((carrier) => {
|
|
1252
|
+
totalHandlers += carrier.subscribers?.size ?? 0;
|
|
1253
|
+
});
|
|
1254
|
+
const totalKeys = this.subscribedCarriers.size;
|
|
1255
|
+
return {
|
|
1256
|
+
totalKeys,
|
|
1257
|
+
totalHandlers,
|
|
1258
|
+
averageHandlersPerKey: totalKeys > 0 ? totalHandlers / totalKeys : 0,
|
|
1259
|
+
queueLength: this.dirtyCarriers.size
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
destroy() {
|
|
1263
|
+
if (this.dequeueFlush) {
|
|
1264
|
+
this.dequeueFlush();
|
|
1265
|
+
this.dequeueFlush = void 0;
|
|
1266
|
+
}
|
|
1267
|
+
this.subscribedCarriers.forEach((carrier) => {
|
|
1268
|
+
carrier.subscribers?.clear();
|
|
1269
|
+
carrier.subscribers = void 0;
|
|
1270
|
+
});
|
|
1271
|
+
this.subscribedCarriers.clear();
|
|
1272
|
+
this.dirtyCarriers.clear();
|
|
1273
|
+
this.isFlushEnqueued = false;
|
|
1274
|
+
}
|
|
1275
|
+
assertNotInFlush() {
|
|
1276
|
+
if (this.queue.isInFlush) {
|
|
1277
|
+
throw new Error(
|
|
1278
|
+
"OIMCarrierKeyedEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
scheduleFlush() {
|
|
1283
|
+
if (this.isFlushEnqueued) return;
|
|
1284
|
+
this.isFlushEnqueued = true;
|
|
1285
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
1286
|
+
}
|
|
1287
|
+
notify(carrier) {
|
|
1288
|
+
const subscribers = carrier.subscribers;
|
|
1289
|
+
if (!subscribers || subscribers.size === 0) return;
|
|
1290
|
+
if (subscribers.size === 1) {
|
|
1291
|
+
const only = subscribers.values().next().value;
|
|
1292
|
+
if (only) only();
|
|
1293
|
+
return;
|
|
1294
|
+
}
|
|
1295
|
+
const snapshot = [];
|
|
1296
|
+
subscribers.forEach((h) => snapshot.push(h));
|
|
1297
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
1298
|
+
const handler = snapshot[i];
|
|
1299
|
+
if (subscribers.has(handler)) handler();
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
1303
|
+
|
|
1087
1304
|
// src/core/OIMReactiveCollection.ts
|
|
1088
1305
|
var OIMReactiveCollection = class extends OIMCollection {
|
|
1089
1306
|
constructor(queue, opts) {
|
|
@@ -1103,7 +1320,10 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1103
1320
|
for (let i = 0; i < snapshot.length; i++) snapshot[i](pks);
|
|
1104
1321
|
};
|
|
1105
1322
|
this.queue = queue;
|
|
1106
|
-
this.updateEmitter = new
|
|
1323
|
+
this.updateEmitter = new OIMCarrierKeyedEmitter(queue, {
|
|
1324
|
+
getOrReserveCarrier: (pk) => this.store.getOrReserveSlotByPk(pk),
|
|
1325
|
+
findCarrier: (pk) => this.store.findSlotByPk(pk)
|
|
1326
|
+
});
|
|
1107
1327
|
}
|
|
1108
1328
|
subscribeOnKey(pk, handler) {
|
|
1109
1329
|
return this.updateEmitter.subscribeOnKey(pk, handler);
|
|
@@ -1135,17 +1355,31 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1135
1355
|
this.anyUpdateHandlers.delete(handler);
|
|
1136
1356
|
};
|
|
1137
1357
|
}
|
|
1358
|
+
// The legacy `emitter` (EOIMCollectionEventType.UPDATE) coexists with the
|
|
1359
|
+
// keyed `updateEmitter`. Build its payload only when something is actually
|
|
1360
|
+
// subscribed — otherwise every upsert/remove allocates a throwaway
|
|
1361
|
+
// `{ pks }` object (and array) that nobody reads.
|
|
1362
|
+
notifyLegacy(pk) {
|
|
1363
|
+
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1364
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
notifyLegacyMany(pks) {
|
|
1368
|
+
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1369
|
+
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1138
1372
|
upsertOneByPk(pk, entity) {
|
|
1139
1373
|
const slot = this.upsertOneWithoutNotificationsByPk(pk, entity);
|
|
1140
|
-
this.
|
|
1141
|
-
this.updateEmitter.
|
|
1374
|
+
this.notifyLegacy(pk);
|
|
1375
|
+
this.updateEmitter.markUpdatedCarrier(slot);
|
|
1142
1376
|
this.trackAnyUpdatePk(pk);
|
|
1143
1377
|
return slot;
|
|
1144
1378
|
}
|
|
1145
1379
|
upsertOne(entity) {
|
|
1146
1380
|
const slot = this.upsertOneWithoutNotifications(entity);
|
|
1147
|
-
this.
|
|
1148
|
-
this.updateEmitter.
|
|
1381
|
+
this.notifyLegacy(slot.pk);
|
|
1382
|
+
this.updateEmitter.markUpdatedCarrier(slot);
|
|
1149
1383
|
this.trackAnyUpdatePk(slot.pk);
|
|
1150
1384
|
return slot;
|
|
1151
1385
|
}
|
|
@@ -1155,15 +1389,17 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1155
1389
|
(entity) => this.upsertOneWithoutNotifications(entity)
|
|
1156
1390
|
);
|
|
1157
1391
|
const pks = slots.map((slot) => slot.pk);
|
|
1158
|
-
this.
|
|
1159
|
-
|
|
1392
|
+
this.notifyLegacyMany(pks);
|
|
1393
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1394
|
+
this.updateEmitter.markUpdatedCarrier(slots[i]);
|
|
1395
|
+
}
|
|
1160
1396
|
this.trackAnyUpdatePks(pks);
|
|
1161
1397
|
return slots;
|
|
1162
1398
|
}
|
|
1163
1399
|
removeOne(entity) {
|
|
1164
1400
|
const pk = this.selectPk(entity);
|
|
1165
1401
|
this.store.removeOneByPk(pk);
|
|
1166
|
-
this.
|
|
1402
|
+
this.notifyLegacy(pk);
|
|
1167
1403
|
this.updateEmitter.markUpdatedKey(pk);
|
|
1168
1404
|
this.trackAnyUpdatePk(pk);
|
|
1169
1405
|
}
|
|
@@ -1171,26 +1407,28 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1171
1407
|
if (entities.length === 0) return;
|
|
1172
1408
|
const pks = entities.map(this.selectPk);
|
|
1173
1409
|
this.store.removeManyByPks(pks);
|
|
1174
|
-
this.
|
|
1410
|
+
this.notifyLegacyMany(pks);
|
|
1175
1411
|
this.updateEmitter.markUpdatedKeys(pks);
|
|
1176
1412
|
this.trackAnyUpdatePks(pks);
|
|
1177
1413
|
}
|
|
1178
1414
|
removeOneByPk(pk) {
|
|
1179
1415
|
this.store.removeOneByPk(pk);
|
|
1180
|
-
this.
|
|
1416
|
+
this.notifyLegacy(pk);
|
|
1181
1417
|
this.updateEmitter.markUpdatedKey(pk);
|
|
1182
1418
|
this.trackAnyUpdatePk(pk);
|
|
1183
1419
|
}
|
|
1184
1420
|
removeManyByPks(pks) {
|
|
1185
1421
|
if (pks.length === 0) return;
|
|
1186
1422
|
this.store.removeManyByPks(pks);
|
|
1187
|
-
this.
|
|
1423
|
+
this.notifyLegacyMany(pks);
|
|
1188
1424
|
this.updateEmitter.markUpdatedKeys(pks);
|
|
1189
1425
|
this.trackAnyUpdatePks(pks);
|
|
1190
1426
|
}
|
|
1191
1427
|
clear() {
|
|
1192
1428
|
this.store.clear();
|
|
1193
|
-
this.emitter.
|
|
1429
|
+
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1430
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [] });
|
|
1431
|
+
}
|
|
1194
1432
|
this.updateEmitter.markAllUpdated();
|
|
1195
1433
|
this.trackAnyUpdateClear();
|
|
1196
1434
|
}
|
|
@@ -1573,6 +1811,21 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1573
1811
|
this.emitUpdateOne(key);
|
|
1574
1812
|
}
|
|
1575
1813
|
}
|
|
1814
|
+
/**
|
|
1815
|
+
* Appends pre-deduplicated slots to a key's bucket IN PLACE (no copy of the
|
|
1816
|
+
* existing bucket) and emits once. Callers own dedup (so this stays O(added),
|
|
1817
|
+
* not O(bucket)); used by collection-bound indexes for fast `addPks`.
|
|
1818
|
+
*/
|
|
1819
|
+
appendSlots(key, slots) {
|
|
1820
|
+
if (slots.length === 0) return;
|
|
1821
|
+
let bucket = this.store.getOneByKey(key);
|
|
1822
|
+
if (!bucket) {
|
|
1823
|
+
bucket = [];
|
|
1824
|
+
this.store.setOneByKey(key, bucket);
|
|
1825
|
+
}
|
|
1826
|
+
for (let i = 0; i < slots.length; i++) bucket.push(slots[i]);
|
|
1827
|
+
this.emitUpdateOne(key);
|
|
1828
|
+
}
|
|
1576
1829
|
/**
|
|
1577
1830
|
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
1578
1831
|
*/
|
|
@@ -1617,6 +1870,9 @@ var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased
|
|
|
1617
1870
|
setSlots(key, slots) {
|
|
1618
1871
|
this.index.setSlots(key, slots);
|
|
1619
1872
|
}
|
|
1873
|
+
appendSlots(key, slots) {
|
|
1874
|
+
this.index.appendSlots(key, slots);
|
|
1875
|
+
}
|
|
1620
1876
|
clear(key) {
|
|
1621
1877
|
this.index.clear(key);
|
|
1622
1878
|
}
|
|
@@ -1625,28 +1881,31 @@ var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased
|
|
|
1625
1881
|
// src/core/OIMReactiveCollectionIndexManualArrayBased.ts
|
|
1626
1882
|
var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexManualArrayBased {
|
|
1627
1883
|
constructor(queue, opts) {
|
|
1628
|
-
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.
|
|
1884
|
+
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.resolveSlot;
|
|
1629
1885
|
super(queue, {
|
|
1630
1886
|
indexOptions: opts.indexOptions
|
|
1631
1887
|
});
|
|
1888
|
+
// Persistent per-key pk membership for O(1) `addPks` dedup (avoids rebuilding
|
|
1889
|
+
// a Set from the whole bucket on every call). Kept in sync by setSlots/clear.
|
|
1890
|
+
this.pksByKey = /* @__PURE__ */ new Map();
|
|
1632
1891
|
this.resolveSlot = resolveSlot;
|
|
1633
1892
|
}
|
|
1634
1893
|
setPks(key, pks) {
|
|
1635
|
-
|
|
1894
|
+
const pkSet = /* @__PURE__ */ new Set();
|
|
1895
|
+
for (let i = 0; i < pks.length; i++) pkSet.add(pks[i]);
|
|
1896
|
+
this.pksByKey.set(key, pkSet);
|
|
1897
|
+
super.setSlots(key, this.resolveSlots(pks));
|
|
1636
1898
|
}
|
|
1637
1899
|
addPks(key, pks) {
|
|
1638
1900
|
if (pks.length === 0) return;
|
|
1639
|
-
const
|
|
1640
|
-
const
|
|
1641
|
-
const nextSlots = existingSlots.slice();
|
|
1642
|
-
let hasChanges = false;
|
|
1901
|
+
const pkSet = this.membershipOf(key);
|
|
1902
|
+
const newSlots = [];
|
|
1643
1903
|
for (const pk of pks) {
|
|
1644
|
-
if (
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
hasChanges = true;
|
|
1904
|
+
if (pkSet.has(pk)) continue;
|
|
1905
|
+
pkSet.add(pk);
|
|
1906
|
+
newSlots.push(this.resolveRequiredSlot(pk));
|
|
1648
1907
|
}
|
|
1649
|
-
if (
|
|
1908
|
+
if (newSlots.length > 0) this.appendSlots(key, newSlots);
|
|
1650
1909
|
}
|
|
1651
1910
|
removePks(key, pks) {
|
|
1652
1911
|
if (pks.length === 0) return;
|
|
@@ -1656,8 +1915,33 @@ var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexM
|
|
|
1656
1915
|
(slot) => !pksToRemove.has(slot.pk)
|
|
1657
1916
|
);
|
|
1658
1917
|
if (nextSlots.length === existingSlots.length) return;
|
|
1918
|
+
const pkSet = this.pksByKey.get(key);
|
|
1919
|
+
if (pkSet) {
|
|
1920
|
+
for (let i = 0; i < pks.length; i++) pkSet.delete(pks[i]);
|
|
1921
|
+
}
|
|
1659
1922
|
if (nextSlots.length === 0) this.clear(key);
|
|
1660
|
-
else
|
|
1923
|
+
else super.setSlots(key, nextSlots);
|
|
1924
|
+
}
|
|
1925
|
+
clear(key) {
|
|
1926
|
+
if (key === void 0) this.pksByKey.clear();
|
|
1927
|
+
else this.pksByKey.delete(key);
|
|
1928
|
+
super.clear(key);
|
|
1929
|
+
}
|
|
1930
|
+
/**
|
|
1931
|
+
* The membership set for a key, lazily seeded from the current bucket so it
|
|
1932
|
+
* stays correct even if slots were set through a lower-level path.
|
|
1933
|
+
*/
|
|
1934
|
+
membershipOf(key) {
|
|
1935
|
+
let pkSet = this.pksByKey.get(key);
|
|
1936
|
+
if (!pkSet) {
|
|
1937
|
+
pkSet = /* @__PURE__ */ new Set();
|
|
1938
|
+
const existing = this.index.getSlotsByKey(key);
|
|
1939
|
+
for (let i = 0; i < existing.length; i++) {
|
|
1940
|
+
pkSet.add(existing[i].pk);
|
|
1941
|
+
}
|
|
1942
|
+
this.pksByKey.set(key, pkSet);
|
|
1943
|
+
}
|
|
1944
|
+
return pkSet;
|
|
1661
1945
|
}
|
|
1662
1946
|
getEntitiesByKey(key) {
|
|
1663
1947
|
return super.getEntitiesByKey(key);
|
|
@@ -1675,11 +1959,7 @@ var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexM
|
|
|
1675
1959
|
}
|
|
1676
1960
|
resolveRequiredSlot(pk) {
|
|
1677
1961
|
const slot = this.resolveSlot(pk);
|
|
1678
|
-
if (!slot) {
|
|
1679
|
-
throw new Error(
|
|
1680
|
-
`[OIMReactiveCollectionIndexManualArrayBased]: Unable to resolve slot for PK "${String(pk)}".`
|
|
1681
|
-
);
|
|
1682
|
-
}
|
|
1962
|
+
if (!slot) return { pk, item: void 0 };
|
|
1683
1963
|
return slot;
|
|
1684
1964
|
}
|
|
1685
1965
|
};
|
|
@@ -1695,6 +1975,41 @@ var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
|
1695
1975
|
this.emitUpdateOne(key);
|
|
1696
1976
|
}
|
|
1697
1977
|
}
|
|
1978
|
+
/**
|
|
1979
|
+
* Adds slots to a key's bucket IN PLACE (no copy of the existing Set) and
|
|
1980
|
+
* emits once. O(added). Used by collection-bound indexes for fast `addPks`.
|
|
1981
|
+
*/
|
|
1982
|
+
addSlots(key, slots) {
|
|
1983
|
+
if (slots.length === 0) return;
|
|
1984
|
+
let bucket = this.store.getOneByKey(key);
|
|
1985
|
+
if (!bucket) {
|
|
1986
|
+
bucket = /* @__PURE__ */ new Set();
|
|
1987
|
+
this.store.setOneByKey(key, bucket);
|
|
1988
|
+
}
|
|
1989
|
+
let changed = false;
|
|
1990
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1991
|
+
if (!bucket.has(slots[i])) {
|
|
1992
|
+
bucket.add(slots[i]);
|
|
1993
|
+
changed = true;
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
if (changed) this.emitUpdateOne(key);
|
|
1997
|
+
}
|
|
1998
|
+
/**
|
|
1999
|
+
* Removes slots from a key's bucket IN PLACE (O(removed)) and emits once.
|
|
2000
|
+
*/
|
|
2001
|
+
removeSlots(key, slots) {
|
|
2002
|
+
if (slots.length === 0) return;
|
|
2003
|
+
const bucket = this.store.getOneByKey(key);
|
|
2004
|
+
if (!bucket) return;
|
|
2005
|
+
let changed = false;
|
|
2006
|
+
for (let i = 0; i < slots.length; i++) {
|
|
2007
|
+
if (bucket.delete(slots[i])) changed = true;
|
|
2008
|
+
}
|
|
2009
|
+
if (!changed) return;
|
|
2010
|
+
if (bucket.size === 0) this.store.removeOneByKey(key);
|
|
2011
|
+
this.emitUpdateOne(key);
|
|
2012
|
+
}
|
|
1698
2013
|
/**
|
|
1699
2014
|
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
1700
2015
|
*/
|
|
@@ -1739,6 +2054,12 @@ var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
|
1739
2054
|
setSlots(key, slots) {
|
|
1740
2055
|
this.index.setSlots(key, slots);
|
|
1741
2056
|
}
|
|
2057
|
+
addSlots(key, slots) {
|
|
2058
|
+
this.index.addSlots(key, slots);
|
|
2059
|
+
}
|
|
2060
|
+
removeSlots(key, slots) {
|
|
2061
|
+
this.index.removeSlots(key, slots);
|
|
2062
|
+
}
|
|
1742
2063
|
clear(key) {
|
|
1743
2064
|
this.index.clear(key);
|
|
1744
2065
|
}
|
|
@@ -1747,46 +2068,73 @@ var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
|
1747
2068
|
// src/core/OIMReactiveCollectionIndexManualSetBased.ts
|
|
1748
2069
|
var OIMReactiveCollectionIndexManualSetBased = class extends OIMReactiveIndexManualSetBased {
|
|
1749
2070
|
constructor(queue, opts) {
|
|
1750
|
-
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.
|
|
2071
|
+
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.resolveSlot;
|
|
1751
2072
|
super(queue, {
|
|
1752
2073
|
indexOptions: opts.indexOptions
|
|
1753
2074
|
});
|
|
2075
|
+
// Persistent per-key pk → slot map for O(1) add (dedup) and O(1) remove
|
|
2076
|
+
// (slot lookup by pk). Kept in sync by setPks/addPks/removePks/clear.
|
|
2077
|
+
this.slotByPk = /* @__PURE__ */ new Map();
|
|
1754
2078
|
this.resolveSlot = resolveSlot;
|
|
1755
2079
|
}
|
|
1756
2080
|
setPks(key, pks) {
|
|
1757
|
-
|
|
2081
|
+
const map = /* @__PURE__ */ new Map();
|
|
2082
|
+
const slots = [];
|
|
2083
|
+
for (let i = 0; i < pks.length; i++) {
|
|
2084
|
+
const pk = pks[i];
|
|
2085
|
+
const slot = this.resolveRequiredSlot(pk);
|
|
2086
|
+
if (!map.has(pk)) map.set(pk, slot);
|
|
2087
|
+
slots.push(slot);
|
|
2088
|
+
}
|
|
2089
|
+
this.slotByPk.set(key, map);
|
|
2090
|
+
super.setSlots(key, slots);
|
|
1758
2091
|
}
|
|
1759
2092
|
addPks(key, pks) {
|
|
1760
2093
|
if (pks.length === 0) return;
|
|
1761
|
-
const
|
|
1762
|
-
const
|
|
1763
|
-
const nextSlots = new Set(existingSlots);
|
|
1764
|
-
let hasChanges = false;
|
|
2094
|
+
const map = this.membershipOf(key);
|
|
2095
|
+
const newSlots = [];
|
|
1765
2096
|
for (const pk of pks) {
|
|
1766
|
-
if (
|
|
2097
|
+
if (map.has(pk)) continue;
|
|
1767
2098
|
const slot = this.resolveRequiredSlot(pk);
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
hasChanges = true;
|
|
2099
|
+
map.set(pk, slot);
|
|
2100
|
+
newSlots.push(slot);
|
|
1771
2101
|
}
|
|
1772
|
-
if (
|
|
2102
|
+
if (newSlots.length > 0) this.addSlots(key, newSlots);
|
|
1773
2103
|
}
|
|
1774
2104
|
removePks(key, pks) {
|
|
1775
2105
|
if (pks.length === 0) return;
|
|
1776
|
-
const
|
|
1777
|
-
|
|
1778
|
-
const
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
if (
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
nextSlots.add(slot);
|
|
2106
|
+
const map = this.membershipOf(key);
|
|
2107
|
+
if (map.size === 0) return;
|
|
2108
|
+
const removed = [];
|
|
2109
|
+
for (const pk of pks) {
|
|
2110
|
+
const slot = map.get(pk);
|
|
2111
|
+
if (slot) {
|
|
2112
|
+
map.delete(pk);
|
|
2113
|
+
removed.push(slot);
|
|
1785
2114
|
}
|
|
1786
2115
|
}
|
|
1787
|
-
if (
|
|
1788
|
-
if (
|
|
1789
|
-
|
|
2116
|
+
if (removed.length === 0) return;
|
|
2117
|
+
if (map.size === 0) this.slotByPk.delete(key);
|
|
2118
|
+
this.removeSlots(key, removed);
|
|
2119
|
+
}
|
|
2120
|
+
clear(key) {
|
|
2121
|
+
if (key === void 0) this.slotByPk.clear();
|
|
2122
|
+
else this.slotByPk.delete(key);
|
|
2123
|
+
super.clear(key);
|
|
2124
|
+
}
|
|
2125
|
+
/**
|
|
2126
|
+
* The pk→slot map for a key, lazily seeded from the current bucket so it
|
|
2127
|
+
* stays correct even if slots were set through a lower-level path.
|
|
2128
|
+
*/
|
|
2129
|
+
membershipOf(key) {
|
|
2130
|
+
let map = this.slotByPk.get(key);
|
|
2131
|
+
if (!map) {
|
|
2132
|
+
map = /* @__PURE__ */ new Map();
|
|
2133
|
+
const existing = this.index.getSlotsByKey(key);
|
|
2134
|
+
for (const slot of existing) map.set(slot.pk, slot);
|
|
2135
|
+
this.slotByPk.set(key, map);
|
|
2136
|
+
}
|
|
2137
|
+
return map;
|
|
1790
2138
|
}
|
|
1791
2139
|
getEntitiesByKey(key) {
|
|
1792
2140
|
return super.getEntitiesByKey(key);
|
|
@@ -1794,18 +2142,9 @@ var OIMReactiveCollectionIndexManualSetBased = class extends OIMReactiveIndexMan
|
|
|
1794
2142
|
getEntitiesByKeys(keys) {
|
|
1795
2143
|
return super.getEntitiesByKeys(keys);
|
|
1796
2144
|
}
|
|
1797
|
-
resolveSlots(pks) {
|
|
1798
|
-
const slots = /* @__PURE__ */ new Set();
|
|
1799
|
-
for (const pk of pks) slots.add(this.resolveRequiredSlot(pk));
|
|
1800
|
-
return slots;
|
|
1801
|
-
}
|
|
1802
2145
|
resolveRequiredSlot(pk) {
|
|
1803
2146
|
const slot = this.resolveSlot(pk);
|
|
1804
|
-
if (!slot) {
|
|
1805
|
-
throw new Error(
|
|
1806
|
-
`[OIMReactiveCollectionIndexManualSetBased]: Unable to resolve slot for PK "${String(pk)}".`
|
|
1807
|
-
);
|
|
1808
|
-
}
|
|
2147
|
+
if (!slot) return { pk, item: void 0 };
|
|
1809
2148
|
return slot;
|
|
1810
2149
|
}
|
|
1811
2150
|
};
|
|
@@ -1920,17 +2259,56 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1920
2259
|
indexOptions: opts.indexOptions
|
|
1921
2260
|
});
|
|
1922
2261
|
this.keysByPk = /* @__PURE__ */ new Map();
|
|
2262
|
+
// Last known sort value per pk (only when `orderBy` is used), so an update
|
|
2263
|
+
// touching an unrelated field can skip re-sorting when the value is unchanged.
|
|
2264
|
+
this.orderValueByPk = /* @__PURE__ */ new Map();
|
|
1923
2265
|
this.onCollectionUpdate = (pks) => {
|
|
1924
2266
|
if (pks.length === 0) {
|
|
1925
2267
|
this.rebuildFromCollection();
|
|
1926
2268
|
return;
|
|
1927
2269
|
}
|
|
1928
|
-
const
|
|
2270
|
+
const ordered = !!(this.compareEntities || this.orderBy);
|
|
2271
|
+
const keysToSort = ordered ? /* @__PURE__ */ new Set() : null;
|
|
1929
2272
|
for (const pk of pks) {
|
|
1930
|
-
this.
|
|
2273
|
+
const prevKeys = this.keysByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
2274
|
+
const slot = this.collection.getSlotByPk(pk);
|
|
2275
|
+
const entity = slot?.item;
|
|
2276
|
+
const nextKeys = entity === void 0 ? /* @__PURE__ */ new Set() : new Set(this.normalizeKeys(this.selectIndexKeys(entity)));
|
|
2277
|
+
let orderChanged = false;
|
|
2278
|
+
if (this.orderBy) {
|
|
2279
|
+
if (entity === void 0 || nextKeys.size === 0) {
|
|
2280
|
+
this.orderValueByPk.delete(pk);
|
|
2281
|
+
} else {
|
|
2282
|
+
const value = this.orderBy(entity);
|
|
2283
|
+
orderChanged = !this.orderValueByPk.has(pk) || this.orderValueByPk.get(pk) !== value;
|
|
2284
|
+
this.orderValueByPk.set(pk, value);
|
|
2285
|
+
}
|
|
2286
|
+
} else if (this.compareEntities && entity !== void 0) {
|
|
2287
|
+
orderChanged = true;
|
|
2288
|
+
}
|
|
2289
|
+
for (const key of prevKeys) {
|
|
2290
|
+
if (!nextKeys.has(key)) this.removePks(key, [pk]);
|
|
2291
|
+
}
|
|
2292
|
+
if (entity !== void 0) {
|
|
2293
|
+
for (const key of nextKeys) {
|
|
2294
|
+
if (!prevKeys.has(key)) {
|
|
2295
|
+
this.addPks(key, [pk]);
|
|
2296
|
+
keysToSort?.add(key);
|
|
2297
|
+
} else if (orderChanged) {
|
|
2298
|
+
keysToSort?.add(key);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
if (nextKeys.size === 0) this.keysByPk.delete(pk);
|
|
2303
|
+
else this.keysByPk.set(pk, nextKeys);
|
|
1931
2304
|
}
|
|
1932
|
-
|
|
1933
|
-
|
|
2305
|
+
if (keysToSort) {
|
|
2306
|
+
for (const key of keysToSort) {
|
|
2307
|
+
this.setSlots(
|
|
2308
|
+
key,
|
|
2309
|
+
this.sortSlots(this.index.getSlotsByKey(key))
|
|
2310
|
+
);
|
|
2311
|
+
}
|
|
1934
2312
|
}
|
|
1935
2313
|
};
|
|
1936
2314
|
this.collection = collection;
|
|
@@ -1947,6 +2325,7 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1947
2325
|
}
|
|
1948
2326
|
rebuildFromCollection() {
|
|
1949
2327
|
this.keysByPk.clear();
|
|
2328
|
+
this.orderValueByPk.clear();
|
|
1950
2329
|
super.clear();
|
|
1951
2330
|
const slotsByKey = /* @__PURE__ */ new Map();
|
|
1952
2331
|
const slots = this.collection.getAllSlots();
|
|
@@ -1955,6 +2334,9 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1955
2334
|
const keys = this.normalizeKeys(this.selectIndexKeys(slot.item));
|
|
1956
2335
|
if (keys.length === 0) continue;
|
|
1957
2336
|
this.keysByPk.set(slot.pk, new Set(keys));
|
|
2337
|
+
if (this.orderBy) {
|
|
2338
|
+
this.orderValueByPk.set(slot.pk, this.orderBy(slot.item));
|
|
2339
|
+
}
|
|
1958
2340
|
for (const key of keys) {
|
|
1959
2341
|
let slotsForKey = slotsByKey.get(key);
|
|
1960
2342
|
if (!slotsForKey) {
|
|
@@ -1971,6 +2353,7 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1971
2353
|
clear(key) {
|
|
1972
2354
|
if (key === void 0) {
|
|
1973
2355
|
this.keysByPk.clear();
|
|
2356
|
+
this.orderValueByPk.clear();
|
|
1974
2357
|
} else {
|
|
1975
2358
|
for (const keys of this.keysByPk.values()) {
|
|
1976
2359
|
keys.delete(key);
|
|
@@ -1981,37 +2364,11 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1981
2364
|
destroy() {
|
|
1982
2365
|
this.unsubscribeFromCollection();
|
|
1983
2366
|
this.keysByPk.clear();
|
|
2367
|
+
this.orderValueByPk.clear();
|
|
1984
2368
|
super.destroy();
|
|
1985
2369
|
}
|
|
1986
|
-
trackPkKeys(pk, affectedKeys) {
|
|
1987
|
-
const prevKeys = this.keysByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
1988
|
-
for (const key of prevKeys) affectedKeys.add(key);
|
|
1989
|
-
const slot = this.collection.getSlotByPk(pk);
|
|
1990
|
-
const entity = slot?.item;
|
|
1991
|
-
const nextKeys = entity === void 0 ? /* @__PURE__ */ new Set() : new Set(this.normalizeKeys(this.selectIndexKeys(entity)));
|
|
1992
|
-
for (const key of nextKeys) affectedKeys.add(key);
|
|
1993
|
-
if (nextKeys.size === 0) {
|
|
1994
|
-
this.keysByPk.delete(pk);
|
|
1995
|
-
} else {
|
|
1996
|
-
this.keysByPk.set(pk, nextKeys);
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
rebuildKey(key) {
|
|
2000
|
-
const keySlots = [];
|
|
2001
|
-
const slots = this.collection.getAllSlots();
|
|
2002
|
-
for (const slot of slots) {
|
|
2003
|
-
if (slot.item === void 0) continue;
|
|
2004
|
-
const keys = this.keysByPk.get(slot.pk);
|
|
2005
|
-
if (keys?.has(key)) keySlots.push(slot);
|
|
2006
|
-
}
|
|
2007
|
-
if (keySlots.length === 0) {
|
|
2008
|
-
super.clear(key);
|
|
2009
|
-
} else {
|
|
2010
|
-
this.setSlots(key, this.sortSlots(keySlots));
|
|
2011
|
-
}
|
|
2012
|
-
}
|
|
2013
2370
|
sortSlots(slots) {
|
|
2014
|
-
if (!this.compareEntities && !this.orderBy) return slots;
|
|
2371
|
+
if (!this.compareEntities && !this.orderBy) return slots.slice();
|
|
2015
2372
|
return slots.slice().sort((a, b) => {
|
|
2016
2373
|
const aItem = a.item;
|
|
2017
2374
|
const bItem = b.item;
|
|
@@ -2294,6 +2651,11 @@ var OIMComparatorFactory = class {
|
|
|
2294
2651
|
}
|
|
2295
2652
|
};
|
|
2296
2653
|
|
|
2654
|
+
// src/core/createInPlaceEntityUpdater.ts
|
|
2655
|
+
function createInPlaceEntityUpdater() {
|
|
2656
|
+
return (draft, prev) => Object.assign(prev, draft);
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2297
2659
|
// src/core/OIMEventQueue.ts
|
|
2298
2660
|
var OIMEventQueue = class {
|
|
2299
2661
|
constructor(options = {}) {
|
|
@@ -3729,6 +4091,7 @@ var OIMIndexPksByKeysArrayBasedSelector = class extends OIMSelector {
|
|
|
3729
4091
|
EOIMEventQueueSchedulerEventType,
|
|
3730
4092
|
EOIMIndexEventType,
|
|
3731
4093
|
EOIMObjectEventType,
|
|
4094
|
+
OIMCarrierKeyedEmitter,
|
|
3732
4095
|
OIMCollection,
|
|
3733
4096
|
OIMCollectionByPkSelector,
|
|
3734
4097
|
OIMCollectionByPksSelector,
|
|
@@ -3796,6 +4159,7 @@ var OIMIndexPksByKeysArrayBasedSelector = class extends OIMSelector {
|
|
|
3796
4159
|
OIMReactiveIndexSetBased,
|
|
3797
4160
|
OIMReactiveObject,
|
|
3798
4161
|
OIMSelector,
|
|
4162
|
+
createInPlaceEntityUpdater,
|
|
3799
4163
|
createOIMCollectionIndexFactory,
|
|
3800
4164
|
createOIMCollectionKit
|
|
3801
4165
|
});
|