@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.
- package/dist/{chunk-WZZP7SQB.cjs → chunk-TMUFELR5.cjs} +377 -30
- package/dist/{chunk-GW23IWNE.js → chunk-WJI7D5C7.js} +377 -30
- package/dist/components/index.cjs +7 -7
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{index-DMgtXEt5.d.cts → index-DU-lFo9B.d.cts} +13 -1
- package/dist/{index-DMgtXEt5.d.ts → index-DU-lFo9B.d.ts} +13 -1
- package/dist/index.cjs +22 -22
- package/dist/index.d.cts +65 -7
- package/dist/index.d.ts +65 -7
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +374 -28
- package/dist/server/index.d.cts +64 -2
- package/dist/server/index.d.ts +64 -2
- package/dist/server/index.js +374 -28
- package/package.json +1 -1
|
@@ -437,7 +437,7 @@ function createBillingMethods(deps) {
|
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
// src/client/version-check.ts
|
|
440
|
-
var SDK_VERSION = "1.
|
|
440
|
+
var SDK_VERSION = "1.14.0";
|
|
441
441
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
442
442
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
443
443
|
function sdkHeaders() {
|
|
@@ -483,6 +483,22 @@ npm install @feelflow/ffid-sdk@latest \u3067\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8
|
|
|
483
483
|
var OAUTH_TOKEN_ENDPOINT = "/api/v1/oauth/token";
|
|
484
484
|
var OAUTH_REVOKE_ENDPOINT = "/api/v1/oauth/revoke";
|
|
485
485
|
var MS_PER_SECOND = 1e3;
|
|
486
|
+
function validateTokenResponse(tokenResponse) {
|
|
487
|
+
const invalid = [];
|
|
488
|
+
if (!tokenResponse.access_token) {
|
|
489
|
+
invalid.push("access_token");
|
|
490
|
+
}
|
|
491
|
+
if (!tokenResponse.refresh_token) {
|
|
492
|
+
invalid.push("refresh_token");
|
|
493
|
+
}
|
|
494
|
+
if (typeof tokenResponse.expires_in !== "number" || tokenResponse.expires_in <= 0) {
|
|
495
|
+
invalid.push("expires_in");
|
|
496
|
+
}
|
|
497
|
+
if (invalid.length > 0) {
|
|
498
|
+
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(", ")}`;
|
|
499
|
+
}
|
|
500
|
+
return null;
|
|
501
|
+
}
|
|
486
502
|
function createOAuthTokenMethods(deps) {
|
|
487
503
|
const {
|
|
488
504
|
baseUrl,
|
|
@@ -552,6 +568,16 @@ function createOAuthTokenMethods(deps) {
|
|
|
552
568
|
}
|
|
553
569
|
};
|
|
554
570
|
}
|
|
571
|
+
const validationError = validateTokenResponse(tokenResponse);
|
|
572
|
+
if (validationError) {
|
|
573
|
+
logger.error("Token exchange validation failed:", validationError);
|
|
574
|
+
return {
|
|
575
|
+
error: {
|
|
576
|
+
code: errorCodes.TOKEN_EXCHANGE_ERROR,
|
|
577
|
+
message: validationError
|
|
578
|
+
}
|
|
579
|
+
};
|
|
580
|
+
}
|
|
555
581
|
tokenStore.setTokens({
|
|
556
582
|
accessToken: tokenResponse.access_token,
|
|
557
583
|
refreshToken: tokenResponse.refresh_token,
|
|
@@ -620,6 +646,16 @@ function createOAuthTokenMethods(deps) {
|
|
|
620
646
|
}
|
|
621
647
|
};
|
|
622
648
|
}
|
|
649
|
+
const validationError = validateTokenResponse(tokenResponse);
|
|
650
|
+
if (validationError) {
|
|
651
|
+
logger.error("Token refresh validation failed:", validationError);
|
|
652
|
+
return {
|
|
653
|
+
error: {
|
|
654
|
+
code: errorCodes.TOKEN_REFRESH_ERROR,
|
|
655
|
+
message: validationError
|
|
656
|
+
}
|
|
657
|
+
};
|
|
658
|
+
}
|
|
623
659
|
tokenStore.setTokens({
|
|
624
660
|
accessToken: tokenResponse.access_token,
|
|
625
661
|
refreshToken: tokenResponse.refresh_token,
|
|
@@ -873,14 +909,20 @@ async function generateCodeChallenge(verifier) {
|
|
|
873
909
|
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
874
910
|
return base64UrlEncode(digest);
|
|
875
911
|
}
|
|
876
|
-
function storeCodeVerifier(verifier) {
|
|
912
|
+
function storeCodeVerifier(verifier, logger) {
|
|
877
913
|
try {
|
|
878
|
-
if (typeof window === "undefined")
|
|
914
|
+
if (typeof window === "undefined") {
|
|
915
|
+
logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
|
|
916
|
+
return false;
|
|
917
|
+
}
|
|
879
918
|
window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
|
|
880
|
-
|
|
919
|
+
return true;
|
|
920
|
+
} catch (error) {
|
|
921
|
+
logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
922
|
+
return false;
|
|
881
923
|
}
|
|
882
924
|
}
|
|
883
|
-
function retrieveCodeVerifier() {
|
|
925
|
+
function retrieveCodeVerifier(logger) {
|
|
884
926
|
try {
|
|
885
927
|
if (typeof window === "undefined") return null;
|
|
886
928
|
const verifier = window.sessionStorage.getItem(VERIFIER_STORAGE_KEY);
|
|
@@ -888,7 +930,8 @@ function retrieveCodeVerifier() {
|
|
|
888
930
|
window.sessionStorage.removeItem(VERIFIER_STORAGE_KEY);
|
|
889
931
|
}
|
|
890
932
|
return verifier;
|
|
891
|
-
} catch {
|
|
933
|
+
} catch (error) {
|
|
934
|
+
logger?.warn("retrieveCodeVerifier: sessionStorage \u304B\u3089\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
892
935
|
return null;
|
|
893
936
|
}
|
|
894
937
|
}
|
|
@@ -903,6 +946,7 @@ function base64UrlEncode(buffer) {
|
|
|
903
946
|
|
|
904
947
|
// src/client/redirect.ts
|
|
905
948
|
var OAUTH_AUTHORIZE_ENDPOINT = "/api/v1/oauth/authorize";
|
|
949
|
+
var AUTH_LOGOUT_ENDPOINT = "/api/v1/auth/logout";
|
|
906
950
|
var STATE_RANDOM_BYTES = 16;
|
|
907
951
|
var HEX_BASE2 = 16;
|
|
908
952
|
function generateRandomState() {
|
|
@@ -921,32 +965,34 @@ function createRedirectMethods(deps) {
|
|
|
921
965
|
} = deps;
|
|
922
966
|
async function redirectToAuthorize() {
|
|
923
967
|
const verifier = generateCodeVerifier();
|
|
924
|
-
storeCodeVerifier(verifier);
|
|
968
|
+
storeCodeVerifier(verifier, logger);
|
|
969
|
+
let challenge;
|
|
925
970
|
try {
|
|
926
|
-
|
|
927
|
-
const state = generateRandomState();
|
|
928
|
-
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
929
|
-
const params = new URLSearchParams({
|
|
930
|
-
response_type: "code",
|
|
931
|
-
client_id: clientId,
|
|
932
|
-
redirect_uri: redirectUri,
|
|
933
|
-
state,
|
|
934
|
-
code_challenge: challenge,
|
|
935
|
-
code_challenge_method: "S256"
|
|
936
|
-
});
|
|
937
|
-
const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
|
|
938
|
-
logger.debug("Redirecting to authorize:", authorizeUrl);
|
|
939
|
-
window.location.href = authorizeUrl;
|
|
940
|
-
return true;
|
|
971
|
+
challenge = await generateCodeChallenge(verifier);
|
|
941
972
|
} catch (error) {
|
|
973
|
+
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";
|
|
942
974
|
logger.error("PKCE \u30B3\u30FC\u30C9\u30C1\u30E3\u30EC\u30F3\u30B8\u306E\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
943
|
-
return false;
|
|
975
|
+
return { success: false, error: errorMessage };
|
|
944
976
|
}
|
|
977
|
+
const state = generateRandomState();
|
|
978
|
+
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
979
|
+
const params = new URLSearchParams({
|
|
980
|
+
response_type: "code",
|
|
981
|
+
client_id: clientId,
|
|
982
|
+
redirect_uri: redirectUri,
|
|
983
|
+
state,
|
|
984
|
+
code_challenge: challenge,
|
|
985
|
+
code_challenge_method: "S256"
|
|
986
|
+
});
|
|
987
|
+
const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
|
|
988
|
+
logger.debug("Redirecting to authorize:", authorizeUrl);
|
|
989
|
+
window.location.href = authorizeUrl;
|
|
990
|
+
return { success: true };
|
|
945
991
|
}
|
|
946
992
|
async function redirectToLogin() {
|
|
947
993
|
if (typeof window === "undefined") {
|
|
948
|
-
logger.
|
|
949
|
-
return false;
|
|
994
|
+
logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
|
|
995
|
+
return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
|
|
950
996
|
}
|
|
951
997
|
if (authMode === "token") {
|
|
952
998
|
return redirectToAuthorize();
|
|
@@ -955,17 +1001,289 @@ function createRedirectMethods(deps) {
|
|
|
955
1001
|
const loginUrl = `${baseUrl}/login?redirect=${encodeURIComponent(currentUrl)}&service=${encodeURIComponent(serviceCode)}`;
|
|
956
1002
|
logger.debug("Redirecting to login:", loginUrl);
|
|
957
1003
|
window.location.href = loginUrl;
|
|
958
|
-
return true;
|
|
1004
|
+
return { success: true };
|
|
959
1005
|
}
|
|
960
1006
|
function getLoginUrl(redirectUrl) {
|
|
961
|
-
|
|
1007
|
+
let redirect;
|
|
1008
|
+
if (redirectUrl != null) {
|
|
1009
|
+
redirect = redirectUrl;
|
|
1010
|
+
} else if (typeof window !== "undefined") {
|
|
1011
|
+
redirect = window.location.href;
|
|
1012
|
+
} else {
|
|
1013
|
+
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");
|
|
1014
|
+
redirect = "";
|
|
1015
|
+
}
|
|
962
1016
|
return `${baseUrl}/login?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
|
|
963
1017
|
}
|
|
964
1018
|
function getSignupUrl(redirectUrl) {
|
|
965
|
-
|
|
1019
|
+
let redirect;
|
|
1020
|
+
if (redirectUrl != null) {
|
|
1021
|
+
redirect = redirectUrl;
|
|
1022
|
+
} else if (typeof window !== "undefined") {
|
|
1023
|
+
redirect = window.location.href;
|
|
1024
|
+
} else {
|
|
1025
|
+
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");
|
|
1026
|
+
redirect = "";
|
|
1027
|
+
}
|
|
966
1028
|
return `${baseUrl}/signup?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
|
|
967
1029
|
}
|
|
968
|
-
|
|
1030
|
+
function getLogoutUrl(postLogoutRedirectUri) {
|
|
1031
|
+
const url = new URL(`${baseUrl}${AUTH_LOGOUT_ENDPOINT}`);
|
|
1032
|
+
url.searchParams.set("client_id", clientId);
|
|
1033
|
+
if (postLogoutRedirectUri != null) {
|
|
1034
|
+
url.searchParams.set("post_logout_redirect_uri", postLogoutRedirectUri);
|
|
1035
|
+
}
|
|
1036
|
+
return url.toString();
|
|
1037
|
+
}
|
|
1038
|
+
function redirectToLogout(postLogoutRedirectUri) {
|
|
1039
|
+
if (typeof window === "undefined") {
|
|
1040
|
+
logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
|
|
1041
|
+
return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
|
|
1042
|
+
}
|
|
1043
|
+
const logoutUrl = getLogoutUrl(postLogoutRedirectUri);
|
|
1044
|
+
logger.debug("Redirecting to logout:", logoutUrl);
|
|
1045
|
+
window.location.href = logoutUrl;
|
|
1046
|
+
return { success: true };
|
|
1047
|
+
}
|
|
1048
|
+
return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout };
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
// src/client/password-reset.ts
|
|
1052
|
+
var RESET_PASSWORD_BASE = "/api/v1/auth/reset-password";
|
|
1053
|
+
function isBlank(value) {
|
|
1054
|
+
return !value || !value.trim();
|
|
1055
|
+
}
|
|
1056
|
+
function createPasswordResetMethods(deps) {
|
|
1057
|
+
const { baseUrl, logger, createError, fetchWithAuth, errorCodes } = deps;
|
|
1058
|
+
async function fetchPublic(endpoint, options = {}) {
|
|
1059
|
+
const url = `${baseUrl}${endpoint}`;
|
|
1060
|
+
logger.debug("Fetching (public):", url);
|
|
1061
|
+
let response;
|
|
1062
|
+
try {
|
|
1063
|
+
response = await fetch(url, {
|
|
1064
|
+
...options,
|
|
1065
|
+
credentials: "include",
|
|
1066
|
+
headers: {
|
|
1067
|
+
"Content-Type": "application/json",
|
|
1068
|
+
...sdkHeaders(),
|
|
1069
|
+
...options.headers
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
} catch (error) {
|
|
1073
|
+
logger.error("Network error:", error);
|
|
1074
|
+
return {
|
|
1075
|
+
error: {
|
|
1076
|
+
code: errorCodes.NETWORK_ERROR,
|
|
1077
|
+
message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
let raw;
|
|
1082
|
+
try {
|
|
1083
|
+
raw = await response.json();
|
|
1084
|
+
} catch (parseError) {
|
|
1085
|
+
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
1086
|
+
return {
|
|
1087
|
+
error: {
|
|
1088
|
+
code: errorCodes.PARSE_ERROR,
|
|
1089
|
+
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})`
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
logger.debug("Response (public):", response.status, raw);
|
|
1094
|
+
checkVersionHeader(response, logger);
|
|
1095
|
+
if (!response.ok) {
|
|
1096
|
+
return {
|
|
1097
|
+
error: raw.error ?? {
|
|
1098
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1099
|
+
message: "\u30D1\u30B9\u30EF\u30FC\u30C9\u30EA\u30BB\u30C3\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
if (raw.data === void 0) {
|
|
1104
|
+
return {
|
|
1105
|
+
error: {
|
|
1106
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1107
|
+
message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
|
|
1108
|
+
}
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
return { data: raw.data };
|
|
1112
|
+
}
|
|
1113
|
+
async function requestPasswordReset(email) {
|
|
1114
|
+
if (isBlank(email)) {
|
|
1115
|
+
return {
|
|
1116
|
+
error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1117
|
+
};
|
|
1118
|
+
}
|
|
1119
|
+
return fetchPublic(
|
|
1120
|
+
RESET_PASSWORD_BASE,
|
|
1121
|
+
{
|
|
1122
|
+
method: "POST",
|
|
1123
|
+
body: JSON.stringify({ email })
|
|
1124
|
+
}
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
async function verifyPasswordResetToken(accessToken) {
|
|
1128
|
+
if (isBlank(accessToken)) {
|
|
1129
|
+
return {
|
|
1130
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
const query = new URLSearchParams({
|
|
1134
|
+
access_token: accessToken,
|
|
1135
|
+
type: "recovery"
|
|
1136
|
+
});
|
|
1137
|
+
return fetchPublic(
|
|
1138
|
+
`${RESET_PASSWORD_BASE}/verify?${query.toString()}`
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
async function establishResetSession(accessToken, refreshToken) {
|
|
1142
|
+
if (isBlank(accessToken)) {
|
|
1143
|
+
return {
|
|
1144
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
if (isBlank(refreshToken)) {
|
|
1148
|
+
return {
|
|
1149
|
+
error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1150
|
+
};
|
|
1151
|
+
}
|
|
1152
|
+
return fetchPublic(
|
|
1153
|
+
`${RESET_PASSWORD_BASE}/session`,
|
|
1154
|
+
{
|
|
1155
|
+
method: "POST",
|
|
1156
|
+
body: JSON.stringify({ accessToken, refreshToken })
|
|
1157
|
+
}
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
async function confirmPasswordReset(password) {
|
|
1161
|
+
if (isBlank(password)) {
|
|
1162
|
+
return {
|
|
1163
|
+
error: createError("VALIDATION_ERROR", "\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1164
|
+
};
|
|
1165
|
+
}
|
|
1166
|
+
return fetchWithAuth(
|
|
1167
|
+
`${RESET_PASSWORD_BASE}/confirm`,
|
|
1168
|
+
{
|
|
1169
|
+
method: "POST",
|
|
1170
|
+
body: JSON.stringify({ password })
|
|
1171
|
+
}
|
|
1172
|
+
);
|
|
1173
|
+
}
|
|
1174
|
+
return {
|
|
1175
|
+
requestPasswordReset,
|
|
1176
|
+
verifyPasswordResetToken,
|
|
1177
|
+
establishResetSession,
|
|
1178
|
+
confirmPasswordReset
|
|
1179
|
+
};
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
// src/client/otp.ts
|
|
1183
|
+
var OTP_BASE = "/api/v1/auth/otp";
|
|
1184
|
+
function isBlank2(value) {
|
|
1185
|
+
return !value || !value.trim();
|
|
1186
|
+
}
|
|
1187
|
+
function createOtpMethods(deps) {
|
|
1188
|
+
const { baseUrl, logger, createError, errorCodes } = deps;
|
|
1189
|
+
async function fetchPublic(endpoint, options = {}) {
|
|
1190
|
+
const url = `${baseUrl}${endpoint}`;
|
|
1191
|
+
logger.debug("Fetching (public):", url);
|
|
1192
|
+
let response;
|
|
1193
|
+
try {
|
|
1194
|
+
response = await fetch(url, {
|
|
1195
|
+
...options,
|
|
1196
|
+
credentials: "include",
|
|
1197
|
+
headers: {
|
|
1198
|
+
"Content-Type": "application/json",
|
|
1199
|
+
...sdkHeaders(),
|
|
1200
|
+
...options.headers
|
|
1201
|
+
}
|
|
1202
|
+
});
|
|
1203
|
+
} catch (error) {
|
|
1204
|
+
logger.error("Network error:", error);
|
|
1205
|
+
return {
|
|
1206
|
+
error: {
|
|
1207
|
+
code: errorCodes.NETWORK_ERROR,
|
|
1208
|
+
message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
}
|
|
1212
|
+
let raw;
|
|
1213
|
+
try {
|
|
1214
|
+
raw = await response.json();
|
|
1215
|
+
} catch (parseError) {
|
|
1216
|
+
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
1217
|
+
return {
|
|
1218
|
+
error: {
|
|
1219
|
+
code: errorCodes.PARSE_ERROR,
|
|
1220
|
+
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})`
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
logger.debug("Response (public):", response.status, raw);
|
|
1225
|
+
checkVersionHeader(response, logger);
|
|
1226
|
+
if (!response.ok) {
|
|
1227
|
+
return {
|
|
1228
|
+
error: raw.error ?? {
|
|
1229
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1230
|
+
message: "OTP\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
}
|
|
1234
|
+
if (raw.data === void 0) {
|
|
1235
|
+
return {
|
|
1236
|
+
error: {
|
|
1237
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1238
|
+
message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1241
|
+
}
|
|
1242
|
+
return { data: raw.data };
|
|
1243
|
+
}
|
|
1244
|
+
async function sendOtp(email, options) {
|
|
1245
|
+
if (isBlank2(email)) {
|
|
1246
|
+
return {
|
|
1247
|
+
error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
return fetchPublic(
|
|
1251
|
+
`${OTP_BASE}/send`,
|
|
1252
|
+
{
|
|
1253
|
+
method: "POST",
|
|
1254
|
+
body: JSON.stringify({
|
|
1255
|
+
email,
|
|
1256
|
+
...options?.redirectUrl ? { redirectUrl: options.redirectUrl } : {}
|
|
1257
|
+
})
|
|
1258
|
+
}
|
|
1259
|
+
);
|
|
1260
|
+
}
|
|
1261
|
+
async function verifyOtp(params) {
|
|
1262
|
+
if (isBlank2(params.accessToken)) {
|
|
1263
|
+
return {
|
|
1264
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
if (isBlank2(params.refreshToken)) {
|
|
1268
|
+
return {
|
|
1269
|
+
error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1270
|
+
};
|
|
1271
|
+
}
|
|
1272
|
+
return fetchPublic(
|
|
1273
|
+
`${OTP_BASE}/verify`,
|
|
1274
|
+
{
|
|
1275
|
+
method: "POST",
|
|
1276
|
+
body: JSON.stringify({
|
|
1277
|
+
accessToken: params.accessToken,
|
|
1278
|
+
refreshToken: params.refreshToken
|
|
1279
|
+
})
|
|
1280
|
+
}
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
return {
|
|
1284
|
+
sendOtp,
|
|
1285
|
+
verifyOtp
|
|
1286
|
+
};
|
|
969
1287
|
}
|
|
970
1288
|
|
|
971
1289
|
// src/client/ffid-client.ts
|
|
@@ -1100,6 +1418,9 @@ function createFFIDClient(config) {
|
|
|
1100
1418
|
}
|
|
1101
1419
|
};
|
|
1102
1420
|
}
|
|
1421
|
+
} else {
|
|
1422
|
+
logger.warn("Token refresh failed, returning refresh error:", refreshResult.error);
|
|
1423
|
+
return { error: refreshResult.error };
|
|
1103
1424
|
}
|
|
1104
1425
|
}
|
|
1105
1426
|
let raw;
|
|
@@ -1150,7 +1471,7 @@ function createFFIDClient(config) {
|
|
|
1150
1471
|
}
|
|
1151
1472
|
return signOutCookie();
|
|
1152
1473
|
}
|
|
1153
|
-
const { redirectToLogin, getLoginUrl, getSignupUrl } = createRedirectMethods({
|
|
1474
|
+
const { redirectToLogin, getLoginUrl, getSignupUrl, getLogoutUrl, redirectToLogout } = createRedirectMethods({
|
|
1154
1475
|
authMode,
|
|
1155
1476
|
baseUrl,
|
|
1156
1477
|
clientId,
|
|
@@ -1177,6 +1498,24 @@ function createFFIDClient(config) {
|
|
|
1177
1498
|
fetchWithAuth,
|
|
1178
1499
|
createError
|
|
1179
1500
|
});
|
|
1501
|
+
const {
|
|
1502
|
+
requestPasswordReset,
|
|
1503
|
+
verifyPasswordResetToken,
|
|
1504
|
+
establishResetSession,
|
|
1505
|
+
confirmPasswordReset
|
|
1506
|
+
} = createPasswordResetMethods({
|
|
1507
|
+
baseUrl,
|
|
1508
|
+
logger,
|
|
1509
|
+
createError,
|
|
1510
|
+
fetchWithAuth,
|
|
1511
|
+
errorCodes: FFID_ERROR_CODES
|
|
1512
|
+
});
|
|
1513
|
+
const { sendOtp, verifyOtp } = createOtpMethods({
|
|
1514
|
+
baseUrl,
|
|
1515
|
+
logger,
|
|
1516
|
+
createError,
|
|
1517
|
+
errorCodes: FFID_ERROR_CODES
|
|
1518
|
+
});
|
|
1180
1519
|
const verifyAccessToken = createVerifyAccessToken({
|
|
1181
1520
|
authMode,
|
|
1182
1521
|
baseUrl,
|
|
@@ -1193,7 +1532,9 @@ function createFFIDClient(config) {
|
|
|
1193
1532
|
getSession,
|
|
1194
1533
|
signOut,
|
|
1195
1534
|
redirectToLogin,
|
|
1535
|
+
redirectToLogout,
|
|
1196
1536
|
getLoginUrl,
|
|
1537
|
+
getLogoutUrl,
|
|
1197
1538
|
getSignupUrl,
|
|
1198
1539
|
createError,
|
|
1199
1540
|
exchangeCodeForTokens,
|
|
@@ -1202,6 +1543,12 @@ function createFFIDClient(config) {
|
|
|
1202
1543
|
createCheckoutSession,
|
|
1203
1544
|
createPortalSession,
|
|
1204
1545
|
verifyAccessToken,
|
|
1546
|
+
requestPasswordReset,
|
|
1547
|
+
verifyPasswordResetToken,
|
|
1548
|
+
establishResetSession,
|
|
1549
|
+
confirmPasswordReset,
|
|
1550
|
+
sendOtp,
|
|
1551
|
+
verifyOtp,
|
|
1205
1552
|
/** Token store (token mode only) */
|
|
1206
1553
|
tokenStore,
|
|
1207
1554
|
/** Resolved auth mode */
|