@oimdb/core 3.7.0 → 3.9.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 +43 -4
- package/dist/index.cjs +1298 -327
- package/dist/index.d.cts +893 -267
- package/dist/index.d.ts +893 -267
- package/dist/index.js +1284 -327
- package/llms.txt +82 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -227,21 +227,82 @@ var OIMEventQueueScheduler = class {
|
|
|
227
227
|
}
|
|
228
228
|
};
|
|
229
229
|
|
|
230
|
+
// src/core/OIMKeyedBucketSetBased.ts
|
|
231
|
+
var OIMKeyedBucketSetBased = class extends Set {
|
|
232
|
+
constructor(key) {
|
|
233
|
+
super();
|
|
234
|
+
this.key = key;
|
|
235
|
+
}
|
|
236
|
+
hasSubscribers() {
|
|
237
|
+
return this.subscribers !== void 0 && this.subscribers.size > 0;
|
|
238
|
+
}
|
|
239
|
+
/** Clearing the slot set also clears the pk membership — they stay in sync. */
|
|
240
|
+
clear() {
|
|
241
|
+
super.clear();
|
|
242
|
+
this.membership?.clear();
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
|
|
230
246
|
// src/core/OIMIndexStoreMapDrivenSetBased.ts
|
|
231
247
|
var OIMIndexStoreMapDrivenSetBased = class extends OIMIndexStoreSetBased {
|
|
232
248
|
constructor() {
|
|
233
249
|
super(...arguments);
|
|
250
|
+
// Live buckets (non-empty, or freshly promoted). Enumeration reads these only.
|
|
234
251
|
this.slots = /* @__PURE__ */ new Map();
|
|
252
|
+
// Empty buckets kept alive solely by their subscribers, so a subscription
|
|
253
|
+
// survives a key going empty → re-filled. Invisible to reads/enumeration.
|
|
254
|
+
this.reservedBuckets = /* @__PURE__ */ new Map();
|
|
255
|
+
}
|
|
256
|
+
getOrReserveBucket(key) {
|
|
257
|
+
const live = this.slots.get(key);
|
|
258
|
+
if (live) return live;
|
|
259
|
+
let reserved = this.reservedBuckets.get(key);
|
|
260
|
+
if (!reserved) {
|
|
261
|
+
reserved = new OIMKeyedBucketSetBased(key);
|
|
262
|
+
this.reservedBuckets.set(key, reserved);
|
|
263
|
+
}
|
|
264
|
+
return reserved;
|
|
265
|
+
}
|
|
266
|
+
findBucket(key) {
|
|
267
|
+
return this.slots.get(key) ?? this.reservedBuckets.get(key);
|
|
268
|
+
}
|
|
269
|
+
retainBucket(bucket) {
|
|
270
|
+
if (bucket.size === 0) return;
|
|
271
|
+
this.reservedBuckets.delete(bucket.key);
|
|
272
|
+
if (!this.slots.has(bucket.key)) this.slots.set(bucket.key, bucket);
|
|
273
|
+
}
|
|
274
|
+
releaseBucket(bucket) {
|
|
275
|
+
if (bucket.size > 0) return;
|
|
276
|
+
this.slots.delete(bucket.key);
|
|
277
|
+
if (bucket.hasSubscribers()) {
|
|
278
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
279
|
+
} else {
|
|
280
|
+
this.reservedBuckets.delete(bucket.key);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
dropIfReserved(key) {
|
|
284
|
+
const reserved = this.reservedBuckets.get(key);
|
|
285
|
+
if (reserved && reserved.size === 0 && !reserved.hasSubscribers()) {
|
|
286
|
+
this.reservedBuckets.delete(key);
|
|
287
|
+
}
|
|
235
288
|
}
|
|
236
289
|
setOneByKey(key, slots) {
|
|
237
|
-
this.
|
|
290
|
+
const bucket = this.getOrReserveBucket(key);
|
|
291
|
+
if (bucket !== slots) {
|
|
292
|
+
bucket.clear();
|
|
293
|
+
for (const slot of slots) bucket.add(slot);
|
|
294
|
+
}
|
|
295
|
+
if (bucket.size > 0) this.retainBucket(bucket);
|
|
296
|
+
else this.releaseBucket(bucket);
|
|
238
297
|
}
|
|
239
298
|
removeOneByKey(key) {
|
|
240
299
|
this.slots.delete(key);
|
|
300
|
+
this.reservedBuckets.delete(key);
|
|
241
301
|
}
|
|
242
302
|
removeManyByKeys(keys) {
|
|
243
303
|
for (const key of keys) {
|
|
244
304
|
this.slots.delete(key);
|
|
305
|
+
this.reservedBuckets.delete(key);
|
|
245
306
|
}
|
|
246
307
|
}
|
|
247
308
|
getOneByKey(key) {
|
|
@@ -250,10 +311,8 @@ var OIMIndexStoreMapDrivenSetBased = class extends OIMIndexStoreSetBased {
|
|
|
250
311
|
getManyByKeys(keys) {
|
|
251
312
|
const result = /* @__PURE__ */ new Map();
|
|
252
313
|
for (const key of keys) {
|
|
253
|
-
const slots = this.
|
|
254
|
-
if (slots !== void 0)
|
|
255
|
-
result.set(key, slots);
|
|
256
|
-
}
|
|
314
|
+
const slots = this.slots.get(key);
|
|
315
|
+
if (slots !== void 0) result.set(key, slots);
|
|
257
316
|
}
|
|
258
317
|
return result;
|
|
259
318
|
}
|
|
@@ -267,6 +326,12 @@ var OIMIndexStoreMapDrivenSetBased = class extends OIMIndexStoreSetBased {
|
|
|
267
326
|
return this.slots.size;
|
|
268
327
|
}
|
|
269
328
|
clear() {
|
|
329
|
+
for (const bucket of this.slots.values()) {
|
|
330
|
+
bucket.clear();
|
|
331
|
+
if (bucket.hasSubscribers()) {
|
|
332
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
270
335
|
this.slots.clear();
|
|
271
336
|
}
|
|
272
337
|
};
|
|
@@ -274,10 +339,9 @@ var OIMIndexStoreMapDrivenSetBased = class extends OIMIndexStoreSetBased {
|
|
|
274
339
|
// src/abstract/OIMIndexSetBased.ts
|
|
275
340
|
var OIMIndexSetBased = class extends OIMIndex {
|
|
276
341
|
constructor(options = {}) {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
);
|
|
342
|
+
const store = options.store ?? new OIMIndexStoreMapDrivenSetBased();
|
|
343
|
+
super(store, options.comparePks);
|
|
344
|
+
this.setStore = store;
|
|
281
345
|
}
|
|
282
346
|
getBucketSize(bucket) {
|
|
283
347
|
return bucket.size;
|
|
@@ -305,22 +369,36 @@ var OIMIndexSetBased = class extends OIMIndex {
|
|
|
305
369
|
for (const slot of slots) pks.add(slot.pk);
|
|
306
370
|
return pks;
|
|
307
371
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
372
|
+
/**
|
|
373
|
+
* True if a comparator is set and considers `bucket`'s current pks equal to
|
|
374
|
+
* `newSlots` — i.e. a `setSlots` would be a no-op and should not emit.
|
|
375
|
+
*/
|
|
376
|
+
bucketMatchesComparator(bucket, newSlots) {
|
|
377
|
+
if (!this.comparePks) return false;
|
|
378
|
+
if (bucket.size !== newSlots.size) return false;
|
|
379
|
+
if (bucket.size === 0) return true;
|
|
380
|
+
return this.comparePks(
|
|
381
|
+
Array.from(this.slotsToPks(bucket)),
|
|
382
|
+
Array.from(this.slotsToPks(newSlots))
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// src/core/OIMKeyedBucketArrayBased.ts
|
|
388
|
+
var OIMKeyedBucketArrayBased = class extends Array {
|
|
389
|
+
constructor(key) {
|
|
390
|
+
super();
|
|
391
|
+
this.key = key;
|
|
392
|
+
}
|
|
393
|
+
static get [Symbol.species]() {
|
|
394
|
+
return Array;
|
|
395
|
+
}
|
|
396
|
+
hasSubscribers() {
|
|
397
|
+
return this.subscribers !== void 0 && this.subscribers.size > 0;
|
|
398
|
+
}
|
|
399
|
+
/** Empty the bucket in place (Array has no `clear`). */
|
|
400
|
+
clear() {
|
|
401
|
+
this.length = 0;
|
|
324
402
|
}
|
|
325
403
|
};
|
|
326
404
|
|
|
@@ -328,17 +406,61 @@ var OIMIndexSetBased = class extends OIMIndex {
|
|
|
328
406
|
var OIMIndexStoreMapDrivenArrayBased = class extends OIMIndexStoreArrayBased {
|
|
329
407
|
constructor() {
|
|
330
408
|
super(...arguments);
|
|
409
|
+
// Live buckets (non-empty). Enumeration reads these only.
|
|
331
410
|
this.slots = /* @__PURE__ */ new Map();
|
|
411
|
+
// Empty buckets kept alive by their subscribers, invisible to reads.
|
|
412
|
+
this.reservedBuckets = /* @__PURE__ */ new Map();
|
|
413
|
+
}
|
|
414
|
+
getOrReserveBucket(key) {
|
|
415
|
+
const live = this.slots.get(key);
|
|
416
|
+
if (live) return live;
|
|
417
|
+
let reserved = this.reservedBuckets.get(key);
|
|
418
|
+
if (!reserved) {
|
|
419
|
+
reserved = new OIMKeyedBucketArrayBased(key);
|
|
420
|
+
this.reservedBuckets.set(key, reserved);
|
|
421
|
+
}
|
|
422
|
+
return reserved;
|
|
423
|
+
}
|
|
424
|
+
findBucket(key) {
|
|
425
|
+
return this.slots.get(key) ?? this.reservedBuckets.get(key);
|
|
426
|
+
}
|
|
427
|
+
retainBucket(bucket) {
|
|
428
|
+
if (bucket.length === 0) return;
|
|
429
|
+
this.reservedBuckets.delete(bucket.key);
|
|
430
|
+
if (!this.slots.has(bucket.key)) this.slots.set(bucket.key, bucket);
|
|
431
|
+
}
|
|
432
|
+
releaseBucket(bucket) {
|
|
433
|
+
if (bucket.length > 0) return;
|
|
434
|
+
this.slots.delete(bucket.key);
|
|
435
|
+
if (bucket.hasSubscribers()) {
|
|
436
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
437
|
+
} else {
|
|
438
|
+
this.reservedBuckets.delete(bucket.key);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
dropIfReserved(key) {
|
|
442
|
+
const reserved = this.reservedBuckets.get(key);
|
|
443
|
+
if (reserved && reserved.length === 0 && !reserved.hasSubscribers()) {
|
|
444
|
+
this.reservedBuckets.delete(key);
|
|
445
|
+
}
|
|
332
446
|
}
|
|
333
447
|
setOneByKey(key, slots) {
|
|
334
|
-
this.
|
|
448
|
+
const bucket = this.getOrReserveBucket(key);
|
|
449
|
+
if (bucket !== slots) {
|
|
450
|
+
bucket.length = 0;
|
|
451
|
+
for (let i = 0; i < slots.length; i++) bucket.push(slots[i]);
|
|
452
|
+
}
|
|
453
|
+
if (bucket.length > 0) this.retainBucket(bucket);
|
|
454
|
+
else this.releaseBucket(bucket);
|
|
335
455
|
}
|
|
336
456
|
removeOneByKey(key) {
|
|
337
457
|
this.slots.delete(key);
|
|
458
|
+
this.reservedBuckets.delete(key);
|
|
338
459
|
}
|
|
339
460
|
removeManyByKeys(keys) {
|
|
340
461
|
for (const key of keys) {
|
|
341
462
|
this.slots.delete(key);
|
|
463
|
+
this.reservedBuckets.delete(key);
|
|
342
464
|
}
|
|
343
465
|
}
|
|
344
466
|
getOneByKey(key) {
|
|
@@ -347,10 +469,8 @@ var OIMIndexStoreMapDrivenArrayBased = class extends OIMIndexStoreArrayBased {
|
|
|
347
469
|
getManyByKeys(keys) {
|
|
348
470
|
const result = /* @__PURE__ */ new Map();
|
|
349
471
|
for (const key of keys) {
|
|
350
|
-
const slots = this.
|
|
351
|
-
if (slots !== void 0)
|
|
352
|
-
result.set(key, slots);
|
|
353
|
-
}
|
|
472
|
+
const slots = this.slots.get(key);
|
|
473
|
+
if (slots !== void 0) result.set(key, slots);
|
|
354
474
|
}
|
|
355
475
|
return result;
|
|
356
476
|
}
|
|
@@ -364,6 +484,12 @@ var OIMIndexStoreMapDrivenArrayBased = class extends OIMIndexStoreArrayBased {
|
|
|
364
484
|
return this.slots.size;
|
|
365
485
|
}
|
|
366
486
|
clear() {
|
|
487
|
+
for (const bucket of this.slots.values()) {
|
|
488
|
+
bucket.length = 0;
|
|
489
|
+
if (bucket.hasSubscribers()) {
|
|
490
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
367
493
|
this.slots.clear();
|
|
368
494
|
}
|
|
369
495
|
};
|
|
@@ -371,10 +497,9 @@ var OIMIndexStoreMapDrivenArrayBased = class extends OIMIndexStoreArrayBased {
|
|
|
371
497
|
// src/abstract/OIMIndexArrayBased.ts
|
|
372
498
|
var OIMIndexArrayBased = class extends OIMIndex {
|
|
373
499
|
constructor(options = {}) {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
);
|
|
500
|
+
const store = options.store ?? new OIMIndexStoreMapDrivenArrayBased();
|
|
501
|
+
super(store, options.comparePks);
|
|
502
|
+
this.arrayStore = store;
|
|
378
503
|
}
|
|
379
504
|
getBucketSize(bucket) {
|
|
380
505
|
return bucket.length;
|
|
@@ -392,10 +517,15 @@ var OIMIndexArrayBased = class extends OIMIndex {
|
|
|
392
517
|
return result;
|
|
393
518
|
}
|
|
394
519
|
getSlotsByKey(key) {
|
|
395
|
-
|
|
520
|
+
const bucket = this.store.getOneByKey(key);
|
|
521
|
+
return bucket ? bucket.slice() : [];
|
|
396
522
|
}
|
|
397
523
|
getSlotsByKeys(keys) {
|
|
398
|
-
|
|
524
|
+
const result = /* @__PURE__ */ new Map();
|
|
525
|
+
for (const [key, bucket] of this.store.getManyByKeys(keys)) {
|
|
526
|
+
result.set(key, bucket.slice());
|
|
527
|
+
}
|
|
528
|
+
return result;
|
|
399
529
|
}
|
|
400
530
|
slotsToPks(slots) {
|
|
401
531
|
const pks = [];
|
|
@@ -403,28 +533,24 @@ var OIMIndexArrayBased = class extends OIMIndex {
|
|
|
403
533
|
for (let i = 0; i < slots.length; i++) pks[i] = slots[i].pk;
|
|
404
534
|
return pks;
|
|
405
535
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
this.store.setOneByKey(key, newSlots);
|
|
421
|
-
return true;
|
|
536
|
+
/**
|
|
537
|
+
* True if a comparator is set and considers `bucket`'s pks equal to
|
|
538
|
+
* `newSlots` — i.e. a `setSlots` would be a no-op and should not emit.
|
|
539
|
+
*/
|
|
540
|
+
bucketMatchesComparator(bucket, newSlots) {
|
|
541
|
+
if (!this.comparePks) return false;
|
|
542
|
+
if (bucket.length !== newSlots.length) return false;
|
|
543
|
+
if (bucket.length === 0) return true;
|
|
544
|
+
return this.comparePks(
|
|
545
|
+
this.slotsToPks(bucket),
|
|
546
|
+
this.slotsToPks(newSlots)
|
|
547
|
+
);
|
|
422
548
|
}
|
|
423
549
|
};
|
|
424
550
|
|
|
425
551
|
// src/core/OIMCarrierKeyedEmitter.ts
|
|
426
552
|
var OIMCarrierKeyedEmitter = class {
|
|
427
|
-
constructor(queue,
|
|
553
|
+
constructor(queue, carrierProvider) {
|
|
428
554
|
// Carriers with at least one subscriber — for markAllUpdated / metrics.
|
|
429
555
|
this.subscribedCarriers = /* @__PURE__ */ new Set();
|
|
430
556
|
// Pending flush batch. A plain array + a `carrier.dirty` flag for dedup —
|
|
@@ -449,17 +575,17 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
449
575
|
}
|
|
450
576
|
};
|
|
451
577
|
this.queue = queue;
|
|
452
|
-
this.
|
|
578
|
+
this.carrierProvider = carrierProvider;
|
|
453
579
|
}
|
|
454
580
|
subscribeOnKey(key, handler) {
|
|
455
|
-
const carrier = this.
|
|
581
|
+
const carrier = this.carrierProvider.getOrReserveCarrier(key);
|
|
456
582
|
this.addHandler(carrier, handler);
|
|
457
583
|
return () => this.removeHandler(carrier, handler);
|
|
458
584
|
}
|
|
459
585
|
subscribeOnKeys(keys, handler) {
|
|
460
586
|
const carriers = [];
|
|
461
587
|
for (let i = 0; i < keys.length; i++) {
|
|
462
|
-
const carrier = this.
|
|
588
|
+
const carrier = this.carrierProvider.getOrReserveCarrier(keys[i]);
|
|
463
589
|
this.addHandler(carrier, handler);
|
|
464
590
|
carriers.push(carrier);
|
|
465
591
|
}
|
|
@@ -470,7 +596,7 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
470
596
|
};
|
|
471
597
|
}
|
|
472
598
|
unsubscribeFromKey(key, handler) {
|
|
473
|
-
const carrier = this.
|
|
599
|
+
const carrier = this.carrierProvider.findCarrier(key);
|
|
474
600
|
if (carrier) this.removeHandler(carrier, handler);
|
|
475
601
|
}
|
|
476
602
|
unsubscribeFromKeys(keys, handler) {
|
|
@@ -493,7 +619,7 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
493
619
|
subscribers.delete(handler);
|
|
494
620
|
if (subscribers.size === 0) {
|
|
495
621
|
this.subscribedCarriers.delete(carrier);
|
|
496
|
-
this.
|
|
622
|
+
this.carrierProvider.onCarrierEmptied?.(carrier);
|
|
497
623
|
}
|
|
498
624
|
}
|
|
499
625
|
/** Fast path: the writer already holds the carrier. */
|
|
@@ -507,11 +633,19 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
507
633
|
this.scheduleFlush();
|
|
508
634
|
}
|
|
509
635
|
markUpdatedKey(key) {
|
|
510
|
-
|
|
636
|
+
if (this.subscribedCarriers.size === 0) {
|
|
637
|
+
this.assertNotInFlush();
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
const carrier = this.carrierProvider.findCarrier(key);
|
|
511
641
|
if (carrier) this.markUpdatedCarrier(carrier);
|
|
512
642
|
else this.assertNotInFlush();
|
|
513
643
|
}
|
|
514
644
|
markUpdatedKeys(keys) {
|
|
645
|
+
if (this.subscribedCarriers.size === 0) {
|
|
646
|
+
this.assertNotInFlush();
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
515
649
|
for (let i = 0; i < keys.length; i++) this.markUpdatedKey(keys[i]);
|
|
516
650
|
}
|
|
517
651
|
markAllUpdated() {
|
|
@@ -528,7 +662,7 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
528
662
|
return this.subscribedCarriers.size > 0;
|
|
529
663
|
}
|
|
530
664
|
getHandlerCount(key) {
|
|
531
|
-
return this.
|
|
665
|
+
return this.carrierProvider.findCarrier(key)?.subscribers?.size ?? 0;
|
|
532
666
|
}
|
|
533
667
|
getMetrics() {
|
|
534
668
|
let totalHandlers = 0;
|
|
@@ -588,8 +722,8 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
588
722
|
}
|
|
589
723
|
};
|
|
590
724
|
|
|
591
|
-
// src/core/
|
|
592
|
-
var
|
|
725
|
+
// src/core/OIMKeyedCarrierProvider.ts
|
|
726
|
+
var OIMKeyedCarrierProvider = class {
|
|
593
727
|
constructor() {
|
|
594
728
|
this.carriers = /* @__PURE__ */ new Map();
|
|
595
729
|
}
|
|
@@ -611,8 +745,8 @@ var OIMKeyedCarrierResolver = class {
|
|
|
611
745
|
|
|
612
746
|
// src/abstract/OIMReactiveIndex.ts
|
|
613
747
|
var OIMReactiveIndex = class {
|
|
614
|
-
constructor(queue, createIndex) {
|
|
615
|
-
this.updateEmitter = new OIMCarrierKeyedEmitter(queue,
|
|
748
|
+
constructor(queue, createIndex, createCarrierProvider = () => new OIMKeyedCarrierProvider()) {
|
|
749
|
+
this.updateEmitter = new OIMCarrierKeyedEmitter(queue, createCarrierProvider());
|
|
616
750
|
this.index = createIndex(this.updateEmitter);
|
|
617
751
|
}
|
|
618
752
|
getEntitiesByKey(key) {
|
|
@@ -668,8 +802,8 @@ var OIMReactiveIndex = class {
|
|
|
668
802
|
|
|
669
803
|
// src/abstract/OIMReactiveIndexSetBased.ts
|
|
670
804
|
var OIMReactiveIndexSetBased = class extends OIMReactiveIndex {
|
|
671
|
-
constructor(queue, createIndex) {
|
|
672
|
-
super(queue, createIndex);
|
|
805
|
+
constructor(queue, createIndex, createCarrierProvider) {
|
|
806
|
+
super(queue, createIndex, createCarrierProvider);
|
|
673
807
|
}
|
|
674
808
|
getPksByKey(key) {
|
|
675
809
|
return this.index.getPksByKey(key);
|
|
@@ -687,8 +821,8 @@ var OIMReactiveIndexSetBased = class extends OIMReactiveIndex {
|
|
|
687
821
|
|
|
688
822
|
// src/abstract/OIMReactiveIndexArrayBased.ts
|
|
689
823
|
var OIMReactiveIndexArrayBased = class extends OIMReactiveIndex {
|
|
690
|
-
constructor(queue, createIndex) {
|
|
691
|
-
super(queue, createIndex);
|
|
824
|
+
constructor(queue, createIndex, createCarrierProvider) {
|
|
825
|
+
super(queue, createIndex, createCarrierProvider);
|
|
692
826
|
}
|
|
693
827
|
getPksByKey(key) {
|
|
694
828
|
return this.index.getPksByKey(key);
|
|
@@ -1151,6 +1285,14 @@ var OIMCollection = class {
|
|
|
1151
1285
|
getOrReserveSlotByPk(pk) {
|
|
1152
1286
|
return this.store.getOrReserveSlotByPk(pk);
|
|
1153
1287
|
}
|
|
1288
|
+
/**
|
|
1289
|
+
* The existing slot for `pk` (live or reserved) WITHOUT creating one — used
|
|
1290
|
+
* by indexes to resolve a pk to its canonical slot for removal (delete by
|
|
1291
|
+
* reference), with no side effect for a pk that is not present.
|
|
1292
|
+
*/
|
|
1293
|
+
findSlotByPk(pk) {
|
|
1294
|
+
return this.store.findSlotByPk(pk);
|
|
1295
|
+
}
|
|
1154
1296
|
getSlotsByPks(pks) {
|
|
1155
1297
|
return this.store.getSlotsByPks(pks);
|
|
1156
1298
|
}
|
|
@@ -1219,15 +1361,12 @@ var OIMCollection = class {
|
|
|
1219
1361
|
`[OIMCollection]: PK is required to upsert an entity ${JSON.stringify(entity)}`
|
|
1220
1362
|
);
|
|
1221
1363
|
}
|
|
1222
|
-
const
|
|
1223
|
-
if (
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
this.updateEntity(entity, existingEntity)
|
|
1227
|
-
);
|
|
1228
|
-
} else {
|
|
1229
|
-
return this.store.setOneByPk(pk, entity);
|
|
1364
|
+
const slot = this.store.getSlotByPk(pk);
|
|
1365
|
+
if (slot !== void 0 && slot.item !== void 0) {
|
|
1366
|
+
slot.item = this.updateEntity(entity, slot.item);
|
|
1367
|
+
return slot;
|
|
1230
1368
|
}
|
|
1369
|
+
return this.store.setOneByPk(pk, entity);
|
|
1231
1370
|
}
|
|
1232
1371
|
destroy() {
|
|
1233
1372
|
this.store.destroy();
|
|
@@ -1240,13 +1379,15 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1240
1379
|
constructor(queue, opts) {
|
|
1241
1380
|
super(opts);
|
|
1242
1381
|
this.anyUpdateHandlers = /* @__PURE__ */ new Set();
|
|
1382
|
+
// Only ever holds `slot.pk` (one canonical reference per logical key), so a
|
|
1383
|
+
// native `Set` dedups correctly by reference even for composite pks.
|
|
1243
1384
|
this.pendingAnyUpdatePks = /* @__PURE__ */ new Set();
|
|
1244
1385
|
this.isAnyUpdateClearPending = false;
|
|
1245
1386
|
this.isAnyUpdateScheduled = false;
|
|
1246
1387
|
this.runAnyUpdate = () => {
|
|
1247
1388
|
if (!this.isAnyUpdateScheduled) return;
|
|
1248
1389
|
this.isAnyUpdateScheduled = false;
|
|
1249
|
-
const pks = this.isAnyUpdateClearPending ? [] : Array.from(this.pendingAnyUpdatePks);
|
|
1390
|
+
const pks = this.isAnyUpdateClearPending ? [] : Array.from(this.pendingAnyUpdatePks.values());
|
|
1250
1391
|
this.pendingAnyUpdatePks.clear();
|
|
1251
1392
|
this.isAnyUpdateClearPending = false;
|
|
1252
1393
|
const snapshot = Array.from(this.anyUpdateHandlers);
|
|
@@ -1405,38 +1546,40 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1405
1546
|
if (key === void 0) {
|
|
1406
1547
|
const keys = this.getKeys();
|
|
1407
1548
|
if (keys.length > 0) {
|
|
1408
|
-
this.
|
|
1549
|
+
this.arrayStore.clear();
|
|
1409
1550
|
this.emitUpdate(Array.from(keys));
|
|
1410
1551
|
}
|
|
1411
1552
|
return;
|
|
1412
1553
|
}
|
|
1413
|
-
|
|
1414
|
-
|
|
1554
|
+
const bucket = this.arrayStore.findBucket(key);
|
|
1555
|
+
if (bucket && bucket.length > 0) {
|
|
1556
|
+
bucket.length = 0;
|
|
1557
|
+
this.arrayStore.releaseBucket(bucket);
|
|
1415
1558
|
this.emitUpdate([key]);
|
|
1416
1559
|
}
|
|
1417
1560
|
}
|
|
1418
1561
|
pushSlot(key, slot) {
|
|
1419
|
-
const
|
|
1420
|
-
const index =
|
|
1421
|
-
|
|
1562
|
+
const bucket = this.arrayStore.getOrReserveBucket(key);
|
|
1563
|
+
const index = bucket.length;
|
|
1564
|
+
bucket.push(slot);
|
|
1565
|
+
this.arrayStore.retainBucket(bucket);
|
|
1422
1566
|
this.emitUpdate([key]);
|
|
1423
1567
|
return index;
|
|
1424
1568
|
}
|
|
1425
1569
|
insertSlotAt(key, index, slot) {
|
|
1426
|
-
const
|
|
1427
|
-
const safeIndex = Math.max(0, Math.min(index,
|
|
1428
|
-
|
|
1570
|
+
const bucket = this.arrayStore.getOrReserveBucket(key);
|
|
1571
|
+
const safeIndex = Math.max(0, Math.min(index, bucket.length));
|
|
1572
|
+
bucket.splice(safeIndex, 0, slot);
|
|
1573
|
+
this.arrayStore.retainBucket(bucket);
|
|
1429
1574
|
this.emitUpdate([key]);
|
|
1430
1575
|
return safeIndex;
|
|
1431
1576
|
}
|
|
1432
1577
|
removeAt(key, index) {
|
|
1433
|
-
const
|
|
1434
|
-
if (!
|
|
1435
|
-
if (index < 0 || index >=
|
|
1436
|
-
const [removed] =
|
|
1437
|
-
if (
|
|
1438
|
-
this.store.removeOneByKey(key);
|
|
1439
|
-
}
|
|
1578
|
+
const bucket = this.arrayStore.findBucket(key);
|
|
1579
|
+
if (!bucket) return void 0;
|
|
1580
|
+
if (index < 0 || index >= bucket.length) return void 0;
|
|
1581
|
+
const [removed] = bucket.splice(index, 1);
|
|
1582
|
+
if (bucket.length === 0) this.arrayStore.releaseBucket(bucket);
|
|
1440
1583
|
this.emitUpdate([key]);
|
|
1441
1584
|
return removed;
|
|
1442
1585
|
}
|
|
@@ -1445,35 +1588,33 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1445
1588
|
* Returns the number actually removed (clamped to bounds; 0 if nothing).
|
|
1446
1589
|
*/
|
|
1447
1590
|
removeRange(key, index, count) {
|
|
1448
|
-
const
|
|
1449
|
-
if (!
|
|
1450
|
-
if (index < 0 || index >=
|
|
1451
|
-
const actual = Math.min(count,
|
|
1452
|
-
|
|
1453
|
-
if (
|
|
1454
|
-
this.store.removeOneByKey(key);
|
|
1455
|
-
}
|
|
1591
|
+
const bucket = this.arrayStore.findBucket(key);
|
|
1592
|
+
if (!bucket) return 0;
|
|
1593
|
+
if (index < 0 || index >= bucket.length || count <= 0) return 0;
|
|
1594
|
+
const actual = Math.min(count, bucket.length - index);
|
|
1595
|
+
bucket.splice(index, actual);
|
|
1596
|
+
if (bucket.length === 0) this.arrayStore.releaseBucket(bucket);
|
|
1456
1597
|
this.emitUpdate([key]);
|
|
1457
1598
|
return actual;
|
|
1458
1599
|
}
|
|
1459
1600
|
move(key, fromIndex, toIndex) {
|
|
1460
|
-
const
|
|
1461
|
-
if (!
|
|
1462
|
-
if (fromIndex < 0 || fromIndex >=
|
|
1463
|
-
if (toIndex < 0 || toIndex >=
|
|
1464
|
-
if (fromIndex === toIndex) return
|
|
1465
|
-
const [slot] =
|
|
1601
|
+
const bucket = this.arrayStore.findBucket(key);
|
|
1602
|
+
if (!bucket) return void 0;
|
|
1603
|
+
if (fromIndex < 0 || fromIndex >= bucket.length) return void 0;
|
|
1604
|
+
if (toIndex < 0 || toIndex >= bucket.length) return void 0;
|
|
1605
|
+
if (fromIndex === toIndex) return bucket[fromIndex];
|
|
1606
|
+
const [slot] = bucket.splice(fromIndex, 1);
|
|
1466
1607
|
if (slot === void 0) return void 0;
|
|
1467
|
-
|
|
1608
|
+
bucket.splice(toIndex, 0, slot);
|
|
1468
1609
|
this.emitUpdate([key]);
|
|
1469
1610
|
return slot;
|
|
1470
1611
|
}
|
|
1471
1612
|
/** Replace the slot at `index` in place. Returns the safe index, or -1. */
|
|
1472
1613
|
setSlotAt(key, index, slot) {
|
|
1473
|
-
const
|
|
1474
|
-
if (!
|
|
1475
|
-
if (index < 0 || index >=
|
|
1476
|
-
|
|
1614
|
+
const bucket = this.arrayStore.findBucket(key);
|
|
1615
|
+
if (!bucket) return -1;
|
|
1616
|
+
if (index < 0 || index >= bucket.length) return -1;
|
|
1617
|
+
bucket[index] = slot;
|
|
1477
1618
|
this.emitUpdate([key]);
|
|
1478
1619
|
return index;
|
|
1479
1620
|
}
|
|
@@ -1483,52 +1624,49 @@ var OIMIndexManualOrderedArrayBased = class extends OIMIndexArrayBased {
|
|
|
1483
1624
|
* Returns the number actually moved (0 if a no-op / out of bounds).
|
|
1484
1625
|
*/
|
|
1485
1626
|
moveRange(key, from, to, count) {
|
|
1486
|
-
const
|
|
1487
|
-
if (!
|
|
1488
|
-
if (from < 0 || from >=
|
|
1489
|
-
const actual = Math.min(count,
|
|
1490
|
-
const insertAt = Math.max(0, Math.min(to,
|
|
1627
|
+
const bucket = this.arrayStore.findBucket(key);
|
|
1628
|
+
if (!bucket) return 0;
|
|
1629
|
+
if (from < 0 || from >= bucket.length || count <= 0) return 0;
|
|
1630
|
+
const actual = Math.min(count, bucket.length - from);
|
|
1631
|
+
const insertAt = Math.max(0, Math.min(to, bucket.length - actual));
|
|
1491
1632
|
if (insertAt === from) return 0;
|
|
1492
|
-
const block =
|
|
1493
|
-
|
|
1633
|
+
const block = bucket.splice(from, actual);
|
|
1634
|
+
bucket.splice(insertAt, 0, ...block);
|
|
1494
1635
|
this.emitUpdate([key]);
|
|
1495
1636
|
return actual;
|
|
1496
1637
|
}
|
|
1497
1638
|
resetSlots(key, slots) {
|
|
1498
1639
|
if (slots.length === 0) {
|
|
1499
|
-
|
|
1500
|
-
|
|
1640
|
+
const bucket2 = this.arrayStore.findBucket(key);
|
|
1641
|
+
if (bucket2 && bucket2.length > 0) {
|
|
1642
|
+
bucket2.length = 0;
|
|
1643
|
+
this.arrayStore.releaseBucket(bucket2);
|
|
1501
1644
|
this.emitUpdate([key]);
|
|
1502
1645
|
}
|
|
1503
1646
|
return;
|
|
1504
1647
|
}
|
|
1505
|
-
this.
|
|
1648
|
+
const bucket = this.arrayStore.getOrReserveBucket(key);
|
|
1649
|
+
bucket.length = 0;
|
|
1650
|
+
for (let i = 0; i < slots.length; i++) bucket.push(slots[i]);
|
|
1651
|
+
this.arrayStore.retainBucket(bucket);
|
|
1506
1652
|
this.emitUpdate([key]);
|
|
1507
1653
|
}
|
|
1508
|
-
getOrCreateList(key) {
|
|
1509
|
-
let list = this.store.getOneByKey(key);
|
|
1510
|
-
if (!list) {
|
|
1511
|
-
list = [];
|
|
1512
|
-
this.store.setOneByKey(key, list);
|
|
1513
|
-
}
|
|
1514
|
-
return list;
|
|
1515
|
-
}
|
|
1516
1654
|
};
|
|
1517
1655
|
|
|
1518
1656
|
// src/core/OIMCollectionIndexManualOrderedArrayBased.ts
|
|
1519
1657
|
var OIMCollectionIndexManualOrderedArrayBased = class extends OIMIndexManualOrderedArrayBased {
|
|
1520
1658
|
constructor(opts) {
|
|
1521
1659
|
super();
|
|
1522
|
-
this.
|
|
1660
|
+
this.getSlot = opts.collection !== void 0 ? (pk) => opts.collection.getSlotByPk(pk) : opts.getSlot;
|
|
1523
1661
|
}
|
|
1524
1662
|
push(key, pk) {
|
|
1525
|
-
return this.pushSlot(key, this.
|
|
1663
|
+
return this.pushSlot(key, this.getRequiredSlot(pk));
|
|
1526
1664
|
}
|
|
1527
1665
|
insertAt(key, index, pk) {
|
|
1528
|
-
return this.insertSlotAt(key, index, this.
|
|
1666
|
+
return this.insertSlotAt(key, index, this.getRequiredSlot(pk));
|
|
1529
1667
|
}
|
|
1530
1668
|
reset(key, pks) {
|
|
1531
|
-
this.resetSlots(key, this.
|
|
1669
|
+
this.resetSlots(key, this.getRequiredSlots(pks));
|
|
1532
1670
|
}
|
|
1533
1671
|
getEntitiesByKey(key) {
|
|
1534
1672
|
return super.getEntitiesByKey(key);
|
|
@@ -1536,26 +1674,25 @@ var OIMCollectionIndexManualOrderedArrayBased = class extends OIMIndexManualOrde
|
|
|
1536
1674
|
getEntitiesByKeys(keys) {
|
|
1537
1675
|
return super.getEntitiesByKeys(keys);
|
|
1538
1676
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1677
|
+
// Gets the slot for a pk, throwing if the (custom) getter has none — this
|
|
1678
|
+
// ordered index requires a real slot to place in order.
|
|
1679
|
+
getRequiredSlot(pk) {
|
|
1680
|
+
const slot = this.getSlot(pk);
|
|
1681
|
+
if (!slot) {
|
|
1682
|
+
throw new Error(
|
|
1683
|
+
`[OIMCollectionIndexManualOrderedArrayBased]: no slot for PK "${String(pk)}".`
|
|
1684
|
+
);
|
|
1685
|
+
}
|
|
1686
|
+
return slot;
|
|
1541
1687
|
}
|
|
1542
|
-
|
|
1688
|
+
getRequiredSlots(pks) {
|
|
1543
1689
|
const slots = [];
|
|
1544
1690
|
slots.length = pks.length;
|
|
1545
1691
|
for (let i = 0; i < pks.length; i++) {
|
|
1546
|
-
slots[i] = this.
|
|
1692
|
+
slots[i] = this.getRequiredSlot(pks[i]);
|
|
1547
1693
|
}
|
|
1548
1694
|
return slots;
|
|
1549
1695
|
}
|
|
1550
|
-
resolveRequiredSlot(pk) {
|
|
1551
|
-
const slot = this.resolveSlot(pk);
|
|
1552
|
-
if (!slot) {
|
|
1553
|
-
throw new Error(
|
|
1554
|
-
`[OIMCollectionIndexManualOrderedArrayBased]: Unable to resolve slot for PK "${String(pk)}".`
|
|
1555
|
-
);
|
|
1556
|
-
}
|
|
1557
|
-
return slot;
|
|
1558
|
-
}
|
|
1559
1696
|
};
|
|
1560
1697
|
|
|
1561
1698
|
// src/enums/EOIMEventQueueEventType.ts
|
|
@@ -1974,18 +2111,18 @@ var OIMOrderedListCommandStream = class extends OIMOrderedListCommandBuffer {
|
|
|
1974
2111
|
var OIMCollectionOrderedListCommandStream = class extends OIMOrderedListCommandStream {
|
|
1975
2112
|
constructor(queue, opts) {
|
|
1976
2113
|
const index = opts.index ?? new OIMCollectionIndexManualOrderedArrayBased(
|
|
1977
|
-
opts.collection !== void 0 ? { collection: opts.collection } : {
|
|
2114
|
+
opts.collection !== void 0 ? { collection: opts.collection } : { getSlot: opts.getSlot }
|
|
1978
2115
|
);
|
|
1979
2116
|
super(queue, index);
|
|
1980
2117
|
this.index = index;
|
|
1981
2118
|
}
|
|
1982
2119
|
push(key, pk) {
|
|
1983
|
-
const slot = this.
|
|
2120
|
+
const slot = this.getRequiredSlot(pk);
|
|
1984
2121
|
const index = this.index.pushSlot(key, slot);
|
|
1985
2122
|
this.appendCommand(key, { type: "insert", index, item: slot });
|
|
1986
2123
|
}
|
|
1987
2124
|
insertAt(key, index, pk) {
|
|
1988
|
-
const slot = this.
|
|
2125
|
+
const slot = this.getRequiredSlot(pk);
|
|
1989
2126
|
const safeIndex = this.index.insertSlotAt(key, index, slot);
|
|
1990
2127
|
this.appendCommand(key, {
|
|
1991
2128
|
type: "insert",
|
|
@@ -1995,7 +2132,7 @@ var OIMCollectionOrderedListCommandStream = class extends OIMOrderedListCommandS
|
|
|
1995
2132
|
}
|
|
1996
2133
|
/** Replace the element at `index` with the slot for `pk`, in place. */
|
|
1997
2134
|
setAt(key, index, pk) {
|
|
1998
|
-
const slot = this.
|
|
2135
|
+
const slot = this.getRequiredSlot(pk);
|
|
1999
2136
|
const safeIndex = this.index.setSlotAt(key, index, slot);
|
|
2000
2137
|
if (safeIndex < 0) return;
|
|
2001
2138
|
this.appendCommand(key, {
|
|
@@ -2005,7 +2142,7 @@ var OIMCollectionOrderedListCommandStream = class extends OIMOrderedListCommandS
|
|
|
2005
2142
|
});
|
|
2006
2143
|
}
|
|
2007
2144
|
set(key, pks) {
|
|
2008
|
-
const slots = pks.map((pk) => this.
|
|
2145
|
+
const slots = pks.map((pk) => this.getRequiredSlot(pk));
|
|
2009
2146
|
this.index.resetSlots(key, slots);
|
|
2010
2147
|
this.appendResetCommand(key, slots);
|
|
2011
2148
|
}
|
|
@@ -2017,8 +2154,8 @@ var OIMCollectionOrderedListCommandStream = class extends OIMOrderedListCommandS
|
|
|
2017
2154
|
getEntitiesByKey(key) {
|
|
2018
2155
|
return this.index.getEntitiesByKey(key);
|
|
2019
2156
|
}
|
|
2020
|
-
|
|
2021
|
-
return this.index.
|
|
2157
|
+
getRequiredSlot(pk) {
|
|
2158
|
+
return this.index.getRequiredSlot(
|
|
2022
2159
|
pk
|
|
2023
2160
|
);
|
|
2024
2161
|
}
|
|
@@ -2030,43 +2167,68 @@ var OIMIndexManualArrayBased = class extends OIMIndexArrayBased {
|
|
|
2030
2167
|
super(options);
|
|
2031
2168
|
}
|
|
2032
2169
|
setSlots(key, slots) {
|
|
2033
|
-
const
|
|
2034
|
-
if (
|
|
2035
|
-
|
|
2036
|
-
|
|
2170
|
+
const bucket = this.arrayStore.getOrReserveBucket(key);
|
|
2171
|
+
if (this.bucketMatchesComparator(bucket, slots)) return;
|
|
2172
|
+
bucket.length = 0;
|
|
2173
|
+
for (let i = 0; i < slots.length; i++) bucket.push(slots[i]);
|
|
2174
|
+
if (bucket.length > 0) this.arrayStore.retainBucket(bucket);
|
|
2175
|
+
else this.arrayStore.releaseBucket(bucket);
|
|
2176
|
+
this.emitBucketChanged(bucket);
|
|
2037
2177
|
}
|
|
2038
2178
|
/**
|
|
2039
|
-
* Appends pre-deduplicated slots to a key's bucket IN PLACE
|
|
2040
|
-
*
|
|
2041
|
-
* not O(bucket)); used by collection-bound indexes for fast `addPks`.
|
|
2179
|
+
* Appends pre-deduplicated slots to a key's bucket IN PLACE and emits once.
|
|
2180
|
+
* O(added); callers own dedup.
|
|
2042
2181
|
*/
|
|
2043
2182
|
appendSlots(key, slots) {
|
|
2044
2183
|
if (slots.length === 0) return;
|
|
2045
|
-
|
|
2046
|
-
if (!bucket) {
|
|
2047
|
-
bucket = [];
|
|
2048
|
-
this.store.setOneByKey(key, bucket);
|
|
2049
|
-
}
|
|
2184
|
+
const bucket = this.arrayStore.getOrReserveBucket(key);
|
|
2050
2185
|
for (let i = 0; i < slots.length; i++) bucket.push(slots[i]);
|
|
2051
|
-
this.
|
|
2186
|
+
this.arrayStore.retainBucket(bucket);
|
|
2187
|
+
this.emitBucketChanged(bucket);
|
|
2052
2188
|
}
|
|
2053
2189
|
/**
|
|
2054
|
-
* Clear all primary keys for a specific index key, or all keys if
|
|
2190
|
+
* Clear all primary keys for a specific index key, or all keys if none given.
|
|
2055
2191
|
*/
|
|
2056
2192
|
clear(key) {
|
|
2057
2193
|
if (key === void 0) {
|
|
2058
|
-
const allKeys = this.
|
|
2194
|
+
const allKeys = this.arrayStore.getAllKeys();
|
|
2059
2195
|
if (allKeys.length > 0) {
|
|
2060
|
-
this.
|
|
2196
|
+
this.arrayStore.clear();
|
|
2061
2197
|
this.emitUpdate(allKeys);
|
|
2062
2198
|
}
|
|
2063
2199
|
} else {
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2200
|
+
const bucket = this.arrayStore.findBucket(key);
|
|
2201
|
+
if (bucket && bucket.length > 0) {
|
|
2202
|
+
bucket.length = 0;
|
|
2203
|
+
this.arrayStore.releaseBucket(bucket);
|
|
2204
|
+
this.emitBucketChanged(bucket);
|
|
2067
2205
|
}
|
|
2068
2206
|
}
|
|
2069
2207
|
}
|
|
2208
|
+
/**
|
|
2209
|
+
* Emit that a bucket changed. Base (non-reactive) path emits by key on the
|
|
2210
|
+
* plain event emitter; the reactive subclass overrides this to mark the
|
|
2211
|
+
* bucket carrier directly (O(1), no key→carrier lookup).
|
|
2212
|
+
*/
|
|
2213
|
+
emitBucketChanged(bucket) {
|
|
2214
|
+
this.emitUpdateOne(bucket.key);
|
|
2215
|
+
}
|
|
2216
|
+
};
|
|
2217
|
+
|
|
2218
|
+
// src/core/OIMBucketCarrierProvider.ts
|
|
2219
|
+
var OIMBucketCarrierProvider = class {
|
|
2220
|
+
constructor(store) {
|
|
2221
|
+
this.store = store;
|
|
2222
|
+
}
|
|
2223
|
+
getOrReserveCarrier(key) {
|
|
2224
|
+
return this.store.getOrReserveBucket(key);
|
|
2225
|
+
}
|
|
2226
|
+
findCarrier(key) {
|
|
2227
|
+
return this.store.findBucket(key);
|
|
2228
|
+
}
|
|
2229
|
+
onCarrierEmptied(carrier) {
|
|
2230
|
+
this.store.dropIfReserved(carrier.key);
|
|
2231
|
+
}
|
|
2070
2232
|
};
|
|
2071
2233
|
|
|
2072
2234
|
// src/core/OIMReactiveIndexManualArrayBased.ts
|
|
@@ -2075,6 +2237,10 @@ var OIMIndexManualArrayBasedReactive = class extends OIMIndexManualArrayBased {
|
|
|
2075
2237
|
super(opts);
|
|
2076
2238
|
this.updateEmitter = updateEmitter;
|
|
2077
2239
|
}
|
|
2240
|
+
// Deliver straight off the bucket the write just touched — O(1).
|
|
2241
|
+
emitBucketChanged(bucket) {
|
|
2242
|
+
this.updateEmitter.markUpdatedCarrier(bucket);
|
|
2243
|
+
}
|
|
2078
2244
|
emitUpdate(keys) {
|
|
2079
2245
|
this.updateEmitter.markUpdatedKeys(keys);
|
|
2080
2246
|
}
|
|
@@ -2084,12 +2250,15 @@ var OIMIndexManualArrayBasedReactive = class extends OIMIndexManualArrayBased {
|
|
|
2084
2250
|
};
|
|
2085
2251
|
var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased {
|
|
2086
2252
|
constructor(queue, opts) {
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2253
|
+
const store = opts?.indexOptions?.store ?? new OIMIndexStoreMapDrivenArrayBased();
|
|
2254
|
+
super(
|
|
2255
|
+
queue,
|
|
2256
|
+
(updateEmitter) => new OIMIndexManualArrayBasedReactive(updateEmitter, {
|
|
2257
|
+
comparePks: opts?.indexOptions?.comparePks,
|
|
2258
|
+
store
|
|
2259
|
+
}),
|
|
2260
|
+
() => new OIMBucketCarrierProvider(store)
|
|
2261
|
+
);
|
|
2093
2262
|
}
|
|
2094
2263
|
setSlots(key, slots) {
|
|
2095
2264
|
this.index.setSlots(key, slots);
|
|
@@ -2105,50 +2274,61 @@ var OIMReactiveIndexManualArrayBased = class extends OIMReactiveIndexArrayBased
|
|
|
2105
2274
|
// src/core/OIMReactiveCollectionIndexManualArrayBased.ts
|
|
2106
2275
|
var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexManualArrayBased {
|
|
2107
2276
|
constructor(queue, opts) {
|
|
2108
|
-
const
|
|
2277
|
+
const getSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.getSlot;
|
|
2109
2278
|
super(queue, {
|
|
2110
2279
|
indexOptions: opts.indexOptions
|
|
2111
2280
|
});
|
|
2112
|
-
// Persistent per-key
|
|
2113
|
-
//
|
|
2114
|
-
|
|
2115
|
-
this.
|
|
2281
|
+
// Persistent per-key membership for O(1) `addPks` dedup, keyed by the
|
|
2282
|
+
// canonical slot reference (correct for composite pks with a native Set — no
|
|
2283
|
+
// content-addressing needed, since slots are one reference per logical key).
|
|
2284
|
+
this.slotsByKey = /* @__PURE__ */ new Map();
|
|
2285
|
+
this.getSlot = getSlot;
|
|
2286
|
+
this.findSlotForRemoval = opts.collection !== void 0 ? (pk) => opts.collection.findSlotByPk(pk) : opts.getSlot;
|
|
2116
2287
|
}
|
|
2117
2288
|
setPks(key, pks) {
|
|
2118
|
-
const
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
super.setSlots(key, this.resolveSlots(pks));
|
|
2289
|
+
const slots = this.getSlotsOrTransient(pks);
|
|
2290
|
+
this.slotsByKey.set(key, new Set(slots));
|
|
2291
|
+
super.setSlots(key, slots);
|
|
2122
2292
|
}
|
|
2123
2293
|
addPks(key, pks) {
|
|
2124
2294
|
if (pks.length === 0) return;
|
|
2125
|
-
const
|
|
2295
|
+
const slotSet = this.membershipOf(key);
|
|
2126
2296
|
const newSlots = [];
|
|
2127
2297
|
for (const pk of pks) {
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2298
|
+
const slot = this.getSlotOrTransient(pk);
|
|
2299
|
+
if (slotSet.has(slot)) continue;
|
|
2300
|
+
slotSet.add(slot);
|
|
2301
|
+
newSlots.push(slot);
|
|
2131
2302
|
}
|
|
2132
2303
|
if (newSlots.length > 0) this.appendSlots(key, newSlots);
|
|
2133
2304
|
}
|
|
2134
2305
|
removePks(key, pks) {
|
|
2135
2306
|
if (pks.length === 0) return;
|
|
2136
|
-
const
|
|
2307
|
+
const slotsToRemove = /* @__PURE__ */ new Set();
|
|
2308
|
+
const pksToRemove = /* @__PURE__ */ new Set();
|
|
2309
|
+
for (let i = 0; i < pks.length; i++) {
|
|
2310
|
+
const slot = this.findSlotForRemoval(pks[i]);
|
|
2311
|
+
if (slot) slotsToRemove.add(slot);
|
|
2312
|
+
else pksToRemove.add(pks[i]);
|
|
2313
|
+
}
|
|
2137
2314
|
const existingSlots = this.index.getSlotsByKey(key);
|
|
2138
|
-
const
|
|
2139
|
-
|
|
2140
|
-
)
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2315
|
+
const slotSet = this.slotsByKey.get(key);
|
|
2316
|
+
const nextSlots = [];
|
|
2317
|
+
for (let i = 0; i < existingSlots.length; i++) {
|
|
2318
|
+
const slot = existingSlots[i];
|
|
2319
|
+
if (slotsToRemove.has(slot) || pksToRemove.has(slot.pk)) {
|
|
2320
|
+
slotSet?.delete(slot);
|
|
2321
|
+
} else {
|
|
2322
|
+
nextSlots.push(slot);
|
|
2323
|
+
}
|
|
2145
2324
|
}
|
|
2325
|
+
if (nextSlots.length === existingSlots.length) return;
|
|
2146
2326
|
if (nextSlots.length === 0) this.clear(key);
|
|
2147
2327
|
else super.setSlots(key, nextSlots);
|
|
2148
2328
|
}
|
|
2149
2329
|
clear(key) {
|
|
2150
|
-
if (key === void 0) this.
|
|
2151
|
-
else this.
|
|
2330
|
+
if (key === void 0) this.slotsByKey.clear();
|
|
2331
|
+
else this.slotsByKey.delete(key);
|
|
2152
2332
|
super.clear(key);
|
|
2153
2333
|
}
|
|
2154
2334
|
/**
|
|
@@ -2156,16 +2336,12 @@ var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexM
|
|
|
2156
2336
|
* stays correct even if slots were set through a lower-level path.
|
|
2157
2337
|
*/
|
|
2158
2338
|
membershipOf(key) {
|
|
2159
|
-
let
|
|
2160
|
-
if (!
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
for (let i = 0; i < existing.length; i++) {
|
|
2164
|
-
pkSet.add(existing[i].pk);
|
|
2165
|
-
}
|
|
2166
|
-
this.pksByKey.set(key, pkSet);
|
|
2339
|
+
let slotSet = this.slotsByKey.get(key);
|
|
2340
|
+
if (!slotSet) {
|
|
2341
|
+
slotSet = new Set(this.index.getSlotsByKey(key));
|
|
2342
|
+
this.slotsByKey.set(key, slotSet);
|
|
2167
2343
|
}
|
|
2168
|
-
return
|
|
2344
|
+
return slotSet;
|
|
2169
2345
|
}
|
|
2170
2346
|
getEntitiesByKey(key) {
|
|
2171
2347
|
return super.getEntitiesByKey(key);
|
|
@@ -2173,16 +2349,16 @@ var OIMReactiveCollectionIndexManualArrayBased = class extends OIMReactiveIndexM
|
|
|
2173
2349
|
getEntitiesByKeys(keys) {
|
|
2174
2350
|
return super.getEntitiesByKeys(keys);
|
|
2175
2351
|
}
|
|
2176
|
-
|
|
2352
|
+
getSlotsOrTransient(pks) {
|
|
2177
2353
|
const slots = [];
|
|
2178
2354
|
slots.length = pks.length;
|
|
2179
2355
|
for (let i = 0; i < pks.length; i++) {
|
|
2180
|
-
slots[i] = this.
|
|
2356
|
+
slots[i] = this.getSlotOrTransient(pks[i]);
|
|
2181
2357
|
}
|
|
2182
2358
|
return slots;
|
|
2183
2359
|
}
|
|
2184
|
-
|
|
2185
|
-
const slot = this.
|
|
2360
|
+
getSlotOrTransient(pk) {
|
|
2361
|
+
const slot = this.getSlot(pk);
|
|
2186
2362
|
if (!slot) return { pk, item: void 0 };
|
|
2187
2363
|
return slot;
|
|
2188
2364
|
}
|
|
@@ -2194,22 +2370,101 @@ var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
|
2194
2370
|
super(options);
|
|
2195
2371
|
}
|
|
2196
2372
|
setSlots(key, slots) {
|
|
2197
|
-
const
|
|
2198
|
-
|
|
2199
|
-
|
|
2373
|
+
const bucket = this.setStore.getOrReserveBucket(key);
|
|
2374
|
+
this.replaceBucketContents(bucket, slots);
|
|
2375
|
+
}
|
|
2376
|
+
// --- pk-oriented writes: resolve the bucket ONCE and use its own membership
|
|
2377
|
+
// (pk → slot) for dedup/removal, so a composite (trie) key is walked a single
|
|
2378
|
+
// time instead of once for the bucket and once for a separate membership map.
|
|
2379
|
+
setPks(key, pks, getSlot) {
|
|
2380
|
+
const bucket = this.setStore.getOrReserveBucket(key);
|
|
2381
|
+
const slots = [];
|
|
2382
|
+
for (let i = 0; i < pks.length; i++) slots.push(getSlot(pks[i]));
|
|
2383
|
+
this.replaceBucketContents(bucket, slots);
|
|
2384
|
+
const membership = bucket.membership ?? (bucket.membership = /* @__PURE__ */ new Map());
|
|
2385
|
+
membership.clear();
|
|
2386
|
+
for (let i = 0; i < slots.length; i++) {
|
|
2387
|
+
if (!membership.has(slots[i].pk)) {
|
|
2388
|
+
membership.set(slots[i].pk, slots[i]);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
addPks(key, pks, getSlot) {
|
|
2393
|
+
if (pks.length === 0) return;
|
|
2394
|
+
const bucket = this.setStore.getOrReserveBucket(key);
|
|
2395
|
+
const membership = this.membershipOf(bucket);
|
|
2396
|
+
let changed = false;
|
|
2397
|
+
for (let i = 0; i < pks.length; i++) {
|
|
2398
|
+
const slot = getSlot(pks[i]);
|
|
2399
|
+
if (membership.has(slot.pk)) continue;
|
|
2400
|
+
membership.set(slot.pk, slot);
|
|
2401
|
+
if (!bucket.has(slot)) {
|
|
2402
|
+
bucket.add(slot);
|
|
2403
|
+
changed = true;
|
|
2404
|
+
}
|
|
2200
2405
|
}
|
|
2406
|
+
if (!changed) return;
|
|
2407
|
+
this.setStore.retainBucket(bucket);
|
|
2408
|
+
this.emitBucketChanged(bucket);
|
|
2201
2409
|
}
|
|
2202
2410
|
/**
|
|
2203
|
-
*
|
|
2204
|
-
*
|
|
2411
|
+
* Removes by pk. `pks` must be canonical `slot.pk` references (membership is
|
|
2412
|
+
* keyed by them): for primitive pks that is just the pk; a collection-bound
|
|
2413
|
+
* composite index canonicalizes raw pks to `slot.pk` before calling this.
|
|
2414
|
+
*/
|
|
2415
|
+
removePks(key, pks) {
|
|
2416
|
+
if (pks.length === 0) return;
|
|
2417
|
+
const bucket = this.setStore.findBucket(key);
|
|
2418
|
+
if (!bucket || bucket.size === 0) return;
|
|
2419
|
+
const membership = this.membershipOf(bucket);
|
|
2420
|
+
let changed = false;
|
|
2421
|
+
for (let i = 0; i < pks.length; i++) {
|
|
2422
|
+
const slot = membership.get(pks[i]);
|
|
2423
|
+
if (slot) {
|
|
2424
|
+
membership.delete(pks[i]);
|
|
2425
|
+
if (bucket.delete(slot)) changed = true;
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
if (!changed) return;
|
|
2429
|
+
if (bucket.size === 0) this.setStore.releaseBucket(bucket);
|
|
2430
|
+
this.emitBucketChanged(bucket);
|
|
2431
|
+
}
|
|
2432
|
+
/**
|
|
2433
|
+
* The bucket's pk → slot membership, lazily created and seeded from the
|
|
2434
|
+
* bucket's current slots (so it stays correct even if slots were written
|
|
2435
|
+
* through the lower-level `setSlots` path).
|
|
2436
|
+
*/
|
|
2437
|
+
membershipOf(bucket) {
|
|
2438
|
+
let membership = bucket.membership;
|
|
2439
|
+
if (!membership) {
|
|
2440
|
+
membership = /* @__PURE__ */ new Map();
|
|
2441
|
+
bucket.membership = membership;
|
|
2442
|
+
}
|
|
2443
|
+
if (membership.size === 0 && bucket.size > 0) {
|
|
2444
|
+
for (const slot of bucket) membership.set(slot.pk, slot);
|
|
2445
|
+
}
|
|
2446
|
+
return membership;
|
|
2447
|
+
}
|
|
2448
|
+
replaceBucketContents(bucket, slots) {
|
|
2449
|
+
if (this.comparePks) {
|
|
2450
|
+
const newSet = slots instanceof Set ? slots : new Set(slots);
|
|
2451
|
+
if (this.bucketMatchesComparator(bucket, newSet)) return;
|
|
2452
|
+
bucket.clear();
|
|
2453
|
+
for (const slot of newSet) bucket.add(slot);
|
|
2454
|
+
} else {
|
|
2455
|
+
bucket.clear();
|
|
2456
|
+
for (const slot of slots) bucket.add(slot);
|
|
2457
|
+
}
|
|
2458
|
+
if (bucket.size > 0) this.setStore.retainBucket(bucket);
|
|
2459
|
+
else this.setStore.releaseBucket(bucket);
|
|
2460
|
+
this.emitBucketChanged(bucket);
|
|
2461
|
+
}
|
|
2462
|
+
/**
|
|
2463
|
+
* Adds slots to a key's bucket IN PLACE and emits once. O(added).
|
|
2205
2464
|
*/
|
|
2206
2465
|
addSlots(key, slots) {
|
|
2207
2466
|
if (slots.length === 0) return;
|
|
2208
|
-
|
|
2209
|
-
if (!bucket) {
|
|
2210
|
-
bucket = /* @__PURE__ */ new Set();
|
|
2211
|
-
this.store.setOneByKey(key, bucket);
|
|
2212
|
-
}
|
|
2467
|
+
const bucket = this.setStore.getOrReserveBucket(key);
|
|
2213
2468
|
let changed = false;
|
|
2214
2469
|
for (let i = 0; i < slots.length; i++) {
|
|
2215
2470
|
if (!bucket.has(slots[i])) {
|
|
@@ -2217,25 +2472,27 @@ var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
|
2217
2472
|
changed = true;
|
|
2218
2473
|
}
|
|
2219
2474
|
}
|
|
2220
|
-
if (changed)
|
|
2475
|
+
if (!changed) return;
|
|
2476
|
+
this.setStore.retainBucket(bucket);
|
|
2477
|
+
this.emitBucketChanged(bucket);
|
|
2221
2478
|
}
|
|
2222
2479
|
/**
|
|
2223
2480
|
* Removes slots from a key's bucket IN PLACE (O(removed)) and emits once.
|
|
2224
2481
|
*/
|
|
2225
2482
|
removeSlots(key, slots) {
|
|
2226
2483
|
if (slots.length === 0) return;
|
|
2227
|
-
const bucket = this.
|
|
2484
|
+
const bucket = this.setStore.findBucket(key);
|
|
2228
2485
|
if (!bucket) return;
|
|
2229
2486
|
let changed = false;
|
|
2230
2487
|
for (let i = 0; i < slots.length; i++) {
|
|
2231
2488
|
if (bucket.delete(slots[i])) changed = true;
|
|
2232
2489
|
}
|
|
2233
2490
|
if (!changed) return;
|
|
2234
|
-
if (bucket.size === 0) this.
|
|
2235
|
-
this.
|
|
2491
|
+
if (bucket.size === 0) this.setStore.releaseBucket(bucket);
|
|
2492
|
+
this.emitBucketChanged(bucket);
|
|
2236
2493
|
}
|
|
2237
2494
|
/**
|
|
2238
|
-
* Clear all primary keys for a specific index key, or all keys if
|
|
2495
|
+
* Clear all primary keys for a specific index key, or all keys if none given.
|
|
2239
2496
|
*/
|
|
2240
2497
|
clear(key) {
|
|
2241
2498
|
if (key === void 0) {
|
|
@@ -2245,12 +2502,22 @@ var OIMIndexManualSetBased = class extends OIMIndexSetBased {
|
|
|
2245
2502
|
this.emitUpdate(allKeys);
|
|
2246
2503
|
}
|
|
2247
2504
|
} else {
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2505
|
+
const bucket = this.setStore.findBucket(key);
|
|
2506
|
+
if (bucket && bucket.size > 0) {
|
|
2507
|
+
bucket.clear();
|
|
2508
|
+
this.setStore.releaseBucket(bucket);
|
|
2509
|
+
this.emitBucketChanged(bucket);
|
|
2251
2510
|
}
|
|
2252
2511
|
}
|
|
2253
2512
|
}
|
|
2513
|
+
/**
|
|
2514
|
+
* Emit that a bucket changed. Base (non-reactive) path emits by key on the
|
|
2515
|
+
* plain event emitter; the reactive subclass overrides this to mark the
|
|
2516
|
+
* bucket carrier directly (O(1), no key→carrier lookup).
|
|
2517
|
+
*/
|
|
2518
|
+
emitBucketChanged(bucket) {
|
|
2519
|
+
this.emitUpdateOne(bucket.key);
|
|
2520
|
+
}
|
|
2254
2521
|
};
|
|
2255
2522
|
|
|
2256
2523
|
// src/core/OIMReactiveIndexManualSetBased.ts
|
|
@@ -2259,6 +2526,12 @@ var OIMIndexManualSetBasedReactive = class extends OIMIndexManualSetBased {
|
|
|
2259
2526
|
super(opts);
|
|
2260
2527
|
this.updateEmitter = updateEmitter;
|
|
2261
2528
|
}
|
|
2529
|
+
// Deliver straight off the bucket the write just touched — O(1), no
|
|
2530
|
+
// key→carrier lookup (the whole point of bucket-as-carrier).
|
|
2531
|
+
emitBucketChanged(bucket) {
|
|
2532
|
+
this.updateEmitter.markUpdatedCarrier(bucket);
|
|
2533
|
+
}
|
|
2534
|
+
// clear(all) still emits by key set (rare path).
|
|
2262
2535
|
emitUpdate(keys) {
|
|
2263
2536
|
this.updateEmitter.markUpdatedKeys(keys);
|
|
2264
2537
|
}
|
|
@@ -2268,12 +2541,15 @@ var OIMIndexManualSetBasedReactive = class extends OIMIndexManualSetBased {
|
|
|
2268
2541
|
};
|
|
2269
2542
|
var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
2270
2543
|
constructor(queue, opts) {
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2544
|
+
const store = opts?.indexOptions?.store ?? new OIMIndexStoreMapDrivenSetBased();
|
|
2545
|
+
super(
|
|
2546
|
+
queue,
|
|
2547
|
+
(updateEmitter) => new OIMIndexManualSetBasedReactive(updateEmitter, {
|
|
2548
|
+
comparePks: opts?.indexOptions?.comparePks,
|
|
2549
|
+
store
|
|
2550
|
+
}),
|
|
2551
|
+
() => new OIMBucketCarrierProvider(store)
|
|
2552
|
+
);
|
|
2277
2553
|
}
|
|
2278
2554
|
setSlots(key, slots) {
|
|
2279
2555
|
this.index.setSlots(key, slots);
|
|
@@ -2292,73 +2568,439 @@ var OIMReactiveIndexManualSetBased = class extends OIMReactiveIndexSetBased {
|
|
|
2292
2568
|
// src/core/OIMReactiveCollectionIndexManualSetBased.ts
|
|
2293
2569
|
var OIMReactiveCollectionIndexManualSetBased = class extends OIMReactiveIndexManualSetBased {
|
|
2294
2570
|
constructor(queue, opts) {
|
|
2295
|
-
const
|
|
2571
|
+
const getSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.getSlot;
|
|
2296
2572
|
super(queue, {
|
|
2297
2573
|
indexOptions: opts.indexOptions
|
|
2298
2574
|
});
|
|
2299
|
-
//
|
|
2300
|
-
//
|
|
2301
|
-
this.
|
|
2302
|
-
|
|
2575
|
+
// Bound once so the hot pk-write path passes a stable function (no per-call
|
|
2576
|
+
// closure allocation).
|
|
2577
|
+
this.getSlotOrTransient = (pk) => {
|
|
2578
|
+
const slot = this.getSlot(pk);
|
|
2579
|
+
if (!slot) return { pk, item: void 0 };
|
|
2580
|
+
return slot;
|
|
2581
|
+
};
|
|
2582
|
+
this.getSlot = getSlot;
|
|
2583
|
+
this.findSlotForRemoval = opts.collection !== void 0 ? (pk) => opts.collection.findSlotByPk(pk) : opts.getSlot;
|
|
2303
2584
|
}
|
|
2304
2585
|
setPks(key, pks) {
|
|
2305
|
-
|
|
2306
|
-
|
|
2586
|
+
this.index.setPks(key, pks, this.getSlotOrTransient);
|
|
2587
|
+
}
|
|
2588
|
+
addPks(key, pks) {
|
|
2589
|
+
this.index.addPks(key, pks, this.getSlotOrTransient);
|
|
2590
|
+
}
|
|
2591
|
+
removePks(key, pks) {
|
|
2592
|
+
const canonical = [];
|
|
2307
2593
|
for (let i = 0; i < pks.length; i++) {
|
|
2308
|
-
const
|
|
2309
|
-
|
|
2310
|
-
if (!map.has(pk)) map.set(pk, slot);
|
|
2311
|
-
slots.push(slot);
|
|
2594
|
+
const slot = this.findSlotForRemoval(pks[i]);
|
|
2595
|
+
canonical.push(slot ? slot.pk : pks[i]);
|
|
2312
2596
|
}
|
|
2313
|
-
this.
|
|
2314
|
-
|
|
2597
|
+
this.index.removePks(key, canonical);
|
|
2598
|
+
}
|
|
2599
|
+
getEntitiesByKey(key) {
|
|
2600
|
+
return super.getEntitiesByKey(key);
|
|
2601
|
+
}
|
|
2602
|
+
getEntitiesByKeys(keys) {
|
|
2603
|
+
return super.getEntitiesByKeys(keys);
|
|
2604
|
+
}
|
|
2605
|
+
};
|
|
2606
|
+
|
|
2607
|
+
// src/core/OIMTrieMap.ts
|
|
2608
|
+
var OIMTrieMap = class {
|
|
2609
|
+
constructor() {
|
|
2610
|
+
this.root = { hasValue: false };
|
|
2611
|
+
this._size = 0;
|
|
2612
|
+
}
|
|
2613
|
+
/** Number of stored paths (terminal nodes), not the number of trie nodes. */
|
|
2614
|
+
get size() {
|
|
2615
|
+
return this._size;
|
|
2616
|
+
}
|
|
2617
|
+
set(path, value) {
|
|
2618
|
+
let node = this.root;
|
|
2619
|
+
for (let i = 0; i < path.length; i++) {
|
|
2620
|
+
let children = node.children;
|
|
2621
|
+
if (!children) {
|
|
2622
|
+
children = /* @__PURE__ */ new Map();
|
|
2623
|
+
node.children = children;
|
|
2624
|
+
}
|
|
2625
|
+
let next = children.get(path[i]);
|
|
2626
|
+
if (!next) {
|
|
2627
|
+
next = { hasValue: false };
|
|
2628
|
+
children.set(path[i], next);
|
|
2629
|
+
}
|
|
2630
|
+
node = next;
|
|
2631
|
+
}
|
|
2632
|
+
if (!node.hasValue) {
|
|
2633
|
+
node.hasValue = true;
|
|
2634
|
+
this._size++;
|
|
2635
|
+
}
|
|
2636
|
+
node.value = value;
|
|
2637
|
+
}
|
|
2638
|
+
get(path) {
|
|
2639
|
+
const node = this.findNode(path);
|
|
2640
|
+
return node && node.hasValue ? node.value : void 0;
|
|
2641
|
+
}
|
|
2642
|
+
has(path) {
|
|
2643
|
+
const node = this.findNode(path);
|
|
2644
|
+
return !!node && node.hasValue;
|
|
2645
|
+
}
|
|
2646
|
+
delete(path) {
|
|
2647
|
+
const parents = [];
|
|
2648
|
+
let node = this.root;
|
|
2649
|
+
for (let i = 0; i < path.length; i++) {
|
|
2650
|
+
const next = node.children?.get(path[i]);
|
|
2651
|
+
if (!next) return false;
|
|
2652
|
+
parents.push(node);
|
|
2653
|
+
node = next;
|
|
2654
|
+
}
|
|
2655
|
+
if (!node.hasValue) return false;
|
|
2656
|
+
node.hasValue = false;
|
|
2657
|
+
node.value = void 0;
|
|
2658
|
+
this._size--;
|
|
2659
|
+
let child = node;
|
|
2660
|
+
for (let i = parents.length - 1; i >= 0; i--) {
|
|
2661
|
+
if (child.hasValue || child.children && child.children.size > 0) {
|
|
2662
|
+
break;
|
|
2663
|
+
}
|
|
2664
|
+
const parent = parents[i];
|
|
2665
|
+
parent.children.delete(path[i]);
|
|
2666
|
+
if (parent.children.size === 0) parent.children = void 0;
|
|
2667
|
+
child = parent;
|
|
2668
|
+
}
|
|
2669
|
+
return true;
|
|
2670
|
+
}
|
|
2671
|
+
clear() {
|
|
2672
|
+
this.root.children = void 0;
|
|
2673
|
+
this.root.value = void 0;
|
|
2674
|
+
this.root.hasValue = false;
|
|
2675
|
+
this._size = 0;
|
|
2676
|
+
}
|
|
2677
|
+
/** Depth-first iteration over `[path, value]` for every stored path. */
|
|
2678
|
+
*entries() {
|
|
2679
|
+
const stack = [{ node: this.root, path: [] }];
|
|
2680
|
+
while (stack.length > 0) {
|
|
2681
|
+
const frame = stack.pop();
|
|
2682
|
+
const { node, path } = frame;
|
|
2683
|
+
if (node.hasValue) {
|
|
2684
|
+
yield [path, node.value];
|
|
2685
|
+
}
|
|
2686
|
+
if (node.children) {
|
|
2687
|
+
for (const [segment, child] of node.children) {
|
|
2688
|
+
stack.push({ node: child, path: [...path, segment] });
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
*keys() {
|
|
2694
|
+
for (const [path] of this.entries()) yield path;
|
|
2695
|
+
}
|
|
2696
|
+
*values() {
|
|
2697
|
+
for (const [, value] of this.entries()) yield value;
|
|
2698
|
+
}
|
|
2699
|
+
findNode(path) {
|
|
2700
|
+
let node = this.root;
|
|
2701
|
+
for (let i = 0; i < path.length; i++) {
|
|
2702
|
+
node = node.children?.get(path[i]);
|
|
2703
|
+
if (!node) return void 0;
|
|
2704
|
+
}
|
|
2705
|
+
return node;
|
|
2706
|
+
}
|
|
2707
|
+
};
|
|
2708
|
+
|
|
2709
|
+
// src/core/OIMIndexStoreTrieDrivenSetBased.ts
|
|
2710
|
+
var OIMIndexStoreTrieDrivenSetBased = class extends OIMIndexStoreSetBased {
|
|
2711
|
+
constructor() {
|
|
2712
|
+
super(...arguments);
|
|
2713
|
+
this.slots = new OIMTrieMap();
|
|
2714
|
+
this.reservedBuckets = new OIMTrieMap();
|
|
2715
|
+
}
|
|
2716
|
+
getOrReserveBucket(key) {
|
|
2717
|
+
const live = this.slots.get(key);
|
|
2718
|
+
if (live) return live;
|
|
2719
|
+
let reserved = this.reservedBuckets.get(key);
|
|
2720
|
+
if (!reserved) {
|
|
2721
|
+
reserved = new OIMKeyedBucketSetBased(key);
|
|
2722
|
+
this.reservedBuckets.set(key, reserved);
|
|
2723
|
+
}
|
|
2724
|
+
return reserved;
|
|
2725
|
+
}
|
|
2726
|
+
findBucket(key) {
|
|
2727
|
+
return this.slots.get(key) ?? this.reservedBuckets.get(key);
|
|
2728
|
+
}
|
|
2729
|
+
retainBucket(bucket) {
|
|
2730
|
+
if (bucket.size === 0) return;
|
|
2731
|
+
this.reservedBuckets.delete(bucket.key);
|
|
2732
|
+
if (!this.slots.has(bucket.key)) this.slots.set(bucket.key, bucket);
|
|
2733
|
+
}
|
|
2734
|
+
releaseBucket(bucket) {
|
|
2735
|
+
if (bucket.size > 0) return;
|
|
2736
|
+
this.slots.delete(bucket.key);
|
|
2737
|
+
if (bucket.hasSubscribers()) {
|
|
2738
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
2739
|
+
} else {
|
|
2740
|
+
this.reservedBuckets.delete(bucket.key);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
dropIfReserved(key) {
|
|
2744
|
+
const reserved = this.reservedBuckets.get(key);
|
|
2745
|
+
if (reserved && reserved.size === 0 && !reserved.hasSubscribers()) {
|
|
2746
|
+
this.reservedBuckets.delete(key);
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
setOneByKey(key, slots) {
|
|
2750
|
+
const bucket = this.getOrReserveBucket(key);
|
|
2751
|
+
if (bucket !== slots) {
|
|
2752
|
+
bucket.clear();
|
|
2753
|
+
for (const slot of slots) bucket.add(slot);
|
|
2754
|
+
}
|
|
2755
|
+
if (bucket.size > 0) this.retainBucket(bucket);
|
|
2756
|
+
else this.releaseBucket(bucket);
|
|
2757
|
+
}
|
|
2758
|
+
removeOneByKey(key) {
|
|
2759
|
+
this.slots.delete(key);
|
|
2760
|
+
this.reservedBuckets.delete(key);
|
|
2761
|
+
}
|
|
2762
|
+
removeManyByKeys(keys) {
|
|
2763
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2764
|
+
this.slots.delete(keys[i]);
|
|
2765
|
+
this.reservedBuckets.delete(keys[i]);
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2768
|
+
getOneByKey(key) {
|
|
2769
|
+
return this.slots.get(key);
|
|
2770
|
+
}
|
|
2771
|
+
getManyByKeys(keys) {
|
|
2772
|
+
const result = /* @__PURE__ */ new Map();
|
|
2773
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2774
|
+
const slots = this.slots.get(keys[i]);
|
|
2775
|
+
if (slots !== void 0) result.set(keys[i], slots);
|
|
2776
|
+
}
|
|
2777
|
+
return result;
|
|
2778
|
+
}
|
|
2779
|
+
getAllKeys() {
|
|
2780
|
+
return Array.from(this.slots.keys());
|
|
2781
|
+
}
|
|
2782
|
+
getAll() {
|
|
2783
|
+
const result = /* @__PURE__ */ new Map();
|
|
2784
|
+
for (const [path, bucket] of this.slots.entries()) {
|
|
2785
|
+
result.set(path, bucket);
|
|
2786
|
+
}
|
|
2787
|
+
return result;
|
|
2788
|
+
}
|
|
2789
|
+
countAll() {
|
|
2790
|
+
return this.slots.size;
|
|
2791
|
+
}
|
|
2792
|
+
clear() {
|
|
2793
|
+
for (const bucket of this.slots.values()) {
|
|
2794
|
+
bucket.clear();
|
|
2795
|
+
if (bucket.hasSubscribers()) {
|
|
2796
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
this.slots.clear();
|
|
2800
|
+
}
|
|
2801
|
+
};
|
|
2802
|
+
|
|
2803
|
+
// src/core/OIMReactiveCollectionIndexCompositeTrieSetBased.ts
|
|
2804
|
+
var OIMReactiveCollectionIndexCompositeTrieSetBased = class extends OIMReactiveIndexManualSetBased {
|
|
2805
|
+
constructor(queue, opts) {
|
|
2806
|
+
const getSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.getSlot;
|
|
2807
|
+
super(queue, {
|
|
2808
|
+
indexOptions: {
|
|
2809
|
+
comparePks: opts.indexOptions?.comparePks,
|
|
2810
|
+
store: opts.indexOptions?.store ?? new OIMIndexStoreTrieDrivenSetBased()
|
|
2811
|
+
}
|
|
2812
|
+
});
|
|
2813
|
+
this.getSlotOrTransient = (pk) => {
|
|
2814
|
+
const slot = this.getSlot(pk);
|
|
2815
|
+
if (!slot) return { pk, item: void 0 };
|
|
2816
|
+
return slot;
|
|
2817
|
+
};
|
|
2818
|
+
this.getSlot = getSlot;
|
|
2819
|
+
this.findSlotForRemoval = opts.collection !== void 0 ? (pk) => opts.collection.findSlotByPk(pk) : opts.getSlot;
|
|
2820
|
+
}
|
|
2821
|
+
setPks(key, pks) {
|
|
2822
|
+
this.index.setPks(key, pks, this.getSlotOrTransient);
|
|
2823
|
+
}
|
|
2824
|
+
addPks(key, pks) {
|
|
2825
|
+
this.index.addPks(key, pks, this.getSlotOrTransient);
|
|
2826
|
+
}
|
|
2827
|
+
removePks(key, pks) {
|
|
2828
|
+
const canonical = [];
|
|
2829
|
+
for (let i = 0; i < pks.length; i++) {
|
|
2830
|
+
const slot = this.findSlotForRemoval(pks[i]);
|
|
2831
|
+
canonical.push(slot ? slot.pk : pks[i]);
|
|
2832
|
+
}
|
|
2833
|
+
this.index.removePks(key, canonical);
|
|
2834
|
+
}
|
|
2835
|
+
getEntitiesByKey(key) {
|
|
2836
|
+
return super.getEntitiesByKey(key);
|
|
2837
|
+
}
|
|
2838
|
+
getEntitiesByKeys(keys) {
|
|
2839
|
+
return super.getEntitiesByKeys(keys);
|
|
2840
|
+
}
|
|
2841
|
+
};
|
|
2842
|
+
|
|
2843
|
+
// src/core/OIMIndexStoreTrieDrivenArrayBased.ts
|
|
2844
|
+
var OIMIndexStoreTrieDrivenArrayBased = class extends OIMIndexStoreArrayBased {
|
|
2845
|
+
constructor() {
|
|
2846
|
+
super(...arguments);
|
|
2847
|
+
this.slots = new OIMTrieMap();
|
|
2848
|
+
this.reservedBuckets = new OIMTrieMap();
|
|
2849
|
+
}
|
|
2850
|
+
getOrReserveBucket(key) {
|
|
2851
|
+
const live = this.slots.get(key);
|
|
2852
|
+
if (live) return live;
|
|
2853
|
+
let reserved = this.reservedBuckets.get(key);
|
|
2854
|
+
if (!reserved) {
|
|
2855
|
+
reserved = new OIMKeyedBucketArrayBased(key);
|
|
2856
|
+
this.reservedBuckets.set(key, reserved);
|
|
2857
|
+
}
|
|
2858
|
+
return reserved;
|
|
2859
|
+
}
|
|
2860
|
+
findBucket(key) {
|
|
2861
|
+
return this.slots.get(key) ?? this.reservedBuckets.get(key);
|
|
2862
|
+
}
|
|
2863
|
+
retainBucket(bucket) {
|
|
2864
|
+
if (bucket.length === 0) return;
|
|
2865
|
+
this.reservedBuckets.delete(bucket.key);
|
|
2866
|
+
if (!this.slots.has(bucket.key)) this.slots.set(bucket.key, bucket);
|
|
2867
|
+
}
|
|
2868
|
+
releaseBucket(bucket) {
|
|
2869
|
+
if (bucket.length > 0) return;
|
|
2870
|
+
this.slots.delete(bucket.key);
|
|
2871
|
+
if (bucket.hasSubscribers()) {
|
|
2872
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
2873
|
+
} else {
|
|
2874
|
+
this.reservedBuckets.delete(bucket.key);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
dropIfReserved(key) {
|
|
2878
|
+
const reserved = this.reservedBuckets.get(key);
|
|
2879
|
+
if (reserved && reserved.length === 0 && !reserved.hasSubscribers()) {
|
|
2880
|
+
this.reservedBuckets.delete(key);
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
setOneByKey(key, slots) {
|
|
2884
|
+
const bucket = this.getOrReserveBucket(key);
|
|
2885
|
+
if (bucket !== slots) {
|
|
2886
|
+
bucket.length = 0;
|
|
2887
|
+
for (let i = 0; i < slots.length; i++) bucket.push(slots[i]);
|
|
2888
|
+
}
|
|
2889
|
+
if (bucket.length > 0) this.retainBucket(bucket);
|
|
2890
|
+
else this.releaseBucket(bucket);
|
|
2891
|
+
}
|
|
2892
|
+
removeOneByKey(key) {
|
|
2893
|
+
this.slots.delete(key);
|
|
2894
|
+
this.reservedBuckets.delete(key);
|
|
2895
|
+
}
|
|
2896
|
+
removeManyByKeys(keys) {
|
|
2897
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2898
|
+
this.slots.delete(keys[i]);
|
|
2899
|
+
this.reservedBuckets.delete(keys[i]);
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
getOneByKey(key) {
|
|
2903
|
+
return this.slots.get(key);
|
|
2904
|
+
}
|
|
2905
|
+
getManyByKeys(keys) {
|
|
2906
|
+
const result = /* @__PURE__ */ new Map();
|
|
2907
|
+
for (let i = 0; i < keys.length; i++) {
|
|
2908
|
+
const slots = this.slots.get(keys[i]);
|
|
2909
|
+
if (slots !== void 0) result.set(keys[i], slots);
|
|
2910
|
+
}
|
|
2911
|
+
return result;
|
|
2912
|
+
}
|
|
2913
|
+
getAllKeys() {
|
|
2914
|
+
return Array.from(this.slots.keys());
|
|
2915
|
+
}
|
|
2916
|
+
getAll() {
|
|
2917
|
+
const result = /* @__PURE__ */ new Map();
|
|
2918
|
+
for (const [path, bucket] of this.slots.entries()) {
|
|
2919
|
+
result.set(path, bucket);
|
|
2920
|
+
}
|
|
2921
|
+
return result;
|
|
2922
|
+
}
|
|
2923
|
+
countAll() {
|
|
2924
|
+
return this.slots.size;
|
|
2925
|
+
}
|
|
2926
|
+
clear() {
|
|
2927
|
+
for (const bucket of this.slots.values()) {
|
|
2928
|
+
bucket.length = 0;
|
|
2929
|
+
if (bucket.hasSubscribers()) {
|
|
2930
|
+
this.reservedBuckets.set(bucket.key, bucket);
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
this.slots.clear();
|
|
2934
|
+
}
|
|
2935
|
+
};
|
|
2936
|
+
|
|
2937
|
+
// src/core/OIMReactiveCollectionIndexCompositeTrieArrayBased.ts
|
|
2938
|
+
var OIMReactiveCollectionIndexCompositeTrieArrayBased = class extends OIMReactiveIndexManualArrayBased {
|
|
2939
|
+
constructor(queue, opts) {
|
|
2940
|
+
const getSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.getSlot;
|
|
2941
|
+
super(queue, {
|
|
2942
|
+
indexOptions: {
|
|
2943
|
+
comparePks: opts.indexOptions?.comparePks,
|
|
2944
|
+
store: opts.indexOptions?.store ?? new OIMIndexStoreTrieDrivenArrayBased()
|
|
2945
|
+
}
|
|
2946
|
+
});
|
|
2947
|
+
// Persistent per-key-path pk membership for O(1) `addPks` dedup. Trie-keyed
|
|
2948
|
+
// so a rebuilt key path matches by content.
|
|
2949
|
+
this.pksByKey = new OIMTrieMap();
|
|
2950
|
+
this.getSlot = getSlot;
|
|
2951
|
+
}
|
|
2952
|
+
setPks(key, pks) {
|
|
2953
|
+
const pkSet = /* @__PURE__ */ new Set();
|
|
2954
|
+
for (let i = 0; i < pks.length; i++) pkSet.add(pks[i]);
|
|
2955
|
+
this.pksByKey.set(key, pkSet);
|
|
2956
|
+
super.setSlots(key, this.getSlotsOrTransient(pks));
|
|
2315
2957
|
}
|
|
2316
2958
|
addPks(key, pks) {
|
|
2317
2959
|
if (pks.length === 0) return;
|
|
2318
|
-
const
|
|
2960
|
+
const pkSet = this.membershipOf(key);
|
|
2319
2961
|
const newSlots = [];
|
|
2320
2962
|
for (const pk of pks) {
|
|
2321
|
-
if (
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
newSlots.push(slot);
|
|
2963
|
+
if (pkSet.has(pk)) continue;
|
|
2964
|
+
pkSet.add(pk);
|
|
2965
|
+
newSlots.push(this.getSlotOrTransient(pk));
|
|
2325
2966
|
}
|
|
2326
|
-
if (newSlots.length > 0) this.
|
|
2967
|
+
if (newSlots.length > 0) this.appendSlots(key, newSlots);
|
|
2327
2968
|
}
|
|
2328
2969
|
removePks(key, pks) {
|
|
2329
2970
|
if (pks.length === 0) return;
|
|
2330
|
-
const
|
|
2331
|
-
|
|
2332
|
-
const
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2971
|
+
const pksToRemove = new Set(pks);
|
|
2972
|
+
const existingSlots = this.index.getSlotsByKey(key);
|
|
2973
|
+
const nextSlots = existingSlots.filter(
|
|
2974
|
+
(slot) => !pksToRemove.has(slot.pk)
|
|
2975
|
+
);
|
|
2976
|
+
if (nextSlots.length === existingSlots.length) return;
|
|
2977
|
+
const pkSet = this.pksByKey.get(key);
|
|
2978
|
+
if (pkSet) {
|
|
2979
|
+
for (let i = 0; i < pks.length; i++) pkSet.delete(pks[i]);
|
|
2339
2980
|
}
|
|
2340
|
-
if (
|
|
2341
|
-
|
|
2342
|
-
this.removeSlots(key, removed);
|
|
2981
|
+
if (nextSlots.length === 0) this.clear(key);
|
|
2982
|
+
else super.setSlots(key, nextSlots);
|
|
2343
2983
|
}
|
|
2344
2984
|
clear(key) {
|
|
2345
|
-
if (key === void 0) this.
|
|
2346
|
-
else this.
|
|
2985
|
+
if (key === void 0) this.pksByKey.clear();
|
|
2986
|
+
else this.pksByKey.delete(key);
|
|
2347
2987
|
super.clear(key);
|
|
2348
2988
|
}
|
|
2349
2989
|
/**
|
|
2350
|
-
* The
|
|
2351
|
-
* stays correct even if slots were set through a lower-level path.
|
|
2990
|
+
* The membership set for a key path, lazily seeded from the current bucket so
|
|
2991
|
+
* it stays correct even if slots were set through a lower-level path.
|
|
2352
2992
|
*/
|
|
2353
2993
|
membershipOf(key) {
|
|
2354
|
-
let
|
|
2355
|
-
if (!
|
|
2356
|
-
|
|
2994
|
+
let pkSet = this.pksByKey.get(key);
|
|
2995
|
+
if (!pkSet) {
|
|
2996
|
+
pkSet = /* @__PURE__ */ new Set();
|
|
2357
2997
|
const existing = this.index.getSlotsByKey(key);
|
|
2358
|
-
for (
|
|
2359
|
-
|
|
2998
|
+
for (let i = 0; i < existing.length; i++) {
|
|
2999
|
+
pkSet.add(existing[i].pk);
|
|
3000
|
+
}
|
|
3001
|
+
this.pksByKey.set(key, pkSet);
|
|
2360
3002
|
}
|
|
2361
|
-
return
|
|
3003
|
+
return pkSet;
|
|
2362
3004
|
}
|
|
2363
3005
|
getEntitiesByKey(key) {
|
|
2364
3006
|
return super.getEntitiesByKey(key);
|
|
@@ -2366,8 +3008,16 @@ var OIMReactiveCollectionIndexManualSetBased = class extends OIMReactiveIndexMan
|
|
|
2366
3008
|
getEntitiesByKeys(keys) {
|
|
2367
3009
|
return super.getEntitiesByKeys(keys);
|
|
2368
3010
|
}
|
|
2369
|
-
|
|
2370
|
-
const
|
|
3011
|
+
getSlotsOrTransient(pks) {
|
|
3012
|
+
const slots = [];
|
|
3013
|
+
slots.length = pks.length;
|
|
3014
|
+
for (let i = 0; i < pks.length; i++) {
|
|
3015
|
+
slots[i] = this.getSlotOrTransient(pks[i]);
|
|
3016
|
+
}
|
|
3017
|
+
return slots;
|
|
3018
|
+
}
|
|
3019
|
+
getSlotOrTransient(pk) {
|
|
3020
|
+
const slot = this.getSlot(pk);
|
|
2371
3021
|
if (!slot) return { pk, item: void 0 };
|
|
2372
3022
|
return slot;
|
|
2373
3023
|
}
|
|
@@ -2680,20 +3330,20 @@ var OIMReactiveGlobalIndexManualArrayBased = class extends OIMReactiveGlobalInde
|
|
|
2680
3330
|
// src/core/OIMReactiveCollectionGlobalIndexManualArrayBased.ts
|
|
2681
3331
|
var OIMReactiveCollectionGlobalIndexManualArrayBased = class extends OIMReactiveGlobalIndexManualArrayBased {
|
|
2682
3332
|
constructor(queue, opts) {
|
|
2683
|
-
const
|
|
3333
|
+
const getSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.getSlot;
|
|
2684
3334
|
super(queue, { indexOptions: opts.indexOptions });
|
|
2685
3335
|
// Single pk membership set for O(1) `addPks` dedup. Lazily seeded from the
|
|
2686
3336
|
// bucket so it stays correct even after a raw `setSlots` (e.g. derived
|
|
2687
3337
|
// rebuild), matching the keyed index's `membershipOf`.
|
|
2688
3338
|
this.membership = /* @__PURE__ */ new Set();
|
|
2689
3339
|
this.membershipSeeded = false;
|
|
2690
|
-
this.
|
|
3340
|
+
this.getSlot = getSlot;
|
|
2691
3341
|
}
|
|
2692
3342
|
setPks(pks) {
|
|
2693
3343
|
this.membership.clear();
|
|
2694
3344
|
for (let i = 0; i < pks.length; i++) this.membership.add(pks[i]);
|
|
2695
3345
|
this.membershipSeeded = true;
|
|
2696
|
-
super.setSlots(this.
|
|
3346
|
+
super.setSlots(this.getSlotsOrTransient(pks));
|
|
2697
3347
|
}
|
|
2698
3348
|
addPks(pks) {
|
|
2699
3349
|
if (pks.length === 0) return;
|
|
@@ -2702,7 +3352,7 @@ var OIMReactiveCollectionGlobalIndexManualArrayBased = class extends OIMReactive
|
|
|
2702
3352
|
for (const pk of pks) {
|
|
2703
3353
|
if (membership.has(pk)) continue;
|
|
2704
3354
|
membership.add(pk);
|
|
2705
|
-
newSlots.push(this.
|
|
3355
|
+
newSlots.push(this.getSlotOrTransient(pk));
|
|
2706
3356
|
}
|
|
2707
3357
|
if (newSlots.length > 0) super.appendSlots(newSlots);
|
|
2708
3358
|
}
|
|
@@ -2739,16 +3389,16 @@ var OIMReactiveCollectionGlobalIndexManualArrayBased = class extends OIMReactive
|
|
|
2739
3389
|
getEntities() {
|
|
2740
3390
|
return super.getEntities();
|
|
2741
3391
|
}
|
|
2742
|
-
|
|
3392
|
+
getSlotsOrTransient(pks) {
|
|
2743
3393
|
const slots = [];
|
|
2744
3394
|
slots.length = pks.length;
|
|
2745
3395
|
for (let i = 0; i < pks.length; i++) {
|
|
2746
|
-
slots[i] = this.
|
|
3396
|
+
slots[i] = this.getSlotOrTransient(pks[i]);
|
|
2747
3397
|
}
|
|
2748
3398
|
return slots;
|
|
2749
3399
|
}
|
|
2750
|
-
|
|
2751
|
-
const slot = this.
|
|
3400
|
+
getSlotOrTransient(pk) {
|
|
3401
|
+
const slot = this.getSlot(pk);
|
|
2752
3402
|
if (!slot) return { pk, item: void 0 };
|
|
2753
3403
|
return slot;
|
|
2754
3404
|
}
|
|
@@ -2828,18 +3478,18 @@ var OIMReactiveGlobalIndexManualSetBased = class extends OIMReactiveGlobalIndexS
|
|
|
2828
3478
|
// src/core/OIMReactiveCollectionGlobalIndexManualSetBased.ts
|
|
2829
3479
|
var OIMReactiveCollectionGlobalIndexManualSetBased = class extends OIMReactiveGlobalIndexManualSetBased {
|
|
2830
3480
|
constructor(queue, opts) {
|
|
2831
|
-
const
|
|
3481
|
+
const getSlot = opts.collection !== void 0 ? (pk) => opts.collection.getOrReserveSlotByPk(pk) : opts.getSlot;
|
|
2832
3482
|
super(queue, { indexOptions: opts.indexOptions });
|
|
2833
3483
|
this.membership = /* @__PURE__ */ new Map();
|
|
2834
3484
|
this.membershipSeeded = false;
|
|
2835
|
-
this.
|
|
3485
|
+
this.getSlot = getSlot;
|
|
2836
3486
|
}
|
|
2837
3487
|
setPks(pks) {
|
|
2838
3488
|
this.membership.clear();
|
|
2839
3489
|
const slots = [];
|
|
2840
3490
|
for (let i = 0; i < pks.length; i++) {
|
|
2841
3491
|
const pk = pks[i];
|
|
2842
|
-
const slot = this.
|
|
3492
|
+
const slot = this.getSlotOrTransient(pk);
|
|
2843
3493
|
if (!this.membership.has(pk)) this.membership.set(pk, slot);
|
|
2844
3494
|
slots.push(slot);
|
|
2845
3495
|
}
|
|
@@ -2852,7 +3502,7 @@ var OIMReactiveCollectionGlobalIndexManualSetBased = class extends OIMReactiveGl
|
|
|
2852
3502
|
const newSlots = [];
|
|
2853
3503
|
for (const pk of pks) {
|
|
2854
3504
|
if (membership.has(pk)) continue;
|
|
2855
|
-
const slot = this.
|
|
3505
|
+
const slot = this.getSlotOrTransient(pk);
|
|
2856
3506
|
membership.set(pk, slot);
|
|
2857
3507
|
newSlots.push(slot);
|
|
2858
3508
|
}
|
|
@@ -2891,8 +3541,8 @@ var OIMReactiveCollectionGlobalIndexManualSetBased = class extends OIMReactiveGl
|
|
|
2891
3541
|
getEntities() {
|
|
2892
3542
|
return super.getEntities();
|
|
2893
3543
|
}
|
|
2894
|
-
|
|
2895
|
-
const slot = this.
|
|
3544
|
+
getSlotOrTransient(pk) {
|
|
3545
|
+
const slot = this.getSlot(pk);
|
|
2896
3546
|
if (!slot) return { pk, item: void 0 };
|
|
2897
3547
|
return slot;
|
|
2898
3548
|
}
|
|
@@ -3071,6 +3721,30 @@ var OIMCollectionIndexFactory = class {
|
|
|
3071
3721
|
indexOptions: opts.indexOptions
|
|
3072
3722
|
});
|
|
3073
3723
|
}
|
|
3724
|
+
/**
|
|
3725
|
+
* Composite (trie-backed) manual Set-based index keyed by an
|
|
3726
|
+
* arbitrary-length key path, e.g. `setPks([userId, projectId, role], pks)`.
|
|
3727
|
+
* Key paths are matched by content in O(arity) — no string concatenation,
|
|
3728
|
+
* no separator collisions, each segment keeps its type. Primitive-keyed
|
|
3729
|
+
* indexes are unaffected and keep their native-`Map` fast path.
|
|
3730
|
+
*/
|
|
3731
|
+
compositeSetIndex(opts = {}) {
|
|
3732
|
+
return new OIMReactiveCollectionIndexCompositeTrieSetBased(this.queue, {
|
|
3733
|
+
collection: this.collection,
|
|
3734
|
+
indexOptions: opts.indexOptions
|
|
3735
|
+
});
|
|
3736
|
+
}
|
|
3737
|
+
/**
|
|
3738
|
+
* Composite (trie-backed) manual Array-based (ordered) index keyed by an
|
|
3739
|
+
* arbitrary-length key path, e.g. `setPks([channelId, threadId], pks)`.
|
|
3740
|
+
* Ordered counterpart of `compositeSetIndex`.
|
|
3741
|
+
*/
|
|
3742
|
+
compositeArrayIndex(opts = {}) {
|
|
3743
|
+
return new OIMReactiveCollectionIndexCompositeTrieArrayBased(this.queue, {
|
|
3744
|
+
collection: this.collection,
|
|
3745
|
+
indexOptions: opts.indexOptions
|
|
3746
|
+
});
|
|
3747
|
+
}
|
|
3074
3748
|
derivedSetIndex(selectIndexKeys, opts = {}) {
|
|
3075
3749
|
return new OIMDerivedCollectionIndexSetBased(
|
|
3076
3750
|
this.queue,
|
|
@@ -3277,7 +3951,7 @@ var OIMObject = class {
|
|
|
3277
3951
|
var OIMReactiveObject = class extends OIMObject {
|
|
3278
3952
|
constructor(queue, opts) {
|
|
3279
3953
|
super(opts);
|
|
3280
|
-
this.updateEmitter = new OIMCarrierKeyedEmitter(queue, new
|
|
3954
|
+
this.updateEmitter = new OIMCarrierKeyedEmitter(queue, new OIMKeyedCarrierProvider());
|
|
3281
3955
|
}
|
|
3282
3956
|
/**
|
|
3283
3957
|
* Mark the written key(s) on the keyed emitter directly — no general-event
|
|
@@ -3319,6 +3993,148 @@ var OIMReactiveObject = class extends OIMObject {
|
|
|
3319
3993
|
}
|
|
3320
3994
|
};
|
|
3321
3995
|
|
|
3996
|
+
// src/core/OIMCollectionStoreTrieDriven.ts
|
|
3997
|
+
var OIMCollectionStoreTrieDriven = class extends OIMCollectionStore {
|
|
3998
|
+
constructor() {
|
|
3999
|
+
super(...arguments);
|
|
4000
|
+
this.slots = new OIMTrieMap();
|
|
4001
|
+
this.reservedSlots = new OIMTrieMap();
|
|
4002
|
+
}
|
|
4003
|
+
setOneByPk(pk, entity) {
|
|
4004
|
+
const slot = this.slots.get(pk);
|
|
4005
|
+
if (slot) {
|
|
4006
|
+
slot.item = entity;
|
|
4007
|
+
return slot;
|
|
4008
|
+
}
|
|
4009
|
+
const reserved = this.reservedSlots.get(pk);
|
|
4010
|
+
if (reserved) {
|
|
4011
|
+
reserved.item = entity;
|
|
4012
|
+
this.reservedSlots.delete(pk);
|
|
4013
|
+
this.slots.set(pk, reserved);
|
|
4014
|
+
return reserved;
|
|
4015
|
+
}
|
|
4016
|
+
const nextSlot = {
|
|
4017
|
+
pk,
|
|
4018
|
+
item: entity
|
|
4019
|
+
};
|
|
4020
|
+
this.slots.set(pk, nextSlot);
|
|
4021
|
+
return nextSlot;
|
|
4022
|
+
}
|
|
4023
|
+
getOrReserveSlotByPk(pk) {
|
|
4024
|
+
const slot = this.slots.get(pk);
|
|
4025
|
+
if (slot) return slot;
|
|
4026
|
+
let reserved = this.reservedSlots.get(pk);
|
|
4027
|
+
if (!reserved) {
|
|
4028
|
+
reserved = { pk, item: void 0 };
|
|
4029
|
+
this.reservedSlots.set(pk, reserved);
|
|
4030
|
+
}
|
|
4031
|
+
return reserved;
|
|
4032
|
+
}
|
|
4033
|
+
setManyByPks(pks, entities) {
|
|
4034
|
+
const slots = [];
|
|
4035
|
+
slots.length = pks.length;
|
|
4036
|
+
for (let i = 0; i < pks.length; i++) {
|
|
4037
|
+
slots[i] = this.setOneByPk(pks[i], entities[i]);
|
|
4038
|
+
}
|
|
4039
|
+
return slots;
|
|
4040
|
+
}
|
|
4041
|
+
getSlotByPk(pk) {
|
|
4042
|
+
return this.slots.get(pk);
|
|
4043
|
+
}
|
|
4044
|
+
findSlotByPk(pk) {
|
|
4045
|
+
return this.slots.get(pk) ?? this.reservedSlots.get(pk);
|
|
4046
|
+
}
|
|
4047
|
+
hasSubscribers(slot) {
|
|
4048
|
+
return slot.subscribers !== void 0 && slot.subscribers.size > 0;
|
|
4049
|
+
}
|
|
4050
|
+
getSlotsByPks(pks) {
|
|
4051
|
+
const result = [];
|
|
4052
|
+
result.length = pks.length;
|
|
4053
|
+
let writeIndex = 0;
|
|
4054
|
+
for (let i = 0; i < pks.length; i++) {
|
|
4055
|
+
const slot = this.slots.get(pks[i]);
|
|
4056
|
+
if (slot !== void 0) result[writeIndex++] = slot;
|
|
4057
|
+
}
|
|
4058
|
+
result.length = writeIndex;
|
|
4059
|
+
return result;
|
|
4060
|
+
}
|
|
4061
|
+
getAllSlots() {
|
|
4062
|
+
return Array.from(this.slots.values());
|
|
4063
|
+
}
|
|
4064
|
+
removeOneByPk(pk) {
|
|
4065
|
+
const slot = this.slots.get(pk);
|
|
4066
|
+
if (slot) {
|
|
4067
|
+
slot.item = void 0;
|
|
4068
|
+
this.slots.delete(pk);
|
|
4069
|
+
if (this.hasSubscribers(slot)) {
|
|
4070
|
+
this.reservedSlots.set(pk, slot);
|
|
4071
|
+
}
|
|
4072
|
+
return;
|
|
4073
|
+
}
|
|
4074
|
+
const reserved = this.reservedSlots.get(pk);
|
|
4075
|
+
if (reserved) {
|
|
4076
|
+
reserved.item = void 0;
|
|
4077
|
+
if (!this.hasSubscribers(reserved)) {
|
|
4078
|
+
this.reservedSlots.delete(pk);
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
removeManyByPks(pks) {
|
|
4083
|
+
for (const pk of pks) this.removeOneByPk(pk);
|
|
4084
|
+
}
|
|
4085
|
+
getOneByPk(pk) {
|
|
4086
|
+
return this.slots.get(pk)?.item;
|
|
4087
|
+
}
|
|
4088
|
+
getManyByPks(pks) {
|
|
4089
|
+
const result = [];
|
|
4090
|
+
result.length = pks.length;
|
|
4091
|
+
let writeIndex = 0;
|
|
4092
|
+
for (let i = 0; i < pks.length; i++) {
|
|
4093
|
+
const entity = this.getOneByPk(pks[i]);
|
|
4094
|
+
if (entity !== void 0) result[writeIndex++] = entity;
|
|
4095
|
+
}
|
|
4096
|
+
result.length = writeIndex;
|
|
4097
|
+
return result;
|
|
4098
|
+
}
|
|
4099
|
+
getAll() {
|
|
4100
|
+
const result = [];
|
|
4101
|
+
for (const slot of this.slots.values()) {
|
|
4102
|
+
if (slot.item !== void 0) result.push(slot.item);
|
|
4103
|
+
}
|
|
4104
|
+
return result;
|
|
4105
|
+
}
|
|
4106
|
+
countAll() {
|
|
4107
|
+
return this.slots.size;
|
|
4108
|
+
}
|
|
4109
|
+
clear() {
|
|
4110
|
+
const retained = [];
|
|
4111
|
+
for (const slot of this.slots.values()) {
|
|
4112
|
+
slot.item = void 0;
|
|
4113
|
+
if (this.hasSubscribers(slot)) retained.push(slot);
|
|
4114
|
+
}
|
|
4115
|
+
this.slots.clear();
|
|
4116
|
+
for (const slot of this.reservedSlots.values()) {
|
|
4117
|
+
slot.item = void 0;
|
|
4118
|
+
if (this.hasSubscribers(slot)) retained.push(slot);
|
|
4119
|
+
}
|
|
4120
|
+
this.reservedSlots.clear();
|
|
4121
|
+
for (const slot of retained) {
|
|
4122
|
+
this.reservedSlots.set(slot.pk, slot);
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
getAllPks() {
|
|
4126
|
+
return Array.from(this.slots.keys());
|
|
4127
|
+
}
|
|
4128
|
+
destroy() {
|
|
4129
|
+
this.clear();
|
|
4130
|
+
for (const slot of this.reservedSlots.values()) {
|
|
4131
|
+
slot.subscribers?.clear();
|
|
4132
|
+
slot.subscribers = void 0;
|
|
4133
|
+
}
|
|
4134
|
+
this.reservedSlots.clear();
|
|
4135
|
+
}
|
|
4136
|
+
};
|
|
4137
|
+
|
|
3322
4138
|
// src/core/OIMObjectStoreMapDriven.ts
|
|
3323
4139
|
var OIMObjectStoreMapDriven = class extends OIMObjectStore {
|
|
3324
4140
|
constructor() {
|
|
@@ -3366,6 +4182,27 @@ var OIMObjectStoreMapDriven = class extends OIMObjectStore {
|
|
|
3366
4182
|
}
|
|
3367
4183
|
};
|
|
3368
4184
|
|
|
4185
|
+
// src/core/OIMKeyPathCarrierProvider.ts
|
|
4186
|
+
var OIMKeyPathCarrierProvider = class {
|
|
4187
|
+
constructor() {
|
|
4188
|
+
this.carriers = new OIMTrieMap();
|
|
4189
|
+
}
|
|
4190
|
+
getOrReserveCarrier(key) {
|
|
4191
|
+
let carrier = this.carriers.get(key);
|
|
4192
|
+
if (!carrier) {
|
|
4193
|
+
carrier = { key };
|
|
4194
|
+
this.carriers.set(key, carrier);
|
|
4195
|
+
}
|
|
4196
|
+
return carrier;
|
|
4197
|
+
}
|
|
4198
|
+
findCarrier(key) {
|
|
4199
|
+
return this.carriers.get(key);
|
|
4200
|
+
}
|
|
4201
|
+
onCarrierEmptied(carrier) {
|
|
4202
|
+
this.carriers.delete(carrier.key);
|
|
4203
|
+
}
|
|
4204
|
+
};
|
|
4205
|
+
|
|
3369
4206
|
// src/core/OIMComparatorFactory.ts
|
|
3370
4207
|
var OIMComparatorFactory = class {
|
|
3371
4208
|
createShallowComparator() {
|
|
@@ -3584,6 +4421,103 @@ var OIMMap2Keys = class {
|
|
|
3584
4421
|
}
|
|
3585
4422
|
};
|
|
3586
4423
|
|
|
4424
|
+
// src/core/OIMDisposeScope.ts
|
|
4425
|
+
var OIMDisposeScope = class _OIMDisposeScope {
|
|
4426
|
+
constructor() {
|
|
4427
|
+
this.disposables = [];
|
|
4428
|
+
this.disposed = false;
|
|
4429
|
+
}
|
|
4430
|
+
/** Number of not-yet-disposed items currently held. */
|
|
4431
|
+
get size() {
|
|
4432
|
+
return this.disposables.length;
|
|
4433
|
+
}
|
|
4434
|
+
get isDisposed() {
|
|
4435
|
+
return this.disposed;
|
|
4436
|
+
}
|
|
4437
|
+
/**
|
|
4438
|
+
* Register a disposable (object with `destroy()` or an unsubscribe function)
|
|
4439
|
+
* and return it unchanged, so it can be captured inline. If the scope is
|
|
4440
|
+
* already disposed the item is disposed immediately, so nothing leaks.
|
|
4441
|
+
*/
|
|
4442
|
+
add(disposable) {
|
|
4443
|
+
if (this.disposed) {
|
|
4444
|
+
this.disposeOne(disposable);
|
|
4445
|
+
return disposable;
|
|
4446
|
+
}
|
|
4447
|
+
this.disposables.push(disposable);
|
|
4448
|
+
return disposable;
|
|
4449
|
+
}
|
|
4450
|
+
/** A nested scope, itself registered here — dispose it early or with the parent. */
|
|
4451
|
+
child() {
|
|
4452
|
+
return this.add(new _OIMDisposeScope());
|
|
4453
|
+
}
|
|
4454
|
+
/**
|
|
4455
|
+
* Dispose everything in reverse registration order, then clear. Idempotent.
|
|
4456
|
+
* If any `destroy()`/unsubscribe throws, the rest are still disposed and the
|
|
4457
|
+
* first error is rethrown once teardown completes.
|
|
4458
|
+
*/
|
|
4459
|
+
destroy() {
|
|
4460
|
+
if (this.disposed) return;
|
|
4461
|
+
this.disposed = true;
|
|
4462
|
+
let firstError;
|
|
4463
|
+
let hasError = false;
|
|
4464
|
+
for (let i = this.disposables.length - 1; i >= 0; i--) {
|
|
4465
|
+
try {
|
|
4466
|
+
this.disposeOne(this.disposables[i]);
|
|
4467
|
+
} catch (error) {
|
|
4468
|
+
if (!hasError) {
|
|
4469
|
+
hasError = true;
|
|
4470
|
+
firstError = error;
|
|
4471
|
+
}
|
|
4472
|
+
}
|
|
4473
|
+
}
|
|
4474
|
+
this.disposables.length = 0;
|
|
4475
|
+
if (hasError) throw firstError;
|
|
4476
|
+
}
|
|
4477
|
+
disposeOne(disposable) {
|
|
4478
|
+
if (typeof disposable === "function") disposable();
|
|
4479
|
+
else disposable.destroy();
|
|
4480
|
+
}
|
|
4481
|
+
};
|
|
4482
|
+
function createOIMDisposeScope() {
|
|
4483
|
+
return new OIMDisposeScope();
|
|
4484
|
+
}
|
|
4485
|
+
|
|
4486
|
+
// src/core/OIMTrieSet.ts
|
|
4487
|
+
var OIMTrieSet = class {
|
|
4488
|
+
constructor() {
|
|
4489
|
+
this.map = new OIMTrieMap();
|
|
4490
|
+
}
|
|
4491
|
+
get size() {
|
|
4492
|
+
return this.map.size;
|
|
4493
|
+
}
|
|
4494
|
+
add(key) {
|
|
4495
|
+
this.map.set(key, true);
|
|
4496
|
+
}
|
|
4497
|
+
has(key) {
|
|
4498
|
+
return this.map.has(key);
|
|
4499
|
+
}
|
|
4500
|
+
delete(key) {
|
|
4501
|
+
return this.map.delete(key);
|
|
4502
|
+
}
|
|
4503
|
+
*values() {
|
|
4504
|
+
yield* this.map.keys();
|
|
4505
|
+
}
|
|
4506
|
+
clear() {
|
|
4507
|
+
this.map.clear();
|
|
4508
|
+
}
|
|
4509
|
+
};
|
|
4510
|
+
|
|
4511
|
+
// src/core/OIMPkCodecKeyPath.ts
|
|
4512
|
+
var OIMPkCodecKeyPath = class {
|
|
4513
|
+
encode(pk) {
|
|
4514
|
+
return JSON.stringify(pk);
|
|
4515
|
+
}
|
|
4516
|
+
decode(encoded) {
|
|
4517
|
+
return JSON.parse(encoded);
|
|
4518
|
+
}
|
|
4519
|
+
};
|
|
4520
|
+
|
|
3587
4521
|
// src/modules/compute/core/OIMComputeRuntime.ts
|
|
3588
4522
|
var OIMComputeRuntime = class {
|
|
3589
4523
|
constructor(queue) {
|
|
@@ -4187,6 +5121,27 @@ var OIMCollectionSelectors = class {
|
|
|
4187
5121
|
key
|
|
4188
5122
|
);
|
|
4189
5123
|
}
|
|
5124
|
+
/**
|
|
5125
|
+
* Entities of a composite (key-path) set-based index for one key path, e.g.
|
|
5126
|
+
* `entitiesByCompositeSetIndexKey(index, [projectId, role])`.
|
|
5127
|
+
*/
|
|
5128
|
+
entitiesByCompositeSetIndexKey(index, key) {
|
|
5129
|
+
return new OIMEntitiesByIndexKeySetBasedSelector(
|
|
5130
|
+
this.runtime,
|
|
5131
|
+
this.collection,
|
|
5132
|
+
index,
|
|
5133
|
+
key
|
|
5134
|
+
);
|
|
5135
|
+
}
|
|
5136
|
+
/** Entities of a composite (key-path) array-based index for one key path. */
|
|
5137
|
+
entitiesByCompositeArrayIndexKey(index, key) {
|
|
5138
|
+
return new OIMEntitiesByIndexKeyArrayBasedSelector(
|
|
5139
|
+
this.runtime,
|
|
5140
|
+
this.collection,
|
|
5141
|
+
index,
|
|
5142
|
+
key
|
|
5143
|
+
);
|
|
5144
|
+
}
|
|
4190
5145
|
/** Entities of a keyless (whole-collection) array-based index, ordered. */
|
|
4191
5146
|
entitiesByArrayGlobalIndex(index) {
|
|
4192
5147
|
return new OIMEntitiesByGlobalIndexArrayBasedSelector(
|
|
@@ -4210,7 +5165,16 @@ function createOIMCollectionKit(queue, opts) {
|
|
|
4210
5165
|
const collection = new OIMReactiveCollection(queue, opts);
|
|
4211
5166
|
const indexFactory = new OIMCollectionIndexFactory(queue, collection);
|
|
4212
5167
|
const select = new OIMCollectionSelectors(queue, collection);
|
|
4213
|
-
|
|
5168
|
+
const scope = new OIMDisposeScope();
|
|
5169
|
+
scope.add(collection);
|
|
5170
|
+
return {
|
|
5171
|
+
queue,
|
|
5172
|
+
collection,
|
|
5173
|
+
indexFactory,
|
|
5174
|
+
select,
|
|
5175
|
+
scope,
|
|
5176
|
+
destroy: () => scope.destroy()
|
|
5177
|
+
};
|
|
4214
5178
|
}
|
|
4215
5179
|
|
|
4216
5180
|
// src/modules/wrapper/collection/OIMCollectionChangedFields.ts
|
|
@@ -5191,35 +6155,20 @@ var OIMComputed = class {
|
|
|
5191
6155
|
};
|
|
5192
6156
|
|
|
5193
6157
|
// src/modules/effect/core/OIMEffectDependencyKeyed.ts
|
|
5194
|
-
function isReadonlyArray(value) {
|
|
5195
|
-
return Array.isArray(value);
|
|
5196
|
-
}
|
|
5197
6158
|
var OIMEffectDependencyKeyed = class {
|
|
5198
|
-
constructor(source,
|
|
6159
|
+
constructor(source, key) {
|
|
5199
6160
|
this.source = source;
|
|
5200
|
-
|
|
5201
|
-
this.keys = keyOrKeys;
|
|
5202
|
-
} else {
|
|
5203
|
-
this.key = keyOrKeys;
|
|
5204
|
-
}
|
|
6161
|
+
this.key = key;
|
|
5205
6162
|
}
|
|
5206
6163
|
subscribe(onUpdate) {
|
|
5207
|
-
if (this.keys !== void 0) {
|
|
5208
|
-
return this.source.subscribeOnKeys(this.keys, onUpdate);
|
|
5209
|
-
}
|
|
5210
|
-
if (this.key === void 0) return () => {
|
|
5211
|
-
};
|
|
5212
6164
|
return this.source.subscribeOnKey(this.key, onUpdate);
|
|
5213
6165
|
}
|
|
5214
6166
|
};
|
|
5215
6167
|
|
|
5216
6168
|
// src/modules/effect/core/OIMEffectDependencyKeyedObject.ts
|
|
5217
6169
|
var OIMEffectDependencyKeyedObject = class {
|
|
5218
|
-
constructor(object,
|
|
5219
|
-
this.dep = new OIMEffectDependencyKeyed(
|
|
5220
|
-
object,
|
|
5221
|
-
keyOrKeys
|
|
5222
|
-
);
|
|
6170
|
+
constructor(object, key) {
|
|
6171
|
+
this.dep = new OIMEffectDependencyKeyed(object, key);
|
|
5223
6172
|
}
|
|
5224
6173
|
get source() {
|
|
5225
6174
|
return this.dep.source;
|
|
@@ -5231,11 +6180,8 @@ var OIMEffectDependencyKeyedObject = class {
|
|
|
5231
6180
|
|
|
5232
6181
|
// src/modules/effect/core/OIMEffectDependencyKeyedCollection.ts
|
|
5233
6182
|
var OIMEffectDependencyKeyedCollection = class {
|
|
5234
|
-
constructor(collection,
|
|
5235
|
-
this.dep = new OIMEffectDependencyKeyed(
|
|
5236
|
-
collection,
|
|
5237
|
-
pkOrPks
|
|
5238
|
-
);
|
|
6183
|
+
constructor(collection, pk) {
|
|
6184
|
+
this.dep = new OIMEffectDependencyKeyed(collection, pk);
|
|
5239
6185
|
}
|
|
5240
6186
|
get source() {
|
|
5241
6187
|
return this.dep.source;
|
|
@@ -5247,11 +6193,8 @@ var OIMEffectDependencyKeyedCollection = class {
|
|
|
5247
6193
|
|
|
5248
6194
|
// src/modules/effect/core/OIMEffectDependencyKeyedIndex.ts
|
|
5249
6195
|
var OIMEffectDependencyKeyedIndex = class {
|
|
5250
|
-
constructor(index,
|
|
5251
|
-
this.dep = new OIMEffectDependencyKeyed(
|
|
5252
|
-
index,
|
|
5253
|
-
keyOrKeys
|
|
5254
|
-
);
|
|
6196
|
+
constructor(index, key) {
|
|
6197
|
+
this.dep = new OIMEffectDependencyKeyed(index, key);
|
|
5255
6198
|
}
|
|
5256
6199
|
get source() {
|
|
5257
6200
|
return this.dep.source;
|
|
@@ -5398,6 +6341,7 @@ export {
|
|
|
5398
6341
|
EOIMEventQueueSchedulerEventType,
|
|
5399
6342
|
EOIMIndexEventType,
|
|
5400
6343
|
EOIMObjectEventType,
|
|
6344
|
+
OIMBucketCarrierProvider,
|
|
5401
6345
|
OIMCarrierKeyedEmitter,
|
|
5402
6346
|
OIMCarrierSingleEmitter,
|
|
5403
6347
|
OIMCollection,
|
|
@@ -5410,6 +6354,7 @@ export {
|
|
|
5410
6354
|
OIMCollectionSelectors,
|
|
5411
6355
|
OIMCollectionStore,
|
|
5412
6356
|
OIMCollectionStoreMapDriven,
|
|
6357
|
+
OIMCollectionStoreTrieDriven,
|
|
5413
6358
|
OIMComparatorFactory,
|
|
5414
6359
|
OIMComputeRuntime,
|
|
5415
6360
|
OIMComputed,
|
|
@@ -5418,6 +6363,7 @@ export {
|
|
|
5418
6363
|
OIMDerivedCollectionGlobalIndexSetBased,
|
|
5419
6364
|
OIMDerivedCollectionIndexArrayBased,
|
|
5420
6365
|
OIMDerivedCollectionIndexSetBased,
|
|
6366
|
+
OIMDisposeScope,
|
|
5421
6367
|
OIMEffect,
|
|
5422
6368
|
OIMEffectDependencyComputed,
|
|
5423
6369
|
OIMEffectDependencyKeyed,
|
|
@@ -5460,6 +6406,11 @@ export {
|
|
|
5460
6406
|
OIMIndexStoreMapDrivenArrayBased,
|
|
5461
6407
|
OIMIndexStoreMapDrivenSetBased,
|
|
5462
6408
|
OIMIndexStoreSetBased,
|
|
6409
|
+
OIMIndexStoreTrieDrivenArrayBased,
|
|
6410
|
+
OIMIndexStoreTrieDrivenSetBased,
|
|
6411
|
+
OIMKeyPathCarrierProvider,
|
|
6412
|
+
OIMKeyedBucketArrayBased,
|
|
6413
|
+
OIMKeyedBucketSetBased,
|
|
5463
6414
|
OIMMap2Keys,
|
|
5464
6415
|
OIMObject,
|
|
5465
6416
|
OIMObjectStore,
|
|
@@ -5471,10 +6422,13 @@ export {
|
|
|
5471
6422
|
OIMOrderedListCommandStream,
|
|
5472
6423
|
OIMOrderedListCommandStreamDiffDriven,
|
|
5473
6424
|
OIMOrderedListMappedCommandStream,
|
|
6425
|
+
OIMPkCodecKeyPath,
|
|
5474
6426
|
OIMPkSelectorFactory,
|
|
5475
6427
|
OIMReactiveCollection,
|
|
5476
6428
|
OIMReactiveCollectionGlobalIndexManualArrayBased,
|
|
5477
6429
|
OIMReactiveCollectionGlobalIndexManualSetBased,
|
|
6430
|
+
OIMReactiveCollectionIndexCompositeTrieArrayBased,
|
|
6431
|
+
OIMReactiveCollectionIndexCompositeTrieSetBased,
|
|
5478
6432
|
OIMReactiveCollectionIndexManualArrayBased,
|
|
5479
6433
|
OIMReactiveCollectionIndexManualSetBased,
|
|
5480
6434
|
OIMReactiveGlobalIndex,
|
|
@@ -5489,10 +6443,13 @@ export {
|
|
|
5489
6443
|
OIMReactiveIndexSetBased,
|
|
5490
6444
|
OIMReactiveObject,
|
|
5491
6445
|
OIMSelector,
|
|
6446
|
+
OIMTrieMap,
|
|
6447
|
+
OIMTrieSet,
|
|
5492
6448
|
createInPlaceEntityUpdater,
|
|
5493
6449
|
createMergeEntityUpdater,
|
|
5494
6450
|
createOIMCollectionIndexFactory,
|
|
5495
6451
|
createOIMCollectionKit,
|
|
6452
|
+
createOIMDisposeScope,
|
|
5496
6453
|
createOIMGlobalIndexSlotMap,
|
|
5497
6454
|
createOIMIndexSlotMap,
|
|
5498
6455
|
createOIMOrderedListCommandStreamDiffDriven,
|