@oimdb/core 3.10.0 → 3.11.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 +18 -1
- package/dist/index.cjs +730 -451
- package/dist/index.d.cts +308 -120
- package/dist/index.d.ts +308 -120
- package/dist/index.js +724 -450
- package/llms.txt +77 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -225,6 +225,25 @@ var OIMEventQueueScheduler = class {
|
|
|
225
225
|
flush() {
|
|
226
226
|
this.emitter.emit(0 /* FLUSH */, void 0);
|
|
227
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Detach a Node timer handle from the event loop, returning it unchanged.
|
|
230
|
+
*
|
|
231
|
+
* A pending flush must never be a reason for a process to stay alive: if
|
|
232
|
+
* nothing else is running there is no UI left to update, and the flush is
|
|
233
|
+
* moot. Without this a scheduled-but-not-yet-run flush keeps Node awake —
|
|
234
|
+
* which is why a test suite that leaves a queue scheduled reports
|
|
235
|
+
* "a worker process has failed to exit gracefully".
|
|
236
|
+
*
|
|
237
|
+
* In the browser `setTimeout` returns a number, which has no `unref`, so the
|
|
238
|
+
* call is guarded and the handle passes straight through.
|
|
239
|
+
*/
|
|
240
|
+
unref(handle) {
|
|
241
|
+
const maybeUnrefable = handle;
|
|
242
|
+
if (typeof maybeUnrefable?.unref === "function") {
|
|
243
|
+
maybeUnrefable.unref();
|
|
244
|
+
}
|
|
245
|
+
return handle;
|
|
246
|
+
}
|
|
228
247
|
};
|
|
229
248
|
|
|
230
249
|
// src/core/OIMKeyedBucketSetBased.ts
|
|
@@ -559,19 +578,28 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
559
578
|
// doubles as membership: a carrier is in this array iff `carrier.dirty`.
|
|
560
579
|
this.dirtyCarriers = [];
|
|
561
580
|
this.isFlushEnqueued = false;
|
|
581
|
+
// Number of live subscriptions whose single handler spans 2+ distinct
|
|
582
|
+
// carriers (a `subscribeOnKeys` over distinct keys). While this is > 0 a
|
|
583
|
+
// flush coalesces delivery so such a handler fires at most ONCE per flush,
|
|
584
|
+
// not once per changed carrier — the callback carries no key, so extra
|
|
585
|
+
// fires are pure waste. At 0 the hot single-subscriber path pays nothing:
|
|
586
|
+
// no per-flush Set, no membership checks.
|
|
587
|
+
this.multiCarrierSubscriptions = 0;
|
|
562
588
|
this.onFlush = () => {
|
|
563
589
|
this.isFlushEnqueued = false;
|
|
564
590
|
if (this.dirtyCarriers.length === 0) return;
|
|
565
591
|
const flushing = this.dirtyCarriers;
|
|
566
592
|
this.dirtyCarriers = [];
|
|
593
|
+
const delivered = this.multiCarrierSubscriptions > 0 ? this.deliveredPool ?? (this.deliveredPool = /* @__PURE__ */ new Set()) : void 0;
|
|
567
594
|
let i = 0;
|
|
568
595
|
try {
|
|
569
596
|
for (; i < flushing.length; i++) {
|
|
570
597
|
flushing[i].dirty = false;
|
|
571
|
-
this.notify(flushing[i]);
|
|
598
|
+
this.notify(flushing[i], delivered);
|
|
572
599
|
}
|
|
573
600
|
} finally {
|
|
574
601
|
for (; i < flushing.length; i++) flushing[i].dirty = false;
|
|
602
|
+
delivered?.clear();
|
|
575
603
|
}
|
|
576
604
|
};
|
|
577
605
|
this.queue = queue;
|
|
@@ -589,7 +617,13 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
589
617
|
this.addHandler(carrier, handler);
|
|
590
618
|
carriers.push(carrier);
|
|
591
619
|
}
|
|
620
|
+
const spansMultipleCarriers = carriers.length > 1;
|
|
621
|
+
if (spansMultipleCarriers) this.multiCarrierSubscriptions++;
|
|
622
|
+
let unsubscribed = false;
|
|
592
623
|
return () => {
|
|
624
|
+
if (unsubscribed) return;
|
|
625
|
+
unsubscribed = true;
|
|
626
|
+
if (spansMultipleCarriers) this.multiCarrierSubscriptions--;
|
|
593
627
|
for (let i = 0; i < carriers.length; i++) {
|
|
594
628
|
this.removeHandler(carriers[i], handler);
|
|
595
629
|
}
|
|
@@ -705,19 +739,31 @@ var OIMCarrierKeyedEmitter = class {
|
|
|
705
739
|
this.isFlushEnqueued = true;
|
|
706
740
|
this.queue.enqueue(this.onFlush);
|
|
707
741
|
}
|
|
708
|
-
notify(carrier) {
|
|
742
|
+
notify(carrier, delivered) {
|
|
709
743
|
const subscribers = carrier.subscribers;
|
|
710
744
|
if (!subscribers || subscribers.size === 0) return;
|
|
711
745
|
if (subscribers.size === 1) {
|
|
712
746
|
const only = subscribers.values().next().value;
|
|
713
|
-
if (only)
|
|
747
|
+
if (!only) return;
|
|
748
|
+
if (delivered) {
|
|
749
|
+
const size = delivered.size;
|
|
750
|
+
delivered.add(only);
|
|
751
|
+
if (delivered.size === size) return;
|
|
752
|
+
}
|
|
753
|
+
only();
|
|
714
754
|
return;
|
|
715
755
|
}
|
|
716
756
|
const snapshot = [];
|
|
717
757
|
subscribers.forEach((h) => snapshot.push(h));
|
|
718
758
|
for (let i = 0; i < snapshot.length; i++) {
|
|
719
759
|
const handler = snapshot[i];
|
|
720
|
-
if (subscribers.has(handler))
|
|
760
|
+
if (!subscribers.has(handler)) continue;
|
|
761
|
+
if (delivered) {
|
|
762
|
+
const size = delivered.size;
|
|
763
|
+
delivered.add(handler);
|
|
764
|
+
if (delivered.size === size) continue;
|
|
765
|
+
}
|
|
766
|
+
handler();
|
|
721
767
|
}
|
|
722
768
|
}
|
|
723
769
|
};
|
|
@@ -1339,8 +1385,11 @@ var OIMCollection = class {
|
|
|
1339
1385
|
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1340
1386
|
}
|
|
1341
1387
|
clear() {
|
|
1388
|
+
const pks = this.store.getAllPks();
|
|
1342
1389
|
this.store.clear();
|
|
1343
|
-
|
|
1390
|
+
if (pks.length > 0) {
|
|
1391
|
+
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1392
|
+
}
|
|
1344
1393
|
}
|
|
1345
1394
|
countAll() {
|
|
1346
1395
|
return this.store.countAll();
|
|
@@ -1382,14 +1431,12 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1382
1431
|
// Only ever holds `slot.pk` (one canonical reference per logical key), so a
|
|
1383
1432
|
// native `Set` dedups correctly by reference even for composite pks.
|
|
1384
1433
|
this.pendingAnyUpdatePks = /* @__PURE__ */ new Set();
|
|
1385
|
-
this.isAnyUpdateClearPending = false;
|
|
1386
1434
|
this.isAnyUpdateScheduled = false;
|
|
1387
1435
|
this.runAnyUpdate = () => {
|
|
1388
1436
|
if (!this.isAnyUpdateScheduled) return;
|
|
1389
1437
|
this.isAnyUpdateScheduled = false;
|
|
1390
|
-
const pks =
|
|
1438
|
+
const pks = Array.from(this.pendingAnyUpdatePks.values());
|
|
1391
1439
|
this.pendingAnyUpdatePks.clear();
|
|
1392
|
-
this.isAnyUpdateClearPending = false;
|
|
1393
1440
|
const snapshot = Array.from(this.anyUpdateHandlers);
|
|
1394
1441
|
for (let i = 0; i < snapshot.length; i++) snapshot[i](pks);
|
|
1395
1442
|
};
|
|
@@ -1429,30 +1476,43 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1429
1476
|
this.anyUpdateHandlers.delete(handler);
|
|
1430
1477
|
};
|
|
1431
1478
|
}
|
|
1432
|
-
//
|
|
1433
|
-
//
|
|
1434
|
-
//
|
|
1435
|
-
//
|
|
1436
|
-
|
|
1479
|
+
// Two notification channels coexist on a reactive collection; they serve
|
|
1480
|
+
// different audiences and NEITHER is obsolete:
|
|
1481
|
+
// • the keyed `updateEmitter` — per-key/per-carrier pings ("did MY key
|
|
1482
|
+
// change?", payload-less `void`), for leaf subscribers like React hooks
|
|
1483
|
+
// that declare the keys they care about up front;
|
|
1484
|
+
// • this `emitter` UPDATE event — the aggregate/batch channel that carries
|
|
1485
|
+
// the full list of changed pks in one SYNCHRONOUS callback, for
|
|
1486
|
+
// consumers that do NOT know their keys ahead of time and must re-derive
|
|
1487
|
+
// over the batch: derived indexes/collections, changed-fields, persist,
|
|
1488
|
+
// snapshot-manager. `pks` always enumerates exactly what changed — even
|
|
1489
|
+
// clear() lists every removed key, so an empty array never occurs.
|
|
1490
|
+
// It is not a per-key emitter with fewer features — it is the opposite
|
|
1491
|
+
// shape (enumerated batch, not "my key"), which is why it stays.
|
|
1492
|
+
//
|
|
1493
|
+
// Emit on the batch channel only when something is actually subscribed —
|
|
1494
|
+
// otherwise every upsert/remove allocates a throwaway `{ pks }` object (and
|
|
1495
|
+
// array) that nobody reads.
|
|
1496
|
+
notifyBatch(pk) {
|
|
1437
1497
|
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1438
1498
|
this.emitter.emit(0 /* UPDATE */, { pks: [pk] });
|
|
1439
1499
|
}
|
|
1440
1500
|
}
|
|
1441
|
-
|
|
1501
|
+
notifyBatchMany(pks) {
|
|
1442
1502
|
if (this.emitter.hasHandlers(0 /* UPDATE */)) {
|
|
1443
1503
|
this.emitter.emit(0 /* UPDATE */, { pks });
|
|
1444
1504
|
}
|
|
1445
1505
|
}
|
|
1446
1506
|
upsertOneByPk(pk, entity) {
|
|
1447
1507
|
const slot = this.upsertOneWithoutNotificationsByPk(pk, entity);
|
|
1448
|
-
this.
|
|
1508
|
+
this.notifyBatch(pk);
|
|
1449
1509
|
this.updateEmitter.markUpdatedCarrier(slot);
|
|
1450
1510
|
this.trackAnyUpdatePk(pk);
|
|
1451
1511
|
return slot;
|
|
1452
1512
|
}
|
|
1453
1513
|
upsertOne(entity) {
|
|
1454
1514
|
const slot = this.upsertOneWithoutNotifications(entity);
|
|
1455
|
-
this.
|
|
1515
|
+
this.notifyBatch(slot.pk);
|
|
1456
1516
|
this.updateEmitter.markUpdatedCarrier(slot);
|
|
1457
1517
|
this.trackAnyUpdatePk(slot.pk);
|
|
1458
1518
|
return slot;
|
|
@@ -1463,7 +1523,7 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1463
1523
|
(entity) => this.upsertOneWithoutNotifications(entity)
|
|
1464
1524
|
);
|
|
1465
1525
|
const pks = slots.map((slot) => slot.pk);
|
|
1466
|
-
this.
|
|
1526
|
+
this.notifyBatchMany(pks);
|
|
1467
1527
|
for (let i = 0; i < slots.length; i++) {
|
|
1468
1528
|
this.updateEmitter.markUpdatedCarrier(slots[i]);
|
|
1469
1529
|
}
|
|
@@ -1473,7 +1533,7 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1473
1533
|
removeOne(entity) {
|
|
1474
1534
|
const pk = this.selectPk(entity);
|
|
1475
1535
|
this.store.removeOneByPk(pk);
|
|
1476
|
-
this.
|
|
1536
|
+
this.notifyBatch(pk);
|
|
1477
1537
|
this.updateEmitter.markUpdatedKey(pk);
|
|
1478
1538
|
this.trackAnyUpdatePk(pk);
|
|
1479
1539
|
}
|
|
@@ -1481,30 +1541,32 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1481
1541
|
if (entities.length === 0) return;
|
|
1482
1542
|
const pks = entities.map(this.selectPk);
|
|
1483
1543
|
this.store.removeManyByPks(pks);
|
|
1484
|
-
this.
|
|
1544
|
+
this.notifyBatchMany(pks);
|
|
1485
1545
|
this.updateEmitter.markUpdatedKeys(pks);
|
|
1486
1546
|
this.trackAnyUpdatePks(pks);
|
|
1487
1547
|
}
|
|
1488
1548
|
removeOneByPk(pk) {
|
|
1489
1549
|
this.store.removeOneByPk(pk);
|
|
1490
|
-
this.
|
|
1550
|
+
this.notifyBatch(pk);
|
|
1491
1551
|
this.updateEmitter.markUpdatedKey(pk);
|
|
1492
1552
|
this.trackAnyUpdatePk(pk);
|
|
1493
1553
|
}
|
|
1494
1554
|
removeManyByPks(pks) {
|
|
1495
1555
|
if (pks.length === 0) return;
|
|
1496
1556
|
this.store.removeManyByPks(pks);
|
|
1497
|
-
this.
|
|
1557
|
+
this.notifyBatchMany(pks);
|
|
1498
1558
|
this.updateEmitter.markUpdatedKeys(pks);
|
|
1499
1559
|
this.trackAnyUpdatePks(pks);
|
|
1500
1560
|
}
|
|
1501
1561
|
clear() {
|
|
1562
|
+
const needsPks = this.emitter.hasHandlers(0 /* UPDATE */) || this.anyUpdateHandlers.size > 0;
|
|
1563
|
+
const pks = needsPks ? this.store.getAllPks() : void 0;
|
|
1502
1564
|
this.store.clear();
|
|
1503
|
-
if (
|
|
1504
|
-
this.
|
|
1565
|
+
if (pks && pks.length > 0) {
|
|
1566
|
+
this.notifyBatchMany(pks);
|
|
1567
|
+
this.trackAnyUpdatePks(pks);
|
|
1505
1568
|
}
|
|
1506
1569
|
this.updateEmitter.markAllUpdated();
|
|
1507
|
-
this.trackAnyUpdateClear();
|
|
1508
1570
|
}
|
|
1509
1571
|
trackAnyUpdatePk(pk) {
|
|
1510
1572
|
if (this.anyUpdateHandlers.size === 0) return;
|
|
@@ -1513,14 +1575,9 @@ var OIMReactiveCollection = class extends OIMCollection {
|
|
|
1513
1575
|
}
|
|
1514
1576
|
trackAnyUpdatePks(pks) {
|
|
1515
1577
|
if (this.anyUpdateHandlers.size === 0) return;
|
|
1516
|
-
for (let i = 0; i < pks.length; i++)
|
|
1578
|
+
for (let i = 0; i < pks.length; i++) {
|
|
1517
1579
|
this.pendingAnyUpdatePks.add(pks[i]);
|
|
1518
|
-
|
|
1519
|
-
}
|
|
1520
|
-
trackAnyUpdateClear() {
|
|
1521
|
-
if (this.anyUpdateHandlers.size === 0) return;
|
|
1522
|
-
this.isAnyUpdateClearPending = true;
|
|
1523
|
-
this.pendingAnyUpdatePks.clear();
|
|
1580
|
+
}
|
|
1524
1581
|
this.ensureAnyUpdateEnqueued();
|
|
1525
1582
|
}
|
|
1526
1583
|
ensureAnyUpdateEnqueued() {
|
|
@@ -1953,8 +2010,13 @@ var OIMUpdateEventEmitter = class {
|
|
|
1953
2010
|
var OIMOrderedListCommandBuffer = class {
|
|
1954
2011
|
constructor(queue) {
|
|
1955
2012
|
this.commandsByKey = /* @__PURE__ */ new Map();
|
|
2013
|
+
// Keys whose buffered leading `reset` is stale: an edit after the reset
|
|
2014
|
+
// should be folded into it, but we defer the (O(list-size)) rebuild to the
|
|
2015
|
+
// next read instead of redoing it on every subsequent edit in the batch.
|
|
2016
|
+
this.staleResetKeys = /* @__PURE__ */ new Set();
|
|
1956
2017
|
this.onAfterFlush = () => {
|
|
1957
2018
|
this.commandsByKey.clear();
|
|
2019
|
+
this.staleResetKeys.clear();
|
|
1958
2020
|
};
|
|
1959
2021
|
this.commandsEventEmitter = new OIMUpdateEventEmitter(
|
|
1960
2022
|
queue,
|
|
@@ -1969,9 +2031,11 @@ var OIMOrderedListCommandBuffer = class {
|
|
|
1969
2031
|
return this.commandsEventEmitter.subscribeOnKey(key, handler);
|
|
1970
2032
|
}
|
|
1971
2033
|
getBufferedCommands(key) {
|
|
2034
|
+
this.materializeStaleReset(key);
|
|
1972
2035
|
return this.commandsByKey.get(key) ?? [];
|
|
1973
2036
|
}
|
|
1974
2037
|
consumeCommands(key) {
|
|
2038
|
+
this.materializeStaleReset(key);
|
|
1975
2039
|
const cmds = this.commandsByKey.get(key);
|
|
1976
2040
|
if (!cmds || cmds.length === 0) return [];
|
|
1977
2041
|
return cmds.slice();
|
|
@@ -1980,6 +2044,20 @@ var OIMOrderedListCommandBuffer = class {
|
|
|
1980
2044
|
this.commandsEventEmitter.destroy();
|
|
1981
2045
|
this.unsubscribeAfterFlush();
|
|
1982
2046
|
this.commandsByKey.clear();
|
|
2047
|
+
this.staleResetKeys.clear();
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Rebuild a deferred leading `reset` from the current order, once, at read
|
|
2051
|
+
* time. All the post-reset edits that were folded in are already reflected
|
|
2052
|
+
* in the driver's backing order, so a single rebuild here is equivalent to
|
|
2053
|
+
* having recomputed the reset on each of those edits.
|
|
2054
|
+
*/
|
|
2055
|
+
materializeStaleReset(key) {
|
|
2056
|
+
if (!this.staleResetKeys.delete(key)) return;
|
|
2057
|
+
const cmds = this.commandsByKey.get(key);
|
|
2058
|
+
if (cmds && cmds.length > 0 && cmds[0].type === "reset") {
|
|
2059
|
+
cmds[0] = this.createResetCommand(this.getItemsByKey(key));
|
|
2060
|
+
}
|
|
1983
2061
|
}
|
|
1984
2062
|
appendCommand(key, cmd) {
|
|
1985
2063
|
let cmds = this.commandsByKey.get(key);
|
|
@@ -1990,8 +2068,9 @@ var OIMOrderedListCommandBuffer = class {
|
|
|
1990
2068
|
if (cmd.type === "reset") {
|
|
1991
2069
|
cmds.length = 0;
|
|
1992
2070
|
cmds.push(cmd);
|
|
2071
|
+
this.staleResetKeys.delete(key);
|
|
1993
2072
|
} else if (cmds.length > 0 && cmds[0].type === "reset") {
|
|
1994
|
-
|
|
2073
|
+
this.staleResetKeys.add(key);
|
|
1995
2074
|
} else {
|
|
1996
2075
|
cmds.push(cmd);
|
|
1997
2076
|
}
|
|
@@ -3033,10 +3112,6 @@ var OIMDerivedCollectionIndexSetBased = class extends OIMReactiveCollectionIndex
|
|
|
3033
3112
|
});
|
|
3034
3113
|
this.keysByPk = /* @__PURE__ */ new Map();
|
|
3035
3114
|
this.onCollectionUpdate = (pks) => {
|
|
3036
|
-
if (pks.length === 0) {
|
|
3037
|
-
this.rebuildFromCollection();
|
|
3038
|
-
return;
|
|
3039
|
-
}
|
|
3040
3115
|
for (const pk of pks) {
|
|
3041
3116
|
this.syncPk(pk);
|
|
3042
3117
|
}
|
|
@@ -3138,10 +3213,6 @@ var OIMDerivedCollectionIndexArrayBased = class extends OIMReactiveCollectionInd
|
|
|
3138
3213
|
// touching an unrelated field can skip re-sorting when the value is unchanged.
|
|
3139
3214
|
this.orderValueByPk = /* @__PURE__ */ new Map();
|
|
3140
3215
|
this.onCollectionUpdate = (pks) => {
|
|
3141
|
-
if (pks.length === 0) {
|
|
3142
|
-
this.rebuildFromCollection();
|
|
3143
|
-
return;
|
|
3144
|
-
}
|
|
3145
3216
|
const ordered = !!(this.compareEntities || this.orderBy);
|
|
3146
3217
|
const keysToSort = ordered ? /* @__PURE__ */ new Set() : null;
|
|
3147
3218
|
for (const pk of pks) {
|
|
@@ -3558,10 +3629,6 @@ var OIMDerivedCollectionGlobalIndexArrayBased = class extends OIMReactiveCollect
|
|
|
3558
3629
|
// an unrelated field can skip re-sorting when the value is unchanged.
|
|
3559
3630
|
this.orderValueByPk = /* @__PURE__ */ new Map();
|
|
3560
3631
|
this.onCollectionUpdate = (pks) => {
|
|
3561
|
-
if (pks.length === 0) {
|
|
3562
|
-
this.rebuildFromCollection();
|
|
3563
|
-
return;
|
|
3564
|
-
}
|
|
3565
3632
|
const ordered = !!(this.compareEntities || this.orderBy);
|
|
3566
3633
|
let needsSort = false;
|
|
3567
3634
|
for (const pk of pks) {
|
|
@@ -3659,10 +3726,6 @@ var OIMDerivedCollectionGlobalIndexSetBased = class extends OIMReactiveCollectio
|
|
|
3659
3726
|
super(queue, { collection, indexOptions: opts.indexOptions });
|
|
3660
3727
|
this.presentPks = /* @__PURE__ */ new Set();
|
|
3661
3728
|
this.onCollectionUpdate = (pks) => {
|
|
3662
|
-
if (pks.length === 0) {
|
|
3663
|
-
this.rebuildFromCollection();
|
|
3664
|
-
return;
|
|
3665
|
-
}
|
|
3666
3729
|
for (const pk of pks) {
|
|
3667
3730
|
const prev = this.presentPks.has(pk);
|
|
3668
3731
|
const slot = this.collection.getSlotByPk(pk);
|
|
@@ -3838,6 +3901,55 @@ function createOIMCollectionIndexFactory(queue, collection) {
|
|
|
3838
3901
|
return new OIMCollectionIndexFactory(queue, collection);
|
|
3839
3902
|
}
|
|
3840
3903
|
|
|
3904
|
+
// src/core/OIMDerivedCollection.ts
|
|
3905
|
+
var OIMDerivedCollection = class extends OIMReactiveCollection {
|
|
3906
|
+
constructor(queue, source, derive, opts) {
|
|
3907
|
+
super(queue, {
|
|
3908
|
+
store: opts?.store,
|
|
3909
|
+
// Each sync recomputes the WHOLE derived entity → replace, not merge.
|
|
3910
|
+
updateEntity: (draft) => draft
|
|
3911
|
+
});
|
|
3912
|
+
this.onSourceUpdate = (pks) => {
|
|
3913
|
+
for (let i = 0; i < pks.length; i++) this.syncPk(pks[i]);
|
|
3914
|
+
};
|
|
3915
|
+
this.source = source;
|
|
3916
|
+
this.derive = derive;
|
|
3917
|
+
this.compareDerived = opts?.compare ?? Object.is;
|
|
3918
|
+
this.unsubscribeFromSource = source.emitter.on(
|
|
3919
|
+
0 /* UPDATE */,
|
|
3920
|
+
(payload) => this.onSourceUpdate(payload.pks)
|
|
3921
|
+
);
|
|
3922
|
+
if (opts?.buildInitial !== false) {
|
|
3923
|
+
this.rebuildFromSource();
|
|
3924
|
+
}
|
|
3925
|
+
}
|
|
3926
|
+
rebuildFromSource() {
|
|
3927
|
+
for (const pk of this.getAllPks()) {
|
|
3928
|
+
if (this.source.getOneByPk(pk) === void 0) {
|
|
3929
|
+
this.removeOneByPk(pk);
|
|
3930
|
+
}
|
|
3931
|
+
}
|
|
3932
|
+
for (const slot of this.source.getAllSlots()) {
|
|
3933
|
+
if (slot.item !== void 0) this.syncPk(slot.pk);
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
destroy() {
|
|
3937
|
+
this.unsubscribeFromSource();
|
|
3938
|
+
super.destroy();
|
|
3939
|
+
}
|
|
3940
|
+
syncPk(pk) {
|
|
3941
|
+
const sourceEntity = this.source.getOneByPk(pk);
|
|
3942
|
+
if (sourceEntity === void 0) {
|
|
3943
|
+
if (this.getOneByPk(pk) !== void 0) this.removeOneByPk(pk);
|
|
3944
|
+
return;
|
|
3945
|
+
}
|
|
3946
|
+
const next = this.derive(sourceEntity, pk);
|
|
3947
|
+
const prev = this.getOneByPk(pk);
|
|
3948
|
+
if (prev !== void 0 && this.compareDerived(prev, next)) return;
|
|
3949
|
+
this.upsertOneByPk(pk, next);
|
|
3950
|
+
}
|
|
3951
|
+
};
|
|
3952
|
+
|
|
3841
3953
|
// src/core/OIMObjectStoreRecordDriven.ts
|
|
3842
3954
|
var OIMObjectStoreRecordDriven = class extends OIMObjectStore {
|
|
3843
3955
|
constructor(initial) {
|
|
@@ -3910,8 +4022,11 @@ var OIMObject = class {
|
|
|
3910
4022
|
return this.store.getAll();
|
|
3911
4023
|
}
|
|
3912
4024
|
clear() {
|
|
4025
|
+
const keys = this.store.keys();
|
|
3913
4026
|
this.store.clear();
|
|
3914
|
-
|
|
4027
|
+
if (keys.length > 0) {
|
|
4028
|
+
this.onUpdatedKeys(keys);
|
|
4029
|
+
}
|
|
3915
4030
|
}
|
|
3916
4031
|
/**
|
|
3917
4032
|
* Write fan-out hooks. Split single-key vs multi-key so a reactive subclass
|
|
@@ -4214,8 +4329,9 @@ var OIMComparatorFactory = class {
|
|
|
4214
4329
|
if (ka.length !== kb.length) return true;
|
|
4215
4330
|
for (let i = 0; i < ka.length; i++) {
|
|
4216
4331
|
const k = ka[i];
|
|
4217
|
-
if (b[k] !== a[k])
|
|
4332
|
+
if (b[k] !== a[k]) {
|
|
4218
4333
|
return true;
|
|
4334
|
+
}
|
|
4219
4335
|
}
|
|
4220
4336
|
return false;
|
|
4221
4337
|
};
|
|
@@ -4265,10 +4381,14 @@ var OIMEventQueue = class {
|
|
|
4265
4381
|
return this.isFlushing;
|
|
4266
4382
|
}
|
|
4267
4383
|
/**
|
|
4268
|
-
* Execute
|
|
4384
|
+
* Execute the tasks pending at the moment the flush starts — a single pass,
|
|
4385
|
+
* not a drain-to-empty.
|
|
4269
4386
|
*
|
|
4270
|
-
*
|
|
4271
|
-
*
|
|
4387
|
+
* The pending set is swapped out for an empty spare up front and the flush
|
|
4388
|
+
* iterates that captured set. Tasks enqueued during the flush land in the
|
|
4389
|
+
* fresh set and run on the NEXT flush, not this one. (Contrast
|
|
4390
|
+
* `OIMComputeRuntime.flush()`, which re-reads its bucket per level and so
|
|
4391
|
+
* does drain same-level tasks scheduled mid-flush.)
|
|
4272
4392
|
*/
|
|
4273
4393
|
flush() {
|
|
4274
4394
|
this.scheduler?.cancel();
|
|
@@ -4542,20 +4662,92 @@ var OIMPkCodecKeyPath = class {
|
|
|
4542
4662
|
}
|
|
4543
4663
|
};
|
|
4544
4664
|
|
|
4665
|
+
// src/modules/effect/core/OIMEffectDependencyComputed.ts
|
|
4666
|
+
var OIMEffectDependencyComputed = class {
|
|
4667
|
+
constructor(source) {
|
|
4668
|
+
this.source = source;
|
|
4669
|
+
}
|
|
4670
|
+
subscribe(onUpdate) {
|
|
4671
|
+
return this.source.emitter.on("update", onUpdate);
|
|
4672
|
+
}
|
|
4673
|
+
};
|
|
4674
|
+
|
|
4545
4675
|
// src/modules/compute/core/OIMComputeRuntime.ts
|
|
4546
4676
|
var OIMComputeRuntime = class {
|
|
4547
4677
|
constructor(queue) {
|
|
4548
4678
|
this.queue = queue;
|
|
4549
4679
|
this.isFlushScheduled = false;
|
|
4550
4680
|
this.isFlushing = false;
|
|
4681
|
+
// Active level range (min > max means nothing pending).
|
|
4551
4682
|
this.minLevel = Infinity;
|
|
4552
4683
|
this.maxLevel = -Infinity;
|
|
4553
|
-
this.dirtyByLevel =
|
|
4684
|
+
this.dirtyByLevel = [];
|
|
4554
4685
|
this.afterFlushTasks = /* @__PURE__ */ new Set();
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4686
|
+
// Topological depth per computed node — the engine is the ONLY owner of
|
|
4687
|
+
// levels; nodes never expose their own. A node's dependents look up its depth
|
|
4688
|
+
// here (by the computed reference their dependency wraps). Written once at
|
|
4689
|
+
// construction, never on the hot flush path.
|
|
4690
|
+
this.levelByComputed = /* @__PURE__ */ new WeakMap();
|
|
4691
|
+
this._isDestroyed = false;
|
|
4692
|
+
this.unsubscribeFromQueue = this.queue.emitter.on(
|
|
4693
|
+
0 /* AFTER_FLUSH */,
|
|
4694
|
+
() => {
|
|
4695
|
+
if (!this.isFlushScheduled) return;
|
|
4696
|
+
this.flush();
|
|
4697
|
+
}
|
|
4698
|
+
);
|
|
4699
|
+
}
|
|
4700
|
+
/**
|
|
4701
|
+
* Whether {@link destroy} has run. A destroyed runtime is detached from its
|
|
4702
|
+
* queue and must not be reused — `getOIMComputeRuntime` reads this to hand
|
|
4703
|
+
* out a fresh runtime instead of a dead one.
|
|
4704
|
+
*/
|
|
4705
|
+
get isDestroyed() {
|
|
4706
|
+
return this._isDestroyed;
|
|
4707
|
+
}
|
|
4708
|
+
/**
|
|
4709
|
+
* Detach from the queue and drop everything pending.
|
|
4710
|
+
*
|
|
4711
|
+
* Without this the AFTER_FLUSH subscription lives as long as the queue does,
|
|
4712
|
+
* even once every computed / effect on this runtime is gone — harmless (the
|
|
4713
|
+
* handler early-returns) but impossible to unwind. Destroying does NOT
|
|
4714
|
+
* destroy the nodes scheduled on it; destroy them first, then the runtime.
|
|
4715
|
+
* Idempotent.
|
|
4716
|
+
*/
|
|
4717
|
+
destroy() {
|
|
4718
|
+
if (this._isDestroyed) return;
|
|
4719
|
+
this._isDestroyed = true;
|
|
4720
|
+
this.unsubscribeFromQueue();
|
|
4721
|
+
for (let i = 0; i < this.dirtyByLevel.length; i++) {
|
|
4722
|
+
this.dirtyByLevel[i]?.clear();
|
|
4723
|
+
}
|
|
4724
|
+
this.afterFlushTasks.clear();
|
|
4725
|
+
this.minLevel = Infinity;
|
|
4726
|
+
this.maxLevel = -Infinity;
|
|
4727
|
+
this.isFlushScheduled = false;
|
|
4728
|
+
}
|
|
4729
|
+
/**
|
|
4730
|
+
* Topological depth for a node with these dependencies: one above the deepest
|
|
4731
|
+
* computed dependency (source-only → 0). The engine owns this — callers pass
|
|
4732
|
+
* their dependencies and get back a level, they never compute it themselves.
|
|
4733
|
+
*/
|
|
4734
|
+
computeLevel(deps) {
|
|
4735
|
+
let max = -1;
|
|
4736
|
+
for (const dep of deps) {
|
|
4737
|
+
if (dep instanceof OIMEffectDependencyComputed) {
|
|
4738
|
+
const depLevel = this.levelByComputed.get(dep.source) ?? 0;
|
|
4739
|
+
if (depLevel > max) max = depLevel;
|
|
4740
|
+
}
|
|
4741
|
+
}
|
|
4742
|
+
return max + 1;
|
|
4743
|
+
}
|
|
4744
|
+
/** Record a computed's depth so its dependents can look it up. */
|
|
4745
|
+
registerLevel(computed, level) {
|
|
4746
|
+
this.levelByComputed.set(computed, level);
|
|
4747
|
+
}
|
|
4748
|
+
/** The recorded topological depth of a computed (0 if unknown). Introspection. */
|
|
4749
|
+
getLevel(computed) {
|
|
4750
|
+
return this.levelByComputed.get(computed) ?? 0;
|
|
4559
4751
|
}
|
|
4560
4752
|
/**
|
|
4561
4753
|
* Schedule a one-shot task to run on the next `queue.flush()` (AFTER_FLUSH),
|
|
@@ -4567,10 +4759,10 @@ var OIMComputeRuntime = class {
|
|
|
4567
4759
|
if (!isActive) return;
|
|
4568
4760
|
task();
|
|
4569
4761
|
};
|
|
4570
|
-
let bucket = this.dirtyByLevel
|
|
4571
|
-
if (
|
|
4762
|
+
let bucket = this.dirtyByLevel[level];
|
|
4763
|
+
if (bucket === void 0) {
|
|
4572
4764
|
bucket = /* @__PURE__ */ new Set();
|
|
4573
|
-
this.dirtyByLevel
|
|
4765
|
+
this.dirtyByLevel[level] = bucket;
|
|
4574
4766
|
}
|
|
4575
4767
|
bucket.add(wrapped);
|
|
4576
4768
|
if (level < this.minLevel) this.minLevel = level;
|
|
@@ -4602,7 +4794,7 @@ var OIMComputeRuntime = class {
|
|
|
4602
4794
|
}
|
|
4603
4795
|
flush() {
|
|
4604
4796
|
this.isFlushScheduled = false;
|
|
4605
|
-
if (this.
|
|
4797
|
+
if (this.minLevel > this.maxLevel && this.afterFlushTasks.size === 0)
|
|
4606
4798
|
return;
|
|
4607
4799
|
this.isFlushing = true;
|
|
4608
4800
|
try {
|
|
@@ -4611,15 +4803,15 @@ var OIMComputeRuntime = class {
|
|
|
4611
4803
|
this.afterFlushTasks.clear();
|
|
4612
4804
|
for (let i = 0; i < snapshot.length; i++) snapshot[i]();
|
|
4613
4805
|
}
|
|
4614
|
-
if (this.
|
|
4806
|
+
if (this.minLevel > this.maxLevel) return;
|
|
4615
4807
|
let level = this.minLevel;
|
|
4616
4808
|
let max = this.maxLevel;
|
|
4617
4809
|
while (level <= max) {
|
|
4618
4810
|
for (; ; ) {
|
|
4619
|
-
const bucket = this.dirtyByLevel
|
|
4620
|
-
if (
|
|
4621
|
-
this.dirtyByLevel.delete(level);
|
|
4811
|
+
const bucket = this.dirtyByLevel[level];
|
|
4812
|
+
if (bucket === void 0 || bucket.size === 0) break;
|
|
4622
4813
|
const snapshot = Array.from(bucket);
|
|
4814
|
+
bucket.clear();
|
|
4623
4815
|
for (let i = 0; i < snapshot.length; i++) snapshot[i]();
|
|
4624
4816
|
}
|
|
4625
4817
|
if (this.maxLevel > max) max = this.maxLevel;
|
|
@@ -4627,24 +4819,38 @@ var OIMComputeRuntime = class {
|
|
|
4627
4819
|
}
|
|
4628
4820
|
} finally {
|
|
4629
4821
|
this.isFlushing = false;
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
|
|
4633
|
-
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
this.isFlushScheduled = true;
|
|
4822
|
+
this.recomputePendingRange();
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4825
|
+
recomputePendingRange() {
|
|
4826
|
+
let nextMin = Infinity;
|
|
4827
|
+
let nextMax = -Infinity;
|
|
4828
|
+
const buckets = this.dirtyByLevel;
|
|
4829
|
+
for (let i = 0; i < buckets.length; i++) {
|
|
4830
|
+
const bucket = buckets[i];
|
|
4831
|
+
if (bucket !== void 0 && bucket.size > 0) {
|
|
4832
|
+
if (i < nextMin) nextMin = i;
|
|
4833
|
+
if (i > nextMax) nextMax = i;
|
|
4643
4834
|
}
|
|
4644
4835
|
}
|
|
4836
|
+
this.minLevel = nextMin;
|
|
4837
|
+
this.maxLevel = nextMax;
|
|
4838
|
+
if (nextMin <= nextMax) this.isFlushScheduled = true;
|
|
4645
4839
|
}
|
|
4646
4840
|
};
|
|
4647
4841
|
|
|
4842
|
+
// src/dx/oimComputeRuntimeByQueue.ts
|
|
4843
|
+
var oimComputeRuntimeByQueue = /* @__PURE__ */ new WeakMap();
|
|
4844
|
+
|
|
4845
|
+
// src/dx/getOIMComputeRuntime.ts
|
|
4846
|
+
function getOIMComputeRuntime(queue) {
|
|
4847
|
+
const runtime = oimComputeRuntimeByQueue.get(queue);
|
|
4848
|
+
if (runtime !== void 0 && !runtime.isDestroyed) return runtime;
|
|
4849
|
+
const nextRuntime = new OIMComputeRuntime(queue);
|
|
4850
|
+
oimComputeRuntimeByQueue.set(queue, nextRuntime);
|
|
4851
|
+
return nextRuntime;
|
|
4852
|
+
}
|
|
4853
|
+
|
|
4648
4854
|
// src/modules/selector/core/OIMSelector.ts
|
|
4649
4855
|
var OIMSelector = class {
|
|
4650
4856
|
constructor(runtime, sourceDeps, computedDeps = []) {
|
|
@@ -4905,8 +5111,9 @@ var OIMEntitiesByIndexKeyArrayBasedSelector = class extends OIMSelector {
|
|
|
4905
5111
|
areEqual(prev, next) {
|
|
4906
5112
|
if (prev === next) return true;
|
|
4907
5113
|
if (prev.length !== next.length) return false;
|
|
4908
|
-
for (let i = 0; i < prev.length; i++)
|
|
5114
|
+
for (let i = 0; i < prev.length; i++) {
|
|
4909
5115
|
if (prev[i] !== next[i]) return false;
|
|
5116
|
+
}
|
|
4910
5117
|
return true;
|
|
4911
5118
|
}
|
|
4912
5119
|
};
|
|
@@ -4976,8 +5183,9 @@ var OIMEntitiesByIndexKeySetBasedSelector = class extends OIMSelector {
|
|
|
4976
5183
|
areEqual(prev, next) {
|
|
4977
5184
|
if (prev === next) return true;
|
|
4978
5185
|
if (prev.length !== next.length) return false;
|
|
4979
|
-
for (let i = 0; i < prev.length; i++)
|
|
5186
|
+
for (let i = 0; i < prev.length; i++) {
|
|
4980
5187
|
if (prev[i] !== next[i]) return false;
|
|
5188
|
+
}
|
|
4981
5189
|
return true;
|
|
4982
5190
|
}
|
|
4983
5191
|
};
|
|
@@ -5041,8 +5249,9 @@ var OIMEntitiesByGlobalIndexArrayBasedSelector = class extends OIMSelector {
|
|
|
5041
5249
|
areEqual(prev, next) {
|
|
5042
5250
|
if (prev === next) return true;
|
|
5043
5251
|
if (prev.length !== next.length) return false;
|
|
5044
|
-
for (let i = 0; i < prev.length; i++)
|
|
5252
|
+
for (let i = 0; i < prev.length; i++) {
|
|
5045
5253
|
if (prev[i] !== next[i]) return false;
|
|
5254
|
+
}
|
|
5046
5255
|
return true;
|
|
5047
5256
|
}
|
|
5048
5257
|
};
|
|
@@ -5107,8 +5316,9 @@ var OIMEntitiesByGlobalIndexSetBasedSelector = class extends OIMSelector {
|
|
|
5107
5316
|
areEqual(prev, next) {
|
|
5108
5317
|
if (prev === next) return true;
|
|
5109
5318
|
if (prev.length !== next.length) return false;
|
|
5110
|
-
for (let i = 0; i < prev.length; i++)
|
|
5319
|
+
for (let i = 0; i < prev.length; i++) {
|
|
5111
5320
|
if (prev[i] !== next[i]) return false;
|
|
5321
|
+
}
|
|
5112
5322
|
return true;
|
|
5113
5323
|
}
|
|
5114
5324
|
};
|
|
@@ -5117,7 +5327,7 @@ var OIMEntitiesByGlobalIndexSetBasedSelector = class extends OIMSelector {
|
|
|
5117
5327
|
var OIMCollectionSelectors = class {
|
|
5118
5328
|
constructor(queue, collection) {
|
|
5119
5329
|
this.collection = collection;
|
|
5120
|
-
this.runtime =
|
|
5330
|
+
this.runtime = getOIMComputeRuntime(queue);
|
|
5121
5331
|
}
|
|
5122
5332
|
byPk(pk) {
|
|
5123
5333
|
return new OIMCollectionByPkSelector(this.runtime, this.collection, pk);
|
|
@@ -5184,127 +5394,408 @@ var OIMCollectionSelectors = class {
|
|
|
5184
5394
|
}
|
|
5185
5395
|
};
|
|
5186
5396
|
|
|
5187
|
-
// src/
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
indexFactory,
|
|
5198
|
-
select,
|
|
5199
|
-
scope,
|
|
5200
|
-
destroy: () => scope.destroy()
|
|
5201
|
-
};
|
|
5202
|
-
}
|
|
5397
|
+
// src/modules/effect/core/OIMEffectDependencyKeyed.ts
|
|
5398
|
+
var OIMEffectDependencyKeyed = class {
|
|
5399
|
+
constructor(source, key) {
|
|
5400
|
+
this.source = source;
|
|
5401
|
+
this.key = key;
|
|
5402
|
+
}
|
|
5403
|
+
subscribe(onUpdate) {
|
|
5404
|
+
return this.source.subscribeOnKey(this.key, onUpdate);
|
|
5405
|
+
}
|
|
5406
|
+
};
|
|
5203
5407
|
|
|
5204
|
-
// src/modules/
|
|
5205
|
-
var
|
|
5206
|
-
constructor(
|
|
5207
|
-
this.
|
|
5208
|
-
this.lastEntitySnapshotByPk = /* @__PURE__ */ new Map();
|
|
5209
|
-
// PKs written through this wrapper during the current flush. Their fields are
|
|
5210
|
-
// already tracked accurately via trackPatch, so the flush-time external-write
|
|
5211
|
-
// handler skips them — no redundant diff + snapshot re-clone. Cleared per flush.
|
|
5212
|
-
this.writtenThroughThisFlush = /* @__PURE__ */ new Set();
|
|
5213
|
-
this.changedFieldsByPk = /* @__PURE__ */ new Map();
|
|
5214
|
-
this.changedPksByField = /* @__PURE__ */ new Map();
|
|
5215
|
-
this.onAfterFlush = () => {
|
|
5216
|
-
this.clear();
|
|
5217
|
-
this.writtenThroughThisFlush.clear();
|
|
5218
|
-
};
|
|
5219
|
-
this.onCollectionUpdate = (payload) => {
|
|
5220
|
-
if (this.isInWrite) return;
|
|
5221
|
-
if (payload.pks.length === 0) return;
|
|
5222
|
-
for (let i = 0; i < payload.pks.length; i++) {
|
|
5223
|
-
const pk = payload.pks[i];
|
|
5224
|
-
if (this.writtenThroughThisFlush.has(pk)) continue;
|
|
5225
|
-
this.trackExternalMutationByPk(pk);
|
|
5226
|
-
}
|
|
5227
|
-
};
|
|
5228
|
-
this.collection = collection;
|
|
5229
|
-
this.detectExternalMutations = opts?.detectExternalMutations !== false;
|
|
5230
|
-
this.selectPk = opts?.selectPk ?? (() => {
|
|
5231
|
-
throw new Error(
|
|
5232
|
-
`[OIMCollectionChangedFields]: selectPk was not provided. Use upsertOneByPk(...) or pass opts.selectPk.`
|
|
5233
|
-
);
|
|
5234
|
-
});
|
|
5235
|
-
this.changedPksEventEmitter = new OIMUpdateEventEmitter(
|
|
5236
|
-
queue,
|
|
5237
|
-
"after_flush"
|
|
5238
|
-
);
|
|
5239
|
-
this.changedFieldsEventEmitter = new OIMUpdateEventEmitter(queue, "after_flush");
|
|
5240
|
-
this.unsubscribeAfterFlush = queue.emitter.on(
|
|
5241
|
-
0 /* AFTER_FLUSH */,
|
|
5242
|
-
this.onAfterFlush
|
|
5243
|
-
);
|
|
5244
|
-
if (this.detectExternalMutations) {
|
|
5245
|
-
const maybeReactive = collection;
|
|
5246
|
-
this.unsubscribeFromCollectionEmitter = maybeReactive.subscribeOnAnyUpdate ? maybeReactive.subscribeOnAnyUpdate((pks) => {
|
|
5247
|
-
this.onCollectionUpdate({
|
|
5248
|
-
pks
|
|
5249
|
-
});
|
|
5250
|
-
}) : collection.emitter.on(
|
|
5251
|
-
0 /* UPDATE */,
|
|
5252
|
-
this.onCollectionUpdate
|
|
5253
|
-
);
|
|
5254
|
-
}
|
|
5408
|
+
// src/modules/effect/core/OIMEffectDependencyKeyedCollection.ts
|
|
5409
|
+
var OIMEffectDependencyKeyedCollection = class {
|
|
5410
|
+
constructor(collection, pk) {
|
|
5411
|
+
this.dep = new OIMEffectDependencyKeyed(collection, pk);
|
|
5255
5412
|
}
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
this.trackPatch(pk, patch);
|
|
5259
|
-
return this.collection.upsertOneByPk(pk, patch);
|
|
5260
|
-
});
|
|
5261
|
-
this.updateEntitySnapshot(pk);
|
|
5262
|
-
return slot;
|
|
5413
|
+
get source() {
|
|
5414
|
+
return this.dep.source;
|
|
5263
5415
|
}
|
|
5264
|
-
|
|
5265
|
-
|
|
5266
|
-
const pk = this.selectPk(entity);
|
|
5267
|
-
this.trackPatch(pk, entity);
|
|
5268
|
-
return this.collection.upsertOne(entity);
|
|
5269
|
-
});
|
|
5270
|
-
this.updateEntitySnapshot(slot.pk);
|
|
5271
|
-
return slot;
|
|
5416
|
+
subscribe(onUpdate) {
|
|
5417
|
+
return this.dep.subscribe(onUpdate);
|
|
5272
5418
|
}
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5278
|
-
|
|
5279
|
-
this.trackPatch(pk, entity);
|
|
5280
|
-
}
|
|
5281
|
-
return this.collection.upsertMany(entities);
|
|
5282
|
-
});
|
|
5283
|
-
for (let i = 0; i < pks.length; i++) this.updateEntitySnapshot(pks[i]);
|
|
5284
|
-
return slots;
|
|
5419
|
+
};
|
|
5420
|
+
|
|
5421
|
+
// src/modules/effect/core/OIMEffectDependencyKeyedIndex.ts
|
|
5422
|
+
var OIMEffectDependencyKeyedIndex = class {
|
|
5423
|
+
constructor(index, key) {
|
|
5424
|
+
this.dep = new OIMEffectDependencyKeyed(index, key);
|
|
5285
5425
|
}
|
|
5286
|
-
|
|
5287
|
-
return this.
|
|
5426
|
+
get source() {
|
|
5427
|
+
return this.dep.source;
|
|
5288
5428
|
}
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
if (!existing) return /* @__PURE__ */ new Set();
|
|
5292
|
-
return new Set(existing);
|
|
5429
|
+
subscribe(onUpdate) {
|
|
5430
|
+
return this.dep.subscribe(onUpdate);
|
|
5293
5431
|
}
|
|
5294
|
-
|
|
5295
|
-
|
|
5432
|
+
};
|
|
5433
|
+
|
|
5434
|
+
// src/modules/effect/core/OIMEffectDependencyKeyedObject.ts
|
|
5435
|
+
var OIMEffectDependencyKeyedObject = class {
|
|
5436
|
+
constructor(object, key) {
|
|
5437
|
+
this.dep = new OIMEffectDependencyKeyed(object, key);
|
|
5296
5438
|
}
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
if (!existing) return /* @__PURE__ */ new Set();
|
|
5300
|
-
return new Set(existing);
|
|
5439
|
+
get source() {
|
|
5440
|
+
return this.dep.source;
|
|
5301
5441
|
}
|
|
5302
|
-
|
|
5303
|
-
this.
|
|
5304
|
-
this.changedPksByField.clear();
|
|
5442
|
+
subscribe(onUpdate) {
|
|
5443
|
+
return this.dep.subscribe(onUpdate);
|
|
5305
5444
|
}
|
|
5306
|
-
|
|
5307
|
-
|
|
5445
|
+
};
|
|
5446
|
+
|
|
5447
|
+
// src/dx/on.ts
|
|
5448
|
+
var on = {
|
|
5449
|
+
/** Depend on one PK of a collection. */
|
|
5450
|
+
collection: (collection, pk) => new OIMEffectDependencyKeyedCollection(collection, pk),
|
|
5451
|
+
/** Depend on one key of an index. */
|
|
5452
|
+
index: (index, key) => new OIMEffectDependencyKeyedIndex(index, key),
|
|
5453
|
+
/** Depend on one key of a reactive object. */
|
|
5454
|
+
object: (object, key) => new OIMEffectDependencyKeyedObject(object, key),
|
|
5455
|
+
/** Depend on another computed. */
|
|
5456
|
+
computed: (computed) => new OIMEffectDependencyComputed(computed)
|
|
5457
|
+
};
|
|
5458
|
+
|
|
5459
|
+
// src/modules/effect/core/OIMEffect.ts
|
|
5460
|
+
var OIMEffect = class {
|
|
5461
|
+
constructor(runtime, opts, level) {
|
|
5462
|
+
this.sourceDeps = [];
|
|
5463
|
+
this.computedDeps = [];
|
|
5464
|
+
this.sourceUnsubscribers = [];
|
|
5465
|
+
this.computedUnsubscribers = [];
|
|
5466
|
+
this.isResubscribeEnqueued = false;
|
|
5467
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
5468
|
+
this.isScheduled = false;
|
|
5469
|
+
this.runTask = () => {
|
|
5470
|
+
this.isScheduled = false;
|
|
5471
|
+
this.dequeueScheduled = void 0;
|
|
5472
|
+
this.runOnce();
|
|
5473
|
+
};
|
|
5474
|
+
this.onSourceInvalidate = () => {
|
|
5475
|
+
this.onUpdate?.();
|
|
5476
|
+
if (!this.isTemporarilyUnsubscribedForFlush) {
|
|
5477
|
+
this.isTemporarilyUnsubscribedForFlush = true;
|
|
5478
|
+
this.unsubscribeFromSourceDeps();
|
|
5479
|
+
this.ensureResubscribeAfterFlush();
|
|
5480
|
+
}
|
|
5481
|
+
if (this.isScheduled) return;
|
|
5482
|
+
this.isScheduled = true;
|
|
5483
|
+
this.dequeueScheduled = this.runtime.schedule(this.runTask, this.level);
|
|
5484
|
+
};
|
|
5485
|
+
this.onComputedInvalidate = () => {
|
|
5486
|
+
this.onUpdate?.();
|
|
5487
|
+
if (this.isScheduled) return;
|
|
5488
|
+
this.isScheduled = true;
|
|
5489
|
+
this.dequeueScheduled = this.runtime.schedule(this.runTask, this.level);
|
|
5490
|
+
};
|
|
5491
|
+
this.onAfterFlush = () => {
|
|
5492
|
+
if (!this.isResubscribeEnqueued) return;
|
|
5493
|
+
this.isResubscribeEnqueued = false;
|
|
5494
|
+
this.dequeueResubscribe = void 0;
|
|
5495
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
5496
|
+
if (this.sourceUnsubscribers.length === 0) {
|
|
5497
|
+
for (const dep of this.sourceDeps) {
|
|
5498
|
+
this.sourceUnsubscribers.push(
|
|
5499
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
5500
|
+
);
|
|
5501
|
+
}
|
|
5502
|
+
}
|
|
5503
|
+
};
|
|
5504
|
+
this.runtime = runtime;
|
|
5505
|
+
this.onUpdate = opts.onUpdate;
|
|
5506
|
+
this.run = opts.run;
|
|
5507
|
+
this.deps = opts.deps ?? [];
|
|
5508
|
+
for (const dep of this.deps) {
|
|
5509
|
+
if (dep instanceof OIMEffectDependencyComputed) {
|
|
5510
|
+
this.computedDeps.push(dep);
|
|
5511
|
+
} else {
|
|
5512
|
+
this.sourceDeps.push(dep);
|
|
5513
|
+
}
|
|
5514
|
+
}
|
|
5515
|
+
this.level = level ?? this.runtime.computeLevel(this.deps);
|
|
5516
|
+
this.subscribeToDeps();
|
|
5517
|
+
}
|
|
5518
|
+
destroy() {
|
|
5519
|
+
if (this.dequeueScheduled) {
|
|
5520
|
+
this.dequeueScheduled();
|
|
5521
|
+
this.dequeueScheduled = void 0;
|
|
5522
|
+
}
|
|
5523
|
+
this.unsubscribeFromAllDeps();
|
|
5524
|
+
if (this.dequeueResubscribe) {
|
|
5525
|
+
this.dequeueResubscribe();
|
|
5526
|
+
this.dequeueResubscribe = void 0;
|
|
5527
|
+
}
|
|
5528
|
+
this.isResubscribeEnqueued = false;
|
|
5529
|
+
this.isTemporarilyUnsubscribedForFlush = false;
|
|
5530
|
+
}
|
|
5531
|
+
runOnce() {
|
|
5532
|
+
this.run();
|
|
5533
|
+
}
|
|
5534
|
+
subscribeToDeps() {
|
|
5535
|
+
if (this.sourceUnsubscribers.length > 0 || this.computedUnsubscribers.length > 0)
|
|
5536
|
+
return;
|
|
5537
|
+
for (const dep of this.sourceDeps) {
|
|
5538
|
+
this.sourceUnsubscribers.push(
|
|
5539
|
+
dep.subscribe(this.onSourceInvalidate)
|
|
5540
|
+
);
|
|
5541
|
+
}
|
|
5542
|
+
for (const dep of this.computedDeps) {
|
|
5543
|
+
this.computedUnsubscribers.push(
|
|
5544
|
+
dep.subscribe(this.onComputedInvalidate)
|
|
5545
|
+
);
|
|
5546
|
+
}
|
|
5547
|
+
}
|
|
5548
|
+
unsubscribeFromSourceDeps() {
|
|
5549
|
+
if (this.sourceUnsubscribers.length === 0) return;
|
|
5550
|
+
for (const unsubscribe of this.sourceUnsubscribers) unsubscribe();
|
|
5551
|
+
this.sourceUnsubscribers = [];
|
|
5552
|
+
}
|
|
5553
|
+
unsubscribeFromAllDeps() {
|
|
5554
|
+
this.unsubscribeFromSourceDeps();
|
|
5555
|
+
if (this.computedUnsubscribers.length === 0) return;
|
|
5556
|
+
for (const unsubscribe of this.computedUnsubscribers) unsubscribe();
|
|
5557
|
+
this.computedUnsubscribers = [];
|
|
5558
|
+
}
|
|
5559
|
+
ensureResubscribeAfterFlush() {
|
|
5560
|
+
if (this.isResubscribeEnqueued) return;
|
|
5561
|
+
this.isResubscribeEnqueued = true;
|
|
5562
|
+
this.dequeueResubscribe = this.runtime.scheduleAfterFlush(
|
|
5563
|
+
this.onAfterFlush
|
|
5564
|
+
);
|
|
5565
|
+
}
|
|
5566
|
+
};
|
|
5567
|
+
|
|
5568
|
+
// src/modules/computed/enums/EOIMComputedEventType.ts
|
|
5569
|
+
var EOIMComputedEventType = /* @__PURE__ */ ((EOIMComputedEventType2) => {
|
|
5570
|
+
EOIMComputedEventType2["UPDATE"] = "update";
|
|
5571
|
+
return EOIMComputedEventType2;
|
|
5572
|
+
})(EOIMComputedEventType || {});
|
|
5573
|
+
|
|
5574
|
+
// src/modules/computed/core/OIMComputed.ts
|
|
5575
|
+
var OIMComputed = class {
|
|
5576
|
+
constructor(runtime, opts) {
|
|
5577
|
+
this.emitter = new OIMEventEmitter();
|
|
5578
|
+
this.hasValue = false;
|
|
5579
|
+
this.isDirty = true;
|
|
5580
|
+
this.runtime = runtime;
|
|
5581
|
+
this.compute = opts.compute;
|
|
5582
|
+
this.compare = opts.compare ?? Object.is;
|
|
5583
|
+
this._deps = opts.deps ?? [];
|
|
5584
|
+
this.updateEventEmitter = new OIMUpdateEventEmitter(
|
|
5585
|
+
this.runtime.queue,
|
|
5586
|
+
"immediate"
|
|
5587
|
+
);
|
|
5588
|
+
const level = this.runtime.computeLevel(this._deps);
|
|
5589
|
+
this.runtime.registerLevel(this, level);
|
|
5590
|
+
this.effect = new OIMEffect(
|
|
5591
|
+
this.runtime,
|
|
5592
|
+
{
|
|
5593
|
+
deps: this._deps,
|
|
5594
|
+
onUpdate: () => {
|
|
5595
|
+
this.isDirty = true;
|
|
5596
|
+
},
|
|
5597
|
+
run: () => {
|
|
5598
|
+
this.recomputeAndEmitIfChanged();
|
|
5599
|
+
}
|
|
5600
|
+
},
|
|
5601
|
+
level
|
|
5602
|
+
);
|
|
5603
|
+
}
|
|
5604
|
+
get needsRecompute() {
|
|
5605
|
+
return this.isDirty;
|
|
5606
|
+
}
|
|
5607
|
+
get isReady() {
|
|
5608
|
+
return this.hasValue;
|
|
5609
|
+
}
|
|
5610
|
+
get deps() {
|
|
5611
|
+
return this._deps;
|
|
5612
|
+
}
|
|
5613
|
+
get() {
|
|
5614
|
+
this.recomputeAndEmitIfChanged();
|
|
5615
|
+
return this.value;
|
|
5616
|
+
}
|
|
5617
|
+
getIfReady() {
|
|
5618
|
+
return this.hasValue ? this.value : void 0;
|
|
5619
|
+
}
|
|
5620
|
+
destroy() {
|
|
5621
|
+
this.effect.destroy();
|
|
5622
|
+
this.updateEventEmitter.destroy();
|
|
5623
|
+
this.emitter.offAll();
|
|
5624
|
+
}
|
|
5625
|
+
recomputeAndEmitIfChanged() {
|
|
5626
|
+
if (!this.isDirty) return;
|
|
5627
|
+
const prev = this.value;
|
|
5628
|
+
const hadPrev = this.hasValue;
|
|
5629
|
+
const next = this.compute();
|
|
5630
|
+
this.value = next;
|
|
5631
|
+
this.hasValue = true;
|
|
5632
|
+
this.isDirty = false;
|
|
5633
|
+
const changed = !hadPrev || !this.compare(prev, next);
|
|
5634
|
+
if (!changed) return;
|
|
5635
|
+
this.emitter.emit("update" /* UPDATE */, {
|
|
5636
|
+
keys: ["value"]
|
|
5637
|
+
});
|
|
5638
|
+
this.updateEventEmitter.markUpdatedKey("value");
|
|
5639
|
+
}
|
|
5640
|
+
};
|
|
5641
|
+
|
|
5642
|
+
// src/dx/OIMCollectionKit.ts
|
|
5643
|
+
function createOIMCollectionKit(queue, opts) {
|
|
5644
|
+
const collection = new OIMReactiveCollection(queue, opts);
|
|
5645
|
+
const indexFactory = new OIMCollectionIndexFactory(queue, collection);
|
|
5646
|
+
const select = new OIMCollectionSelectors(queue, collection);
|
|
5647
|
+
const runtime = getOIMComputeRuntime(queue);
|
|
5648
|
+
const scope = new OIMDisposeScope();
|
|
5649
|
+
scope.add(collection);
|
|
5650
|
+
return {
|
|
5651
|
+
queue,
|
|
5652
|
+
collection,
|
|
5653
|
+
indexFactory,
|
|
5654
|
+
select,
|
|
5655
|
+
on,
|
|
5656
|
+
computed: (deps, compute, options) => {
|
|
5657
|
+
const computed = new OIMComputed(runtime, {
|
|
5658
|
+
deps,
|
|
5659
|
+
compute,
|
|
5660
|
+
compare: options?.compare
|
|
5661
|
+
});
|
|
5662
|
+
scope.add(computed);
|
|
5663
|
+
return computed;
|
|
5664
|
+
},
|
|
5665
|
+
effect: (deps, run, options) => {
|
|
5666
|
+
const effect = new OIMEffect(runtime, {
|
|
5667
|
+
deps,
|
|
5668
|
+
run,
|
|
5669
|
+
onUpdate: options?.onUpdate
|
|
5670
|
+
});
|
|
5671
|
+
scope.add(effect);
|
|
5672
|
+
return effect;
|
|
5673
|
+
},
|
|
5674
|
+
scope,
|
|
5675
|
+
destroy: () => scope.destroy()
|
|
5676
|
+
};
|
|
5677
|
+
}
|
|
5678
|
+
|
|
5679
|
+
// src/dx/peekOIMComputeRuntime.ts
|
|
5680
|
+
function peekOIMComputeRuntime(queue) {
|
|
5681
|
+
const runtime = oimComputeRuntimeByQueue.get(queue);
|
|
5682
|
+
return runtime === void 0 || runtime.isDestroyed ? void 0 : runtime;
|
|
5683
|
+
}
|
|
5684
|
+
|
|
5685
|
+
// src/dx/setOIMComputeRuntime.ts
|
|
5686
|
+
function setOIMComputeRuntime(queue, runtime) {
|
|
5687
|
+
if (runtime.queue !== queue) {
|
|
5688
|
+
throw new Error(
|
|
5689
|
+
"setOIMComputeRuntime: the runtime is attached to a different queue. A runtime drains on its own queue and would never run here."
|
|
5690
|
+
);
|
|
5691
|
+
}
|
|
5692
|
+
oimComputeRuntimeByQueue.set(queue, runtime);
|
|
5693
|
+
}
|
|
5694
|
+
|
|
5695
|
+
// src/modules/wrapper/collection/OIMCollectionChangedFields.ts
|
|
5696
|
+
var OIMCollectionChangedFields = class {
|
|
5697
|
+
constructor(queue, collection, opts) {
|
|
5698
|
+
this.isInWrite = false;
|
|
5699
|
+
this.lastEntitySnapshotByPk = /* @__PURE__ */ new Map();
|
|
5700
|
+
// PKs written through this wrapper during the current flush. Their fields are
|
|
5701
|
+
// already tracked accurately via trackPatch, so the flush-time external-write
|
|
5702
|
+
// handler skips them — no redundant diff + snapshot re-clone. Cleared per flush.
|
|
5703
|
+
this.writtenThroughThisFlush = /* @__PURE__ */ new Set();
|
|
5704
|
+
this.changedFieldsByPk = /* @__PURE__ */ new Map();
|
|
5705
|
+
this.changedPksByField = /* @__PURE__ */ new Map();
|
|
5706
|
+
this.onAfterFlush = () => {
|
|
5707
|
+
this.clear();
|
|
5708
|
+
this.writtenThroughThisFlush.clear();
|
|
5709
|
+
};
|
|
5710
|
+
this.onCollectionUpdate = (payload) => {
|
|
5711
|
+
if (this.isInWrite) return;
|
|
5712
|
+
if (payload.pks.length === 0) return;
|
|
5713
|
+
for (let i = 0; i < payload.pks.length; i++) {
|
|
5714
|
+
const pk = payload.pks[i];
|
|
5715
|
+
if (this.writtenThroughThisFlush.has(pk)) continue;
|
|
5716
|
+
this.trackExternalMutationByPk(pk);
|
|
5717
|
+
}
|
|
5718
|
+
};
|
|
5719
|
+
this.collection = collection;
|
|
5720
|
+
this.detectExternalMutations = opts?.detectExternalMutations !== false;
|
|
5721
|
+
this.selectPk = opts?.selectPk ?? (() => {
|
|
5722
|
+
throw new Error(
|
|
5723
|
+
`[OIMCollectionChangedFields]: selectPk was not provided. Use upsertOneByPk(...) or pass opts.selectPk.`
|
|
5724
|
+
);
|
|
5725
|
+
});
|
|
5726
|
+
this.changedPksEventEmitter = new OIMUpdateEventEmitter(
|
|
5727
|
+
queue,
|
|
5728
|
+
"after_flush"
|
|
5729
|
+
);
|
|
5730
|
+
this.changedFieldsEventEmitter = new OIMUpdateEventEmitter(queue, "after_flush");
|
|
5731
|
+
this.unsubscribeAfterFlush = queue.emitter.on(
|
|
5732
|
+
0 /* AFTER_FLUSH */,
|
|
5733
|
+
this.onAfterFlush
|
|
5734
|
+
);
|
|
5735
|
+
if (this.detectExternalMutations) {
|
|
5736
|
+
const maybeReactive = collection;
|
|
5737
|
+
this.unsubscribeFromCollectionEmitter = maybeReactive.subscribeOnAnyUpdate ? maybeReactive.subscribeOnAnyUpdate((pks) => {
|
|
5738
|
+
this.onCollectionUpdate({
|
|
5739
|
+
pks
|
|
5740
|
+
});
|
|
5741
|
+
}) : collection.emitter.on(
|
|
5742
|
+
0 /* UPDATE */,
|
|
5743
|
+
this.onCollectionUpdate
|
|
5744
|
+
);
|
|
5745
|
+
}
|
|
5746
|
+
}
|
|
5747
|
+
upsertOneByPk(pk, patch) {
|
|
5748
|
+
const slot = this.withWrite(() => {
|
|
5749
|
+
this.trackPatch(pk, patch);
|
|
5750
|
+
return this.collection.upsertOneByPk(pk, patch);
|
|
5751
|
+
});
|
|
5752
|
+
this.updateEntitySnapshot(pk);
|
|
5753
|
+
return slot;
|
|
5754
|
+
}
|
|
5755
|
+
upsertOne(entity) {
|
|
5756
|
+
const slot = this.withWrite(() => {
|
|
5757
|
+
const pk = this.selectPk(entity);
|
|
5758
|
+
this.trackPatch(pk, entity);
|
|
5759
|
+
return this.collection.upsertOne(entity);
|
|
5760
|
+
});
|
|
5761
|
+
this.updateEntitySnapshot(slot.pk);
|
|
5762
|
+
return slot;
|
|
5763
|
+
}
|
|
5764
|
+
upsertMany(entities) {
|
|
5765
|
+
const pks = [];
|
|
5766
|
+
const slots = this.withWrite(() => {
|
|
5767
|
+
for (const entity of entities) {
|
|
5768
|
+
const pk = this.selectPk(entity);
|
|
5769
|
+
pks.push(pk);
|
|
5770
|
+
this.trackPatch(pk, entity);
|
|
5771
|
+
}
|
|
5772
|
+
return this.collection.upsertMany(entities);
|
|
5773
|
+
});
|
|
5774
|
+
for (let i = 0; i < pks.length; i++) this.updateEntitySnapshot(pks[i]);
|
|
5775
|
+
return slots;
|
|
5776
|
+
}
|
|
5777
|
+
getChangedFieldsByPk(pk) {
|
|
5778
|
+
return this.changedFieldsByPk.get(pk) ?? /* @__PURE__ */ new Set();
|
|
5779
|
+
}
|
|
5780
|
+
consumeChangedFieldsByPk(pk) {
|
|
5781
|
+
const existing = this.changedFieldsByPk.get(pk);
|
|
5782
|
+
if (!existing) return /* @__PURE__ */ new Set();
|
|
5783
|
+
return new Set(existing);
|
|
5784
|
+
}
|
|
5785
|
+
getChangedPksByField(field) {
|
|
5786
|
+
return this.changedPksByField.get(field) ?? /* @__PURE__ */ new Set();
|
|
5787
|
+
}
|
|
5788
|
+
consumeChangedPksByField(field) {
|
|
5789
|
+
const existing = this.changedPksByField.get(field);
|
|
5790
|
+
if (!existing) return /* @__PURE__ */ new Set();
|
|
5791
|
+
return new Set(existing);
|
|
5792
|
+
}
|
|
5793
|
+
clear() {
|
|
5794
|
+
this.changedFieldsByPk.clear();
|
|
5795
|
+
this.changedPksByField.clear();
|
|
5796
|
+
}
|
|
5797
|
+
destroy() {
|
|
5798
|
+
this.changedPksEventEmitter.destroy();
|
|
5308
5799
|
this.changedFieldsEventEmitter.destroy();
|
|
5309
5800
|
this.unsubscribeAfterFlush();
|
|
5310
5801
|
this.unsubscribeFromCollectionEmitter?.();
|
|
@@ -5343,8 +5834,9 @@ var OIMCollectionChangedFields = class {
|
|
|
5343
5834
|
Object.keys(nextObj).forEach((k) => keys.add(k));
|
|
5344
5835
|
const changed = [];
|
|
5345
5836
|
keys.forEach((k) => {
|
|
5346
|
-
if (prevObj[k] !== nextObj[k])
|
|
5837
|
+
if (prevObj[k] !== nextObj[k]) {
|
|
5347
5838
|
changed.push(k);
|
|
5839
|
+
}
|
|
5348
5840
|
});
|
|
5349
5841
|
return changed;
|
|
5350
5842
|
}
|
|
@@ -5510,10 +6002,15 @@ var OIMOrderedListMappedCommandStream = class _OIMOrderedListMappedCommandStream
|
|
|
5510
6002
|
try {
|
|
5511
6003
|
const subs = this.subscribers.get(key);
|
|
5512
6004
|
if (subs && subs.size > 0) {
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
6005
|
+
if (subs.size === 1) {
|
|
6006
|
+
const only = subs.values().next().value;
|
|
6007
|
+
if (only) only();
|
|
6008
|
+
} else {
|
|
6009
|
+
const snapshot = Array.from(subs);
|
|
6010
|
+
for (let s = 0; s < snapshot.length; s++) {
|
|
6011
|
+
const handler = snapshot[s];
|
|
6012
|
+
if (subs.has(handler)) handler();
|
|
6013
|
+
}
|
|
5517
6014
|
}
|
|
5518
6015
|
}
|
|
5519
6016
|
} finally {
|
|
@@ -5807,10 +6304,13 @@ var OIMEventQueueSchedulerAnimationFrame = class extends OIMEventQueueScheduler
|
|
|
5807
6304
|
this.flush();
|
|
5808
6305
|
});
|
|
5809
6306
|
} else {
|
|
5810
|
-
this.frameId =
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
6307
|
+
this.frameId = this.unref(
|
|
6308
|
+
setTimeout(() => {
|
|
6309
|
+
this.frameId = void 0;
|
|
6310
|
+
this.flush();
|
|
6311
|
+
}, 16)
|
|
6312
|
+
// ~60fps
|
|
6313
|
+
);
|
|
5814
6314
|
}
|
|
5815
6315
|
}
|
|
5816
6316
|
cancel() {
|
|
@@ -5856,10 +6356,12 @@ var OIMEventQueueSchedulerTimeout = class extends OIMEventQueueScheduler {
|
|
|
5856
6356
|
}
|
|
5857
6357
|
schedule() {
|
|
5858
6358
|
if (this.timeoutId !== void 0) return;
|
|
5859
|
-
this.timeoutId =
|
|
5860
|
-
|
|
5861
|
-
|
|
5862
|
-
|
|
6359
|
+
this.timeoutId = this.unref(
|
|
6360
|
+
setTimeout(() => {
|
|
6361
|
+
this.timeoutId = void 0;
|
|
6362
|
+
this.flush();
|
|
6363
|
+
}, this.delay)
|
|
6364
|
+
);
|
|
5863
6365
|
}
|
|
5864
6366
|
cancel() {
|
|
5865
6367
|
if (this.timeoutId === void 0) return;
|
|
@@ -5893,13 +6395,13 @@ var OIMEventQueueSchedulerImmediate = class extends OIMEventQueueScheduler {
|
|
|
5893
6395
|
this.flush();
|
|
5894
6396
|
};
|
|
5895
6397
|
if (this.useSetImmediate) {
|
|
5896
|
-
this.immediateId = setImmediate(callback);
|
|
6398
|
+
this.immediateId = this.unref(setImmediate(callback));
|
|
5897
6399
|
} else if (this.useMessageChannel && this.messageChannel) {
|
|
5898
6400
|
this.immediateId = 1;
|
|
5899
6401
|
this.pendingCallback = callback;
|
|
5900
6402
|
this.messageChannel.port1.postMessage(null);
|
|
5901
6403
|
} else {
|
|
5902
|
-
this.immediateId = setTimeout(callback, 0);
|
|
6404
|
+
this.immediateId = this.unref(setTimeout(callback, 0));
|
|
5903
6405
|
}
|
|
5904
6406
|
}
|
|
5905
6407
|
cancel() {
|
|
@@ -5992,242 +6494,6 @@ var OIMDBSettings = class {
|
|
|
5992
6494
|
OIMDBSettings.UPDATED_KEYS_INDEX_KEY = "__updatedKeys__";
|
|
5993
6495
|
OIMDBSettings.FLUSHING_KEYS_INDEX_KEY = "__flushingKeys__";
|
|
5994
6496
|
|
|
5995
|
-
// src/modules/effect/core/OIMEffectDependencyComputed.ts
|
|
5996
|
-
var OIMEffectDependencyComputed = class {
|
|
5997
|
-
constructor(source) {
|
|
5998
|
-
this.source = source;
|
|
5999
|
-
}
|
|
6000
|
-
subscribe(onUpdate) {
|
|
6001
|
-
return this.source.emitter.on("update", onUpdate);
|
|
6002
|
-
}
|
|
6003
|
-
};
|
|
6004
|
-
|
|
6005
|
-
// src/modules/effect/core/OIMEffect.ts
|
|
6006
|
-
var OIMEffect = class {
|
|
6007
|
-
constructor(runtime, opts) {
|
|
6008
|
-
this.sourceDeps = [];
|
|
6009
|
-
this.computedDeps = [];
|
|
6010
|
-
this.sourceUnsubscribers = [];
|
|
6011
|
-
this.computedUnsubscribers = [];
|
|
6012
|
-
this.isResubscribeEnqueued = false;
|
|
6013
|
-
this.isTemporarilyUnsubscribedForFlush = false;
|
|
6014
|
-
this.isScheduled = false;
|
|
6015
|
-
this.runTask = () => {
|
|
6016
|
-
this.isScheduled = false;
|
|
6017
|
-
this.dequeueScheduled = void 0;
|
|
6018
|
-
this.runOnce();
|
|
6019
|
-
};
|
|
6020
|
-
this.onSourceInvalidate = () => {
|
|
6021
|
-
this.onUpdate?.();
|
|
6022
|
-
if (!this.isTemporarilyUnsubscribedForFlush) {
|
|
6023
|
-
this.isTemporarilyUnsubscribedForFlush = true;
|
|
6024
|
-
this.unsubscribeFromSourceDeps();
|
|
6025
|
-
this.ensureResubscribeAfterFlush();
|
|
6026
|
-
}
|
|
6027
|
-
if (this.isScheduled) return;
|
|
6028
|
-
this.isScheduled = true;
|
|
6029
|
-
this.dequeueScheduled = this.runtime.schedule(this.runTask);
|
|
6030
|
-
};
|
|
6031
|
-
this.onComputedInvalidate = () => {
|
|
6032
|
-
this.onUpdate?.();
|
|
6033
|
-
if (this.isScheduled) return;
|
|
6034
|
-
this.isScheduled = true;
|
|
6035
|
-
this.dequeueScheduled = this.runtime.schedule(this.runTask);
|
|
6036
|
-
};
|
|
6037
|
-
this.onAfterFlush = () => {
|
|
6038
|
-
if (!this.isResubscribeEnqueued) return;
|
|
6039
|
-
this.isResubscribeEnqueued = false;
|
|
6040
|
-
this.dequeueResubscribe = void 0;
|
|
6041
|
-
this.isTemporarilyUnsubscribedForFlush = false;
|
|
6042
|
-
if (this.sourceUnsubscribers.length === 0) {
|
|
6043
|
-
for (const dep of this.sourceDeps) {
|
|
6044
|
-
this.sourceUnsubscribers.push(
|
|
6045
|
-
dep.subscribe(this.onSourceInvalidate)
|
|
6046
|
-
);
|
|
6047
|
-
}
|
|
6048
|
-
}
|
|
6049
|
-
};
|
|
6050
|
-
this.runtime = runtime;
|
|
6051
|
-
this.onUpdate = opts.onUpdate;
|
|
6052
|
-
this.run = opts.run;
|
|
6053
|
-
this.deps = opts.deps ?? [];
|
|
6054
|
-
for (const dep of this.deps) {
|
|
6055
|
-
if (dep instanceof OIMEffectDependencyComputed) {
|
|
6056
|
-
this.computedDeps.push(dep);
|
|
6057
|
-
} else {
|
|
6058
|
-
this.sourceDeps.push(dep);
|
|
6059
|
-
}
|
|
6060
|
-
}
|
|
6061
|
-
this.subscribeToDeps();
|
|
6062
|
-
}
|
|
6063
|
-
destroy() {
|
|
6064
|
-
if (this.dequeueScheduled) {
|
|
6065
|
-
this.dequeueScheduled();
|
|
6066
|
-
this.dequeueScheduled = void 0;
|
|
6067
|
-
}
|
|
6068
|
-
this.unsubscribeFromAllDeps();
|
|
6069
|
-
if (this.dequeueResubscribe) {
|
|
6070
|
-
this.dequeueResubscribe();
|
|
6071
|
-
this.dequeueResubscribe = void 0;
|
|
6072
|
-
}
|
|
6073
|
-
this.isResubscribeEnqueued = false;
|
|
6074
|
-
this.isTemporarilyUnsubscribedForFlush = false;
|
|
6075
|
-
}
|
|
6076
|
-
runOnce() {
|
|
6077
|
-
this.run();
|
|
6078
|
-
}
|
|
6079
|
-
subscribeToDeps() {
|
|
6080
|
-
if (this.sourceUnsubscribers.length > 0 || this.computedUnsubscribers.length > 0)
|
|
6081
|
-
return;
|
|
6082
|
-
for (const dep of this.sourceDeps) {
|
|
6083
|
-
this.sourceUnsubscribers.push(
|
|
6084
|
-
dep.subscribe(this.onSourceInvalidate)
|
|
6085
|
-
);
|
|
6086
|
-
}
|
|
6087
|
-
for (const dep of this.computedDeps) {
|
|
6088
|
-
this.computedUnsubscribers.push(
|
|
6089
|
-
dep.subscribe(this.onComputedInvalidate)
|
|
6090
|
-
);
|
|
6091
|
-
}
|
|
6092
|
-
}
|
|
6093
|
-
unsubscribeFromSourceDeps() {
|
|
6094
|
-
if (this.sourceUnsubscribers.length === 0) return;
|
|
6095
|
-
for (const unsubscribe of this.sourceUnsubscribers) unsubscribe();
|
|
6096
|
-
this.sourceUnsubscribers = [];
|
|
6097
|
-
}
|
|
6098
|
-
unsubscribeFromAllDeps() {
|
|
6099
|
-
this.unsubscribeFromSourceDeps();
|
|
6100
|
-
if (this.computedUnsubscribers.length === 0) return;
|
|
6101
|
-
for (const unsubscribe of this.computedUnsubscribers) unsubscribe();
|
|
6102
|
-
this.computedUnsubscribers = [];
|
|
6103
|
-
}
|
|
6104
|
-
ensureResubscribeAfterFlush() {
|
|
6105
|
-
if (this.isResubscribeEnqueued) return;
|
|
6106
|
-
this.isResubscribeEnqueued = true;
|
|
6107
|
-
this.dequeueResubscribe = this.runtime.scheduleAfterFlush(
|
|
6108
|
-
this.onAfterFlush
|
|
6109
|
-
);
|
|
6110
|
-
}
|
|
6111
|
-
};
|
|
6112
|
-
|
|
6113
|
-
// src/modules/computed/enums/EOIMComputedEventType.ts
|
|
6114
|
-
var EOIMComputedEventType = /* @__PURE__ */ ((EOIMComputedEventType2) => {
|
|
6115
|
-
EOIMComputedEventType2["UPDATE"] = "update";
|
|
6116
|
-
return EOIMComputedEventType2;
|
|
6117
|
-
})(EOIMComputedEventType || {});
|
|
6118
|
-
|
|
6119
|
-
// src/modules/computed/core/OIMComputed.ts
|
|
6120
|
-
var OIMComputed = class {
|
|
6121
|
-
constructor(runtime, opts) {
|
|
6122
|
-
this.emitter = new OIMEventEmitter();
|
|
6123
|
-
this.hasValue = false;
|
|
6124
|
-
this.isDirty = true;
|
|
6125
|
-
this.runtime = runtime;
|
|
6126
|
-
this.compute = opts.compute;
|
|
6127
|
-
this.compare = opts.compare ?? Object.is;
|
|
6128
|
-
this._deps = opts.deps ?? [];
|
|
6129
|
-
this.updateEventEmitter = new OIMUpdateEventEmitter(
|
|
6130
|
-
this.runtime.queue,
|
|
6131
|
-
"immediate"
|
|
6132
|
-
);
|
|
6133
|
-
this.effect = new OIMEffect(this.runtime, {
|
|
6134
|
-
deps: this._deps,
|
|
6135
|
-
onUpdate: () => {
|
|
6136
|
-
this.isDirty = true;
|
|
6137
|
-
},
|
|
6138
|
-
run: () => {
|
|
6139
|
-
this.recomputeAndEmitIfChanged();
|
|
6140
|
-
}
|
|
6141
|
-
});
|
|
6142
|
-
}
|
|
6143
|
-
get needsRecompute() {
|
|
6144
|
-
return this.isDirty;
|
|
6145
|
-
}
|
|
6146
|
-
get isReady() {
|
|
6147
|
-
return this.hasValue;
|
|
6148
|
-
}
|
|
6149
|
-
get deps() {
|
|
6150
|
-
return this._deps;
|
|
6151
|
-
}
|
|
6152
|
-
get() {
|
|
6153
|
-
this.recomputeAndEmitIfChanged();
|
|
6154
|
-
return this.value;
|
|
6155
|
-
}
|
|
6156
|
-
getIfReady() {
|
|
6157
|
-
return this.hasValue ? this.value : void 0;
|
|
6158
|
-
}
|
|
6159
|
-
destroy() {
|
|
6160
|
-
this.effect.destroy();
|
|
6161
|
-
this.updateEventEmitter.destroy();
|
|
6162
|
-
this.emitter.offAll();
|
|
6163
|
-
}
|
|
6164
|
-
recomputeAndEmitIfChanged() {
|
|
6165
|
-
if (!this.isDirty) return;
|
|
6166
|
-
const prev = this.value;
|
|
6167
|
-
const hadPrev = this.hasValue;
|
|
6168
|
-
const next = this.compute();
|
|
6169
|
-
this.value = next;
|
|
6170
|
-
this.hasValue = true;
|
|
6171
|
-
this.isDirty = false;
|
|
6172
|
-
const changed = !hadPrev || !this.compare(prev, next);
|
|
6173
|
-
if (!changed) return;
|
|
6174
|
-
this.emitter.emit("update" /* UPDATE */, {
|
|
6175
|
-
keys: ["value"]
|
|
6176
|
-
});
|
|
6177
|
-
this.updateEventEmitter.markUpdatedKey("value");
|
|
6178
|
-
}
|
|
6179
|
-
};
|
|
6180
|
-
|
|
6181
|
-
// src/modules/effect/core/OIMEffectDependencyKeyed.ts
|
|
6182
|
-
var OIMEffectDependencyKeyed = class {
|
|
6183
|
-
constructor(source, key) {
|
|
6184
|
-
this.source = source;
|
|
6185
|
-
this.key = key;
|
|
6186
|
-
}
|
|
6187
|
-
subscribe(onUpdate) {
|
|
6188
|
-
return this.source.subscribeOnKey(this.key, onUpdate);
|
|
6189
|
-
}
|
|
6190
|
-
};
|
|
6191
|
-
|
|
6192
|
-
// src/modules/effect/core/OIMEffectDependencyKeyedObject.ts
|
|
6193
|
-
var OIMEffectDependencyKeyedObject = class {
|
|
6194
|
-
constructor(object, key) {
|
|
6195
|
-
this.dep = new OIMEffectDependencyKeyed(object, key);
|
|
6196
|
-
}
|
|
6197
|
-
get source() {
|
|
6198
|
-
return this.dep.source;
|
|
6199
|
-
}
|
|
6200
|
-
subscribe(onUpdate) {
|
|
6201
|
-
return this.dep.subscribe(onUpdate);
|
|
6202
|
-
}
|
|
6203
|
-
};
|
|
6204
|
-
|
|
6205
|
-
// src/modules/effect/core/OIMEffectDependencyKeyedCollection.ts
|
|
6206
|
-
var OIMEffectDependencyKeyedCollection = class {
|
|
6207
|
-
constructor(collection, pk) {
|
|
6208
|
-
this.dep = new OIMEffectDependencyKeyed(collection, pk);
|
|
6209
|
-
}
|
|
6210
|
-
get source() {
|
|
6211
|
-
return this.dep.source;
|
|
6212
|
-
}
|
|
6213
|
-
subscribe(onUpdate) {
|
|
6214
|
-
return this.dep.subscribe(onUpdate);
|
|
6215
|
-
}
|
|
6216
|
-
};
|
|
6217
|
-
|
|
6218
|
-
// src/modules/effect/core/OIMEffectDependencyKeyedIndex.ts
|
|
6219
|
-
var OIMEffectDependencyKeyedIndex = class {
|
|
6220
|
-
constructor(index, key) {
|
|
6221
|
-
this.dep = new OIMEffectDependencyKeyed(index, key);
|
|
6222
|
-
}
|
|
6223
|
-
get source() {
|
|
6224
|
-
return this.dep.source;
|
|
6225
|
-
}
|
|
6226
|
-
subscribe(onUpdate) {
|
|
6227
|
-
return this.dep.subscribe(onUpdate);
|
|
6228
|
-
}
|
|
6229
|
-
};
|
|
6230
|
-
|
|
6231
6497
|
// src/modules/selector/core/OIMObjectValueByKeySelector.ts
|
|
6232
6498
|
var OIMObjectValueByKeySelector = class extends OIMSelector {
|
|
6233
6499
|
constructor(runtime, obj, key) {
|
|
@@ -6305,8 +6571,9 @@ var OIMIndexPksByKeyArrayBasedSelector = class extends OIMSelector {
|
|
|
6305
6571
|
areEqual(prev, next) {
|
|
6306
6572
|
if (prev === next) return true;
|
|
6307
6573
|
if (prev.length !== next.length) return false;
|
|
6308
|
-
for (let i = 0; i < prev.length; i++)
|
|
6574
|
+
for (let i = 0; i < prev.length; i++) {
|
|
6309
6575
|
if (prev[i] !== next[i]) return false;
|
|
6576
|
+
}
|
|
6310
6577
|
return true;
|
|
6311
6578
|
}
|
|
6312
6579
|
};
|
|
@@ -6329,8 +6596,9 @@ var OIMIndexPksByKeysSetBasedSelector = class extends OIMSelector {
|
|
|
6329
6596
|
areEqual(prev, next) {
|
|
6330
6597
|
if (prev === next) return true;
|
|
6331
6598
|
if (prev.length !== next.length) return false;
|
|
6332
|
-
for (let i = 0; i < prev.length; i++)
|
|
6599
|
+
for (let i = 0; i < prev.length; i++) {
|
|
6333
6600
|
if (prev[i] !== next[i]) return false;
|
|
6601
|
+
}
|
|
6334
6602
|
return true;
|
|
6335
6603
|
}
|
|
6336
6604
|
};
|
|
@@ -6353,8 +6621,9 @@ var OIMIndexPksByKeysArrayBasedSelector = class extends OIMSelector {
|
|
|
6353
6621
|
areEqual(prev, next) {
|
|
6354
6622
|
if (prev === next) return true;
|
|
6355
6623
|
if (prev.length !== next.length) return false;
|
|
6356
|
-
for (let i = 0; i < prev.length; i++)
|
|
6624
|
+
for (let i = 0; i < prev.length; i++) {
|
|
6357
6625
|
if (prev[i] !== next[i]) return false;
|
|
6626
|
+
}
|
|
6358
6627
|
return true;
|
|
6359
6628
|
}
|
|
6360
6629
|
};
|
|
@@ -6383,6 +6652,7 @@ export {
|
|
|
6383
6652
|
OIMComputeRuntime,
|
|
6384
6653
|
OIMComputed,
|
|
6385
6654
|
OIMDBSettings,
|
|
6655
|
+
OIMDerivedCollection,
|
|
6386
6656
|
OIMDerivedCollectionGlobalIndexArrayBased,
|
|
6387
6657
|
OIMDerivedCollectionGlobalIndexSetBased,
|
|
6388
6658
|
OIMDerivedCollectionIndexArrayBased,
|
|
@@ -6478,5 +6748,9 @@ export {
|
|
|
6478
6748
|
createOIMIndexSlotMap,
|
|
6479
6749
|
createOIMOrderedListCommandStreamDiffDriven,
|
|
6480
6750
|
createOIMOrderedListMappedCommandStream,
|
|
6481
|
-
diffOrderedListByPk
|
|
6751
|
+
diffOrderedListByPk,
|
|
6752
|
+
getOIMComputeRuntime,
|
|
6753
|
+
on,
|
|
6754
|
+
peekOIMComputeRuntime,
|
|
6755
|
+
setOIMComputeRuntime
|
|
6482
6756
|
};
|