@returningai/widget-sdk 1.8.5 → 1.8.6

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.
@@ -12343,6 +12343,109 @@ function isTokenExpired(expiry) {
12343
12343
  if (!expiry) return true;
12344
12344
  return Date.now() >= expiry - 6e4;
12345
12345
  }
12346
+ const RETRY_DELAYS_MS = [5e3, 15e3, 3e4];
12347
+ const RETRYABLE_CLIENT_STATUSES = /* @__PURE__ */ new Set([408, 425, 429]);
12348
+ function isPermanentAuthFailure(error) {
12349
+ if (!error) return false;
12350
+ const { status } = error;
12351
+ return status >= 400 && status < 500 && !RETRYABLE_CLIENT_STATUSES.has(status);
12352
+ }
12353
+ function createDefaultEnvironment$1() {
12354
+ const visibilityDocument = typeof document === "undefined" ? void 0 : document;
12355
+ const pageWindow = typeof window === "undefined" ? void 0 : window;
12356
+ return {
12357
+ isHidden: () => (visibilityDocument == null ? void 0 : visibilityDocument.visibilityState) === "hidden",
12358
+ setTimeout: (callback, delayMs) => globalThis.setTimeout(callback, delayMs),
12359
+ clearTimeout: (timerId) => globalThis.clearTimeout(timerId),
12360
+ addVisibilityChangeListener: (listener) => visibilityDocument == null ? void 0 : visibilityDocument.addEventListener("visibilitychange", listener),
12361
+ removeVisibilityChangeListener: (listener) => visibilityDocument == null ? void 0 : visibilityDocument.removeEventListener("visibilitychange", listener),
12362
+ addPageShowListener: (listener) => pageWindow == null ? void 0 : pageWindow.addEventListener("pageshow", listener),
12363
+ removePageShowListener: (listener) => pageWindow == null ? void 0 : pageWindow.removeEventListener("pageshow", listener),
12364
+ addOnlineListener: (listener) => pageWindow == null ? void 0 : pageWindow.addEventListener("online", listener),
12365
+ removeOnlineListener: (listener) => pageWindow == null ? void 0 : pageWindow.removeEventListener("online", listener)
12366
+ };
12367
+ }
12368
+ function createAuthRenewalRecoveryController(retry, environment = createDefaultEnvironment$1()) {
12369
+ let pending = false;
12370
+ let retryInFlight = false;
12371
+ let rescheduleRequested = false;
12372
+ let retryAttempt = 0;
12373
+ let timerId = null;
12374
+ let listening = false;
12375
+ const clearTimer = () => {
12376
+ if (timerId === null) return;
12377
+ environment.clearTimeout(timerId);
12378
+ timerId = null;
12379
+ };
12380
+ const disarmSignals = () => {
12381
+ if (!listening) return;
12382
+ listening = false;
12383
+ environment.removeVisibilityChangeListener(handleForeground);
12384
+ environment.removePageShowListener(handleForeground);
12385
+ environment.removeOnlineListener(handleOnline);
12386
+ };
12387
+ const reset = () => {
12388
+ pending = false;
12389
+ retryAttempt = 0;
12390
+ rescheduleRequested = false;
12391
+ clearTimer();
12392
+ disarmSignals();
12393
+ };
12394
+ const requestRetry = (resetBudget, allowWhileHidden) => {
12395
+ if (!pending || retryInFlight || !allowWhileHidden && environment.isHidden()) {
12396
+ return;
12397
+ }
12398
+ if (resetBudget) retryAttempt = 0;
12399
+ clearTimer();
12400
+ retryInFlight = true;
12401
+ Promise.resolve().then(retry).catch((error) => {
12402
+ console.error("[rai-widget] Session renewal retry failed:", error);
12403
+ }).finally(() => {
12404
+ retryInFlight = false;
12405
+ if (rescheduleRequested) {
12406
+ rescheduleRequested = false;
12407
+ scheduleRetry();
12408
+ }
12409
+ });
12410
+ };
12411
+ function handleForeground() {
12412
+ if (environment.isHidden()) return;
12413
+ requestRetry(true, false);
12414
+ }
12415
+ function handleOnline() {
12416
+ requestRetry(true, true);
12417
+ }
12418
+ const armSignals = () => {
12419
+ if (listening) return;
12420
+ listening = true;
12421
+ environment.addVisibilityChangeListener(handleForeground);
12422
+ environment.addPageShowListener(handleForeground);
12423
+ environment.addOnlineListener(handleOnline);
12424
+ };
12425
+ const scheduleRetry = () => {
12426
+ if (retryInFlight && !pending) return;
12427
+ pending = true;
12428
+ armSignals();
12429
+ if (retryInFlight) {
12430
+ rescheduleRequested = true;
12431
+ return;
12432
+ }
12433
+ if (timerId !== null || environment.isHidden() || retryAttempt >= RETRY_DELAYS_MS.length) {
12434
+ return;
12435
+ }
12436
+ const delayMs = RETRY_DELAYS_MS[retryAttempt];
12437
+ retryAttempt += 1;
12438
+ timerId = environment.setTimeout(() => {
12439
+ timerId = null;
12440
+ requestRetry(false, false);
12441
+ }, delayMs);
12442
+ };
12443
+ return {
12444
+ schedule: scheduleRetry,
12445
+ succeeded: reset,
12446
+ cancel: reset
12447
+ };
12448
+ }
12346
12449
  function setTokens(config, state, data, onRefreshScheduled) {
12347
12450
  state.accessToken = data.accessToken;
12348
12451
  state.refreshToken = data.refreshToken;
@@ -12368,6 +12471,12 @@ function buildIdentityProof(config) {
12368
12471
  }
12369
12472
  return proof;
12370
12473
  }
12474
+ function calculateRefreshDelay(accessTokenExpiry, now = Date.now()) {
12475
+ const remainingLifetime = accessTokenExpiry - now;
12476
+ if (remainingLifetime <= 0) return 0;
12477
+ const refreshLeadTime = Math.min(6e4, remainingLifetime / 2);
12478
+ return Math.max(0, Math.floor(remainingLifetime - refreshLeadTime));
12479
+ }
12371
12480
  async function authenticateServerless(config, state, onRefreshScheduled) {
12372
12481
  const nonce = crypto.randomUUID();
12373
12482
  const timestamp = Date.now();
@@ -12380,6 +12489,7 @@ async function authenticateServerless(config, state, onRefreshScheduled) {
12380
12489
  );
12381
12490
  }
12382
12491
  let is4xx = false;
12492
+ let responseStatus = 0;
12383
12493
  try {
12384
12494
  const body = {
12385
12495
  nonce,
@@ -12393,6 +12503,7 @@ async function authenticateServerless(config, state, onRefreshScheduled) {
12393
12503
  body: JSON.stringify(body),
12394
12504
  credentials: "include"
12395
12505
  });
12506
+ responseStatus = response.status;
12396
12507
  if (!response.ok) {
12397
12508
  is4xx = response.status >= 400 && response.status < 500;
12398
12509
  const errorBody = await response.json().catch(() => ({ error: "Authentication failed" }));
@@ -12421,7 +12532,7 @@ async function authenticateServerless(config, state, onRefreshScheduled) {
12421
12532
  } catch (err) {
12422
12533
  if (is4xx || attempt === maxRetries) {
12423
12534
  state.lastAuthError ?? (state.lastAuthError = {
12424
- status: 0,
12535
+ status: responseStatus,
12425
12536
  error: err instanceof Error ? err.message : "Authentication failed"
12426
12537
  });
12427
12538
  state.isAuthenticated = false;
@@ -12435,6 +12546,15 @@ async function authenticateServerless(config, state, onRefreshScheduled) {
12435
12546
  async function authenticateViaProxy(config, state, onRefreshScheduled) {
12436
12547
  const maxRetries = config.maxRetries ?? 3;
12437
12548
  const retryDelay = config.retryDelay ?? 500;
12549
+ const previousAuthentication = {
12550
+ accessToken: state.accessToken,
12551
+ refreshToken: state.refreshToken,
12552
+ tokenFamily: state.tokenFamily,
12553
+ accessTokenExpiry: state.accessTokenExpiry,
12554
+ refreshTokenExpiry: state.refreshTokenExpiry,
12555
+ isAuthenticated: state.isAuthenticated,
12556
+ widgetData: state.widgetData
12557
+ };
12438
12558
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
12439
12559
  if (attempt > 0) {
12440
12560
  await new Promise(
@@ -12476,7 +12596,13 @@ async function authenticateViaProxy(config, state, onRefreshScheduled) {
12476
12596
  status,
12477
12597
  error: err instanceof Error ? err.message : "Authentication failed"
12478
12598
  };
12479
- state.isAuthenticated = false;
12599
+ if (isPermanentAuthFailure(state.lastAuthError)) {
12600
+ const permanentError = state.lastAuthError;
12601
+ clearAuthenticationData(state);
12602
+ state.lastAuthError = permanentError;
12603
+ } else {
12604
+ Object.assign(state, previousAuthentication);
12605
+ }
12480
12606
  return false;
12481
12607
  }
12482
12608
  }
@@ -12488,10 +12614,16 @@ async function refreshAccessToken(config, state, onRefreshScheduled, sendToken)
12488
12614
  if (state.isRefreshing) {
12489
12615
  return state.refreshPromise;
12490
12616
  }
12491
- if (!state.refreshToken) {
12492
- return false;
12493
- }
12494
12617
  const presentedRefreshToken = state.refreshToken;
12618
+ const previousAuthentication = {
12619
+ accessToken: state.accessToken,
12620
+ refreshToken: state.refreshToken,
12621
+ tokenFamily: state.tokenFamily,
12622
+ accessTokenExpiry: state.accessTokenExpiry,
12623
+ refreshTokenExpiry: state.refreshTokenExpiry,
12624
+ isAuthenticated: state.isAuthenticated,
12625
+ widgetData: state.widgetData
12626
+ };
12495
12627
  state.isRefreshing = true;
12496
12628
  state.refreshPromise = (async () => {
12497
12629
  const reauthenticateAfterRefreshFailure = async () => {
@@ -12500,13 +12632,22 @@ async function refreshAccessToken(config, state, onRefreshScheduled, sendToken)
12500
12632
  if (sendToken) sendToken();
12501
12633
  return true;
12502
12634
  }
12503
- clearAuthenticationData(state);
12504
- clearStorage(config);
12505
12635
  const authed = await authenticateServerless(config, state, onRefreshScheduled);
12506
12636
  if (authed && sendToken) sendToken();
12637
+ if (!authed && isPermanentAuthFailure(state.lastAuthError)) {
12638
+ const permanentError = state.lastAuthError;
12639
+ clearAuthenticationData(state);
12640
+ state.lastAuthError = permanentError;
12641
+ clearStorage(config);
12642
+ } else if (!authed) {
12643
+ Object.assign(state, previousAuthentication);
12644
+ }
12507
12645
  return authed;
12508
12646
  };
12509
12647
  try {
12648
+ if (!presentedRefreshToken) {
12649
+ return reauthenticateAfterRefreshFailure();
12650
+ }
12510
12651
  const response = await fetch(`${config.apiUrl}/${config.widgetId}/auth/refresh`, {
12511
12652
  method: "POST",
12512
12653
  headers: {
@@ -12737,11 +12878,12 @@ function captureSnapshot(state) {
12737
12878
  widgetData: state.widgetData
12738
12879
  };
12739
12880
  }
12740
- function applySnapshot(subscriber, snapshot) {
12881
+ function applySnapshot(subscriber, snapshot, notify = true) {
12741
12882
  var _a;
12742
12883
  Object.assign(subscriber.state, snapshot);
12743
12884
  if (snapshot.refreshToken) saveToStorage(subscriber.config, subscriber.state);
12744
12885
  else clearStorage(subscriber.config);
12886
+ if (!notify) return;
12745
12887
  try {
12746
12888
  (_a = subscriber.onSnapshot) == null ? void 0 : _a.call(subscriber);
12747
12889
  } catch (error) {
@@ -12786,7 +12928,7 @@ function subscribeAuthSession(config, state, onSnapshot) {
12786
12928
  return Promise.resolve(true);
12787
12929
  }
12788
12930
  if (session.inFlight) return session.inFlight;
12789
- if (session.snapshot) applySnapshot(subscriber, session.snapshot);
12931
+ if (session.snapshot) applySnapshot(subscriber, session.snapshot, false);
12790
12932
  const startingGeneration = session.generation;
12791
12933
  const inFlight = (async () => {
12792
12934
  const succeeded = await execute();
@@ -14151,7 +14293,11 @@ class BaseWidget extends HTMLElement {
14151
14293
  __publicField(this, "bundleUnmount");
14152
14294
  __publicField(this, "cancelBundleForegroundRecovery");
14153
14295
  __publicField(this, "authSession");
14296
+ __publicField(this, "authRenewalRecovery");
14154
14297
  this.shadow = this.attachShadow({ mode: "closed" });
14298
+ this.authRenewalRecovery = createAuthRenewalRecoveryController(
14299
+ () => this.performScheduledRefresh()
14300
+ );
14155
14301
  }
14156
14302
  static get observedAttributes() {
14157
14303
  return [
@@ -14211,6 +14357,7 @@ class BaseWidget extends HTMLElement {
14211
14357
  (_c = this.identityAttributeObserver) == null ? void 0 : _c.disconnect();
14212
14358
  (_d = this.cancelBundleForegroundRecovery) == null ? void 0 : _d.call(this);
14213
14359
  this.cancelBundleForegroundRecovery = void 0;
14360
+ this.authRenewalRecovery.cancel();
14214
14361
  this.teardownMountedWidget();
14215
14362
  this.clearLottieInstances();
14216
14363
  this.restoreLoaderHeight();
@@ -14819,6 +14966,7 @@ class BaseWidget extends HTMLElement {
14819
14966
  var _a, _b;
14820
14967
  (_a = this.cancelBundleForegroundRecovery) == null ? void 0 : _a.call(this);
14821
14968
  this.cancelBundleForegroundRecovery = void 0;
14969
+ this.authRenewalRecovery.cancel();
14822
14970
  const initId = ++this.initGeneration;
14823
14971
  this.hasAttemptedInit = true;
14824
14972
  if (!this.config.communityId) {
@@ -14827,6 +14975,9 @@ class BaseWidget extends HTMLElement {
14827
14975
  }
14828
14976
  if (!this.config.authUrl && !this.authSession) {
14829
14977
  this.authSession = subscribeAuthSession(this.config, this.state, () => {
14978
+ if (this.state.isAuthenticated && !this.state.lastAuthError) {
14979
+ this.authRenewalRecovery.succeeded();
14980
+ }
14830
14981
  if (this.config.autoRefresh) this.scheduleRefresh();
14831
14982
  if (this.state.iframe) {
14832
14983
  sendTokenToWidget(this.config, this.state, this.state.iframe);
@@ -15182,38 +15333,49 @@ class BaseWidget extends HTMLElement {
15182
15333
  scheduleRefresh() {
15183
15334
  if (this.state.refreshTimer) clearTimeout(this.state.refreshTimer);
15184
15335
  if (!this.state.accessTokenExpiry) return;
15185
- const delay = this.state.accessTokenExpiry - Date.now() - 6e4;
15336
+ const delay = calculateRefreshDelay(this.state.accessTokenExpiry);
15337
+ if (delay > 0) {
15338
+ this.state.refreshTimer = setTimeout(
15339
+ () => void this.performScheduledRefresh(),
15340
+ delay
15341
+ );
15342
+ } else {
15343
+ void this.performScheduledRefresh();
15344
+ }
15345
+ }
15346
+ async performScheduledRefresh() {
15347
+ this.state.refreshTimer = null;
15186
15348
  const pushToken = () => {
15187
15349
  if (this.state.iframe)
15188
15350
  sendTokenToWidget(this.config, this.state, this.state.iframe);
15189
15351
  syncBundleAccessToken(this.config, this.state);
15190
15352
  };
15191
- const doRefresh = async () => {
15192
- if (this.config.authUrl) {
15193
- const ok = await authenticateViaProxy(
15194
- this.config,
15195
- this.state,
15196
- () => this.scheduleRefresh()
15197
- );
15198
- if (ok) pushToken();
15199
- else this.handleSessionExpired();
15200
- } else {
15201
- const ok = this.authSession ? await this.authSession.run(
15202
- "refresh",
15203
- () => refreshAccessToken(this.config, this.state)
15204
- ) : await refreshAccessToken(
15205
- this.config,
15206
- this.state,
15207
- () => this.scheduleRefresh(),
15208
- pushToken
15209
- );
15210
- if (!ok) this.handleSessionExpired();
15211
- }
15212
- };
15213
- if (delay > 0) {
15214
- this.state.refreshTimer = setTimeout(doRefresh, delay);
15353
+ let ok;
15354
+ if (this.config.authUrl) {
15355
+ ok = await authenticateViaProxy(
15356
+ this.config,
15357
+ this.state,
15358
+ () => this.scheduleRefresh()
15359
+ );
15360
+ if (ok) pushToken();
15361
+ } else {
15362
+ ok = this.authSession ? await this.authSession.run(
15363
+ "refresh",
15364
+ () => refreshAccessToken(this.config, this.state)
15365
+ ) : await refreshAccessToken(
15366
+ this.config,
15367
+ this.state,
15368
+ () => this.scheduleRefresh(),
15369
+ pushToken
15370
+ );
15371
+ }
15372
+ if (ok) {
15373
+ this.authRenewalRecovery.succeeded();
15374
+ } else if (isPermanentAuthFailure(this.state.lastAuthError)) {
15375
+ this.authRenewalRecovery.cancel();
15376
+ this.handleSessionExpired();
15215
15377
  } else {
15216
- doRefresh();
15378
+ this.authRenewalRecovery.schedule();
15217
15379
  }
15218
15380
  }
15219
15381
  schedulePeriodicSync(iframe) {
@@ -15224,18 +15386,13 @@ class BaseWidget extends HTMLElement {
15224
15386
  }, 12e4);
15225
15387
  }
15226
15388
  /**
15227
- * A background refresh exhausted every recovery path — /auth/refresh failed
15228
- * and the re-auth that follows it failed too, so `state.isAuthenticated` is
15229
- * now false and there is no live token.
15230
- *
15231
- * Every startup auth path already calls showError() on failure; this one is
15232
- * reached from a timer, so without it the widget stays mounted showing stale
15233
- * content while isAuthenticated() reports false to the host page — which is
15234
- * how a signed-in user ends up looking at content meant for signed-out users.
15235
- * The event gives hosts a signal to re-mint credentials instead of polling.
15389
+ * A background refresh reached a confirmed permanent authentication failure
15390
+ * after exhausting its safe recovery paths. Transient transport, throttling,
15391
+ * and server failures are retained by authRenewalRecovery instead.
15236
15392
  */
15237
15393
  handleSessionExpired() {
15238
15394
  var _a;
15395
+ this.authRenewalRecovery.cancel();
15239
15396
  if (this.state.refreshTimer) {
15240
15397
  clearTimeout(this.state.refreshTimer);
15241
15398
  this.state.refreshTimer = null;
@@ -15255,6 +15412,7 @@ class BaseWidget extends HTMLElement {
15255
15412
  // ── Logout helper ─────────────────────────────────────────────────────
15256
15413
  async logoutAndClear() {
15257
15414
  var _a;
15415
+ this.authRenewalRecovery.cancel();
15258
15416
  await logout(this.config, this.state);
15259
15417
  (_a = this.authSession) == null ? void 0 : _a.clear();
15260
15418
  this.teardownMountedWidget();
@@ -15264,6 +15422,7 @@ class BaseWidget extends HTMLElement {
15264
15422
  // ── Public API ────────────────────────────────────────────────────────
15265
15423
  async reload() {
15266
15424
  var _a, _b;
15425
+ this.authRenewalRecovery.cancel();
15267
15426
  const previousConfig = this.config;
15268
15427
  (_a = this.authSession) == null ? void 0 : _a.release();
15269
15428
  this.authSession = void 0;
@@ -15411,7 +15570,7 @@ class CustomWidget extends BaseWidget {
15411
15570
  }
15412
15571
  }
15413
15572
  }
15414
- console.log(`[rai-widget] v${"1.8.5"}`);
15573
+ console.log(`[rai-widget] v${"1.8.6"}`);
15415
15574
  class StoreWidgetCompat extends StoreWidget {
15416
15575
  }
15417
15576
  const WIDGET_REGISTRY = [
@@ -15475,7 +15634,7 @@ function exposePublicApi() {
15475
15634
  })();
15476
15635
  const widget = container == null ? void 0 : container.querySelector(ALL_WIDGET_SELECTOR);
15477
15636
  window.ReturningAIWidget = {
15478
- version: "1.8.5",
15637
+ version: "1.8.6",
15479
15638
  reload: () => (widget == null ? void 0 : widget.reload()) ?? Promise.resolve(),
15480
15639
  logout: () => (widget == null ? void 0 : widget.logoutPublic()) ?? Promise.resolve(),
15481
15640
  isAuthenticated: () => (widget == null ? void 0 : widget.isAuthenticated()) ?? false,
@@ -24,6 +24,7 @@ export declare abstract class BaseWidget extends HTMLElement {
24
24
  private bundleUnmount?;
25
25
  private cancelBundleForegroundRecovery?;
26
26
  private authSession?;
27
+ private authRenewalRecovery;
27
28
  constructor();
28
29
  registerCallback<K extends keyof ReturningAIWidgetCallbackMap>(callbackName: K, callback: ReturningAIWidgetCallbackMap[K]): void;
29
30
  registerCallback(callbackName: string, callback: ReturningAIWidgetCallback): void;
@@ -111,17 +112,12 @@ export declare abstract class BaseWidget extends HTMLElement {
111
112
  private prepareBundleRuntimeEnvironment;
112
113
  private mountWidget;
113
114
  private scheduleRefresh;
115
+ private performScheduledRefresh;
114
116
  private schedulePeriodicSync;
115
117
  /**
116
- * A background refresh exhausted every recovery path — /auth/refresh failed
117
- * and the re-auth that follows it failed too, so `state.isAuthenticated` is
118
- * now false and there is no live token.
119
- *
120
- * Every startup auth path already calls showError() on failure; this one is
121
- * reached from a timer, so without it the widget stays mounted showing stale
122
- * content while isAuthenticated() reports false to the host page — which is
123
- * how a signed-in user ends up looking at content meant for signed-out users.
124
- * The event gives hosts a signal to re-mint credentials instead of polling.
118
+ * A background refresh reached a confirmed permanent authentication failure
119
+ * after exhausting its safe recovery paths. Transient transport, throttling,
120
+ * and server failures are retained by authRenewalRecovery instead.
125
121
  */
126
122
  private handleSessionExpired;
127
123
  private logoutAndClear;
@@ -0,0 +1,19 @@
1
+ import type { WidgetState } from "../types";
2
+ export interface AuthRenewalRecoveryEnvironment {
3
+ isHidden: () => boolean;
4
+ setTimeout: (callback: () => void, delayMs: number) => unknown;
5
+ clearTimeout: (timerId: unknown) => void;
6
+ addVisibilityChangeListener: (listener: () => void) => void;
7
+ removeVisibilityChangeListener: (listener: () => void) => void;
8
+ addPageShowListener: (listener: () => void) => void;
9
+ removePageShowListener: (listener: () => void) => void;
10
+ addOnlineListener: (listener: () => void) => void;
11
+ removeOnlineListener: (listener: () => void) => void;
12
+ }
13
+ export interface AuthRenewalRecoveryController {
14
+ schedule(): void;
15
+ succeeded(): void;
16
+ cancel(): void;
17
+ }
18
+ export declare function isPermanentAuthFailure(error: WidgetState["lastAuthError"]): boolean;
19
+ export declare function createAuthRenewalRecoveryController(retry: () => Promise<void> | void, environment?: AuthRenewalRecoveryEnvironment): AuthRenewalRecoveryController;
@@ -1,4 +1,5 @@
1
1
  import type { WidgetConfig, WidgetState } from '../types';
2
+ export declare function calculateRefreshDelay(accessTokenExpiry: number, now?: number): number;
2
3
  export declare function authenticateServerless(config: WidgetConfig, state: WidgetState, onRefreshScheduled?: () => void): Promise<boolean>;
3
4
  export declare function authenticateViaProxy(config: WidgetConfig, state: WidgetState, onRefreshScheduled?: () => void): Promise<boolean>;
4
5
  export declare function refreshAccessToken(config: WidgetConfig, state: WidgetState, onRefreshScheduled?: () => void, sendToken?: () => void): Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@returningai/widget-sdk",
3
- "version": "1.8.5",
3
+ "version": "1.8.6",
4
4
  "description": "Shadow DOM isolated widget SDK for ReturningAI",
5
5
  "main": "dist/rai-widget.iife.js",
6
6
  "module": "dist/rai-widget.js",
@@ -25,7 +25,7 @@
25
25
  "build:all": "npm run build && npm run build:banner",
26
26
  "build:all:min": "npm run build:min && npm run build:banner:min",
27
27
  "types": "tsc --emitDeclarationOnly --outDir dist/types && cp src/jsx.d.ts dist/types/jsx.d.ts",
28
- "test": "npm run test:host-callback && npm run test:bundle-readiness && npm run test:bundle-runtime-cache && npm run test:bundle-token-sync && npm run test:auth-bootstrap && npm run test:auth-error-reporting && npm run test:auth-refresh-state && npm run test:auth-session-coordinator && npm run test:startup-performance && npm run test:widget-error-presentation && npm run test:jsx-types",
28
+ "test": "npm run test:host-callback && npm run test:bundle-readiness && npm run test:bundle-runtime-cache && npm run test:bundle-token-sync && npm run test:auth-bootstrap && npm run test:auth-error-reporting && npm run test:auth-refresh-state && npm run test:auth-renewal-recovery && npm run test:auth-session-coordinator && npm run test:startup-performance && npm run test:widget-error-presentation && npm run test:jsx-types",
29
29
  "test:host-callback": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/postmessage-host-callback.test.js",
30
30
  "test:bundle-readiness": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/bundle-readiness.test.js",
31
31
  "test:bundle-runtime-cache": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/bundle-runtime-cache.test.js",
@@ -33,6 +33,7 @@
33
33
  "test:auth-bootstrap": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/auth-bootstrap.test.js",
34
34
  "test:auth-error-reporting": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/auth-error-reporting.test.js",
35
35
  "test:auth-refresh-state": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/auth-refresh-state.test.js",
36
+ "test:auth-renewal-recovery": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/auth-renewal-recovery.test.js",
36
37
  "test:auth-session-coordinator": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/auth-session-coordinator.test.js",
37
38
  "test:startup-performance": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/startup-performance.test.js",
38
39
  "test:widget-error-presentation": "rm -rf test/.tmp && tsc -p test/tsconfig.json && node test/.tmp/test/widget-error-presentation.test.js",