@better-auth/core 1.5.6 → 1.5.7-beta.1

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 (169) hide show
  1. package/dist/api/index.d.mts +41 -11
  2. package/dist/api/index.mjs +1 -2
  3. package/dist/api/index.mjs.map +1 -1
  4. package/dist/async_hooks/index.mjs +1 -1
  5. package/dist/async_hooks/pure.index.mjs +1 -1
  6. package/dist/async_hooks/pure.index.mjs.map +1 -1
  7. package/dist/context/endpoint-context.d.mts +1 -1
  8. package/dist/context/endpoint-context.mjs +1 -2
  9. package/dist/context/endpoint-context.mjs.map +1 -1
  10. package/dist/context/global.mjs +2 -2
  11. package/dist/context/global.mjs.map +1 -1
  12. package/dist/context/index.mjs +1 -2
  13. package/dist/context/request-state.mjs +1 -2
  14. package/dist/context/request-state.mjs.map +1 -1
  15. package/dist/context/transaction.mjs +1 -2
  16. package/dist/context/transaction.mjs.map +1 -1
  17. package/dist/db/adapter/factory.mjs +1 -2
  18. package/dist/db/adapter/factory.mjs.map +1 -1
  19. package/dist/db/adapter/get-default-field-name.mjs +1 -2
  20. package/dist/db/adapter/get-default-field-name.mjs.map +1 -1
  21. package/dist/db/adapter/get-default-model-name.mjs +1 -2
  22. package/dist/db/adapter/get-default-model-name.mjs.map +1 -1
  23. package/dist/db/adapter/get-field-attributes.mjs +1 -2
  24. package/dist/db/adapter/get-field-attributes.mjs.map +1 -1
  25. package/dist/db/adapter/get-field-name.mjs +1 -2
  26. package/dist/db/adapter/get-field-name.mjs.map +1 -1
  27. package/dist/db/adapter/get-id-field.mjs +1 -2
  28. package/dist/db/adapter/get-id-field.mjs.map +1 -1
  29. package/dist/db/adapter/get-model-name.mjs +1 -2
  30. package/dist/db/adapter/get-model-name.mjs.map +1 -1
  31. package/dist/db/adapter/index.mjs +1 -2
  32. package/dist/db/adapter/index.mjs.map +1 -1
  33. package/dist/db/adapter/utils.mjs +1 -1
  34. package/dist/db/adapter/utils.mjs.map +1 -1
  35. package/dist/db/get-tables.mjs +1 -1
  36. package/dist/db/index.mjs +1 -2
  37. package/dist/db/schema/account.mjs +1 -2
  38. package/dist/db/schema/account.mjs.map +1 -1
  39. package/dist/db/schema/rate-limit.mjs +1 -2
  40. package/dist/db/schema/rate-limit.mjs.map +1 -1
  41. package/dist/db/schema/session.mjs +1 -2
  42. package/dist/db/schema/session.mjs.map +1 -1
  43. package/dist/db/schema/shared.mjs +1 -2
  44. package/dist/db/schema/shared.mjs.map +1 -1
  45. package/dist/db/schema/user.mjs +1 -2
  46. package/dist/db/schema/user.mjs.map +1 -1
  47. package/dist/db/schema/verification.mjs +1 -2
  48. package/dist/db/schema/verification.mjs.map +1 -1
  49. package/dist/env/color-depth.mjs +1 -2
  50. package/dist/env/color-depth.mjs.map +1 -1
  51. package/dist/env/env-impl.mjs +1 -1
  52. package/dist/env/env-impl.mjs.map +1 -1
  53. package/dist/env/index.mjs +1 -2
  54. package/dist/env/logger.mjs +1 -2
  55. package/dist/env/logger.mjs.map +1 -1
  56. package/dist/error/codes.mjs +1 -2
  57. package/dist/error/codes.mjs.map +1 -1
  58. package/dist/error/index.mjs +1 -2
  59. package/dist/error/index.mjs.map +1 -1
  60. package/dist/index.mjs +1 -1
  61. package/dist/instrumentation/attributes.mjs +1 -2
  62. package/dist/instrumentation/attributes.mjs.map +1 -1
  63. package/dist/instrumentation/index.mjs +1 -2
  64. package/dist/instrumentation/tracer.mjs +2 -3
  65. package/dist/instrumentation/tracer.mjs.map +1 -1
  66. package/dist/oauth2/client-credentials-token.mjs +1 -2
  67. package/dist/oauth2/client-credentials-token.mjs.map +1 -1
  68. package/dist/oauth2/create-authorization-url.mjs +1 -2
  69. package/dist/oauth2/create-authorization-url.mjs.map +1 -1
  70. package/dist/oauth2/index.mjs +1 -2
  71. package/dist/oauth2/refresh-access-token.mjs +1 -2
  72. package/dist/oauth2/refresh-access-token.mjs.map +1 -1
  73. package/dist/oauth2/utils.mjs +1 -2
  74. package/dist/oauth2/utils.mjs.map +1 -1
  75. package/dist/oauth2/validate-authorization-code.mjs +1 -2
  76. package/dist/oauth2/validate-authorization-code.mjs.map +1 -1
  77. package/dist/oauth2/verify.mjs +1 -2
  78. package/dist/oauth2/verify.mjs.map +1 -1
  79. package/dist/social-providers/apple.mjs +1 -2
  80. package/dist/social-providers/apple.mjs.map +1 -1
  81. package/dist/social-providers/atlassian.mjs +1 -2
  82. package/dist/social-providers/atlassian.mjs.map +1 -1
  83. package/dist/social-providers/cognito.mjs +1 -2
  84. package/dist/social-providers/cognito.mjs.map +1 -1
  85. package/dist/social-providers/discord.mjs +1 -2
  86. package/dist/social-providers/discord.mjs.map +1 -1
  87. package/dist/social-providers/dropbox.mjs +1 -2
  88. package/dist/social-providers/dropbox.mjs.map +1 -1
  89. package/dist/social-providers/facebook.mjs +1 -2
  90. package/dist/social-providers/facebook.mjs.map +1 -1
  91. package/dist/social-providers/figma.mjs +1 -2
  92. package/dist/social-providers/figma.mjs.map +1 -1
  93. package/dist/social-providers/github.mjs +1 -2
  94. package/dist/social-providers/github.mjs.map +1 -1
  95. package/dist/social-providers/gitlab.mjs +1 -2
  96. package/dist/social-providers/gitlab.mjs.map +1 -1
  97. package/dist/social-providers/google.mjs +1 -2
  98. package/dist/social-providers/google.mjs.map +1 -1
  99. package/dist/social-providers/huggingface.mjs +1 -2
  100. package/dist/social-providers/huggingface.mjs.map +1 -1
  101. package/dist/social-providers/index.mjs +1 -2
  102. package/dist/social-providers/index.mjs.map +1 -1
  103. package/dist/social-providers/kakao.mjs +1 -2
  104. package/dist/social-providers/kakao.mjs.map +1 -1
  105. package/dist/social-providers/kick.mjs +1 -2
  106. package/dist/social-providers/kick.mjs.map +1 -1
  107. package/dist/social-providers/line.mjs +1 -2
  108. package/dist/social-providers/line.mjs.map +1 -1
  109. package/dist/social-providers/linear.mjs +1 -2
  110. package/dist/social-providers/linear.mjs.map +1 -1
  111. package/dist/social-providers/linkedin.mjs +1 -2
  112. package/dist/social-providers/linkedin.mjs.map +1 -1
  113. package/dist/social-providers/microsoft-entra-id.mjs +1 -2
  114. package/dist/social-providers/microsoft-entra-id.mjs.map +1 -1
  115. package/dist/social-providers/naver.mjs +1 -2
  116. package/dist/social-providers/naver.mjs.map +1 -1
  117. package/dist/social-providers/notion.mjs +1 -2
  118. package/dist/social-providers/notion.mjs.map +1 -1
  119. package/dist/social-providers/paybin.mjs +1 -2
  120. package/dist/social-providers/paybin.mjs.map +1 -1
  121. package/dist/social-providers/paypal.mjs +1 -2
  122. package/dist/social-providers/paypal.mjs.map +1 -1
  123. package/dist/social-providers/polar.mjs +1 -2
  124. package/dist/social-providers/polar.mjs.map +1 -1
  125. package/dist/social-providers/railway.mjs +1 -2
  126. package/dist/social-providers/railway.mjs.map +1 -1
  127. package/dist/social-providers/reddit.mjs +1 -2
  128. package/dist/social-providers/reddit.mjs.map +1 -1
  129. package/dist/social-providers/roblox.mjs +1 -2
  130. package/dist/social-providers/roblox.mjs.map +1 -1
  131. package/dist/social-providers/salesforce.mjs +1 -2
  132. package/dist/social-providers/salesforce.mjs.map +1 -1
  133. package/dist/social-providers/slack.mjs +1 -2
  134. package/dist/social-providers/slack.mjs.map +1 -1
  135. package/dist/social-providers/spotify.mjs +1 -2
  136. package/dist/social-providers/spotify.mjs.map +1 -1
  137. package/dist/social-providers/tiktok.mjs +1 -2
  138. package/dist/social-providers/tiktok.mjs.map +1 -1
  139. package/dist/social-providers/twitch.mjs +1 -2
  140. package/dist/social-providers/twitch.mjs.map +1 -1
  141. package/dist/social-providers/twitter.mjs +1 -2
  142. package/dist/social-providers/twitter.mjs.map +1 -1
  143. package/dist/social-providers/vercel.mjs +1 -2
  144. package/dist/social-providers/vercel.mjs.map +1 -1
  145. package/dist/social-providers/vk.mjs +1 -2
  146. package/dist/social-providers/vk.mjs.map +1 -1
  147. package/dist/social-providers/wechat.mjs +1 -2
  148. package/dist/social-providers/wechat.mjs.map +1 -1
  149. package/dist/social-providers/zoom.mjs +1 -2
  150. package/dist/social-providers/zoom.mjs.map +1 -1
  151. package/dist/types/context.d.mts +1 -3
  152. package/dist/types/plugin.d.mts +4 -1
  153. package/dist/utils/db.mjs +1 -1
  154. package/dist/utils/deprecate.mjs +1 -1
  155. package/dist/utils/error-codes.mjs +1 -1
  156. package/dist/utils/fetch-metadata.mjs +1 -1
  157. package/dist/utils/id.mjs +1 -2
  158. package/dist/utils/id.mjs.map +1 -1
  159. package/dist/utils/ip.mjs +1 -2
  160. package/dist/utils/ip.mjs.map +1 -1
  161. package/dist/utils/json.mjs +1 -2
  162. package/dist/utils/json.mjs.map +1 -1
  163. package/dist/utils/string.mjs +1 -1
  164. package/dist/utils/url.mjs +1 -1
  165. package/package.json +5 -5
  166. package/src/api/index.ts +151 -41
  167. package/src/context/endpoint-context.ts +2 -1
  168. package/src/types/context.ts +1 -3
  169. package/src/types/plugin.ts +14 -1
@@ -1 +1 @@
1
- {"version":3,"file":"microsoft-entra-id.mjs","names":[],"sources":["../../src/social-providers/microsoft-entra-id.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { logger } from \"../env\";\nimport { APIError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\n/**\n * @see [Microsoft Identity Platform - Optional claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference)\n */\nexport interface MicrosoftEntraIDProfile extends Record<string, any> {\n\t/** Identifies the intended recipient of the token */\n\taud: string;\n\t/** Identifies the issuer, or \"authorization server\" that constructs and returns the token */\n\tiss: string;\n\t/** Indicates when the authentication for the token occurred */\n\tiat: Date;\n\t/** Records the identity provider that authenticated the subject of the token */\n\tidp: string;\n\t/** Identifies the time before which the JWT can't be accepted for processing */\n\tnbf: Date;\n\t/** Identifies the expiration time on or after which the JWT can't be accepted for processing */\n\texp: Date;\n\t/** Code hash included in ID tokens when issued with an OAuth 2.0 authorization code */\n\tc_hash: string;\n\t/** Access token hash included in ID tokens when issued with an OAuth 2.0 access token */\n\tat_hash: string;\n\t/** Internal claim used to record data for token reuse */\n\taio: string;\n\t/** The primary username that represents the user */\n\tpreferred_username: string;\n\t/** User's email address */\n\temail: string;\n\t/** Human-readable value that identifies the subject of the token */\n\tname: string;\n\t/** Matches the parameter included in the original authorize request */\n\tnonce: string;\n\t/** User's profile picture */\n\tpicture: string;\n\t/** Immutable identifier for the user account */\n\toid: string;\n\t/** Set of roles assigned to the user */\n\troles: string[];\n\t/** Internal claim used to revalidate tokens */\n\trh: string;\n\t/** Subject identifier - unique to application ID */\n\tsub: string;\n\t/** Tenant ID the user is signing in to */\n\ttid: string;\n\t/** Unique identifier for a session */\n\tsid: string;\n\t/** Token identifier claim */\n\tuti: string;\n\t/** Indicates if user is in at least one group */\n\thasgroups: boolean;\n\t/** User account status in tenant (0 = member, 1 = guest) */\n\tacct: 0 | 1;\n\t/** Auth Context IDs */\n\tacrs: string;\n\t/** Time when the user last authenticated */\n\tauth_time: Date;\n\t/** User's country/region */\n\tctry: string;\n\t/** IP address of requesting client when inside VNET */\n\tfwd: string;\n\t/** Group claims */\n\tgroups: string;\n\t/** Login hint for SSO */\n\tlogin_hint: string;\n\t/** Resource tenant's country/region */\n\ttenant_ctry: string;\n\t/** Region of the resource tenant */\n\ttenant_region_scope: string;\n\t/** UserPrincipalName */\n\tupn: string;\n\t/** User's verified primary email addresses */\n\tverified_primary_email: string[];\n\t/** User's verified secondary email addresses */\n\tverified_secondary_email: string[];\n\t/** Whether the user's email is verified (optional claim, must be configured in app registration) */\n\temail_verified?: boolean | undefined;\n\t/** VNET specifier information */\n\tvnet: string;\n\t/** Client Capabilities */\n\txms_cc: string;\n\t/** Whether user's email domain is verified */\n\txms_edov: boolean;\n\t/** Preferred data location for Multi-Geo tenants */\n\txms_pdl: string;\n\t/** User preferred language */\n\txms_pl: string;\n\t/** Tenant preferred language */\n\txms_tpl: string;\n\t/** Zero-touch Deployment ID */\n\tztdid: string;\n\t/** IP Address */\n\tipaddr: string;\n\t/** On-premises Security Identifier */\n\tonprem_sid: string;\n\t/** Password Expiration Time */\n\tpwd_exp: number;\n\t/** Change Password URL */\n\tpwd_url: string;\n\t/** Inside Corporate Network flag */\n\tin_corp: string;\n\t/** User's family name/surname */\n\tfamily_name: string;\n\t/** User's given/first name */\n\tgiven_name: string;\n}\n\nexport interface MicrosoftOptions\n\textends ProviderOptions<MicrosoftEntraIDProfile> {\n\tclientId: string;\n\t/**\n\t * The tenant ID of the Microsoft account\n\t * @default \"common\"\n\t */\n\ttenantId?: string | undefined;\n\t/**\n\t * The authentication authority URL. Use the default \"https://login.microsoftonline.com\" for standard Entra ID or \"https://<tenant-id>.ciamlogin.com\" for CIAM scenarios.\n\t * @default \"https://login.microsoftonline.com\"\n\t */\n\tauthority?: string | undefined;\n\t/**\n\t * The size of the profile photo\n\t * @default 48\n\t */\n\tprofilePhotoSize?:\n\t\t| (48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648)\n\t\t| undefined;\n\t/**\n\t * Disable profile photo\n\t */\n\tdisableProfilePhoto?: boolean | undefined;\n}\n\nexport const microsoft = (options: MicrosoftOptions) => {\n\tconst tenant = options.tenantId || \"common\";\n\tconst authority = options.authority || \"https://login.microsoftonline.com\";\n\tconst authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;\n\tconst tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;\n\treturn {\n\t\tid: \"microsoft\",\n\t\tname: \"Microsoft EntraID\",\n\t\tcreateAuthorizationURL(data) {\n\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\tif (options.scope) scopes.push(...options.scope);\n\t\t\tif (data.scopes) scopes.push(...data.scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"microsoft\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tstate: data.state,\n\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\tscopes,\n\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t\tloginHint: data.loginHint,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode({ code, codeVerifier, redirectURI }) {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { kid, alg: jwtAlg } = decodeProtectedHeader(token);\n\t\t\t\tif (!kid || !jwtAlg) return false;\n\n\t\t\t\tconst publicKey = await getMicrosoftPublicKey(kid, tenant, authority);\n\t\t\t\tconst verifyOptions: {\n\t\t\t\t\talgorithms: [string];\n\t\t\t\t\taudience: string;\n\t\t\t\t\tmaxTokenAge: string;\n\t\t\t\t\tissuer?: string;\n\t\t\t\t} = {\n\t\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\t\taudience: options.clientId,\n\t\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t\t};\n\t\t\t\t/**\n\t\t\t\t * Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.\n\t\t\t\t * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints\n\t\t\t\t */\n\t\t\t\tif (\n\t\t\t\t\ttenant !== \"common\" &&\n\t\t\t\t\ttenant !== \"organizations\" &&\n\t\t\t\t\ttenant !== \"consumers\"\n\t\t\t\t) {\n\t\t\t\t\tverifyOptions.issuer = `${authority}/${tenant}/v2.0`;\n\t\t\t\t}\n\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(\n\t\t\t\t\ttoken,\n\t\t\t\t\tpublicKey,\n\t\t\t\t\tverifyOptions,\n\t\t\t\t);\n\n\t\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to verify ID token:\", error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst user = decodeJwt(token.idToken) as MicrosoftEntraIDProfile;\n\t\t\tconst profilePhotoSize = options.profilePhotoSize || 48;\n\t\t\tawait betterFetch<ArrayBuffer>(\n\t\t\t\t`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t\tasync onResponse(context) {\n\t\t\t\t\t\tif (options.disableProfilePhoto || !context.response.ok) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst response = context.response.clone();\n\t\t\t\t\t\t\tconst pictureBuffer = await response.arrayBuffer();\n\t\t\t\t\t\t\tconst pictureBase64 = base64.encode(pictureBuffer);\n\t\t\t\t\t\t\tuser.picture = `data:image/jpeg;base64, ${pictureBase64}`;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\te && typeof e === \"object\" && \"name\" in e\n\t\t\t\t\t\t\t\t\t? (e.name as string)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\te,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\t\t\t// Microsoft Entra ID does NOT include email_verified claim by default.\n\t\t\t// It must be configured as an optional claim in the app registration.\n\t\t\t// We default to false when not provided for security consistency.\n\t\t\t// We can also check verified_primary_email/verified_secondary_email arrays as fallback.\n\t\t\tconst emailVerified =\n\t\t\t\tuser.email_verified !== undefined\n\t\t\t\t\t? user.email_verified\n\t\t\t\t\t: user.email &&\n\t\t\t\t\t\t\t(user.verified_primary_email?.includes(user.email) ||\n\t\t\t\t\t\t\t\tuser.verified_secondary_email?.includes(user.email))\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false;\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: user.sub,\n\t\t\t\t\tname: user.name,\n\t\t\t\t\temail: user.email,\n\t\t\t\t\timage: user.picture,\n\t\t\t\t\temailVerified,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: user,\n\t\t\t};\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\t\t\tif (options.scope) scopes.push(...options.scope);\n\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\textraParams: {\n\t\t\t\t\t\t\tscope: scopes.join(\" \"), // Include the scopes in request to microsoft\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider;\n};\n\nexport const getMicrosoftPublicKey = async (\n\tkid: string,\n\ttenant: string,\n\tauthority: string,\n) => {\n\tconst { data } = await betterFetch<{\n\t\tkeys: Array<{\n\t\t\tkid: string;\n\t\t\talg: string;\n\t\t\tkty: string;\n\t\t\tuse: string;\n\t\t\tn: string;\n\t\t\te: string;\n\t\t\tx5c?: string[];\n\t\t\tx5t?: string;\n\t\t}>;\n\t}>(`${authority}/${tenant}/discovery/v2.0/keys`);\n\n\tif (!data?.keys) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Keys not found\",\n\t\t});\n\t}\n\n\tconst jwk = data.keys.find((key) => key.kid === kid);\n\tif (!jwk) {\n\t\tthrow new Error(`JWK with kid ${kid} not found`);\n\t}\n\n\treturn await importJWK(jwk, jwk.alg);\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"microsoft-entra-id.mjs","names":[],"sources":["../../src/social-providers/microsoft-entra-id.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt, decodeProtectedHeader, importJWK, jwtVerify } from \"jose\";\nimport { logger } from \"../env\";\nimport { APIError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\n/**\n * @see [Microsoft Identity Platform - Optional claims reference](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims-reference)\n */\nexport interface MicrosoftEntraIDProfile extends Record<string, any> {\n\t/** Identifies the intended recipient of the token */\n\taud: string;\n\t/** Identifies the issuer, or \"authorization server\" that constructs and returns the token */\n\tiss: string;\n\t/** Indicates when the authentication for the token occurred */\n\tiat: Date;\n\t/** Records the identity provider that authenticated the subject of the token */\n\tidp: string;\n\t/** Identifies the time before which the JWT can't be accepted for processing */\n\tnbf: Date;\n\t/** Identifies the expiration time on or after which the JWT can't be accepted for processing */\n\texp: Date;\n\t/** Code hash included in ID tokens when issued with an OAuth 2.0 authorization code */\n\tc_hash: string;\n\t/** Access token hash included in ID tokens when issued with an OAuth 2.0 access token */\n\tat_hash: string;\n\t/** Internal claim used to record data for token reuse */\n\taio: string;\n\t/** The primary username that represents the user */\n\tpreferred_username: string;\n\t/** User's email address */\n\temail: string;\n\t/** Human-readable value that identifies the subject of the token */\n\tname: string;\n\t/** Matches the parameter included in the original authorize request */\n\tnonce: string;\n\t/** User's profile picture */\n\tpicture: string;\n\t/** Immutable identifier for the user account */\n\toid: string;\n\t/** Set of roles assigned to the user */\n\troles: string[];\n\t/** Internal claim used to revalidate tokens */\n\trh: string;\n\t/** Subject identifier - unique to application ID */\n\tsub: string;\n\t/** Tenant ID the user is signing in to */\n\ttid: string;\n\t/** Unique identifier for a session */\n\tsid: string;\n\t/** Token identifier claim */\n\tuti: string;\n\t/** Indicates if user is in at least one group */\n\thasgroups: boolean;\n\t/** User account status in tenant (0 = member, 1 = guest) */\n\tacct: 0 | 1;\n\t/** Auth Context IDs */\n\tacrs: string;\n\t/** Time when the user last authenticated */\n\tauth_time: Date;\n\t/** User's country/region */\n\tctry: string;\n\t/** IP address of requesting client when inside VNET */\n\tfwd: string;\n\t/** Group claims */\n\tgroups: string;\n\t/** Login hint for SSO */\n\tlogin_hint: string;\n\t/** Resource tenant's country/region */\n\ttenant_ctry: string;\n\t/** Region of the resource tenant */\n\ttenant_region_scope: string;\n\t/** UserPrincipalName */\n\tupn: string;\n\t/** User's verified primary email addresses */\n\tverified_primary_email: string[];\n\t/** User's verified secondary email addresses */\n\tverified_secondary_email: string[];\n\t/** Whether the user's email is verified (optional claim, must be configured in app registration) */\n\temail_verified?: boolean | undefined;\n\t/** VNET specifier information */\n\tvnet: string;\n\t/** Client Capabilities */\n\txms_cc: string;\n\t/** Whether user's email domain is verified */\n\txms_edov: boolean;\n\t/** Preferred data location for Multi-Geo tenants */\n\txms_pdl: string;\n\t/** User preferred language */\n\txms_pl: string;\n\t/** Tenant preferred language */\n\txms_tpl: string;\n\t/** Zero-touch Deployment ID */\n\tztdid: string;\n\t/** IP Address */\n\tipaddr: string;\n\t/** On-premises Security Identifier */\n\tonprem_sid: string;\n\t/** Password Expiration Time */\n\tpwd_exp: number;\n\t/** Change Password URL */\n\tpwd_url: string;\n\t/** Inside Corporate Network flag */\n\tin_corp: string;\n\t/** User's family name/surname */\n\tfamily_name: string;\n\t/** User's given/first name */\n\tgiven_name: string;\n}\n\nexport interface MicrosoftOptions\n\textends ProviderOptions<MicrosoftEntraIDProfile> {\n\tclientId: string;\n\t/**\n\t * The tenant ID of the Microsoft account\n\t * @default \"common\"\n\t */\n\ttenantId?: string | undefined;\n\t/**\n\t * The authentication authority URL. Use the default \"https://login.microsoftonline.com\" for standard Entra ID or \"https://<tenant-id>.ciamlogin.com\" for CIAM scenarios.\n\t * @default \"https://login.microsoftonline.com\"\n\t */\n\tauthority?: string | undefined;\n\t/**\n\t * The size of the profile photo\n\t * @default 48\n\t */\n\tprofilePhotoSize?:\n\t\t| (48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648)\n\t\t| undefined;\n\t/**\n\t * Disable profile photo\n\t */\n\tdisableProfilePhoto?: boolean | undefined;\n}\n\nexport const microsoft = (options: MicrosoftOptions) => {\n\tconst tenant = options.tenantId || \"common\";\n\tconst authority = options.authority || \"https://login.microsoftonline.com\";\n\tconst authorizationEndpoint = `${authority}/${tenant}/oauth2/v2.0/authorize`;\n\tconst tokenEndpoint = `${authority}/${tenant}/oauth2/v2.0/token`;\n\treturn {\n\t\tid: \"microsoft\",\n\t\tname: \"Microsoft EntraID\",\n\t\tcreateAuthorizationURL(data) {\n\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\tif (options.scope) scopes.push(...options.scope);\n\t\t\tif (data.scopes) scopes.push(...data.scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"microsoft\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tstate: data.state,\n\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\tscopes,\n\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t\tloginHint: data.loginHint,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode({ code, codeVerifier, redirectURI }) {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { kid, alg: jwtAlg } = decodeProtectedHeader(token);\n\t\t\t\tif (!kid || !jwtAlg) return false;\n\n\t\t\t\tconst publicKey = await getMicrosoftPublicKey(kid, tenant, authority);\n\t\t\t\tconst verifyOptions: {\n\t\t\t\t\talgorithms: [string];\n\t\t\t\t\taudience: string;\n\t\t\t\t\tmaxTokenAge: string;\n\t\t\t\t\tissuer?: string;\n\t\t\t\t} = {\n\t\t\t\t\talgorithms: [jwtAlg],\n\t\t\t\t\taudience: options.clientId,\n\t\t\t\t\tmaxTokenAge: \"1h\",\n\t\t\t\t};\n\t\t\t\t/**\n\t\t\t\t * Issuer varies per user's tenant for multi-tenant endpoints, so only validate for specific tenants.\n\t\t\t\t * @see https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols#endpoints\n\t\t\t\t */\n\t\t\t\tif (\n\t\t\t\t\ttenant !== \"common\" &&\n\t\t\t\t\ttenant !== \"organizations\" &&\n\t\t\t\t\ttenant !== \"consumers\"\n\t\t\t\t) {\n\t\t\t\t\tverifyOptions.issuer = `${authority}/${tenant}/v2.0`;\n\t\t\t\t}\n\t\t\t\tconst { payload: jwtClaims } = await jwtVerify(\n\t\t\t\t\ttoken,\n\t\t\t\t\tpublicKey,\n\t\t\t\t\tverifyOptions,\n\t\t\t\t);\n\n\t\t\t\tif (nonce && jwtClaims.nonce !== nonce) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to verify ID token:\", error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst user = decodeJwt(token.idToken) as MicrosoftEntraIDProfile;\n\t\t\tconst profilePhotoSize = options.profilePhotoSize || 48;\n\t\t\tawait betterFetch<ArrayBuffer>(\n\t\t\t\t`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t\tasync onResponse(context) {\n\t\t\t\t\t\tif (options.disableProfilePhoto || !context.response.ok) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst response = context.response.clone();\n\t\t\t\t\t\t\tconst pictureBuffer = await response.arrayBuffer();\n\t\t\t\t\t\t\tconst pictureBase64 = base64.encode(pictureBuffer);\n\t\t\t\t\t\t\tuser.picture = `data:image/jpeg;base64, ${pictureBase64}`;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\te && typeof e === \"object\" && \"name\" in e\n\t\t\t\t\t\t\t\t\t? (e.name as string)\n\t\t\t\t\t\t\t\t\t: \"\",\n\t\t\t\t\t\t\t\te,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\t\t\t// Microsoft Entra ID does NOT include email_verified claim by default.\n\t\t\t// It must be configured as an optional claim in the app registration.\n\t\t\t// We default to false when not provided for security consistency.\n\t\t\t// We can also check verified_primary_email/verified_secondary_email arrays as fallback.\n\t\t\tconst emailVerified =\n\t\t\t\tuser.email_verified !== undefined\n\t\t\t\t\t? user.email_verified\n\t\t\t\t\t: user.email &&\n\t\t\t\t\t\t\t(user.verified_primary_email?.includes(user.email) ||\n\t\t\t\t\t\t\t\tuser.verified_secondary_email?.includes(user.email))\n\t\t\t\t\t\t? true\n\t\t\t\t\t\t: false;\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: user.sub,\n\t\t\t\t\tname: user.name,\n\t\t\t\t\temail: user.email,\n\t\t\t\t\timage: user.picture,\n\t\t\t\t\temailVerified,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: user,\n\t\t\t};\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\tconst scopes = options.disableDefaultScope\n\t\t\t\t\t\t? []\n\t\t\t\t\t\t: [\"openid\", \"profile\", \"email\", \"User.Read\", \"offline_access\"];\n\t\t\t\t\tif (options.scope) scopes.push(...options.scope);\n\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\textraParams: {\n\t\t\t\t\t\t\tscope: scopes.join(\" \"), // Include the scopes in request to microsoft\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider;\n};\n\nexport const getMicrosoftPublicKey = async (\n\tkid: string,\n\ttenant: string,\n\tauthority: string,\n) => {\n\tconst { data } = await betterFetch<{\n\t\tkeys: Array<{\n\t\t\tkid: string;\n\t\t\talg: string;\n\t\t\tkty: string;\n\t\t\tuse: string;\n\t\t\tn: string;\n\t\t\te: string;\n\t\t\tx5c?: string[];\n\t\t\tx5t?: string;\n\t\t}>;\n\t}>(`${authority}/${tenant}/discovery/v2.0/keys`);\n\n\tif (!data?.keys) {\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"Keys not found\",\n\t\t});\n\t}\n\n\tconst jwk = data.keys.find((key) => key.kid === kid);\n\tif (!jwk) {\n\t\tthrow new Error(`JWK with kid ${kid} not found`);\n\t}\n\n\treturn await importJWK(jwk, jwk.alg);\n};\n"],"mappings":"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"}
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
3
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
4
  import "../oauth2/index.mjs";
5
5
  import { betterFetch } from "@better-fetch/fetch";
6
-
7
6
  //#region src/social-providers/naver.ts
8
7
  const naver = (options) => {
9
8
  const tokenEndpoint = "https://nid.naver.com/oauth2.0/token";
@@ -63,7 +62,7 @@ const naver = (options) => {
63
62
  options
64
63
  };
65
64
  };
66
-
67
65
  //#endregion
68
66
  export { naver };
67
+
69
68
  //# sourceMappingURL=naver.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"naver.mjs","names":[],"sources":["../../src/social-providers/naver.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface NaverProfile {\n\t/** API response result code */\n\tresultcode: string;\n\t/** API response message */\n\tmessage: string;\n\tresponse: {\n\t\t/** Unique Naver user identifier */\n\t\tid: string;\n\t\t/** User nickname */\n\t\tnickname: string;\n\t\t/** User real name */\n\t\tname: string;\n\t\t/** User email address */\n\t\temail: string;\n\t\t/** Gender (F: female, M: male, U: unknown) */\n\t\tgender: string;\n\t\t/** Age range */\n\t\tage: string;\n\t\t/** Birthday (MM-DD format) */\n\t\tbirthday: string;\n\t\t/** Birth year */\n\t\tbirthyear: string;\n\t\t/** Profile image URL */\n\t\tprofile_image: string;\n\t\t/** Mobile phone number */\n\t\tmobile: string;\n\t};\n}\n\nexport interface NaverOptions extends ProviderOptions<NaverProfile> {\n\tclientId: string;\n}\n\nexport const naver = (options: NaverOptions) => {\n\tconst tokenEndpoint = \"https://nid.naver.com/oauth2.0/token\";\n\treturn {\n\t\tid: \"naver\",\n\t\tname: \"Naver\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"profile\", \"email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"naver\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://nid.naver.com/oauth2.0/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<NaverProfile>(\n\t\t\t\t\"https://openapi.naver.com/v1/nid/me\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error || !profile || profile.resultcode !== \"00\") {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\tconst res = profile.response || {};\n\t\t\tconst user = {\n\t\t\t\tid: res.id,\n\t\t\t\tname: res.name || res.nickname || \"\",\n\t\t\t\temail: res.email,\n\t\t\t\timage: res.profile_image,\n\t\t\t\temailVerified: false,\n\t\t\t\t...userMap,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tuser,\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<NaverProfile>;\n};\n"],"mappings":";;;;;;;AAyCA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,WAAW,QAAQ;AACvE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,uCACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AACD,OAAI,SAAS,CAAC,WAAW,QAAQ,eAAe,KAC/C,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;GACzD,MAAM,MAAM,QAAQ,YAAY,EAAE;AASlC,UAAO;IACN,MATY;KACZ,IAAI,IAAI;KACR,MAAM,IAAI,QAAQ,IAAI,YAAY;KAClC,OAAO,IAAI;KACX,OAAO,IAAI;KACX,eAAe;KACf,GAAG;KACH;IAGA,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"naver.mjs","names":[],"sources":["../../src/social-providers/naver.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface NaverProfile {\n\t/** API response result code */\n\tresultcode: string;\n\t/** API response message */\n\tmessage: string;\n\tresponse: {\n\t\t/** Unique Naver user identifier */\n\t\tid: string;\n\t\t/** User nickname */\n\t\tnickname: string;\n\t\t/** User real name */\n\t\tname: string;\n\t\t/** User email address */\n\t\temail: string;\n\t\t/** Gender (F: female, M: male, U: unknown) */\n\t\tgender: string;\n\t\t/** Age range */\n\t\tage: string;\n\t\t/** Birthday (MM-DD format) */\n\t\tbirthday: string;\n\t\t/** Birth year */\n\t\tbirthyear: string;\n\t\t/** Profile image URL */\n\t\tprofile_image: string;\n\t\t/** Mobile phone number */\n\t\tmobile: string;\n\t};\n}\n\nexport interface NaverOptions extends ProviderOptions<NaverProfile> {\n\tclientId: string;\n}\n\nexport const naver = (options: NaverOptions) => {\n\tconst tokenEndpoint = \"https://nid.naver.com/oauth2.0/token\";\n\treturn {\n\t\tid: \"naver\",\n\t\tname: \"Naver\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"profile\", \"email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"naver\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://nid.naver.com/oauth2.0/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<NaverProfile>(\n\t\t\t\t\"https://openapi.naver.com/v1/nid/me\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error || !profile || profile.resultcode !== \"00\") {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\tconst res = profile.response || {};\n\t\t\tconst user = {\n\t\t\t\tid: res.id,\n\t\t\t\tname: res.name || res.nickname || \"\",\n\t\t\t\temail: res.email,\n\t\t\t\timage: res.profile_image,\n\t\t\t\temailVerified: false,\n\t\t\t\t...userMap,\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tuser,\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<NaverProfile>;\n};\n"],"mappings":";;;;;;AAyCA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,WAAW,QAAQ;AACvE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,uCACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AACD,OAAI,SAAS,CAAC,WAAW,QAAQ,eAAe,KAC/C,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;GACzD,MAAM,MAAM,QAAQ,YAAY,EAAE;AASlC,UAAO;IACN,MATY;KACZ,IAAI,IAAI;KACR,MAAM,IAAI,QAAQ,IAAI,YAAY;KAClC,OAAO,IAAI;KACX,OAAO,IAAI;KACX,eAAe;KACf,GAAG;KACH;IAGA,MAAM;IACN;;EAEF;EACA"}
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
3
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
4
  import "../oauth2/index.mjs";
5
5
  import { betterFetch } from "@better-fetch/fetch";
6
-
7
6
  //#region src/social-providers/notion.ts
8
7
  const notion = (options) => {
9
8
  const tokenEndpoint = "https://api.notion.com/v1/oauth/token";
@@ -70,7 +69,7 @@ const notion = (options) => {
70
69
  options
71
70
  };
72
71
  };
73
-
74
72
  //#endregion
75
73
  export { notion };
74
+
76
75
  //# sourceMappingURL=notion.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"notion.mjs","names":[],"sources":["../../src/social-providers/notion.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface NotionProfile {\n\tobject: \"user\";\n\tid: string;\n\ttype: \"person\" | \"bot\";\n\tname?: string | undefined;\n\tavatar_url?: string | undefined;\n\tperson?:\n\t\t| {\n\t\t\t\temail?: string;\n\t\t }\n\t\t| undefined;\n}\n\nexport interface NotionOptions extends ProviderOptions<NotionProfile> {\n\tclientId: string;\n}\n\nexport const notion = (options: NotionOptions) => {\n\tconst tokenEndpoint = \"https://api.notion.com/v1/oauth/token\";\n\treturn {\n\t\tid: \"notion\",\n\t\tname: \"Notion\",\n\t\tcreateAuthorizationURL({ state, scopes, loginHint, redirectURI }) {\n\t\t\tconst _scopes: string[] = options.disableDefaultScope ? [] : [];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"notion\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://api.notion.com/v1/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tloginHint,\n\t\t\t\tadditionalParams: {\n\t\t\t\t\towner: \"user\",\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t\tauthentication: \"basic\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<{\n\t\t\t\tbot: {\n\t\t\t\t\towner: {\n\t\t\t\t\t\tuser: NotionProfile;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t}>(\"https://api.notion.com/v1/users/me\", {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\"Notion-Version\": \"2022-06-28\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (error || !profile) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userProfile = profile.bot?.owner?.user;\n\t\t\tif (!userProfile) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(userProfile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: userProfile.id,\n\t\t\t\t\tname: userProfile.name || \"\",\n\t\t\t\t\temail: userProfile.person?.email || null,\n\t\t\t\t\timage: userProfile.avatar_url,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: userProfile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<NotionProfile>;\n};\n"],"mappings":";;;;;;;AAyBA,MAAa,UAAU,YAA2B;CACjD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,WAAW,eAAe;GACjE,MAAM,UAAoB,QAAQ,sBAAsB,EAAE,GAAG,EAAE;AAC/D,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,kBAAkB,EACjB,OAAO,QACP;IACD,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,gBAAgB;IAChB,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YAMpC,sCAAsC,EACxC,SAAS;IACR,eAAe,UAAU,MAAM;IAC/B,kBAAkB;IAClB,EACD,CAAC;AACF,OAAI,SAAS,CAAC,QACb,QAAO;GAER,MAAM,cAAc,QAAQ,KAAK,OAAO;AACxC,OAAI,CAAC,YACJ,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,YAAY;AAC7D,UAAO;IACN,MAAM;KACL,IAAI,YAAY;KAChB,MAAM,YAAY,QAAQ;KAC1B,OAAO,YAAY,QAAQ,SAAS;KACpC,OAAO,YAAY;KACnB,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"notion.mjs","names":[],"sources":["../../src/social-providers/notion.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface NotionProfile {\n\tobject: \"user\";\n\tid: string;\n\ttype: \"person\" | \"bot\";\n\tname?: string | undefined;\n\tavatar_url?: string | undefined;\n\tperson?:\n\t\t| {\n\t\t\t\temail?: string;\n\t\t }\n\t\t| undefined;\n}\n\nexport interface NotionOptions extends ProviderOptions<NotionProfile> {\n\tclientId: string;\n}\n\nexport const notion = (options: NotionOptions) => {\n\tconst tokenEndpoint = \"https://api.notion.com/v1/oauth/token\";\n\treturn {\n\t\tid: \"notion\",\n\t\tname: \"Notion\",\n\t\tcreateAuthorizationURL({ state, scopes, loginHint, redirectURI }) {\n\t\t\tconst _scopes: string[] = options.disableDefaultScope ? [] : [];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"notion\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://api.notion.com/v1/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tloginHint,\n\t\t\t\tadditionalParams: {\n\t\t\t\t\towner: \"user\",\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t\tauthentication: \"basic\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<{\n\t\t\t\tbot: {\n\t\t\t\t\towner: {\n\t\t\t\t\t\tuser: NotionProfile;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t}>(\"https://api.notion.com/v1/users/me\", {\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\"Notion-Version\": \"2022-06-28\",\n\t\t\t\t},\n\t\t\t});\n\t\t\tif (error || !profile) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userProfile = profile.bot?.owner?.user;\n\t\t\tif (!userProfile) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(userProfile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: userProfile.id,\n\t\t\t\t\tname: userProfile.name || \"\",\n\t\t\t\t\temail: userProfile.person?.email || null,\n\t\t\t\t\timage: userProfile.avatar_url,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: userProfile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<NotionProfile>;\n};\n"],"mappings":";;;;;;AAyBA,MAAa,UAAU,YAA2B;CACjD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,WAAW,eAAe;GACjE,MAAM,UAAoB,QAAQ,sBAAsB,EAAE,GAAG,EAAE;AAC/D,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,kBAAkB,EACjB,OAAO,QACP;IACD,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,gBAAgB;IAChB,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YAMpC,sCAAsC,EACxC,SAAS;IACR,eAAe,UAAU,MAAM;IAC/B,kBAAkB;IAClB,EACD,CAAC;AACF,OAAI,SAAS,CAAC,QACb,QAAO;GAER,MAAM,cAAc,QAAQ,KAAK,OAAO;AACxC,OAAI,CAAC,YACJ,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,YAAY;AAC7D,UAAO;IACN,MAAM;KACL,IAAI,YAAY;KAChB,MAAM,YAAY,QAAQ;KAC1B,OAAO,YAAY,QAAQ,SAAS;KACpC,OAAO,YAAY;KACnB,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
@@ -6,7 +6,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
6
6
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
7
7
  import "../oauth2/index.mjs";
8
8
  import { decodeJwt } from "jose";
9
-
10
9
  //#region src/social-providers/paybin.ts
11
10
  const paybin = (options) => {
12
11
  const issuer = options.issuer || "https://idp.paybin.io";
@@ -80,7 +79,7 @@ const paybin = (options) => {
80
79
  options
81
80
  };
82
81
  };
83
-
84
82
  //#endregion
85
83
  export { paybin };
84
+
86
85
  //# sourceMappingURL=paybin.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"paybin.mjs","names":[],"sources":["../../src/social-providers/paybin.ts"],"sourcesContent":["import { decodeJwt } from \"jose\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface PaybinProfile {\n\tsub: string;\n\temail: string;\n\temail_verified?: boolean | undefined;\n\tname?: string | undefined;\n\tpreferred_username?: string | undefined;\n\tpicture?: string | undefined;\n\tgiven_name?: string | undefined;\n\tfamily_name?: string | undefined;\n}\n\nexport interface PaybinOptions extends ProviderOptions<PaybinProfile> {\n\tclientId: string;\n\t/**\n\t * The issuer URL of your Paybin OAuth server\n\t * @default \"https://idp.paybin.io\"\n\t */\n\tissuer?: string | undefined;\n}\n\nexport const paybin = (options: PaybinOptions) => {\n\tconst issuer = options.issuer || \"https://idp.paybin.io\";\n\tconst authorizationEndpoint = `${issuer}/oauth2/authorize`;\n\tconst tokenEndpoint = `${issuer}/oauth2/token`;\n\n\treturn {\n\t\tid: \"paybin\",\n\t\tname: \"Paybin\",\n\t\tasync createAuthorizationURL({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI,\n\t\t\tloginHint,\n\t\t}) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret is required for Paybin. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Paybin\");\n\t\t\t}\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"email\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"paybin\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t\tloginHint,\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst user = decodeJwt(token.idToken) as PaybinProfile;\n\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: user.sub,\n\t\t\t\t\tname: user.name || user.preferred_username || \"\",\n\t\t\t\t\temail: user.email,\n\t\t\t\t\timage: user.picture,\n\t\t\t\t\temailVerified: user.email_verified || false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: user,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<PaybinProfile>;\n};\n"],"mappings":";;;;;;;;;;AA8BA,MAAa,UAAU,YAA2B;CACjD,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,wBAAwB,GAAG,OAAO;CACxC,MAAM,gBAAgB,GAAG,OAAO;AAEhC,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAC5B,OACA,QACA,cACA,aACA,aACE;AACF,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MACN,gGACA;AACD,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,sCAAsC;GAEjE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAS;IAAU;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAYnC,UAXY,MAAM,uBAAuB;IACxC,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA;IACA,QAAQ,QAAQ;IAChB;IACA,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAElC,OAAI,CAAC,MAAM,QACV,QAAO;GAER,MAAM,OAAO,UAAU,MAAM,QAAQ;GACrC,MAAM,UAAU,MAAM,QAAQ,mBAAmB,KAAK;AACtD,UAAO;IACN,MAAM;KACL,IAAI,KAAK;KACT,MAAM,KAAK,QAAQ,KAAK,sBAAsB;KAC9C,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,eAAe,KAAK,kBAAkB;KACtC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"paybin.mjs","names":[],"sources":["../../src/social-providers/paybin.ts"],"sourcesContent":["import { decodeJwt } from \"jose\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface PaybinProfile {\n\tsub: string;\n\temail: string;\n\temail_verified?: boolean | undefined;\n\tname?: string | undefined;\n\tpreferred_username?: string | undefined;\n\tpicture?: string | undefined;\n\tgiven_name?: string | undefined;\n\tfamily_name?: string | undefined;\n}\n\nexport interface PaybinOptions extends ProviderOptions<PaybinProfile> {\n\tclientId: string;\n\t/**\n\t * The issuer URL of your Paybin OAuth server\n\t * @default \"https://idp.paybin.io\"\n\t */\n\tissuer?: string | undefined;\n}\n\nexport const paybin = (options: PaybinOptions) => {\n\tconst issuer = options.issuer || \"https://idp.paybin.io\";\n\tconst authorizationEndpoint = `${issuer}/oauth2/authorize`;\n\tconst tokenEndpoint = `${issuer}/oauth2/token`;\n\n\treturn {\n\t\tid: \"paybin\",\n\t\tname: \"Paybin\",\n\t\tasync createAuthorizationURL({\n\t\t\tstate,\n\t\t\tscopes,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI,\n\t\t\tloginHint,\n\t\t}) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret is required for Paybin. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Paybin\");\n\t\t\t}\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"email\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"paybin\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t\tloginHint,\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst user = decodeJwt(token.idToken) as PaybinProfile;\n\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: user.sub,\n\t\t\t\t\tname: user.name || user.preferred_username || \"\",\n\t\t\t\t\temail: user.email,\n\t\t\t\t\timage: user.picture,\n\t\t\t\t\temailVerified: user.email_verified || false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: user,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<PaybinProfile>;\n};\n"],"mappings":";;;;;;;;;AA8BA,MAAa,UAAU,YAA2B;CACjD,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,wBAAwB,GAAG,OAAO;CACxC,MAAM,gBAAgB,GAAG,OAAO;AAEhC,QAAO;EACN,IAAI;EACJ,MAAM;EACN,MAAM,uBAAuB,EAC5B,OACA,QACA,cACA,aACA,aACE;AACF,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MACN,gGACA;AACD,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,sCAAsC;GAEjE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAS;IAAU;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAYnC,UAXY,MAAM,uBAAuB;IACxC,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA;IACA,QAAQ,QAAQ;IAChB;IACA,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAElC,OAAI,CAAC,MAAM,QACV,QAAO;GAER,MAAM,OAAO,UAAU,MAAM,QAAQ;GACrC,MAAM,UAAU,MAAM,QAAQ,mBAAmB,KAAK;AACtD,UAAO;IACN,MAAM;KACL,IAAI,KAAK;KACT,MAAM,KAAK,QAAQ,KAAK,sBAAsB;KAC9C,OAAO,KAAK;KACZ,OAAO,KAAK;KACZ,eAAe,KAAK,kBAAkB;KACtC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
@@ -6,7 +6,6 @@ import "../oauth2/index.mjs";
6
6
  import { base64 } from "@better-auth/utils/base64";
7
7
  import { betterFetch } from "@better-fetch/fetch";
8
8
  import { decodeJwt } from "jose";
9
-
10
9
  //#region src/social-providers/paypal.ts
11
10
  const paypal = (options) => {
12
11
  const isSandbox = (options.environment || "sandbox") === "sandbox";
@@ -139,7 +138,7 @@ const paypal = (options) => {
139
138
  options
140
139
  };
141
140
  };
142
-
143
141
  //#endregion
144
142
  export { paypal };
143
+
145
144
  //# sourceMappingURL=paypal.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"paypal.mjs","names":[],"sources":["../../src/social-providers/paypal.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt } from \"jose\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { createAuthorizationURL } from \"../oauth2\";\n\nexport interface PayPalProfile {\n\tuser_id: string;\n\tname: string;\n\tgiven_name: string;\n\tfamily_name: string;\n\tmiddle_name?: string | undefined;\n\tpicture?: string | undefined;\n\temail: string;\n\temail_verified: boolean;\n\tgender?: string | undefined;\n\tbirthdate?: string | undefined;\n\tzoneinfo?: string | undefined;\n\tlocale?: string | undefined;\n\tphone_number?: string | undefined;\n\taddress?:\n\t\t| {\n\t\t\t\tstreet_address?: string;\n\t\t\t\tlocality?: string;\n\t\t\t\tregion?: string;\n\t\t\t\tpostal_code?: string;\n\t\t\t\tcountry?: string;\n\t\t }\n\t\t| undefined;\n\tverified_account?: boolean | undefined;\n\taccount_type?: string | undefined;\n\tage_range?: string | undefined;\n\tpayer_id?: string | undefined;\n}\n\nexport interface PayPalTokenResponse {\n\tscope?: string | undefined;\n\taccess_token: string;\n\trefresh_token?: string | undefined;\n\ttoken_type: \"Bearer\";\n\tid_token?: string | undefined;\n\texpires_in: number;\n\tnonce?: string | undefined;\n}\n\nexport interface PayPalOptions extends ProviderOptions<PayPalProfile> {\n\tclientId: string;\n\t/**\n\t * PayPal environment - 'sandbox' for testing, 'live' for production\n\t * @default 'sandbox'\n\t */\n\tenvironment?: (\"sandbox\" | \"live\") | undefined;\n\t/**\n\t * Whether to request shipping address information\n\t * @default false\n\t */\n\trequestShippingAddress?: boolean | undefined;\n}\n\nexport const paypal = (options: PayPalOptions) => {\n\tconst environment = options.environment || \"sandbox\";\n\tconst isSandbox = environment === \"sandbox\";\n\n\tconst authorizationEndpoint = isSandbox\n\t\t? \"https://www.sandbox.paypal.com/signin/authorize\"\n\t\t: \"https://www.paypal.com/signin/authorize\";\n\n\tconst tokenEndpoint = isSandbox\n\t\t? \"https://api-m.sandbox.paypal.com/v1/oauth2/token\"\n\t\t: \"https://api-m.paypal.com/v1/oauth2/token\";\n\n\tconst userInfoEndpoint = isSandbox\n\t\t? \"https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo\"\n\t\t: \"https://api-m.paypal.com/v1/identity/oauth2/userinfo\";\n\n\treturn {\n\t\tid: \"paypal\",\n\t\tname: \"PayPal\",\n\t\tasync createAuthorizationURL({ state, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret is required for PayPal. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Log in with PayPal doesn't use traditional OAuth2 scopes\n\t\t\t * Instead, permissions are configured in the PayPal Developer Dashboard\n\t\t\t * We don't pass any scopes to avoid \"invalid scope\" errors\n\t\t\t **/\n\n\t\t\tconst _scopes: string[] = [];\n\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"paypal\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\t/**\n\t\t\t * PayPal requires Basic Auth for token exchange\n\t\t\t **/\n\n\t\t\tconst credentials = base64.encode(\n\t\t\t\t`${options.clientId}:${options.clientSecret}`,\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst response = await betterFetch(tokenEndpoint, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Basic ${credentials}`,\n\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\"Accept-Language\": \"en_US\",\n\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t},\n\t\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\t\t\tcode: code,\n\t\t\t\t\t\tredirect_uri: redirectURI,\n\t\t\t\t\t}).toString(),\n\t\t\t\t});\n\n\t\t\t\tif (!response.data) {\n\t\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_GET_ACCESS_TOKEN\");\n\t\t\t\t}\n\n\t\t\t\tconst data = response.data as PayPalTokenResponse;\n\n\t\t\t\tconst result = {\n\t\t\t\t\taccessToken: data.access_token,\n\t\t\t\t\trefreshToken: data.refresh_token,\n\t\t\t\t\taccessTokenExpiresAt: data.expires_in\n\t\t\t\t\t\t? new Date(Date.now() + data.expires_in * 1000)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\tidToken: data.id_token,\n\t\t\t\t};\n\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"PayPal token exchange failed:\", error);\n\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_GET_ACCESS_TOKEN\");\n\t\t\t}\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\tconst credentials = base64.encode(\n\t\t\t\t\t\t`${options.clientId}:${options.clientSecret}`,\n\t\t\t\t\t);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await betterFetch(tokenEndpoint, {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\tAuthorization: `Basic ${credentials}`,\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Accept-Language\": \"en_US\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\t\t\t\t\trefresh_token: refreshToken,\n\t\t\t\t\t\t\t}).toString(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!response.data) {\n\t\t\t\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_REFRESH_ACCESS_TOKEN\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst data = response.data as any;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\taccessToken: data.access_token,\n\t\t\t\t\t\t\trefreshToken: data.refresh_token,\n\t\t\t\t\t\t\taccessTokenExpiresAt: data.expires_in\n\t\t\t\t\t\t\t\t? new Date(Date.now() + data.expires_in * 1000)\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger.error(\"PayPal token refresh failed:\", error);\n\t\t\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_REFRESH_ACCESS_TOKEN\");\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst payload = decodeJwt(token);\n\t\t\t\treturn !!payload.sub;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to verify PayPal ID token:\", error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tif (!token.accessToken) {\n\t\t\t\tlogger.error(\"Access token is required to fetch PayPal user info\");\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await betterFetch<PayPalProfile>(\n\t\t\t\t\t`${userInfoEndpoint}?schema=paypalv1.1`,\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!response.data) {\n\t\t\t\t\tlogger.error(\"Failed to fetch user info from PayPal\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst userInfo = response.data;\n\t\t\t\tconst userMap = await options.mapProfileToUser?.(userInfo);\n\n\t\t\t\tconst result = {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: userInfo.user_id,\n\t\t\t\t\t\tname: userInfo.name,\n\t\t\t\t\t\temail: userInfo.email,\n\t\t\t\t\t\timage: userInfo.picture,\n\t\t\t\t\t\temailVerified: userInfo.email_verified,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: userInfo,\n\t\t\t\t};\n\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to fetch user info from PayPal:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\n\t\toptions,\n\t} satisfies OAuthProvider<PayPalProfile>;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"paypal.mjs","names":[],"sources":["../../src/social-providers/paypal.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { decodeJwt } from \"jose\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { createAuthorizationURL } from \"../oauth2\";\n\nexport interface PayPalProfile {\n\tuser_id: string;\n\tname: string;\n\tgiven_name: string;\n\tfamily_name: string;\n\tmiddle_name?: string | undefined;\n\tpicture?: string | undefined;\n\temail: string;\n\temail_verified: boolean;\n\tgender?: string | undefined;\n\tbirthdate?: string | undefined;\n\tzoneinfo?: string | undefined;\n\tlocale?: string | undefined;\n\tphone_number?: string | undefined;\n\taddress?:\n\t\t| {\n\t\t\t\tstreet_address?: string;\n\t\t\t\tlocality?: string;\n\t\t\t\tregion?: string;\n\t\t\t\tpostal_code?: string;\n\t\t\t\tcountry?: string;\n\t\t }\n\t\t| undefined;\n\tverified_account?: boolean | undefined;\n\taccount_type?: string | undefined;\n\tage_range?: string | undefined;\n\tpayer_id?: string | undefined;\n}\n\nexport interface PayPalTokenResponse {\n\tscope?: string | undefined;\n\taccess_token: string;\n\trefresh_token?: string | undefined;\n\ttoken_type: \"Bearer\";\n\tid_token?: string | undefined;\n\texpires_in: number;\n\tnonce?: string | undefined;\n}\n\nexport interface PayPalOptions extends ProviderOptions<PayPalProfile> {\n\tclientId: string;\n\t/**\n\t * PayPal environment - 'sandbox' for testing, 'live' for production\n\t * @default 'sandbox'\n\t */\n\tenvironment?: (\"sandbox\" | \"live\") | undefined;\n\t/**\n\t * Whether to request shipping address information\n\t * @default false\n\t */\n\trequestShippingAddress?: boolean | undefined;\n}\n\nexport const paypal = (options: PayPalOptions) => {\n\tconst environment = options.environment || \"sandbox\";\n\tconst isSandbox = environment === \"sandbox\";\n\n\tconst authorizationEndpoint = isSandbox\n\t\t? \"https://www.sandbox.paypal.com/signin/authorize\"\n\t\t: \"https://www.paypal.com/signin/authorize\";\n\n\tconst tokenEndpoint = isSandbox\n\t\t? \"https://api-m.sandbox.paypal.com/v1/oauth2/token\"\n\t\t: \"https://api-m.paypal.com/v1/oauth2/token\";\n\n\tconst userInfoEndpoint = isSandbox\n\t\t? \"https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo\"\n\t\t: \"https://api-m.paypal.com/v1/identity/oauth2/userinfo\";\n\n\treturn {\n\t\tid: \"paypal\",\n\t\tname: \"PayPal\",\n\t\tasync createAuthorizationURL({ state, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret is required for PayPal. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Log in with PayPal doesn't use traditional OAuth2 scopes\n\t\t\t * Instead, permissions are configured in the PayPal Developer Dashboard\n\t\t\t * We don't pass any scopes to avoid \"invalid scope\" errors\n\t\t\t **/\n\n\t\t\tconst _scopes: string[] = [];\n\n\t\t\tconst url = await createAuthorizationURL({\n\t\t\t\tid: \"paypal\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\t/**\n\t\t\t * PayPal requires Basic Auth for token exchange\n\t\t\t **/\n\n\t\t\tconst credentials = base64.encode(\n\t\t\t\t`${options.clientId}:${options.clientSecret}`,\n\t\t\t);\n\n\t\t\ttry {\n\t\t\t\tconst response = await betterFetch(tokenEndpoint, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Basic ${credentials}`,\n\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\"Accept-Language\": \"en_US\",\n\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t},\n\t\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\t\t\tcode: code,\n\t\t\t\t\t\tredirect_uri: redirectURI,\n\t\t\t\t\t}).toString(),\n\t\t\t\t});\n\n\t\t\t\tif (!response.data) {\n\t\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_GET_ACCESS_TOKEN\");\n\t\t\t\t}\n\n\t\t\t\tconst data = response.data as PayPalTokenResponse;\n\n\t\t\t\tconst result = {\n\t\t\t\t\taccessToken: data.access_token,\n\t\t\t\t\trefreshToken: data.refresh_token,\n\t\t\t\t\taccessTokenExpiresAt: data.expires_in\n\t\t\t\t\t\t? new Date(Date.now() + data.expires_in * 1000)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\tidToken: data.id_token,\n\t\t\t\t};\n\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"PayPal token exchange failed:\", error);\n\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_GET_ACCESS_TOKEN\");\n\t\t\t}\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\tconst credentials = base64.encode(\n\t\t\t\t\t\t`${options.clientId}:${options.clientSecret}`,\n\t\t\t\t\t);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst response = await betterFetch(tokenEndpoint, {\n\t\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\tAuthorization: `Basic ${credentials}`,\n\t\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t\t\t\"Accept-Language\": \"en_US\",\n\t\t\t\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\t\t\t\tgrant_type: \"refresh_token\",\n\t\t\t\t\t\t\t\trefresh_token: refreshToken,\n\t\t\t\t\t\t\t}).toString(),\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (!response.data) {\n\t\t\t\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_REFRESH_ACCESS_TOKEN\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst data = response.data as any;\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\taccessToken: data.access_token,\n\t\t\t\t\t\t\trefreshToken: data.refresh_token,\n\t\t\t\t\t\t\taccessTokenExpiresAt: data.expires_in\n\t\t\t\t\t\t\t\t? new Date(Date.now() + data.expires_in * 1000)\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t};\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tlogger.error(\"PayPal token refresh failed:\", error);\n\t\t\t\t\t\tthrow new BetterAuthError(\"FAILED_TO_REFRESH_ACCESS_TOKEN\");\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\tasync verifyIdToken(token, nonce) {\n\t\t\tif (options.disableIdTokenSignIn) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (options.verifyIdToken) {\n\t\t\t\treturn options.verifyIdToken(token, nonce);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst payload = decodeJwt(token);\n\t\t\t\treturn !!payload.sub;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to verify PayPal ID token:\", error);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tif (!token.accessToken) {\n\t\t\t\tlogger.error(\"Access token is required to fetch PayPal user info\");\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst response = await betterFetch<PayPalProfile>(\n\t\t\t\t\t`${userInfoEndpoint}?schema=paypalv1.1`,\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!response.data) {\n\t\t\t\t\tlogger.error(\"Failed to fetch user info from PayPal\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst userInfo = response.data;\n\t\t\t\tconst userMap = await options.mapProfileToUser?.(userInfo);\n\n\t\t\t\tconst result = {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: userInfo.user_id,\n\t\t\t\t\t\tname: userInfo.name,\n\t\t\t\t\t\temail: userInfo.email,\n\t\t\t\t\t\timage: userInfo.picture,\n\t\t\t\t\t\temailVerified: userInfo.email_verified,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: userInfo,\n\t\t\t\t};\n\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to fetch user info from PayPal:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\n\t\toptions,\n\t} satisfies OAuthProvider<PayPalProfile>;\n};\n"],"mappings":"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"}
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
3
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
4
  import "../oauth2/index.mjs";
5
5
  import { betterFetch } from "@better-fetch/fetch";
6
-
7
6
  //#region src/social-providers/polar.ts
8
7
  const polar = (options) => {
9
8
  const tokenEndpoint = "https://api.polar.sh/v1/oauth2/token";
@@ -69,7 +68,7 @@ const polar = (options) => {
69
68
  options
70
69
  };
71
70
  };
72
-
73
71
  //#endregion
74
72
  export { polar };
73
+
75
74
  //# sourceMappingURL=polar.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"polar.mjs","names":[],"sources":["../../src/social-providers/polar.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface PolarProfile {\n\tid: string;\n\temail: string;\n\tusername: string;\n\tavatar_url: string;\n\tgithub_username?: string | undefined;\n\taccount_id?: string | undefined;\n\tpublic_name?: string | undefined;\n\temail_verified?: boolean | undefined;\n\tprofile_settings?:\n\t\t| {\n\t\t\t\tprofile_settings_enabled?: boolean;\n\t\t\t\tprofile_settings_public_name?: string;\n\t\t\t\tprofile_settings_public_avatar?: string;\n\t\t\t\tprofile_settings_public_bio?: string;\n\t\t\t\tprofile_settings_public_location?: string;\n\t\t\t\tprofile_settings_public_website?: string;\n\t\t\t\tprofile_settings_public_twitter?: string;\n\t\t\t\tprofile_settings_public_github?: string;\n\t\t\t\tprofile_settings_public_email?: string;\n\t\t }\n\t\t| undefined;\n}\n\nexport interface PolarOptions extends ProviderOptions<PolarProfile> {}\n\nexport const polar = (options: PolarOptions) => {\n\tconst tokenEndpoint = \"https://api.polar.sh/v1/oauth2/token\";\n\treturn {\n\t\tid: \"polar\",\n\t\tname: \"Polar\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"polar\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://polar.sh/oauth2/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<PolarProfile>(\n\t\t\t\t\"https://api.polar.sh/v1/oauth2/userinfo\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Polar may provide email_verified claim, but it's not guaranteed.\n\t\t\t// We check for it first, then default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.public_name || profile.username || \"\",\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.avatar_url,\n\t\t\t\t\temailVerified: profile.email_verified ?? false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<PolarProfile>;\n};\n"],"mappings":";;;;;;;AAkCA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;GACpE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAW;IAAQ;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,QAAQ,QAAQ;IAChB,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,2CACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AACD,OAAI,MACH,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,eAAe,QAAQ,YAAY;KACjD,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf,eAAe,QAAQ,kBAAkB;KACzC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"polar.mjs","names":[],"sources":["../../src/social-providers/polar.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface PolarProfile {\n\tid: string;\n\temail: string;\n\tusername: string;\n\tavatar_url: string;\n\tgithub_username?: string | undefined;\n\taccount_id?: string | undefined;\n\tpublic_name?: string | undefined;\n\temail_verified?: boolean | undefined;\n\tprofile_settings?:\n\t\t| {\n\t\t\t\tprofile_settings_enabled?: boolean;\n\t\t\t\tprofile_settings_public_name?: string;\n\t\t\t\tprofile_settings_public_avatar?: string;\n\t\t\t\tprofile_settings_public_bio?: string;\n\t\t\t\tprofile_settings_public_location?: string;\n\t\t\t\tprofile_settings_public_website?: string;\n\t\t\t\tprofile_settings_public_twitter?: string;\n\t\t\t\tprofile_settings_public_github?: string;\n\t\t\t\tprofile_settings_public_email?: string;\n\t\t }\n\t\t| undefined;\n}\n\nexport interface PolarOptions extends ProviderOptions<PolarProfile> {}\n\nexport const polar = (options: PolarOptions) => {\n\tconst tokenEndpoint = \"https://api.polar.sh/v1/oauth2/token\";\n\treturn {\n\t\tid: \"polar\",\n\t\tname: \"Polar\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"polar\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://polar.sh/oauth2/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\tprompt: options.prompt,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<PolarProfile>(\n\t\t\t\t\"https://api.polar.sh/v1/oauth2/userinfo\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Polar may provide email_verified claim, but it's not guaranteed.\n\t\t\t// We check for it first, then default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.public_name || profile.username || \"\",\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.avatar_url,\n\t\t\t\t\temailVerified: profile.email_verified ?? false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<PolarProfile>;\n};\n"],"mappings":";;;;;;AAkCA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;GACpE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAW;IAAQ;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,QAAQ,QAAQ;IAChB,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,2CACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AACD,OAAI,MACH,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,eAAe,QAAQ,YAAY;KACjD,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf,eAAe,QAAQ,kBAAkB;KACzC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
3
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
4
  import "../oauth2/index.mjs";
5
5
  import { betterFetch } from "@better-fetch/fetch";
6
-
7
6
  //#region src/social-providers/railway.ts
8
7
  const authorizationEndpoint = "https://backboard.railway.com/oauth/auth";
9
8
  const tokenEndpoint = "https://backboard.railway.com/oauth/token";
@@ -72,7 +71,7 @@ const railway = (options) => {
72
71
  options
73
72
  };
74
73
  };
75
-
76
74
  //#endregion
77
75
  export { railway };
76
+
78
77
  //# sourceMappingURL=railway.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"railway.mjs","names":[],"sources":["../../src/social-providers/railway.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nconst authorizationEndpoint = \"https://backboard.railway.com/oauth/auth\";\nconst tokenEndpoint = \"https://backboard.railway.com/oauth/token\";\nconst userinfoEndpoint = \"https://backboard.railway.com/oauth/me\";\n\nexport interface RailwayProfile {\n\t/** The user's unique ID (OAuth `sub` claim). */\n\tsub: string;\n\t/** The user's email address. */\n\temail: string;\n\t/** The user's display name. */\n\tname: string;\n\t/** URL of the user's profile picture. */\n\tpicture: string;\n}\n\nexport interface RailwayOptions extends ProviderOptions<RailwayProfile> {\n\tclientId: string;\n}\n\nexport const railway = (options: RailwayOptions) => {\n\treturn {\n\t\tid: \"railway\",\n\t\tname: \"Railway\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"email\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"railway\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t\tauthentication: \"basic\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t\tauthentication: \"basic\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<RailwayProfile>(\n\t\t\t\tuserinfoEndpoint,\n\t\t\t\t{ headers: { authorization: `Bearer ${token.accessToken}` } },\n\t\t\t);\n\t\t\tif (error || !profile) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Railway does not provide an email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.picture,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<RailwayProfile>;\n};\n"],"mappings":";;;;;;;AAQA,MAAM,wBAAwB;AAC9B,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AAiBzB,MAAa,WAAW,YAA4B;AACnD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;GACpE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAS;IAAU;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,gBAAgB;IAChB,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,gBAAgB;IAChB,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,kBACA,EAAE,SAAS,EAAE,eAAe,UAAU,MAAM,eAAe,EAAE,CAC7D;AACD,OAAI,SAAS,CAAC,QACb,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"railway.mjs","names":[],"sources":["../../src/social-providers/railway.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nconst authorizationEndpoint = \"https://backboard.railway.com/oauth/auth\";\nconst tokenEndpoint = \"https://backboard.railway.com/oauth/token\";\nconst userinfoEndpoint = \"https://backboard.railway.com/oauth/me\";\n\nexport interface RailwayProfile {\n\t/** The user's unique ID (OAuth `sub` claim). */\n\tsub: string;\n\t/** The user's email address. */\n\temail: string;\n\t/** The user's display name. */\n\tname: string;\n\t/** URL of the user's profile picture. */\n\tpicture: string;\n}\n\nexport interface RailwayOptions extends ProviderOptions<RailwayProfile> {\n\tclientId: string;\n}\n\nexport const railway = (options: RailwayOptions) => {\n\treturn {\n\t\tid: \"railway\",\n\t\tname: \"Railway\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"email\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"railway\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t\tauthentication: \"basic\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t\tauthentication: \"basic\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<RailwayProfile>(\n\t\t\t\tuserinfoEndpoint,\n\t\t\t\t{ headers: { authorization: `Bearer ${token.accessToken}` } },\n\t\t\t);\n\t\t\tif (error || !profile) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Railway does not provide an email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.picture,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<RailwayProfile>;\n};\n"],"mappings":";;;;;;AAQA,MAAM,wBAAwB;AAC9B,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AAiBzB,MAAa,WAAW,YAA4B;AACnD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;GACpE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAS;IAAU;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,gBAAgB;IAChB,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,gBAAgB;IAChB,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,kBACA,EAAE,SAAS,EAAE,eAAe,UAAU,MAAM,eAAe,EAAE,CAC7D;AACD,OAAI,SAAS,CAAC,QACb,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,OAAO,QAAQ;KACf,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
@@ -4,7 +4,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
4
4
  import "../oauth2/index.mjs";
5
5
  import { base64 } from "@better-auth/utils/base64";
6
6
  import { betterFetch } from "@better-fetch/fetch";
7
-
8
7
  //#region src/social-providers/reddit.ts
9
8
  const reddit = (options) => {
10
9
  return {
@@ -78,7 +77,7 @@ const reddit = (options) => {
78
77
  options
79
78
  };
80
79
  };
81
-
82
80
  //#endregion
83
81
  export { reddit };
82
+
84
83
  //# sourceMappingURL=reddit.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"reddit.mjs","names":[],"sources":["../../src/social-providers/reddit.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\tgetOAuth2Tokens,\n\trefreshAccessToken,\n} from \"../oauth2\";\n\nexport interface RedditProfile {\n\tid: string;\n\tname: string;\n\ticon_img: string | null;\n\thas_verified_email: boolean;\n\toauth_client_id: string;\n\tverified: boolean;\n}\n\nexport interface RedditOptions extends ProviderOptions<RedditProfile> {\n\tclientId: string;\n\tduration?: string | undefined;\n}\n\nexport const reddit = (options: RedditOptions) => {\n\treturn {\n\t\tid: \"reddit\",\n\t\tname: \"Reddit\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"identity\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"reddit\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://www.reddit.com/api/v1/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tduration: options.duration,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\tconst body = new URLSearchParams({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: options.redirectURI || redirectURI,\n\t\t\t});\n\t\t\tconst headers = {\n\t\t\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\t\t\taccept: \"text/plain\",\n\t\t\t\t\"user-agent\": \"better-auth\",\n\t\t\t\tAuthorization: `Basic ${base64.encode(\n\t\t\t\t\t`${options.clientId}:${options.clientSecret}`,\n\t\t\t\t)}`,\n\t\t\t};\n\n\t\t\tconst { data, error } = await betterFetch<object>(\n\t\t\t\t\"https://www.reddit.com/api/v1/access_token\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders,\n\t\t\t\t\tbody: body.toString(),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\treturn getOAuth2Tokens(data);\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tauthentication: \"basic\",\n\t\t\t\t\t\ttokenEndpoint: \"https://www.reddit.com/api/v1/access_token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tconst { data: profile, error } = await betterFetch<RedditProfile>(\n\t\t\t\t\"https://oauth.reddit.com/api/v1/me\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t\"User-Agent\": \"better-auth\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.oauth_client_id,\n\t\t\t\t\temailVerified: profile.has_verified_email,\n\t\t\t\t\timage: profile.icon_img?.split(\"?\")[0]!,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<RedditProfile>;\n};\n"],"mappings":";;;;;;;;AAuBA,MAAa,UAAU,YAA2B;AACjD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,WAAW;AAC/D,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,UAAU,QAAQ;IAClB,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;GAC3D,MAAM,OAAO,IAAI,gBAAgB;IAChC,YAAY;IACZ;IACA,cAAc,QAAQ,eAAe;IACrC,CAAC;GAUF,MAAM,EAAE,MAAM,UAAU,MAAM,YAC7B,8CACA;IACC,QAAQ;IACR,SAbc;KACf,gBAAgB;KAChB,QAAQ;KACR,cAAc;KACd,eAAe,SAAS,OAAO,OAC9B,GAAG,QAAQ,SAAS,GAAG,QAAQ,eAC/B;KACD;IAOC,MAAM,KAAK,UAAU;IACrB,CACD;AAED,OAAI,MACH,OAAM;AAGP,UAAO,gBAAgB,KAAK;;EAG7B,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,gBAAgB;IAChB,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAGlC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,sCACA,EACC,SAAS;IACR,eAAe,UAAU,MAAM;IAC/B,cAAc;IACd,EACD,CACD;AAED,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAEzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,eAAe,QAAQ;KACvB,OAAO,QAAQ,UAAU,MAAM,IAAI,CAAC;KACpC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"reddit.mjs","names":[],"sources":["../../src/social-providers/reddit.ts"],"sourcesContent":["import { base64 } from \"@better-auth/utils/base64\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\tgetOAuth2Tokens,\n\trefreshAccessToken,\n} from \"../oauth2\";\n\nexport interface RedditProfile {\n\tid: string;\n\tname: string;\n\ticon_img: string | null;\n\thas_verified_email: boolean;\n\toauth_client_id: string;\n\tverified: boolean;\n}\n\nexport interface RedditOptions extends ProviderOptions<RedditProfile> {\n\tclientId: string;\n\tduration?: string | undefined;\n}\n\nexport const reddit = (options: RedditOptions) => {\n\treturn {\n\t\tid: \"reddit\",\n\t\tname: \"Reddit\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"identity\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"reddit\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://www.reddit.com/api/v1/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tduration: options.duration,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\tconst body = new URLSearchParams({\n\t\t\t\tgrant_type: \"authorization_code\",\n\t\t\t\tcode,\n\t\t\t\tredirect_uri: options.redirectURI || redirectURI,\n\t\t\t});\n\t\t\tconst headers = {\n\t\t\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\t\t\taccept: \"text/plain\",\n\t\t\t\t\"user-agent\": \"better-auth\",\n\t\t\t\tAuthorization: `Basic ${base64.encode(\n\t\t\t\t\t`${options.clientId}:${options.clientSecret}`,\n\t\t\t\t)}`,\n\t\t\t};\n\n\t\t\tconst { data, error } = await betterFetch<object>(\n\t\t\t\t\"https://www.reddit.com/api/v1/access_token\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders,\n\t\t\t\t\tbody: body.toString(),\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\treturn getOAuth2Tokens(data);\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tauthentication: \"basic\",\n\t\t\t\t\t\ttokenEndpoint: \"https://www.reddit.com/api/v1/access_token\",\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\tconst { data: profile, error } = await betterFetch<RedditProfile>(\n\t\t\t\t\"https://oauth.reddit.com/api/v1/me\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t\"User-Agent\": \"better-auth\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.oauth_client_id,\n\t\t\t\t\temailVerified: profile.has_verified_email,\n\t\t\t\t\timage: profile.icon_img?.split(\"?\")[0]!,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<RedditProfile>;\n};\n"],"mappings":";;;;;;;AAuBA,MAAa,UAAU,YAA2B;AACjD,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,WAAW;AAC/D,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA,UAAU,QAAQ;IAClB,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;GAC3D,MAAM,OAAO,IAAI,gBAAgB;IAChC,YAAY;IACZ;IACA,cAAc,QAAQ,eAAe;IACrC,CAAC;GAUF,MAAM,EAAE,MAAM,UAAU,MAAM,YAC7B,8CACA;IACC,QAAQ;IACR,SAbc;KACf,gBAAgB;KAChB,QAAQ;KACR,cAAc;KACd,eAAe,SAAS,OAAO,OAC9B,GAAG,QAAQ,SAAS,GAAG,QAAQ,eAC/B;KACD;IAOC,MAAM,KAAK,UAAU;IACrB,CACD;AAED,OAAI,MACH,OAAM;AAGP,UAAO,gBAAgB,KAAK;;EAG7B,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD,gBAAgB;IAChB,eAAe;IACf,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAGlC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,sCACA,EACC,SAAS;IACR,eAAe,UAAU,MAAM;IAC/B,cAAc;IACd,EACD,CACD;AAED,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAEzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,eAAe,QAAQ;KACvB,OAAO,QAAQ,UAAU,MAAM,IAAI,CAAC;KACpC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
@@ -2,7 +2,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
2
2
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
3
3
  import "../oauth2/index.mjs";
4
4
  import { betterFetch } from "@better-fetch/fetch";
5
-
6
5
  //#region src/social-providers/roblox.ts
7
6
  const roblox = (options) => {
8
7
  const tokenEndpoint = "https://apis.roblox.com/oauth/v1/token";
@@ -55,7 +54,7 @@ const roblox = (options) => {
55
54
  options
56
55
  };
57
56
  };
58
-
59
57
  //#endregion
60
58
  export { roblox };
59
+
61
60
  //# sourceMappingURL=roblox.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"roblox.mjs","names":[],"sources":["../../src/social-providers/roblox.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { refreshAccessToken, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface RobloxProfile extends Record<string, any> {\n\t/** the user's id */\n\tsub: string;\n\t/** the user's username */\n\tpreferred_username: string;\n\t/** the user's display name, will return the same value as the preferred_username if not set */\n\tnickname: string;\n\t/** the user's display name, again, will return the same value as the preferred_username if not set */\n\tname: string;\n\t/** the account creation date as a unix timestamp in seconds */\n\tcreated_at: number;\n\t/** the user's profile URL */\n\tprofile: string;\n\t/** the user's avatar URL */\n\tpicture: string;\n}\n\nexport interface RobloxOptions extends ProviderOptions<RobloxProfile> {\n\tclientId: string;\n\tprompt?:\n\t\t| (\n\t\t\t\t| \"none\"\n\t\t\t\t| \"consent\"\n\t\t\t\t| \"login\"\n\t\t\t\t| \"select_account\"\n\t\t\t\t| \"select_account consent\"\n\t\t )\n\t\t| undefined;\n}\n\nexport const roblox = (options: RobloxOptions) => {\n\tconst tokenEndpoint = \"https://apis.roblox.com/oauth/v1/token\";\n\treturn {\n\t\tid: \"roblox\",\n\t\tname: \"Roblox\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"openid\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn new URL(\n\t\t\t\t`https://apis.roblox.com/oauth/v1/authorize?scope=${_scopes.join(\n\t\t\t\t\t\"+\",\n\t\t\t\t)}&response_type=code&client_id=${\n\t\t\t\t\toptions.clientId\n\t\t\t\t}&redirect_uri=${encodeURIComponent(\n\t\t\t\t\toptions.redirectURI || redirectURI,\n\t\t\t\t)}&state=${state}&prompt=${options.prompt || \"select_account consent\"}`,\n\t\t\t);\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t\tauthentication: \"post\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<RobloxProfile>(\n\t\t\t\t\"https://apis.roblox.com/oauth/v1/userinfo\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Roblox does not provide email or email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: profile.nickname || profile.preferred_username || \"\",\n\t\t\t\t\timage: profile.picture,\n\t\t\t\t\temail: profile.preferred_username || null, // Roblox does not provide email\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: {\n\t\t\t\t\t...profile,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<RobloxProfile>;\n};\n"],"mappings":";;;;;;AAkCA,MAAa,UAAU,YAA2B;CACjD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,UAAU,UAAU;AACxE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,IAAI,IACV,oDAAoD,QAAQ,KAC3D,IACA,CAAC,gCACD,QAAQ,SACR,gBAAgB,mBAChB,QAAQ,eAAe,YACvB,CAAC,SAAS,MAAM,UAAU,QAAQ,UAAU,2BAC7C;;EAEF,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA,aAAa,QAAQ,eAAe;IACpC;IACA;IACA,gBAAgB;IAChB,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,6CACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,YAAY,QAAQ,sBAAsB;KACxD,OAAO,QAAQ;KACf,OAAO,QAAQ,sBAAsB;KACrC,eAAe;KACf,GAAG;KACH;IACD,MAAM,EACL,GAAG,SACH;IACD;;EAEF;EACA"}
1
+ {"version":3,"file":"roblox.mjs","names":[],"sources":["../../src/social-providers/roblox.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { refreshAccessToken, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface RobloxProfile extends Record<string, any> {\n\t/** the user's id */\n\tsub: string;\n\t/** the user's username */\n\tpreferred_username: string;\n\t/** the user's display name, will return the same value as the preferred_username if not set */\n\tnickname: string;\n\t/** the user's display name, again, will return the same value as the preferred_username if not set */\n\tname: string;\n\t/** the account creation date as a unix timestamp in seconds */\n\tcreated_at: number;\n\t/** the user's profile URL */\n\tprofile: string;\n\t/** the user's avatar URL */\n\tpicture: string;\n}\n\nexport interface RobloxOptions extends ProviderOptions<RobloxProfile> {\n\tclientId: string;\n\tprompt?:\n\t\t| (\n\t\t\t\t| \"none\"\n\t\t\t\t| \"consent\"\n\t\t\t\t| \"login\"\n\t\t\t\t| \"select_account\"\n\t\t\t\t| \"select_account consent\"\n\t\t )\n\t\t| undefined;\n}\n\nexport const roblox = (options: RobloxOptions) => {\n\tconst tokenEndpoint = \"https://apis.roblox.com/oauth/v1/token\";\n\treturn {\n\t\tid: \"roblox\",\n\t\tname: \"Roblox\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"openid\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn new URL(\n\t\t\t\t`https://apis.roblox.com/oauth/v1/authorize?scope=${_scopes.join(\n\t\t\t\t\t\"+\",\n\t\t\t\t)}&response_type=code&client_id=${\n\t\t\t\t\toptions.clientId\n\t\t\t\t}&redirect_uri=${encodeURIComponent(\n\t\t\t\t\toptions.redirectURI || redirectURI,\n\t\t\t\t)}&state=${state}&prompt=${options.prompt || \"select_account consent\"}`,\n\t\t\t);\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t\tauthentication: \"post\",\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<RobloxProfile>(\n\t\t\t\t\"https://apis.roblox.com/oauth/v1/userinfo\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\t// Roblox does not provide email or email_verified claim.\n\t\t\t// We default to false for security consistency.\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: profile.nickname || profile.preferred_username || \"\",\n\t\t\t\t\timage: profile.picture,\n\t\t\t\t\temail: profile.preferred_username || null, // Roblox does not provide email\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: {\n\t\t\t\t\t...profile,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<RobloxProfile>;\n};\n"],"mappings":";;;;;AAkCA,MAAa,UAAU,YAA2B;CACjD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,UAAU,UAAU;AACxE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,IAAI,IACV,oDAAoD,QAAQ,KAC3D,IACA,CAAC,gCACD,QAAQ,SACR,gBAAgB,mBAChB,QAAQ,eAAe,YACvB,CAAC,SAAS,MAAM,UAAU,QAAQ,UAAU,2BAC7C;;EAEF,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA,aAAa,QAAQ,eAAe;IACpC;IACA;IACA,gBAAgB;IAChB,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,6CACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AAGzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,YAAY,QAAQ,sBAAsB;KACxD,OAAO,QAAQ;KACf,OAAO,QAAQ,sBAAsB;KACrC,eAAe;KACf,GAAG;KACH;IACD,MAAM,EACL,GAAG,SACH;IACD;;EAEF;EACA"}
@@ -6,7 +6,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
6
6
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
7
7
  import "../oauth2/index.mjs";
8
8
  import { betterFetch } from "@better-fetch/fetch";
9
-
10
9
  //#region src/social-providers/salesforce.ts
11
10
  const salesforce = (options) => {
12
11
  const isSandbox = (options.environment ?? "production") === "sandbox";
@@ -86,7 +85,7 @@ const salesforce = (options) => {
86
85
  options
87
86
  };
88
87
  };
89
-
90
88
  //#endregion
91
89
  export { salesforce };
90
+
92
91
  //# sourceMappingURL=salesforce.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"salesforce.mjs","names":[],"sources":["../../src/social-providers/salesforce.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface SalesforceProfile {\n\tsub: string;\n\tuser_id: string;\n\torganization_id: string;\n\tpreferred_username?: string | undefined;\n\temail: string;\n\temail_verified?: boolean | undefined;\n\tname: string;\n\tgiven_name?: string | undefined;\n\tfamily_name?: string | undefined;\n\tzoneinfo?: string | undefined;\n\tphotos?:\n\t\t| {\n\t\t\t\tpicture?: string;\n\t\t\t\tthumbnail?: string;\n\t\t }\n\t\t| undefined;\n}\n\nexport interface SalesforceOptions extends ProviderOptions<SalesforceProfile> {\n\tclientId: string;\n\tenvironment?: (\"sandbox\" | \"production\") | undefined;\n\tloginUrl?: string | undefined;\n\t/**\n\t * Override the redirect URI if auto-detection fails.\n\t * Should match the Callback URL configured in your Salesforce Connected App.\n\t * @example \"http://localhost:3000/api/auth/callback/salesforce\"\n\t */\n\tredirectURI?: string | undefined;\n}\n\nexport const salesforce = (options: SalesforceOptions) => {\n\tconst environment = options.environment ?? \"production\";\n\tconst isSandbox = environment === \"sandbox\";\n\tconst authorizationEndpoint = options.loginUrl\n\t\t? `https://${options.loginUrl}/services/oauth2/authorize`\n\t\t: isSandbox\n\t\t\t? \"https://test.salesforce.com/services/oauth2/authorize\"\n\t\t\t: \"https://login.salesforce.com/services/oauth2/authorize\";\n\n\tconst tokenEndpoint = options.loginUrl\n\t\t? `https://${options.loginUrl}/services/oauth2/token`\n\t\t: isSandbox\n\t\t\t? \"https://test.salesforce.com/services/oauth2/token\"\n\t\t\t: \"https://login.salesforce.com/services/oauth2/token\";\n\n\tconst userInfoEndpoint = options.loginUrl\n\t\t? `https://${options.loginUrl}/services/oauth2/userinfo`\n\t\t: isSandbox\n\t\t\t? \"https://test.salesforce.com/services/oauth2/userinfo\"\n\t\t\t: \"https://login.salesforce.com/services/oauth2/userinfo\";\n\n\treturn {\n\t\tid: \"salesforce\",\n\t\tname: \"Salesforce\",\n\n\t\tasync createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret are required for Salesforce. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Salesforce\");\n\t\t\t}\n\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"email\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"salesforce\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t});\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { data: user } = await betterFetch<SalesforceProfile>(\n\t\t\t\t\tuserInfoEndpoint,\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!user) {\n\t\t\t\t\tlogger.error(\"Failed to fetch user info from Salesforce\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\n\t\t\t\treturn {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: user.user_id,\n\t\t\t\t\t\tname: user.name,\n\t\t\t\t\t\temail: user.email,\n\t\t\t\t\t\timage: user.photos?.picture || user.photos?.thumbnail,\n\t\t\t\t\t\temailVerified: user.email_verified ?? false,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: user,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to fetch user info from Salesforce:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\n\t\toptions,\n\t} satisfies OAuthProvider<SalesforceProfile>;\n};\n"],"mappings":";;;;;;;;;;AAyCA,MAAa,cAAc,YAA+B;CAEzD,MAAM,aADc,QAAQ,eAAe,kBACT;CAClC,MAAM,wBAAwB,QAAQ,WACnC,WAAW,QAAQ,SAAS,8BAC5B,YACC,0DACA;CAEJ,MAAM,gBAAgB,QAAQ,WAC3B,WAAW,QAAQ,SAAS,0BAC5B,YACC,sDACA;CAEJ,MAAM,mBAAmB,QAAQ,WAC9B,WAAW,QAAQ,SAAS,6BAC5B,YACC,yDACA;AAEJ,QAAO;EACN,IAAI;EACJ,MAAM;EAEN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;AAC1E,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MACN,qGACA;AACD,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,0CAA0C;GAGrE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAS;IAAU;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAEnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA,aAAa,QAAQ,eAAe;IACpC,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA,aAAa,QAAQ,eAAe;IACpC;IACA;IACA,CAAC;;EAGH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAGL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAGlC,OAAI;IACH,MAAM,EAAE,MAAM,SAAS,MAAM,YAC5B,kBACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,QAAI,CAAC,MAAM;AACV,YAAO,MAAM,4CAA4C;AACzD,YAAO;;IAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,KAAK;AAEtD,WAAO;KACN,MAAM;MACL,IAAI,KAAK;MACT,MAAM,KAAK;MACX,OAAO,KAAK;MACZ,OAAO,KAAK,QAAQ,WAAW,KAAK,QAAQ;MAC5C,eAAe,KAAK,kBAAkB;MACtC,GAAG;MACH;KACD,MAAM;KACN;YACO,OAAO;AACf,WAAO,MAAM,8CAA8C,MAAM;AACjE,WAAO;;;EAIT;EACA"}
1
+ {"version":3,"file":"salesforce.mjs","names":[],"sources":["../../src/social-providers/salesforce.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport { logger } from \"../env\";\nimport { BetterAuthError } from \"../error\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface SalesforceProfile {\n\tsub: string;\n\tuser_id: string;\n\torganization_id: string;\n\tpreferred_username?: string | undefined;\n\temail: string;\n\temail_verified?: boolean | undefined;\n\tname: string;\n\tgiven_name?: string | undefined;\n\tfamily_name?: string | undefined;\n\tzoneinfo?: string | undefined;\n\tphotos?:\n\t\t| {\n\t\t\t\tpicture?: string;\n\t\t\t\tthumbnail?: string;\n\t\t }\n\t\t| undefined;\n}\n\nexport interface SalesforceOptions extends ProviderOptions<SalesforceProfile> {\n\tclientId: string;\n\tenvironment?: (\"sandbox\" | \"production\") | undefined;\n\tloginUrl?: string | undefined;\n\t/**\n\t * Override the redirect URI if auto-detection fails.\n\t * Should match the Callback URL configured in your Salesforce Connected App.\n\t * @example \"http://localhost:3000/api/auth/callback/salesforce\"\n\t */\n\tredirectURI?: string | undefined;\n}\n\nexport const salesforce = (options: SalesforceOptions) => {\n\tconst environment = options.environment ?? \"production\";\n\tconst isSandbox = environment === \"sandbox\";\n\tconst authorizationEndpoint = options.loginUrl\n\t\t? `https://${options.loginUrl}/services/oauth2/authorize`\n\t\t: isSandbox\n\t\t\t? \"https://test.salesforce.com/services/oauth2/authorize\"\n\t\t\t: \"https://login.salesforce.com/services/oauth2/authorize\";\n\n\tconst tokenEndpoint = options.loginUrl\n\t\t? `https://${options.loginUrl}/services/oauth2/token`\n\t\t: isSandbox\n\t\t\t? \"https://test.salesforce.com/services/oauth2/token\"\n\t\t\t: \"https://login.salesforce.com/services/oauth2/token\";\n\n\tconst userInfoEndpoint = options.loginUrl\n\t\t? `https://${options.loginUrl}/services/oauth2/userinfo`\n\t\t: isSandbox\n\t\t\t? \"https://test.salesforce.com/services/oauth2/userinfo\"\n\t\t\t: \"https://login.salesforce.com/services/oauth2/userinfo\";\n\n\treturn {\n\t\tid: \"salesforce\",\n\t\tname: \"Salesforce\",\n\n\t\tasync createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret are required for Salesforce. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Salesforce\");\n\t\t\t}\n\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"email\", \"profile\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"salesforce\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t});\n\t\t},\n\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { data: user } = await betterFetch<SalesforceProfile>(\n\t\t\t\t\tuserInfoEndpoint,\n\t\t\t\t\t{\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tif (!user) {\n\t\t\t\t\tlogger.error(\"Failed to fetch user info from Salesforce\");\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst userMap = await options.mapProfileToUser?.(user);\n\n\t\t\t\treturn {\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: user.user_id,\n\t\t\t\t\t\tname: user.name,\n\t\t\t\t\t\temail: user.email,\n\t\t\t\t\t\timage: user.photos?.picture || user.photos?.thumbnail,\n\t\t\t\t\t\temailVerified: user.email_verified ?? false,\n\t\t\t\t\t\t...userMap,\n\t\t\t\t\t},\n\t\t\t\t\tdata: user,\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\"Failed to fetch user info from Salesforce:\", error);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t},\n\n\t\toptions,\n\t} satisfies OAuthProvider<SalesforceProfile>;\n};\n"],"mappings":";;;;;;;;;AAyCA,MAAa,cAAc,YAA+B;CAEzD,MAAM,aADc,QAAQ,eAAe,kBACT;CAClC,MAAM,wBAAwB,QAAQ,WACnC,WAAW,QAAQ,SAAS,8BAC5B,YACC,0DACA;CAEJ,MAAM,gBAAgB,QAAQ,WAC3B,WAAW,QAAQ,SAAS,0BAC5B,YACC,sDACA;CAEJ,MAAM,mBAAmB,QAAQ,WAC9B,WAAW,QAAQ,SAAS,6BAC5B,YACC,yDACA;AAEJ,QAAO;EACN,IAAI;EACJ,MAAM;EAEN,MAAM,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;AAC1E,OAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,cAAc;AAC/C,WAAO,MACN,qGACA;AACD,UAAM,IAAI,gBAAgB,gCAAgC;;AAE3D,OAAI,CAAC,aACJ,OAAM,IAAI,gBAAgB,0CAA0C;GAGrE,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAS;IAAU;AACjC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AAEnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA;IACA,QAAQ;IACR;IACA;IACA,aAAa,QAAQ,eAAe;IACpC,CAAC;;EAGH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA,aAAa,QAAQ,eAAe;IACpC;IACA;IACA,CAAC;;EAGH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAGL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;AAGlC,OAAI;IACH,MAAM,EAAE,MAAM,SAAS,MAAM,YAC5B,kBACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,QAAI,CAAC,MAAM;AACV,YAAO,MAAM,4CAA4C;AACzD,YAAO;;IAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,KAAK;AAEtD,WAAO;KACN,MAAM;MACL,IAAI,KAAK;MACT,MAAM,KAAK;MACX,OAAO,KAAK;MACZ,OAAO,KAAK,QAAQ,WAAW,KAAK,QAAQ;MAC5C,eAAe,KAAK,kBAAkB;MACtC,GAAG;MACH;KACD,MAAM;KACN;YACO,OAAO;AACf,WAAO,MAAM,8CAA8C,MAAM;AACjE,WAAO;;;EAIT;EACA"}
@@ -2,7 +2,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
2
2
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
3
3
  import "../oauth2/index.mjs";
4
4
  import { betterFetch } from "@better-fetch/fetch";
5
-
6
5
  //#region src/social-providers/slack.ts
7
6
  const slack = (options) => {
8
7
  const tokenEndpoint = "https://slack.com/api/openid.connect.token";
@@ -64,7 +63,7 @@ const slack = (options) => {
64
63
  options
65
64
  };
66
65
  };
67
-
68
66
  //#endregion
69
67
  export { slack };
68
+
70
69
  //# sourceMappingURL=slack.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"slack.mjs","names":[],"sources":["../../src/social-providers/slack.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { refreshAccessToken, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface SlackProfile extends Record<string, any> {\n\tok: boolean;\n\tsub: string;\n\t\"https://slack.com/user_id\": string;\n\t\"https://slack.com/team_id\": string;\n\temail: string;\n\temail_verified: boolean;\n\tdate_email_verified: number;\n\tname: string;\n\tpicture: string;\n\tgiven_name: string;\n\tfamily_name: string;\n\tlocale: string;\n\t\"https://slack.com/team_name\": string;\n\t\"https://slack.com/team_domain\": string;\n\t\"https://slack.com/user_image_24\": string;\n\t\"https://slack.com/user_image_32\": string;\n\t\"https://slack.com/user_image_48\": string;\n\t\"https://slack.com/user_image_72\": string;\n\t\"https://slack.com/user_image_192\": string;\n\t\"https://slack.com/user_image_512\": string;\n\t\"https://slack.com/team_image_34\": string;\n\t\"https://slack.com/team_image_44\": string;\n\t\"https://slack.com/team_image_68\": string;\n\t\"https://slack.com/team_image_88\": string;\n\t\"https://slack.com/team_image_102\": string;\n\t\"https://slack.com/team_image_132\": string;\n\t\"https://slack.com/team_image_230\": string;\n\t\"https://slack.com/team_image_default\": boolean;\n}\n\nexport interface SlackOptions extends ProviderOptions<SlackProfile> {\n\tclientId: string;\n}\n\nexport const slack = (options: SlackOptions) => {\n\tconst tokenEndpoint = \"https://slack.com/api/openid.connect.token\";\n\treturn {\n\t\tid: \"slack\",\n\t\tname: \"Slack\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\"];\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tconst url = new URL(\"https://slack.com/openid/connect/authorize\");\n\t\t\turl.searchParams.set(\"scope\", _scopes.join(\" \"));\n\t\t\turl.searchParams.set(\"response_type\", \"code\");\n\t\t\turl.searchParams.set(\"client_id\", options.clientId);\n\t\t\turl.searchParams.set(\"redirect_uri\", options.redirectURI || redirectURI);\n\t\t\turl.searchParams.set(\"state\", state);\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<SlackProfile>(\n\t\t\t\t\"https://slack.com/api/openid.connect.userInfo\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile[\"https://slack.com/user_id\"],\n\t\t\t\t\tname: profile.name || \"\",\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\temailVerified: profile.email_verified,\n\t\t\t\t\timage: profile.picture || profile[\"https://slack.com/user_image_512\"],\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<SlackProfile>;\n};\n"],"mappings":";;;;;;AAuCA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAW;IAAQ;AACjC,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;GACjD,MAAM,MAAM,IAAI,IAAI,6CAA6C;AACjE,OAAI,aAAa,IAAI,SAAS,QAAQ,KAAK,IAAI,CAAC;AAChD,OAAI,aAAa,IAAI,iBAAiB,OAAO;AAC7C,OAAI,aAAa,IAAI,aAAa,QAAQ,SAAS;AACnD,OAAI,aAAa,IAAI,gBAAgB,QAAQ,eAAe,YAAY;AACxE,OAAI,aAAa,IAAI,SAAS,MAAM;AACpC,UAAO;;EAER,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,iDACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,QAAQ;KACtB,OAAO,QAAQ;KACf,eAAe,QAAQ;KACvB,OAAO,QAAQ,WAAW,QAAQ;KAClC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"slack.mjs","names":[],"sources":["../../src/social-providers/slack.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { refreshAccessToken, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface SlackProfile extends Record<string, any> {\n\tok: boolean;\n\tsub: string;\n\t\"https://slack.com/user_id\": string;\n\t\"https://slack.com/team_id\": string;\n\temail: string;\n\temail_verified: boolean;\n\tdate_email_verified: number;\n\tname: string;\n\tpicture: string;\n\tgiven_name: string;\n\tfamily_name: string;\n\tlocale: string;\n\t\"https://slack.com/team_name\": string;\n\t\"https://slack.com/team_domain\": string;\n\t\"https://slack.com/user_image_24\": string;\n\t\"https://slack.com/user_image_32\": string;\n\t\"https://slack.com/user_image_48\": string;\n\t\"https://slack.com/user_image_72\": string;\n\t\"https://slack.com/user_image_192\": string;\n\t\"https://slack.com/user_image_512\": string;\n\t\"https://slack.com/team_image_34\": string;\n\t\"https://slack.com/team_image_44\": string;\n\t\"https://slack.com/team_image_68\": string;\n\t\"https://slack.com/team_image_88\": string;\n\t\"https://slack.com/team_image_102\": string;\n\t\"https://slack.com/team_image_132\": string;\n\t\"https://slack.com/team_image_230\": string;\n\t\"https://slack.com/team_image_default\": boolean;\n}\n\nexport interface SlackOptions extends ProviderOptions<SlackProfile> {\n\tclientId: string;\n}\n\nexport const slack = (options: SlackOptions) => {\n\tconst tokenEndpoint = \"https://slack.com/api/openid.connect.token\";\n\treturn {\n\t\tid: \"slack\",\n\t\tname: \"Slack\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope\n\t\t\t\t? []\n\t\t\t\t: [\"openid\", \"profile\", \"email\"];\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tconst url = new URL(\"https://slack.com/openid/connect/authorize\");\n\t\t\turl.searchParams.set(\"scope\", _scopes.join(\" \"));\n\t\t\turl.searchParams.set(\"response_type\", \"code\");\n\t\t\turl.searchParams.set(\"client_id\", options.clientId);\n\t\t\turl.searchParams.set(\"redirect_uri\", options.redirectURI || redirectURI);\n\t\t\turl.searchParams.set(\"state\", state);\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<SlackProfile>(\n\t\t\t\t\"https://slack.com/api/openid.connect.userInfo\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile[\"https://slack.com/user_id\"],\n\t\t\t\t\tname: profile.name || \"\",\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\temailVerified: profile.email_verified,\n\t\t\t\t\timage: profile.picture || profile[\"https://slack.com/user_image_512\"],\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<SlackProfile>;\n};\n"],"mappings":";;;;;AAuCA,MAAa,SAAS,YAA0B;CAC/C,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,eAAe;GACtD,MAAM,UAAU,QAAQ,sBACrB,EAAE,GACF;IAAC;IAAU;IAAW;IAAQ;AACjC,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;GACjD,MAAM,MAAM,IAAI,IAAI,6CAA6C;AACjE,OAAI,aAAa,IAAI,SAAS,QAAQ,KAAK,IAAI,CAAC;AAChD,OAAI,aAAa,IAAI,iBAAiB,OAAO;AAC7C,OAAI,aAAa,IAAI,aAAa,QAAQ,SAAS;AACnD,OAAI,aAAa,IAAI,gBAAgB,QAAQ,eAAe,YAAY;AACxE,OAAI,aAAa,IAAI,SAAS,MAAM;AACpC,UAAO;;EAER,2BAA2B,OAAO,EAAE,MAAM,kBAAkB;AAC3D,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,iDACA,EACC,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B,EACD,CACD;AAED,OAAI,MACH,QAAO;GAGR,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ,QAAQ;KACtB,OAAO,QAAQ;KACf,eAAe,QAAQ;KACvB,OAAO,QAAQ,WAAW,QAAQ;KAClC,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
@@ -3,7 +3,6 @@ import { refreshAccessToken } from "../oauth2/refresh-access-token.mjs";
3
3
  import { validateAuthorizationCode } from "../oauth2/validate-authorization-code.mjs";
4
4
  import "../oauth2/index.mjs";
5
5
  import { betterFetch } from "@better-fetch/fetch";
6
-
7
6
  //#region src/social-providers/spotify.ts
8
7
  const spotify = (options) => {
9
8
  const tokenEndpoint = "https://accounts.spotify.com/api/token";
@@ -67,7 +66,7 @@ const spotify = (options) => {
67
66
  options
68
67
  };
69
68
  };
70
-
71
69
  //#endregion
72
70
  export { spotify };
71
+
73
72
  //# sourceMappingURL=spotify.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"spotify.mjs","names":[],"sources":["../../src/social-providers/spotify.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface SpotifyProfile {\n\tid: string;\n\tdisplay_name: string;\n\temail: string;\n\timages: {\n\t\turl: string;\n\t}[];\n}\n\nexport interface SpotifyOptions extends ProviderOptions<SpotifyProfile> {\n\tclientId: string;\n}\n\nexport const spotify = (options: SpotifyOptions) => {\n\tconst tokenEndpoint = \"https://accounts.spotify.com/api/token\";\n\treturn {\n\t\tid: \"spotify\",\n\t\tname: \"Spotify\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"user-read-email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"spotify\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://accounts.spotify.com/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<SpotifyProfile>(\n\t\t\t\t\"https://api.spotify.com/v1/me\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.display_name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.images[0]?.url,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<SpotifyProfile>;\n};\n"],"mappings":";;;;;;;AAqBA,MAAa,WAAW,YAA4B;CACnD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;GACpE,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,kBAAkB;AACtE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,iCACA;IACC,QAAQ;IACR,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B;IACD,CACD;AACD,OAAI,MACH,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,OAAO,QAAQ,OAAO,IAAI;KAC1B,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}
1
+ {"version":3,"file":"spotify.mjs","names":[],"sources":["../../src/social-providers/spotify.ts"],"sourcesContent":["import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport {\n\tcreateAuthorizationURL,\n\trefreshAccessToken,\n\tvalidateAuthorizationCode,\n} from \"../oauth2\";\n\nexport interface SpotifyProfile {\n\tid: string;\n\tdisplay_name: string;\n\temail: string;\n\timages: {\n\t\turl: string;\n\t}[];\n}\n\nexport interface SpotifyOptions extends ProviderOptions<SpotifyProfile> {\n\tclientId: string;\n}\n\nexport const spotify = (options: SpotifyOptions) => {\n\tconst tokenEndpoint = \"https://accounts.spotify.com/api/token\";\n\treturn {\n\t\tid: \"spotify\",\n\t\tname: \"Spotify\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.disableDefaultScope ? [] : [\"user-read-email\"];\n\t\t\tif (options.scope) _scopes.push(...options.scope);\n\t\t\tif (scopes) _scopes.push(...scopes);\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"spotify\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://accounts.spotify.com/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\trefreshAccessToken: options.refreshAccessToken\n\t\t\t? options.refreshAccessToken\n\t\t\t: async (refreshToken) => {\n\t\t\t\t\treturn refreshAccessToken({\n\t\t\t\t\t\trefreshToken,\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tclientId: options.clientId,\n\t\t\t\t\t\t\tclientKey: options.clientKey,\n\t\t\t\t\t\t\tclientSecret: options.clientSecret,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttokenEndpoint,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (options.getUserInfo) {\n\t\t\t\treturn options.getUserInfo(token);\n\t\t\t}\n\t\t\tconst { data: profile, error } = await betterFetch<SpotifyProfile>(\n\t\t\t\t\"https://api.spotify.com/v1/me\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst userMap = await options.mapProfileToUser?.(profile);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.display_name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.images[0]?.url,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t\t...userMap,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t\toptions,\n\t} satisfies OAuthProvider<SpotifyProfile>;\n};\n"],"mappings":";;;;;;AAqBA,MAAa,WAAW,YAA4B;CACnD,MAAM,gBAAgB;AACtB,QAAO;EACN,IAAI;EACJ,MAAM;EACN,uBAAuB,EAAE,OAAO,QAAQ,cAAc,eAAe;GACpE,MAAM,UAAU,QAAQ,sBAAsB,EAAE,GAAG,CAAC,kBAAkB;AACtE,OAAI,QAAQ,MAAO,SAAQ,KAAK,GAAG,QAAQ,MAAM;AACjD,OAAI,OAAQ,SAAQ,KAAK,GAAG,OAAO;AACnC,UAAO,uBAAuB;IAC7B,IAAI;IACJ;IACA,uBAAuB;IACvB,QAAQ;IACR;IACA;IACA;IACA,CAAC;;EAEH,2BAA2B,OAAO,EAAE,MAAM,cAAc,kBAAkB;AACzE,UAAO,0BAA0B;IAChC;IACA;IACA;IACA;IACA;IACA,CAAC;;EAEH,oBAAoB,QAAQ,qBACzB,QAAQ,qBACR,OAAO,iBAAiB;AACxB,UAAO,mBAAmB;IACzB;IACA,SAAS;KACR,UAAU,QAAQ;KAClB,WAAW,QAAQ;KACnB,cAAc,QAAQ;KACtB;IACD;IACA,CAAC;;EAEL,MAAM,YAAY,OAAO;AACxB,OAAI,QAAQ,YACX,QAAO,QAAQ,YAAY,MAAM;GAElC,MAAM,EAAE,MAAM,SAAS,UAAU,MAAM,YACtC,iCACA;IACC,QAAQ;IACR,SAAS,EACR,eAAe,UAAU,MAAM,eAC/B;IACD,CACD;AACD,OAAI,MACH,QAAO;GAER,MAAM,UAAU,MAAM,QAAQ,mBAAmB,QAAQ;AACzD,UAAO;IACN,MAAM;KACL,IAAI,QAAQ;KACZ,MAAM,QAAQ;KACd,OAAO,QAAQ;KACf,OAAO,QAAQ,OAAO,IAAI;KAC1B,eAAe;KACf,GAAG;KACH;IACD,MAAM;IACN;;EAEF;EACA"}