@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.
Files changed (130) hide show
  1. package/dist/api/index.d.mts +2 -2
  2. package/dist/context/index.d.mts +2 -2
  3. package/dist/db/adapter/index.d.mts +2 -2
  4. package/dist/db/index.d.mts +2 -2
  5. package/dist/env/index.d.mts +1 -1
  6. package/dist/env/index.mjs +1 -1
  7. package/dist/{env-JMSMESs1.mjs → env-4_Lym7sj.mjs} +7 -7
  8. package/dist/index-65G5U5DB.d.mts +3002 -0
  9. package/dist/{index-DLP-K0uY.d.mts → index-CmdhhvA2.d.mts} +3 -3
  10. package/dist/index.d.mts +3 -3
  11. package/dist/oauth2/index.d.mts +2 -2
  12. package/dist/social-providers/index.d.mts +3 -3
  13. package/dist/social-providers/index.mjs +71 -2412
  14. package/dist/src/api/index.d.ts +119 -0
  15. package/dist/src/async_hooks/index.d.ts +6 -0
  16. package/dist/src/context/endpoint-context.d.ts +14 -0
  17. package/dist/src/context/index.d.ts +3 -0
  18. package/dist/src/context/request-state.d.ts +13 -0
  19. package/dist/src/context/transaction.d.ts +11 -0
  20. package/dist/src/db/adapter/index.d.ts +401 -0
  21. package/{src/db/index.ts → dist/src/db/index.d.ts} +2 -18
  22. package/dist/src/db/plugin.d.ts +10 -0
  23. package/dist/src/db/schema/account.d.ts +22 -0
  24. package/dist/src/db/schema/rate-limit.d.ts +10 -0
  25. package/dist/src/db/schema/session.d.ts +17 -0
  26. package/dist/src/db/schema/shared.d.ts +6 -0
  27. package/dist/src/db/schema/user.d.ts +16 -0
  28. package/{src/db/schema/verification.ts → dist/src/db/schema/verification.d.ts} +8 -8
  29. package/dist/src/db/type.d.ts +159 -0
  30. package/dist/src/env/color-depth.d.ts +1 -0
  31. package/dist/src/env/env-impl.d.ts +29 -0
  32. package/dist/src/env/index.d.ts +3 -0
  33. package/dist/src/env/logger.d.ts +50 -0
  34. package/dist/src/error/codes.d.ts +27 -0
  35. package/dist/src/error/index.d.ts +4 -0
  36. package/dist/src/oauth2/client-credentials-token.d.ts +21 -0
  37. package/dist/src/oauth2/create-authorization-url.d.ts +21 -0
  38. package/dist/src/oauth2/index.d.ts +6 -0
  39. package/dist/src/oauth2/oauth-provider.d.ts +178 -0
  40. package/dist/src/oauth2/refresh-access-token.d.ts +20 -0
  41. package/dist/src/oauth2/utils.d.ts +3 -0
  42. package/dist/src/oauth2/validate-authorization-code.d.ts +28 -0
  43. package/dist/src/social-providers/github.d.ts +89 -0
  44. package/dist/src/social-providers/google.d.ts +82 -0
  45. package/dist/src/social-providers/index.d.ts +93 -0
  46. package/dist/src/types/context.d.ts +177 -0
  47. package/dist/src/types/cookie.d.ts +15 -0
  48. package/dist/src/types/helper.d.ts +9 -0
  49. package/dist/src/types/index.d.ts +7 -0
  50. package/dist/src/types/init-options.d.ts +1140 -0
  51. package/dist/src/types/plugin-client.d.ts +88 -0
  52. package/dist/src/types/plugin.d.ts +120 -0
  53. package/dist/src/utils/error-codes.d.ts +9 -0
  54. package/package.json +11 -5
  55. package/.turbo/turbo-build.log +0 -42
  56. package/dist/index-DjrJweYn.d.mts +0 -7312
  57. package/src/api/index.ts +0 -57
  58. package/src/async_hooks/index.ts +0 -35
  59. package/src/context/endpoint-context.ts +0 -48
  60. package/src/context/index.ts +0 -21
  61. package/src/context/request-state.test.ts +0 -346
  62. package/src/context/request-state.ts +0 -75
  63. package/src/context/transaction.ts +0 -72
  64. package/src/db/adapter/index.ts +0 -466
  65. package/src/db/plugin.ts +0 -11
  66. package/src/db/schema/account.ts +0 -34
  67. package/src/db/schema/rate-limit.ts +0 -21
  68. package/src/db/schema/session.ts +0 -17
  69. package/src/db/schema/shared.ts +0 -7
  70. package/src/db/schema/user.ts +0 -16
  71. package/src/db/type.ts +0 -180
  72. package/src/env/color-depth.ts +0 -172
  73. package/src/env/env-impl.ts +0 -124
  74. package/src/env/index.ts +0 -23
  75. package/src/env/logger.test.ts +0 -33
  76. package/src/env/logger.ts +0 -145
  77. package/src/error/codes.ts +0 -31
  78. package/src/error/index.ts +0 -11
  79. package/src/oauth2/client-credentials-token.ts +0 -102
  80. package/src/oauth2/create-authorization-url.ts +0 -85
  81. package/src/oauth2/index.ts +0 -21
  82. package/src/oauth2/oauth-provider.ts +0 -211
  83. package/src/oauth2/refresh-access-token.ts +0 -124
  84. package/src/oauth2/utils.ts +0 -36
  85. package/src/oauth2/validate-authorization-code.ts +0 -154
  86. package/src/social-providers/apple.ts +0 -213
  87. package/src/social-providers/atlassian.ts +0 -132
  88. package/src/social-providers/cognito.ts +0 -269
  89. package/src/social-providers/discord.ts +0 -169
  90. package/src/social-providers/dropbox.ts +0 -112
  91. package/src/social-providers/facebook.ts +0 -204
  92. package/src/social-providers/figma.ts +0 -115
  93. package/src/social-providers/github.ts +0 -154
  94. package/src/social-providers/gitlab.ts +0 -152
  95. package/src/social-providers/google.ts +0 -171
  96. package/src/social-providers/huggingface.ts +0 -118
  97. package/src/social-providers/index.ts +0 -124
  98. package/src/social-providers/kakao.ts +0 -178
  99. package/src/social-providers/kick.ts +0 -92
  100. package/src/social-providers/line.ts +0 -169
  101. package/src/social-providers/linear.ts +0 -120
  102. package/src/social-providers/linkedin.ts +0 -110
  103. package/src/social-providers/microsoft-entra-id.ts +0 -245
  104. package/src/social-providers/naver.ts +0 -112
  105. package/src/social-providers/notion.ts +0 -108
  106. package/src/social-providers/paybin.ts +0 -122
  107. package/src/social-providers/paypal.ts +0 -263
  108. package/src/social-providers/polar.ts +0 -107
  109. package/src/social-providers/reddit.ts +0 -122
  110. package/src/social-providers/roblox.ts +0 -110
  111. package/src/social-providers/salesforce.ts +0 -159
  112. package/src/social-providers/slack.ts +0 -111
  113. package/src/social-providers/spotify.ts +0 -93
  114. package/src/social-providers/tiktok.ts +0 -210
  115. package/src/social-providers/twitch.ts +0 -111
  116. package/src/social-providers/twitter.ts +0 -198
  117. package/src/social-providers/vk.ts +0 -126
  118. package/src/social-providers/zoom.ts +0 -217
  119. package/src/types/context.ts +0 -269
  120. package/src/types/cookie.ts +0 -7
  121. package/src/types/helper.ts +0 -6
  122. package/src/types/index.ts +0 -21
  123. package/src/types/init-options.ts +0 -1346
  124. package/src/types/plugin-client.ts +0 -100
  125. package/src/types/plugin.ts +0 -158
  126. package/src/utils/error-codes.ts +0 -51
  127. package/tsconfig.json +0 -7
  128. package/tsdown.config.ts +0 -20
  129. /package/{src/index.ts → dist/src/index.d.ts} +0 -0
  130. /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
- };