@xenide-io/suite-client 0.6.0 → 0.6.1

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.mjs CHANGED
@@ -9508,6 +9508,7 @@ function createApiClient(config) {
9508
9508
  let refreshToken = null;
9509
9509
  let activeWorkspaceId = null;
9510
9510
  const etagBodies = /* @__PURE__ */ new Map();
9511
+ const pendingGets = /* @__PURE__ */ new Map();
9511
9512
  let authFailureHandler = null;
9512
9513
  let authFailureFired = false;
9513
9514
  let refreshPromise = null;
@@ -9634,6 +9635,7 @@ function createApiClient(config) {
9634
9635
  refreshToken = null;
9635
9636
  activeWorkspaceId = null;
9636
9637
  etagBodies.clear();
9638
+ pendingGets.clear();
9637
9639
  if (typeof window !== "undefined") {
9638
9640
  window.localStorage.removeItem(ACCESS_KEY);
9639
9641
  window.localStorage.removeItem(REFRESH_KEY);
@@ -9702,6 +9704,30 @@ function createApiClient(config) {
9702
9704
  }
9703
9705
  }
9704
9706
  async function apiFetch(path, init = {}) {
9707
+ if ((init.method ?? "GET").toUpperCase() !== "GET") {
9708
+ pendingGets.clear();
9709
+ try {
9710
+ return await apiFetchInternal(path, init);
9711
+ } finally {
9712
+ pendingGets.clear();
9713
+ }
9714
+ }
9715
+ if (Object.keys(init).length > 0) return apiFetchInternal(path, init);
9716
+ const key = JSON.stringify([
9717
+ getAccessToken(),
9718
+ getActiveWorkspaceId(),
9719
+ path
9720
+ ]);
9721
+ let pending = pendingGets.get(key);
9722
+ if (!pending) {
9723
+ pending = apiFetchInternal(path, init).finally(() => {
9724
+ if (pendingGets.get(key) === pending) pendingGets.delete(key);
9725
+ });
9726
+ pendingGets.set(key, pending);
9727
+ }
9728
+ return (await pending).clone();
9729
+ }
9730
+ async function apiFetchInternal(path, init = {}) {
9705
9731
  const { skipAuth, ...requestInit } = init;
9706
9732
  const token = getAccessToken();
9707
9733
  const headers = {
@@ -10436,40 +10462,49 @@ function createCrossAppSync(config) {
10436
10462
  const subscribers = [];
10437
10463
  let pollInterval = null;
10438
10464
  let pollListeners = 0;
10465
+ let inFlight = false;
10466
+ let primed = false;
10467
+ let scope;
10468
+ let lastRequestedScope;
10469
+ let lastRequestedAt;
10439
10470
  async function fetchCheckpoint() {
10471
+ if (inFlight || document.visibilityState !== "visible") return null;
10472
+ const requestScope = config.getScope?.();
10473
+ if (requestScope === lastRequestedScope && lastRequestedAt !== void 0 && Date.now() - lastRequestedAt < pollMs)
10474
+ return null;
10475
+ inFlight = true;
10476
+ lastRequestedScope = requestScope;
10477
+ lastRequestedAt = Date.now();
10440
10478
  try {
10441
10479
  const res = await config.api.get(config.checkpointPath);
10442
10480
  if (!res.ok) return null;
10443
- return await res.json();
10481
+ const data = await res.json();
10482
+ if (requestScope !== config.getScope?.()) return null;
10483
+ if (scope !== requestScope) {
10484
+ primed = false;
10485
+ scope = requestScope;
10486
+ }
10487
+ return data;
10444
10488
  } catch {
10445
10489
  return null;
10446
- }
10447
- }
10448
- function notify(topic) {
10449
- for (const sub of subscribers) {
10450
- if (!sub.topic || sub.topic === topic) {
10451
- if (lastKnown[topic] > sub.lastSync) {
10452
- sub.lastSync = lastKnown[topic];
10453
- sub.callback();
10454
- }
10455
- }
10490
+ } finally {
10491
+ inFlight = false;
10456
10492
  }
10457
10493
  }
10458
10494
  function checkAndNotify(data) {
10459
- const tasks = data.tasks_synced_at || 0;
10460
- const time = data.time_synced_at || 0;
10461
- const integration = data.integration_synced_at || 0;
10462
- if (tasks > lastKnown.tasks) {
10463
- lastKnown.tasks = tasks;
10464
- notify("tasks");
10465
- }
10466
- if (time > lastKnown.time) {
10467
- lastKnown.time = time;
10468
- notify("time");
10469
- }
10470
- if (integration > lastKnown.integration) {
10471
- lastKnown.integration = integration;
10472
- notify("integration");
10495
+ const next = {
10496
+ tasks: data.tasks_synced_at || 0,
10497
+ time: data.time_synced_at || 0,
10498
+ integration: data.integration_synced_at || 0
10499
+ };
10500
+ const changed = ["tasks", "time", "integration"].filter(
10501
+ (topic) => primed && next[topic] > lastKnown[topic]
10502
+ );
10503
+ Object.assign(lastKnown, next);
10504
+ primed = true;
10505
+ for (const sub of subscribers) {
10506
+ if (changed.some((topic) => !sub.topic || sub.topic === topic))
10507
+ sub.callback();
10473
10508
  }
10474
10509
  }
10475
10510
  function startPolling() {
@@ -10496,8 +10531,7 @@ function createCrossAppSync(config) {
10496
10531
  };
10497
10532
  const sub = {
10498
10533
  topic,
10499
- callback: onSync,
10500
- lastSync: lastKnown[topic || "tasks"]
10534
+ callback: onSync
10501
10535
  };
10502
10536
  subscribers.push(sub);
10503
10537
  pollListeners += 1;
@@ -10602,17 +10636,22 @@ function useSuiteRevisions(options) {
10602
10636
  let seen = {};
10603
10637
  let ready = switching;
10604
10638
  let timer;
10639
+ let inFlight = false;
10640
+ let disposed = false;
10605
10641
  const tick = async () => {
10606
- let data = null;
10642
+ if (inFlight || disposed) return;
10643
+ inFlight = true;
10607
10644
  try {
10608
- data = await loadRef.current();
10645
+ const data = await loadRef.current();
10646
+ if (disposed) return;
10647
+ const step = nextRevisionTick(seen, ready, data);
10648
+ seen = step.seen;
10649
+ ready = step.ready;
10650
+ for (const topic of step.changed) onTopicRef.current(topic);
10609
10651
  } catch {
10610
- return;
10652
+ } finally {
10653
+ inFlight = false;
10611
10654
  }
10612
- const step = nextRevisionTick(seen, ready, data);
10613
- seen = step.seen;
10614
- ready = step.ready;
10615
- for (const topic of step.changed) onTopicRef.current(topic);
10616
10655
  };
10617
10656
  const stop = () => {
10618
10657
  if (timer !== void 0) window.clearInterval(timer);
@@ -10630,6 +10669,7 @@ function useSuiteRevisions(options) {
10630
10669
  if (document.visibilityState === "visible") start();
10631
10670
  document.addEventListener("visibilitychange", onVisibility);
10632
10671
  return () => {
10672
+ disposed = true;
10633
10673
  stop();
10634
10674
  document.removeEventListener("visibilitychange", onVisibility);
10635
10675
  };