@feelflow/ffid-sdk 2.16.0 → 2.17.0

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.
@@ -808,7 +808,7 @@ 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.0";
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() {
@@ -1262,6 +1262,9 @@ function createSessionMethods(deps) {
1262
1262
 
1263
1263
  // src/auth/pkce.ts
1264
1264
  var VERIFIER_STORAGE_KEY = "ffid_code_verifier";
1265
+ var VERIFIER_FALLBACK_STORAGE_KEY = "ffid_code_verifier_fb";
1266
+ var VERIFIER_FALLBACK_TIMESTAMP_KEY = "ffid_code_verifier_fb_ts";
1267
+ var CODE_VERIFIER_MAX_AGE_MS = 5 * 60 * 1e3;
1265
1268
  var CODE_VERIFIER_MIN_LENGTH = 43;
1266
1269
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1267
1270
  function generateCodeVerifier() {
@@ -1281,30 +1284,77 @@ async function generateCodeChallenge(verifier) {
1281
1284
  return base64UrlEncode(digest);
1282
1285
  }
1283
1286
  function storeCodeVerifier(verifier, logger) {
1287
+ if (typeof window === "undefined") {
1288
+ logger?.warn("storeCodeVerifier: storage is not available in SSR context");
1289
+ return false;
1290
+ }
1291
+ let sessionStored = false;
1284
1292
  try {
1285
- if (typeof window === "undefined") {
1286
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1287
- return false;
1288
- }
1289
1293
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1290
- return true;
1294
+ sessionStored = true;
1291
1295
  } catch (error) {
1292
1296
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1293
- return false;
1294
1297
  }
1298
+ let localStored = false;
1299
+ try {
1300
+ window.localStorage.setItem(VERIFIER_FALLBACK_STORAGE_KEY, verifier);
1301
+ window.localStorage.setItem(VERIFIER_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1302
+ localStored = true;
1303
+ } catch (error) {
1304
+ logger?.warn("storeCodeVerifier: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1305
+ }
1306
+ return sessionStored || localStored;
1295
1307
  }
1296
1308
  function retrieveCodeVerifier(logger) {
1309
+ if (typeof window === "undefined") return null;
1310
+ let sessionVerifier = null;
1297
1311
  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;
1312
+ sessionVerifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
1304
1313
  } catch (error) {
1305
1314
  logger?.warn("retrieveCodeVerifier: sessionStorage \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1315
+ }
1316
+ if (sessionVerifier) {
1317
+ cleanupVerifierStorage(logger);
1318
+ return sessionVerifier;
1319
+ }
1320
+ let fallbackVerifier = null;
1321
+ let fallbackTimestamp = null;
1322
+ try {
1323
+ fallbackVerifier = window.localStorage.getItem(VERIFIER_FALLBACK_STORAGE_KEY);
1324
+ fallbackTimestamp = window.localStorage.getItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1325
+ } catch (error) {
1326
+ logger?.warn("retrieveCodeVerifier: localStorage fallback \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1327
+ cleanupVerifierStorage(logger);
1328
+ return null;
1329
+ }
1330
+ if (!fallbackVerifier || !fallbackTimestamp) {
1331
+ cleanupVerifierStorage(logger);
1306
1332
  return null;
1307
1333
  }
1334
+ const ts = Number(fallbackTimestamp);
1335
+ const age = Date.now() - ts;
1336
+ if (!Number.isFinite(ts) || age < 0 || age > CODE_VERIFIER_MAX_AGE_MS) {
1337
+ cleanupVerifierStorage(logger);
1338
+ return null;
1339
+ }
1340
+ logger?.warn(
1341
+ "retrieveCodeVerifier: sessionStorage was empty, recovered code_verifier from localStorage fallback"
1342
+ );
1343
+ cleanupVerifierStorage(logger);
1344
+ return fallbackVerifier;
1345
+ }
1346
+ function cleanupVerifierStorage(logger) {
1347
+ try {
1348
+ window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
1349
+ } catch (error) {
1350
+ logger?.warn("retrieveCodeVerifier: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1351
+ }
1352
+ try {
1353
+ window.localStorage.removeItem(VERIFIER_FALLBACK_STORAGE_KEY);
1354
+ window.localStorage.removeItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1355
+ } catch (error) {
1356
+ logger?.warn("retrieveCodeVerifier: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1357
+ }
1308
1358
  }
1309
1359
  function base64UrlEncode(buffer) {
1310
1360
  const bytes = new Uint8Array(buffer);
@@ -2496,7 +2546,7 @@ function FFIDProvider({
2496
2546
  const code = urlParams.get("code");
2497
2547
  if (!code) return;
2498
2548
  client.logger.debug("Authorization code detected, exchanging for tokens");
2499
- const codeVerifier = retrieveCodeVerifier();
2549
+ const codeVerifier = retrieveCodeVerifier(client.logger);
2500
2550
  client.exchangeCodeForTokens(code, codeVerifier ?? void 0).then((result) => {
2501
2551
  if (result.error) {
2502
2552
  client.logger.error("Token exchange failed:", result.error);
@@ -810,7 +810,7 @@ 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.0";
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() {
@@ -1264,6 +1264,9 @@ function createSessionMethods(deps) {
1264
1264
 
1265
1265
  // src/auth/pkce.ts
1266
1266
  var VERIFIER_STORAGE_KEY = "ffid_code_verifier";
1267
+ var VERIFIER_FALLBACK_STORAGE_KEY = "ffid_code_verifier_fb";
1268
+ var VERIFIER_FALLBACK_TIMESTAMP_KEY = "ffid_code_verifier_fb_ts";
1269
+ var CODE_VERIFIER_MAX_AGE_MS = 5 * 60 * 1e3;
1267
1270
  var CODE_VERIFIER_MIN_LENGTH = 43;
1268
1271
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1269
1272
  function generateCodeVerifier() {
@@ -1283,30 +1286,77 @@ async function generateCodeChallenge(verifier) {
1283
1286
  return base64UrlEncode(digest);
1284
1287
  }
1285
1288
  function storeCodeVerifier(verifier, logger) {
1289
+ if (typeof window === "undefined") {
1290
+ logger?.warn("storeCodeVerifier: storage is not available in SSR context");
1291
+ return false;
1292
+ }
1293
+ let sessionStored = false;
1286
1294
  try {
1287
- if (typeof window === "undefined") {
1288
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1289
- return false;
1290
- }
1291
1295
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1292
- return true;
1296
+ sessionStored = true;
1293
1297
  } catch (error) {
1294
1298
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1295
- return false;
1296
1299
  }
1300
+ let localStored = false;
1301
+ try {
1302
+ window.localStorage.setItem(VERIFIER_FALLBACK_STORAGE_KEY, verifier);
1303
+ window.localStorage.setItem(VERIFIER_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1304
+ localStored = true;
1305
+ } catch (error) {
1306
+ logger?.warn("storeCodeVerifier: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1307
+ }
1308
+ return sessionStored || localStored;
1297
1309
  }
1298
1310
  function retrieveCodeVerifier(logger) {
1311
+ if (typeof window === "undefined") return null;
1312
+ let sessionVerifier = null;
1299
1313
  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;
1314
+ sessionVerifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
1306
1315
  } catch (error) {
1307
1316
  logger?.warn("retrieveCodeVerifier: sessionStorage \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1317
+ }
1318
+ if (sessionVerifier) {
1319
+ cleanupVerifierStorage(logger);
1320
+ return sessionVerifier;
1321
+ }
1322
+ let fallbackVerifier = null;
1323
+ let fallbackTimestamp = null;
1324
+ try {
1325
+ fallbackVerifier = window.localStorage.getItem(VERIFIER_FALLBACK_STORAGE_KEY);
1326
+ fallbackTimestamp = window.localStorage.getItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1327
+ } catch (error) {
1328
+ logger?.warn("retrieveCodeVerifier: localStorage fallback \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1329
+ cleanupVerifierStorage(logger);
1330
+ return null;
1331
+ }
1332
+ if (!fallbackVerifier || !fallbackTimestamp) {
1333
+ cleanupVerifierStorage(logger);
1308
1334
  return null;
1309
1335
  }
1336
+ const ts = Number(fallbackTimestamp);
1337
+ const age = Date.now() - ts;
1338
+ if (!Number.isFinite(ts) || age < 0 || age > CODE_VERIFIER_MAX_AGE_MS) {
1339
+ cleanupVerifierStorage(logger);
1340
+ return null;
1341
+ }
1342
+ logger?.warn(
1343
+ "retrieveCodeVerifier: sessionStorage was empty, recovered code_verifier from localStorage fallback"
1344
+ );
1345
+ cleanupVerifierStorage(logger);
1346
+ return fallbackVerifier;
1347
+ }
1348
+ function cleanupVerifierStorage(logger) {
1349
+ try {
1350
+ window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
1351
+ } catch (error) {
1352
+ logger?.warn("retrieveCodeVerifier: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1353
+ }
1354
+ try {
1355
+ window.localStorage.removeItem(VERIFIER_FALLBACK_STORAGE_KEY);
1356
+ window.localStorage.removeItem(VERIFIER_FALLBACK_TIMESTAMP_KEY);
1357
+ } catch (error) {
1358
+ logger?.warn("retrieveCodeVerifier: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1359
+ }
1310
1360
  }
1311
1361
  function base64UrlEncode(buffer) {
1312
1362
  const bytes = new Uint8Array(buffer);
@@ -2498,7 +2548,7 @@ function FFIDProvider({
2498
2548
  const code = urlParams.get("code");
2499
2549
  if (!code) return;
2500
2550
  client.logger.debug("Authorization code detected, exchanging for tokens");
2501
- const codeVerifier = retrieveCodeVerifier();
2551
+ const codeVerifier = retrieveCodeVerifier(client.logger);
2502
2552
  client.exchangeCodeForTokens(code, codeVerifier ?? void 0).then((result) => {
2503
2553
  if (result.error) {
2504
2554
  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 chunkOWE6EPWE_cjs = require('../chunk-OWE6EPWE.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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_cjs.FFIDUserMenu; }
34
34
  });
@@ -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-O2YI5N6S.js';
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 chunkOWE6EPWE_cjs = require('./chunk-OWE6EPWE.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 } = chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_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 chunkOWE6EPWE_cjs.withSubscription; }
178
178
  });
179
179
  exports.FFID_NEWSLETTER_TYPES = FFID_NEWSLETTER_TYPES;
180
180
  exports.createKVCacheAdapter = createKVCacheAdapter;
package/dist/index.d.cts CHANGED
@@ -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
@@ -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-O2YI5N6S.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-O2YI5N6S.js';
3
3
  import { useRef, useEffect } from 'react';
4
4
  import { jsx, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -806,7 +806,7 @@ 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.0";
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() {
@@ -1260,6 +1260,8 @@ function createSessionMethods(deps) {
1260
1260
 
1261
1261
  // src/auth/pkce.ts
1262
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";
1263
1265
  var CODE_VERIFIER_MIN_LENGTH = 43;
1264
1266
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1265
1267
  function generateCodeVerifier() {
@@ -1279,17 +1281,26 @@ async function generateCodeChallenge(verifier) {
1279
1281
  return base64UrlEncode(digest);
1280
1282
  }
1281
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;
1282
1289
  try {
1283
- if (typeof window === "undefined") {
1284
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1285
- return false;
1286
- }
1287
1290
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1288
- return true;
1291
+ sessionStored = true;
1289
1292
  } catch (error) {
1290
1293
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1291
- return false;
1292
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;
1293
1304
  }
1294
1305
  function base64UrlEncode(buffer) {
1295
1306
  const bytes = new Uint8Array(buffer);
@@ -805,7 +805,7 @@ 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.0";
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() {
@@ -1259,6 +1259,8 @@ function createSessionMethods(deps) {
1259
1259
 
1260
1260
  // src/auth/pkce.ts
1261
1261
  var VERIFIER_STORAGE_KEY = "ffid_code_verifier";
1262
+ var VERIFIER_FALLBACK_STORAGE_KEY = "ffid_code_verifier_fb";
1263
+ var VERIFIER_FALLBACK_TIMESTAMP_KEY = "ffid_code_verifier_fb_ts";
1262
1264
  var CODE_VERIFIER_MIN_LENGTH = 43;
1263
1265
  var UNRESERVED_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
1264
1266
  function generateCodeVerifier() {
@@ -1278,17 +1280,26 @@ async function generateCodeChallenge(verifier) {
1278
1280
  return base64UrlEncode(digest);
1279
1281
  }
1280
1282
  function storeCodeVerifier(verifier, logger) {
1283
+ if (typeof window === "undefined") {
1284
+ logger?.warn("storeCodeVerifier: storage is not available in SSR context");
1285
+ return false;
1286
+ }
1287
+ let sessionStored = false;
1281
1288
  try {
1282
- if (typeof window === "undefined") {
1283
- logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
1284
- return false;
1285
- }
1286
1289
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
1287
- return true;
1290
+ sessionStored = true;
1288
1291
  } catch (error) {
1289
1292
  logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1290
- return false;
1291
1293
  }
1294
+ let localStored = false;
1295
+ try {
1296
+ window.localStorage.setItem(VERIFIER_FALLBACK_STORAGE_KEY, verifier);
1297
+ window.localStorage.setItem(VERIFIER_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1298
+ localStored = true;
1299
+ } catch (error) {
1300
+ logger?.warn("storeCodeVerifier: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1301
+ }
1302
+ return sessionStored || localStored;
1292
1303
  }
1293
1304
  function base64UrlEncode(buffer) {
1294
1305
  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.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",