@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.js
CHANGED
|
@@ -177,10 +177,18 @@ var OIMIndex = class {
|
|
|
177
177
|
emitUpdateOne(key) {
|
|
178
178
|
this.emitUpdate([key]);
|
|
179
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* Maps a bucket's slots to entities, preserving positional holes: a slot
|
|
182
|
+
* whose entity is not present yet (reserved by an index ahead of its data)
|
|
183
|
+
* or was removed yields `undefined` at its position rather than being
|
|
184
|
+
* dropped. This keeps the result aligned with `getPksByKey`, so callers can
|
|
185
|
+
* render a per-item loading/placeholder state instead of a silently shorter
|
|
186
|
+
* list.
|
|
187
|
+
*/
|
|
180
188
|
slotsToEntities(slots) {
|
|
181
189
|
const entities = [];
|
|
182
190
|
for (const slot of slots) {
|
|
183
|
-
|
|
191
|
+
entities.push(slot.item);
|
|
184
192
|
}
|
|
185
193
|
return entities;
|
|
186
194
|
}
|
|
@@ -436,12 +444,7 @@ var OIMUpdateEventEmitter = class {
|
|
|
436
444
|
this.updatedKeys.clear();
|
|
437
445
|
return;
|
|
438
446
|
}
|
|
439
|
-
|
|
440
|
-
const snapshot = [];
|
|
441
|
-
handlers.forEach((h) => snapshot.push(h));
|
|
442
|
-
return snapshot;
|
|
443
|
-
};
|
|
444
|
-
this.runSinglePass(makeHandlerSnapshot);
|
|
447
|
+
this.runSinglePass();
|
|
445
448
|
};
|
|
446
449
|
this.onAfterFlush = () => {
|
|
447
450
|
if (!this.isAfterFlushDeliveryScheduled) return;
|
|
@@ -536,18 +539,32 @@ var OIMUpdateEventEmitter = class {
|
|
|
536
539
|
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
537
540
|
}
|
|
538
541
|
deliverImmediate() {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
542
|
+
this.runSinglePass();
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Notifies all handlers for a key. The overwhelmingly common case is a
|
|
546
|
+
* single subscriber per key (one component per pk), handled without any
|
|
547
|
+
* allocation. For multiple subscribers a snapshot is taken so a handler may
|
|
548
|
+
* (un)subscribe during iteration without corrupting the walk.
|
|
549
|
+
*/
|
|
550
|
+
notifyHandlers(handlers) {
|
|
551
|
+
if (handlers.size === 1) {
|
|
552
|
+
const only = handlers.values().next().value;
|
|
553
|
+
if (only) only();
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const snapshot = [];
|
|
557
|
+
handlers.forEach((h) => snapshot.push(h));
|
|
558
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
559
|
+
const handler = snapshot[i];
|
|
560
|
+
if (handlers.has(handler)) handler();
|
|
561
|
+
}
|
|
545
562
|
}
|
|
546
563
|
/**
|
|
547
564
|
* Deliver updated keys and notify handlers once.
|
|
548
565
|
* Re-entrant updates during delivery are forbidden and will throw in markUpdatedKeys().
|
|
549
566
|
*/
|
|
550
|
-
runSinglePass(
|
|
567
|
+
runSinglePass() {
|
|
551
568
|
if (this.updatedKeys.size === 0) return;
|
|
552
569
|
const flushingKeys = this.updatedKeys;
|
|
553
570
|
this.updatedKeys = /* @__PURE__ */ new Set();
|
|
@@ -556,21 +573,13 @@ var OIMUpdateEventEmitter = class {
|
|
|
556
573
|
flushingKeys.forEach((key) => {
|
|
557
574
|
const handlers = this.keyHandlers.get(key);
|
|
558
575
|
if (!handlers || handlers.size === 0) return;
|
|
559
|
-
|
|
560
|
-
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
561
|
-
const handler = handlerSnapshot[i];
|
|
562
|
-
if (handlers.has(handler)) handler();
|
|
563
|
-
}
|
|
576
|
+
this.notifyHandlers(handlers);
|
|
564
577
|
});
|
|
565
578
|
} else {
|
|
566
579
|
this.keyHandlers.forEach((handlers, key) => {
|
|
567
580
|
if (!flushingKeys.has(key)) return;
|
|
568
581
|
if (!handlers || handlers.size === 0) return;
|
|
569
|
-
|
|
570
|
-
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
571
|
-
const handler = handlerSnapshot[i];
|
|
572
|
-
if (handlers.has(handler)) handler();
|
|
573
|
-
}
|
|
582
|
+
this.notifyHandlers(handlers);
|
|
574
583
|
});
|
|
575
584
|
}
|
|
576
585
|
}
|
|
@@ -779,17 +788,39 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
779
788
|
constructor() {
|
|
780
789
|
super(...arguments);
|
|
781
790
|
this.slots = /* @__PURE__ */ new Map();
|
|
791
|
+
// Slots reserved by indexes for PKs whose entity has not arrived yet.
|
|
792
|
+
// They carry `item: undefined` and live apart from `slots` so they do not
|
|
793
|
+
// leak into entity enumeration (getAll/getAllPks/countAll). When the entity
|
|
794
|
+
// is finally written, the reserved slot is promoted into `slots` — keeping
|
|
795
|
+
// the reference that indexes already hold, so it fills in live.
|
|
796
|
+
this.reservedSlots = /* @__PURE__ */ new Map();
|
|
782
797
|
}
|
|
783
798
|
setOneByPk(pk, entity) {
|
|
784
799
|
const slot = this.slots.get(pk);
|
|
785
800
|
if (slot) {
|
|
786
801
|
slot.item = entity;
|
|
787
802
|
return slot;
|
|
788
|
-
} else {
|
|
789
|
-
const nextSlot = { pk, item: entity };
|
|
790
|
-
this.slots.set(pk, nextSlot);
|
|
791
|
-
return nextSlot;
|
|
792
803
|
}
|
|
804
|
+
const reserved = this.reservedSlots.get(pk);
|
|
805
|
+
if (reserved) {
|
|
806
|
+
reserved.item = entity;
|
|
807
|
+
this.reservedSlots.delete(pk);
|
|
808
|
+
this.slots.set(pk, reserved);
|
|
809
|
+
return reserved;
|
|
810
|
+
}
|
|
811
|
+
const nextSlot = { pk, item: entity };
|
|
812
|
+
this.slots.set(pk, nextSlot);
|
|
813
|
+
return nextSlot;
|
|
814
|
+
}
|
|
815
|
+
getOrReserveSlotByPk(pk) {
|
|
816
|
+
const slot = this.slots.get(pk);
|
|
817
|
+
if (slot) return slot;
|
|
818
|
+
let reserved = this.reservedSlots.get(pk);
|
|
819
|
+
if (!reserved) {
|
|
820
|
+
reserved = { pk, item: void 0 };
|
|
821
|
+
this.reservedSlots.set(pk, reserved);
|
|
822
|
+
}
|
|
823
|
+
return reserved;
|
|
793
824
|
}
|
|
794
825
|
setManyByPks(pks, entities) {
|
|
795
826
|
const slots = [];
|
|
@@ -802,6 +833,12 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
802
833
|
getSlotByPk(pk) {
|
|
803
834
|
return this.slots.get(pk);
|
|
804
835
|
}
|
|
836
|
+
findSlotByPk(pk) {
|
|
837
|
+
return this.slots.get(pk) ?? this.reservedSlots.get(pk);
|
|
838
|
+
}
|
|
839
|
+
hasSubscribers(slot) {
|
|
840
|
+
return slot.subscribers !== void 0 && slot.subscribers.size > 0;
|
|
841
|
+
}
|
|
805
842
|
getSlotsByPks(pks) {
|
|
806
843
|
const result = [];
|
|
807
844
|
result.length = pks.length;
|
|
@@ -820,8 +857,21 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
820
857
|
}
|
|
821
858
|
removeOneByPk(pk) {
|
|
822
859
|
const slot = this.slots.get(pk);
|
|
823
|
-
if (slot)
|
|
824
|
-
|
|
860
|
+
if (slot) {
|
|
861
|
+
slot.item = void 0;
|
|
862
|
+
this.slots.delete(pk);
|
|
863
|
+
if (this.hasSubscribers(slot)) {
|
|
864
|
+
this.reservedSlots.set(pk, slot);
|
|
865
|
+
}
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
const reserved = this.reservedSlots.get(pk);
|
|
869
|
+
if (reserved) {
|
|
870
|
+
reserved.item = void 0;
|
|
871
|
+
if (!this.hasSubscribers(reserved)) {
|
|
872
|
+
this.reservedSlots.delete(pk);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
825
875
|
}
|
|
826
876
|
removeManyByPks(pks) {
|
|
827
877
|
for (const pk of pks) {
|
|
@@ -855,16 +905,31 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
855
905
|
return this.slots.size;
|
|
856
906
|
}
|
|
857
907
|
clear() {
|
|
908
|
+
const retained = [];
|
|
858
909
|
for (const slot of this.slots.values()) {
|
|
859
910
|
slot.item = void 0;
|
|
911
|
+
if (this.hasSubscribers(slot)) retained.push(slot);
|
|
860
912
|
}
|
|
861
913
|
this.slots.clear();
|
|
914
|
+
for (const slot of this.reservedSlots.values()) {
|
|
915
|
+
slot.item = void 0;
|
|
916
|
+
if (this.hasSubscribers(slot)) retained.push(slot);
|
|
917
|
+
}
|
|
918
|
+
this.reservedSlots.clear();
|
|
919
|
+
for (const slot of retained) {
|
|
920
|
+
this.reservedSlots.set(slot.pk, slot);
|
|
921
|
+
}
|
|
862
922
|
}
|
|
863
923
|
getAllPks() {
|
|
864
924
|
return Array.from(this.slots.keys());
|
|
865
925
|
}
|
|
866
926
|
destroy() {
|
|
867
927
|
this.clear();
|
|
928
|
+
for (const slot of this.reservedSlots.values()) {
|
|
929
|
+
slot.subscribers?.clear();
|
|
930
|
+
slot.subscribers = void 0;
|
|
931
|
+
}
|
|
932
|
+
this.reservedSlots.clear();
|
|
868
933
|
}
|
|
869
934
|
};
|
|
870
935
|
|
|
@@ -900,6 +965,9 @@ var OIMCollection = class {
|
|
|
900
965
|
getSlotByPk(pk) {
|
|
901
966
|
return this.store.getSlotByPk(pk);
|
|
902
967
|
}
|
|
968
|
+
getOrReserveSlotByPk(pk) {
|
|
969
|
+
return this.store.getOrReserveSlotByPk(pk);
|
|
970
|
+
}
|
|
903
971
|
getSlotsByPks(pks) {
|
|
904
972
|
return this.store.getSlotsByPks(pks);
|
|
905
973
|
}
|
|
@@ -984,6 +1052,153 @@ var OIMCollection = class {
|
|
|
984
1052
|
}
|
|
985
1053
|
};
|
|
986
1054
|
|
|
1055
|
+
// src/core/OIMCarrierKeyedEmitter.ts
|
|
1056
|
+
var OIMCarrierKeyedEmitter = class {
|
|
1057
|
+
constructor(queue, resolver) {
|
|
1058
|
+
// Carriers with at least one subscriber — for markAllUpdated / metrics.
|
|
1059
|
+
this.subscribedCarriers = /* @__PURE__ */ new Set();
|
|
1060
|
+
this.dirtyCarriers = /* @__PURE__ */ new Set();
|
|
1061
|
+
this.isFlushEnqueued = false;
|
|
1062
|
+
this.onFlush = () => {
|
|
1063
|
+
this.isFlushEnqueued = false;
|
|
1064
|
+
this.dequeueFlush = void 0;
|
|
1065
|
+
if (this.dirtyCarriers.size === 0) return;
|
|
1066
|
+
const flushing = this.dirtyCarriers;
|
|
1067
|
+
this.dirtyCarriers = /* @__PURE__ */ new Set();
|
|
1068
|
+
flushing.forEach((carrier) => this.notify(carrier));
|
|
1069
|
+
};
|
|
1070
|
+
this.queue = queue;
|
|
1071
|
+
this.resolver = resolver;
|
|
1072
|
+
}
|
|
1073
|
+
subscribeOnKey(key, handler) {
|
|
1074
|
+
const carrier = this.resolver.getOrReserveCarrier(key);
|
|
1075
|
+
this.addHandler(carrier, handler);
|
|
1076
|
+
return () => this.removeHandler(carrier, handler);
|
|
1077
|
+
}
|
|
1078
|
+
subscribeOnKeys(keys, handler) {
|
|
1079
|
+
const carriers = [];
|
|
1080
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1081
|
+
const carrier = this.resolver.getOrReserveCarrier(keys[i]);
|
|
1082
|
+
this.addHandler(carrier, handler);
|
|
1083
|
+
carriers.push(carrier);
|
|
1084
|
+
}
|
|
1085
|
+
return () => {
|
|
1086
|
+
for (let i = 0; i < carriers.length; i++) {
|
|
1087
|
+
this.removeHandler(carriers[i], handler);
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
unsubscribeFromKey(key, handler) {
|
|
1092
|
+
const carrier = this.resolver.findCarrier(key);
|
|
1093
|
+
if (carrier) this.removeHandler(carrier, handler);
|
|
1094
|
+
}
|
|
1095
|
+
unsubscribeFromKeys(keys, handler) {
|
|
1096
|
+
for (let i = 0; i < keys.length; i++) {
|
|
1097
|
+
this.unsubscribeFromKey(keys[i], handler);
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
addHandler(carrier, handler) {
|
|
1101
|
+
let subscribers = carrier.subscribers;
|
|
1102
|
+
if (!subscribers) {
|
|
1103
|
+
subscribers = /* @__PURE__ */ new Set();
|
|
1104
|
+
carrier.subscribers = subscribers;
|
|
1105
|
+
}
|
|
1106
|
+
subscribers.add(handler);
|
|
1107
|
+
this.subscribedCarriers.add(carrier);
|
|
1108
|
+
}
|
|
1109
|
+
removeHandler(carrier, handler) {
|
|
1110
|
+
const subscribers = carrier.subscribers;
|
|
1111
|
+
if (!subscribers) return;
|
|
1112
|
+
subscribers.delete(handler);
|
|
1113
|
+
if (subscribers.size === 0) {
|
|
1114
|
+
this.subscribedCarriers.delete(carrier);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
/** Fast path: the writer already holds the carrier. */
|
|
1118
|
+
markUpdatedCarrier(carrier) {
|
|
1119
|
+
this.assertNotInFlush();
|
|
1120
|
+
const subscribers = carrier.subscribers;
|
|
1121
|
+
if (!subscribers || subscribers.size === 0) return;
|
|
1122
|
+
this.dirtyCarriers.add(carrier);
|
|
1123
|
+
this.scheduleFlush();
|
|
1124
|
+
}
|
|
1125
|
+
markUpdatedKey(key) {
|
|
1126
|
+
const carrier = this.resolver.findCarrier(key);
|
|
1127
|
+
if (carrier) this.markUpdatedCarrier(carrier);
|
|
1128
|
+
else this.assertNotInFlush();
|
|
1129
|
+
}
|
|
1130
|
+
markUpdatedKeys(keys) {
|
|
1131
|
+
for (let i = 0; i < keys.length; i++) this.markUpdatedKey(keys[i]);
|
|
1132
|
+
}
|
|
1133
|
+
markAllUpdated() {
|
|
1134
|
+
this.assertNotInFlush();
|
|
1135
|
+
if (this.subscribedCarriers.size === 0) return;
|
|
1136
|
+
this.subscribedCarriers.forEach(
|
|
1137
|
+
(carrier) => this.dirtyCarriers.add(carrier)
|
|
1138
|
+
);
|
|
1139
|
+
this.scheduleFlush();
|
|
1140
|
+
}
|
|
1141
|
+
hasSubscriptions() {
|
|
1142
|
+
return this.subscribedCarriers.size > 0;
|
|
1143
|
+
}
|
|
1144
|
+
getHandlerCount(key) {
|
|
1145
|
+
return this.resolver.findCarrier(key)?.subscribers?.size ?? 0;
|
|
1146
|
+
}
|
|
1147
|
+
getMetrics() {
|
|
1148
|
+
let totalHandlers = 0;
|
|
1149
|
+
this.subscribedCarriers.forEach((carrier) => {
|
|
1150
|
+
totalHandlers += carrier.subscribers?.size ?? 0;
|
|
1151
|
+
});
|
|
1152
|
+
const totalKeys = this.subscribedCarriers.size;
|
|
1153
|
+
return {
|
|
1154
|
+
totalKeys,
|
|
1155
|
+
totalHandlers,
|
|
1156
|
+
averageHandlersPerKey: totalKeys > 0 ? totalHandlers / totalKeys : 0,
|
|
1157
|
+
queueLength: this.dirtyCarriers.size
|
|
1158
|
+
};
|
|
1159
|
+
}
|
|
1160
|
+
destroy() {
|
|
1161
|
+
if (this.dequeueFlush) {
|
|
1162
|
+
this.dequeueFlush();
|
|
1163
|
+
this.dequeueFlush = void 0;
|
|
1164
|
+
}
|
|
1165
|
+
this.subscribedCarriers.forEach((carrier) => {
|
|
1166
|
+
carrier.subscribers?.clear();
|
|
1167
|
+
carrier.subscribers = void 0;
|
|
1168
|
+
});
|
|
1169
|
+
this.subscribedCarriers.clear();
|
|
1170
|
+
this.dirtyCarriers.clear();
|
|
1171
|
+
this.isFlushEnqueued = false;
|
|
1172
|
+
}
|
|
1173
|
+
assertNotInFlush() {
|
|
1174
|
+
if (this.queue.isInFlush) {
|
|
1175
|
+
throw new Error(
|
|
1176
|
+
"OIMCarrierKeyedEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
1177
|
+
);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
scheduleFlush() {
|
|
1181
|
+
if (this.isFlushEnqueued) return;
|
|
1182
|
+
this.isFlushEnqueued = true;
|
|
1183
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
1184
|
+
}
|
|
1185
|
+
notify(carrier) {
|
|
1186
|
+
const subscribers = carrier.subscribers;
|
|
1187
|
+
if (!subscribers || subscribers.size === 0) return;
|
|
1188
|
+
if (subscribers.size === 1) {
|
|
1189
|
+
const only = subscribers.values().next().value;
|
|
1190
|
+
if (only) only();
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
const snapshot = [];
|
|
1194
|
+
subscribers.forEach((h) => snapshot.push(h));
|
|
1195
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
1196
|
+
const handler = snapshot[i];
|
|
1197
|
+
if (subscribers.has(handler)) handler();
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
|
|
987
1202
|
// src/core/OIMReactiveCollection.ts
|
|
988
1203
|
var OIMReactiveCollection = class extends OIMCollection {
|
|
989
1204
|
constructor(queue, opts) {
|
|
@@ -1003,7 +1218,10 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1003
1218
|
for (let i = 0; i < snapshot.length; i++) snapshot[i](pks);
|
|
1004
1219
|
};
|
|
1005
1220
|
this.queue = queue;
|
|
1006
|
-
this.updateEmitter = new
|
|
1221
|
+
this.updateEmitter = new OIMCarrierKeyedEmitter(queue, {
|
|
1222
|
+
getOrReserveCarrier: (pk) => this.store.getOrReserveSlotByPk(pk),
|
|
1223
|
+
findCarrier: (pk) => this.store.findSlotByPk(pk)
|
|
1224
|
+
});
|
|
1007
1225
|
}
|
|
1008
1226
|
subscribeOnKey(pk, handler) {
|
|
1009
1227
|
return this.updateEmitter.subscribeOnKey(pk, handler);
|
|
@@ -1035,17 +1253,31 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1035
1253
|
this.anyUpdateHandlers.delete(handler);
|
|
1036
1254
|
};
|
|
1037
1255
|
}
|
|
1256
|
+
// The legacy `emitter` (EOIMCollectionEventType.UPDATE) coexists with the
|
|
1257
|
+
// keyed `updateEmitter`. Build its payload only when something is actually
|
|
1258
|
+
// subscribed — otherwise every upsert/remove allocates a throwaway
|
|
1259
|
+
// `{ pks }` object (and array) that nobody reads.
|
|
1260
|
+
notifyLegacy(pk) {
|
|
1261
|
+
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1262
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
notifyLegacyMany(pks) {
|
|
1266
|
+
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1267
|
+
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1038
1270
|
upsertOneByPk(pk, entity) {
|
|
1039
1271
|
const slot = this.upsertOneWithoutNotificationsByPk(pk, entity);
|
|
1040
|
-
this.
|
|
1041
|
-
this.updateEmitter.
|
|
1272
|
+
this.notifyLegacy(pk);
|
|
1273
|
+
this.updateEmitter.markUpdatedCarrier(slot);
|
|
1042
1274
|
this.trackAnyUpdatePk(pk);
|
|
1043
1275
|
return slot;
|
|
1044
1276
|
}
|
|
1045
1277
|
upsertOne(entity) {
|
|
1046
1278
|
const slot = this.upsertOneWithoutNotifications(entity);
|
|
1047
|
-
this.
|
|
1048
|
-
this.updateEmitter.
|
|
1279
|
+
this.notifyLegacy(slot.pk);
|
|
1280
|
+
this.updateEmitter.markUpdatedCarrier(slot);
|
|
1049
1281
|
this.trackAnyUpdatePk(slot.pk);
|
|
1050
1282
|
return slot;
|
|
1051
1283
|
}
|
|
@@ -1055,15 +1287,17 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1055
1287
|
(entity) => this.upsertOneWithoutNotifications(entity)
|
|
1056
1288
|
);
|
|
1057
1289
|
const pks = slots.map((slot) => slot.pk);
|
|
1058
|
-
this.
|
|
1059
|
-
|
|
1290
|
+
this.notifyLegacyMany(pks);
|
|
1291
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1292
|
+
this.updateEmitter.markUpdatedCarrier(slots[i]);
|
|
1293
|
+
}
|
|
1060
1294
|
this.trackAnyUpdatePks(pks);
|
|
1061
1295
|
return slots;
|
|
1062
1296
|
}
|
|
1063
1297
|
removeOne(entity) {
|
|
1064
1298
|
const pk = this.selectPk(entity);
|
|
1065
1299
|
this.store.removeOneByPk(pk);
|
|
1066
|
-
this.
|
|
1300
|
+
this.notifyLegacy(pk);
|
|
1067
1301
|
this.updateEmitter.markUpdatedKey(pk);
|
|
1068
1302
|
this.trackAnyUpdatePk(pk);
|
|
1069
1303
|
}
|
|
@@ -1071,26 +1305,28 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1071
1305
|
if (entities.length === 0) return;
|
|
1072
1306
|
const pks = entities.map(this.selectPk);
|
|
1073
1307
|
this.store.removeManyByPks(pks);
|
|
1074
|
-
this.
|
|
1308
|
+
this.notifyLegacyMany(pks);
|
|
1075
1309
|
this.updateEmitter.markUpdatedKeys(pks);
|
|
1076
1310
|
this.trackAnyUpdatePks(pks);
|
|
1077
1311
|
}
|
|
1078
1312
|
removeOneByPk(pk) {
|
|
1079
1313
|
this.store.removeOneByPk(pk);
|
|
1080
|
-
this.
|
|
1314
|
+
this.notifyLegacy(pk);
|
|
1081
1315
|
this.updateEmitter.markUpdatedKey(pk);
|
|
1082
1316
|
this.trackAnyUpdatePk(pk);
|
|
1083
1317
|
}
|
|
1084
1318
|
removeManyByPks(pks) {
|
|
1085
1319
|
if (pks.length === 0) return;
|
|
1086
1320
|
this.store.removeManyByPks(pks);
|
|
1087
|
-
this.
|
|
1321
|
+
this.notifyLegacyMany(pks);
|
|
1088
1322
|
this.updateEmitter.markUpdatedKeys(pks);
|
|
1089
1323
|
this.trackAnyUpdatePks(pks);
|
|
1090
1324
|
}
|
|
1091
1325
|
clear() {
|
|
1092
1326
|
this.store.clear();
|
|
1093
|
-
this.emitter.
|
|
1327
|
+
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1328
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [] });
|
|
1329
|
+
}
|
|
1094
1330
|
this.updateEmitter.markAllUpdated();
|
|
1095
1331
|
this.trackAnyUpdateClear();
|
|
1096
1332
|
}
|
|
@@ -1473,6 +1709,21 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1473
1709
|
this.emitUpdateOne(key);
|
|
1474
1710
|
}
|
|
1475
1711
|
}
|
|
1712
|
+
/**
|
|
1713
|
+
* Appends pre-deduplicated slots to a key's bucket IN PLACE (no copy of the
|
|
1714
|
+
* existing bucket) and emits once. Callers own dedup (so this stays O(added),
|
|
1715
|
+
* not O(bucket)); used by collection-bound indexes for fast `addPks`.
|
|
1716
|
+
*/
|
|
1717
|
+
appendSlots(key, slots) {
|
|
1718
|
+
if (slots.length === 0) return;
|
|
1719
|
+
let bucket = this.store.getOneByKey(key);
|
|
1720
|
+
if (!bucket) {
|
|
1721
|
+
bucket = [];
|
|
1722
|
+
this.store.setOneByKey(key, bucket);
|
|
1723
|
+
}
|
|
1724
|
+
for (let i = 0; i < slots.length; i++) bucket.push(slots[i]);
|
|
1725
|
+
this.emitUpdateOne(key);
|
|
1726
|
+
}
|
|
1476
1727
|
/**
|
|
1477
1728
|
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
1478
1729
|
*/
|
|
@@ -1517,6 +1768,9 @@ var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased
|
|
|
1517
1768
|
setSlots(key, slots) {
|
|
1518
1769
|
this.index.setSlots(key, slots);
|
|
1519
1770
|
}
|
|
1771
|
+
appendSlots(key, slots) {
|
|
1772
|
+
this.index.appendSlots(key, slots);
|
|
1773
|
+
}
|
|
1520
1774
|
clear(key) {
|
|
1521
1775
|
this.index.clear(key);
|
|
1522
1776
|
}
|
|
@@ -1525,28 +1779,31 @@ var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased
|
|
|
1525
1779
|
// src/core/OIMReactiveCollectionIndexManualArrayBased.ts
|
|
1526
1780
|
var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexManualArrayBased {
|
|
1527
1781
|
constructor(queue, opts) {
|
|
1528
|
-
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.
|
|
1782
|
+
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.resolveSlot;
|
|
1529
1783
|
super(queue, {
|
|
1530
1784
|
indexOptions: opts.indexOptions
|
|
1531
1785
|
});
|
|
1786
|
+
// Persistent per-key pk membership for O(1) `addPks` dedup (avoids rebuilding
|
|
1787
|
+
// a Set from the whole bucket on every call). Kept in sync by setSlots/clear.
|
|
1788
|
+
this.pksByKey = /* @__PURE__ */ new Map();
|
|
1532
1789
|
this.resolveSlot = resolveSlot;
|
|
1533
1790
|
}
|
|
1534
1791
|
setPks(key, pks) {
|
|
1535
|
-
|
|
1792
|
+
const pkSet = /* @__PURE__ */ new Set();
|
|
1793
|
+
for (let i = 0; i < pks.length; i++) pkSet.add(pks[i]);
|
|
1794
|
+
this.pksByKey.set(key, pkSet);
|
|
1795
|
+
super.setSlots(key, this.resolveSlots(pks));
|
|
1536
1796
|
}
|
|
1537
1797
|
addPks(key, pks) {
|
|
1538
1798
|
if (pks.length === 0) return;
|
|
1539
|
-
const
|
|
1540
|
-
const
|
|
1541
|
-
const nextSlots = existingSlots.slice();
|
|
1542
|
-
let hasChanges = false;
|
|
1799
|
+
const pkSet = this.membershipOf(key);
|
|
1800
|
+
const newSlots = [];
|
|
1543
1801
|
for (const pk of pks) {
|
|
1544
|
-
if (
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
hasChanges = true;
|
|
1802
|
+
if (pkSet.has(pk)) continue;
|
|
1803
|
+
pkSet.add(pk);
|
|
1804
|
+
newSlots.push(this.resolveRequiredSlot(pk));
|
|
1548
1805
|
}
|
|
1549
|
-
if (
|
|
1806
|
+
if (newSlots.length > 0) this.appendSlots(key, newSlots);
|
|
1550
1807
|
}
|
|
1551
1808
|
removePks(key, pks) {
|
|
1552
1809
|
if (pks.length === 0) return;
|
|
@@ -1556,8 +1813,33 @@ var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexM
|
|
|
1556
1813
|
(slot) => !pksToRemove.has(slot.pk)
|
|
1557
1814
|
);
|
|
1558
1815
|
if (nextSlots.length === existingSlots.length) return;
|
|
1816
|
+
const pkSet = this.pksByKey.get(key);
|
|
1817
|
+
if (pkSet) {
|
|
1818
|
+
for (let i = 0; i < pks.length; i++) pkSet.delete(pks[i]);
|
|
1819
|
+
}
|
|
1559
1820
|
if (nextSlots.length === 0) this.clear(key);
|
|
1560
|
-
else
|
|
1821
|
+
else super.setSlots(key, nextSlots);
|
|
1822
|
+
}
|
|
1823
|
+
clear(key) {
|
|
1824
|
+
if (key === void 0) this.pksByKey.clear();
|
|
1825
|
+
else this.pksByKey.delete(key);
|
|
1826
|
+
super.clear(key);
|
|
1827
|
+
}
|
|
1828
|
+
/**
|
|
1829
|
+
* The membership set for a key, lazily seeded from the current bucket so it
|
|
1830
|
+
* stays correct even if slots were set through a lower-level path.
|
|
1831
|
+
*/
|
|
1832
|
+
membershipOf(key) {
|
|
1833
|
+
let pkSet = this.pksByKey.get(key);
|
|
1834
|
+
if (!pkSet) {
|
|
1835
|
+
pkSet = /* @__PURE__ */ new Set();
|
|
1836
|
+
const existing = this.index.getSlotsByKey(key);
|
|
1837
|
+
for (let i = 0; i < existing.length; i++) {
|
|
1838
|
+
pkSet.add(existing[i].pk);
|
|
1839
|
+
}
|
|
1840
|
+
this.pksByKey.set(key, pkSet);
|
|
1841
|
+
}
|
|
1842
|
+
return pkSet;
|
|
1561
1843
|
}
|
|
1562
1844
|
getEntitiesByKey(key) {
|
|
1563
1845
|
return super.getEntitiesByKey(key);
|
|
@@ -1575,11 +1857,7 @@ var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexM
|
|
|
1575
1857
|
}
|
|
1576
1858
|
resolveRequiredSlot(pk) {
|
|
1577
1859
|
const slot = this.resolveSlot(pk);
|
|
1578
|
-
if (!slot) {
|
|
1579
|
-
throw new Error(
|
|
1580
|
-
`[OIMReactiveCollectionIndexManualArrayBased]: Unable to resolve slot for PK "${String(pk)}".`
|
|
1581
|
-
);
|
|
1582
|
-
}
|
|
1860
|
+
if (!slot) return { pk, item: void 0 };
|
|
1583
1861
|
return slot;
|
|
1584
1862
|
}
|
|
1585
1863
|
};
|
|
@@ -1595,6 +1873,41 @@ var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
|
1595
1873
|
this.emitUpdateOne(key);
|
|
1596
1874
|
}
|
|
1597
1875
|
}
|
|
1876
|
+
/**
|
|
1877
|
+
* Adds slots to a key's bucket IN PLACE (no copy of the existing Set) and
|
|
1878
|
+
* emits once. O(added). Used by collection-bound indexes for fast `addPks`.
|
|
1879
|
+
*/
|
|
1880
|
+
addSlots(key, slots) {
|
|
1881
|
+
if (slots.length === 0) return;
|
|
1882
|
+
let bucket = this.store.getOneByKey(key);
|
|
1883
|
+
if (!bucket) {
|
|
1884
|
+
bucket = /* @__PURE__ */ new Set();
|
|
1885
|
+
this.store.setOneByKey(key, bucket);
|
|
1886
|
+
}
|
|
1887
|
+
let changed = false;
|
|
1888
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1889
|
+
if (!bucket.has(slots[i])) {
|
|
1890
|
+
bucket.add(slots[i]);
|
|
1891
|
+
changed = true;
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
if (changed) this.emitUpdateOne(key);
|
|
1895
|
+
}
|
|
1896
|
+
/**
|
|
1897
|
+
* Removes slots from a key's bucket IN PLACE (O(removed)) and emits once.
|
|
1898
|
+
*/
|
|
1899
|
+
removeSlots(key, slots) {
|
|
1900
|
+
if (slots.length === 0) return;
|
|
1901
|
+
const bucket = this.store.getOneByKey(key);
|
|
1902
|
+
if (!bucket) return;
|
|
1903
|
+
let changed = false;
|
|
1904
|
+
for (let i = 0; i < slots.length; i++) {
|
|
1905
|
+
if (bucket.delete(slots[i])) changed = true;
|
|
1906
|
+
}
|
|
1907
|
+
if (!changed) return;
|
|
1908
|
+
if (bucket.size === 0) this.store.removeOneByKey(key);
|
|
1909
|
+
this.emitUpdateOne(key);
|
|
1910
|
+
}
|
|
1598
1911
|
/**
|
|
1599
1912
|
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
1600
1913
|
*/
|
|
@@ -1639,6 +1952,12 @@ var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
|
1639
1952
|
setSlots(key, slots) {
|
|
1640
1953
|
this.index.setSlots(key, slots);
|
|
1641
1954
|
}
|
|
1955
|
+
addSlots(key, slots) {
|
|
1956
|
+
this.index.addSlots(key, slots);
|
|
1957
|
+
}
|
|
1958
|
+
removeSlots(key, slots) {
|
|
1959
|
+
this.index.removeSlots(key, slots);
|
|
1960
|
+
}
|
|
1642
1961
|
clear(key) {
|
|
1643
1962
|
this.index.clear(key);
|
|
1644
1963
|
}
|
|
@@ -1647,46 +1966,73 @@ var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
|
1647
1966
|
// src/core/OIMReactiveCollectionIndexManualSetBased.ts
|
|
1648
1967
|
var OIMReactiveCollectionIndexManualSetBased = class extends OIMReactiveIndexManualSetBased {
|
|
1649
1968
|
constructor(queue, opts) {
|
|
1650
|
-
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.
|
|
1969
|
+
const resolveSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.resolveSlot;
|
|
1651
1970
|
super(queue, {
|
|
1652
1971
|
indexOptions: opts.indexOptions
|
|
1653
1972
|
});
|
|
1973
|
+
// Persistent per-key pk → slot map for O(1) add (dedup) and O(1) remove
|
|
1974
|
+
// (slot lookup by pk). Kept in sync by setPks/addPks/removePks/clear.
|
|
1975
|
+
this.slotByPk = /* @__PURE__ */ new Map();
|
|
1654
1976
|
this.resolveSlot = resolveSlot;
|
|
1655
1977
|
}
|
|
1656
1978
|
setPks(key, pks) {
|
|
1657
|
-
|
|
1979
|
+
const map = /* @__PURE__ */ new Map();
|
|
1980
|
+
const slots = [];
|
|
1981
|
+
for (let i = 0; i < pks.length; i++) {
|
|
1982
|
+
const pk = pks[i];
|
|
1983
|
+
const slot = this.resolveRequiredSlot(pk);
|
|
1984
|
+
if (!map.has(pk)) map.set(pk, slot);
|
|
1985
|
+
slots.push(slot);
|
|
1986
|
+
}
|
|
1987
|
+
this.slotByPk.set(key, map);
|
|
1988
|
+
super.setSlots(key, slots);
|
|
1658
1989
|
}
|
|
1659
1990
|
addPks(key, pks) {
|
|
1660
1991
|
if (pks.length === 0) return;
|
|
1661
|
-
const
|
|
1662
|
-
const
|
|
1663
|
-
const nextSlots = new Set(existingSlots);
|
|
1664
|
-
let hasChanges = false;
|
|
1992
|
+
const map = this.membershipOf(key);
|
|
1993
|
+
const newSlots = [];
|
|
1665
1994
|
for (const pk of pks) {
|
|
1666
|
-
if (
|
|
1995
|
+
if (map.has(pk)) continue;
|
|
1667
1996
|
const slot = this.resolveRequiredSlot(pk);
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
hasChanges = true;
|
|
1997
|
+
map.set(pk, slot);
|
|
1998
|
+
newSlots.push(slot);
|
|
1671
1999
|
}
|
|
1672
|
-
if (
|
|
2000
|
+
if (newSlots.length > 0) this.addSlots(key, newSlots);
|
|
1673
2001
|
}
|
|
1674
2002
|
removePks(key, pks) {
|
|
1675
2003
|
if (pks.length === 0) return;
|
|
1676
|
-
const
|
|
1677
|
-
|
|
1678
|
-
const
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
if (
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
nextSlots.add(slot);
|
|
2004
|
+
const map = this.membershipOf(key);
|
|
2005
|
+
if (map.size === 0) return;
|
|
2006
|
+
const removed = [];
|
|
2007
|
+
for (const pk of pks) {
|
|
2008
|
+
const slot = map.get(pk);
|
|
2009
|
+
if (slot) {
|
|
2010
|
+
map.delete(pk);
|
|
2011
|
+
removed.push(slot);
|
|
1685
2012
|
}
|
|
1686
2013
|
}
|
|
1687
|
-
if (
|
|
1688
|
-
if (
|
|
1689
|
-
|
|
2014
|
+
if (removed.length === 0) return;
|
|
2015
|
+
if (map.size === 0) this.slotByPk.delete(key);
|
|
2016
|
+
this.removeSlots(key, removed);
|
|
2017
|
+
}
|
|
2018
|
+
clear(key) {
|
|
2019
|
+
if (key === void 0) this.slotByPk.clear();
|
|
2020
|
+
else this.slotByPk.delete(key);
|
|
2021
|
+
super.clear(key);
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* The pk→slot map for a key, lazily seeded from the current bucket so it
|
|
2025
|
+
* stays correct even if slots were set through a lower-level path.
|
|
2026
|
+
*/
|
|
2027
|
+
membershipOf(key) {
|
|
2028
|
+
let map = this.slotByPk.get(key);
|
|
2029
|
+
if (!map) {
|
|
2030
|
+
map = /* @__PURE__ */ new Map();
|
|
2031
|
+
const existing = this.index.getSlotsByKey(key);
|
|
2032
|
+
for (const slot of existing) map.set(slot.pk, slot);
|
|
2033
|
+
this.slotByPk.set(key, map);
|
|
2034
|
+
}
|
|
2035
|
+
return map;
|
|
1690
2036
|
}
|
|
1691
2037
|
getEntitiesByKey(key) {
|
|
1692
2038
|
return super.getEntitiesByKey(key);
|
|
@@ -1694,18 +2040,9 @@ var OIMReactiveCollectionIndexManualSetBased = class extends OIMReactiveIndexMan
|
|
|
1694
2040
|
getEntitiesByKeys(keys) {
|
|
1695
2041
|
return super.getEntitiesByKeys(keys);
|
|
1696
2042
|
}
|
|
1697
|
-
resolveSlots(pks) {
|
|
1698
|
-
const slots = /* @__PURE__ */ new Set();
|
|
1699
|
-
for (const pk of pks) slots.add(this.resolveRequiredSlot(pk));
|
|
1700
|
-
return slots;
|
|
1701
|
-
}
|
|
1702
2043
|
resolveRequiredSlot(pk) {
|
|
1703
2044
|
const slot = this.resolveSlot(pk);
|
|
1704
|
-
if (!slot) {
|
|
1705
|
-
throw new Error(
|
|
1706
|
-
`[OIMReactiveCollectionIndexManualSetBased]: Unable to resolve slot for PK "${String(pk)}".`
|
|
1707
|
-
);
|
|
1708
|
-
}
|
|
2045
|
+
if (!slot) return { pk, item: void 0 };
|
|
1709
2046
|
return slot;
|
|
1710
2047
|
}
|
|
1711
2048
|
};
|
|
@@ -1820,17 +2157,56 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1820
2157
|
indexOptions: opts.indexOptions
|
|
1821
2158
|
});
|
|
1822
2159
|
this.keysByPk = /* @__PURE__ */ new Map();
|
|
2160
|
+
// Last known sort value per pk (only when `orderBy` is used), so an update
|
|
2161
|
+
// touching an unrelated field can skip re-sorting when the value is unchanged.
|
|
2162
|
+
this.orderValueByPk = /* @__PURE__ */ new Map();
|
|
1823
2163
|
this.onCollectionUpdate = (pks) => {
|
|
1824
2164
|
if (pks.length === 0) {
|
|
1825
2165
|
this.rebuildFromCollection();
|
|
1826
2166
|
return;
|
|
1827
2167
|
}
|
|
1828
|
-
const
|
|
2168
|
+
const ordered = !!(this.compareEntities || this.orderBy);
|
|
2169
|
+
const keysToSort = ordered ? /* @__PURE__ */ new Set() : null;
|
|
1829
2170
|
for (const pk of pks) {
|
|
1830
|
-
this.
|
|
2171
|
+
const prevKeys = this.keysByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
2172
|
+
const slot = this.collection.getSlotByPk(pk);
|
|
2173
|
+
const entity = slot?.item;
|
|
2174
|
+
const nextKeys = entity === void 0 ? /* @__PURE__ */ new Set() : new Set(this.normalizeKeys(this.selectIndexKeys(entity)));
|
|
2175
|
+
let orderChanged = false;
|
|
2176
|
+
if (this.orderBy) {
|
|
2177
|
+
if (entity === void 0 || nextKeys.size === 0) {
|
|
2178
|
+
this.orderValueByPk.delete(pk);
|
|
2179
|
+
} else {
|
|
2180
|
+
const value = this.orderBy(entity);
|
|
2181
|
+
orderChanged = !this.orderValueByPk.has(pk) || this.orderValueByPk.get(pk) !== value;
|
|
2182
|
+
this.orderValueByPk.set(pk, value);
|
|
2183
|
+
}
|
|
2184
|
+
} else if (this.compareEntities && entity !== void 0) {
|
|
2185
|
+
orderChanged = true;
|
|
2186
|
+
}
|
|
2187
|
+
for (const key of prevKeys) {
|
|
2188
|
+
if (!nextKeys.has(key)) this.removePks(key, [pk]);
|
|
2189
|
+
}
|
|
2190
|
+
if (entity !== void 0) {
|
|
2191
|
+
for (const key of nextKeys) {
|
|
2192
|
+
if (!prevKeys.has(key)) {
|
|
2193
|
+
this.addPks(key, [pk]);
|
|
2194
|
+
keysToSort?.add(key);
|
|
2195
|
+
} else if (orderChanged) {
|
|
2196
|
+
keysToSort?.add(key);
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
if (nextKeys.size === 0) this.keysByPk.delete(pk);
|
|
2201
|
+
else this.keysByPk.set(pk, nextKeys);
|
|
1831
2202
|
}
|
|
1832
|
-
|
|
1833
|
-
|
|
2203
|
+
if (keysToSort) {
|
|
2204
|
+
for (const key of keysToSort) {
|
|
2205
|
+
this.setSlots(
|
|
2206
|
+
key,
|
|
2207
|
+
this.sortSlots(this.index.getSlotsByKey(key))
|
|
2208
|
+
);
|
|
2209
|
+
}
|
|
1834
2210
|
}
|
|
1835
2211
|
};
|
|
1836
2212
|
this.collection = collection;
|
|
@@ -1847,6 +2223,7 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1847
2223
|
}
|
|
1848
2224
|
rebuildFromCollection() {
|
|
1849
2225
|
this.keysByPk.clear();
|
|
2226
|
+
this.orderValueByPk.clear();
|
|
1850
2227
|
super.clear();
|
|
1851
2228
|
const slotsByKey = /* @__PURE__ */ new Map();
|
|
1852
2229
|
const slots = this.collection.getAllSlots();
|
|
@@ -1855,6 +2232,9 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1855
2232
|
const keys = this.normalizeKeys(this.selectIndexKeys(slot.item));
|
|
1856
2233
|
if (keys.length === 0) continue;
|
|
1857
2234
|
this.keysByPk.set(slot.pk, new Set(keys));
|
|
2235
|
+
if (this.orderBy) {
|
|
2236
|
+
this.orderValueByPk.set(slot.pk, this.orderBy(slot.item));
|
|
2237
|
+
}
|
|
1858
2238
|
for (const key of keys) {
|
|
1859
2239
|
let slotsForKey = slotsByKey.get(key);
|
|
1860
2240
|
if (!slotsForKey) {
|
|
@@ -1871,6 +2251,7 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1871
2251
|
clear(key) {
|
|
1872
2252
|
if (key === void 0) {
|
|
1873
2253
|
this.keysByPk.clear();
|
|
2254
|
+
this.orderValueByPk.clear();
|
|
1874
2255
|
} else {
|
|
1875
2256
|
for (const keys of this.keysByPk.values()) {
|
|
1876
2257
|
keys.delete(key);
|
|
@@ -1881,37 +2262,11 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
1881
2262
|
destroy() {
|
|
1882
2263
|
this.unsubscribeFromCollection();
|
|
1883
2264
|
this.keysByPk.clear();
|
|
2265
|
+
this.orderValueByPk.clear();
|
|
1884
2266
|
super.destroy();
|
|
1885
2267
|
}
|
|
1886
|
-
trackPkKeys(pk, affectedKeys) {
|
|
1887
|
-
const prevKeys = this.keysByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
1888
|
-
for (const key of prevKeys) affectedKeys.add(key);
|
|
1889
|
-
const slot = this.collection.getSlotByPk(pk);
|
|
1890
|
-
const entity = slot?.item;
|
|
1891
|
-
const nextKeys = entity === void 0 ? /* @__PURE__ */ new Set() : new Set(this.normalizeKeys(this.selectIndexKeys(entity)));
|
|
1892
|
-
for (const key of nextKeys) affectedKeys.add(key);
|
|
1893
|
-
if (nextKeys.size === 0) {
|
|
1894
|
-
this.keysByPk.delete(pk);
|
|
1895
|
-
} else {
|
|
1896
|
-
this.keysByPk.set(pk, nextKeys);
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
rebuildKey(key) {
|
|
1900
|
-
const keySlots = [];
|
|
1901
|
-
const slots = this.collection.getAllSlots();
|
|
1902
|
-
for (const slot of slots) {
|
|
1903
|
-
if (slot.item === void 0) continue;
|
|
1904
|
-
const keys = this.keysByPk.get(slot.pk);
|
|
1905
|
-
if (keys?.has(key)) keySlots.push(slot);
|
|
1906
|
-
}
|
|
1907
|
-
if (keySlots.length === 0) {
|
|
1908
|
-
super.clear(key);
|
|
1909
|
-
} else {
|
|
1910
|
-
this.setSlots(key, this.sortSlots(keySlots));
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
2268
|
sortSlots(slots) {
|
|
1914
|
-
if (!this.compareEntities && !this.orderBy) return slots;
|
|
2269
|
+
if (!this.compareEntities && !this.orderBy) return slots.slice();
|
|
1915
2270
|
return slots.slice().sort((a, b) => {
|
|
1916
2271
|
const aItem = a.item;
|
|
1917
2272
|
const bItem = b.item;
|
|
@@ -2194,6 +2549,11 @@ var OIMComparatorFactory = class {
|
|
|
2194
2549
|
}
|
|
2195
2550
|
};
|
|
2196
2551
|
|
|
2552
|
+
// src/core/createInPlaceEntityUpdater.ts
|
|
2553
|
+
function createInPlaceEntityUpdater() {
|
|
2554
|
+
return (draft, prev) => Object.assign(prev, draft);
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2197
2557
|
// src/core/OIMEventQueue.ts
|
|
2198
2558
|
var OIMEventQueue = class {
|
|
2199
2559
|
constructor(options = {}) {
|
|
@@ -3628,6 +3988,7 @@ export {
|
|
|
3628
3988
|
EOIMEventQueueSchedulerEventType,
|
|
3629
3989
|
EOIMIndexEventType,
|
|
3630
3990
|
EOIMObjectEventType,
|
|
3991
|
+
OIMCarrierKeyedEmitter,
|
|
3631
3992
|
OIMCollection,
|
|
3632
3993
|
OIMCollectionByPkSelector,
|
|
3633
3994
|
OIMCollectionByPksSelector,
|
|
@@ -3695,6 +4056,7 @@ export {
|
|
|
3695
4056
|
OIMReactiveIndexSetBased,
|
|
3696
4057
|
OIMReactiveObject,
|
|
3697
4058
|
OIMSelector,
|
|
4059
|
+
createInPlaceEntityUpdater,
|
|
3698
4060
|
createOIMCollectionIndexFactory,
|
|
3699
4061
|
createOIMCollectionKit
|
|
3700
4062
|
};
|