@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.
Files changed (185) hide show
  1. package/.turbo/turbo-build.log +172 -35
  2. package/dist/api/index.d.mts +178 -1
  3. package/dist/api/index.mjs +2 -1
  4. package/dist/context/endpoint-context.d.mts +19 -0
  5. package/dist/context/endpoint-context.mjs +31 -0
  6. package/dist/context/global.d.mts +7 -0
  7. package/dist/context/global.mjs +37 -0
  8. package/dist/context/index.d.mts +5 -53
  9. package/dist/context/index.mjs +5 -2
  10. package/dist/context/request-state.d.mts +27 -0
  11. package/dist/context/request-state.mjs +49 -0
  12. package/dist/context/transaction.d.mts +16 -0
  13. package/dist/context/transaction.mjs +52 -0
  14. package/dist/db/adapter/factory.d.mts +27 -0
  15. package/dist/db/adapter/factory.mjs +738 -0
  16. package/dist/db/adapter/get-default-field-name.d.mts +18 -0
  17. package/dist/db/adapter/get-default-field-name.mjs +38 -0
  18. package/dist/db/adapter/get-default-model-name.d.mts +12 -0
  19. package/dist/db/adapter/get-default-model-name.mjs +32 -0
  20. package/dist/db/adapter/get-field-attributes.d.mts +29 -0
  21. package/dist/db/adapter/get-field-attributes.mjs +39 -0
  22. package/dist/db/adapter/get-field-name.d.mts +18 -0
  23. package/dist/db/adapter/get-field-name.mjs +33 -0
  24. package/dist/db/adapter/get-id-field.d.mts +39 -0
  25. package/dist/db/adapter/get-id-field.mjs +68 -0
  26. package/dist/db/adapter/get-model-name.d.mts +12 -0
  27. package/dist/db/adapter/get-model-name.mjs +23 -0
  28. package/dist/db/adapter/index.d.mts +513 -1
  29. package/dist/db/adapter/index.mjs +8 -970
  30. package/dist/db/adapter/types.d.mts +139 -0
  31. package/dist/db/adapter/utils.d.mts +7 -0
  32. package/dist/db/adapter/utils.mjs +38 -0
  33. package/dist/db/get-tables.d.mts +8 -0
  34. package/dist/{get-tables-CMc_Emww.mjs → db/get-tables.mjs} +1 -1
  35. package/dist/db/index.d.mts +10 -2
  36. package/dist/db/index.mjs +7 -60
  37. package/dist/db/plugin.d.mts +12 -0
  38. package/dist/db/schema/account.d.mts +26 -0
  39. package/dist/db/schema/account.mjs +19 -0
  40. package/dist/db/schema/rate-limit.d.mts +14 -0
  41. package/dist/db/schema/rate-limit.mjs +11 -0
  42. package/dist/db/schema/session.d.mts +21 -0
  43. package/dist/db/schema/session.mjs +14 -0
  44. package/dist/db/schema/shared.d.mts +10 -0
  45. package/dist/db/schema/shared.mjs +11 -0
  46. package/dist/db/schema/user.d.mts +20 -0
  47. package/dist/db/schema/user.mjs +13 -0
  48. package/dist/db/schema/verification.d.mts +19 -0
  49. package/dist/db/schema/verification.mjs +12 -0
  50. package/dist/db/type.d.mts +143 -0
  51. package/dist/env/color-depth.d.mts +4 -0
  52. package/dist/env/color-depth.mjs +88 -0
  53. package/dist/env/env-impl.d.mts +32 -0
  54. package/dist/env/env-impl.mjs +82 -0
  55. package/dist/env/index.d.mts +4 -2
  56. package/dist/env/index.mjs +3 -1
  57. package/dist/{index-BRBu0-5h.d.mts → env/logger.d.mts} +1 -35
  58. package/dist/env/logger.mjs +81 -0
  59. package/dist/error/codes.d.mts +48 -0
  60. package/dist/{error-DP1xOn7P.mjs → error/codes.mjs} +3 -14
  61. package/dist/error/index.d.mts +5 -48
  62. package/dist/error/index.mjs +12 -3
  63. package/dist/index.d.mts +8 -2
  64. package/dist/oauth2/client-credentials-token.d.mts +36 -0
  65. package/dist/oauth2/client-credentials-token.mjs +54 -0
  66. package/dist/oauth2/create-authorization-url.d.mts +45 -0
  67. package/dist/oauth2/create-authorization-url.mjs +42 -0
  68. package/dist/oauth2/index.d.mts +8 -2
  69. package/dist/oauth2/index.mjs +6 -2
  70. package/dist/oauth2/oauth-provider.d.mts +194 -0
  71. package/dist/oauth2/refresh-access-token.d.mts +36 -0
  72. package/dist/oauth2/refresh-access-token.mjs +58 -0
  73. package/dist/oauth2/utils.d.mts +7 -0
  74. package/dist/oauth2/utils.mjs +27 -0
  75. package/dist/oauth2/validate-authorization-code.d.mts +55 -0
  76. package/dist/oauth2/validate-authorization-code.mjs +71 -0
  77. package/dist/oauth2/verify.d.mts +49 -0
  78. package/dist/oauth2/verify.mjs +95 -0
  79. package/dist/social-providers/apple.d.mts +119 -0
  80. package/dist/social-providers/apple.mjs +102 -0
  81. package/dist/social-providers/atlassian.d.mts +72 -0
  82. package/dist/social-providers/atlassian.mjs +83 -0
  83. package/dist/social-providers/cognito.d.mts +87 -0
  84. package/dist/social-providers/cognito.mjs +166 -0
  85. package/dist/social-providers/discord.d.mts +126 -0
  86. package/dist/social-providers/discord.mjs +64 -0
  87. package/dist/social-providers/dropbox.d.mts +71 -0
  88. package/dist/social-providers/dropbox.mjs +75 -0
  89. package/dist/social-providers/facebook.d.mts +81 -0
  90. package/dist/social-providers/facebook.mjs +120 -0
  91. package/dist/social-providers/figma.d.mts +63 -0
  92. package/dist/social-providers/figma.mjs +84 -0
  93. package/dist/social-providers/github.d.mts +104 -0
  94. package/dist/social-providers/github.mjs +80 -0
  95. package/dist/social-providers/gitlab.d.mts +125 -0
  96. package/dist/social-providers/gitlab.mjs +82 -0
  97. package/dist/social-providers/google.d.mts +99 -0
  98. package/dist/social-providers/google.mjs +109 -0
  99. package/dist/social-providers/huggingface.d.mts +85 -0
  100. package/dist/social-providers/huggingface.mjs +75 -0
  101. package/dist/social-providers/index.d.mts +1723 -1
  102. package/dist/social-providers/index.mjs +33 -2570
  103. package/dist/social-providers/kakao.d.mts +163 -0
  104. package/dist/social-providers/kakao.mjs +72 -0
  105. package/dist/social-providers/kick.d.mts +75 -0
  106. package/dist/social-providers/kick.mjs +71 -0
  107. package/dist/social-providers/line.d.mts +107 -0
  108. package/dist/social-providers/line.mjs +113 -0
  109. package/dist/social-providers/linear.d.mts +70 -0
  110. package/dist/social-providers/linear.mjs +88 -0
  111. package/dist/social-providers/linkedin.d.mts +69 -0
  112. package/dist/social-providers/linkedin.mjs +76 -0
  113. package/dist/social-providers/microsoft-entra-id.d.mts +174 -0
  114. package/dist/social-providers/microsoft-entra-id.mjs +106 -0
  115. package/dist/social-providers/naver.d.mts +104 -0
  116. package/dist/social-providers/naver.mjs +67 -0
  117. package/dist/social-providers/notion.d.mts +66 -0
  118. package/dist/social-providers/notion.mjs +75 -0
  119. package/dist/social-providers/paybin.d.mts +73 -0
  120. package/dist/social-providers/paybin.mjs +85 -0
  121. package/dist/social-providers/paypal.d.mts +131 -0
  122. package/dist/social-providers/paypal.mjs +144 -0
  123. package/dist/social-providers/polar.d.mts +76 -0
  124. package/dist/social-providers/polar.mjs +73 -0
  125. package/dist/social-providers/reddit.d.mts +64 -0
  126. package/dist/social-providers/reddit.mjs +83 -0
  127. package/dist/social-providers/roblox.d.mts +72 -0
  128. package/dist/social-providers/roblox.mjs +59 -0
  129. package/dist/social-providers/salesforce.d.mts +81 -0
  130. package/dist/social-providers/salesforce.mjs +91 -0
  131. package/dist/social-providers/slack.d.mts +85 -0
  132. package/dist/social-providers/slack.mjs +68 -0
  133. package/dist/social-providers/spotify.d.mts +65 -0
  134. package/dist/social-providers/spotify.mjs +71 -0
  135. package/dist/social-providers/tiktok.d.mts +171 -0
  136. package/dist/social-providers/tiktok.mjs +62 -0
  137. package/dist/social-providers/twitch.d.mts +81 -0
  138. package/dist/social-providers/twitch.mjs +78 -0
  139. package/dist/social-providers/twitter.d.mts +140 -0
  140. package/dist/social-providers/twitter.mjs +87 -0
  141. package/dist/social-providers/vercel.d.mts +64 -0
  142. package/dist/social-providers/vercel.mjs +61 -0
  143. package/dist/social-providers/vk.d.mts +72 -0
  144. package/dist/social-providers/vk.mjs +83 -0
  145. package/dist/social-providers/zoom.d.mts +173 -0
  146. package/dist/social-providers/zoom.mjs +72 -0
  147. package/dist/types/context.d.mts +215 -0
  148. package/dist/types/cookie.d.mts +15 -0
  149. package/dist/types/helper.d.mts +8 -0
  150. package/dist/types/index.d.mts +8 -0
  151. package/dist/types/init-options.d.mts +1266 -0
  152. package/dist/types/plugin-client.d.mts +103 -0
  153. package/dist/types/plugin.d.mts +121 -0
  154. package/dist/utils/deprecate.d.mts +10 -0
  155. package/dist/utils/deprecate.mjs +17 -0
  156. package/dist/utils/error-codes.d.mts +9 -0
  157. package/dist/utils/error-codes.mjs +7 -0
  158. package/dist/utils/id.d.mts +4 -0
  159. package/dist/utils/id.mjs +9 -0
  160. package/dist/utils/index.d.mts +5 -26
  161. package/dist/utils/index.mjs +5 -2
  162. package/dist/utils/json.d.mts +4 -0
  163. package/dist/utils/json.mjs +25 -0
  164. package/dist/utils/string.d.mts +4 -0
  165. package/dist/utils/string.mjs +7 -0
  166. package/package.json +1 -1
  167. package/src/context/endpoint-context.ts +7 -15
  168. package/src/context/global.ts +57 -0
  169. package/src/context/index.ts +1 -0
  170. package/src/context/request-state.ts +7 -12
  171. package/src/context/transaction.ts +7 -16
  172. package/src/db/adapter/factory.ts +13 -13
  173. package/src/db/adapter/get-default-model-name.ts +1 -1
  174. package/src/db/adapter/get-id-field.ts +2 -2
  175. package/src/error/index.ts +2 -3
  176. package/src/social-providers/gitlab.ts +1 -1
  177. package/src/types/context.ts +137 -131
  178. package/src/types/cookie.ts +6 -4
  179. package/src/types/index.ts +2 -1
  180. package/tsdown.config.ts +9 -0
  181. package/dist/context-BGZ8V6DD.mjs +0 -126
  182. package/dist/env-DbssmzoK.mjs +0 -245
  183. package/dist/index-zgYuzZ7O.d.mts +0 -8020
  184. package/dist/oauth2-COJkghlT.mjs +0 -326
  185. package/dist/utils-U2L7n92V.mjs +0 -59
@@ -0,0 +1,73 @@
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/polar.ts
8
+ const polar = (options) => {
9
+ return {
10
+ id: "polar",
11
+ name: "Polar",
12
+ createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
13
+ const _scopes = options.disableDefaultScope ? [] : [
14
+ "openid",
15
+ "profile",
16
+ "email"
17
+ ];
18
+ if (options.scope) _scopes.push(...options.scope);
19
+ if (scopes) _scopes.push(...scopes);
20
+ return createAuthorizationURL({
21
+ id: "polar",
22
+ options,
23
+ authorizationEndpoint: "https://polar.sh/oauth2/authorize",
24
+ scopes: _scopes,
25
+ state,
26
+ codeVerifier,
27
+ redirectURI,
28
+ prompt: options.prompt
29
+ });
30
+ },
31
+ validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
32
+ return validateAuthorizationCode({
33
+ code,
34
+ codeVerifier,
35
+ redirectURI,
36
+ options,
37
+ tokenEndpoint: "https://api.polar.sh/v1/oauth2/token"
38
+ });
39
+ },
40
+ refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
41
+ return refreshAccessToken({
42
+ refreshToken,
43
+ options: {
44
+ clientId: options.clientId,
45
+ clientKey: options.clientKey,
46
+ clientSecret: options.clientSecret
47
+ },
48
+ tokenEndpoint: "https://api.polar.sh/v1/oauth2/token"
49
+ });
50
+ },
51
+ async getUserInfo(token) {
52
+ if (options.getUserInfo) return options.getUserInfo(token);
53
+ const { data: profile, error } = await betterFetch("https://api.polar.sh/v1/oauth2/userinfo", { headers: { Authorization: `Bearer ${token.accessToken}` } });
54
+ if (error) return null;
55
+ const userMap = await options.mapProfileToUser?.(profile);
56
+ return {
57
+ user: {
58
+ id: profile.id,
59
+ name: profile.public_name || profile.username,
60
+ email: profile.email,
61
+ image: profile.avatar_url,
62
+ emailVerified: profile.email_verified ?? false,
63
+ ...userMap
64
+ },
65
+ data: profile
66
+ };
67
+ },
68
+ options
69
+ };
70
+ };
71
+
72
+ //#endregion
73
+ export { polar };
@@ -0,0 +1,64 @@
1
+ import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
2
+ import "../oauth2/index.mjs";
3
+
4
+ //#region src/social-providers/reddit.d.ts
5
+ interface RedditProfile {
6
+ id: string;
7
+ name: string;
8
+ icon_img: string | null;
9
+ has_verified_email: boolean;
10
+ oauth_client_id: string;
11
+ verified: boolean;
12
+ }
13
+ interface RedditOptions extends ProviderOptions<RedditProfile> {
14
+ clientId: string;
15
+ duration?: string | undefined;
16
+ }
17
+ declare const reddit: (options: RedditOptions) => {
18
+ id: "reddit";
19
+ name: string;
20
+ createAuthorizationURL({
21
+ state,
22
+ scopes,
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
+ redirectURI
35
+ }: {
36
+ code: string;
37
+ redirectURI: string;
38
+ codeVerifier?: string | undefined;
39
+ deviceId?: string | undefined;
40
+ }) => Promise<OAuth2Tokens>;
41
+ refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
42
+ getUserInfo(token: OAuth2Tokens & {
43
+ user?: {
44
+ name?: {
45
+ firstName?: string;
46
+ lastName?: string;
47
+ };
48
+ email?: string;
49
+ } | undefined;
50
+ }): Promise<{
51
+ user: {
52
+ id: string;
53
+ name?: string;
54
+ email?: string | null;
55
+ image?: string;
56
+ emailVerified: boolean;
57
+ [key: string]: any;
58
+ };
59
+ data: any;
60
+ } | null>;
61
+ options: RedditOptions;
62
+ };
63
+ //#endregion
64
+ export { RedditOptions, RedditProfile, reddit };
@@ -0,0 +1,83 @@
1
+ import { getOAuth2Tokens } from "../oauth2/utils.mjs";
2
+ import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
3
+ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
4
+ import "../oauth2/index.mjs";
5
+ import { base64 } from "@better-auth/utils/base64";
6
+ import { betterFetch } from "@better-fetch/fetch";
7
+
8
+ //#region src/social-providers/reddit.ts
9
+ const reddit = (options) => {
10
+ return {
11
+ id: "reddit",
12
+ name: "Reddit",
13
+ createAuthorizationURL({ state, scopes, redirectURI }) {
14
+ const _scopes = options.disableDefaultScope ? [] : ["identity"];
15
+ if (options.scope) _scopes.push(...options.scope);
16
+ if (scopes) _scopes.push(...scopes);
17
+ return createAuthorizationURL({
18
+ id: "reddit",
19
+ options,
20
+ authorizationEndpoint: "https://www.reddit.com/api/v1/authorize",
21
+ scopes: _scopes,
22
+ state,
23
+ redirectURI,
24
+ duration: options.duration
25
+ });
26
+ },
27
+ validateAuthorizationCode: async ({ code, redirectURI }) => {
28
+ const body = new URLSearchParams({
29
+ grant_type: "authorization_code",
30
+ code,
31
+ redirect_uri: options.redirectURI || redirectURI
32
+ });
33
+ const { data, error } = await betterFetch("https://www.reddit.com/api/v1/access_token", {
34
+ method: "POST",
35
+ headers: {
36
+ "content-type": "application/x-www-form-urlencoded",
37
+ accept: "text/plain",
38
+ "user-agent": "better-auth",
39
+ Authorization: `Basic ${base64.encode(`${options.clientId}:${options.clientSecret}`)}`
40
+ },
41
+ body: body.toString()
42
+ });
43
+ if (error) throw error;
44
+ return getOAuth2Tokens(data);
45
+ },
46
+ refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
47
+ return refreshAccessToken({
48
+ refreshToken,
49
+ options: {
50
+ clientId: options.clientId,
51
+ clientKey: options.clientKey,
52
+ clientSecret: options.clientSecret
53
+ },
54
+ authentication: "basic",
55
+ tokenEndpoint: "https://www.reddit.com/api/v1/access_token"
56
+ });
57
+ },
58
+ async getUserInfo(token) {
59
+ if (options.getUserInfo) return options.getUserInfo(token);
60
+ const { data: profile, error } = await betterFetch("https://oauth.reddit.com/api/v1/me", { headers: {
61
+ Authorization: `Bearer ${token.accessToken}`,
62
+ "User-Agent": "better-auth"
63
+ } });
64
+ if (error) return null;
65
+ const userMap = await options.mapProfileToUser?.(profile);
66
+ return {
67
+ user: {
68
+ id: profile.id,
69
+ name: profile.name,
70
+ email: profile.oauth_client_id,
71
+ emailVerified: profile.has_verified_email,
72
+ image: profile.icon_img?.split("?")[0],
73
+ ...userMap
74
+ },
75
+ data: profile
76
+ };
77
+ },
78
+ options
79
+ };
80
+ };
81
+
82
+ //#endregion
83
+ export { reddit };
@@ -0,0 +1,72 @@
1
+ import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
2
+ import "../oauth2/index.mjs";
3
+
4
+ //#region src/social-providers/roblox.d.ts
5
+ interface RobloxProfile extends Record<string, any> {
6
+ /** the user's id */
7
+ sub: string;
8
+ /** the user's username */
9
+ preferred_username: string;
10
+ /** the user's display name, will return the same value as the preferred_username if not set */
11
+ nickname: string;
12
+ /** the user's display name, again, will return the same value as the preferred_username if not set */
13
+ name: string;
14
+ /** the account creation date as a unix timestamp in seconds */
15
+ created_at: number;
16
+ /** the user's profile URL */
17
+ profile: string;
18
+ /** the user's avatar URL */
19
+ picture: string;
20
+ }
21
+ interface RobloxOptions extends ProviderOptions<RobloxProfile> {
22
+ clientId: string;
23
+ prompt?: ("none" | "consent" | "login" | "select_account" | "select_account consent") | undefined;
24
+ }
25
+ declare const roblox: (options: RobloxOptions) => {
26
+ id: "roblox";
27
+ name: string;
28
+ createAuthorizationURL({
29
+ state,
30
+ scopes,
31
+ redirectURI
32
+ }: {
33
+ state: string;
34
+ codeVerifier: string;
35
+ scopes?: string[] | undefined;
36
+ redirectURI: string;
37
+ display?: string | undefined;
38
+ loginHint?: string | undefined;
39
+ }): URL;
40
+ validateAuthorizationCode: ({
41
+ code,
42
+ redirectURI
43
+ }: {
44
+ code: string;
45
+ redirectURI: string;
46
+ codeVerifier?: string | undefined;
47
+ deviceId?: string | undefined;
48
+ }) => Promise<OAuth2Tokens>;
49
+ refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
50
+ getUserInfo(token: OAuth2Tokens & {
51
+ user?: {
52
+ name?: {
53
+ firstName?: string;
54
+ lastName?: string;
55
+ };
56
+ email?: string;
57
+ } | undefined;
58
+ }): Promise<{
59
+ user: {
60
+ id: string;
61
+ name?: string;
62
+ email?: string | null;
63
+ image?: string;
64
+ emailVerified: boolean;
65
+ [key: string]: any;
66
+ };
67
+ data: any;
68
+ } | null>;
69
+ options: RobloxOptions;
70
+ };
71
+ //#endregion
72
+ export { RobloxOptions, RobloxProfile, roblox };
@@ -0,0 +1,59 @@
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/roblox.ts
7
+ const roblox = (options) => {
8
+ return {
9
+ id: "roblox",
10
+ name: "Roblox",
11
+ createAuthorizationURL({ state, scopes, redirectURI }) {
12
+ const _scopes = options.disableDefaultScope ? [] : ["openid", "profile"];
13
+ if (options.scope) _scopes.push(...options.scope);
14
+ if (scopes) _scopes.push(...scopes);
15
+ return new URL(`https://apis.roblox.com/oauth/v1/authorize?scope=${_scopes.join("+")}&response_type=code&client_id=${options.clientId}&redirect_uri=${encodeURIComponent(options.redirectURI || redirectURI)}&state=${state}&prompt=${options.prompt || "select_account consent"}`);
16
+ },
17
+ validateAuthorizationCode: async ({ code, redirectURI }) => {
18
+ return validateAuthorizationCode({
19
+ code,
20
+ redirectURI: options.redirectURI || redirectURI,
21
+ options,
22
+ tokenEndpoint: "https://apis.roblox.com/oauth/v1/token",
23
+ authentication: "post"
24
+ });
25
+ },
26
+ refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
27
+ return refreshAccessToken({
28
+ refreshToken,
29
+ options: {
30
+ clientId: options.clientId,
31
+ clientKey: options.clientKey,
32
+ clientSecret: options.clientSecret
33
+ },
34
+ tokenEndpoint: "https://apis.roblox.com/oauth/v1/token"
35
+ });
36
+ },
37
+ async getUserInfo(token) {
38
+ if (options.getUserInfo) return options.getUserInfo(token);
39
+ const { data: profile, error } = await betterFetch("https://apis.roblox.com/oauth/v1/userinfo", { headers: { authorization: `Bearer ${token.accessToken}` } });
40
+ if (error) return null;
41
+ const userMap = await options.mapProfileToUser?.(profile);
42
+ return {
43
+ user: {
44
+ id: profile.sub,
45
+ name: profile.nickname || profile.preferred_username || "",
46
+ image: profile.picture,
47
+ email: profile.preferred_username || null,
48
+ emailVerified: false,
49
+ ...userMap
50
+ },
51
+ data: { ...profile }
52
+ };
53
+ },
54
+ options
55
+ };
56
+ };
57
+
58
+ //#endregion
59
+ export { roblox };
@@ -0,0 +1,81 @@
1
+ import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
2
+ import "../oauth2/index.mjs";
3
+
4
+ //#region src/social-providers/salesforce.d.ts
5
+ interface SalesforceProfile {
6
+ sub: string;
7
+ user_id: string;
8
+ organization_id: string;
9
+ preferred_username?: string | undefined;
10
+ email: string;
11
+ email_verified?: boolean | undefined;
12
+ name: string;
13
+ given_name?: string | undefined;
14
+ family_name?: string | undefined;
15
+ zoneinfo?: string | undefined;
16
+ photos?: {
17
+ picture?: string;
18
+ thumbnail?: string;
19
+ } | undefined;
20
+ }
21
+ interface SalesforceOptions extends ProviderOptions<SalesforceProfile> {
22
+ clientId: string;
23
+ environment?: ("sandbox" | "production") | undefined;
24
+ loginUrl?: string | undefined;
25
+ /**
26
+ * Override the redirect URI if auto-detection fails.
27
+ * Should match the Callback URL configured in your Salesforce Connected App.
28
+ * @example "http://localhost:3000/api/auth/callback/salesforce"
29
+ */
30
+ redirectURI?: string | undefined;
31
+ }
32
+ declare const salesforce: (options: SalesforceOptions) => {
33
+ id: "salesforce";
34
+ name: string;
35
+ createAuthorizationURL({
36
+ state,
37
+ scopes,
38
+ codeVerifier,
39
+ redirectURI
40
+ }: {
41
+ state: string;
42
+ codeVerifier: string;
43
+ scopes?: string[] | undefined;
44
+ redirectURI: string;
45
+ display?: string | undefined;
46
+ loginHint?: string | undefined;
47
+ }): Promise<URL>;
48
+ validateAuthorizationCode: ({
49
+ code,
50
+ codeVerifier,
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: SalesforceOptions;
79
+ };
80
+ //#endregion
81
+ export { SalesforceOptions, SalesforceProfile, salesforce };
@@ -0,0 +1,91 @@
1
+ import { logger } from "../env/logger.mjs";
2
+ import "../env/index.mjs";
3
+ import { BetterAuthError } from "../error/index.mjs";
4
+ import { createAuthorizationURL } from "../oauth2/create-authorization-url.mjs";
5
+ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
6
+ import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
7
+ import "../oauth2/index.mjs";
8
+ import { betterFetch } from "@better-fetch/fetch";
9
+
10
+ //#region src/social-providers/salesforce.ts
11
+ const salesforce = (options) => {
12
+ const isSandbox = (options.environment ?? "production") === "sandbox";
13
+ const authorizationEndpoint = options.loginUrl ? `https://${options.loginUrl}/services/oauth2/authorize` : isSandbox ? "https://test.salesforce.com/services/oauth2/authorize" : "https://login.salesforce.com/services/oauth2/authorize";
14
+ const tokenEndpoint = options.loginUrl ? `https://${options.loginUrl}/services/oauth2/token` : isSandbox ? "https://test.salesforce.com/services/oauth2/token" : "https://login.salesforce.com/services/oauth2/token";
15
+ const userInfoEndpoint = options.loginUrl ? `https://${options.loginUrl}/services/oauth2/userinfo` : isSandbox ? "https://test.salesforce.com/services/oauth2/userinfo" : "https://login.salesforce.com/services/oauth2/userinfo";
16
+ return {
17
+ id: "salesforce",
18
+ name: "Salesforce",
19
+ async createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
20
+ if (!options.clientId || !options.clientSecret) {
21
+ logger.error("Client Id and Client Secret are required for Salesforce. Make sure to provide them in the options.");
22
+ throw new BetterAuthError("CLIENT_ID_AND_SECRET_REQUIRED");
23
+ }
24
+ if (!codeVerifier) throw new BetterAuthError("codeVerifier is required for Salesforce");
25
+ const _scopes = options.disableDefaultScope ? [] : [
26
+ "openid",
27
+ "email",
28
+ "profile"
29
+ ];
30
+ if (options.scope) _scopes.push(...options.scope);
31
+ if (scopes) _scopes.push(...scopes);
32
+ return createAuthorizationURL({
33
+ id: "salesforce",
34
+ options,
35
+ authorizationEndpoint,
36
+ scopes: _scopes,
37
+ state,
38
+ codeVerifier,
39
+ redirectURI: options.redirectURI || redirectURI
40
+ });
41
+ },
42
+ validateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {
43
+ return validateAuthorizationCode({
44
+ code,
45
+ codeVerifier,
46
+ redirectURI: options.redirectURI || redirectURI,
47
+ options,
48
+ tokenEndpoint
49
+ });
50
+ },
51
+ refreshAccessToken: options.refreshAccessToken ? options.refreshAccessToken : async (refreshToken) => {
52
+ return refreshAccessToken({
53
+ refreshToken,
54
+ options: {
55
+ clientId: options.clientId,
56
+ clientSecret: options.clientSecret
57
+ },
58
+ tokenEndpoint
59
+ });
60
+ },
61
+ async getUserInfo(token) {
62
+ if (options.getUserInfo) return options.getUserInfo(token);
63
+ try {
64
+ const { data: user } = await betterFetch(userInfoEndpoint, { headers: { Authorization: `Bearer ${token.accessToken}` } });
65
+ if (!user) {
66
+ logger.error("Failed to fetch user info from Salesforce");
67
+ return null;
68
+ }
69
+ const userMap = await options.mapProfileToUser?.(user);
70
+ return {
71
+ user: {
72
+ id: user.user_id,
73
+ name: user.name,
74
+ email: user.email,
75
+ image: user.photos?.picture || user.photos?.thumbnail,
76
+ emailVerified: user.email_verified ?? false,
77
+ ...userMap
78
+ },
79
+ data: user
80
+ };
81
+ } catch (error) {
82
+ logger.error("Failed to fetch user info from Salesforce:", error);
83
+ return null;
84
+ }
85
+ },
86
+ options
87
+ };
88
+ };
89
+
90
+ //#endregion
91
+ export { salesforce };
@@ -0,0 +1,85 @@
1
+ import { OAuth2Tokens, ProviderOptions } from "../oauth2/oauth-provider.mjs";
2
+ import "../oauth2/index.mjs";
3
+
4
+ //#region src/social-providers/slack.d.ts
5
+ interface SlackProfile extends Record<string, any> {
6
+ ok: boolean;
7
+ sub: string;
8
+ "https://slack.com/user_id": string;
9
+ "https://slack.com/team_id": string;
10
+ email: string;
11
+ email_verified: boolean;
12
+ date_email_verified: number;
13
+ name: string;
14
+ picture: string;
15
+ given_name: string;
16
+ family_name: string;
17
+ locale: string;
18
+ "https://slack.com/team_name": string;
19
+ "https://slack.com/team_domain": string;
20
+ "https://slack.com/user_image_24": string;
21
+ "https://slack.com/user_image_32": string;
22
+ "https://slack.com/user_image_48": string;
23
+ "https://slack.com/user_image_72": string;
24
+ "https://slack.com/user_image_192": string;
25
+ "https://slack.com/user_image_512": string;
26
+ "https://slack.com/team_image_34": string;
27
+ "https://slack.com/team_image_44": string;
28
+ "https://slack.com/team_image_68": string;
29
+ "https://slack.com/team_image_88": string;
30
+ "https://slack.com/team_image_102": string;
31
+ "https://slack.com/team_image_132": string;
32
+ "https://slack.com/team_image_230": string;
33
+ "https://slack.com/team_image_default": boolean;
34
+ }
35
+ interface SlackOptions extends ProviderOptions<SlackProfile> {
36
+ clientId: string;
37
+ }
38
+ declare const slack: (options: SlackOptions) => {
39
+ id: "slack";
40
+ name: string;
41
+ createAuthorizationURL({
42
+ state,
43
+ scopes,
44
+ redirectURI
45
+ }: {
46
+ state: string;
47
+ codeVerifier: string;
48
+ scopes?: string[] | undefined;
49
+ redirectURI: string;
50
+ display?: string | undefined;
51
+ loginHint?: string | undefined;
52
+ }): URL;
53
+ validateAuthorizationCode: ({
54
+ code,
55
+ redirectURI
56
+ }: {
57
+ code: string;
58
+ redirectURI: string;
59
+ codeVerifier?: string | undefined;
60
+ deviceId?: string | undefined;
61
+ }) => Promise<OAuth2Tokens>;
62
+ refreshAccessToken: (refreshToken: string) => Promise<OAuth2Tokens>;
63
+ getUserInfo(token: OAuth2Tokens & {
64
+ user?: {
65
+ name?: {
66
+ firstName?: string;
67
+ lastName?: string;
68
+ };
69
+ email?: string;
70
+ } | undefined;
71
+ }): Promise<{
72
+ user: {
73
+ id: string;
74
+ name?: string;
75
+ email?: string | null;
76
+ image?: string;
77
+ emailVerified: boolean;
78
+ [key: string]: any;
79
+ };
80
+ data: any;
81
+ } | null>;
82
+ options: SlackOptions;
83
+ };
84
+ //#endregion
85
+ export { SlackOptions, SlackProfile, slack };
@@ -0,0 +1,68 @@
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/slack.ts
7
+ const slack = (options) => {
8
+ return {
9
+ id: "slack",
10
+ name: "Slack",
11
+ createAuthorizationURL({ state, scopes, redirectURI }) {
12
+ const _scopes = options.disableDefaultScope ? [] : [
13
+ "openid",
14
+ "profile",
15
+ "email"
16
+ ];
17
+ if (scopes) _scopes.push(...scopes);
18
+ if (options.scope) _scopes.push(...options.scope);
19
+ const url = new URL("https://slack.com/openid/connect/authorize");
20
+ url.searchParams.set("scope", _scopes.join(" "));
21
+ url.searchParams.set("response_type", "code");
22
+ url.searchParams.set("client_id", options.clientId);
23
+ url.searchParams.set("redirect_uri", options.redirectURI || redirectURI);
24
+ url.searchParams.set("state", state);
25
+ return url;
26
+ },
27
+ validateAuthorizationCode: async ({ code, redirectURI }) => {
28
+ return validateAuthorizationCode({
29
+ code,
30
+ redirectURI,
31
+ options,
32
+ tokenEndpoint: "https://slack.com/api/openid.connect.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://slack.com/api/openid.connect.token"
44
+ });
45
+ },
46
+ async getUserInfo(token) {
47
+ if (options.getUserInfo) return options.getUserInfo(token);
48
+ const { data: profile, error } = await betterFetch("https://slack.com/api/openid.connect.userInfo", { headers: { authorization: `Bearer ${token.accessToken}` } });
49
+ if (error) return null;
50
+ const userMap = await options.mapProfileToUser?.(profile);
51
+ return {
52
+ user: {
53
+ id: profile["https://slack.com/user_id"],
54
+ name: profile.name || "",
55
+ email: profile.email,
56
+ emailVerified: profile.email_verified,
57
+ image: profile.picture || profile["https://slack.com/user_image_512"],
58
+ ...userMap
59
+ },
60
+ data: profile
61
+ };
62
+ },
63
+ options
64
+ };
65
+ };
66
+
67
+ //#endregion
68
+ export { slack };