@feelflow/ffid-sdk 2.16.0 → 2.17.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.
@@ -810,10 +810,11 @@ function createProfileMethods(deps) {
810
810
  }
811
811
 
812
812
  // src/client/version-check.ts
813
- var SDK_VERSION = "2.16.0";
813
+ var SDK_VERSION = "2.17.1";
814
814
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
815
815
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
816
816
  function sdkHeaders() {
817
+ if (typeof window !== "undefined") return {};
817
818
  return {
818
819
  "User-Agent": SDK_USER_AGENT,
819
820
  [SDK_VERSION_HEADER]: SDK_VERSION
@@ -1264,6 +1265,9 @@ function createSessionMethods(deps) {
1264
1265
 
1265
1266
  // src/auth/pkce.ts
1266
1267
  var VERIFIER_STORAGE_KEY = "ffid_code_verifier";
1268
+ var VERIFIER_FALLBACK_STORAGE_KEY = "ffid_code_verifier_fb";
1269
+ var VERIFIER_FALLBACK_TIMESTAMP_KEY = "ffid_code_verifier_fb_ts";
1270
+ var CODE_VERIFIER_MAX_AGE_MS = 5 * 60 * 1e3;
1267
1271
  var CODE_VERIFIER_MIN_LENGTH = 43;
1268
1272
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1269
1273
  function generateCodeVerifier() {
@@ -1283,30 +1287,77 @@ async function generateCodeChallenge(verifier) {
1283
1287
  return base64UrlEncode(digest);
1284
1288
  }
1285
1289
  function storeCodeVerifier(verifier, logger) {
1290
+ if (typeof window === "undefined") {
1291
+ logger?.warn("storeCodeVerifier: storage is not available in SSR context");
1292
+ return false;
1293
+ }
1294
+ let sessionStored = false;
1286
1295
  try {
1287
- if (typeof window === "undefined") {
1288
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1289
- return false;
1290
- }
1291
1296
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1292
- return true;
1297
+ sessionStored = true;
1293
1298
  } catch (error) {
1294
1299
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1295
- return false;
1296
1300
  }
1301
+ let localStored = false;
1302
+ try {
1303
+ window.localStorage.setItem(VERIFIER_FALLBACK_STORAGE_KEY, verifier);
1304
+ window.localStorage.setItem(VERIFIER_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1305
+ localStored = true;
1306
+ } catch (error) {
1307
+ logger?.warn("storeCodeVerifier: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1308
+ }
1309
+ return sessionStored || localStored;
1297
1310
  }
1298
1311
  function retrieveCodeVerifier(logger) {
1312
+ if (typeof window === "undefined") return null;
1313
+ let sessionVerifier = null;
1299
1314
  try {
1300
- if (typeof window === "undefined") return null;
1301
- const verifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
1302
- if (verifier) {
1303
- window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
1304
- }
1305
- return verifier;
1315
+ sessionVerifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
1306
1316
  } catch (error) {
1307
1317
  logger?.warn("retrieveCodeVerifier: sessionStorage \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1318
+ }
1319
+ if (sessionVerifier) {
1320
+ cleanupVerifierStorage(logger);
1321
+ return sessionVerifier;
1322
+ }
1323
+ let fallbackVerifier = null;
1324
+ let fallbackTimestamp = null;
1325
+ try {
1326
+ fallbackVerifier = window.localStorage.getItem(VERIFIER_FALLBACK_STORAGE_KEY);
1327
+ fallbackTimestamp = window.localStorage.getItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1328
+ } catch (error) {
1329
+ logger?.warn("retrieveCodeVerifier: localStorage fallback \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1330
+ cleanupVerifierStorage(logger);
1331
+ return null;
1332
+ }
1333
+ if (!fallbackVerifier || !fallbackTimestamp) {
1334
+ cleanupVerifierStorage(logger);
1308
1335
  return null;
1309
1336
  }
1337
+ const ts = Number(fallbackTimestamp);
1338
+ const age = Date.now() - ts;
1339
+ if (!Number.isFinite(ts) || age < 0 || age > CODE_VERIFIER_MAX_AGE_MS) {
1340
+ cleanupVerifierStorage(logger);
1341
+ return null;
1342
+ }
1343
+ logger?.warn(
1344
+ "retrieveCodeVerifier: sessionStorage was empty, recovered code_verifier from localStorage fallback"
1345
+ );
1346
+ cleanupVerifierStorage(logger);
1347
+ return fallbackVerifier;
1348
+ }
1349
+ function cleanupVerifierStorage(logger) {
1350
+ try {
1351
+ window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
1352
+ } catch (error) {
1353
+ logger?.warn("retrieveCodeVerifier: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1354
+ }
1355
+ try {
1356
+ window.localStorage.removeItem(VERIFIER_FALLBACK_STORAGE_KEY);
1357
+ window.localStorage.removeItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1358
+ } catch (error) {
1359
+ logger?.warn("retrieveCodeVerifier: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1360
+ }
1310
1361
  }
1311
1362
  function base64UrlEncode(buffer) {
1312
1363
  const bytes = new Uint8Array(buffer);
@@ -2498,7 +2549,7 @@ function FFIDProvider({
2498
2549
  const code = urlParams.get("code");
2499
2550
  if (!code) return;
2500
2551
  client.logger.debug("Authorization code detected, exchanging for tokens");
2501
- const codeVerifier = retrieveCodeVerifier();
2552
+ const codeVerifier = retrieveCodeVerifier(client.logger);
2502
2553
  client.exchangeCodeForTokens(code, codeVerifier ?? void 0).then((result) => {
2503
2554
  if (result.error) {
2504
2555
  client.logger.error("Token exchange failed:", result.error);
@@ -808,10 +808,11 @@ function createProfileMethods(deps) {
808
808
  }
809
809
 
810
810
  // src/client/version-check.ts
811
- var SDK_VERSION = "2.16.0";
811
+ var SDK_VERSION = "2.17.1";
812
812
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
813
813
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
814
814
  function sdkHeaders() {
815
+ if (typeof window !== "undefined") return {};
815
816
  return {
816
817
  "User-Agent": SDK_USER_AGENT,
817
818
  [SDK_VERSION_HEADER]: SDK_VERSION
@@ -1262,6 +1263,9 @@ function createSessionMethods(deps) {
1262
1263
 
1263
1264
  // src/auth/pkce.ts
1264
1265
  var VERIFIER_STORAGE_KEY = "ffid_code_verifier";
1266
+ var VERIFIER_FALLBACK_STORAGE_KEY = "ffid_code_verifier_fb";
1267
+ var VERIFIER_FALLBACK_TIMESTAMP_KEY = "ffid_code_verifier_fb_ts";
1268
+ var CODE_VERIFIER_MAX_AGE_MS = 5 * 60 * 1e3;
1265
1269
  var CODE_VERIFIER_MIN_LENGTH = 43;
1266
1270
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1267
1271
  function generateCodeVerifier() {
@@ -1281,30 +1285,77 @@ async function generateCodeChallenge(verifier) {
1281
1285
  return base64UrlEncode(digest);
1282
1286
  }
1283
1287
  function storeCodeVerifier(verifier, logger) {
1288
+ if (typeof window === "undefined") {
1289
+ logger?.warn("storeCodeVerifier: storage is not available in SSR context");
1290
+ return false;
1291
+ }
1292
+ let sessionStored = false;
1284
1293
  try {
1285
- if (typeof window === "undefined") {
1286
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1287
- return false;
1288
- }
1289
1294
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1290
- return true;
1295
+ sessionStored = true;
1291
1296
  } catch (error) {
1292
1297
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1293
- return false;
1294
1298
  }
1299
+ let localStored = false;
1300
+ try {
1301
+ window.localStorage.setItem(VERIFIER_FALLBACK_STORAGE_KEY, verifier);
1302
+ window.localStorage.setItem(VERIFIER_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1303
+ localStored = true;
1304
+ } catch (error) {
1305
+ logger?.warn("storeCodeVerifier: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1306
+ }
1307
+ return sessionStored || localStored;
1295
1308
  }
1296
1309
  function retrieveCodeVerifier(logger) {
1310
+ if (typeof window === "undefined") return null;
1311
+ let sessionVerifier = null;
1297
1312
  try {
1298
- if (typeof window === "undefined") return null;
1299
- const verifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
1300
- if (verifier) {
1301
- window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
1302
- }
1303
- return verifier;
1313
+ sessionVerifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
1304
1314
  } catch (error) {
1305
1315
  logger?.warn("retrieveCodeVerifier: sessionStorage \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1316
+ }
1317
+ if (sessionVerifier) {
1318
+ cleanupVerifierStorage(logger);
1319
+ return sessionVerifier;
1320
+ }
1321
+ let fallbackVerifier = null;
1322
+ let fallbackTimestamp = null;
1323
+ try {
1324
+ fallbackVerifier = window.localStorage.getItem(VERIFIER_FALLBACK_STORAGE_KEY);
1325
+ fallbackTimestamp = window.localStorage.getItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1326
+ } catch (error) {
1327
+ logger?.warn("retrieveCodeVerifier: localStorage fallback \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1328
+ cleanupVerifierStorage(logger);
1329
+ return null;
1330
+ }
1331
+ if (!fallbackVerifier || !fallbackTimestamp) {
1332
+ cleanupVerifierStorage(logger);
1306
1333
  return null;
1307
1334
  }
1335
+ const ts = Number(fallbackTimestamp);
1336
+ const age = Date.now() - ts;
1337
+ if (!Number.isFinite(ts) || age < 0 || age > CODE_VERIFIER_MAX_AGE_MS) {
1338
+ cleanupVerifierStorage(logger);
1339
+ return null;
1340
+ }
1341
+ logger?.warn(
1342
+ "retrieveCodeVerifier: sessionStorage was empty, recovered code_verifier from localStorage fallback"
1343
+ );
1344
+ cleanupVerifierStorage(logger);
1345
+ return fallbackVerifier;
1346
+ }
1347
+ function cleanupVerifierStorage(logger) {
1348
+ try {
1349
+ window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
1350
+ } catch (error) {
1351
+ logger?.warn("retrieveCodeVerifier: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1352
+ }
1353
+ try {
1354
+ window.localStorage.removeItem(VERIFIER_FALLBACK_STORAGE_KEY);
1355
+ window.localStorage.removeItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1356
+ } catch (error) {
1357
+ logger?.warn("retrieveCodeVerifier: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1358
+ }
1308
1359
  }
1309
1360
  function base64UrlEncode(buffer) {
1310
1361
  const bytes = new Uint8Array(buffer);
@@ -2496,7 +2547,7 @@ function FFIDProvider({
2496
2547
  const code = urlParams.get("code");
2497
2548
  if (!code) return;
2498
2549
  client.logger.debug("Authorization code detected, exchanging for tokens");
2499
- const codeVerifier = retrieveCodeVerifier();
2550
+ const codeVerifier = retrieveCodeVerifier(client.logger);
2500
2551
  client.exchangeCodeForTokens(code, codeVerifier ?? void 0).then((result) => {
2501
2552
  if (result.error) {
2502
2553
  client.logger.error("Token exchange failed:", result.error);
@@ -1,34 +1,34 @@
1
1
  'use strict';
2
2
 
3
- var chunkPA6S2M7C_cjs = require('../chunk-PA6S2M7C.cjs');
3
+ var chunkDERFBYBZ_cjs = require('../chunk-DERFBYBZ.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkDERFBYBZ_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkDERFBYBZ_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDInquiryForm", {
16
16
  enumerable: true,
17
- get: function () { return chunkPA6S2M7C_cjs.FFIDInquiryForm; }
17
+ get: function () { return chunkDERFBYBZ_cjs.FFIDInquiryForm; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDLoginButton", {
20
20
  enumerable: true,
21
- get: function () { return chunkPA6S2M7C_cjs.FFIDLoginButton; }
21
+ get: function () { return chunkDERFBYBZ_cjs.FFIDLoginButton; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
24
24
  enumerable: true,
25
- get: function () { return chunkPA6S2M7C_cjs.FFIDOrganizationSwitcher; }
25
+ get: function () { return chunkDERFBYBZ_cjs.FFIDOrganizationSwitcher; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
28
28
  enumerable: true,
29
- get: function () { return chunkPA6S2M7C_cjs.FFIDSubscriptionBadge; }
29
+ get: function () { return chunkDERFBYBZ_cjs.FFIDSubscriptionBadge; }
30
30
  });
31
31
  Object.defineProperty(exports, "FFIDUserMenu", {
32
32
  enumerable: true,
33
- get: function () { return chunkPA6S2M7C_cjs.FFIDUserMenu; }
33
+ get: function () { return chunkDERFBYBZ_cjs.FFIDUserMenu; }
34
34
  });
@@ -1,3 +1,3 @@
1
- export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-DbEyptzr.cjs';
1
+ export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-Cv1qXIl1.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-DbEyptzr.js';
1
+ export { K as FFIDAnnouncementBadge, aj as FFIDAnnouncementBadgeClassNames, ak as FFIDAnnouncementBadgeProps, M as FFIDAnnouncementList, al as FFIDAnnouncementListClassNames, am as FFIDAnnouncementListProps, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a2 as FFIDLoginButton, an as FFIDLoginButtonProps, a8 as FFIDOrganizationSwitcher, ao as FFIDOrganizationSwitcherClassNames, ap as FFIDOrganizationSwitcherProps, aa as FFIDSubscriptionBadge, aq as FFIDSubscriptionBadgeClassNames, ar as FFIDSubscriptionBadgeProps, ac as FFIDUserMenu, as as FFIDUserMenuClassNames, at as FFIDUserMenuProps } from '../index-Cv1qXIl1.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-4IWCKZJV.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-FGTRPNSW.js';
@@ -471,8 +471,11 @@ interface FFIDUserProfile {
471
471
  * When `accessToken` is supplied with a non-empty value, it overrides the client's
472
472
  * configured auth mode: authentication for that request uses only
473
473
  * `Authorization: Bearer <accessToken>` (no service key, no cookie, no token-store
474
- * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` and
475
- * SDK metadata headers (User-Agent / X-FFID-SDK-Version) are still attached.
474
+ * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` are
475
+ * still attached. SDK metadata headers (`User-Agent` / `X-FFID-SDK-Version`) are
476
+ * attached on non-browser runtimes only (Node.js / Cloudflare Workers / Edge /
477
+ * Deno); browsers receive an empty object to avoid iOS WebKit `fetch()` breakage
478
+ * (see #2417).
476
479
  *
477
480
  * Runtime semantics:
478
481
  * - `accessToken` omitted (or `undefined`) → no override, configured `authMode` is used
@@ -471,8 +471,11 @@ interface FFIDUserProfile {
471
471
  * When `accessToken` is supplied with a non-empty value, it overrides the client's
472
472
  * configured auth mode: authentication for that request uses only
473
473
  * `Authorization: Bearer <accessToken>` (no service key, no cookie, no token-store
474
- * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` and
475
- * SDK metadata headers (User-Agent / X-FFID-SDK-Version) are still attached.
474
+ * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` are
475
+ * still attached. SDK metadata headers (`User-Agent` / `X-FFID-SDK-Version`) are
476
+ * attached on non-browser runtimes only (Node.js / Cloudflare Workers / Edge /
477
+ * Deno); browsers receive an empty object to avoid iOS WebKit `fetch()` breakage
478
+ * (see #2417).
476
479
  *
477
480
  * Runtime semantics:
478
481
  * - `accessToken` omitted (or `undefined`) → no override, configured `authMode` is used
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkPA6S2M7C_cjs = require('./chunk-PA6S2M7C.cjs');
3
+ var chunkDERFBYBZ_cjs = require('./chunk-DERFBYBZ.cjs');
4
4
  var react = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
 
@@ -46,7 +46,7 @@ function createKVCacheAdapter(kv) {
46
46
  }
47
47
  function withFFIDAuth(Component, options = {}) {
48
48
  const WrappedComponent = (props) => {
49
- const { isLoading, isAuthenticated, login } = chunkPA6S2M7C_cjs.useFFIDContext();
49
+ const { isLoading, isAuthenticated, login } = chunkDERFBYBZ_cjs.useFFIDContext();
50
50
  const hasRedirected = react.useRef(false);
51
51
  react.useEffect(() => {
52
52
  if (!isLoading && !isAuthenticated && options.redirectToLogin && !hasRedirected.current) {
@@ -74,107 +74,107 @@ var FFID_NEWSLETTER_TYPES = ["inquiry_followup", "general"];
74
74
 
75
75
  Object.defineProperty(exports, "DEFAULT_API_BASE_URL", {
76
76
  enumerable: true,
77
- get: function () { return chunkPA6S2M7C_cjs.DEFAULT_API_BASE_URL; }
77
+ get: function () { return chunkDERFBYBZ_cjs.DEFAULT_API_BASE_URL; }
78
78
  });
79
79
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
80
80
  enumerable: true,
81
- get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementBadge; }
81
+ get: function () { return chunkDERFBYBZ_cjs.FFIDAnnouncementBadge; }
82
82
  });
83
83
  Object.defineProperty(exports, "FFIDAnnouncementList", {
84
84
  enumerable: true,
85
- get: function () { return chunkPA6S2M7C_cjs.FFIDAnnouncementList; }
85
+ get: function () { return chunkDERFBYBZ_cjs.FFIDAnnouncementList; }
86
86
  });
87
87
  Object.defineProperty(exports, "FFIDInquiryForm", {
88
88
  enumerable: true,
89
- get: function () { return chunkPA6S2M7C_cjs.FFIDInquiryForm; }
89
+ get: function () { return chunkDERFBYBZ_cjs.FFIDInquiryForm; }
90
90
  });
91
91
  Object.defineProperty(exports, "FFIDLoginButton", {
92
92
  enumerable: true,
93
- get: function () { return chunkPA6S2M7C_cjs.FFIDLoginButton; }
93
+ get: function () { return chunkDERFBYBZ_cjs.FFIDLoginButton; }
94
94
  });
95
95
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
96
96
  enumerable: true,
97
- get: function () { return chunkPA6S2M7C_cjs.FFIDOrganizationSwitcher; }
97
+ get: function () { return chunkDERFBYBZ_cjs.FFIDOrganizationSwitcher; }
98
98
  });
99
99
  Object.defineProperty(exports, "FFIDProvider", {
100
100
  enumerable: true,
101
- get: function () { return chunkPA6S2M7C_cjs.FFIDProvider; }
101
+ get: function () { return chunkDERFBYBZ_cjs.FFIDProvider; }
102
102
  });
103
103
  Object.defineProperty(exports, "FFIDSDKError", {
104
104
  enumerable: true,
105
- get: function () { return chunkPA6S2M7C_cjs.FFIDSDKError; }
105
+ get: function () { return chunkDERFBYBZ_cjs.FFIDSDKError; }
106
106
  });
107
107
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
108
108
  enumerable: true,
109
- get: function () { return chunkPA6S2M7C_cjs.FFIDSubscriptionBadge; }
109
+ get: function () { return chunkDERFBYBZ_cjs.FFIDSubscriptionBadge; }
110
110
  });
111
111
  Object.defineProperty(exports, "FFIDUserMenu", {
112
112
  enumerable: true,
113
- get: function () { return chunkPA6S2M7C_cjs.FFIDUserMenu; }
113
+ get: function () { return chunkDERFBYBZ_cjs.FFIDUserMenu; }
114
114
  });
115
115
  Object.defineProperty(exports, "FFID_ANNOUNCEMENTS_ERROR_CODES", {
116
116
  enumerable: true,
117
- get: function () { return chunkPA6S2M7C_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
117
+ get: function () { return chunkDERFBYBZ_cjs.FFID_ANNOUNCEMENTS_ERROR_CODES; }
118
118
  });
119
119
  Object.defineProperty(exports, "FFID_INQUIRY_CATEGORIES", {
120
120
  enumerable: true,
121
- get: function () { return chunkPA6S2M7C_cjs.FFID_INQUIRY_CATEGORIES; }
121
+ get: function () { return chunkDERFBYBZ_cjs.FFID_INQUIRY_CATEGORIES; }
122
122
  });
123
123
  Object.defineProperty(exports, "FFID_INQUIRY_CATEGORIES_SITE_2026", {
124
124
  enumerable: true,
125
- get: function () { return chunkPA6S2M7C_cjs.FFID_INQUIRY_CATEGORIES_SITE_2026; }
125
+ get: function () { return chunkDERFBYBZ_cjs.FFID_INQUIRY_CATEGORIES_SITE_2026; }
126
126
  });
127
127
  Object.defineProperty(exports, "createFFIDAnnouncementsClient", {
128
128
  enumerable: true,
129
- get: function () { return chunkPA6S2M7C_cjs.createFFIDAnnouncementsClient; }
129
+ get: function () { return chunkDERFBYBZ_cjs.createFFIDAnnouncementsClient; }
130
130
  });
131
131
  Object.defineProperty(exports, "createFFIDClient", {
132
132
  enumerable: true,
133
- get: function () { return chunkPA6S2M7C_cjs.createFFIDClient; }
133
+ get: function () { return chunkDERFBYBZ_cjs.createFFIDClient; }
134
134
  });
135
135
  Object.defineProperty(exports, "createTokenStore", {
136
136
  enumerable: true,
137
- get: function () { return chunkPA6S2M7C_cjs.createTokenStore; }
137
+ get: function () { return chunkDERFBYBZ_cjs.createTokenStore; }
138
138
  });
139
139
  Object.defineProperty(exports, "generateCodeChallenge", {
140
140
  enumerable: true,
141
- get: function () { return chunkPA6S2M7C_cjs.generateCodeChallenge; }
141
+ get: function () { return chunkDERFBYBZ_cjs.generateCodeChallenge; }
142
142
  });
143
143
  Object.defineProperty(exports, "generateCodeVerifier", {
144
144
  enumerable: true,
145
- get: function () { return chunkPA6S2M7C_cjs.generateCodeVerifier; }
145
+ get: function () { return chunkDERFBYBZ_cjs.generateCodeVerifier; }
146
146
  });
147
147
  Object.defineProperty(exports, "isFFIDInquiryCategorySite2026", {
148
148
  enumerable: true,
149
- get: function () { return chunkPA6S2M7C_cjs.isFFIDInquiryCategorySite2026; }
149
+ get: function () { return chunkDERFBYBZ_cjs.isFFIDInquiryCategorySite2026; }
150
150
  });
151
151
  Object.defineProperty(exports, "normalizeRedirectUri", {
152
152
  enumerable: true,
153
- get: function () { return chunkPA6S2M7C_cjs.normalizeRedirectUri; }
153
+ get: function () { return chunkDERFBYBZ_cjs.normalizeRedirectUri; }
154
154
  });
155
155
  Object.defineProperty(exports, "retrieveCodeVerifier", {
156
156
  enumerable: true,
157
- get: function () { return chunkPA6S2M7C_cjs.retrieveCodeVerifier; }
157
+ get: function () { return chunkDERFBYBZ_cjs.retrieveCodeVerifier; }
158
158
  });
159
159
  Object.defineProperty(exports, "storeCodeVerifier", {
160
160
  enumerable: true,
161
- get: function () { return chunkPA6S2M7C_cjs.storeCodeVerifier; }
161
+ get: function () { return chunkDERFBYBZ_cjs.storeCodeVerifier; }
162
162
  });
163
163
  Object.defineProperty(exports, "useFFID", {
164
164
  enumerable: true,
165
- get: function () { return chunkPA6S2M7C_cjs.useFFID; }
165
+ get: function () { return chunkDERFBYBZ_cjs.useFFID; }
166
166
  });
167
167
  Object.defineProperty(exports, "useFFIDAnnouncements", {
168
168
  enumerable: true,
169
- get: function () { return chunkPA6S2M7C_cjs.useFFIDAnnouncements; }
169
+ get: function () { return chunkDERFBYBZ_cjs.useFFIDAnnouncements; }
170
170
  });
171
171
  Object.defineProperty(exports, "useSubscription", {
172
172
  enumerable: true,
173
- get: function () { return chunkPA6S2M7C_cjs.useSubscription; }
173
+ get: function () { return chunkDERFBYBZ_cjs.useSubscription; }
174
174
  });
175
175
  Object.defineProperty(exports, "withSubscription", {
176
176
  enumerable: true,
177
- get: function () { return chunkPA6S2M7C_cjs.withSubscription; }
177
+ get: function () { return chunkDERFBYBZ_cjs.withSubscription; }
178
178
  });
179
179
  exports.FFID_NEWSLETTER_TYPES = FFID_NEWSLETTER_TYPES;
180
180
  exports.createKVCacheAdapter = createKVCacheAdapter;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-DbEyptzr.cjs';
2
- export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-DbEyptzr.cjs';
1
+ import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-Cv1qXIl1.cjs';
2
+ export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-Cv1qXIl1.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, ComponentType, FC } from 'react';
5
5
 
@@ -73,20 +73,23 @@ interface PKCELogger {
73
73
  warn: (...args: unknown[]) => void;
74
74
  }
75
75
  /**
76
- * Store code verifier in sessionStorage for later retrieval.
77
- * Uses window.sessionStorage explicitly to ensure browser Web Storage API.
76
+ * Store code verifier for later retrieval.
77
+ *
78
+ * Writes to both sessionStorage (primary) and localStorage (fallback for iOS
79
+ * WebKit sessionStorage eviction during external OAuth bounces). Returns true
80
+ * if at least one write succeeded.
78
81
  *
79
82
  * @param verifier - The code verifier to store
80
83
  * @param logger - Optional logger for warning on storage failure
81
- * @returns true if stored successfully, false otherwise
84
+ * @returns true if stored in at least one storage, false otherwise
82
85
  */
83
86
  declare function storeCodeVerifier(verifier: string, logger?: PKCELogger): boolean;
84
87
  /**
85
- * Retrieve and remove the code verifier from sessionStorage.
86
- * Uses window.sessionStorage explicitly to ensure browser Web Storage API.
88
+ * Retrieve and remove the code verifier.
87
89
  *
88
- * Returns null if no verifier is stored or if storage is unavailable.
89
- * Removes the verifier after retrieval (one-time use).
90
+ * Reads from sessionStorage first, falls back to localStorage (with 5-minute TTL).
91
+ * Removes from all storages after retrieval (one-time use). Returns null if no
92
+ * verifier is stored, the fallback is stale (>5 min), or storage is unavailable.
90
93
  *
91
94
  * @param logger - Optional logger for warning on storage failure
92
95
  */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-DbEyptzr.js';
2
- export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-DbEyptzr.js';
1
+ import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDListMembersResponse, h as FFIDMemberRole, i as FFIDUpdateMemberRoleResponse, j as FFIDRemoveMemberResponse, k as FFIDProfileCallOptions, l as FFIDUserProfile, m as FFIDUpdateUserProfileRequest, n as FFIDCreateCheckoutParams, o as FFIDCheckoutSessionResponse, p as FFIDCreatePortalParams, q as FFIDPortalSessionResponse, r as FFIDVerifyAccessTokenOptions, s as FFIDOAuthUserInfo, t as FFIDInquiryCreateParams, u as FFIDInquiryCreateResponse, v as FFIDAuthMode, w as FFIDLogger, x as FFIDCacheAdapter, y as FFIDUser, z as FFIDOrganization, A as FFIDSubscription, B as FFIDSubscriptionContextValue, C as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, D as FFIDAnnouncementsApiResponse, E as AnnouncementListResponse, G as FFIDAnnouncementsLogger } from './index-Cv1qXIl1.js';
2
+ export { H as Announcement, I as AnnouncementStatus, J as AnnouncementType, K as FFIDAnnouncementBadge, M as FFIDAnnouncementList, N as FFIDAnnouncementsError, O as FFIDAnnouncementsErrorCode, P as FFIDAnnouncementsServerResponse, Q as FFIDCacheConfig, R as FFIDContextValue, S as FFIDInquiryCategory, T as FFIDInquiryCategorySite2026, U as FFIDInquiryForm, V as FFIDInquiryFormCategoryItem, W as FFIDInquiryFormClassNames, X as FFIDInquiryFormOrganization, Y as FFIDInquiryFormPlaceholderContext, Z as FFIDInquiryFormPrefill, _ as FFIDInquiryFormProps, $ as FFIDInquiryFormSubmitData, a0 as FFIDInquiryFormSubmitResult, a1 as FFIDJwtClaims, a2 as FFIDLoginButton, a3 as FFIDMemberStatus, a4 as FFIDOAuthTokenResponse, a5 as FFIDOAuthUserInfoMemberRole, a6 as FFIDOAuthUserInfoSubscription, a7 as FFIDOrganizationMember, a8 as FFIDOrganizationSwitcher, a9 as FFIDSeatModel, aa as FFIDSubscriptionBadge, ab as FFIDTokenIntrospectionResponse, ac as FFIDUserMenu, ad as FFID_INQUIRY_CATEGORIES, ae as FFID_INQUIRY_CATEGORIES_SITE_2026, af as UseFFIDAnnouncementsOptions, ag as UseFFIDAnnouncementsReturn, ah as isFFIDInquiryCategorySite2026, ai as useFFIDAnnouncements } from './index-Cv1qXIl1.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import { ReactNode, ComponentType, FC } from 'react';
5
5
 
@@ -73,20 +73,23 @@ interface PKCELogger {
73
73
  warn: (...args: unknown[]) => void;
74
74
  }
75
75
  /**
76
- * Store code verifier in sessionStorage for later retrieval.
77
- * Uses window.sessionStorage explicitly to ensure browser Web Storage API.
76
+ * Store code verifier for later retrieval.
77
+ *
78
+ * Writes to both sessionStorage (primary) and localStorage (fallback for iOS
79
+ * WebKit sessionStorage eviction during external OAuth bounces). Returns true
80
+ * if at least one write succeeded.
78
81
  *
79
82
  * @param verifier - The code verifier to store
80
83
  * @param logger - Optional logger for warning on storage failure
81
- * @returns true if stored successfully, false otherwise
84
+ * @returns true if stored in at least one storage, false otherwise
82
85
  */
83
86
  declare function storeCodeVerifier(verifier: string, logger?: PKCELogger): boolean;
84
87
  /**
85
- * Retrieve and remove the code verifier from sessionStorage.
86
- * Uses window.sessionStorage explicitly to ensure browser Web Storage API.
88
+ * Retrieve and remove the code verifier.
87
89
  *
88
- * Returns null if no verifier is stored or if storage is unavailable.
89
- * Removes the verifier after retrieval (one-time use).
90
+ * Reads from sessionStorage first, falls back to localStorage (with 5-minute TTL).
91
+ * Removes from all storages after retrieval (one-time use). Returns null if no
92
+ * verifier is stored, the fallback is stale (>5 min), or storage is unavailable.
90
93
  *
91
94
  * @param logger - Optional logger for warning on storage failure
92
95
  */
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useFFIDContext } from './chunk-4IWCKZJV.js';
2
- export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-4IWCKZJV.js';
1
+ import { useFFIDContext } from './chunk-FGTRPNSW.js';
2
+ export { DEFAULT_API_BASE_URL, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-FGTRPNSW.js';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -806,10 +806,11 @@ function createProfileMethods(deps) {
806
806
  }
807
807
 
808
808
  // src/client/version-check.ts
809
- var SDK_VERSION = "2.16.0";
809
+ var SDK_VERSION = "2.17.1";
810
810
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
811
811
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
812
812
  function sdkHeaders() {
813
+ if (typeof window !== "undefined") return {};
813
814
  return {
814
815
  "User-Agent": SDK_USER_AGENT,
815
816
  [SDK_VERSION_HEADER]: SDK_VERSION
@@ -1260,6 +1261,8 @@ function createSessionMethods(deps) {
1260
1261
 
1261
1262
  // src/auth/pkce.ts
1262
1263
  var VERIFIER_STORAGE_KEY = "ffid_code_verifier";
1264
+ var VERIFIER_FALLBACK_STORAGE_KEY = "ffid_code_verifier_fb";
1265
+ var VERIFIER_FALLBACK_TIMESTAMP_KEY = "ffid_code_verifier_fb_ts";
1263
1266
  var CODE_VERIFIER_MIN_LENGTH = 43;
1264
1267
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1265
1268
  function generateCodeVerifier() {
@@ -1279,17 +1282,26 @@ async function generateCodeChallenge(verifier) {
1279
1282
  return base64UrlEncode(digest);
1280
1283
  }
1281
1284
  function storeCodeVerifier(verifier, logger) {
1285
+ if (typeof window === "undefined") {
1286
+ logger?.warn("storeCodeVerifier: storage is not available in SSR context");
1287
+ return false;
1288
+ }
1289
+ let sessionStored = false;
1282
1290
  try {
1283
- if (typeof window === "undefined") {
1284
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1285
- return false;
1286
- }
1287
1291
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1288
- return true;
1292
+ sessionStored = true;
1289
1293
  } catch (error) {
1290
1294
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1291
- return false;
1292
1295
  }
1296
+ let localStored = false;
1297
+ try {
1298
+ window.localStorage.setItem(VERIFIER_FALLBACK_STORAGE_KEY, verifier);
1299
+ window.localStorage.setItem(VERIFIER_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1300
+ localStored = true;
1301
+ } catch (error) {
1302
+ logger?.warn("storeCodeVerifier: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1303
+ }
1304
+ return sessionStored || localStored;
1293
1305
  }
1294
1306
  function base64UrlEncode(buffer) {
1295
1307
  const bytes = new Uint8Array(buffer);
@@ -825,8 +825,11 @@ interface FFIDUserProfile {
825
825
  * When `accessToken` is supplied with a non-empty value, it overrides the client's
826
826
  * configured auth mode: authentication for that request uses only
827
827
  * `Authorization: Bearer <accessToken>` (no service key, no cookie, no token-store
828
- * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` and
829
- * SDK metadata headers (User-Agent / X-FFID-SDK-Version) are still attached.
828
+ * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` are
829
+ * still attached. SDK metadata headers (`User-Agent` / `X-FFID-SDK-Version`) are
830
+ * attached on non-browser runtimes only (Node.js / Cloudflare Workers / Edge /
831
+ * Deno); browsers receive an empty object to avoid iOS WebKit `fetch()` breakage
832
+ * (see #2417).
830
833
  *
831
834
  * Runtime semantics:
832
835
  * - `accessToken` omitted (or `undefined`) → no override, configured `authMode` is used
@@ -825,8 +825,11 @@ interface FFIDUserProfile {
825
825
  * When `accessToken` is supplied with a non-empty value, it overrides the client's
826
826
  * configured auth mode: authentication for that request uses only
827
827
  * `Authorization: Bearer <accessToken>` (no service key, no cookie, no token-store
828
- * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` and
829
- * SDK metadata headers (User-Agent / X-FFID-SDK-Version) are still attached.
828
+ * lookup, no auto-refresh on 401). Non-auth headers such as `Content-Type` are
829
+ * still attached. SDK metadata headers (`User-Agent` / `X-FFID-SDK-Version`) are
830
+ * attached on non-browser runtimes only (Node.js / Cloudflare Workers / Edge /
831
+ * Deno); browsers receive an empty object to avoid iOS WebKit `fetch()` breakage
832
+ * (see #2417).
830
833
  *
831
834
  * Runtime semantics:
832
835
  * - `accessToken` omitted (or `undefined`) → no override, configured `authMode` is used
@@ -805,10 +805,11 @@ function createProfileMethods(deps) {
805
805
  }
806
806
 
807
807
  // src/client/version-check.ts
808
- var SDK_VERSION = "2.16.0";
808
+ var SDK_VERSION = "2.17.1";
809
809
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
810
810
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
811
811
  function sdkHeaders() {
812
+ if (typeof window !== "undefined") return {};
812
813
  return {
813
814
  "User-Agent": SDK_USER_AGENT,
814
815
  [SDK_VERSION_HEADER]: SDK_VERSION
@@ -1259,6 +1260,8 @@ function createSessionMethods(deps) {
1259
1260
 
1260
1261
  // src/auth/pkce.ts
1261
1262
  var VERIFIER_STORAGE_KEY = "ffid_code_verifier";
1263
+ var VERIFIER_FALLBACK_STORAGE_KEY = "ffid_code_verifier_fb";
1264
+ var VERIFIER_FALLBACK_TIMESTAMP_KEY = "ffid_code_verifier_fb_ts";
1262
1265
  var CODE_VERIFIER_MIN_LENGTH = 43;
1263
1266
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1264
1267
  function generateCodeVerifier() {
@@ -1278,17 +1281,26 @@ async function generateCodeChallenge(verifier) {
1278
1281
  return base64UrlEncode(digest);
1279
1282
  }
1280
1283
  function storeCodeVerifier(verifier, logger) {
1284
+ if (typeof window === "undefined") {
1285
+ logger?.warn("storeCodeVerifier: storage is not available in SSR context");
1286
+ return false;
1287
+ }
1288
+ let sessionStored = false;
1281
1289
  try {
1282
- if (typeof window === "undefined") {
1283
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1284
- return false;
1285
- }
1286
1290
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1287
- return true;
1291
+ sessionStored = true;
1288
1292
  } catch (error) {
1289
1293
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1290
- return false;
1291
1294
  }
1295
+ let localStored = false;
1296
+ try {
1297
+ window.localStorage.setItem(VERIFIER_FALLBACK_STORAGE_KEY, verifier);
1298
+ window.localStorage.setItem(VERIFIER_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1299
+ localStored = true;
1300
+ } catch (error) {
1301
+ logger?.warn("storeCodeVerifier: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1302
+ }
1303
+ return sessionStored || localStored;
1292
1304
  }
1293
1305
  function base64UrlEncode(buffer) {
1294
1306
  const bytes = new Uint8Array(buffer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "2.16.0",
3
+ "version": "2.17.1",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",