better-auth 1.4.9 → 1.5.0-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 (228) hide show
  1. package/dist/api/index.d.mts +396 -395
  2. package/dist/api/index.mjs +6 -4
  3. package/dist/api/index.mjs.map +1 -1
  4. package/dist/api/middlewares/origin-check.d.mts +3 -3
  5. package/dist/api/middlewares/origin-check.mjs +14 -4
  6. package/dist/api/middlewares/origin-check.mjs.map +1 -1
  7. package/dist/api/routes/account.d.mts +11 -11
  8. package/dist/api/routes/account.mjs +59 -30
  9. package/dist/api/routes/account.mjs.map +1 -1
  10. package/dist/api/routes/callback.d.mts +2 -2
  11. package/dist/api/routes/email-verification.d.mts +4 -4
  12. package/dist/api/routes/email-verification.mjs +14 -14
  13. package/dist/api/routes/email-verification.mjs.map +1 -1
  14. package/dist/api/routes/error.d.mts +2 -2
  15. package/dist/api/routes/ok.d.mts +2 -2
  16. package/dist/api/routes/reset-password.d.mts +5 -5
  17. package/dist/api/routes/reset-password.mjs +9 -7
  18. package/dist/api/routes/reset-password.mjs.map +1 -1
  19. package/dist/api/routes/session.d.mts +14 -14
  20. package/dist/api/routes/session.mjs +31 -11
  21. package/dist/api/routes/session.mjs.map +1 -1
  22. package/dist/api/routes/sign-in.d.mts +3 -3
  23. package/dist/api/routes/sign-in.mjs +22 -17
  24. package/dist/api/routes/sign-in.mjs.map +1 -1
  25. package/dist/api/routes/sign-out.d.mts +2 -2
  26. package/dist/api/routes/sign-up.d.mts +2 -2
  27. package/dist/api/routes/sign-up.mjs +15 -12
  28. package/dist/api/routes/sign-up.mjs.map +1 -1
  29. package/dist/api/routes/update-user.d.mts +13 -13
  30. package/dist/api/routes/update-user.mjs +29 -24
  31. package/dist/api/routes/update-user.mjs.map +1 -1
  32. package/dist/api/to-auth-endpoints.mjs +7 -6
  33. package/dist/api/to-auth-endpoints.mjs.map +1 -1
  34. package/dist/client/lynx/index.d.mts +15 -15
  35. package/dist/client/plugins/index.d.mts +12 -2
  36. package/dist/client/plugins/index.mjs +11 -1
  37. package/dist/client/react/index.d.mts +13 -13
  38. package/dist/client/solid/index.d.mts +13 -13
  39. package/dist/client/svelte/index.d.mts +15 -15
  40. package/dist/client/types.d.mts +4 -1
  41. package/dist/client/vue/index.d.mts +13 -13
  42. package/dist/context/create-context.mjs +2 -2
  43. package/dist/context/create-context.mjs.map +1 -1
  44. package/dist/context/helpers.mjs +2 -2
  45. package/dist/context/helpers.mjs.map +1 -1
  46. package/dist/db/field.d.mts +6 -6
  47. package/dist/db/schema.mjs +14 -5
  48. package/dist/db/schema.mjs.map +1 -1
  49. package/dist/index.d.mts +1 -1
  50. package/dist/integrations/next-js.d.mts +4 -4
  51. package/dist/integrations/svelte-kit.d.mts +2 -2
  52. package/dist/integrations/tanstack-start.d.mts +4 -4
  53. package/dist/oauth2/link-account.mjs +3 -2
  54. package/dist/oauth2/link-account.mjs.map +1 -1
  55. package/dist/oauth2/state.mjs +3 -3
  56. package/dist/oauth2/state.mjs.map +1 -1
  57. package/dist/plugins/admin/admin.d.mts +200 -137
  58. package/dist/plugins/admin/admin.mjs +3 -4
  59. package/dist/plugins/admin/admin.mjs.map +1 -1
  60. package/dist/plugins/admin/client.d.mts +87 -0
  61. package/dist/plugins/admin/client.mjs +3 -1
  62. package/dist/plugins/admin/client.mjs.map +1 -1
  63. package/dist/plugins/admin/error-codes.d.mts +90 -0
  64. package/dist/plugins/admin/error-codes.mjs.map +1 -1
  65. package/dist/plugins/admin/routes.mjs +40 -46
  66. package/dist/plugins/admin/routes.mjs.map +1 -1
  67. package/dist/plugins/anonymous/client.d.mts +19 -0
  68. package/dist/plugins/anonymous/client.mjs +4 -1
  69. package/dist/plugins/anonymous/client.mjs.map +1 -1
  70. package/dist/plugins/anonymous/error-codes.d.mts +22 -0
  71. package/dist/plugins/anonymous/index.d.mts +21 -9
  72. package/dist/plugins/anonymous/index.mjs +5 -5
  73. package/dist/plugins/anonymous/index.mjs.map +1 -1
  74. package/dist/plugins/api-key/client.d.mts +103 -0
  75. package/dist/plugins/api-key/client.mjs +4 -1
  76. package/dist/plugins/api-key/client.mjs.map +1 -1
  77. package/dist/plugins/api-key/error-codes.d.mts +106 -0
  78. package/dist/plugins/api-key/error-codes.mjs +34 -0
  79. package/dist/plugins/api-key/error-codes.mjs.map +1 -0
  80. package/dist/plugins/api-key/index.d.mts +181 -112
  81. package/dist/plugins/api-key/index.mjs +7 -34
  82. package/dist/plugins/api-key/index.mjs.map +1 -1
  83. package/dist/plugins/api-key/rate-limit.mjs +3 -2
  84. package/dist/plugins/api-key/rate-limit.mjs.map +1 -1
  85. package/dist/plugins/api-key/routes/create-api-key.mjs +19 -17
  86. package/dist/plugins/api-key/routes/create-api-key.mjs.map +1 -1
  87. package/dist/plugins/api-key/routes/delete-api-key.mjs +7 -5
  88. package/dist/plugins/api-key/routes/delete-api-key.mjs.map +1 -1
  89. package/dist/plugins/api-key/routes/get-api-key.mjs +5 -3
  90. package/dist/plugins/api-key/routes/get-api-key.mjs.map +1 -1
  91. package/dist/plugins/api-key/routes/update-api-key.mjs +18 -16
  92. package/dist/plugins/api-key/routes/update-api-key.mjs.map +1 -1
  93. package/dist/plugins/api-key/routes/verify-api-key.mjs +16 -35
  94. package/dist/plugins/api-key/routes/verify-api-key.mjs.map +1 -1
  95. package/dist/plugins/bearer/index.d.mts +3 -3
  96. package/dist/plugins/captcha/index.d.mts +2 -2
  97. package/dist/plugins/captcha/index.mjs +3 -3
  98. package/dist/plugins/captcha/index.mjs.map +1 -1
  99. package/dist/plugins/captcha/verify-handlers/captchafox.mjs +2 -2
  100. package/dist/plugins/captcha/verify-handlers/captchafox.mjs.map +1 -1
  101. package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs +2 -2
  102. package/dist/plugins/captcha/verify-handlers/cloudflare-turnstile.mjs.map +1 -1
  103. package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs +2 -2
  104. package/dist/plugins/captcha/verify-handlers/google-recaptcha.mjs.map +1 -1
  105. package/dist/plugins/captcha/verify-handlers/h-captcha.mjs +2 -2
  106. package/dist/plugins/captcha/verify-handlers/h-captcha.mjs.map +1 -1
  107. package/dist/plugins/custom-session/index.d.mts +5 -5
  108. package/dist/plugins/device-authorization/index.d.mts +54 -18
  109. package/dist/plugins/device-authorization/routes.mjs +18 -18
  110. package/dist/plugins/device-authorization/routes.mjs.map +1 -1
  111. package/dist/plugins/email-otp/client.d.mts +15 -0
  112. package/dist/plugins/email-otp/client.mjs +4 -1
  113. package/dist/plugins/email-otp/client.mjs.map +1 -1
  114. package/dist/plugins/email-otp/error-codes.d.mts +18 -0
  115. package/dist/plugins/email-otp/error-codes.mjs +12 -0
  116. package/dist/plugins/email-otp/error-codes.mjs.map +1 -0
  117. package/dist/plugins/email-otp/index.d.mts +64 -55
  118. package/dist/plugins/email-otp/index.mjs +4 -3
  119. package/dist/plugins/email-otp/index.mjs.map +1 -1
  120. package/dist/plugins/email-otp/routes.mjs +30 -35
  121. package/dist/plugins/email-otp/routes.mjs.map +1 -1
  122. package/dist/plugins/generic-oauth/client.d.mts +27 -0
  123. package/dist/plugins/generic-oauth/client.mjs +4 -1
  124. package/dist/plugins/generic-oauth/client.mjs.map +1 -1
  125. package/dist/plugins/generic-oauth/error-codes.d.mts +30 -0
  126. package/dist/plugins/generic-oauth/index.d.mts +55 -37
  127. package/dist/plugins/generic-oauth/index.mjs +4 -4
  128. package/dist/plugins/generic-oauth/index.mjs.map +1 -1
  129. package/dist/plugins/generic-oauth/routes.mjs +11 -12
  130. package/dist/plugins/generic-oauth/routes.mjs.map +1 -1
  131. package/dist/plugins/haveibeenpwned/index.d.mts +7 -4
  132. package/dist/plugins/haveibeenpwned/index.mjs +5 -4
  133. package/dist/plugins/haveibeenpwned/index.mjs.map +1 -1
  134. package/dist/plugins/index.d.mts +4 -2
  135. package/dist/plugins/index.mjs +6 -4
  136. package/dist/plugins/jwt/index.d.mts +9 -9
  137. package/dist/plugins/jwt/index.mjs +2 -2
  138. package/dist/plugins/jwt/index.mjs.map +1 -1
  139. package/dist/plugins/last-login-method/index.d.mts +4 -4
  140. package/dist/plugins/magic-link/index.d.mts +4 -4
  141. package/dist/plugins/mcp/authorize.mjs +1 -1
  142. package/dist/plugins/mcp/authorize.mjs.map +1 -1
  143. package/dist/plugins/mcp/index.d.mts +10 -10
  144. package/dist/plugins/multi-session/client.d.mts +10 -14
  145. package/dist/plugins/multi-session/client.mjs +5 -2
  146. package/dist/plugins/multi-session/client.mjs.map +1 -1
  147. package/dist/plugins/multi-session/error-codes.d.mts +10 -0
  148. package/dist/plugins/multi-session/error-codes.mjs +8 -0
  149. package/dist/plugins/multi-session/error-codes.mjs.map +1 -0
  150. package/dist/plugins/multi-session/index.d.mts +18 -14
  151. package/dist/plugins/multi-session/index.mjs +6 -7
  152. package/dist/plugins/multi-session/index.mjs.map +1 -1
  153. package/dist/plugins/oauth-proxy/index.d.mts +8 -8
  154. package/dist/plugins/oidc-provider/authorize.mjs +1 -1
  155. package/dist/plugins/oidc-provider/authorize.mjs.map +1 -1
  156. package/dist/plugins/oidc-provider/error.mjs +1 -1
  157. package/dist/plugins/oidc-provider/error.mjs.map +1 -1
  158. package/dist/plugins/oidc-provider/index.d.mts +15 -15
  159. package/dist/plugins/one-tap/client.d.mts +2 -2
  160. package/dist/plugins/one-tap/index.d.mts +2 -2
  161. package/dist/plugins/one-time-token/index.d.mts +5 -5
  162. package/dist/plugins/open-api/index.d.mts +3 -3
  163. package/dist/plugins/organization/client.d.mts +229 -2
  164. package/dist/plugins/organization/client.mjs +3 -1
  165. package/dist/plugins/organization/client.mjs.map +1 -1
  166. package/dist/plugins/organization/error-codes.d.mts +224 -56
  167. package/dist/plugins/organization/organization.d.mts +7 -7
  168. package/dist/plugins/organization/organization.mjs +4 -4
  169. package/dist/plugins/organization/organization.mjs.map +1 -1
  170. package/dist/plugins/organization/routes/crud-access-control.d.mts +22 -22
  171. package/dist/plugins/organization/routes/crud-access-control.mjs +40 -39
  172. package/dist/plugins/organization/routes/crud-access-control.mjs.map +1 -1
  173. package/dist/plugins/organization/routes/crud-invites.d.mts +58 -58
  174. package/dist/plugins/organization/routes/crud-invites.mjs +42 -40
  175. package/dist/plugins/organization/routes/crud-invites.mjs.map +1 -1
  176. package/dist/plugins/organization/routes/crud-members.d.mts +67 -67
  177. package/dist/plugins/organization/routes/crud-members.mjs +41 -54
  178. package/dist/plugins/organization/routes/crud-members.mjs.map +1 -1
  179. package/dist/plugins/organization/routes/crud-org.d.mts +51 -51
  180. package/dist/plugins/organization/routes/crud-org.mjs +28 -25
  181. package/dist/plugins/organization/routes/crud-org.mjs.map +1 -1
  182. package/dist/plugins/organization/routes/crud-team.d.mts +77 -77
  183. package/dist/plugins/organization/routes/crud-team.mjs +41 -47
  184. package/dist/plugins/organization/routes/crud-team.mjs.map +1 -1
  185. package/dist/plugins/phone-number/client.d.mts +51 -0
  186. package/dist/plugins/phone-number/client.mjs +4 -1
  187. package/dist/plugins/phone-number/client.mjs.map +1 -1
  188. package/dist/plugins/phone-number/error-codes.d.mts +54 -0
  189. package/dist/plugins/phone-number/index.d.mts +81 -45
  190. package/dist/plugins/phone-number/index.mjs +2 -2
  191. package/dist/plugins/phone-number/index.mjs.map +1 -1
  192. package/dist/plugins/phone-number/routes.mjs +27 -28
  193. package/dist/plugins/phone-number/routes.mjs.map +1 -1
  194. package/dist/plugins/siwe/index.d.mts +3 -3
  195. package/dist/plugins/siwe/index.mjs +7 -6
  196. package/dist/plugins/siwe/index.mjs.map +1 -1
  197. package/dist/plugins/two-factor/backup-codes/index.mjs +7 -7
  198. package/dist/plugins/two-factor/backup-codes/index.mjs.map +1 -1
  199. package/dist/plugins/two-factor/client.d.mts +39 -0
  200. package/dist/plugins/two-factor/client.mjs +4 -1
  201. package/dist/plugins/two-factor/client.mjs.map +1 -1
  202. package/dist/plugins/two-factor/error-code.d.mts +36 -9
  203. package/dist/plugins/two-factor/index.d.mts +54 -27
  204. package/dist/plugins/two-factor/index.mjs +4 -5
  205. package/dist/plugins/two-factor/index.mjs.map +1 -1
  206. package/dist/plugins/two-factor/otp/index.mjs +8 -6
  207. package/dist/plugins/two-factor/otp/index.mjs.map +1 -1
  208. package/dist/plugins/two-factor/totp/index.mjs +16 -8
  209. package/dist/plugins/two-factor/totp/index.mjs.map +1 -1
  210. package/dist/plugins/two-factor/verify-two-factor.mjs +9 -6
  211. package/dist/plugins/two-factor/verify-two-factor.mjs.map +1 -1
  212. package/dist/plugins/username/client.d.mts +35 -0
  213. package/dist/plugins/username/client.mjs +4 -1
  214. package/dist/plugins/username/client.mjs.map +1 -1
  215. package/dist/plugins/username/error-codes.d.mts +32 -8
  216. package/dist/plugins/username/index.d.mts +41 -17
  217. package/dist/plugins/username/index.mjs +21 -31
  218. package/dist/plugins/username/index.mjs.map +1 -1
  219. package/dist/plugins/username/schema.d.mts +3 -3
  220. package/dist/test-utils/test-instance.d.mts +1349 -1198
  221. package/dist/utils/is-api-error.d.mts +7 -0
  222. package/dist/utils/is-api-error.mjs +11 -0
  223. package/dist/utils/is-api-error.mjs.map +1 -0
  224. package/dist/utils/password.mjs +3 -3
  225. package/dist/utils/password.mjs.map +1 -1
  226. package/dist/utils/plugin-helper.mjs +2 -2
  227. package/dist/utils/plugin-helper.mjs.map +1 -1
  228. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"reset-password.mjs","names":[],"sources":["../../../src/api/routes/reset-password.ts"],"sourcesContent":["import type { AuthContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport { generateId } from \"../../utils\";\nimport { getDate } from \"../../utils/date\";\nimport { originCheck } from \"../middlewares\";\n\nfunction redirectError(\n\tctx: AuthContext,\n\tcallbackURL: string | undefined,\n\tquery?: Record<string, string> | undefined,\n): string {\n\tconst url = callbackURL\n\t\t? new URL(callbackURL, ctx.baseURL)\n\t\t: new URL(`${ctx.baseURL}/error`);\n\tif (query)\n\t\tObject.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));\n\treturn url.href;\n}\n\nfunction redirectCallback(\n\tctx: AuthContext,\n\tcallbackURL: string,\n\tquery?: Record<string, string> | undefined,\n): string {\n\tconst url = new URL(callbackURL, ctx.baseURL);\n\tif (query)\n\t\tObject.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));\n\treturn url.href;\n}\n\nexport const requestPasswordReset = createAuthEndpoint(\n\t\"/request-password-reset\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * The email address of the user to send a password reset email to.\n\t\t\t */\n\t\t\temail: z.email().meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"The email address of the user to send a password reset email to\",\n\t\t\t}),\n\t\t\t/**\n\t\t\t * The URL to redirect the user to reset their password.\n\t\t\t * If the token isn't valid or expired, it'll be redirected with a query parameter `?\n\t\t\t * error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?\n\t\t\t * token=VALID_TOKEN\n\t\t\t */\n\t\t\tredirectTo: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The URL to redirect the user to reset their password. If the token isn't valid or expired, it'll be redirected with a query parameter `?error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?token=VALID_TOKEN\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"requestPasswordReset\",\n\t\t\t\tdescription: \"Send a password reset email to the user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.emailAndPassword?.sendResetPassword) {\n\t\t\tctx.context.logger.error(\n\t\t\t\t\"Reset password isn't enabled.Please pass an emailAndPassword.sendResetPassword function in your auth config!\",\n\t\t\t);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Reset password isn't enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email, redirectTo } = ctx.body;\n\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\tincludeAccounts: true,\n\t\t});\n\t\tif (!user) {\n\t\t\t/**\n\t\t\t * We simulate the verification token generation and the database lookup\n\t\t\t * to mitigate timing attacks.\n\t\t\t */\n\t\t\tgenerateId(24);\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\"dummy-verification-token\",\n\t\t\t);\n\t\t\tctx.context.logger.error(\"Reset Password: User not found\", { email });\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t\tmessage:\n\t\t\t\t\t\"If this email exists in our system, check your email for the reset link\",\n\t\t\t});\n\t\t}\n\t\tconst defaultExpiresIn = 60 * 60 * 1;\n\t\tconst expiresAt = getDate(\n\t\t\tctx.context.options.emailAndPassword.resetPasswordTokenExpiresIn ||\n\t\t\t\tdefaultExpiresIn,\n\t\t\t\"sec\",\n\t\t);\n\t\tconst verificationToken = generateId(24);\n\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\tvalue: user.user.id,\n\t\t\tidentifier: `reset-password:${verificationToken}`,\n\t\t\texpiresAt,\n\t\t});\n\t\tconst callbackURL = redirectTo ? encodeURIComponent(redirectTo) : \"\";\n\t\tconst url = `${ctx.context.baseURL}/reset-password/${verificationToken}?callbackURL=${callbackURL}`;\n\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\tctx.context.options.emailAndPassword.sendResetPassword(\n\t\t\t\t{\n\t\t\t\t\tuser: user.user,\n\t\t\t\t\turl,\n\t\t\t\t\ttoken: verificationToken,\n\t\t\t\t},\n\t\t\t\tctx.request,\n\t\t\t),\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t\tmessage:\n\t\t\t\t\"If this email exists in our system, check your email for the reset link\",\n\t\t});\n\t},\n);\n\nexport const requestPasswordResetCallback = createAuthEndpoint(\n\t\"/reset-password/:token\",\n\t{\n\t\tmethod: \"GET\",\n\t\toperationId: \"forgetPasswordCallback\",\n\t\tquery: z.object({\n\t\t\tcallbackURL: z.string().meta({\n\t\t\t\tdescription: \"The URL to redirect the user to reset their password\",\n\t\t\t}),\n\t\t}),\n\t\tuse: [originCheck((ctx) => ctx.query.callbackURL)],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"resetPasswordCallback\",\n\t\t\t\tdescription: \"Redirects the user to the callback URL with the token\",\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"token\",\n\t\t\t\t\t\tin: \"path\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription: \"The token to reset the password\",\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"callbackURL\",\n\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription: \"The URL to redirect the user to reset their password\",\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst { token } = ctx.params;\n\t\tconst { callbackURL } = ctx.query;\n\t\tif (!token || !callbackURL) {\n\t\t\tthrow ctx.redirect(\n\t\t\t\tredirectError(ctx.context, callbackURL, { error: \"INVALID_TOKEN\" }),\n\t\t\t);\n\t\t}\n\t\tconst verification =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t`reset-password:${token}`,\n\t\t\t);\n\t\tif (!verification || verification.expiresAt < new Date()) {\n\t\t\tthrow ctx.redirect(\n\t\t\t\tredirectError(ctx.context, callbackURL, { error: \"INVALID_TOKEN\" }),\n\t\t\t);\n\t\t}\n\n\t\tthrow ctx.redirect(redirectCallback(ctx.context, callbackURL, { token }));\n\t},\n);\n\nexport const resetPassword = createAuthEndpoint(\n\t\"/reset-password\",\n\t{\n\t\tmethod: \"POST\",\n\t\toperationId: \"resetPassword\",\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\ttoken: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\tnewPassword: z.string().meta({\n\t\t\t\tdescription: \"The new password to set\",\n\t\t\t}),\n\t\t\ttoken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The token to reset the password\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"resetPassword\",\n\t\t\t\tdescription: \"Reset the password for a user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst token = ctx.body.token || ctx.query?.token;\n\t\tif (!token) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_TOKEN,\n\t\t\t});\n\t\t}\n\n\t\tconst { newPassword } = ctx.body;\n\n\t\tconst minLength = ctx.context.password?.config.minPasswordLength;\n\t\tconst maxLength = ctx.context.password?.config.maxPasswordLength;\n\t\tif (newPassword.length < minLength) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_SHORT,\n\t\t\t});\n\t\t}\n\t\tif (newPassword.length > maxLength) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.PASSWORD_TOO_LONG,\n\t\t\t});\n\t\t}\n\n\t\tconst id = `reset-password:${token}`;\n\n\t\tconst verification =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(id);\n\t\tif (!verification || verification.expiresAt < new Date()) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: BASE_ERROR_CODES.INVALID_TOKEN,\n\t\t\t});\n\t\t}\n\t\tconst userId = verification.value;\n\t\tconst hashedPassword = await ctx.context.password.hash(newPassword);\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(userId);\n\t\tconst account = accounts.find((ac) => ac.providerId === \"credential\");\n\t\tif (!account) {\n\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\tuserId,\n\t\t\t\tproviderId: \"credential\",\n\t\t\t\tpassword: hashedPassword,\n\t\t\t\taccountId: userId,\n\t\t\t});\n\t\t} else {\n\t\t\tawait ctx.context.internalAdapter.updatePassword(userId, hashedPassword);\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteVerificationValue(verification.id);\n\n\t\tif (ctx.context.options.emailAndPassword?.onPasswordReset) {\n\t\t\tconst user = await ctx.context.internalAdapter.findUserById(userId);\n\t\t\tif (user) {\n\t\t\t\tawait ctx.context.options.emailAndPassword.onPasswordReset(\n\t\t\t\t\t{\n\t\t\t\t\t\tuser,\n\t\t\t\t\t},\n\t\t\t\t\tctx.request,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (ctx.context.options.emailAndPassword?.revokeSessionsOnPasswordReset) {\n\t\t\tawait ctx.context.internalAdapter.deleteSessions(userId);\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"reset-password.mjs","names":[],"sources":["../../../src/api/routes/reset-password.ts"],"sourcesContent":["import type { AuthContext } from \"@better-auth/core\";\nimport { createAuthEndpoint } from \"@better-auth/core/api\";\nimport { APIError, BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport * as z from \"zod\";\nimport { generateId } from \"../../utils\";\nimport { getDate } from \"../../utils/date\";\nimport { originCheck } from \"../middlewares\";\n\nfunction redirectError(\n\tctx: AuthContext,\n\tcallbackURL: string | undefined,\n\tquery?: Record<string, string> | undefined,\n): string {\n\tconst url = callbackURL\n\t\t? new URL(callbackURL, ctx.baseURL)\n\t\t: new URL(`${ctx.baseURL}/error`);\n\tif (query)\n\t\tObject.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));\n\treturn url.href;\n}\n\nfunction redirectCallback(\n\tctx: AuthContext,\n\tcallbackURL: string,\n\tquery?: Record<string, string> | undefined,\n): string {\n\tconst url = new URL(callbackURL, ctx.baseURL);\n\tif (query)\n\t\tObject.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));\n\treturn url.href;\n}\n\nexport const requestPasswordReset = createAuthEndpoint(\n\t\"/request-password-reset\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * The email address of the user to send a password reset email to.\n\t\t\t */\n\t\t\temail: z.email().meta({\n\t\t\t\tdescription:\n\t\t\t\t\t\"The email address of the user to send a password reset email to\",\n\t\t\t}),\n\t\t\t/**\n\t\t\t * The URL to redirect the user to reset their password.\n\t\t\t * If the token isn't valid or expired, it'll be redirected with a query parameter `?\n\t\t\t * error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?\n\t\t\t * token=VALID_TOKEN\n\t\t\t */\n\t\t\tredirectTo: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription:\n\t\t\t\t\t\t\"The URL to redirect the user to reset their password. If the token isn't valid or expired, it'll be redirected with a query parameter `?error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?token=VALID_TOKEN\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"requestPasswordReset\",\n\t\t\t\tdescription: \"Send a password reset email to the user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tmessage: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.emailAndPassword?.sendResetPassword) {\n\t\t\tctx.context.logger.error(\n\t\t\t\t\"Reset password isn't enabled.Please pass an emailAndPassword.sendResetPassword function in your auth config!\",\n\t\t\t);\n\t\t\tthrow APIError.from(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Reset password isn't enabled\",\n\t\t\t\tcode: \"RESET_PASSWORD_DISABLED\",\n\t\t\t});\n\t\t}\n\t\tconst { email, redirectTo } = ctx.body;\n\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\tincludeAccounts: true,\n\t\t});\n\t\tif (!user) {\n\t\t\t/**\n\t\t\t * We simulate the verification token generation and the database lookup\n\t\t\t * to mitigate timing attacks.\n\t\t\t */\n\t\t\tgenerateId(24);\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t\"dummy-verification-token\",\n\t\t\t);\n\t\t\tctx.context.logger.error(\"Reset Password: User not found\", { email });\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t\tmessage:\n\t\t\t\t\t\"If this email exists in our system, check your email for the reset link\",\n\t\t\t});\n\t\t}\n\t\tconst defaultExpiresIn = 60 * 60 * 1;\n\t\tconst expiresAt = getDate(\n\t\t\tctx.context.options.emailAndPassword.resetPasswordTokenExpiresIn ||\n\t\t\t\tdefaultExpiresIn,\n\t\t\t\"sec\",\n\t\t);\n\t\tconst verificationToken = generateId(24);\n\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\tvalue: user.user.id,\n\t\t\tidentifier: `reset-password:${verificationToken}`,\n\t\t\texpiresAt,\n\t\t});\n\t\tconst callbackURL = redirectTo ? encodeURIComponent(redirectTo) : \"\";\n\t\tconst url = `${ctx.context.baseURL}/reset-password/${verificationToken}?callbackURL=${callbackURL}`;\n\t\tawait ctx.context.runInBackgroundOrAwait(\n\t\t\tctx.context.options.emailAndPassword.sendResetPassword(\n\t\t\t\t{\n\t\t\t\t\tuser: user.user,\n\t\t\t\t\turl,\n\t\t\t\t\ttoken: verificationToken,\n\t\t\t\t},\n\t\t\t\tctx.request,\n\t\t\t),\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t\tmessage:\n\t\t\t\t\"If this email exists in our system, check your email for the reset link\",\n\t\t});\n\t},\n);\n\nexport const requestPasswordResetCallback = createAuthEndpoint(\n\t\"/reset-password/:token\",\n\t{\n\t\tmethod: \"GET\",\n\t\toperationId: \"forgetPasswordCallback\",\n\t\tquery: z.object({\n\t\t\tcallbackURL: z.string().meta({\n\t\t\t\tdescription: \"The URL to redirect the user to reset their password\",\n\t\t\t}),\n\t\t}),\n\t\tuse: [originCheck((ctx) => ctx.query.callbackURL)],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"resetPasswordCallback\",\n\t\t\t\tdescription: \"Redirects the user to the callback URL with the token\",\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"token\",\n\t\t\t\t\t\tin: \"path\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription: \"The token to reset the password\",\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"callbackURL\",\n\t\t\t\t\t\tin: \"query\",\n\t\t\t\t\t\trequired: true,\n\t\t\t\t\t\tdescription: \"The URL to redirect the user to reset their password\",\n\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst { token } = ctx.params;\n\t\tconst { callbackURL } = ctx.query;\n\t\tif (!token || !callbackURL) {\n\t\t\tthrow ctx.redirect(\n\t\t\t\tredirectError(ctx.context, callbackURL, { error: \"INVALID_TOKEN\" }),\n\t\t\t);\n\t\t}\n\t\tconst verification =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t`reset-password:${token}`,\n\t\t\t);\n\t\tif (!verification || verification.expiresAt < new Date()) {\n\t\t\tthrow ctx.redirect(\n\t\t\t\tredirectError(ctx.context, callbackURL, { error: \"INVALID_TOKEN\" }),\n\t\t\t);\n\t\t}\n\n\t\tthrow ctx.redirect(redirectCallback(ctx.context, callbackURL, { token }));\n\t},\n);\n\nexport const resetPassword = createAuthEndpoint(\n\t\"/reset-password\",\n\t{\n\t\tmethod: \"POST\",\n\t\toperationId: \"resetPassword\",\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\ttoken: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\tnewPassword: z.string().meta({\n\t\t\t\tdescription: \"The new password to set\",\n\t\t\t}),\n\t\t\ttoken: z\n\t\t\t\t.string()\n\t\t\t\t.meta({\n\t\t\t\t\tdescription: \"The token to reset the password\",\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t}),\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\toperationId: \"resetPassword\",\n\t\t\t\tdescription: \"Reset the password for a user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst token = ctx.body.token || ctx.query?.token;\n\t\tif (!token) {\n\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_TOKEN);\n\t\t}\n\n\t\tconst { newPassword } = ctx.body;\n\n\t\tconst minLength = ctx.context.password?.config.minPasswordLength;\n\t\tconst maxLength = ctx.context.password?.config.maxPasswordLength;\n\t\tif (newPassword.length < minLength) {\n\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.PASSWORD_TOO_SHORT);\n\t\t}\n\t\tif (newPassword.length > maxLength) {\n\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.PASSWORD_TOO_LONG);\n\t\t}\n\n\t\tconst id = `reset-password:${token}`;\n\n\t\tconst verification =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(id);\n\t\tif (!verification || verification.expiresAt < new Date()) {\n\t\t\tthrow APIError.from(\"BAD_REQUEST\", BASE_ERROR_CODES.INVALID_TOKEN);\n\t\t}\n\t\tconst userId = verification.value;\n\t\tconst hashedPassword = await ctx.context.password.hash(newPassword);\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(userId);\n\t\tconst account = accounts.find((ac) => ac.providerId === \"credential\");\n\t\tif (!account) {\n\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\tuserId,\n\t\t\t\tproviderId: \"credential\",\n\t\t\t\tpassword: hashedPassword,\n\t\t\t\taccountId: userId,\n\t\t\t});\n\t\t} else {\n\t\t\tawait ctx.context.internalAdapter.updatePassword(userId, hashedPassword);\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteVerificationValue(verification.id);\n\n\t\tif (ctx.context.options.emailAndPassword?.onPasswordReset) {\n\t\t\tconst user = await ctx.context.internalAdapter.findUserById(userId);\n\t\t\tif (user) {\n\t\t\t\tawait ctx.context.options.emailAndPassword.onPasswordReset(\n\t\t\t\t\t{\n\t\t\t\t\t\tuser,\n\t\t\t\t\t},\n\t\t\t\t\tctx.request,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (ctx.context.options.emailAndPassword?.revokeSessionsOnPasswordReset) {\n\t\t\tawait ctx.context.internalAdapter.deleteSessions(userId);\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n"],"mappings":"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"}
@@ -3,10 +3,10 @@ import { InferSession, InferUser, Session, User } from "../../types/models.mjs";
3
3
  import "../../types/index.mjs";
4
4
  import { BetterAuthOptions, GenericEndpointContext } from "@better-auth/core";
5
5
  import * as z from "zod";
6
- import * as better_call896 from "better-call";
6
+ import * as better_call741 from "better-call";
7
7
 
8
8
  //#region src/api/routes/session.d.ts
9
- declare const getSession: <Option extends BetterAuthOptions>() => better_call896.StrictEndpoint<"/get-session", {
9
+ declare const getSession: <Option extends BetterAuthOptions>() => better_call741.StrictEndpoint<"/get-session", {
10
10
  method: "GET";
11
11
  operationId: string;
12
12
  query: z.ZodOptional<z.ZodObject<{
@@ -56,7 +56,7 @@ declare const getSessionFromCtx: <U extends Record<string, any> = Record<string,
56
56
  /**
57
57
  * The middleware forces the endpoint to require a valid session.
58
58
  */
59
- declare const sessionMiddleware: (inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
59
+ declare const sessionMiddleware: (inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
60
60
  session: {
61
61
  session: Record<string, any> & {
62
62
  id: string;
@@ -84,7 +84,7 @@ declare const sessionMiddleware: (inputContext: better_call896.MiddlewareInputCo
84
84
  * This should be used for sensitive operations like password changes, account deletion, etc.
85
85
  * to ensure that revoked sessions cannot be used even if they're still cached in cookies.
86
86
  */
87
- declare const sensitiveSessionMiddleware: (inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
87
+ declare const sensitiveSessionMiddleware: (inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
88
88
  session: {
89
89
  session: Record<string, any> & {
90
90
  id: string;
@@ -111,7 +111,7 @@ declare const sensitiveSessionMiddleware: (inputContext: better_call896.Middlewa
111
111
  * This middleware allows you to call the endpoint on the client if session is valid.
112
112
  * However, if called on the server, no session is required.
113
113
  */
114
- declare const requestOnlySessionMiddleware: (inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
114
+ declare const requestOnlySessionMiddleware: (inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
115
115
  session: {
116
116
  session: Record<string, any> & {
117
117
  id: string;
@@ -141,7 +141,7 @@ declare const requestOnlySessionMiddleware: (inputContext: better_call896.Middle
141
141
  * Session freshness check will be skipped if the session config's freshAge
142
142
  * is set to 0
143
143
  */
144
- declare const freshSessionMiddleware: (inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
144
+ declare const freshSessionMiddleware: (inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
145
145
  session: {
146
146
  session: Record<string, any> & {
147
147
  id: string;
@@ -167,10 +167,10 @@ declare const freshSessionMiddleware: (inputContext: better_call896.MiddlewareIn
167
167
  /**
168
168
  * user active sessions list
169
169
  */
170
- declare const listSessions: <Option extends BetterAuthOptions>() => better_call896.StrictEndpoint<"/list-sessions", {
170
+ declare const listSessions: <Option extends BetterAuthOptions>() => better_call741.StrictEndpoint<"/list-sessions", {
171
171
  method: "GET";
172
172
  operationId: string;
173
- use: ((inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
173
+ use: ((inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
174
174
  session: {
175
175
  session: Record<string, any> & {
176
176
  id: string;
@@ -219,12 +219,12 @@ declare const listSessions: <Option extends BetterAuthOptions>() => better_call8
219
219
  /**
220
220
  * revoke a single session
221
221
  */
222
- declare const revokeSession: better_call896.StrictEndpoint<"/revoke-session", {
222
+ declare const revokeSession: better_call741.StrictEndpoint<"/revoke-session", {
223
223
  method: "POST";
224
224
  body: z.ZodObject<{
225
225
  token: z.ZodString;
226
226
  }, z.core.$strip>;
227
- use: ((inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
227
+ use: ((inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
228
228
  session: {
229
229
  session: Record<string, any> & {
230
230
  id: string;
@@ -294,9 +294,9 @@ declare const revokeSession: better_call896.StrictEndpoint<"/revoke-session", {
294
294
  /**
295
295
  * revoke all user sessions
296
296
  */
297
- declare const revokeSessions: better_call896.StrictEndpoint<"/revoke-sessions", {
297
+ declare const revokeSessions: better_call741.StrictEndpoint<"/revoke-sessions", {
298
298
  method: "POST";
299
- use: ((inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
299
+ use: ((inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
300
300
  session: {
301
301
  session: Record<string, any> & {
302
302
  id: string;
@@ -347,10 +347,10 @@ declare const revokeSessions: better_call896.StrictEndpoint<"/revoke-sessions",
347
347
  }, {
348
348
  status: boolean;
349
349
  }>;
350
- declare const revokeOtherSessions: better_call896.StrictEndpoint<"/revoke-other-sessions", {
350
+ declare const revokeOtherSessions: better_call741.StrictEndpoint<"/revoke-other-sessions", {
351
351
  method: "POST";
352
352
  requireHeaders: true;
353
- use: ((inputContext: better_call896.MiddlewareInputContext<better_call896.MiddlewareOptions>) => Promise<{
353
+ use: ((inputContext: better_call741.MiddlewareInputContext<better_call741.MiddlewareOptions>) => Promise<{
354
354
  session: {
355
355
  session: Record<string, any> & {
356
356
  id: string;
@@ -5,10 +5,9 @@ import { symmetricDecodeJWT, verifyJWT } from "../../crypto/jwt.mjs";
5
5
  import "../../crypto/index.mjs";
6
6
  import { getChunkedCookie, getSessionQuerySchema } from "../../cookies/session-store.mjs";
7
7
  import { deleteSessionCookie, setCookieCache, setSessionCookie } from "../../cookies/index.mjs";
8
- import { BASE_ERROR_CODES } from "@better-auth/core/error";
8
+ import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
9
9
  import { safeJSONParse } from "@better-auth/core/utils";
10
10
  import * as z from "zod";
11
- import { APIError } from "better-call";
12
11
  import { createAuthEndpoint, createAuthMiddleware } from "@better-auth/core/api";
13
12
  import { base64Url } from "@better-auth/utils/base64";
14
13
  import { binary } from "@better-auth/utils/binary";
@@ -227,7 +226,7 @@ const getSession = () => createAuthEndpoint("/get-session", {
227
226
  return ctx.json(session);
228
227
  } catch (error) {
229
228
  ctx.context.logger.error("INTERNAL_SERVER_ERROR", error);
230
- throw new APIError("INTERNAL_SERVER_ERROR", { message: BASE_ERROR_CODES.FAILED_TO_GET_SESSION });
229
+ throw APIError.from("INTERNAL_SERVER_ERROR", BASE_ERROR_CODES.FAILED_TO_GET_SESSION);
231
230
  }
232
231
  });
233
232
  const getSessionFromCtx = async (ctx, config) => {
@@ -253,7 +252,10 @@ const getSessionFromCtx = async (ctx, config) => {
253
252
  */
254
253
  const sessionMiddleware = createAuthMiddleware(async (ctx) => {
255
254
  const session = await getSessionFromCtx(ctx);
256
- if (!session?.session) throw new APIError("UNAUTHORIZED");
255
+ if (!session?.session) throw APIError.from("UNAUTHORIZED", {
256
+ message: "Unauthorized",
257
+ code: "UNAUTHORIZED"
258
+ });
257
259
  return { session };
258
260
  });
259
261
  /**
@@ -263,7 +265,10 @@ const sessionMiddleware = createAuthMiddleware(async (ctx) => {
263
265
  */
264
266
  const sensitiveSessionMiddleware = createAuthMiddleware(async (ctx) => {
265
267
  const session = await getSessionFromCtx(ctx, { disableCookieCache: true });
266
- if (!session?.session) throw new APIError("UNAUTHORIZED");
268
+ if (!session?.session) throw APIError.from("UNAUTHORIZED", {
269
+ message: "Unauthorized",
270
+ code: "UNAUTHORIZED"
271
+ });
267
272
  return { session };
268
273
  });
269
274
  /**
@@ -272,7 +277,10 @@ const sensitiveSessionMiddleware = createAuthMiddleware(async (ctx) => {
272
277
  */
273
278
  const requestOnlySessionMiddleware = createAuthMiddleware(async (ctx) => {
274
279
  const session = await getSessionFromCtx(ctx);
275
- if (!session?.session && (ctx.request || ctx.headers)) throw new APIError("UNAUTHORIZED");
280
+ if (!session?.session && (ctx.request || ctx.headers)) throw APIError.from("UNAUTHORIZED", {
281
+ message: "Unauthorized",
282
+ code: "UNAUTHORIZED"
283
+ });
276
284
  return { session };
277
285
  });
278
286
  /**
@@ -284,11 +292,14 @@ const requestOnlySessionMiddleware = createAuthMiddleware(async (ctx) => {
284
292
  */
285
293
  const freshSessionMiddleware = createAuthMiddleware(async (ctx) => {
286
294
  const session = await getSessionFromCtx(ctx);
287
- if (!session?.session) throw new APIError("UNAUTHORIZED");
295
+ if (!session?.session) throw APIError.from("UNAUTHORIZED", {
296
+ message: "Unauthorized",
297
+ code: "UNAUTHORIZED"
298
+ });
288
299
  if (ctx.context.sessionConfig.freshAge === 0) return { session };
289
300
  const freshAge = ctx.context.sessionConfig.freshAge;
290
301
  const lastUpdated = new Date(session.session.updatedAt || session.session.createdAt).getTime();
291
- if (!(Date.now() - lastUpdated < freshAge * 1e3)) throw new APIError("FORBIDDEN", { message: "Session is not fresh" });
302
+ if (!(Date.now() - lastUpdated < freshAge * 1e3)) throw APIError.from("FORBIDDEN", BASE_ERROR_CODES.SESSION_NOT_FRESH);
292
303
  return { session };
293
304
  });
294
305
  /**
@@ -357,7 +368,10 @@ const revokeSession = createAuthEndpoint("/revoke-session", {
357
368
  await ctx.context.internalAdapter.deleteSession(token);
358
369
  } catch (error) {
359
370
  ctx.context.logger.error(error && typeof error === "object" && "name" in error ? error.name : "", error);
360
- throw new APIError("INTERNAL_SERVER_ERROR");
371
+ throw APIError.from("INTERNAL_SERVER_ERROR", {
372
+ message: "Internal Server Error",
373
+ code: "INTERNAL_SERVER_ERROR"
374
+ });
361
375
  }
362
376
  return ctx.json({ status: true });
363
377
  });
@@ -387,7 +401,10 @@ const revokeSessions = createAuthEndpoint("/revoke-sessions", {
387
401
  await ctx.context.internalAdapter.deleteSessions(ctx.context.session.user.id);
388
402
  } catch (error) {
389
403
  ctx.context.logger.error(error && typeof error === "object" && "name" in error ? error.name : "", error);
390
- throw new APIError("INTERNAL_SERVER_ERROR");
404
+ throw APIError.from("INTERNAL_SERVER_ERROR", {
405
+ message: "Internal Server Error",
406
+ code: "INTERNAL_SERVER_ERROR"
407
+ });
391
408
  }
392
409
  return ctx.json({ status: true });
393
410
  });
@@ -411,7 +428,10 @@ const revokeOtherSessions = createAuthEndpoint("/revoke-other-sessions", {
411
428
  } }
412
429
  }, async (ctx) => {
413
430
  const session = ctx.context.session;
414
- if (!session.user) throw new APIError("UNAUTHORIZED");
431
+ if (!session.user) throw APIError.from("UNAUTHORIZED", {
432
+ message: "Unauthorized",
433
+ code: "UNAUTHORIZED"
434
+ });
415
435
  const otherSessions = (await ctx.context.internalAdapter.listSessions(session.user.id)).filter((session$1) => {
416
436
  return session$1.expiresAt > /* @__PURE__ */ new Date();
417
437
  }).filter((session$1) => session$1.token !== ctx.context.session.session.token);
@@ -1 +1 @@
1
- {"version":3,"file":"session.mjs","names":["sessionDataPayload: {\n\t\t\t\t\tsession: {\n\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t};\n\t\t\t\t\texpiresAt: number;\n\t\t\t\t} | null","session","e: any"],"sources":["../../../src/api/routes/session.ts"],"sourcesContent":["import type {\n\tBetterAuthOptions,\n\tGenericEndpointContext,\n} from \"@better-auth/core\";\nimport {\n\tcreateAuthEndpoint,\n\tcreateAuthMiddleware,\n} from \"@better-auth/core/api\";\nimport { BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { safeJSONParse } from \"@better-auth/core/utils\";\nimport { base64Url } from \"@better-auth/utils/base64\";\nimport { binary } from \"@better-auth/utils/binary\";\nimport { createHMAC } from \"@better-auth/utils/hmac\";\nimport { APIError } from \"better-call\";\nimport * as z from \"zod\";\nimport {\n\tdeleteSessionCookie,\n\tgetChunkedCookie,\n\tsetCookieCache,\n\tsetSessionCookie,\n} from \"../../cookies\";\nimport { getSessionQuerySchema } from \"../../cookies/session-store\";\nimport { symmetricDecodeJWT, verifyJWT } from \"../../crypto\";\nimport { parseSessionOutput, parseUserOutput } from \"../../db\";\nimport type { InferSession, InferUser, Session, User } from \"../../types\";\nimport type { Prettify } from \"../../types/helper\";\nimport { getDate } from \"../../utils/date\";\n\nexport const getSession = <Option extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/get-session\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\toperationId: \"getSession\",\n\t\t\tquery: getSessionQuerySchema,\n\t\t\trequireHeaders: true,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"getSession\",\n\t\t\t\t\tdescription: \"Get the current session\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"session\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t\tasync (\n\t\t\tctx,\n\t\t): Promise<{\n\t\t\tsession: InferSession<Option>;\n\t\t\tuser: InferUser<Option>;\n\t\t} | null> => {\n\t\t\ttry {\n\t\t\t\tconst sessionCookieToken = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.sessionToken.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\n\n\t\t\t\tif (!sessionCookieToken) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst sessionDataCookie = getChunkedCookie(\n\t\t\t\t\tctx,\n\t\t\t\t\tctx.context.authCookies.sessionData.name,\n\t\t\t\t);\n\n\t\t\t\tlet sessionDataPayload: {\n\t\t\t\t\tsession: {\n\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t};\n\t\t\t\t\texpiresAt: number;\n\t\t\t\t} | null = null;\n\n\t\t\t\tif (sessionDataCookie) {\n\t\t\t\t\tconst strategy =\n\t\t\t\t\t\tctx.context.options.session?.cookieCache?.strategy || \"compact\";\n\n\t\t\t\t\tif (strategy === \"jwe\") {\n\t\t\t\t\t\t// Decode JWE (encrypted)\n\t\t\t\t\t\tconst payload = await symmetricDecodeJWT<{\n\t\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t\t\texp?: number;\n\t\t\t\t\t\t}>(sessionDataCookie, ctx.context.secret, \"better-auth-session\");\n\n\t\t\t\t\t\tif (payload && payload.session && payload.user) {\n\t\t\t\t\t\t\tsessionDataPayload = {\n\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\tsession: payload.session,\n\t\t\t\t\t\t\t\t\tuser: payload.user,\n\t\t\t\t\t\t\t\t\tupdatedAt: payload.updatedAt,\n\t\t\t\t\t\t\t\t\tversion: payload.version,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\texpiresAt: payload.exp ? payload.exp * 1000 : Date.now(),\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (strategy === \"jwt\") {\n\t\t\t\t\t\t// Decode JWT (signed with HMAC, not encrypted)\n\t\t\t\t\t\tconst payload = await verifyJWT<{\n\t\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t\t\texp?: number;\n\t\t\t\t\t\t}>(sessionDataCookie, ctx.context.secret);\n\n\t\t\t\t\t\tif (payload && payload.session && payload.user) {\n\t\t\t\t\t\t\tsessionDataPayload = {\n\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\tsession: payload.session,\n\t\t\t\t\t\t\t\t\tuser: payload.user,\n\t\t\t\t\t\t\t\t\tupdatedAt: payload.updatedAt,\n\t\t\t\t\t\t\t\t\tversion: payload.version,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\texpiresAt: payload.exp ? payload.exp * 1000 : Date.now(),\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Decode compact format (or legacy base64-hmac)\n\t\t\t\t\t\tconst parsed = safeJSONParse<{\n\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tsignature: string;\n\t\t\t\t\t\t\texpiresAt: number;\n\t\t\t\t\t\t}>(binary.decode(base64Url.decode(sessionDataCookie)));\n\n\t\t\t\t\t\tif (parsed) {\n\t\t\t\t\t\t\tconst isValid = await createHMAC(\n\t\t\t\t\t\t\t\t\"SHA-256\",\n\t\t\t\t\t\t\t\t\"base64urlnopad\",\n\t\t\t\t\t\t\t).verify(\n\t\t\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\t\t\t...parsed.session,\n\t\t\t\t\t\t\t\t\texpiresAt: parsed.expiresAt,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tparsed.signature,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (isValid) {\n\t\t\t\t\t\t\t\tsessionDataPayload = parsed;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn ctx.json(null);\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\n\t\t\t\tconst dontRememberMe = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.dontRememberToken.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\n\n\t\t\t\t/**\n\t\t\t\t * If session data is present in the cookie, check if it should be used or refreshed\n\t\t\t\t */\n\t\t\t\tif (\n\t\t\t\t\tsessionDataPayload?.session &&\n\t\t\t\t\tctx.context.options.session?.cookieCache?.enabled &&\n\t\t\t\t\t!ctx.query?.disableCookieCache\n\t\t\t\t) {\n\t\t\t\t\tconst session = sessionDataPayload.session;\n\n\t\t\t\t\tconst versionConfig =\n\t\t\t\t\t\tctx.context.options.session?.cookieCache?.version;\n\t\t\t\t\tlet expectedVersion = \"1\";\n\t\t\t\t\tif (versionConfig) {\n\t\t\t\t\t\tif (typeof versionConfig === \"string\") {\n\t\t\t\t\t\t\texpectedVersion = versionConfig;\n\t\t\t\t\t\t} else if (typeof versionConfig === \"function\") {\n\t\t\t\t\t\t\tconst result = versionConfig(session.session, session.user);\n\t\t\t\t\t\t\texpectedVersion =\n\t\t\t\t\t\t\t\tresult instanceof Promise ? await result : result;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst cookieVersion = session.version || \"1\";\n\t\t\t\t\tif (cookieVersion !== expectedVersion) {\n\t\t\t\t\t\t// Version mismatch - invalidate the cookie cache\n\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst cachedSessionExpiresAt = new Date(\n\t\t\t\t\t\t\tsession.session.expiresAt as unknown as string | number | Date,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst hasExpired =\n\t\t\t\t\t\t\tsessionDataPayload.expiresAt < Date.now() ||\n\t\t\t\t\t\t\tcachedSessionExpiresAt < new Date();\n\n\t\t\t\t\t\tif (hasExpired) {\n\t\t\t\t\t\t\t// When the session data cookie has expired, delete it;\n\t\t\t\t\t\t\t// then we try to fetch from DB\n\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Check if the cookie cache needs to be refreshed based on refreshCache\n\t\t\t\t\t\t\tconst cookieRefreshCache =\n\t\t\t\t\t\t\t\tctx.context.sessionConfig.cookieRefreshCache;\n\n\t\t\t\t\t\t\tif (cookieRefreshCache === false) {\n\t\t\t\t\t\t\t\t// If refreshCache is disabled, return the session from cookie as-is\n\t\t\t\t\t\t\t\tctx.context.session = session;\n\t\t\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\t\t\tsession: session.session,\n\t\t\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t\t\t} as {\n\t\t\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst timeUntilExpiry = sessionDataPayload.expiresAt - Date.now();\n\t\t\t\t\t\t\tconst updateAge = cookieRefreshCache.updateAge * 1000; // Convert to milliseconds\n\n\t\t\t\t\t\t\tif (timeUntilExpiry < updateAge) {\n\t\t\t\t\t\t\t\tconst cookieMaxAge =\n\t\t\t\t\t\t\t\t\tctx.context.options.session?.cookieCache?.maxAge || 60 * 5;\n\t\t\t\t\t\t\t\tconst newExpiresAt = getDate(cookieMaxAge, \"sec\");\n\t\t\t\t\t\t\t\tconst refreshedSession = {\n\t\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\t\t...session.session,\n\t\t\t\t\t\t\t\t\t\texpiresAt: newExpiresAt,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t\t\t\tupdatedAt: Date.now(),\n\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t// Set the refreshed cookie cache\n\t\t\t\t\t\t\t\tawait setCookieCache(ctx, refreshedSession, false);\n\n\t\t\t\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\t\t\t\t// Rehydrate date fields from JSON strings before parsing\n\t\t\t\t\t\t\t\tconst parsedRefreshedSession = parseSessionOutput(\n\t\t\t\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t...refreshedSession.session,\n\t\t\t\t\t\t\t\t\t\texpiresAt: new Date(refreshedSession.session.expiresAt),\n\t\t\t\t\t\t\t\t\t\tcreatedAt: new Date(refreshedSession.session.createdAt),\n\t\t\t\t\t\t\t\t\t\tupdatedAt: new Date(refreshedSession.session.updatedAt),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst parsedRefreshedUser = parseUserOutput(\n\t\t\t\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t...refreshedSession.user,\n\t\t\t\t\t\t\t\t\t\tcreatedAt: new Date(refreshedSession.user.createdAt),\n\t\t\t\t\t\t\t\t\t\tupdatedAt: new Date(refreshedSession.user.updatedAt),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tctx.context.session = {\n\t\t\t\t\t\t\t\t\tsession: parsedRefreshedSession,\n\t\t\t\t\t\t\t\t\tuser: parsedRefreshedUser,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\t\t\tsession: parsedRefreshedSession,\n\t\t\t\t\t\t\t\t\tuser: parsedRefreshedUser,\n\t\t\t\t\t\t\t\t} as {\n\t\t\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\t\t\tconst parsedSession = parseSessionOutput(ctx.context.options, {\n\t\t\t\t\t\t\t\t...session.session,\n\t\t\t\t\t\t\t\texpiresAt: new Date(session.session.expiresAt),\n\t\t\t\t\t\t\t\tcreatedAt: new Date(session.session.createdAt),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(session.session.updatedAt),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst parsedUser = parseUserOutput(ctx.context.options, {\n\t\t\t\t\t\t\t\t...session.user,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(session.user.createdAt),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(session.user.updatedAt),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tctx.context.session = {\n\t\t\t\t\t\t\t\tsession: parsedSession,\n\t\t\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\t\tsession: parsedSession,\n\t\t\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t\t\t} as {\n\t\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\t\tuser: InferUser<Option>;\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\n\t\t\t\tconst session =\n\t\t\t\t\tawait ctx.context.internalAdapter.findSession(sessionCookieToken);\n\t\t\t\tctx.context.session = session;\n\t\t\t\tif (!session || session.session.expiresAt < new Date()) {\n\t\t\t\t\tdeleteSessionCookie(ctx);\n\t\t\t\t\tif (session) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * if session expired clean up the session\n\t\t\t\t\t\t */\n\t\t\t\t\t\tawait ctx.context.internalAdapter.deleteSession(\n\t\t\t\t\t\t\tsession.session.token,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * We don't need to update the session if the user doesn't want to be remembered\n\t\t\t\t * or if the session refresh is disabled\n\t\t\t\t */\n\t\t\t\tif (dontRememberMe || ctx.query?.disableRefresh) {\n\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\tconst parsedSession = parseSessionOutput(\n\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\tsession.session,\n\t\t\t\t\t);\n\t\t\t\t\tconst parsedUser = parseUserOutput(ctx.context.options, session.user);\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsession: parsedSession,\n\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t} as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst expiresIn = ctx.context.sessionConfig.expiresIn;\n\t\t\t\tconst updateAge = ctx.context.sessionConfig.updateAge;\n\t\t\t\t/**\n\t\t\t\t * Calculate last updated date to throttle write updates to database\n\t\t\t\t * Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge\n\t\t\t\t *\n\t\t\t\t * e.g. ({expiry date} - 30 days) + 1 hour\n\t\t\t\t *\n\t\t\t\t * inspired by: https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/lib/actions/session.ts\n\t\t\t\t */\n\t\t\t\tconst sessionIsDueToBeUpdatedDate =\n\t\t\t\t\tsession.session.expiresAt.valueOf() -\n\t\t\t\t\texpiresIn * 1000 +\n\t\t\t\t\tupdateAge * 1000;\n\t\t\t\tconst shouldBeUpdated = sessionIsDueToBeUpdatedDate <= Date.now();\n\n\t\t\t\tif (\n\t\t\t\t\tshouldBeUpdated &&\n\t\t\t\t\t(!ctx.query?.disableRefresh ||\n\t\t\t\t\t\t!ctx.context.options.session?.disableSessionRefresh)\n\t\t\t\t) {\n\t\t\t\t\tconst updatedSession =\n\t\t\t\t\t\tawait ctx.context.internalAdapter.updateSession(\n\t\t\t\t\t\t\tsession.session.token,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\texpiresAt: getDate(ctx.context.sessionConfig.expiresIn, \"sec\"),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\tif (!updatedSession) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Handle case where session update fails (e.g., concurrent deletion)\n\t\t\t\t\t\t */\n\t\t\t\t\t\tdeleteSessionCookie(ctx);\n\t\t\t\t\t\treturn ctx.json(null, { status: 401 });\n\t\t\t\t\t}\n\t\t\t\t\tconst maxAge =\n\t\t\t\t\t\t(updatedSession.expiresAt.valueOf() - Date.now()) / 1000;\n\t\t\t\t\tawait setSessionCookie(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsession: updatedSession,\n\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmaxAge,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\n\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\tconst parsedUpdatedSession = parseSessionOutput(\n\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\tupdatedSession,\n\t\t\t\t\t);\n\t\t\t\t\tconst parsedUser = parseUserOutput(ctx.context.options, session.user);\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsession: parsedUpdatedSession,\n\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t} as unknown as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setCookieCache(ctx, session, !!dontRememberMe);\n\t\t\t\treturn ctx.json(\n\t\t\t\t\tsession as unknown as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tctx.context.logger.error(\"INTERNAL_SERVER_ERROR\", error);\n\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\tmessage: BASE_ERROR_CODES.FAILED_TO_GET_SESSION,\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t);\n\nexport const getSessionFromCtx = async <\n\tU extends Record<string, any> = Record<string, any>,\n\tS extends Record<string, any> = Record<string, any>,\n>(\n\tctx: GenericEndpointContext,\n\tconfig?:\n\t\t| {\n\t\t\t\tdisableCookieCache?: boolean;\n\t\t\t\tdisableRefresh?: boolean;\n\t\t }\n\t\t| undefined,\n) => {\n\tif (ctx.context.session) {\n\t\treturn ctx.context.session as {\n\t\t\tsession: S & Session;\n\t\t\tuser: U & User;\n\t\t};\n\t}\n\n\tconst session = await getSession()({\n\t\t...ctx,\n\t\tasResponse: false,\n\t\theaders: ctx.headers!,\n\t\treturnHeaders: false,\n\t\treturnStatus: false,\n\t\tquery: {\n\t\t\t...config,\n\t\t\t...ctx.query,\n\t\t},\n\t}).catch((e) => {\n\t\treturn null;\n\t});\n\tctx.context.session = session;\n\treturn session as {\n\t\tsession: S & Session;\n\t\tuser: U & User;\n\t} | null;\n};\n\n/**\n * The middleware forces the endpoint to require a valid session.\n */\nexport const sessionMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session?.session) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\treturn {\n\t\tsession,\n\t};\n});\n\n/**\n * This middleware forces the endpoint to require a valid session and ignores cookie cache.\n * This should be used for sensitive operations like password changes, account deletion, etc.\n * to ensure that revoked sessions cannot be used even if they're still cached in cookies.\n */\nexport const sensitiveSessionMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst session = await getSessionFromCtx(ctx, { disableCookieCache: true });\n\tif (!session?.session) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\treturn {\n\t\tsession,\n\t};\n});\n\n/**\n * This middleware allows you to call the endpoint on the client if session is valid.\n * However, if called on the server, no session is required.\n */\nexport const requestOnlySessionMiddleware = createAuthMiddleware(\n\tasync (ctx) => {\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (!session?.session && (ctx.request || ctx.headers)) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\treturn { session };\n\t},\n);\n\n/**\n * This middleware forces the endpoint to require a valid session,\n * as well as making sure the session is fresh before proceeding.\n *\n * Session freshness check will be skipped if the session config's freshAge\n * is set to 0\n */\nexport const freshSessionMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session?.session) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\tif (ctx.context.sessionConfig.freshAge === 0) {\n\t\treturn {\n\t\t\tsession,\n\t\t};\n\t}\n\tconst freshAge = ctx.context.sessionConfig.freshAge;\n\tconst lastUpdated = new Date(\n\t\tsession.session.updatedAt || session.session.createdAt,\n\t).getTime();\n\tconst now = Date.now();\n\tconst isFresh = now - lastUpdated < freshAge * 1000;\n\tif (!isFresh) {\n\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\tmessage: \"Session is not fresh\",\n\t\t});\n\t}\n\treturn {\n\t\tsession,\n\t};\n});\n/**\n * user active sessions list\n */\nexport const listSessions = <Option extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/list-sessions\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\toperationId: \"listUserSessions\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\trequireHeaders: true,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"listUserSessions\",\n\t\t\t\t\tdescription: \"List all active sessions for the user\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t\tasync (ctx) => {\n\t\t\ttry {\n\t\t\t\tconst sessions = await ctx.context.internalAdapter.listSessions(\n\t\t\t\t\tctx.context.session.user.id,\n\t\t\t\t);\n\t\t\t\tconst activeSessions = sessions.filter((session) => {\n\t\t\t\t\treturn session.expiresAt > new Date();\n\t\t\t\t});\n\t\t\t\treturn ctx.json(\n\t\t\t\t\tactiveSessions as unknown as Prettify<InferSession<Option>>[],\n\t\t\t\t);\n\t\t\t} catch (e: any) {\n\t\t\t\tctx.context.logger.error(e);\n\t\t\t\tthrow ctx.error(\"INTERNAL_SERVER_ERROR\");\n\t\t\t}\n\t\t},\n\t);\n\n/**\n * revoke a single session\n */\nexport const revokeSession = createAuthEndpoint(\n\t\"/revoke-session\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\ttoken: z.string().meta({\n\t\t\t\tdescription: \"The token to revoke\",\n\t\t\t}),\n\t\t}),\n\t\tuse: [sensitiveSessionMiddleware],\n\t\trequireHeaders: true,\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Revoke a single session\",\n\t\t\t\trequestBody: {\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"The token to revoke\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\trequired: [\"token\"],\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\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the session was revoked successfully\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst token = ctx.body.token;\n\t\tconst session = await ctx.context.internalAdapter.findSession(token);\n\n\t\tif (session?.session.userId === ctx.context.session.user.id) {\n\t\t\ttry {\n\t\t\t\tawait ctx.context.internalAdapter.deleteSession(token);\n\t\t\t} catch (error) {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\terror && typeof error === \"object\" && \"name\" in error\n\t\t\t\t\t\t? (error.name as string)\n\t\t\t\t\t\t: \"\",\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t\t}\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n/**\n * revoke all user sessions\n */\nexport const revokeSessions = createAuthEndpoint(\n\t\"/revoke-sessions\",\n\t{\n\t\tmethod: \"POST\",\n\t\tuse: [sensitiveSessionMiddleware],\n\t\trequireHeaders: true,\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Revoke all sessions for the user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if all sessions were revoked successfully\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\ttry {\n\t\t\tawait ctx.context.internalAdapter.deleteSessions(\n\t\t\t\tctx.context.session.user.id,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tctx.context.logger.error(\n\t\t\t\terror && typeof error === \"object\" && \"name\" in error\n\t\t\t\t\t? (error.name as string)\n\t\t\t\t\t: \"\",\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const revokeOtherSessions = createAuthEndpoint(\n\t\"/revoke-other-sessions\",\n\t{\n\t\tmethod: \"POST\",\n\t\trequireHeaders: true,\n\t\tuse: [sensitiveSessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Revoke all other sessions for the user except the current one\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if all other sessions were revoked successfully\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst session = ctx.context.session;\n\t\tif (!session.user) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\tconst sessions = await ctx.context.internalAdapter.listSessions(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst activeSessions = sessions.filter((session) => {\n\t\t\treturn session.expiresAt > new Date();\n\t\t});\n\t\tconst otherSessions = activeSessions.filter(\n\t\t\t(session) => session.token !== ctx.context.session.session.token,\n\t\t);\n\t\tawait Promise.all(\n\t\t\totherSessions.map((session) =>\n\t\t\t\tctx.context.internalAdapter.deleteSession(session.token),\n\t\t\t),\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"session.mjs","names":["sessionDataPayload: {\n\t\t\t\t\tsession: {\n\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t};\n\t\t\t\t\texpiresAt: number;\n\t\t\t\t} | null","session","e: any"],"sources":["../../../src/api/routes/session.ts"],"sourcesContent":["import type {\n\tBetterAuthOptions,\n\tGenericEndpointContext,\n} from \"@better-auth/core\";\nimport {\n\tcreateAuthEndpoint,\n\tcreateAuthMiddleware,\n} from \"@better-auth/core/api\";\nimport { APIError, BASE_ERROR_CODES } from \"@better-auth/core/error\";\nimport { safeJSONParse } from \"@better-auth/core/utils\";\nimport { base64Url } from \"@better-auth/utils/base64\";\nimport { binary } from \"@better-auth/utils/binary\";\nimport { createHMAC } from \"@better-auth/utils/hmac\";\n\nimport * as z from \"zod\";\nimport {\n\tdeleteSessionCookie,\n\tgetChunkedCookie,\n\tsetCookieCache,\n\tsetSessionCookie,\n} from \"../../cookies\";\nimport { getSessionQuerySchema } from \"../../cookies/session-store\";\nimport { symmetricDecodeJWT, verifyJWT } from \"../../crypto\";\nimport { parseSessionOutput, parseUserOutput } from \"../../db\";\nimport type { InferSession, InferUser, Session, User } from \"../../types\";\nimport type { Prettify } from \"../../types/helper\";\nimport { getDate } from \"../../utils/date\";\n\nexport const getSession = <Option extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/get-session\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\toperationId: \"getSession\",\n\t\t\tquery: getSessionQuerySchema,\n\t\t\trequireHeaders: true,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"getSession\",\n\t\t\t\t\tdescription: \"Get the current session\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\t\tnullable: true,\n\t\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/User\",\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\trequired: [\"session\", \"user\"],\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t\tasync (\n\t\t\tctx,\n\t\t): Promise<{\n\t\t\tsession: InferSession<Option>;\n\t\t\tuser: InferUser<Option>;\n\t\t} | null> => {\n\t\t\ttry {\n\t\t\t\tconst sessionCookieToken = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.sessionToken.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\n\n\t\t\t\tif (!sessionCookieToken) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst sessionDataCookie = getChunkedCookie(\n\t\t\t\t\tctx,\n\t\t\t\t\tctx.context.authCookies.sessionData.name,\n\t\t\t\t);\n\n\t\t\t\tlet sessionDataPayload: {\n\t\t\t\t\tsession: {\n\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t};\n\t\t\t\t\texpiresAt: number;\n\t\t\t\t} | null = null;\n\n\t\t\t\tif (sessionDataCookie) {\n\t\t\t\t\tconst strategy =\n\t\t\t\t\t\tctx.context.options.session?.cookieCache?.strategy || \"compact\";\n\n\t\t\t\t\tif (strategy === \"jwe\") {\n\t\t\t\t\t\t// Decode JWE (encrypted)\n\t\t\t\t\t\tconst payload = await symmetricDecodeJWT<{\n\t\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t\t\texp?: number;\n\t\t\t\t\t\t}>(sessionDataCookie, ctx.context.secret, \"better-auth-session\");\n\n\t\t\t\t\t\tif (payload && payload.session && payload.user) {\n\t\t\t\t\t\t\tsessionDataPayload = {\n\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\tsession: payload.session,\n\t\t\t\t\t\t\t\t\tuser: payload.user,\n\t\t\t\t\t\t\t\t\tupdatedAt: payload.updatedAt,\n\t\t\t\t\t\t\t\t\tversion: payload.version,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\texpiresAt: payload.exp ? payload.exp * 1000 : Date.now(),\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (strategy === \"jwt\") {\n\t\t\t\t\t\t// Decode JWT (signed with HMAC, not encrypted)\n\t\t\t\t\t\tconst payload = await verifyJWT<{\n\t\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t\t\texp?: number;\n\t\t\t\t\t\t}>(sessionDataCookie, ctx.context.secret);\n\n\t\t\t\t\t\tif (payload && payload.session && payload.user) {\n\t\t\t\t\t\t\tsessionDataPayload = {\n\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\tsession: payload.session,\n\t\t\t\t\t\t\t\t\tuser: payload.user,\n\t\t\t\t\t\t\t\t\tupdatedAt: payload.updatedAt,\n\t\t\t\t\t\t\t\t\tversion: payload.version,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\texpiresAt: payload.exp ? payload.exp * 1000 : Date.now(),\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Decode compact format (or legacy base64-hmac)\n\t\t\t\t\t\tconst parsed = safeJSONParse<{\n\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\tsession: Session;\n\t\t\t\t\t\t\t\tuser: User;\n\t\t\t\t\t\t\t\tupdatedAt: number;\n\t\t\t\t\t\t\t\tversion?: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tsignature: string;\n\t\t\t\t\t\t\texpiresAt: number;\n\t\t\t\t\t\t}>(binary.decode(base64Url.decode(sessionDataCookie)));\n\n\t\t\t\t\t\tif (parsed) {\n\t\t\t\t\t\t\tconst isValid = await createHMAC(\n\t\t\t\t\t\t\t\t\"SHA-256\",\n\t\t\t\t\t\t\t\t\"base64urlnopad\",\n\t\t\t\t\t\t\t).verify(\n\t\t\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\t\t\t...parsed.session,\n\t\t\t\t\t\t\t\t\texpiresAt: parsed.expiresAt,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tparsed.signature,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (isValid) {\n\t\t\t\t\t\t\t\tsessionDataPayload = parsed;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\treturn ctx.json(null);\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\n\t\t\t\tconst dontRememberMe = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.dontRememberToken.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\n\n\t\t\t\t/**\n\t\t\t\t * If session data is present in the cookie, check if it should be used or refreshed\n\t\t\t\t */\n\t\t\t\tif (\n\t\t\t\t\tsessionDataPayload?.session &&\n\t\t\t\t\tctx.context.options.session?.cookieCache?.enabled &&\n\t\t\t\t\t!ctx.query?.disableCookieCache\n\t\t\t\t) {\n\t\t\t\t\tconst session = sessionDataPayload.session;\n\n\t\t\t\t\tconst versionConfig =\n\t\t\t\t\t\tctx.context.options.session?.cookieCache?.version;\n\t\t\t\t\tlet expectedVersion = \"1\";\n\t\t\t\t\tif (versionConfig) {\n\t\t\t\t\t\tif (typeof versionConfig === \"string\") {\n\t\t\t\t\t\t\texpectedVersion = versionConfig;\n\t\t\t\t\t\t} else if (typeof versionConfig === \"function\") {\n\t\t\t\t\t\t\tconst result = versionConfig(session.session, session.user);\n\t\t\t\t\t\t\texpectedVersion =\n\t\t\t\t\t\t\t\tresult instanceof Promise ? await result : result;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst cookieVersion = session.version || \"1\";\n\t\t\t\t\tif (cookieVersion !== expectedVersion) {\n\t\t\t\t\t\t// Version mismatch - invalidate the cookie cache\n\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst cachedSessionExpiresAt = new Date(\n\t\t\t\t\t\t\tsession.session.expiresAt as unknown as string | number | Date,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tconst hasExpired =\n\t\t\t\t\t\t\tsessionDataPayload.expiresAt < Date.now() ||\n\t\t\t\t\t\t\tcachedSessionExpiresAt < new Date();\n\n\t\t\t\t\t\tif (hasExpired) {\n\t\t\t\t\t\t\t// When the session data cookie has expired, delete it;\n\t\t\t\t\t\t\t// then we try to fetch from DB\n\t\t\t\t\t\t\tconst dataCookie = ctx.context.authCookies.sessionData.name;\n\t\t\t\t\t\t\tctx.setCookie(dataCookie, \"\", {\n\t\t\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Check if the cookie cache needs to be refreshed based on refreshCache\n\t\t\t\t\t\t\tconst cookieRefreshCache =\n\t\t\t\t\t\t\t\tctx.context.sessionConfig.cookieRefreshCache;\n\n\t\t\t\t\t\t\tif (cookieRefreshCache === false) {\n\t\t\t\t\t\t\t\t// If refreshCache is disabled, return the session from cookie as-is\n\t\t\t\t\t\t\t\tctx.context.session = session;\n\t\t\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\t\t\tsession: session.session,\n\t\t\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t\t\t} as {\n\t\t\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst timeUntilExpiry = sessionDataPayload.expiresAt - Date.now();\n\t\t\t\t\t\t\tconst updateAge = cookieRefreshCache.updateAge * 1000; // Convert to milliseconds\n\n\t\t\t\t\t\t\tif (timeUntilExpiry < updateAge) {\n\t\t\t\t\t\t\t\tconst cookieMaxAge =\n\t\t\t\t\t\t\t\t\tctx.context.options.session?.cookieCache?.maxAge || 60 * 5;\n\t\t\t\t\t\t\t\tconst newExpiresAt = getDate(cookieMaxAge, \"sec\");\n\t\t\t\t\t\t\t\tconst refreshedSession = {\n\t\t\t\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\t\t\t\t...session.session,\n\t\t\t\t\t\t\t\t\t\texpiresAt: newExpiresAt,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t\t\t\tupdatedAt: Date.now(),\n\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t// Set the refreshed cookie cache\n\t\t\t\t\t\t\t\tawait setCookieCache(ctx, refreshedSession, false);\n\n\t\t\t\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\t\t\t\t// Rehydrate date fields from JSON strings before parsing\n\t\t\t\t\t\t\t\tconst parsedRefreshedSession = parseSessionOutput(\n\t\t\t\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t...refreshedSession.session,\n\t\t\t\t\t\t\t\t\t\texpiresAt: new Date(refreshedSession.session.expiresAt),\n\t\t\t\t\t\t\t\t\t\tcreatedAt: new Date(refreshedSession.session.createdAt),\n\t\t\t\t\t\t\t\t\t\tupdatedAt: new Date(refreshedSession.session.updatedAt),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tconst parsedRefreshedUser = parseUserOutput(\n\t\t\t\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t...refreshedSession.user,\n\t\t\t\t\t\t\t\t\t\tcreatedAt: new Date(refreshedSession.user.createdAt),\n\t\t\t\t\t\t\t\t\t\tupdatedAt: new Date(refreshedSession.user.updatedAt),\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tctx.context.session = {\n\t\t\t\t\t\t\t\t\tsession: parsedRefreshedSession,\n\t\t\t\t\t\t\t\t\tuser: parsedRefreshedUser,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\t\t\tsession: parsedRefreshedSession,\n\t\t\t\t\t\t\t\t\tuser: parsedRefreshedUser,\n\t\t\t\t\t\t\t\t} as {\n\t\t\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\t\t\tconst parsedSession = parseSessionOutput(ctx.context.options, {\n\t\t\t\t\t\t\t\t...session.session,\n\t\t\t\t\t\t\t\texpiresAt: new Date(session.session.expiresAt),\n\t\t\t\t\t\t\t\tcreatedAt: new Date(session.session.createdAt),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(session.session.updatedAt),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst parsedUser = parseUserOutput(ctx.context.options, {\n\t\t\t\t\t\t\t\t...session.user,\n\t\t\t\t\t\t\t\tcreatedAt: new Date(session.user.createdAt),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(session.user.updatedAt),\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tctx.context.session = {\n\t\t\t\t\t\t\t\tsession: parsedSession,\n\t\t\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\t\t\tsession: parsedSession,\n\t\t\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t\t\t} as {\n\t\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\t\tuser: InferUser<Option>;\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\n\t\t\t\tconst session =\n\t\t\t\t\tawait ctx.context.internalAdapter.findSession(sessionCookieToken);\n\t\t\t\tctx.context.session = session;\n\t\t\t\tif (!session || session.session.expiresAt < new Date()) {\n\t\t\t\t\tdeleteSessionCookie(ctx);\n\t\t\t\t\tif (session) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * if session expired clean up the session\n\t\t\t\t\t\t */\n\t\t\t\t\t\tawait ctx.context.internalAdapter.deleteSession(\n\t\t\t\t\t\t\tsession.session.token,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json(null);\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * We don't need to update the session if the user doesn't want to be remembered\n\t\t\t\t * or if the session refresh is disabled\n\t\t\t\t */\n\t\t\t\tif (dontRememberMe || ctx.query?.disableRefresh) {\n\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\tconst parsedSession = parseSessionOutput(\n\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\tsession.session,\n\t\t\t\t\t);\n\t\t\t\t\tconst parsedUser = parseUserOutput(ctx.context.options, session.user);\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsession: parsedSession,\n\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t} as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst expiresIn = ctx.context.sessionConfig.expiresIn;\n\t\t\t\tconst updateAge = ctx.context.sessionConfig.updateAge;\n\t\t\t\t/**\n\t\t\t\t * Calculate last updated date to throttle write updates to database\n\t\t\t\t * Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge\n\t\t\t\t *\n\t\t\t\t * e.g. ({expiry date} - 30 days) + 1 hour\n\t\t\t\t *\n\t\t\t\t * inspired by: https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/lib/actions/session.ts\n\t\t\t\t */\n\t\t\t\tconst sessionIsDueToBeUpdatedDate =\n\t\t\t\t\tsession.session.expiresAt.valueOf() -\n\t\t\t\t\texpiresIn * 1000 +\n\t\t\t\t\tupdateAge * 1000;\n\t\t\t\tconst shouldBeUpdated = sessionIsDueToBeUpdatedDate <= Date.now();\n\n\t\t\t\tif (\n\t\t\t\t\tshouldBeUpdated &&\n\t\t\t\t\t(!ctx.query?.disableRefresh ||\n\t\t\t\t\t\t!ctx.context.options.session?.disableSessionRefresh)\n\t\t\t\t) {\n\t\t\t\t\tconst updatedSession =\n\t\t\t\t\t\tawait ctx.context.internalAdapter.updateSession(\n\t\t\t\t\t\t\tsession.session.token,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\texpiresAt: getDate(ctx.context.sessionConfig.expiresIn, \"sec\"),\n\t\t\t\t\t\t\t\tupdatedAt: new Date(),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\tif (!updatedSession) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Handle case where session update fails (e.g., concurrent deletion)\n\t\t\t\t\t\t */\n\t\t\t\t\t\tdeleteSessionCookie(ctx);\n\t\t\t\t\t\treturn ctx.json(null, { status: 401 });\n\t\t\t\t\t}\n\t\t\t\t\tconst maxAge =\n\t\t\t\t\t\t(updatedSession.expiresAt.valueOf() - Date.now()) / 1000;\n\t\t\t\t\tawait setSessionCookie(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsession: updatedSession,\n\t\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfalse,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmaxAge,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\n\t\t\t\t\t// Parse session and user to ensure additionalFields are included\n\t\t\t\t\tconst parsedUpdatedSession = parseSessionOutput(\n\t\t\t\t\t\tctx.context.options,\n\t\t\t\t\t\tupdatedSession,\n\t\t\t\t\t);\n\t\t\t\t\tconst parsedUser = parseUserOutput(ctx.context.options, session.user);\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsession: parsedUpdatedSession,\n\t\t\t\t\t\tuser: parsedUser,\n\t\t\t\t\t} as unknown as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tawait setCookieCache(ctx, session, !!dontRememberMe);\n\t\t\t\treturn ctx.json(\n\t\t\t\t\tsession as unknown as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tctx.context.logger.error(\"INTERNAL_SERVER_ERROR\", error);\n\t\t\t\tthrow APIError.from(\n\t\t\t\t\t\"INTERNAL_SERVER_ERROR\",\n\t\t\t\t\tBASE_ERROR_CODES.FAILED_TO_GET_SESSION,\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t);\n\nexport const getSessionFromCtx = async <\n\tU extends Record<string, any> = Record<string, any>,\n\tS extends Record<string, any> = Record<string, any>,\n>(\n\tctx: GenericEndpointContext,\n\tconfig?:\n\t\t| {\n\t\t\t\tdisableCookieCache?: boolean;\n\t\t\t\tdisableRefresh?: boolean;\n\t\t }\n\t\t| undefined,\n) => {\n\tif (ctx.context.session) {\n\t\treturn ctx.context.session as {\n\t\t\tsession: S & Session;\n\t\t\tuser: U & User;\n\t\t};\n\t}\n\n\tconst session = await getSession()({\n\t\t...ctx,\n\t\tasResponse: false,\n\t\theaders: ctx.headers!,\n\t\treturnHeaders: false,\n\t\treturnStatus: false,\n\t\tquery: {\n\t\t\t...config,\n\t\t\t...ctx.query,\n\t\t},\n\t}).catch((e) => {\n\t\treturn null;\n\t});\n\tctx.context.session = session;\n\treturn session as {\n\t\tsession: S & Session;\n\t\tuser: U & User;\n\t} | null;\n};\n\n/**\n * The middleware forces the endpoint to require a valid session.\n */\nexport const sessionMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session?.session) {\n\t\tthrow APIError.from(\"UNAUTHORIZED\", {\n\t\t\tmessage: \"Unauthorized\",\n\t\t\tcode: \"UNAUTHORIZED\",\n\t\t});\n\t}\n\treturn {\n\t\tsession,\n\t};\n});\n\n/**\n * This middleware forces the endpoint to require a valid session and ignores cookie cache.\n * This should be used for sensitive operations like password changes, account deletion, etc.\n * to ensure that revoked sessions cannot be used even if they're still cached in cookies.\n */\nexport const sensitiveSessionMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst session = await getSessionFromCtx(ctx, { disableCookieCache: true });\n\tif (!session?.session) {\n\t\tthrow APIError.from(\"UNAUTHORIZED\", {\n\t\t\tmessage: \"Unauthorized\",\n\t\t\tcode: \"UNAUTHORIZED\",\n\t\t});\n\t}\n\treturn {\n\t\tsession,\n\t};\n});\n\n/**\n * This middleware allows you to call the endpoint on the client if session is valid.\n * However, if called on the server, no session is required.\n */\nexport const requestOnlySessionMiddleware = createAuthMiddleware(\n\tasync (ctx) => {\n\t\tconst session = await getSessionFromCtx(ctx);\n\t\tif (!session?.session && (ctx.request || ctx.headers)) {\n\t\t\tthrow APIError.from(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Unauthorized\",\n\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t});\n\t\t}\n\t\treturn { session };\n\t},\n);\n\n/**\n * This middleware forces the endpoint to require a valid session,\n * as well as making sure the session is fresh before proceeding.\n *\n * Session freshness check will be skipped if the session config's freshAge\n * is set to 0\n */\nexport const freshSessionMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session?.session) {\n\t\tthrow APIError.from(\"UNAUTHORIZED\", {\n\t\t\tmessage: \"Unauthorized\",\n\t\t\tcode: \"UNAUTHORIZED\",\n\t\t});\n\t}\n\tif (ctx.context.sessionConfig.freshAge === 0) {\n\t\treturn {\n\t\t\tsession,\n\t\t};\n\t}\n\tconst freshAge = ctx.context.sessionConfig.freshAge;\n\tconst lastUpdated = new Date(\n\t\tsession.session.updatedAt || session.session.createdAt,\n\t).getTime();\n\tconst now = Date.now();\n\tconst isFresh = now - lastUpdated < freshAge * 1000;\n\tif (!isFresh) {\n\t\tthrow APIError.from(\"FORBIDDEN\", BASE_ERROR_CODES.SESSION_NOT_FRESH);\n\t}\n\treturn {\n\t\tsession,\n\t};\n});\n/**\n * user active sessions list\n */\nexport const listSessions = <Option extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/list-sessions\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\toperationId: \"listUserSessions\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\trequireHeaders: true,\n\t\t\tmetadata: {\n\t\t\t\topenapi: {\n\t\t\t\t\toperationId: \"listUserSessions\",\n\t\t\t\t\tdescription: \"List all active sessions for the user\",\n\t\t\t\t\tresponses: {\n\t\t\t\t\t\t\"200\": {\n\t\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\t\ttype: \"array\",\n\t\t\t\t\t\t\t\t\t\titems: {\n\t\t\t\t\t\t\t\t\t\t\t$ref: \"#/components/schemas/Session\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\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},\n\t\tasync (ctx) => {\n\t\t\ttry {\n\t\t\t\tconst sessions = await ctx.context.internalAdapter.listSessions(\n\t\t\t\t\tctx.context.session.user.id,\n\t\t\t\t);\n\t\t\t\tconst activeSessions = sessions.filter((session) => {\n\t\t\t\t\treturn session.expiresAt > new Date();\n\t\t\t\t});\n\t\t\t\treturn ctx.json(\n\t\t\t\t\tactiveSessions as unknown as Prettify<InferSession<Option>>[],\n\t\t\t\t);\n\t\t\t} catch (e: any) {\n\t\t\t\tctx.context.logger.error(e);\n\t\t\t\tthrow ctx.error(\"INTERNAL_SERVER_ERROR\");\n\t\t\t}\n\t\t},\n\t);\n\n/**\n * revoke a single session\n */\nexport const revokeSession = createAuthEndpoint(\n\t\"/revoke-session\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\ttoken: z.string().meta({\n\t\t\t\tdescription: \"The token to revoke\",\n\t\t\t}),\n\t\t}),\n\t\tuse: [sensitiveSessionMiddleware],\n\t\trequireHeaders: true,\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Revoke a single session\",\n\t\t\t\trequestBody: {\n\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\ttoken: {\n\t\t\t\t\t\t\t\t\t\ttype: \"string\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"The token to revoke\",\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\trequired: [\"token\"],\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\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if the session was revoked successfully\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst token = ctx.body.token;\n\t\tconst session = await ctx.context.internalAdapter.findSession(token);\n\n\t\tif (session?.session.userId === ctx.context.session.user.id) {\n\t\t\ttry {\n\t\t\t\tawait ctx.context.internalAdapter.deleteSession(token);\n\t\t\t} catch (error) {\n\t\t\t\tctx.context.logger.error(\n\t\t\t\t\terror && typeof error === \"object\" && \"name\" in error\n\t\t\t\t\t\t? (error.name as string)\n\t\t\t\t\t\t: \"\",\n\t\t\t\t\terror,\n\t\t\t\t);\n\t\t\t\tthrow APIError.from(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\tmessage: \"Internal Server Error\",\n\t\t\t\t\tcode: \"INTERNAL_SERVER_ERROR\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n/**\n * revoke all user sessions\n */\nexport const revokeSessions = createAuthEndpoint(\n\t\"/revoke-sessions\",\n\t{\n\t\tmethod: \"POST\",\n\t\tuse: [sensitiveSessionMiddleware],\n\t\trequireHeaders: true,\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription: \"Revoke all sessions for the user\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if all sessions were revoked successfully\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\ttry {\n\t\t\tawait ctx.context.internalAdapter.deleteSessions(\n\t\t\t\tctx.context.session.user.id,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tctx.context.logger.error(\n\t\t\t\terror && typeof error === \"object\" && \"name\" in error\n\t\t\t\t\t? (error.name as string)\n\t\t\t\t\t: \"\",\n\t\t\t\terror,\n\t\t\t);\n\t\t\tthrow APIError.from(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\tmessage: \"Internal Server Error\",\n\t\t\t\tcode: \"INTERNAL_SERVER_ERROR\",\n\t\t\t});\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const revokeOtherSessions = createAuthEndpoint(\n\t\"/revoke-other-sessions\",\n\t{\n\t\tmethod: \"POST\",\n\t\trequireHeaders: true,\n\t\tuse: [sensitiveSessionMiddleware],\n\t\tmetadata: {\n\t\t\topenapi: {\n\t\t\t\tdescription:\n\t\t\t\t\t\"Revoke all other sessions for the user except the current one\",\n\t\t\t\tresponses: {\n\t\t\t\t\t\"200\": {\n\t\t\t\t\t\tdescription: \"Success\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\t\"application/json\": {\n\t\t\t\t\t\t\t\tschema: {\n\t\t\t\t\t\t\t\t\ttype: \"object\",\n\t\t\t\t\t\t\t\t\tproperties: {\n\t\t\t\t\t\t\t\t\t\tstatus: {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"boolean\",\n\t\t\t\t\t\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\t\t\t\t\t\"Indicates if all other sessions were revoked successfully\",\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\trequired: [\"status\"],\n\t\t\t\t\t\t\t\t},\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},\n\t},\n\tasync (ctx) => {\n\t\tconst session = ctx.context.session;\n\t\tif (!session.user) {\n\t\t\tthrow APIError.from(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Unauthorized\",\n\t\t\t\tcode: \"UNAUTHORIZED\",\n\t\t\t});\n\t\t}\n\t\tconst sessions = await ctx.context.internalAdapter.listSessions(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst activeSessions = sessions.filter((session) => {\n\t\t\treturn session.expiresAt > new Date();\n\t\t});\n\t\tconst otherSessions = activeSessions.filter(\n\t\t\t(session) => session.token !== ctx.context.session.session.token,\n\t\t);\n\t\tawait Promise.all(\n\t\t\totherSessions.map((session) =>\n\t\t\t\tctx.context.internalAdapter.deleteSession(session.token),\n\t\t\t),\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { InferUser } from "../../types/models.mjs";
2
2
  import "../../types/index.mjs";
3
3
  import { BetterAuthOptions } from "@better-auth/core";
4
4
  import * as z from "zod";
5
- import * as better_call894 from "better-call";
5
+ import * as better_call738 from "better-call";
6
6
 
7
7
  //#region src/api/routes/sign-in.d.ts
8
8
  declare const socialSignInBodySchema: z.ZodObject<{
@@ -23,7 +23,7 @@ declare const socialSignInBodySchema: z.ZodObject<{
23
23
  loginHint: z.ZodOptional<z.ZodString>;
24
24
  additionalData: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodAny>>;
25
25
  }, z.core.$strip>;
26
- declare const signInSocial: <O extends BetterAuthOptions>() => better_call894.StrictEndpoint<"/sign-in/social", {
26
+ declare const signInSocial: <O extends BetterAuthOptions>() => better_call738.StrictEndpoint<"/sign-in/social", {
27
27
  method: "POST";
28
28
  operationId: string;
29
29
  body: z.ZodObject<{
@@ -98,7 +98,7 @@ declare const signInSocial: <O extends BetterAuthOptions>() => better_call894.St
98
98
  url: undefined;
99
99
  user: InferUser<O>;
100
100
  }>;
101
- declare const signInEmail: <O extends BetterAuthOptions>() => better_call894.StrictEndpoint<"/sign-in/email", {
101
+ declare const signInEmail: <O extends BetterAuthOptions>() => better_call738.StrictEndpoint<"/sign-in/email", {
102
102
  method: "POST";
103
103
  operationId: string;
104
104
  body: z.ZodObject<{
@@ -4,9 +4,8 @@ import { setSessionCookie } from "../../cookies/index.mjs";
4
4
  import { handleOAuthUserInfo } from "../../oauth2/link-account.mjs";
5
5
  import { createEmailVerificationToken } from "./email-verification.mjs";
6
6
  import "../../utils/index.mjs";
7
- import { BASE_ERROR_CODES } from "@better-auth/core/error";
7
+ import { APIError, BASE_ERROR_CODES } from "@better-auth/core/error";
8
8
  import * as z from "zod";
9
- import { APIError } from "better-call";
10
9
  import { SocialProviderListEnum } from "@better-auth/core/social-providers";
11
10
  import { createAuthEndpoint } from "@better-auth/core/api";
12
11
 
@@ -71,17 +70,17 @@ const signInSocial = () => createAuthEndpoint("/sign-in/social", {
71
70
  const provider = c.context.socialProviders.find((p) => p.id === c.body.provider);
72
71
  if (!provider) {
73
72
  c.context.logger.error("Provider not found. Make sure to add the provider in your auth config", { provider: c.body.provider });
74
- throw new APIError("NOT_FOUND", { message: BASE_ERROR_CODES.PROVIDER_NOT_FOUND });
73
+ throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.PROVIDER_NOT_FOUND);
75
74
  }
76
75
  if (c.body.idToken) {
77
76
  if (!provider.verifyIdToken) {
78
77
  c.context.logger.error("Provider does not support id token verification", { provider: c.body.provider });
79
- throw new APIError("NOT_FOUND", { message: BASE_ERROR_CODES.ID_TOKEN_NOT_SUPPORTED });
78
+ throw APIError.from("NOT_FOUND", BASE_ERROR_CODES.ID_TOKEN_NOT_SUPPORTED);
80
79
  }
81
80
  const { token, nonce } = c.body.idToken;
82
81
  if (!await provider.verifyIdToken(token, nonce)) {
83
82
  c.context.logger.error("Invalid id token", { provider: c.body.provider });
84
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.INVALID_TOKEN });
83
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.INVALID_TOKEN);
85
84
  }
86
85
  const userInfo = await provider.getUserInfo({
87
86
  idToken: token,
@@ -90,11 +89,11 @@ const signInSocial = () => createAuthEndpoint("/sign-in/social", {
90
89
  });
91
90
  if (!userInfo || !userInfo?.user) {
92
91
  c.context.logger.error("Failed to get user info", { provider: c.body.provider });
93
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO });
92
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.FAILED_TO_GET_USER_INFO);
94
93
  }
95
94
  if (!userInfo.user.email) {
96
95
  c.context.logger.error("User email not found", { provider: c.body.provider });
97
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.USER_EMAIL_NOT_FOUND });
96
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.USER_EMAIL_NOT_FOUND);
98
97
  }
99
98
  const data = await handleOAuthUserInfo(c, {
100
99
  userInfo: {
@@ -113,7 +112,10 @@ const signInSocial = () => createAuthEndpoint("/sign-in/social", {
113
112
  callbackURL: c.body.callbackURL,
114
113
  disableSignUp: provider.disableImplicitSignUp && !c.body.requestSignUp || provider.disableSignUp
115
114
  });
116
- if (data.error) throw new APIError("UNAUTHORIZED", { message: data.error });
115
+ if (data.error) throw APIError.from("UNAUTHORIZED", {
116
+ message: data.error,
117
+ code: "OAUTH_LINK_ERROR"
118
+ });
117
119
  await setSessionCookie(c, data.data);
118
120
  return c.json({
119
121
  redirect: false,
@@ -187,37 +189,40 @@ const signInEmail = () => createAuthEndpoint("/sign-in/email", {
187
189
  }, async (ctx) => {
188
190
  if (!ctx.context.options?.emailAndPassword?.enabled) {
189
191
  ctx.context.logger.error("Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!");
190
- throw new APIError("BAD_REQUEST", { message: "Email and password is not enabled" });
192
+ throw APIError.from("BAD_REQUEST", {
193
+ code: "EMAIL_PASSWORD_DISABLED",
194
+ message: "Email and password is not enabled"
195
+ });
191
196
  }
192
197
  const { email, password } = ctx.body;
193
- if (!z.email().safeParse(email).success) throw new APIError("BAD_REQUEST", { message: BASE_ERROR_CODES.INVALID_EMAIL });
198
+ if (!z.email().safeParse(email).success) throw APIError.from("BAD_REQUEST", BASE_ERROR_CODES.INVALID_EMAIL);
194
199
  const user = await ctx.context.internalAdapter.findUserByEmail(email, { includeAccounts: true });
195
200
  if (!user) {
196
201
  await ctx.context.password.hash(password);
197
202
  ctx.context.logger.error("User not found", { email });
198
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD });
203
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD);
199
204
  }
200
205
  const credentialAccount = user.accounts.find((a) => a.providerId === "credential");
201
206
  if (!credentialAccount) {
202
207
  await ctx.context.password.hash(password);
203
208
  ctx.context.logger.error("Credential account not found", { email });
204
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD });
209
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD);
205
210
  }
206
211
  const currentPassword = credentialAccount?.password;
207
212
  if (!currentPassword) {
208
213
  await ctx.context.password.hash(password);
209
214
  ctx.context.logger.error("Password not found", { email });
210
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD });
215
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD);
211
216
  }
212
217
  if (!await ctx.context.password.verify({
213
218
  hash: currentPassword,
214
219
  password
215
220
  })) {
216
221
  ctx.context.logger.error("Invalid password");
217
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD });
222
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.INVALID_EMAIL_OR_PASSWORD);
218
223
  }
219
224
  if (ctx.context.options?.emailAndPassword?.requireEmailVerification && !user.user.emailVerified) {
220
- if (!ctx.context.options?.emailVerification?.sendVerificationEmail) throw new APIError("FORBIDDEN", { message: BASE_ERROR_CODES.EMAIL_NOT_VERIFIED });
225
+ if (!ctx.context.options?.emailVerification?.sendVerificationEmail) throw APIError.from("FORBIDDEN", BASE_ERROR_CODES.EMAIL_NOT_VERIFIED);
221
226
  if (ctx.context.options?.emailVerification?.sendOnSignIn) {
222
227
  const token = await createEmailVerificationToken(ctx.context.secret, user.user.email, void 0, ctx.context.options.emailVerification?.expiresIn);
223
228
  const callbackURL = ctx.body.callbackURL ? encodeURIComponent(ctx.body.callbackURL) : encodeURIComponent("/");
@@ -228,12 +233,12 @@ const signInEmail = () => createAuthEndpoint("/sign-in/email", {
228
233
  token
229
234
  }, ctx.request));
230
235
  }
231
- throw new APIError("FORBIDDEN", { message: BASE_ERROR_CODES.EMAIL_NOT_VERIFIED });
236
+ throw APIError.from("FORBIDDEN", BASE_ERROR_CODES.EMAIL_NOT_VERIFIED);
232
237
  }
233
238
  const session = await ctx.context.internalAdapter.createSession(user.user.id, ctx.body.rememberMe === false);
234
239
  if (!session) {
235
240
  ctx.context.logger.error("Failed to create session");
236
- throw new APIError("UNAUTHORIZED", { message: BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION });
241
+ throw APIError.from("UNAUTHORIZED", BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION);
237
242
  }
238
243
  await setSessionCookie(ctx, {
239
244
  session,