@arcote.tech/arc-adapter-db-sqlite 0.7.14 → 0.7.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +203 -256
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1487,12 +1487,13 @@ class EventWire {
|
|
|
1487
1487
|
onSyncedCallback;
|
|
1488
1488
|
reconnectTimeout;
|
|
1489
1489
|
syncRequested = false;
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
constructor(baseUrl) {
|
|
1490
|
+
querySubscriptions = new Map;
|
|
1491
|
+
querySubCounter = 0;
|
|
1492
|
+
enableEventSync;
|
|
1493
|
+
constructor(baseUrl, options) {
|
|
1494
1494
|
this.baseUrl = baseUrl;
|
|
1495
1495
|
this.instanceId = ++eventWireInstanceCounter;
|
|
1496
|
+
this.enableEventSync = options?.enableEventSync ?? true;
|
|
1496
1497
|
}
|
|
1497
1498
|
setScopeToken(scope, token) {
|
|
1498
1499
|
if (token === null) {
|
|
@@ -1538,9 +1539,11 @@ class EventWire {
|
|
|
1538
1539
|
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
1539
1540
|
this.state = "connected";
|
|
1540
1541
|
this.sendAllScopeTokens();
|
|
1541
|
-
this.
|
|
1542
|
+
if (this.enableEventSync) {
|
|
1543
|
+
this.requestSync();
|
|
1544
|
+
}
|
|
1542
1545
|
this.flushPendingEvents();
|
|
1543
|
-
this.
|
|
1546
|
+
this.sendAllQuerySubscriptions();
|
|
1544
1547
|
} else {
|
|
1545
1548
|
console.log(`[EventWire] onopen called but ws is not OPEN, readyState:`, this.ws?.readyState);
|
|
1546
1549
|
}
|
|
@@ -1616,9 +1619,13 @@ class EventWire {
|
|
|
1616
1619
|
onSynced(callback) {
|
|
1617
1620
|
this.onSyncedCallback = callback;
|
|
1618
1621
|
}
|
|
1619
|
-
subscribeQuery(descriptor,
|
|
1620
|
-
const subscriptionId = `qs_${
|
|
1621
|
-
this.
|
|
1622
|
+
subscribeQuery(descriptor, scope, callbacks) {
|
|
1623
|
+
const subscriptionId = `qs_${this.instanceId}_${++this.querySubCounter}`;
|
|
1624
|
+
this.querySubscriptions.set(subscriptionId, {
|
|
1625
|
+
descriptor,
|
|
1626
|
+
scope,
|
|
1627
|
+
callbacks
|
|
1628
|
+
});
|
|
1622
1629
|
if (this.state === "connected" && this.ws) {
|
|
1623
1630
|
this.ws.send(JSON.stringify({
|
|
1624
1631
|
type: "subscribe-query",
|
|
@@ -1626,20 +1633,17 @@ class EventWire {
|
|
|
1626
1633
|
descriptor,
|
|
1627
1634
|
scope
|
|
1628
1635
|
}));
|
|
1629
|
-
} else {
|
|
1630
|
-
this.pendingViewSubs.push({ subscriptionId, descriptor, scope });
|
|
1631
1636
|
}
|
|
1632
1637
|
return subscriptionId;
|
|
1633
1638
|
}
|
|
1634
1639
|
unsubscribeQuery(subscriptionId) {
|
|
1635
|
-
this.
|
|
1640
|
+
this.querySubscriptions.delete(subscriptionId);
|
|
1636
1641
|
if (this.state === "connected" && this.ws) {
|
|
1637
1642
|
this.ws.send(JSON.stringify({
|
|
1638
1643
|
type: "unsubscribe-query",
|
|
1639
1644
|
subscriptionId
|
|
1640
1645
|
}));
|
|
1641
1646
|
}
|
|
1642
|
-
this.pendingViewSubs = this.pendingViewSubs.filter((s) => s.subscriptionId !== subscriptionId);
|
|
1643
1647
|
}
|
|
1644
1648
|
getState() {
|
|
1645
1649
|
return this.state;
|
|
@@ -1672,10 +1676,17 @@ class EventWire {
|
|
|
1672
1676
|
this.lastHostEventId = message.lastHostEventId;
|
|
1673
1677
|
}
|
|
1674
1678
|
break;
|
|
1675
|
-
case "query-
|
|
1676
|
-
const
|
|
1677
|
-
if (
|
|
1678
|
-
|
|
1679
|
+
case "query-snapshot": {
|
|
1680
|
+
const sub = this.querySubscriptions.get(message.subscriptionId);
|
|
1681
|
+
if (sub) {
|
|
1682
|
+
sub.callbacks.onSnapshot(message.result ?? null);
|
|
1683
|
+
}
|
|
1684
|
+
break;
|
|
1685
|
+
}
|
|
1686
|
+
case "query-changes": {
|
|
1687
|
+
const sub = this.querySubscriptions.get(message.subscriptionId);
|
|
1688
|
+
if (sub && Array.isArray(message.changes)) {
|
|
1689
|
+
sub.callbacks.onChanges(message.changes);
|
|
1679
1690
|
}
|
|
1680
1691
|
break;
|
|
1681
1692
|
}
|
|
@@ -1703,18 +1714,17 @@ class EventWire {
|
|
|
1703
1714
|
this.pendingEvents = [];
|
|
1704
1715
|
}
|
|
1705
1716
|
}
|
|
1706
|
-
|
|
1717
|
+
sendAllQuerySubscriptions() {
|
|
1707
1718
|
if (!this.ws || this.state !== "connected")
|
|
1708
1719
|
return;
|
|
1709
|
-
for (const sub of this.
|
|
1720
|
+
for (const [subscriptionId, sub] of this.querySubscriptions) {
|
|
1710
1721
|
this.ws.send(JSON.stringify({
|
|
1711
1722
|
type: "subscribe-query",
|
|
1712
|
-
subscriptionId
|
|
1723
|
+
subscriptionId,
|
|
1713
1724
|
descriptor: sub.descriptor,
|
|
1714
1725
|
scope: sub.scope
|
|
1715
1726
|
}));
|
|
1716
1727
|
}
|
|
1717
|
-
this.pendingViewSubs = [];
|
|
1718
1728
|
}
|
|
1719
1729
|
scheduleReconnect() {
|
|
1720
1730
|
if (this.reconnectTimeout)
|
|
@@ -3541,6 +3551,48 @@ function deepMerge(target, source) {
|
|
|
3541
3551
|
function isPlainObject(item) {
|
|
3542
3552
|
return item && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && Object.prototype.toString.call(item) === "[object Object]";
|
|
3543
3553
|
}
|
|
3554
|
+
function murmurHash(key, seed = 0) {
|
|
3555
|
+
let remainder, bytes, h1, h1b, c1, c2, k1, i;
|
|
3556
|
+
remainder = key.length & 3;
|
|
3557
|
+
bytes = key.length - remainder;
|
|
3558
|
+
h1 = seed;
|
|
3559
|
+
c1 = 3432918353;
|
|
3560
|
+
c2 = 461845907;
|
|
3561
|
+
i = 0;
|
|
3562
|
+
while (i < bytes) {
|
|
3563
|
+
k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
|
|
3564
|
+
++i;
|
|
3565
|
+
k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
|
|
3566
|
+
k1 = k1 << 15 | k1 >>> 17;
|
|
3567
|
+
k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
|
|
3568
|
+
h1 ^= k1;
|
|
3569
|
+
h1 = h1 << 13 | h1 >>> 19;
|
|
3570
|
+
h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
|
|
3571
|
+
h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
|
|
3572
|
+
}
|
|
3573
|
+
k1 = 0;
|
|
3574
|
+
if (remainder >= 3) {
|
|
3575
|
+
k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
|
|
3576
|
+
}
|
|
3577
|
+
if (remainder >= 2) {
|
|
3578
|
+
k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
|
|
3579
|
+
}
|
|
3580
|
+
if (remainder >= 1) {
|
|
3581
|
+
k1 ^= key.charCodeAt(i) & 255;
|
|
3582
|
+
k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
|
|
3583
|
+
k1 = k1 << 15 | k1 >>> 17;
|
|
3584
|
+
k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
|
|
3585
|
+
h1 ^= k1;
|
|
3586
|
+
}
|
|
3587
|
+
h1 ^= key.length;
|
|
3588
|
+
h1 ^= h1 >>> 16;
|
|
3589
|
+
h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
|
|
3590
|
+
h1 ^= h1 >>> 13;
|
|
3591
|
+
h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
|
|
3592
|
+
h1 ^= h1 >>> 16;
|
|
3593
|
+
return h1 >>> 0;
|
|
3594
|
+
}
|
|
3595
|
+
|
|
3544
3596
|
class ForkedStoreState extends StoreState {
|
|
3545
3597
|
master;
|
|
3546
3598
|
changedItems = new Map;
|
|
@@ -3689,12 +3741,19 @@ class MasterStoreState extends StoreState {
|
|
|
3689
3741
|
constructor(storeName, dataStorage, deserialize) {
|
|
3690
3742
|
super(storeName, dataStorage, deserialize);
|
|
3691
3743
|
}
|
|
3744
|
+
async readExisting(transaction, id2, transactionCache) {
|
|
3745
|
+
const cacheKey = `${this.storeName}:${id2}`;
|
|
3746
|
+
if (transactionCache && transactionCache.has(cacheKey)) {
|
|
3747
|
+
return transactionCache.get(cacheKey);
|
|
3748
|
+
}
|
|
3749
|
+
return transaction.find(this.storeName, { where: { _id: id2 } }).then((results) => results[0]);
|
|
3750
|
+
}
|
|
3692
3751
|
async applyChangeAndReturnEvent(transaction, change, transactionCache) {
|
|
3693
3752
|
if (change.type === "set") {
|
|
3694
3753
|
await transaction.set(this.storeName, change.data);
|
|
3695
3754
|
const item = this.deserialize ? this.deserialize(change.data) : change.data;
|
|
3696
3755
|
if (transactionCache) {
|
|
3697
|
-
transactionCache.set(change.data._id
|
|
3756
|
+
transactionCache.set(`${this.storeName}:${change.data._id}`, item);
|
|
3698
3757
|
}
|
|
3699
3758
|
return {
|
|
3700
3759
|
from: null,
|
|
@@ -3708,6 +3767,9 @@ class MasterStoreState extends StoreState {
|
|
|
3708
3767
|
}
|
|
3709
3768
|
if (change.type === "delete") {
|
|
3710
3769
|
await transaction.remove(this.storeName, change.id);
|
|
3770
|
+
if (transactionCache) {
|
|
3771
|
+
transactionCache.delete(`${this.storeName}:${change.id}`);
|
|
3772
|
+
}
|
|
3711
3773
|
return {
|
|
3712
3774
|
from: null,
|
|
3713
3775
|
to: null,
|
|
@@ -3719,17 +3781,12 @@ class MasterStoreState extends StoreState {
|
|
|
3719
3781
|
};
|
|
3720
3782
|
}
|
|
3721
3783
|
if (change.type === "modify") {
|
|
3722
|
-
|
|
3723
|
-
if (transactionCache && transactionCache.has(change.id)) {
|
|
3724
|
-
existing = transactionCache.get(change.id);
|
|
3725
|
-
} else {
|
|
3726
|
-
existing = await transaction.find(this.storeName, { where: { _id: change.id } }).then((results) => results[0]);
|
|
3727
|
-
}
|
|
3784
|
+
const existing = await this.readExisting(transaction, change.id, transactionCache);
|
|
3728
3785
|
const updated = existing ? deepMerge(existing, change.data) : { _id: change.id, ...change.data };
|
|
3729
3786
|
await transaction.set(this.storeName, updated);
|
|
3730
3787
|
const item = this.deserialize ? this.deserialize(updated) : updated;
|
|
3731
3788
|
if (transactionCache) {
|
|
3732
|
-
transactionCache.set(change.id
|
|
3789
|
+
transactionCache.set(`${this.storeName}:${change.id}`, item);
|
|
3733
3790
|
}
|
|
3734
3791
|
return {
|
|
3735
3792
|
from: null,
|
|
@@ -3742,17 +3799,12 @@ class MasterStoreState extends StoreState {
|
|
|
3742
3799
|
};
|
|
3743
3800
|
}
|
|
3744
3801
|
if (change.type === "mutate") {
|
|
3745
|
-
|
|
3746
|
-
if (transactionCache && transactionCache.has(change.id)) {
|
|
3747
|
-
existing = transactionCache.get(change.id);
|
|
3748
|
-
} else {
|
|
3749
|
-
existing = await transaction.find(this.storeName, { where: { _id: change.id } }).then((results) => results[0]);
|
|
3750
|
-
}
|
|
3802
|
+
const existing = await this.readExisting(transaction, change.id, transactionCache);
|
|
3751
3803
|
const updated = apply(existing || {}, change.patches);
|
|
3752
3804
|
await transaction.set(this.storeName, updated);
|
|
3753
3805
|
const item = this.deserialize ? this.deserialize(updated) : updated;
|
|
3754
3806
|
if (transactionCache) {
|
|
3755
|
-
transactionCache.set(change.id
|
|
3807
|
+
transactionCache.set(`${this.storeName}:${change.id}`, item);
|
|
3756
3808
|
}
|
|
3757
3809
|
return {
|
|
3758
3810
|
from: null,
|
|
@@ -3988,7 +4040,8 @@ class ObservableDataStorage {
|
|
|
3988
4040
|
}
|
|
3989
4041
|
handleStoreChange(storeName, events) {
|
|
3990
4042
|
let hasChanges = false;
|
|
3991
|
-
|
|
4043
|
+
const staleKeys = [];
|
|
4044
|
+
for (const [key, query] of this.trackedQueries) {
|
|
3992
4045
|
if (query.storeName !== storeName)
|
|
3993
4046
|
continue;
|
|
3994
4047
|
let currentResult = query.result;
|
|
@@ -4000,10 +4053,20 @@ class ObservableDataStorage {
|
|
|
4000
4053
|
queryChanged = true;
|
|
4001
4054
|
}
|
|
4002
4055
|
}
|
|
4003
|
-
if (queryChanged)
|
|
4004
|
-
|
|
4056
|
+
if (!queryChanged)
|
|
4057
|
+
continue;
|
|
4058
|
+
if (query.options.limit !== undefined && query.result.length === query.options.limit && currentResult.length < query.options.limit) {
|
|
4059
|
+
staleKeys.push(key);
|
|
4005
4060
|
hasChanges = true;
|
|
4061
|
+
continue;
|
|
4006
4062
|
}
|
|
4063
|
+
query.result = currentResult;
|
|
4064
|
+
hasChanges = true;
|
|
4065
|
+
}
|
|
4066
|
+
for (const key of staleKeys) {
|
|
4067
|
+
const query = this.trackedQueries.get(key);
|
|
4068
|
+
this.source.getStore(query.storeName).unsubscribe(query.listener);
|
|
4069
|
+
this.trackedQueries.delete(key);
|
|
4007
4070
|
}
|
|
4008
4071
|
if (hasChanges) {
|
|
4009
4072
|
this.onChange();
|
|
@@ -4219,13 +4282,6 @@ class ScopedModel {
|
|
|
4219
4282
|
}
|
|
4220
4283
|
return wire.query(viewName, options, this.getAuth());
|
|
4221
4284
|
}
|
|
4222
|
-
subscribeQuery(descriptor, callback) {
|
|
4223
|
-
const wire = this.parent.getAdapters().eventWire;
|
|
4224
|
-
if (!wire) {
|
|
4225
|
-
throw new Error(`Cannot subscribe to query: no eventWire available.`);
|
|
4226
|
-
}
|
|
4227
|
-
return wire.subscribeQuery(descriptor, callback, this.scopeName);
|
|
4228
|
-
}
|
|
4229
4285
|
get query() {
|
|
4230
4286
|
return buildContextAccessor(this.context, this.scopedAdapters, "queryContext", (descriptor) => descriptor);
|
|
4231
4287
|
}
|
|
@@ -4281,244 +4337,135 @@ class Model {
|
|
|
4281
4337
|
return s;
|
|
4282
4338
|
}
|
|
4283
4339
|
}
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
registerViews(views) {
|
|
4292
|
-
this.views = views;
|
|
4293
|
-
for (const view3 of views) {
|
|
4294
|
-
if (!this.stores.has(view3.name)) {
|
|
4295
|
-
this.stores.set(view3.name, new StreamingStore);
|
|
4296
|
-
}
|
|
4340
|
+
function applyQueryChanges(result, changes) {
|
|
4341
|
+
const next = [...result];
|
|
4342
|
+
for (const change of changes) {
|
|
4343
|
+
if (change.type === "delete") {
|
|
4344
|
+
const idx = next.findIndex((it) => it._id === change.id);
|
|
4345
|
+
if (idx !== -1)
|
|
4346
|
+
next.splice(idx, 1);
|
|
4297
4347
|
}
|
|
4298
4348
|
}
|
|
4299
|
-
|
|
4300
|
-
if (
|
|
4301
|
-
|
|
4349
|
+
for (const change of changes) {
|
|
4350
|
+
if (change.type === "set") {
|
|
4351
|
+
const idx = next.findIndex((it) => it._id === change.id);
|
|
4352
|
+
if (idx !== -1)
|
|
4353
|
+
next.splice(idx, 1);
|
|
4354
|
+
next.splice(change.index, 0, change.item);
|
|
4302
4355
|
}
|
|
4303
|
-
return this.stores.get(viewName);
|
|
4304
|
-
}
|
|
4305
|
-
hasData(viewName) {
|
|
4306
|
-
const store = this.stores.get(viewName);
|
|
4307
|
-
return store ? store.hasData() : false;
|
|
4308
|
-
}
|
|
4309
|
-
hasActiveStream(viewName) {
|
|
4310
|
-
return this.activeStreams.has(viewName);
|
|
4311
4356
|
}
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4357
|
+
return next;
|
|
4358
|
+
}
|
|
4359
|
+
class StreamingQueryCache {
|
|
4360
|
+
entries = new Map;
|
|
4361
|
+
static UNSUBSCRIBE_DELAY_MS = 5000;
|
|
4362
|
+
entryKey(descriptor, scope) {
|
|
4363
|
+
return `${scope ?? "default"}:${murmurHash(JSON.stringify(descriptor))}`;
|
|
4364
|
+
}
|
|
4365
|
+
subscribe(descriptor, scope, eventWire, onChange) {
|
|
4366
|
+
const key = this.entryKey(descriptor, scope);
|
|
4367
|
+
let entry = this.entries.get(key);
|
|
4368
|
+
if (entry) {
|
|
4369
|
+
if (entry.pendingUnsub) {
|
|
4370
|
+
clearTimeout(entry.pendingUnsub);
|
|
4371
|
+
entry.pendingUnsub = undefined;
|
|
4372
|
+
}
|
|
4373
|
+
entry.refCount++;
|
|
4374
|
+
} else {
|
|
4375
|
+
const newEntry = {
|
|
4376
|
+
result: undefined,
|
|
4377
|
+
hasResult: false,
|
|
4378
|
+
listeners: new Set,
|
|
4379
|
+
refCount: 1,
|
|
4380
|
+
subscriptionId: ""
|
|
4324
4381
|
};
|
|
4382
|
+
newEntry.subscriptionId = eventWire.subscribeQuery(descriptor, scope, {
|
|
4383
|
+
onSnapshot: (result) => {
|
|
4384
|
+
newEntry.result = result;
|
|
4385
|
+
newEntry.hasResult = true;
|
|
4386
|
+
this.notify(newEntry);
|
|
4387
|
+
},
|
|
4388
|
+
onChanges: (changes) => {
|
|
4389
|
+
if (!newEntry.hasResult || !Array.isArray(newEntry.result)) {
|
|
4390
|
+
return;
|
|
4391
|
+
}
|
|
4392
|
+
newEntry.result = applyQueryChanges(newEntry.result, changes);
|
|
4393
|
+
this.notify(newEntry);
|
|
4394
|
+
}
|
|
4395
|
+
});
|
|
4396
|
+
this.entries.set(key, newEntry);
|
|
4397
|
+
entry = newEntry;
|
|
4325
4398
|
}
|
|
4326
|
-
const
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
refCount: 1
|
|
4330
|
-
});
|
|
4399
|
+
const subscribed = entry;
|
|
4400
|
+
subscribed.listeners.add(onChange);
|
|
4401
|
+
let active = true;
|
|
4331
4402
|
return {
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
this.pendingUnsubscribes.set(viewName, timeout);
|
|
4352
|
-
}
|
|
4353
|
-
}
|
|
4354
|
-
subscribeQuery(descriptor, eventWire, scope) {
|
|
4355
|
-
const key = descriptor.element;
|
|
4356
|
-
if (scope)
|
|
4357
|
-
this.streamScopes.set(key, scope);
|
|
4358
|
-
const { unsubscribe } = this.registerStream(key, () => {
|
|
4359
|
-
const subId = eventWire.subscribeQuery(descriptor, (data) => {
|
|
4360
|
-
this.setViewData(descriptor.element, data);
|
|
4361
|
-
}, scope);
|
|
4362
|
-
return { unsubscribe: () => eventWire.unsubscribeQuery(subId) };
|
|
4363
|
-
});
|
|
4364
|
-
return unsubscribe;
|
|
4365
|
-
}
|
|
4366
|
-
invalidateScope(scope) {
|
|
4367
|
-
for (const [viewName, viewScope] of this.streamScopes) {
|
|
4368
|
-
if (viewScope !== scope)
|
|
4369
|
-
continue;
|
|
4370
|
-
const pending = this.pendingUnsubscribes.get(viewName);
|
|
4371
|
-
if (pending) {
|
|
4372
|
-
clearTimeout(pending);
|
|
4373
|
-
this.pendingUnsubscribes.delete(viewName);
|
|
4403
|
+
read: () => ({
|
|
4404
|
+
result: subscribed.result,
|
|
4405
|
+
loading: !subscribed.hasResult
|
|
4406
|
+
}),
|
|
4407
|
+
unsubscribe: () => {
|
|
4408
|
+
if (!active)
|
|
4409
|
+
return;
|
|
4410
|
+
active = false;
|
|
4411
|
+
subscribed.listeners.delete(onChange);
|
|
4412
|
+
subscribed.refCount--;
|
|
4413
|
+
if (subscribed.refCount > 0)
|
|
4414
|
+
return;
|
|
4415
|
+
subscribed.pendingUnsub = setTimeout(() => {
|
|
4416
|
+
subscribed.pendingUnsub = undefined;
|
|
4417
|
+
if (subscribed.refCount > 0)
|
|
4418
|
+
return;
|
|
4419
|
+
eventWire.unsubscribeQuery(subscribed.subscriptionId);
|
|
4420
|
+
this.entries.delete(key);
|
|
4421
|
+
}, StreamingQueryCache.UNSUBSCRIBE_DELAY_MS);
|
|
4374
4422
|
}
|
|
4375
|
-
|
|
4376
|
-
if (stream) {
|
|
4377
|
-
try {
|
|
4378
|
-
stream.unsubscribe();
|
|
4379
|
-
} catch {}
|
|
4380
|
-
this.activeStreams.delete(viewName);
|
|
4381
|
-
}
|
|
4382
|
-
this.streamScopes.delete(viewName);
|
|
4383
|
-
const store = this.stores.get(viewName);
|
|
4384
|
-
if (store)
|
|
4385
|
-
store.clear();
|
|
4386
|
-
}
|
|
4387
|
-
}
|
|
4388
|
-
setViewData(viewName, data) {
|
|
4389
|
-
const store = this.stores.get(viewName);
|
|
4390
|
-
if (!store)
|
|
4391
|
-
return;
|
|
4392
|
-
if (Array.isArray(data)) {
|
|
4393
|
-
store.setAll(data);
|
|
4394
|
-
} else if (data && typeof data === "object" && "_id" in data) {
|
|
4395
|
-
store.setAll([data]);
|
|
4396
|
-
} else {
|
|
4397
|
-
store.setAll([]);
|
|
4398
|
-
}
|
|
4423
|
+
};
|
|
4399
4424
|
}
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
if (!handler)
|
|
4425
|
+
invalidateScope(scope, eventWire) {
|
|
4426
|
+
const prefix = `${scope}:`;
|
|
4427
|
+
for (const [key, entry] of this.entries) {
|
|
4428
|
+
if (!key.startsWith(prefix))
|
|
4405
4429
|
continue;
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
modify: async (id3, data) => {
|
|
4414
|
-
store.modify(String(id3), data);
|
|
4415
|
-
},
|
|
4416
|
-
remove: async (id3) => {
|
|
4417
|
-
store.remove(String(id3));
|
|
4418
|
-
},
|
|
4419
|
-
find: async (options) => {
|
|
4420
|
-
return store.find(options);
|
|
4421
|
-
},
|
|
4422
|
-
findOne: async (where) => {
|
|
4423
|
-
return store.findOne(where);
|
|
4424
|
-
},
|
|
4425
|
-
$auth: {}
|
|
4426
|
-
};
|
|
4427
|
-
await handler(ctx, event3);
|
|
4428
|
-
}
|
|
4429
|
-
}
|
|
4430
|
-
clear() {
|
|
4431
|
-
for (const stream of this.activeStreams.values()) {
|
|
4432
|
-
stream.unsubscribe();
|
|
4433
|
-
}
|
|
4434
|
-
this.activeStreams.clear();
|
|
4435
|
-
this.streamScopes.clear();
|
|
4436
|
-
for (const timeout of this.pendingUnsubscribes.values()) {
|
|
4437
|
-
clearTimeout(timeout);
|
|
4438
|
-
}
|
|
4439
|
-
this.pendingUnsubscribes.clear();
|
|
4440
|
-
for (const store of this.stores.values()) {
|
|
4441
|
-
store.clear();
|
|
4430
|
+
if (entry.pendingUnsub)
|
|
4431
|
+
clearTimeout(entry.pendingUnsub);
|
|
4432
|
+
eventWire?.unsubscribeQuery(entry.subscriptionId);
|
|
4433
|
+
this.entries.delete(key);
|
|
4434
|
+
entry.result = undefined;
|
|
4435
|
+
entry.hasResult = false;
|
|
4436
|
+
this.notify(entry);
|
|
4442
4437
|
}
|
|
4443
4438
|
}
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
initialized = false;
|
|
4450
|
-
hasData() {
|
|
4451
|
-
return this.initialized;
|
|
4452
|
-
}
|
|
4453
|
-
setAll(items) {
|
|
4454
|
-
this.initialized = true;
|
|
4455
|
-
this.data.clear();
|
|
4456
|
-
for (const item of items) {
|
|
4457
|
-
this.data.set(item._id, item);
|
|
4458
|
-
}
|
|
4459
|
-
this.notifyListeners(null);
|
|
4460
|
-
}
|
|
4461
|
-
set(id3, item) {
|
|
4462
|
-
this.data.set(id3, item);
|
|
4463
|
-
this.notifyListeners([{ type: "set", id: id3, item }]);
|
|
4464
|
-
}
|
|
4465
|
-
modify(id3, updates) {
|
|
4466
|
-
const existing = this.data.get(id3);
|
|
4467
|
-
if (existing) {
|
|
4468
|
-
const updated = { ...existing, ...updates };
|
|
4469
|
-
this.data.set(id3, updated);
|
|
4470
|
-
this.notifyListeners([{ type: "set", id: id3, item: updated }]);
|
|
4439
|
+
clear(eventWire) {
|
|
4440
|
+
for (const entry of this.entries.values()) {
|
|
4441
|
+
if (entry.pendingUnsub)
|
|
4442
|
+
clearTimeout(entry.pendingUnsub);
|
|
4443
|
+
eventWire?.unsubscribeQuery(entry.subscriptionId);
|
|
4471
4444
|
}
|
|
4445
|
+
this.entries.clear();
|
|
4472
4446
|
}
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
this.data.clear();
|
|
4481
|
-
this.notifyListeners(null);
|
|
4482
|
-
}
|
|
4483
|
-
find(options = {}) {
|
|
4484
|
-
let results = Array.from(this.data.values());
|
|
4485
|
-
if (options.where) {
|
|
4486
|
-
results = results.filter((item) => checkItemMatchesWhere(item, options.where));
|
|
4487
|
-
}
|
|
4488
|
-
return applyOrderByAndLimit(results, options);
|
|
4489
|
-
}
|
|
4490
|
-
findOne(where) {
|
|
4491
|
-
const results = this.find({ where });
|
|
4492
|
-
return results[0];
|
|
4493
|
-
}
|
|
4494
|
-
subscribe(listener4) {
|
|
4495
|
-
this.listeners.add(listener4);
|
|
4496
|
-
return () => {
|
|
4497
|
-
this.listeners.delete(listener4);
|
|
4498
|
-
};
|
|
4499
|
-
}
|
|
4500
|
-
notifyListeners(events) {
|
|
4501
|
-
for (const listener4 of this.listeners) {
|
|
4502
|
-
listener4(events);
|
|
4447
|
+
notify(entry) {
|
|
4448
|
+
for (const listener4 of entry.listeners) {
|
|
4449
|
+
try {
|
|
4450
|
+
listener4();
|
|
4451
|
+
} catch (err) {
|
|
4452
|
+
console.error(`[Arc] Query cache listener error:`, err);
|
|
4453
|
+
}
|
|
4503
4454
|
}
|
|
4504
4455
|
}
|
|
4505
4456
|
}
|
|
4506
4457
|
|
|
4507
4458
|
class StreamingEventPublisher {
|
|
4508
|
-
cache;
|
|
4509
4459
|
eventWire;
|
|
4510
4460
|
views = [];
|
|
4511
4461
|
subscribers = new Map;
|
|
4512
|
-
constructor(
|
|
4513
|
-
this.cache = cache;
|
|
4462
|
+
constructor(eventWire) {
|
|
4514
4463
|
this.eventWire = eventWire;
|
|
4515
4464
|
}
|
|
4516
4465
|
registerViews(views) {
|
|
4517
4466
|
this.views = views;
|
|
4518
|
-
this.cache.registerViews(views);
|
|
4519
4467
|
}
|
|
4520
4468
|
async publish(event3) {
|
|
4521
|
-
await this.cache.applyEvent(event3);
|
|
4522
4469
|
await this.notifySubscribers(event3);
|
|
4523
4470
|
this.eventWire.syncEvents([
|
|
4524
4471
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcote.tech/arc-adapter-db-sqlite",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"test": "bun test"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@arcote.tech/arc": "^0.7.
|
|
23
|
+
"@arcote.tech/arc": "^0.7.16"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"typescript": "^5.0.0"
|