@feelflow/ffid-sdk 1.11.0 → 1.14.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.
@@ -435,7 +435,7 @@ function createBillingMethods(deps) {
435
435
  }
436
436
 
437
437
  // src/client/version-check.ts
438
- var SDK_VERSION = "1.11.0";
438
+ var SDK_VERSION = "1.14.0";
439
439
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
440
440
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
441
441
  function sdkHeaders() {
@@ -481,6 +481,22 @@ npm install @feelflow/ffid-sdk@latest \u3067\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8
481
481
  var OAUTH_TOKEN_ENDPOINT = "/api/v1/oauth/token";
482
482
  var OAUTH_REVOKE_ENDPOINT = "/api/v1/oauth/revoke";
483
483
  var MS_PER_SECOND = 1e3;
484
+ function validateTokenResponse(tokenResponse) {
485
+ const invalid = [];
486
+ if (!tokenResponse.access_token) {
487
+ invalid.push("access_token");
488
+ }
489
+ if (!tokenResponse.refresh_token) {
490
+ invalid.push("refresh_token");
491
+ }
492
+ if (typeof tokenResponse.expires_in !== "number" || tokenResponse.expires_in <= 0) {
493
+ invalid.push("expires_in");
494
+ }
495
+ if (invalid.length > 0) {
496
+ return `\u30C8\u30FC\u30AF\u30F3\u30EC\u30B9\u30DD\u30F3\u30B9\u306B\u4E0D\u6B63\u306A\u30D5\u30A3\u30FC\u30EB\u30C9\u304C\u3042\u308A\u307E\u3059: ${invalid.join(", ")}`;
497
+ }
498
+ return null;
499
+ }
484
500
  function createOAuthTokenMethods(deps) {
485
501
  const {
486
502
  baseUrl,
@@ -550,6 +566,16 @@ function createOAuthTokenMethods(deps) {
550
566
  }
551
567
  };
552
568
  }
569
+ const validationError = validateTokenResponse(tokenResponse);
570
+ if (validationError) {
571
+ logger.error("Token exchange validation failed:", validationError);
572
+ return {
573
+ error: {
574
+ code: errorCodes.TOKEN_EXCHANGE_ERROR,
575
+ message: validationError
576
+ }
577
+ };
578
+ }
553
579
  tokenStore.setTokens({
554
580
  accessToken: tokenResponse.access_token,
555
581
  refreshToken: tokenResponse.refresh_token,
@@ -618,6 +644,16 @@ function createOAuthTokenMethods(deps) {
618
644
  }
619
645
  };
620
646
  }
647
+ const validationError = validateTokenResponse(tokenResponse);
648
+ if (validationError) {
649
+ logger.error("Token refresh validation failed:", validationError);
650
+ return {
651
+ error: {
652
+ code: errorCodes.TOKEN_REFRESH_ERROR,
653
+ message: validationError
654
+ }
655
+ };
656
+ }
621
657
  tokenStore.setTokens({
622
658
  accessToken: tokenResponse.access_token,
623
659
  refreshToken: tokenResponse.refresh_token,
@@ -871,14 +907,20 @@ async function generateCodeChallenge(verifier) {
871
907
  const digest = await crypto.subtle.digest("SHA-256", data);
872
908
  return base64UrlEncode(digest);
873
909
  }
874
- function storeCodeVerifier(verifier) {
910
+ function storeCodeVerifier(verifier, logger) {
875
911
  try {
876
- if (typeof window === "undefined") return;
912
+ if (typeof window === "undefined") {
913
+ logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
914
+ return false;
915
+ }
877
916
  window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
878
- } catch {
917
+ return true;
918
+ } catch (error) {
919
+ logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
920
+ return false;
879
921
  }
880
922
  }
881
- function retrieveCodeVerifier() {
923
+ function retrieveCodeVerifier(logger) {
882
924
  try {
883
925
  if (typeof window === "undefined") return null;
884
926
  const verifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
@@ -886,7 +928,8 @@ function retrieveCodeVerifier() {
886
928
  window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
887
929
  }
888
930
  return verifier;
889
- } catch {
931
+ } catch (error) {
932
+ logger?.warn("retrieveCodeVerifier: sessionStorage \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
890
933
  return null;
891
934
  }
892
935
  }
@@ -901,6 +944,7 @@ function base64UrlEncode(buffer) {
901
944
 
902
945
  // src/client/redirect.ts
903
946
  var OAUTH_AUTHORIZE_ENDPOINT = "/api/v1/oauth/authorize";
947
+ var AUTH_LOGOUT_ENDPOINT = "/api/v1/auth/logout";
904
948
  var STATE_RANDOM_BYTES = 16;
905
949
  var HEX_BASE2 = 16;
906
950
  function generateRandomState() {
@@ -919,32 +963,34 @@ function createRedirectMethods(deps) {
919
963
  } = deps;
920
964
  async function redirectToAuthorize() {
921
965
  const verifier = generateCodeVerifier();
922
- storeCodeVerifier(verifier);
966
+ storeCodeVerifier(verifier, logger);
967
+ let challenge;
923
968
  try {
924
- const challenge = await generateCodeChallenge(verifier);
925
- const state = generateRandomState();
926
- const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
927
- const params = new URLSearchParams({
928
- response_type: "code",
929
- client_id: clientId,
930
- redirect_uri: redirectUri,
931
- state,
932
- code_challenge: challenge,
933
- code_challenge_method: "S256"
934
- });
935
- const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
936
- logger.debug("Redirecting to authorize:", authorizeUrl);
937
- window.location.href = authorizeUrl;
938
- return true;
969
+ challenge = await generateCodeChallenge(verifier);
939
970
  } catch (error) {
971
+ const errorMessage = error instanceof Error ? error.message : "PKCE \u30B3\u30FC\u30C9\u30C1\u30E3\u30EC\u30F3\u30B8\u306E\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F";
940
972
  logger.error("PKCE \u30B3\u30FC\u30C9\u30C1\u30E3\u30EC\u30F3\u30B8\u306E\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
941
- return false;
973
+ return { success: false, error: errorMessage };
942
974
  }
975
+ const state = generateRandomState();
976
+ const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
977
+ const params = new URLSearchParams({
978
+ response_type: "code",
979
+ client_id: clientId,
980
+ redirect_uri: redirectUri,
981
+ state,
982
+ code_challenge: challenge,
983
+ code_challenge_method: "S256"
984
+ });
985
+ const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
986
+ logger.debug("Redirecting to authorize:", authorizeUrl);
987
+ window.location.href = authorizeUrl;
988
+ return { success: true };
943
989
  }
944
990
  async function redirectToLogin() {
945
991
  if (typeof window === "undefined") {
946
- logger.debug("Cannot redirect in SSR context");
947
- return false;
992
+ logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
993
+ return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
948
994
  }
949
995
  if (authMode === "token") {
950
996
  return redirectToAuthorize();
@@ -953,17 +999,289 @@ function createRedirectMethods(deps) {
953
999
  const loginUrl = `${baseUrl}/login?redirect=${encodeURIComponent(currentUrl)}&service=${encodeURIComponent(serviceCode)}`;
954
1000
  logger.debug("Redirecting to login:", loginUrl);
955
1001
  window.location.href = loginUrl;
956
- return true;
1002
+ return { success: true };
957
1003
  }
958
1004
  function getLoginUrl(redirectUrl) {
959
- const redirect = redirectUrl ?? (typeof window !== "undefined" ? window.location.href : "");
1005
+ let redirect;
1006
+ if (redirectUrl != null) {
1007
+ redirect = redirectUrl;
1008
+ } else if (typeof window !== "undefined") {
1009
+ redirect = window.location.href;
1010
+ } else {
1011
+ logger.warn("getLoginUrl: SSR \u74B0\u5883\u3067 redirectUrl \u304C\u672A\u6307\u5B9A\u306E\u305F\u3081\u7A7A\u6587\u5B57\u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3057\u307E\u3059");
1012
+ redirect = "";
1013
+ }
960
1014
  return `${baseUrl}/login?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
961
1015
  }
962
1016
  function getSignupUrl(redirectUrl) {
963
- const redirect = redirectUrl ?? (typeof window !== "undefined" ? window.location.href : "");
1017
+ let redirect;
1018
+ if (redirectUrl != null) {
1019
+ redirect = redirectUrl;
1020
+ } else if (typeof window !== "undefined") {
1021
+ redirect = window.location.href;
1022
+ } else {
1023
+ logger.warn("getSignupUrl: SSR \u74B0\u5883\u3067 redirectUrl \u304C\u672A\u6307\u5B9A\u306E\u305F\u3081\u7A7A\u6587\u5B57\u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3057\u307E\u3059");
1024
+ redirect = "";
1025
+ }
964
1026
  return `${baseUrl}/signup?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
965
1027
  }
966
- return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl };
1028
+ function getLogoutUrl(postLogoutRedirectUri) {
1029
+ const url = new URL(`${baseUrl}${AUTH_LOGOUT_ENDPOINT}`);
1030
+ url.searchParams.set("client_id", clientId);
1031
+ if (postLogoutRedirectUri != null) {
1032
+ url.searchParams.set("post_logout_redirect_uri", postLogoutRedirectUri);
1033
+ }
1034
+ return url.toString();
1035
+ }
1036
+ function redirectToLogout(postLogoutRedirectUri) {
1037
+ if (typeof window === "undefined") {
1038
+ logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
1039
+ return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
1040
+ }
1041
+ const logoutUrl = getLogoutUrl(postLogoutRedirectUri);
1042
+ logger.debug("Redirecting to logout:", logoutUrl);
1043
+ window.location.href = logoutUrl;
1044
+ return { success: true };
1045
+ }
1046
+ return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout };
1047
+ }
1048
+
1049
+ // src/client/password-reset.ts
1050
+ var RESET_PASSWORD_BASE = "/api/v1/auth/reset-password";
1051
+ function isBlank(value) {
1052
+ return !value || !value.trim();
1053
+ }
1054
+ function createPasswordResetMethods(deps) {
1055
+ const { baseUrl, logger, createError, fetchWithAuth, errorCodes } = deps;
1056
+ async function fetchPublic(endpoint, options = {}) {
1057
+ const url = `${baseUrl}${endpoint}`;
1058
+ logger.debug("Fetching (public):", url);
1059
+ let response;
1060
+ try {
1061
+ response = await fetch(url, {
1062
+ ...options,
1063
+ credentials: "include",
1064
+ headers: {
1065
+ "Content-Type": "application/json",
1066
+ ...sdkHeaders(),
1067
+ ...options.headers
1068
+ }
1069
+ });
1070
+ } catch (error) {
1071
+ logger.error("Network error:", error);
1072
+ return {
1073
+ error: {
1074
+ code: errorCodes.NETWORK_ERROR,
1075
+ message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
1076
+ }
1077
+ };
1078
+ }
1079
+ let raw;
1080
+ try {
1081
+ raw = await response.json();
1082
+ } catch (parseError) {
1083
+ logger.error("Parse error:", parseError, "Status:", response.status);
1084
+ return {
1085
+ error: {
1086
+ code: errorCodes.PARSE_ERROR,
1087
+ message: `\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u4E0D\u6B63\u306A\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F (status: ${response.status})`
1088
+ }
1089
+ };
1090
+ }
1091
+ logger.debug("Response (public):", response.status, raw);
1092
+ checkVersionHeader(response, logger);
1093
+ if (!response.ok) {
1094
+ return {
1095
+ error: raw.error ?? {
1096
+ code: errorCodes.UNKNOWN_ERROR,
1097
+ message: "\u30D1\u30B9\u30EF\u30FC\u30C9\u30EA\u30BB\u30C3\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
1098
+ }
1099
+ };
1100
+ }
1101
+ if (raw.data === void 0) {
1102
+ return {
1103
+ error: {
1104
+ code: errorCodes.UNKNOWN_ERROR,
1105
+ message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
1106
+ }
1107
+ };
1108
+ }
1109
+ return { data: raw.data };
1110
+ }
1111
+ async function requestPasswordReset(email) {
1112
+ if (isBlank(email)) {
1113
+ return {
1114
+ error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
1115
+ };
1116
+ }
1117
+ return fetchPublic(
1118
+ RESET_PASSWORD_BASE,
1119
+ {
1120
+ method: "POST",
1121
+ body: JSON.stringify({ email })
1122
+ }
1123
+ );
1124
+ }
1125
+ async function verifyPasswordResetToken(accessToken) {
1126
+ if (isBlank(accessToken)) {
1127
+ return {
1128
+ error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
1129
+ };
1130
+ }
1131
+ const query = new URLSearchParams({
1132
+ access_token: accessToken,
1133
+ type: "recovery"
1134
+ });
1135
+ return fetchPublic(
1136
+ `${RESET_PASSWORD_BASE}/verify?${query.toString()}`
1137
+ );
1138
+ }
1139
+ async function establishResetSession(accessToken, refreshToken) {
1140
+ if (isBlank(accessToken)) {
1141
+ return {
1142
+ error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
1143
+ };
1144
+ }
1145
+ if (isBlank(refreshToken)) {
1146
+ return {
1147
+ error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
1148
+ };
1149
+ }
1150
+ return fetchPublic(
1151
+ `${RESET_PASSWORD_BASE}/session`,
1152
+ {
1153
+ method: "POST",
1154
+ body: JSON.stringify({ accessToken, refreshToken })
1155
+ }
1156
+ );
1157
+ }
1158
+ async function confirmPasswordReset(password) {
1159
+ if (isBlank(password)) {
1160
+ return {
1161
+ error: createError("VALIDATION_ERROR", "\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u5FC5\u9808\u3067\u3059")
1162
+ };
1163
+ }
1164
+ return fetchWithAuth(
1165
+ `${RESET_PASSWORD_BASE}/confirm`,
1166
+ {
1167
+ method: "POST",
1168
+ body: JSON.stringify({ password })
1169
+ }
1170
+ );
1171
+ }
1172
+ return {
1173
+ requestPasswordReset,
1174
+ verifyPasswordResetToken,
1175
+ establishResetSession,
1176
+ confirmPasswordReset
1177
+ };
1178
+ }
1179
+
1180
+ // src/client/otp.ts
1181
+ var OTP_BASE = "/api/v1/auth/otp";
1182
+ function isBlank2(value) {
1183
+ return !value || !value.trim();
1184
+ }
1185
+ function createOtpMethods(deps) {
1186
+ const { baseUrl, logger, createError, errorCodes } = deps;
1187
+ async function fetchPublic(endpoint, options = {}) {
1188
+ const url = `${baseUrl}${endpoint}`;
1189
+ logger.debug("Fetching (public):", url);
1190
+ let response;
1191
+ try {
1192
+ response = await fetch(url, {
1193
+ ...options,
1194
+ credentials: "include",
1195
+ headers: {
1196
+ "Content-Type": "application/json",
1197
+ ...sdkHeaders(),
1198
+ ...options.headers
1199
+ }
1200
+ });
1201
+ } catch (error) {
1202
+ logger.error("Network error:", error);
1203
+ return {
1204
+ error: {
1205
+ code: errorCodes.NETWORK_ERROR,
1206
+ message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
1207
+ }
1208
+ };
1209
+ }
1210
+ let raw;
1211
+ try {
1212
+ raw = await response.json();
1213
+ } catch (parseError) {
1214
+ logger.error("Parse error:", parseError, "Status:", response.status);
1215
+ return {
1216
+ error: {
1217
+ code: errorCodes.PARSE_ERROR,
1218
+ message: `\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u4E0D\u6B63\u306A\u30EC\u30B9\u30DD\u30F3\u30B9\u3092\u53D7\u4FE1\u3057\u307E\u3057\u305F (status: ${response.status})`
1219
+ }
1220
+ };
1221
+ }
1222
+ logger.debug("Response (public):", response.status, raw);
1223
+ checkVersionHeader(response, logger);
1224
+ if (!response.ok) {
1225
+ return {
1226
+ error: raw.error ?? {
1227
+ code: errorCodes.UNKNOWN_ERROR,
1228
+ message: "OTP\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
1229
+ }
1230
+ };
1231
+ }
1232
+ if (raw.data === void 0) {
1233
+ return {
1234
+ error: {
1235
+ code: errorCodes.UNKNOWN_ERROR,
1236
+ message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
1237
+ }
1238
+ };
1239
+ }
1240
+ return { data: raw.data };
1241
+ }
1242
+ async function sendOtp(email, options) {
1243
+ if (isBlank2(email)) {
1244
+ return {
1245
+ error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
1246
+ };
1247
+ }
1248
+ return fetchPublic(
1249
+ `${OTP_BASE}/send`,
1250
+ {
1251
+ method: "POST",
1252
+ body: JSON.stringify({
1253
+ email,
1254
+ ...options?.redirectUrl ? { redirectUrl: options.redirectUrl } : {}
1255
+ })
1256
+ }
1257
+ );
1258
+ }
1259
+ async function verifyOtp(params) {
1260
+ if (isBlank2(params.accessToken)) {
1261
+ return {
1262
+ error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
1263
+ };
1264
+ }
1265
+ if (isBlank2(params.refreshToken)) {
1266
+ return {
1267
+ error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
1268
+ };
1269
+ }
1270
+ return fetchPublic(
1271
+ `${OTP_BASE}/verify`,
1272
+ {
1273
+ method: "POST",
1274
+ body: JSON.stringify({
1275
+ accessToken: params.accessToken,
1276
+ refreshToken: params.refreshToken
1277
+ })
1278
+ }
1279
+ );
1280
+ }
1281
+ return {
1282
+ sendOtp,
1283
+ verifyOtp
1284
+ };
967
1285
  }
968
1286
 
969
1287
  // src/client/ffid-client.ts
@@ -1098,6 +1416,9 @@ function createFFIDClient(config) {
1098
1416
  }
1099
1417
  };
1100
1418
  }
1419
+ } else {
1420
+ logger.warn("Token refresh failed, returning refresh error:", refreshResult.error);
1421
+ return { error: refreshResult.error };
1101
1422
  }
1102
1423
  }
1103
1424
  let raw;
@@ -1148,7 +1469,7 @@ function createFFIDClient(config) {
1148
1469
  }
1149
1470
  return signOutCookie();
1150
1471
  }
1151
- const { redirectToLogin, getLoginUrl, getSignupUrl } = createRedirectMethods({
1472
+ const { redirectToLogin, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
1152
1473
  authMode,
1153
1474
  baseUrl,
1154
1475
  clientId,
@@ -1175,6 +1496,24 @@ function createFFIDClient(config) {
1175
1496
  fetchWithAuth,
1176
1497
  createError
1177
1498
  });
1499
+ const {
1500
+ requestPasswordReset,
1501
+ verifyPasswordResetToken,
1502
+ establishResetSession,
1503
+ confirmPasswordReset
1504
+ } = createPasswordResetMethods({
1505
+ baseUrl,
1506
+ logger,
1507
+ createError,
1508
+ fetchWithAuth,
1509
+ errorCodes: FFID_ERROR_CODES
1510
+ });
1511
+ const { sendOtp, verifyOtp } = createOtpMethods({
1512
+ baseUrl,
1513
+ logger,
1514
+ createError,
1515
+ errorCodes: FFID_ERROR_CODES
1516
+ });
1178
1517
  const verifyAccessToken = createVerifyAccessToken({
1179
1518
  authMode,
1180
1519
  baseUrl,
@@ -1191,7 +1530,9 @@ function createFFIDClient(config) {
1191
1530
  getSession,
1192
1531
  signOut,
1193
1532
  redirectToLogin,
1533
+ redirectToLogout,
1194
1534
  getLoginUrl,
1535
+ getLogoutUrl,
1195
1536
  getSignupUrl,
1196
1537
  createError,
1197
1538
  exchangeCodeForTokens,
@@ -1200,6 +1541,12 @@ function createFFIDClient(config) {
1200
1541
  createCheckoutSession,
1201
1542
  createPortalSession,
1202
1543
  verifyAccessToken,
1544
+ requestPasswordReset,
1545
+ verifyPasswordResetToken,
1546
+ establishResetSession,
1547
+ confirmPasswordReset,
1548
+ sendOtp,
1549
+ verifyOtp,
1203
1550
  /** Token store (token mode only) */
1204
1551
  tokenStore,
1205
1552
  /** Resolved auth mode */
@@ -1,30 +1,30 @@
1
1
  'use strict';
2
2
 
3
- var chunkWZZP7SQB_cjs = require('../chunk-WZZP7SQB.cjs');
3
+ var chunkTMUFELR5_cjs = require('../chunk-TMUFELR5.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunkWZZP7SQB_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkTMUFELR5_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunkWZZP7SQB_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkTMUFELR5_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDLoginButton", {
16
16
  enumerable: true,
17
- get: function () { return chunkWZZP7SQB_cjs.FFIDLoginButton; }
17
+ get: function () { return chunkTMUFELR5_cjs.FFIDLoginButton; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
20
20
  enumerable: true,
21
- get: function () { return chunkWZZP7SQB_cjs.FFIDOrganizationSwitcher; }
21
+ get: function () { return chunkTMUFELR5_cjs.FFIDOrganizationSwitcher; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
24
24
  enumerable: true,
25
- get: function () { return chunkWZZP7SQB_cjs.FFIDSubscriptionBadge; }
25
+ get: function () { return chunkTMUFELR5_cjs.FFIDSubscriptionBadge; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDUserMenu", {
28
28
  enumerable: true,
29
- get: function () { return chunkWZZP7SQB_cjs.FFIDUserMenu; }
29
+ get: function () { return chunkTMUFELR5_cjs.FFIDUserMenu; }
30
30
  });
@@ -1,3 +1,3 @@
1
- export { x as FFIDAnnouncementBadge, V as FFIDAnnouncementBadgeClassNames, W as FFIDAnnouncementBadgeProps, y as FFIDAnnouncementList, X as FFIDAnnouncementListClassNames, Y as FFIDAnnouncementListProps, H as FFIDLoginButton, Z as FFIDLoginButtonProps, M as FFIDOrganizationSwitcher, _ as FFIDOrganizationSwitcherClassNames, $ as FFIDOrganizationSwitcherProps, O as FFIDSubscriptionBadge, a0 as FFIDSubscriptionBadgeClassNames, a1 as FFIDSubscriptionBadgeProps, R as FFIDUserMenu, a2 as FFIDUserMenuClassNames, a3 as FFIDUserMenuProps } from '../index-DMgtXEt5.cjs';
1
+ export { y as FFIDAnnouncementBadge, W as FFIDAnnouncementBadgeClassNames, X as FFIDAnnouncementBadgeProps, z as FFIDAnnouncementList, Y as FFIDAnnouncementListClassNames, Z as FFIDAnnouncementListProps, I as FFIDLoginButton, _ as FFIDLoginButtonProps, N as FFIDOrganizationSwitcher, $ as FFIDOrganizationSwitcherClassNames, a0 as FFIDOrganizationSwitcherProps, P as FFIDSubscriptionBadge, a1 as FFIDSubscriptionBadgeClassNames, a2 as FFIDSubscriptionBadgeProps, S as FFIDUserMenu, a3 as FFIDUserMenuClassNames, a4 as FFIDUserMenuProps } from '../index-DU-lFo9B.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { x as FFIDAnnouncementBadge, V as FFIDAnnouncementBadgeClassNames, W as FFIDAnnouncementBadgeProps, y as FFIDAnnouncementList, X as FFIDAnnouncementListClassNames, Y as FFIDAnnouncementListProps, H as FFIDLoginButton, Z as FFIDLoginButtonProps, M as FFIDOrganizationSwitcher, _ as FFIDOrganizationSwitcherClassNames, $ as FFIDOrganizationSwitcherProps, O as FFIDSubscriptionBadge, a0 as FFIDSubscriptionBadgeClassNames, a1 as FFIDSubscriptionBadgeProps, R as FFIDUserMenu, a2 as FFIDUserMenuClassNames, a3 as FFIDUserMenuProps } from '../index-DMgtXEt5.js';
1
+ export { y as FFIDAnnouncementBadge, W as FFIDAnnouncementBadgeClassNames, X as FFIDAnnouncementBadgeProps, z as FFIDAnnouncementList, Y as FFIDAnnouncementListClassNames, Z as FFIDAnnouncementListProps, I as FFIDLoginButton, _ as FFIDLoginButtonProps, N as FFIDOrganizationSwitcher, $ as FFIDOrganizationSwitcherClassNames, a0 as FFIDOrganizationSwitcherProps, P as FFIDSubscriptionBadge, a1 as FFIDSubscriptionBadgeClassNames, a2 as FFIDSubscriptionBadgeProps, S as FFIDUserMenu, a3 as FFIDUserMenuClassNames, a4 as FFIDUserMenuProps } from '../index-DU-lFo9B.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-GW23IWNE.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-WJI7D5C7.js';
@@ -375,6 +375,18 @@ interface FFIDCreatePortalParams {
375
375
  /** URL to redirect when user exits the portal */
376
376
  returnUrl: string;
377
377
  }
378
+ /**
379
+ * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
380
+ *
381
+ * Structured return type so callers can inspect failure reasons
382
+ * instead of receiving a bare `false`.
383
+ */
384
+ type FFIDRedirectResult = {
385
+ success: true;
386
+ } | {
387
+ success: false;
388
+ error: string;
389
+ };
378
390
  /**
379
391
  * OAuth 2.0 token response from FFID token endpoint
380
392
  */
@@ -776,4 +788,4 @@ interface FFIDAnnouncementListProps {
776
788
  */
777
789
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
778
790
 
779
- export { type FFIDOrganizationSwitcherProps as $, type AnnouncementListResponse as A, type FFIDAnnouncementsErrorCode as B, type FFIDAnnouncementsServerResponse as C, type FFIDCacheConfig as D, type FFIDContextValue as E, type FFIDConfig as F, type FFIDJwtClaims as G, FFIDLoginButton as H, type FFIDOAuthTokenResponse as I, type FFIDOAuthUserInfoMemberRole as J, type FFIDOAuthUserInfoSubscription as K, type ListAnnouncementsOptions as L, FFIDOrganizationSwitcher as M, type FFIDSeatModel as N, FFIDSubscriptionBadge as O, type FFIDSubscriptionStatus as P, type FFIDTokenIntrospectionResponse as Q, FFIDUserMenu as R, type UseFFIDAnnouncementsReturn as S, useFFIDAnnouncements as T, type UseFFIDAnnouncementsOptions as U, type FFIDAnnouncementBadgeClassNames as V, type FFIDAnnouncementBadgeProps as W, type FFIDAnnouncementListClassNames as X, type FFIDAnnouncementListProps as Y, type FFIDLoginButtonProps as Z, type FFIDOrganizationSwitcherClassNames as _, type FFIDApiResponse as a, type FFIDSubscriptionBadgeClassNames as a0, type FFIDSubscriptionBadgeProps as a1, type FFIDUserMenuClassNames as a2, type FFIDUserMenuProps as a3, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDCreateCheckoutParams as e, type FFIDCheckoutSessionResponse as f, type FFIDCreatePortalParams as g, type FFIDPortalSessionResponse as h, type FFIDVerifyAccessTokenOptions as i, type FFIDOAuthUserInfo as j, type FFIDAuthMode as k, type FFIDLogger as l, type FFIDCacheAdapter as m, type FFIDUser as n, type FFIDOrganization as o, type FFIDSubscription as p, type FFIDSubscriptionContextValue as q, type FFIDAnnouncementsClientConfig as r, type FFIDAnnouncementsApiResponse as s, type FFIDAnnouncementsLogger as t, type Announcement as u, type AnnouncementStatus as v, type AnnouncementType as w, FFIDAnnouncementBadge as x, FFIDAnnouncementList as y, type FFIDAnnouncementsError as z };
791
+ export { type FFIDOrganizationSwitcherClassNames as $, type AnnouncementListResponse as A, type FFIDAnnouncementsError as B, type FFIDAnnouncementsErrorCode as C, type FFIDAnnouncementsServerResponse as D, type FFIDCacheConfig as E, type FFIDConfig as F, type FFIDContextValue as G, type FFIDJwtClaims as H, FFIDLoginButton as I, type FFIDOAuthTokenResponse as J, type FFIDOAuthUserInfoMemberRole as K, type ListAnnouncementsOptions as L, type FFIDOAuthUserInfoSubscription as M, FFIDOrganizationSwitcher as N, type FFIDSeatModel as O, FFIDSubscriptionBadge as P, type FFIDSubscriptionStatus as Q, type FFIDTokenIntrospectionResponse as R, FFIDUserMenu as S, type UseFFIDAnnouncementsReturn as T, type UseFFIDAnnouncementsOptions as U, useFFIDAnnouncements as V, type FFIDAnnouncementBadgeClassNames as W, type FFIDAnnouncementBadgeProps as X, type FFIDAnnouncementListClassNames as Y, type FFIDAnnouncementListProps as Z, type FFIDLoginButtonProps as _, type FFIDApiResponse as a, type FFIDOrganizationSwitcherProps as a0, type FFIDSubscriptionBadgeClassNames as a1, type FFIDSubscriptionBadgeProps as a2, type FFIDUserMenuClassNames as a3, type FFIDUserMenuProps as a4, type FFIDSessionResponse as b, type FFIDRedirectResult as c, type FFIDError as d, type FFIDSubscriptionCheckResponse as e, type FFIDCreateCheckoutParams as f, type FFIDCheckoutSessionResponse as g, type FFIDCreatePortalParams as h, type FFIDPortalSessionResponse as i, type FFIDVerifyAccessTokenOptions as j, type FFIDOAuthUserInfo as k, type FFIDAuthMode as l, type FFIDLogger as m, type FFIDCacheAdapter as n, type FFIDUser as o, type FFIDOrganization as p, type FFIDSubscription as q, type FFIDSubscriptionContextValue as r, type FFIDAnnouncementsClientConfig as s, type FFIDAnnouncementsApiResponse as t, type FFIDAnnouncementsLogger as u, type Announcement as v, type AnnouncementStatus as w, type AnnouncementType as x, FFIDAnnouncementBadge as y, FFIDAnnouncementList as z };
@@ -375,6 +375,18 @@ interface FFIDCreatePortalParams {
375
375
  /** URL to redirect when user exits the portal */
376
376
  returnUrl: string;
377
377
  }
378
+ /**
379
+ * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
380
+ *
381
+ * Structured return type so callers can inspect failure reasons
382
+ * instead of receiving a bare `false`.
383
+ */
384
+ type FFIDRedirectResult = {
385
+ success: true;
386
+ } | {
387
+ success: false;
388
+ error: string;
389
+ };
378
390
  /**
379
391
  * OAuth 2.0 token response from FFID token endpoint
380
392
  */
@@ -776,4 +788,4 @@ interface FFIDAnnouncementListProps {
776
788
  */
777
789
  declare function FFIDAnnouncementList({ announcements, isLoading, className, classNames, style, formatDate, emptyMessage, loadingRender, renderItem, maxContentLines, }: FFIDAnnouncementListProps): react_jsx_runtime.JSX.Element;
778
790
 
779
- export { type FFIDOrganizationSwitcherProps as $, type AnnouncementListResponse as A, type FFIDAnnouncementsErrorCode as B, type FFIDAnnouncementsServerResponse as C, type FFIDCacheConfig as D, type FFIDContextValue as E, type FFIDConfig as F, type FFIDJwtClaims as G, FFIDLoginButton as H, type FFIDOAuthTokenResponse as I, type FFIDOAuthUserInfoMemberRole as J, type FFIDOAuthUserInfoSubscription as K, type ListAnnouncementsOptions as L, FFIDOrganizationSwitcher as M, type FFIDSeatModel as N, FFIDSubscriptionBadge as O, type FFIDSubscriptionStatus as P, type FFIDTokenIntrospectionResponse as Q, FFIDUserMenu as R, type UseFFIDAnnouncementsReturn as S, useFFIDAnnouncements as T, type UseFFIDAnnouncementsOptions as U, type FFIDAnnouncementBadgeClassNames as V, type FFIDAnnouncementBadgeProps as W, type FFIDAnnouncementListClassNames as X, type FFIDAnnouncementListProps as Y, type FFIDLoginButtonProps as Z, type FFIDOrganizationSwitcherClassNames as _, type FFIDApiResponse as a, type FFIDSubscriptionBadgeClassNames as a0, type FFIDSubscriptionBadgeProps as a1, type FFIDUserMenuClassNames as a2, type FFIDUserMenuProps as a3, type FFIDSessionResponse as b, type FFIDError as c, type FFIDSubscriptionCheckResponse as d, type FFIDCreateCheckoutParams as e, type FFIDCheckoutSessionResponse as f, type FFIDCreatePortalParams as g, type FFIDPortalSessionResponse as h, type FFIDVerifyAccessTokenOptions as i, type FFIDOAuthUserInfo as j, type FFIDAuthMode as k, type FFIDLogger as l, type FFIDCacheAdapter as m, type FFIDUser as n, type FFIDOrganization as o, type FFIDSubscription as p, type FFIDSubscriptionContextValue as q, type FFIDAnnouncementsClientConfig as r, type FFIDAnnouncementsApiResponse as s, type FFIDAnnouncementsLogger as t, type Announcement as u, type AnnouncementStatus as v, type AnnouncementType as w, FFIDAnnouncementBadge as x, FFIDAnnouncementList as y, type FFIDAnnouncementsError as z };
791
+ export { type FFIDOrganizationSwitcherClassNames as $, type AnnouncementListResponse as A, type FFIDAnnouncementsError as B, type FFIDAnnouncementsErrorCode as C, type FFIDAnnouncementsServerResponse as D, type FFIDCacheConfig as E, type FFIDConfig as F, type FFIDContextValue as G, type FFIDJwtClaims as H, FFIDLoginButton as I, type FFIDOAuthTokenResponse as J, type FFIDOAuthUserInfoMemberRole as K, type ListAnnouncementsOptions as L, type FFIDOAuthUserInfoSubscription as M, FFIDOrganizationSwitcher as N, type FFIDSeatModel as O, FFIDSubscriptionBadge as P, type FFIDSubscriptionStatus as Q, type FFIDTokenIntrospectionResponse as R, FFIDUserMenu as S, type UseFFIDAnnouncementsReturn as T, type UseFFIDAnnouncementsOptions as U, useFFIDAnnouncements as V, type FFIDAnnouncementBadgeClassNames as W, type FFIDAnnouncementBadgeProps as X, type FFIDAnnouncementListClassNames as Y, type FFIDAnnouncementListProps as Z, type FFIDLoginButtonProps as _, type FFIDApiResponse as a, type FFIDOrganizationSwitcherProps as a0, type FFIDSubscriptionBadgeClassNames as a1, type FFIDSubscriptionBadgeProps as a2, type FFIDUserMenuClassNames as a3, type FFIDUserMenuProps as a4, type FFIDSessionResponse as b, type FFIDRedirectResult as c, type FFIDError as d, type FFIDSubscriptionCheckResponse as e, type FFIDCreateCheckoutParams as f, type FFIDCheckoutSessionResponse as g, type FFIDCreatePortalParams as h, type FFIDPortalSessionResponse as i, type FFIDVerifyAccessTokenOptions as j, type FFIDOAuthUserInfo as k, type FFIDAuthMode as l, type FFIDLogger as m, type FFIDCacheAdapter as n, type FFIDUser as o, type FFIDOrganization as p, type FFIDSubscription as q, type FFIDSubscriptionContextValue as r, type FFIDAnnouncementsClientConfig as s, type FFIDAnnouncementsApiResponse as t, type FFIDAnnouncementsLogger as u, type Announcement as v, type AnnouncementStatus as w, type AnnouncementType as x, FFIDAnnouncementBadge as y, FFIDAnnouncementList as z };