@feelflow/ffid-sdk 1.11.0 → 1.13.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-7YV3SUEY.cjs} +354 -28
- package/dist/{chunk-GW23IWNE.js → chunk-KFOIVZEY.js} +354 -28
- 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-GrAWBpmf.d.cts} +13 -1
- package/dist/{index-DMgtXEt5.d.ts → index-GrAWBpmf.d.ts} +13 -1
- package/dist/index.cjs +22 -22
- package/dist/index.d.cts +63 -7
- package/dist/index.d.ts +63 -7
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +351 -26
- package/dist/server/index.d.cts +62 -2
- package/dist/server/index.d.ts +62 -2
- package/dist/server/index.js +351 -26
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -433,7 +433,7 @@ function createBillingMethods(deps) {
|
|
|
433
433
|
}
|
|
434
434
|
|
|
435
435
|
// src/client/version-check.ts
|
|
436
|
-
var SDK_VERSION = "1.
|
|
436
|
+
var SDK_VERSION = "1.13.0";
|
|
437
437
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
438
438
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
439
439
|
function sdkHeaders() {
|
|
@@ -479,6 +479,22 @@ npm install @feelflow/ffid-sdk@latest \u3067\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8
|
|
|
479
479
|
var OAUTH_TOKEN_ENDPOINT = "/api/v1/oauth/token";
|
|
480
480
|
var OAUTH_REVOKE_ENDPOINT = "/api/v1/oauth/revoke";
|
|
481
481
|
var MS_PER_SECOND = 1e3;
|
|
482
|
+
function validateTokenResponse(tokenResponse) {
|
|
483
|
+
const invalid = [];
|
|
484
|
+
if (!tokenResponse.access_token) {
|
|
485
|
+
invalid.push("access_token");
|
|
486
|
+
}
|
|
487
|
+
if (!tokenResponse.refresh_token) {
|
|
488
|
+
invalid.push("refresh_token");
|
|
489
|
+
}
|
|
490
|
+
if (typeof tokenResponse.expires_in !== "number" || tokenResponse.expires_in <= 0) {
|
|
491
|
+
invalid.push("expires_in");
|
|
492
|
+
}
|
|
493
|
+
if (invalid.length > 0) {
|
|
494
|
+
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(", ")}`;
|
|
495
|
+
}
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
482
498
|
function createOAuthTokenMethods(deps) {
|
|
483
499
|
const {
|
|
484
500
|
baseUrl,
|
|
@@ -548,6 +564,16 @@ function createOAuthTokenMethods(deps) {
|
|
|
548
564
|
}
|
|
549
565
|
};
|
|
550
566
|
}
|
|
567
|
+
const validationError = validateTokenResponse(tokenResponse);
|
|
568
|
+
if (validationError) {
|
|
569
|
+
logger.error("Token exchange validation failed:", validationError);
|
|
570
|
+
return {
|
|
571
|
+
error: {
|
|
572
|
+
code: errorCodes.TOKEN_EXCHANGE_ERROR,
|
|
573
|
+
message: validationError
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
}
|
|
551
577
|
tokenStore.setTokens({
|
|
552
578
|
accessToken: tokenResponse.access_token,
|
|
553
579
|
refreshToken: tokenResponse.refresh_token,
|
|
@@ -616,6 +642,16 @@ function createOAuthTokenMethods(deps) {
|
|
|
616
642
|
}
|
|
617
643
|
};
|
|
618
644
|
}
|
|
645
|
+
const validationError = validateTokenResponse(tokenResponse);
|
|
646
|
+
if (validationError) {
|
|
647
|
+
logger.error("Token refresh validation failed:", validationError);
|
|
648
|
+
return {
|
|
649
|
+
error: {
|
|
650
|
+
code: errorCodes.TOKEN_REFRESH_ERROR,
|
|
651
|
+
message: validationError
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
619
655
|
tokenStore.setTokens({
|
|
620
656
|
accessToken: tokenResponse.access_token,
|
|
621
657
|
refreshToken: tokenResponse.refresh_token,
|
|
@@ -869,11 +905,17 @@ async function generateCodeChallenge(verifier) {
|
|
|
869
905
|
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
870
906
|
return base64UrlEncode(digest);
|
|
871
907
|
}
|
|
872
|
-
function storeCodeVerifier(verifier) {
|
|
908
|
+
function storeCodeVerifier(verifier, logger) {
|
|
873
909
|
try {
|
|
874
|
-
if (typeof window === "undefined")
|
|
910
|
+
if (typeof window === "undefined") {
|
|
911
|
+
logger?.warn("storeCodeVerifier: sessionStorage is not available in SSR context");
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
875
914
|
window.sessionStorage.setItem(VERIFIER_STORAGE_KEY, verifier);
|
|
876
|
-
|
|
915
|
+
return true;
|
|
916
|
+
} catch (error) {
|
|
917
|
+
logger?.warn("storeCodeVerifier: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
918
|
+
return false;
|
|
877
919
|
}
|
|
878
920
|
}
|
|
879
921
|
function base64UrlEncode(buffer) {
|
|
@@ -905,32 +947,34 @@ function createRedirectMethods(deps) {
|
|
|
905
947
|
} = deps;
|
|
906
948
|
async function redirectToAuthorize() {
|
|
907
949
|
const verifier = generateCodeVerifier();
|
|
908
|
-
storeCodeVerifier(verifier);
|
|
950
|
+
storeCodeVerifier(verifier, logger);
|
|
951
|
+
let challenge;
|
|
909
952
|
try {
|
|
910
|
-
|
|
911
|
-
const state = generateRandomState();
|
|
912
|
-
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
913
|
-
const params = new URLSearchParams({
|
|
914
|
-
response_type: "code",
|
|
915
|
-
client_id: clientId,
|
|
916
|
-
redirect_uri: redirectUri,
|
|
917
|
-
state,
|
|
918
|
-
code_challenge: challenge,
|
|
919
|
-
code_challenge_method: "S256"
|
|
920
|
-
});
|
|
921
|
-
const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
|
|
922
|
-
logger.debug("Redirecting to authorize:", authorizeUrl);
|
|
923
|
-
window.location.href = authorizeUrl;
|
|
924
|
-
return true;
|
|
953
|
+
challenge = await generateCodeChallenge(verifier);
|
|
925
954
|
} catch (error) {
|
|
955
|
+
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";
|
|
926
956
|
logger.error("PKCE \u30B3\u30FC\u30C9\u30C1\u30E3\u30EC\u30F3\u30B8\u306E\u751F\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
|
|
927
|
-
return false;
|
|
957
|
+
return { success: false, error: errorMessage };
|
|
928
958
|
}
|
|
959
|
+
const state = generateRandomState();
|
|
960
|
+
const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
|
|
961
|
+
const params = new URLSearchParams({
|
|
962
|
+
response_type: "code",
|
|
963
|
+
client_id: clientId,
|
|
964
|
+
redirect_uri: redirectUri,
|
|
965
|
+
state,
|
|
966
|
+
code_challenge: challenge,
|
|
967
|
+
code_challenge_method: "S256"
|
|
968
|
+
});
|
|
969
|
+
const authorizeUrl = `${baseUrl}${OAUTH_AUTHORIZE_ENDPOINT}?${params.toString()}`;
|
|
970
|
+
logger.debug("Redirecting to authorize:", authorizeUrl);
|
|
971
|
+
window.location.href = authorizeUrl;
|
|
972
|
+
return { success: true };
|
|
929
973
|
}
|
|
930
974
|
async function redirectToLogin() {
|
|
931
975
|
if (typeof window === "undefined") {
|
|
932
|
-
logger.
|
|
933
|
-
return false;
|
|
976
|
+
logger.warn("SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093");
|
|
977
|
+
return { success: false, error: "SSR \u74B0\u5883\u3067\u306F\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3067\u304D\u307E\u305B\u3093" };
|
|
934
978
|
}
|
|
935
979
|
if (authMode === "token") {
|
|
936
980
|
return redirectToAuthorize();
|
|
@@ -939,19 +983,273 @@ function createRedirectMethods(deps) {
|
|
|
939
983
|
const loginUrl = `${baseUrl}/login?redirect=${encodeURIComponent(currentUrl)}&service=${encodeURIComponent(serviceCode)}`;
|
|
940
984
|
logger.debug("Redirecting to login:", loginUrl);
|
|
941
985
|
window.location.href = loginUrl;
|
|
942
|
-
return true;
|
|
986
|
+
return { success: true };
|
|
943
987
|
}
|
|
944
988
|
function getLoginUrl(redirectUrl) {
|
|
945
|
-
|
|
989
|
+
let redirect;
|
|
990
|
+
if (redirectUrl != null) {
|
|
991
|
+
redirect = redirectUrl;
|
|
992
|
+
} else if (typeof window !== "undefined") {
|
|
993
|
+
redirect = window.location.href;
|
|
994
|
+
} else {
|
|
995
|
+
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");
|
|
996
|
+
redirect = "";
|
|
997
|
+
}
|
|
946
998
|
return `${baseUrl}/login?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
|
|
947
999
|
}
|
|
948
1000
|
function getSignupUrl(redirectUrl) {
|
|
949
|
-
|
|
1001
|
+
let redirect;
|
|
1002
|
+
if (redirectUrl != null) {
|
|
1003
|
+
redirect = redirectUrl;
|
|
1004
|
+
} else if (typeof window !== "undefined") {
|
|
1005
|
+
redirect = window.location.href;
|
|
1006
|
+
} else {
|
|
1007
|
+
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");
|
|
1008
|
+
redirect = "";
|
|
1009
|
+
}
|
|
950
1010
|
return `${baseUrl}/signup?redirect=${encodeURIComponent(redirect)}&service=${encodeURIComponent(serviceCode)}`;
|
|
951
1011
|
}
|
|
952
1012
|
return { redirectToLogin, redirectToAuthorize, getLoginUrl, getSignupUrl };
|
|
953
1013
|
}
|
|
954
1014
|
|
|
1015
|
+
// src/client/password-reset.ts
|
|
1016
|
+
var RESET_PASSWORD_BASE = "/api/v1/auth/reset-password";
|
|
1017
|
+
function isBlank(value) {
|
|
1018
|
+
return !value || !value.trim();
|
|
1019
|
+
}
|
|
1020
|
+
function createPasswordResetMethods(deps) {
|
|
1021
|
+
const { baseUrl, logger, createError, fetchWithAuth, errorCodes } = deps;
|
|
1022
|
+
async function fetchPublic(endpoint, options = {}) {
|
|
1023
|
+
const url = `${baseUrl}${endpoint}`;
|
|
1024
|
+
logger.debug("Fetching (public):", url);
|
|
1025
|
+
let response;
|
|
1026
|
+
try {
|
|
1027
|
+
response = await fetch(url, {
|
|
1028
|
+
...options,
|
|
1029
|
+
credentials: "include",
|
|
1030
|
+
headers: {
|
|
1031
|
+
"Content-Type": "application/json",
|
|
1032
|
+
...sdkHeaders(),
|
|
1033
|
+
...options.headers
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
} catch (error) {
|
|
1037
|
+
logger.error("Network error:", error);
|
|
1038
|
+
return {
|
|
1039
|
+
error: {
|
|
1040
|
+
code: errorCodes.NETWORK_ERROR,
|
|
1041
|
+
message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
let raw;
|
|
1046
|
+
try {
|
|
1047
|
+
raw = await response.json();
|
|
1048
|
+
} catch (parseError) {
|
|
1049
|
+
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
1050
|
+
return {
|
|
1051
|
+
error: {
|
|
1052
|
+
code: errorCodes.PARSE_ERROR,
|
|
1053
|
+
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})`
|
|
1054
|
+
}
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
logger.debug("Response (public):", response.status, raw);
|
|
1058
|
+
checkVersionHeader(response, logger);
|
|
1059
|
+
if (!response.ok) {
|
|
1060
|
+
return {
|
|
1061
|
+
error: raw.error ?? {
|
|
1062
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1063
|
+
message: "\u30D1\u30B9\u30EF\u30FC\u30C9\u30EA\u30BB\u30C3\u30C8\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1064
|
+
}
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
if (raw.data === void 0) {
|
|
1068
|
+
return {
|
|
1069
|
+
error: {
|
|
1070
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1071
|
+
message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
|
|
1072
|
+
}
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
return { data: raw.data };
|
|
1076
|
+
}
|
|
1077
|
+
async function requestPasswordReset(email) {
|
|
1078
|
+
if (isBlank(email)) {
|
|
1079
|
+
return {
|
|
1080
|
+
error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
return fetchPublic(
|
|
1084
|
+
RESET_PASSWORD_BASE,
|
|
1085
|
+
{
|
|
1086
|
+
method: "POST",
|
|
1087
|
+
body: JSON.stringify({ email })
|
|
1088
|
+
}
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
async function verifyPasswordResetToken(accessToken) {
|
|
1092
|
+
if (isBlank(accessToken)) {
|
|
1093
|
+
return {
|
|
1094
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1097
|
+
const query = new URLSearchParams({
|
|
1098
|
+
access_token: accessToken,
|
|
1099
|
+
type: "recovery"
|
|
1100
|
+
});
|
|
1101
|
+
return fetchPublic(
|
|
1102
|
+
`${RESET_PASSWORD_BASE}/verify?${query.toString()}`
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
async function establishResetSession(accessToken, refreshToken) {
|
|
1106
|
+
if (isBlank(accessToken)) {
|
|
1107
|
+
return {
|
|
1108
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
if (isBlank(refreshToken)) {
|
|
1112
|
+
return {
|
|
1113
|
+
error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
return fetchPublic(
|
|
1117
|
+
`${RESET_PASSWORD_BASE}/session`,
|
|
1118
|
+
{
|
|
1119
|
+
method: "POST",
|
|
1120
|
+
body: JSON.stringify({ accessToken, refreshToken })
|
|
1121
|
+
}
|
|
1122
|
+
);
|
|
1123
|
+
}
|
|
1124
|
+
async function confirmPasswordReset(password) {
|
|
1125
|
+
if (isBlank(password)) {
|
|
1126
|
+
return {
|
|
1127
|
+
error: createError("VALIDATION_ERROR", "\u30D1\u30B9\u30EF\u30FC\u30C9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
return fetchWithAuth(
|
|
1131
|
+
`${RESET_PASSWORD_BASE}/confirm`,
|
|
1132
|
+
{
|
|
1133
|
+
method: "POST",
|
|
1134
|
+
body: JSON.stringify({ password })
|
|
1135
|
+
}
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1138
|
+
return {
|
|
1139
|
+
requestPasswordReset,
|
|
1140
|
+
verifyPasswordResetToken,
|
|
1141
|
+
establishResetSession,
|
|
1142
|
+
confirmPasswordReset
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
// src/client/otp.ts
|
|
1147
|
+
var OTP_BASE = "/api/v1/auth/otp";
|
|
1148
|
+
function isBlank2(value) {
|
|
1149
|
+
return !value || !value.trim();
|
|
1150
|
+
}
|
|
1151
|
+
function createOtpMethods(deps) {
|
|
1152
|
+
const { baseUrl, logger, createError, errorCodes } = deps;
|
|
1153
|
+
async function fetchPublic(endpoint, options = {}) {
|
|
1154
|
+
const url = `${baseUrl}${endpoint}`;
|
|
1155
|
+
logger.debug("Fetching (public):", url);
|
|
1156
|
+
let response;
|
|
1157
|
+
try {
|
|
1158
|
+
response = await fetch(url, {
|
|
1159
|
+
...options,
|
|
1160
|
+
credentials: "include",
|
|
1161
|
+
headers: {
|
|
1162
|
+
"Content-Type": "application/json",
|
|
1163
|
+
...sdkHeaders(),
|
|
1164
|
+
...options.headers
|
|
1165
|
+
}
|
|
1166
|
+
});
|
|
1167
|
+
} catch (error) {
|
|
1168
|
+
logger.error("Network error:", error);
|
|
1169
|
+
return {
|
|
1170
|
+
error: {
|
|
1171
|
+
code: errorCodes.NETWORK_ERROR,
|
|
1172
|
+
message: error instanceof Error ? error.message : "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F"
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
}
|
|
1176
|
+
let raw;
|
|
1177
|
+
try {
|
|
1178
|
+
raw = await response.json();
|
|
1179
|
+
} catch (parseError) {
|
|
1180
|
+
logger.error("Parse error:", parseError, "Status:", response.status);
|
|
1181
|
+
return {
|
|
1182
|
+
error: {
|
|
1183
|
+
code: errorCodes.PARSE_ERROR,
|
|
1184
|
+
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})`
|
|
1185
|
+
}
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
logger.debug("Response (public):", response.status, raw);
|
|
1189
|
+
checkVersionHeader(response, logger);
|
|
1190
|
+
if (!response.ok) {
|
|
1191
|
+
return {
|
|
1192
|
+
error: raw.error ?? {
|
|
1193
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1194
|
+
message: "OTP\u8A8D\u8A3C\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
|
|
1195
|
+
}
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
if (raw.data === void 0) {
|
|
1199
|
+
return {
|
|
1200
|
+
error: {
|
|
1201
|
+
code: errorCodes.UNKNOWN_ERROR,
|
|
1202
|
+
message: "\u30B5\u30FC\u30D0\u30FC\u304B\u3089\u30C7\u30FC\u30BF\u304C\u8FD4\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F"
|
|
1203
|
+
}
|
|
1204
|
+
};
|
|
1205
|
+
}
|
|
1206
|
+
return { data: raw.data };
|
|
1207
|
+
}
|
|
1208
|
+
async function sendOtp(email, options) {
|
|
1209
|
+
if (isBlank2(email)) {
|
|
1210
|
+
return {
|
|
1211
|
+
error: createError("VALIDATION_ERROR", "\u30E1\u30FC\u30EB\u30A2\u30C9\u30EC\u30B9\u306F\u5FC5\u9808\u3067\u3059")
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
return fetchPublic(
|
|
1215
|
+
`${OTP_BASE}/send`,
|
|
1216
|
+
{
|
|
1217
|
+
method: "POST",
|
|
1218
|
+
body: JSON.stringify({
|
|
1219
|
+
email,
|
|
1220
|
+
...options?.redirectUrl ? { redirectUrl: options.redirectUrl } : {}
|
|
1221
|
+
})
|
|
1222
|
+
}
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
async function verifyOtp(params) {
|
|
1226
|
+
if (isBlank2(params.accessToken)) {
|
|
1227
|
+
return {
|
|
1228
|
+
error: createError("VALIDATION_ERROR", "\u30A2\u30AF\u30BB\u30B9\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1229
|
+
};
|
|
1230
|
+
}
|
|
1231
|
+
if (isBlank2(params.refreshToken)) {
|
|
1232
|
+
return {
|
|
1233
|
+
error: createError("VALIDATION_ERROR", "\u30EA\u30D5\u30EC\u30C3\u30B7\u30E5\u30C8\u30FC\u30AF\u30F3\u306F\u5FC5\u9808\u3067\u3059")
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
return fetchPublic(
|
|
1237
|
+
`${OTP_BASE}/verify`,
|
|
1238
|
+
{
|
|
1239
|
+
method: "POST",
|
|
1240
|
+
body: JSON.stringify({
|
|
1241
|
+
accessToken: params.accessToken,
|
|
1242
|
+
refreshToken: params.refreshToken
|
|
1243
|
+
})
|
|
1244
|
+
}
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
return {
|
|
1248
|
+
sendOtp,
|
|
1249
|
+
verifyOtp
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
|
|
955
1253
|
// src/client/ffid-client.ts
|
|
956
1254
|
var UNAUTHORIZED_STATUS2 = 401;
|
|
957
1255
|
var SDK_LOG_PREFIX = "[FFID SDK]";
|
|
@@ -1084,6 +1382,9 @@ function createFFIDClient(config) {
|
|
|
1084
1382
|
}
|
|
1085
1383
|
};
|
|
1086
1384
|
}
|
|
1385
|
+
} else {
|
|
1386
|
+
logger.warn("Token refresh failed, returning refresh error:", refreshResult.error);
|
|
1387
|
+
return { error: refreshResult.error };
|
|
1087
1388
|
}
|
|
1088
1389
|
}
|
|
1089
1390
|
let raw;
|
|
@@ -1161,6 +1462,24 @@ function createFFIDClient(config) {
|
|
|
1161
1462
|
fetchWithAuth,
|
|
1162
1463
|
createError
|
|
1163
1464
|
});
|
|
1465
|
+
const {
|
|
1466
|
+
requestPasswordReset,
|
|
1467
|
+
verifyPasswordResetToken,
|
|
1468
|
+
establishResetSession,
|
|
1469
|
+
confirmPasswordReset
|
|
1470
|
+
} = createPasswordResetMethods({
|
|
1471
|
+
baseUrl,
|
|
1472
|
+
logger,
|
|
1473
|
+
createError,
|
|
1474
|
+
fetchWithAuth,
|
|
1475
|
+
errorCodes: FFID_ERROR_CODES
|
|
1476
|
+
});
|
|
1477
|
+
const { sendOtp, verifyOtp } = createOtpMethods({
|
|
1478
|
+
baseUrl,
|
|
1479
|
+
logger,
|
|
1480
|
+
createError,
|
|
1481
|
+
errorCodes: FFID_ERROR_CODES
|
|
1482
|
+
});
|
|
1164
1483
|
const verifyAccessToken = createVerifyAccessToken({
|
|
1165
1484
|
authMode,
|
|
1166
1485
|
baseUrl,
|
|
@@ -1186,6 +1505,12 @@ function createFFIDClient(config) {
|
|
|
1186
1505
|
createCheckoutSession,
|
|
1187
1506
|
createPortalSession,
|
|
1188
1507
|
verifyAccessToken,
|
|
1508
|
+
requestPasswordReset,
|
|
1509
|
+
verifyPasswordResetToken,
|
|
1510
|
+
establishResetSession,
|
|
1511
|
+
confirmPasswordReset,
|
|
1512
|
+
sendOtp,
|
|
1513
|
+
verifyOtp,
|
|
1189
1514
|
/** Token store (token mode only) */
|
|
1190
1515
|
tokenStore,
|
|
1191
1516
|
/** Resolved auth mode */
|
package/dist/server/index.d.cts
CHANGED
|
@@ -301,6 +301,55 @@ interface FFIDCreatePortalParams {
|
|
|
301
301
|
/** URL to redirect when user exits the portal */
|
|
302
302
|
returnUrl: string;
|
|
303
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Result of a redirect operation (redirectToLogin / redirectToAuthorize)
|
|
306
|
+
*
|
|
307
|
+
* Structured return type so callers can inspect failure reasons
|
|
308
|
+
* instead of receiving a bare `false`.
|
|
309
|
+
*/
|
|
310
|
+
type FFIDRedirectResult = {
|
|
311
|
+
success: true;
|
|
312
|
+
} | {
|
|
313
|
+
success: false;
|
|
314
|
+
error: string;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
/** OTP / magic link methods - sendOtp / verifyOtp */
|
|
318
|
+
|
|
319
|
+
/** Response from sendOtp */
|
|
320
|
+
interface FFIDOtpSendResponse {
|
|
321
|
+
message: string;
|
|
322
|
+
}
|
|
323
|
+
/** Response from verifyOtp */
|
|
324
|
+
interface FFIDOtpVerifyResponse {
|
|
325
|
+
user: {
|
|
326
|
+
id: string;
|
|
327
|
+
email: string;
|
|
328
|
+
displayName: string | null;
|
|
329
|
+
avatarUrl: string | null;
|
|
330
|
+
};
|
|
331
|
+
session: {
|
|
332
|
+
accessToken: string;
|
|
333
|
+
refreshToken: string;
|
|
334
|
+
expiresAt: number;
|
|
335
|
+
expiresIn: number;
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** Password reset methods - requestPasswordReset / verifyPasswordResetToken / establishResetSession / confirmPasswordReset */
|
|
340
|
+
|
|
341
|
+
/** Response from requestPasswordReset */
|
|
342
|
+
interface FFIDPasswordResetResponse {
|
|
343
|
+
message: string;
|
|
344
|
+
}
|
|
345
|
+
/** Response from verifyPasswordResetToken */
|
|
346
|
+
interface FFIDPasswordResetVerifyResponse {
|
|
347
|
+
valid: boolean;
|
|
348
|
+
}
|
|
349
|
+
/** Response from establishResetSession */
|
|
350
|
+
type FFIDResetSessionResponse = FFIDPasswordResetResponse;
|
|
351
|
+
/** Response from confirmPasswordReset */
|
|
352
|
+
type FFIDPasswordResetConfirmResponse = FFIDPasswordResetResponse;
|
|
304
353
|
|
|
305
354
|
/**
|
|
306
355
|
* Token Store
|
|
@@ -347,7 +396,7 @@ declare function createTokenStore(storageType?: 'localStorage' | 'memory'): Toke
|
|
|
347
396
|
declare function createFFIDClient(config: FFIDConfig): {
|
|
348
397
|
getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
|
|
349
398
|
signOut: () => Promise<FFIDApiResponse<void>>;
|
|
350
|
-
redirectToLogin: () => Promise<
|
|
399
|
+
redirectToLogin: () => Promise<FFIDRedirectResult>;
|
|
351
400
|
getLoginUrl: (redirectUrl?: string) => string;
|
|
352
401
|
getSignupUrl: (redirectUrl?: string) => string;
|
|
353
402
|
createError: (code: string, message: string) => FFIDError;
|
|
@@ -360,6 +409,17 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
360
409
|
createCheckoutSession: (params: FFIDCreateCheckoutParams) => Promise<FFIDApiResponse<FFIDCheckoutSessionResponse>>;
|
|
361
410
|
createPortalSession: (params: FFIDCreatePortalParams) => Promise<FFIDApiResponse<FFIDPortalSessionResponse>>;
|
|
362
411
|
verifyAccessToken: (accessToken: string, options?: FFIDVerifyAccessTokenOptions) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
|
|
412
|
+
requestPasswordReset: (email: string) => Promise<FFIDApiResponse<FFIDPasswordResetResponse>>;
|
|
413
|
+
verifyPasswordResetToken: (accessToken: string) => Promise<FFIDApiResponse<FFIDPasswordResetVerifyResponse>>;
|
|
414
|
+
establishResetSession: (accessToken: string, refreshToken: string) => Promise<FFIDApiResponse<FFIDResetSessionResponse>>;
|
|
415
|
+
confirmPasswordReset: (password: string) => Promise<FFIDApiResponse<FFIDPasswordResetConfirmResponse>>;
|
|
416
|
+
sendOtp: (email: string, options?: {
|
|
417
|
+
redirectUrl?: string;
|
|
418
|
+
}) => Promise<FFIDApiResponse<FFIDOtpSendResponse>>;
|
|
419
|
+
verifyOtp: (params: {
|
|
420
|
+
accessToken: string;
|
|
421
|
+
refreshToken: string;
|
|
422
|
+
}) => Promise<FFIDApiResponse<FFIDOtpVerifyResponse>>;
|
|
363
423
|
/** Token store (token mode only) */
|
|
364
424
|
tokenStore: TokenStore;
|
|
365
425
|
/** Resolved auth mode */
|
|
@@ -428,4 +488,4 @@ interface KVNamespaceLike {
|
|
|
428
488
|
*/
|
|
429
489
|
declare function createKVCacheAdapter(kv: KVNamespaceLike): FFIDCacheAdapter;
|
|
430
490
|
|
|
431
|
-
export { type FFIDCacheAdapter, type FFIDCacheConfig, type FFIDClient, type FFIDConfig, type FFIDOAuthUserInfo, type FFIDOrganization, type FFIDSubscription, type FFIDUser, type FFIDVerifyAccessTokenOptions, type KVNamespaceLike, type TokenData, type TokenStore, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, createVerifyAccessToken };
|
|
491
|
+
export { type FFIDCacheAdapter, type FFIDCacheConfig, type FFIDClient, type FFIDConfig, type FFIDOAuthUserInfo, type FFIDOrganization, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDResetSessionResponse, type FFIDSubscription, type FFIDUser, type FFIDVerifyAccessTokenOptions, type KVNamespaceLike, type TokenData, type TokenStore, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, createVerifyAccessToken };
|
package/dist/server/index.d.ts
CHANGED
|
@@ -301,6 +301,55 @@ interface FFIDCreatePortalParams {
|
|
|
301
301
|
/** URL to redirect when user exits the portal */
|
|
302
302
|
returnUrl: string;
|
|
303
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Result of a redirect operation (redirectToLogin / redirectToAuthorize)
|
|
306
|
+
*
|
|
307
|
+
* Structured return type so callers can inspect failure reasons
|
|
308
|
+
* instead of receiving a bare `false`.
|
|
309
|
+
*/
|
|
310
|
+
type FFIDRedirectResult = {
|
|
311
|
+
success: true;
|
|
312
|
+
} | {
|
|
313
|
+
success: false;
|
|
314
|
+
error: string;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
/** OTP / magic link methods - sendOtp / verifyOtp */
|
|
318
|
+
|
|
319
|
+
/** Response from sendOtp */
|
|
320
|
+
interface FFIDOtpSendResponse {
|
|
321
|
+
message: string;
|
|
322
|
+
}
|
|
323
|
+
/** Response from verifyOtp */
|
|
324
|
+
interface FFIDOtpVerifyResponse {
|
|
325
|
+
user: {
|
|
326
|
+
id: string;
|
|
327
|
+
email: string;
|
|
328
|
+
displayName: string | null;
|
|
329
|
+
avatarUrl: string | null;
|
|
330
|
+
};
|
|
331
|
+
session: {
|
|
332
|
+
accessToken: string;
|
|
333
|
+
refreshToken: string;
|
|
334
|
+
expiresAt: number;
|
|
335
|
+
expiresIn: number;
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** Password reset methods - requestPasswordReset / verifyPasswordResetToken / establishResetSession / confirmPasswordReset */
|
|
340
|
+
|
|
341
|
+
/** Response from requestPasswordReset */
|
|
342
|
+
interface FFIDPasswordResetResponse {
|
|
343
|
+
message: string;
|
|
344
|
+
}
|
|
345
|
+
/** Response from verifyPasswordResetToken */
|
|
346
|
+
interface FFIDPasswordResetVerifyResponse {
|
|
347
|
+
valid: boolean;
|
|
348
|
+
}
|
|
349
|
+
/** Response from establishResetSession */
|
|
350
|
+
type FFIDResetSessionResponse = FFIDPasswordResetResponse;
|
|
351
|
+
/** Response from confirmPasswordReset */
|
|
352
|
+
type FFIDPasswordResetConfirmResponse = FFIDPasswordResetResponse;
|
|
304
353
|
|
|
305
354
|
/**
|
|
306
355
|
* Token Store
|
|
@@ -347,7 +396,7 @@ declare function createTokenStore(storageType?: 'localStorage' | 'memory'): Toke
|
|
|
347
396
|
declare function createFFIDClient(config: FFIDConfig): {
|
|
348
397
|
getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
|
|
349
398
|
signOut: () => Promise<FFIDApiResponse<void>>;
|
|
350
|
-
redirectToLogin: () => Promise<
|
|
399
|
+
redirectToLogin: () => Promise<FFIDRedirectResult>;
|
|
351
400
|
getLoginUrl: (redirectUrl?: string) => string;
|
|
352
401
|
getSignupUrl: (redirectUrl?: string) => string;
|
|
353
402
|
createError: (code: string, message: string) => FFIDError;
|
|
@@ -360,6 +409,17 @@ declare function createFFIDClient(config: FFIDConfig): {
|
|
|
360
409
|
createCheckoutSession: (params: FFIDCreateCheckoutParams) => Promise<FFIDApiResponse<FFIDCheckoutSessionResponse>>;
|
|
361
410
|
createPortalSession: (params: FFIDCreatePortalParams) => Promise<FFIDApiResponse<FFIDPortalSessionResponse>>;
|
|
362
411
|
verifyAccessToken: (accessToken: string, options?: FFIDVerifyAccessTokenOptions) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
|
|
412
|
+
requestPasswordReset: (email: string) => Promise<FFIDApiResponse<FFIDPasswordResetResponse>>;
|
|
413
|
+
verifyPasswordResetToken: (accessToken: string) => Promise<FFIDApiResponse<FFIDPasswordResetVerifyResponse>>;
|
|
414
|
+
establishResetSession: (accessToken: string, refreshToken: string) => Promise<FFIDApiResponse<FFIDResetSessionResponse>>;
|
|
415
|
+
confirmPasswordReset: (password: string) => Promise<FFIDApiResponse<FFIDPasswordResetConfirmResponse>>;
|
|
416
|
+
sendOtp: (email: string, options?: {
|
|
417
|
+
redirectUrl?: string;
|
|
418
|
+
}) => Promise<FFIDApiResponse<FFIDOtpSendResponse>>;
|
|
419
|
+
verifyOtp: (params: {
|
|
420
|
+
accessToken: string;
|
|
421
|
+
refreshToken: string;
|
|
422
|
+
}) => Promise<FFIDApiResponse<FFIDOtpVerifyResponse>>;
|
|
363
423
|
/** Token store (token mode only) */
|
|
364
424
|
tokenStore: TokenStore;
|
|
365
425
|
/** Resolved auth mode */
|
|
@@ -428,4 +488,4 @@ interface KVNamespaceLike {
|
|
|
428
488
|
*/
|
|
429
489
|
declare function createKVCacheAdapter(kv: KVNamespaceLike): FFIDCacheAdapter;
|
|
430
490
|
|
|
431
|
-
export { type FFIDCacheAdapter, type FFIDCacheConfig, type FFIDClient, type FFIDConfig, type FFIDOAuthUserInfo, type FFIDOrganization, type FFIDSubscription, type FFIDUser, type FFIDVerifyAccessTokenOptions, type KVNamespaceLike, type TokenData, type TokenStore, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, createVerifyAccessToken };
|
|
491
|
+
export { type FFIDCacheAdapter, type FFIDCacheConfig, type FFIDClient, type FFIDConfig, type FFIDOAuthUserInfo, type FFIDOrganization, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDResetSessionResponse, type FFIDSubscription, type FFIDUser, type FFIDVerifyAccessTokenOptions, type KVNamespaceLike, type TokenData, type TokenStore, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, createVerifyAccessToken };
|