@gatwech/core 0.0.10 → 1.0.0-beta.18
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/api/index.d.mts +2 -2
- package/dist/context/index.d.mts +2 -2
- package/dist/db/adapter/index.d.mts +2 -2
- package/dist/db/index.d.mts +2 -2
- package/dist/env/index.d.mts +1 -1
- package/dist/env/index.mjs +1 -1
- package/dist/{env-JMSMESs1.mjs → env-4_Lym7sj.mjs} +7 -7
- package/dist/index-65G5U5DB.d.mts +3002 -0
- package/dist/{index-DLP-K0uY.d.mts → index-CmdhhvA2.d.mts} +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/oauth2/index.d.mts +2 -2
- package/dist/social-providers/index.d.mts +3 -3
- package/dist/social-providers/index.mjs +71 -2412
- package/dist/src/api/index.d.ts +119 -0
- package/dist/src/async_hooks/index.d.ts +6 -0
- package/dist/src/context/endpoint-context.d.ts +14 -0
- package/dist/src/context/index.d.ts +3 -0
- package/dist/src/context/request-state.d.ts +13 -0
- package/dist/src/context/transaction.d.ts +11 -0
- package/dist/src/db/adapter/index.d.ts +401 -0
- package/{src/db/index.ts → dist/src/db/index.d.ts} +2 -18
- package/dist/src/db/plugin.d.ts +10 -0
- package/dist/src/db/schema/account.d.ts +22 -0
- package/dist/src/db/schema/rate-limit.d.ts +10 -0
- package/dist/src/db/schema/session.d.ts +17 -0
- package/dist/src/db/schema/shared.d.ts +6 -0
- package/dist/src/db/schema/user.d.ts +16 -0
- package/{src/db/schema/verification.ts → dist/src/db/schema/verification.d.ts} +8 -8
- package/dist/src/db/type.d.ts +159 -0
- package/dist/src/env/color-depth.d.ts +1 -0
- package/dist/src/env/env-impl.d.ts +29 -0
- package/dist/src/env/index.d.ts +3 -0
- package/dist/src/env/logger.d.ts +50 -0
- package/dist/src/error/codes.d.ts +27 -0
- package/dist/src/error/index.d.ts +4 -0
- package/dist/src/oauth2/client-credentials-token.d.ts +21 -0
- package/dist/src/oauth2/create-authorization-url.d.ts +21 -0
- package/dist/src/oauth2/index.d.ts +6 -0
- package/dist/src/oauth2/oauth-provider.d.ts +178 -0
- package/dist/src/oauth2/refresh-access-token.d.ts +20 -0
- package/dist/src/oauth2/utils.d.ts +3 -0
- package/dist/src/oauth2/validate-authorization-code.d.ts +28 -0
- package/dist/src/social-providers/github.d.ts +89 -0
- package/dist/src/social-providers/google.d.ts +82 -0
- package/dist/src/social-providers/index.d.ts +93 -0
- package/dist/src/types/context.d.ts +177 -0
- package/dist/src/types/cookie.d.ts +15 -0
- package/dist/src/types/helper.d.ts +9 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/init-options.d.ts +1140 -0
- package/dist/src/types/plugin-client.d.ts +88 -0
- package/dist/src/types/plugin.d.ts +120 -0
- package/dist/src/utils/error-codes.d.ts +9 -0
- package/package.json +11 -5
- package/.turbo/turbo-build.log +0 -42
- package/dist/index-DjrJweYn.d.mts +0 -7312
- package/src/api/index.ts +0 -57
- package/src/async_hooks/index.ts +0 -35
- package/src/context/endpoint-context.ts +0 -48
- package/src/context/index.ts +0 -21
- package/src/context/request-state.test.ts +0 -346
- package/src/context/request-state.ts +0 -75
- package/src/context/transaction.ts +0 -72
- package/src/db/adapter/index.ts +0 -466
- package/src/db/plugin.ts +0 -11
- package/src/db/schema/account.ts +0 -34
- package/src/db/schema/rate-limit.ts +0 -21
- package/src/db/schema/session.ts +0 -17
- package/src/db/schema/shared.ts +0 -7
- package/src/db/schema/user.ts +0 -16
- package/src/db/type.ts +0 -180
- package/src/env/color-depth.ts +0 -172
- package/src/env/env-impl.ts +0 -124
- package/src/env/index.ts +0 -23
- package/src/env/logger.test.ts +0 -33
- package/src/env/logger.ts +0 -145
- package/src/error/codes.ts +0 -31
- package/src/error/index.ts +0 -11
- package/src/oauth2/client-credentials-token.ts +0 -102
- package/src/oauth2/create-authorization-url.ts +0 -85
- package/src/oauth2/index.ts +0 -21
- package/src/oauth2/oauth-provider.ts +0 -211
- package/src/oauth2/refresh-access-token.ts +0 -124
- package/src/oauth2/utils.ts +0 -36
- package/src/oauth2/validate-authorization-code.ts +0 -154
- package/src/social-providers/apple.ts +0 -213
- package/src/social-providers/atlassian.ts +0 -132
- package/src/social-providers/cognito.ts +0 -269
- package/src/social-providers/discord.ts +0 -169
- package/src/social-providers/dropbox.ts +0 -112
- package/src/social-providers/facebook.ts +0 -204
- package/src/social-providers/figma.ts +0 -115
- package/src/social-providers/github.ts +0 -154
- package/src/social-providers/gitlab.ts +0 -152
- package/src/social-providers/google.ts +0 -171
- package/src/social-providers/huggingface.ts +0 -118
- package/src/social-providers/index.ts +0 -124
- package/src/social-providers/kakao.ts +0 -178
- package/src/social-providers/kick.ts +0 -92
- package/src/social-providers/line.ts +0 -169
- package/src/social-providers/linear.ts +0 -120
- package/src/social-providers/linkedin.ts +0 -110
- package/src/social-providers/microsoft-entra-id.ts +0 -245
- package/src/social-providers/naver.ts +0 -112
- package/src/social-providers/notion.ts +0 -108
- package/src/social-providers/paybin.ts +0 -122
- package/src/social-providers/paypal.ts +0 -263
- package/src/social-providers/polar.ts +0 -107
- package/src/social-providers/reddit.ts +0 -122
- package/src/social-providers/roblox.ts +0 -110
- package/src/social-providers/salesforce.ts +0 -159
- package/src/social-providers/slack.ts +0 -111
- package/src/social-providers/spotify.ts +0 -93
- package/src/social-providers/tiktok.ts +0 -210
- package/src/social-providers/twitch.ts +0 -111
- package/src/social-providers/twitter.ts +0 -198
- package/src/social-providers/vk.ts +0 -126
- package/src/social-providers/zoom.ts +0 -217
- package/src/types/context.ts +0 -269
- package/src/types/cookie.ts +0 -7
- package/src/types/helper.ts +0 -6
- package/src/types/index.ts +0 -21
- package/src/types/init-options.ts +0 -1346
- package/src/types/plugin-client.ts +0 -100
- package/src/types/plugin.ts +0 -158
- package/src/utils/error-codes.ts +0 -51
- package/tsconfig.json +0 -7
- package/tsdown.config.ts +0 -20
- /package/{src/index.ts → dist/src/index.d.ts} +0 -0
- /package/{src/utils/index.ts → dist/src/utils/index.d.ts} +0 -0
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
|
-
import {
|
|
4
|
-
createAuthorizationURL,
|
|
5
|
-
refreshAccessToken,
|
|
6
|
-
validateAuthorizationCode,
|
|
7
|
-
} from "../oauth2";
|
|
8
|
-
|
|
9
|
-
export interface NaverProfile {
|
|
10
|
-
/** API response result code */
|
|
11
|
-
resultcode: string;
|
|
12
|
-
/** API response message */
|
|
13
|
-
message: string;
|
|
14
|
-
response: {
|
|
15
|
-
/** Unique Naver user identifier */
|
|
16
|
-
id: string;
|
|
17
|
-
/** User nickname */
|
|
18
|
-
nickname: string;
|
|
19
|
-
/** User real name */
|
|
20
|
-
name: string;
|
|
21
|
-
/** User email address */
|
|
22
|
-
email: string;
|
|
23
|
-
/** Gender (F: female, M: male, U: unknown) */
|
|
24
|
-
gender: string;
|
|
25
|
-
/** Age range */
|
|
26
|
-
age: string;
|
|
27
|
-
/** Birthday (MM-DD format) */
|
|
28
|
-
birthday: string;
|
|
29
|
-
/** Birth year */
|
|
30
|
-
birthyear: string;
|
|
31
|
-
/** Profile image URL */
|
|
32
|
-
profile_image: string;
|
|
33
|
-
/** Mobile phone number */
|
|
34
|
-
mobile: string;
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface NaverOptions extends ProviderOptions<NaverProfile> {
|
|
39
|
-
clientId: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export const naver = (options: NaverOptions) => {
|
|
43
|
-
return {
|
|
44
|
-
id: "naver",
|
|
45
|
-
name: "Naver",
|
|
46
|
-
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
47
|
-
const _scopes = options.disableDefaultScope ? [] : ["profile", "email"];
|
|
48
|
-
if (options.scope) _scopes.push(...options.scope);
|
|
49
|
-
if (scopes) _scopes.push(...scopes);
|
|
50
|
-
return createAuthorizationURL({
|
|
51
|
-
id: "naver",
|
|
52
|
-
options,
|
|
53
|
-
authorizationEndpoint: "https://nid.naver.com/oauth2.0/authorize",
|
|
54
|
-
scopes: _scopes,
|
|
55
|
-
state,
|
|
56
|
-
redirectURI,
|
|
57
|
-
});
|
|
58
|
-
},
|
|
59
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
60
|
-
return validateAuthorizationCode({
|
|
61
|
-
code,
|
|
62
|
-
redirectURI,
|
|
63
|
-
options,
|
|
64
|
-
tokenEndpoint: "https://nid.naver.com/oauth2.0/token",
|
|
65
|
-
});
|
|
66
|
-
},
|
|
67
|
-
refreshAccessToken: options.refreshAccessToken
|
|
68
|
-
? options.refreshAccessToken
|
|
69
|
-
: async (refreshToken) => {
|
|
70
|
-
return refreshAccessToken({
|
|
71
|
-
refreshToken,
|
|
72
|
-
options: {
|
|
73
|
-
clientId: options.clientId,
|
|
74
|
-
clientKey: options.clientKey,
|
|
75
|
-
clientSecret: options.clientSecret,
|
|
76
|
-
},
|
|
77
|
-
tokenEndpoint: "https://nid.naver.com/oauth2.0/token",
|
|
78
|
-
});
|
|
79
|
-
},
|
|
80
|
-
async getUserInfo(token) {
|
|
81
|
-
if (options.getUserInfo) {
|
|
82
|
-
return options.getUserInfo(token);
|
|
83
|
-
}
|
|
84
|
-
const { data: profile, error } = await betterFetch<NaverProfile>(
|
|
85
|
-
"https://openapi.naver.com/v1/nid/me",
|
|
86
|
-
{
|
|
87
|
-
headers: {
|
|
88
|
-
Authorization: `Bearer ${token.accessToken}`,
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
);
|
|
92
|
-
if (error || !profile || profile.resultcode !== "00") {
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
const userMap = await options.mapProfileToUser?.(profile);
|
|
96
|
-
const res = profile.response || {};
|
|
97
|
-
const user = {
|
|
98
|
-
id: res.id,
|
|
99
|
-
name: res.name || res.nickname,
|
|
100
|
-
email: res.email,
|
|
101
|
-
image: res.profile_image,
|
|
102
|
-
emailVerified: false,
|
|
103
|
-
...userMap,
|
|
104
|
-
};
|
|
105
|
-
return {
|
|
106
|
-
user,
|
|
107
|
-
data: profile,
|
|
108
|
-
};
|
|
109
|
-
},
|
|
110
|
-
options,
|
|
111
|
-
} satisfies OAuthProvider<NaverProfile>;
|
|
112
|
-
};
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
|
-
import {
|
|
4
|
-
createAuthorizationURL,
|
|
5
|
-
refreshAccessToken,
|
|
6
|
-
validateAuthorizationCode,
|
|
7
|
-
} from "../oauth2";
|
|
8
|
-
|
|
9
|
-
export interface NotionProfile {
|
|
10
|
-
object: "user";
|
|
11
|
-
id: string;
|
|
12
|
-
type: "person" | "bot";
|
|
13
|
-
name?: string | undefined;
|
|
14
|
-
avatar_url?: string | undefined;
|
|
15
|
-
person?:
|
|
16
|
-
| {
|
|
17
|
-
email?: string;
|
|
18
|
-
}
|
|
19
|
-
| undefined;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface NotionOptions extends ProviderOptions<NotionProfile> {
|
|
23
|
-
clientId: string;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const notion = (options: NotionOptions) => {
|
|
27
|
-
const tokenEndpoint = "https://api.notion.com/v1/oauth/token";
|
|
28
|
-
return {
|
|
29
|
-
id: "notion",
|
|
30
|
-
name: "Notion",
|
|
31
|
-
createAuthorizationURL({ state, scopes, loginHint, redirectURI }) {
|
|
32
|
-
const _scopes: string[] = options.disableDefaultScope ? [] : [];
|
|
33
|
-
if (options.scope) _scopes.push(...options.scope);
|
|
34
|
-
if (scopes) _scopes.push(...scopes);
|
|
35
|
-
return createAuthorizationURL({
|
|
36
|
-
id: "notion",
|
|
37
|
-
options,
|
|
38
|
-
authorizationEndpoint: "https://api.notion.com/v1/oauth/authorize",
|
|
39
|
-
scopes: _scopes,
|
|
40
|
-
state,
|
|
41
|
-
redirectURI,
|
|
42
|
-
loginHint,
|
|
43
|
-
additionalParams: {
|
|
44
|
-
owner: "user",
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
},
|
|
48
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
49
|
-
return validateAuthorizationCode({
|
|
50
|
-
code,
|
|
51
|
-
redirectURI,
|
|
52
|
-
options,
|
|
53
|
-
tokenEndpoint,
|
|
54
|
-
authentication: "basic",
|
|
55
|
-
});
|
|
56
|
-
},
|
|
57
|
-
refreshAccessToken: options.refreshAccessToken
|
|
58
|
-
? options.refreshAccessToken
|
|
59
|
-
: async (refreshToken) => {
|
|
60
|
-
return refreshAccessToken({
|
|
61
|
-
refreshToken,
|
|
62
|
-
options: {
|
|
63
|
-
clientId: options.clientId,
|
|
64
|
-
clientKey: options.clientKey,
|
|
65
|
-
clientSecret: options.clientSecret,
|
|
66
|
-
},
|
|
67
|
-
tokenEndpoint,
|
|
68
|
-
});
|
|
69
|
-
},
|
|
70
|
-
async getUserInfo(token) {
|
|
71
|
-
if (options.getUserInfo) {
|
|
72
|
-
return options.getUserInfo(token);
|
|
73
|
-
}
|
|
74
|
-
const { data: profile, error } = await betterFetch<{
|
|
75
|
-
bot: {
|
|
76
|
-
owner: {
|
|
77
|
-
user: NotionProfile;
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
}>("https://api.notion.com/v1/users/me", {
|
|
81
|
-
headers: {
|
|
82
|
-
Authorization: `Bearer ${token.accessToken}`,
|
|
83
|
-
"Notion-Version": "2022-06-28",
|
|
84
|
-
},
|
|
85
|
-
});
|
|
86
|
-
if (error || !profile) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
const userProfile = profile.bot?.owner?.user;
|
|
90
|
-
if (!userProfile) {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
const userMap = await options.mapProfileToUser?.(userProfile);
|
|
94
|
-
return {
|
|
95
|
-
user: {
|
|
96
|
-
id: userProfile.id,
|
|
97
|
-
name: userProfile.name || "Notion User",
|
|
98
|
-
email: userProfile.person?.email || null,
|
|
99
|
-
image: userProfile.avatar_url,
|
|
100
|
-
emailVerified: !!userProfile.person?.email,
|
|
101
|
-
...userMap,
|
|
102
|
-
},
|
|
103
|
-
data: userProfile,
|
|
104
|
-
};
|
|
105
|
-
},
|
|
106
|
-
options,
|
|
107
|
-
} satisfies OAuthProvider<NotionProfile>;
|
|
108
|
-
};
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { decodeJwt } from "jose";
|
|
2
|
-
import { logger } from "../env";
|
|
3
|
-
import { PayvoAuthError } from "../error";
|
|
4
|
-
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
5
|
-
import {
|
|
6
|
-
createAuthorizationURL,
|
|
7
|
-
refreshAccessToken,
|
|
8
|
-
validateAuthorizationCode,
|
|
9
|
-
} from "../oauth2";
|
|
10
|
-
|
|
11
|
-
export interface PaybinProfile {
|
|
12
|
-
sub: string;
|
|
13
|
-
email: string;
|
|
14
|
-
email_verified?: boolean | undefined;
|
|
15
|
-
name?: string | undefined;
|
|
16
|
-
preferred_username?: string | undefined;
|
|
17
|
-
picture?: string | undefined;
|
|
18
|
-
given_name?: string | undefined;
|
|
19
|
-
family_name?: string | undefined;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface PaybinOptions extends ProviderOptions<PaybinProfile> {
|
|
23
|
-
clientId: string;
|
|
24
|
-
/**
|
|
25
|
-
* The issuer URL of your Paybin OAuth server
|
|
26
|
-
* @default "https://idp.paybin.io"
|
|
27
|
-
*/
|
|
28
|
-
issuer?: string | undefined;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const paybin = (options: PaybinOptions) => {
|
|
32
|
-
const issuer = options.issuer || "https://idp.paybin.io";
|
|
33
|
-
const authorizationEndpoint = `${issuer}/oauth2/authorize`;
|
|
34
|
-
const tokenEndpoint = `${issuer}/oauth2/token`;
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
id: "paybin",
|
|
38
|
-
name: "Paybin",
|
|
39
|
-
async createAuthorizationURL({
|
|
40
|
-
state,
|
|
41
|
-
scopes,
|
|
42
|
-
codeVerifier,
|
|
43
|
-
redirectURI,
|
|
44
|
-
loginHint,
|
|
45
|
-
}) {
|
|
46
|
-
if (!options.clientId || !options.clientSecret) {
|
|
47
|
-
logger.error(
|
|
48
|
-
"Client Id and Client Secret is required for Paybin. Make sure to provide them in the options."
|
|
49
|
-
);
|
|
50
|
-
throw new PayvoAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
|
|
51
|
-
}
|
|
52
|
-
if (!codeVerifier) {
|
|
53
|
-
throw new PayvoAuthError("codeVerifier is required for Paybin");
|
|
54
|
-
}
|
|
55
|
-
const _scopes = options.disableDefaultScope
|
|
56
|
-
? []
|
|
57
|
-
: ["openid", "email", "profile"];
|
|
58
|
-
if (options.scope) _scopes.push(...options.scope);
|
|
59
|
-
if (scopes) _scopes.push(...scopes);
|
|
60
|
-
const url = await createAuthorizationURL({
|
|
61
|
-
id: "paybin",
|
|
62
|
-
options,
|
|
63
|
-
authorizationEndpoint,
|
|
64
|
-
scopes: _scopes,
|
|
65
|
-
state,
|
|
66
|
-
codeVerifier,
|
|
67
|
-
redirectURI,
|
|
68
|
-
prompt: options.prompt,
|
|
69
|
-
loginHint,
|
|
70
|
-
});
|
|
71
|
-
return url;
|
|
72
|
-
},
|
|
73
|
-
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
74
|
-
return validateAuthorizationCode({
|
|
75
|
-
code,
|
|
76
|
-
codeVerifier,
|
|
77
|
-
redirectURI,
|
|
78
|
-
options,
|
|
79
|
-
tokenEndpoint,
|
|
80
|
-
});
|
|
81
|
-
},
|
|
82
|
-
refreshAccessToken: options.refreshAccessToken
|
|
83
|
-
? options.refreshAccessToken
|
|
84
|
-
: async (refreshToken) => {
|
|
85
|
-
return refreshAccessToken({
|
|
86
|
-
refreshToken,
|
|
87
|
-
options: {
|
|
88
|
-
clientId: options.clientId,
|
|
89
|
-
clientKey: options.clientKey,
|
|
90
|
-
clientSecret: options.clientSecret,
|
|
91
|
-
},
|
|
92
|
-
tokenEndpoint,
|
|
93
|
-
});
|
|
94
|
-
},
|
|
95
|
-
async getUserInfo(token) {
|
|
96
|
-
if (options.getUserInfo) {
|
|
97
|
-
return options.getUserInfo(token);
|
|
98
|
-
}
|
|
99
|
-
if (!token.idToken) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
const user = decodeJwt(token.idToken) as PaybinProfile;
|
|
103
|
-
const userMap = await options.mapProfileToUser?.(user);
|
|
104
|
-
return {
|
|
105
|
-
user: {
|
|
106
|
-
id: user.sub,
|
|
107
|
-
name:
|
|
108
|
-
user.name ||
|
|
109
|
-
user.preferred_username ||
|
|
110
|
-
(user.email ? user.email.split("@")[0] : "User") ||
|
|
111
|
-
"User",
|
|
112
|
-
email: user.email,
|
|
113
|
-
image: user.picture,
|
|
114
|
-
emailVerified: user.email_verified || false,
|
|
115
|
-
...userMap,
|
|
116
|
-
},
|
|
117
|
-
data: user,
|
|
118
|
-
};
|
|
119
|
-
},
|
|
120
|
-
options,
|
|
121
|
-
} satisfies OAuthProvider<PaybinProfile>;
|
|
122
|
-
};
|
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
import { base64 } from "@gatwech/utils/base64";
|
|
2
|
-
import { betterFetch } from "@better-fetch/fetch";
|
|
3
|
-
import { decodeJwt } from "jose";
|
|
4
|
-
import { logger } from "../env";
|
|
5
|
-
import { PayvoAuthError } from "../error";
|
|
6
|
-
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
7
|
-
import { createAuthorizationURL } from "../oauth2";
|
|
8
|
-
|
|
9
|
-
export interface PayPalProfile {
|
|
10
|
-
user_id: string;
|
|
11
|
-
name: string;
|
|
12
|
-
given_name: string;
|
|
13
|
-
family_name: string;
|
|
14
|
-
middle_name?: string | undefined;
|
|
15
|
-
picture?: string | undefined;
|
|
16
|
-
email: string;
|
|
17
|
-
email_verified: boolean;
|
|
18
|
-
gender?: string | undefined;
|
|
19
|
-
birthdate?: string | undefined;
|
|
20
|
-
zoneinfo?: string | undefined;
|
|
21
|
-
locale?: string | undefined;
|
|
22
|
-
phone_number?: string | undefined;
|
|
23
|
-
address?:
|
|
24
|
-
| {
|
|
25
|
-
street_address?: string;
|
|
26
|
-
locality?: string;
|
|
27
|
-
region?: string;
|
|
28
|
-
postal_code?: string;
|
|
29
|
-
country?: string;
|
|
30
|
-
}
|
|
31
|
-
| undefined;
|
|
32
|
-
verified_account?: boolean | undefined;
|
|
33
|
-
account_type?: string | undefined;
|
|
34
|
-
age_range?: string | undefined;
|
|
35
|
-
payer_id?: string | undefined;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface PayPalTokenResponse {
|
|
39
|
-
scope?: string | undefined;
|
|
40
|
-
access_token: string;
|
|
41
|
-
refresh_token?: string | undefined;
|
|
42
|
-
token_type: "Bearer";
|
|
43
|
-
id_token?: string | undefined;
|
|
44
|
-
expires_in: number;
|
|
45
|
-
nonce?: string | undefined;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export interface PayPalOptions extends ProviderOptions<PayPalProfile> {
|
|
49
|
-
clientId: string;
|
|
50
|
-
/**
|
|
51
|
-
* PayPal environment - 'sandbox' for testing, 'live' for production
|
|
52
|
-
* @default 'sandbox'
|
|
53
|
-
*/
|
|
54
|
-
environment?: ("sandbox" | "live") | undefined;
|
|
55
|
-
/**
|
|
56
|
-
* Whether to request shipping address information
|
|
57
|
-
* @default false
|
|
58
|
-
*/
|
|
59
|
-
requestShippingAddress?: boolean | undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export const paypal = (options: PayPalOptions) => {
|
|
63
|
-
const environment = options.environment || "sandbox";
|
|
64
|
-
const isSandbox = environment === "sandbox";
|
|
65
|
-
|
|
66
|
-
const authorizationEndpoint = isSandbox
|
|
67
|
-
? "https://www.sandbox.paypal.com/signin/authorize"
|
|
68
|
-
: "https://www.paypal.com/signin/authorize";
|
|
69
|
-
|
|
70
|
-
const tokenEndpoint = isSandbox
|
|
71
|
-
? "https://api-m.sandbox.paypal.com/v1/oauth2/token"
|
|
72
|
-
: "https://api-m.paypal.com/v1/oauth2/token";
|
|
73
|
-
|
|
74
|
-
const userInfoEndpoint = isSandbox
|
|
75
|
-
? "https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo"
|
|
76
|
-
: "https://api-m.paypal.com/v1/identity/oauth2/userinfo";
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
id: "paypal",
|
|
80
|
-
name: "PayPal",
|
|
81
|
-
async createAuthorizationURL({ state, codeVerifier, redirectURI }) {
|
|
82
|
-
if (!options.clientId || !options.clientSecret) {
|
|
83
|
-
logger.error(
|
|
84
|
-
"Client Id and Client Secret is required for PayPal. Make sure to provide them in the options."
|
|
85
|
-
);
|
|
86
|
-
throw new PayvoAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Log in with PayPal doesn't use traditional OAuth2 scopes
|
|
91
|
-
* Instead, permissions are configured in the PayPal Developer Dashboard
|
|
92
|
-
* We don't pass any scopes to avoid "invalid scope" errors
|
|
93
|
-
**/
|
|
94
|
-
|
|
95
|
-
const _scopes: string[] = [];
|
|
96
|
-
|
|
97
|
-
const url = await createAuthorizationURL({
|
|
98
|
-
id: "paypal",
|
|
99
|
-
options,
|
|
100
|
-
authorizationEndpoint,
|
|
101
|
-
scopes: _scopes,
|
|
102
|
-
state,
|
|
103
|
-
codeVerifier,
|
|
104
|
-
redirectURI,
|
|
105
|
-
prompt: options.prompt,
|
|
106
|
-
});
|
|
107
|
-
return url;
|
|
108
|
-
},
|
|
109
|
-
|
|
110
|
-
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
111
|
-
/**
|
|
112
|
-
* PayPal requires Basic Auth for token exchange
|
|
113
|
-
**/
|
|
114
|
-
|
|
115
|
-
const credentials = base64.encode(
|
|
116
|
-
`${options.clientId}:${options.clientSecret}`
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
const response = await betterFetch(tokenEndpoint, {
|
|
121
|
-
method: "POST",
|
|
122
|
-
headers: {
|
|
123
|
-
Authorization: `Basic ${credentials}`,
|
|
124
|
-
Accept: "application/json",
|
|
125
|
-
"Accept-Language": "en_US",
|
|
126
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
127
|
-
},
|
|
128
|
-
body: new URLSearchParams({
|
|
129
|
-
grant_type: "authorization_code",
|
|
130
|
-
code: code,
|
|
131
|
-
redirect_uri: redirectURI,
|
|
132
|
-
}).toString(),
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
if (!response.data) {
|
|
136
|
-
throw new PayvoAuthError("FAILED_TO_GET_ACCESS_TOKEN");
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const data = response.data as PayPalTokenResponse;
|
|
140
|
-
|
|
141
|
-
const result = {
|
|
142
|
-
accessToken: data.access_token,
|
|
143
|
-
refreshToken: data.refresh_token,
|
|
144
|
-
accessTokenExpiresAt: data.expires_in
|
|
145
|
-
? new Date(Date.now() + data.expires_in * 1000)
|
|
146
|
-
: undefined,
|
|
147
|
-
idToken: data.id_token,
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
return result;
|
|
151
|
-
} catch (error) {
|
|
152
|
-
logger.error("PayPal token exchange failed:", error);
|
|
153
|
-
throw new PayvoAuthError("FAILED_TO_GET_ACCESS_TOKEN");
|
|
154
|
-
}
|
|
155
|
-
},
|
|
156
|
-
|
|
157
|
-
refreshAccessToken: options.refreshAccessToken
|
|
158
|
-
? options.refreshAccessToken
|
|
159
|
-
: async (refreshToken) => {
|
|
160
|
-
const credentials = base64.encode(
|
|
161
|
-
`${options.clientId}:${options.clientSecret}`
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
try {
|
|
165
|
-
const response = await betterFetch(tokenEndpoint, {
|
|
166
|
-
method: "POST",
|
|
167
|
-
headers: {
|
|
168
|
-
Authorization: `Basic ${credentials}`,
|
|
169
|
-
Accept: "application/json",
|
|
170
|
-
"Accept-Language": "en_US",
|
|
171
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
172
|
-
},
|
|
173
|
-
body: new URLSearchParams({
|
|
174
|
-
grant_type: "refresh_token",
|
|
175
|
-
refresh_token: refreshToken,
|
|
176
|
-
}).toString(),
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
if (!response.data) {
|
|
180
|
-
throw new PayvoAuthError("FAILED_TO_REFRESH_ACCESS_TOKEN");
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
const data = response.data as any;
|
|
184
|
-
return {
|
|
185
|
-
accessToken: data.access_token,
|
|
186
|
-
refreshToken: data.refresh_token,
|
|
187
|
-
accessTokenExpiresAt: data.expires_in
|
|
188
|
-
? new Date(Date.now() + data.expires_in * 1000)
|
|
189
|
-
: undefined,
|
|
190
|
-
};
|
|
191
|
-
} catch (error) {
|
|
192
|
-
logger.error("PayPal token refresh failed:", error);
|
|
193
|
-
throw new PayvoAuthError("FAILED_TO_REFRESH_ACCESS_TOKEN");
|
|
194
|
-
}
|
|
195
|
-
},
|
|
196
|
-
|
|
197
|
-
async verifyIdToken(token, nonce) {
|
|
198
|
-
if (options.disableIdTokenSignIn) {
|
|
199
|
-
return false;
|
|
200
|
-
}
|
|
201
|
-
if (options.verifyIdToken) {
|
|
202
|
-
return options.verifyIdToken(token, nonce);
|
|
203
|
-
}
|
|
204
|
-
try {
|
|
205
|
-
const payload = decodeJwt(token);
|
|
206
|
-
return !!payload.sub;
|
|
207
|
-
} catch (error) {
|
|
208
|
-
logger.error("Failed to verify PayPal ID token:", error);
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
|
-
},
|
|
212
|
-
|
|
213
|
-
async getUserInfo(token) {
|
|
214
|
-
if (options.getUserInfo) {
|
|
215
|
-
return options.getUserInfo(token);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (!token.accessToken) {
|
|
219
|
-
logger.error("Access token is required to fetch PayPal user info");
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
try {
|
|
224
|
-
const response = await betterFetch<PayPalProfile>(
|
|
225
|
-
`${userInfoEndpoint}?schema=paypalv1.1`,
|
|
226
|
-
{
|
|
227
|
-
headers: {
|
|
228
|
-
Authorization: `Bearer ${token.accessToken}`,
|
|
229
|
-
Accept: "application/json",
|
|
230
|
-
},
|
|
231
|
-
}
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
if (!response.data) {
|
|
235
|
-
logger.error("Failed to fetch user info from PayPal");
|
|
236
|
-
return null;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const userInfo = response.data;
|
|
240
|
-
const userMap = await options.mapProfileToUser?.(userInfo);
|
|
241
|
-
|
|
242
|
-
const result = {
|
|
243
|
-
user: {
|
|
244
|
-
id: userInfo.user_id,
|
|
245
|
-
name: userInfo.name,
|
|
246
|
-
email: userInfo.email,
|
|
247
|
-
image: userInfo.picture,
|
|
248
|
-
emailVerified: userInfo.email_verified,
|
|
249
|
-
...userMap,
|
|
250
|
-
},
|
|
251
|
-
data: userInfo,
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
return result;
|
|
255
|
-
} catch (error) {
|
|
256
|
-
logger.error("Failed to fetch user info from PayPal:", error);
|
|
257
|
-
return null;
|
|
258
|
-
}
|
|
259
|
-
},
|
|
260
|
-
|
|
261
|
-
options,
|
|
262
|
-
} satisfies OAuthProvider<PayPalProfile>;
|
|
263
|
-
};
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { betterFetch } from "@better-fetch/fetch";
|
|
2
|
-
import type { OAuthProvider, ProviderOptions } from "../oauth2";
|
|
3
|
-
import {
|
|
4
|
-
createAuthorizationURL,
|
|
5
|
-
refreshAccessToken,
|
|
6
|
-
validateAuthorizationCode,
|
|
7
|
-
} from "../oauth2";
|
|
8
|
-
|
|
9
|
-
export interface PolarProfile {
|
|
10
|
-
id: string;
|
|
11
|
-
email: string;
|
|
12
|
-
username: string;
|
|
13
|
-
avatar_url: string;
|
|
14
|
-
github_username?: string | undefined;
|
|
15
|
-
account_id?: string | undefined;
|
|
16
|
-
public_name?: string | undefined;
|
|
17
|
-
profile_settings?:
|
|
18
|
-
| {
|
|
19
|
-
profile_settings_enabled?: boolean;
|
|
20
|
-
profile_settings_public_name?: string;
|
|
21
|
-
profile_settings_public_avatar?: string;
|
|
22
|
-
profile_settings_public_bio?: string;
|
|
23
|
-
profile_settings_public_location?: string;
|
|
24
|
-
profile_settings_public_website?: string;
|
|
25
|
-
profile_settings_public_twitter?: string;
|
|
26
|
-
profile_settings_public_github?: string;
|
|
27
|
-
profile_settings_public_email?: string;
|
|
28
|
-
}
|
|
29
|
-
| undefined;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export interface PolarOptions extends ProviderOptions<PolarProfile> {}
|
|
33
|
-
|
|
34
|
-
export const polar = (options: PolarOptions) => {
|
|
35
|
-
return {
|
|
36
|
-
id: "polar",
|
|
37
|
-
name: "Polar",
|
|
38
|
-
createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
39
|
-
const _scopes = options.disableDefaultScope
|
|
40
|
-
? []
|
|
41
|
-
: ["openid", "profile", "email"];
|
|
42
|
-
if (options.scope) _scopes.push(...options.scope);
|
|
43
|
-
if (scopes) _scopes.push(...scopes);
|
|
44
|
-
return createAuthorizationURL({
|
|
45
|
-
id: "polar",
|
|
46
|
-
options,
|
|
47
|
-
authorizationEndpoint: "https://polar.sh/oauth2/authorize",
|
|
48
|
-
scopes: _scopes,
|
|
49
|
-
state,
|
|
50
|
-
codeVerifier,
|
|
51
|
-
redirectURI,
|
|
52
|
-
prompt: options.prompt,
|
|
53
|
-
});
|
|
54
|
-
},
|
|
55
|
-
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
56
|
-
return validateAuthorizationCode({
|
|
57
|
-
code,
|
|
58
|
-
codeVerifier,
|
|
59
|
-
redirectURI,
|
|
60
|
-
options,
|
|
61
|
-
tokenEndpoint: "https://api.polar.sh/v1/oauth2/token",
|
|
62
|
-
});
|
|
63
|
-
},
|
|
64
|
-
refreshAccessToken: options.refreshAccessToken
|
|
65
|
-
? options.refreshAccessToken
|
|
66
|
-
: async (refreshToken) => {
|
|
67
|
-
return refreshAccessToken({
|
|
68
|
-
refreshToken,
|
|
69
|
-
options: {
|
|
70
|
-
clientId: options.clientId,
|
|
71
|
-
clientKey: options.clientKey,
|
|
72
|
-
clientSecret: options.clientSecret,
|
|
73
|
-
},
|
|
74
|
-
tokenEndpoint: "https://api.polar.sh/v1/oauth2/token",
|
|
75
|
-
});
|
|
76
|
-
},
|
|
77
|
-
async getUserInfo(token) {
|
|
78
|
-
if (options.getUserInfo) {
|
|
79
|
-
return options.getUserInfo(token);
|
|
80
|
-
}
|
|
81
|
-
const { data: profile, error } = await betterFetch<PolarProfile>(
|
|
82
|
-
"https://api.polar.sh/v1/oauth2/userinfo",
|
|
83
|
-
{
|
|
84
|
-
headers: {
|
|
85
|
-
Authorization: `Bearer ${token.accessToken}`,
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
);
|
|
89
|
-
if (error) {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
const userMap = await options.mapProfileToUser?.(profile);
|
|
93
|
-
return {
|
|
94
|
-
user: {
|
|
95
|
-
id: profile.id,
|
|
96
|
-
name: profile.public_name || profile.username,
|
|
97
|
-
email: profile.email,
|
|
98
|
-
image: profile.avatar_url,
|
|
99
|
-
emailVerified: true,
|
|
100
|
-
...userMap,
|
|
101
|
-
},
|
|
102
|
-
data: profile,
|
|
103
|
-
};
|
|
104
|
-
},
|
|
105
|
-
options,
|
|
106
|
-
} satisfies OAuthProvider<PolarProfile>;
|
|
107
|
-
};
|