better-auth 0.6.2-beta.4 → 0.6.2-beta.6

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 (64) hide show
  1. package/dist/api.cjs +1 -1
  2. package/dist/api.cjs.map +1 -1
  3. package/dist/api.js +1 -1
  4. package/dist/chunk-34NVICFQ.js +85 -0
  5. package/dist/chunk-34NVICFQ.js.map +1 -0
  6. package/dist/chunk-5MAH3KZL.js +2 -0
  7. package/dist/chunk-5MAH3KZL.js.map +1 -0
  8. package/dist/chunk-727CSAR4.js +2 -0
  9. package/dist/chunk-727CSAR4.js.map +1 -0
  10. package/dist/chunk-CZEDMXB5.cjs +2 -0
  11. package/dist/chunk-CZEDMXB5.cjs.map +1 -0
  12. package/dist/chunk-HKHGHEMG.js +2 -0
  13. package/dist/chunk-HKHGHEMG.js.map +1 -0
  14. package/dist/chunk-K7YCIO4R.cjs +85 -0
  15. package/dist/chunk-K7YCIO4R.cjs.map +1 -0
  16. package/dist/chunk-KRITL7AB.cjs +2 -0
  17. package/dist/chunk-KRITL7AB.cjs.map +1 -0
  18. package/dist/chunk-KUWS4XJC.cjs +2 -0
  19. package/dist/chunk-KUWS4XJC.cjs.map +1 -0
  20. package/dist/chunk-L75WJCSN.js +2 -0
  21. package/dist/chunk-L75WJCSN.js.map +1 -0
  22. package/dist/chunk-OK6SC5MD.js +2 -0
  23. package/dist/chunk-OK6SC5MD.js.map +1 -0
  24. package/dist/chunk-OLSW6BBQ.js +2 -0
  25. package/dist/chunk-OLSW6BBQ.js.map +1 -0
  26. package/dist/chunk-QRD23MTT.cjs +2 -0
  27. package/dist/chunk-QRD23MTT.cjs.map +1 -0
  28. package/dist/chunk-RGMELFK6.cjs +2 -0
  29. package/dist/chunk-RGMELFK6.cjs.map +1 -0
  30. package/dist/chunk-ZHX7Q23Q.cjs +2 -0
  31. package/dist/chunk-ZHX7Q23Q.cjs.map +1 -0
  32. package/dist/client/plugins.cjs +1 -1
  33. package/dist/client/plugins.cjs.map +1 -1
  34. package/dist/client/plugins.js +1 -1
  35. package/dist/client/plugins.js.map +1 -1
  36. package/dist/client.cjs +1 -1
  37. package/dist/client.js +1 -1
  38. package/dist/cookies.cjs +1 -1
  39. package/dist/cookies.js +1 -1
  40. package/dist/crypto.cjs +1 -1
  41. package/dist/crypto.cjs.map +1 -1
  42. package/dist/crypto.js +1 -1
  43. package/dist/db.cjs +1 -1
  44. package/dist/db.js +1 -1
  45. package/dist/index.cjs +1 -1
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.js +1 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/plugins.cjs +2 -2
  50. package/dist/plugins.cjs.map +1 -1
  51. package/dist/plugins.js +2 -2
  52. package/dist/plugins.js.map +1 -1
  53. package/dist/react.cjs +1 -1
  54. package/dist/react.js +1 -1
  55. package/dist/social.cjs +1 -1
  56. package/dist/social.cjs.map +1 -1
  57. package/dist/social.js +1 -1
  58. package/dist/solid.cjs +1 -1
  59. package/dist/solid.js +1 -1
  60. package/dist/svelte.cjs +1 -1
  61. package/dist/svelte.js +1 -1
  62. package/dist/vue.cjs +1 -1
  63. package/dist/vue.js +1 -1
  64. package/package.json +1 -1
package/dist/api.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkUGP43E4Icjs = require('./chunk-UGP43E4I.cjs');require('./chunk-5CGFZN2L.cjs');require('./chunk-2BBAB6DP.cjs');require('./chunk-4INQICGP.cjs');require('./chunk-U5FXGV3G.cjs');require('./chunk-DMAK6URH.cjs');require('./chunk-6YSOZOBL.cjs');require('./chunk-OQSWDMGG.cjs');require('./chunk-4CFYZITA.cjs');require('./chunk-LF4SJYGR.cjs');require('./chunk-WNGZ4EQP.cjs');require('./chunk-M4G6J7DP.cjs');exports.APIError = _chunkUGP43E4Icjs.J; exports.callbackOAuth = _chunkUGP43E4Icjs.r; exports.changeEmail = _chunkUGP43E4Icjs.A; exports.changePassword = _chunkUGP43E4Icjs.x; exports.createAuthEndpoint = _chunkUGP43E4Icjs.c; exports.createAuthMiddleware = _chunkUGP43E4Icjs.b; exports.createEmailVerificationToken = _chunkUGP43E4Icjs.l; exports.csrfMiddleware = _chunkUGP43E4Icjs.d; exports.deleteUser = _chunkUGP43E4Icjs.z; exports.error = _chunkUGP43E4Icjs.C; exports.forgetPassword = _chunkUGP43E4Icjs.t; exports.forgetPasswordCallback = _chunkUGP43E4Icjs.u; exports.getCSRFToken = _chunkUGP43E4Icjs.B; exports.getEndpoints = _chunkUGP43E4Icjs.H; exports.getSession = _chunkUGP43E4Icjs.f; exports.getSessionFromCtx = _chunkUGP43E4Icjs.g; exports.linkSocialAccount = _chunkUGP43E4Icjs.G; exports.listSessions = _chunkUGP43E4Icjs.i; exports.listUserAccounts = _chunkUGP43E4Icjs.F; exports.ok = _chunkUGP43E4Icjs.D; exports.optionsMiddleware = _chunkUGP43E4Icjs.a; exports.resetPassword = _chunkUGP43E4Icjs.v; exports.revokeSession = _chunkUGP43E4Icjs.j; exports.revokeSessions = _chunkUGP43E4Icjs.k; exports.router = _chunkUGP43E4Icjs.I; exports.sendVerificationEmail = _chunkUGP43E4Icjs.m; exports.sessionMiddleware = _chunkUGP43E4Icjs.h; exports.setPassword = _chunkUGP43E4Icjs.y; exports.signInEmail = _chunkUGP43E4Icjs.p; exports.signInOAuth = _chunkUGP43E4Icjs.o; exports.signOut = _chunkUGP43E4Icjs.s; exports.signUpEmail = _chunkUGP43E4Icjs.E; exports.updateUser = _chunkUGP43E4Icjs.w; exports.verifyEmail = _chunkUGP43E4Icjs.n;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var _chunkK7YCIO4Rcjs = require('./chunk-K7YCIO4R.cjs');require('./chunk-5CGFZN2L.cjs');require('./chunk-YAP2H3N7.cjs');require('./chunk-252SWVAC.cjs');require('./chunk-U5FXGV3G.cjs');require('./chunk-DMAK6URH.cjs');require('./chunk-6YSOZOBL.cjs');require('./chunk-BF3ZIVEP.cjs');require('./chunk-4CFYZITA.cjs');require('./chunk-5OJURFG2.cjs');require('./chunk-WNGZ4EQP.cjs');require('./chunk-M4G6J7DP.cjs');exports.APIError = _chunkK7YCIO4Rcjs.I; exports.callbackOAuth = _chunkK7YCIO4Rcjs.r; exports.changeEmail = _chunkK7YCIO4Rcjs.A; exports.changePassword = _chunkK7YCIO4Rcjs.x; exports.createAuthEndpoint = _chunkK7YCIO4Rcjs.c; exports.createAuthMiddleware = _chunkK7YCIO4Rcjs.b; exports.createEmailVerificationToken = _chunkK7YCIO4Rcjs.l; exports.deleteUser = _chunkK7YCIO4Rcjs.z; exports.error = _chunkK7YCIO4Rcjs.B; exports.forgetPassword = _chunkK7YCIO4Rcjs.t; exports.forgetPasswordCallback = _chunkK7YCIO4Rcjs.u; exports.getEndpoints = _chunkK7YCIO4Rcjs.G; exports.getSession = _chunkK7YCIO4Rcjs.f; exports.getSessionFromCtx = _chunkK7YCIO4Rcjs.g; exports.linkSocialAccount = _chunkK7YCIO4Rcjs.F; exports.listSessions = _chunkK7YCIO4Rcjs.i; exports.listUserAccounts = _chunkK7YCIO4Rcjs.E; exports.ok = _chunkK7YCIO4Rcjs.C; exports.optionsMiddleware = _chunkK7YCIO4Rcjs.a; exports.originCheckMiddleware = _chunkK7YCIO4Rcjs.d; exports.resetPassword = _chunkK7YCIO4Rcjs.v; exports.revokeSession = _chunkK7YCIO4Rcjs.j; exports.revokeSessions = _chunkK7YCIO4Rcjs.k; exports.router = _chunkK7YCIO4Rcjs.H; exports.sendVerificationEmail = _chunkK7YCIO4Rcjs.m; exports.sessionMiddleware = _chunkK7YCIO4Rcjs.h; exports.setPassword = _chunkK7YCIO4Rcjs.y; exports.signInEmail = _chunkK7YCIO4Rcjs.p; exports.signInOAuth = _chunkK7YCIO4Rcjs.o; exports.signOut = _chunkK7YCIO4Rcjs.s; exports.signUpEmail = _chunkK7YCIO4Rcjs.D; exports.updateUser = _chunkK7YCIO4Rcjs.w; exports.verifyEmail = _chunkK7YCIO4Rcjs.n;
2
2
  //# sourceMappingURL=api.cjs.map
package/dist/api.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/beka/Desktop/Development/better-auth/packages/better-auth/dist/api.cjs"],"names":[],"mappings":"AAAA,iIAA2P,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,+/CAAopB","file":"/Users/beka/Desktop/Development/better-auth/packages/better-auth/dist/api.cjs"}
1
+ {"version":3,"sources":["/Users/beka/Desktop/Development/better-auth/packages/better-auth/dist/api.cjs"],"names":[],"mappings":"AAAA,iIAAoP,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,gCAA6B,09CAAyoB","file":"/Users/beka/Desktop/Development/better-auth/packages/better-auth/dist/api.cjs"}
package/dist/api.js CHANGED
@@ -1,2 +1,2 @@
1
- import{A as y,B as z,C as A,D as B,E as C,F as D,G as E,H as F,I as G,J as H,a,b,c,d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,m as l,n as m,o as n,p as o,r as p,s as q,t as r,u as s,v as t,w as u,x as v,y as w,z as x}from"./chunk-S56R3UUZ.js";import"./chunk-57KKPQYR.js";import"./chunk-UMXT2JXJ.js";import"./chunk-L3RMKKWR.js";import"./chunk-4X5O2226.js";import"./chunk-TUL3AUOB.js";import"./chunk-C57CCQKY.js";import"./chunk-CO5UG7AX.js";import"./chunk-AFA2APLD.js";import"./chunk-4CY5SJAH.js";import"./chunk-GNYPEE5I.js";import"./chunk-4C666HHU.js";export{H as APIError,p as callbackOAuth,y as changeEmail,v as changePassword,c as createAuthEndpoint,b as createAuthMiddleware,k as createEmailVerificationToken,d as csrfMiddleware,x as deleteUser,A as error,r as forgetPassword,s as forgetPasswordCallback,z as getCSRFToken,F as getEndpoints,e as getSession,f as getSessionFromCtx,E as linkSocialAccount,h as listSessions,D as listUserAccounts,B as ok,a as optionsMiddleware,t as resetPassword,i as revokeSession,j as revokeSessions,G as router,l as sendVerificationEmail,g as sessionMiddleware,w as setPassword,o as signInEmail,n as signInOAuth,q as signOut,C as signUpEmail,u as updateUser,m as verifyEmail};
1
+ import{A as y,B as z,C as A,D as B,E as C,F as D,G as E,H as F,I as G,a,b,c,d,f as e,g as f,h as g,i as h,j as i,k as j,l as k,m as l,n as m,o as n,p as o,r as p,s as q,t as r,u as s,v as t,w as u,x as v,y as w,z as x}from"./chunk-34NVICFQ.js";import"./chunk-57KKPQYR.js";import"./chunk-BEPTBELC.js";import"./chunk-Q3A6PFDU.js";import"./chunk-4X5O2226.js";import"./chunk-TUL3AUOB.js";import"./chunk-C57CCQKY.js";import"./chunk-N7CDYTQY.js";import"./chunk-AFA2APLD.js";import"./chunk-Y2NG2HM2.js";import"./chunk-GNYPEE5I.js";import"./chunk-4C666HHU.js";export{G as APIError,p as callbackOAuth,y as changeEmail,v as changePassword,c as createAuthEndpoint,b as createAuthMiddleware,k as createEmailVerificationToken,x as deleteUser,z as error,r as forgetPassword,s as forgetPasswordCallback,E as getEndpoints,e as getSession,f as getSessionFromCtx,D as linkSocialAccount,h as listSessions,C as listUserAccounts,A as ok,a as optionsMiddleware,d as originCheckMiddleware,t as resetPassword,i as revokeSession,j as revokeSessions,F as router,l as sendVerificationEmail,g as sessionMiddleware,w as setPassword,o as signInEmail,n as signInOAuth,q as signOut,B as signUpEmail,u as updateUser,m as verifyEmail};
2
2
  //# sourceMappingURL=api.js.map
@@ -0,0 +1,85 @@
1
+ import{a as X}from"./chunk-57KKPQYR.js";import{a as D,n as F}from"./chunk-BEPTBELC.js";import{a as Y,c as g}from"./chunk-Q3A6PFDU.js";import{a as K,b as M,c as W}from"./chunk-4X5O2226.js";import{a as Q}from"./chunk-TUL3AUOB.js";import{c as T,d as _}from"./chunk-Y2NG2HM2.js";import{APIError as Ie,createRouter as Ye,statusCode as Ke}from"better-call";import{APIError as _e}from"better-call";import{createEndpointCreator as Pe,createMiddleware as ee,createMiddlewareCreator as xe}from"better-call";var te=ee(async()=>({})),B=xe({use:[te,ee(async()=>({}))]}),p=Pe({use:[te]});var oe=B(async e=>{if(e.context.options.advanced?.disableOriginCheck||e.request?.method!=="POST")return;let{body:t,query:o,context:r}=e,s=e.headers?.get("origin")||e.headers?.get("referer")||"",n=t?.callbackURL,i=t?.redirectTo,d=o?.currentURL,l=r.trustedOrigins,a=(c,f)=>{if(!l.some(u=>c?.startsWith(u)||c?.startsWith("/")&&f!=="origin"))throw g.error(`Invalid ${f}: ${c}`),g.info(`If it's a valid URL, please add ${c} to trustedOrigins in your auth config
2
+ `,`Current list of trustedOrigins: ${l}`),new _e("FORBIDDEN",{message:`Invalid ${f}`})};n&&a(n,"callbackURL"),i&&a(i,"redirectURL"),d&&a(d,"currentURL"),a(s,"origin")});import{APIError as I}from"better-call";import{generateCodeVerifier as Ve}from"oslo/oauth2";import{z as L}from"zod";import{APIError as Ce}from"better-call";var b=B(async e=>{let{body:t,query:o,context:r}=e,s=t?.callbackURL||o?.callbackURL||o?.redirectTo||t?.redirectTo,n=o?.currentURL,i=r.trustedOrigins,d=(l,a)=>{if(l?.startsWith("http")&&!i.some(f=>l.startsWith(f)))throw g.error(`Invalid ${a}: ${l}`),g.info(`If it's a valid URL, please add ${l} to trustedOrigins in your auth config
3
+ `,`Current list of trustedOrigins: ${i}`),new Ce("FORBIDDEN",{message:`Invalid ${a}`})};d(s,"callbackURL"),d(n,"currentURL")});import{TimeSpan as De}from"oslo";import{createJWT as Be,validateJWT as qe}from"oslo/jwt";import{z as O}from"zod";import{APIError as q}from"better-call";import{APIError as j}from"better-call";import{z as $}from"zod";var J=()=>p("/get-session",{method:"GET",query:$.optional($.object({disableCookieCache:$.boolean().optional()})),requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let o=await e.getSignedCookie(e.context.authCookies.sessionData.name,e.context.secret),r=await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret);if(o&&e.context.options.session?.cookieCache?.enabled&&!e.query?.disableCookieCache){let a=JSON.parse(o)?.session;if(a?.expiresAt>new Date)return e.json(a)}let s=await e.context.internalAdapter.findSession(t);if(!s||s.session.expiresAt<new Date)return _(e),s&&await e.context.internalAdapter.deleteSession(s.session.id),e.json(null,{status:401});if(r)return e.json(s);let n=e.context.sessionConfig.expiresIn,i=e.context.sessionConfig.updateAge;if(s.session.expiresAt.valueOf()-n*1e3+i*1e3<=Date.now()){let a=await e.context.internalAdapter.updateSession(s.session.id,{expiresAt:Q(e.context.sessionConfig.expiresIn,"sec")});if(!a)return _(e),e.json(null,{status:401});let c=(a.expiresAt.valueOf()-Date.now())/1e3;return await T(e,{session:a,user:s.user},!1,{maxAge:c}),e.json({session:a,user:s.user})}return e.json(s)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),G=async e=>await J()({...e,_flag:"json",headers:e.headers}),k=B(async e=>{let t=await G(e);if(!t?.session)throw new j("UNAUTHORIZED");return{session:t}}),re=()=>p("/user/list-sessions",{method:"GET",use:[k],requireHeaders:!0},async e=>{let o=(await e.context.internalAdapter.listSessions(e.context.session.user.id)).filter(r=>r.expiresAt>new Date);return e.json(o)}),se=p("/user/revoke-session",{method:"POST",body:$.object({id:$.string()}),use:[k],requireHeaders:!0},async e=>{let t=e.body.id,o=await e.context.internalAdapter.findSession(t);if(!o)throw new j("BAD_REQUEST",{message:"Session not found"});if(o.session.userId!==e.context.session.user.id)throw new j("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(r){throw e.context.logger.error(r),new j("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),ne=p("/user/revoke-sessions",{method:"POST",use:[k],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new j("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});async function P(e,t,o){return await Be("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:o},{expiresIn:new De(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var ie=p("/send-verification-email",{method:"POST",query:O.object({currentURL:O.string().optional()}).optional(),body:O.object({email:O.string().email(),callbackURL:O.string().optional()}),use:[b]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new q("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,o=await e.context.internalAdapter.findUserByEmail(t);if(!o)throw new q("BAD_REQUEST",{message:"User not found"});let r=await P(e.context.secret,t),s=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(o.user,s,r),e.json({status:!0})}),ae=p("/verify-email",{method:"GET",query:O.object({token:O.string(),callbackURL:O.string().optional()}),use:[b]},async e=>{let{token:t}=e.query,o;try{o=await qe("HS256",Buffer.from(e.context.secret),t)}catch(i){throw e.context.logger.error("Failed to verify email",i),new q("BAD_REQUEST",{message:"Invalid token"})}let s=O.object({email:O.string().email(),updateTo:O.string().optional()}).parse(o.payload);if(!await e.context.internalAdapter.findUserByEmail(s.email))throw new q("BAD_REQUEST",{message:"User not found"});if(s.updateTo){let i=await G(e);if(!i)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new q("UNAUTHORIZED",{message:"Session not found"});if(i.user.email!==s.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new q("UNAUTHORIZED",{message:"Invalid session"});let d=await e.context.internalAdapter.updateUserByEmail(s.email,{email:s.updateTo});if(await e.context.options.emailVerification?.sendVerificationEmail?.(d,`${e.context.baseURL}/verify-email?token=${t}`,t),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:d,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(s.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var de=p("/sign-in/social",{method:"POST",requireHeaders:!0,query:L.object({currentURL:L.string().optional()}).optional(),body:L.object({callbackURL:L.string().optional(),provider:L.enum(F)}),use:[b]},async e=>{let t=e.context.socialProviders.find(l=>l.id===e.body.provider);if(!t)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new I("NOT_FOUND",{message:"Provider not found"});let o=e.context.authCookies,r=e.query?.currentURL?new URL(e.query?.currentURL):null,s=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${r?.origin}${e.body.callbackURL||""}`,n=await M(s||r?.origin||e.context.options.baseURL);await e.setSignedCookie(o.state.name,n.hash,e.context.secret,o.state.options);let i=Ve();await e.setSignedCookie(o.pkCodeVerifier.name,i,e.context.secret,o.pkCodeVerifier.options);let d=await t.createAuthorizationURL({state:n.raw,codeVerifier:i,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:d.toString(),state:n,codeVerifier:i,redirect:!0})}),ce=p("/sign-in/email",{method:"POST",body:L.object({email:L.string(),password:L.string(),callbackURL:L.string().optional(),dontRememberMe:L.boolean().default(!1).optional()}),use:[b]},async e=>{if(!e.context.options?.emailAndPassword?.enabled)throw e.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!"),new I("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:o}=e.body;if(!L.string().email().safeParse(t).success)throw new I("BAD_REQUEST",{message:"Invalid email"});if(!L.string().email().safeParse(t).success)throw new I("BAD_REQUEST",{message:"Invalid email"});let n=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!n)throw await e.context.password.hash(o),e.context.logger.error("User not found",{email:t}),new I("UNAUTHORIZED",{message:"Invalid email or password"});let i=n.accounts.find(c=>c.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new I("UNAUTHORIZED",{message:"Invalid email or password"});let d=i?.password;if(!d)throw e.context.logger.error("Password not found",{email:t}),new I("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(d,o))throw e.context.logger.error("Invalid password"),new I("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!n.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw g.error("Email verification is required but no email verification handler is provided"),new I("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let c=await P(e.context.secret,n.user.email),f=`${e.context.options.baseURL}/verify-email?token=${c}`;throw await e.context.options.emailVerification.sendVerificationEmail(n.user,f,c),e.context.logger.error("Email not verified",{email:t}),new I("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let a=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!a)throw e.context.logger.error("Failed to create session"),new I("UNAUTHORIZED",{message:"Failed to create session"});return await T(e,{session:a,user:n.user},e.body.dontRememberMe),e.json({user:n.user,session:a,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as H}from"zod";import{z as m}from"zod";var qt=m.object({id:m.string(),providerId:m.string(),accountId:m.string(),userId:m.string(),accessToken:m.string().nullable().optional(),refreshToken:m.string().nullable().optional(),idToken:m.string().nullable().optional(),expiresAt:m.date().nullable().optional(),password:m.string().optional().nullable()}),le=m.object({id:m.string(),email:m.string().transform(e=>e.toLowerCase()),emailVerified:m.boolean().default(!1),name:m.string(),image:m.string().optional(),createdAt:m.date().default(new Date),updatedAt:m.date().default(new Date)}),Vt=m.object({id:m.string(),userId:m.string(),expiresAt:m.date(),ipAddress:m.string().optional(),userAgent:m.string().optional()}),jt=m.object({id:m.string(),value:m.string(),expiresAt:m.date(),identifier:m.string()});function je(e,t){let o={...t==="user"?e.user?.additionalFields:{},...t==="session"?e.session?.additionalFields:{}};for(let r of e.plugins||[])r.schema&&r.schema[t]&&(o={...o,...r.schema[t].fields});return o}function $e(e,t){let o=t.action||"create",r=t.fields,s={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){s[n]=r[n].defaultValue;continue}continue}s[n]=e[n];continue}if(r[n].defaultValue&&o==="create"){s[n]=r[n].defaultValue;continue}}return s}function Z(e,t,o){let r=je(e,"user");return $e(t||{},{fields:r,action:o})}import{isDevelopment as Ne}from"std-env";var ue=p("/callback/:id",{method:"GET",query:H.object({state:H.string(),code:H.string().optional(),error:H.string().optional()}),metadata:D},async e=>{if(e.query.error||!e.query.code){let S=W(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${S}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(w=>w.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let o=W(e.query.state);if(!o.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:r,currentURL:s,link:n}}=o,i=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!i)throw g.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await K(e.query.state,i))throw g.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let l=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),a;try{a=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:l,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(w){throw e.context.logger.error(w),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(a).then(w=>w?.user),f=Y(),y=le.safeParse({...c,id:f});if(!c||y.success===!1)throw g.error("Unable to get user info",y.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!r)throw g.error("No callback URL found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(n){if(n.email!==c.email.toLowerCase())return u("email_doesn't_match");if(!await e.context.internalAdapter.createAccount({userId:n.userId,providerId:t.id,accountId:c.id}))return u("unable_to_link_account");throw e.redirect(r||s||e.context.options.baseURL)}function u(w){throw e.redirect(`${s||r||`${e.context.baseURL}/error`}?error=${w}`)}let A=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(w=>{throw g.error(`Better auth was unable to query your database.
4
+ Error: `,w),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),R=A?.user;if(A){let w=A.accounts.find(S=>S.providerId===t.id);if(w)await e.context.internalAdapter.updateAccount(w.id,{accessToken:a.accessToken,idToken:a.idToken,refreshToken:a.refreshToken,expiresAt:a.accessTokenExpiresAt});else{(!e.context.options.account?.accountLinking?.trustedProviders?.includes(t.id)&&!c.emailVerified||!e.context.options.account?.accountLinking?.enabled)&&(Ne&&g.warn(`User already exist but account isn't linked to ${t.id}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`),u("account_not_linked"));try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:A.user.id,accessToken:a.accessToken,idToken:a.idToken,refreshToken:a.refreshToken,expiresAt:a.accessTokenExpiresAt})}catch(ve){g.error("Unable to link account",ve),u("unable_to_link_account")}}}else try{let w=c.emailVerified||!1;if(R=await e.context.internalAdapter.createOAuthUser({...y.data,emailVerified:w},{accessToken:a.accessToken,idToken:a.idToken,refreshToken:a.refreshToken,expiresAt:a.accessTokenExpiresAt,providerId:t.id,accountId:c.id.toString()}).then(S=>S?.user),!w&&R&&e.context.options.emailVerification?.sendOnSignUp){let S=await P(e.context.secret,R.email),C=`${e.context.baseURL}/verify-email?token=${S}&callbackURL=${r}`;await e.context.options.emailVerification?.sendVerificationEmail?.(R,C,S)}}catch(w){g.error("Unable to create user",w),u("unable_to_create_user")}if(!R)return u("unable_to_create_user");let h=await e.context.internalAdapter.createSession(R.id,e.request);throw h||u("unable_to_create_session"),await T(e,{session:h,user:R}),e.redirect(r)});import"zod";import{APIError as Me}from"better-call";var pe=p("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Me("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),_(e),e.json({success:!0})});import{z as v}from"zod";import{APIError as z}from"better-call";var me=p("/forget-password",{method:"POST",body:v.object({email:v.string().email(),redirectTo:v.string()}),use:[b]},async e=>{if(!e.context.options.emailAndPassword?.sendResetPassword)throw e.context.logger.error("Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function in your auth config!"),new z("BAD_REQUEST",{message:"Reset password isn't enabled"});let{email:t,redirectTo:o}=e.body,r=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!r)return e.context.logger.error("Reset Password: User not found",{email:t}),e.json({status:!1},{body:{status:!0}});let s=60*60*1,n=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||s)),i=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:r.user.id,identifier:`reset-password:${i}`,expiresAt:n});let d=`${e.context.baseURL}/reset-password/${i}?callbackURL=${o}`;return await e.context.options.emailAndPassword.sendResetPassword(r.user,d),e.json({status:!0})}),fe=p("/reset-password/:token",{method:"GET",query:v.object({callbackURL:v.string()}),use:[b]},async e=>{let{token:t}=e.params,o=e.query.callbackURL,r=o.startsWith("http")?o:`${e.context.options.baseURL}${o}`;if(!t||!o)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let s=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!s||s.expiresAt<new Date?e.redirect(`${r}?error=INVALID_TOKEN`):e.redirect(`${r}${r.includes("?")?"&":"?"}token=${t}`)}),we=p("/reset-password",{query:v.optional(v.object({token:v.string().optional(),currentURL:v.string().optional()})),method:"POST",body:v.object({newPassword:v.string()})},async e=>{let t=e.query?.token||(e.query?.currentURL?new URL(e.query.currentURL).searchParams.get("token"):"");if(!t)throw new z("BAD_REQUEST",{message:"Token not found"});let{newPassword:o}=e.body,r=`reset-password:${t}`,s=await e.context.internalAdapter.findVerificationValue(r);if(!s||s.expiresAt<new Date)throw new z("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(s.id);let n=s.value,i=await e.context.password.hash(o);if(!(await e.context.internalAdapter.findAccounts(n)).find(c=>c.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:n,providerId:"credential",password:i,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(n,i))throw new z("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{z as U}from"zod";import{APIError as E}from"better-call";var ge=()=>p("/user/update",{method:"POST",body:U.record(U.string(),U.any()),use:[k,b]},async e=>{let t=e.body;if(t.email)throw new E("BAD_REQUEST",{message:"You can't update email"});let{name:o,image:r,...s}=t,n=e.context.session;if(!r&&!o&&Object.keys(s).length===0)return e.json({user:n.user});let i=Z(e.context.options,s,"update"),d=await e.context.internalAdapter.updateUserByEmail(n.user.email,{name:o,image:r,...i});return await T(e,{session:n.session,user:d}),e.json({user:d})}),he=p("/user/change-password",{method:"POST",body:U.object({newPassword:U.string(),currentPassword:U.string(),revokeOtherSessions:U.boolean().optional()}),use:[k]},async e=>{let{newPassword:t,currentPassword:o,revokeOtherSessions:r}=e.body,s=e.context.session,n=e.context.password.config.minPasswordLength;if(t.length<n)throw e.context.logger.error("Password is too short"),new E("BAD_REQUEST",{message:"Password is too short"});let i=e.context.password.config.maxPasswordLength;if(t.length>i)throw e.context.logger.error("Password is too long"),new E("BAD_REQUEST",{message:"Password too long"});let l=(await e.context.internalAdapter.findAccounts(s.user.id)).find(f=>f.providerId==="credential"&&f.password);if(!l||!l.password)throw new E("BAD_REQUEST",{message:"User does not have a password"});let a=await e.context.password.hash(t);if(!await e.context.password.verify(l.password,o))throw new E("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(l.id,{password:a}),r){await e.context.internalAdapter.deleteSessions(s.user.id);let f=await e.context.internalAdapter.createSession(s.user.id,e.headers);if(!f)throw new E("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await T(e,{session:f,user:s.user})}return e.json(s.user)}),ye=p("/user/set-password",{method:"POST",body:U.object({newPassword:U.string()}),metadata:{SERVER_ONLY:!0},use:[k]},async e=>{let{newPassword:t}=e.body,o=e.context.session,r=e.context.password.config.minPasswordLength;if(t.length<r)throw e.context.logger.error("Password is too short"),new E("BAD_REQUEST",{message:"Password is too short"});let s=e.context.password.config.maxPasswordLength;if(t.length>s)throw e.context.logger.error("Password is too long"),new E("BAD_REQUEST",{message:"Password too long"});let i=(await e.context.internalAdapter.findAccounts(o.user.id)).find(l=>l.providerId==="credential"&&l.password),d=await e.context.password.hash(t);if(!i)return await e.context.internalAdapter.linkAccount({userId:o.user.id,providerId:"credential",accountId:o.user.id,password:d}),e.json(o.user);throw new E("BAD_REQUEST",{message:"user already has a password"})}),Re=p("/user/delete",{method:"POST",body:U.object({password:U.string()}),use:[k]},async e=>{let{password:t}=e.body,o=e.context.session,s=(await e.context.internalAdapter.findAccounts(o.user.id)).find(i=>i.providerId==="credential"&&i.password);if(!s||!s.password)throw new E("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(s.password,t))throw new E("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(o.user.id),await e.context.internalAdapter.deleteSessions(o.user.id),_(e),e.json(null)}),Ae=p("/user/change-email",{method:"POST",query:U.object({currentURL:U.string().optional()}).optional(),body:U.object({newEmail:U.string().email(),callbackURL:U.string().optional()}),use:[k,b]},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new E("BAD_REQUEST",{message:"Change email is disabled"});if(e.body.newEmail===e.context.session.user.email)throw e.context.logger.error("Email is the same"),new E("BAD_REQUEST",{message:"Email is the same"});if(await e.context.internalAdapter.findUserByEmail(e.body.newEmail))throw e.context.logger.error("Email already exists"),new E("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let s=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:s,status:!0})}if(!e.context.options.user.changeEmail.sendChangeEmailVerification)throw e.context.logger.error("Verification email isn't enabled."),new E("BAD_REQUEST",{message:"Verification email isn't enabled"});let o=await P(e.context.secret,e.context.session.user.email,e.body.newEmail),r=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.user.changeEmail.sendChangeEmailVerification(e.context.session.user,e.body.newEmail,r,o),e.json({user:null,status:!0})});var Qe=(e="Unknown")=>`<!DOCTYPE html>
5
+ <html lang="en">
6
+ <head>
7
+ <meta charset="UTF-8">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
9
+ <title>Authentication Error</title>
10
+ <style>
11
+ :root {
12
+ --bg-color: #f8f9fa;
13
+ --text-color: #212529;
14
+ --accent-color: #000000;
15
+ --error-color: #dc3545;
16
+ --border-color: #e9ecef;
17
+ }
18
+ body {
19
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
20
+ background-color: var(--bg-color);
21
+ color: var(--text-color);
22
+ display: flex;
23
+ justify-content: center;
24
+ align-items: center;
25
+ height: 100vh;
26
+ margin: 0;
27
+ line-height: 1.5;
28
+ }
29
+ .error-container {
30
+ background-color: #ffffff;
31
+ border-radius: 12px;
32
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
33
+ padding: 2.5rem;
34
+ text-align: center;
35
+ max-width: 90%;
36
+ width: 400px;
37
+ }
38
+ h1 {
39
+ color: var(--error-color);
40
+ font-size: 1.75rem;
41
+ margin-bottom: 1rem;
42
+ font-weight: 600;
43
+ }
44
+ p {
45
+ margin-bottom: 1.5rem;
46
+ color: #495057;
47
+ }
48
+ .btn {
49
+ background-color: var(--accent-color);
50
+ color: #ffffff;
51
+ text-decoration: none;
52
+ padding: 0.75rem 1.5rem;
53
+ border-radius: 6px;
54
+ transition: all 0.3s ease;
55
+ display: inline-block;
56
+ font-weight: 500;
57
+ border: 2px solid var(--accent-color);
58
+ }
59
+ .btn:hover {
60
+ background-color: #131721;
61
+ }
62
+ .error-code {
63
+ font-size: 0.875rem;
64
+ color: #6c757d;
65
+ margin-top: 1.5rem;
66
+ padding-top: 1.5rem;
67
+ border-top: 1px solid var(--border-color);
68
+ }
69
+ .icon {
70
+ font-size: 3rem;
71
+ margin-bottom: 1rem;
72
+ }
73
+ </style>
74
+ </head>
75
+ <body>
76
+ <div class="error-container">
77
+ <div class="icon">\u26A0\uFE0F</div>
78
+ <h1>Better Auth Error</h1>
79
+ <p>We encountered an issue while processing your request. Please try again or contact the application owner if the problem persists.</p>
80
+ <a href="/" id="returnLink" class="btn">Return to Application</a>
81
+ <div class="error-code">Error Code: <span id="errorCode">${e}</span></div>
82
+ </div>
83
+ </body>
84
+ </html>`,be=p("/error",{method:"GET",metadata:D},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(Qe(t),{headers:{"Content-Type":"text/html"}})});var Ue=p("/ok",{method:"GET",metadata:D},async e=>e.json({ok:!0}));import{z as V}from"zod";import{APIError as x}from"better-call";var Ee=()=>p("/sign-up/email",{method:"POST",query:V.object({currentURL:V.string().optional()}).optional(),body:V.record(V.string(),V.any()),use:[b]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new x("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:o,email:r,password:s,image:n,callbackURL:i,...d}=t;if(!V.string().email().safeParse(r).success)throw new x("BAD_REQUEST",{message:"Invalid email"});let a=e.context.password.config.minPasswordLength;if(s.length<a)throw e.context.logger.error("Password is too short"),new x("BAD_REQUEST",{message:"Password is too short"});let c=e.context.password.config.maxPasswordLength;if(s.length>c)throw e.context.logger.error("Password is too long"),new x("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(r))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${r}`),new x("UNPROCESSABLE_ENTITY",{message:"User with this email already exists"});let y=Z(e.context.options,d),u;try{if(u=await e.context.internalAdapter.createUser({email:r.toLowerCase(),name:o,image:n,...y,emailVerified:!1}),!u)throw new x("BAD_REQUEST",{message:"Failed to create user"})}catch(h){throw g.error("Failed to create user",h),new x("UNPROCESSABLE_ENTITY",{message:"Failed to create user",details:h})}if(!u)throw new x("UNPROCESSABLE_ENTITY",{message:"Failed to create user"});let A=await e.context.password.hash(s);if(await e.context.internalAdapter.linkAccount({userId:u.id,providerId:"credential",accountId:u.id,password:A,expiresAt:Q(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let h=await P(e.context.secret,u.email),w=`${e.context.baseURL}/verify-email?token=${h}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(u,w,h)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({user:u,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:u,session:null}});let R=await e.context.internalAdapter.createSession(u.id,e.request);if(!R)throw new x("BAD_REQUEST",{message:"Failed to create session"});return await T(e,{session:R,user:u}),e.json({user:u,session:R},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:u,session:R}})});import{z as N}from"zod";import{APIError as ke}from"better-call";import{generateCodeVerifier as Fe}from"oslo/oauth2";var Le=p("/user/list-accounts",{method:"GET",use:[k]},async e=>{let t=e.context.session,o=await e.context.internalAdapter.findAccounts(t.user.id);return e.json(o)}),Se=p("/user/link-social",{method:"POST",requireHeaders:!0,query:N.object({currentURL:N.string().optional()}).optional(),body:N.object({callbackURL:N.string().optional(),provider:N.enum(F)}),use:[b,k]},async e=>{let t=e.context.session;if((await e.context.internalAdapter.findAccounts(t.user.id)).find(f=>f.providerId===e.body.provider))throw new ke("BAD_REQUEST",{message:"Social Account is already linked."});let s=e.context.socialProviders.find(f=>f.id===e.body.provider);if(!s)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new ke("NOT_FOUND",{message:"Provider not found"});let n=e.context.authCookies,i=e.query?.currentURL?new URL(e.query?.currentURL):null,d=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${i?.origin}${e.body.callbackURL||""}`,l=await M(d||i?.origin||e.context.options.baseURL,{email:t.user.email,userId:t.user.id});await e.setSignedCookie(n.state.name,l.hash,e.context.secret,n.state.options);let a=Fe();await e.setSignedCookie(n.pkCodeVerifier.name,a,e.context.secret,n.pkCodeVerifier.options);let c=await s.createAuthorizationURL({state:l.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/link-account/${s.id}`});return e.json({url:c.toString(),state:l,codeVerifier:a,redirect:!0})});function Ze(e,t,o){let r=Date.now(),s=t*1e3;return r-o.lastRequest<s&&o.count>=e}function He(e){return new Response(JSON.stringify({message:"Too many requests. Please try again later."}),{status:429,statusText:"Too Many Requests",headers:{"X-Retry-After":e.toString()}})}function ze(e,t){let o=Date.now(),r=t*1e3;return Math.ceil((e+r-o)/1e3)}function We(e,t){let o=t??"rateLimit",r=e.adapter;return{get:async s=>await r.findOne({model:o,where:[{field:"key",value:s}]}),set:async(s,n,i)=>{try{i?await r.update({model:t??"rateLimit",where:[{field:"key",value:s}],update:{count:n.count,lastRequest:n.lastRequest}}):await r.create({model:t??"rateLimit",data:{key:s,count:n.count,lastRequest:n.lastRequest}})}catch(d){g.error("Error setting rate limit",d)}}}}var Te=new Map;function Je(e){return e.rateLimit.storage==="secondary-storage"?{get:async o=>{let r=await e.options.secondaryStorage?.get(o);return r?JSON.parse(r):void 0},set:async(o,r)=>{await e.options.secondaryStorage?.set?.(o,JSON.stringify(r))}}:e.rateLimit.storage==="memory"?{async get(o){return Te.get(o)},async set(o,r,s){Te.set(o,r)}}:We(e,e.rateLimit.tableName)}async function Oe(e,t){if(!t.rateLimit.enabled)return;let o=t.baseURL,r=e.url.replace(o,""),s=t.rateLimit.window,n=t.rateLimit.max,i=X(e)+r,l=Ge().find(y=>y.pathMatcher(r));l&&(s=l.window,n=l.max);for(let y of t.options.plugins||[])if(y.rateLimit){let u=y.rateLimit.find(A=>A.pathMatcher(r));if(u){s=u.window,n=u.max;break}}if(t.rateLimit.customRules){let y=t.rateLimit.customRules[r];y&&(s=y.window,n=y.max)}let a=Je(t),c=await a.get(i),f=Date.now();if(!c)await a.set(i,{key:i,count:1,lastRequest:f});else{let y=f-c.lastRequest;if(Ze(n,s,c)){let u=ze(c.lastRequest,s);return He(u)}else y>s*1e3?await a.set(i,{...c,count:1,lastRequest:f}):await a.set(i,{...c,count:c.count+1,lastRequest:f})}}function Ge(){return[{pathMatcher(t){return t.startsWith("/sign-in")||t.startsWith("/sign-up")},window:10,max:3}]}import{APIError as Mr}from"better-call";function Xe(e,t){let o=t.plugins?.reduce((d,l)=>({...d,...l.endpoints}),{}),r=t.plugins?.map(d=>d.middlewares?.map(l=>{let a=async c=>l.middleware({...c,context:{...e,...c.context}});return a.path=l.path,a.options=l.middleware.options,a.headers=l.middleware.headers,{path:l.path,middleware:a}})).filter(d=>d!==void 0).flat()||[],n={...{signInOAuth:de,callbackOAuth:ue,getSession:J(),signOut:pe,signUpEmail:Ee(),signInEmail:ce,forgetPassword:me,resetPassword:we,verifyEmail:ae,sendVerificationEmail:ie,changeEmail:Ae,changePassword:he,setPassword:ye,updateUser:ge(),deleteUser:Re,forgetPasswordCallback:fe,listSessions:re(),revokeSession:se,revokeSessions:ne,linkSocialAccount:Se,listUserAccounts:Le},...o,ok:Ue,error:be},i={};for(let[d,l]of Object.entries(n))i[d]=async(a={})=>{let c=await e;for(let u of t.plugins||[])if(u.hooks?.before){for(let A of u.hooks.before)if(A.matcher({...l,...a,context:c})){let h=await A.handler({...a,context:{...c,...a?.context}});h&&"context"in h&&(c={...c,...h.context})}}let f;try{f=await l({...a,context:{...c,...a.context}})}catch(u){if(u instanceof Ie){let A=t.plugins?.map(h=>{if(h.hooks?.after)return h.hooks.after}).filter(h=>h!==void 0).flat();if(!A?.length)throw u;let R=new Response(JSON.stringify(u.body),{status:Ke[u.status],headers:u.headers});for(let h of A||[])if(h.matcher(a)){let S=Object.assign(a,{context:{...e,returned:R}}),C=await h.handler(S);C&&"response"in C&&(R=C.response)}return R}throw u}let y=f;for(let u of t.plugins||[])if(u.hooks?.after){for(let A of u.hooks.after)if(A.matcher(a)){let h=Object.assign(a,{context:{...e,returned:y}}),w=await A.handler(h);w&&"response"in w&&(y=w.response)}}return y},i[d].path=l.path,i[d].method=l.method,i[d].options=l.options,i[d].headers=l.headers;return{api:i,middlewares:r}}var Br=(e,t)=>{let{api:o,middlewares:r}=Xe(e,t),s=new URL(e.baseURL).pathname;return Ye(o,{extraContext:e,basePath:s,routerMiddleware:[{path:"/**",middleware:oe},...r],async onRequest(n){for(let i of e.options.plugins||[])if(i.onRequest){let d=await i.onRequest(n,e);if(d)return d}return Oe(n,e)},async onResponse(n){for(let i of e.options.plugins||[])if(i.onResponse){let d=await i.onResponse(n,e);if(d)return d.response}return n},onError(n){if(t.onAPIError?.throw)throw n;if(t.onAPIError?.onError){t.onAPIError.onError(n,e);return}let i=t.logger?.verboseLogging?g:void 0;t.logger?.disabled!==!0&&(n instanceof Ie?(n.status==="INTERNAL_SERVER_ERROR"&&g.error(n),i?.error(n.message)):g?.error(n))}})};export{te as a,B as b,p as c,oe as d,b as e,J as f,G as g,k as h,re as i,se as j,ne as k,P as l,ie as m,ae as n,de as o,ce as p,le as q,ue as r,pe as s,me as t,fe as u,we as v,ge as w,he as x,ye as y,Re as z,Ae as A,be as B,Ue as C,Ee as D,Le as E,Se as F,Xe as G,Br as H,Mr as I};
85
+ //# sourceMappingURL=chunk-34NVICFQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/api/index.ts","../src/api/middlewares/origin-check.ts","../src/api/call.ts","../src/api/routes/sign-in.ts","../src/api/middlewares/redirect.ts","../src/api/routes/email-verification.ts","../src/api/routes/session.ts","../src/api/routes/callback.ts","../src/db/schema.ts","../src/api/routes/sign-out.ts","../src/api/routes/forget-password.ts","../src/api/routes/update-user.ts","../src/api/routes/error.ts","../src/api/routes/ok.ts","../src/api/routes/sign-up.ts","../src/api/routes/account.ts","../src/api/rate-limiter/index.ts"],"sourcesContent":["import { APIError, type Endpoint, createRouter, statusCode } from \"better-call\";\nimport type { AuthContext } from \"../init\";\nimport type { BetterAuthOptions } from \"../types\";\nimport type { UnionToIntersection } from \"../types/helper\";\nimport { originCheckMiddleware } from \"./middlewares/origin-check\";\nimport {\n\tcallbackOAuth,\n\tforgetPassword,\n\tforgetPasswordCallback,\n\tgetSession,\n\tlistSessions,\n\tresetPassword,\n\trevokeSession,\n\trevokeSessions,\n\tsendVerificationEmail,\n\tchangeEmail,\n\tsignInEmail,\n\tsignInOAuth,\n\tsignOut,\n\tverifyEmail,\n\tlinkSocialAccount,\n\tlistUserAccounts,\n\tchangePassword,\n\tdeleteUser,\n\tsetPassword,\n\tupdateUser,\n} from \"./routes\";\nimport { ok } from \"./routes/ok\";\nimport { signUpEmail } from \"./routes/sign-up\";\nimport { error } from \"./routes/error\";\nimport { logger } from \"../utils/logger\";\nimport type { BetterAuthPlugin } from \"../plugins\";\nimport { onRequestRateLimit } from \"./rate-limiter\";\n\nexport function getEndpoints<\n\tC extends AuthContext,\n\tOption extends BetterAuthOptions,\n>(ctx: Promise<C> | C, options: Option) {\n\tconst pluginEndpoints = options.plugins?.reduce(\n\t\t(acc, plugin) => {\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t...plugin.endpoints,\n\t\t\t};\n\t\t},\n\t\t{} as Record<string, any>,\n\t);\n\n\ttype PluginEndpoint = UnionToIntersection<\n\t\tOption[\"plugins\"] extends Array<infer T>\n\t\t\t? T extends BetterAuthPlugin\n\t\t\t\t? T extends {\n\t\t\t\t\t\tendpoints: infer E;\n\t\t\t\t\t}\n\t\t\t\t\t? E\n\t\t\t\t\t: {}\n\t\t\t\t: {}\n\t\t\t: {}\n\t>;\n\n\tconst middlewares =\n\t\toptions.plugins\n\t\t\t?.map((plugin) =>\n\t\t\t\tplugin.middlewares?.map((m) => {\n\t\t\t\t\tconst middleware = (async (context: any) => {\n\t\t\t\t\t\treturn m.middleware({\n\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\t\t\t...context.context,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}) as Endpoint;\n\t\t\t\t\tmiddleware.path = m.path;\n\t\t\t\t\tmiddleware.options = m.middleware.options;\n\t\t\t\t\tmiddleware.headers = m.middleware.headers;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpath: m.path,\n\t\t\t\t\t\tmiddleware,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.filter((plugin) => plugin !== undefined)\n\t\t\t.flat() || [];\n\n\tconst baseEndpoints = {\n\t\tsignInOAuth,\n\t\tcallbackOAuth,\n\t\tgetSession: getSession<Option>(),\n\t\tsignOut,\n\t\tsignUpEmail: signUpEmail<Option>(),\n\t\tsignInEmail,\n\t\tforgetPassword,\n\t\tresetPassword,\n\t\tverifyEmail,\n\t\tsendVerificationEmail,\n\t\tchangeEmail,\n\t\tchangePassword,\n\t\tsetPassword,\n\t\tupdateUser: updateUser<Option>(),\n\t\tdeleteUser,\n\t\tforgetPasswordCallback,\n\t\tlistSessions: listSessions<Option>(),\n\t\trevokeSession,\n\t\trevokeSessions,\n\t\tlinkSocialAccount,\n\t\tlistUserAccounts,\n\t};\n\tconst endpoints = {\n\t\t...baseEndpoints,\n\t\t...pluginEndpoints,\n\t\tok,\n\t\terror,\n\t};\n\tlet api: Record<string, any> = {};\n\tfor (const [key, value] of Object.entries(endpoints)) {\n\t\tapi[key] = async (context = {} as any) => {\n\t\t\tlet c = await ctx;\n\t\t\tfor (const plugin of options.plugins || []) {\n\t\t\t\tif (plugin.hooks?.before) {\n\t\t\t\t\tfor (const hook of plugin.hooks.before) {\n\t\t\t\t\t\tconst match = hook.matcher({\n\t\t\t\t\t\t\t...value,\n\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\tcontext: c,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tconst hookRes = await hook.handler({\n\t\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\t...context?.context,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (hookRes && \"context\" in hookRes) {\n\t\t\t\t\t\t\t\tc = {\n\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\t...hookRes.context,\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\tlet endpointRes: any;\n\t\t\ttry {\n\t\t\t\t//@ts-ignore\n\t\t\t\tendpointRes = await value({\n\t\t\t\t\t...context,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\t...c,\n\t\t\t\t\t\t...context.context,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tif (e instanceof APIError) {\n\t\t\t\t\tconst afterPlugins = options.plugins\n\t\t\t\t\t\t?.map((plugin) => {\n\t\t\t\t\t\t\tif (plugin.hooks?.after) {\n\t\t\t\t\t\t\t\treturn plugin.hooks.after;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.filter((plugin) => plugin !== undefined)\n\t\t\t\t\t\t.flat();\n\n\t\t\t\t\tif (!afterPlugins?.length) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t\tlet response = new Response(JSON.stringify(e.body), {\n\t\t\t\t\t\tstatus: statusCode[e.status],\n\t\t\t\t\t\theaders: e.headers,\n\t\t\t\t\t});\n\n\t\t\t\t\tfor (const hook of afterPlugins || []) {\n\t\t\t\t\t\tconst match = hook.matcher(context);\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tconst obj = Object.assign(context, {\n\t\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\t\t\t\treturned: response,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst hookRes = await hook.handler(obj);\n\t\t\t\t\t\t\tif (hookRes && \"response\" in hookRes) {\n\t\t\t\t\t\t\t\tresponse = hookRes.response as any;\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\treturn response;\n\t\t\t\t}\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\tlet response = endpointRes;\n\t\t\tfor (const plugin of options.plugins || []) {\n\t\t\t\tif (plugin.hooks?.after) {\n\t\t\t\t\tfor (const hook of plugin.hooks.after) {\n\t\t\t\t\t\tconst match = hook.matcher(context);\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tconst obj = Object.assign(context, {\n\t\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\t\t\t\treturned: response,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst hookRes = await hook.handler(obj);\n\t\t\t\t\t\t\tif (hookRes && \"response\" in hookRes) {\n\t\t\t\t\t\t\t\tresponse = hookRes.response as any;\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\treturn response;\n\t\t};\n\t\tapi[key].path = value.path;\n\t\tapi[key].method = value.method;\n\t\tapi[key].options = value.options;\n\t\tapi[key].headers = value.headers;\n\t}\n\treturn {\n\t\tapi: api as typeof endpoints & PluginEndpoint,\n\t\tmiddlewares,\n\t};\n}\n\nexport const router = <C extends AuthContext, Option extends BetterAuthOptions>(\n\tctx: C,\n\toptions: Option,\n) => {\n\tconst { api, middlewares } = getEndpoints(ctx, options);\n\tconst basePath = new URL(ctx.baseURL).pathname;\n\n\treturn createRouter(api, {\n\t\textraContext: ctx,\n\t\tbasePath,\n\t\trouterMiddleware: [\n\t\t\t{\n\t\t\t\tpath: \"/**\",\n\t\t\t\tmiddleware: originCheckMiddleware,\n\t\t\t},\n\t\t\t...middlewares,\n\t\t],\n\t\tasync onRequest(req) {\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onRequest) {\n\t\t\t\t\tconst response = await plugin.onRequest(req, ctx);\n\t\t\t\t\tif (response) {\n\t\t\t\t\t\treturn response;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn onRequestRateLimit(req, ctx);\n\t\t},\n\t\tasync onResponse(res) {\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onResponse) {\n\t\t\t\t\tconst response = await plugin.onResponse(res, ctx);\n\t\t\t\t\tif (response) {\n\t\t\t\t\t\treturn response.response;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tonError(e) {\n\t\t\tif (options.onAPIError?.throw) {\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\tif (options.onAPIError?.onError) {\n\t\t\t\toptions.onAPIError.onError(e, ctx);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst log = options.logger?.verboseLogging ? logger : undefined;\n\t\t\tif (options.logger?.disabled !== true) {\n\t\t\t\tif (e instanceof APIError) {\n\t\t\t\t\tif (e.status === \"INTERNAL_SERVER_ERROR\") {\n\t\t\t\t\t\tlogger.error(e);\n\t\t\t\t\t}\n\t\t\t\t\tlog?.error(e.message);\n\t\t\t\t} else {\n\t\t\t\t\tlogger?.error(e);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t});\n};\n\nexport * from \"./routes\";\nexport * from \"./middlewares\";\nexport * from \"./call\";\nexport { APIError } from \"better-call\";\n","import { APIError } from \"better-call\";\nimport { createAuthMiddleware } from \"../call\";\nimport { logger } from \"../../utils\";\n\n/**\n * Middleware to validate callbackURL, redirectURL, currentURL and origin against trustedOrigins,\n */\nexport const originCheckMiddleware = createAuthMiddleware(async (ctx) => {\n\tif (\n\t\tctx.context.options.advanced?.disableOriginCheck ||\n\t\tctx.request?.method !== \"POST\"\n\t) {\n\t\treturn;\n\t}\n\tconst { body, query, context } = ctx;\n\tconst originHeader =\n\t\tctx.headers?.get(\"origin\") || ctx.headers?.get(\"referer\") || \"\";\n\tconst callbackURL = body?.callbackURL;\n\tconst redirectURL = body?.redirectTo;\n\tconst currentURL = query?.currentURL;\n\tconst trustedOrigins = context.trustedOrigins;\n\n\tconst validateURL = (url: string | undefined, label: string) => {\n\t\tconst isTrustedOrigin = trustedOrigins.some(\n\t\t\t(origin) =>\n\t\t\t\turl?.startsWith(origin) || (url?.startsWith(\"/\") && label !== \"origin\"),\n\t\t);\n\t\tif (!isTrustedOrigin) {\n\t\t\tlogger.error(`Invalid ${label}: ${url}`);\n\t\t\tlogger.info(\n\t\t\t\t`If it's a valid URL, please add ${url} to trustedOrigins in your auth config\\n`,\n\t\t\t\t`Current list of trustedOrigins: ${trustedOrigins}`,\n\t\t\t);\n\t\t\tthrow new APIError(\"FORBIDDEN\", { message: `Invalid ${label}` });\n\t\t}\n\t};\n\n\tcallbackURL && validateURL(callbackURL, \"callbackURL\");\n\tredirectURL && validateURL(redirectURL, \"redirectURL\");\n\tcurrentURL && validateURL(currentURL, \"currentURL\");\n\t//origin must always be validated\n\tvalidateURL(originHeader, \"origin\");\n});\n","import {\n\tAPIError,\n\ttype Endpoint,\n\ttype EndpointResponse,\n\tcreateEndpointCreator,\n\tcreateMiddleware,\n\tcreateMiddlewareCreator,\n} from \"better-call\";\nimport type { AuthContext } from \"../init\";\nimport type { BetterAuthOptions } from \"../types/options\";\n\nexport const optionsMiddleware = createMiddleware(async () => {\n\t/**\n\t * This will be passed on the instance of\n\t * the context. Used to infer the type\n\t * here.\n\t */\n\treturn {} as AuthContext;\n});\n\nexport const createAuthMiddleware = createMiddlewareCreator({\n\tuse: [\n\t\toptionsMiddleware,\n\t\t/**\n\t\t * Only use for post hooks\n\t\t */\n\t\tcreateMiddleware(async () => {\n\t\t\treturn {} as {\n\t\t\t\treturned?: Response;\n\t\t\t};\n\t\t}),\n\t],\n});\n\nexport const createAuthEndpoint = createEndpointCreator({\n\tuse: [optionsMiddleware],\n});\n\nexport type AuthEndpoint = Endpoint<\n\t(ctx: {\n\t\toptions: BetterAuthOptions;\n\t\tbody: any;\n\t\tquery: any;\n\t\tparams: any;\n\t\theaders: Headers;\n\t}) => Promise<EndpointResponse>\n>;\n\nexport type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;\n","import { APIError } from \"better-call\";\nimport { generateCodeVerifier } from \"oslo/oauth2\";\nimport { z } from \"zod\";\nimport { generateState } from \"../../oauth2/state\";\nimport { createAuthEndpoint } from \"../call\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { socialProviderList } from \"../../social-providers\";\nimport { createEmailVerificationToken } from \"./email-verification\";\nimport { logger } from \"../../utils\";\n\nexport const signInOAuth = createAuthEndpoint(\n\t\"/sign-in/social\",\n\t{\n\t\tmethod: \"POST\",\n\t\trequireHeaders: true,\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\t/**\n\t\t\t\t * Redirect to the current URL after the\n\t\t\t\t * user has signed in.\n\t\t\t\t */\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * Callback URL to redirect to after the user has signed in.\n\t\t\t */\n\t\t\tcallbackURL: z.string().optional(),\n\t\t\t/**\n\t\t\t * OAuth2 provider to use`\n\t\t\t */\n\t\t\tprovider: z.enum(socialProviderList),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (c) => {\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.body.provider,\n\t\t);\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t{\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\tmessage: \"Provider not found\",\n\t\t\t});\n\t\t}\n\t\tconst cookie = c.context.authCookies;\n\t\tconst currentURL = c.query?.currentURL\n\t\t\t? new URL(c.query?.currentURL)\n\t\t\t: null;\n\n\t\tconst callbackURL = c.body.callbackURL?.startsWith(\"http\")\n\t\t\t? c.body.callbackURL\n\t\t\t: `${currentURL?.origin}${c.body.callbackURL || \"\"}`;\n\n\t\tconst state = await generateState(\n\t\t\tcallbackURL || currentURL?.origin || c.context.options.baseURL,\n\t\t);\n\t\tawait c.setSignedCookie(\n\t\t\tcookie.state.name,\n\t\t\tstate.hash,\n\t\t\tc.context.secret,\n\t\t\tcookie.state.options,\n\t\t);\n\t\tconst codeVerifier = generateCodeVerifier();\n\t\tawait c.setSignedCookie(\n\t\t\tcookie.pkCodeVerifier.name,\n\t\t\tcodeVerifier,\n\t\t\tc.context.secret,\n\t\t\tcookie.pkCodeVerifier.options,\n\t\t);\n\t\tconst url = await provider.createAuthorizationURL({\n\t\t\tstate: state.raw,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t});\n\t\treturn c.json({\n\t\t\turl: url.toString(),\n\t\t\tstate: state,\n\t\t\tcodeVerifier,\n\t\t\tredirect: true,\n\t\t});\n\t},\n);\n\nexport const signInEmail = createAuthEndpoint(\n\t\"/sign-in/email\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\temail: z.string(),\n\t\t\tpassword: z.string(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t\t/**\n\t\t\t * If this is true the session will only be valid for the current browser session\n\t\t\t * @default false\n\t\t\t */\n\t\t\tdontRememberMe: z.boolean().default(false).optional(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options?.emailAndPassword?.enabled) {\n\t\t\tctx.context.logger.error(\n\t\t\t\t\"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!\",\n\t\t\t);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Email and password is not enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email, password } = ctx.body;\n\t\tconst isValidEmail = z.string().email().safeParse(email);\n\t\tif (!isValidEmail.success) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid email\",\n\t\t\t});\n\t\t}\n\t\tconst checkEmail = z.string().email().safeParse(email);\n\t\tif (!checkEmail.success) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid email\",\n\t\t\t});\n\t\t}\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\tincludeAccounts: true,\n\t\t});\n\n\t\tif (!user) {\n\t\t\tawait ctx.context.password.hash(password);\n\t\t\tctx.context.logger.error(\"User not found\", { email });\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid email or password\",\n\t\t\t});\n\t\t}\n\n\t\tconst credentialAccount = user.accounts.find(\n\t\t\t(a) => a.providerId === \"credential\",\n\t\t);\n\t\tif (!credentialAccount) {\n\t\t\tctx.context.logger.error(\"Credential account not found\", { email });\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid email or password\",\n\t\t\t});\n\t\t}\n\t\tconst currentPassword = credentialAccount?.password;\n\t\tif (!currentPassword) {\n\t\t\tctx.context.logger.error(\"Password not found\", { email });\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Unexpected error\",\n\t\t\t});\n\t\t}\n\t\tconst validPassword = await ctx.context.password.verify(\n\t\t\tcurrentPassword,\n\t\t\tpassword,\n\t\t);\n\t\tif (!validPassword) {\n\t\t\tctx.context.logger.error(\"Invalid password\");\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid email or password\",\n\t\t\t});\n\t\t}\n\n\t\tif (\n\t\t\tctx.context.options?.emailAndPassword?.requireEmailVerification &&\n\t\t\t!user.user.emailVerified\n\t\t) {\n\t\t\tif (!ctx.context.options?.emailVerification?.sendVerificationEmail) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Email verification is required but no email verification handler is provided\",\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\tmessage: \"Email is not verified.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\tctx.context.secret,\n\t\t\t\tuser.user.email,\n\t\t\t);\n\t\t\tconst url = `${ctx.context.options.baseURL}/verify-email?token=${token}`;\n\t\t\tawait ctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\tuser.user,\n\t\t\t\turl,\n\t\t\t\ttoken,\n\t\t\t);\n\t\t\tctx.context.logger.error(\"Email not verified\", { email });\n\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\tmessage:\n\t\t\t\t\t\"Email is not verified. Check your email for a verification link\",\n\t\t\t});\n\t\t}\n\n\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\tuser.user.id,\n\t\t\tctx.headers,\n\t\t\tctx.body.dontRememberMe,\n\t\t);\n\n\t\tif (!session) {\n\t\t\tctx.context.logger.error(\"Failed to create session\");\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Failed to create session\",\n\t\t\t});\n\t\t}\n\n\t\tawait setSessionCookie(\n\t\t\tctx,\n\t\t\t{\n\t\t\t\tsession,\n\t\t\t\tuser: user.user,\n\t\t\t},\n\t\t\tctx.body.dontRememberMe,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tuser: user.user,\n\t\t\tsession,\n\t\t\tredirect: !!ctx.body.callbackURL,\n\t\t\turl: ctx.body.callbackURL,\n\t\t});\n\t},\n);\n","import { APIError } from \"better-call\";\nimport { createAuthMiddleware } from \"../call\";\nimport { logger } from \"../../utils/logger\";\n\n/**\n * Middleware to validate callbackURL and currentURL against trustedOrigins,\n * preventing open redirect attacks.\n */\nexport const redirectURLMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst { body, query, context } = ctx;\n\n\tconst callbackURL =\n\t\tbody?.callbackURL ||\n\t\tquery?.callbackURL ||\n\t\tquery?.redirectTo ||\n\t\tbody?.redirectTo;\n\tconst currentURL = query?.currentURL;\n\tconst trustedOrigins = context.trustedOrigins;\n\n\tconst validateURL = (url: string | undefined, label: string) => {\n\t\tif (url?.startsWith(\"http\")) {\n\t\t\tconst isTrustedOrigin = trustedOrigins.some((origin) =>\n\t\t\t\turl.startsWith(origin),\n\t\t\t);\n\t\t\tif (!isTrustedOrigin) {\n\t\t\t\tlogger.error(`Invalid ${label}: ${url}`);\n\t\t\t\tlogger.info(\n\t\t\t\t\t`If it's a valid URL, please add ${url} to trustedOrigins in your auth config\\n`,\n\t\t\t\t\t`Current list of trustedOrigins: ${trustedOrigins}`,\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", { message: `Invalid ${label}` });\n\t\t\t}\n\t\t}\n\t};\n\n\tvalidateURL(callbackURL, \"callbackURL\");\n\tvalidateURL(currentURL, \"currentURL\");\n});\n","import { TimeSpan } from \"oslo\";\nimport { createJWT, validateJWT, type JWT } from \"oslo/jwt\";\nimport { z } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { getSessionFromCtx } from \"./session\";\n\nexport async function createEmailVerificationToken(\n\tsecret: string,\n\temail: string,\n\t/**\n\t * The email to update from\n\t */\n\tupdateTo?: string,\n) {\n\tconst token = await createJWT(\n\t\t\"HS256\",\n\t\tBuffer.from(secret),\n\t\t{\n\t\t\temail: email.toLowerCase(),\n\t\t\tupdateTo,\n\t\t},\n\t\t{\n\t\t\texpiresIn: new TimeSpan(1, \"h\"),\n\t\t\tissuer: \"better-auth\",\n\t\t\tsubject: \"verify-email\",\n\t\t\taudiences: [email],\n\t\t\tincludeIssuedTimestamp: true,\n\t\t},\n\t);\n\treturn token;\n}\n\nexport const sendVerificationEmail = createAuthEndpoint(\n\t\"/send-verification-email\",\n\t{\n\t\tmethod: \"POST\",\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\temail: z.string().email(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email } = ctx.body;\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\tif (!user) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User not found\",\n\t\t\t});\n\t\t}\n\t\tconst token = await createEmailVerificationToken(ctx.context.secret, email);\n\t\tconst url = `${\n\t\t\tctx.context.baseURL\n\t\t}/verify-email?token=${token}&callbackURL=${\n\t\t\tctx.body.callbackURL || ctx.query?.currentURL || \"/\"\n\t\t}`;\n\t\tawait ctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\tuser.user,\n\t\t\turl,\n\t\t\ttoken,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const verifyEmail = createAuthEndpoint(\n\t\"/verify-email\",\n\t{\n\t\tmethod: \"GET\",\n\t\tquery: z.object({\n\t\t\ttoken: z.string(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { token } = ctx.query;\n\t\tlet jwt: JWT;\n\t\ttry {\n\t\t\tjwt = await validateJWT(\"HS256\", Buffer.from(ctx.context.secret), token);\n\t\t} catch (e) {\n\t\t\tctx.context.logger.error(\"Failed to verify email\", e);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid token\",\n\t\t\t});\n\t\t}\n\t\tconst schema = z.object({\n\t\t\temail: z.string().email(),\n\t\t\tupdateTo: z.string().optional(),\n\t\t});\n\t\tconst parsed = schema.parse(jwt.payload);\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(\n\t\t\tparsed.email,\n\t\t);\n\t\tif (!user) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User not found\",\n\t\t\t});\n\t\t}\n\t\tif (parsed.updateTo) {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) {\n\t\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}?error=unauthorized`);\n\t\t\t\t}\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Session not found\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (session.user.email !== parsed.email) {\n\t\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}?error=unauthorized`);\n\t\t\t\t}\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Invalid session\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\t\tparsed.email,\n\t\t\t\t{\n\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t//send verification email to the new email\n\t\t\tawait ctx.context.options.emailVerification?.sendVerificationEmail?.(\n\t\t\t\tupdatedUser,\n\t\t\t\t`${ctx.context.baseURL}/verify-email?token=${token}`,\n\t\t\t\ttoken,\n\t\t\t);\n\n\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\tuser: updatedUser,\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.updateUserByEmail(parsed.email, {\n\t\t\temailVerified: true,\n\t\t});\n\t\tif (ctx.query.callbackURL) {\n\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t}\n\t\treturn ctx.json({\n\t\t\tuser: null,\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n","import { APIError, type Context } from \"better-call\";\nimport { createAuthEndpoint, createAuthMiddleware } from \"../call\";\nimport { getDate } from \"../../utils/date\";\nimport { deleteSessionCookie, setSessionCookie } from \"../../cookies\";\nimport { z } from \"zod\";\nimport type {\n\tBetterAuthOptions,\n\tInferSession,\n\tInferUser,\n\tPrettify,\n} from \"../../types\";\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\tquery: z.optional(\n\t\t\t\tz.object({\n\t\t\t\t\t/**\n\t\t\t\t\t * If cookie cache is enabled, it will disable the cache\n\t\t\t\t\t * and fetch the session from the database\n\t\t\t\t\t */\n\t\t\t\t\tdisableCookieCache: z.boolean().optional(),\n\t\t\t\t}),\n\t\t\t),\n\t\t\trequireHeaders: true,\n\t\t},\n\t\tasync (ctx) => {\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\t\t\t\tif (!sessionCookieToken) {\n\t\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst sessionData = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.sessionData.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\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\t\t\t\t/**\n\t\t\t\t * If session data is present in the cookie, return it\n\t\t\t\t */\n\t\t\t\tif (\n\t\t\t\t\tsessionData &&\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 = JSON.parse(sessionData)?.session;\n\t\t\t\t\tif (session?.expiresAt > new Date()) {\n\t\t\t\t\t\treturn ctx.json(\n\t\t\t\t\t\t\tsession 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\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(session.session.id);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\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 */\n\t\t\t\tif (dontRememberMe) {\n\t\t\t\t\treturn ctx.json(\n\t\t\t\t\t\tsession as unknown as {\n\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t\t},\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 (shouldBeUpdated) {\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.id,\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},\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\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsession: updatedSession,\n\t\t\t\t\t\tuser: session.user,\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\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(error);\n\t\t\t\treturn ctx.json(null, { status: 500 });\n\t\t\t}\n\t\t},\n\t);\n\nexport const getSessionFromCtx = async (ctx: Context<any, any>) => {\n\t//@ts-ignore\n\tconst session = await getSession()({\n\t\t...ctx,\n\t\t_flag: \"json\",\n\t\theaders: ctx.headers!,\n\t});\n\n\treturn session;\n};\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 * user active sessions list\n */\nexport const listSessions = <Option extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/user/list-sessions\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\trequireHeaders: true,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst sessions = await ctx.context.internalAdapter.listSessions(\n\t\t\t\tctx.context.session.user.id,\n\t\t\t);\n\t\t\tconst activeSessions = sessions.filter((session) => {\n\t\t\t\treturn session.expiresAt > new Date();\n\t\t\t});\n\t\t\treturn ctx.json(\n\t\t\t\tactiveSessions as unknown as Prettify<InferSession<Option>>[],\n\t\t\t);\n\t\t},\n\t);\n\n/**\n * revoke a single session\n */\nexport const revokeSession = createAuthEndpoint(\n\t\"/user/revoke-session\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tid: z.string(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t\trequireHeaders: true,\n\t},\n\tasync (ctx) => {\n\t\tconst id = ctx.body.id;\n\t\tconst findSession = await ctx.context.internalAdapter.findSession(id);\n\t\tif (!findSession) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Session not found\",\n\t\t\t});\n\t\t}\n\t\tif (findSession.session.userId !== ctx.context.session.user.id) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\ttry {\n\t\t\tawait ctx.context.internalAdapter.deleteSession(id);\n\t\t} catch (error) {\n\t\t\tctx.context.logger.error(error);\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/**\n * revoke all user sessions\n */\nexport const revokeSessions = createAuthEndpoint(\n\t\"/user/revoke-sessions\",\n\t{\n\t\tmethod: \"POST\",\n\t\tuse: [sessionMiddleware],\n\t\trequireHeaders: true,\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(error);\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","import { z } from \"zod\";\nimport { userSchema, type User } from \"../../db/schema\";\nimport { generateId } from \"../../utils/id\";\nimport { parseState } from \"../../oauth2/state\";\nimport { createAuthEndpoint } from \"../call\";\nimport { HIDE_METADATA } from \"../../utils/hide-metadata\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { logger } from \"../../utils/logger\";\nimport type { OAuth2Tokens } from \"../../oauth2\";\nimport { compareHash } from \"../../crypto/hash\";\nimport { createEmailVerificationToken } from \"./email-verification\";\nimport { isDevelopment } from \"std-env\";\n\nexport const callbackOAuth = createAuthEndpoint(\n\t\"/callback/:id\",\n\t{\n\t\tmethod: \"GET\",\n\t\tquery: z.object({\n\t\t\tstate: z.string(),\n\t\t\tcode: z.string().optional(),\n\t\t\terror: z.string().optional(),\n\t\t}),\n\t\tmetadata: HIDE_METADATA,\n\t},\n\tasync (c) => {\n\t\tif (c.query.error || !c.query.code) {\n\t\t\tconst parsedState = parseState(c.query.state);\n\t\t\tconst callbackURL =\n\t\t\t\tparsedState.data?.callbackURL || `${c.context.baseURL}/error`;\n\t\t\tc.context.logger.error(c.query.error, c.params.id);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${callbackURL}?error=${c.query.error || \"oAuth_code_missing\"}`,\n\t\t\t);\n\t\t}\n\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.params.id,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Oauth provider with id\",\n\t\t\t\tc.params.id,\n\t\t\t\t\"not found\",\n\t\t\t);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=oauth_provider_not_found`,\n\t\t\t);\n\t\t}\n\n\t\tconst parsedState = parseState(c.query.state);\n\t\tif (!parsedState.success) {\n\t\t\tc.context.logger.error(\"Unable to parse state\");\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\n\t\tconst {\n\t\t\tdata: { callbackURL, currentURL, link },\n\t\t} = parsedState;\n\n\t\tconst storedState = await c.getSignedCookie(\n\t\t\tc.context.authCookies.state.name,\n\t\t\tc.context.secret,\n\t\t);\n\n\t\tif (!storedState) {\n\t\t\tlogger.error(\"No stored state found\");\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\n\t\tconst isValidState = await compareHash(c.query.state, storedState);\n\t\tif (!isValidState) {\n\t\t\tlogger.error(\"OAuth state mismatch\");\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\t\tconst codeVerifier = await c.getSignedCookie(\n\t\t\tc.context.authCookies.pkCodeVerifier.name,\n\t\t\tc.context.secret,\n\t\t);\n\t\tlet tokens: OAuth2Tokens;\n\t\ttry {\n\t\t\ttokens = await provider.validateAuthorizationCode({\n\t\t\t\tcode: c.query.code,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tc.context.logger.error(e);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\t\tconst userInfo = await provider\n\t\t\t.getUserInfo(tokens)\n\t\t\t.then((res) => res?.user);\n\t\tconst id = generateId();\n\t\tconst data = userSchema.safeParse({\n\t\t\t...userInfo,\n\t\t\tid,\n\t\t});\n\n\t\tif (!userInfo || data.success === false) {\n\t\t\tlogger.error(\"Unable to get user info\", data.error);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\t\tif (!callbackURL) {\n\t\t\tlogger.error(\"No callback URL found\");\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\n\t\tif (link) {\n\t\t\tif (link.email !== userInfo.email.toLowerCase()) {\n\t\t\t\treturn redirectOnError(\"email_doesn't_match\");\n\t\t\t}\n\t\t\tconst newAccount = await c.context.internalAdapter.createAccount({\n\t\t\t\tuserId: link.userId,\n\t\t\t\tproviderId: provider.id,\n\t\t\t\taccountId: userInfo.id,\n\t\t\t});\n\t\t\tif (!newAccount) {\n\t\t\t\treturn redirectOnError(\"unable_to_link_account\");\n\t\t\t}\n\t\t\tthrow c.redirect(callbackURL || currentURL || c.context.options.baseURL!);\n\t\t}\n\n\t\tfunction redirectOnError(error: string) {\n\t\t\tthrow c.redirect(\n\t\t\t\t`${\n\t\t\t\t\tcurrentURL || callbackURL || `${c.context.baseURL}/error`\n\t\t\t\t}?error=${error}`,\n\t\t\t);\n\t\t}\n\n\t\tconst dbUser = await c.context.internalAdapter\n\t\t\t.findUserByEmail(userInfo.email, {\n\t\t\t\tincludeAccounts: true,\n\t\t\t})\n\t\t\t.catch((e) => {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Better auth was unable to query your database.\\nError: \",\n\t\t\t\t\te,\n\t\t\t\t);\n\t\t\t\tthrow c.redirect(\n\t\t\t\t\t`${c.context.baseURL}/error?error=internal_server_error`,\n\t\t\t\t);\n\t\t\t});\n\n\t\tlet user = dbUser?.user;\n\t\tif (dbUser) {\n\t\t\tconst hasBeenLinked = dbUser.accounts.find(\n\t\t\t\t(a) => a.providerId === provider.id,\n\t\t\t);\n\t\t\tif (!hasBeenLinked) {\n\t\t\t\tconst trustedProviders =\n\t\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\t\t\t\tconst isTrustedProvider = trustedProviders?.includes(\n\t\t\t\t\tprovider.id as \"apple\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\t(!isTrustedProvider && !userInfo.emailVerified) ||\n\t\t\t\t\t!c.context.options.account?.accountLinking?.enabled\n\t\t\t\t) {\n\t\t\t\t\tif (isDevelopment) {\n\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t`User already exist but account isn't linked to ${provider.id}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tredirectOnError(\"account_not_linked\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tawait c.context.internalAdapter.linkAccount({\n\t\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\t\taccountId: userInfo.id.toString(),\n\t\t\t\t\t\tid: `${provider.id}:${userInfo.id}`,\n\t\t\t\t\t\tuserId: dbUser.user.id,\n\t\t\t\t\t\taccessToken: tokens.accessToken,\n\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t\trefreshToken: tokens.refreshToken,\n\t\t\t\t\t\texpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlogger.error(\"Unable to link account\", e);\n\t\t\t\t\tredirectOnError(\"unable_to_link_account\");\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait c.context.internalAdapter.updateAccount(hasBeenLinked.id, {\n\t\t\t\t\taccessToken: tokens.accessToken,\n\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\trefreshToken: tokens.refreshToken,\n\t\t\t\t\texpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tconst emailVerified = userInfo.emailVerified || false;\n\t\t\t\tuser = await c.context.internalAdapter\n\t\t\t\t\t.createOAuthUser(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...data.data,\n\t\t\t\t\t\t\temailVerified,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\taccessToken: tokens.accessToken,\n\t\t\t\t\t\t\tidToken: tokens.idToken,\n\t\t\t\t\t\t\trefreshToken: tokens.refreshToken,\n\t\t\t\t\t\t\texpiresAt: tokens.accessTokenExpiresAt,\n\t\t\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\t\t\taccountId: userInfo.id.toString(),\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t\t.then((res) => res?.user);\n\t\t\t\tif (\n\t\t\t\t\t!emailVerified &&\n\t\t\t\t\tuser &&\n\t\t\t\t\tc.context.options.emailVerification?.sendOnSignUp\n\t\t\t\t) {\n\t\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\t\tc.context.secret,\n\t\t\t\t\t\tuser.email,\n\t\t\t\t\t);\n\t\t\t\t\tconst url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\t\t\t\t\tawait c.context.options.emailVerification?.sendVerificationEmail?.(\n\t\t\t\t\t\tuser,\n\t\t\t\t\t\turl,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(\"Unable to create user\", e);\n\t\t\t\tredirectOnError(\"unable_to_create_user\");\n\t\t\t}\n\t\t}\n\n\t\tif (!user) {\n\t\t\treturn redirectOnError(\"unable_to_create_user\");\n\t\t}\n\n\t\tconst session = await c.context.internalAdapter.createSession(\n\t\t\tuser.id,\n\t\t\tc.request,\n\t\t);\n\t\tif (!session) {\n\t\t\tredirectOnError(\"unable_to_create_session\");\n\t\t}\n\t\tawait setSessionCookie(c, {\n\t\t\tsession,\n\t\t\tuser,\n\t\t});\n\t\tthrow c.redirect(callbackURL);\n\t},\n);\n","import { z } from \"zod\";\nimport type { FieldAttribute } from \".\";\nimport type { BetterAuthOptions } from \"../types\";\n\nexport const accountSchema = z.object({\n\tid: z.string(),\n\tproviderId: z.string(),\n\taccountId: z.string(),\n\tuserId: z.string(),\n\taccessToken: z.string().nullable().optional(),\n\trefreshToken: z.string().nullable().optional(),\n\tidToken: z.string().nullable().optional(),\n\t/**\n\t * Access token expires at\n\t */\n\texpiresAt: z.date().nullable().optional(),\n\t/**\n\t * Password is only stored in the credential provider\n\t */\n\tpassword: z.string().optional().nullable(),\n});\n\nexport const userSchema = z.object({\n\tid: z.string(),\n\temail: z.string().transform((val) => val.toLowerCase()),\n\temailVerified: z.boolean().default(false),\n\tname: z.string(),\n\timage: z.string().optional(),\n\tcreatedAt: z.date().default(new Date()),\n\tupdatedAt: z.date().default(new Date()),\n});\n\nexport const sessionSchema = z.object({\n\tid: z.string(),\n\tuserId: z.string(),\n\texpiresAt: z.date(),\n\tipAddress: z.string().optional(),\n\tuserAgent: z.string().optional(),\n});\n\nexport const verificationSchema = z.object({\n\tid: z.string(),\n\tvalue: z.string(),\n\texpiresAt: z.date(),\n\tidentifier: z.string(),\n});\n\nexport type User = z.infer<typeof userSchema>;\nexport type Account = z.infer<typeof accountSchema>;\nexport type Session = z.infer<typeof sessionSchema>;\nexport type Verification = z.infer<typeof verificationSchema>;\n\nexport function parseOutputData<T extends Record<string, any>>(\n\tdata: T,\n\tschema: {\n\t\tfields: Record<string, FieldAttribute>;\n\t},\n) {\n\tconst fields = schema.fields;\n\tconst parsedData: Record<string, any> = {};\n\tfor (const key in data) {\n\t\tconst field = fields[key];\n\t\tif (!field) {\n\t\t\tparsedData[key] = data[key];\n\t\t\tcontinue;\n\t\t}\n\t\tif (field.returned === false) {\n\t\t\tcontinue;\n\t\t}\n\t\tparsedData[key] = data[key];\n\t}\n\treturn parsedData as T;\n}\n\nexport function getAllFields(options: BetterAuthOptions, table: string) {\n\tlet schema: Record<string, FieldAttribute> = {\n\t\t...(table === \"user\" ? options.user?.additionalFields : {}),\n\t\t...(table === \"session\" ? options.session?.additionalFields : {}),\n\t};\n\tfor (const plugin of options.plugins || []) {\n\t\tif (plugin.schema && plugin.schema[table]) {\n\t\t\tschema = {\n\t\t\t\t...schema,\n\t\t\t\t...plugin.schema[table].fields,\n\t\t\t};\n\t\t}\n\t}\n\treturn schema;\n}\n\nexport function parseUserOutput(options: BetterAuthOptions, user: User) {\n\tconst schema = getAllFields(options, \"user\");\n\treturn parseOutputData(user, { fields: schema });\n}\n\nexport function parseAccountOutput(\n\toptions: BetterAuthOptions,\n\taccount: Account,\n) {\n\tconst schema = getAllFields(options, \"account\");\n\treturn parseOutputData(account, { fields: schema });\n}\n\nexport function parseSessionOutput(\n\toptions: BetterAuthOptions,\n\tsession: Session,\n) {\n\tconst schema = getAllFields(options, \"session\");\n\treturn parseOutputData(session, { fields: schema });\n}\n\nexport function parseInputData<T extends Record<string, any>>(\n\tdata: T,\n\tschema: {\n\t\tfields: Record<string, FieldAttribute>;\n\t\taction?: \"create\" | \"update\";\n\t},\n) {\n\tconst action = schema.action || \"create\";\n\tconst fields = schema.fields;\n\tconst parsedData: Record<string, any> = {};\n\tfor (const key in fields) {\n\t\tif (key in data) {\n\t\t\tif (fields[key].input === false) {\n\t\t\t\tif (fields[key].defaultValue) {\n\t\t\t\t\tparsedData[key] = fields[key].defaultValue;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tparsedData[key] = data[key];\n\t\t\tcontinue;\n\t\t}\n\t\tif (fields[key].defaultValue && action === \"create\") {\n\t\t\tparsedData[key] = fields[key].defaultValue;\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn parsedData as Partial<T>;\n}\n\nexport function parseUserInput(\n\toptions: BetterAuthOptions,\n\tuser?: Record<string, any>,\n\taction?: \"create\" | \"update\",\n) {\n\tconst schema = getAllFields(options, \"user\");\n\treturn parseInputData(user || {}, { fields: schema, action });\n}\n\nexport function parseAdditionalUserInput(\n\toptions: BetterAuthOptions,\n\tuser?: Record<string, any>,\n) {\n\tconst schema = getAllFields(options, \"user\");\n\treturn parseInputData(user || {}, { fields: schema });\n}\n\nexport function parseAccountInput(\n\toptions: BetterAuthOptions,\n\taccount: Partial<Account>,\n) {\n\tconst schema = getAllFields(options, \"account\");\n\treturn parseInputData(account, { fields: schema });\n}\n\nexport function parseSessionInput(\n\toptions: BetterAuthOptions,\n\tsession: Partial<Session>,\n) {\n\tconst schema = getAllFields(options, \"session\");\n\treturn parseInputData(session, { fields: schema });\n}\n","import { z } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { deleteSessionCookie } from \"../../cookies\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\n\nexport const signOut = createAuthEndpoint(\n\t\"/sign-out\",\n\t{\n\t\tmethod: \"POST\",\n\t},\n\tasync (ctx) => {\n\t\tconst sessionCookieToken = await ctx.getSignedCookie(\n\t\t\tctx.context.authCookies.sessionToken.name,\n\t\t\tctx.context.secret,\n\t\t);\n\t\tif (!sessionCookieToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Session not found\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteSession(sessionCookieToken);\n\t\tdeleteSessionCookie(ctx);\n\t\treturn ctx.json({\n\t\t\tsuccess: true,\n\t\t});\n\t},\n);\n","import { z } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\n\nexport const forgetPassword = createAuthEndpoint(\n\t\"/forget-password\",\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.string().email(),\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.string(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\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.sendResetPasswordToken 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\tctx.context.logger.error(\"Reset Password: User not found\", { email });\n\t\t\t//only on the server status is false for the client it's always true\n\t\t\t//to avoid leaking information\n\t\t\treturn ctx.json(\n\t\t\t\t{\n\t\t\t\t\tstatus: false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tstatus: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tconst defaultExpiresIn = 60 * 60 * 1;\n\t\tconst expiresAt = new Date(\n\t\t\tDate.now() +\n\t\t\t\t1000 *\n\t\t\t\t\t(ctx.context.options.emailAndPassword.resetPasswordTokenExpiresIn ||\n\t\t\t\t\t\tdefaultExpiresIn),\n\t\t);\n\t\tconst verificationToken = ctx.context.uuid();\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 url = `${ctx.context.baseURL}/reset-password/${verificationToken}?callbackURL=${redirectTo}`;\n\t\tawait ctx.context.options.emailAndPassword.sendResetPassword(\n\t\t\tuser.user,\n\t\t\turl,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const forgetPasswordCallback = createAuthEndpoint(\n\t\"/reset-password/:token\",\n\t{\n\t\tmethod: \"GET\",\n\t\tquery: z.object({\n\t\t\tcallbackURL: z.string(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { token } = ctx.params;\n\t\tconst callbackURL = ctx.query.callbackURL;\n\t\tconst redirectTo = callbackURL.startsWith(\"http\")\n\t\t\t? callbackURL\n\t\t\t: `${ctx.context.options.baseURL}${callbackURL}`;\n\t\tif (!token || !callbackURL) {\n\t\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=INVALID_TOKEN`);\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(`${redirectTo}?error=INVALID_TOKEN`);\n\t\t}\n\t\tthrow ctx.redirect(\n\t\t\t`${redirectTo}${redirectTo.includes(\"?\") ? \"&\" : \"?\"}token=${token}`,\n\t\t);\n\t},\n);\n\nexport const resetPassword = createAuthEndpoint(\n\t\"/reset-password\",\n\t{\n\t\tquery: z.optional(\n\t\t\tz.object({\n\t\t\t\ttoken: z.string().optional(),\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t}),\n\t\t),\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tnewPassword: z.string(),\n\t\t}),\n\t},\n\tasync (ctx) => {\n\t\tconst token =\n\t\t\tctx.query?.token ||\n\t\t\t(ctx.query?.currentURL\n\t\t\t\t? new URL(ctx.query.currentURL).searchParams.get(\"token\")\n\t\t\t\t: \"\");\n\t\tif (!token) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Token not found\",\n\t\t\t});\n\t\t}\n\t\tconst { newPassword } = ctx.body;\n\t\tconst id = `reset-password:${token}`;\n\t\tconst verification =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(id);\n\n\t\tif (!verification || verification.expiresAt < new Date()) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid token\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteVerificationValue(verification.id);\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: ctx.context.uuid(),\n\t\t\t});\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\t\tconst updatedUser = await ctx.context.internalAdapter.updatePassword(\n\t\t\tuserId,\n\t\t\thashedPassword,\n\t\t);\n\t\tif (!updatedUser) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Failed to update password\",\n\t\t\t});\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n","import { z, ZodObject, ZodOptional, ZodString } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { alphabet, generateRandomString } from \"../../crypto/random\";\nimport { deleteSessionCookie, setSessionCookie } from \"../../cookies\";\nimport { sessionMiddleware } from \"./session\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { createEmailVerificationToken } from \"./email-verification\";\nimport type { toZod } from \"../../types/to-zod\";\nimport type { AdditionalUserFieldsInput, BetterAuthOptions } from \"../../types\";\nimport { parseUserInput } from \"../../db/schema\";\n\nexport const updateUser = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/user/update\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: z.record(z.string(), z.any()) as unknown as ZodObject<{\n\t\t\t\tname: ZodOptional<ZodString>;\n\t\t\t\timage: ZodOptional<ZodString>;\n\t\t\t}> &\n\t\t\t\ttoZod<AdditionalUserFieldsInput<O>>,\n\t\t\tuse: [sessionMiddleware, redirectURLMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst body = ctx.body as {\n\t\t\t\tname?: string;\n\t\t\t\timage?: string;\n\t\t\t\t[key: string]: any;\n\t\t\t};\n\n\t\t\tif (body.email) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"You can't update email\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst { name, image, ...rest } = body;\n\t\t\tconst session = ctx.context.session;\n\t\t\tif (!image && !name && Object.keys(rest).length === 0) {\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tuser: session.user,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst additionalFields = parseUserInput(\n\t\t\t\tctx.context.options,\n\t\t\t\trest,\n\t\t\t\t\"update\",\n\t\t\t);\n\t\t\tconst user = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\t\tsession.user.email,\n\t\t\t\t{\n\t\t\t\t\tname,\n\t\t\t\t\timage,\n\t\t\t\t\t...additionalFields,\n\t\t\t\t},\n\t\t\t);\n\t\t\t/**\n\t\t\t * Update the session cookie with the new user data\n\t\t\t */\n\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\tsession: session.session,\n\t\t\t\tuser,\n\t\t\t});\n\t\t\treturn ctx.json({\n\t\t\t\tuser,\n\t\t\t});\n\t\t},\n\t);\n\nexport const changePassword = createAuthEndpoint(\n\t\"/user/change-password\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * The new password to set\n\t\t\t */\n\t\t\tnewPassword: z.string(),\n\t\t\t/**\n\t\t\t * The current password of the user\n\t\t\t */\n\t\t\tcurrentPassword: z.string(),\n\t\t\t/**\n\t\t\t * revoke all sessions that are not the\n\t\t\t * current one logged in by the user\n\t\t\t */\n\t\t\trevokeOtherSessions: z.boolean().optional(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { newPassword, currentPassword, revokeOtherSessions } = ctx.body;\n\t\tconst session = ctx.context.session;\n\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\tif (newPassword.length < minPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password is too short\",\n\t\t\t});\n\t\t}\n\n\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\n\t\tif (newPassword.length > maxPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password too long\",\n\t\t\t});\n\t\t}\n\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst account = accounts.find(\n\t\t\t(account) => account.providerId === \"credential\" && account.password,\n\t\t);\n\t\tif (!account || !account.password) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User does not have a password\",\n\t\t\t});\n\t\t}\n\t\tconst passwordHash = await ctx.context.password.hash(newPassword);\n\t\tconst verify = await ctx.context.password.verify(\n\t\t\taccount.password,\n\t\t\tcurrentPassword,\n\t\t);\n\t\tif (!verify) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Incorrect password\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.updateAccount(account.id, {\n\t\t\tpassword: passwordHash,\n\t\t});\n\t\tif (revokeOtherSessions) {\n\t\t\tawait ctx.context.internalAdapter.deleteSessions(session.user.id);\n\t\t\tconst newSession = await ctx.context.internalAdapter.createSession(\n\t\t\t\tsession.user.id,\n\t\t\t\tctx.headers,\n\t\t\t);\n\t\t\tif (!newSession) {\n\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\tmessage: \"Unable to create session\",\n\t\t\t\t});\n\t\t\t}\n\t\t\t// set the new session cookie\n\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\tsession: newSession,\n\t\t\t\tuser: session.user,\n\t\t\t});\n\t\t}\n\n\t\treturn ctx.json(session.user);\n\t},\n);\n\nexport const setPassword = createAuthEndpoint(\n\t\"/user/set-password\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * The new password to set\n\t\t\t */\n\t\t\tnewPassword: z.string(),\n\t\t}),\n\t\tmetadata: {\n\t\t\tSERVER_ONLY: true,\n\t\t},\n\t\tuse: [sessionMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { newPassword } = ctx.body;\n\t\tconst session = ctx.context.session;\n\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\tif (newPassword.length < minPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password is too short\",\n\t\t\t});\n\t\t}\n\n\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\n\t\tif (newPassword.length > maxPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password too long\",\n\t\t\t});\n\t\t}\n\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst account = accounts.find(\n\t\t\t(account) => account.providerId === \"credential\" && account.password,\n\t\t);\n\t\tconst passwordHash = await ctx.context.password.hash(newPassword);\n\t\tif (!account) {\n\t\t\tawait ctx.context.internalAdapter.linkAccount({\n\t\t\t\tuserId: session.user.id,\n\t\t\t\tproviderId: \"credential\",\n\t\t\t\taccountId: session.user.id,\n\t\t\t\tpassword: passwordHash,\n\t\t\t});\n\t\t\treturn ctx.json(session.user);\n\t\t}\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"user already has a password\",\n\t\t});\n\t},\n);\n\nexport const deleteUser = createAuthEndpoint(\n\t\"/user/delete\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tpassword: z.string(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { password } = ctx.body;\n\t\tconst session = ctx.context.session;\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst account = accounts.find(\n\t\t\t(account) => account.providerId === \"credential\" && account.password,\n\t\t);\n\t\tif (!account || !account.password) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User does not have a password\",\n\t\t\t});\n\t\t}\n\t\tconst verify = await ctx.context.password.verify(\n\t\t\taccount.password,\n\t\t\tpassword,\n\t\t);\n\t\tif (!verify) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Incorrect password\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteUser(session.user.id);\n\t\tawait ctx.context.internalAdapter.deleteSessions(session.user.id);\n\t\tdeleteSessionCookie(ctx);\n\t\treturn ctx.json(null);\n\t},\n);\n\nexport const changeEmail = createAuthEndpoint(\n\t\"/user/change-email\",\n\t{\n\t\tmethod: \"POST\",\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\tnewEmail: z.string().email(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t}),\n\t\tuse: [sessionMiddleware, redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.user?.changeEmail?.enabled) {\n\t\t\tctx.context.logger.error(\"Change email is disabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Change email is disabled\",\n\t\t\t});\n\t\t}\n\n\t\tif (ctx.body.newEmail === ctx.context.session.user.email) {\n\t\t\tctx.context.logger.error(\"Email is the same\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Email is the same\",\n\t\t\t});\n\t\t}\n\t\tconst existingUser = await ctx.context.internalAdapter.findUserByEmail(\n\t\t\tctx.body.newEmail,\n\t\t);\n\t\tif (existingUser) {\n\t\t\tctx.context.logger.error(\"Email already exists\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Couldn't update your email\",\n\t\t\t});\n\t\t}\n\t\t/**\n\t\t * If the email is not verified, we can update the email\n\t\t */\n\t\tif (ctx.context.session.user.emailVerified !== true) {\n\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\t\tctx.context.session.user.email,\n\t\t\t\t{\n\t\t\t\t\temail: ctx.body.newEmail,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tuser: updatedUser,\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * If the email is verified, we need to send a verification email\n\t\t */\n\t\tif (!ctx.context.options.user.changeEmail.sendChangeEmailVerification) {\n\t\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t\t});\n\t\t}\n\n\t\tconst token = await createEmailVerificationToken(\n\t\t\tctx.context.secret,\n\t\t\tctx.context.session.user.email,\n\t\t\tctx.body.newEmail,\n\t\t);\n\t\tconst url = `${\n\t\t\tctx.context.baseURL\n\t\t}/verify-email?token=${token}&callbackURL=${\n\t\t\tctx.body.callbackURL || ctx.query?.currentURL || \"/\"\n\t\t}`;\n\t\tawait ctx.context.options.user.changeEmail.sendChangeEmailVerification(\n\t\t\tctx.context.session.user,\n\t\t\tctx.body.newEmail,\n\t\t\turl,\n\t\t\ttoken,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tuser: null,\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n","import { HIDE_METADATA } from \"../../utils/hide-metadata\";\nimport { createAuthEndpoint } from \"../call\";\n\nconst html = (errorCode: string = \"Unknown\") => `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Authentication Error</title>\n <style>\n :root {\n --bg-color: #f8f9fa;\n --text-color: #212529;\n --accent-color: #000000;\n --error-color: #dc3545;\n --border-color: #e9ecef;\n }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n background-color: var(--bg-color);\n color: var(--text-color);\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n line-height: 1.5;\n }\n .error-container {\n background-color: #ffffff;\n border-radius: 12px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);\n padding: 2.5rem;\n text-align: center;\n max-width: 90%;\n width: 400px;\n }\n h1 {\n color: var(--error-color);\n font-size: 1.75rem;\n margin-bottom: 1rem;\n font-weight: 600;\n }\n p {\n margin-bottom: 1.5rem;\n color: #495057;\n }\n .btn {\n background-color: var(--accent-color);\n color: #ffffff;\n text-decoration: none;\n padding: 0.75rem 1.5rem;\n border-radius: 6px;\n transition: all 0.3s ease;\n display: inline-block;\n font-weight: 500;\n border: 2px solid var(--accent-color);\n }\n .btn:hover {\n background-color: #131721;\n }\n .error-code {\n font-size: 0.875rem;\n color: #6c757d;\n margin-top: 1.5rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border-color);\n }\n .icon {\n font-size: 3rem;\n margin-bottom: 1rem;\n }\n </style>\n</head>\n<body>\n <div class=\"error-container\">\n <div class=\"icon\">⚠️</div>\n <h1>Better Auth Error</h1>\n <p>We encountered an issue while processing your request. Please try again or contact the application owner if the problem persists.</p>\n <a href=\"/\" id=\"returnLink\" class=\"btn\">Return to Application</a>\n <div class=\"error-code\">Error Code: <span id=\"errorCode\">${errorCode}</span></div>\n </div>\n</body>\n</html>`;\n\nexport const error = createAuthEndpoint(\n\t\"/error\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: HIDE_METADATA,\n\t},\n\tasync (c) => {\n\t\tconst query =\n\t\t\tnew URL(c.request?.url || \"\").searchParams.get(\"error\") || \"Unknown\";\n\t\treturn new Response(html(query), {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t},\n\t\t});\n\t},\n);\n","import { HIDE_METADATA } from \"../../utils/hide-metadata\";\nimport { createAuthEndpoint } from \"../call\";\n\nexport const ok = createAuthEndpoint(\n\t\"/ok\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: HIDE_METADATA,\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\tok: true,\n\t\t});\n\t},\n);\n","import { z, ZodObject, ZodOptional, ZodString } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { createEmailVerificationToken } from \"./email-verification\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { APIError } from \"better-call\";\nimport type {\n\tAdditionalUserFieldsInput,\n\tBetterAuthOptions,\n\tInferSession,\n\tInferUser,\n\tUser,\n} from \"../../types\";\nimport type { toZod } from \"../../types/to-zod\";\nimport { parseUserInput } from \"../../db/schema\";\nimport { getDate } from \"../../utils/date\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { logger } from \"../../utils\";\n\nexport const signUpEmail = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-up/email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tquery: z\n\t\t\t\t.object({\n\t\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tbody: z.record(z.string(), z.any()) as unknown as ZodObject<{\n\t\t\t\tname: ZodString;\n\t\t\t\temail: ZodString;\n\t\t\t\tpassword: ZodString;\n\t\t\t\tcallbackURL: ZodOptional<ZodString>;\n\t\t\t}> &\n\t\t\t\ttoZod<AdditionalUserFieldsInput<O>>,\n\t\t\tuse: [redirectURLMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tif (!ctx.context.options.emailAndPassword?.enabled) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Email and password sign up is not enabled\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst body = ctx.body as any as User & {\n\t\t\t\tpassword: string;\n\t\t\t\tcallbackURL?: string;\n\t\t\t} & {\n\t\t\t\t[key: string]: any;\n\t\t\t};\n\t\t\tconst { name, email, password, image, callbackURL, ...additionalFields } =\n\t\t\t\tbody;\n\t\t\tconst isValidEmail = z.string().email().safeParse(email);\n\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Invalid email\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\t\tif (password.length < minPasswordLength) {\n\t\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Password is too short\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\t\t\tif (password.length > maxPasswordLength) {\n\t\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Password is too long\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst dbUser = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (dbUser?.user) {\n\t\t\t\tctx.context.logger.info(`Sign-up attempt for existing email: ${email}`);\n\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\tmessage: \"User with this email already exists\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst additionalData = parseUserInput(\n\t\t\t\tctx.context.options,\n\t\t\t\tadditionalFields as any,\n\t\t\t);\n\t\t\tlet createdUser: User;\n\t\t\ttry {\n\t\t\t\tcreatedUser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\temail: email.toLowerCase(),\n\t\t\t\t\tname,\n\t\t\t\t\timage,\n\t\t\t\t\t...additionalData,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t});\n\t\t\t\tif (!createdUser) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: \"Failed to create user\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(\"Failed to create user\", e);\n\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\tmessage: \"Failed to create user\",\n\t\t\t\t\tdetails: e,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!createdUser) {\n\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\tmessage: \"Failed to create user\",\n\t\t\t\t});\n\t\t\t}\n\t\t\t/**\n\t\t\t * Link the account to the user\n\t\t\t */\n\t\t\tconst hash = await ctx.context.password.hash(password);\n\t\t\tawait ctx.context.internalAdapter.linkAccount({\n\t\t\t\tuserId: createdUser.id,\n\t\t\t\tproviderId: \"credential\",\n\t\t\t\taccountId: createdUser.id,\n\t\t\t\tpassword: hash,\n\t\t\t\texpiresAt: getDate(60 * 60 * 24 * 30, \"sec\"),\n\t\t\t});\n\t\t\tif (ctx.context.options.emailVerification?.sendOnSignUp) {\n\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t\tcreatedUser.email,\n\t\t\t\t);\n\t\t\t\tconst url = `${\n\t\t\t\t\tctx.context.baseURL\n\t\t\t\t}/verify-email?token=${token}&callbackURL=${\n\t\t\t\t\tbody.callbackURL || ctx.query?.currentURL || \"/\"\n\t\t\t\t}`;\n\t\t\t\tawait ctx.context.options.emailVerification?.sendVerificationEmail?.(\n\t\t\t\t\tcreatedUser,\n\t\t\t\t\turl,\n\t\t\t\t\ttoken,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t!ctx.context.options.emailAndPassword.autoSignIn ||\n\t\t\t\tctx.context.options.emailAndPassword.requireEmailVerification\n\t\t\t) {\n\t\t\t\treturn ctx.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tuser: createdUser as InferUser<O>,\n\t\t\t\t\t\tsession: null,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tbody: body.callbackURL\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\turl: body.callbackURL,\n\t\t\t\t\t\t\t\t\tredirect: true,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t\t\t\t\tsession: null,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\tcreatedUser.id,\n\t\t\t\tctx.request,\n\t\t\t);\n\t\t\tif (!session) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Failed to create session\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\tsession,\n\t\t\t\tuser: createdUser,\n\t\t\t});\n\t\t\treturn ctx.json(\n\t\t\t\t{\n\t\t\t\t\tuser: createdUser as InferUser<O>,\n\t\t\t\t\tsession: session as InferSession<O>,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbody: body.callbackURL\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\turl: body.callbackURL,\n\t\t\t\t\t\t\t\tredirect: true,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t);\n","import { z } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { socialProviderList } from \"../../social-providers\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { APIError } from \"better-call\";\nimport { generateState, parseState, type OAuth2Tokens } from \"../../oauth2\";\nimport { generateCodeVerifier } from \"oslo/oauth2\";\nimport { HIDE_METADATA, logger } from \"../../utils\";\nimport { compareHash } from \"../../crypto/hash\";\nimport { getSessionFromCtx, sessionMiddleware } from \"./session\";\nimport { userSchema } from \"../../db/schema\";\n\nexport const listUserAccounts = createAuthEndpoint(\n\t\"/user/list-accounts\",\n\t{\n\t\tmethod: \"GET\",\n\t\tuse: [sessionMiddleware],\n\t},\n\tasync (c) => {\n\t\tconst session = c.context.session;\n\t\tconst accounts = await c.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\treturn c.json(accounts);\n\t},\n);\n\nexport const linkSocialAccount = createAuthEndpoint(\n\t\"/user/link-social\",\n\t{\n\t\tmethod: \"POST\",\n\t\trequireHeaders: true,\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\t/**\n\t\t\t\t * Redirect to the current URL after the\n\t\t\t\t * user has signed in.\n\t\t\t\t */\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * Callback URL to redirect to after the user has signed in.\n\t\t\t */\n\t\t\tcallbackURL: z.string().optional(),\n\t\t\t/**\n\t\t\t * OAuth2 provider to use`\n\t\t\t */\n\t\t\tprovider: z.enum(socialProviderList),\n\t\t}),\n\t\tuse: [redirectURLMiddleware, sessionMiddleware],\n\t},\n\tasync (c) => {\n\t\tconst session = c.context.session;\n\t\tconst account = await c.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst existingAccount = account.find(\n\t\t\t(a) => a.providerId === c.body.provider,\n\t\t);\n\t\tif (existingAccount) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Social Account is already linked.\",\n\t\t\t});\n\t\t}\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.body.provider,\n\t\t);\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t{\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\tmessage: \"Provider not found\",\n\t\t\t});\n\t\t}\n\t\tconst cookie = c.context.authCookies;\n\t\tconst currentURL = c.query?.currentURL\n\t\t\t? new URL(c.query?.currentURL)\n\t\t\t: null;\n\n\t\tconst callbackURL = c.body.callbackURL?.startsWith(\"http\")\n\t\t\t? c.body.callbackURL\n\t\t\t: `${currentURL?.origin}${c.body.callbackURL || \"\"}`;\n\n\t\tconst state = await generateState(\n\t\t\tcallbackURL || currentURL?.origin || c.context.options.baseURL,\n\t\t\t{\n\t\t\t\temail: session.user.email,\n\t\t\t\tuserId: session.user.id,\n\t\t\t},\n\t\t);\n\t\tawait c.setSignedCookie(\n\t\t\tcookie.state.name,\n\t\t\tstate.hash,\n\t\t\tc.context.secret,\n\t\t\tcookie.state.options,\n\t\t);\n\t\tconst codeVerifier = generateCodeVerifier();\n\t\tawait c.setSignedCookie(\n\t\t\tcookie.pkCodeVerifier.name,\n\t\t\tcodeVerifier,\n\t\t\tc.context.secret,\n\t\t\tcookie.pkCodeVerifier.options,\n\t\t);\n\t\tconst url = await provider.createAuthorizationURL({\n\t\t\tstate: state.raw,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI: `${c.context.baseURL}/link-account/${provider.id}`,\n\t\t});\n\t\treturn c.json({\n\t\t\turl: url.toString(),\n\t\t\tstate: state,\n\t\t\tcodeVerifier,\n\t\t\tredirect: true,\n\t\t});\n\t},\n);\n","import type { AuthContext, RateLimit } from \"../../types\";\nimport { getIp } from \"../../utils/get-request-ip\";\nimport { logger } from \"../../utils/logger\";\n\nfunction shouldRateLimit(\n\tmax: number,\n\twindow: number,\n\trateLimitData: RateLimit,\n) {\n\tconst now = Date.now();\n\tconst windowInMs = window * 1000;\n\tconst timeSinceLastRequest = now - rateLimitData.lastRequest;\n\treturn timeSinceLastRequest < windowInMs && rateLimitData.count >= max;\n}\n\nfunction rateLimitResponse(retryAfter: number) {\n\treturn new Response(\n\t\tJSON.stringify({\n\t\t\tmessage: \"Too many requests. Please try again later.\",\n\t\t}),\n\t\t{\n\t\t\tstatus: 429,\n\t\t\tstatusText: \"Too Many Requests\",\n\t\t\theaders: {\n\t\t\t\t\"X-Retry-After\": retryAfter.toString(),\n\t\t\t},\n\t\t},\n\t);\n}\n\nfunction getRetryAfter(lastRequest: number, window: number) {\n\tconst now = Date.now();\n\tconst windowInMs = window * 1000;\n\treturn Math.ceil((lastRequest + windowInMs - now) / 1000);\n}\n\nfunction createDBStorage(ctx: AuthContext, tableName?: string) {\n\tconst model = tableName ?? \"rateLimit\";\n\tconst db = ctx.adapter;\n\treturn {\n\t\tget: async (key: string) => {\n\t\t\tconst res = await db.findOne<RateLimit>({\n\t\t\t\tmodel,\n\t\t\t\twhere: [{ field: \"key\", value: key }],\n\t\t\t});\n\t\t\treturn res;\n\t\t},\n\t\tset: async (key: string, value: RateLimit, _update?: boolean) => {\n\t\t\ttry {\n\t\t\t\tif (_update) {\n\t\t\t\t\tawait db.update({\n\t\t\t\t\t\tmodel: tableName ?? \"rateLimit\",\n\t\t\t\t\t\twhere: [{ field: \"key\", value: key }],\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tcount: value.count,\n\t\t\t\t\t\t\tlastRequest: value.lastRequest,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait db.create({\n\t\t\t\t\t\tmodel: tableName ?? \"rateLimit\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tcount: value.count,\n\t\t\t\t\t\t\tlastRequest: value.lastRequest,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(\"Error setting rate limit\", e);\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst memory = new Map<string, RateLimit>();\nexport function getRateLimitStorage(ctx: AuthContext) {\n\tif (ctx.rateLimit.storage === \"secondary-storage\") {\n\t\treturn {\n\t\t\tget: async (key: string) => {\n\t\t\t\tconst stringified = await ctx.options.secondaryStorage?.get(key);\n\t\t\t\treturn stringified ? (JSON.parse(stringified) as RateLimit) : undefined;\n\t\t\t},\n\t\t\tset: async (key: string, value: RateLimit) => {\n\t\t\t\tawait ctx.options.secondaryStorage?.set?.(key, JSON.stringify(value));\n\t\t\t},\n\t\t};\n\t}\n\tconst storage = ctx.rateLimit.storage;\n\tif (storage === \"memory\") {\n\t\treturn {\n\t\t\tasync get(key: string) {\n\t\t\t\treturn memory.get(key);\n\t\t\t},\n\t\t\tasync set(key: string, value: RateLimit, _update?: boolean) {\n\t\t\t\tmemory.set(key, value);\n\t\t\t},\n\t\t};\n\t}\n\treturn createDBStorage(ctx, ctx.rateLimit.tableName);\n}\n\nexport async function onRequestRateLimit(req: Request, ctx: AuthContext) {\n\tif (!ctx.rateLimit.enabled) {\n\t\treturn;\n\t}\n\n\tconst baseURL = ctx.baseURL;\n\tconst path = req.url.replace(baseURL, \"\");\n\tlet window = ctx.rateLimit.window;\n\tlet max = ctx.rateLimit.max;\n\tconst key = getIp(req) + path;\n\tconst specialRules = getDefaultSpecialRules();\n\tconst specialRule = specialRules.find((rule) => rule.pathMatcher(path));\n\n\tif (specialRule) {\n\t\twindow = specialRule.window;\n\t\tmax = specialRule.max;\n\t}\n\n\tfor (const plugin of ctx.options.plugins || []) {\n\t\tif (plugin.rateLimit) {\n\t\t\tconst matchedRule = plugin.rateLimit.find((rule) =>\n\t\t\t\trule.pathMatcher(path),\n\t\t\t);\n\t\t\tif (matchedRule) {\n\t\t\t\twindow = matchedRule.window;\n\t\t\t\tmax = matchedRule.max;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (ctx.rateLimit.customRules) {\n\t\tconst customRule = ctx.rateLimit.customRules[path];\n\t\tif (customRule) {\n\t\t\twindow = customRule.window;\n\t\t\tmax = customRule.max;\n\t\t}\n\t}\n\n\tconst storage = getRateLimitStorage(ctx);\n\tconst data = await storage.get(key);\n\tconst now = Date.now();\n\n\tif (!data) {\n\t\tawait storage.set(key, {\n\t\t\tkey,\n\t\t\tcount: 1,\n\t\t\tlastRequest: now,\n\t\t});\n\t} else {\n\t\tconst timeSinceLastRequest = now - data.lastRequest;\n\n\t\tif (shouldRateLimit(max, window, data)) {\n\t\t\tconst retryAfter = getRetryAfter(data.lastRequest, window);\n\t\t\treturn rateLimitResponse(retryAfter);\n\t\t} else if (timeSinceLastRequest > window * 1000) {\n\t\t\t// Reset the count if the window has passed since the last request\n\t\t\tawait storage.set(key, {\n\t\t\t\t...data,\n\t\t\t\tcount: 1,\n\t\t\t\tlastRequest: now,\n\t\t\t});\n\t\t} else {\n\t\t\tawait storage.set(key, {\n\t\t\t\t...data,\n\t\t\t\tcount: data.count + 1,\n\t\t\t\tlastRequest: now,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction getDefaultSpecialRules() {\n\tconst specialRules = [\n\t\t{\n\t\t\tpathMatcher(path: string) {\n\t\t\t\treturn path.startsWith(\"/sign-in\") || path.startsWith(\"/sign-up\");\n\t\t\t},\n\t\t\twindow: 10,\n\t\t\tmax: 3,\n\t\t},\n\t];\n\treturn specialRules;\n}\n"],"mappings":"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","names":["APIError","createRouter","statusCode","APIError","createEndpointCreator","createMiddleware","createMiddlewareCreator","optionsMiddleware","createAuthMiddleware","createAuthEndpoint","originCheckMiddleware","createAuthMiddleware","ctx","body","query","context","originHeader","callbackURL","redirectURL","currentURL","trustedOrigins","validateURL","url","label","origin","logger","APIError","APIError","generateCodeVerifier","z","APIError","redirectURLMiddleware","createAuthMiddleware","ctx","body","query","context","callbackURL","currentURL","trustedOrigins","validateURL","url","label","origin","logger","APIError","TimeSpan","createJWT","validateJWT","z","APIError","APIError","z","getSession","createAuthEndpoint","ctx","sessionCookieToken","sessionData","dontRememberMe","session","deleteSessionCookie","expiresIn","updateAge","updatedSession","getDate","maxAge","setSessionCookie","error","getSessionFromCtx","sessionMiddleware","createAuthMiddleware","APIError","listSessions","activeSessions","revokeSession","id","findSession","revokeSessions","createEmailVerificationToken","secret","email","updateTo","createJWT","TimeSpan","sendVerificationEmail","createAuthEndpoint","z","redirectURLMiddleware","ctx","APIError","user","token","url","verifyEmail","jwt","validateJWT","e","parsed","session","getSessionFromCtx","updatedUser","signInOAuth","createAuthEndpoint","z","socialProviderList","redirectURLMiddleware","c","provider","p","APIError","cookie","currentURL","callbackURL","state","generateState","codeVerifier","generateCodeVerifier","url","signInEmail","ctx","email","password","user","credentialAccount","a","currentPassword","logger","token","createEmailVerificationToken","session","setSessionCookie","z","z","accountSchema","userSchema","val","sessionSchema","verificationSchema","getAllFields","options","table","schema","plugin","parseInputData","data","schema","action","fields","parsedData","key","parseUserInput","options","user","getAllFields","isDevelopment","callbackOAuth","createAuthEndpoint","z","HIDE_METADATA","c","callbackURL","parseState","provider","p","parsedState","currentURL","link","storedState","logger","compareHash","codeVerifier","tokens","e","userInfo","res","id","generateId","data","userSchema","redirectOnError","error","dbUser","user","hasBeenLinked","a","emailVerified","token","createEmailVerificationToken","url","session","setSessionCookie","APIError","signOut","createAuthEndpoint","ctx","sessionCookieToken","APIError","deleteSessionCookie","z","APIError","forgetPassword","createAuthEndpoint","z","redirectURLMiddleware","ctx","APIError","email","redirectTo","user","defaultExpiresIn","expiresAt","verificationToken","url","forgetPasswordCallback","token","callbackURL","verification","resetPassword","newPassword","id","userId","hashedPassword","ac","z","APIError","updateUser","createAuthEndpoint","z","sessionMiddleware","redirectURLMiddleware","ctx","body","APIError","name","image","rest","session","additionalFields","parseUserInput","user","setSessionCookie","changePassword","newPassword","currentPassword","revokeOtherSessions","minPasswordLength","maxPasswordLength","account","passwordHash","newSession","setPassword","deleteUser","password","deleteSessionCookie","changeEmail","updatedUser","token","createEmailVerificationToken","url","html","errorCode","error","createAuthEndpoint","HIDE_METADATA","c","query","ok","createAuthEndpoint","HIDE_METADATA","ctx","z","APIError","signUpEmail","createAuthEndpoint","z","redirectURLMiddleware","ctx","APIError","body","name","email","password","image","callbackURL","additionalFields","minPasswordLength","maxPasswordLength","additionalData","parseUserInput","createdUser","e","logger","hash","getDate","token","createEmailVerificationToken","url","session","setSessionCookie","z","APIError","generateCodeVerifier","listUserAccounts","createAuthEndpoint","sessionMiddleware","c","session","accounts","linkSocialAccount","z","socialProviderList","redirectURLMiddleware","a","APIError","provider","p","cookie","currentURL","callbackURL","state","generateState","codeVerifier","generateCodeVerifier","url","shouldRateLimit","max","window","rateLimitData","now","windowInMs","rateLimitResponse","retryAfter","getRetryAfter","lastRequest","createDBStorage","ctx","tableName","model","db","key","value","_update","e","logger","memory","getRateLimitStorage","stringified","onRequestRateLimit","req","baseURL","path","getIp","specialRule","getDefaultSpecialRules","rule","plugin","matchedRule","customRule","storage","data","timeSinceLastRequest","APIError","getEndpoints","ctx","options","pluginEndpoints","acc","plugin","middlewares","m","middleware","context","endpoints","signInOAuth","callbackOAuth","getSession","signOut","signUpEmail","signInEmail","forgetPassword","resetPassword","verifyEmail","sendVerificationEmail","changeEmail","changePassword","setPassword","updateUser","deleteUser","forgetPasswordCallback","listSessions","revokeSession","revokeSessions","linkSocialAccount","listUserAccounts","ok","error","api","key","value","hook","hookRes","endpointRes","e","afterPlugins","response","statusCode","obj","router","basePath","createRouter","originCheckMiddleware","req","onRequestRateLimit","res","log","logger"]}
@@ -0,0 +1,2 @@
1
+ import{c as n}from"./chunk-OK6SC5MD.js";var m=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t.startsWith("/two-factor/"),signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});import{WebAuthnError as p,startAuthentication as y,startRegistration as u}from"@simplewebauthn/browser";import{atom as l}from"nanostores";var f=(e,{_listPasskeys:t})=>({signIn:{passkey:async(r,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:r?.email}});if(!a.data)return a;try{let s=await y(a.data,r?.autoFill||!1),o=await e("/passkey/verify-authentication",{body:{response:s},...r?.fetchOptions,...i,method:"POST"});if(!o.data)return o}catch(s){console.log(s)}}},passkey:{addPasskey:async(r,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await u(a.data),o=await e("/passkey/verify-registration",{...r?.fetchOptions,...i,body:{response:s,name:r?.name},method:"POST"});if(!o.data)return o;t.set(Math.random())}catch(s){return s instanceof p?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),O=()=>{let e=l();return{id:"passkey",$InferServerPlugin:{},getActions:t=>f(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:n(e,"/passkey/list-user-passkeys",t,{method:"GET",credentials:"include"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};export{m as a,f as b,O as c};
2
+ //# sourceMappingURL=chunk-5MAH3KZL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/plugins/two-factor/client.ts","../src/plugins/passkey/client.ts"],"sourcesContent":["import type { BetterAuthClientPlugin } from \"../../client/types\";\nimport type { twoFactor as twoFa } from \"../../plugins/two-factor\";\n\nexport const twoFactorClient = (\n\toptions: {\n\t\ttwoFactorPage: string;\n\t\t/**\n\t\t * Redirect to the two factor page. If twoFactorPage\n\t\t * is not set this will redirect to the root path.\n\t\t * @default true\n\t\t */\n\t\tredirect?: boolean;\n\t} = {\n\t\tredirect: true,\n\t\ttwoFactorPage: \"/\",\n\t},\n) => {\n\treturn {\n\t\tid: \"two-factor\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof twoFa>,\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher: (path) => path.startsWith(\"/two-factor/\"),\n\t\t\t\tsignal: \"_sessionSignal\",\n\t\t\t},\n\t\t],\n\t\tpathMethods: {\n\t\t\t\"/two-factor/disable\": \"POST\",\n\t\t\t\"/two-factor/enable\": \"POST\",\n\t\t\t\"/two-factor/send-otp\": \"POST\",\n\t\t\t\"/two-factor/generate-backup-codes\": \"POST\",\n\t\t},\n\t\tfetchPlugins: [\n\t\t\t{\n\t\t\t\tid: \"two-factor\",\n\t\t\t\tname: \"two-factor\",\n\t\t\t\thooks: {\n\t\t\t\t\tasync onSuccess(context) {\n\t\t\t\t\t\tif (context.data?.twoFactorRedirect) {\n\t\t\t\t\t\t\tif (options.redirect || options.twoFactorPage) {\n\t\t\t\t\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\t\t\t\t\twindow.location.href = options.twoFactorPage;\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} satisfies BetterAuthClientPlugin;\n};\n","import type { BetterFetch, BetterFetchOption } from \"@better-fetch/fetch\";\nimport {\n\tWebAuthnError,\n\tstartAuthentication,\n\tstartRegistration,\n} from \"@simplewebauthn/browser\";\nimport type {\n\tPublicKeyCredentialCreationOptionsJSON,\n\tPublicKeyCredentialRequestOptionsJSON,\n} from \"@simplewebauthn/types\";\nimport type { Session } from \"inspector\";\nimport type { User } from \"../../db/schema\";\nimport type { passkey as passkeyPl, Passkey } from \"../../plugins\";\nimport type { BetterAuthClientPlugin } from \"../../client/types\";\nimport { useAuthQuery } from \"../../client\";\nimport { atom } from \"nanostores\";\n\nexport const getPasskeyActions = (\n\t$fetch: BetterFetch,\n\t{\n\t\t_listPasskeys,\n\t}: {\n\t\t_listPasskeys: ReturnType<typeof atom<any>>;\n\t},\n) => {\n\tconst signInPasskey = async (\n\t\topts?: {\n\t\t\tautoFill?: boolean;\n\t\t\temail?: string;\n\t\t\tfetchOptions?: BetterFetchOption;\n\t\t},\n\t\toptions?: BetterFetchOption,\n\t) => {\n\t\tconst response = await $fetch<PublicKeyCredentialRequestOptionsJSON>(\n\t\t\t\"/passkey/generate-authenticate-options\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\temail: opts?.email,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\tif (!response.data) {\n\t\t\treturn response;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startAuthentication(\n\t\t\t\tresponse.data,\n\t\t\t\topts?.autoFill || false,\n\t\t\t);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tsession: Session;\n\t\t\t\tuser: User;\n\t\t\t}>(\"/passkey/verify-authentication\", {\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t},\n\t\t\t\t...opts?.fetchOptions,\n\t\t\t\t...options,\n\t\t\t\tmethod: \"POST\",\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.log(e);\n\t\t}\n\t};\n\n\tconst registerPasskey = async (\n\t\topts?: {\n\t\t\tfetchOptions?: BetterFetchOption;\n\t\t\t/**\n\t\t\t * The name of the passkey. This is used to\n\t\t\t * identify the passkey in the UI.\n\t\t\t */\n\t\t\tname?: string;\n\t\t},\n\t\tfetchOpts?: BetterFetchOption,\n\t) => {\n\t\tconst options = await $fetch<PublicKeyCredentialCreationOptionsJSON>(\n\t\t\t\"/passkey/generate-register-options\",\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t},\n\t\t);\n\t\tif (!options.data) {\n\t\t\treturn options;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startRegistration(options.data);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tpasskey: Passkey;\n\t\t\t}>(\"/passkey/verify-registration\", {\n\t\t\t\t...opts?.fetchOptions,\n\t\t\t\t...fetchOpts,\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t\tname: opts?.name,\n\t\t\t\t},\n\t\t\t\tmethod: \"POST\",\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t\t_listPasskeys.set(Math.random());\n\t\t} catch (e) {\n\t\t\tif (e instanceof WebAuthnError) {\n\t\t\t\tif (e.code === \"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"previously registered\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (e.code === \"ERROR_CEREMONY_ABORTED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"registration cancelled\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tdata: null,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: e.message,\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tdata: null,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: e instanceof Error ? e.message : \"unknown error\",\n\t\t\t\t\tstatus: 500,\n\t\t\t\t\tstatusText: \"INTERNAL_SERVER_ERROR\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t};\n\n\treturn {\n\t\tsignIn: {\n\t\t\t/**\n\t\t\t * Sign in with a registered passkey\n\t\t\t */\n\t\t\tpasskey: signInPasskey,\n\t\t},\n\t\tpasskey: {\n\t\t\t/**\n\t\t\t * Add a passkey to the user account\n\t\t\t */\n\t\t\taddPasskey: registerPasskey,\n\t\t},\n\t\t/**\n\t\t * Inferred Internal Types\n\t\t */\n\t\t$Infer: {} as {\n\t\t\tPasskey: Passkey;\n\t\t},\n\t};\n};\n\nexport const passkeyClient = () => {\n\tconst _listPasskeys = atom<any>();\n\treturn {\n\t\tid: \"passkey\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof passkeyPl>,\n\t\tgetActions: ($fetch) =>\n\t\t\tgetPasskeyActions($fetch, {\n\t\t\t\t_listPasskeys,\n\t\t\t}),\n\t\tgetAtoms($fetch) {\n\t\t\tconst listPasskeys = useAuthQuery<Passkey[]>(\n\t\t\t\t_listPasskeys,\n\t\t\t\t\"/passkey/list-user-passkeys\",\n\t\t\t\t$fetch,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tlistPasskeys,\n\t\t\t\t_listPasskeys,\n\t\t\t};\n\t\t},\n\t\tpathMethods: {\n\t\t\t\"/passkey/register\": \"POST\",\n\t\t\t\"/passkey/authenticate\": \"POST\",\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/passkey/verify-registration\" ||\n\t\t\t\t\t\tpath === \"/passkey/delete-passkey\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_listPasskeys\",\n\t\t\t},\n\t\t],\n\t} satisfies BetterAuthClientPlugin;\n};\n"],"mappings":"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","names":["twoFactorClient","options","path","context","WebAuthnError","startAuthentication","startRegistration","atom","getPasskeyActions","$fetch","_listPasskeys","opts","options","response","res","startAuthentication","verified","e","fetchOpts","startRegistration","WebAuthnError","passkeyClient","useAuthQuery","path"]}
@@ -0,0 +1,2 @@
1
+ import{a as y}from"./chunk-ZXH7J5K5.js";import{createFetch as w}from"@better-fetch/fetch";import"nanostores";import"@better-fetch/fetch";var P={id:"redirect",name:"Redirect",hooks:{onSuccess(e){e.data?.url&&e.data?.redirect&&typeof window<"u"&&(window.location.href=e.data.url)}}},O={id:"add-current-url",name:"Add current URL",hooks:{onRequest(e){if(typeof window<"u"){let r=new URL(e.url);r.searchParams.set("currentURL",window.location.href),e.url=r}return e}}};var k=e=>{let r="credentials"in Request.prototype,l=y(e?.fetchOptions?.baseURL||e?.baseURL),s=w({baseURL:l,...r?{credentials:"include"}:{},method:"GET",...e?.fetchOptions,plugins:e?.disableDefaultFetchPlugins?e.fetchOptions?.plugins:[P,O,...e?.fetchOptions?.plugins?.filter(t=>t!==void 0)||[],...e?.plugins?.flatMap(t=>t.fetchPlugins).filter(t=>t!==void 0)||[]]}),n=e?.plugins||[],u={},c={},o={"/sign-out":"POST","/user/revoke-sessions":"POST"},i=[{signal:"_sessionSignal",matcher(t){return t==="/sign-out"||t==="/user/update"||t.startsWith("/sign-in")||t.startsWith("/sign-up")}}];for(let t of n)t.getActions&&Object.assign(u,t.getActions?.(s)),t.getAtoms&&Object.assign(c,t.getAtoms?.(s)),t.pathMethods&&Object.assign(o,t.pathMethods),t.atomListeners&&i.push(...t.atomListeners);return{pluginsActions:u,pluginsAtoms:c,pluginPathMethods:o,atomListeners:i,$fetch:s}};function C(e,r,l){let s=r[e],{fetchOptions:n,query:u,...c}=l||{};return s||(n?.method?n.method:c&&Object.keys(c).length>0?"POST":"GET")}function _(e,r,l,s,n){function u(c=[]){return new Proxy(function(){},{get(o,i){let t=[...c,i],a=e;for(let d of t)if(a&&typeof a=="object"&&d in a)a=a[d];else{a=void 0;break}return typeof a=="function"?a:u(t)},apply:async(o,i,t)=>{let a="/"+c.map(g=>g.replace(/[A-Z]/g,p=>`-${p.toLowerCase()}`)).join("/"),d=t[0]||{},b=t[1]||{},{query:A,fetchOptions:R,...B}=d,f={...b,...R},m=C(a,l,d);return await r(a,{...f,body:m==="GET"?void 0:{...B,...f?.body||{}},query:A||f?.query,method:m,async onSuccess(g){await f?.onSuccess?.(g);let p=n?.find(T=>T.matcher(a));if(!p)return;let h=s[p.signal];if(!h)return;let S=h.get();setTimeout(()=>{h.set(!S)},10)}})}})}return u()}import"@better-fetch/fetch";import{atom as L,onMount as U}from"nanostores";var F=(e,r,l,s)=>{let n=L({data:null,error:null,isPending:!0,isRefetching:!1}),u=()=>{let o=typeof s=="function"?s({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):s;return l(r,{...o,onSuccess:async i=>{n.set({data:i.data,error:null,isPending:!1,isRefetching:!1}),await o?.onSuccess?.(i)},async onError(i){n.set({error:i.error,data:null,isPending:!1,isRefetching:!1}),await o?.onError?.(i)},async onRequest(i){let t=n.get();n.set({isPending:t.data===null,data:t.data,error:null,isRefetching:!0}),await o?.onRequest?.(i)}})};e=Array.isArray(e)?e:[e];let c=!1;for(let o of e)o.subscribe(()=>{c?u():U(n,()=>(u(),c=!0,()=>{n.off(),o.off()}))});return n};import{atom as W}from"nanostores";function H(e){let r=W(!1);return{$session:F(r,"/get-session",e,{method:"GET"}),_sessionSignal:r,$Infer:{}}}export{k as a,_ as b,F as c,H as d};
2
+ //# sourceMappingURL=chunk-727CSAR4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client/config.ts","../src/client/fetch-plugins.ts","../src/client/proxy.ts","../src/client/query.ts","../src/client/session-atom.ts"],"sourcesContent":["import { createFetch } from \"@better-fetch/fetch\";\nimport { getBaseURL } from \"../utils/url\";\nimport { type Atom } from \"nanostores\";\nimport type { AtomListener, ClientOptions } from \"./types\";\nimport { addCurrentURL, redirectPlugin } from \"./fetch-plugins\";\n\nexport const getClientConfig = <O extends ClientOptions>(options?: O) => {\n\t/* check if the credentials property is supported. Useful for cf workers */\n\tconst isCredentialsSupported = \"credentials\" in Request.prototype;\n\tconst baseURL = getBaseURL(\n\t\toptions?.fetchOptions?.baseURL || options?.baseURL,\n\t);\n\tconst $fetch = createFetch({\n\t\tbaseURL,\n\t\t...(isCredentialsSupported ? { credentials: \"include\" } : {}),\n\t\tmethod: \"GET\",\n\t\t...options?.fetchOptions,\n\n\t\tplugins: options?.disableDefaultFetchPlugins\n\t\t\t? options.fetchOptions?.plugins\n\t\t\t: [\n\t\t\t\t\tredirectPlugin,\n\t\t\t\t\taddCurrentURL,\n\t\t\t\t\t...(options?.fetchOptions?.plugins?.filter(\n\t\t\t\t\t\t(pl) => pl !== undefined,\n\t\t\t\t\t) || []),\n\t\t\t\t\t...(options?.plugins\n\t\t\t\t\t\t?.flatMap((plugin) => plugin.fetchPlugins)\n\t\t\t\t\t\t.filter((pl) => pl !== undefined) || []),\n\t\t\t\t],\n\t});\n\n\tconst plugins = options?.plugins || [];\n\tlet pluginsActions = {} as Record<string, any>;\n\tlet pluginsAtoms = {} as Record<string, Atom<any>>;\n\tlet pluginPathMethods: Record<string, \"POST\" | \"GET\"> = {\n\t\t\"/sign-out\": \"POST\",\n\t\t\"/user/revoke-sessions\": \"POST\",\n\t};\n\tconst atomListeners: AtomListener[] = [\n\t\t{\n\t\t\tsignal: \"_sessionSignal\",\n\t\t\tmatcher(path) {\n\t\t\t\treturn (\n\t\t\t\t\tpath === \"/sign-out\" ||\n\t\t\t\t\tpath === \"/user/update\" ||\n\t\t\t\t\tpath.startsWith(\"/sign-in\") ||\n\t\t\t\t\tpath.startsWith(\"/sign-up\")\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n\tfor (const plugin of plugins) {\n\t\tif (plugin.getActions) {\n\t\t\tObject.assign(pluginsActions, plugin.getActions?.($fetch));\n\t\t}\n\t\tif (plugin.getAtoms) {\n\t\t\tObject.assign(pluginsAtoms, plugin.getAtoms?.($fetch));\n\t\t}\n\t\tif (plugin.pathMethods) {\n\t\t\tObject.assign(pluginPathMethods, plugin.pathMethods);\n\t\t}\n\t\tif (plugin.atomListeners) {\n\t\t\tatomListeners.push(...plugin.atomListeners);\n\t\t}\n\t}\n\treturn {\n\t\tpluginsActions,\n\t\tpluginsAtoms,\n\t\tpluginPathMethods,\n\t\tatomListeners,\n\t\t$fetch,\n\t};\n};\n","import { type BetterFetchPlugin } from \"@better-fetch/fetch\";\n\nexport const redirectPlugin = {\n\tid: \"redirect\",\n\tname: \"Redirect\",\n\thooks: {\n\t\tonSuccess(context) {\n\t\t\tif (context.data?.url && context.data?.redirect) {\n\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\twindow.location.href = context.data.url;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n\nexport const addCurrentURL = {\n\tid: \"add-current-url\",\n\tname: \"Add current URL\",\n\thooks: {\n\t\tonRequest(context) {\n\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\tconst url = new URL(context.url);\n\t\t\t\turl.searchParams.set(\"currentURL\", window.location.href);\n\t\t\t\tcontext.url = url;\n\t\t\t}\n\t\t\treturn context;\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n","import type { BetterFetch, BetterFetchOption } from \"@better-fetch/fetch\";\nimport type { Atom, PreinitializedWritableAtom } from \"nanostores\";\nimport type { ProxyRequest } from \"./path-to-object\";\nimport type { BetterAuthClientPlugin } from \"./types\";\n\nfunction getMethod(\n\tpath: string,\n\tknownPathMethods: Record<string, \"POST\" | \"GET\">,\n\targs:\n\t\t| { fetchOptions?: BetterFetchOption; query?: Record<string, any> }\n\t\t| undefined,\n) {\n\tconst method = knownPathMethods[path];\n\tconst { fetchOptions, query, ...body } = args || {};\n\tif (method) {\n\t\treturn method;\n\t}\n\tif (fetchOptions?.method) {\n\t\treturn fetchOptions.method;\n\t}\n\tif (body && Object.keys(body).length > 0) {\n\t\treturn \"POST\";\n\t}\n\treturn \"GET\";\n}\n\nexport type AuthProxySignal = {\n\tatom: PreinitializedWritableAtom<boolean>;\n\tmatcher: (path: string) => boolean;\n};\n\nexport function createDynamicPathProxy<T extends Record<string, any>>(\n\troutes: T,\n\tclient: BetterFetch,\n\tknownPathMethods: Record<string, \"POST\" | \"GET\">,\n\tatoms: Record<string, Atom>,\n\tatomListeners: BetterAuthClientPlugin[\"atomListeners\"],\n): T {\n\tfunction createProxy(path: string[] = []): any {\n\t\treturn new Proxy(function () {}, {\n\t\t\tget(target, prop: string) {\n\t\t\t\tconst fullPath = [...path, prop];\n\t\t\t\tlet current: any = routes;\n\t\t\t\tfor (const segment of fullPath) {\n\t\t\t\t\tif (current && typeof current === \"object\" && segment in current) {\n\t\t\t\t\t\tcurrent = current[segment];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcurrent = undefined;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (typeof current === \"function\") {\n\t\t\t\t\treturn current;\n\t\t\t\t}\n\t\t\t\treturn createProxy(fullPath);\n\t\t\t},\n\t\t\tapply: async (_, __, args) => {\n\t\t\t\tconst routePath =\n\t\t\t\t\t\"/\" +\n\t\t\t\t\tpath\n\t\t\t\t\t\t.map((segment) =>\n\t\t\t\t\t\t\tsegment.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.join(\"/\");\n\t\t\t\tconst arg = (args[0] || {}) as ProxyRequest;\n\t\t\t\tconst fetchOptions = (args[1] || {}) as BetterFetchOption;\n\t\t\t\tconst { query, fetchOptions: argFetchOptions, ...body } = arg;\n\t\t\t\tconst options = {\n\t\t\t\t\t...fetchOptions,\n\t\t\t\t\t...argFetchOptions,\n\t\t\t\t} as BetterFetchOption;\n\t\t\t\tconst method = getMethod(routePath, knownPathMethods, arg);\n\n\t\t\t\treturn await client(routePath, {\n\t\t\t\t\t...options,\n\n\t\t\t\t\tbody:\n\t\t\t\t\t\tmethod === \"GET\"\n\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\t...body,\n\t\t\t\t\t\t\t\t\t...(options?.body || {}),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\tquery: query || options?.query,\n\t\t\t\t\tmethod,\n\t\t\t\t\tasync onSuccess(context) {\n\t\t\t\t\t\tawait options?.onSuccess?.(context);\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * We trigger listeners\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst matches = atomListeners?.find((s) => s.matcher(routePath));\n\t\t\t\t\t\tif (!matches) return;\n\t\t\t\t\t\tconst signal = atoms[matches.signal as any];\n\t\t\t\t\t\tif (!signal) return;\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * To avoid race conditions we set the signal in a setTimeout\n\t\t\t\t\t\t */\n\t\t\t\t\t\tconst val = signal.get();\n\t\t\t\t\t\tsetTimeout(() => {\n\t\t\t\t\t\t\t//@ts-expect-error\n\t\t\t\t\t\t\tsignal.set(!val);\n\t\t\t\t\t\t}, 10);\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\t}\n\treturn createProxy() as T;\n}\n","import {\n\tBetterFetchError,\n\ttype BetterFetch,\n\ttype BetterFetchOption,\n} from \"@better-fetch/fetch\";\nimport { atom, onMount, type PreinitializedWritableAtom } from \"nanostores\";\n\nexport const useAuthQuery = <T>(\n\tinitializedAtom:\n\t\t| PreinitializedWritableAtom<any>\n\t\t| PreinitializedWritableAtom<any>[],\n\tpath: string,\n\t$fetch: BetterFetch,\n\toptions?:\n\t\t| ((value: {\n\t\t\t\tdata: null | T;\n\t\t\t\terror: null | BetterFetchError;\n\t\t\t\tisPending: boolean;\n\t\t }) => BetterFetchOption)\n\t\t| BetterFetchOption,\n) => {\n\tconst value = atom<{\n\t\tdata: null | T;\n\t\terror: null | BetterFetchError;\n\t\tisPending: boolean;\n\t\tisRefetching: boolean;\n\t}>({\n\t\tdata: null,\n\t\terror: null,\n\t\tisPending: true,\n\t\tisRefetching: false,\n\t});\n\n\tconst fn = () => {\n\t\tconst opts =\n\t\t\ttypeof options === \"function\"\n\t\t\t\t? options({\n\t\t\t\t\t\tdata: value.get().data,\n\t\t\t\t\t\terror: value.get().error,\n\t\t\t\t\t\tisPending: value.get().isPending,\n\t\t\t\t\t})\n\t\t\t\t: options;\n\t\treturn $fetch<T>(path, {\n\t\t\t...opts,\n\t\t\tonSuccess: async (context) => {\n\t\t\t\tvalue.set({\n\t\t\t\t\tdata: context.data,\n\t\t\t\t\terror: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t\tisRefetching: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onSuccess?.(context);\n\t\t\t},\n\t\t\tasync onError(context) {\n\t\t\t\tvalue.set({\n\t\t\t\t\terror: context.error,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t\tisRefetching: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onError?.(context);\n\t\t\t},\n\t\t\tasync onRequest(context) {\n\t\t\t\tconst currentValue = value.get();\n\t\t\t\tvalue.set({\n\t\t\t\t\tisPending: currentValue.data === null,\n\t\t\t\t\tdata: currentValue.data,\n\t\t\t\t\terror: null,\n\t\t\t\t\tisRefetching: true,\n\t\t\t\t});\n\t\t\t\tawait opts?.onRequest?.(context);\n\t\t\t},\n\t\t});\n\t};\n\n\tinitializedAtom = Array.isArray(initializedAtom)\n\t\t? initializedAtom\n\t\t: [initializedAtom];\n\tlet isMounted = false;\n\tfor (const initAtom of initializedAtom) {\n\t\tinitAtom.subscribe(() => {\n\t\t\tif (isMounted) {\n\t\t\t\tfn();\n\t\t\t} else {\n\t\t\t\tonMount(value, () => {\n\t\t\t\t\tfn();\n\t\t\t\t\tisMounted = true;\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tvalue.off();\n\t\t\t\t\t\tinitAtom.off();\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\treturn value;\n};\n","import type { BetterFetch } from \"@better-fetch/fetch\";\nimport { atom } from \"nanostores\";\nimport type { Prettify } from \"../types/helper\";\nimport type {\n\tClientOptions,\n\tInferSessionFromClient,\n\tInferUserFromClient,\n} from \"./types\";\nimport { useAuthQuery } from \"./query\";\n\nexport function getSessionAtom<Option extends ClientOptions>(\n\t$fetch: BetterFetch,\n) {\n\ttype UserWithAdditionalFields = InferUserFromClient<Option>;\n\ttype SessionWithAdditionalFields = InferSessionFromClient<Option>;\n\tconst $signal = atom<boolean>(false);\n\tconst session = useAuthQuery<{\n\t\tuser: Prettify<UserWithAdditionalFields>;\n\t\tsession: Prettify<SessionWithAdditionalFields>;\n\t}>($signal, \"/get-session\", $fetch, {\n\t\tmethod: \"GET\",\n\t});\n\treturn {\n\t\t$session: session,\n\t\t_sessionSignal: $signal,\n\t\t$Infer: {} as {\n\t\t\tSession: {\n\t\t\t\tsession: SessionWithAdditionalFields;\n\t\t\t\tuser: UserWithAdditionalFields;\n\t\t\t};\n\t\t},\n\t};\n}\n"],"mappings":"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","names":["createFetch","redirectPlugin","context","addCurrentURL","url","getClientConfig","options","isCredentialsSupported","baseURL","getBaseURL","$fetch","createFetch","redirectPlugin","addCurrentURL","pl","plugin","plugins","pluginsActions","pluginsAtoms","pluginPathMethods","atomListeners","path","getMethod","path","knownPathMethods","args","method","fetchOptions","query","body","createDynamicPathProxy","routes","client","atoms","atomListeners","createProxy","target","prop","fullPath","current","segment","_","__","routePath","letter","arg","argFetchOptions","options","context","matches","s","signal","val","atom","onMount","useAuthQuery","initializedAtom","path","$fetch","options","value","fn","opts","context","currentValue","isMounted","initAtom","atom","getSessionAtom","$fetch","$signal","atom","useAuthQuery"]}