@arcote.tech/arc-adapter-db-postgres 0.7.15 → 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.
Files changed (2) hide show
  1. package/dist/index.js +196 -290
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1484,7 +1484,8 @@ class EventWire {
1484
1484
  onSyncedCallback;
1485
1485
  reconnectTimeout;
1486
1486
  syncRequested = false;
1487
- viewSubscriptions = new Map;
1487
+ querySubscriptions = new Map;
1488
+ querySubCounter = 0;
1488
1489
  enableEventSync;
1489
1490
  constructor(baseUrl, options) {
1490
1491
  this.baseUrl = baseUrl;
@@ -1539,7 +1540,7 @@ class EventWire {
1539
1540
  this.requestSync();
1540
1541
  }
1541
1542
  this.flushPendingEvents();
1542
- this.sendAllViewSubscriptions();
1543
+ this.sendAllQuerySubscriptions();
1543
1544
  } else {
1544
1545
  console.log(`[EventWire] onopen called but ws is not OPEN, readyState:`, this.ws?.readyState);
1545
1546
  }
@@ -1615,24 +1616,29 @@ class EventWire {
1615
1616
  onSynced(callback) {
1616
1617
  this.onSyncedCallback = callback;
1617
1618
  }
1618
- subscribeView(element, scope, callbacks) {
1619
- const key = `${scope}:${element}`;
1620
- this.viewSubscriptions.set(key, callbacks);
1619
+ subscribeQuery(descriptor, scope, callbacks) {
1620
+ const subscriptionId = `qs_${this.instanceId}_${++this.querySubCounter}`;
1621
+ this.querySubscriptions.set(subscriptionId, {
1622
+ descriptor,
1623
+ scope,
1624
+ callbacks
1625
+ });
1621
1626
  if (this.state === "connected" && this.ws) {
1622
1627
  this.ws.send(JSON.stringify({
1623
- type: "subscribe-view",
1624
- element,
1628
+ type: "subscribe-query",
1629
+ subscriptionId,
1630
+ descriptor,
1625
1631
  scope
1626
1632
  }));
1627
1633
  }
1634
+ return subscriptionId;
1628
1635
  }
1629
- unsubscribeView(element, scope) {
1630
- this.viewSubscriptions.delete(`${scope}:${element}`);
1636
+ unsubscribeQuery(subscriptionId) {
1637
+ this.querySubscriptions.delete(subscriptionId);
1631
1638
  if (this.state === "connected" && this.ws) {
1632
1639
  this.ws.send(JSON.stringify({
1633
- type: "unsubscribe-view",
1634
- element,
1635
- scope
1640
+ type: "unsubscribe-query",
1641
+ subscriptionId
1636
1642
  }));
1637
1643
  }
1638
1644
  }
@@ -1667,17 +1673,17 @@ class EventWire {
1667
1673
  this.lastHostEventId = message.lastHostEventId;
1668
1674
  }
1669
1675
  break;
1670
- case "view-snapshot": {
1671
- const sub = this.viewSubscriptions.get(`${message.scope}:${message.element}`);
1676
+ case "query-snapshot": {
1677
+ const sub = this.querySubscriptions.get(message.subscriptionId);
1672
1678
  if (sub) {
1673
- sub.onSnapshot(message.items ?? []);
1679
+ sub.callbacks.onSnapshot(message.result ?? null);
1674
1680
  }
1675
1681
  break;
1676
1682
  }
1677
- case "view-changes": {
1678
- const sub = this.viewSubscriptions.get(`${message.scope}:${message.element}`);
1683
+ case "query-changes": {
1684
+ const sub = this.querySubscriptions.get(message.subscriptionId);
1679
1685
  if (sub && Array.isArray(message.changes)) {
1680
- sub.onChanges(message.changes);
1686
+ sub.callbacks.onChanges(message.changes);
1681
1687
  }
1682
1688
  break;
1683
1689
  }
@@ -1705,17 +1711,15 @@ class EventWire {
1705
1711
  this.pendingEvents = [];
1706
1712
  }
1707
1713
  }
1708
- sendAllViewSubscriptions() {
1714
+ sendAllQuerySubscriptions() {
1709
1715
  if (!this.ws || this.state !== "connected")
1710
1716
  return;
1711
- for (const key of this.viewSubscriptions.keys()) {
1712
- const sepIdx = key.indexOf(":");
1713
- const scope = key.slice(0, sepIdx);
1714
- const element = key.slice(sepIdx + 1);
1717
+ for (const [subscriptionId, sub] of this.querySubscriptions) {
1715
1718
  this.ws.send(JSON.stringify({
1716
- type: "subscribe-view",
1717
- element,
1718
- scope
1719
+ type: "subscribe-query",
1720
+ subscriptionId,
1721
+ descriptor: sub.descriptor,
1722
+ scope: sub.scope
1719
1723
  }));
1720
1724
  }
1721
1725
  }
@@ -1739,19 +1743,12 @@ class LocalEventPublisher {
1739
1743
  views = [];
1740
1744
  syncCallback;
1741
1745
  subscribers = new Map;
1742
- viewChangesCallbacks = new Set;
1743
1746
  constructor(dataStorage) {
1744
1747
  this.dataStorage = dataStorage;
1745
1748
  }
1746
1749
  onPublish(callback) {
1747
1750
  this.syncCallback = callback;
1748
1751
  }
1749
- onViewChanges(callback) {
1750
- this.viewChangesCallbacks.add(callback);
1751
- return () => {
1752
- this.viewChangesCallbacks.delete(callback);
1753
- };
1754
- }
1755
1752
  registerViews(views) {
1756
1753
  this.views = views;
1757
1754
  }
@@ -1819,19 +1816,7 @@ class LocalEventPublisher {
1819
1816
  });
1820
1817
  const viewChanges = await this.collectViewChanges(event);
1821
1818
  allChanges.push(...viewChanges);
1822
- const viewStoreNames = new Set(viewChanges.map((c) => c.store));
1823
- const committed = await this.dataStorage.commitChanges(allChanges, {
1824
- captureRowsFor: viewStoreNames
1825
- });
1826
- if (committed.length > 0 && this.viewChangesCallbacks.size > 0) {
1827
- for (const callback of this.viewChangesCallbacks) {
1828
- try {
1829
- callback(committed);
1830
- } catch (error) {
1831
- console.error(`[EventPublisher] onViewChanges callback error:`, error);
1832
- }
1833
- }
1834
- }
1819
+ await this.dataStorage.commitChanges(allChanges);
1835
1820
  await this.notifySubscribers(event);
1836
1821
  if (this.syncCallback) {
1837
1822
  this.syncCallback(event);
@@ -2471,9 +2456,8 @@ class ArcObject extends ArcAbstract {
2471
2456
  }
2472
2457
  }
2473
2458
  class DataStorage {
2474
- async commitChanges(changes, _options) {
2459
+ async commitChanges(changes) {
2475
2460
  await Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applyChanges(changes2)));
2476
- return [];
2477
2461
  }
2478
2462
  }
2479
2463
 
@@ -3564,6 +3548,48 @@ function deepMerge(target, source) {
3564
3548
  function isPlainObject(item) {
3565
3549
  return item && typeof item === "object" && !Array.isArray(item) && !(item instanceof Date) && Object.prototype.toString.call(item) === "[object Object]";
3566
3550
  }
3551
+ function murmurHash(key, seed = 0) {
3552
+ let remainder, bytes, h1, h1b, c1, c2, k1, i;
3553
+ remainder = key.length & 3;
3554
+ bytes = key.length - remainder;
3555
+ h1 = seed;
3556
+ c1 = 3432918353;
3557
+ c2 = 461845907;
3558
+ i = 0;
3559
+ while (i < bytes) {
3560
+ k1 = key.charCodeAt(i) & 255 | (key.charCodeAt(++i) & 255) << 8 | (key.charCodeAt(++i) & 255) << 16 | (key.charCodeAt(++i) & 255) << 24;
3561
+ ++i;
3562
+ k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
3563
+ k1 = k1 << 15 | k1 >>> 17;
3564
+ k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
3565
+ h1 ^= k1;
3566
+ h1 = h1 << 13 | h1 >>> 19;
3567
+ h1b = (h1 & 65535) * 5 + (((h1 >>> 16) * 5 & 65535) << 16) & 4294967295;
3568
+ h1 = (h1b & 65535) + 27492 + (((h1b >>> 16) + 58964 & 65535) << 16);
3569
+ }
3570
+ k1 = 0;
3571
+ if (remainder >= 3) {
3572
+ k1 ^= (key.charCodeAt(i + 2) & 255) << 16;
3573
+ }
3574
+ if (remainder >= 2) {
3575
+ k1 ^= (key.charCodeAt(i + 1) & 255) << 8;
3576
+ }
3577
+ if (remainder >= 1) {
3578
+ k1 ^= key.charCodeAt(i) & 255;
3579
+ k1 = (k1 & 65535) * c1 + (((k1 >>> 16) * c1 & 65535) << 16) & 4294967295;
3580
+ k1 = k1 << 15 | k1 >>> 17;
3581
+ k1 = (k1 & 65535) * c2 + (((k1 >>> 16) * c2 & 65535) << 16) & 4294967295;
3582
+ h1 ^= k1;
3583
+ }
3584
+ h1 ^= key.length;
3585
+ h1 ^= h1 >>> 16;
3586
+ h1 = (h1 & 65535) * 2246822507 + (((h1 >>> 16) * 2246822507 & 65535) << 16) & 4294967295;
3587
+ h1 ^= h1 >>> 13;
3588
+ h1 = (h1 & 65535) * 3266489909 + (((h1 >>> 16) * 3266489909 & 65535) << 16) & 4294967295;
3589
+ h1 ^= h1 >>> 16;
3590
+ return h1 >>> 0;
3591
+ }
3592
+
3567
3593
  class ForkedStoreState extends StoreState {
3568
3594
  master;
3569
3595
  changedItems = new Map;
@@ -3719,12 +3745,8 @@ class MasterStoreState extends StoreState {
3719
3745
  }
3720
3746
  return transaction.find(this.storeName, { where: { _id: id2 } }).then((results) => results[0]);
3721
3747
  }
3722
- async applyChangeAndReturnEvent(transaction, change, transactionCache, options) {
3748
+ async applyChangeAndReturnEvent(transaction, change, transactionCache) {
3723
3749
  if (change.type === "set") {
3724
- let existing;
3725
- if (options?.captureRows) {
3726
- existing = await this.readExisting(transaction, change.data._id, transactionCache);
3727
- }
3728
3750
  await transaction.set(this.storeName, change.data);
3729
3751
  const item = this.deserialize ? this.deserialize(change.data) : change.data;
3730
3752
  if (transactionCache) {
@@ -3737,16 +3759,10 @@ class MasterStoreState extends StoreState {
3737
3759
  type: "set",
3738
3760
  item: change.data,
3739
3761
  id: change.data._id
3740
- },
3741
- oldRow: existing ?? null,
3742
- newRow: change.data
3762
+ }
3743
3763
  };
3744
3764
  }
3745
3765
  if (change.type === "delete") {
3746
- let existing;
3747
- if (options?.captureRows) {
3748
- existing = await this.readExisting(transaction, change.id, transactionCache);
3749
- }
3750
3766
  await transaction.remove(this.storeName, change.id);
3751
3767
  if (transactionCache) {
3752
3768
  transactionCache.delete(`${this.storeName}:${change.id}`);
@@ -3758,9 +3774,7 @@ class MasterStoreState extends StoreState {
3758
3774
  type: "delete",
3759
3775
  item: null,
3760
3776
  id: change.id
3761
- },
3762
- oldRow: existing ?? null,
3763
- newRow: null
3777
+ }
3764
3778
  };
3765
3779
  }
3766
3780
  if (change.type === "modify") {
@@ -3778,9 +3792,7 @@ class MasterStoreState extends StoreState {
3778
3792
  type: "set",
3779
3793
  item,
3780
3794
  id: change.id
3781
- },
3782
- oldRow: existing ?? null,
3783
- newRow: updated
3795
+ }
3784
3796
  };
3785
3797
  }
3786
3798
  if (change.type === "mutate") {
@@ -3798,9 +3810,7 @@ class MasterStoreState extends StoreState {
3798
3810
  type: "set",
3799
3811
  item,
3800
3812
  id: change.id
3801
- },
3802
- oldRow: existing ?? null,
3803
- newRow: updated
3813
+ }
3804
3814
  };
3805
3815
  }
3806
3816
  throw new Error("Unknown change type");
@@ -3878,22 +3888,17 @@ class MasterDataStorage extends DataStorage {
3878
3888
  applySerializedChanges(changes) {
3879
3889
  return Promise.all(changes.map(({ store, changes: changes2 }) => this.getStore(store).applySerializedChanges(changes2)));
3880
3890
  }
3881
- async commitChanges(changes, options) {
3891
+ async commitChanges(changes) {
3882
3892
  const transaction = await this.getReadWriteTransaction();
3883
3893
  const transactionCache = new Map;
3884
3894
  const eventsByStore = new Map;
3885
- const committed = [];
3886
3895
  for (const { store, changes: storeChanges } of changes) {
3887
3896
  const storeState = this.getStore(store);
3888
3897
  const storeEvents = [];
3889
- const capture = options?.captureRowsFor?.has(store) ?? false;
3890
3898
  for (const change of storeChanges) {
3891
- const { event: event3, oldRow, newRow } = await storeState.applyChangeAndReturnEvent(transaction, change, transactionCache, { captureRows: capture });
3899
+ const { event: event3 } = await storeState.applyChangeAndReturnEvent(transaction, change, transactionCache);
3892
3900
  if (event3)
3893
3901
  storeEvents.push(event3);
3894
- if (capture) {
3895
- committed.push({ store, id: event3.id, oldRow, newRow });
3896
- }
3897
3902
  }
3898
3903
  if (storeEvents.length > 0) {
3899
3904
  eventsByStore.set(store, storeEvents);
@@ -3904,7 +3909,6 @@ class MasterDataStorage extends DataStorage {
3904
3909
  const storeState = this.getStore(store);
3905
3910
  storeState.notifyListenersPublic(events);
3906
3911
  }
3907
- return committed;
3908
3912
  }
3909
3913
  fork() {
3910
3914
  return new ForkedDataStorage(this);
@@ -4019,8 +4023,8 @@ class ObservableDataStorage {
4019
4023
  getReadWriteTransaction() {
4020
4024
  return this.source.getReadWriteTransaction();
4021
4025
  }
4022
- commitChanges(changes, options) {
4023
- return this.source.commitChanges(changes, options);
4026
+ commitChanges(changes) {
4027
+ return this.source.commitChanges(changes);
4024
4028
  }
4025
4029
  trackQuery(storeName, options, result, listener4) {
4026
4030
  const key = this.getQueryKey(storeName, options);
@@ -4033,7 +4037,8 @@ class ObservableDataStorage {
4033
4037
  }
4034
4038
  handleStoreChange(storeName, events) {
4035
4039
  let hasChanges = false;
4036
- for (const query of this.trackedQueries.values()) {
4040
+ const staleKeys = [];
4041
+ for (const [key, query] of this.trackedQueries) {
4037
4042
  if (query.storeName !== storeName)
4038
4043
  continue;
4039
4044
  let currentResult = query.result;
@@ -4045,10 +4050,20 @@ class ObservableDataStorage {
4045
4050
  queryChanged = true;
4046
4051
  }
4047
4052
  }
4048
- if (queryChanged) {
4049
- query.result = currentResult;
4053
+ if (!queryChanged)
4054
+ continue;
4055
+ if (query.options.limit !== undefined && query.result.length === query.options.limit && currentResult.length < query.options.limit) {
4056
+ staleKeys.push(key);
4050
4057
  hasChanges = true;
4058
+ continue;
4051
4059
  }
4060
+ query.result = currentResult;
4061
+ hasChanges = true;
4062
+ }
4063
+ for (const key of staleKeys) {
4064
+ const query = this.trackedQueries.get(key);
4065
+ this.source.getStore(query.storeName).unsubscribe(query.listener);
4066
+ this.trackedQueries.delete(key);
4052
4067
  }
4053
4068
  if (hasChanges) {
4054
4069
  this.onChange();
@@ -4319,244 +4334,135 @@ class Model {
4319
4334
  return s;
4320
4335
  }
4321
4336
  }
4322
- var DEFAULT_SCOPE = "default";
4323
-
4324
- class StreamingQueryCache {
4325
- stores = new Map;
4326
- views = [];
4327
- activeStreams = new Map;
4328
- pendingUnsubscribes = new Map;
4329
- static UNSUBSCRIBE_DELAY_MS = 5000;
4330
- storeKey(viewName, scope) {
4331
- return `${scope ?? DEFAULT_SCOPE}:${viewName}`;
4332
- }
4333
- registerViews(views) {
4334
- this.views = views;
4335
- }
4336
- getStore(viewName, scope) {
4337
- const key = this.storeKey(viewName, scope);
4338
- if (!this.stores.has(key)) {
4339
- this.stores.set(key, new StreamingStore);
4337
+ function applyQueryChanges(result, changes) {
4338
+ const next = [...result];
4339
+ for (const change of changes) {
4340
+ if (change.type === "delete") {
4341
+ const idx = next.findIndex((it) => it._id === change.id);
4342
+ if (idx !== -1)
4343
+ next.splice(idx, 1);
4340
4344
  }
4341
- return this.stores.get(key);
4342
- }
4343
- hasData(viewName, scope) {
4344
- const store = this.stores.get(this.storeKey(viewName, scope));
4345
- return store ? store.hasData() : false;
4346
4345
  }
4347
- registerStream(key, createStream) {
4348
- const pending = this.pendingUnsubscribes.get(key);
4349
- if (pending) {
4350
- clearTimeout(pending);
4351
- this.pendingUnsubscribes.delete(key);
4346
+ for (const change of changes) {
4347
+ if (change.type === "set") {
4348
+ const idx = next.findIndex((it) => it._id === change.id);
4349
+ if (idx !== -1)
4350
+ next.splice(idx, 1);
4351
+ next.splice(change.index, 0, change.item);
4352
4352
  }
4353
- const existing = this.activeStreams.get(key);
4354
- if (existing) {
4355
- existing.refCount++;
4356
- return {
4357
- unsubscribe: () => this.unregisterStream(key),
4358
- wasReused: true
4353
+ }
4354
+ return next;
4355
+ }
4356
+ class StreamingQueryCache {
4357
+ entries = new Map;
4358
+ static UNSUBSCRIBE_DELAY_MS = 5000;
4359
+ entryKey(descriptor, scope) {
4360
+ return `${scope ?? "default"}:${murmurHash(JSON.stringify(descriptor))}`;
4361
+ }
4362
+ subscribe(descriptor, scope, eventWire, onChange) {
4363
+ const key = this.entryKey(descriptor, scope);
4364
+ let entry = this.entries.get(key);
4365
+ if (entry) {
4366
+ if (entry.pendingUnsub) {
4367
+ clearTimeout(entry.pendingUnsub);
4368
+ entry.pendingUnsub = undefined;
4369
+ }
4370
+ entry.refCount++;
4371
+ } else {
4372
+ const newEntry = {
4373
+ result: undefined,
4374
+ hasResult: false,
4375
+ listeners: new Set,
4376
+ refCount: 1,
4377
+ subscriptionId: ""
4359
4378
  };
4379
+ newEntry.subscriptionId = eventWire.subscribeQuery(descriptor, scope, {
4380
+ onSnapshot: (result) => {
4381
+ newEntry.result = result;
4382
+ newEntry.hasResult = true;
4383
+ this.notify(newEntry);
4384
+ },
4385
+ onChanges: (changes) => {
4386
+ if (!newEntry.hasResult || !Array.isArray(newEntry.result)) {
4387
+ return;
4388
+ }
4389
+ newEntry.result = applyQueryChanges(newEntry.result, changes);
4390
+ this.notify(newEntry);
4391
+ }
4392
+ });
4393
+ this.entries.set(key, newEntry);
4394
+ entry = newEntry;
4360
4395
  }
4361
- const streamConn = createStream();
4362
- this.activeStreams.set(key, {
4363
- unsubscribe: streamConn.unsubscribe,
4364
- refCount: 1
4365
- });
4396
+ const subscribed = entry;
4397
+ subscribed.listeners.add(onChange);
4398
+ let active = true;
4366
4399
  return {
4367
- unsubscribe: () => this.unregisterStream(key),
4368
- wasReused: false
4400
+ read: () => ({
4401
+ result: subscribed.result,
4402
+ loading: !subscribed.hasResult
4403
+ }),
4404
+ unsubscribe: () => {
4405
+ if (!active)
4406
+ return;
4407
+ active = false;
4408
+ subscribed.listeners.delete(onChange);
4409
+ subscribed.refCount--;
4410
+ if (subscribed.refCount > 0)
4411
+ return;
4412
+ subscribed.pendingUnsub = setTimeout(() => {
4413
+ subscribed.pendingUnsub = undefined;
4414
+ if (subscribed.refCount > 0)
4415
+ return;
4416
+ eventWire.unsubscribeQuery(subscribed.subscriptionId);
4417
+ this.entries.delete(key);
4418
+ }, StreamingQueryCache.UNSUBSCRIBE_DELAY_MS);
4419
+ }
4369
4420
  };
4370
4421
  }
4371
- unregisterStream(key) {
4372
- const stream = this.activeStreams.get(key);
4373
- if (!stream)
4374
- return;
4375
- stream.refCount--;
4376
- if (stream.refCount <= 0) {
4377
- const timeout = setTimeout(() => {
4378
- this.pendingUnsubscribes.delete(key);
4379
- const current2 = this.activeStreams.get(key);
4380
- if (current2 && current2.refCount <= 0) {
4381
- current2.unsubscribe();
4382
- this.activeStreams.delete(key);
4383
- }
4384
- }, StreamingQueryCache.UNSUBSCRIBE_DELAY_MS);
4385
- this.pendingUnsubscribes.set(key, timeout);
4386
- }
4387
- }
4388
- subscribeView(viewName, eventWire, scope) {
4389
- const key = this.storeKey(viewName, scope);
4390
- const { unsubscribe } = this.registerStream(key, () => {
4391
- const store = this.stores.get(key) ?? new StreamingStore;
4392
- this.stores.set(key, store);
4393
- eventWire.subscribeView(viewName, scope ?? DEFAULT_SCOPE, {
4394
- onSnapshot: (items) => store.setAll(items),
4395
- onChanges: (changes) => store.applyChanges(changes)
4396
- });
4397
- return {
4398
- unsubscribe: () => eventWire.unsubscribeView(viewName, scope ?? DEFAULT_SCOPE)
4399
- };
4400
- });
4401
- return unsubscribe;
4402
- }
4403
- invalidateScope(scope) {
4422
+ invalidateScope(scope, eventWire) {
4404
4423
  const prefix = `${scope}:`;
4405
- for (const [key, timeout] of this.pendingUnsubscribes) {
4406
- if (!key.startsWith(prefix))
4407
- continue;
4408
- clearTimeout(timeout);
4409
- this.pendingUnsubscribes.delete(key);
4410
- }
4411
- for (const [key, stream] of this.activeStreams) {
4412
- if (!key.startsWith(prefix))
4413
- continue;
4414
- try {
4415
- stream.unsubscribe();
4416
- } catch {}
4417
- this.activeStreams.delete(key);
4418
- }
4419
- for (const [key, store] of this.stores) {
4424
+ for (const [key, entry] of this.entries) {
4420
4425
  if (!key.startsWith(prefix))
4421
4426
  continue;
4422
- store.clear();
4423
- }
4424
- }
4425
- async applyEvent(event3) {
4426
- for (const view3 of this.views) {
4427
- const handlers = view3.getHandlers();
4428
- const handler = handlers[event3.type];
4429
- if (!handler)
4430
- continue;
4431
- const suffix = `:${view3.name}`;
4432
- for (const [key, store] of this.stores) {
4433
- if (!key.endsWith(suffix))
4434
- continue;
4435
- const ctx = {
4436
- set: async (id3, data) => {
4437
- store.set(String(id3), { _id: String(id3), ...data });
4438
- },
4439
- modify: async (id3, data) => {
4440
- store.modify(String(id3), data);
4441
- },
4442
- remove: async (id3) => {
4443
- store.remove(String(id3));
4444
- },
4445
- find: async (options) => {
4446
- return store.find(options);
4447
- },
4448
- findOne: async (where) => {
4449
- return store.findOne(where);
4450
- },
4451
- $auth: {}
4452
- };
4453
- await handler(ctx, event3);
4454
- }
4455
- }
4456
- }
4457
- clear() {
4458
- for (const stream of this.activeStreams.values()) {
4459
- stream.unsubscribe();
4460
- }
4461
- this.activeStreams.clear();
4462
- for (const timeout of this.pendingUnsubscribes.values()) {
4463
- clearTimeout(timeout);
4464
- }
4465
- this.pendingUnsubscribes.clear();
4466
- for (const store of this.stores.values()) {
4467
- store.clear();
4427
+ if (entry.pendingUnsub)
4428
+ clearTimeout(entry.pendingUnsub);
4429
+ eventWire?.unsubscribeQuery(entry.subscriptionId);
4430
+ this.entries.delete(key);
4431
+ entry.result = undefined;
4432
+ entry.hasResult = false;
4433
+ this.notify(entry);
4468
4434
  }
4469
4435
  }
4470
- }
4471
-
4472
- class StreamingStore {
4473
- data = new Map;
4474
- listeners = new Set;
4475
- initialized = false;
4476
- hasData() {
4477
- return this.initialized;
4478
- }
4479
- setAll(items) {
4480
- this.initialized = true;
4481
- this.data.clear();
4482
- for (const item of items) {
4483
- this.data.set(item._id, item);
4436
+ clear(eventWire) {
4437
+ for (const entry of this.entries.values()) {
4438
+ if (entry.pendingUnsub)
4439
+ clearTimeout(entry.pendingUnsub);
4440
+ eventWire?.unsubscribeQuery(entry.subscriptionId);
4484
4441
  }
4485
- this.notifyListeners(null);
4442
+ this.entries.clear();
4486
4443
  }
4487
- applyChanges(events) {
4488
- if (events.length === 0)
4489
- return;
4490
- for (const event3 of events) {
4491
- if (event3.type === "set" && event3.item) {
4492
- this.data.set(event3.id, event3.item);
4493
- } else if (event3.type === "delete") {
4494
- this.data.delete(event3.id);
4444
+ notify(entry) {
4445
+ for (const listener4 of entry.listeners) {
4446
+ try {
4447
+ listener4();
4448
+ } catch (err) {
4449
+ console.error(`[Arc] Query cache listener error:`, err);
4495
4450
  }
4496
4451
  }
4497
- this.notifyListeners(events);
4498
- }
4499
- set(id3, item) {
4500
- this.data.set(id3, item);
4501
- this.notifyListeners([{ type: "set", id: id3, item }]);
4502
- }
4503
- modify(id3, updates) {
4504
- const existing = this.data.get(id3);
4505
- if (existing) {
4506
- const updated = { ...existing, ...updates };
4507
- this.data.set(id3, updated);
4508
- this.notifyListeners([{ type: "set", id: id3, item: updated }]);
4509
- }
4510
- }
4511
- remove(id3) {
4512
- if (this.data.delete(id3)) {
4513
- this.notifyListeners([{ type: "delete", id: id3, item: null }]);
4514
- }
4515
- }
4516
- clear() {
4517
- this.initialized = false;
4518
- this.data.clear();
4519
- this.notifyListeners(null);
4520
- }
4521
- find(options = {}) {
4522
- let results = Array.from(this.data.values());
4523
- if (options.where) {
4524
- results = results.filter((item) => checkItemMatchesWhere(item, options.where));
4525
- }
4526
- return applyOrderByAndLimit(results, options);
4527
- }
4528
- findOne(where) {
4529
- const results = this.find({ where });
4530
- return results[0];
4531
- }
4532
- subscribe(listener4) {
4533
- this.listeners.add(listener4);
4534
- return () => {
4535
- this.listeners.delete(listener4);
4536
- };
4537
- }
4538
- notifyListeners(events) {
4539
- for (const listener4 of this.listeners) {
4540
- listener4(events);
4541
- }
4542
4452
  }
4543
4453
  }
4544
4454
 
4545
4455
  class StreamingEventPublisher {
4546
- cache;
4547
4456
  eventWire;
4548
4457
  views = [];
4549
4458
  subscribers = new Map;
4550
- constructor(cache, eventWire) {
4551
- this.cache = cache;
4459
+ constructor(eventWire) {
4552
4460
  this.eventWire = eventWire;
4553
4461
  }
4554
4462
  registerViews(views) {
4555
4463
  this.views = views;
4556
- this.cache.registerViews(views);
4557
4464
  }
4558
4465
  async publish(event3) {
4559
- await this.cache.applyEvent(event3);
4560
4466
  await this.notifySubscribers(event3);
4561
4467
  this.eventWire.syncEvents([
4562
4468
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-adapter-db-postgres",
3
- "version": "0.7.15",
3
+ "version": "0.7.16",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "postgres": "^3.4.4"
24
24
  },
25
25
  "peerDependencies": {
26
- "@arcote.tech/arc": "^0.7.15"
26
+ "@arcote.tech/arc": "^0.7.16"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/pg": "^8.11.0",