@better-auth/core 1.4.12-beta.2 → 1.4.13
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/.turbo/turbo-build.log +172 -35
- package/dist/api/index.d.mts +178 -1
- package/dist/api/index.mjs +2 -1
- package/dist/context/endpoint-context.d.mts +19 -0
- package/dist/context/endpoint-context.mjs +31 -0
- package/dist/context/global.d.mts +7 -0
- package/dist/context/global.mjs +37 -0
- package/dist/context/index.d.mts +5 -53
- package/dist/context/index.mjs +5 -2
- package/dist/context/request-state.d.mts +27 -0
- package/dist/context/request-state.mjs +49 -0
- package/dist/context/transaction.d.mts +16 -0
- package/dist/context/transaction.mjs +52 -0
- package/dist/db/adapter/factory.d.mts +27 -0
- package/dist/db/adapter/factory.mjs +738 -0
- package/dist/db/adapter/get-default-field-name.d.mts +18 -0
- package/dist/db/adapter/get-default-field-name.mjs +38 -0
- package/dist/db/adapter/get-default-model-name.d.mts +12 -0
- package/dist/db/adapter/get-default-model-name.mjs +32 -0
- package/dist/db/adapter/get-field-attributes.d.mts +29 -0
- package/dist/db/adapter/get-field-attributes.mjs +39 -0
- package/dist/db/adapter/get-field-name.d.mts +18 -0
- package/dist/db/adapter/get-field-name.mjs +33 -0
- package/dist/db/adapter/get-id-field.d.mts +39 -0
- package/dist/db/adapter/get-id-field.mjs +68 -0
- package/dist/db/adapter/get-model-name.d.mts +12 -0
- package/dist/db/adapter/get-model-name.mjs +23 -0
- package/dist/db/adapter/index.d.mts +513 -1
- package/dist/db/adapter/index.mjs +8 -970
- package/dist/db/adapter/types.d.mts +139 -0
- package/dist/db/adapter/utils.d.mts +7 -0
- package/dist/db/adapter/utils.mjs +38 -0
- package/dist/db/get-tables.d.mts +8 -0
- package/dist/{get-tables-CMc_Emww.mjs → db/get-tables.mjs} +1 -1
- package/dist/db/index.d.mts +10 -2
- package/dist/db/index.mjs +7 -60
- package/dist/db/plugin.d.mts +12 -0
- package/dist/db/schema/account.d.mts +26 -0
- package/dist/db/schema/account.mjs +19 -0
- package/dist/db/schema/rate-limit.d.mts +14 -0
- package/dist/db/schema/rate-limit.mjs +11 -0
- package/dist/db/schema/session.d.mts +21 -0
- package/dist/db/schema/session.mjs +14 -0
- package/dist/db/schema/shared.d.mts +10 -0
- package/dist/db/schema/shared.mjs +11 -0
- package/dist/db/schema/user.d.mts +20 -0
- package/dist/db/schema/user.mjs +13 -0
- package/dist/db/schema/verification.d.mts +19 -0
- package/dist/db/schema/verification.mjs +12 -0
- package/dist/db/type.d.mts +143 -0
- package/dist/env/color-depth.d.mts +4 -0
- package/dist/env/color-depth.mjs +88 -0
- package/dist/env/env-impl.d.mts +32 -0
- package/dist/env/env-impl.mjs +82 -0
- package/dist/env/index.d.mts +4 -2
- package/dist/env/index.mjs +3 -1
- package/dist/{index-BRBu0-5h.d.mts → env/logger.d.mts} +1 -35
- package/dist/env/logger.mjs +81 -0
- package/dist/error/codes.d.mts +48 -0
- package/dist/{error-DP1xOn7P.mjs → error/codes.mjs} +3 -14
- package/dist/error/index.d.mts +5 -48
- package/dist/error/index.mjs +12 -3
- package/dist/index.d.mts +8 -2
- package/dist/oauth2/client-credentials-token.d.mts +36 -0
- package/dist/oauth2/client-credentials-token.mjs +54 -0
- package/dist/oauth2/create-authorization-url.d.mts +45 -0
- package/dist/oauth2/create-authorization-url.mjs +42 -0
- package/dist/oauth2/index.d.mts +8 -2
- package/dist/oauth2/index.mjs +6 -2
- package/dist/oauth2/oauth-provider.d.mts +194 -0
- package/dist/oauth2/refresh-access-token.d.mts +36 -0
- package/dist/oauth2/refresh-access-token.mjs +58 -0
- package/dist/oauth2/utils.d.mts +7 -0
- package/dist/oauth2/utils.mjs +27 -0
- package/dist/oauth2/validate-authorization-code.d.mts +55 -0
- package/dist/oauth2/validate-authorization-code.mjs +71 -0
- package/dist/oauth2/verify.d.mts +49 -0
- package/dist/oauth2/verify.mjs +95 -0
- package/dist/social-providers/apple.d.mts +119 -0
- package/dist/social-providers/apple.mjs +102 -0
- package/dist/social-providers/atlassian.d.mts +72 -0
- package/dist/social-providers/atlassian.mjs +83 -0
- package/dist/social-providers/cognito.d.mts +87 -0
- package/dist/social-providers/cognito.mjs +166 -0
- package/dist/social-providers/discord.d.mts +126 -0
- package/dist/social-providers/discord.mjs +64 -0
- package/dist/social-providers/dropbox.d.mts +71 -0
- package/dist/social-providers/dropbox.mjs +75 -0
- package/dist/social-providers/facebook.d.mts +81 -0
- package/dist/social-providers/facebook.mjs +120 -0
- package/dist/social-providers/figma.d.mts +63 -0
- package/dist/social-providers/figma.mjs +84 -0
- package/dist/social-providers/github.d.mts +104 -0
- package/dist/social-providers/github.mjs +80 -0
- package/dist/social-providers/gitlab.d.mts +125 -0
- package/dist/social-providers/gitlab.mjs +82 -0
- package/dist/social-providers/google.d.mts +99 -0
- package/dist/social-providers/google.mjs +109 -0
- package/dist/social-providers/huggingface.d.mts +85 -0
- package/dist/social-providers/huggingface.mjs +75 -0
- package/dist/social-providers/index.d.mts +1723 -1
- package/dist/social-providers/index.mjs +33 -2570
- package/dist/social-providers/kakao.d.mts +163 -0
- package/dist/social-providers/kakao.mjs +72 -0
- package/dist/social-providers/kick.d.mts +75 -0
- package/dist/social-providers/kick.mjs +71 -0
- package/dist/social-providers/line.d.mts +107 -0
- package/dist/social-providers/line.mjs +113 -0
- package/dist/social-providers/linear.d.mts +70 -0
- package/dist/social-providers/linear.mjs +88 -0
- package/dist/social-providers/linkedin.d.mts +69 -0
- package/dist/social-providers/linkedin.mjs +76 -0
- package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
- package/dist/social-providers/microsoft-entra-id.mjs +106 -0
- package/dist/social-providers/naver.d.mts +104 -0
- package/dist/social-providers/naver.mjs +67 -0
- package/dist/social-providers/notion.d.mts +66 -0
- package/dist/social-providers/notion.mjs +75 -0
- package/dist/social-providers/paybin.d.mts +73 -0
- package/dist/social-providers/paybin.mjs +85 -0
- package/dist/social-providers/paypal.d.mts +131 -0
- package/dist/social-providers/paypal.mjs +144 -0
- package/dist/social-providers/polar.d.mts +76 -0
- package/dist/social-providers/polar.mjs +73 -0
- package/dist/social-providers/reddit.d.mts +64 -0
- package/dist/social-providers/reddit.mjs +83 -0
- package/dist/social-providers/roblox.d.mts +72 -0
- package/dist/social-providers/roblox.mjs +59 -0
- package/dist/social-providers/salesforce.d.mts +81 -0
- package/dist/social-providers/salesforce.mjs +91 -0
- package/dist/social-providers/slack.d.mts +85 -0
- package/dist/social-providers/slack.mjs +68 -0
- package/dist/social-providers/spotify.d.mts +65 -0
- package/dist/social-providers/spotify.mjs +71 -0
- package/dist/social-providers/tiktok.d.mts +171 -0
- package/dist/social-providers/tiktok.mjs +62 -0
- package/dist/social-providers/twitch.d.mts +81 -0
- package/dist/social-providers/twitch.mjs +78 -0
- package/dist/social-providers/twitter.d.mts +140 -0
- package/dist/social-providers/twitter.mjs +87 -0
- package/dist/social-providers/vercel.d.mts +64 -0
- package/dist/social-providers/vercel.mjs +61 -0
- package/dist/social-providers/vk.d.mts +72 -0
- package/dist/social-providers/vk.mjs +83 -0
- package/dist/social-providers/zoom.d.mts +173 -0
- package/dist/social-providers/zoom.mjs +72 -0
- package/dist/types/context.d.mts +215 -0
- package/dist/types/cookie.d.mts +15 -0
- package/dist/types/helper.d.mts +8 -0
- package/dist/types/index.d.mts +8 -0
- package/dist/types/init-options.d.mts +1266 -0
- package/dist/types/plugin-client.d.mts +103 -0
- package/dist/types/plugin.d.mts +121 -0
- package/dist/utils/deprecate.d.mts +10 -0
- package/dist/utils/deprecate.mjs +17 -0
- package/dist/utils/error-codes.d.mts +9 -0
- package/dist/utils/error-codes.mjs +7 -0
- package/dist/utils/id.d.mts +4 -0
- package/dist/utils/id.mjs +9 -0
- package/dist/utils/index.d.mts +5 -26
- package/dist/utils/index.mjs +5 -2
- package/dist/utils/json.d.mts +4 -0
- package/dist/utils/json.mjs +25 -0
- package/dist/utils/string.d.mts +4 -0
- package/dist/utils/string.mjs +7 -0
- package/package.json +1 -1
- package/src/context/endpoint-context.ts +7 -15
- package/src/context/global.ts +57 -0
- package/src/context/index.ts +1 -0
- package/src/context/request-state.ts +7 -12
- package/src/context/transaction.ts +7 -16
- package/src/db/adapter/factory.ts +13 -13
- package/src/db/adapter/get-default-model-name.ts +1 -1
- package/src/db/adapter/get-id-field.ts +2 -2
- package/src/error/index.ts +2 -3
- package/src/social-providers/gitlab.ts +1 -1
- package/src/types/context.ts +137 -131
- package/src/types/cookie.ts +6 -4
- package/src/types/index.ts +2 -1
- package/tsdown.config.ts +9 -0
- package/dist/context-BGZ8V6DD.mjs +0 -126
- package/dist/env-DbssmzoK.mjs +0 -245
- package/dist/index-zgYuzZ7O.d.mts +0 -8020
- package/dist/oauth2-COJkghlT.mjs +0 -326
- package/dist/utils-U2L7n92V.mjs +0 -59
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
|
|
2
|
+
import "../oauth2/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/social-providers/spotify.d.ts
|
|
5
|
+
interface SpotifyProfile {
|
|
6
|
+
id: string;
|
|
7
|
+
display_name: string;
|
|
8
|
+
email: string;
|
|
9
|
+
images: {
|
|
10
|
+
url: string;
|
|
11
|
+
}[];
|
|
12
|
+
}
|
|
13
|
+
interface SpotifyOptions extends ProviderOptions<SpotifyProfile> {
|
|
14
|
+
clientId: string;
|
|
15
|
+
}
|
|
16
|
+
declare const spotify: (options: SpotifyOptions) => {
|
|
17
|
+
id: "spotify";
|
|
18
|
+
name: string;
|
|
19
|
+
createAuthorizationURL({
|
|
20
|
+
state,
|
|
21
|
+
scopes,
|
|
22
|
+
codeVerifier,
|
|
23
|
+
redirectURI
|
|
24
|
+
}: {
|
|
25
|
+
state: string;
|
|
26
|
+
codeVerifier: string;
|
|
27
|
+
scopes?: string[] | undefined;
|
|
28
|
+
redirectURI: string;
|
|
29
|
+
display?: string | undefined;
|
|
30
|
+
loginHint?: string | undefined;
|
|
31
|
+
}): Promise<URL>;
|
|
32
|
+
validateAuthorizationCode: ({
|
|
33
|
+
code,
|
|
34
|
+
codeVerifier,
|
|
35
|
+
redirectURI
|
|
36
|
+
}: {
|
|
37
|
+
code: string;
|
|
38
|
+
redirectURI: string;
|
|
39
|
+
codeVerifier?: string | undefined;
|
|
40
|
+
deviceId?: string | undefined;
|
|
41
|
+
}) => Promise<OAuth2Tokens>;
|
|
42
|
+
refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
|
|
43
|
+
getUserInfo(token: OAuth2Tokens & {
|
|
44
|
+
user?: {
|
|
45
|
+
name?: {
|
|
46
|
+
firstName?: string;
|
|
47
|
+
lastName?: string;
|
|
48
|
+
};
|
|
49
|
+
email?: string;
|
|
50
|
+
} | undefined;
|
|
51
|
+
}): Promise<{
|
|
52
|
+
user: {
|
|
53
|
+
id: string;
|
|
54
|
+
name?: string;
|
|
55
|
+
email?: string | null;
|
|
56
|
+
image?: string;
|
|
57
|
+
emailVerified: boolean;
|
|
58
|
+
[key: string]: any;
|
|
59
|
+
};
|
|
60
|
+
data: any;
|
|
61
|
+
} | null>;
|
|
62
|
+
options: SpotifyOptions;
|
|
63
|
+
};
|
|
64
|
+
//#endregion
|
|
65
|
+
export { SpotifyOptions, SpotifyProfile, spotify };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
|
|
2
|
+
import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
3
|
+
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
4
|
+
import "../oauth2/index.mjs";
|
|
5
|
+
import { betterFetch } from "@better-fetch/fetch";
|
|
6
|
+
|
|
7
|
+
//#region src/social-providers/spotify.ts
|
|
8
|
+
const spotify = (options) => {
|
|
9
|
+
return {
|
|
10
|
+
id: "spotify",
|
|
11
|
+
name: "Spotify",
|
|
12
|
+
createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
13
|
+
const _scopes = options.disableDefaultScope ? [] : ["user-read-email"];
|
|
14
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
15
|
+
if (scopes) _scopes.push(...scopes);
|
|
16
|
+
return createAuthorizationURL({
|
|
17
|
+
id: "spotify",
|
|
18
|
+
options,
|
|
19
|
+
authorizationEndpoint: "https://accounts.spotify.com/authorize",
|
|
20
|
+
scopes: _scopes,
|
|
21
|
+
state,
|
|
22
|
+
codeVerifier,
|
|
23
|
+
redirectURI
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
|
|
27
|
+
return validateAuthorizationCode({
|
|
28
|
+
code,
|
|
29
|
+
codeVerifier,
|
|
30
|
+
redirectURI,
|
|
31
|
+
options,
|
|
32
|
+
tokenEndpoint: "https://accounts.spotify.com/api/token"
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
36
|
+
return refreshAccessToken({
|
|
37
|
+
refreshToken,
|
|
38
|
+
options: {
|
|
39
|
+
clientId: options.clientId,
|
|
40
|
+
clientKey: options.clientKey,
|
|
41
|
+
clientSecret: options.clientSecret
|
|
42
|
+
},
|
|
43
|
+
tokenEndpoint: "https://accounts.spotify.com/api/token"
|
|
44
|
+
});
|
|
45
|
+
},
|
|
46
|
+
async getUserInfo(token) {
|
|
47
|
+
if (options.getUserInfo) return options.getUserInfo(token);
|
|
48
|
+
const { data: profile, error } = await betterFetch("https://api.spotify.com/v1/me", {
|
|
49
|
+
method: "GET",
|
|
50
|
+
headers: { Authorization: `Bearer ${token.accessToken}` }
|
|
51
|
+
});
|
|
52
|
+
if (error) return null;
|
|
53
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
54
|
+
return {
|
|
55
|
+
user: {
|
|
56
|
+
id: profile.id,
|
|
57
|
+
name: profile.display_name,
|
|
58
|
+
email: profile.email,
|
|
59
|
+
image: profile.images[0]?.url,
|
|
60
|
+
emailVerified: false,
|
|
61
|
+
...userMap
|
|
62
|
+
},
|
|
63
|
+
data: profile
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
options
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
//#endregion
|
|
71
|
+
export { spotify };
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
|
|
2
|
+
import "../oauth2/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/social-providers/tiktok.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* [More info](https://developers.tiktok.com/doc/tiktok-api-v2-get-user-info/)
|
|
7
|
+
*/
|
|
8
|
+
interface TiktokProfile extends Record<string, any> {
|
|
9
|
+
data: {
|
|
10
|
+
user: {
|
|
11
|
+
/**
|
|
12
|
+
* The unique identification of the user in the current application.Open id
|
|
13
|
+
* for the client.
|
|
14
|
+
*
|
|
15
|
+
* To return this field, add `fields=open_id` in the user profile request's query parameter.
|
|
16
|
+
*/
|
|
17
|
+
open_id: string;
|
|
18
|
+
/**
|
|
19
|
+
* The unique identification of the user across different apps for the same developer.
|
|
20
|
+
* For example, if a partner has X number of clients,
|
|
21
|
+
* it will get X number of open_id for the same TikTok user,
|
|
22
|
+
* but one persistent union_id for the particular user.
|
|
23
|
+
*
|
|
24
|
+
* To return this field, add `fields=union_id` in the user profile request's query parameter.
|
|
25
|
+
*/
|
|
26
|
+
union_id?: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* User's profile image.
|
|
29
|
+
*
|
|
30
|
+
* To return this field, add `fields=avatar_url` in the user profile request's query parameter.
|
|
31
|
+
*/
|
|
32
|
+
avatar_url?: string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* User`s profile image in 100x100 size.
|
|
35
|
+
*
|
|
36
|
+
* To return this field, add `fields=avatar_url_100` in the user profile request's query parameter.
|
|
37
|
+
*/
|
|
38
|
+
avatar_url_100?: string | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* User's profile image with higher resolution
|
|
41
|
+
*
|
|
42
|
+
* To return this field, add `fields=avatar_url_100` in the user profile request's query parameter.
|
|
43
|
+
*/
|
|
44
|
+
avatar_large_url: string;
|
|
45
|
+
/**
|
|
46
|
+
* User's profile name
|
|
47
|
+
*
|
|
48
|
+
* To return this field, add `fields=display_name` in the user profile request's query parameter.
|
|
49
|
+
*/
|
|
50
|
+
display_name: string;
|
|
51
|
+
/**
|
|
52
|
+
* User's username.
|
|
53
|
+
*
|
|
54
|
+
* To return this field, add `fields=username` in the user profile request's query parameter.
|
|
55
|
+
*/
|
|
56
|
+
username: string;
|
|
57
|
+
/** @note Email is currently unsupported by TikTok */
|
|
58
|
+
email?: string | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* User's bio description if there is a valid one.
|
|
61
|
+
*
|
|
62
|
+
* To return this field, add `fields=bio_description` in the user profile request's query parameter.
|
|
63
|
+
*/
|
|
64
|
+
bio_description?: string | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* The link to user's TikTok profile page.
|
|
67
|
+
*
|
|
68
|
+
* To return this field, add `fields=profile_deep_link` in the user profile request's query parameter.
|
|
69
|
+
*/
|
|
70
|
+
profile_deep_link?: string | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Whether TikTok has provided a verified badge to the account after confirming
|
|
73
|
+
* that it belongs to the user it represents.
|
|
74
|
+
*
|
|
75
|
+
* To return this field, add `fields=is_verified` in the user profile request's query parameter.
|
|
76
|
+
*/
|
|
77
|
+
is_verified?: boolean | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* User's followers count.
|
|
80
|
+
*
|
|
81
|
+
* To return this field, add `fields=follower_count` in the user profile request's query parameter.
|
|
82
|
+
*/
|
|
83
|
+
follower_count?: number | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* The number of accounts that the user is following.
|
|
86
|
+
*
|
|
87
|
+
* To return this field, add `fields=following_count` in the user profile request's query parameter.
|
|
88
|
+
*/
|
|
89
|
+
following_count?: number | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* The total number of likes received by the user across all of their videos.
|
|
92
|
+
*
|
|
93
|
+
* To return this field, add `fields=likes_count` in the user profile request's query parameter.
|
|
94
|
+
*/
|
|
95
|
+
likes_count?: number | undefined;
|
|
96
|
+
/**
|
|
97
|
+
* The total number of publicly posted videos by the user.
|
|
98
|
+
*
|
|
99
|
+
* To return this field, add `fields=video_count` in the user profile request's query parameter.
|
|
100
|
+
*/
|
|
101
|
+
video_count?: number | undefined;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
error?: {
|
|
105
|
+
/**
|
|
106
|
+
* The error category in string.
|
|
107
|
+
*/
|
|
108
|
+
code?: string;
|
|
109
|
+
/**
|
|
110
|
+
* The error message in string.
|
|
111
|
+
*/
|
|
112
|
+
message?: string;
|
|
113
|
+
/**
|
|
114
|
+
* The error message in string.
|
|
115
|
+
*/
|
|
116
|
+
log_id?: string;
|
|
117
|
+
} | undefined;
|
|
118
|
+
}
|
|
119
|
+
interface TiktokOptions extends ProviderOptions {
|
|
120
|
+
clientId?: never | undefined;
|
|
121
|
+
clientSecret: string;
|
|
122
|
+
clientKey: string;
|
|
123
|
+
}
|
|
124
|
+
declare const tiktok: (options: TiktokOptions) => {
|
|
125
|
+
id: "tiktok";
|
|
126
|
+
name: string;
|
|
127
|
+
createAuthorizationURL({
|
|
128
|
+
state,
|
|
129
|
+
scopes,
|
|
130
|
+
redirectURI
|
|
131
|
+
}: {
|
|
132
|
+
state: string;
|
|
133
|
+
codeVerifier: string;
|
|
134
|
+
scopes?: string[] | undefined;
|
|
135
|
+
redirectURI: string;
|
|
136
|
+
display?: string | undefined;
|
|
137
|
+
loginHint?: string | undefined;
|
|
138
|
+
}): URL;
|
|
139
|
+
validateAuthorizationCode: ({
|
|
140
|
+
code,
|
|
141
|
+
redirectURI
|
|
142
|
+
}: {
|
|
143
|
+
code: string;
|
|
144
|
+
redirectURI: string;
|
|
145
|
+
codeVerifier?: string | undefined;
|
|
146
|
+
deviceId?: string | undefined;
|
|
147
|
+
}) => Promise<OAuth2Tokens>;
|
|
148
|
+
refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
|
|
149
|
+
getUserInfo(token: OAuth2Tokens & {
|
|
150
|
+
user?: {
|
|
151
|
+
name?: {
|
|
152
|
+
firstName?: string;
|
|
153
|
+
lastName?: string;
|
|
154
|
+
};
|
|
155
|
+
email?: string;
|
|
156
|
+
} | undefined;
|
|
157
|
+
}): Promise<{
|
|
158
|
+
user: {
|
|
159
|
+
id: string;
|
|
160
|
+
name?: string;
|
|
161
|
+
email?: string | null;
|
|
162
|
+
image?: string;
|
|
163
|
+
emailVerified: boolean;
|
|
164
|
+
[key: string]: any;
|
|
165
|
+
};
|
|
166
|
+
data: any;
|
|
167
|
+
} | null>;
|
|
168
|
+
options: TiktokOptions;
|
|
169
|
+
};
|
|
170
|
+
//#endregion
|
|
171
|
+
export { TiktokOptions, TiktokProfile, tiktok };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
2
|
+
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
3
|
+
import "../oauth2/index.mjs";
|
|
4
|
+
import { betterFetch } from "@better-fetch/fetch";
|
|
5
|
+
|
|
6
|
+
//#region src/social-providers/tiktok.ts
|
|
7
|
+
const tiktok = (options) => {
|
|
8
|
+
return {
|
|
9
|
+
id: "tiktok",
|
|
10
|
+
name: "TikTok",
|
|
11
|
+
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
12
|
+
const _scopes = options.disableDefaultScope ? [] : ["user.info.profile"];
|
|
13
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
14
|
+
if (scopes) _scopes.push(...scopes);
|
|
15
|
+
return new URL(`https://www.tiktok.com/v2/auth/authorize?scope=${_scopes.join(",")}&response_type=code&client_key=${options.clientKey}&redirect_uri=${encodeURIComponent(options.redirectURI || redirectURI)}&state=${state}`);
|
|
16
|
+
},
|
|
17
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
18
|
+
return validateAuthorizationCode({
|
|
19
|
+
code,
|
|
20
|
+
redirectURI: options.redirectURI || redirectURI,
|
|
21
|
+
options: {
|
|
22
|
+
clientKey: options.clientKey,
|
|
23
|
+
clientSecret: options.clientSecret
|
|
24
|
+
},
|
|
25
|
+
tokenEndpoint: "https://open.tiktokapis.com/v2/oauth/token/"
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
29
|
+
return refreshAccessToken({
|
|
30
|
+
refreshToken,
|
|
31
|
+
options: { clientSecret: options.clientSecret },
|
|
32
|
+
tokenEndpoint: "https://open.tiktokapis.com/v2/oauth/token/",
|
|
33
|
+
authentication: "post",
|
|
34
|
+
extraParams: { client_key: options.clientKey }
|
|
35
|
+
});
|
|
36
|
+
},
|
|
37
|
+
async getUserInfo(token) {
|
|
38
|
+
if (options.getUserInfo) return options.getUserInfo(token);
|
|
39
|
+
const { data: profile, error } = await betterFetch(`https://open.tiktokapis.com/v2/user/info/?fields=${[
|
|
40
|
+
"open_id",
|
|
41
|
+
"avatar_large_url",
|
|
42
|
+
"display_name",
|
|
43
|
+
"username"
|
|
44
|
+
].join(",")}`, { headers: { authorization: `Bearer ${token.accessToken}` } });
|
|
45
|
+
if (error) return null;
|
|
46
|
+
return {
|
|
47
|
+
user: {
|
|
48
|
+
email: profile.data.user.email || profile.data.user.username,
|
|
49
|
+
id: profile.data.user.open_id,
|
|
50
|
+
name: profile.data.user.display_name || profile.data.user.username,
|
|
51
|
+
image: profile.data.user.avatar_large_url,
|
|
52
|
+
emailVerified: false
|
|
53
|
+
},
|
|
54
|
+
data: profile
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
options
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
//#endregion
|
|
62
|
+
export { tiktok };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
|
|
2
|
+
import "../oauth2/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/social-providers/twitch.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* @see https://dev.twitch.tv/docs/authentication/getting-tokens-oidc/#requesting-claims
|
|
7
|
+
*/
|
|
8
|
+
interface TwitchProfile {
|
|
9
|
+
/**
|
|
10
|
+
* The sub of the user
|
|
11
|
+
*/
|
|
12
|
+
sub: string;
|
|
13
|
+
/**
|
|
14
|
+
* The preferred username of the user
|
|
15
|
+
*/
|
|
16
|
+
preferred_username: string;
|
|
17
|
+
/**
|
|
18
|
+
* The email of the user
|
|
19
|
+
*/
|
|
20
|
+
email: string;
|
|
21
|
+
/**
|
|
22
|
+
* Indicate if this user has a verified email.
|
|
23
|
+
*/
|
|
24
|
+
email_verified: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* The picture of the user
|
|
27
|
+
*/
|
|
28
|
+
picture: string;
|
|
29
|
+
}
|
|
30
|
+
interface TwitchOptions extends ProviderOptions<TwitchProfile> {
|
|
31
|
+
clientId: string;
|
|
32
|
+
claims?: string[] | undefined;
|
|
33
|
+
}
|
|
34
|
+
declare const twitch: (options: TwitchOptions) => {
|
|
35
|
+
id: "twitch";
|
|
36
|
+
name: string;
|
|
37
|
+
createAuthorizationURL({
|
|
38
|
+
state,
|
|
39
|
+
scopes,
|
|
40
|
+
redirectURI
|
|
41
|
+
}: {
|
|
42
|
+
state: string;
|
|
43
|
+
codeVerifier: string;
|
|
44
|
+
scopes?: string[] | undefined;
|
|
45
|
+
redirectURI: string;
|
|
46
|
+
display?: string | undefined;
|
|
47
|
+
loginHint?: string | undefined;
|
|
48
|
+
}): Promise<URL>;
|
|
49
|
+
validateAuthorizationCode: ({
|
|
50
|
+
code,
|
|
51
|
+
redirectURI
|
|
52
|
+
}: {
|
|
53
|
+
code: string;
|
|
54
|
+
redirectURI: string;
|
|
55
|
+
codeVerifier?: string | undefined;
|
|
56
|
+
deviceId?: string | undefined;
|
|
57
|
+
}) => Promise<OAuth2Tokens>;
|
|
58
|
+
refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
|
|
59
|
+
getUserInfo(token: OAuth2Tokens & {
|
|
60
|
+
user?: {
|
|
61
|
+
name?: {
|
|
62
|
+
firstName?: string;
|
|
63
|
+
lastName?: string;
|
|
64
|
+
};
|
|
65
|
+
email?: string;
|
|
66
|
+
} | undefined;
|
|
67
|
+
}): Promise<{
|
|
68
|
+
user: {
|
|
69
|
+
id: string;
|
|
70
|
+
name?: string;
|
|
71
|
+
email?: string | null;
|
|
72
|
+
image?: string;
|
|
73
|
+
emailVerified: boolean;
|
|
74
|
+
[key: string]: any;
|
|
75
|
+
};
|
|
76
|
+
data: any;
|
|
77
|
+
} | null>;
|
|
78
|
+
options: TwitchOptions;
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { TwitchOptions, TwitchProfile, twitch };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { logger } from "../env/logger.mjs";
|
|
2
|
+
import "../env/index.mjs";
|
|
3
|
+
import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
|
|
4
|
+
import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
|
|
5
|
+
import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
|
|
6
|
+
import "../oauth2/index.mjs";
|
|
7
|
+
import { decodeJwt } from "jose";
|
|
8
|
+
|
|
9
|
+
//#region src/social-providers/twitch.ts
|
|
10
|
+
const twitch = (options) => {
|
|
11
|
+
return {
|
|
12
|
+
id: "twitch",
|
|
13
|
+
name: "Twitch",
|
|
14
|
+
createAuthorizationURL({ state, scopes, redirectURI }) {
|
|
15
|
+
const _scopes = options.disableDefaultScope ? [] : ["user:read:email", "openid"];
|
|
16
|
+
if (options.scope) _scopes.push(...options.scope);
|
|
17
|
+
if (scopes) _scopes.push(...scopes);
|
|
18
|
+
return createAuthorizationURL({
|
|
19
|
+
id: "twitch",
|
|
20
|
+
redirectURI,
|
|
21
|
+
options,
|
|
22
|
+
authorizationEndpoint: "https://id.twitch.tv/oauth2/authorize",
|
|
23
|
+
scopes: _scopes,
|
|
24
|
+
state,
|
|
25
|
+
claims: options.claims || [
|
|
26
|
+
"email",
|
|
27
|
+
"email_verified",
|
|
28
|
+
"preferred_username",
|
|
29
|
+
"picture"
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
validateAuthorizationCode: async ({ code, redirectURI }) => {
|
|
34
|
+
return validateAuthorizationCode({
|
|
35
|
+
code,
|
|
36
|
+
redirectURI,
|
|
37
|
+
options,
|
|
38
|
+
tokenEndpoint: "https://id.twitch.tv/oauth2/token"
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
|
|
42
|
+
return refreshAccessToken({
|
|
43
|
+
refreshToken,
|
|
44
|
+
options: {
|
|
45
|
+
clientId: options.clientId,
|
|
46
|
+
clientKey: options.clientKey,
|
|
47
|
+
clientSecret: options.clientSecret
|
|
48
|
+
},
|
|
49
|
+
tokenEndpoint: "https://id.twitch.tv/oauth2/token"
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
async getUserInfo(token) {
|
|
53
|
+
if (options.getUserInfo) return options.getUserInfo(token);
|
|
54
|
+
const idToken = token.idToken;
|
|
55
|
+
if (!idToken) {
|
|
56
|
+
logger.error("No idToken found in token");
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const profile = decodeJwt(idToken);
|
|
60
|
+
const userMap = await options.mapProfileToUser?.(profile);
|
|
61
|
+
return {
|
|
62
|
+
user: {
|
|
63
|
+
id: profile.sub,
|
|
64
|
+
name: profile.preferred_username,
|
|
65
|
+
email: profile.email,
|
|
66
|
+
image: profile.picture,
|
|
67
|
+
emailVerified: profile.email_verified,
|
|
68
|
+
...userMap
|
|
69
|
+
},
|
|
70
|
+
data: profile
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
options
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
//#endregion
|
|
78
|
+
export { twitch };
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
|
|
2
|
+
import "../oauth2/index.mjs";
|
|
3
|
+
|
|
4
|
+
//#region src/social-providers/twitter.d.ts
|
|
5
|
+
interface TwitterProfile {
|
|
6
|
+
data: {
|
|
7
|
+
/**
|
|
8
|
+
* Unique identifier of this user. This is returned as a string in order to avoid complications with languages and tools
|
|
9
|
+
* that cannot handle large integers.
|
|
10
|
+
*/
|
|
11
|
+
id: string;
|
|
12
|
+
/** The friendly name of this user, as shown on their profile. */
|
|
13
|
+
name: string;
|
|
14
|
+
/** The email address of this user. */
|
|
15
|
+
email?: string | undefined;
|
|
16
|
+
/** The Twitter handle (screen name) of this user. */
|
|
17
|
+
username: string;
|
|
18
|
+
/**
|
|
19
|
+
* The location specified in the user's profile, if the user provided one.
|
|
20
|
+
* As this is a freeform value, it may not indicate a valid location, but it may be fuzzily evaluated when performing searches with location queries.
|
|
21
|
+
*
|
|
22
|
+
* To return this field, add `user.fields=location` in the authorization request's query parameter.
|
|
23
|
+
*/
|
|
24
|
+
location?: string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* This object and its children fields contain details about text that has a special meaning in the user's description.
|
|
27
|
+
*
|
|
28
|
+
*To return this field, add `user.fields=entities` in the authorization request's query parameter.
|
|
29
|
+
*/
|
|
30
|
+
entities?: {
|
|
31
|
+
/** Contains details about the user's profile website. */
|
|
32
|
+
url: {
|
|
33
|
+
/** Contains details about the user's profile website. */
|
|
34
|
+
urls: Array<{
|
|
35
|
+
/** The start position (zero-based) of the recognized user's profile website. All start indices are inclusive. */
|
|
36
|
+
start: number;
|
|
37
|
+
/** The end position (zero-based) of the recognized user's profile website. This end index is exclusive. */
|
|
38
|
+
end: number;
|
|
39
|
+
/** The URL in the format entered by the user. */
|
|
40
|
+
url: string;
|
|
41
|
+
/** The fully resolved URL. */
|
|
42
|
+
expanded_url: string;
|
|
43
|
+
/** The URL as displayed in the user's profile. */
|
|
44
|
+
display_url: string;
|
|
45
|
+
}>;
|
|
46
|
+
};
|
|
47
|
+
/** Contains details about URLs, Hashtags, Cashtags, or mentions located within a user's description. */
|
|
48
|
+
description: {
|
|
49
|
+
hashtags: Array<{
|
|
50
|
+
start: number;
|
|
51
|
+
end: number;
|
|
52
|
+
tag: string;
|
|
53
|
+
}>;
|
|
54
|
+
};
|
|
55
|
+
} | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Indicate if this user is a verified Twitter user.
|
|
58
|
+
*
|
|
59
|
+
* To return this field, add `user.fields=verified` in the authorization request's query parameter.
|
|
60
|
+
*/
|
|
61
|
+
verified?: boolean | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* The text of this user's profile description (also known as bio), if the user provided one.
|
|
64
|
+
*
|
|
65
|
+
* To return this field, add `user.fields=description` in the authorization request's query parameter.
|
|
66
|
+
*/
|
|
67
|
+
description?: string | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* The URL specified in the user's profile, if present.
|
|
70
|
+
*
|
|
71
|
+
* To return this field, add `user.fields=url` in the authorization request's query parameter.
|
|
72
|
+
*/
|
|
73
|
+
url?: string | undefined;
|
|
74
|
+
/** The URL to the profile image for this user, as shown on the user's profile. */
|
|
75
|
+
profile_image_url?: string | undefined;
|
|
76
|
+
protected?: boolean | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Unique identifier of this user's pinned Tweet.
|
|
79
|
+
*
|
|
80
|
+
* You can obtain the expanded object in `includes.tweets` by adding `expansions=pinned_tweet_id` in the authorization request's query parameter.
|
|
81
|
+
*/
|
|
82
|
+
pinned_tweet_id?: string | undefined;
|
|
83
|
+
created_at?: string | undefined;
|
|
84
|
+
};
|
|
85
|
+
includes?: {
|
|
86
|
+
tweets?: Array<{
|
|
87
|
+
id: string;
|
|
88
|
+
text: string;
|
|
89
|
+
}>;
|
|
90
|
+
} | undefined;
|
|
91
|
+
[claims: string]: unknown;
|
|
92
|
+
}
|
|
93
|
+
interface TwitterOption extends ProviderOptions<TwitterProfile> {
|
|
94
|
+
clientId: string;
|
|
95
|
+
}
|
|
96
|
+
declare const twitter: (options: TwitterOption) => {
|
|
97
|
+
id: "twitter";
|
|
98
|
+
name: string;
|
|
99
|
+
createAuthorizationURL(data: {
|
|
100
|
+
state: string;
|
|
101
|
+
codeVerifier: string;
|
|
102
|
+
scopes?: string[] | undefined;
|
|
103
|
+
redirectURI: string;
|
|
104
|
+
display?: string | undefined;
|
|
105
|
+
loginHint?: string | undefined;
|
|
106
|
+
}): Promise<URL>;
|
|
107
|
+
validateAuthorizationCode: ({
|
|
108
|
+
code,
|
|
109
|
+
codeVerifier,
|
|
110
|
+
redirectURI
|
|
111
|
+
}: {
|
|
112
|
+
code: string;
|
|
113
|
+
redirectURI: string;
|
|
114
|
+
codeVerifier?: string | undefined;
|
|
115
|
+
deviceId?: string | undefined;
|
|
116
|
+
}) => Promise<OAuth2Tokens>;
|
|
117
|
+
refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
|
|
118
|
+
getUserInfo(token: OAuth2Tokens & {
|
|
119
|
+
user?: {
|
|
120
|
+
name?: {
|
|
121
|
+
firstName?: string;
|
|
122
|
+
lastName?: string;
|
|
123
|
+
};
|
|
124
|
+
email?: string;
|
|
125
|
+
} | undefined;
|
|
126
|
+
}): Promise<{
|
|
127
|
+
user: {
|
|
128
|
+
id: string;
|
|
129
|
+
name?: string;
|
|
130
|
+
email?: string | null;
|
|
131
|
+
image?: string;
|
|
132
|
+
emailVerified: boolean;
|
|
133
|
+
[key: string]: any;
|
|
134
|
+
};
|
|
135
|
+
data: any;
|
|
136
|
+
} | null>;
|
|
137
|
+
options: TwitterOption;
|
|
138
|
+
};
|
|
139
|
+
//#endregion
|
|
140
|
+
export { TwitterOption, TwitterProfile, twitter };
|