better-auth 1.0.22-beta.2 → 1.0.22-beta.4

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 (117) hide show
  1. package/dist/adapters/drizzle.d.cts +1 -1
  2. package/dist/adapters/drizzle.d.ts +1 -1
  3. package/dist/adapters/kysely.d.cts +1 -1
  4. package/dist/adapters/kysely.d.ts +1 -1
  5. package/dist/adapters/memory.d.cts +1 -1
  6. package/dist/adapters/memory.d.ts +1 -1
  7. package/dist/adapters/mongodb.d.cts +1 -1
  8. package/dist/adapters/mongodb.d.ts +1 -1
  9. package/dist/adapters/prisma.d.cts +1 -1
  10. package/dist/adapters/prisma.d.ts +1 -1
  11. package/dist/api.cjs +4 -4
  12. package/dist/api.d.cts +1 -1
  13. package/dist/api.d.ts +1 -1
  14. package/dist/api.js +4 -4
  15. package/dist/{auth-B_LFm6_Y.d.ts → auth-5DAdlxmK.d.ts} +5 -1
  16. package/dist/{auth-DCr9mzAB.d.cts → auth-CqgjEQ5z.d.cts} +5 -1
  17. package/dist/client/plugins.d.cts +1 -1
  18. package/dist/client/plugins.d.ts +1 -1
  19. package/dist/client.d.cts +1 -1
  20. package/dist/client.d.ts +1 -1
  21. package/dist/cookies.cjs +1 -1
  22. package/dist/cookies.d.cts +1 -1
  23. package/dist/cookies.d.ts +1 -1
  24. package/dist/cookies.js +1 -1
  25. package/dist/db.d.cts +2 -2
  26. package/dist/db.d.ts +2 -2
  27. package/dist/index.cjs +4 -4
  28. package/dist/index.d.cts +2 -2
  29. package/dist/index.d.ts +2 -2
  30. package/dist/index.js +4 -4
  31. package/dist/next-js.cjs +1 -1
  32. package/dist/next-js.d.cts +1 -1
  33. package/dist/next-js.d.ts +1 -1
  34. package/dist/next-js.js +1 -1
  35. package/dist/node.d.cts +1 -1
  36. package/dist/node.d.ts +1 -1
  37. package/dist/oauth2.d.cts +2 -2
  38. package/dist/oauth2.d.ts +2 -2
  39. package/dist/plugin/custom-session.cjs +4 -4
  40. package/dist/plugin/custom-session.d.cts +1 -1
  41. package/dist/plugin/custom-session.d.ts +1 -1
  42. package/dist/plugin/custom-session.js +4 -4
  43. package/dist/plugins/admin.cjs +4 -4
  44. package/dist/plugins/admin.d.cts +1 -1
  45. package/dist/plugins/admin.d.ts +1 -1
  46. package/dist/plugins/admin.js +4 -4
  47. package/dist/plugins/anonymous.cjs +4 -4
  48. package/dist/plugins/anonymous.d.cts +1 -1
  49. package/dist/plugins/anonymous.d.ts +1 -1
  50. package/dist/plugins/anonymous.js +4 -4
  51. package/dist/plugins/bearer.cjs +4 -4
  52. package/dist/plugins/bearer.d.cts +1 -1
  53. package/dist/plugins/bearer.d.ts +1 -1
  54. package/dist/plugins/bearer.js +4 -4
  55. package/dist/plugins/email-otp.cjs +4 -4
  56. package/dist/plugins/email-otp.d.cts +9 -1
  57. package/dist/plugins/email-otp.d.ts +9 -1
  58. package/dist/plugins/email-otp.js +4 -4
  59. package/dist/plugins/generic-oauth.cjs +4 -4
  60. package/dist/plugins/generic-oauth.d.cts +1 -1
  61. package/dist/plugins/generic-oauth.d.ts +1 -1
  62. package/dist/plugins/generic-oauth.js +4 -4
  63. package/dist/plugins/jwt.cjs +4 -4
  64. package/dist/plugins/jwt.d.cts +1 -1
  65. package/dist/plugins/jwt.d.ts +1 -1
  66. package/dist/plugins/jwt.js +4 -4
  67. package/dist/plugins/magic-link.cjs +1 -1
  68. package/dist/plugins/magic-link.js +1 -1
  69. package/dist/plugins/multi-session.cjs +4 -4
  70. package/dist/plugins/multi-session.d.cts +1 -1
  71. package/dist/plugins/multi-session.d.ts +1 -1
  72. package/dist/plugins/multi-session.js +4 -4
  73. package/dist/plugins/one-tap.cjs +4 -4
  74. package/dist/plugins/one-tap.js +4 -4
  75. package/dist/plugins/open-api.cjs +7 -7
  76. package/dist/plugins/open-api.js +7 -7
  77. package/dist/plugins/organization.cjs +4 -4
  78. package/dist/plugins/organization.js +4 -4
  79. package/dist/plugins/passkey.cjs +4 -4
  80. package/dist/plugins/passkey.d.cts +1 -1
  81. package/dist/plugins/passkey.d.ts +1 -1
  82. package/dist/plugins/passkey.js +4 -4
  83. package/dist/plugins/phone-number.cjs +4 -4
  84. package/dist/plugins/phone-number.d.cts +1 -1
  85. package/dist/plugins/phone-number.d.ts +1 -1
  86. package/dist/plugins/phone-number.js +4 -4
  87. package/dist/plugins/two-factor.cjs +4 -4
  88. package/dist/plugins/two-factor.d.cts +1 -1
  89. package/dist/plugins/two-factor.d.ts +1 -1
  90. package/dist/plugins/two-factor.js +4 -4
  91. package/dist/plugins/username.cjs +4 -4
  92. package/dist/plugins/username.d.cts +1 -1
  93. package/dist/plugins/username.d.ts +1 -1
  94. package/dist/plugins/username.js +4 -4
  95. package/dist/plugins.cjs +7 -7
  96. package/dist/plugins.d.cts +2 -2
  97. package/dist/plugins.d.ts +2 -2
  98. package/dist/plugins.js +7 -7
  99. package/dist/react.d.cts +1 -1
  100. package/dist/react.d.ts +1 -1
  101. package/dist/social.cjs +1 -1
  102. package/dist/social.js +1 -1
  103. package/dist/solid-start.d.cts +1 -1
  104. package/dist/solid-start.d.ts +1 -1
  105. package/dist/solid.d.cts +1 -1
  106. package/dist/solid.d.ts +1 -1
  107. package/dist/{state-BMhSL6qk.d.cts → state-D0kKjicr.d.cts} +1 -1
  108. package/dist/{state-DEA00tVL.d.ts → state-y6QaYxkU.d.ts} +1 -1
  109. package/dist/svelte-kit.d.cts +1 -1
  110. package/dist/svelte-kit.d.ts +1 -1
  111. package/dist/svelte.d.cts +1 -1
  112. package/dist/svelte.d.ts +1 -1
  113. package/dist/types.d.cts +2 -2
  114. package/dist/types.d.ts +2 -2
  115. package/dist/vue.d.cts +1 -1
  116. package/dist/vue.d.ts +1 -1
  117. package/package.json +1 -1
package/dist/api.js CHANGED
@@ -1,6 +1,6 @@
1
- import{APIError as H,createRouter as xr,getCookie as Ir,getSignedCookie as Lr,setCookie as Pr,setSignedCookie as Dr}from"better-call";import{APIError as vt}from"better-call";import{createEndpointCreator as Ut,createMiddleware as ge,createMiddlewareCreator as _t}from"better-call";var he=ge(async()=>({})),Z=_t({use:[he,ge(async()=>({}))]}),h=Ut({use:[he]});function le(e){return e==="-"||e==="^"||e==="$"||e==="+"||e==="."||e==="("||e===")"||e==="|"||e==="["||e==="]"||e==="{"||e==="}"||e==="*"||e==="?"||e==="\\"?`\\${e}`:e}function Tt(e){let t="";for(let r=0;r<e.length;r++)t+=le(e[r]);return t}function we(e,t=!0){if(Array.isArray(e))return`(?:${e.map(u=>`^${we(u,t)}$`).join("|")})`;let r="",o="",n=".";t===!0?(r="/",o="[/\\\\]",n="[^/\\\\]"):t&&(r=t,o=Tt(r),o.length>1?(o=`(?:${o})`,n=`((?!${o}).)`):n=`[^${o}]`);let i=t?`${o}+?`:"",s=t?`${o}*?`:"",c=t?e.split(r):[e],a="";for(let d=0;d<c.length;d++){let u=c[d],f=c[d+1],g="";if(!(!u&&d>0)){if(t&&(d===c.length-1?g=s:f!=="**"?g=i:g=""),t&&u==="**"){g&&(a+=d===0?"":g,a+=`(?:${n}*?${g})*?`);continue}for(let l=0;l<u.length;l++){let b=u[l];b==="\\"?l<u.length-1&&(a+=le(u[l+1]),l++):b==="?"?a+=n:b==="*"?a+=`${n}*?`:a+=le(b)}a+=g}}return a}function Ot(e,t){if(typeof t!="string")throw new TypeError(`Sample must be a string, but ${typeof t} given`);return e.test(t)}function ee(e,t){if(typeof e!="string"&&!Array.isArray(e))throw new TypeError(`The first argument must be a single pattern string or an array of patterns, but ${typeof e} given`);if((typeof t=="string"||typeof t=="boolean")&&(t={separator:t}),arguments.length===2&&!(typeof t>"u"||typeof t=="object"&&t!==null&&!Array.isArray(t)))throw new TypeError(`The second argument must be an options object or a string/boolean separator, but ${typeof t} given`);if(t=t||{},t.separator==="\\")throw new Error("\\ is not a valid separator because it is used for escaping. Try setting the separator to `true` instead");let r=we(e,t.separator),o=new RegExp(`^${r}$`,t.flags),n=Ot.bind(null,o);return n.options=t,n.pattern=e,n.regexp=o,n}var te=Object.create(null),Q=e=>globalThis.process?.env||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?te:globalThis),ye=new Proxy(te,{get(e,t){return Q()[t]??te[t]},has(e,t){let r=Q();return t in r||t in te},set(e,t,r){let o=Q(!0);return o[t]=r,!0},deleteProperty(e,t){if(!t)return!1;let r=Q(!0);return delete r[t],!0},ownKeys(){let e=Q(!0);return Object.keys(e)}});function St(e){return e?e!=="false":!1}var ue=typeof process<"u"&&process.env&&process.env.NODE_ENV||"";var re=ue==="dev"||ue==="development",be=ue==="test"||St(ye.TEST);var z=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};function Ae(e){try{return new URL(e).origin}catch{return null}}function Re(e){return e.includes("://")?new URL(e).host:e}var ke=Z(async e=>{if(e.request?.method!=="POST")return;let{body:t,query:r,context:o}=e,n=e.headers?.get("origin")||e.headers?.get("referer")||"",i=t?.callbackURL||r?.callbackURL,s=t?.redirectTo,c=r?.currentURL,a=t?.errorCallbackURL,d=t?.newUserCallbackURL,u=o.trustedOrigins,f=e.headers?.has("cookie"),g=(b,_)=>b.startsWith("/")?!1:_.includes("*")?ee(_)(Re(b)):b.startsWith(_),l=(b,_)=>{if(!b)return;if(!u.some(w=>g(b,w)||b?.startsWith("/")&&_!=="origin"&&!b.includes(":")))throw e.context.logger.error(`Invalid ${_}: ${b}`),e.context.logger.info(`If it's a valid URL, please add ${b} to trustedOrigins in your auth config
2
- `,`Current list of trustedOrigins: ${u}`),new vt("FORBIDDEN",{message:`Invalid ${_}`})};f&&!e.context.options.advanced?.disableCSRFCheck&&l(n,"origin"),i&&l(i,"callbackURL"),s&&l(s,"redirectURL"),c&&l(c,"currentURL"),a&&l(a,"errorCallbackURL"),d&&l(s,"newUserCallbackURL")});import{APIError as S}from"better-call";import{z as U}from"zod";import{TimeSpan as no}from"oslo";import{base64url as Pt}from"oslo/encoding";import{HMAC as Ee,sha256 as Yr}from"oslo/crypto";async function It({value:e,secret:t}){return new Ee("SHA-256").sign(new TextEncoder().encode(t),new TextEncoder().encode(e)).then(o=>Buffer.from(o).toString("base64"))}function Lt({value:e,signature:t,secret:r}){return new Ee("SHA-256").verify(new TextEncoder().encode(r),Buffer.from(t,"base64"),new TextEncoder().encode(e))}var oe={sign:It,verify:Lt};var q=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));async function v(e,t,r,o){let n=e.context.authCookies.sessionToken.options,i=r?void 0:e.context.sessionConfig.expiresIn;if(await e.setSignedCookie(e.context.authCookies.sessionToken.name,t.session.token,e.context.secret,{...n,maxAge:i,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options),e.context.options.session?.cookieCache?.enabled){let c=Pt.encode(new TextEncoder().encode(JSON.stringify({session:t,expiresAt:q(e.context.authCookies.sessionData.options.maxAge||60,"sec").getTime(),signature:await oe.sign({value:JSON.stringify(t),secret:e.context.secret})})),{includePadding:!1});if(c.length>4093)throw new z("Session data is too large to store in the cookie. Please disable session cookie caching or reduce the size of the session data");e.setCookie(e.context.authCookies.sessionData.name,c,e.context.authCookies.sessionData.options)}e.context.setNewSession(t),e.context.options.secondaryStorage&&await e.context.secondaryStorage?.set(t.session.token,JSON.stringify({user:t.user,session:t.session}),Math.floor((new Date(t.session.expiresAt).getTime()-Date.now())/1e3))}function N(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{...e.context.authCookies.sessionToken.options,maxAge:0}),e.setCookie(e.context.authCookies.sessionData.name,"",{...e.context.authCookies.sessionData.options,maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{...e.context.authCookies.dontRememberToken.options,maxAge:0})}import{betterFetch as Bt}from"@better-fetch/fetch";import{APIError as $t}from"better-call";import{decodeProtectedHeader as zt,importJWK as qt,jwtVerify as Ft}from"jose";import{parseJWT as Mt}from"oslo/jwt";import{sha256 as Dt}from"oslo/crypto";import{base64url as Ct}from"oslo/encoding";async function Ue(e){let t=await Dt(new TextEncoder().encode(e));return Ct.encode(new Uint8Array(t),{includePadding:!1})}function ie(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_in?q(e.expires_in,"sec"):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function E({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:s,redirectURI:c,duration:a}){let d=new URL(r);if(d.searchParams.set("response_type","code"),d.searchParams.set("client_id",t.clientId),d.searchParams.set("state",o),d.searchParams.set("scope",i.join(" ")),d.searchParams.set("redirect_uri",t.redirectURI||c),n){let u=await Ue(n);d.searchParams.set("code_challenge_method","S256"),d.searchParams.set("code_challenge",u)}if(s){let u=s.reduce((f,g)=>(f[g]=null,f),{});d.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...u}}))}return a&&d.searchParams.set("duration",a),d}import{betterFetch as Nt}from"@better-fetch/fetch";async function k({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n,authentication:i}){let s=new URLSearchParams,c={"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"};if(s.set("grant_type","authorization_code"),s.set("code",e),t&&s.set("code_verifier",t),s.set("redirect_uri",r),i==="basic"){let f=btoa(`${o.clientId}:${o.clientSecret}`);c.authorization=`Basic ${f}`}else s.set("client_id",o.clientId),s.set("client_secret",o.clientSecret);let{data:a,error:d}=await Nt(n,{method:"POST",body:s,headers:c});if(d)throw d;return ie(a)}import{generateCodeVerifier as jt,generateState as Vt}from"oslo/oauth2";import{z as V}from"zod";import{APIError as _e}from"better-call";async function ne(e,t){let r=e.body?.callbackURL||(e.query?.currentURL?Ae(e.query?.currentURL):"")||e.context.options.baseURL;if(!r)throw new _e("BAD_REQUEST",{message:"callbackURL is required"});let o=jt(),n=Vt(),i=JSON.stringify({callbackURL:r,codeVerifier:o,errorURL:e.body?.errorCallbackURL||e.query?.currentURL,newUserURL:e.body?.newUserCallbackURL,link:t,expiresAt:Date.now()+10*60*1e3}),s=new Date;s.setMinutes(s.getMinutes()+10);let c=await e.context.internalAdapter.createVerificationValue({value:i,identifier:n,expiresAt:s});if(!c)throw e.context.logger.error("Unable to create verification. Make sure the database adapter is properly working and there is a verification table in the database"),new _e("INTERNAL_SERVER_ERROR",{message:"Unable to create verification"});return{state:c.identifier,codeVerifier:o}}async function Te(e){let t=e.query.state||e.body.state,r=await e.context.internalAdapter.findVerificationValue(t);if(!r)throw e.context.logger.error("State Mismatch. Verification not found",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let o=V.object({callbackURL:V.string(),codeVerifier:V.string(),errorURL:V.string().optional(),newUserURL:V.string().optional(),expiresAt:V.number(),link:V.object({email:V.string(),userId:V.string()}).optional()}).parse(JSON.parse(r.value));if(o.errorURL||(o.errorURL=`${e.context.baseURL}/error`),o.expiresAt<Date.now())throw await e.context.internalAdapter.deleteVerificationValue(r.id),e.context.logger.error("State expired.",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);return await e.context.internalAdapter.deleteVerificationValue(r.id),o}var Oe=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=o||["email","name"];return e.scope&&i.push(...e.scope),new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${i.join(" ")}&state=${r}&response_mode=form_post`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>k({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async verifyIdToken(r,o){if(e.disableIdTokenSignIn)return!1;if(e.verifyIdToken)return e.verifyIdToken(r,o);let n=zt(r),{kid:i,alg:s}=n;if(!i||!s)return!1;let c=await Ht(i),{payload:a}=await Ft(r,c,{algorithms:[s],issuer:"https://appleid.apple.com",audience:e.clientId,maxTokenAge:"1h"});return["email_verified","is_private_email"].forEach(d=>{a[d]!==void 0&&(a[d]=!!a[d])}),o&&a.nonce!==o?!1:!!a},async getUserInfo(r){if(e.getUserInfo)return e.getUserInfo(r);if(!r.idToken)return null;let o=Mt(r.idToken)?.payload;if(!o)return null;let n=o.user?`${o.user.name.firstName} ${o.user.name.lastName}`:o.email,i=await e.mapProfileToUser?.(o);return{user:{id:o.sub,name:n,emailVerified:!1,email:o.email,...i},data:o}}}},Ht=async e=>{let t="https://appleid.apple.com",r="/auth/keys",{data:o}=await Bt(`${t}${r}`);if(!o?.keys)throw new $t("BAD_REQUEST",{message:"Keys not found"});let n=o.keys.find(i=>i.kid===e);if(!n)throw new Error(`JWK with kid ${e} not found`);return await qt(n,n.alg)};import{betterFetch as Gt}from"@better-fetch/fetch";var Se=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["identify","email"];return e.scope&&n.push(...e.scope),new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}&prompt=${e.prompt||"none"}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>k({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await Gt("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let i=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${i}.png`}else{let i=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${i}`}let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url,...n},data:r}}});import{betterFetch as Wt}from"@better-fetch/fetch";var ve=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["email","public_profile"];return e.scope&&n.push(...e.scope),await E({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>k({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await Wt("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.name,email:r.email,image:r.picture.data.url,emailVerified:r.email_verified,...n},data:r}}});import{betterFetch as xe}from"@better-fetch/fetch";var Ie=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"GitHub",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let s=o||["user:email"];return e.scope&&s.push(...e.scope),E({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:s,state:r,redirectURI:i})},validateAuthorizationCode:async({code:r,redirectURI:o})=>k({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){if(e.getUserInfo)return e.getUserInfo(r);let{data:o,error:n}=await xe("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:c,error:a}=await xe("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});a||(o.email=(c.find(d=>d.primary)??c[0])?.email,i=c.find(d=>d.email===o.email)?.verified??!1)}let s=await e.mapProfileToUser?.(o);return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i,...s},data:o}}}};import{parseJWT as Yt}from"oslo/jwt";import{createConsola as Zt}from"consola";var pe=["info","success","warn","error","debug"];function Qt(e,t){return pe.indexOf(t)<=pe.indexOf(e)}var Kt=Zt({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),Jt=e=>{let t=e?.disabled!==!0,r=e?.level??"error",o=(n,i,s=[])=>{if(!(!t||!Qt(r,n))){if(!e||typeof e.log!="function"){Kt[n]("",i,...s);return}e.log(n==="success"?"info":n,i,s)}};return Object.fromEntries(pe.map(n=>[n,(...[i,...s])=>o(n,i,s)]))},L=Jt();import{betterFetch as Xt}from"@better-fetch/fetch";var Le=e=>({id:"google",name:"Google",async createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw L.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new z("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new z("codeVerifier is required for Google");let i=r||["email","profile","openid"];e.scope&&i.push(...e.scope);let s=await E({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n});return e.accessType&&s.searchParams.set("access_type",e.accessType),e.prompt&&s.searchParams.set("prompt",e.prompt),s},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>k({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async verifyIdToken(t,r){if(e.disableIdTokenSignIn)return!1;if(e.verifyIdToken)return e.verifyIdToken(t,r);let o=`https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=${t}`,{data:n}=await Xt(o);return n?n.aud===e.clientId&&n.iss==="https://accounts.google.com":!1},async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);if(!t.idToken)return null;let r=Yt(t.idToken)?.payload,o=await e.mapProfileToUser?.(r);return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified,...o},data:r}}});import{betterFetch as er}from"@better-fetch/fetch";import{parseJWT as tr}from"oslo/jwt";var Pe=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=n.scopes||["openid","profile","email","User.Read"];return e.scope&&i.push(...e.scope),E({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:s}){return k({code:n,codeVerifier:i,redirectURI:e.redirectURI||s,options:e,tokenEndpoint:o})},async getUserInfo(n){if(e.getUserInfo)return e.getUserInfo(n);if(!n.idToken)return null;let i=tr(n.idToken)?.payload,s=e.profilePhotoSize||48;await er(`https://graph.microsoft.com/v1.0/me/photos/${s}x${s}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(a){if(!(e.disableProfilePhoto||!a.response.ok))try{let u=await a.response.clone().arrayBuffer(),f=Buffer.from(u).toString("base64");i.picture=`data:image/jpeg;base64, ${f}`}catch(d){L.error(d&&typeof d=="object"&&"name"in d?d.name:"",d)}}});let c=await e.mapProfileToUser?.(i);return{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0,...c},data:i}}}};import{betterFetch as rr}from"@better-fetch/fetch";var De=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=r||["user-read-email"];return e.scope&&i.push(...e.scope),E({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>k({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await rr("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1,...n},data:r}}});var G={isAction:!1};import{nanoid as or}from"nanoid";var Ce=e=>or(e);import{parseJWT as ir}from"oslo/jwt";var Ne=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["user:read:email","openid"];return e.scope&&n.push(...e.scope),E({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>k({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let r=t.idToken;if(!r)return L.error("No idToken found in token"),null;let o=ir(r)?.payload,n=await e.mapProfileToUser?.(o);return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1,...n},data:o}}});import{betterFetch as nr}from"@better-fetch/fetch";var je=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=t.scopes||["users.read","tweet.read","offline.access"];return e.scope&&r.push(...e.scope),E({id:"twitter",options:e,authorizationEndpoint:"https://x.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>k({code:t,codeVerifier:r,authentication:"basic",redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://api.x.com/2/oauth2/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await nr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.data.id,name:r.data.name,email:r.data.username||null,image:r.data.profile_image_url,emailVerified:r.data.verified||!1,...n},data:r}}});import{betterFetch as sr}from"@better-fetch/fetch";var Ve=e=>{let t="https://api.dropboxapi.com/oauth2/token";return{id:"dropbox",name:"Dropbox",createAuthorizationURL:async({state:r,scopes:o,codeVerifier:n,redirectURI:i})=>{let s=o||["account_info.read"];return e.scope&&s.push(...e.scope),await E({id:"dropbox",options:e,authorizationEndpoint:"https://www.dropbox.com/oauth2/authorize",scopes:s,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>await k({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(e.getUserInfo)return e.getUserInfo(r);let{data:o,error:n}=await sr("https://api.dropboxapi.com/2/users/get_current_account",{method:"POST",headers:{Authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=await e.mapProfileToUser?.(o);return{user:{id:o.account_id,name:o.name?.display_name,email:o.email,emailVerified:o.email_verified||!1,image:o.profile_photo_url,...i},data:o}}}};import{betterFetch as ar}from"@better-fetch/fetch";var Be=e=>{let t="https://www.linkedin.com/oauth/v2/authorization",r="https://www.linkedin.com/oauth/v2/accessToken";return{id:"linkedin",name:"Linkedin",createAuthorizationURL:async({state:o,scopes:n,redirectURI:i})=>{let s=n||["profile","email","openid"];return e.scope&&s.push(...e.scope),await E({id:"linkedin",options:e,authorizationEndpoint:t,scopes:s,state:o,redirectURI:i})},validateAuthorizationCode:async({code:o,redirectURI:n})=>await k({code:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:r}),async getUserInfo(o){let{data:n,error:i}=await ar("https://api.linkedin.com/v2/userinfo",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken}`}});if(i)return null;let s=await e.mapProfileToUser?.(n);return{user:{id:n.sub,name:n.name,email:n.email,emailVerified:n.email_verified||!1,image:n.picture,...s},data:n}}}};import{betterFetch as cr}from"@better-fetch/fetch";var me=(e="")=>e.split("://").map(t=>t.replace(/\/{2,}/g,"/")).join("://"),dr=e=>{let t=e||"https://gitlab.com";return{authorizationEndpoint:me(`${t}/oauth/authorize`),tokenEndpoint:me(`${t}/oauth/token`),userinfoEndpoint:me(`${t}/api/v4/user`)}},$e=e=>{let{authorizationEndpoint:t,tokenEndpoint:r,userinfoEndpoint:o}=dr(e.issuer),n="gitlab";return{id:n,name:"Gitlab",createAuthorizationURL:async({state:s,scopes:c,codeVerifier:a,redirectURI:d})=>{let u=c||["read_user"];return e.scope&&u.push(...e.scope),await E({id:n,options:e,authorizationEndpoint:t,scopes:u,state:s,redirectURI:d,codeVerifier:a})},validateAuthorizationCode:async({code:s,redirectURI:c,codeVerifier:a})=>k({code:s,redirectURI:e.redirectURI||c,options:e,codeVerifier:a,tokenEndpoint:r}),async getUserInfo(s){if(e.getUserInfo)return e.getUserInfo(s);let{data:c,error:a}=await cr(o,{headers:{authorization:`Bearer ${s.accessToken}`}});if(a||c.state!=="active"||c.locked)return null;let d=await e.mapProfileToUser?.(c);return{user:{id:c.id.toString(),name:c.name??c.username,email:c.email,image:c.avatar_url,emailVerified:!0,...d},data:c}}}};import{betterFetch as ze}from"@better-fetch/fetch";var qe=e=>({id:"reddit",name:"Reddit",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["identity"];return e.scope&&n.push(...e.scope),E({id:"reddit",options:e,authorizationEndpoint:"https://www.reddit.com/api/v1/authorize",scopes:n,state:t,redirectURI:o,duration:e.duration})},validateAuthorizationCode:async({code:t,redirectURI:r})=>{let o=new URLSearchParams({grant_type:"authorization_code",code:t,redirect_uri:e.redirectURI||r}),n={"content-type":"application/x-www-form-urlencoded",accept:"text/plain","user-agent":"better-auth",Authorization:`Basic ${Buffer.from(`${e.clientId}:${e.clientSecret}`).toString("base64")}`},{data:i,error:s}=await ze("https://www.reddit.com/api/v1/access_token",{method:"POST",headers:n,body:o.toString()});if(s)throw s;return ie(i)},async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await ze("https://oauth.reddit.com/api/v1/me",{headers:{Authorization:`Bearer ${t.accessToken}`,"User-Agent":"better-auth"}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.name,email:r.oauth_client_id,emailVerified:r.has_verified_email,image:r.icon_img?.split("?")[0],...n},data:r}}});var lr={apple:Oe,discord:Se,facebook:ve,github:Ie,microsoft:Pe,google:Le,spotify:De,twitch:Ne,twitter:je,dropbox:Ve,linkedin:Be,gitlab:$e,reddit:qe},se=Object.keys(lr);import{TimeSpan as ur}from"oslo";import{createJWT as pr,validateJWT as mr}from"oslo/jwt";import{z as C}from"zod";import{APIError as K}from"better-call";import{APIError as B}from"better-call";import{z as F}from"zod";function Fe(e){try{return JSON.parse(e)}catch{return null}}var p={USER_NOT_FOUND:"User not found",FAILED_TO_CREATE_USER:"Failed to create user",FAILED_TO_CREATE_SESSION:"Failed to create session",FAILED_TO_UPDATE_USER:"Failed to update user",FAILED_TO_GET_SESSION:"Failed to get session",INVALID_PASSWORD:"Invalid password",INVALID_EMAIL:"Invalid email",INVALID_EMAIL_OR_PASSWORD:"Invalid email or password",SOCIAL_ACCOUNT_ALREADY_LINKED:"Social account already linked",PROVIDER_NOT_FOUND:"Provider not found",INVALID_TOKEN:"invalid token",ID_TOKEN_NOT_SUPPORTED:"id_token not supported",FAILED_TO_GET_USER_INFO:"Failed to get user info",USER_EMAIL_NOT_FOUND:"User email not found",EMAIL_NOT_VERIFIED:"Email not verified",PASSWORD_TOO_SHORT:"Password too short",PASSWORD_TOO_LONG:"Password too long",USER_ALREADY_EXISTS:"User already exists",EMAIL_CAN_NOT_BE_UPDATED:"Email can not be updated",CREDENTIAL_ACCOUNT_NOT_FOUND:"Credential account not found"};var fe=()=>h("/get-session",{method:"GET",query:F.optional(F.object({disableCookieCache:F.boolean({description:"Disable cookie cache and fetch session from database"}).or(F.string().transform(e=>e==="true")).optional(),disableRefresh:F.boolean({description:"Disable session refresh. Useful for checking session status, without updating the session"}).optional()})),requireHeaders:!0,metadata:{openapi:{description:"Get the current session",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{session:{type:"object",properties:{token:{type:"string"},userId:{type:"string"},expiresAt:{type:"string"}}},user:{type:"object",$ref:"#/components/schemas/User"}}}}}}}}}},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null);let r=e.getCookie(e.context.authCookies.sessionData.name),o=r?Fe(Buffer.from(r,"base64").toString()):null;if(o&&!await oe.verify({value:JSON.stringify(o.session),signature:o?.signature,secret:e.context.secret}))return N(e),e.json(null);let n=await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret);if(o?.session&&e.context.options.session?.cookieCache?.enabled&&!e.query?.disableCookieCache){let u=o.session;if(o.expiresAt<Date.now()||u.session.expiresAt<new Date){let g=e.context.authCookies.sessionData.name;e.setCookie(g,"",{maxAge:0})}else return e.json(u)}let i=await e.context.internalAdapter.findSession(t);if(e.context.session=i,!i||i.session.expiresAt<new Date)return N(e),i&&await e.context.internalAdapter.deleteSession(i.session.token),e.json(null);if(n||e.query?.disableRefresh)return e.json(i);let s=e.context.sessionConfig.expiresIn,c=e.context.sessionConfig.updateAge;if(i.session.expiresAt.valueOf()-s*1e3+c*1e3<=Date.now()){let u=await e.context.internalAdapter.updateSession(i.session.token,{expiresAt:q(e.context.sessionConfig.expiresIn,"sec")});if(!u)return N(e),e.json(null,{status:401});let f=(u.expiresAt.valueOf()-Date.now())/1e3;return await v(e,{session:u,user:i.user},!1,{maxAge:f}),e.json({session:u,user:i.user})}return e.json(i)}catch(t){throw e.context.logger.error("INTERNAL_SERVER_ERROR",t),new B("INTERNAL_SERVER_ERROR",{message:p.FAILED_TO_GET_SESSION})}}),M=async(e,t)=>{if(e.context.session)return e.context.session;let r=await fe()({...e,_flag:"json",headers:e.headers,query:t}).catch(o=>null);return e.context.session=r,r},P=Z(async e=>{let t=await M(e);if(!t?.session)throw new B("UNAUTHORIZED");return{session:t}}),Me=Z(async e=>{let t=await M(e);if(!t?.session)throw new B("UNAUTHORIZED");if(e.context.sessionConfig.freshAge===0)return{session:t};let r=e.context.sessionConfig.freshAge,o=t.session.updatedAt?.valueOf()||t.session.createdAt.valueOf();if(!(Date.now()-o<r*1e3))throw new B("FORBIDDEN",{message:"Session is not fresh"});return{session:t}}),He=()=>h("/list-sessions",{method:"GET",use:[P],requireHeaders:!0,metadata:{openapi:{description:"List all active sessions for the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"array",items:{type:"object",properties:{token:{type:"string"},userId:{type:"string"},expiresAt:{type:"string"}}}}}}}}}}},async e=>{let r=(await e.context.internalAdapter.listSessions(e.context.session.user.id)).filter(o=>o.expiresAt>new Date);return e.json(r)}),Ge=h("/revoke-session",{method:"POST",body:F.object({token:F.string({description:"The token to revoke"})}),use:[P],requireHeaders:!0,metadata:{openapi:{description:"Revoke a single session",requestBody:{content:{"application/json":{schema:{type:"object",properties:{token:{type:"string"}},required:["token"]}}}}}}},async e=>{let t=e.body.token,r=await e.context.internalAdapter.findSession(t);if(!r)throw new B("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new B("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o&&typeof o=="object"&&"name"in o?o.name:"",o),new B("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),We=h("/revoke-sessions",{method:"POST",use:[P],requireHeaders:!0,metadata:{openapi:{description:"Revoke all sessions for the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}},required:["status"]}}}}}}}},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t&&typeof t=="object"&&"name"in t?t.name:"",t),new B("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Ze=h("/revoke-other-sessions",{method:"POST",requireHeaders:!0,use:[P],metadata:{openapi:{description:"Revoke all other sessions for the user except the current one",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},async e=>{let t=e.context.session;if(!t.user)throw new B("UNAUTHORIZED");let n=(await e.context.internalAdapter.listSessions(t.user.id)).filter(i=>i.expiresAt>new Date).filter(i=>i.token!==e.context.session.session.token);return await Promise.all(n.map(i=>e.context.internalAdapter.deleteSession(i.token))),e.json({status:!0})});async function j(e,t,r){return await pr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new ur(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}async function fr(e,t){if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new K("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await j(e.context.secret,t.email),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification.sendVerificationEmail({user:t,url:o,token:r},e.request)}var Qe=h("/send-verification-email",{method:"POST",query:C.object({currentURL:C.string({description:"The URL to use for email verification callback"}).optional()}).optional(),body:C.object({email:C.string({description:"The email to send the verification email to"}).email(),callbackURL:C.string({description:"The URL to use for email verification callback"}).optional()}),metadata:{openapi:{description:"Send a verification email to the user",requestBody:{content:{"application/json":{schema:{type:"object",properties:{email:{type:"string",description:"The email to send the verification email to"},callbackURL:{type:"string",description:"The URL to use for email verification callback"}},required:["email"]}}}},responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new K("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new K("BAD_REQUEST",{message:p.USER_NOT_FOUND});return await fr(e,r.user),e.json({status:!0})}),Ke=h("/verify-email",{method:"GET",query:C.object({token:C.string({description:"The token to verify the email"}),callbackURL:C.string({description:"The URL to redirect to after email verification"}).optional()}),metadata:{openapi:{description:"Verify the email of the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"},status:{type:"boolean"}},required:["user","status"]}}}}}}}},async e=>{function t(c){throw e.query.callbackURL?e.query.callbackURL.includes("?")?e.redirect(`${e.query.callbackURL}&error=${c}`):e.redirect(`${e.query.callbackURL}?error=${c}`):new K("UNAUTHORIZED",{message:c})}let{token:r}=e.query,o;try{o=await mr("HS256",Buffer.from(e.context.secret),r)}catch(c){return e.context.logger.error("Failed to verify email",c),t("invalid_token")}let i=C.object({email:C.string().email(),updateTo:C.string().optional()}).parse(o.payload),s=await e.context.internalAdapter.findUserByEmail(i.email);if(!s)return t("user_not_found");if(i.updateTo){let c=await M(e);if(!c){if(e.query.callbackURL)throw e.redirect(`${e.query.callbackURL}?error=unauthorized`);return t("unauthorized")}if(c.user.email!==i.email){if(e.query.callbackURL)throw e.redirect(`${e.query.callbackURL}?error=unauthorized`);return t("unauthorized")}let a=await e.context.internalAdapter.updateUserByEmail(i.email,{email:i.updateTo,emailVerified:!1}),d=await j(e.context.secret,i.updateTo);if(await e.context.options.emailVerification?.sendVerificationEmail?.({user:a,url:`${e.context.baseURL}/verify-email?token=${d}`,token:d},e.request),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:a,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(i.email,{emailVerified:!0}),e.context.options.emailVerification?.autoSignInAfterVerification&&!await M(e)){let a=await e.context.internalAdapter.createSession(s.user.id,e.request);if(!a)throw new K("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});await v(e,{session:a,user:s.user})}if(e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});async function ae(e,{userInfo:t,account:r,callbackURL:o}){let n=await e.context.internalAdapter.findUserByEmail(t.email.toLowerCase(),{includeAccounts:!0}).catch(a=>{throw L.error(`Better auth was unable to query your database.
3
- Error: `,a),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),i=n?.user,s=!i;if(n){let a=n.accounts.find(d=>d.providerId===r.providerId);if(a){let d=Object.fromEntries(Object.entries({accessToken:r.accessToken,idToken:r.idToken,refreshToken:r.refreshToken,accessTokenExpiresAt:r.accessTokenExpiresAt,refreshTokenExpiresAt:r.refreshTokenExpiresAt}).filter(([u,f])=>f!==void 0));Object.keys(d).length>0&&await e.context.internalAdapter.updateAccount(a.id,d)}else{if(!e.context.options.account?.accountLinking?.trustedProviders?.includes(r.providerId)&&!t.emailVerified||e.context.options.account?.accountLinking?.enabled===!1)return re&&L.warn(`User already exist but account isn't linked to ${r.providerId}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`),{error:"account not linked",data:null};try{await e.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:t.id.toString(),userId:n.user.id,accessToken:r.accessToken,idToken:r.idToken,refreshToken:r.refreshToken,accessTokenExpiresAt:r.accessTokenExpiresAt,refreshTokenExpiresAt:r.refreshTokenExpiresAt,scope:r.scope})}catch(f){return L.error("Unable to link account",f),{error:"unable to link account",data:null}}i=await e.context.internalAdapter.updateUser(n.user.id,{...t,updatedAt:new Date})}}else if(i=await e.context.internalAdapter.createOAuthUser({...t,email:t.email.toLowerCase(),id:void 0},{accessToken:r.accessToken,idToken:r.idToken,refreshToken:r.refreshToken,accessTokenExpiresAt:r.accessTokenExpiresAt,refreshTokenExpiresAt:r.refreshTokenExpiresAt,scope:r.scope,providerId:r.providerId,accountId:t.id.toString()}).then(a=>a?.user),!t.emailVerified&&i&&e.context.options.emailVerification?.sendOnSignUp){let a=await j(e.context.secret,i.email),d=`${e.context.baseURL}/verify-email?token=${a}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.({user:i,url:d,token:a},e.request)}if(!i)return{error:"unable to create user",data:null,isRegister:!1};let c=await e.context.internalAdapter.createSession(i.id,e.request);return c?{data:{session:c,user:i},error:null,isRegister:s}:{error:"unable to create session",data:null,isRegister:!1}}var Je=h("/sign-in/social",{method:"POST",query:U.object({currentURL:U.string().optional()}).optional(),body:U.object({callbackURL:U.string({description:"Callback URL to redirect to after the user has signed in"}).optional(),newUserCallbackURL:U.string().optional(),errorCallbackURL:U.string({description:"Callback URL to redirect to if an error happens"}).optional(),provider:U.enum(se,{description:"OAuth2 provider to use"}),disableRedirect:U.boolean({description:"Disable automatic redirection to the provider. Useful for handling the redirection yourself"}).optional(),idToken:U.optional(U.object({token:U.string({description:"ID token from the provider"}),nonce:U.string({description:"Nonce used to generate the token"}).optional(),accessToken:U.string({description:"Access token from the provider"}).optional(),refreshToken:U.string({description:"Refresh token from the provider"}).optional(),expiresAt:U.number({description:"Expiry date of the token"}).optional()}),{description:"ID token from the provider to sign in the user with id token"})}),metadata:{openapi:{description:"Sign in with a social provider",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{session:{type:"string"},user:{type:"object"},url:{type:"string"},redirect:{type:"boolean"}},required:["session","user","url","redirect"]}}}}}}}},async e=>{let t=e.context.socialProviders.find(i=>i.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 S("NOT_FOUND",{message:p.PROVIDER_NOT_FOUND});if(e.body.idToken){if(!t.verifyIdToken)throw e.context.logger.error("Provider does not support id token verification",{provider:e.body.provider}),new S("NOT_FOUND",{message:p.ID_TOKEN_NOT_SUPPORTED});let{token:i,nonce:s}=e.body.idToken;if(!await t.verifyIdToken(i,s))throw e.context.logger.error("Invalid id token",{provider:e.body.provider}),new S("UNAUTHORIZED",{message:p.INVALID_TOKEN});let a=await t.getUserInfo({idToken:i,accessToken:e.body.idToken.accessToken,refreshToken:e.body.idToken.refreshToken});if(!a||!a?.user)throw e.context.logger.error("Failed to get user info",{provider:e.body.provider}),new S("UNAUTHORIZED",{message:p.FAILED_TO_GET_USER_INFO});if(!a.user.email)throw e.context.logger.error("User email not found",{provider:e.body.provider}),new S("UNAUTHORIZED",{message:p.USER_EMAIL_NOT_FOUND});let d=await ae(e,{userInfo:{email:a.user.email,id:a.user.id,name:a.user.name||"",image:a.user.image,emailVerified:a.user.emailVerified||!1},account:{providerId:t.id,accountId:a.user.id,accessToken:e.body.idToken.accessToken}});if(d.error)throw new S("UNAUTHORIZED",{message:d.error});return await v(e,d.data),e.json({session:d.data.session,user:d.data.user,url:void 0,redirect:!1})}let{codeVerifier:r,state:o}=await ne(e),n=await t.createAuthorizationURL({state:o,codeVerifier:r,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:n.toString(),redirect:!e.body.disableRedirect})}),Ye=h("/sign-in/email",{method:"POST",body:U.object({email:U.string({description:"Email of the user"}),password:U.string({description:"Password of the user"}),callbackURL:U.string({description:"Callback URL to use as a redirect for email verification"}).optional(),rememberMe:U.boolean({description:"If this is false, the session will not be remembered. Default is `true`."}).default(!0).optional()}),metadata:{openapi:{description:"Sign in with email and password",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"},url:{type:"string"},redirect:{type:"boolean"}},required:["session","user","url","redirect"]}}}}}}}},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 S("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!U.string().email().safeParse(t).success)throw new S("BAD_REQUEST",{message:p.INVALID_EMAIL});let n=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!n)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});let i=n.accounts.find(d=>d.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});let s=i?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});if(!await e.context.password.verify({hash:s,password:r}))throw e.context.logger.error("Invalid password"),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!n.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw new S("UNAUTHORIZED",{message:p.EMAIL_NOT_VERIFIED});let d=await j(e.context.secret,n.user.email),u=`${e.context.baseURL}/verify-email?token=${d}&callbackURL=${e.body.callbackURL||"/"}`;throw await e.context.options.emailVerification.sendVerificationEmail({user:n.user,url:u,token:d},e.request),e.context.logger.error("Email not verified",{email:t}),new S("FORBIDDEN",{message:p.EMAIL_NOT_VERIFIED})}let a=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.rememberMe===!1);if(!a)throw e.context.logger.error("Failed to create session"),new S("UNAUTHORIZED",{message:p.FAILED_TO_CREATE_SESSION});return await v(e,{session:a,user:n.user},e.body.rememberMe===!1),e.json({user:{id:n.user.id,email:n.user.email,name:n.user.name,image:n.user.image,emailVerified:n.user.emailVerified,createdAt:n.user.createdAt,updatedAt:n.user.updatedAt},redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as J}from"zod";var ce=J.object({code:J.string().optional(),error:J.string().optional(),error_description:J.string().optional(),state:J.string().optional()}),Xe=h("/callback/:id",{method:["GET","POST"],body:ce.optional(),query:ce.optional(),metadata:G},async e=>{let t;try{if(e.method==="GET")t=ce.parse(e.query);else if(e.method==="POST")t=ce.parse(e.body);else throw new Error("Unsupported method")}catch(A){throw e.context.logger.error("INVALID_CALLBACK_REQUEST",A),e.redirect(`${e.context.baseURL}/error?error=invalid_callback_request`)}let{code:r,error:o,state:n,error_description:i}=t;if(!n)throw e.context.logger.error("State not found",o),e.redirect(`${e.context.baseURL}/error?error=state_not_found`);if(!r)throw e.context.logger.error("Code not found"),e.redirect(`${e.context.baseURL}/error?error=${o||"no_code"}&error_description=${i}`);let s=e.context.socialProviders.find(A=>A.id===e.params.id);if(!s)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{codeVerifier:c,callbackURL:a,link:d,errorURL:u,newUserURL:f}=await Te(e),g;try{g=await s.validateAuthorizationCode({code:r,codeVerifier:c,redirectURI:`${e.context.baseURL}/callback/${s.id}`})}catch(A){throw e.context.logger.error("",A),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let l=await s.getUserInfo(g).then(A=>A?.user);function b(A){let y=u||a||`${e.context.baseURL}/error`;throw y.includes("?")?y=`${y}&error=${A}`:y=`${y}?error=${A}`,e.redirect(y)}if(!l)return e.context.logger.error("Unable to get user info"),b("unable_to_get_user_info");if(!l.email)return e.context.logger.error("Provider did not return email. This could be due to misconfiguration in the provider settings."),b("email_not_found");if(!a)throw e.context.logger.error("No callback URL found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(d){if(d.email!==l.email.toLowerCase())return b("email_doesn't_match");if(!await e.context.internalAdapter.createAccount({userId:d.userId,providerId:s.id,accountId:l.id}))return b("unable_to_link_account");let y;try{y=a.toString()}catch{y=a}throw e.redirect(y)}let _=await ae(e,{userInfo:{...l,email:l.email,name:l.name||l.email},account:{providerId:s.id,accountId:l.id,...g,scope:g.scopes?.join(",")},callbackURL:a});if(_.error)return e.context.logger.error(_.error.split(" ").join("_")),b(_.error.split(" ").join("_"));let{session:x,user:w}=_.data;await v(e,{session:x,user:w});let R;try{R=(_.isRegister&&f||a).toString()}catch{R=_.isRegister&&f||a}throw e.redirect(R)});import"zod";import{APIError as gr}from"better-call";var et=h("/sign-out",{method:"POST",requireHeaders:!0,metadata:{openapi:{description:"Sign out the current user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean"}}}}}}}}}},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw N(e),new gr("BAD_REQUEST",{message:p.FAILED_TO_GET_SESSION});return await e.context.internalAdapter.deleteSession(t),N(e),e.json({success:!0})});import{z as D}from"zod";import{APIError as Y}from"better-call";function tt(e,t,r){let o=t?new URL(t,e.baseURL):new URL(`${e.baseURL}/error`);return r&&Object.entries(r).forEach(([n,i])=>o.searchParams.set(n,i)),o.href}function hr(e,t,r){let o=new URL(t,e.baseURL);return r&&Object.entries(r).forEach(([n,i])=>o.searchParams.set(n,i)),o.href}var rt=h("/forget-password",{method:"POST",body:D.object({email:D.string({description:"The email address of the user to send a password reset email to"}).email(),redirectTo:D.string({description:"The URL to redirect the user to reset their password. If the token isn't valid or expired, it'll be redirected with a query parameter `?error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?token=VALID_TOKEN"}).optional()}),metadata:{openapi:{description:"Send a password reset email to the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},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 Y("BAD_REQUEST",{message:"Reset password isn't enabled"});let{email:t,redirectTo:r}=e.body,o=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!o)return e.context.logger.error("Reset Password: User not found",{email:t}),e.json({status:!1},{body:{status:!0}});let n=60*60*1,i=q(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n,"sec"),s=Ce(24);await e.context.internalAdapter.createVerificationValue({value:o.user.id.toString(),identifier:`reset-password:${s}`,expiresAt:i});let c=`${e.context.baseURL}/reset-password/${s}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword({user:o.user,url:c,token:s},e.request),e.json({status:!0})}),ot=h("/reset-password/:token",{method:"GET",query:D.object({callbackURL:D.string({description:"The URL to redirect the user to reset their password"})}),metadata:{openapi:{description:"Redirects the user to the callback URL with the token",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{token:{type:"string"}}}}}}}}}},async e=>{let{token:t}=e.params,{callbackURL:r}=e.query;if(!t||!r)throw e.redirect(tt(e.context,r,{error:"INVALID_TOKEN"}));let o=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!o||o.expiresAt<new Date?e.redirect(tt(e.context,r,{error:"INVALID_TOKEN"})):e.redirect(hr(e.context,r,{token:t}))}),it=h("/reset-password",{query:D.optional(D.object({token:D.string().optional(),currentURL:D.string().optional()})),method:"POST",body:D.object({newPassword:D.string({description:"The new password to set"}),token:D.string({description:"The token to reset the password"}).optional()}),metadata:{openapi:{description:"Reset the password for a user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},async e=>{let t=e.body.token||e.query?.token||(e.query?.currentURL?new URL(e.query.currentURL).searchParams.get("token"):"");if(!t)throw new Y("BAD_REQUEST",{message:p.INVALID_TOKEN});let{newPassword:r}=e.body,o=e.context.password?.config.minPasswordLength,n=e.context.password?.config.maxPasswordLength;if(r.length<o)throw new Y("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});if(r.length>n)throw new Y("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});let i=`reset-password:${t}`,s=await e.context.internalAdapter.findVerificationValue(i);if(!s||s.expiresAt<new Date)throw new Y("BAD_REQUEST",{message:p.INVALID_TOKEN});await e.context.internalAdapter.deleteVerificationValue(s.id);let c=s.value,a=await e.context.password.hash(r);return(await e.context.internalAdapter.findAccounts(c)).find(f=>f.providerId==="credential")?(await e.context.internalAdapter.updatePassword(c,a),e.json({status:!0})):(await e.context.internalAdapter.createAccount({userId:c,providerId:"credential",password:a,accountId:c}),e.json({status:!0}))});import{z as O}from"zod";import{APIError as T}from"better-call";import{z as m}from"zod";import{APIError as wr}from"better-call";var bs=m.object({id:m.string(),providerId:m.string(),accountId:m.string(),userId:m.string(),accessToken:m.string().nullish(),refreshToken:m.string().nullish(),idToken:m.string().nullish(),accessTokenExpiresAt:m.date().nullish(),refreshTokenExpiresAt:m.date().nullish(),scope:m.string().nullish(),password:m.string().nullish(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date)}),As=m.object({id:m.string(),email:m.string().transform(e=>e.toLowerCase()),emailVerified:m.boolean().default(!1),name:m.string(),image:m.string().nullish(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date)}),Rs=m.object({id:m.string(),userId:m.string(),expiresAt:m.date(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date),token:m.string(),ipAddress:m.string().nullish(),userAgent:m.string().nullish()}),ks=m.object({id:m.string(),value:m.string(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date),expiresAt:m.date(),identifier:m.string()});function yr(e,t){let r={...t==="user"?e.user?.additionalFields:{},...t==="session"?e.session?.additionalFields:{}};for(let o of e.plugins||[])o.schema&&o.schema[t]&&(r={...r,...o.schema[t].fields});return r}function br(e,t){let r=t.action||"create",o=t.fields,n={};for(let i in o){if(i in e){if(o[i].input===!1){if(o[i].defaultValue){n[i]=o[i].defaultValue;continue}continue}if(o[i].validator?.input&&e[i]!==void 0){n[i]=o[i].validator.input.parse(e[i]);continue}if(o[i].transform?.input&&e[i]!==void 0){n[i]=o[i].transform?.input(e[i]);continue}n[i]=e[i];continue}if(o[i].defaultValue&&r==="create"){n[i]=o[i].defaultValue;continue}if(o[i].required&&r==="create")throw new wr("BAD_REQUEST",{message:`${i} is required`})}return n}function de(e,t,r){let o=yr(e,"user");return br(t||{},{fields:o,action:r})}import{xchacha20poly1305 as Ns}from"@noble/ciphers/chacha";import{bytesToHex as Vs,hexToBytes as Bs,utf8ToBytes as $s}from"@noble/ciphers/utils";import{managedNonce as qs}from"@noble/ciphers/webcrypto";import{sha256 as Ms}from"oslo/crypto";import Gs from"uncrypto";import{decodeHex as _s,encodeHex as Ts}from"oslo/encoding";import{scryptAsync as vs}from"@noble/hashes/scrypt";import{getRandomValues as Is}from"uncrypto";import nt from"uncrypto";function Ar(e){return e.toString(2).padStart(8,"0")}function Rr(e){return[...e].map(t=>Ar(t)).join("")}function st(e){return parseInt(Rr(e),2)}function kr(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));nt.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=st(o);for(;n>=e;)nt.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=st(o);return n}function at(e,t){let r="";for(let o=0;o<e;o++)r+=t[kr(t.length)];return r}function ct(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}var dt=()=>h("/update-user",{method:"POST",body:O.record(O.string(),O.any()),use:[P],metadata:{openapi:{description:"Update the current user",requestBody:{content:{"application/json":{schema:{type:"object",properties:{name:{type:"string",description:"The name of the user"},image:{type:"string",description:"The image of the user"}}}}}},responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"}}}}}}}}}},async e=>{let t=e.body;if(t.email)throw new T("BAD_REQUEST",{message:p.EMAIL_CAN_NOT_BE_UPDATED});let{name:r,image:o,...n}=t,i=e.context.session;if(o===void 0&&r===void 0&&Object.keys(n).length===0)return e.json({id:i.user.id,email:i.user.email,name:i.user.name,image:i.user.image,emailVerified:i.user.emailVerified,createdAt:i.user.createdAt,updatedAt:i.user.updatedAt});let s=de(e.context.options,n,"update"),c=await e.context.internalAdapter.updateUserByEmail(i.user.email,{name:r,image:o,...s});return await v(e,{session:i.session,user:c}),e.json({id:c.id,email:c.email,name:c.name,image:c.image,emailVerified:c.emailVerified,createdAt:c.createdAt,updatedAt:c.updatedAt})}),lt=h("/change-password",{method:"POST",body:O.object({newPassword:O.string({description:"The new password to set"}),currentPassword:O.string({description:"The current password"}),revokeOtherSessions:O.boolean({description:"Revoke all other sessions"}).optional()}),use:[P],metadata:{openapi:{description:"Change the password of the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{description:"The user object",$ref:"#/components/schemas/User"}}}}}}}}}},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,i=e.context.password.config.minPasswordLength;if(t.length<i)throw e.context.logger.error("Password is too short"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});let s=e.context.password.config.maxPasswordLength;if(t.length>s)throw e.context.logger.error("Password is too long"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});let a=(await e.context.internalAdapter.findAccounts(n.user.id)).find(f=>f.providerId==="credential"&&f.password);if(!a||!a.password)throw new T("BAD_REQUEST",{message:p.CREDENTIAL_ACCOUNT_NOT_FOUND});let d=await e.context.password.hash(t);if(!await e.context.password.verify({hash:a.password,password:r}))throw new T("BAD_REQUEST",{message:p.INVALID_PASSWORD});if(await e.context.internalAdapter.updateAccount(a.id,{password:d}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let f=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!f)throw new T("INTERNAL_SERVER_ERROR",{message:p.FAILED_TO_GET_SESSION});await v(e,{session:f,user:n.user})}return e.json(n.user)}),ut=h("/set-password",{method:"POST",body:O.object({newPassword:O.string()}),metadata:{SERVER_ONLY:!0},use:[P]},async e=>{let{newPassword:t}=e.body,r=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)throw e.context.logger.error("Password is too short"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});let s=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password),c=await e.context.password.hash(t);if(!s)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:c}),e.json(r.user);throw new T("BAD_REQUEST",{message:"user already has a password"})}),pt=h("/delete-user",{method:"POST",use:[Me],metadata:{openapi:{description:"Delete the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object"}}}}}}}},async e=>{if(!e.context.options.user?.deleteUser?.enabled)throw e.context.logger.error("Delete user is disabled. Enable it in the options",{session:e.context.session}),new T("NOT_FOUND");let t=e.context.session;if(e.context.options.user.deleteUser?.sendDeleteAccountVerification){let n=at(32,ct("a-z","A-Z","0-9"));await e.context.internalAdapter.createVerificationValue({value:t.user.id,identifier:`delete-account-${n}`,expiresAt:new Date(Date.now()+1e3*60*60*24)});let i=`${e.context.baseURL}/delete-user/callback?token=${n}`;return await e.context.options.user.deleteUser.sendDeleteAccountVerification({user:t.user,url:i,token:n},e.request),e.json({success:!0,message:"Verification email sent"})}let r=e.context.options.user.deleteUser?.beforeDelete;r&&await r(t.user,e.request),await e.context.internalAdapter.deleteUser(t.user.id),await e.context.internalAdapter.deleteSessions(t.user.id),await e.context.internalAdapter.deleteAccounts(t.user.id),N(e);let o=e.context.options.user.deleteUser?.afterDelete;return o&&await o(t.user,e.request),e.json({success:!0,message:"User deleted"})}),mt=h("/delete-user/callback",{method:"GET",query:O.object({token:O.string()})},async e=>{if(!e.context.options.user?.deleteUser?.enabled)throw e.context.logger.error("Delete user is disabled. Enable it in the options"),new T("NOT_FOUND");let t=await M(e);if(!t)throw new T("NOT_FOUND",{message:p.FAILED_TO_GET_USER_INFO});let r=await e.context.internalAdapter.findVerificationValue(`delete-account-${e.query.token}`);if(!r||r.expiresAt<new Date)throw r&&await e.context.internalAdapter.deleteVerificationValue(r.id),new T("NOT_FOUND",{message:p.INVALID_TOKEN});if(r.value!==t.user.id)throw new T("NOT_FOUND",{message:p.INVALID_TOKEN});let o=e.context.options.user.deleteUser?.beforeDelete;o&&await o(t.user,e.request),await e.context.internalAdapter.deleteUser(t.user.id),await e.context.internalAdapter.deleteSessions(t.user.id),await e.context.internalAdapter.deleteAccounts(t.user.id),await e.context.internalAdapter.deleteVerificationValue(r.id),N(e);let n=e.context.options.user.deleteUser?.afterDelete;return n&&await n(t.user,e.request),e.json({success:!0,message:"User deleted"})}),ft=h("/change-email",{method:"POST",query:O.object({currentURL:O.string().optional()}).optional(),body:O.object({newEmail:O.string({description:"The new email to set"}).email(),callbackURL:O.string({description:"The URL to redirect to after email verification"}).optional()}),use:[P],metadata:{openapi:{responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"},status:{type:"boolean"}}}}}}}}}},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new T("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 T("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 T("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let n=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:n,status:!0})}if(!e.context.options.user.changeEmail.sendChangeEmailVerification)throw e.context.logger.error("Verification email isn't enabled."),new T("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await j(e.context.secret,e.context.session.user.email,e.body.newEmail),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.user.changeEmail.sendChangeEmailVerification({user:e.context.session.user,newEmail:e.body.newEmail,url:o,token:r},e.request),e.json({user:null,status:!0})});var Er=(e="Unknown")=>`<!DOCTYPE html>
1
+ import{APIError as H,createRouter as Ir,getCookie as Lr,getSignedCookie as Pr,setCookie as Dr,setSignedCookie as Cr}from"better-call";import{APIError as xt}from"better-call";import{createEndpointCreator as _t,createMiddleware as he,createMiddlewareCreator as Tt}from"better-call";var we=he(async()=>({})),Z=Tt({use:[we,he(async()=>({}))]}),h=_t({use:[we]});function le(e){return e==="-"||e==="^"||e==="$"||e==="+"||e==="."||e==="("||e===")"||e==="|"||e==="["||e==="]"||e==="{"||e==="}"||e==="*"||e==="?"||e==="\\"?`\\${e}`:e}function Ot(e){let t="";for(let r=0;r<e.length;r++)t+=le(e[r]);return t}function ye(e,t=!0){if(Array.isArray(e))return`(?:${e.map(u=>`^${ye(u,t)}$`).join("|")})`;let r="",o="",n=".";t===!0?(r="/",o="[/\\\\]",n="[^/\\\\]"):t&&(r=t,o=Ot(r),o.length>1?(o=`(?:${o})`,n=`((?!${o}).)`):n=`[^${o}]`);let i=t?`${o}+?`:"",s=t?`${o}*?`:"",c=t?e.split(r):[e],a="";for(let d=0;d<c.length;d++){let u=c[d],f=c[d+1],g="";if(!(!u&&d>0)){if(t&&(d===c.length-1?g=s:f!=="**"?g=i:g=""),t&&u==="**"){g&&(a+=d===0?"":g,a+=`(?:${n}*?${g})*?`);continue}for(let l=0;l<u.length;l++){let b=u[l];b==="\\"?l<u.length-1&&(a+=le(u[l+1]),l++):b==="?"?a+=n:b==="*"?a+=`${n}*?`:a+=le(b)}a+=g}}return a}function St(e,t){if(typeof t!="string")throw new TypeError(`Sample must be a string, but ${typeof t} given`);return e.test(t)}function ee(e,t){if(typeof e!="string"&&!Array.isArray(e))throw new TypeError(`The first argument must be a single pattern string or an array of patterns, but ${typeof e} given`);if((typeof t=="string"||typeof t=="boolean")&&(t={separator:t}),arguments.length===2&&!(typeof t>"u"||typeof t=="object"&&t!==null&&!Array.isArray(t)))throw new TypeError(`The second argument must be an options object or a string/boolean separator, but ${typeof t} given`);if(t=t||{},t.separator==="\\")throw new Error("\\ is not a valid separator because it is used for escaping. Try setting the separator to `true` instead");let r=ye(e,t.separator),o=new RegExp(`^${r}$`,t.flags),n=St.bind(null,o);return n.options=t,n.pattern=e,n.regexp=o,n}var te=Object.create(null),Q=e=>globalThis.process?.env||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?te:globalThis),be=new Proxy(te,{get(e,t){return Q()[t]??te[t]},has(e,t){let r=Q();return t in r||t in te},set(e,t,r){let o=Q(!0);return o[t]=r,!0},deleteProperty(e,t){if(!t)return!1;let r=Q(!0);return delete r[t],!0},ownKeys(){let e=Q(!0);return Object.keys(e)}});function vt(e){return e?e!=="false":!1}var ue=typeof process<"u"&&process.env&&process.env.NODE_ENV||"";var re=ue==="dev"||ue==="development",Ae=ue==="test"||vt(be.TEST);var z=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};function Re(e){try{return new URL(e).origin}catch{return null}}function ke(e){return e.includes("://")?new URL(e).host:e}var Ee=Z(async e=>{if(e.request?.method!=="POST")return;let{body:t,query:r,context:o}=e,n=e.headers?.get("origin")||e.headers?.get("referer")||"",i=t?.callbackURL||r?.callbackURL,s=t?.redirectTo,c=r?.currentURL,a=t?.errorCallbackURL,d=t?.newUserCallbackURL,u=o.trustedOrigins,f=e.headers?.has("cookie"),g=(b,_)=>b.startsWith("/")?!1:_.includes("*")?ee(_)(ke(b)):b.startsWith(_),l=(b,_)=>{if(!b)return;if(!u.some(w=>g(b,w)||b?.startsWith("/")&&_!=="origin"&&!b.includes(":")))throw e.context.logger.error(`Invalid ${_}: ${b}`),e.context.logger.info(`If it's a valid URL, please add ${b} to trustedOrigins in your auth config
2
+ `,`Current list of trustedOrigins: ${u}`),new xt("FORBIDDEN",{message:`Invalid ${_}`})};f&&!e.context.options.advanced?.disableCSRFCheck&&l(n,"origin"),i&&l(i,"callbackURL"),s&&l(s,"redirectURL"),c&&l(c,"currentURL"),a&&l(a,"errorCallbackURL"),d&&l(s,"newUserCallbackURL")});import{APIError as S}from"better-call";import{z as U}from"zod";import{TimeSpan as so}from"oslo";import{base64url as Dt}from"oslo/encoding";import{HMAC as Ue,sha256 as Xr}from"oslo/crypto";async function Lt({value:e,secret:t}){return new Ue("SHA-256").sign(new TextEncoder().encode(t),new TextEncoder().encode(e)).then(o=>Buffer.from(o).toString("base64"))}function Pt({value:e,signature:t,secret:r}){return new Ue("SHA-256").verify(new TextEncoder().encode(r),Buffer.from(t,"base64"),new TextEncoder().encode(e))}var oe={sign:Lt,verify:Pt};var q=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));async function pe(e,t){if(e.context.options.session?.cookieCache?.enabled){let o=Dt.encode(new TextEncoder().encode(JSON.stringify({session:t,expiresAt:q(e.context.authCookies.sessionData.options.maxAge||60,"sec").getTime(),signature:await oe.sign({value:JSON.stringify(t),secret:e.context.secret})})),{includePadding:!1});if(o.length>4093)throw new z("Session data is too large to store in the cookie. Please disable session cookie caching or reduce the size of the session data");e.setCookie(e.context.authCookies.sessionData.name,o,e.context.authCookies.sessionData.options)}}async function v(e,t,r,o){let n=e.context.authCookies.sessionToken.options,i=r?void 0:e.context.sessionConfig.expiresIn;await e.setSignedCookie(e.context.authCookies.sessionToken.name,t.session.token,e.context.secret,{...n,maxAge:i,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options),await pe(e,t),e.context.setNewSession(t),e.context.options.secondaryStorage&&await e.context.secondaryStorage?.set(t.session.token,JSON.stringify({user:t.user,session:t.session}),Math.floor((new Date(t.session.expiresAt).getTime()-Date.now())/1e3))}function N(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{...e.context.authCookies.sessionToken.options,maxAge:0}),e.setCookie(e.context.authCookies.sessionData.name,"",{...e.context.authCookies.sessionData.options,maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{...e.context.authCookies.dontRememberToken.options,maxAge:0})}import{betterFetch as $t}from"@better-fetch/fetch";import{APIError as zt}from"better-call";import{decodeProtectedHeader as qt,importJWK as Ft,jwtVerify as Mt}from"jose";import{parseJWT as Ht}from"oslo/jwt";import{sha256 as Ct}from"oslo/crypto";import{base64url as Nt}from"oslo/encoding";async function _e(e){let t=await Ct(new TextEncoder().encode(e));return Nt.encode(new Uint8Array(t),{includePadding:!1})}function ie(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_in?q(e.expires_in,"sec"):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function E({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:s,redirectURI:c,duration:a}){let d=new URL(r);if(d.searchParams.set("response_type","code"),d.searchParams.set("client_id",t.clientId),d.searchParams.set("state",o),d.searchParams.set("scope",i.join(" ")),d.searchParams.set("redirect_uri",t.redirectURI||c),n){let u=await _e(n);d.searchParams.set("code_challenge_method","S256"),d.searchParams.set("code_challenge",u)}if(s){let u=s.reduce((f,g)=>(f[g]=null,f),{});d.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...u}}))}return a&&d.searchParams.set("duration",a),d}import{betterFetch as jt}from"@better-fetch/fetch";async function k({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n,authentication:i}){let s=new URLSearchParams,c={"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"};if(s.set("grant_type","authorization_code"),s.set("code",e),t&&s.set("code_verifier",t),s.set("redirect_uri",r),i==="basic"){let f=btoa(`${o.clientId}:${o.clientSecret}`);c.authorization=`Basic ${f}`}else s.set("client_id",o.clientId),s.set("client_secret",o.clientSecret);let{data:a,error:d}=await jt(n,{method:"POST",body:s,headers:c});if(d)throw d;return ie(a)}import{generateCodeVerifier as Vt,generateState as Bt}from"oslo/oauth2";import{z as V}from"zod";import{APIError as Te}from"better-call";async function ne(e,t){let r=e.body?.callbackURL||(e.query?.currentURL?Re(e.query?.currentURL):"")||e.context.options.baseURL;if(!r)throw new Te("BAD_REQUEST",{message:"callbackURL is required"});let o=Vt(),n=Bt(),i=JSON.stringify({callbackURL:r,codeVerifier:o,errorURL:e.body?.errorCallbackURL||e.query?.currentURL,newUserURL:e.body?.newUserCallbackURL,link:t,expiresAt:Date.now()+10*60*1e3}),s=new Date;s.setMinutes(s.getMinutes()+10);let c=await e.context.internalAdapter.createVerificationValue({value:i,identifier:n,expiresAt:s});if(!c)throw e.context.logger.error("Unable to create verification. Make sure the database adapter is properly working and there is a verification table in the database"),new Te("INTERNAL_SERVER_ERROR",{message:"Unable to create verification"});return{state:c.identifier,codeVerifier:o}}async function Oe(e){let t=e.query.state||e.body.state,r=await e.context.internalAdapter.findVerificationValue(t);if(!r)throw e.context.logger.error("State Mismatch. Verification not found",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let o=V.object({callbackURL:V.string(),codeVerifier:V.string(),errorURL:V.string().optional(),newUserURL:V.string().optional(),expiresAt:V.number(),link:V.object({email:V.string(),userId:V.string()}).optional()}).parse(JSON.parse(r.value));if(o.errorURL||(o.errorURL=`${e.context.baseURL}/error`),o.expiresAt<Date.now())throw await e.context.internalAdapter.deleteVerificationValue(r.id),e.context.logger.error("State expired.",{state:t}),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);return await e.context.internalAdapter.deleteVerificationValue(r.id),o}var Se=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=o||["email","name"];return e.scope&&i.push(...e.scope),new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${e.redirectURI||n}&scope=${i.join(" ")}&state=${r}&response_mode=form_post`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>k({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async verifyIdToken(r,o){if(e.disableIdTokenSignIn)return!1;if(e.verifyIdToken)return e.verifyIdToken(r,o);let n=qt(r),{kid:i,alg:s}=n;if(!i||!s)return!1;let c=await Gt(i),{payload:a}=await Mt(r,c,{algorithms:[s],issuer:"https://appleid.apple.com",audience:e.clientId,maxTokenAge:"1h"});return["email_verified","is_private_email"].forEach(d=>{a[d]!==void 0&&(a[d]=!!a[d])}),o&&a.nonce!==o?!1:!!a},async getUserInfo(r){if(e.getUserInfo)return e.getUserInfo(r);if(!r.idToken)return null;let o=Ht(r.idToken)?.payload;if(!o)return null;let n=o.user?`${o.user.name.firstName} ${o.user.name.lastName}`:o.email,i=await e.mapProfileToUser?.(o);return{user:{id:o.sub,name:n,emailVerified:!1,email:o.email,...i},data:o}}}},Gt=async e=>{let t="https://appleid.apple.com",r="/auth/keys",{data:o}=await $t(`${t}${r}`);if(!o?.keys)throw new zt("BAD_REQUEST",{message:"Keys not found"});let n=o.keys.find(i=>i.kid===e);if(!n)throw new Error(`JWK with kid ${e} not found`);return await Ft(n,n.alg)};import{betterFetch as Wt}from"@better-fetch/fetch";var ve=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["identify","email"];return e.scope&&n.push(...e.scope),new URL(`https://discord.com/api/oauth2/authorize?scope=${n.join("+")}&response_type=code&client_id=${e.clientId}&redirect_uri=${encodeURIComponent(e.redirectURI||o)}&state=${t}&prompt=${e.prompt||"none"}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>k({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await Wt("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let i=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${i}.png`}else{let i=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${i}`}let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url,...n},data:r}}});import{betterFetch as Zt}from"@better-fetch/fetch";var xe=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["email","public_profile"];return e.scope&&n.push(...e.scope),await E({id:"facebook",options:e,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:n,state:t,redirectURI:o})},validateAuthorizationCode:async({code:t,redirectURI:r})=>k({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await Zt("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.name,email:r.email,image:r.picture.data.url,emailVerified:r.email_verified,...n},data:r}}});import{betterFetch as Ie}from"@better-fetch/fetch";var Le=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"GitHub",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:i}){let s=o||["user:email"];return e.scope&&s.push(...e.scope),E({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:s,state:r,redirectURI:i})},validateAuthorizationCode:async({code:r,redirectURI:o})=>k({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){if(e.getUserInfo)return e.getUserInfo(r);let{data:o,error:n}=await Ie("https://api.github.com/user",{headers:{"User-Agent":"better-auth",authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=!1;if(!o.email){let{data:c,error:a}=await Ie("https://api.github.com/user/emails",{headers:{authorization:`Bearer ${r.accessToken}`,"User-Agent":"better-auth"}});a||(o.email=(c.find(d=>d.primary)??c[0])?.email,i=c.find(d=>d.email===o.email)?.verified??!1)}let s=await e.mapProfileToUser?.(o);return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i,...s},data:o}}}};import{parseJWT as Xt}from"oslo/jwt";import{createConsola as Qt}from"consola";var me=["info","success","warn","error","debug"];function Kt(e,t){return me.indexOf(t)<=me.indexOf(e)}var Jt=Qt({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),Yt=e=>{let t=e?.disabled!==!0,r=e?.level??"error",o=(n,i,s=[])=>{if(!(!t||!Kt(r,n))){if(!e||typeof e.log!="function"){Jt[n]("",i,...s);return}e.log(n==="success"?"info":n,i,s)}};return Object.fromEntries(me.map(n=>[n,(...[i,...s])=>o(n,i,s)]))},L=Yt();import{betterFetch as er}from"@better-fetch/fetch";var Pe=e=>({id:"google",name:"Google",async createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw L.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new z("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new z("codeVerifier is required for Google");let i=r||["email","profile","openid"];e.scope&&i.push(...e.scope);let s=await E({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n});return e.accessType&&s.searchParams.set("access_type",e.accessType),e.prompt&&s.searchParams.set("prompt",e.prompt),s},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>k({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async verifyIdToken(t,r){if(e.disableIdTokenSignIn)return!1;if(e.verifyIdToken)return e.verifyIdToken(t,r);let o=`https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=${t}`,{data:n}=await er(o);return n?n.aud===e.clientId&&n.iss==="https://accounts.google.com":!1},async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);if(!t.idToken)return null;let r=Xt(t.idToken)?.payload,o=await e.mapProfileToUser?.(r);return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified,...o},data:r}}});import{betterFetch as tr}from"@better-fetch/fetch";import{parseJWT as rr}from"oslo/jwt";var De=e=>{let t=e.tenantId||"common",r=`https://login.microsoftonline.com/${t}/oauth2/v2.0/authorize`,o=`https://login.microsoftonline.com/${t}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(n){let i=n.scopes||["openid","profile","email","User.Read"];return e.scope&&i.push(...e.scope),E({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:s}){return k({code:n,codeVerifier:i,redirectURI:e.redirectURI||s,options:e,tokenEndpoint:o})},async getUserInfo(n){if(e.getUserInfo)return e.getUserInfo(n);if(!n.idToken)return null;let i=rr(n.idToken)?.payload,s=e.profilePhotoSize||48;await tr(`https://graph.microsoft.com/v1.0/me/photos/${s}x${s}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(a){if(!(e.disableProfilePhoto||!a.response.ok))try{let u=await a.response.clone().arrayBuffer(),f=Buffer.from(u).toString("base64");i.picture=`data:image/jpeg;base64, ${f}`}catch(d){L.error(d&&typeof d=="object"&&"name"in d?d.name:"",d)}}});let c=await e.mapProfileToUser?.(i);return{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0,...c},data:i}}}};import{betterFetch as or}from"@better-fetch/fetch";var Ce=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=r||["user-read-email"];return e.scope&&i.push(...e.scope),E({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>k({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await or("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1,...n},data:r}}});var G={isAction:!1};import{nanoid as ir}from"nanoid";var Ne=e=>ir(e);import{parseJWT as nr}from"oslo/jwt";var je=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["user:read:email","openid"];return e.scope&&n.push(...e.scope),E({id:"twitch",redirectURI:o,options:e,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:n,state:t,claims:e.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>k({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let r=t.idToken;if(!r)return L.error("No idToken found in token"),null;let o=nr(r)?.payload,n=await e.mapProfileToUser?.(o);return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1,...n},data:o}}});import{betterFetch as sr}from"@better-fetch/fetch";var Ve=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=t.scopes||["users.read","tweet.read","offline.access"];return e.scope&&r.push(...e.scope),E({id:"twitter",options:e,authorizationEndpoint:"https://x.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>k({code:t,codeVerifier:r,authentication:"basic",redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://api.x.com/2/oauth2/token"}),async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await sr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.data.id,name:r.data.name,email:r.data.username||null,image:r.data.profile_image_url,emailVerified:r.data.verified||!1,...n},data:r}}});import{betterFetch as ar}from"@better-fetch/fetch";var Be=e=>{let t="https://api.dropboxapi.com/oauth2/token";return{id:"dropbox",name:"Dropbox",createAuthorizationURL:async({state:r,scopes:o,codeVerifier:n,redirectURI:i})=>{let s=o||["account_info.read"];return e.scope&&s.push(...e.scope),await E({id:"dropbox",options:e,authorizationEndpoint:"https://www.dropbox.com/oauth2/authorize",scopes:s,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>await k({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(e.getUserInfo)return e.getUserInfo(r);let{data:o,error:n}=await ar("https://api.dropboxapi.com/2/users/get_current_account",{method:"POST",headers:{Authorization:`Bearer ${r.accessToken}`}});if(n)return null;let i=await e.mapProfileToUser?.(o);return{user:{id:o.account_id,name:o.name?.display_name,email:o.email,emailVerified:o.email_verified||!1,image:o.profile_photo_url,...i},data:o}}}};import{betterFetch as cr}from"@better-fetch/fetch";var $e=e=>{let t="https://www.linkedin.com/oauth/v2/authorization",r="https://www.linkedin.com/oauth/v2/accessToken";return{id:"linkedin",name:"Linkedin",createAuthorizationURL:async({state:o,scopes:n,redirectURI:i})=>{let s=n||["profile","email","openid"];return e.scope&&s.push(...e.scope),await E({id:"linkedin",options:e,authorizationEndpoint:t,scopes:s,state:o,redirectURI:i})},validateAuthorizationCode:async({code:o,redirectURI:n})=>await k({code:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:r}),async getUserInfo(o){let{data:n,error:i}=await cr("https://api.linkedin.com/v2/userinfo",{method:"GET",headers:{Authorization:`Bearer ${o.accessToken}`}});if(i)return null;let s=await e.mapProfileToUser?.(n);return{user:{id:n.sub,name:n.name,email:n.email,emailVerified:n.email_verified||!1,image:n.picture,...s},data:n}}}};import{betterFetch as dr}from"@better-fetch/fetch";var fe=(e="")=>e.split("://").map(t=>t.replace(/\/{2,}/g,"/")).join("://"),lr=e=>{let t=e||"https://gitlab.com";return{authorizationEndpoint:fe(`${t}/oauth/authorize`),tokenEndpoint:fe(`${t}/oauth/token`),userinfoEndpoint:fe(`${t}/api/v4/user`)}},ze=e=>{let{authorizationEndpoint:t,tokenEndpoint:r,userinfoEndpoint:o}=lr(e.issuer),n="gitlab";return{id:n,name:"Gitlab",createAuthorizationURL:async({state:s,scopes:c,codeVerifier:a,redirectURI:d})=>{let u=c||["read_user"];return e.scope&&u.push(...e.scope),await E({id:n,options:e,authorizationEndpoint:t,scopes:u,state:s,redirectURI:d,codeVerifier:a})},validateAuthorizationCode:async({code:s,redirectURI:c,codeVerifier:a})=>k({code:s,redirectURI:e.redirectURI||c,options:e,codeVerifier:a,tokenEndpoint:r}),async getUserInfo(s){if(e.getUserInfo)return e.getUserInfo(s);let{data:c,error:a}=await dr(o,{headers:{authorization:`Bearer ${s.accessToken}`}});if(a||c.state!=="active"||c.locked)return null;let d=await e.mapProfileToUser?.(c);return{user:{id:c.id.toString(),name:c.name??c.username,email:c.email,image:c.avatar_url,emailVerified:!0,...d},data:c}}}};import{betterFetch as qe}from"@better-fetch/fetch";var Fe=e=>({id:"reddit",name:"Reddit",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=r||["identity"];return e.scope&&n.push(...e.scope),E({id:"reddit",options:e,authorizationEndpoint:"https://www.reddit.com/api/v1/authorize",scopes:n,state:t,redirectURI:o,duration:e.duration})},validateAuthorizationCode:async({code:t,redirectURI:r})=>{let o=new URLSearchParams({grant_type:"authorization_code",code:t,redirect_uri:e.redirectURI||r}),n={"content-type":"application/x-www-form-urlencoded",accept:"text/plain","user-agent":"better-auth",Authorization:`Basic ${Buffer.from(`${e.clientId}:${e.clientSecret}`).toString("base64")}`},{data:i,error:s}=await qe("https://www.reddit.com/api/v1/access_token",{method:"POST",headers:n,body:o.toString()});if(s)throw s;return ie(i)},async getUserInfo(t){if(e.getUserInfo)return e.getUserInfo(t);let{data:r,error:o}=await qe("https://oauth.reddit.com/api/v1/me",{headers:{Authorization:`Bearer ${t.accessToken}`,"User-Agent":"better-auth"}});if(o)return null;let n=await e.mapProfileToUser?.(r);return{user:{id:r.id,name:r.name,email:r.oauth_client_id,emailVerified:r.has_verified_email,image:r.icon_img?.split("?")[0],...n},data:r}}});var ur={apple:Se,discord:ve,facebook:xe,github:Le,microsoft:De,google:Pe,spotify:Ce,twitch:je,twitter:Ve,dropbox:Be,linkedin:$e,gitlab:ze,reddit:Fe},se=Object.keys(ur);import{TimeSpan as pr}from"oslo";import{createJWT as mr,validateJWT as fr}from"oslo/jwt";import{z as C}from"zod";import{APIError as K}from"better-call";import{APIError as B}from"better-call";import{z as F}from"zod";function Me(e){try{return JSON.parse(e)}catch{return null}}var p={USER_NOT_FOUND:"User not found",FAILED_TO_CREATE_USER:"Failed to create user",FAILED_TO_CREATE_SESSION:"Failed to create session",FAILED_TO_UPDATE_USER:"Failed to update user",FAILED_TO_GET_SESSION:"Failed to get session",INVALID_PASSWORD:"Invalid password",INVALID_EMAIL:"Invalid email",INVALID_EMAIL_OR_PASSWORD:"Invalid email or password",SOCIAL_ACCOUNT_ALREADY_LINKED:"Social account already linked",PROVIDER_NOT_FOUND:"Provider not found",INVALID_TOKEN:"invalid token",ID_TOKEN_NOT_SUPPORTED:"id_token not supported",FAILED_TO_GET_USER_INFO:"Failed to get user info",USER_EMAIL_NOT_FOUND:"User email not found",EMAIL_NOT_VERIFIED:"Email not verified",PASSWORD_TOO_SHORT:"Password too short",PASSWORD_TOO_LONG:"Password too long",USER_ALREADY_EXISTS:"User already exists",EMAIL_CAN_NOT_BE_UPDATED:"Email can not be updated",CREDENTIAL_ACCOUNT_NOT_FOUND:"Credential account not found"};var ge=()=>h("/get-session",{method:"GET",query:F.optional(F.object({disableCookieCache:F.boolean({description:"Disable cookie cache and fetch session from database"}).or(F.string().transform(e=>e==="true")).optional(),disableRefresh:F.boolean({description:"Disable session refresh. Useful for checking session status, without updating the session"}).optional()})),requireHeaders:!0,metadata:{openapi:{description:"Get the current session",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{session:{type:"object",properties:{token:{type:"string"},userId:{type:"string"},expiresAt:{type:"string"}}},user:{type:"object",$ref:"#/components/schemas/User"}}}}}}}}}},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null);let r=e.getCookie(e.context.authCookies.sessionData.name),o=r?Me(Buffer.from(r,"base64").toString()):null;if(o&&!await oe.verify({value:JSON.stringify(o.session),signature:o?.signature,secret:e.context.secret}))return N(e),e.json(null);let n=await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret);if(o?.session&&e.context.options.session?.cookieCache?.enabled&&!e.query?.disableCookieCache){let u=o.session;if(o.expiresAt<Date.now()||u.session.expiresAt<new Date){let g=e.context.authCookies.sessionData.name;e.setCookie(g,"",{maxAge:0})}else return e.json(u)}let i=await e.context.internalAdapter.findSession(t);if(e.context.session=i,!i||i.session.expiresAt<new Date)return N(e),i&&await e.context.internalAdapter.deleteSession(i.session.token),e.json(null);if(n||e.query?.disableRefresh)return e.json(i);let s=e.context.sessionConfig.expiresIn,c=e.context.sessionConfig.updateAge;if(i.session.expiresAt.valueOf()-s*1e3+c*1e3<=Date.now()){let u=await e.context.internalAdapter.updateSession(i.session.token,{expiresAt:q(e.context.sessionConfig.expiresIn,"sec")});if(!u)return N(e),e.json(null,{status:401});let f=(u.expiresAt.valueOf()-Date.now())/1e3;return await v(e,{session:u,user:i.user},!1,{maxAge:f}),e.json({session:u,user:i.user})}return await pe(e,i),e.json(i)}catch(t){throw e.context.logger.error("INTERNAL_SERVER_ERROR",t),new B("INTERNAL_SERVER_ERROR",{message:p.FAILED_TO_GET_SESSION})}}),M=async(e,t)=>{if(e.context.session)return e.context.session;let r=await ge()({...e,_flag:"json",headers:e.headers,query:t}).catch(o=>null);return e.context.session=r,r},P=Z(async e=>{let t=await M(e);if(!t?.session)throw new B("UNAUTHORIZED");return{session:t}}),He=Z(async e=>{let t=await M(e);if(!t?.session)throw new B("UNAUTHORIZED");if(e.context.sessionConfig.freshAge===0)return{session:t};let r=e.context.sessionConfig.freshAge,o=t.session.updatedAt?.valueOf()||t.session.createdAt.valueOf();if(!(Date.now()-o<r*1e3))throw new B("FORBIDDEN",{message:"Session is not fresh"});return{session:t}}),Ge=()=>h("/list-sessions",{method:"GET",use:[P],requireHeaders:!0,metadata:{openapi:{description:"List all active sessions for the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"array",items:{type:"object",properties:{token:{type:"string"},userId:{type:"string"},expiresAt:{type:"string"}}}}}}}}}}},async e=>{let r=(await e.context.internalAdapter.listSessions(e.context.session.user.id)).filter(o=>o.expiresAt>new Date);return e.json(r)}),We=h("/revoke-session",{method:"POST",body:F.object({token:F.string({description:"The token to revoke"})}),use:[P],requireHeaders:!0,metadata:{openapi:{description:"Revoke a single session",requestBody:{content:{"application/json":{schema:{type:"object",properties:{token:{type:"string"}},required:["token"]}}}}}}},async e=>{let t=e.body.token,r=await e.context.internalAdapter.findSession(t);if(!r)throw new B("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new B("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o&&typeof o=="object"&&"name"in o?o.name:"",o),new B("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Ze=h("/revoke-sessions",{method:"POST",use:[P],requireHeaders:!0,metadata:{openapi:{description:"Revoke all sessions for the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}},required:["status"]}}}}}}}},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t&&typeof t=="object"&&"name"in t?t.name:"",t),new B("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Qe=h("/revoke-other-sessions",{method:"POST",requireHeaders:!0,use:[P],metadata:{openapi:{description:"Revoke all other sessions for the user except the current one",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},async e=>{let t=e.context.session;if(!t.user)throw new B("UNAUTHORIZED");let n=(await e.context.internalAdapter.listSessions(t.user.id)).filter(i=>i.expiresAt>new Date).filter(i=>i.token!==e.context.session.session.token);return await Promise.all(n.map(i=>e.context.internalAdapter.deleteSession(i.token))),e.json({status:!0})});async function j(e,t,r){return await mr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new pr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}async function gr(e,t){if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new K("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await j(e.context.secret,t.email),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification.sendVerificationEmail({user:t,url:o,token:r},e.request)}var Ke=h("/send-verification-email",{method:"POST",query:C.object({currentURL:C.string({description:"The URL to use for email verification callback"}).optional()}).optional(),body:C.object({email:C.string({description:"The email to send the verification email to"}).email(),callbackURL:C.string({description:"The URL to use for email verification callback"}).optional()}),metadata:{openapi:{description:"Send a verification email to the user",requestBody:{content:{"application/json":{schema:{type:"object",properties:{email:{type:"string",description:"The email to send the verification email to"},callbackURL:{type:"string",description:"The URL to use for email verification callback"}},required:["email"]}}}},responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new K("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new K("BAD_REQUEST",{message:p.USER_NOT_FOUND});return await gr(e,r.user),e.json({status:!0})}),Je=h("/verify-email",{method:"GET",query:C.object({token:C.string({description:"The token to verify the email"}),callbackURL:C.string({description:"The URL to redirect to after email verification"}).optional()}),metadata:{openapi:{description:"Verify the email of the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"},status:{type:"boolean"}},required:["user","status"]}}}}}}}},async e=>{function t(c){throw e.query.callbackURL?e.query.callbackURL.includes("?")?e.redirect(`${e.query.callbackURL}&error=${c}`):e.redirect(`${e.query.callbackURL}?error=${c}`):new K("UNAUTHORIZED",{message:c})}let{token:r}=e.query,o;try{o=await fr("HS256",Buffer.from(e.context.secret),r)}catch(c){return e.context.logger.error("Failed to verify email",c),t("invalid_token")}let i=C.object({email:C.string().email(),updateTo:C.string().optional()}).parse(o.payload),s=await e.context.internalAdapter.findUserByEmail(i.email);if(!s)return t("user_not_found");if(i.updateTo){let c=await M(e);if(!c){if(e.query.callbackURL)throw e.redirect(`${e.query.callbackURL}?error=unauthorized`);return t("unauthorized")}if(c.user.email!==i.email){if(e.query.callbackURL)throw e.redirect(`${e.query.callbackURL}?error=unauthorized`);return t("unauthorized")}let a=await e.context.internalAdapter.updateUserByEmail(i.email,{email:i.updateTo,emailVerified:!1}),d=await j(e.context.secret,i.updateTo);if(await e.context.options.emailVerification?.sendVerificationEmail?.({user:a,url:`${e.context.baseURL}/verify-email?token=${d}`,token:d},e.request),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:a,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(i.email,{emailVerified:!0}),e.context.options.emailVerification?.autoSignInAfterVerification&&!await M(e)){let a=await e.context.internalAdapter.createSession(s.user.id,e.request);if(!a)throw new K("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});await v(e,{session:a,user:s.user})}if(e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});async function ae(e,{userInfo:t,account:r,callbackURL:o}){let n=await e.context.internalAdapter.findUserByEmail(t.email.toLowerCase(),{includeAccounts:!0}).catch(a=>{throw L.error(`Better auth was unable to query your database.
3
+ Error: `,a),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),i=n?.user,s=!i;if(n){let a=n.accounts.find(d=>d.providerId===r.providerId);if(a){let d=Object.fromEntries(Object.entries({accessToken:r.accessToken,idToken:r.idToken,refreshToken:r.refreshToken,accessTokenExpiresAt:r.accessTokenExpiresAt,refreshTokenExpiresAt:r.refreshTokenExpiresAt}).filter(([u,f])=>f!==void 0));Object.keys(d).length>0&&await e.context.internalAdapter.updateAccount(a.id,d)}else{if(!e.context.options.account?.accountLinking?.trustedProviders?.includes(r.providerId)&&!t.emailVerified||e.context.options.account?.accountLinking?.enabled===!1)return re&&L.warn(`User already exist but account isn't linked to ${r.providerId}. To read more about how account linking works in Better Auth see https://www.better-auth.com/docs/concepts/users-accounts#account-linking.`),{error:"account not linked",data:null};try{await e.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:t.id.toString(),userId:n.user.id,accessToken:r.accessToken,idToken:r.idToken,refreshToken:r.refreshToken,accessTokenExpiresAt:r.accessTokenExpiresAt,refreshTokenExpiresAt:r.refreshTokenExpiresAt,scope:r.scope})}catch(f){return L.error("Unable to link account",f),{error:"unable to link account",data:null}}i=await e.context.internalAdapter.updateUser(n.user.id,{...t,updatedAt:new Date})}}else if(i=await e.context.internalAdapter.createOAuthUser({...t,email:t.email.toLowerCase(),id:void 0},{accessToken:r.accessToken,idToken:r.idToken,refreshToken:r.refreshToken,accessTokenExpiresAt:r.accessTokenExpiresAt,refreshTokenExpiresAt:r.refreshTokenExpiresAt,scope:r.scope,providerId:r.providerId,accountId:t.id.toString()}).then(a=>a?.user),!t.emailVerified&&i&&e.context.options.emailVerification?.sendOnSignUp){let a=await j(e.context.secret,i.email),d=`${e.context.baseURL}/verify-email?token=${a}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.({user:i,url:d,token:a},e.request)}if(!i)return{error:"unable to create user",data:null,isRegister:!1};let c=await e.context.internalAdapter.createSession(i.id,e.request);return c?{data:{session:c,user:i},error:null,isRegister:s}:{error:"unable to create session",data:null,isRegister:!1}}var Ye=h("/sign-in/social",{method:"POST",query:U.object({currentURL:U.string().optional()}).optional(),body:U.object({callbackURL:U.string({description:"Callback URL to redirect to after the user has signed in"}).optional(),newUserCallbackURL:U.string().optional(),errorCallbackURL:U.string({description:"Callback URL to redirect to if an error happens"}).optional(),provider:U.enum(se,{description:"OAuth2 provider to use"}),disableRedirect:U.boolean({description:"Disable automatic redirection to the provider. Useful for handling the redirection yourself"}).optional(),idToken:U.optional(U.object({token:U.string({description:"ID token from the provider"}),nonce:U.string({description:"Nonce used to generate the token"}).optional(),accessToken:U.string({description:"Access token from the provider"}).optional(),refreshToken:U.string({description:"Refresh token from the provider"}).optional(),expiresAt:U.number({description:"Expiry date of the token"}).optional()}),{description:"ID token from the provider to sign in the user with id token"})}),metadata:{openapi:{description:"Sign in with a social provider",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{session:{type:"string"},user:{type:"object"},url:{type:"string"},redirect:{type:"boolean"}},required:["session","user","url","redirect"]}}}}}}}},async e=>{let t=e.context.socialProviders.find(i=>i.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 S("NOT_FOUND",{message:p.PROVIDER_NOT_FOUND});if(e.body.idToken){if(!t.verifyIdToken)throw e.context.logger.error("Provider does not support id token verification",{provider:e.body.provider}),new S("NOT_FOUND",{message:p.ID_TOKEN_NOT_SUPPORTED});let{token:i,nonce:s}=e.body.idToken;if(!await t.verifyIdToken(i,s))throw e.context.logger.error("Invalid id token",{provider:e.body.provider}),new S("UNAUTHORIZED",{message:p.INVALID_TOKEN});let a=await t.getUserInfo({idToken:i,accessToken:e.body.idToken.accessToken,refreshToken:e.body.idToken.refreshToken});if(!a||!a?.user)throw e.context.logger.error("Failed to get user info",{provider:e.body.provider}),new S("UNAUTHORIZED",{message:p.FAILED_TO_GET_USER_INFO});if(!a.user.email)throw e.context.logger.error("User email not found",{provider:e.body.provider}),new S("UNAUTHORIZED",{message:p.USER_EMAIL_NOT_FOUND});let d=await ae(e,{userInfo:{email:a.user.email,id:a.user.id,name:a.user.name||"",image:a.user.image,emailVerified:a.user.emailVerified||!1},account:{providerId:t.id,accountId:a.user.id,accessToken:e.body.idToken.accessToken}});if(d.error)throw new S("UNAUTHORIZED",{message:d.error});return await v(e,d.data),e.json({session:d.data.session,user:d.data.user,url:void 0,redirect:!1})}let{codeVerifier:r,state:o}=await ne(e),n=await t.createAuthorizationURL({state:o,codeVerifier:r,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:n.toString(),redirect:!e.body.disableRedirect})}),Xe=h("/sign-in/email",{method:"POST",body:U.object({email:U.string({description:"Email of the user"}),password:U.string({description:"Password of the user"}),callbackURL:U.string({description:"Callback URL to use as a redirect for email verification"}).optional(),rememberMe:U.boolean({description:"If this is false, the session will not be remembered. Default is `true`."}).default(!0).optional()}),metadata:{openapi:{description:"Sign in with email and password",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"},url:{type:"string"},redirect:{type:"boolean"}},required:["session","user","url","redirect"]}}}}}}}},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 S("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!U.string().email().safeParse(t).success)throw new S("BAD_REQUEST",{message:p.INVALID_EMAIL});let n=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!n)throw await e.context.password.hash(r),e.context.logger.error("User not found",{email:t}),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});let i=n.accounts.find(d=>d.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});let s=i?.password;if(!s)throw e.context.logger.error("Password not found",{email:t}),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});if(!await e.context.password.verify({hash:s,password:r}))throw e.context.logger.error("Invalid password"),new S("UNAUTHORIZED",{message:p.INVALID_EMAIL_OR_PASSWORD});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!n.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw new S("UNAUTHORIZED",{message:p.EMAIL_NOT_VERIFIED});let d=await j(e.context.secret,n.user.email),u=`${e.context.baseURL}/verify-email?token=${d}&callbackURL=${e.body.callbackURL||"/"}`;throw await e.context.options.emailVerification.sendVerificationEmail({user:n.user,url:u,token:d},e.request),e.context.logger.error("Email not verified",{email:t}),new S("FORBIDDEN",{message:p.EMAIL_NOT_VERIFIED})}let a=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.rememberMe===!1);if(!a)throw e.context.logger.error("Failed to create session"),new S("UNAUTHORIZED",{message:p.FAILED_TO_CREATE_SESSION});return await v(e,{session:a,user:n.user},e.body.rememberMe===!1),e.json({user:{id:n.user.id,email:n.user.email,name:n.user.name,image:n.user.image,emailVerified:n.user.emailVerified,createdAt:n.user.createdAt,updatedAt:n.user.updatedAt},redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{z as J}from"zod";var ce=J.object({code:J.string().optional(),error:J.string().optional(),error_description:J.string().optional(),state:J.string().optional()}),et=h("/callback/:id",{method:["GET","POST"],body:ce.optional(),query:ce.optional(),metadata:G},async e=>{let t;try{if(e.method==="GET")t=ce.parse(e.query);else if(e.method==="POST")t=ce.parse(e.body);else throw new Error("Unsupported method")}catch(A){throw e.context.logger.error("INVALID_CALLBACK_REQUEST",A),e.redirect(`${e.context.baseURL}/error?error=invalid_callback_request`)}let{code:r,error:o,state:n,error_description:i}=t;if(!n)throw e.context.logger.error("State not found",o),e.redirect(`${e.context.baseURL}/error?error=state_not_found`);if(!r)throw e.context.logger.error("Code not found"),e.redirect(`${e.context.baseURL}/error?error=${o||"no_code"}&error_description=${i}`);let s=e.context.socialProviders.find(A=>A.id===e.params.id);if(!s)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{codeVerifier:c,callbackURL:a,link:d,errorURL:u,newUserURL:f}=await Oe(e),g;try{g=await s.validateAuthorizationCode({code:r,codeVerifier:c,redirectURI:`${e.context.baseURL}/callback/${s.id}`})}catch(A){throw e.context.logger.error("",A),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let l=await s.getUserInfo(g).then(A=>A?.user);function b(A){let y=u||a||`${e.context.baseURL}/error`;throw y.includes("?")?y=`${y}&error=${A}`:y=`${y}?error=${A}`,e.redirect(y)}if(!l)return e.context.logger.error("Unable to get user info"),b("unable_to_get_user_info");if(!l.email)return e.context.logger.error("Provider did not return email. This could be due to misconfiguration in the provider settings."),b("email_not_found");if(!a)throw e.context.logger.error("No callback URL found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(d){if(d.email!==l.email.toLowerCase())return b("email_doesn't_match");if(!await e.context.internalAdapter.createAccount({userId:d.userId,providerId:s.id,accountId:l.id}))return b("unable_to_link_account");let y;try{y=a.toString()}catch{y=a}throw e.redirect(y)}let _=await ae(e,{userInfo:{...l,email:l.email,name:l.name||l.email},account:{providerId:s.id,accountId:l.id,...g,scope:g.scopes?.join(",")},callbackURL:a});if(_.error)return e.context.logger.error(_.error.split(" ").join("_")),b(_.error.split(" ").join("_"));let{session:x,user:w}=_.data;await v(e,{session:x,user:w});let R;try{R=(_.isRegister&&f||a).toString()}catch{R=_.isRegister&&f||a}throw e.redirect(R)});import"zod";import{APIError as hr}from"better-call";var tt=h("/sign-out",{method:"POST",requireHeaders:!0,metadata:{openapi:{description:"Sign out the current user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{success:{type:"boolean"}}}}}}}}}},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw N(e),new hr("BAD_REQUEST",{message:p.FAILED_TO_GET_SESSION});return await e.context.internalAdapter.deleteSession(t),N(e),e.json({success:!0})});import{z as D}from"zod";import{APIError as Y}from"better-call";function rt(e,t,r){let o=t?new URL(t,e.baseURL):new URL(`${e.baseURL}/error`);return r&&Object.entries(r).forEach(([n,i])=>o.searchParams.set(n,i)),o.href}function wr(e,t,r){let o=new URL(t,e.baseURL);return r&&Object.entries(r).forEach(([n,i])=>o.searchParams.set(n,i)),o.href}var ot=h("/forget-password",{method:"POST",body:D.object({email:D.string({description:"The email address of the user to send a password reset email to"}).email(),redirectTo:D.string({description:"The URL to redirect the user to reset their password. If the token isn't valid or expired, it'll be redirected with a query parameter `?error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?token=VALID_TOKEN"}).optional()}),metadata:{openapi:{description:"Send a password reset email to the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},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 Y("BAD_REQUEST",{message:"Reset password isn't enabled"});let{email:t,redirectTo:r}=e.body,o=await e.context.internalAdapter.findUserByEmail(t,{includeAccounts:!0});if(!o)return e.context.logger.error("Reset Password: User not found",{email:t}),e.json({status:!1},{body:{status:!0}});let n=60*60*1,i=q(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n,"sec"),s=Ne(24);await e.context.internalAdapter.createVerificationValue({value:o.user.id.toString(),identifier:`reset-password:${s}`,expiresAt:i});let c=`${e.context.baseURL}/reset-password/${s}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword({user:o.user,url:c,token:s},e.request),e.json({status:!0})}),it=h("/reset-password/:token",{method:"GET",query:D.object({callbackURL:D.string({description:"The URL to redirect the user to reset their password"})}),metadata:{openapi:{description:"Redirects the user to the callback URL with the token",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{token:{type:"string"}}}}}}}}}},async e=>{let{token:t}=e.params,{callbackURL:r}=e.query;if(!t||!r)throw e.redirect(rt(e.context,r,{error:"INVALID_TOKEN"}));let o=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!o||o.expiresAt<new Date?e.redirect(rt(e.context,r,{error:"INVALID_TOKEN"})):e.redirect(wr(e.context,r,{token:t}))}),nt=h("/reset-password",{query:D.optional(D.object({token:D.string().optional(),currentURL:D.string().optional()})),method:"POST",body:D.object({newPassword:D.string({description:"The new password to set"}),token:D.string({description:"The token to reset the password"}).optional()}),metadata:{openapi:{description:"Reset the password for a user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{status:{type:"boolean"}}}}}}}}}},async e=>{let t=e.body.token||e.query?.token||(e.query?.currentURL?new URL(e.query.currentURL).searchParams.get("token"):"");if(!t)throw new Y("BAD_REQUEST",{message:p.INVALID_TOKEN});let{newPassword:r}=e.body,o=e.context.password?.config.minPasswordLength,n=e.context.password?.config.maxPasswordLength;if(r.length<o)throw new Y("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});if(r.length>n)throw new Y("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});let i=`reset-password:${t}`,s=await e.context.internalAdapter.findVerificationValue(i);if(!s||s.expiresAt<new Date)throw new Y("BAD_REQUEST",{message:p.INVALID_TOKEN});await e.context.internalAdapter.deleteVerificationValue(s.id);let c=s.value,a=await e.context.password.hash(r);return(await e.context.internalAdapter.findAccounts(c)).find(f=>f.providerId==="credential")?(await e.context.internalAdapter.updatePassword(c,a),e.json({status:!0})):(await e.context.internalAdapter.createAccount({userId:c,providerId:"credential",password:a,accountId:c}),e.json({status:!0}))});import{z as O}from"zod";import{APIError as T}from"better-call";import{z as m}from"zod";import{APIError as yr}from"better-call";var As=m.object({id:m.string(),providerId:m.string(),accountId:m.string(),userId:m.string(),accessToken:m.string().nullish(),refreshToken:m.string().nullish(),idToken:m.string().nullish(),accessTokenExpiresAt:m.date().nullish(),refreshTokenExpiresAt:m.date().nullish(),scope:m.string().nullish(),password:m.string().nullish(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date)}),Rs=m.object({id:m.string(),email:m.string().transform(e=>e.toLowerCase()),emailVerified:m.boolean().default(!1),name:m.string(),image:m.string().nullish(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date)}),ks=m.object({id:m.string(),userId:m.string(),expiresAt:m.date(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date),token:m.string(),ipAddress:m.string().nullish(),userAgent:m.string().nullish()}),Es=m.object({id:m.string(),value:m.string(),createdAt:m.date().default(()=>new Date),updatedAt:m.date().default(()=>new Date),expiresAt:m.date(),identifier:m.string()});function br(e,t){let r={...t==="user"?e.user?.additionalFields:{},...t==="session"?e.session?.additionalFields:{}};for(let o of e.plugins||[])o.schema&&o.schema[t]&&(r={...r,...o.schema[t].fields});return r}function Ar(e,t){let r=t.action||"create",o=t.fields,n={};for(let i in o){if(i in e){if(o[i].input===!1){if(o[i].defaultValue){n[i]=o[i].defaultValue;continue}continue}if(o[i].validator?.input&&e[i]!==void 0){n[i]=o[i].validator.input.parse(e[i]);continue}if(o[i].transform?.input&&e[i]!==void 0){n[i]=o[i].transform?.input(e[i]);continue}n[i]=e[i];continue}if(o[i].defaultValue&&r==="create"){n[i]=o[i].defaultValue;continue}if(o[i].required&&r==="create")throw new yr("BAD_REQUEST",{message:`${i} is required`})}return n}function de(e,t,r){let o=br(e,"user");return Ar(t||{},{fields:o,action:r})}import{xchacha20poly1305 as js}from"@noble/ciphers/chacha";import{bytesToHex as Bs,hexToBytes as $s,utf8ToBytes as zs}from"@noble/ciphers/utils";import{managedNonce as Fs}from"@noble/ciphers/webcrypto";import{sha256 as Hs}from"oslo/crypto";import Ws from"uncrypto";import{decodeHex as Ts,encodeHex as Os}from"oslo/encoding";import{scryptAsync as xs}from"@noble/hashes/scrypt";import{getRandomValues as Ls}from"uncrypto";import st from"uncrypto";function Rr(e){return e.toString(2).padStart(8,"0")}function kr(e){return[...e].map(t=>Rr(t)).join("")}function at(e){return parseInt(kr(e),2)}function Er(e){if(e<0||!Number.isInteger(e))throw new Error("Argument 'max' must be an integer greater than or equal to 0");let t=(e-1).toString(2).length,r=t%8,o=new Uint8Array(Math.ceil(t/8));st.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=at(o);for(;n>=e;)st.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=at(o);return n}function ct(e,t){let r="";for(let o=0;o<e;o++)r+=t[Er(t.length)];return r}function dt(...e){let t=new Set(e),r="";for(let o of t)o==="a-z"?r+="abcdefghijklmnopqrstuvwxyz":o==="A-Z"?r+="ABCDEFGHIJKLMNOPQRSTUVWXYZ":o==="0-9"?r+="0123456789":r+=o;return r}var lt=()=>h("/update-user",{method:"POST",body:O.record(O.string(),O.any()),use:[P],metadata:{openapi:{description:"Update the current user",requestBody:{content:{"application/json":{schema:{type:"object",properties:{name:{type:"string",description:"The name of the user"},image:{type:"string",description:"The image of the user"}}}}}},responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"}}}}}}}}}},async e=>{let t=e.body;if(t.email)throw new T("BAD_REQUEST",{message:p.EMAIL_CAN_NOT_BE_UPDATED});let{name:r,image:o,...n}=t,i=e.context.session;if(o===void 0&&r===void 0&&Object.keys(n).length===0)return e.json({id:i.user.id,email:i.user.email,name:i.user.name,image:i.user.image,emailVerified:i.user.emailVerified,createdAt:i.user.createdAt,updatedAt:i.user.updatedAt});let s=de(e.context.options,n,"update"),c=await e.context.internalAdapter.updateUserByEmail(i.user.email,{name:r,image:o,...s});return await v(e,{session:i.session,user:c}),e.json({id:c.id,email:c.email,name:c.name,image:c.image,emailVerified:c.emailVerified,createdAt:c.createdAt,updatedAt:c.updatedAt})}),ut=h("/change-password",{method:"POST",body:O.object({newPassword:O.string({description:"The new password to set"}),currentPassword:O.string({description:"The current password"}),revokeOtherSessions:O.boolean({description:"Revoke all other sessions"}).optional()}),use:[P],metadata:{openapi:{description:"Change the password of the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{description:"The user object",$ref:"#/components/schemas/User"}}}}}}}}}},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,i=e.context.password.config.minPasswordLength;if(t.length<i)throw e.context.logger.error("Password is too short"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});let s=e.context.password.config.maxPasswordLength;if(t.length>s)throw e.context.logger.error("Password is too long"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});let a=(await e.context.internalAdapter.findAccounts(n.user.id)).find(f=>f.providerId==="credential"&&f.password);if(!a||!a.password)throw new T("BAD_REQUEST",{message:p.CREDENTIAL_ACCOUNT_NOT_FOUND});let d=await e.context.password.hash(t);if(!await e.context.password.verify({hash:a.password,password:r}))throw new T("BAD_REQUEST",{message:p.INVALID_PASSWORD});if(await e.context.internalAdapter.updateAccount(a.id,{password:d}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let f=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!f)throw new T("INTERNAL_SERVER_ERROR",{message:p.FAILED_TO_GET_SESSION});await v(e,{session:f,user:n.user})}return e.json(n.user)}),pt=h("/set-password",{method:"POST",body:O.object({newPassword:O.string()}),metadata:{SERVER_ONLY:!0},use:[P]},async e=>{let{newPassword:t}=e.body,r=e.context.session,o=e.context.password.config.minPasswordLength;if(t.length<o)throw e.context.logger.error("Password is too short"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new T("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});let s=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password),c=await e.context.password.hash(t);if(!s)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:c}),e.json(r.user);throw new T("BAD_REQUEST",{message:"user already has a password"})}),mt=h("/delete-user",{method:"POST",use:[He],metadata:{openapi:{description:"Delete the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object"}}}}}}}},async e=>{if(!e.context.options.user?.deleteUser?.enabled)throw e.context.logger.error("Delete user is disabled. Enable it in the options",{session:e.context.session}),new T("NOT_FOUND");let t=e.context.session;if(e.context.options.user.deleteUser?.sendDeleteAccountVerification){let n=ct(32,dt("a-z","A-Z","0-9"));await e.context.internalAdapter.createVerificationValue({value:t.user.id,identifier:`delete-account-${n}`,expiresAt:new Date(Date.now()+1e3*60*60*24)});let i=`${e.context.baseURL}/delete-user/callback?token=${n}`;return await e.context.options.user.deleteUser.sendDeleteAccountVerification({user:t.user,url:i,token:n},e.request),e.json({success:!0,message:"Verification email sent"})}let r=e.context.options.user.deleteUser?.beforeDelete;r&&await r(t.user,e.request),await e.context.internalAdapter.deleteUser(t.user.id),await e.context.internalAdapter.deleteSessions(t.user.id),await e.context.internalAdapter.deleteAccounts(t.user.id),N(e);let o=e.context.options.user.deleteUser?.afterDelete;return o&&await o(t.user,e.request),e.json({success:!0,message:"User deleted"})}),ft=h("/delete-user/callback",{method:"GET",query:O.object({token:O.string()})},async e=>{if(!e.context.options.user?.deleteUser?.enabled)throw e.context.logger.error("Delete user is disabled. Enable it in the options"),new T("NOT_FOUND");let t=await M(e);if(!t)throw new T("NOT_FOUND",{message:p.FAILED_TO_GET_USER_INFO});let r=await e.context.internalAdapter.findVerificationValue(`delete-account-${e.query.token}`);if(!r||r.expiresAt<new Date)throw r&&await e.context.internalAdapter.deleteVerificationValue(r.id),new T("NOT_FOUND",{message:p.INVALID_TOKEN});if(r.value!==t.user.id)throw new T("NOT_FOUND",{message:p.INVALID_TOKEN});let o=e.context.options.user.deleteUser?.beforeDelete;o&&await o(t.user,e.request),await e.context.internalAdapter.deleteUser(t.user.id),await e.context.internalAdapter.deleteSessions(t.user.id),await e.context.internalAdapter.deleteAccounts(t.user.id),await e.context.internalAdapter.deleteVerificationValue(r.id),N(e);let n=e.context.options.user.deleteUser?.afterDelete;return n&&await n(t.user,e.request),e.json({success:!0,message:"User deleted"})}),gt=h("/change-email",{method:"POST",query:O.object({currentURL:O.string().optional()}).optional(),body:O.object({newEmail:O.string({description:"The new email to set"}).email(),callbackURL:O.string({description:"The URL to redirect to after email verification"}).optional()}),use:[P],metadata:{openapi:{responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{user:{type:"object"},status:{type:"boolean"}}}}}}}}}},async e=>{if(!e.context.options.user?.changeEmail?.enabled)throw e.context.logger.error("Change email is disabled."),new T("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 T("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 T("BAD_REQUEST",{message:"Couldn't update your email"});if(e.context.session.user.emailVerified!==!0){let n=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:n,status:!0})}if(!e.context.options.user.changeEmail.sendChangeEmailVerification)throw e.context.logger.error("Verification email isn't enabled."),new T("BAD_REQUEST",{message:"Verification email isn't enabled"});let r=await j(e.context.secret,e.context.session.user.email,e.body.newEmail),o=`${e.context.baseURL}/verify-email?token=${r}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.user.changeEmail.sendChangeEmailVerification({user:e.context.session.user,newEmail:e.body.newEmail,url:o,token:r},e.request),e.json({user:null,status:!0})});var Ur=(e="Unknown")=>`<!DOCTYPE html>
4
4
  <html lang="en">
5
5
  <head>
6
6
  <meta charset="UTF-8">
@@ -80,4 +80,4 @@ Error: `,a),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)
80
80
  <div class="error-code">Error Code: <span id="errorCode">${e}</span></div>
81
81
  </div>
82
82
  </body>
83
- </html>`,gt=h("/error",{method:"GET",metadata:{...G,openapi:{description:"Displays an error page",responses:{200:{description:"Success",content:{"text/html":{schema:{type:"string"}}}}}}}},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(Er(t),{headers:{"Content-Type":"text/html"}})});var ht=h("/ok",{method:"GET",metadata:{...G,openapi:{description:"Check if the API is working",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{ok:{type:"boolean"}}}}}}}}}},async e=>e.json({ok:!0}));import{z as W}from"zod";import{APIError as $}from"better-call";var wt=()=>h("/sign-up/email",{method:"POST",query:W.object({currentURL:W.string().optional()}).optional(),body:W.record(W.string(),W.any()),metadata:{openapi:{description:"Sign up a user using email and password",requestBody:{content:{"application/json":{schema:{type:"object",properties:{name:{type:"string",description:"The name of the user"},email:{type:"string",description:"The email of the user"},password:{type:"string",description:"The password of the user"},callbackURL:{type:"string",description:"The URL to use for email verification callback"}},required:["name","email","password"]}}}},responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{id:{type:"string",description:"The id of the user"},email:{type:"string",description:"The email of the user"},name:{type:"string",description:"The name of the user"},image:{type:"string",description:"The image of the user"},emailVerified:{type:"boolean",description:"If the email is verified"}}}}}}}}}},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new $("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:s,...c}=t;if(!W.string().email().safeParse(o).success)throw new $("BAD_REQUEST",{message:p.INVALID_EMAIL});let d=e.context.password.config.minPasswordLength;if(n.length<d)throw e.context.logger.error("Password is too short"),new $("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});let u=e.context.password.config.maxPasswordLength;if(n.length>u)throw e.context.logger.error("Password is too long"),new $("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new $("UNPROCESSABLE_ENTITY",{message:p.USER_ALREADY_EXISTS});let g=de(e.context.options,c),l;try{if(l=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1}),!l)throw new $("BAD_REQUEST",{message:p.FAILED_TO_CREATE_USER})}catch(x){throw re&&e.context.logger.error("Failed to create user",x),new $("UNPROCESSABLE_ENTITY",{message:p.FAILED_TO_CREATE_USER,details:x})}if(!l)throw new $("UNPROCESSABLE_ENTITY",{message:p.FAILED_TO_CREATE_USER});let b=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:l.id,providerId:"credential",accountId:l.id,password:b}),e.context.options.emailVerification?.sendOnSignUp){let x=await j(e.context.secret,l.email),w=`${e.context.baseURL}/verify-email?token=${x}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.({user:l,url:w,token:x},e.request)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({id:l.id,email:l.email,name:l.name,image:l.image,emailVerified:l.emailVerified});let _=await e.context.internalAdapter.createSession(l.id,e.request);if(!_)throw new $("BAD_REQUEST",{message:p.FAILED_TO_CREATE_SESSION});return await v(e,{session:_,user:l}),e.json({id:l.id,email:l.email,name:l.name,image:l.image,emailVerified:l.emailVerified,createdAt:l.createdAt,updatedAt:l.updatedAt})});import{z as X}from"zod";import{APIError as yt}from"better-call";var bt=h("/list-accounts",{method:"GET",use:[P],metadata:{openapi:{description:"List all accounts linked to the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"array",items:{type:"object",properties:{id:{type:"string"},provider:{type:"string"}}}}}}}}}}},async e=>{let t=e.context.session,r=await e.context.internalAdapter.findAccounts(t.user.id);return e.json(r.map(o=>({id:o.id,provider:o.providerId})))}),At=h("/link-social",{method:"POST",requireHeaders:!0,query:X.object({currentURL:X.string().optional()}).optional(),body:X.object({callbackURL:X.string({description:"The URL to redirect to after the user has signed in"}).optional(),provider:X.enum(se,{description:"The OAuth2 provider to use"})}),use:[P],metadata:{openapi:{description:"Link a social account to the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{url:{type:"string"},redirect:{type:"boolean"}},required:["url","redirect"]}}}}}}}},async e=>{let t=e.context.session;if((await e.context.internalAdapter.findAccounts(t.user.id)).find(c=>c.providerId===e.body.provider))throw new yt("BAD_REQUEST",{message:p.SOCIAL_ACCOUNT_ALREADY_LINKED});let n=e.context.socialProviders.find(c=>c.id===e.body.provider);if(!n)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new yt("NOT_FOUND",{message:p.PROVIDER_NOT_FOUND});let i=await ne(e,{userId:t.user.id,email:t.user.email}),s=await n.createAuthorizationURL({state:i.state,codeVerifier:i.codeVerifier,redirectURI:`${e.context.baseURL}/callback/${n.id}`});return e.json({url:s.toString(),redirect:!0})});function Rt(e,t){if(t.advanced?.ipAddress?.disableIpTracking)return null;let r="127.0.0.1";if(be)return r;let n=t.advanced?.ipAddress?.ipAddressHeaders||["x-client-ip","x-forwarded-for","cf-connecting-ip","fastly-client-ip","x-real-ip","x-cluster-client-ip","x-forwarded","forwarded-for","forwarded"],i=e instanceof Request?e.headers:e;for(let s of n){let c=i.get(s);if(typeof c=="string"){let a=c.split(",")[0].trim();if(a)return a}}return null}function Ur(e,t,r){let o=Date.now(),n=t*1e3;return o-r.lastRequest<n&&r.count>=e}function _r(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 Tr(e,t){let r=Date.now(),o=t*1e3;return Math.ceil((e+o-r)/1e3)}function Or(e,t){let r="rateLimit",o=e.adapter;return{get:async n=>(await o.findMany({model:r,where:[{field:"key",value:n}]}))[0],set:async(n,i,s)=>{try{s?await o.updateMany({model:t??"rateLimit",where:[{field:"key",value:n}],update:{count:i.count,lastRequest:i.lastRequest}}):await o.create({model:t??"rateLimit",data:{key:n,count:i.count,lastRequest:i.lastRequest}})}catch(c){e.logger.error("Error setting rate limit",c)}}}}var kt=new Map;function Sr(e){return e.options.rateLimit?.customStorage?e.options.rateLimit.customStorage:e.rateLimit.storage==="secondary-storage"?{get:async r=>{let o=await e.options.secondaryStorage?.get(r);return o?JSON.parse(o):void 0},set:async(r,o)=>{await e.options.secondaryStorage?.set?.(r,JSON.stringify(o))}}:e.rateLimit.storage==="memory"?{async get(r){return kt.get(r)},async set(r,o,n){kt.set(r,o)}}:Or(e,e.rateLimit.modelName)}async function Et(e,t){if(!t.rateLimit.enabled)return;let r=t.baseURL,o=e.url.replace(r,"").split("?")[0],n=t.rateLimit.window,i=t.rateLimit.max,s=Rt(e,t.options)+o,a=vr().find(g=>g.pathMatcher(o));a&&(n=a.window,i=a.max);for(let g of t.options.plugins||[])if(g.rateLimit){let l=g.rateLimit.find(b=>b.pathMatcher(o));if(l){n=l.window,i=l.max;break}}if(t.rateLimit.customRules){let g=Object.keys(t.rateLimit.customRules).find(l=>l.includes("*")?ee(l)(o):l===o);if(g){let l=t.rateLimit.customRules[g],b=typeof l=="function"?await l(e):l;b&&(n=b.window,i=b.max)}}let d=Sr(t),u=await d.get(s),f=Date.now();if(!u)await d.set(s,{key:s,count:1,lastRequest:f});else{let g=f-u.lastRequest;if(Ur(i,n,u)){let l=Tr(u.lastRequest,n);return _r(l)}else g>n*1e3?await d.set(s,{...u,count:1,lastRequest:f},!0):await d.set(s,{...u,count:u.count+1,lastRequest:f},!0)}}function vr(){return[{pathMatcher(t){return t.startsWith("/sign-in")||t.startsWith("/sign-up")||t.startsWith("/change-password")||t.startsWith("/change-email")},window:10,max:3}]}import Cr from"defu";import{APIError as wc}from"better-call";function Nr(e,t){let r=t.plugins?.reduce((c,a)=>({...c,...a.endpoints}),{}),o=t.plugins?.map(c=>c.middlewares?.map(a=>{let d=async u=>a.middleware({...u,context:{...e,...u.context}});return d.path=a.path,d.options=a.middleware.options,d.headers=a.middleware.headers,{path:a.path,middleware:d}})).filter(c=>c!==void 0).flat()||[],i={...{signInSocial:Je,callbackOAuth:Xe,getSession:fe(),signOut:et,signUpEmail:wt(),signInEmail:Ye,forgetPassword:rt,resetPassword:it,verifyEmail:Ke,sendVerificationEmail:Qe,changeEmail:ft,changePassword:lt,setPassword:ut,updateUser:dt(),deleteUser:pt,forgetPasswordCallback:ot,listSessions:He(),revokeSession:Ge,revokeSessions:We,revokeOtherSessions:Ze,linkSocialAccount:At,listUserAccounts:bt,deleteUserCallback:mt},...r,ok:ht,error:gt},s={};for(let[c,a]of Object.entries(i))s[c]=async(d={})=>{a.headers=new Headers;let u={setHeader(w,R){a.headers.set(w,R)},setCookie(w,R,A){Pr(a.headers,w,R,A)},getCookie(w,R){let y=d.headers?.get("cookie");return Ir(y||"",w,R)},getSignedCookie(w,R,A){let y=d.headers;return y?Lr(y,R,w,A):null},async setSignedCookie(w,R,A,y){await Dr(a.headers,w,R,A,y)},redirect(w){return a.headers.set("Location",w),new H("FOUND")},responseHeader:a.headers},f=await e,g=null,l={...u,...d,path:a.path,context:{...f,...d.context,session:null,setNewSession:function(w){this.newSession=w,g=w}}},b=t.plugins||[];for(let w of b){let R=w.hooks?.before??[];for(let A of R){if(!A.matcher(l))continue;let y=await A.handler(l);if(y&&"context"in y){l=Cr(l,y.context);continue}if(y)return y}}let _;try{_=await a(l),g&&(l.context.newSession=g)}catch(w){if(g&&(l.context.newSession=g),w instanceof H){let R=t.plugins?.map(A=>{if(A.hooks?.after)return A.hooks.after}).filter(A=>A!==void 0).flat();if(!R?.length)throw w.headers=a.headers,w;l.context.returned=w,l.context.returned.headers=a.headers;for(let A of R||[])if(A.matcher(l))try{let I=await A.handler(l);I&&"response"in I&&(l.context.returned=I.response)}catch(I){if(I instanceof H){l.context.returned=I;continue}throw I}if(l.context.returned instanceof H)throw l.context.returned.headers=a.headers,l.context.returned;return l.context.returned}throw w}l.context.returned=_,l.responseHeader=a.headers;for(let w of t.plugins||[])if(w.hooks?.after){for(let R of w.hooks.after)if(R.matcher(l))try{let y=await R.handler(l);if(y)if("responseHeader"in y){let I=y.responseHeader;l.responseHeader=I}else l.context.returned=y}catch(y){if(y instanceof H){l.context.returned=y;continue}throw y}}let x=l.context.returned;return x instanceof Response&&a.headers.forEach((w,R)=>{R==="set-cookie"?x.headers.append(R,w):x.headers.set(R,w)}),x},s[c].path=a.path,s[c].method=a.method,s[c].options=a.options,s[c].headers=a.headers;return{api:s,middlewares:o}}var uc=(e,t)=>{let{api:r,middlewares:o}=Nr(e,t),n=new URL(e.baseURL).pathname;return xr(r,{extraContext:e,basePath:n,routerMiddleware:[{path:"/**",middleware:ke},...o],async onRequest(i){for(let s of e.options.plugins||[])if(s.onRequest){let c=await s.onRequest(i,e);if(c&&"response"in c)return c.response}return Et(i,e)},async onResponse(i){for(let s of e.options.plugins||[])if(s.onResponse){let c=await s.onResponse(i,e);if(c)return c.response}return i},onError(i){if(i instanceof H&&i.status==="FOUND")return;if(t.onAPIError?.throw)throw i;if(t.onAPIError?.onError){t.onAPIError.onError(i,e);return}let s=t.logger?.level,c=s==="error"||s==="warn"||s==="debug"?L:void 0;if(t.logger?.disabled!==!0){if(i&&typeof i=="object"&&"message"in i&&typeof i.message=="string"&&(i.message.includes("no column")||i.message.includes("column")||i.message.includes("relation")||i.message.includes("table")||i.message.includes("does not exist"))){e.logger?.error(i.message);return}i instanceof H?(i.status==="INTERNAL_SERVER_ERROR"&&e.logger.error(i.status,i),c?.error(i.message)):e.logger?.error(i&&typeof i=="object"&&"name"in i?i.name:"",i)}}})};export{wc as APIError,Xe as callbackOAuth,ft as changeEmail,lt as changePassword,h as createAuthEndpoint,Z as createAuthMiddleware,j as createEmailVerificationToken,pt as deleteUser,mt as deleteUserCallback,gt as error,rt as forgetPassword,ot as forgetPasswordCallback,Me as freshSessionMiddleware,Nr as getEndpoints,fe as getSession,M as getSessionFromCtx,At as linkSocialAccount,He as listSessions,bt as listUserAccounts,ht as ok,he as optionsMiddleware,ke as originCheckMiddleware,it as resetPassword,Ze as revokeOtherSessions,Ge as revokeSession,We as revokeSessions,uc as router,Qe as sendVerificationEmail,fr as sendVerificationEmailFn,P as sessionMiddleware,ut as setPassword,Ye as signInEmail,Je as signInSocial,et as signOut,wt as signUpEmail,dt as updateUser,Ke as verifyEmail};
83
+ </html>`,ht=h("/error",{method:"GET",metadata:{...G,openapi:{description:"Displays an error page",responses:{200:{description:"Success",content:{"text/html":{schema:{type:"string"}}}}}}}},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(Ur(t),{headers:{"Content-Type":"text/html"}})});var wt=h("/ok",{method:"GET",metadata:{...G,openapi:{description:"Check if the API is working",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{ok:{type:"boolean"}}}}}}}}}},async e=>e.json({ok:!0}));import{z as W}from"zod";import{APIError as $}from"better-call";var yt=()=>h("/sign-up/email",{method:"POST",query:W.object({currentURL:W.string().optional()}).optional(),body:W.record(W.string(),W.any()),metadata:{openapi:{description:"Sign up a user using email and password",requestBody:{content:{"application/json":{schema:{type:"object",properties:{name:{type:"string",description:"The name of the user"},email:{type:"string",description:"The email of the user"},password:{type:"string",description:"The password of the user"},callbackURL:{type:"string",description:"The URL to use for email verification callback"}},required:["name","email","password"]}}}},responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{id:{type:"string",description:"The id of the user"},email:{type:"string",description:"The email of the user"},name:{type:"string",description:"The name of the user"},image:{type:"string",description:"The image of the user"},emailVerified:{type:"boolean",description:"If the email is verified"}}}}}}}}}},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new $("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:s,...c}=t;if(!W.string().email().safeParse(o).success)throw new $("BAD_REQUEST",{message:p.INVALID_EMAIL});let d=e.context.password.config.minPasswordLength;if(n.length<d)throw e.context.logger.error("Password is too short"),new $("BAD_REQUEST",{message:p.PASSWORD_TOO_SHORT});let u=e.context.password.config.maxPasswordLength;if(n.length>u)throw e.context.logger.error("Password is too long"),new $("BAD_REQUEST",{message:p.PASSWORD_TOO_LONG});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new $("UNPROCESSABLE_ENTITY",{message:p.USER_ALREADY_EXISTS});let g=de(e.context.options,c),l;try{if(l=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...g,emailVerified:!1}),!l)throw new $("BAD_REQUEST",{message:p.FAILED_TO_CREATE_USER})}catch(x){throw re&&e.context.logger.error("Failed to create user",x),new $("UNPROCESSABLE_ENTITY",{message:p.FAILED_TO_CREATE_USER,details:x})}if(!l)throw new $("UNPROCESSABLE_ENTITY",{message:p.FAILED_TO_CREATE_USER});let b=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:l.id,providerId:"credential",accountId:l.id,password:b}),e.context.options.emailVerification?.sendOnSignUp){let x=await j(e.context.secret,l.email),w=`${e.context.baseURL}/verify-email?token=${x}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.({user:l,url:w,token:x},e.request)}if(!e.context.options.emailAndPassword.autoSignIn||e.context.options.emailAndPassword.requireEmailVerification)return e.json({id:l.id,email:l.email,name:l.name,image:l.image,emailVerified:l.emailVerified});let _=await e.context.internalAdapter.createSession(l.id,e.request);if(!_)throw new $("BAD_REQUEST",{message:p.FAILED_TO_CREATE_SESSION});return await v(e,{session:_,user:l}),e.json({id:l.id,email:l.email,name:l.name,image:l.image,emailVerified:l.emailVerified,createdAt:l.createdAt,updatedAt:l.updatedAt})});import{z as X}from"zod";import{APIError as bt}from"better-call";var At=h("/list-accounts",{method:"GET",use:[P],metadata:{openapi:{description:"List all accounts linked to the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"array",items:{type:"object",properties:{id:{type:"string"},provider:{type:"string"}}}}}}}}}}},async e=>{let t=e.context.session,r=await e.context.internalAdapter.findAccounts(t.user.id);return e.json(r.map(o=>({id:o.id,provider:o.providerId})))}),Rt=h("/link-social",{method:"POST",requireHeaders:!0,query:X.object({currentURL:X.string().optional()}).optional(),body:X.object({callbackURL:X.string({description:"The URL to redirect to after the user has signed in"}).optional(),provider:X.enum(se,{description:"The OAuth2 provider to use"})}),use:[P],metadata:{openapi:{description:"Link a social account to the user",responses:{200:{description:"Success",content:{"application/json":{schema:{type:"object",properties:{url:{type:"string"},redirect:{type:"boolean"}},required:["url","redirect"]}}}}}}}},async e=>{let t=e.context.session;if((await e.context.internalAdapter.findAccounts(t.user.id)).find(c=>c.providerId===e.body.provider))throw new bt("BAD_REQUEST",{message:p.SOCIAL_ACCOUNT_ALREADY_LINKED});let n=e.context.socialProviders.find(c=>c.id===e.body.provider);if(!n)throw e.context.logger.error("Provider not found. Make sure to add the provider in your auth config",{provider:e.body.provider}),new bt("NOT_FOUND",{message:p.PROVIDER_NOT_FOUND});let i=await ne(e,{userId:t.user.id,email:t.user.email}),s=await n.createAuthorizationURL({state:i.state,codeVerifier:i.codeVerifier,redirectURI:`${e.context.baseURL}/callback/${n.id}`});return e.json({url:s.toString(),redirect:!0})});function kt(e,t){if(t.advanced?.ipAddress?.disableIpTracking)return null;let r="127.0.0.1";if(Ae)return r;let n=t.advanced?.ipAddress?.ipAddressHeaders||["x-client-ip","x-forwarded-for","cf-connecting-ip","fastly-client-ip","x-real-ip","x-cluster-client-ip","x-forwarded","forwarded-for","forwarded"],i=e instanceof Request?e.headers:e;for(let s of n){let c=i.get(s);if(typeof c=="string"){let a=c.split(",")[0].trim();if(a)return a}}return null}function _r(e,t,r){let o=Date.now(),n=t*1e3;return o-r.lastRequest<n&&r.count>=e}function Tr(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 Or(e,t){let r=Date.now(),o=t*1e3;return Math.ceil((e+o-r)/1e3)}function Sr(e,t){let r="rateLimit",o=e.adapter;return{get:async n=>(await o.findMany({model:r,where:[{field:"key",value:n}]}))[0],set:async(n,i,s)=>{try{s?await o.updateMany({model:t??"rateLimit",where:[{field:"key",value:n}],update:{count:i.count,lastRequest:i.lastRequest}}):await o.create({model:t??"rateLimit",data:{key:n,count:i.count,lastRequest:i.lastRequest}})}catch(c){e.logger.error("Error setting rate limit",c)}}}}var Et=new Map;function vr(e){return e.options.rateLimit?.customStorage?e.options.rateLimit.customStorage:e.rateLimit.storage==="secondary-storage"?{get:async r=>{let o=await e.options.secondaryStorage?.get(r);return o?JSON.parse(o):void 0},set:async(r,o)=>{await e.options.secondaryStorage?.set?.(r,JSON.stringify(o))}}:e.rateLimit.storage==="memory"?{async get(r){return Et.get(r)},async set(r,o,n){Et.set(r,o)}}:Sr(e,e.rateLimit.modelName)}async function Ut(e,t){if(!t.rateLimit.enabled)return;let r=t.baseURL,o=e.url.replace(r,"").split("?")[0],n=t.rateLimit.window,i=t.rateLimit.max,s=kt(e,t.options)+o,a=xr().find(g=>g.pathMatcher(o));a&&(n=a.window,i=a.max);for(let g of t.options.plugins||[])if(g.rateLimit){let l=g.rateLimit.find(b=>b.pathMatcher(o));if(l){n=l.window,i=l.max;break}}if(t.rateLimit.customRules){let g=Object.keys(t.rateLimit.customRules).find(l=>l.includes("*")?ee(l)(o):l===o);if(g){let l=t.rateLimit.customRules[g],b=typeof l=="function"?await l(e):l;b&&(n=b.window,i=b.max)}}let d=vr(t),u=await d.get(s),f=Date.now();if(!u)await d.set(s,{key:s,count:1,lastRequest:f});else{let g=f-u.lastRequest;if(_r(i,n,u)){let l=Or(u.lastRequest,n);return Tr(l)}else g>n*1e3?await d.set(s,{...u,count:1,lastRequest:f},!0):await d.set(s,{...u,count:u.count+1,lastRequest:f},!0)}}function xr(){return[{pathMatcher(t){return t.startsWith("/sign-in")||t.startsWith("/sign-up")||t.startsWith("/change-password")||t.startsWith("/change-email")},window:10,max:3}]}import Nr from"defu";import{APIError as yc}from"better-call";function jr(e,t){let r=t.plugins?.reduce((c,a)=>({...c,...a.endpoints}),{}),o=t.plugins?.map(c=>c.middlewares?.map(a=>{let d=async u=>a.middleware({...u,context:{...e,...u.context}});return d.path=a.path,d.options=a.middleware.options,d.headers=a.middleware.headers,{path:a.path,middleware:d}})).filter(c=>c!==void 0).flat()||[],i={...{signInSocial:Ye,callbackOAuth:et,getSession:ge(),signOut:tt,signUpEmail:yt(),signInEmail:Xe,forgetPassword:ot,resetPassword:nt,verifyEmail:Je,sendVerificationEmail:Ke,changeEmail:gt,changePassword:ut,setPassword:pt,updateUser:lt(),deleteUser:mt,forgetPasswordCallback:it,listSessions:Ge(),revokeSession:We,revokeSessions:Ze,revokeOtherSessions:Qe,linkSocialAccount:Rt,listUserAccounts:At,deleteUserCallback:ft},...r,ok:wt,error:ht},s={};for(let[c,a]of Object.entries(i))s[c]=async(d={})=>{a.headers=new Headers;let u={setHeader(w,R){a.headers.set(w,R)},setCookie(w,R,A){Dr(a.headers,w,R,A)},getCookie(w,R){let y=d.headers?.get("cookie");return Lr(y||"",w,R)},getSignedCookie(w,R,A){let y=d.headers;return y?Pr(y,R,w,A):null},async setSignedCookie(w,R,A,y){await Cr(a.headers,w,R,A,y)},redirect(w){return a.headers.set("Location",w),new H("FOUND")},responseHeader:a.headers},f=await e,g=null,l={...u,...d,path:a.path,context:{...f,...d.context,session:null,setNewSession:function(w){this.newSession=w,g=w}}},b=t.plugins||[];for(let w of b){let R=w.hooks?.before??[];for(let A of R){if(!A.matcher(l))continue;let y=await A.handler(l);if(y&&"context"in y){l=Nr(l,y.context);continue}if(y)return y}}let _;try{_=await a(l),g&&(l.context.newSession=g)}catch(w){if(g&&(l.context.newSession=g),w instanceof H){let R=t.plugins?.map(A=>{if(A.hooks?.after)return A.hooks.after}).filter(A=>A!==void 0).flat();if(!R?.length)throw w.headers=a.headers,w;l.context.returned=w,l.context.returned.headers=a.headers;for(let A of R||[])if(A.matcher(l))try{let I=await A.handler(l);I&&"response"in I&&(l.context.returned=I.response)}catch(I){if(I instanceof H){l.context.returned=I;continue}throw I}if(l.context.returned instanceof H)throw l.context.returned.headers=a.headers,l.context.returned;return l.context.returned}throw w}l.context.returned=_,l.responseHeader=a.headers;for(let w of t.plugins||[])if(w.hooks?.after){for(let R of w.hooks.after)if(R.matcher(l))try{let y=await R.handler(l);if(y)if("responseHeader"in y){let I=y.responseHeader;l.responseHeader=I}else l.context.returned=y}catch(y){if(y instanceof H){l.context.returned=y;continue}throw y}}let x=l.context.returned;return x instanceof Response&&a.headers.forEach((w,R)=>{R==="set-cookie"?x.headers.append(R,w):x.headers.set(R,w)}),x},s[c].path=a.path,s[c].method=a.method,s[c].options=a.options,s[c].headers=a.headers;return{api:s,middlewares:o}}var pc=(e,t)=>{let{api:r,middlewares:o}=jr(e,t),n=new URL(e.baseURL).pathname;return Ir(r,{extraContext:e,basePath:n,routerMiddleware:[{path:"/**",middleware:Ee},...o],async onRequest(i){for(let s of e.options.plugins||[])if(s.onRequest){let c=await s.onRequest(i,e);if(c&&"response"in c)return c.response}return Ut(i,e)},async onResponse(i){for(let s of e.options.plugins||[])if(s.onResponse){let c=await s.onResponse(i,e);if(c)return c.response}return i},onError(i){if(i instanceof H&&i.status==="FOUND")return;if(t.onAPIError?.throw)throw i;if(t.onAPIError?.onError){t.onAPIError.onError(i,e);return}let s=t.logger?.level,c=s==="error"||s==="warn"||s==="debug"?L:void 0;if(t.logger?.disabled!==!0){if(i&&typeof i=="object"&&"message"in i&&typeof i.message=="string"&&(i.message.includes("no column")||i.message.includes("column")||i.message.includes("relation")||i.message.includes("table")||i.message.includes("does not exist"))){e.logger?.error(i.message);return}i instanceof H?(i.status==="INTERNAL_SERVER_ERROR"&&e.logger.error(i.status,i),c?.error(i.message)):e.logger?.error(i&&typeof i=="object"&&"name"in i?i.name:"",i)}}})};export{yc as APIError,et as callbackOAuth,gt as changeEmail,ut as changePassword,h as createAuthEndpoint,Z as createAuthMiddleware,j as createEmailVerificationToken,mt as deleteUser,ft as deleteUserCallback,ht as error,ot as forgetPassword,it as forgetPasswordCallback,He as freshSessionMiddleware,jr as getEndpoints,ge as getSession,M as getSessionFromCtx,Rt as linkSocialAccount,Ge as listSessions,At as listUserAccounts,wt as ok,we as optionsMiddleware,Ee as originCheckMiddleware,nt as resetPassword,Qe as revokeOtherSessions,We as revokeSession,Ze as revokeSessions,pc as router,Ke as sendVerificationEmail,gr as sendVerificationEmailFn,P as sessionMiddleware,pt as setPassword,Xe as signInEmail,Ye as signInSocial,tt as signOut,yt as signUpEmail,lt as updateUser,Je as verifyEmail};
@@ -1429,6 +1429,10 @@ declare function getCookies(options: BetterAuthOptions): {
1429
1429
  };
1430
1430
  };
1431
1431
  type BetterAuthCookies = ReturnType<typeof getCookies>;
1432
+ declare function setCookieCache(ctx: GenericEndpointContext, session: {
1433
+ session: Session & Record<string, any>;
1434
+ user: User;
1435
+ }): Promise<void>;
1432
1436
  declare function setSessionCookie(ctx: GenericEndpointContext, session: {
1433
1437
  session: Session & Record<string, any>;
1434
1438
  user: User;
@@ -14274,4 +14278,4 @@ type Auth = {
14274
14278
  $ERROR_CODES: typeof BASE_ERROR_CODES;
14275
14279
  };
14276
14280
 
14277
- export { type InferValueType as $, type AuthEndpoint as A, type BetterAuthOptions as B, parseCookies as C, parseSetCookieHeader as D, type EligibleCookies as E, levels as F, type GenericEndpointContext as G, type HookEndpointContext as H, type InferOptionSchema as I, shouldPublishLog as J, type KyselyDatabaseType as K, type LogLevel as L, type Models as M, type Logger as N, type LogHandlerParams as O, type PluginSchema as P, createLogger as Q, type RateLimit as R, type SecondaryStorage as S, logger as T, type FieldAttribute as U, type FieldType as V, type Where as W, createInternalAdapter as X, type InternalAdapter as Y, type FieldAttributeConfig as Z, createFieldAttribute as _, BASE_ERROR_CODES as a, type InferFieldsOutput as a0, type InferFieldsInput as a1, type InferFieldsInputClient as a2, type PluginFieldAttribute as a3, type InferFieldsFromPlugins as a4, type InferFieldsFromOptions as a5, type BetterAuthDbSchema as a6, getAuthTables as a7, getEndpoints as a8, router as a9, ok as aA, signUpEmail as aB, listUserAccounts as aC, linkSocialAccount as aD, originCheckMiddleware as aE, signInSocial as aa, signInEmail as ab, callbackOAuth as ac, getSession as ad, getSessionFromCtx as ae, sessionMiddleware as af, freshSessionMiddleware as ag, listSessions as ah, revokeSession as ai, revokeSessions as aj, revokeOtherSessions as ak, signOut as al, forgetPassword as am, forgetPasswordCallback as an, resetPassword as ao, createEmailVerificationToken as ap, sendVerificationEmailFn as aq, sendVerificationEmail as ar, verifyEmail as as, updateUser as at, changePassword as au, setPassword as av, deleteUser as aw, deleteUserCallback as ax, changeEmail as ay, error as az, type BetterAuthPlugin as b, type InferPluginErrorCodes as c, createAuthMiddleware as d, createAuthEndpoint as e, type AuthMiddleware as f, type Auth as g, type AuthContext as h, type InferUser as i, type InferSession as j, type WithJsDoc as k, betterAuth as l, type AdditionalUserFieldsInput as m, type AdditionalUserFieldsOutput as n, optionsMiddleware as o, type AdditionalSessionFieldsInput as p, type AdditionalSessionFieldsOutput as q, type InferPluginTypes as r, init as s, type Adapter as t, type AdapterInstance as u, createCookieGetter as v, getCookies as w, type BetterAuthCookies as x, setSessionCookie as y, deleteSessionCookie as z };
14281
+ export { createFieldAttribute as $, type AuthEndpoint as A, type BetterAuthOptions as B, deleteSessionCookie as C, parseCookies as D, type EligibleCookies as E, parseSetCookieHeader as F, type GenericEndpointContext as G, type HookEndpointContext as H, type InferOptionSchema as I, levels as J, type KyselyDatabaseType as K, type LogLevel as L, type Models as M, shouldPublishLog as N, type Logger as O, type PluginSchema as P, type LogHandlerParams as Q, type RateLimit as R, type SecondaryStorage as S, createLogger as T, logger as U, type FieldAttribute as V, type Where as W, type FieldType as X, createInternalAdapter as Y, type InternalAdapter as Z, type FieldAttributeConfig as _, BASE_ERROR_CODES as a, type InferValueType as a0, type InferFieldsOutput as a1, type InferFieldsInput as a2, type InferFieldsInputClient as a3, type PluginFieldAttribute as a4, type InferFieldsFromPlugins as a5, type InferFieldsFromOptions as a6, type BetterAuthDbSchema as a7, getAuthTables as a8, getEndpoints as a9, error as aA, ok as aB, signUpEmail as aC, listUserAccounts as aD, linkSocialAccount as aE, originCheckMiddleware as aF, router as aa, signInSocial as ab, signInEmail as ac, callbackOAuth as ad, getSession as ae, getSessionFromCtx as af, sessionMiddleware as ag, freshSessionMiddleware as ah, listSessions as ai, revokeSession as aj, revokeSessions as ak, revokeOtherSessions as al, signOut as am, forgetPassword as an, forgetPasswordCallback as ao, resetPassword as ap, createEmailVerificationToken as aq, sendVerificationEmailFn as ar, sendVerificationEmail as as, verifyEmail as at, updateUser as au, changePassword as av, setPassword as aw, deleteUser as ax, deleteUserCallback as ay, changeEmail as az, type BetterAuthPlugin as b, type InferPluginErrorCodes as c, createAuthMiddleware as d, createAuthEndpoint as e, type AuthMiddleware as f, type Auth as g, type AuthContext as h, type InferUser as i, type InferSession as j, type WithJsDoc as k, betterAuth as l, type AdditionalUserFieldsInput as m, type AdditionalUserFieldsOutput as n, optionsMiddleware as o, type AdditionalSessionFieldsInput as p, type AdditionalSessionFieldsOutput as q, type InferPluginTypes as r, init as s, type Adapter as t, type AdapterInstance as u, createCookieGetter as v, getCookies as w, type BetterAuthCookies as x, setCookieCache as y, setSessionCookie as z };
@@ -1429,6 +1429,10 @@ declare function getCookies(options: BetterAuthOptions): {
1429
1429
  };
1430
1430
  };
1431
1431
  type BetterAuthCookies = ReturnType<typeof getCookies>;
1432
+ declare function setCookieCache(ctx: GenericEndpointContext, session: {
1433
+ session: Session & Record<string, any>;
1434
+ user: User;
1435
+ }): Promise<void>;
1432
1436
  declare function setSessionCookie(ctx: GenericEndpointContext, session: {
1433
1437
  session: Session & Record<string, any>;
1434
1438
  user: User;
@@ -14274,4 +14278,4 @@ type Auth = {
14274
14278
  $ERROR_CODES: typeof BASE_ERROR_CODES;
14275
14279
  };
14276
14280
 
14277
- export { type InferValueType as $, type AuthEndpoint as A, type BetterAuthOptions as B, parseCookies as C, parseSetCookieHeader as D, type EligibleCookies as E, levels as F, type GenericEndpointContext as G, type HookEndpointContext as H, type InferOptionSchema as I, shouldPublishLog as J, type KyselyDatabaseType as K, type LogLevel as L, type Models as M, type Logger as N, type LogHandlerParams as O, type PluginSchema as P, createLogger as Q, type RateLimit as R, type SecondaryStorage as S, logger as T, type FieldAttribute as U, type FieldType as V, type Where as W, createInternalAdapter as X, type InternalAdapter as Y, type FieldAttributeConfig as Z, createFieldAttribute as _, BASE_ERROR_CODES as a, type InferFieldsOutput as a0, type InferFieldsInput as a1, type InferFieldsInputClient as a2, type PluginFieldAttribute as a3, type InferFieldsFromPlugins as a4, type InferFieldsFromOptions as a5, type BetterAuthDbSchema as a6, getAuthTables as a7, getEndpoints as a8, router as a9, ok as aA, signUpEmail as aB, listUserAccounts as aC, linkSocialAccount as aD, originCheckMiddleware as aE, signInSocial as aa, signInEmail as ab, callbackOAuth as ac, getSession as ad, getSessionFromCtx as ae, sessionMiddleware as af, freshSessionMiddleware as ag, listSessions as ah, revokeSession as ai, revokeSessions as aj, revokeOtherSessions as ak, signOut as al, forgetPassword as am, forgetPasswordCallback as an, resetPassword as ao, createEmailVerificationToken as ap, sendVerificationEmailFn as aq, sendVerificationEmail as ar, verifyEmail as as, updateUser as at, changePassword as au, setPassword as av, deleteUser as aw, deleteUserCallback as ax, changeEmail as ay, error as az, type BetterAuthPlugin as b, type InferPluginErrorCodes as c, createAuthMiddleware as d, createAuthEndpoint as e, type AuthMiddleware as f, type Auth as g, type AuthContext as h, type InferUser as i, type InferSession as j, type WithJsDoc as k, betterAuth as l, type AdditionalUserFieldsInput as m, type AdditionalUserFieldsOutput as n, optionsMiddleware as o, type AdditionalSessionFieldsInput as p, type AdditionalSessionFieldsOutput as q, type InferPluginTypes as r, init as s, type Adapter as t, type AdapterInstance as u, createCookieGetter as v, getCookies as w, type BetterAuthCookies as x, setSessionCookie as y, deleteSessionCookie as z };
14281
+ export { createFieldAttribute as $, type AuthEndpoint as A, type BetterAuthOptions as B, deleteSessionCookie as C, parseCookies as D, type EligibleCookies as E, parseSetCookieHeader as F, type GenericEndpointContext as G, type HookEndpointContext as H, type InferOptionSchema as I, levels as J, type KyselyDatabaseType as K, type LogLevel as L, type Models as M, shouldPublishLog as N, type Logger as O, type PluginSchema as P, type LogHandlerParams as Q, type RateLimit as R, type SecondaryStorage as S, createLogger as T, logger as U, type FieldAttribute as V, type Where as W, type FieldType as X, createInternalAdapter as Y, type InternalAdapter as Z, type FieldAttributeConfig as _, BASE_ERROR_CODES as a, type InferValueType as a0, type InferFieldsOutput as a1, type InferFieldsInput as a2, type InferFieldsInputClient as a3, type PluginFieldAttribute as a4, type InferFieldsFromPlugins as a5, type InferFieldsFromOptions as a6, type BetterAuthDbSchema as a7, getAuthTables as a8, getEndpoints as a9, error as aA, ok as aB, signUpEmail as aC, listUserAccounts as aD, linkSocialAccount as aE, originCheckMiddleware as aF, router as aa, signInSocial as ab, signInEmail as ac, callbackOAuth as ad, getSession as ae, getSessionFromCtx as af, sessionMiddleware as ag, freshSessionMiddleware as ah, listSessions as ai, revokeSession as aj, revokeSessions as ak, revokeOtherSessions as al, signOut as am, forgetPassword as an, forgetPasswordCallback as ao, resetPassword as ap, createEmailVerificationToken as aq, sendVerificationEmailFn as ar, sendVerificationEmail as as, verifyEmail as at, updateUser as au, changePassword as av, setPassword as aw, deleteUser as ax, deleteUserCallback as ay, changeEmail as az, type BetterAuthPlugin as b, type InferPluginErrorCodes as c, createAuthMiddleware as d, createAuthEndpoint as e, type AuthMiddleware as f, type Auth as g, type AuthContext as h, type InferUser as i, type InferSession as j, type WithJsDoc as k, betterAuth as l, type AdditionalUserFieldsInput as m, type AdditionalUserFieldsOutput as n, optionsMiddleware as o, type AdditionalSessionFieldsInput as p, type AdditionalSessionFieldsOutput as q, type InferPluginTypes as r, init as s, type Adapter as t, type AdapterInstance as u, createCookieGetter as v, getCookies as w, type BetterAuthCookies as x, setCookieCache as y, setSessionCookie as z };
@@ -10,7 +10,7 @@ export { twoFactorClient } from '../plugins/two-factor.cjs';
10
10
  import { magicLink } from '../plugins/magic-link.cjs';
11
11
  import { phoneNumber } from '../plugins/phone-number.cjs';
12
12
  import { anonymous } from '../plugins/anonymous.cjs';
13
- import { U as FieldAttribute, B as BetterAuthOptions, b as BetterAuthPlugin } from '../auth-DCr9mzAB.cjs';
13
+ import { V as FieldAttribute, B as BetterAuthOptions, b as BetterAuthPlugin } from '../auth-CqgjEQ5z.cjs';
14
14
  import { admin } from '../plugins/admin.cjs';
15
15
  import { genericOAuth } from '../plugins/generic-oauth.cjs';
16
16
  import { jwt } from '../plugins/jwt.cjs';
@@ -10,7 +10,7 @@ export { twoFactorClient } from '../plugins/two-factor.js';
10
10
  import { magicLink } from '../plugins/magic-link.js';
11
11
  import { phoneNumber } from '../plugins/phone-number.js';
12
12
  import { anonymous } from '../plugins/anonymous.js';
13
- import { U as FieldAttribute, B as BetterAuthOptions, b as BetterAuthPlugin } from '../auth-B_LFm6_Y.js';
13
+ import { V as FieldAttribute, B as BetterAuthOptions, b as BetterAuthPlugin } from '../auth-5DAdlxmK.js';
14
14
  import { admin } from '../plugins/admin.js';
15
15
  import { genericOAuth } from '../plugins/generic-oauth.js';
16
16
  import { jwt } from '../plugins/jwt.js';
package/dist/client.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as BASE_ERROR_CODES, b as BetterAuthPlugin } from './auth-DCr9mzAB.cjs';
1
+ import { a as BASE_ERROR_CODES, b as BetterAuthPlugin } from './auth-CqgjEQ5z.cjs';
2
2
  import { ClientOptions, InferClientAPI, InferActions, InferErrorCodes, BetterAuthClientPlugin, IsSignal } from './types.cjs';
3
3
  export { AtomListener, InferAdditionalFromClient, InferPluginsFromClient, InferSessionFromClient, InferUserFromClient, Store } from './types.cjs';
4
4
  import * as nanostores from 'nanostores';
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as BASE_ERROR_CODES, b as BetterAuthPlugin } from './auth-B_LFm6_Y.js';
1
+ import { a as BASE_ERROR_CODES, b as BetterAuthPlugin } from './auth-5DAdlxmK.js';
2
2
  import { ClientOptions, InferClientAPI, InferActions, InferErrorCodes, BetterAuthClientPlugin, IsSignal } from './types.js';
3
3
  export { AtomListener, InferAdditionalFromClient, InferPluginsFromClient, InferSessionFromClient, InferUserFromClient, Store } from './types.js';
4
4
  import * as nanostores from 'nanostores';
package/dist/cookies.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var h=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var O=Object.prototype.hasOwnProperty;var _=(e,t)=>{for(var o in t)h(e,o,{get:t[o],enumerable:!0})},P=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of B(t))!O.call(e,s)&&s!==o&&h(e,s,{get:()=>t[s],enumerable:!(n=D(t,s))||n.enumerable});return e};var R=e=>P(h({},"__esModule",{value:!0}),e);var q={};_(q,{createCookieGetter:()=>T,deleteSessionCookie:()=>I,getCookies:()=>N,parseCookies:()=>$,parseSetCookieHeader:()=>M,setSessionCookie:()=>H});module.exports=R(q);var v=require("oslo"),A=require("oslo/encoding");var p=require("oslo/crypto");async function U({value:e,secret:t}){return new p.HMAC("SHA-256").sign(new TextEncoder().encode(t),new TextEncoder().encode(e)).then(n=>Buffer.from(n).toString("base64"))}function j({value:e,signature:t,secret:o}){return new p.HMAC("SHA-256").verify(new TextEncoder().encode(o),Buffer.from(t,"base64"),new TextEncoder().encode(e))}var x={sign:U,verify:j};var m=class extends Error{constructor(t,o){super(t),this.name="BetterAuthError",this.message=t,this.cause=o,this.stack=""}};var C=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));var k=Object.create(null),d=e=>globalThis.process?.env||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?k:globalThis),L=new Proxy(k,{get(e,t){return d()[t]??k[t]},has(e,t){let o=d();return t in o||t in k},set(e,t,o){let n=d(!0);return n[t]=o,!0},deleteProperty(e,t){if(!t)return!1;let o=d(!0);return delete o[t],!0},ownKeys(){let e=d(!0);return Object.keys(e)}});function V(e){return e?e!=="false":!1}var y=typeof process<"u"&&process.env&&process.env.NODE_ENV||"",w=y==="production";var X=y==="test"||V(L.TEST);function M(e){let t=new Map;return e.split(", ").forEach(n=>{let s=n.split(";").map(g=>g.trim()),[a,...u]=s,[c,...l]=a.split("="),f=l.join("=");if(!c||f===void 0)return;let i={value:f};u.forEach(g=>{let[S,...E]=g.split("="),r=E.join("="),b=S.trim().toLowerCase();switch(b){case"max-age":i["max-age"]=r?parseInt(r.trim(),10):void 0;break;case"expires":i.expires=r?new Date(r.trim()):void 0;break;case"domain":i.domain=r?r.trim():void 0;break;case"path":i.path=r?r.trim():void 0;break;case"secure":i.secure=!0;break;case"httponly":i.httponly=!0;break;case"samesite":i.samesite=r?r.trim().toLowerCase():void 0;break;default:i[b]=r?r.trim():!0;break}}),t.set(c,i)}),t}function T(e){let o=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:e.baseURL!==void 0?!!e.baseURL.startsWith("https://"):w)?"__Secure-":"",n=!!e.advanced?.crossSubDomainCookies?.enabled,s=n?e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0):void 0;if(n&&!s)throw new m("baseURL is required when crossSubdomainCookies are enabled");function a(u,c={}){let l=e.advanced?.cookiePrefix||"better-auth",f=e.advanced?.cookies?.[u]?.name||`${l}.${u}`,i=e.advanced?.cookies?.[u]?.attributes;return{name:`${o}${f}`,attributes:{secure:!!o,sameSite:"lax",path:"/",httpOnly:!0,...n?{domain:s}:{},...e.advanced?.defaultCookieAttributes,...c,...i}}}return a}function N(e){let t=T(e),o=e.session?.expiresIn||new v.TimeSpan(7,"d").seconds(),n=t("session_token",{maxAge:o}),s=t("session_data",{maxAge:e.session?.cookieCache?.maxAge||60*5}),a=t("dont_remember");return{sessionToken:{name:n.name,options:n.attributes},sessionData:{name:s.name,options:s.attributes},dontRememberToken:{name:a.name,options:a.attributes}}}async function H(e,t,o,n){let s=e.context.authCookies.sessionToken.options,a=o?void 0:e.context.sessionConfig.expiresIn;if(await e.setSignedCookie(e.context.authCookies.sessionToken.name,t.session.token,e.context.secret,{...s,maxAge:a,...n}),o&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options),e.context.options.session?.cookieCache?.enabled){let c=A.base64url.encode(new TextEncoder().encode(JSON.stringify({session:t,expiresAt:C(e.context.authCookies.sessionData.options.maxAge||60,"sec").getTime(),signature:await x.sign({value:JSON.stringify(t),secret:e.context.secret})})),{includePadding:!1});if(c.length>4093)throw new m("Session data is too large to store in the cookie. Please disable session cookie caching or reduce the size of the session data");e.setCookie(e.context.authCookies.sessionData.name,c,e.context.authCookies.sessionData.options)}e.context.setNewSession(t),e.context.options.secondaryStorage&&await e.context.secondaryStorage?.set(t.session.token,JSON.stringify({user:t.user,session:t.session}),Math.floor((new Date(t.session.expiresAt).getTime()-Date.now())/1e3))}function I(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{...e.context.authCookies.sessionToken.options,maxAge:0}),e.setCookie(e.context.authCookies.sessionData.name,"",{...e.context.authCookies.sessionData.options,maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{...e.context.authCookies.dontRememberToken.options,maxAge:0})}function $(e){let t=e.split("; "),o=new Map;return t.forEach(n=>{let[s,a]=n.split("=");o.set(s,a)}),o}0&&(module.exports={createCookieGetter,deleteSessionCookie,getCookies,parseCookies,parseSetCookieHeader,setSessionCookie});
1
+ "use strict";var h=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var R=(e,t)=>{for(var o in t)h(e,o,{get:t[o],enumerable:!0})},P=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of O(t))!_.call(e,s)&&s!==o&&h(e,s,{get:()=>t[s],enumerable:!(n=B(t,s))||n.enumerable});return e};var U=e=>P(h({},"__esModule",{value:!0}),e);var q={};R(q,{createCookieGetter:()=>S,deleteSessionCookie:()=>I,getCookies:()=>G,parseCookies:()=>$,parseSetCookieHeader:()=>N,setCookieCache:()=>T,setSessionCookie:()=>H});module.exports=U(q);var v=require("oslo"),A=require("oslo/encoding");var p=require("oslo/crypto");async function j({value:e,secret:t}){return new p.HMAC("SHA-256").sign(new TextEncoder().encode(t),new TextEncoder().encode(e)).then(n=>Buffer.from(n).toString("base64"))}function L({value:e,signature:t,secret:o}){return new p.HMAC("SHA-256").verify(new TextEncoder().encode(o),Buffer.from(t,"base64"),new TextEncoder().encode(e))}var C={sign:j,verify:L};var u=class extends Error{constructor(t,o){super(t),this.name="BetterAuthError",this.message=t,this.cause=o,this.stack=""}};var x=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));var k=Object.create(null),m=e=>globalThis.process?.env||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?k:globalThis),V=new Proxy(k,{get(e,t){return m()[t]??k[t]},has(e,t){let o=m();return t in o||t in k},set(e,t,o){let n=m(!0);return n[t]=o,!0},deleteProperty(e,t){if(!t)return!1;let o=m(!0);return delete o[t],!0},ownKeys(){let e=m(!0);return Object.keys(e)}});function M(e){return e?e!=="false":!1}var y=typeof process<"u"&&process.env&&process.env.NODE_ENV||"",w=y==="production";var Y=y==="test"||M(V.TEST);function N(e){let t=new Map;return e.split(", ").forEach(n=>{let s=n.split(";").map(g=>g.trim()),[a,...c]=s,[d,...l]=a.split("="),f=l.join("=");if(!d||f===void 0)return;let i={value:f};c.forEach(g=>{let[E,...D]=g.split("="),r=D.join("="),b=E.trim().toLowerCase();switch(b){case"max-age":i["max-age"]=r?parseInt(r.trim(),10):void 0;break;case"expires":i.expires=r?new Date(r.trim()):void 0;break;case"domain":i.domain=r?r.trim():void 0;break;case"path":i.path=r?r.trim():void 0;break;case"secure":i.secure=!0;break;case"httponly":i.httponly=!0;break;case"samesite":i.samesite=r?r.trim().toLowerCase():void 0;break;default:i[b]=r?r.trim():!0;break}}),t.set(d,i)}),t}function S(e){let o=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:e.baseURL!==void 0?!!e.baseURL.startsWith("https://"):w)?"__Secure-":"",n=!!e.advanced?.crossSubDomainCookies?.enabled,s=n?e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0):void 0;if(n&&!s)throw new u("baseURL is required when crossSubdomainCookies are enabled");function a(c,d={}){let l=e.advanced?.cookiePrefix||"better-auth",f=e.advanced?.cookies?.[c]?.name||`${l}.${c}`,i=e.advanced?.cookies?.[c]?.attributes;return{name:`${o}${f}`,attributes:{secure:!!o,sameSite:"lax",path:"/",httpOnly:!0,...n?{domain:s}:{},...e.advanced?.defaultCookieAttributes,...d,...i}}}return a}function G(e){let t=S(e),o=e.session?.expiresIn||new v.TimeSpan(7,"d").seconds(),n=t("session_token",{maxAge:o}),s=t("session_data",{maxAge:e.session?.cookieCache?.maxAge||60*5}),a=t("dont_remember");return{sessionToken:{name:n.name,options:n.attributes},sessionData:{name:s.name,options:s.attributes},dontRememberToken:{name:a.name,options:a.attributes}}}async function T(e,t){if(e.context.options.session?.cookieCache?.enabled){let n=A.base64url.encode(new TextEncoder().encode(JSON.stringify({session:t,expiresAt:x(e.context.authCookies.sessionData.options.maxAge||60,"sec").getTime(),signature:await C.sign({value:JSON.stringify(t),secret:e.context.secret})})),{includePadding:!1});if(n.length>4093)throw new u("Session data is too large to store in the cookie. Please disable session cookie caching or reduce the size of the session data");e.setCookie(e.context.authCookies.sessionData.name,n,e.context.authCookies.sessionData.options)}}async function H(e,t,o,n){let s=e.context.authCookies.sessionToken.options,a=o?void 0:e.context.sessionConfig.expiresIn;await e.setSignedCookie(e.context.authCookies.sessionToken.name,t.session.token,e.context.secret,{...s,maxAge:a,...n}),o&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options),await T(e,t),e.context.setNewSession(t),e.context.options.secondaryStorage&&await e.context.secondaryStorage?.set(t.session.token,JSON.stringify({user:t.user,session:t.session}),Math.floor((new Date(t.session.expiresAt).getTime()-Date.now())/1e3))}function I(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{...e.context.authCookies.sessionToken.options,maxAge:0}),e.setCookie(e.context.authCookies.sessionData.name,"",{...e.context.authCookies.sessionData.options,maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{...e.context.authCookies.dontRememberToken.options,maxAge:0})}function $(e){let t=e.split("; "),o=new Map;return t.forEach(n=>{let[s,a]=n.split("=");o.set(s,a)}),o}0&&(module.exports={createCookieGetter,deleteSessionCookie,getCookies,parseCookies,parseSetCookieHeader,setCookieCache,setSessionCookie});
@@ -1,5 +1,5 @@
1
1
  import 'better-call';
2
- export { x as BetterAuthCookies, E as EligibleCookies, v as createCookieGetter, z as deleteSessionCookie, w as getCookies, C as parseCookies, D as parseSetCookieHeader, y as setSessionCookie } from './auth-DCr9mzAB.cjs';
2
+ export { x as BetterAuthCookies, E as EligibleCookies, v as createCookieGetter, C as deleteSessionCookie, w as getCookies, D as parseCookies, F as parseSetCookieHeader, y as setCookieCache, z as setSessionCookie } from './auth-CqgjEQ5z.cjs';
3
3
  import './schema-DG_8mn16.cjs';
4
4
  import 'kysely';
5
5
  import 'zod';
package/dist/cookies.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import 'better-call';
2
- export { x as BetterAuthCookies, E as EligibleCookies, v as createCookieGetter, z as deleteSessionCookie, w as getCookies, C as parseCookies, D as parseSetCookieHeader, y as setSessionCookie } from './auth-B_LFm6_Y.js';
2
+ export { x as BetterAuthCookies, E as EligibleCookies, v as createCookieGetter, C as deleteSessionCookie, w as getCookies, D as parseCookies, F as parseSetCookieHeader, y as setCookieCache, z as setSessionCookie } from './auth-5DAdlxmK.js';
3
3
  import './schema-DG_8mn16.js';
4
4
  import 'kysely';
5
5
  import 'zod';
package/dist/cookies.js CHANGED
@@ -1 +1 @@
1
- import{TimeSpan as D}from"oslo";import{base64url as B}from"oslo/encoding";import{HMAC as h,sha256 as U}from"oslo/crypto";async function A({value:e,secret:t}){return new h("SHA-256").sign(new TextEncoder().encode(t),new TextEncoder().encode(e)).then(n=>Buffer.from(n).toString("base64"))}function T({value:e,signature:t,secret:o}){return new h("SHA-256").verify(new TextEncoder().encode(o),Buffer.from(t,"base64"),new TextEncoder().encode(e))}var b={sign:A,verify:T};var m=class extends Error{constructor(t,o){super(t),this.name="BetterAuthError",this.message=t,this.cause=o,this.stack=""}};var x=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));var p=Object.create(null),d=e=>globalThis.process?.env||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?p:globalThis),S=new Proxy(p,{get(e,t){return d()[t]??p[t]},has(e,t){let o=d();return t in o||t in p},set(e,t,o){let n=d(!0);return n[t]=o,!0},deleteProperty(e,t){if(!t)return!1;let o=d(!0);return delete o[t],!0},ownKeys(){let e=d(!0);return Object.keys(e)}});function E(e){return e?e!=="false":!1}var C=typeof process<"u"&&process.env&&process.env.NODE_ENV||"",y=C==="production";var N=C==="test"||E(S.TEST);function I(e){let t=new Map;return e.split(", ").forEach(n=>{let r=n.split(";").map(l=>l.trim()),[a,...u]=r,[c,...k]=a.split("="),f=k.join("=");if(!c||f===void 0)return;let i={value:f};u.forEach(l=>{let[w,...v]=l.split("="),s=v.join("="),g=w.trim().toLowerCase();switch(g){case"max-age":i["max-age"]=s?parseInt(s.trim(),10):void 0;break;case"expires":i.expires=s?new Date(s.trim()):void 0;break;case"domain":i.domain=s?s.trim():void 0;break;case"path":i.path=s?s.trim():void 0;break;case"secure":i.secure=!0;break;case"httponly":i.httponly=!0;break;case"samesite":i.samesite=s?s.trim().toLowerCase():void 0;break;default:i[g]=s?s.trim():!0;break}}),t.set(c,i)}),t}function O(e){let o=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:e.baseURL!==void 0?!!e.baseURL.startsWith("https://"):y)?"__Secure-":"",n=!!e.advanced?.crossSubDomainCookies?.enabled,r=n?e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0):void 0;if(n&&!r)throw new m("baseURL is required when crossSubdomainCookies are enabled");function a(u,c={}){let k=e.advanced?.cookiePrefix||"better-auth",f=e.advanced?.cookies?.[u]?.name||`${k}.${u}`,i=e.advanced?.cookies?.[u]?.attributes;return{name:`${o}${f}`,attributes:{secure:!!o,sameSite:"lax",path:"/",httpOnly:!0,...n?{domain:r}:{},...e.advanced?.defaultCookieAttributes,...c,...i}}}return a}function F(e){let t=O(e),o=e.session?.expiresIn||new D(7,"d").seconds(),n=t("session_token",{maxAge:o}),r=t("session_data",{maxAge:e.session?.cookieCache?.maxAge||60*5}),a=t("dont_remember");return{sessionToken:{name:n.name,options:n.attributes},sessionData:{name:r.name,options:r.attributes},dontRememberToken:{name:a.name,options:a.attributes}}}async function Q(e,t,o,n){let r=e.context.authCookies.sessionToken.options,a=o?void 0:e.context.sessionConfig.expiresIn;if(await e.setSignedCookie(e.context.authCookies.sessionToken.name,t.session.token,e.context.secret,{...r,maxAge:a,...n}),o&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options),e.context.options.session?.cookieCache?.enabled){let c=B.encode(new TextEncoder().encode(JSON.stringify({session:t,expiresAt:x(e.context.authCookies.sessionData.options.maxAge||60,"sec").getTime(),signature:await b.sign({value:JSON.stringify(t),secret:e.context.secret})})),{includePadding:!1});if(c.length>4093)throw new m("Session data is too large to store in the cookie. Please disable session cookie caching or reduce the size of the session data");e.setCookie(e.context.authCookies.sessionData.name,c,e.context.authCookies.sessionData.options)}e.context.setNewSession(t),e.context.options.secondaryStorage&&await e.context.secondaryStorage?.set(t.session.token,JSON.stringify({user:t.user,session:t.session}),Math.floor((new Date(t.session.expiresAt).getTime()-Date.now())/1e3))}function X(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{...e.context.authCookies.sessionToken.options,maxAge:0}),e.setCookie(e.context.authCookies.sessionData.name,"",{...e.context.authCookies.sessionData.options,maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{...e.context.authCookies.dontRememberToken.options,maxAge:0})}function Y(e){let t=e.split("; "),o=new Map;return t.forEach(n=>{let[r,a]=n.split("=");o.set(r,a)}),o}export{O as createCookieGetter,X as deleteSessionCookie,F as getCookies,Y as parseCookies,I as parseSetCookieHeader,Q as setSessionCookie};
1
+ import{TimeSpan as D}from"oslo";import{base64url as B}from"oslo/encoding";import{HMAC as h,sha256 as j}from"oslo/crypto";async function A({value:e,secret:t}){return new h("SHA-256").sign(new TextEncoder().encode(t),new TextEncoder().encode(e)).then(n=>Buffer.from(n).toString("base64"))}function S({value:e,signature:t,secret:o}){return new h("SHA-256").verify(new TextEncoder().encode(o),Buffer.from(t,"base64"),new TextEncoder().encode(e))}var b={sign:A,verify:S};var u=class extends Error{constructor(t,o){super(t),this.name="BetterAuthError",this.message=t,this.cause=o,this.stack=""}};var C=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));var p=Object.create(null),m=e=>globalThis.process?.env||globalThis.Deno?.env.toObject()||globalThis.__env__||(e?p:globalThis),T=new Proxy(p,{get(e,t){return m()[t]??p[t]},has(e,t){let o=m();return t in o||t in p},set(e,t,o){let n=m(!0);return n[t]=o,!0},deleteProperty(e,t){if(!t)return!1;let o=m(!0);return delete o[t],!0},ownKeys(){let e=m(!0);return Object.keys(e)}});function E(e){return e?e!=="false":!1}var x=typeof process<"u"&&process.env&&process.env.NODE_ENV||"",y=x==="production";var G=x==="test"||E(T.TEST);function I(e){let t=new Map;return e.split(", ").forEach(n=>{let r=n.split(";").map(l=>l.trim()),[a,...c]=r,[d,...k]=a.split("="),f=k.join("=");if(!d||f===void 0)return;let i={value:f};c.forEach(l=>{let[w,...v]=l.split("="),s=v.join("="),g=w.trim().toLowerCase();switch(g){case"max-age":i["max-age"]=s?parseInt(s.trim(),10):void 0;break;case"expires":i.expires=s?new Date(s.trim()):void 0;break;case"domain":i.domain=s?s.trim():void 0;break;case"path":i.path=s?s.trim():void 0;break;case"secure":i.secure=!0;break;case"httponly":i.httponly=!0;break;case"samesite":i.samesite=s?s.trim().toLowerCase():void 0;break;default:i[g]=s?s.trim():!0;break}}),t.set(d,i)}),t}function O(e){let o=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:e.baseURL!==void 0?!!e.baseURL.startsWith("https://"):y)?"__Secure-":"",n=!!e.advanced?.crossSubDomainCookies?.enabled,r=n?e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0):void 0;if(n&&!r)throw new u("baseURL is required when crossSubdomainCookies are enabled");function a(c,d={}){let k=e.advanced?.cookiePrefix||"better-auth",f=e.advanced?.cookies?.[c]?.name||`${k}.${c}`,i=e.advanced?.cookies?.[c]?.attributes;return{name:`${o}${f}`,attributes:{secure:!!o,sameSite:"lax",path:"/",httpOnly:!0,...n?{domain:r}:{},...e.advanced?.defaultCookieAttributes,...d,...i}}}return a}function Q(e){let t=O(e),o=e.session?.expiresIn||new D(7,"d").seconds(),n=t("session_token",{maxAge:o}),r=t("session_data",{maxAge:e.session?.cookieCache?.maxAge||60*5}),a=t("dont_remember");return{sessionToken:{name:n.name,options:n.attributes},sessionData:{name:r.name,options:r.attributes},dontRememberToken:{name:a.name,options:a.attributes}}}async function _(e,t){if(e.context.options.session?.cookieCache?.enabled){let n=B.encode(new TextEncoder().encode(JSON.stringify({session:t,expiresAt:C(e.context.authCookies.sessionData.options.maxAge||60,"sec").getTime(),signature:await b.sign({value:JSON.stringify(t),secret:e.context.secret})})),{includePadding:!1});if(n.length>4093)throw new u("Session data is too large to store in the cookie. Please disable session cookie caching or reduce the size of the session data");e.setCookie(e.context.authCookies.sessionData.name,n,e.context.authCookies.sessionData.options)}}async function X(e,t,o,n){let r=e.context.authCookies.sessionToken.options,a=o?void 0:e.context.sessionConfig.expiresIn;await e.setSignedCookie(e.context.authCookies.sessionToken.name,t.session.token,e.context.secret,{...r,maxAge:a,...n}),o&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options),await _(e,t),e.context.setNewSession(t),e.context.options.secondaryStorage&&await e.context.secondaryStorage?.set(t.session.token,JSON.stringify({user:t.user,session:t.session}),Math.floor((new Date(t.session.expiresAt).getTime()-Date.now())/1e3))}function Y(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{...e.context.authCookies.sessionToken.options,maxAge:0}),e.setCookie(e.context.authCookies.sessionData.name,"",{...e.context.authCookies.sessionData.options,maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{...e.context.authCookies.dontRememberToken.options,maxAge:0})}function Z(e){let t=e.split("; "),o=new Map;return t.forEach(n=>{let[r,a]=n.split("=");o.set(r,a)}),o}export{O as createCookieGetter,Y as deleteSessionCookie,Q as getCookies,Z as parseCookies,I as parseSetCookieHeader,_ as setCookieCache,X as setSessionCookie};