@oimdb/core 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +396 -63
- package/dist/index.cjs +1706 -799
- package/dist/index.d.cts +456 -292
- package/dist/index.d.ts +456 -292
- package/dist/index.js +1694 -790
- package/package.json +4 -1
package/dist/index.cjs
CHANGED
|
@@ -22,17 +22,18 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
EOIMCollectionEventType: () => EOIMCollectionEventType,
|
|
24
24
|
EOIMComputedEventType: () => EOIMComputedEventType,
|
|
25
|
-
EOIMEffectPhase: () => EOIMEffectPhase,
|
|
26
25
|
EOIMEventQueueEventType: () => EOIMEventQueueEventType,
|
|
27
26
|
EOIMEventQueueSchedulerEventType: () => EOIMEventQueueSchedulerEventType,
|
|
28
27
|
EOIMIndexEventType: () => EOIMIndexEventType,
|
|
29
28
|
EOIMObjectEventType: () => EOIMObjectEventType,
|
|
30
|
-
EOIMUpdateEventCoalescerEventType: () => EOIMUpdateEventCoalescerEventType,
|
|
31
29
|
OIMCollection: () => OIMCollection,
|
|
30
|
+
OIMCollectionByPkSelector: () => OIMCollectionByPkSelector,
|
|
31
|
+
OIMCollectionByPksSelector: () => OIMCollectionByPksSelector,
|
|
32
32
|
OIMCollectionChangedFieldsWrapper: () => OIMCollectionChangedFieldsWrapper,
|
|
33
33
|
OIMCollectionStore: () => OIMCollectionStore,
|
|
34
34
|
OIMCollectionStoreMapDriven: () => OIMCollectionStoreMapDriven,
|
|
35
35
|
OIMComparatorFactory: () => OIMComparatorFactory,
|
|
36
|
+
OIMComputativeRuntime: () => OIMComputativeRuntime,
|
|
36
37
|
OIMComputed: () => OIMComputed,
|
|
37
38
|
OIMDBSettings: () => OIMDBSettings,
|
|
38
39
|
OIMEffect: () => OIMEffect,
|
|
@@ -41,6 +42,8 @@ __export(index_exports, {
|
|
|
41
42
|
OIMEffectDependencyKeyedCollection: () => OIMEffectDependencyKeyedCollection,
|
|
42
43
|
OIMEffectDependencyKeyedIndex: () => OIMEffectDependencyKeyedIndex,
|
|
43
44
|
OIMEffectDependencyKeyedObject: () => OIMEffectDependencyKeyedObject,
|
|
45
|
+
OIMEntitiesByIndexKeyArrayBasedSelector: () => OIMEntitiesByIndexKeyArrayBasedSelector,
|
|
46
|
+
OIMEntitiesByIndexKeySetBasedSelector: () => OIMEntitiesByIndexKeySetBasedSelector,
|
|
44
47
|
OIMEntityUpdaterFactory: () => OIMEntityUpdaterFactory,
|
|
45
48
|
OIMEventEmitter: () => OIMEventEmitter,
|
|
46
49
|
OIMEventQueue: () => OIMEventQueue,
|
|
@@ -55,6 +58,10 @@ __export(index_exports, {
|
|
|
55
58
|
OIMIndexManualArrayBased: () => OIMIndexManualArrayBased,
|
|
56
59
|
OIMIndexManualOrderedArrayBased: () => OIMIndexManualOrderedArrayBased,
|
|
57
60
|
OIMIndexManualSetBased: () => OIMIndexManualSetBased,
|
|
61
|
+
OIMIndexPksByKeyArrayBasedSelector: () => OIMIndexPksByKeyArrayBasedSelector,
|
|
62
|
+
OIMIndexPksByKeySetBasedSelector: () => OIMIndexPksByKeySetBasedSelector,
|
|
63
|
+
OIMIndexPksByKeysArrayBasedSelector: () => OIMIndexPksByKeysArrayBasedSelector,
|
|
64
|
+
OIMIndexPksByKeysSetBasedSelector: () => OIMIndexPksByKeysSetBasedSelector,
|
|
58
65
|
OIMIndexSetBased: () => OIMIndexSetBased,
|
|
59
66
|
OIMIndexStoreArrayBased: () => OIMIndexStoreArrayBased,
|
|
60
67
|
OIMIndexStoreMapDrivenArrayBased: () => OIMIndexStoreMapDrivenArrayBased,
|
|
@@ -65,6 +72,8 @@ __export(index_exports, {
|
|
|
65
72
|
OIMObjectStore: () => OIMObjectStore,
|
|
66
73
|
OIMObjectStoreMapDriven: () => OIMObjectStoreMapDriven,
|
|
67
74
|
OIMObjectStoreRecordDriven: () => OIMObjectStoreRecordDriven,
|
|
75
|
+
OIMObjectValueByKeySelector: () => OIMObjectValueByKeySelector,
|
|
76
|
+
OIMObjectValuesByKeysSelector: () => OIMObjectValuesByKeysSelector,
|
|
68
77
|
OIMOrderedListIndexCommandStreamWrapper: () => OIMOrderedListIndexCommandStreamWrapper,
|
|
69
78
|
OIMPkSelectorFactory: () => OIMPkSelectorFactory,
|
|
70
79
|
OIMRICollection: () => OIMRICollection,
|
|
@@ -74,13 +83,7 @@ __export(index_exports, {
|
|
|
74
83
|
OIMReactiveIndexManualSetBased: () => OIMReactiveIndexManualSetBased,
|
|
75
84
|
OIMReactiveIndexSetBased: () => OIMReactiveIndexSetBased,
|
|
76
85
|
OIMReactiveObject: () => OIMReactiveObject,
|
|
77
|
-
|
|
78
|
-
OIMUpdateEventCoalescerCollection: () => OIMUpdateEventCoalescerCollection,
|
|
79
|
-
OIMUpdateEventCoalescerComputed: () => OIMUpdateEventCoalescerComputed,
|
|
80
|
-
OIMUpdateEventCoalescerIndex: () => OIMUpdateEventCoalescerIndex,
|
|
81
|
-
OIMUpdateEventCoalescerManual: () => OIMUpdateEventCoalescerManual,
|
|
82
|
-
OIMUpdateEventCoalescerObject: () => OIMUpdateEventCoalescerObject,
|
|
83
|
-
OIMUpdateEventEmitter: () => OIMUpdateEventEmitter
|
|
86
|
+
OIMSelector: () => OIMSelector
|
|
84
87
|
});
|
|
85
88
|
module.exports = __toCommonJS(index_exports);
|
|
86
89
|
|
|
@@ -101,6 +104,11 @@ var OIMEventEmitter = class {
|
|
|
101
104
|
constructor() {
|
|
102
105
|
this.buckets = {};
|
|
103
106
|
}
|
|
107
|
+
hasHandlers(event) {
|
|
108
|
+
const bucket = this.buckets[event];
|
|
109
|
+
if (!bucket) return false;
|
|
110
|
+
return bucket.indexByHandler.size > 0;
|
|
111
|
+
}
|
|
104
112
|
getOrCreateBucket(event) {
|
|
105
113
|
let bucket = this.buckets[event];
|
|
106
114
|
if (!bucket) {
|
|
@@ -231,58 +239,75 @@ var EOIMIndexEventType = /* @__PURE__ */ ((EOIMIndexEventType2) => {
|
|
|
231
239
|
var OIMIndexStoreMapDrivenSetBased = class extends OIMIndexStoreSetBased {
|
|
232
240
|
constructor() {
|
|
233
241
|
super(...arguments);
|
|
234
|
-
this.
|
|
242
|
+
this.slots = /* @__PURE__ */ new Map();
|
|
235
243
|
}
|
|
236
|
-
setOneByKey(key,
|
|
237
|
-
this.
|
|
244
|
+
setOneByKey(key, slots) {
|
|
245
|
+
this.slots.set(key, slots);
|
|
238
246
|
}
|
|
239
247
|
removeOneByKey(key) {
|
|
240
|
-
this.
|
|
248
|
+
this.slots.delete(key);
|
|
241
249
|
}
|
|
242
250
|
removeManyByKeys(keys) {
|
|
243
251
|
for (const key of keys) {
|
|
244
|
-
this.
|
|
252
|
+
this.slots.delete(key);
|
|
245
253
|
}
|
|
246
254
|
}
|
|
247
255
|
getOneByKey(key) {
|
|
248
|
-
return this.
|
|
256
|
+
return this.slots.get(key);
|
|
249
257
|
}
|
|
250
258
|
getManyByKeys(keys) {
|
|
251
259
|
const result = /* @__PURE__ */ new Map();
|
|
252
260
|
for (const key of keys) {
|
|
253
|
-
const
|
|
254
|
-
if (
|
|
255
|
-
result.set(key,
|
|
261
|
+
const slots = this.getOneByKey(key);
|
|
262
|
+
if (slots !== void 0) {
|
|
263
|
+
result.set(key, slots);
|
|
256
264
|
}
|
|
257
265
|
}
|
|
258
266
|
return result;
|
|
259
267
|
}
|
|
260
268
|
getAllKeys() {
|
|
261
|
-
return Array.from(this.
|
|
269
|
+
return Array.from(this.slots.keys());
|
|
262
270
|
}
|
|
263
271
|
getAll() {
|
|
264
|
-
return new Map(this.
|
|
272
|
+
return new Map(this.slots);
|
|
265
273
|
}
|
|
266
274
|
countAll() {
|
|
267
|
-
return this.
|
|
275
|
+
return this.slots.size;
|
|
268
276
|
}
|
|
269
277
|
clear() {
|
|
270
|
-
this.
|
|
278
|
+
this.slots.clear();
|
|
271
279
|
}
|
|
272
280
|
};
|
|
273
281
|
|
|
274
282
|
// src/abstract/OIMIndexSetBased.ts
|
|
275
283
|
var OIMIndexSetBased = class {
|
|
276
284
|
constructor(options = {}) {
|
|
285
|
+
this.fallbackSlots = /* @__PURE__ */ new Map();
|
|
277
286
|
this.emitter = new OIMEventEmitter();
|
|
278
287
|
this.comparePks = options.comparePks;
|
|
279
288
|
this.store = options.store ?? new OIMIndexStoreMapDrivenSetBased();
|
|
289
|
+
this.resolveSlot = options.resolveSlot;
|
|
280
290
|
}
|
|
281
291
|
/**
|
|
282
292
|
* Get primary keys for multiple index keys
|
|
283
293
|
*/
|
|
284
294
|
getPksByKeys(keys) {
|
|
285
|
-
|
|
295
|
+
const result = /* @__PURE__ */ new Map();
|
|
296
|
+
const slotsByKey = this.store.getManyByKeys(keys);
|
|
297
|
+
for (const [key, slots] of slotsByKey) {
|
|
298
|
+
result.set(key, this.slotsToPks(slots));
|
|
299
|
+
}
|
|
300
|
+
return result;
|
|
301
|
+
}
|
|
302
|
+
setSlotResolver(resolveSlot) {
|
|
303
|
+
this.resolveSlot = resolveSlot;
|
|
304
|
+
const allSlots = this.store.getAll();
|
|
305
|
+
for (const [key, slots] of allSlots) {
|
|
306
|
+
this.store.setOneByKey(
|
|
307
|
+
key,
|
|
308
|
+
this.resolveSlots(this.slotsToPks(slots))
|
|
309
|
+
);
|
|
310
|
+
}
|
|
286
311
|
}
|
|
287
312
|
/**
|
|
288
313
|
* @deprecated Use getPksByKey instead
|
|
@@ -295,8 +320,15 @@ var OIMIndexSetBased = class {
|
|
|
295
320
|
* Get primary keys for a specific index key
|
|
296
321
|
*/
|
|
297
322
|
getPksByKey(key) {
|
|
298
|
-
const
|
|
299
|
-
return
|
|
323
|
+
const slotsSet = this.store.getOneByKey(key);
|
|
324
|
+
return slotsSet ? this.slotsToPks(slotsSet) : /* @__PURE__ */ new Set();
|
|
325
|
+
}
|
|
326
|
+
getSlotsByKey(key) {
|
|
327
|
+
const slotsSet = this.store.getOneByKey(key);
|
|
328
|
+
return slotsSet ? slotsSet : /* @__PURE__ */ new Set();
|
|
329
|
+
}
|
|
330
|
+
getSlotsByKeys(keys) {
|
|
331
|
+
return this.store.getManyByKeys(keys);
|
|
300
332
|
}
|
|
301
333
|
/**
|
|
302
334
|
* Check if an index key exists
|
|
@@ -314,8 +346,8 @@ var OIMIndexSetBased = class {
|
|
|
314
346
|
* Get the number of primary keys for a specific index key
|
|
315
347
|
*/
|
|
316
348
|
getKeySize(key) {
|
|
317
|
-
const
|
|
318
|
-
return
|
|
349
|
+
const slotsSet = this.store.getOneByKey(key);
|
|
350
|
+
return slotsSet ? slotsSet.size : 0;
|
|
319
351
|
}
|
|
320
352
|
/**
|
|
321
353
|
* Get total number of index keys
|
|
@@ -337,10 +369,10 @@ var OIMIndexSetBased = class {
|
|
|
337
369
|
let maxBucketSize = 0;
|
|
338
370
|
let minBucketSize = Infinity;
|
|
339
371
|
const allPks = this.store.getAll();
|
|
340
|
-
for (const
|
|
341
|
-
totalPks +=
|
|
342
|
-
maxBucketSize = Math.max(maxBucketSize,
|
|
343
|
-
minBucketSize = Math.min(minBucketSize,
|
|
372
|
+
for (const slotsSet of allPks.values()) {
|
|
373
|
+
totalPks += slotsSet.size;
|
|
374
|
+
maxBucketSize = Math.max(maxBucketSize, slotsSet.size);
|
|
375
|
+
minBucketSize = Math.min(minBucketSize, slotsSet.size);
|
|
344
376
|
}
|
|
345
377
|
return {
|
|
346
378
|
totalKeys: allPks.size,
|
|
@@ -362,92 +394,147 @@ var OIMIndexSetBased = class {
|
|
|
362
394
|
* If comparator is provided and returns true (no changes), skip the update.
|
|
363
395
|
*/
|
|
364
396
|
setPksWithComparison(key, newPks) {
|
|
397
|
+
return this.setSlotsWithComparison(key, this.resolveSlots(newPks));
|
|
398
|
+
}
|
|
399
|
+
setSlotsWithComparison(key, newSlots) {
|
|
365
400
|
if (this.comparePks) {
|
|
366
|
-
const
|
|
367
|
-
if (
|
|
368
|
-
const existingPksArray =
|
|
369
|
-
|
|
401
|
+
const existingSlotsSet = this.store.getOneByKey(key);
|
|
402
|
+
if (existingSlotsSet && existingSlotsSet.size === newSlots.size) {
|
|
403
|
+
const existingPksArray = Array.from(
|
|
404
|
+
this.slotsToPks(existingSlotsSet)
|
|
405
|
+
);
|
|
406
|
+
const newPksArray = Array.from(this.slotsToPks(newSlots));
|
|
370
407
|
if (this.comparePks(existingPksArray, newPksArray)) {
|
|
371
408
|
return false;
|
|
372
409
|
}
|
|
373
|
-
} else if (!
|
|
410
|
+
} else if (!existingSlotsSet && newSlots.size === 0) {
|
|
374
411
|
return false;
|
|
375
412
|
}
|
|
376
413
|
}
|
|
377
|
-
this.store.setOneByKey(key,
|
|
414
|
+
this.store.setOneByKey(key, newSlots);
|
|
378
415
|
return true;
|
|
379
416
|
}
|
|
417
|
+
resolveSlots(pks) {
|
|
418
|
+
const slots = /* @__PURE__ */ new Set();
|
|
419
|
+
for (const pk of pks) slots.add(this.getOrCreateSlot(pk));
|
|
420
|
+
return slots;
|
|
421
|
+
}
|
|
422
|
+
getOrCreateSlot(pk) {
|
|
423
|
+
const resolved = this.resolveSlot?.(pk);
|
|
424
|
+
if (resolved) return resolved;
|
|
425
|
+
let fallback = this.fallbackSlots.get(pk);
|
|
426
|
+
if (!fallback) {
|
|
427
|
+
fallback = { pk, item: void 0 };
|
|
428
|
+
this.fallbackSlots.set(pk, fallback);
|
|
429
|
+
}
|
|
430
|
+
return fallback;
|
|
431
|
+
}
|
|
432
|
+
slotsToPks(slots) {
|
|
433
|
+
const pks = /* @__PURE__ */ new Set();
|
|
434
|
+
for (const slot of slots) pks.add(slot.pk);
|
|
435
|
+
return pks;
|
|
436
|
+
}
|
|
380
437
|
/**
|
|
381
438
|
* Emit update event with changed keys
|
|
382
439
|
*/
|
|
383
440
|
emitUpdate(keys) {
|
|
384
441
|
this.emitter.emit(0 /* UPDATE */, { keys });
|
|
385
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Emit update event for a single key (fast-path override point).
|
|
445
|
+
*/
|
|
446
|
+
emitUpdateOne(key) {
|
|
447
|
+
this.emitUpdate([key]);
|
|
448
|
+
}
|
|
386
449
|
};
|
|
387
450
|
|
|
388
451
|
// src/core/OIMIndexStoreMapDrivenArrayBased.ts
|
|
389
452
|
var OIMIndexStoreMapDrivenArrayBased = class extends OIMIndexStoreArrayBased {
|
|
390
453
|
constructor() {
|
|
391
454
|
super(...arguments);
|
|
392
|
-
this.
|
|
455
|
+
this.slots = /* @__PURE__ */ new Map();
|
|
393
456
|
}
|
|
394
|
-
setOneByKey(key,
|
|
395
|
-
this.
|
|
457
|
+
setOneByKey(key, slots) {
|
|
458
|
+
this.slots.set(key, slots);
|
|
396
459
|
}
|
|
397
460
|
removeOneByKey(key) {
|
|
398
|
-
this.
|
|
461
|
+
this.slots.delete(key);
|
|
399
462
|
}
|
|
400
463
|
removeManyByKeys(keys) {
|
|
401
464
|
for (const key of keys) {
|
|
402
|
-
this.
|
|
465
|
+
this.slots.delete(key);
|
|
403
466
|
}
|
|
404
467
|
}
|
|
405
468
|
getOneByKey(key) {
|
|
406
|
-
return this.
|
|
469
|
+
return this.slots.get(key);
|
|
407
470
|
}
|
|
408
471
|
getManyByKeys(keys) {
|
|
409
472
|
const result = /* @__PURE__ */ new Map();
|
|
410
473
|
for (const key of keys) {
|
|
411
|
-
const
|
|
412
|
-
if (
|
|
413
|
-
result.set(key,
|
|
474
|
+
const slots = this.getOneByKey(key);
|
|
475
|
+
if (slots !== void 0) {
|
|
476
|
+
result.set(key, slots);
|
|
414
477
|
}
|
|
415
478
|
}
|
|
416
479
|
return result;
|
|
417
480
|
}
|
|
418
481
|
getAllKeys() {
|
|
419
|
-
return Array.from(this.
|
|
482
|
+
return Array.from(this.slots.keys());
|
|
420
483
|
}
|
|
421
484
|
getAll() {
|
|
422
|
-
return new Map(this.
|
|
485
|
+
return new Map(this.slots);
|
|
423
486
|
}
|
|
424
487
|
countAll() {
|
|
425
|
-
return this.
|
|
488
|
+
return this.slots.size;
|
|
426
489
|
}
|
|
427
490
|
clear() {
|
|
428
|
-
this.
|
|
491
|
+
this.slots.clear();
|
|
429
492
|
}
|
|
430
493
|
};
|
|
431
494
|
|
|
432
495
|
// src/abstract/OIMIndexArrayBased.ts
|
|
433
496
|
var OIMIndexArrayBased = class {
|
|
434
497
|
constructor(options = {}) {
|
|
498
|
+
this.fallbackSlots = /* @__PURE__ */ new Map();
|
|
435
499
|
this.emitter = new OIMEventEmitter();
|
|
436
500
|
this.comparePks = options.comparePks;
|
|
437
501
|
this.store = options.store ?? new OIMIndexStoreMapDrivenArrayBased();
|
|
502
|
+
this.resolveSlot = options.resolveSlot;
|
|
438
503
|
}
|
|
439
504
|
/**
|
|
440
505
|
* Get primary keys for multiple index keys
|
|
441
506
|
*/
|
|
442
507
|
getPksByKeys(keys) {
|
|
443
|
-
|
|
508
|
+
const result = /* @__PURE__ */ new Map();
|
|
509
|
+
const slotsByKey = this.store.getManyByKeys(keys);
|
|
510
|
+
for (const [key, slots] of slotsByKey) {
|
|
511
|
+
result.set(key, this.slotsToPks(slots));
|
|
512
|
+
}
|
|
513
|
+
return result;
|
|
514
|
+
}
|
|
515
|
+
setSlotResolver(resolveSlot) {
|
|
516
|
+
this.resolveSlot = resolveSlot;
|
|
517
|
+
const allSlots = this.store.getAll();
|
|
518
|
+
for (const [key, slots] of allSlots) {
|
|
519
|
+
this.store.setOneByKey(
|
|
520
|
+
key,
|
|
521
|
+
slots.map((slot) => this.getOrCreateSlot(slot.pk))
|
|
522
|
+
);
|
|
523
|
+
}
|
|
444
524
|
}
|
|
445
525
|
/**
|
|
446
526
|
* Get primary keys for a specific index key
|
|
447
527
|
*/
|
|
448
528
|
getPksByKey(key) {
|
|
449
|
-
const
|
|
450
|
-
return
|
|
529
|
+
const slotsArray = this.store.getOneByKey(key);
|
|
530
|
+
return slotsArray ? this.slotsToPks(slotsArray) : [];
|
|
531
|
+
}
|
|
532
|
+
getSlotsByKey(key) {
|
|
533
|
+
const slotsArray = this.store.getOneByKey(key);
|
|
534
|
+
return slotsArray ? slotsArray : [];
|
|
535
|
+
}
|
|
536
|
+
getSlotsByKeys(keys) {
|
|
537
|
+
return this.store.getManyByKeys(keys);
|
|
451
538
|
}
|
|
452
539
|
/**
|
|
453
540
|
* Check if an index key exists
|
|
@@ -465,8 +552,8 @@ var OIMIndexArrayBased = class {
|
|
|
465
552
|
* Get the number of primary keys for a specific index key
|
|
466
553
|
*/
|
|
467
554
|
getKeySize(key) {
|
|
468
|
-
const
|
|
469
|
-
return
|
|
555
|
+
const slotsArray = this.store.getOneByKey(key);
|
|
556
|
+
return slotsArray ? slotsArray.length : 0;
|
|
470
557
|
}
|
|
471
558
|
/**
|
|
472
559
|
* Get total number of index keys
|
|
@@ -488,10 +575,10 @@ var OIMIndexArrayBased = class {
|
|
|
488
575
|
let maxBucketSize = 0;
|
|
489
576
|
let minBucketSize = Infinity;
|
|
490
577
|
const allPks = this.store.getAll();
|
|
491
|
-
for (const
|
|
492
|
-
totalPks +=
|
|
493
|
-
maxBucketSize = Math.max(maxBucketSize,
|
|
494
|
-
minBucketSize = Math.min(minBucketSize,
|
|
578
|
+
for (const slotsArray of allPks.values()) {
|
|
579
|
+
totalPks += slotsArray.length;
|
|
580
|
+
maxBucketSize = Math.max(maxBucketSize, slotsArray.length);
|
|
581
|
+
minBucketSize = Math.min(minBucketSize, slotsArray.length);
|
|
495
582
|
}
|
|
496
583
|
return {
|
|
497
584
|
totalKeys: allPks.size,
|
|
@@ -513,64 +600,83 @@ var OIMIndexArrayBased = class {
|
|
|
513
600
|
* If comparator is provided and returns true (no changes), skip the update.
|
|
514
601
|
*/
|
|
515
602
|
setPksWithComparison(key, newPks) {
|
|
603
|
+
return this.setSlotsWithComparison(key, this.resolveSlots(newPks));
|
|
604
|
+
}
|
|
605
|
+
setSlotsWithComparison(key, newSlots) {
|
|
516
606
|
if (this.comparePks) {
|
|
517
|
-
const
|
|
518
|
-
if (
|
|
519
|
-
if (this.comparePks(
|
|
607
|
+
const existingSlotsArray = this.store.getOneByKey(key);
|
|
608
|
+
if (existingSlotsArray && existingSlotsArray.length === newSlots.length) {
|
|
609
|
+
if (this.comparePks(
|
|
610
|
+
this.slotsToPks(existingSlotsArray),
|
|
611
|
+
this.slotsToPks(newSlots)
|
|
612
|
+
)) {
|
|
520
613
|
return false;
|
|
521
614
|
}
|
|
522
|
-
} else if (!
|
|
615
|
+
} else if (!existingSlotsArray && newSlots.length === 0) {
|
|
523
616
|
return false;
|
|
524
617
|
}
|
|
525
618
|
}
|
|
526
|
-
this.store.setOneByKey(key,
|
|
619
|
+
this.store.setOneByKey(key, newSlots);
|
|
527
620
|
return true;
|
|
528
621
|
}
|
|
622
|
+
resolveSlots(pks) {
|
|
623
|
+
const slots = [];
|
|
624
|
+
slots.length = pks.length;
|
|
625
|
+
for (let i = 0; i < pks.length; i++) {
|
|
626
|
+
slots[i] = this.getOrCreateSlot(pks[i]);
|
|
627
|
+
}
|
|
628
|
+
return slots;
|
|
629
|
+
}
|
|
630
|
+
getOrCreateSlot(pk) {
|
|
631
|
+
const resolved = this.resolveSlot?.(pk);
|
|
632
|
+
if (resolved) return resolved;
|
|
633
|
+
let fallback = this.fallbackSlots.get(pk);
|
|
634
|
+
if (!fallback) {
|
|
635
|
+
fallback = { pk, item: void 0 };
|
|
636
|
+
this.fallbackSlots.set(pk, fallback);
|
|
637
|
+
}
|
|
638
|
+
return fallback;
|
|
639
|
+
}
|
|
640
|
+
slotsToPks(slots) {
|
|
641
|
+
const pks = [];
|
|
642
|
+
pks.length = slots.length;
|
|
643
|
+
for (let i = 0; i < slots.length; i++) pks[i] = slots[i].pk;
|
|
644
|
+
return pks;
|
|
645
|
+
}
|
|
529
646
|
/**
|
|
530
647
|
* Emit update event with changed keys
|
|
531
648
|
*/
|
|
532
649
|
emitUpdate(keys) {
|
|
533
650
|
this.emitter.emit(0 /* UPDATE */, { keys });
|
|
534
651
|
}
|
|
652
|
+
/**
|
|
653
|
+
* Emit update event for a single key (fast-path override point).
|
|
654
|
+
*/
|
|
655
|
+
emitUpdateOne(key) {
|
|
656
|
+
this.emitUpdate([key]);
|
|
657
|
+
}
|
|
535
658
|
};
|
|
536
659
|
|
|
537
|
-
// src/enum/
|
|
538
|
-
var
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
})(EOIMUpdateEventCoalescerEventType || {});
|
|
660
|
+
// src/enum/EOIMEventQueueEventType.ts
|
|
661
|
+
var EOIMEventQueueEventType = /* @__PURE__ */ ((EOIMEventQueueEventType2) => {
|
|
662
|
+
EOIMEventQueueEventType2[EOIMEventQueueEventType2["AFTER_FLUSH"] = 0] = "AFTER_FLUSH";
|
|
663
|
+
EOIMEventQueueEventType2[EOIMEventQueueEventType2["BEFORE_FLUSH"] = 1] = "BEFORE_FLUSH";
|
|
664
|
+
return EOIMEventQueueEventType2;
|
|
665
|
+
})(EOIMEventQueueEventType || {});
|
|
544
666
|
|
|
545
667
|
// src/core/OIMUpdateEventEmitter.ts
|
|
546
668
|
var OIMUpdateEventEmitter = class {
|
|
547
|
-
constructor(
|
|
548
|
-
this.keyHandlersBeforeFlush = /* @__PURE__ */ new Map();
|
|
669
|
+
constructor(queue, deliveryMode = "queue") {
|
|
549
670
|
this.keyHandlers = /* @__PURE__ */ new Map();
|
|
550
|
-
this.isDestroyed = false;
|
|
551
|
-
this.isDispatching = false;
|
|
552
|
-
this.isInPrePhase = false;
|
|
553
|
-
this.hasPendingDuringPrePhase = false;
|
|
554
671
|
this.isFlushEnqueued = false;
|
|
555
|
-
this.
|
|
556
|
-
|
|
557
|
-
this.hasPendingDuringPrePhase = true;
|
|
558
|
-
return;
|
|
559
|
-
}
|
|
560
|
-
if (this.isFlushEnqueued) return;
|
|
561
|
-
this.isFlushEnqueued = true;
|
|
562
|
-
this.queue.enqueue(this.onFlush);
|
|
563
|
-
};
|
|
672
|
+
this.updatedKeys = /* @__PURE__ */ new Set();
|
|
673
|
+
this.isAfterFlushDeliveryScheduled = false;
|
|
564
674
|
// Stable handler reference to avoid allocating a new closure on every HAS_CHANGES.
|
|
565
675
|
this.onFlush = () => {
|
|
566
676
|
this.isFlushEnqueued = false;
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
this.
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
if (this.keyHandlers.size === 0 && this.keyHandlersBeforeFlush.size === 0) {
|
|
573
|
-
this.coalescer.clearUpdatedKeys();
|
|
677
|
+
this.dequeueFlush = void 0;
|
|
678
|
+
if (this.keyHandlers.size === 0) {
|
|
679
|
+
this.updatedKeys.clear();
|
|
574
680
|
return;
|
|
575
681
|
}
|
|
576
682
|
const makeHandlerSnapshot = (handlers) => {
|
|
@@ -578,95 +684,133 @@ var OIMUpdateEventEmitter = class {
|
|
|
578
684
|
handlers.forEach((h) => snapshot.push(h));
|
|
579
685
|
return snapshot;
|
|
580
686
|
};
|
|
581
|
-
|
|
582
|
-
this.isDispatching = true;
|
|
583
|
-
this.isInPrePhase = true;
|
|
584
|
-
this.hasPendingDuringPrePhase = false;
|
|
585
|
-
const allKeysForNormalPhase = this.runPrePhaseDrain(makeHandlerSnapshot);
|
|
586
|
-
this.isInPrePhase = false;
|
|
587
|
-
this.runHandlersPhase(allKeysForNormalPhase, makeHandlerSnapshot);
|
|
588
|
-
} finally {
|
|
589
|
-
this.isInPrePhase = false;
|
|
590
|
-
this.isDispatching = false;
|
|
591
|
-
}
|
|
687
|
+
this.runSinglePass(makeHandlerSnapshot);
|
|
592
688
|
};
|
|
593
|
-
this.
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
this.
|
|
597
|
-
|
|
598
|
-
this.queue =
|
|
689
|
+
this.onAfterFlush = () => {
|
|
690
|
+
if (!this.isAfterFlushDeliveryScheduled) return;
|
|
691
|
+
this.isAfterFlushDeliveryScheduled = false;
|
|
692
|
+
this.deliverImmediate();
|
|
693
|
+
};
|
|
694
|
+
this.queue = queue;
|
|
695
|
+
this.deliveryMode = deliveryMode;
|
|
696
|
+
if (this.deliveryMode === "after_flush") {
|
|
697
|
+
this.unsubscribeAfterFlushDelivery = this.queue.emitter.on(
|
|
698
|
+
0 /* AFTER_FLUSH */,
|
|
699
|
+
this.onAfterFlush
|
|
700
|
+
);
|
|
701
|
+
}
|
|
599
702
|
}
|
|
600
703
|
/**
|
|
601
|
-
*
|
|
704
|
+
* Mark keys as updated and schedule delivery.
|
|
705
|
+
*
|
|
706
|
+
* If there are no subscriptions, this is a no-op and does not allocate or retain keys.
|
|
602
707
|
*/
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
708
|
+
markUpdatedKeys(keys) {
|
|
709
|
+
if (keys.length === 0) return;
|
|
710
|
+
if (this.deliveryMode === "queue" && this.queue.isInFlush) {
|
|
711
|
+
throw new Error(
|
|
712
|
+
"OIMUpdateEventEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
if (this.keyHandlers.size === 0) return;
|
|
716
|
+
let didAddAny = false;
|
|
717
|
+
for (let i = 0; i < keys.length; i++) {
|
|
718
|
+
const key = keys[i];
|
|
719
|
+
const handlers = this.keyHandlers.get(key);
|
|
720
|
+
if (!handlers || handlers.size === 0) continue;
|
|
721
|
+
this.updatedKeys.add(key);
|
|
722
|
+
didAddAny = true;
|
|
723
|
+
}
|
|
724
|
+
if (!didAddAny) return;
|
|
725
|
+
if (this.deliveryMode === "immediate") {
|
|
726
|
+
this.deliverImmediate();
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
if (this.deliveryMode === "after_flush") {
|
|
730
|
+
this.isAfterFlushDeliveryScheduled = true;
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
if (this.isFlushEnqueued) return;
|
|
734
|
+
this.isFlushEnqueued = true;
|
|
735
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
736
|
+
}
|
|
737
|
+
markUpdatedKey(key) {
|
|
738
|
+
if (this.deliveryMode === "queue" && this.queue.isInFlush) {
|
|
739
|
+
throw new Error(
|
|
740
|
+
"OIMUpdateEventEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
if (this.keyHandlers.size === 0) return;
|
|
744
|
+
const handlers = this.keyHandlers.get(key);
|
|
745
|
+
if (!handlers || handlers.size === 0) return;
|
|
746
|
+
this.updatedKeys.add(key);
|
|
747
|
+
if (this.deliveryMode === "immediate") {
|
|
748
|
+
this.deliverImmediate();
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
if (this.deliveryMode === "after_flush") {
|
|
752
|
+
this.isAfterFlushDeliveryScheduled = true;
|
|
753
|
+
return;
|
|
644
754
|
}
|
|
645
|
-
return
|
|
755
|
+
if (this.isFlushEnqueued) return;
|
|
756
|
+
this.isFlushEnqueued = true;
|
|
757
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
646
758
|
}
|
|
647
|
-
|
|
648
|
-
if (this.
|
|
759
|
+
markAllUpdated() {
|
|
760
|
+
if (this.deliveryMode === "queue" && this.queue.isInFlush) {
|
|
761
|
+
throw new Error(
|
|
762
|
+
"OIMUpdateEventEmitter: updates during queue.flush() are not allowed. Finish all writes before calling queue.flush()."
|
|
763
|
+
);
|
|
764
|
+
}
|
|
765
|
+
if (this.keyHandlers.size === 0) return;
|
|
766
|
+
this.keyHandlers.forEach((_handlers, key) => {
|
|
767
|
+
this.updatedKeys.add(key);
|
|
768
|
+
});
|
|
769
|
+
if (this.deliveryMode === "immediate") {
|
|
770
|
+
this.deliverImmediate();
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
if (this.deliveryMode === "after_flush") {
|
|
774
|
+
this.isAfterFlushDeliveryScheduled = true;
|
|
649
775
|
return;
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
776
|
+
}
|
|
777
|
+
if (this.isFlushEnqueued) return;
|
|
778
|
+
this.isFlushEnqueued = true;
|
|
779
|
+
this.dequeueFlush = this.queue.enqueue(this.onFlush);
|
|
780
|
+
}
|
|
781
|
+
deliverImmediate() {
|
|
782
|
+
const makeHandlerSnapshot = (handlers) => {
|
|
783
|
+
const snapshot = [];
|
|
784
|
+
handlers.forEach((h) => snapshot.push(h));
|
|
785
|
+
return snapshot;
|
|
786
|
+
};
|
|
787
|
+
this.runSinglePass(makeHandlerSnapshot);
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Deliver updated keys and notify handlers once.
|
|
791
|
+
* Re-entrant updates during delivery are forbidden and will throw in markUpdatedKeys().
|
|
792
|
+
*/
|
|
793
|
+
runSinglePass(makeHandlerSnapshot) {
|
|
794
|
+
if (this.updatedKeys.size === 0) return;
|
|
795
|
+
const flushingKeys = this.updatedKeys;
|
|
796
|
+
this.updatedKeys = /* @__PURE__ */ new Set();
|
|
797
|
+
if (this.keyHandlers.size === 0 || flushingKeys.size === 0) return;
|
|
798
|
+
if (flushingKeys.size * 2 < this.keyHandlers.size) {
|
|
799
|
+
flushingKeys.forEach((key) => {
|
|
653
800
|
const handlers = this.keyHandlers.get(key);
|
|
654
801
|
if (!handlers || handlers.size === 0) return;
|
|
655
802
|
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
656
803
|
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
657
|
-
if (this.isDestroyed) return;
|
|
658
804
|
const handler = handlerSnapshot[i];
|
|
659
805
|
if (handlers.has(handler)) handler();
|
|
660
806
|
}
|
|
661
807
|
});
|
|
662
808
|
} else {
|
|
663
809
|
this.keyHandlers.forEach((handlers, key) => {
|
|
664
|
-
if (
|
|
665
|
-
if (!allKeysForNormalPhase.has(key)) return;
|
|
810
|
+
if (!flushingKeys.has(key)) return;
|
|
666
811
|
if (!handlers || handlers.size === 0) return;
|
|
667
812
|
const handlerSnapshot = makeHandlerSnapshot(handlers);
|
|
668
813
|
for (let i = 0; i < handlerSnapshot.length; i++) {
|
|
669
|
-
if (this.isDestroyed) return;
|
|
670
814
|
const handler = handlerSnapshot[i];
|
|
671
815
|
if (handlers.has(handler)) handler();
|
|
672
816
|
}
|
|
@@ -674,14 +818,17 @@ var OIMUpdateEventEmitter = class {
|
|
|
674
818
|
}
|
|
675
819
|
}
|
|
676
820
|
destroy() {
|
|
677
|
-
if (this.
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
821
|
+
if (this.dequeueFlush) {
|
|
822
|
+
this.dequeueFlush();
|
|
823
|
+
this.dequeueFlush = void 0;
|
|
824
|
+
}
|
|
825
|
+
if (this.unsubscribeAfterFlushDelivery) {
|
|
826
|
+
this.unsubscribeAfterFlushDelivery();
|
|
827
|
+
this.unsubscribeAfterFlushDelivery = void 0;
|
|
828
|
+
}
|
|
829
|
+
this.keyHandlers.forEach((handlers) => handlers.clear());
|
|
684
830
|
this.keyHandlers.clear();
|
|
831
|
+
this.updatedKeys.clear();
|
|
685
832
|
}
|
|
686
833
|
/**
|
|
687
834
|
* Get performance metrics for monitoring and debugging
|
|
@@ -702,32 +849,13 @@ var OIMUpdateEventEmitter = class {
|
|
|
702
849
|
* Check if there are any active subscriptions
|
|
703
850
|
*/
|
|
704
851
|
hasSubscriptions() {
|
|
705
|
-
return this.keyHandlers.size > 0
|
|
852
|
+
return this.keyHandlers.size > 0;
|
|
706
853
|
}
|
|
707
854
|
/**
|
|
708
855
|
* Get the number of handlers for a specific key
|
|
709
856
|
*/
|
|
710
857
|
getHandlerCount(key) {
|
|
711
|
-
return
|
|
712
|
-
}
|
|
713
|
-
subscribeOnKeyBeforeFlush(key, handler) {
|
|
714
|
-
let handlers = this.keyHandlersBeforeFlush.get(key);
|
|
715
|
-
if (!handlers) {
|
|
716
|
-
handlers = /* @__PURE__ */ new Set();
|
|
717
|
-
this.keyHandlersBeforeFlush.set(key, handlers);
|
|
718
|
-
}
|
|
719
|
-
handlers.add(handler);
|
|
720
|
-
return () => {
|
|
721
|
-
this.unsubscribeFromKeyBeforeFlush(key, handler);
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
unsubscribeFromKeyBeforeFlush(key, handler) {
|
|
725
|
-
const handlers = this.keyHandlersBeforeFlush.get(key);
|
|
726
|
-
if (!handlers) return;
|
|
727
|
-
handlers.delete(handler);
|
|
728
|
-
if (handlers.size === 0) {
|
|
729
|
-
this.keyHandlersBeforeFlush.delete(key);
|
|
730
|
-
}
|
|
858
|
+
return this.keyHandlers.get(key)?.size ?? 0;
|
|
731
859
|
}
|
|
732
860
|
subscribeOnKey(key, handler) {
|
|
733
861
|
let handlers = this.keyHandlers.get(key);
|
|
@@ -746,6 +874,15 @@ var OIMUpdateEventEmitter = class {
|
|
|
746
874
|
handlers.delete(handler);
|
|
747
875
|
if (handlers.size === 0) {
|
|
748
876
|
this.keyHandlers.delete(key);
|
|
877
|
+
this.updatedKeys.delete(key);
|
|
878
|
+
}
|
|
879
|
+
if (this.keyHandlers.size === 0) {
|
|
880
|
+
this.updatedKeys.clear();
|
|
881
|
+
if (this.dequeueFlush) {
|
|
882
|
+
this.dequeueFlush();
|
|
883
|
+
this.dequeueFlush = void 0;
|
|
884
|
+
}
|
|
885
|
+
this.isFlushEnqueued = false;
|
|
749
886
|
}
|
|
750
887
|
}
|
|
751
888
|
subscribeOnKeys(keys, handler) {
|
|
@@ -767,30 +904,6 @@ var OIMUpdateEventEmitter = class {
|
|
|
767
904
|
}
|
|
768
905
|
};
|
|
769
906
|
}
|
|
770
|
-
subscribeOnKeysBeforeFlush(keys, handler) {
|
|
771
|
-
const subscribedKeys = [];
|
|
772
|
-
for (const key of keys) {
|
|
773
|
-
let handlers = this.keyHandlersBeforeFlush.get(key);
|
|
774
|
-
if (!handlers) {
|
|
775
|
-
handlers = /* @__PURE__ */ new Set();
|
|
776
|
-
this.keyHandlersBeforeFlush.set(key, handlers);
|
|
777
|
-
}
|
|
778
|
-
if (!handlers.has(handler)) {
|
|
779
|
-
handlers.add(handler);
|
|
780
|
-
subscribedKeys.push(key);
|
|
781
|
-
}
|
|
782
|
-
}
|
|
783
|
-
return () => {
|
|
784
|
-
for (const key of subscribedKeys) {
|
|
785
|
-
this.unsubscribeFromKeyBeforeFlush(key, handler);
|
|
786
|
-
}
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
unsubscribeFromKeysBeforeFlush(keys, handler) {
|
|
790
|
-
for (const key of keys) {
|
|
791
|
-
this.unsubscribeFromKeyBeforeFlush(key, handler);
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
907
|
unsubscribeFromKeys(keys, handler) {
|
|
795
908
|
for (const key of keys) {
|
|
796
909
|
this.unsubscribeFromKey(key, handler);
|
|
@@ -798,203 +911,11 @@ var OIMUpdateEventEmitter = class {
|
|
|
798
911
|
}
|
|
799
912
|
};
|
|
800
913
|
|
|
801
|
-
// src/core/OIMIndexManualSetBased.ts
|
|
802
|
-
var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
803
|
-
constructor(options = {}) {
|
|
804
|
-
super(options);
|
|
805
|
-
}
|
|
806
|
-
/**
|
|
807
|
-
* Set primary keys for a specific index key, replacing any existing values.
|
|
808
|
-
* Uses optional comparator to skip updates if PKs haven't actually changed.
|
|
809
|
-
*/
|
|
810
|
-
setPks(key, pks) {
|
|
811
|
-
const hasChanges = this.setPksWithComparison(key, new Set(pks));
|
|
812
|
-
if (hasChanges) {
|
|
813
|
-
this.emitUpdate([key]);
|
|
814
|
-
}
|
|
815
|
-
}
|
|
816
|
-
/**
|
|
817
|
-
* Add primary keys to a specific index key
|
|
818
|
-
*/
|
|
819
|
-
addPks(key, pks) {
|
|
820
|
-
if (pks.length === 0) return;
|
|
821
|
-
let pksSet = this.store.getOneByKey(key);
|
|
822
|
-
if (!pksSet) {
|
|
823
|
-
pksSet = /* @__PURE__ */ new Set();
|
|
824
|
-
this.store.setOneByKey(key, pksSet);
|
|
825
|
-
}
|
|
826
|
-
let hasChanges = false;
|
|
827
|
-
for (const pk of pks) {
|
|
828
|
-
if (!pksSet.has(pk)) {
|
|
829
|
-
pksSet.add(pk);
|
|
830
|
-
hasChanges = true;
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
if (hasChanges) {
|
|
834
|
-
this.store.setOneByKey(key, pksSet);
|
|
835
|
-
this.emitUpdate([key]);
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
/**
|
|
839
|
-
* Remove primary keys from a specific index key
|
|
840
|
-
*/
|
|
841
|
-
removePks(key, pks) {
|
|
842
|
-
if (pks.length === 0) return;
|
|
843
|
-
const pksSet = this.store.getOneByKey(key);
|
|
844
|
-
if (!pksSet) return;
|
|
845
|
-
let hasChanges = false;
|
|
846
|
-
for (const pk of pks) {
|
|
847
|
-
if (pksSet.delete(pk)) {
|
|
848
|
-
hasChanges = true;
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
if (pksSet.size === 0) {
|
|
852
|
-
this.store.removeOneByKey(key);
|
|
853
|
-
hasChanges = true;
|
|
854
|
-
} else if (hasChanges) {
|
|
855
|
-
this.store.setOneByKey(key, pksSet);
|
|
856
|
-
}
|
|
857
|
-
if (hasChanges) {
|
|
858
|
-
this.emitUpdate([key]);
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
/**
|
|
862
|
-
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
863
|
-
*/
|
|
864
|
-
clear(key) {
|
|
865
|
-
if (key === void 0) {
|
|
866
|
-
const allKeys = this.store.getAllKeys();
|
|
867
|
-
if (allKeys.length > 0) {
|
|
868
|
-
this.store.clear();
|
|
869
|
-
this.emitUpdate(allKeys);
|
|
870
|
-
}
|
|
871
|
-
} else {
|
|
872
|
-
if (this.store.getOneByKey(key) !== void 0) {
|
|
873
|
-
this.store.removeOneByKey(key);
|
|
874
|
-
this.emitUpdate([key]);
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
|
-
|
|
880
|
-
// src/const/OIMDBSettings.ts
|
|
881
|
-
var OIMDBSettings = class {
|
|
882
|
-
};
|
|
883
|
-
/**
|
|
884
|
-
* Fixed key used in the manual index to store updated keys set in coalescers.
|
|
885
|
-
* This constant is exported so users can create their own indexes and pass them to coalescers.
|
|
886
|
-
*/
|
|
887
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
888
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY = "__flushingKeys__";
|
|
889
|
-
|
|
890
|
-
// src/core/OIMUpdateEventCoalescer.ts
|
|
891
|
-
var OIMUpdateEventCoalescer = class {
|
|
892
|
-
constructor(index, flushingIndex) {
|
|
893
|
-
this.emitter = new OIMEventEmitter();
|
|
894
|
-
this.hasEmittedChanges = false;
|
|
895
|
-
this.updatedKeysIndex = index ?? new OIMIndexManualSetBased({
|
|
896
|
-
store: new OIMIndexStoreMapDrivenSetBased()
|
|
897
|
-
});
|
|
898
|
-
this.flushingUpdatedKeysIndex = flushingIndex ?? new OIMIndexManualSetBased({
|
|
899
|
-
store: new OIMIndexStoreMapDrivenSetBased()
|
|
900
|
-
});
|
|
901
|
-
if (!this.updatedKeysIndex.hasKey(OIMDBSettings.UPDATED_KEYS_INDEX_KEY)) {
|
|
902
|
-
this.updatedKeysIndex.setPks(
|
|
903
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
904
|
-
[]
|
|
905
|
-
);
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
/**
|
|
909
|
-
* Get the set of keys that have been updated since last clear
|
|
910
|
-
*/
|
|
911
|
-
getUpdatedKeys() {
|
|
912
|
-
return this.updatedKeysIndex.getPksByKey(
|
|
913
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY
|
|
914
|
-
);
|
|
915
|
-
}
|
|
916
|
-
getFlushingUpdatedKeys() {
|
|
917
|
-
return this.flushingUpdatedKeysIndex.getPksByKey(
|
|
918
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY
|
|
919
|
-
);
|
|
920
|
-
}
|
|
921
|
-
markUpdatedKeysAsFlushing() {
|
|
922
|
-
this.flushingUpdatedKeysIndex.setPks(
|
|
923
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY,
|
|
924
|
-
Array.from(this.getUpdatedKeys())
|
|
925
|
-
);
|
|
926
|
-
this.clearUpdatedKeys();
|
|
927
|
-
}
|
|
928
|
-
/**
|
|
929
|
-
* Clear all updated keys and reset the changed state
|
|
930
|
-
*/
|
|
931
|
-
clearUpdatedKeys() {
|
|
932
|
-
this.emitter.emit(
|
|
933
|
-
1 /* BEFORE_FLUSH */,
|
|
934
|
-
void 0
|
|
935
|
-
);
|
|
936
|
-
this.updatedKeysIndex.setPks(OIMDBSettings.UPDATED_KEYS_INDEX_KEY, []);
|
|
937
|
-
this.hasEmittedChanges = false;
|
|
938
|
-
this.emitter.emit(
|
|
939
|
-
2 /* AFTER_FLUSH */,
|
|
940
|
-
void 0
|
|
941
|
-
);
|
|
942
|
-
}
|
|
943
|
-
clearFlushingUpdatedKeys() {
|
|
944
|
-
this.flushingUpdatedKeysIndex.setPks(
|
|
945
|
-
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY,
|
|
946
|
-
[]
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
* Add keys to the updated set and emit HAS_CHANGES event if needed
|
|
951
|
-
*/
|
|
952
|
-
addUpdatedKeys(keys) {
|
|
953
|
-
this.updatedKeysIndex.addPks(
|
|
954
|
-
OIMDBSettings.UPDATED_KEYS_INDEX_KEY,
|
|
955
|
-
keys
|
|
956
|
-
);
|
|
957
|
-
if (!this.hasEmittedChanges) {
|
|
958
|
-
this.hasEmittedChanges = true;
|
|
959
|
-
this.emitter.emit(
|
|
960
|
-
0 /* HAS_CHANGES */,
|
|
961
|
-
void 0
|
|
962
|
-
);
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
};
|
|
966
|
-
|
|
967
|
-
// src/core/OIMUpdateEventCoalescerIndex.ts
|
|
968
|
-
var OIMUpdateEventCoalescerIndex = class extends OIMUpdateEventCoalescer {
|
|
969
|
-
constructor(indexEmitter) {
|
|
970
|
-
super();
|
|
971
|
-
this.indexEmitter = indexEmitter;
|
|
972
|
-
/**
|
|
973
|
-
* When the index is updated, we keep track of the updated keys.
|
|
974
|
-
*/
|
|
975
|
-
this.handleUpdate = (payload) => {
|
|
976
|
-
this.addUpdatedKeys(payload.keys);
|
|
977
|
-
};
|
|
978
|
-
this.indexEmitter.on(0 /* UPDATE */, this.handleUpdate);
|
|
979
|
-
}
|
|
980
|
-
destroy() {
|
|
981
|
-
this.indexEmitter.off(0 /* UPDATE */, this.handleUpdate);
|
|
982
|
-
this.emitter.offAll();
|
|
983
|
-
this.clearUpdatedKeys();
|
|
984
|
-
}
|
|
985
|
-
};
|
|
986
|
-
|
|
987
914
|
// src/abstract/OIMReactiveIndexSetBased.ts
|
|
988
915
|
var OIMReactiveIndexSetBased = class {
|
|
989
|
-
constructor(queue,
|
|
990
|
-
this.
|
|
991
|
-
this.
|
|
992
|
-
this.index.emitter
|
|
993
|
-
);
|
|
994
|
-
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
995
|
-
coalescer: this.coalescer,
|
|
996
|
-
queue
|
|
997
|
-
});
|
|
916
|
+
constructor(queue, createIndex) {
|
|
917
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue);
|
|
918
|
+
this.index = createIndex(this.updateEmitter);
|
|
998
919
|
}
|
|
999
920
|
getPksByKey(key) {
|
|
1000
921
|
return this.index.getPksByKey(key);
|
|
@@ -1002,6 +923,12 @@ var OIMReactiveIndexSetBased = class {
|
|
|
1002
923
|
getPksByKeys(keys) {
|
|
1003
924
|
return this.index.getPksByKeys(keys);
|
|
1004
925
|
}
|
|
926
|
+
getSlotsByKey(key) {
|
|
927
|
+
return this.index.getSlotsByKey(key);
|
|
928
|
+
}
|
|
929
|
+
getSlotsByKeys(keys) {
|
|
930
|
+
return this.index.getSlotsByKeys(keys);
|
|
931
|
+
}
|
|
1005
932
|
hasKey(key) {
|
|
1006
933
|
return this.index.hasKey(key);
|
|
1007
934
|
}
|
|
@@ -1020,24 +947,38 @@ var OIMReactiveIndexSetBased = class {
|
|
|
1020
947
|
getMetrics() {
|
|
1021
948
|
return this.index.getMetrics();
|
|
1022
949
|
}
|
|
1023
|
-
|
|
1024
|
-
this.
|
|
1025
|
-
this.coalescer.destroy();
|
|
1026
|
-
this.index.destroy();
|
|
950
|
+
subscribeOnKey(key, handler) {
|
|
951
|
+
return this.updateEmitter.subscribeOnKey(key, handler);
|
|
1027
952
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
953
|
+
subscribeOnKeys(keys, handler) {
|
|
954
|
+
return this.updateEmitter.subscribeOnKeys(keys, handler);
|
|
955
|
+
}
|
|
956
|
+
unsubscribeFromKey(key, handler) {
|
|
957
|
+
this.updateEmitter.unsubscribeFromKey(key, handler);
|
|
958
|
+
}
|
|
959
|
+
unsubscribeFromKeys(keys, handler) {
|
|
960
|
+
this.updateEmitter.unsubscribeFromKeys(keys, handler);
|
|
961
|
+
}
|
|
962
|
+
hasSubscriptions() {
|
|
963
|
+
return this.updateEmitter.hasSubscriptions();
|
|
964
|
+
}
|
|
965
|
+
getHandlerCount(key) {
|
|
966
|
+
return this.updateEmitter.getHandlerCount(key);
|
|
967
|
+
}
|
|
968
|
+
getSubscriptionMetrics() {
|
|
969
|
+
return this.updateEmitter.getMetrics();
|
|
970
|
+
}
|
|
971
|
+
destroy() {
|
|
972
|
+
this.updateEmitter.destroy();
|
|
973
|
+
this.index.destroy();
|
|
974
|
+
}
|
|
975
|
+
};
|
|
976
|
+
|
|
1030
977
|
// src/abstract/OIMReactiveIndexArrayBased.ts
|
|
1031
978
|
var OIMReactiveIndexArrayBased = class {
|
|
1032
|
-
constructor(queue,
|
|
1033
|
-
this.
|
|
1034
|
-
this.
|
|
1035
|
-
this.index.emitter
|
|
1036
|
-
);
|
|
1037
|
-
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
1038
|
-
coalescer: this.coalescer,
|
|
1039
|
-
queue
|
|
1040
|
-
});
|
|
979
|
+
constructor(queue, createIndex) {
|
|
980
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue);
|
|
981
|
+
this.index = createIndex(this.updateEmitter);
|
|
1041
982
|
}
|
|
1042
983
|
getPksByKey(key) {
|
|
1043
984
|
return this.index.getPksByKey(key);
|
|
@@ -1045,6 +986,12 @@ var OIMReactiveIndexArrayBased = class {
|
|
|
1045
986
|
getPksByKeys(keys) {
|
|
1046
987
|
return this.index.getPksByKeys(keys);
|
|
1047
988
|
}
|
|
989
|
+
getSlotsByKey(key) {
|
|
990
|
+
return this.index.getSlotsByKey(key);
|
|
991
|
+
}
|
|
992
|
+
getSlotsByKeys(keys) {
|
|
993
|
+
return this.index.getSlotsByKeys(keys);
|
|
994
|
+
}
|
|
1048
995
|
hasKey(key) {
|
|
1049
996
|
return this.index.hasKey(key);
|
|
1050
997
|
}
|
|
@@ -1063,9 +1010,29 @@ var OIMReactiveIndexArrayBased = class {
|
|
|
1063
1010
|
getMetrics() {
|
|
1064
1011
|
return this.index.getMetrics();
|
|
1065
1012
|
}
|
|
1013
|
+
subscribeOnKey(key, handler) {
|
|
1014
|
+
return this.updateEmitter.subscribeOnKey(key, handler);
|
|
1015
|
+
}
|
|
1016
|
+
subscribeOnKeys(keys, handler) {
|
|
1017
|
+
return this.updateEmitter.subscribeOnKeys(keys, handler);
|
|
1018
|
+
}
|
|
1019
|
+
unsubscribeFromKey(key, handler) {
|
|
1020
|
+
this.updateEmitter.unsubscribeFromKey(key, handler);
|
|
1021
|
+
}
|
|
1022
|
+
unsubscribeFromKeys(keys, handler) {
|
|
1023
|
+
this.updateEmitter.unsubscribeFromKeys(keys, handler);
|
|
1024
|
+
}
|
|
1025
|
+
hasSubscriptions() {
|
|
1026
|
+
return this.updateEmitter.hasSubscriptions();
|
|
1027
|
+
}
|
|
1028
|
+
getHandlerCount(key) {
|
|
1029
|
+
return this.updateEmitter.getHandlerCount(key);
|
|
1030
|
+
}
|
|
1031
|
+
getSubscriptionMetrics() {
|
|
1032
|
+
return this.updateEmitter.getMetrics();
|
|
1033
|
+
}
|
|
1066
1034
|
destroy() {
|
|
1067
|
-
this.
|
|
1068
|
-
this.coalescer.destroy();
|
|
1035
|
+
this.updateEmitter.destroy();
|
|
1069
1036
|
this.index.destroy();
|
|
1070
1037
|
}
|
|
1071
1038
|
};
|
|
@@ -1085,26 +1052,52 @@ var OIMPkSelectorFactory = class {
|
|
|
1085
1052
|
var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
1086
1053
|
constructor() {
|
|
1087
1054
|
super(...arguments);
|
|
1088
|
-
this.
|
|
1055
|
+
this.slots = /* @__PURE__ */ new Map();
|
|
1089
1056
|
}
|
|
1090
1057
|
setOneByPk(pk, entity) {
|
|
1091
|
-
this.
|
|
1058
|
+
const slot = this.slots.get(pk);
|
|
1059
|
+
if (slot) {
|
|
1060
|
+
slot.item = entity;
|
|
1061
|
+
} else {
|
|
1062
|
+
this.slots.set(pk, { pk, item: entity });
|
|
1063
|
+
}
|
|
1092
1064
|
}
|
|
1093
1065
|
setManyByPks(pks, entities) {
|
|
1094
1066
|
for (let i = 0; i < pks.length; i++) {
|
|
1095
|
-
this.
|
|
1067
|
+
this.setOneByPk(pks[i], entities[i]);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
getSlotByPk(pk) {
|
|
1071
|
+
return this.slots.get(pk);
|
|
1072
|
+
}
|
|
1073
|
+
getSlotsByPks(pks) {
|
|
1074
|
+
const result = [];
|
|
1075
|
+
result.length = pks.length;
|
|
1076
|
+
let writeIndex = 0;
|
|
1077
|
+
for (let i = 0; i < pks.length; i++) {
|
|
1078
|
+
const slot = this.slots.get(pks[i]);
|
|
1079
|
+
if (slot !== void 0) {
|
|
1080
|
+
result[writeIndex++] = slot;
|
|
1081
|
+
}
|
|
1096
1082
|
}
|
|
1083
|
+
result.length = writeIndex;
|
|
1084
|
+
return result;
|
|
1085
|
+
}
|
|
1086
|
+
getAllSlots() {
|
|
1087
|
+
return Array.from(this.slots.values());
|
|
1097
1088
|
}
|
|
1098
1089
|
removeOneByPk(pk) {
|
|
1099
|
-
this.
|
|
1090
|
+
const slot = this.slots.get(pk);
|
|
1091
|
+
if (slot) slot.item = void 0;
|
|
1092
|
+
this.slots.delete(pk);
|
|
1100
1093
|
}
|
|
1101
1094
|
removeManyByPks(pks) {
|
|
1102
1095
|
for (const pk of pks) {
|
|
1103
|
-
this.
|
|
1096
|
+
this.removeOneByPk(pk);
|
|
1104
1097
|
}
|
|
1105
1098
|
}
|
|
1106
1099
|
getOneByPk(pk) {
|
|
1107
|
-
return this.
|
|
1100
|
+
return this.slots.get(pk)?.item;
|
|
1108
1101
|
}
|
|
1109
1102
|
getManyByPks(pks) {
|
|
1110
1103
|
const result = [];
|
|
@@ -1120,16 +1113,23 @@ var OIMCollectionStoreMapDriven = class extends OIMCollectionStore {
|
|
|
1120
1113
|
return result;
|
|
1121
1114
|
}
|
|
1122
1115
|
getAll() {
|
|
1123
|
-
|
|
1116
|
+
const result = [];
|
|
1117
|
+
for (const slot of this.slots.values()) {
|
|
1118
|
+
if (slot.item !== void 0) result.push(slot.item);
|
|
1119
|
+
}
|
|
1120
|
+
return result;
|
|
1124
1121
|
}
|
|
1125
1122
|
countAll() {
|
|
1126
|
-
return this.
|
|
1123
|
+
return this.slots.size;
|
|
1127
1124
|
}
|
|
1128
1125
|
clear() {
|
|
1129
|
-
this.
|
|
1126
|
+
for (const slot of this.slots.values()) {
|
|
1127
|
+
slot.item = void 0;
|
|
1128
|
+
}
|
|
1129
|
+
this.slots.clear();
|
|
1130
1130
|
}
|
|
1131
1131
|
getAllPks() {
|
|
1132
|
-
return Array.from(this.
|
|
1132
|
+
return Array.from(this.slots.keys());
|
|
1133
1133
|
}
|
|
1134
1134
|
destroy() {
|
|
1135
1135
|
this.clear();
|
|
@@ -1165,6 +1165,15 @@ var OIMCollection = class {
|
|
|
1165
1165
|
getManyByPks(pks) {
|
|
1166
1166
|
return this.store.getManyByPks(pks);
|
|
1167
1167
|
}
|
|
1168
|
+
getSlotByPk(pk) {
|
|
1169
|
+
return this.store.getSlotByPk(pk);
|
|
1170
|
+
}
|
|
1171
|
+
getSlotsByPks(pks) {
|
|
1172
|
+
return this.store.getSlotsByPks(pks);
|
|
1173
|
+
}
|
|
1174
|
+
getAllSlots() {
|
|
1175
|
+
return this.store.getAllSlots();
|
|
1176
|
+
}
|
|
1168
1177
|
upsertOneByPk(pk, entity) {
|
|
1169
1178
|
this.upsertOneWithoutNotificationsByPk(pk, entity);
|
|
1170
1179
|
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
@@ -1237,47 +1246,139 @@ var OIMCollection = class {
|
|
|
1237
1246
|
}
|
|
1238
1247
|
};
|
|
1239
1248
|
|
|
1240
|
-
// src/core/OIMUpdateEventCoalescerCollection.ts
|
|
1241
|
-
var OIMUpdateEventCoalescerCollection = class extends OIMUpdateEventCoalescer {
|
|
1242
|
-
constructor(collectionEmitter) {
|
|
1243
|
-
super();
|
|
1244
|
-
this.collectionEmitter = collectionEmitter;
|
|
1245
|
-
/**
|
|
1246
|
-
* When the collection is updated, we keep track of the updated pks.
|
|
1247
|
-
*/
|
|
1248
|
-
this.handleUpdate = (payload) => {
|
|
1249
|
-
this.addUpdatedKeys(payload.pks);
|
|
1250
|
-
};
|
|
1251
|
-
this.collectionEmitter.on(
|
|
1252
|
-
0 /* UPDATE */,
|
|
1253
|
-
this.handleUpdate
|
|
1254
|
-
);
|
|
1255
|
-
}
|
|
1256
|
-
destroy() {
|
|
1257
|
-
this.collectionEmitter.off(
|
|
1258
|
-
0 /* UPDATE */,
|
|
1259
|
-
this.handleUpdate
|
|
1260
|
-
);
|
|
1261
|
-
this.emitter.offAll();
|
|
1262
|
-
this.clearUpdatedKeys();
|
|
1263
|
-
}
|
|
1264
|
-
};
|
|
1265
|
-
|
|
1266
1249
|
// src/core/OIMReactiveCollection.ts
|
|
1267
1250
|
var OIMReactiveCollection = class extends OIMCollection {
|
|
1268
1251
|
constructor(queue, opts) {
|
|
1269
1252
|
super(opts);
|
|
1270
|
-
this.
|
|
1271
|
-
|
|
1253
|
+
this.anyUpdateHandlers = /* @__PURE__ */ new Set();
|
|
1254
|
+
this.pendingAnyUpdatePks = /* @__PURE__ */ new Set();
|
|
1255
|
+
this.isAnyUpdateClearPending = false;
|
|
1256
|
+
this.isAnyUpdateScheduled = false;
|
|
1257
|
+
this.runAnyUpdate = () => {
|
|
1258
|
+
if (!this.isAnyUpdateScheduled) return;
|
|
1259
|
+
this.isAnyUpdateScheduled = false;
|
|
1260
|
+
this.dequeueAnyUpdate = void 0;
|
|
1261
|
+
const pks = this.isAnyUpdateClearPending ? [] : Array.from(this.pendingAnyUpdatePks);
|
|
1262
|
+
this.pendingAnyUpdatePks.clear();
|
|
1263
|
+
this.isAnyUpdateClearPending = false;
|
|
1264
|
+
const snapshot = Array.from(this.anyUpdateHandlers);
|
|
1265
|
+
for (let i = 0; i < snapshot.length; i++) snapshot[i](pks);
|
|
1266
|
+
};
|
|
1267
|
+
this.queue = queue;
|
|
1268
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue, "queue");
|
|
1269
|
+
}
|
|
1270
|
+
subscribeOnKey(pk, handler) {
|
|
1271
|
+
return this.updateEmitter.subscribeOnKey(pk, handler);
|
|
1272
|
+
}
|
|
1273
|
+
subscribeOnKeys(pks, handler) {
|
|
1274
|
+
return this.updateEmitter.subscribeOnKeys(pks, handler);
|
|
1275
|
+
}
|
|
1276
|
+
unsubscribeFromKey(pk, handler) {
|
|
1277
|
+
this.updateEmitter.unsubscribeFromKey(pk, handler);
|
|
1278
|
+
}
|
|
1279
|
+
unsubscribeFromKeys(pks, handler) {
|
|
1280
|
+
this.updateEmitter.unsubscribeFromKeys(pks, handler);
|
|
1281
|
+
}
|
|
1282
|
+
destroySubscriptions() {
|
|
1283
|
+
this.updateEmitter.destroy();
|
|
1284
|
+
}
|
|
1285
|
+
hasSubscriptions() {
|
|
1286
|
+
return this.updateEmitter.hasSubscriptions();
|
|
1287
|
+
}
|
|
1288
|
+
getHandlerCount(pk) {
|
|
1289
|
+
return this.updateEmitter.getHandlerCount(pk);
|
|
1290
|
+
}
|
|
1291
|
+
getMetrics() {
|
|
1292
|
+
return this.updateEmitter.getMetrics();
|
|
1293
|
+
}
|
|
1294
|
+
subscribeOnAnyUpdate(handler) {
|
|
1295
|
+
this.anyUpdateHandlers.add(handler);
|
|
1296
|
+
return () => {
|
|
1297
|
+
this.anyUpdateHandlers.delete(handler);
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
upsertOneByPk(pk, entity) {
|
|
1301
|
+
this.upsertOneWithoutNotificationsByPk(pk, entity);
|
|
1302
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
1303
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1304
|
+
this.trackAnyUpdatePk(pk);
|
|
1305
|
+
}
|
|
1306
|
+
upsertOne(entity) {
|
|
1307
|
+
const pk = this.upsertOneWithoutNotifications(entity);
|
|
1308
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
1309
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1310
|
+
this.trackAnyUpdatePk(pk);
|
|
1311
|
+
}
|
|
1312
|
+
upsertMany(entities) {
|
|
1313
|
+
const pks = entities.map(
|
|
1314
|
+
(entity) => this.upsertOneWithoutNotifications(entity)
|
|
1272
1315
|
);
|
|
1273
|
-
this.
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1316
|
+
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1317
|
+
this.updateEmitter.markUpdatedKeys(pks);
|
|
1318
|
+
this.trackAnyUpdatePks(pks);
|
|
1319
|
+
}
|
|
1320
|
+
removeOne(entity) {
|
|
1321
|
+
const pk = this.selectPk(entity);
|
|
1322
|
+
this.store.removeOneByPk(pk);
|
|
1323
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
1324
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1325
|
+
this.trackAnyUpdatePk(pk);
|
|
1326
|
+
}
|
|
1327
|
+
removeMany(entities) {
|
|
1328
|
+
const pks = entities.map(this.selectPk);
|
|
1329
|
+
this.store.removeManyByPks(pks);
|
|
1330
|
+
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1331
|
+
this.updateEmitter.markUpdatedKeys(pks);
|
|
1332
|
+
this.trackAnyUpdatePks(pks);
|
|
1333
|
+
}
|
|
1334
|
+
removeOneByPk(pk) {
|
|
1335
|
+
this.store.removeOneByPk(pk);
|
|
1336
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
1337
|
+
this.updateEmitter.markUpdatedKey(pk);
|
|
1338
|
+
this.trackAnyUpdatePk(pk);
|
|
1339
|
+
}
|
|
1340
|
+
removeManyByPks(pks) {
|
|
1341
|
+
this.store.removeManyByPks(pks);
|
|
1342
|
+
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1343
|
+
this.updateEmitter.markUpdatedKeys(pks);
|
|
1344
|
+
this.trackAnyUpdatePks(pks);
|
|
1345
|
+
}
|
|
1346
|
+
clear() {
|
|
1347
|
+
this.store.clear();
|
|
1348
|
+
this.emitter.emit(0 /* UPDATE */, { pks: [] });
|
|
1349
|
+
this.updateEmitter.markAllUpdated();
|
|
1350
|
+
this.trackAnyUpdateClear();
|
|
1351
|
+
}
|
|
1352
|
+
trackAnyUpdatePk(pk) {
|
|
1353
|
+
if (this.anyUpdateHandlers.size === 0) return;
|
|
1354
|
+
this.pendingAnyUpdatePks.add(pk);
|
|
1355
|
+
this.ensureAnyUpdateEnqueued();
|
|
1356
|
+
}
|
|
1357
|
+
trackAnyUpdatePks(pks) {
|
|
1358
|
+
if (this.anyUpdateHandlers.size === 0) return;
|
|
1359
|
+
for (let i = 0; i < pks.length; i++)
|
|
1360
|
+
this.pendingAnyUpdatePks.add(pks[i]);
|
|
1361
|
+
this.ensureAnyUpdateEnqueued();
|
|
1362
|
+
}
|
|
1363
|
+
trackAnyUpdateClear() {
|
|
1364
|
+
if (this.anyUpdateHandlers.size === 0) return;
|
|
1365
|
+
this.isAnyUpdateClearPending = true;
|
|
1366
|
+
this.pendingAnyUpdatePks.clear();
|
|
1367
|
+
this.ensureAnyUpdateEnqueued();
|
|
1368
|
+
}
|
|
1369
|
+
ensureAnyUpdateEnqueued() {
|
|
1370
|
+
if (this.isAnyUpdateScheduled) return;
|
|
1371
|
+
this.isAnyUpdateScheduled = true;
|
|
1372
|
+
this.dequeueAnyUpdate = this.queue.enqueue(this.runAnyUpdate);
|
|
1277
1373
|
}
|
|
1278
1374
|
destroy() {
|
|
1279
|
-
this.
|
|
1280
|
-
this.
|
|
1375
|
+
this.updateEmitter.destroy();
|
|
1376
|
+
if (this.dequeueAnyUpdate) {
|
|
1377
|
+
this.dequeueAnyUpdate();
|
|
1378
|
+
this.dequeueAnyUpdate = void 0;
|
|
1379
|
+
}
|
|
1380
|
+
this.anyUpdateHandlers.clear();
|
|
1381
|
+
this.pendingAnyUpdatePks.clear();
|
|
1281
1382
|
super.destroy();
|
|
1282
1383
|
}
|
|
1283
1384
|
};
|
|
@@ -1377,54 +1478,158 @@ var OIMObject = class {
|
|
|
1377
1478
|
}
|
|
1378
1479
|
};
|
|
1379
1480
|
|
|
1380
|
-
// src/core/OIMUpdateEventCoalescerObject.ts
|
|
1381
|
-
var OIMUpdateEventCoalescerObject = class extends OIMUpdateEventCoalescer {
|
|
1382
|
-
constructor(objectEmitter) {
|
|
1383
|
-
super();
|
|
1384
|
-
this.objectEmitter = objectEmitter;
|
|
1385
|
-
/**
|
|
1386
|
-
* When the object is updated, we keep track of the updated keys.
|
|
1387
|
-
*/
|
|
1388
|
-
this.handleUpdate = (payload) => {
|
|
1389
|
-
this.addUpdatedKeys(payload.keys);
|
|
1390
|
-
};
|
|
1391
|
-
this.objectEmitter.on(0 /* UPDATE */, this.handleUpdate);
|
|
1392
|
-
}
|
|
1393
|
-
destroy() {
|
|
1394
|
-
this.objectEmitter.off(0 /* UPDATE */, this.handleUpdate);
|
|
1395
|
-
this.emitter.offAll();
|
|
1396
|
-
this.clearUpdatedKeys();
|
|
1397
|
-
}
|
|
1398
|
-
};
|
|
1399
|
-
|
|
1400
1481
|
// src/core/OIMReactiveObject.ts
|
|
1401
1482
|
var OIMReactiveObject = class extends OIMObject {
|
|
1402
1483
|
constructor(queue, opts) {
|
|
1403
1484
|
super(opts);
|
|
1404
|
-
this.
|
|
1405
|
-
this.
|
|
1406
|
-
|
|
1407
|
-
queue
|
|
1485
|
+
this.updateEmitter = new OIMUpdateEventEmitter(queue, "queue");
|
|
1486
|
+
this.emitter.on(0 /* UPDATE */, (payload) => {
|
|
1487
|
+
this.updateEmitter.markUpdatedKeys(payload.keys);
|
|
1408
1488
|
});
|
|
1409
1489
|
}
|
|
1490
|
+
subscribeOnKey(key, handler) {
|
|
1491
|
+
return this.updateEmitter.subscribeOnKey(key, handler);
|
|
1492
|
+
}
|
|
1493
|
+
subscribeOnKeys(keys, handler) {
|
|
1494
|
+
return this.updateEmitter.subscribeOnKeys(keys, handler);
|
|
1495
|
+
}
|
|
1496
|
+
unsubscribeFromKey(key, handler) {
|
|
1497
|
+
this.updateEmitter.unsubscribeFromKey(key, handler);
|
|
1498
|
+
}
|
|
1499
|
+
unsubscribeFromKeys(keys, handler) {
|
|
1500
|
+
this.updateEmitter.unsubscribeFromKeys(keys, handler);
|
|
1501
|
+
}
|
|
1502
|
+
hasSubscriptions() {
|
|
1503
|
+
return this.updateEmitter.hasSubscriptions();
|
|
1504
|
+
}
|
|
1505
|
+
getHandlerCount(key) {
|
|
1506
|
+
return this.updateEmitter.getHandlerCount(key);
|
|
1507
|
+
}
|
|
1508
|
+
getMetrics() {
|
|
1509
|
+
return this.updateEmitter.getMetrics();
|
|
1510
|
+
}
|
|
1410
1511
|
destroy() {
|
|
1411
|
-
this.
|
|
1412
|
-
this.coalescer.destroy();
|
|
1512
|
+
this.updateEmitter.destroy();
|
|
1413
1513
|
super.destroy();
|
|
1414
1514
|
}
|
|
1415
1515
|
};
|
|
1416
1516
|
|
|
1517
|
+
// src/core/OIMIndexManualSetBased.ts
|
|
1518
|
+
var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
1519
|
+
constructor(options = {}) {
|
|
1520
|
+
super(options);
|
|
1521
|
+
}
|
|
1522
|
+
/**
|
|
1523
|
+
* Set primary keys for a specific index key, replacing any existing values.
|
|
1524
|
+
* Uses optional comparator to skip updates if PKs haven't actually changed.
|
|
1525
|
+
*/
|
|
1526
|
+
setPks(key, pks) {
|
|
1527
|
+
const hasChanges = this.setPksWithComparison(key, new Set(pks));
|
|
1528
|
+
if (hasChanges) {
|
|
1529
|
+
this.emitUpdateOne(key);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
setSlots(key, slots) {
|
|
1533
|
+
const hasChanges = this.setSlotsWithComparison(key, new Set(slots));
|
|
1534
|
+
if (hasChanges) {
|
|
1535
|
+
this.emitUpdateOne(key);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
/**
|
|
1539
|
+
* Add primary keys to a specific index key
|
|
1540
|
+
*/
|
|
1541
|
+
addPks(key, pks) {
|
|
1542
|
+
if (pks.length === 0) return;
|
|
1543
|
+
let slotsSet = this.store.getOneByKey(key);
|
|
1544
|
+
if (!slotsSet) {
|
|
1545
|
+
slotsSet = /* @__PURE__ */ new Set();
|
|
1546
|
+
this.store.setOneByKey(key, slotsSet);
|
|
1547
|
+
}
|
|
1548
|
+
const pksSet = this.slotsToPks(slotsSet);
|
|
1549
|
+
let hasChanges = false;
|
|
1550
|
+
for (const pk of pks) {
|
|
1551
|
+
if (!pksSet.has(pk)) {
|
|
1552
|
+
pksSet.add(pk);
|
|
1553
|
+
slotsSet.add(this.getOrCreateSlot(pk));
|
|
1554
|
+
hasChanges = true;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
if (hasChanges) {
|
|
1558
|
+
this.store.setOneByKey(key, slotsSet);
|
|
1559
|
+
this.emitUpdateOne(key);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Remove primary keys from a specific index key
|
|
1564
|
+
*/
|
|
1565
|
+
removePks(key, pks) {
|
|
1566
|
+
if (pks.length === 0) return;
|
|
1567
|
+
const slotsSet = this.store.getOneByKey(key);
|
|
1568
|
+
if (!slotsSet) return;
|
|
1569
|
+
let hasChanges = false;
|
|
1570
|
+
const pksToRemove = new Set(pks);
|
|
1571
|
+
for (const slot of Array.from(slotsSet)) {
|
|
1572
|
+
if (pksToRemove.has(slot.pk) && slotsSet.delete(slot)) {
|
|
1573
|
+
hasChanges = true;
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1576
|
+
if (slotsSet.size === 0) {
|
|
1577
|
+
this.store.removeOneByKey(key);
|
|
1578
|
+
hasChanges = true;
|
|
1579
|
+
} else if (hasChanges) {
|
|
1580
|
+
this.store.setOneByKey(key, slotsSet);
|
|
1581
|
+
}
|
|
1582
|
+
if (hasChanges) {
|
|
1583
|
+
this.emitUpdateOne(key);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
/**
|
|
1587
|
+
* Clear all primary keys for a specific index key, or all keys if no key specified
|
|
1588
|
+
*/
|
|
1589
|
+
clear(key) {
|
|
1590
|
+
if (key === void 0) {
|
|
1591
|
+
const allKeys = this.store.getAllKeys();
|
|
1592
|
+
if (allKeys.length > 0) {
|
|
1593
|
+
this.store.clear();
|
|
1594
|
+
this.emitUpdate(allKeys);
|
|
1595
|
+
}
|
|
1596
|
+
} else {
|
|
1597
|
+
if (this.store.getOneByKey(key) !== void 0) {
|
|
1598
|
+
this.store.removeOneByKey(key);
|
|
1599
|
+
this.emitUpdateOne(key);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
};
|
|
1604
|
+
|
|
1417
1605
|
// src/core/OIMReactiveIndexManualSetBased.ts
|
|
1606
|
+
var OIMIndexManualSetBasedReactive = class extends OIMIndexManualSetBased {
|
|
1607
|
+
constructor(updateEmitter, opts) {
|
|
1608
|
+
super(opts);
|
|
1609
|
+
this.updateEmitter = updateEmitter;
|
|
1610
|
+
}
|
|
1611
|
+
emitUpdate(keys) {
|
|
1612
|
+
this.updateEmitter.markUpdatedKeys(keys);
|
|
1613
|
+
}
|
|
1614
|
+
emitUpdateOne(key) {
|
|
1615
|
+
this.updateEmitter.markUpdatedKey(key);
|
|
1616
|
+
}
|
|
1617
|
+
};
|
|
1418
1618
|
var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
1419
1619
|
constructor(queue, opts) {
|
|
1420
|
-
super(queue,
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1620
|
+
super(queue, (updateEmitter) => {
|
|
1621
|
+
return new OIMIndexManualSetBasedReactive(
|
|
1622
|
+
updateEmitter,
|
|
1623
|
+
opts?.indexOptions
|
|
1624
|
+
);
|
|
1625
|
+
});
|
|
1424
1626
|
}
|
|
1425
1627
|
setPks(key, pks) {
|
|
1426
1628
|
this.index.setPks(key, pks);
|
|
1427
1629
|
}
|
|
1630
|
+
setSlots(key, slots) {
|
|
1631
|
+
this.index.setSlots(key, slots);
|
|
1632
|
+
}
|
|
1428
1633
|
addPks(key, pks) {
|
|
1429
1634
|
this.index.addPks(key, pks);
|
|
1430
1635
|
}
|
|
@@ -1448,7 +1653,13 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1448
1653
|
setPks(key, pks) {
|
|
1449
1654
|
const hasChanges = this.setPksWithComparison(key, pks);
|
|
1450
1655
|
if (hasChanges) {
|
|
1451
|
-
this.
|
|
1656
|
+
this.emitUpdateOne(key);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
setSlots(key, slots) {
|
|
1660
|
+
const hasChanges = this.setSlotsWithComparison(key, slots);
|
|
1661
|
+
if (hasChanges) {
|
|
1662
|
+
this.emitUpdateOne(key);
|
|
1452
1663
|
}
|
|
1453
1664
|
}
|
|
1454
1665
|
/**
|
|
@@ -1456,22 +1667,24 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1456
1667
|
*/
|
|
1457
1668
|
addPks(key, pks) {
|
|
1458
1669
|
if (pks.length === 0) return;
|
|
1459
|
-
let
|
|
1460
|
-
if (!
|
|
1461
|
-
|
|
1462
|
-
this.store.setOneByKey(key,
|
|
1670
|
+
let slotsArray = this.store.getOneByKey(key);
|
|
1671
|
+
if (!slotsArray) {
|
|
1672
|
+
slotsArray = [];
|
|
1673
|
+
this.store.setOneByKey(key, slotsArray);
|
|
1463
1674
|
}
|
|
1464
|
-
const pksSet = new Set(
|
|
1675
|
+
const pksSet = new Set(slotsArray.map((slot) => slot.pk));
|
|
1465
1676
|
let hasChanges = false;
|
|
1677
|
+
const nextSlots = slotsArray.slice();
|
|
1466
1678
|
for (const pk of pks) {
|
|
1467
1679
|
if (!pksSet.has(pk)) {
|
|
1468
1680
|
pksSet.add(pk);
|
|
1681
|
+
nextSlots.push(this.getOrCreateSlot(pk));
|
|
1469
1682
|
hasChanges = true;
|
|
1470
1683
|
}
|
|
1471
1684
|
}
|
|
1472
1685
|
if (hasChanges) {
|
|
1473
|
-
this.store.setOneByKey(key,
|
|
1474
|
-
this.
|
|
1686
|
+
this.store.setOneByKey(key, nextSlots);
|
|
1687
|
+
this.emitUpdateOne(key);
|
|
1475
1688
|
}
|
|
1476
1689
|
}
|
|
1477
1690
|
/**
|
|
@@ -1479,18 +1692,18 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1479
1692
|
*/
|
|
1480
1693
|
removePks(key, pks) {
|
|
1481
1694
|
if (pks.length === 0) return;
|
|
1482
|
-
const
|
|
1483
|
-
if (!
|
|
1695
|
+
const slotsArray = this.store.getOneByKey(key);
|
|
1696
|
+
if (!slotsArray) return;
|
|
1484
1697
|
const pksSet = new Set(pks);
|
|
1485
|
-
const filtered =
|
|
1486
|
-
const hasChanges = filtered.length !==
|
|
1698
|
+
const filtered = slotsArray.filter((slot) => !pksSet.has(slot.pk));
|
|
1699
|
+
const hasChanges = filtered.length !== slotsArray.length;
|
|
1487
1700
|
if (hasChanges) {
|
|
1488
1701
|
if (filtered.length === 0) {
|
|
1489
1702
|
this.store.removeOneByKey(key);
|
|
1490
1703
|
} else {
|
|
1491
1704
|
this.store.setOneByKey(key, filtered);
|
|
1492
1705
|
}
|
|
1493
|
-
this.
|
|
1706
|
+
this.emitUpdateOne(key);
|
|
1494
1707
|
}
|
|
1495
1708
|
}
|
|
1496
1709
|
/**
|
|
@@ -1506,23 +1719,40 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
1506
1719
|
} else {
|
|
1507
1720
|
if (this.store.getOneByKey(key) !== void 0) {
|
|
1508
1721
|
this.store.removeOneByKey(key);
|
|
1509
|
-
this.
|
|
1722
|
+
this.emitUpdateOne(key);
|
|
1510
1723
|
}
|
|
1511
1724
|
}
|
|
1512
1725
|
}
|
|
1513
1726
|
};
|
|
1514
1727
|
|
|
1515
1728
|
// src/core/OIMReactiveIndexManualArrayBased.ts
|
|
1729
|
+
var OIMIndexManualArrayBasedReactive = class extends OIMIndexManualArrayBased {
|
|
1730
|
+
constructor(updateEmitter, opts) {
|
|
1731
|
+
super(opts);
|
|
1732
|
+
this.updateEmitter = updateEmitter;
|
|
1733
|
+
}
|
|
1734
|
+
emitUpdate(keys) {
|
|
1735
|
+
this.updateEmitter.markUpdatedKeys(keys);
|
|
1736
|
+
}
|
|
1737
|
+
emitUpdateOne(key) {
|
|
1738
|
+
this.updateEmitter.markUpdatedKey(key);
|
|
1739
|
+
}
|
|
1740
|
+
};
|
|
1516
1741
|
var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased {
|
|
1517
1742
|
constructor(queue, opts) {
|
|
1518
|
-
super(queue,
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1743
|
+
super(queue, (updateEmitter) => {
|
|
1744
|
+
return new OIMIndexManualArrayBasedReactive(
|
|
1745
|
+
updateEmitter,
|
|
1746
|
+
opts?.indexOptions
|
|
1747
|
+
);
|
|
1748
|
+
});
|
|
1522
1749
|
}
|
|
1523
1750
|
setPks(key, pks) {
|
|
1524
1751
|
this.index.setPks(key, pks);
|
|
1525
1752
|
}
|
|
1753
|
+
setSlots(key, slots) {
|
|
1754
|
+
this.index.setSlots(key, slots);
|
|
1755
|
+
}
|
|
1526
1756
|
addPks(key, pks) {
|
|
1527
1757
|
this.index.addPks(key, pks);
|
|
1528
1758
|
}
|
|
@@ -1539,6 +1769,10 @@ var OIMRICollection = class extends OIMReactiveCollection {
|
|
|
1539
1769
|
constructor(queue, opts) {
|
|
1540
1770
|
super(queue, opts.collectionOpts);
|
|
1541
1771
|
this.indexes = opts.indexes || {};
|
|
1772
|
+
const indexes = Object.values(this.indexes);
|
|
1773
|
+
for (const index of indexes) {
|
|
1774
|
+
index.index.setSlotResolver((pk) => this.getSlotByPk(pk));
|
|
1775
|
+
}
|
|
1542
1776
|
}
|
|
1543
1777
|
};
|
|
1544
1778
|
|
|
@@ -1607,20 +1841,12 @@ var OIMComparatorFactory = class {
|
|
|
1607
1841
|
}
|
|
1608
1842
|
};
|
|
1609
1843
|
|
|
1610
|
-
// src/enum/EOIMEventQueueEventType.ts
|
|
1611
|
-
var EOIMEventQueueEventType = /* @__PURE__ */ ((EOIMEventQueueEventType2) => {
|
|
1612
|
-
EOIMEventQueueEventType2[EOIMEventQueueEventType2["AFTER_FLUSH"] = 0] = "AFTER_FLUSH";
|
|
1613
|
-
EOIMEventQueueEventType2[EOIMEventQueueEventType2["BEFORE_FLUSH"] = 1] = "BEFORE_FLUSH";
|
|
1614
|
-
return EOIMEventQueueEventType2;
|
|
1615
|
-
})(EOIMEventQueueEventType || {});
|
|
1616
|
-
|
|
1617
1844
|
// src/core/OIMEventQueue.ts
|
|
1618
1845
|
var OIMEventQueue = class {
|
|
1619
1846
|
constructor(options = {}) {
|
|
1620
1847
|
this.emitter = new OIMEventEmitter();
|
|
1621
|
-
this.
|
|
1848
|
+
this.tasks = /* @__PURE__ */ new Set();
|
|
1622
1849
|
this.isFlushing = false;
|
|
1623
|
-
this.pendingSchedule = false;
|
|
1624
1850
|
this.scheduler = options.scheduler;
|
|
1625
1851
|
if (this.scheduler) {
|
|
1626
1852
|
this.flushBound = () => this.flush();
|
|
@@ -1631,62 +1857,76 @@ var OIMEventQueue = class {
|
|
|
1631
1857
|
}
|
|
1632
1858
|
}
|
|
1633
1859
|
/**
|
|
1634
|
-
*
|
|
1635
|
-
*
|
|
1860
|
+
* Enqueue a one-shot task to be executed on the next flush.
|
|
1861
|
+
* Returns a dequeue function that can be called to cancel the task before it runs.
|
|
1636
1862
|
*/
|
|
1637
1863
|
enqueue(fn) {
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1864
|
+
let isActive = true;
|
|
1865
|
+
const task = () => {
|
|
1866
|
+
if (!isActive) return;
|
|
1867
|
+
fn();
|
|
1868
|
+
};
|
|
1869
|
+
this.tasks.add(task);
|
|
1870
|
+
this.ensureScheduled();
|
|
1871
|
+
return () => {
|
|
1872
|
+
if (!isActive) return;
|
|
1873
|
+
isActive = false;
|
|
1874
|
+
this.tasks.delete(task);
|
|
1875
|
+
};
|
|
1876
|
+
}
|
|
1877
|
+
get isInFlush() {
|
|
1878
|
+
return this.isFlushing;
|
|
1647
1879
|
}
|
|
1648
1880
|
/**
|
|
1649
|
-
*
|
|
1650
|
-
* This method is safe to call multiple times and handles reentrancy.
|
|
1881
|
+
* Dequeue (cancel) a previously enqueued task by its dequeue function.
|
|
1651
1882
|
*/
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1883
|
+
dequeue(dequeueFn) {
|
|
1884
|
+
dequeueFn();
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* Execute all pending tasks.
|
|
1888
|
+
*
|
|
1889
|
+
* This flush drains until the queue is empty. If tasks enqueue more tasks, they will be
|
|
1890
|
+
* executed within the same flush.
|
|
1891
|
+
*/
|
|
1892
|
+
flush() {
|
|
1893
|
+
this.scheduler?.cancel();
|
|
1655
1894
|
this.isFlushing = true;
|
|
1656
1895
|
this.emitter.emit(1 /* BEFORE_FLUSH */, void 0);
|
|
1657
|
-
const
|
|
1658
|
-
this.
|
|
1659
|
-
for (let i = 0; i <
|
|
1660
|
-
|
|
1896
|
+
const snapshot = Array.from(this.tasks);
|
|
1897
|
+
this.tasks.clear();
|
|
1898
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
1899
|
+
snapshot[i]();
|
|
1661
1900
|
}
|
|
1662
|
-
this.emitter.emit(0 /* AFTER_FLUSH */, void 0);
|
|
1663
1901
|
this.isFlushing = false;
|
|
1664
|
-
|
|
1665
|
-
this.pendingSchedule = false;
|
|
1666
|
-
this.scheduler.schedule();
|
|
1667
|
-
} else {
|
|
1668
|
-
this.pendingSchedule = false;
|
|
1669
|
-
}
|
|
1902
|
+
this.emitter.emit(0 /* AFTER_FLUSH */, void 0);
|
|
1670
1903
|
}
|
|
1671
1904
|
/**
|
|
1672
1905
|
* Get the current number of queued functions.
|
|
1673
1906
|
*/
|
|
1674
1907
|
get length() {
|
|
1675
|
-
return this.
|
|
1908
|
+
return this.tasks.size;
|
|
1676
1909
|
}
|
|
1677
1910
|
/**
|
|
1678
1911
|
* Check if the queue is empty.
|
|
1679
1912
|
*/
|
|
1680
1913
|
get isEmpty() {
|
|
1681
|
-
return this.
|
|
1914
|
+
return this.tasks.size === 0;
|
|
1682
1915
|
}
|
|
1683
1916
|
/**
|
|
1684
1917
|
* Clear the queue without executing functions and cancel any scheduled flush.
|
|
1685
1918
|
*/
|
|
1686
1919
|
clear() {
|
|
1687
|
-
this.
|
|
1920
|
+
this.tasks.clear();
|
|
1688
1921
|
this.scheduler?.cancel();
|
|
1689
1922
|
}
|
|
1923
|
+
ensureScheduled() {
|
|
1924
|
+
if (!this.scheduler) return;
|
|
1925
|
+
if (this.isFlushing) return;
|
|
1926
|
+
if (this.tasks.size === 1) {
|
|
1927
|
+
this.scheduler.schedule();
|
|
1928
|
+
}
|
|
1929
|
+
}
|
|
1690
1930
|
/**
|
|
1691
1931
|
* Clean up scheduler subscription when queue is no longer needed.
|
|
1692
1932
|
*/
|
|
@@ -1800,56 +2040,75 @@ var OIMMap2Keys = class {
|
|
|
1800
2040
|
}
|
|
1801
2041
|
};
|
|
1802
2042
|
|
|
1803
|
-
// src/modules/wrapper/OIMUpdateEventCoalescerManual.ts
|
|
1804
|
-
var OIMUpdateEventCoalescerManual = class extends OIMUpdateEventCoalescer {
|
|
1805
|
-
markUpdatedKeys(keys) {
|
|
1806
|
-
if (keys.length === 0) return;
|
|
1807
|
-
this.addUpdatedKeys(keys);
|
|
1808
|
-
}
|
|
1809
|
-
destroy() {
|
|
1810
|
-
this.emitter.offAll();
|
|
1811
|
-
this.updatedKeysIndex.destroy();
|
|
1812
|
-
this.flushingUpdatedKeysIndex.destroy();
|
|
1813
|
-
}
|
|
1814
|
-
};
|
|
1815
|
-
|
|
1816
2043
|
// src/modules/wrapper/collection/OIMCollectionChangedFieldsWrapper.ts
|
|
1817
2044
|
var OIMCollectionChangedFieldsWrapper = class {
|
|
1818
2045
|
constructor(queue, collection, opts) {
|
|
2046
|
+
this.isInWrite = false;
|
|
2047
|
+
this.lastEntitySnapshotByPk = /* @__PURE__ */ new Map();
|
|
1819
2048
|
this.changedFieldsByPk = /* @__PURE__ */ new Map();
|
|
1820
2049
|
this.changedPksByField = /* @__PURE__ */ new Map();
|
|
2050
|
+
this.onAfterFlush = () => {
|
|
2051
|
+
this.clear();
|
|
2052
|
+
};
|
|
2053
|
+
this.onCollectionUpdate = (payload) => {
|
|
2054
|
+
if (this.isInWrite) return;
|
|
2055
|
+
if (payload.pks.length === 0) return;
|
|
2056
|
+
for (let i = 0; i < payload.pks.length; i++) {
|
|
2057
|
+
const pk = payload.pks[i];
|
|
2058
|
+
this.trackExternalMutationByPk(pk);
|
|
2059
|
+
}
|
|
2060
|
+
};
|
|
1821
2061
|
this.collection = collection;
|
|
1822
2062
|
this.selectPk = opts?.selectPk ?? (() => {
|
|
1823
2063
|
throw new Error(
|
|
1824
2064
|
`[OIMCollectionChangedFieldsWrapper]: selectPk was not provided. Use upsertOneByPk(...) or pass opts.selectPk.`
|
|
1825
2065
|
);
|
|
1826
2066
|
});
|
|
1827
|
-
this.
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
this.
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
2067
|
+
this.changedPksEventEmitter = new OIMUpdateEventEmitter(
|
|
2068
|
+
queue,
|
|
2069
|
+
"after_flush"
|
|
2070
|
+
);
|
|
2071
|
+
this.changedFieldsEventEmitter = new OIMUpdateEventEmitter(queue, "after_flush");
|
|
2072
|
+
this.unsubscribeAfterFlush = queue.emitter.on(
|
|
2073
|
+
0 /* AFTER_FLUSH */,
|
|
2074
|
+
this.onAfterFlush
|
|
2075
|
+
);
|
|
2076
|
+
const maybeReactive = collection;
|
|
2077
|
+
this.unsubscribeFromCollectionEmitter = maybeReactive.subscribeOnAnyUpdate ? maybeReactive.subscribeOnAnyUpdate((pks) => {
|
|
2078
|
+
this.onCollectionUpdate({
|
|
2079
|
+
pks
|
|
2080
|
+
});
|
|
2081
|
+
}) : collection.emitter.on(
|
|
2082
|
+
0 /* UPDATE */,
|
|
2083
|
+
this.onCollectionUpdate
|
|
2084
|
+
);
|
|
1837
2085
|
}
|
|
1838
2086
|
upsertOneByPk(pk, patch) {
|
|
1839
|
-
this.
|
|
1840
|
-
|
|
2087
|
+
this.withWrite(() => {
|
|
2088
|
+
this.trackPatch(pk, patch);
|
|
2089
|
+
this.collection.upsertOneByPk(pk, patch);
|
|
2090
|
+
});
|
|
2091
|
+
this.updateEntitySnapshot(pk);
|
|
1841
2092
|
}
|
|
1842
2093
|
upsertOne(entity) {
|
|
1843
|
-
|
|
1844
|
-
this.trackPatch(pk, entity);
|
|
1845
|
-
this.collection.upsertOne(entity);
|
|
1846
|
-
}
|
|
1847
|
-
upsertMany(entities) {
|
|
1848
|
-
for (const entity of entities) {
|
|
2094
|
+
this.withWrite(() => {
|
|
1849
2095
|
const pk = this.selectPk(entity);
|
|
1850
2096
|
this.trackPatch(pk, entity);
|
|
1851
|
-
|
|
1852
|
-
|
|
2097
|
+
this.collection.upsertOne(entity);
|
|
2098
|
+
});
|
|
2099
|
+
this.updateEntitySnapshot(this.selectPk(entity));
|
|
2100
|
+
}
|
|
2101
|
+
upsertMany(entities) {
|
|
2102
|
+
const pks = [];
|
|
2103
|
+
this.withWrite(() => {
|
|
2104
|
+
for (const entity of entities) {
|
|
2105
|
+
const pk = this.selectPk(entity);
|
|
2106
|
+
pks.push(pk);
|
|
2107
|
+
this.trackPatch(pk, entity);
|
|
2108
|
+
}
|
|
2109
|
+
this.collection.upsertMany(entities);
|
|
2110
|
+
});
|
|
2111
|
+
for (let i = 0; i < pks.length; i++) this.updateEntitySnapshot(pks[i]);
|
|
1853
2112
|
}
|
|
1854
2113
|
getChangedFieldsByPk(pk) {
|
|
1855
2114
|
return this.changedFieldsByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
@@ -1857,8 +2116,7 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1857
2116
|
consumeChangedFieldsByPk(pk) {
|
|
1858
2117
|
const existing = this.changedFieldsByPk.get(pk);
|
|
1859
2118
|
if (!existing) return /* @__PURE__ */ new Set();
|
|
1860
|
-
|
|
1861
|
-
return existing;
|
|
2119
|
+
return new Set(existing);
|
|
1862
2120
|
}
|
|
1863
2121
|
getChangedPksByField(field) {
|
|
1864
2122
|
return this.changedPksByField.get(field) ?? /* @__PURE__ */ new Set();
|
|
@@ -1866,8 +2124,7 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1866
2124
|
consumeChangedPksByField(field) {
|
|
1867
2125
|
const existing = this.changedPksByField.get(field);
|
|
1868
2126
|
if (!existing) return /* @__PURE__ */ new Set();
|
|
1869
|
-
|
|
1870
|
-
return existing;
|
|
2127
|
+
return new Set(existing);
|
|
1871
2128
|
}
|
|
1872
2129
|
clear() {
|
|
1873
2130
|
this.changedFieldsByPk.clear();
|
|
@@ -1876,18 +2133,60 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1876
2133
|
destroy() {
|
|
1877
2134
|
this.changedPksEventEmitter.destroy();
|
|
1878
2135
|
this.changedFieldsEventEmitter.destroy();
|
|
1879
|
-
this.
|
|
1880
|
-
this.
|
|
2136
|
+
this.unsubscribeAfterFlush();
|
|
2137
|
+
this.unsubscribeFromCollectionEmitter();
|
|
1881
2138
|
this.clear();
|
|
1882
2139
|
}
|
|
1883
|
-
|
|
1884
|
-
if (
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
);
|
|
2140
|
+
withWrite(fn) {
|
|
2141
|
+
if (this.isInWrite) {
|
|
2142
|
+
fn();
|
|
2143
|
+
return;
|
|
1888
2144
|
}
|
|
1889
|
-
|
|
1890
|
-
|
|
2145
|
+
this.isInWrite = true;
|
|
2146
|
+
try {
|
|
2147
|
+
fn();
|
|
2148
|
+
} finally {
|
|
2149
|
+
this.isInWrite = false;
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
trackExternalMutationByPk(pk) {
|
|
2153
|
+
const prev = this.lastEntitySnapshotByPk.get(pk);
|
|
2154
|
+
const next = this.collection.getOneByPk(pk);
|
|
2155
|
+
const changedKeys = this.diffChangedKeys(prev, next);
|
|
2156
|
+
this.updateEntitySnapshot(pk);
|
|
2157
|
+
if (changedKeys.length > 0) {
|
|
2158
|
+
this.trackChangedKeys(pk, changedKeys);
|
|
2159
|
+
} else {
|
|
2160
|
+
this.changedPksEventEmitter.markUpdatedKeys([pk]);
|
|
2161
|
+
}
|
|
2162
|
+
}
|
|
2163
|
+
diffChangedKeys(prev, next) {
|
|
2164
|
+
if (!prev && !next) return [];
|
|
2165
|
+
if (!prev && next) return Object.keys(next);
|
|
2166
|
+
if (prev && !next) return Object.keys(prev);
|
|
2167
|
+
const prevObj = prev;
|
|
2168
|
+
const nextObj = next;
|
|
2169
|
+
const keys = /* @__PURE__ */ new Set();
|
|
2170
|
+
Object.keys(prevObj).forEach((k) => keys.add(k));
|
|
2171
|
+
Object.keys(nextObj).forEach((k) => keys.add(k));
|
|
2172
|
+
const changed = [];
|
|
2173
|
+
keys.forEach((k) => {
|
|
2174
|
+
if (prevObj[k] !== nextObj[k])
|
|
2175
|
+
changed.push(k);
|
|
2176
|
+
});
|
|
2177
|
+
return changed;
|
|
2178
|
+
}
|
|
2179
|
+
updateEntitySnapshot(pk) {
|
|
2180
|
+
const entity = this.collection.getOneByPk(pk);
|
|
2181
|
+
if (!entity) {
|
|
2182
|
+
this.lastEntitySnapshotByPk.delete(pk);
|
|
2183
|
+
return;
|
|
2184
|
+
}
|
|
2185
|
+
this.lastEntitySnapshotByPk.set(pk, {
|
|
2186
|
+
...entity
|
|
2187
|
+
});
|
|
2188
|
+
}
|
|
2189
|
+
trackChangedKeys(pk, keys) {
|
|
1891
2190
|
let pkFields = this.changedFieldsByPk.get(pk);
|
|
1892
2191
|
if (!pkFields) {
|
|
1893
2192
|
pkFields = /* @__PURE__ */ new Set();
|
|
@@ -1902,8 +2201,18 @@ var OIMCollectionChangedFieldsWrapper = class {
|
|
|
1902
2201
|
}
|
|
1903
2202
|
fieldPks.add(pk);
|
|
1904
2203
|
}
|
|
1905
|
-
this.
|
|
1906
|
-
this.
|
|
2204
|
+
this.changedPksEventEmitter.markUpdatedKeys([pk]);
|
|
2205
|
+
this.changedFieldsEventEmitter.markUpdatedKeys(keys);
|
|
2206
|
+
}
|
|
2207
|
+
trackPatch(pk, patch) {
|
|
2208
|
+
if (pk === void 0 || pk === null || pk === "") {
|
|
2209
|
+
throw new Error(
|
|
2210
|
+
`[OIMCollectionChangedFieldsWrapper]: PK is required to track changes.`
|
|
2211
|
+
);
|
|
2212
|
+
}
|
|
2213
|
+
const keys = Object.keys(patch);
|
|
2214
|
+
if (keys.length === 0) return;
|
|
2215
|
+
this.trackChangedKeys(pk, keys);
|
|
1907
2216
|
}
|
|
1908
2217
|
};
|
|
1909
2218
|
|
|
@@ -1926,14 +2235,14 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1926
2235
|
push(key, itemKey) {
|
|
1927
2236
|
const list = this.getOrCreateList(key);
|
|
1928
2237
|
const index = list.length;
|
|
1929
|
-
list.push(itemKey);
|
|
2238
|
+
list.push(this.getOrCreateSlot(itemKey));
|
|
1930
2239
|
this.emitUpdate([key]);
|
|
1931
2240
|
return index;
|
|
1932
2241
|
}
|
|
1933
2242
|
insertAt(key, index, itemKey) {
|
|
1934
2243
|
const list = this.getOrCreateList(key);
|
|
1935
2244
|
const safeIndex = Math.max(0, Math.min(index, list.length));
|
|
1936
|
-
list.splice(safeIndex, 0, itemKey);
|
|
2245
|
+
list.splice(safeIndex, 0, this.getOrCreateSlot(itemKey));
|
|
1937
2246
|
this.emitUpdate([key]);
|
|
1938
2247
|
}
|
|
1939
2248
|
removeAt(key, index) {
|
|
@@ -1945,19 +2254,19 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1945
2254
|
this.store.removeOneByKey(key);
|
|
1946
2255
|
}
|
|
1947
2256
|
this.emitUpdate([key]);
|
|
1948
|
-
return removed;
|
|
2257
|
+
return removed?.pk;
|
|
1949
2258
|
}
|
|
1950
2259
|
move(key, fromIndex, toIndex) {
|
|
1951
2260
|
const list = this.store.getOneByKey(key);
|
|
1952
2261
|
if (!list) return void 0;
|
|
1953
2262
|
if (fromIndex < 0 || fromIndex >= list.length) return void 0;
|
|
1954
2263
|
if (toIndex < 0 || toIndex >= list.length) return void 0;
|
|
1955
|
-
if (fromIndex === toIndex) return list[fromIndex];
|
|
2264
|
+
if (fromIndex === toIndex) return list[fromIndex]?.pk;
|
|
1956
2265
|
const [itemKey] = list.splice(fromIndex, 1);
|
|
1957
2266
|
if (itemKey === void 0) return void 0;
|
|
1958
2267
|
list.splice(toIndex, 0, itemKey);
|
|
1959
2268
|
this.emitUpdate([key]);
|
|
1960
|
-
return itemKey;
|
|
2269
|
+
return itemKey.pk;
|
|
1961
2270
|
}
|
|
1962
2271
|
reset(key, itemKeys) {
|
|
1963
2272
|
if (itemKeys.length === 0) {
|
|
@@ -1967,7 +2276,7 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1967
2276
|
}
|
|
1968
2277
|
return;
|
|
1969
2278
|
}
|
|
1970
|
-
this.store.setOneByKey(key,
|
|
2279
|
+
this.store.setOneByKey(key, this.resolveSlots(itemKeys));
|
|
1971
2280
|
this.emitUpdate([key]);
|
|
1972
2281
|
}
|
|
1973
2282
|
getOrCreateList(key) {
|
|
@@ -1983,13 +2292,33 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1983
2292
|
// src/modules/wrapper/index/OIMOrderedListIndexCommandStreamWrapper.ts
|
|
1984
2293
|
var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
1985
2294
|
constructor(queue, index) {
|
|
2295
|
+
this.isInWrite = false;
|
|
1986
2296
|
this.commandsByKey = /* @__PURE__ */ new Map();
|
|
1987
|
-
this.
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
2297
|
+
this.onAfterFlush = () => {
|
|
2298
|
+
this.commandsByKey.clear();
|
|
2299
|
+
};
|
|
2300
|
+
this.onIndexUpdate = (payload) => {
|
|
2301
|
+
if (this.isInWrite) return;
|
|
2302
|
+
if (payload.keys.length === 0) return;
|
|
2303
|
+
for (let i = 0; i < payload.keys.length; i++) {
|
|
2304
|
+
const key = payload.keys[i];
|
|
2305
|
+
const list = this.index.getPksByKey(key);
|
|
2306
|
+
this.appendCommand(key, { type: "set", keys: Array.from(list) });
|
|
2307
|
+
}
|
|
2308
|
+
};
|
|
2309
|
+
this.commandsEventEmitter = new OIMUpdateEventEmitter(
|
|
2310
|
+
queue,
|
|
2311
|
+
"after_flush"
|
|
2312
|
+
);
|
|
1992
2313
|
this.index = index ?? new OIMIndexManualOrderedArrayBased();
|
|
2314
|
+
this.unsubscribeAfterFlush = queue.emitter.on(
|
|
2315
|
+
0 /* AFTER_FLUSH */,
|
|
2316
|
+
this.onAfterFlush
|
|
2317
|
+
);
|
|
2318
|
+
this.unsubscribeFromIndexEmitter = this.index.emitter.on(
|
|
2319
|
+
0 /* UPDATE */,
|
|
2320
|
+
this.onIndexUpdate
|
|
2321
|
+
);
|
|
1993
2322
|
}
|
|
1994
2323
|
getPksByKey(key) {
|
|
1995
2324
|
return this.index.getPksByKey(key);
|
|
@@ -2001,27 +2330,35 @@ var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
|
2001
2330
|
return this.index.getKeys();
|
|
2002
2331
|
}
|
|
2003
2332
|
push(key, itemKey) {
|
|
2004
|
-
|
|
2005
|
-
|
|
2333
|
+
this.withWrite(() => {
|
|
2334
|
+
const index = this.index.push(key, itemKey);
|
|
2335
|
+
this.appendCommand(key, { type: "add", key: itemKey, index });
|
|
2336
|
+
});
|
|
2006
2337
|
}
|
|
2007
2338
|
removeAt(key, index) {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2339
|
+
this.withWrite(() => {
|
|
2340
|
+
const itemKey = this.index.removeAt(key, index);
|
|
2341
|
+
if (itemKey === void 0) return;
|
|
2342
|
+
this.appendCommand(key, { type: "remove", key: itemKey, index });
|
|
2343
|
+
});
|
|
2011
2344
|
}
|
|
2012
2345
|
move(key, fromIndex, toIndex) {
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2346
|
+
this.withWrite(() => {
|
|
2347
|
+
const itemKey = this.index.move(key, fromIndex, toIndex);
|
|
2348
|
+
if (itemKey === void 0) return;
|
|
2349
|
+
this.appendCommand(key, {
|
|
2350
|
+
type: "move",
|
|
2351
|
+
key: itemKey,
|
|
2352
|
+
fromIndex,
|
|
2353
|
+
toIndex
|
|
2354
|
+
});
|
|
2020
2355
|
});
|
|
2021
2356
|
}
|
|
2022
|
-
|
|
2023
|
-
this.
|
|
2024
|
-
|
|
2357
|
+
set(key, keys) {
|
|
2358
|
+
this.withWrite(() => {
|
|
2359
|
+
this.index.reset(key, keys);
|
|
2360
|
+
this.appendCommand(key, { type: "set", keys });
|
|
2361
|
+
});
|
|
2025
2362
|
}
|
|
2026
2363
|
/**
|
|
2027
2364
|
* Read-only peek at buffered commands without clearing them.
|
|
@@ -2036,8 +2373,7 @@ var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
|
2036
2373
|
consumeCommands(key) {
|
|
2037
2374
|
const cmds = this.commandsByKey.get(key);
|
|
2038
2375
|
if (!cmds || cmds.length === 0) return [];
|
|
2039
|
-
|
|
2040
|
-
return cmds;
|
|
2376
|
+
return cmds.slice();
|
|
2041
2377
|
}
|
|
2042
2378
|
clear(key) {
|
|
2043
2379
|
if (key === void 0) {
|
|
@@ -2050,17 +2386,38 @@ var OIMOrderedListIndexCommandStreamWrapper = class {
|
|
|
2050
2386
|
}
|
|
2051
2387
|
destroy() {
|
|
2052
2388
|
this.commandsEventEmitter.destroy();
|
|
2053
|
-
this.
|
|
2389
|
+
this.unsubscribeAfterFlush();
|
|
2390
|
+
this.unsubscribeFromIndexEmitter();
|
|
2054
2391
|
this.clear();
|
|
2055
2392
|
}
|
|
2393
|
+
withWrite(fn) {
|
|
2394
|
+
if (this.isInWrite) {
|
|
2395
|
+
fn();
|
|
2396
|
+
return;
|
|
2397
|
+
}
|
|
2398
|
+
this.isInWrite = true;
|
|
2399
|
+
try {
|
|
2400
|
+
fn();
|
|
2401
|
+
} finally {
|
|
2402
|
+
this.isInWrite = false;
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2056
2405
|
appendCommand(key, cmd) {
|
|
2057
2406
|
let cmds = this.commandsByKey.get(key);
|
|
2058
2407
|
if (!cmds) {
|
|
2059
2408
|
cmds = [];
|
|
2060
2409
|
this.commandsByKey.set(key, cmds);
|
|
2061
2410
|
}
|
|
2062
|
-
|
|
2063
|
-
|
|
2411
|
+
if (cmd.type === "set") {
|
|
2412
|
+
cmds.length = 0;
|
|
2413
|
+
cmds.push(cmd);
|
|
2414
|
+
} else if (cmds.length > 0 && cmds[0].type === "set") {
|
|
2415
|
+
const setCmd = cmds[0];
|
|
2416
|
+
setCmd.keys = Array.from(this.index.getPksByKey(key));
|
|
2417
|
+
} else {
|
|
2418
|
+
cmds.push(cmd);
|
|
2419
|
+
}
|
|
2420
|
+
this.commandsEventEmitter.markUpdatedKeys([key]);
|
|
2064
2421
|
}
|
|
2065
2422
|
};
|
|
2066
2423
|
|
|
@@ -2233,159 +2590,160 @@ var OIMEventQueueSchedulerFactory = class {
|
|
|
2233
2590
|
}
|
|
2234
2591
|
};
|
|
2235
2592
|
|
|
2593
|
+
// src/const/OIMDBSettings.ts
|
|
2594
|
+
var OIMDBSettings = class {
|
|
2595
|
+
};
|
|
2596
|
+
/**
|
|
2597
|
+
* Fixed key used in the manual index to store updated keys set in coalescers.
|
|
2598
|
+
* This constant is exported so users can create their own indexes and pass them to coalescers.
|
|
2599
|
+
*/
|
|
2600
|
+
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
2601
|
+
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY = "__flushingKeys__";
|
|
2602
|
+
|
|
2603
|
+
// src/modules/effect/core/OIMEffectDependencyComputed.ts
|
|
2604
|
+
var OIMEffectDependencyComputed = class {
|
|
2605
|
+
constructor(computed) {
|
|
2606
|
+
this.computed = computed;
|
|
2607
|
+
}
|
|
2608
|
+
subscribe(onUpdate) {
|
|
2609
|
+
return this.computed.emitter.on("update", onUpdate);
|
|
2610
|
+
}
|
|
2611
|
+
};
|
|
2612
|
+
|
|
2236
2613
|
// src/modules/effect/core/OIMEffect.ts
|
|
2237
2614
|
var OIMEffect = class {
|
|
2238
|
-
constructor(
|
|
2239
|
-
this.
|
|
2240
|
-
this.
|
|
2241
|
-
this.
|
|
2242
|
-
this.
|
|
2615
|
+
constructor(runtime, opts) {
|
|
2616
|
+
this.sourceDeps = [];
|
|
2617
|
+
this.computedDeps = [];
|
|
2618
|
+
this.sourceUnsubscribers = [];
|
|
2619
|
+
this.computedUnsubscribers = [];
|
|
2620
|
+
this.isResubscribeEnqueued = false;
|
|
2621
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2243
2622
|
this.isScheduled = false;
|
|
2244
|
-
this.handleQueueBeforeFlush = () => {
|
|
2245
|
-
this.isInFlush = true;
|
|
2246
|
-
this.hasRunInThisFlush = false;
|
|
2247
|
-
};
|
|
2248
|
-
this.handleQueueAfterFlush = () => {
|
|
2249
|
-
this.isInFlush = false;
|
|
2250
|
-
this.hasRunInThisFlush = false;
|
|
2251
|
-
};
|
|
2252
2623
|
this.runTask = () => {
|
|
2253
2624
|
this.isScheduled = false;
|
|
2254
|
-
|
|
2625
|
+
this.dequeueScheduled = void 0;
|
|
2255
2626
|
this.runOnce();
|
|
2256
2627
|
};
|
|
2257
|
-
this.
|
|
2258
|
-
|
|
2259
|
-
this.
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
this.
|
|
2263
|
-
this.runOnce();
|
|
2264
|
-
return;
|
|
2628
|
+
this.onSourceInvalidate = () => {
|
|
2629
|
+
this.onUpdate?.();
|
|
2630
|
+
if (!this.isTemporarilyUnsubscribedForFlush) {
|
|
2631
|
+
this.isTemporarilyUnsubscribedForFlush = true;
|
|
2632
|
+
this.unsubscribeFromSourceDeps();
|
|
2633
|
+
this.ensureResubscribeAfterFlush();
|
|
2265
2634
|
}
|
|
2266
2635
|
if (this.isScheduled) return;
|
|
2267
2636
|
this.isScheduled = true;
|
|
2268
|
-
this.
|
|
2637
|
+
this.dequeueScheduled = this.runtime.schedule(this.runTask);
|
|
2269
2638
|
};
|
|
2270
|
-
this.
|
|
2271
|
-
|
|
2272
|
-
|
|
2639
|
+
this.onComputedInvalidate = () => {
|
|
2640
|
+
this.onUpdate?.();
|
|
2641
|
+
if (this.isScheduled) return;
|
|
2642
|
+
this.isScheduled = true;
|
|
2643
|
+
this.dequeueScheduled = this.runtime.schedule(this.runTask);
|
|
2644
|
+
};
|
|
2645
|
+
this.onAfterFlush = () => {
|
|
2646
|
+
if (!this.isResubscribeEnqueued) return;
|
|
2647
|
+
this.isResubscribeEnqueued = false;
|
|
2648
|
+
this.dequeueResubscribe = void 0;
|
|
2649
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2650
|
+
if (this.sourceUnsubscribers.length === 0) {
|
|
2651
|
+
for (const dep of this.sourceDeps) {
|
|
2652
|
+
this.sourceUnsubscribers.push(
|
|
2653
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2654
|
+
);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
};
|
|
2658
|
+
this.runtime = runtime;
|
|
2659
|
+
this.onUpdate = opts.onUpdate;
|
|
2273
2660
|
this.run = opts.run;
|
|
2274
2661
|
this.deps = opts.deps ?? [];
|
|
2275
|
-
this.queue.emitter.on(
|
|
2276
|
-
1 /* BEFORE_FLUSH */,
|
|
2277
|
-
this.handleQueueBeforeFlush
|
|
2278
|
-
);
|
|
2279
|
-
this.queue.emitter.on(
|
|
2280
|
-
0 /* AFTER_FLUSH */,
|
|
2281
|
-
this.handleQueueAfterFlush
|
|
2282
|
-
);
|
|
2283
2662
|
for (const dep of this.deps) {
|
|
2284
|
-
|
|
2663
|
+
if (dep instanceof OIMEffectDependencyComputed) {
|
|
2664
|
+
this.computedDeps.push(dep);
|
|
2665
|
+
} else {
|
|
2666
|
+
this.sourceDeps.push(dep);
|
|
2667
|
+
}
|
|
2285
2668
|
}
|
|
2669
|
+
this.subscribeToDeps();
|
|
2286
2670
|
}
|
|
2287
2671
|
destroy() {
|
|
2288
|
-
if (this.
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
this.
|
|
2293
|
-
|
|
2294
|
-
this.
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
);
|
|
2672
|
+
if (this.dequeueScheduled) {
|
|
2673
|
+
this.dequeueScheduled();
|
|
2674
|
+
this.dequeueScheduled = void 0;
|
|
2675
|
+
}
|
|
2676
|
+
this.unsubscribeFromAllDeps();
|
|
2677
|
+
if (this.dequeueResubscribe) {
|
|
2678
|
+
this.dequeueResubscribe();
|
|
2679
|
+
this.dequeueResubscribe = void 0;
|
|
2680
|
+
}
|
|
2681
|
+
this.isResubscribeEnqueued = false;
|
|
2682
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2300
2683
|
}
|
|
2301
2684
|
runOnce() {
|
|
2302
|
-
if (this.isDestroyed) return;
|
|
2303
2685
|
this.run();
|
|
2304
2686
|
}
|
|
2687
|
+
subscribeToDeps() {
|
|
2688
|
+
if (this.sourceUnsubscribers.length > 0 || this.computedUnsubscribers.length > 0)
|
|
2689
|
+
return;
|
|
2690
|
+
for (const dep of this.sourceDeps) {
|
|
2691
|
+
this.sourceUnsubscribers.push(
|
|
2692
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2693
|
+
);
|
|
2694
|
+
}
|
|
2695
|
+
for (const dep of this.computedDeps) {
|
|
2696
|
+
this.computedUnsubscribers.push(
|
|
2697
|
+
dep.subscribe(this.onComputedInvalidate)
|
|
2698
|
+
);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
unsubscribeFromSourceDeps() {
|
|
2702
|
+
if (this.sourceUnsubscribers.length === 0) return;
|
|
2703
|
+
for (const unsubscribe of this.sourceUnsubscribers) unsubscribe();
|
|
2704
|
+
this.sourceUnsubscribers = [];
|
|
2705
|
+
}
|
|
2706
|
+
unsubscribeFromAllDeps() {
|
|
2707
|
+
this.unsubscribeFromSourceDeps();
|
|
2708
|
+
if (this.computedUnsubscribers.length === 0) return;
|
|
2709
|
+
for (const unsubscribe of this.computedUnsubscribers) unsubscribe();
|
|
2710
|
+
this.computedUnsubscribers = [];
|
|
2711
|
+
}
|
|
2712
|
+
ensureResubscribeAfterFlush() {
|
|
2713
|
+
if (this.isResubscribeEnqueued) return;
|
|
2714
|
+
this.isResubscribeEnqueued = true;
|
|
2715
|
+
this.dequeueResubscribe = this.runtime.scheduleAfterFlush(
|
|
2716
|
+
this.onAfterFlush
|
|
2717
|
+
);
|
|
2718
|
+
}
|
|
2305
2719
|
};
|
|
2306
2720
|
|
|
2307
|
-
// src/modules/effect/enum/EOIMEffectPhase.ts
|
|
2308
|
-
var EOIMEffectPhase = /* @__PURE__ */ ((EOIMEffectPhase2) => {
|
|
2309
|
-
EOIMEffectPhase2["PRE"] = "pre";
|
|
2310
|
-
EOIMEffectPhase2["HANDLERS"] = "handlers";
|
|
2311
|
-
return EOIMEffectPhase2;
|
|
2312
|
-
})(EOIMEffectPhase || {});
|
|
2313
|
-
|
|
2314
2721
|
// src/modules/computed/enum/EOIMComputedEventType.ts
|
|
2315
2722
|
var EOIMComputedEventType = /* @__PURE__ */ ((EOIMComputedEventType2) => {
|
|
2316
2723
|
EOIMComputedEventType2["UPDATE"] = "update";
|
|
2317
2724
|
return EOIMComputedEventType2;
|
|
2318
2725
|
})(EOIMComputedEventType || {});
|
|
2319
2726
|
|
|
2320
|
-
// src/modules/computed/core/OIMUpdateEventCoalescerComputed.ts
|
|
2321
|
-
var OIMUpdateEventCoalescerComputed = class extends OIMUpdateEventCoalescer {
|
|
2322
|
-
constructor(computedEmitter) {
|
|
2323
|
-
super();
|
|
2324
|
-
this.computedEmitter = computedEmitter;
|
|
2325
|
-
this.handleUpdate = (payload) => {
|
|
2326
|
-
this.addUpdatedKeys(payload.keys);
|
|
2327
|
-
};
|
|
2328
|
-
this.computedEmitter.on(
|
|
2329
|
-
"update" /* UPDATE */,
|
|
2330
|
-
this.handleUpdate
|
|
2331
|
-
);
|
|
2332
|
-
}
|
|
2333
|
-
destroy() {
|
|
2334
|
-
this.computedEmitter.off(
|
|
2335
|
-
"update" /* UPDATE */,
|
|
2336
|
-
this.handleUpdate
|
|
2337
|
-
);
|
|
2338
|
-
this.emitter.offAll();
|
|
2339
|
-
this.clearUpdatedKeys();
|
|
2340
|
-
}
|
|
2341
|
-
};
|
|
2342
|
-
|
|
2343
2727
|
// src/modules/computed/core/OIMComputed.ts
|
|
2344
2728
|
var OIMComputed = class {
|
|
2345
|
-
constructor(
|
|
2729
|
+
constructor(runtime, opts) {
|
|
2346
2730
|
this.emitter = new OIMEventEmitter();
|
|
2347
2731
|
this.hasValue = false;
|
|
2348
2732
|
this.isDirty = true;
|
|
2349
|
-
this.
|
|
2350
|
-
this.hasRecomputedInThisFlush = false;
|
|
2351
|
-
this.handleQueueBeforeFlush = () => {
|
|
2352
|
-
this.isInFlush = true;
|
|
2353
|
-
this.hasRecomputedInThisFlush = false;
|
|
2354
|
-
};
|
|
2355
|
-
this.handleQueueAfterFlush = () => {
|
|
2356
|
-
this.isInFlush = false;
|
|
2357
|
-
this.hasRecomputedInThisFlush = false;
|
|
2358
|
-
};
|
|
2359
|
-
this.queue = queue;
|
|
2733
|
+
this.runtime = runtime;
|
|
2360
2734
|
this.compute = opts.compute;
|
|
2361
2735
|
this.compare = opts.compare ?? Object.is;
|
|
2362
2736
|
this.deps = opts.deps ?? [];
|
|
2363
|
-
this.
|
|
2364
|
-
this.
|
|
2365
|
-
|
|
2366
|
-
this.updateEventEmitter = new OIMUpdateEventEmitter({
|
|
2367
|
-
coalescer: this.coalescer,
|
|
2368
|
-
queue: this.queue
|
|
2369
|
-
});
|
|
2370
|
-
this.queue.emitter.on(
|
|
2371
|
-
1 /* BEFORE_FLUSH */,
|
|
2372
|
-
this.handleQueueBeforeFlush
|
|
2737
|
+
this.updateEventEmitter = new OIMUpdateEventEmitter(
|
|
2738
|
+
this.runtime.queue,
|
|
2739
|
+
"immediate"
|
|
2373
2740
|
);
|
|
2374
|
-
this.
|
|
2375
|
-
0 /* AFTER_FLUSH */,
|
|
2376
|
-
this.handleQueueAfterFlush
|
|
2377
|
-
);
|
|
2378
|
-
this.effect = new OIMEffect(this.queue, {
|
|
2741
|
+
this.effect = new OIMEffect(this.runtime, {
|
|
2379
2742
|
deps: this.deps,
|
|
2380
|
-
|
|
2381
|
-
onInvalidate: () => {
|
|
2743
|
+
onUpdate: () => {
|
|
2382
2744
|
this.isDirty = true;
|
|
2383
2745
|
},
|
|
2384
2746
|
run: () => {
|
|
2385
|
-
if (this.isInFlush) {
|
|
2386
|
-
if (this.hasRecomputedInThisFlush) return;
|
|
2387
|
-
this.hasRecomputedInThisFlush = true;
|
|
2388
|
-
}
|
|
2389
2747
|
this.recomputeAndEmitIfChanged();
|
|
2390
2748
|
}
|
|
2391
2749
|
});
|
|
@@ -2399,16 +2757,7 @@ var OIMComputed = class {
|
|
|
2399
2757
|
}
|
|
2400
2758
|
destroy() {
|
|
2401
2759
|
this.effect.destroy();
|
|
2402
|
-
this.queue.emitter.off(
|
|
2403
|
-
1 /* BEFORE_FLUSH */,
|
|
2404
|
-
this.handleQueueBeforeFlush
|
|
2405
|
-
);
|
|
2406
|
-
this.queue.emitter.off(
|
|
2407
|
-
0 /* AFTER_FLUSH */,
|
|
2408
|
-
this.handleQueueAfterFlush
|
|
2409
|
-
);
|
|
2410
2760
|
this.updateEventEmitter.destroy();
|
|
2411
|
-
this.coalescer.destroy();
|
|
2412
2761
|
this.emitter.offAll();
|
|
2413
2762
|
}
|
|
2414
2763
|
recomputeAndEmitIfChanged() {
|
|
@@ -2424,6 +2773,7 @@ var OIMComputed = class {
|
|
|
2424
2773
|
this.emitter.emit("update" /* UPDATE */, {
|
|
2425
2774
|
keys: ["value"]
|
|
2426
2775
|
});
|
|
2776
|
+
this.updateEventEmitter.markUpdatedKey("value");
|
|
2427
2777
|
}
|
|
2428
2778
|
};
|
|
2429
2779
|
|
|
@@ -2432,31 +2782,21 @@ function isReadonlyArray(value) {
|
|
|
2432
2782
|
return Array.isArray(value);
|
|
2433
2783
|
}
|
|
2434
2784
|
var OIMEffectDependencyKeyed = class {
|
|
2435
|
-
constructor(
|
|
2436
|
-
this.
|
|
2785
|
+
constructor(subscription, keyOrKeys) {
|
|
2786
|
+
this.subscription = subscription;
|
|
2437
2787
|
if (isReadonlyArray(keyOrKeys)) {
|
|
2438
2788
|
this.keys = keyOrKeys;
|
|
2439
2789
|
} else {
|
|
2440
2790
|
this.key = keyOrKeys;
|
|
2441
2791
|
}
|
|
2442
2792
|
}
|
|
2443
|
-
subscribe(
|
|
2444
|
-
const isPre = phase === "pre" /* PRE */;
|
|
2793
|
+
subscribe(onUpdate) {
|
|
2445
2794
|
if (this.keys !== void 0) {
|
|
2446
|
-
return
|
|
2447
|
-
this.keys,
|
|
2448
|
-
onInvalidate
|
|
2449
|
-
) : this.updateEventEmitter.subscribeOnKeys(
|
|
2450
|
-
this.keys,
|
|
2451
|
-
onInvalidate
|
|
2452
|
-
);
|
|
2795
|
+
return this.subscription.subscribeOnKeys(this.keys, onUpdate);
|
|
2453
2796
|
}
|
|
2454
2797
|
if (this.key === void 0) return () => {
|
|
2455
2798
|
};
|
|
2456
|
-
return
|
|
2457
|
-
this.key,
|
|
2458
|
-
onInvalidate
|
|
2459
|
-
) : this.updateEventEmitter.subscribeOnKey(this.key, onInvalidate);
|
|
2799
|
+
return this.subscription.subscribeOnKey(this.key, onUpdate);
|
|
2460
2800
|
}
|
|
2461
2801
|
};
|
|
2462
2802
|
|
|
@@ -2464,12 +2804,12 @@ var OIMEffectDependencyKeyed = class {
|
|
|
2464
2804
|
var OIMEffectDependencyKeyedObject = class {
|
|
2465
2805
|
constructor(object, keyOrKeys) {
|
|
2466
2806
|
this.dep = new OIMEffectDependencyKeyed(
|
|
2467
|
-
object
|
|
2807
|
+
object,
|
|
2468
2808
|
keyOrKeys
|
|
2469
2809
|
);
|
|
2470
2810
|
}
|
|
2471
|
-
subscribe(
|
|
2472
|
-
return this.dep.subscribe(
|
|
2811
|
+
subscribe(onUpdate) {
|
|
2812
|
+
return this.dep.subscribe(onUpdate);
|
|
2473
2813
|
}
|
|
2474
2814
|
};
|
|
2475
2815
|
|
|
@@ -2477,12 +2817,12 @@ var OIMEffectDependencyKeyedObject = class {
|
|
|
2477
2817
|
var OIMEffectDependencyKeyedCollection = class {
|
|
2478
2818
|
constructor(collection, pkOrPks) {
|
|
2479
2819
|
this.dep = new OIMEffectDependencyKeyed(
|
|
2480
|
-
collection
|
|
2820
|
+
collection,
|
|
2481
2821
|
pkOrPks
|
|
2482
2822
|
);
|
|
2483
2823
|
}
|
|
2484
|
-
subscribe(
|
|
2485
|
-
return this.dep.subscribe(
|
|
2824
|
+
subscribe(onUpdate) {
|
|
2825
|
+
return this.dep.subscribe(onUpdate);
|
|
2486
2826
|
}
|
|
2487
2827
|
};
|
|
2488
2828
|
|
|
@@ -2490,45 +2830,610 @@ var OIMEffectDependencyKeyedCollection = class {
|
|
|
2490
2830
|
var OIMEffectDependencyKeyedIndex = class {
|
|
2491
2831
|
constructor(index, keyOrKeys) {
|
|
2492
2832
|
this.dep = new OIMEffectDependencyKeyed(
|
|
2493
|
-
index
|
|
2833
|
+
index,
|
|
2494
2834
|
keyOrKeys
|
|
2495
2835
|
);
|
|
2496
2836
|
}
|
|
2497
|
-
subscribe(
|
|
2498
|
-
return this.dep.subscribe(
|
|
2837
|
+
subscribe(onUpdate) {
|
|
2838
|
+
return this.dep.subscribe(onUpdate);
|
|
2499
2839
|
}
|
|
2500
2840
|
};
|
|
2501
2841
|
|
|
2502
|
-
// src/modules/
|
|
2503
|
-
var
|
|
2504
|
-
constructor(
|
|
2505
|
-
this.
|
|
2842
|
+
// src/modules/selector/core/OIMSelector.ts
|
|
2843
|
+
var OIMSelector = class {
|
|
2844
|
+
constructor(runtime, sourceDeps, computedDeps = []) {
|
|
2845
|
+
this.runtime = runtime;
|
|
2846
|
+
this.sourceDeps = sourceDeps;
|
|
2847
|
+
this.computedDeps = computedDeps;
|
|
2848
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
2849
|
+
this.sourceUnsubscribers = [];
|
|
2850
|
+
this.computedUnsubscribers = [];
|
|
2851
|
+
this.isResubscribeEnqueued = false;
|
|
2852
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2853
|
+
this.isDeliveryEnqueued = false;
|
|
2854
|
+
this.hasLastValue = false;
|
|
2855
|
+
this.onSourceInvalidate = () => {
|
|
2856
|
+
if (this.listeners.size === 0) return;
|
|
2857
|
+
if (!this.isTemporarilyUnsubscribedForFlush) {
|
|
2858
|
+
this.isTemporarilyUnsubscribedForFlush = true;
|
|
2859
|
+
this.unsubscribeFromSourceDeps();
|
|
2860
|
+
this.ensureResubscribeAfterFlush();
|
|
2861
|
+
}
|
|
2862
|
+
if (this.isDeliveryEnqueued) return;
|
|
2863
|
+
this.isDeliveryEnqueued = true;
|
|
2864
|
+
this.dequeueDelivery = this.runtime.schedule(this.deliver);
|
|
2865
|
+
};
|
|
2866
|
+
this.onComputedInvalidate = () => {
|
|
2867
|
+
if (this.listeners.size === 0) return;
|
|
2868
|
+
if (this.isDeliveryEnqueued) return;
|
|
2869
|
+
this.isDeliveryEnqueued = true;
|
|
2870
|
+
this.dequeueDelivery = this.runtime.schedule(this.deliver);
|
|
2871
|
+
};
|
|
2872
|
+
this.deliver = () => {
|
|
2873
|
+
this.isDeliveryEnqueued = false;
|
|
2874
|
+
this.dequeueDelivery = void 0;
|
|
2875
|
+
if (this.listeners.size === 0) return;
|
|
2876
|
+
const next = this.getValue();
|
|
2877
|
+
if (this.hasLastValue && this.areEqual(this.lastValue, next)) return;
|
|
2878
|
+
this.setLastValue(next);
|
|
2879
|
+
const snapshot = Array.from(this.listeners);
|
|
2880
|
+
for (let i = 0; i < snapshot.length; i++) {
|
|
2881
|
+
const listener = snapshot[i];
|
|
2882
|
+
if (this.listeners.has(listener)) listener(next);
|
|
2883
|
+
}
|
|
2884
|
+
};
|
|
2885
|
+
this.onAfterFlush = () => {
|
|
2886
|
+
if (!this.isResubscribeEnqueued) return;
|
|
2887
|
+
this.isResubscribeEnqueued = false;
|
|
2888
|
+
this.dequeueResubscribe = void 0;
|
|
2889
|
+
if (this.listeners.size === 0) return;
|
|
2890
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2891
|
+
if (this.sourceUnsubscribers.length === 0) {
|
|
2892
|
+
for (const dep of this.sourceDeps) {
|
|
2893
|
+
this.sourceUnsubscribers.push(
|
|
2894
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2895
|
+
);
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
};
|
|
2899
|
+
}
|
|
2900
|
+
get queue() {
|
|
2901
|
+
return this.runtime.queue;
|
|
2902
|
+
}
|
|
2903
|
+
/**
|
|
2904
|
+
* Start watching this selector. The callback is called immediately with the current value,
|
|
2905
|
+
* then coalesced and delivered on `queue.flush()` when the selector invalidates.
|
|
2906
|
+
*/
|
|
2907
|
+
watch(onValue) {
|
|
2908
|
+
this.listeners.add(onValue);
|
|
2909
|
+
if (this.listeners.size === 1) {
|
|
2910
|
+
this.subscribeToDeps();
|
|
2911
|
+
}
|
|
2912
|
+
const current = this.getValue();
|
|
2913
|
+
this.setLastValue(current);
|
|
2914
|
+
onValue(current);
|
|
2915
|
+
return () => {
|
|
2916
|
+
this.listeners.delete(onValue);
|
|
2917
|
+
if (this.listeners.size > 0) return;
|
|
2918
|
+
this.unsubscribeFromAllDeps();
|
|
2919
|
+
if (this.dequeueResubscribe) {
|
|
2920
|
+
this.dequeueResubscribe();
|
|
2921
|
+
this.dequeueResubscribe = void 0;
|
|
2922
|
+
}
|
|
2923
|
+
this.isResubscribeEnqueued = false;
|
|
2924
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
2925
|
+
if (this.dequeueDelivery) {
|
|
2926
|
+
this.dequeueDelivery();
|
|
2927
|
+
this.dequeueDelivery = void 0;
|
|
2928
|
+
}
|
|
2929
|
+
this.isDeliveryEnqueued = false;
|
|
2930
|
+
this.hasLastValue = false;
|
|
2931
|
+
};
|
|
2932
|
+
}
|
|
2933
|
+
areEqual(prev, next) {
|
|
2934
|
+
return Object.is(prev, next);
|
|
2935
|
+
}
|
|
2936
|
+
setLastValue(value) {
|
|
2937
|
+
this.lastValue = value;
|
|
2938
|
+
this.hasLastValue = true;
|
|
2939
|
+
}
|
|
2940
|
+
subscribeToDeps() {
|
|
2941
|
+
if (this.sourceUnsubscribers.length > 0 || this.computedUnsubscribers.length > 0)
|
|
2942
|
+
return;
|
|
2943
|
+
for (const dep of this.sourceDeps) {
|
|
2944
|
+
this.sourceUnsubscribers.push(
|
|
2945
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
2946
|
+
);
|
|
2947
|
+
}
|
|
2948
|
+
for (const dep of this.computedDeps) {
|
|
2949
|
+
this.computedUnsubscribers.push(
|
|
2950
|
+
dep.subscribe(this.onComputedInvalidate)
|
|
2951
|
+
);
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2954
|
+
unsubscribeFromSourceDeps() {
|
|
2955
|
+
if (this.sourceUnsubscribers.length === 0) return;
|
|
2956
|
+
for (const unsub of this.sourceUnsubscribers) unsub();
|
|
2957
|
+
this.sourceUnsubscribers = [];
|
|
2958
|
+
}
|
|
2959
|
+
unsubscribeFromAllDeps() {
|
|
2960
|
+
this.unsubscribeFromSourceDeps();
|
|
2961
|
+
if (this.computedUnsubscribers.length === 0) return;
|
|
2962
|
+
for (const unsub of this.computedUnsubscribers) unsub();
|
|
2963
|
+
this.computedUnsubscribers = [];
|
|
2964
|
+
}
|
|
2965
|
+
ensureResubscribeAfterFlush() {
|
|
2966
|
+
if (this.isResubscribeEnqueued) return;
|
|
2967
|
+
this.isResubscribeEnqueued = true;
|
|
2968
|
+
this.dequeueResubscribe = this.runtime.scheduleAfterFlush(
|
|
2969
|
+
this.onAfterFlush
|
|
2970
|
+
);
|
|
2971
|
+
}
|
|
2972
|
+
};
|
|
2973
|
+
|
|
2974
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyUpdateEventEmitterKey.ts
|
|
2975
|
+
var OIMSelectorSourceDependencyUpdateEventEmitterKey = class {
|
|
2976
|
+
constructor(subscription, key) {
|
|
2977
|
+
this.subscription = subscription;
|
|
2978
|
+
this.key = key;
|
|
2979
|
+
}
|
|
2980
|
+
subscribe(onUpdate) {
|
|
2981
|
+
return this.subscription.subscribeOnKey(this.key, onUpdate);
|
|
2982
|
+
}
|
|
2983
|
+
};
|
|
2984
|
+
|
|
2985
|
+
// src/modules/selector/core/OIMCollectionByPkSelector.ts
|
|
2986
|
+
var OIMCollectionByPkSelector = class extends OIMSelector {
|
|
2987
|
+
constructor(runtime, collection, pk) {
|
|
2988
|
+
super(runtime, [
|
|
2989
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
2990
|
+
collection,
|
|
2991
|
+
pk
|
|
2992
|
+
)
|
|
2993
|
+
]);
|
|
2994
|
+
this.collection = collection;
|
|
2995
|
+
this.pk = pk;
|
|
2996
|
+
}
|
|
2997
|
+
getValue() {
|
|
2998
|
+
return this.collection.getOneByPk(this.pk);
|
|
2999
|
+
}
|
|
3000
|
+
};
|
|
3001
|
+
|
|
3002
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyUpdateEventEmitterKeys.ts
|
|
3003
|
+
var OIMSelectorSourceDependencyUpdateEventEmitterKeys = class {
|
|
3004
|
+
constructor(subscription, keys) {
|
|
3005
|
+
this.subscription = subscription;
|
|
3006
|
+
this.keys = keys;
|
|
3007
|
+
}
|
|
3008
|
+
subscribe(onUpdate) {
|
|
3009
|
+
return this.subscription.subscribeOnKeys(this.keys, onUpdate);
|
|
3010
|
+
}
|
|
3011
|
+
};
|
|
3012
|
+
|
|
3013
|
+
// src/modules/selector/core/OIMCollectionByPksSelector.ts
|
|
3014
|
+
var OIMCollectionByPksSelector = class extends OIMSelector {
|
|
3015
|
+
constructor(runtime, collection, pks) {
|
|
3016
|
+
super(runtime, [
|
|
3017
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
3018
|
+
collection,
|
|
3019
|
+
pks
|
|
3020
|
+
)
|
|
3021
|
+
]);
|
|
3022
|
+
this.collection = collection;
|
|
3023
|
+
this.pks = pks;
|
|
3024
|
+
}
|
|
3025
|
+
getValue() {
|
|
3026
|
+
return this.pks.map((pk) => this.collection.getOneByPk(pk));
|
|
3027
|
+
}
|
|
3028
|
+
areEqual(prev, next) {
|
|
3029
|
+
if (prev === next) return true;
|
|
3030
|
+
if (prev.length !== next.length) return false;
|
|
3031
|
+
for (let i = 0; i < prev.length; i++) {
|
|
3032
|
+
if (prev[i] !== next[i]) return false;
|
|
3033
|
+
}
|
|
3034
|
+
return true;
|
|
3035
|
+
}
|
|
3036
|
+
};
|
|
3037
|
+
|
|
3038
|
+
// src/modules/selector/core/OIMObjectValueByKeySelector.ts
|
|
3039
|
+
var OIMObjectValueByKeySelector = class extends OIMSelector {
|
|
3040
|
+
constructor(runtime, obj, key) {
|
|
3041
|
+
super(runtime, [
|
|
3042
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
3043
|
+
obj,
|
|
3044
|
+
key
|
|
3045
|
+
)
|
|
3046
|
+
]);
|
|
3047
|
+
this.obj = obj;
|
|
3048
|
+
this.key = key;
|
|
3049
|
+
}
|
|
3050
|
+
getValue() {
|
|
3051
|
+
return this.obj.get(this.key);
|
|
3052
|
+
}
|
|
3053
|
+
};
|
|
3054
|
+
|
|
3055
|
+
// src/modules/selector/core/OIMObjectValuesByKeysSelector.ts
|
|
3056
|
+
var OIMObjectValuesByKeysSelector = class extends OIMSelector {
|
|
3057
|
+
constructor(runtime, obj, keys) {
|
|
3058
|
+
super(runtime, [
|
|
3059
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
3060
|
+
obj,
|
|
3061
|
+
keys
|
|
3062
|
+
)
|
|
3063
|
+
]);
|
|
3064
|
+
this.obj = obj;
|
|
3065
|
+
this.keys = keys;
|
|
3066
|
+
}
|
|
3067
|
+
getValue() {
|
|
3068
|
+
return this.keys.map((k) => this.obj.get(k));
|
|
3069
|
+
}
|
|
3070
|
+
areEqual(prev, next) {
|
|
3071
|
+
if (prev === next) return true;
|
|
3072
|
+
if (prev.length !== next.length) return false;
|
|
3073
|
+
for (let i = 0; i < prev.length; i++) {
|
|
3074
|
+
if (prev[i] !== next[i]) return false;
|
|
3075
|
+
}
|
|
3076
|
+
return true;
|
|
3077
|
+
}
|
|
3078
|
+
};
|
|
3079
|
+
|
|
3080
|
+
// src/modules/selector/core/OIMIndexPksByKeySetBasedSelector.ts
|
|
3081
|
+
var OIMIndexPksByKeySetBasedSelector = class extends OIMSelector {
|
|
3082
|
+
constructor(runtime, reactiveIndex, key) {
|
|
3083
|
+
super(runtime, [
|
|
3084
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
3085
|
+
reactiveIndex,
|
|
3086
|
+
key
|
|
3087
|
+
)
|
|
3088
|
+
]);
|
|
3089
|
+
this.reactiveIndex = reactiveIndex;
|
|
3090
|
+
this.key = key;
|
|
3091
|
+
}
|
|
3092
|
+
getValue() {
|
|
3093
|
+
return this.reactiveIndex.getPksByKey(this.key);
|
|
3094
|
+
}
|
|
3095
|
+
};
|
|
3096
|
+
|
|
3097
|
+
// src/modules/selector/core/OIMIndexPksByKeyArrayBasedSelector.ts
|
|
3098
|
+
var OIMIndexPksByKeyArrayBasedSelector = class extends OIMSelector {
|
|
3099
|
+
constructor(runtime, reactiveIndex, key) {
|
|
3100
|
+
super(runtime, [
|
|
3101
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKey(
|
|
3102
|
+
reactiveIndex,
|
|
3103
|
+
key
|
|
3104
|
+
)
|
|
3105
|
+
]);
|
|
3106
|
+
this.reactiveIndex = reactiveIndex;
|
|
3107
|
+
this.key = key;
|
|
3108
|
+
}
|
|
3109
|
+
getValue() {
|
|
3110
|
+
return this.reactiveIndex.getPksByKey(this.key);
|
|
3111
|
+
}
|
|
3112
|
+
areEqual(prev, next) {
|
|
3113
|
+
if (prev === next) return true;
|
|
3114
|
+
if (prev.length !== next.length) return false;
|
|
3115
|
+
for (let i = 0; i < prev.length; i++)
|
|
3116
|
+
if (prev[i] !== next[i]) return false;
|
|
3117
|
+
return true;
|
|
3118
|
+
}
|
|
3119
|
+
};
|
|
3120
|
+
|
|
3121
|
+
// src/modules/selector/core/OIMIndexPksByKeysSetBasedSelector.ts
|
|
3122
|
+
var OIMIndexPksByKeysSetBasedSelector = class extends OIMSelector {
|
|
3123
|
+
constructor(runtime, reactiveIndex, keys) {
|
|
3124
|
+
super(runtime, [
|
|
3125
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
3126
|
+
reactiveIndex,
|
|
3127
|
+
keys
|
|
3128
|
+
)
|
|
3129
|
+
]);
|
|
3130
|
+
this.reactiveIndex = reactiveIndex;
|
|
3131
|
+
this.keys = keys;
|
|
3132
|
+
}
|
|
3133
|
+
getValue() {
|
|
3134
|
+
return this.keys.map((key) => Array.from(this.reactiveIndex.getPksByKey(key))).flat();
|
|
3135
|
+
}
|
|
3136
|
+
areEqual(prev, next) {
|
|
3137
|
+
if (prev === next) return true;
|
|
3138
|
+
if (prev.length !== next.length) return false;
|
|
3139
|
+
for (let i = 0; i < prev.length; i++)
|
|
3140
|
+
if (prev[i] !== next[i]) return false;
|
|
3141
|
+
return true;
|
|
3142
|
+
}
|
|
3143
|
+
};
|
|
3144
|
+
|
|
3145
|
+
// src/modules/selector/core/OIMIndexPksByKeysArrayBasedSelector.ts
|
|
3146
|
+
var OIMIndexPksByKeysArrayBasedSelector = class extends OIMSelector {
|
|
3147
|
+
constructor(runtime, reactiveIndex, keys) {
|
|
3148
|
+
super(runtime, [
|
|
3149
|
+
new OIMSelectorSourceDependencyUpdateEventEmitterKeys(
|
|
3150
|
+
reactiveIndex,
|
|
3151
|
+
keys
|
|
3152
|
+
)
|
|
3153
|
+
]);
|
|
3154
|
+
this.reactiveIndex = reactiveIndex;
|
|
3155
|
+
this.keys = keys;
|
|
3156
|
+
}
|
|
3157
|
+
getValue() {
|
|
3158
|
+
return this.keys.map((key) => this.reactiveIndex.getPksByKey(key)).flat();
|
|
3159
|
+
}
|
|
3160
|
+
areEqual(prev, next) {
|
|
3161
|
+
if (prev === next) return true;
|
|
3162
|
+
if (prev.length !== next.length) return false;
|
|
3163
|
+
for (let i = 0; i < prev.length; i++)
|
|
3164
|
+
if (prev[i] !== next[i]) return false;
|
|
3165
|
+
return true;
|
|
3166
|
+
}
|
|
3167
|
+
};
|
|
3168
|
+
|
|
3169
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyEntitiesByIndexKeySetBased.ts
|
|
3170
|
+
var OIMSelectorSourceDependencyEntitiesByIndexKeySetBased = class {
|
|
3171
|
+
constructor(collection, reactiveIndex, key) {
|
|
3172
|
+
this.collection = collection;
|
|
3173
|
+
this.reactiveIndex = reactiveIndex;
|
|
3174
|
+
this.key = key;
|
|
3175
|
+
this.currentPks = [];
|
|
3176
|
+
}
|
|
3177
|
+
subscribe(onUpdate) {
|
|
3178
|
+
const resubscribeCollection = () => {
|
|
3179
|
+
const nextPks = Array.from(
|
|
3180
|
+
this.reactiveIndex.getSlotsByKey(this.key),
|
|
3181
|
+
(slot) => slot.pk
|
|
3182
|
+
);
|
|
3183
|
+
if (this.sameArray(this.currentPks, nextPks)) return;
|
|
3184
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
3185
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
3186
|
+
this.currentPks = nextPks;
|
|
3187
|
+
if (this.currentPks.length === 0) return;
|
|
3188
|
+
this.unsubscribeFromCollectionKeys = this.collection.subscribeOnKeys(this.currentPks, onUpdate);
|
|
3189
|
+
};
|
|
3190
|
+
const onIndexUpdate = () => {
|
|
3191
|
+
resubscribeCollection();
|
|
3192
|
+
onUpdate();
|
|
3193
|
+
};
|
|
3194
|
+
resubscribeCollection();
|
|
3195
|
+
const unsubscribeFromIndex = this.reactiveIndex.subscribeOnKey(
|
|
3196
|
+
this.key,
|
|
3197
|
+
onIndexUpdate
|
|
3198
|
+
);
|
|
3199
|
+
return () => {
|
|
3200
|
+
unsubscribeFromIndex();
|
|
3201
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
3202
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
3203
|
+
this.currentPks = [];
|
|
3204
|
+
};
|
|
2506
3205
|
}
|
|
2507
|
-
|
|
2508
|
-
if (
|
|
2509
|
-
|
|
3206
|
+
sameArray(a, b) {
|
|
3207
|
+
if (a === b) return true;
|
|
3208
|
+
if (a.length !== b.length) return false;
|
|
3209
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
3210
|
+
return true;
|
|
3211
|
+
}
|
|
3212
|
+
};
|
|
3213
|
+
|
|
3214
|
+
// src/modules/selector/core/OIMEntitiesByIndexKeySetBasedSelector.ts
|
|
3215
|
+
var OIMEntitiesByIndexKeySetBasedSelector = class extends OIMSelector {
|
|
3216
|
+
constructor(runtime, collection, reactiveIndex, key) {
|
|
3217
|
+
super(runtime, [
|
|
3218
|
+
new OIMSelectorSourceDependencyEntitiesByIndexKeySetBased(collection, reactiveIndex, key)
|
|
3219
|
+
]);
|
|
3220
|
+
this.collection = collection;
|
|
3221
|
+
this.reactiveIndex = reactiveIndex;
|
|
3222
|
+
this.key = key;
|
|
3223
|
+
this.reactiveIndex.index.setSlotResolver(
|
|
3224
|
+
(pk) => this.collection.getSlotByPk(pk)
|
|
3225
|
+
);
|
|
3226
|
+
}
|
|
3227
|
+
getValue() {
|
|
3228
|
+
const slots = this.reactiveIndex.getSlotsByKey(this.key);
|
|
3229
|
+
const entities = [];
|
|
3230
|
+
entities.length = slots.size;
|
|
3231
|
+
let writeIndex = 0;
|
|
3232
|
+
for (const slot of slots) {
|
|
3233
|
+
entities[writeIndex++] = slot.item;
|
|
2510
3234
|
}
|
|
2511
|
-
return
|
|
2512
|
-
|
|
2513
|
-
|
|
3235
|
+
return entities;
|
|
3236
|
+
}
|
|
3237
|
+
areEqual(prev, next) {
|
|
3238
|
+
if (prev === next) return true;
|
|
3239
|
+
if (prev.length !== next.length) return false;
|
|
3240
|
+
for (let i = 0; i < prev.length; i++)
|
|
3241
|
+
if (prev[i] !== next[i]) return false;
|
|
3242
|
+
return true;
|
|
3243
|
+
}
|
|
3244
|
+
};
|
|
3245
|
+
|
|
3246
|
+
// src/modules/selector/core/OIMSelectorSourceDependencyEntitiesByIndexKeyArrayBased.ts
|
|
3247
|
+
var OIMSelectorSourceDependencyEntitiesByIndexKeyArrayBased = class {
|
|
3248
|
+
constructor(collection, reactiveIndex, key) {
|
|
3249
|
+
this.collection = collection;
|
|
3250
|
+
this.reactiveIndex = reactiveIndex;
|
|
3251
|
+
this.key = key;
|
|
3252
|
+
this.currentPks = [];
|
|
3253
|
+
}
|
|
3254
|
+
subscribe(onUpdate) {
|
|
3255
|
+
const resubscribeCollection = () => {
|
|
3256
|
+
const nextPks = this.reactiveIndex.getSlotsByKey(this.key).map((slot) => slot.pk);
|
|
3257
|
+
if (this.sameArray(this.currentPks, nextPks)) return;
|
|
3258
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
3259
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
3260
|
+
this.currentPks = nextPks;
|
|
3261
|
+
if (this.currentPks.length === 0) return;
|
|
3262
|
+
this.unsubscribeFromCollectionKeys = this.collection.subscribeOnKeys(this.currentPks, onUpdate);
|
|
3263
|
+
};
|
|
3264
|
+
const onIndexUpdate = () => {
|
|
3265
|
+
resubscribeCollection();
|
|
3266
|
+
onUpdate();
|
|
3267
|
+
};
|
|
3268
|
+
resubscribeCollection();
|
|
3269
|
+
const unsubscribeFromIndex = this.reactiveIndex.subscribeOnKey(
|
|
3270
|
+
this.key,
|
|
3271
|
+
onIndexUpdate
|
|
3272
|
+
);
|
|
3273
|
+
return () => {
|
|
3274
|
+
unsubscribeFromIndex();
|
|
3275
|
+
this.unsubscribeFromCollectionKeys?.();
|
|
3276
|
+
this.unsubscribeFromCollectionKeys = void 0;
|
|
3277
|
+
this.currentPks = [];
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
sameArray(a, b) {
|
|
3281
|
+
if (a === b) return true;
|
|
3282
|
+
if (a.length !== b.length) return false;
|
|
3283
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;
|
|
3284
|
+
return true;
|
|
3285
|
+
}
|
|
3286
|
+
};
|
|
3287
|
+
|
|
3288
|
+
// src/modules/selector/core/OIMEntitiesByIndexKeyArrayBasedSelector.ts
|
|
3289
|
+
var OIMEntitiesByIndexKeyArrayBasedSelector = class extends OIMSelector {
|
|
3290
|
+
constructor(runtime, collection, reactiveIndex, key) {
|
|
3291
|
+
super(runtime, [
|
|
3292
|
+
new OIMSelectorSourceDependencyEntitiesByIndexKeyArrayBased(collection, reactiveIndex, key)
|
|
3293
|
+
]);
|
|
3294
|
+
this.collection = collection;
|
|
3295
|
+
this.reactiveIndex = reactiveIndex;
|
|
3296
|
+
this.key = key;
|
|
3297
|
+
this.reactiveIndex.index.setSlotResolver(
|
|
3298
|
+
(pk) => this.collection.getSlotByPk(pk)
|
|
2514
3299
|
);
|
|
2515
3300
|
}
|
|
3301
|
+
getValue() {
|
|
3302
|
+
const slots = this.reactiveIndex.getSlotsByKey(this.key);
|
|
3303
|
+
const entities = [];
|
|
3304
|
+
entities.length = slots.length;
|
|
3305
|
+
for (let i = 0; i < slots.length; i++) {
|
|
3306
|
+
entities[i] = slots[i].item;
|
|
3307
|
+
}
|
|
3308
|
+
return entities;
|
|
3309
|
+
}
|
|
3310
|
+
areEqual(prev, next) {
|
|
3311
|
+
if (prev === next) return true;
|
|
3312
|
+
if (prev.length !== next.length) return false;
|
|
3313
|
+
for (let i = 0; i < prev.length; i++)
|
|
3314
|
+
if (prev[i] !== next[i]) return false;
|
|
3315
|
+
return true;
|
|
3316
|
+
}
|
|
3317
|
+
};
|
|
3318
|
+
|
|
3319
|
+
// src/modules/computative/core/OIMComputativeRuntime.ts
|
|
3320
|
+
var OIMComputativeRuntime = class {
|
|
3321
|
+
constructor(queue) {
|
|
3322
|
+
this.queue = queue;
|
|
3323
|
+
this.isFlushScheduled = false;
|
|
3324
|
+
this.isFlushing = false;
|
|
3325
|
+
this.minLevel = Infinity;
|
|
3326
|
+
this.maxLevel = -Infinity;
|
|
3327
|
+
this.dirtyByLevel = /* @__PURE__ */ new Map();
|
|
3328
|
+
this.afterFlushTasks = /* @__PURE__ */ new Set();
|
|
3329
|
+
this.queue.emitter.on(0 /* AFTER_FLUSH */, () => {
|
|
3330
|
+
if (!this.isFlushScheduled) return;
|
|
3331
|
+
this.flush();
|
|
3332
|
+
});
|
|
3333
|
+
}
|
|
3334
|
+
/**
|
|
3335
|
+
* Schedule a one-shot task to run on the next `queue.flush()` (AFTER_FLUSH),
|
|
3336
|
+
* ordered by `level` ascending.
|
|
3337
|
+
*/
|
|
3338
|
+
schedule(task, level = 0) {
|
|
3339
|
+
let isActive = true;
|
|
3340
|
+
const wrapped = () => {
|
|
3341
|
+
if (!isActive) return;
|
|
3342
|
+
task();
|
|
3343
|
+
};
|
|
3344
|
+
let bucket = this.dirtyByLevel.get(level);
|
|
3345
|
+
if (!bucket) {
|
|
3346
|
+
bucket = /* @__PURE__ */ new Set();
|
|
3347
|
+
this.dirtyByLevel.set(level, bucket);
|
|
3348
|
+
}
|
|
3349
|
+
bucket.add(wrapped);
|
|
3350
|
+
if (level < this.minLevel) this.minLevel = level;
|
|
3351
|
+
if (level > this.maxLevel) this.maxLevel = level;
|
|
3352
|
+
if (!this.isFlushing) this.isFlushScheduled = true;
|
|
3353
|
+
return () => {
|
|
3354
|
+
if (!isActive) return;
|
|
3355
|
+
isActive = false;
|
|
3356
|
+
bucket.delete(wrapped);
|
|
3357
|
+
};
|
|
3358
|
+
}
|
|
3359
|
+
/**
|
|
3360
|
+
* Run once at the start of the next runtime flush (i.e. after queue.flush()).
|
|
3361
|
+
* Useful for resubscribing dependencies exactly once per source flush.
|
|
3362
|
+
*/
|
|
3363
|
+
scheduleAfterFlush(task) {
|
|
3364
|
+
let isActive = true;
|
|
3365
|
+
const wrapped = () => {
|
|
3366
|
+
if (!isActive) return;
|
|
3367
|
+
task();
|
|
3368
|
+
};
|
|
3369
|
+
this.afterFlushTasks.add(wrapped);
|
|
3370
|
+
if (!this.isFlushing) this.isFlushScheduled = true;
|
|
3371
|
+
return () => {
|
|
3372
|
+
if (!isActive) return;
|
|
3373
|
+
isActive = false;
|
|
3374
|
+
this.afterFlushTasks.delete(wrapped);
|
|
3375
|
+
};
|
|
3376
|
+
}
|
|
3377
|
+
flush() {
|
|
3378
|
+
this.isFlushScheduled = false;
|
|
3379
|
+
if (this.dirtyByLevel.size === 0 && this.afterFlushTasks.size === 0)
|
|
3380
|
+
return;
|
|
3381
|
+
this.isFlushing = true;
|
|
3382
|
+
try {
|
|
3383
|
+
if (this.afterFlushTasks.size > 0) {
|
|
3384
|
+
const snapshot = Array.from(this.afterFlushTasks);
|
|
3385
|
+
this.afterFlushTasks.clear();
|
|
3386
|
+
for (let i = 0; i < snapshot.length; i++) snapshot[i]();
|
|
3387
|
+
}
|
|
3388
|
+
if (this.dirtyByLevel.size === 0) return;
|
|
3389
|
+
let level = this.minLevel;
|
|
3390
|
+
let max = this.maxLevel;
|
|
3391
|
+
while (level <= max) {
|
|
3392
|
+
for (; ; ) {
|
|
3393
|
+
const bucket = this.dirtyByLevel.get(level);
|
|
3394
|
+
if (!bucket || bucket.size === 0) break;
|
|
3395
|
+
this.dirtyByLevel.delete(level);
|
|
3396
|
+
const snapshot = Array.from(bucket);
|
|
3397
|
+
for (let i = 0; i < snapshot.length; i++) snapshot[i]();
|
|
3398
|
+
}
|
|
3399
|
+
if (this.maxLevel > max) max = this.maxLevel;
|
|
3400
|
+
level++;
|
|
3401
|
+
}
|
|
3402
|
+
} finally {
|
|
3403
|
+
this.isFlushing = false;
|
|
3404
|
+
if (this.dirtyByLevel.size === 0) {
|
|
3405
|
+
this.minLevel = Infinity;
|
|
3406
|
+
this.maxLevel = -Infinity;
|
|
3407
|
+
} else {
|
|
3408
|
+
let nextMin = Infinity;
|
|
3409
|
+
let nextMax = -Infinity;
|
|
3410
|
+
this.dirtyByLevel.forEach((_bucket, lvl) => {
|
|
3411
|
+
if (lvl < nextMin) nextMin = lvl;
|
|
3412
|
+
if (lvl > nextMax) nextMax = lvl;
|
|
3413
|
+
});
|
|
3414
|
+
this.minLevel = nextMin;
|
|
3415
|
+
this.maxLevel = nextMax;
|
|
3416
|
+
this.isFlushScheduled = true;
|
|
3417
|
+
}
|
|
3418
|
+
}
|
|
3419
|
+
}
|
|
2516
3420
|
};
|
|
2517
3421
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2518
3422
|
0 && (module.exports = {
|
|
2519
3423
|
EOIMCollectionEventType,
|
|
2520
3424
|
EOIMComputedEventType,
|
|
2521
|
-
EOIMEffectPhase,
|
|
2522
3425
|
EOIMEventQueueEventType,
|
|
2523
3426
|
EOIMEventQueueSchedulerEventType,
|
|
2524
3427
|
EOIMIndexEventType,
|
|
2525
3428
|
EOIMObjectEventType,
|
|
2526
|
-
EOIMUpdateEventCoalescerEventType,
|
|
2527
3429
|
OIMCollection,
|
|
3430
|
+
OIMCollectionByPkSelector,
|
|
3431
|
+
OIMCollectionByPksSelector,
|
|
2528
3432
|
OIMCollectionChangedFieldsWrapper,
|
|
2529
3433
|
OIMCollectionStore,
|
|
2530
3434
|
OIMCollectionStoreMapDriven,
|
|
2531
3435
|
OIMComparatorFactory,
|
|
3436
|
+
OIMComputativeRuntime,
|
|
2532
3437
|
OIMComputed,
|
|
2533
3438
|
OIMDBSettings,
|
|
2534
3439
|
OIMEffect,
|
|
@@ -2537,6 +3442,8 @@ var OIMEffectDependencyComputed = class {
|
|
|
2537
3442
|
OIMEffectDependencyKeyedCollection,
|
|
2538
3443
|
OIMEffectDependencyKeyedIndex,
|
|
2539
3444
|
OIMEffectDependencyKeyedObject,
|
|
3445
|
+
OIMEntitiesByIndexKeyArrayBasedSelector,
|
|
3446
|
+
OIMEntitiesByIndexKeySetBasedSelector,
|
|
2540
3447
|
OIMEntityUpdaterFactory,
|
|
2541
3448
|
OIMEventEmitter,
|
|
2542
3449
|
OIMEventQueue,
|
|
@@ -2551,6 +3458,10 @@ var OIMEffectDependencyComputed = class {
|
|
|
2551
3458
|
OIMIndexManualArrayBased,
|
|
2552
3459
|
OIMIndexManualOrderedArrayBased,
|
|
2553
3460
|
OIMIndexManualSetBased,
|
|
3461
|
+
OIMIndexPksByKeyArrayBasedSelector,
|
|
3462
|
+
OIMIndexPksByKeySetBasedSelector,
|
|
3463
|
+
OIMIndexPksByKeysArrayBasedSelector,
|
|
3464
|
+
OIMIndexPksByKeysSetBasedSelector,
|
|
2554
3465
|
OIMIndexSetBased,
|
|
2555
3466
|
OIMIndexStoreArrayBased,
|
|
2556
3467
|
OIMIndexStoreMapDrivenArrayBased,
|
|
@@ -2561,6 +3472,8 @@ var OIMEffectDependencyComputed = class {
|
|
|
2561
3472
|
OIMObjectStore,
|
|
2562
3473
|
OIMObjectStoreMapDriven,
|
|
2563
3474
|
OIMObjectStoreRecordDriven,
|
|
3475
|
+
OIMObjectValueByKeySelector,
|
|
3476
|
+
OIMObjectValuesByKeysSelector,
|
|
2564
3477
|
OIMOrderedListIndexCommandStreamWrapper,
|
|
2565
3478
|
OIMPkSelectorFactory,
|
|
2566
3479
|
OIMRICollection,
|
|
@@ -2570,11 +3483,5 @@ var OIMEffectDependencyComputed = class {
|
|
|
2570
3483
|
OIMReactiveIndexManualSetBased,
|
|
2571
3484
|
OIMReactiveIndexSetBased,
|
|
2572
3485
|
OIMReactiveObject,
|
|
2573
|
-
|
|
2574
|
-
OIMUpdateEventCoalescerCollection,
|
|
2575
|
-
OIMUpdateEventCoalescerComputed,
|
|
2576
|
-
OIMUpdateEventCoalescerIndex,
|
|
2577
|
-
OIMUpdateEventCoalescerManual,
|
|
2578
|
-
OIMUpdateEventCoalescerObject,
|
|
2579
|
-
OIMUpdateEventEmitter
|
|
3486
|
+
OIMSelector
|
|
2580
3487
|
});
|