@arcote.tech/arc 0.7.10 → 0.7.12

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 CHANGED
@@ -2491,7 +2491,11 @@ class ArcCommand extends ArcContextElement {
2491
2491
  if (!adapters.commandWire) {
2492
2492
  throw new Error(`Command "${this.data.name}" has no handler and no commandWire adapter available for remote execution`);
2493
2493
  }
2494
- return await adapters.commandWire.executeCommand(this.data.name, params);
2494
+ const wireAuth = adapters.scope ? {
2495
+ scope: adapters.scope.scopeName,
2496
+ token: adapters.scope.getToken()
2497
+ } : undefined;
2498
+ return await adapters.commandWire.executeCommand(this.data.name, params, wireAuth);
2495
2499
  };
2496
2500
  return Object.assign(executeFunc, { params: this.data.params });
2497
2501
  }
@@ -4597,6 +4601,7 @@ class StreamingQueryCache {
4597
4601
  views = [];
4598
4602
  activeStreams = new Map;
4599
4603
  pendingUnsubscribes = new Map;
4604
+ streamScopes = new Map;
4600
4605
  static UNSUBSCRIBE_DELAY_MS = 5000;
4601
4606
  registerViews(views) {
4602
4607
  this.views = views;
@@ -4655,6 +4660,7 @@ class StreamingQueryCache {
4655
4660
  if (current && current.refCount <= 0) {
4656
4661
  current.unsubscribe();
4657
4662
  this.activeStreams.delete(viewName);
4663
+ this.streamScopes.delete(viewName);
4658
4664
  }
4659
4665
  }, StreamingQueryCache.UNSUBSCRIBE_DELAY_MS);
4660
4666
  this.pendingUnsubscribes.set(viewName, timeout);
@@ -4662,6 +4668,8 @@ class StreamingQueryCache {
4662
4668
  }
4663
4669
  subscribeQuery(descriptor, eventWire, scope) {
4664
4670
  const key = descriptor.element;
4671
+ if (scope)
4672
+ this.streamScopes.set(key, scope);
4665
4673
  const { unsubscribe } = this.registerStream(key, () => {
4666
4674
  const subId = eventWire.subscribeQuery(descriptor, (data) => {
4667
4675
  this.setViewData(descriptor.element, data);
@@ -4670,6 +4678,28 @@ class StreamingQueryCache {
4670
4678
  });
4671
4679
  return unsubscribe;
4672
4680
  }
4681
+ invalidateScope(scope) {
4682
+ for (const [viewName, viewScope] of this.streamScopes) {
4683
+ if (viewScope !== scope)
4684
+ continue;
4685
+ const pending = this.pendingUnsubscribes.get(viewName);
4686
+ if (pending) {
4687
+ clearTimeout(pending);
4688
+ this.pendingUnsubscribes.delete(viewName);
4689
+ }
4690
+ const stream = this.activeStreams.get(viewName);
4691
+ if (stream) {
4692
+ try {
4693
+ stream.unsubscribe();
4694
+ } catch {}
4695
+ this.activeStreams.delete(viewName);
4696
+ }
4697
+ this.streamScopes.delete(viewName);
4698
+ const store = this.stores.get(viewName);
4699
+ if (store)
4700
+ store.clear();
4701
+ }
4702
+ }
4673
4703
  setViewData(viewName, data) {
4674
4704
  const store = this.stores.get(viewName);
4675
4705
  if (!store)
@@ -4717,6 +4747,11 @@ class StreamingQueryCache {
4717
4747
  stream.unsubscribe();
4718
4748
  }
4719
4749
  this.activeStreams.clear();
4750
+ this.streamScopes.clear();
4751
+ for (const timeout of this.pendingUnsubscribes.values()) {
4752
+ clearTimeout(timeout);
4753
+ }
4754
+ this.pendingUnsubscribes.clear();
4720
4755
  for (const store of this.stores.values()) {
4721
4756
  store.clear();
4722
4757
  }
@@ -38,6 +38,15 @@ export declare class StreamingQueryCache {
38
38
  private views;
39
39
  private activeStreams;
40
40
  private pendingUnsubscribes;
41
+ /**
42
+ * Tag each active stream with the scope name that subscribed it. Used by
43
+ * `invalidateScope()` to force-close streams when a scope's token changes
44
+ * (workspace switch / re-auth) — without this tag, `registerStream()` would
45
+ * reuse the stale WS subscription (refCount > 0, or within the
46
+ * UNSUBSCRIBE_DELAY_MS grace window) and the client would keep receiving
47
+ * data filtered by the previous token.
48
+ */
49
+ private streamScopes;
41
50
  private static UNSUBSCRIBE_DELAY_MS;
42
51
  /**
43
52
  * Register views that this cache will handle
@@ -83,6 +92,23 @@ export declare class StreamingQueryCache {
83
92
  method: string;
84
93
  args: any[];
85
94
  }, eventWire: EventWire, scope?: string): () => void;
95
+ /**
96
+ * Force-close every active stream tagged with `scope`. Called when a
97
+ * scope's token changes (workspace switch / re-auth) so the next
98
+ * `subscribeQuery()` creates a fresh WS subscription with the new token
99
+ * instead of reusing the stale one (which would keep pumping data filtered
100
+ * by the previous token until the page reload).
101
+ *
102
+ * Bypasses both `refCount` (other subscribers still mounted) and the
103
+ * UNSUBSCRIBE_DELAY_MS grace window — both became invalid the moment the
104
+ * token changed. React's `useQuery` re-subscribes immediately afterwards
105
+ * via the `subKey` change (token is in the key), getting a fresh stream.
106
+ *
107
+ * Bonus: each affected store is also cleared so any in-progress render
108
+ * that reads `store.find()` between `setToken` and the new WS data
109
+ * arriving gets `[]` rather than stale rows from the previous workspace.
110
+ */
111
+ invalidateScope(scope: string): void;
86
112
  /**
87
113
  * Set data for a view. Accepts array or single item (from queryMethod findOne).
88
114
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc",
3
3
  "type": "module",
4
- "version": "0.7.10",
4
+ "version": "0.7.12",
5
5
  "private": false,
6
6
  "author": "Przemysław Krasiński [arcote.tech]",
7
7
  "description": "Arc framework core rewrite with improved event emission and type safety",