better-auth 0.4.12-beta.2 → 0.4.12-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.
package/dist/api.js CHANGED
@@ -1,6 +1,6 @@
1
- import{APIError as Lt,createRouter as It}from"better-call";import{APIError as W}from"better-call";import{z as oe}from"zod";import{xchacha20poly1305 as Gt}from"@noble/ciphers/chacha";import{bytesToHex as Zt,hexToBytes as Wt,utf8ToBytes as Jt}from"@noble/ciphers/utils";import{managedNonce as Xt}from"@noble/ciphers/webcrypto";import{sha256 as er}from"oslo/crypto";function Z(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let s=0;s<r.length;s++)n|=r[s]^o[s];return n===0}import{decodeHex as zt,encodeHex as Vt}from"oslo/encoding";import{scryptAsync as Nt}from"@noble/hashes/scrypt";function Je(e){return e.toString(2).padStart(8,"0")}function Ke(e){return[...e].map(t=>Je(t)).join("")}function ee(e){return parseInt(Ke(e),2)}function Xe(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));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=ee(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=ee(o);return n}function j(e,t){let r="";for(let o=0;o<e;o++)r+=t[Xe(t.length)];return r}function q(...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}async function N(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),s=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(s)))}import{createEndpointCreator as Ye,createMiddleware as te,createMiddlewareCreator as et}from"better-call";var re=te(async()=>({})),D=et({use:[re,te(async()=>({}))]}),u=Ye({use:[re]});var ne=D({body:oe.object({csrfToken:oe.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(e.context.trustedOrigins.includes(t.origin))return;let r=e.body?.csrfToken;if(!r)throw new W("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,s]=o?.split("!")||[null,null];if(!r||!o||!n||!s||o!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new W("UNAUTHORIZED",{message:"Invalid CSRF Token"});let i=await N(e.context.secret,n);if(s!==i)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new W("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as O}from"better-call";import{generateCodeVerifier as wt}from"oslo/oauth2";import{z as E}from"zod";import{generateState as tt}from"oslo/oauth2";import{z as M}from"zod";import{sha256 as se}from"oslo/crypto";async function ie(e){let t=await se(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ae(e,t){let r=await se(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Z(r,o)}async function ce(e){let t=tt(),r=JSON.stringify({code:t,callbackURL:e}),o=await ie(r);return{raw:r,hash:o}}function J(e){return M.object({code:M.string(),callbackURL:M.string().optional(),currentURL:M.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as Ur}from"oslo";var I=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};async function P(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function z(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}import{APIError as de}from"better-call";import{createConsola as rt}from"consola";var C=rt({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),ot=e=>({log:(...t)=>{!e?.disabled&&C.log("",...t)},error:(...t)=>{!e?.disabled&&C.error("",...t)},warn:(...t)=>{!e?.disabled&&C.warn("",...t)},info:(...t)=>{!e?.disabled&&C.info("",...t)},debug:(...t)=>{!e?.disabled&&C.debug("",...t)},box:(...t)=>{!e?.disabled&&C.box("",...t)},success:(...t)=>{!e?.disabled&&C.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
2
- `)}}),w=ot();var U=D(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let s=new URL(t).origin;if(!n.includes(s))throw w.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new de("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let s=new URL(o).origin;if(!n.includes(s))throw w.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new de("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as at}from"oslo/jwt";import{sha256 as nt}from"oslo/crypto";import{base64url as st}from"oslo/encoding";async function pe(e){let t=await nt(new TextEncoder().encode(e));return st.encode(new Uint8Array(t),{includePadding:!1})}function ue(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function A({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:s,claims:i,disablePkce:d,redirectURI:a}){let c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",s.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||a),!d&&n){let p=await pe(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",p)}if(i){let p=i.reduce((y,f)=>(y[f]=null,y),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...p}}))}return c}import{betterFetch as it}from"@better-fetch/fetch";async function b({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let s=new URLSearchParams;s.set("grant_type","authorization_code"),s.set("code",e),t&&s.set("code_verifier",t),s.set("redirect_uri",r),s.set("client_id",o.clientId),s.set("client_secret",o.clientSecret);let{data:i,error:d}=await it(n,{method:"POST",body:s,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(d)throw d;return ue(i)}function K(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var le=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let s=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${s.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>b({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=at(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as ct}from"@better-fetch/fetch";var me=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return 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}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await ct("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as dt}from"@better-fetch/fetch";var fe=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await A({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})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await dt("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as ge}from"@better-fetch/fetch";var he=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:s}){let i=e.scope||o||["user:email"];return A({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:i,state:r,redirectURI:s,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>b({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await ge("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let s=!1;if(!o.email){let{data:i,error:d}=await ge("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});d||(o.email=(i.find(a=>a.primary)??i[0])?.email,s=i.find(a=>a.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:s},data:o}}}};import{parseJWT as pt}from"oslo/jwt";var we=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw w.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new I("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new I("codeVerifier is required for Google");let s=e.scope||r||["email","profile"];return A({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=pt(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as ut}from"@better-fetch/fetch";import{parseJWT as lt}from"oslo/jwt";var ye=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 s=e.scope||n.scopes||["openid","profile","email","User.Read"];return A({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:s,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:s,redirectURI:i}){return b({code:n,codeVerifier:s,redirectURI:e.redirectURI||i,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let s=lt(n.idToken)?.payload,i=e.profilePhotoSize||48;return await ut(`https://graph.microsoft.com/v1.0/me/photos/${i}x${i}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(d){if(!(e.disableProfilePhoto||!d.response.ok))try{let c=await d.response.clone().arrayBuffer(),p=Buffer.from(c).toString("base64");s.picture=`data:image/jpeg;base64, ${p}`}catch(a){w.error(a)}}}),{user:{id:s.sub,name:s.name,email:s.email,image:s.picture,emailVerified:!0},data:s}}}};import{betterFetch as mt}from"@better-fetch/fetch";var be=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let s=e.scope||r||["user-read-email"];return A({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await mt("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var S={isAction:!1};var Ae=e=>j(e||21,q("a-z","0-9","A-Z"));import{parseJWT as ft}from"oslo/jwt";var Re=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return A({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"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return w.error("No idToken found in token"),null;let o=ft(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as gt}from"@better-fetch/fetch";var ke=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return A({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await gt("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var ht={apple:le,discord:me,facebook:fe,github:he,microsoft:ye,google:we,spotify:be,twitch:Re,twitter:ke},Ue=Object.keys(ht);var Ee=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:E.object({currentURL:E.string().optional()}).optional(),body:E.object({callbackURL:E.string().optional(),provider:E.enum(Ue)}),use:[U]},async e=>{let t=e.context.socialProviders.find(a=>a.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 O("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,s=await ce(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,s.hash,e.context.secret,r.state.options);let i=wt();await e.setSignedCookie(r.pkCodeVerifier.name,i,e.context.secret,r.pkCodeVerifier.options);let d=await t.createAuthorizationURL({state:s.raw,codeVerifier:i,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:d.toString(),state:s,codeVerifier:i,redirect:!0})}),xe=u("/sign-in/email",{method:"POST",body:E.object({email:E.string().email(),password:E.string(),callbackURL:E.string().optional(),dontRememberMe:E.boolean().default(!1).optional()}),use:[U]},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 O("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!E.string().email().safeParse(t).success)throw new O("BAD_REQUEST",{message:"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 O("UNAUTHORIZED",{message:"Invalid email or password"});let s=n.accounts.find(c=>c.providerId==="credential");if(!s)throw e.context.logger.error("Credential account not found",{email:t}),new O("UNAUTHORIZED",{message:"Invalid email or password"});let i=s?.password;if(!i)throw e.context.logger.error("Password not found",{email:t}),new O("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(i,r))throw e.context.logger.error("Invalid password"),new O("UNAUTHORIZED",{message:"Invalid email or password"});let a=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!a)throw e.context.logger.error("Failed to create session"),new O("UNAUTHORIZED",{message:"Failed to create session"});return await P(e,a.id,e.body.dontRememberMe),e.json({user:n.user,session:a,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as bt}from"better-call";import{z as F}from"zod";import{z as l}from"zod";var An=l.object({id:l.string(),providerId:l.string(),accountId:l.string(),userId:l.string(),accessToken:l.string().nullable().optional(),refreshToken:l.string().nullable().optional(),idToken:l.string().nullable().optional(),expiresAt:l.date().nullable().optional(),password:l.string().optional().nullable()}),Pe=l.object({id:l.string(),email:l.string().transform(e=>e.toLowerCase()),emailVerified:l.boolean().default(!1),name:l.string(),image:l.string().optional(),createdAt:l.date().default(new Date),updatedAt:l.date().default(new Date)}),Rn=l.object({id:l.string(),userId:l.string(),expiresAt:l.date(),ipAddress:l.string().optional(),userAgent:l.string().optional()}),kn=l.object({id:l.string(),value:l.string(),expiresAt:l.date(),identifier:l.string()});function yt(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Te(e,t){let r={...e.user?.additionalFields};return yt(t||{},{fields:r})}var ve=u("/callback/:id",{method:"GET",query:F.object({state:F.string(),code:F.string().optional(),error:F.string().optional()}),metadata:S},async e=>{if(e.query.error||!e.query.code){let h=J(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${h}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(m=>m.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=J(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,s=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!s)throw w.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ae(e.query.state,s))throw w.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let d=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),a;try{a=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:d,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(m){throw e.context.logger.error(m),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(a).then(m=>m?.user),p=Ae(),y=Pe.safeParse({...c,id:p});if(!c||y.success===!1)throw w.error("Unable to get user info",y.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let f=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(m=>{throw w.error(`Better auth was unable to query your database.
3
- Error: `,m),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),g=f?.user.id;if(f){let m=f.accounts.find(k=>k.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,R=h?h.includes(t.id):!0;if(!m&&(!c.emailVerified||!R)){let k;try{k=new URL(n||o),k.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(k.toString())}if(!m)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:f.user.id,...K(a)})}catch(k){throw console.log(k),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{await e.context.internalAdapter.createOAuthUser(y.data,{...K(a),id:`${t.id}:${c.id}`,providerId:t.id,accountId:c.id.toString(),userId:p})}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",h.toString()),e.redirect(h.toString())}if(!g&&!p)throw new bt("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let m=await e.context.internalAdapter.createSession(g||p,e.request);if(!m){let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_session"),e.redirect(h.toString())}try{await P(e,m.id)}catch(h){e.context.logger.error("Unable to set session cookie",h);let R=new URL(n||o);throw R.searchParams.set("error","unable_to_create_session"),e.redirect(R.toString())}}catch{let m=new URL(n||o||"");throw m.searchParams.set("error","unable_to_create_session"),e.redirect(m.toString())}throw e.redirect(o)});import{APIError as V}from"better-call";var H=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as _e}from"zod";var X=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return z(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,s=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+s*1e3<=Date.now()){let a=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:H(e.context.sessionConfig.expiresIn,"sec")});if(!a)return z(e),e.json(null,{status:401});let c=(a.expiresAt.valueOf()-Date.now())/1e3;return await P(e,a.id,!1,{maxAge:c}),e.json({session:a,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),At=async e=>await X()({...e,_flag:"json",headers:e.headers}),L=D(async e=>{let t=await At(e);if(!t?.session)throw new V("UNAUTHORIZED");return{session:t}}),Se=()=>u("/user/list-sessions",{method:"GET",use:[L],requireHeaders:!0},async e=>{let r=(await e.context.internalAdapter.listSessions(e.context.session.user.id)).filter(o=>o.expiresAt>new Date);return e.json(r)}),Oe=u("/user/revoke-session",{method:"POST",body:_e.object({id:_e.string()}),use:[L],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new V("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new V("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new V("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Le=u("/user/revoke-sessions",{method:"POST",use:[L],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new V("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import"zod";import{APIError as Rt}from"better-call";var Ie=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Rt("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),z(e),e.json({success:!0})});import{z as _}from"zod";import{APIError as G}from"better-call";var Ce=u("/forget-password",{method:"POST",body:_.object({email:_.string().email(),redirectTo:_.string()}),use:[U]},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 G("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,s=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),i=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${i}`,expiresAt:s});let d=`${e.context.baseURL}/reset-password/${i}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(d,o.user),e.json({status:!0})}),Be=u("/reset-password/:token",{method:"GET",query:_.object({callbackURL:_.string()}),use:[U]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),De=u("/reset-password",{query:_.object({token:_.string()}).optional(),method:"POST",body:_.object({newPassword:_.string()})},async e=>{let t=e.query?.token;if(!t)throw new G("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new G("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let s=n.value,i=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(s)).find(p=>p.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:s,providerId:"credential",password:i,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(s,i))throw new G("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{TimeSpan as kt}from"oslo";import{createJWT as Ut,validateJWT as Et}from"oslo/jwt";import{z as T}from"zod";import{APIError as Q}from"better-call";async function Y(e,t){return await Ut("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new kt(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var $e=u("/send-verification-email",{method:"POST",query:T.object({currentURL:T.string().optional()}).optional(),body:T.object({email:T.string().email(),callbackURL:T.string().optional()}),use:[U]},async e=>{if(!e.context.options.emailAndPassword?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new Q("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new Q("BAD_REQUEST",{message:"User not found"});let o=await Y(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailAndPassword.sendVerificationEmail(n,r.user,o),e.json({status:!0})}),ze=u("/verify-email",{method:"GET",query:T.object({token:T.string(),callbackURL:T.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await Et("HS256",Buffer.from(e.context.secret),t)}catch(i){throw e.context.logger.error("Failed to verify email",i),new Q("BAD_REQUEST",{message:"Invalid token"})}let n=T.object({email:T.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new Q("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});import{z as x}from"zod";import{APIError as v}from"better-call";var Ve=u("/user/update",{method:"POST",body:x.object({name:x.string().optional(),image:x.string().optional()}),use:[L,U]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),je=u("/user/change-password",{method:"POST",body:x.object({newPassword:x.string(),currentPassword:x.string(),revokeOtherSessions:x.boolean().optional()}),use:[L]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,s=e.context.password.config.minPasswordLength;if(t.length<s)throw e.context.logger.error("Password is too short"),new v("BAD_REQUEST",{message:"Password is too short"});let i=e.context.password.config.maxPasswordLength;if(t.length>i)throw e.context.logger.error("Password is too long"),new v("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(n.user.id)).find(y=>y.providerId==="credential"&&y.password);if(!a||!a.password)throw new v("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(a.password,r))throw new v("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(a.id,{password:c}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let y=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!y)throw new v("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await P(e,y.id)}return e.json(n.user)}),qe=u("/user/set-password",{method:"POST",body:x.object({newPassword:x.string()}),use:[L]},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 v("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new v("BAD_REQUEST",{message:"Password too long"});let i=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password),d=await e.context.password.hash(t);if(!i)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:d}),e.json(r.user);throw new v("BAD_REQUEST",{message:"user already has a password"})}),Ne=u("/user/delete",{method:"POST",body:x.object({password:x.string()}),use:[L]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(i=>i.providerId==="credential"&&i.password);if(!n||!n.password)throw new v("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new v("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)});var Me=u("/csrf",{method:"GET",metadata:S},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t)return{csrfToken:t};let r=j(32,q("a-z","0-9","A-Z")),o=await N(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:r}});var xt=(e="Unknown")=>`<!DOCTYPE html>
1
+ import{APIError as Lt,createRouter as It}from"better-call";import{APIError as W}from"better-call";import{z as oe}from"zod";import{xchacha20poly1305 as Gt}from"@noble/ciphers/chacha";import{bytesToHex as Zt,hexToBytes as Wt,utf8ToBytes as Jt}from"@noble/ciphers/utils";import{managedNonce as Xt}from"@noble/ciphers/webcrypto";import{sha256 as er}from"oslo/crypto";function Z(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let s=0;s<r.length;s++)n|=r[s]^o[s];return n===0}import{decodeHex as zt,encodeHex as Vt}from"oslo/encoding";import{scryptAsync as Nt}from"@noble/hashes/scrypt";function Je(e){return e.toString(2).padStart(8,"0")}function Ke(e){return[...e].map(t=>Je(t)).join("")}function ee(e){return parseInt(Ke(e),2)}function Xe(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));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=ee(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=ee(o);return n}function j(e,t){let r="";for(let o=0;o<e;o++)r+=t[Xe(t.length)];return r}function q(...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}async function N(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),s=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(s)))}import{createEndpointCreator as Ye,createMiddleware as te,createMiddlewareCreator as et}from"better-call";var re=te(async()=>({})),D=et({use:[re,te(async()=>({}))]}),u=Ye({use:[re]});var ne=D({body:oe.object({csrfToken:oe.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(e.context.trustedOrigins.includes(t.origin))return;let r=e.body?.csrfToken;if(!r)throw new W("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,s]=o?.split("!")||[null,null];if(!r||!o||!n||!s||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new W("UNAUTHORIZED",{message:"Invalid CSRF Token"});let i=await N(e.context.secret,n);if(s!==i)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new W("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as O}from"better-call";import{generateCodeVerifier as wt}from"oslo/oauth2";import{z as E}from"zod";import{generateState as tt}from"oslo/oauth2";import{z as M}from"zod";import{sha256 as se}from"oslo/crypto";async function ie(e){let t=await se(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ae(e,t){let r=await se(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Z(r,o)}async function ce(e){let t=tt(),r=JSON.stringify({code:t,callbackURL:e}),o=await ie(r);return{raw:r,hash:o}}function J(e){return M.object({code:M.string(),callbackURL:M.string().optional(),currentURL:M.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as Ur}from"oslo";var I=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};async function P(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function z(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}import{APIError as de}from"better-call";import{createConsola as rt}from"consola";var C=rt({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),ot=e=>({log:(...t)=>{!e?.disabled&&C.log("",...t)},error:(...t)=>{!e?.disabled&&C.error("",...t)},warn:(...t)=>{!e?.disabled&&C.warn("",...t)},info:(...t)=>{!e?.disabled&&C.info("",...t)},debug:(...t)=>{!e?.disabled&&C.debug("",...t)},box:(...t)=>{!e?.disabled&&C.box("",...t)},success:(...t)=>{!e?.disabled&&C.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
2
+ `)}}),w=ot();var U=D(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let s=new URL(t).origin;if(!n.includes(s))throw w.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new de("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let s=new URL(o).origin;if(!n.includes(s))throw w.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new de("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as at}from"oslo/jwt";import{sha256 as nt}from"oslo/crypto";import{base64url as st}from"oslo/encoding";async function pe(e){let t=await nt(new TextEncoder().encode(e));return st.encode(new Uint8Array(t),{includePadding:!1})}function ue(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function A({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:s,claims:i,disablePkce:d,redirectURI:a}){let c=new URL(r);if(c.searchParams.set("response_type","code"),c.searchParams.set("client_id",t.clientId),c.searchParams.set("state",o),c.searchParams.set("scope",s.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||a),!d&&n){let p=await pe(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",p)}if(i){let p=i.reduce((y,f)=>(y[f]=null,y),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...p}}))}return c}import{betterFetch as it}from"@better-fetch/fetch";async function b({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let s=new URLSearchParams;s.set("grant_type","authorization_code"),s.set("code",e),t&&s.set("code_verifier",t),s.set("redirect_uri",r),s.set("client_id",o.clientId),s.set("client_secret",o.clientSecret);let{data:i,error:d}=await it(n,{method:"POST",body:s,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(d)throw d;return ue(i)}function K(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var le=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let s=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${s.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>b({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=at(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as ct}from"@better-fetch/fetch";var me=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return 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}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await ct("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as dt}from"@better-fetch/fetch";var fe=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await A({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})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await dt("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as ge}from"@better-fetch/fetch";var he=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:s}){let i=e.scope||o||["user:email"];return A({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:i,state:r,redirectURI:s,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>b({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await ge("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let s=!1;if(!o.email){let{data:i,error:d}=await ge("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});d||(o.email=(i.find(a=>a.primary)??i[0])?.email,s=i.find(a=>a.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:s},data:o}}}};import{parseJWT as pt}from"oslo/jwt";var we=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw w.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new I("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new I("codeVerifier is required for Google");let s=e.scope||r||["email","profile"];return A({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=pt(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as ut}from"@better-fetch/fetch";import{parseJWT as lt}from"oslo/jwt";var ye=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 s=e.scope||n.scopes||["openid","profile","email","User.Read"];return A({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:s,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:s,redirectURI:i}){return b({code:n,codeVerifier:s,redirectURI:e.redirectURI||i,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let s=lt(n.idToken)?.payload,i=e.profilePhotoSize||48;return await ut(`https://graph.microsoft.com/v1.0/me/photos/${i}x${i}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(d){if(!(e.disableProfilePhoto||!d.response.ok))try{let c=await d.response.clone().arrayBuffer(),p=Buffer.from(c).toString("base64");s.picture=`data:image/jpeg;base64, ${p}`}catch(a){w.error(a)}}}),{user:{id:s.sub,name:s.name,email:s.email,image:s.picture,emailVerified:!0},data:s}}}};import{betterFetch as mt}from"@better-fetch/fetch";var be=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let s=e.scope||r||["user-read-email"];return A({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await mt("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var S={isAction:!1};var Ae=e=>j(e||21,q("a-z","0-9","A-Z"));import{parseJWT as ft}from"oslo/jwt";var Re=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return A({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})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return w.error("No idToken found in token"),null;let o=ft(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as gt}from"@better-fetch/fetch";var ke=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return A({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await gt("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var ht={apple:le,discord:me,facebook:fe,github:he,microsoft:ye,google:we,spotify:be,twitch:Re,twitter:ke},Ue=Object.keys(ht);var Ee=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:E.object({currentURL:E.string().optional()}).optional(),body:E.object({callbackURL:E.string().optional(),provider:E.enum(Ue)}),use:[U]},async e=>{let t=e.context.socialProviders.find(a=>a.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 O("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,s=await ce(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,s.hash,e.context.secret,r.state.options);let i=wt();await e.setSignedCookie(r.pkCodeVerifier.name,i,e.context.secret,r.pkCodeVerifier.options);let d=await t.createAuthorizationURL({state:s.raw,codeVerifier:i,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:d.toString(),state:s,codeVerifier:i,redirect:!0})}),xe=u("/sign-in/email",{method:"POST",body:E.object({email:E.string().email(),password:E.string(),callbackURL:E.string().optional(),dontRememberMe:E.boolean().default(!1).optional()}),use:[U]},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 O("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!E.string().email().safeParse(t).success)throw new O("BAD_REQUEST",{message:"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 O("UNAUTHORIZED",{message:"Invalid email or password"});let s=n.accounts.find(c=>c.providerId==="credential");if(!s)throw e.context.logger.error("Credential account not found",{email:t}),new O("UNAUTHORIZED",{message:"Invalid email or password"});let i=s?.password;if(!i)throw e.context.logger.error("Password not found",{email:t}),new O("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(i,r))throw e.context.logger.error("Invalid password"),new O("UNAUTHORIZED",{message:"Invalid email or password"});let a=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!a)throw e.context.logger.error("Failed to create session"),new O("UNAUTHORIZED",{message:"Failed to create session"});return await P(e,a.id,e.body.dontRememberMe),e.json({user:n.user,session:a,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as bt}from"better-call";import{z as F}from"zod";import{z as l}from"zod";var An=l.object({id:l.string(),providerId:l.string(),accountId:l.string(),userId:l.string(),accessToken:l.string().nullable().optional(),refreshToken:l.string().nullable().optional(),idToken:l.string().nullable().optional(),expiresAt:l.date().nullable().optional(),password:l.string().optional().nullable()}),Pe=l.object({id:l.string(),email:l.string().transform(e=>e.toLowerCase()),emailVerified:l.boolean().default(!1),name:l.string(),image:l.string().optional(),createdAt:l.date().default(new Date),updatedAt:l.date().default(new Date)}),Rn=l.object({id:l.string(),userId:l.string(),expiresAt:l.date(),ipAddress:l.string().optional(),userAgent:l.string().optional()}),kn=l.object({id:l.string(),value:l.string(),expiresAt:l.date(),identifier:l.string()});function yt(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Te(e,t){let r={...e.user?.additionalFields};return yt(t||{},{fields:r})}var ve=u("/callback/:id",{method:"GET",query:F.object({state:F.string(),code:F.string().optional(),error:F.string().optional()}),metadata:S},async e=>{if(e.query.error||!e.query.code){let h=J(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${h}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(m=>m.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=J(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,s=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!s)throw w.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ae(e.query.state,s))throw w.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let d=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),a;try{a=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:d,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(m){throw e.context.logger.error(m),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let c=await t.getUserInfo(a).then(m=>m?.user),p=Ae(),y=Pe.safeParse({...c,id:p});if(!c||y.success===!1)throw w.error("Unable to get user info",y.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let f=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(m=>{throw w.error(`Better auth was unable to query your database.
3
+ Error: `,m),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),g=f?.user.id;if(f){let m=f.accounts.find(k=>k.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,R=h?h.includes(t.id):!0;if(!m&&(!c.emailVerified||!R)){let k;try{k=new URL(n||o),k.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(k.toString())}if(!m)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:f.user.id,...K(a)})}catch(k){throw console.log(k),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{await e.context.internalAdapter.createOAuthUser(y.data,{...K(a),id:`${t.id}:${c.id}`,providerId:t.id,accountId:c.id.toString(),userId:p})}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",h.toString()),e.redirect(h.toString())}if(!g&&!p)throw new bt("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let m=await e.context.internalAdapter.createSession(g||p,e.request);if(!m){let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_session"),e.redirect(h.toString())}try{await P(e,m.id)}catch(h){e.context.logger.error("Unable to set session cookie",h);let R=new URL(n||o);throw R.searchParams.set("error","unable_to_create_session"),e.redirect(R.toString())}}catch{let m=new URL(n||o||"");throw m.searchParams.set("error","unable_to_create_session"),e.redirect(m.toString())}throw e.redirect(o)});import{APIError as V}from"better-call";var H=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as _e}from"zod";var X=()=>u("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return z(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,s=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+s*1e3<=Date.now()){let a=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:H(e.context.sessionConfig.expiresIn,"sec")});if(!a)return z(e),e.json(null,{status:401});let c=(a.expiresAt.valueOf()-Date.now())/1e3;return await P(e,a.id,!1,{maxAge:c}),e.json({session:a,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),At=async e=>await X()({...e,_flag:"json",headers:e.headers}),L=D(async e=>{let t=await At(e);if(!t?.session)throw new V("UNAUTHORIZED");return{session:t}}),Se=()=>u("/user/list-sessions",{method:"GET",use:[L],requireHeaders:!0},async e=>{let r=(await e.context.internalAdapter.listSessions(e.context.session.user.id)).filter(o=>o.expiresAt>new Date);return e.json(r)}),Oe=u("/user/revoke-session",{method:"POST",body:_e.object({id:_e.string()}),use:[L],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new V("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new V("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new V("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Le=u("/user/revoke-sessions",{method:"POST",use:[L],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new V("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import"zod";import{APIError as Rt}from"better-call";var Ie=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Rt("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),z(e),e.json({success:!0})});import{z as _}from"zod";import{APIError as G}from"better-call";var Ce=u("/forget-password",{method:"POST",body:_.object({email:_.string().email(),redirectTo:_.string()}),use:[U]},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 G("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,s=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),i=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${i}`,expiresAt:s});let d=`${e.context.baseURL}/reset-password/${i}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(d,o.user),e.json({status:!0})}),Be=u("/reset-password/:token",{method:"GET",query:_.object({callbackURL:_.string()}),use:[U]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),De=u("/reset-password",{query:_.object({token:_.string()}).optional(),method:"POST",body:_.object({newPassword:_.string()})},async e=>{let t=e.query?.token;if(!t)throw new G("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new G("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let s=n.value,i=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(s)).find(p=>p.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:s,providerId:"credential",password:i,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(s,i))throw new G("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{TimeSpan as kt}from"oslo";import{createJWT as Ut,validateJWT as Et}from"oslo/jwt";import{z as T}from"zod";import{APIError as Q}from"better-call";async function Y(e,t){return await Ut("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new kt(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var $e=u("/send-verification-email",{method:"POST",query:T.object({currentURL:T.string().optional()}).optional(),body:T.object({email:T.string().email(),callbackURL:T.string().optional()}),use:[U]},async e=>{if(!e.context.options.emailAndPassword?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new Q("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new Q("BAD_REQUEST",{message:"User not found"});let o=await Y(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailAndPassword.sendVerificationEmail(n,r.user,o),e.json({status:!0})}),ze=u("/verify-email",{method:"GET",query:T.object({token:T.string(),callbackURL:T.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await Et("HS256",Buffer.from(e.context.secret),t)}catch(i){throw e.context.logger.error("Failed to verify email",i),new Q("BAD_REQUEST",{message:"Invalid token"})}let n=T.object({email:T.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new Q("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});import{z as x}from"zod";import{APIError as v}from"better-call";var Ve=u("/user/update",{method:"POST",body:x.object({name:x.string().optional(),image:x.string().optional()}),use:[L,U]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),je=u("/user/change-password",{method:"POST",body:x.object({newPassword:x.string(),currentPassword:x.string(),revokeOtherSessions:x.boolean().optional()}),use:[L]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,s=e.context.password.config.minPasswordLength;if(t.length<s)throw e.context.logger.error("Password is too short"),new v("BAD_REQUEST",{message:"Password is too short"});let i=e.context.password.config.maxPasswordLength;if(t.length>i)throw e.context.logger.error("Password is too long"),new v("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(n.user.id)).find(y=>y.providerId==="credential"&&y.password);if(!a||!a.password)throw new v("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(a.password,r))throw new v("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(a.id,{password:c}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let y=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!y)throw new v("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await P(e,y.id)}return e.json(n.user)}),qe=u("/user/set-password",{method:"POST",body:x.object({newPassword:x.string()}),use:[L]},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 v("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new v("BAD_REQUEST",{message:"Password too long"});let i=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password),d=await e.context.password.hash(t);if(!i)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:d}),e.json(r.user);throw new v("BAD_REQUEST",{message:"user already has a password"})}),Ne=u("/user/delete",{method:"POST",body:x.object({password:x.string()}),use:[L]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(i=>i.providerId==="credential"&&i.password);if(!n||!n.password)throw new v("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new v("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)});var Me=u("/csrf",{method:"GET",metadata:S},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t){let[s,i]=t.split("!")||[null,null];return{csrfToken:s}}let r=j(32,q("a-z","0-9","A-Z")),o=await N(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:r}});var xt=(e="Unknown")=>`<!DOCTYPE html>
4
4
  <html lang="en">
5
5
  <head>
6
6
  <meta charset="UTF-8">
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import{APIError as pr,createRouter as fr}from"better-call";import{APIError as re}from"better-call";import{z as ke}from"zod";import{xchacha20poly1305 as Er}from"@noble/ciphers/chacha";import{bytesToHex as Or,hexToBytes as Sr,utf8ToBytes as Ir}from"@noble/ciphers/utils";import{managedNonce as _r}from"@noble/ciphers/webcrypto";import{sha256 as Br}from"oslo/crypto";function K(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let s=0;s<r.length;s++)n|=r[s]^o[s];return n===0}import{decodeHex as Pt,encodeHex as ge}from"oslo/encoding";import{scryptAsync as Ot}from"@noble/hashes/scrypt";var q={N:16384,r:16,p:1,dkLen:64};async function he(e,t){return await Ot(e.normalize("NFKC"),t,{N:q.N,p:q.p,r:q.r,dkLen:q.dkLen,maxmem:128*q.N*q.r*2})}var ye=async e=>{let t=ge(crypto.getRandomValues(new Uint8Array(16))),r=await he(e,t);return`${t}:${ge(r)}`},we=async(e,t)=>{let[r,o]=e.split(":"),n=await he(t,r);return K(n,Pt(o))};function St(e){return e.toString(2).padStart(8,"0")}function It(e){return[...e].map(t=>St(t)).join("")}function be(e){return parseInt(It(e),2)}function Lt(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));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=be(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=be(o);return n}function G(e,t){let r="";for(let o=0;o<e;o++)r+=t[Lt(t.length)];return r}function Z(...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}async function W(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),s=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(s)))}import{createEndpointCreator as _t,createMiddleware as Ae,createMiddlewareCreator as Ct}from"better-call";var Re=Ae(async()=>({})),V=Ct({use:[Re,Ae(async()=>({}))]}),h=_t({use:[Re]});var xe=V({body:ke.object({csrfToken:ke.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(e.context.trustedOrigins.includes(t.origin))return;let r=e.body?.csrfToken;if(!r)throw new re("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,s]=o?.split("!")||[null,null];if(!r||!o||!n||!s||o!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new re("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await W(e.context.secret,n);if(s!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new re("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as C}from"better-call";import{generateCodeVerifier as Jt}from"oslo/oauth2";import{z as v}from"zod";import{generateState as Bt}from"oslo/oauth2";import{z as Q}from"zod";import{sha256 as Te}from"oslo/crypto";async function Ue(e){let t=await Te(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ve(e,t){let r=await Te(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return K(r,o)}async function Ee(e){let t=Bt(),r=JSON.stringify({code:t,callbackURL:e}),o=await Ue(r);return{raw:r,hash:o}}function oe(e){return Q.object({code:Q.string(),callbackURL:Q.string().optional(),currentURL:Q.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as Dt}from"oslo";var R=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}},Pe=class extends R{constructor(t){super(`The package "${t}" is required. Make sure it is installed.`,t)}};function Oe(e){let r=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:(e.baseURL?e.baseURL.startsWith("https://"):!1)||process.env.NODE_ENV==="production")?"__Secure-":"",o="better-auth",n=e.session?.expiresIn||new Dt(7,"d").seconds(),s=!!e.advanced?.crossSubDomainCookies?.enabled,a=s?e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0):void 0;if(s&&!a)throw new R("baseURL is required when crossSubdomainCookies are enabled");let c=s?"none":"lax";return{sessionToken:{name:`${r}${o}.session_token`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:n,...s?{domain:a}:{}}},csrfToken:{name:`${r}${o}.csrf_token`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*60*24*7,...s?{domain:a}:{}}},state:{name:`${r}${o}.state`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*15,...s?{domain:a}:{}}},pkCodeVerifier:{name:`${r}${o}.pk_code_verifier`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*15,...s?{domain:a}:{}}},dontRememberToken:{name:`${r}${o}.dont_remember`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,...s?{domain:a}:{}}},nonce:{name:`${r}${o}.nonce`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*15,...s?{domain:a}:{}}}}}function Se(e){let r=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:e.baseURL?.startsWith("https://")||process.env.NODE_ENV==="production")?"__Secure-":"",o="better-auth",n=e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0);function s(a,c){let i=e.advanced?.crossSubDomainCookies?.enabled?e.advanced.crossSubDomainCookies.additionalCookies?.includes(a):void 0;return{name:process.env.NODE_ENV==="production"?`${r}${o}.${a}`:`${o}.${a}`,options:{secure:!!r,sameSite:"lax",path:"/",maxAge:60*15,...c,...i?{domain:n}:{}}}}return s}async function P(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function j(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function so(e){let t=new Map;return e.split(", ").forEach(o=>{let[n,...s]=o.split("; "),[a,c]=n.split("="),i={value:c};s.forEach(d=>{let[l,p]=d.split("=");i[l.toLowerCase()]=p||!0}),t.set(a,i)}),t}import{APIError as Ie}from"better-call";import{createConsola as Nt}from"consola";var D=Nt({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),ne=e=>({log:(...t)=>{!e?.disabled&&D.log("",...t)},error:(...t)=>{!e?.disabled&&D.error("",...t)},warn:(...t)=>{!e?.disabled&&D.warn("",...t)},info:(...t)=>{!e?.disabled&&D.info("",...t)},debug:(...t)=>{!e?.disabled&&D.debug("",...t)},box:(...t)=>{!e?.disabled&&D.box("",...t)},success:(...t)=>{!e?.disabled&&D.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
2
- `)}}),w=ne();var T=V(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let s=new URL(t).origin;if(!n.includes(s))throw w.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new Ie("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let s=new URL(o).origin;if(!n.includes(s))throw w.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new Ie("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as jt}from"oslo/jwt";import{sha256 as qt}from"oslo/crypto";function Ft(e){try{return new URL(e).pathname!=="/"}catch{throw new R(`Invalid base URL: ${e}. Please provide a valid base URL.`)}}function se(e,t="/api/auth"){return Ft(e)?e:(t=t.startsWith("/")?t:`/${t}`,`${e}${t}`)}function z(e,t){if(e)return se(e,t);let r=typeof process<"u"?process.env:{},o=r.BETTER_AUTH_URL||r.NEXT_PUBLIC_BETTER_AUTH_URL||r.PUBLIC_BETTER_AUTH_URL||r.NUXT_PUBLIC_BETTER_AUTH_URL||r.NUXT_PUBLIC_AUTH_URL||(r.BASE_URL!=="/"?r.BASE_URL:void 0);if(o)return se(o,t);if(typeof window<"u")return se(window.location.origin,t)}import{base64url as Vt}from"oslo/encoding";async function Le(e){let t=await qt(new TextEncoder().encode(e));return Vt.encode(new Uint8Array(t),{includePadding:!1})}function _e(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function k({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:s,claims:a,disablePkce:c,redirectURI:i}){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",s.join(" ")),d.searchParams.set("redirect_uri",t.redirectURI||i),!c&&n){let l=await Le(n);d.searchParams.set("code_challenge_method","S256"),d.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,u)=>(p[u]=null,p),{});d.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return d}import{betterFetch as $t}from"@better-fetch/fetch";async function b({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let s=new URLSearchParams;s.set("grant_type","authorization_code"),s.set("code",e),t&&s.set("code_verifier",t),s.set("redirect_uri",r),s.set("client_id",o.clientId),s.set("client_secret",o.clientSecret);let{data:a,error:c}=await $t(n,{method:"POST",body:s,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(c)throw c;return _e(a)}function ie(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var Ce=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let s=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${s.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>b({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=jt(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as zt}from"@better-fetch/fetch";var Be=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return 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}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await zt("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Mt}from"@better-fetch/fetch";var De=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await k({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})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Mt("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as Ne}from"@better-fetch/fetch";var Fe=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:s}){let a=e.scope||o||["user:email"];return k({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:s,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>b({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await Ne("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let s=!1;if(!o.email){let{data:a,error:c}=await Ne("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});c||(o.email=(a.find(i=>i.primary)??a[0])?.email,s=a.find(i=>i.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:s},data:o}}}};import{parseJWT as Ht}from"oslo/jwt";var qe=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw w.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new R("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new R("codeVerifier is required for Google");let s=e.scope||r||["email","profile"];return k({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=Ht(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as Kt}from"@better-fetch/fetch";import{parseJWT as Gt}from"oslo/jwt";var Ve=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 s=e.scope||n.scopes||["openid","profile","email","User.Read"];return k({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:s,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:s,redirectURI:a}){return b({code:n,codeVerifier:s,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let s=Gt(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Kt(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(c){if(!(e.disableProfilePhoto||!c.response.ok))try{let d=await c.response.clone().arrayBuffer(),l=Buffer.from(d).toString("base64");s.picture=`data:image/jpeg;base64, ${l}`}catch(i){w.error(i)}}}),{user:{id:s.sub,name:s.name,email:s.email,image:s.picture,emailVerified:!0},data:s}}}};import{betterFetch as Zt}from"@better-fetch/fetch";var $e=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let s=e.scope||r||["user-read-email"];return k({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await Zt("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";function sn(e){return e.charAt(0).toUpperCase()+e.slice(1)}var _={isAction:!1};var U=e=>G(e||21,Z("a-z","0-9","A-Z"));import{parseJWT as Wt}from"oslo/jwt";var je=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return k({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"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return w.error("No idToken found in token"),null;let o=Wt(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Qt}from"@better-fetch/fetch";var ze=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return k({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Qt("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var ae={apple:Ce,discord:Be,facebook:De,github:Fe,microsoft:Ve,google:qe,spotify:$e,twitch:je,twitter:ze},Me=Object.keys(ae);var He=h("/sign-in/social",{method:"POST",requireHeaders:!0,query:v.object({currentURL:v.string().optional()}).optional(),body:v.object({callbackURL:v.string().optional(),provider:v.enum(Me)}),use:[T]},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 C("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,s=await Ee(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,s.hash,e.context.secret,r.state.options);let a=Jt();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let c=await t.createAuthorizationURL({state:s.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:c.toString(),state:s,codeVerifier:a,redirect:!0})}),Ke=h("/sign-in/email",{method:"POST",body:v.object({email:v.string().email(),password:v.string(),callbackURL:v.string().optional(),dontRememberMe:v.boolean().default(!1).optional()}),use:[T]},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 C("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!v.string().email().safeParse(t).success)throw new C("BAD_REQUEST",{message:"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 C("UNAUTHORIZED",{message:"Invalid email or password"});let s=n.accounts.find(d=>d.providerId==="credential");if(!s)throw e.context.logger.error("Credential account not found",{email:t}),new C("UNAUTHORIZED",{message:"Invalid email or password"});let a=s?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new C("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new C("UNAUTHORIZED",{message:"Invalid email or password"});let i=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!i)throw e.context.logger.error("Failed to create session"),new C("UNAUTHORIZED",{message:"Failed to create session"});return await P(e,i.id,e.body.dontRememberMe),e.json({user:n.user,session:i,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as Yt}from"better-call";import{z as J}from"zod";import{z as y}from"zod";var rs=y.object({id:y.string(),providerId:y.string(),accountId:y.string(),userId:y.string(),accessToken:y.string().nullable().optional(),refreshToken:y.string().nullable().optional(),idToken:y.string().nullable().optional(),expiresAt:y.date().nullable().optional(),password:y.string().optional().nullable()}),Ge=y.object({id:y.string(),email:y.string().transform(e=>e.toLowerCase()),emailVerified:y.boolean().default(!1),name:y.string(),image:y.string().optional(),createdAt:y.date().default(new Date),updatedAt:y.date().default(new Date)}),os=y.object({id:y.string(),userId:y.string(),expiresAt:y.date(),ipAddress:y.string().optional(),userAgent:y.string().optional()}),ns=y.object({id:y.string(),value:y.string(),expiresAt:y.date(),identifier:y.string()});function Xt(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Ze(e,t){let r={...e.user?.additionalFields};return Xt(t||{},{fields:r})}var We=h("/callback/:id",{method:"GET",query:J.object({state:J.string(),code:J.string().optional(),error:J.string().optional()}),metadata:_},async e=>{if(e.query.error||!e.query.code){let g=oe(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${g}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(f=>f.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=oe(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,s=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!s)throw w.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ve(e.query.state,s))throw w.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let c=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),i;try{i=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:c,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(f){throw e.context.logger.error(f),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let d=await t.getUserInfo(i).then(f=>f?.user),l=U(),p=Ge.safeParse({...d,id:l});if(!d||p.success===!1)throw w.error("Unable to get user info",p.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let u=await e.context.internalAdapter.findUserByEmail(d.email,{includeAccounts:!0}).catch(f=>{throw w.error(`Better auth was unable to query your database.
3
- Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=u?.user.id;if(u){let f=u.accounts.find(x=>x.providerId===t.id),g=e.context.options.account?.accountLinking?.trustedProviders,A=g?g.includes(t.id):!0;if(!f&&(!d.emailVerified||!A)){let x;try{x=new URL(n||o),x.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(x.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:d.id.toString(),id:`${t.id}:${d.id}`,userId:u.user.id,...ie(i)})}catch(x){throw console.log(x),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{await e.context.internalAdapter.createOAuthUser(p.data,{...ie(i),id:`${t.id}:${d.id}`,providerId:t.id,accountId:d.id.toString(),userId:l})}catch{let g=new URL(n||o);throw g.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",g.toString()),e.redirect(g.toString())}if(!m&&!l)throw new Yt("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let f=await e.context.internalAdapter.createSession(m||l,e.request);if(!f){let g=new URL(n||o);throw g.searchParams.set("error","unable_to_create_session"),e.redirect(g.toString())}try{await P(e,f.id)}catch(g){e.context.logger.error("Unable to set session cookie",g);let A=new URL(n||o);throw A.searchParams.set("error","unable_to_create_session"),e.redirect(A.toString())}}catch{let f=new URL(n||o||"");throw f.searchParams.set("error","unable_to_create_session"),e.redirect(f.toString())}throw e.redirect(o)});import{APIError as M}from"better-call";var N=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Qe}from"zod";var de=()=>h("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return j(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,s=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+s*1e3<=Date.now()){let i=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:N(e.context.sessionConfig.expiresIn,"sec")});if(!i)return j(e),e.json(null,{status:401});let d=(i.expiresAt.valueOf()-Date.now())/1e3;return await P(e,i.id,!1,{maxAge:d}),e.json({session:i,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),er=async e=>await de()({...e,_flag:"json",headers:e.headers}),B=V(async e=>{let t=await er(e);if(!t?.session)throw new M("UNAUTHORIZED");return{session:t}}),Je=()=>h("/user/list-sessions",{method:"GET",use:[B],requireHeaders:!0},async e=>{let r=(await e.context.internalAdapter.listSessions(e.context.session.user.id)).filter(o=>o.expiresAt>new Date);return e.json(r)}),Xe=h("/user/revoke-session",{method:"POST",body:Qe.object({id:Qe.string()}),use:[B],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new M("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new M("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new M("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Ye=h("/user/revoke-sessions",{method:"POST",use:[B],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new M("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import"zod";import{APIError as tr}from"better-call";var et=h("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new tr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),j(e),e.json({success:!0})});import{z as I}from"zod";import{APIError as X}from"better-call";var tt=h("/forget-password",{method:"POST",body:I.object({email:I.string().email(),redirectTo:I.string()}),use:[T]},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 X("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,s=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),a=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${a}`,expiresAt:s});let c=`${e.context.baseURL}/reset-password/${a}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(c,o.user),e.json({status:!0})}),rt=h("/reset-password/:token",{method:"GET",query:I.object({callbackURL:I.string()}),use:[T]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),ot=h("/reset-password",{query:I.object({token:I.string()}).optional(),method:"POST",body:I.object({newPassword:I.string()})},async e=>{let t=e.query?.token;if(!t)throw new X("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new X("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let s=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(s)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:s,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(s,a))throw new X("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{TimeSpan as rr}from"oslo";import{createJWT as or,validateJWT as nr}from"oslo/jwt";import{z as O}from"zod";import{APIError as Y}from"better-call";async function ce(e,t){return await or("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new rr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var nt=h("/send-verification-email",{method:"POST",query:O.object({currentURL:O.string().optional()}).optional(),body:O.object({email:O.string().email(),callbackURL:O.string().optional()}),use:[T]},async e=>{if(!e.context.options.emailAndPassword?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new Y("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new Y("BAD_REQUEST",{message:"User not found"});let o=await ce(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailAndPassword.sendVerificationEmail(n,r.user,o),e.json({status:!0})}),st=h("/verify-email",{method:"GET",query:O.object({token:O.string(),callbackURL:O.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await nr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new Y("BAD_REQUEST",{message:"Invalid token"})}let n=O.object({email:O.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new Y("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});import{z as E}from"zod";import{APIError as S}from"better-call";var it=h("/user/update",{method:"POST",body:E.object({name:E.string().optional(),image:E.string().optional()}),use:[B,T]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),at=h("/user/change-password",{method:"POST",body:E.object({newPassword:E.string(),currentPassword:E.string(),revokeOtherSessions:E.boolean().optional()}),use:[B]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,s=e.context.password.config.minPasswordLength;if(t.length<s)throw e.context.logger.error("Password is too short"),new S("BAD_REQUEST",{message:"Password is too short"});let a=e.context.password.config.maxPasswordLength;if(t.length>a)throw e.context.logger.error("Password is too long"),new S("BAD_REQUEST",{message:"Password too long"});let i=(await e.context.internalAdapter.findAccounts(n.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!i||!i.password)throw new S("BAD_REQUEST",{message:"User does not have a password"});let d=await e.context.password.hash(t);if(!await e.context.password.verify(i.password,r))throw new S("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(i.id,{password:d}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new S("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await P(e,p.id)}return e.json(n.user)}),dt=h("/user/set-password",{method:"POST",body:E.object({newPassword:E.string()}),use:[B]},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 S("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new S("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(r.user.id)).find(i=>i.providerId==="credential"&&i.password),c=await e.context.password.hash(t);if(!a)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:c}),e.json(r.user);throw new S("BAD_REQUEST",{message:"user already has a password"})}),ct=h("/user/delete",{method:"POST",body:E.object({password:E.string()}),use:[B]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new S("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new S("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)});var lt=h("/csrf",{method:"GET",metadata:_},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t)return{csrfToken:t};let r=G(32,Z("a-z","0-9","A-Z")),o=await W(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:r}});var sr=(e="Unknown")=>`<!DOCTYPE html>
1
+ import{APIError as pr,createRouter as fr}from"better-call";import{APIError as re}from"better-call";import{z as Re}from"zod";import{xchacha20poly1305 as Er}from"@noble/ciphers/chacha";import{bytesToHex as Or,hexToBytes as Sr,utf8ToBytes as Ir}from"@noble/ciphers/utils";import{managedNonce as _r}from"@noble/ciphers/webcrypto";import{sha256 as Br}from"oslo/crypto";function K(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let s=0;s<r.length;s++)n|=r[s]^o[s];return n===0}import{decodeHex as Pt,encodeHex as ge}from"oslo/encoding";import{scryptAsync as Ot}from"@noble/hashes/scrypt";var q={N:16384,r:16,p:1,dkLen:64};async function he(e,t){return await Ot(e.normalize("NFKC"),t,{N:q.N,p:q.p,r:q.r,dkLen:q.dkLen,maxmem:128*q.N*q.r*2})}var ye=async e=>{let t=ge(crypto.getRandomValues(new Uint8Array(16))),r=await he(e,t);return`${t}:${ge(r)}`},we=async(e,t)=>{let[r,o]=e.split(":"),n=await he(t,r);return K(n,Pt(o))};function St(e){return e.toString(2).padStart(8,"0")}function It(e){return[...e].map(t=>St(t)).join("")}function be(e){return parseInt(It(e),2)}function Lt(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));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=be(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=be(o);return n}function G(e,t){let r="";for(let o=0;o<e;o++)r+=t[Lt(t.length)];return r}function Z(...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}async function W(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),s=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(s)))}import{createEndpointCreator as _t,createMiddleware as Ae,createMiddlewareCreator as Ct}from"better-call";var ke=Ae(async()=>({})),V=Ct({use:[ke,Ae(async()=>({}))]}),h=_t({use:[ke]});var xe=V({body:Re.object({csrfToken:Re.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(e.context.trustedOrigins.includes(t.origin))return;let r=e.body?.csrfToken;if(!r)throw new re("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,s]=o?.split("!")||[null,null];if(!r||!o||!n||!s||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new re("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await W(e.context.secret,n);if(s!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new re("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as C}from"better-call";import{generateCodeVerifier as Jt}from"oslo/oauth2";import{z as v}from"zod";import{generateState as Bt}from"oslo/oauth2";import{z as Q}from"zod";import{sha256 as Te}from"oslo/crypto";async function Ue(e){let t=await Te(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ve(e,t){let r=await Te(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return K(r,o)}async function Ee(e){let t=Bt(),r=JSON.stringify({code:t,callbackURL:e}),o=await Ue(r);return{raw:r,hash:o}}function oe(e){return Q.object({code:Q.string(),callbackURL:Q.string().optional(),currentURL:Q.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as Dt}from"oslo";var k=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}},Pe=class extends k{constructor(t){super(`The package "${t}" is required. Make sure it is installed.`,t)}};function Oe(e){let r=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:(e.baseURL?e.baseURL.startsWith("https://"):!1)||process.env.NODE_ENV==="production")?"__Secure-":"",o="better-auth",n=e.session?.expiresIn||new Dt(7,"d").seconds(),s=!!e.advanced?.crossSubDomainCookies?.enabled,a=s?e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0):void 0;if(s&&!a)throw new k("baseURL is required when crossSubdomainCookies are enabled");let c=s?"none":"lax";return{sessionToken:{name:`${r}${o}.session_token`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:n,...s?{domain:a}:{}}},csrfToken:{name:`${r}${o}.csrf_token`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*60*24*7,...s?{domain:a}:{}}},state:{name:`${r}${o}.state`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*15,...s?{domain:a}:{}}},pkCodeVerifier:{name:`${r}${o}.pk_code_verifier`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*15,...s?{domain:a}:{}}},dontRememberToken:{name:`${r}${o}.dont_remember`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,...s?{domain:a}:{}}},nonce:{name:`${r}${o}.nonce`,options:{httpOnly:!0,sameSite:c,path:"/",secure:!!r,maxAge:60*15,...s?{domain:a}:{}}}}}function Se(e){let r=(e.advanced?.useSecureCookies!==void 0?e.advanced?.useSecureCookies:e.baseURL?.startsWith("https://")||process.env.NODE_ENV==="production")?"__Secure-":"",o="better-auth",n=e.advanced?.crossSubDomainCookies?.domain||(e.baseURL?new URL(e.baseURL).hostname:void 0);function s(a,c){let i=e.advanced?.crossSubDomainCookies?.enabled?e.advanced.crossSubDomainCookies.additionalCookies?.includes(a):void 0;return{name:process.env.NODE_ENV==="production"?`${r}${o}.${a}`:`${o}.${a}`,options:{secure:!!r,sameSite:"lax",path:"/",maxAge:60*15,...c,...i?{domain:n}:{}}}}return s}async function P(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function j(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function so(e){let t=new Map;return e.split(", ").forEach(o=>{let[n,...s]=o.split("; "),[a,c]=n.split("="),i={value:c};s.forEach(d=>{let[l,p]=d.split("=");i[l.toLowerCase()]=p||!0}),t.set(a,i)}),t}import{APIError as Ie}from"better-call";import{createConsola as Nt}from"consola";var D=Nt({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),ne=e=>({log:(...t)=>{!e?.disabled&&D.log("",...t)},error:(...t)=>{!e?.disabled&&D.error("",...t)},warn:(...t)=>{!e?.disabled&&D.warn("",...t)},info:(...t)=>{!e?.disabled&&D.info("",...t)},debug:(...t)=>{!e?.disabled&&D.debug("",...t)},box:(...t)=>{!e?.disabled&&D.box("",...t)},success:(...t)=>{!e?.disabled&&D.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
2
+ `)}}),w=ne();var T=V(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let s=new URL(t).origin;if(!n.includes(s))throw w.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new Ie("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let s=new URL(o).origin;if(!n.includes(s))throw w.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new Ie("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as jt}from"oslo/jwt";import{sha256 as qt}from"oslo/crypto";function Ft(e){try{return new URL(e).pathname!=="/"}catch{throw new k(`Invalid base URL: ${e}. Please provide a valid base URL.`)}}function se(e,t="/api/auth"){return Ft(e)?e:(t=t.startsWith("/")?t:`/${t}`,`${e}${t}`)}function z(e,t){if(e)return se(e,t);let r=typeof process<"u"?process.env:{},o=r.BETTER_AUTH_URL||r.NEXT_PUBLIC_BETTER_AUTH_URL||r.PUBLIC_BETTER_AUTH_URL||r.NUXT_PUBLIC_BETTER_AUTH_URL||r.NUXT_PUBLIC_AUTH_URL||(r.BASE_URL!=="/"?r.BASE_URL:void 0);if(o)return se(o,t);if(typeof window<"u")return se(window.location.origin,t)}import{base64url as Vt}from"oslo/encoding";async function Le(e){let t=await qt(new TextEncoder().encode(e));return Vt.encode(new Uint8Array(t),{includePadding:!1})}function _e(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function R({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:s,claims:a,disablePkce:c,redirectURI:i}){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",s.join(" ")),d.searchParams.set("redirect_uri",t.redirectURI||i),!c&&n){let l=await Le(n);d.searchParams.set("code_challenge_method","S256"),d.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,u)=>(p[u]=null,p),{});d.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return d}import{betterFetch as $t}from"@better-fetch/fetch";async function b({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let s=new URLSearchParams;s.set("grant_type","authorization_code"),s.set("code",e),t&&s.set("code_verifier",t),s.set("redirect_uri",r),s.set("client_id",o.clientId),s.set("client_secret",o.clientSecret);let{data:a,error:c}=await $t(n,{method:"POST",body:s,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(c)throw c;return _e(a)}function ie(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var Ce=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let s=e.scope||o||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${e.clientId}&response_type=code&redirect_uri=${n||e.redirectURI}&scope=${s.join(" ")}&state=${r}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>b({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=jt(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as zt}from"@better-fetch/fetch";var Be=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return 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}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await zt("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Mt}from"@better-fetch/fetch";var De=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await R({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})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Mt("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as Ne}from"@better-fetch/fetch";var Fe=e=>{let t="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:r,scopes:o,codeVerifier:n,redirectURI:s}){let a=e.scope||o||["user:email"];return R({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:s,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>b({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await Ne("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let s=!1;if(!o.email){let{data:a,error:c}=await Ne("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});c||(o.email=(a.find(i=>i.primary)??a[0])?.email,s=a.find(i=>i.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:s},data:o}}}};import{parseJWT as Ht}from"oslo/jwt";var qe=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw w.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new k("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new k("codeVerifier is required for Google");let s=e.scope||r||["email","profile"];return R({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=Ht(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as Kt}from"@better-fetch/fetch";import{parseJWT as Gt}from"oslo/jwt";var Ve=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 s=e.scope||n.scopes||["openid","profile","email","User.Read"];return R({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:s,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:s,redirectURI:a}){return b({code:n,codeVerifier:s,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let s=Gt(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Kt(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(c){if(!(e.disableProfilePhoto||!c.response.ok))try{let d=await c.response.clone().arrayBuffer(),l=Buffer.from(d).toString("base64");s.picture=`data:image/jpeg;base64, ${l}`}catch(i){w.error(i)}}}),{user:{id:s.sub,name:s.name,email:s.email,image:s.picture,emailVerified:!0},data:s}}}};import{betterFetch as Zt}from"@better-fetch/fetch";var $e=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let s=e.scope||r||["user-read-email"];return R({id:"spotify",options:e,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:s,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await Zt("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";function sn(e){return e.charAt(0).toUpperCase()+e.slice(1)}var _={isAction:!1};var U=e=>G(e||21,Z("a-z","0-9","A-Z"));import{parseJWT as Wt}from"oslo/jwt";var je=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return R({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})=>b({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return w.error("No idToken found in token"),null;let o=Wt(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Qt}from"@better-fetch/fetch";var ze=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return R({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>b({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Qt("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var ae={apple:Ce,discord:Be,facebook:De,github:Fe,microsoft:Ve,google:qe,spotify:$e,twitch:je,twitter:ze},Me=Object.keys(ae);var He=h("/sign-in/social",{method:"POST",requireHeaders:!0,query:v.object({currentURL:v.string().optional()}).optional(),body:v.object({callbackURL:v.string().optional(),provider:v.enum(Me)}),use:[T]},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 C("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,s=await Ee(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,s.hash,e.context.secret,r.state.options);let a=Jt();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let c=await t.createAuthorizationURL({state:s.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:c.toString(),state:s,codeVerifier:a,redirect:!0})}),Ke=h("/sign-in/email",{method:"POST",body:v.object({email:v.string().email(),password:v.string(),callbackURL:v.string().optional(),dontRememberMe:v.boolean().default(!1).optional()}),use:[T]},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 C("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!v.string().email().safeParse(t).success)throw new C("BAD_REQUEST",{message:"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 C("UNAUTHORIZED",{message:"Invalid email or password"});let s=n.accounts.find(d=>d.providerId==="credential");if(!s)throw e.context.logger.error("Credential account not found",{email:t}),new C("UNAUTHORIZED",{message:"Invalid email or password"});let a=s?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new C("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new C("UNAUTHORIZED",{message:"Invalid email or password"});let i=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!i)throw e.context.logger.error("Failed to create session"),new C("UNAUTHORIZED",{message:"Failed to create session"});return await P(e,i.id,e.body.dontRememberMe),e.json({user:n.user,session:i,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as Yt}from"better-call";import{z as J}from"zod";import{z as y}from"zod";var rs=y.object({id:y.string(),providerId:y.string(),accountId:y.string(),userId:y.string(),accessToken:y.string().nullable().optional(),refreshToken:y.string().nullable().optional(),idToken:y.string().nullable().optional(),expiresAt:y.date().nullable().optional(),password:y.string().optional().nullable()}),Ge=y.object({id:y.string(),email:y.string().transform(e=>e.toLowerCase()),emailVerified:y.boolean().default(!1),name:y.string(),image:y.string().optional(),createdAt:y.date().default(new Date),updatedAt:y.date().default(new Date)}),os=y.object({id:y.string(),userId:y.string(),expiresAt:y.date(),ipAddress:y.string().optional(),userAgent:y.string().optional()}),ns=y.object({id:y.string(),value:y.string(),expiresAt:y.date(),identifier:y.string()});function Xt(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Ze(e,t){let r={...e.user?.additionalFields};return Xt(t||{},{fields:r})}var We=h("/callback/:id",{method:"GET",query:J.object({state:J.string(),code:J.string().optional(),error:J.string().optional()}),metadata:_},async e=>{if(e.query.error||!e.query.code){let g=oe(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${g}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(f=>f.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=oe(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,s=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!s)throw w.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ve(e.query.state,s))throw w.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let c=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),i;try{i=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:c,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(f){throw e.context.logger.error(f),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let d=await t.getUserInfo(i).then(f=>f?.user),l=U(),p=Ge.safeParse({...d,id:l});if(!d||p.success===!1)throw w.error("Unable to get user info",p.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let u=await e.context.internalAdapter.findUserByEmail(d.email,{includeAccounts:!0}).catch(f=>{throw w.error(`Better auth was unable to query your database.
3
+ Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=u?.user.id;if(u){let f=u.accounts.find(x=>x.providerId===t.id),g=e.context.options.account?.accountLinking?.trustedProviders,A=g?g.includes(t.id):!0;if(!f&&(!d.emailVerified||!A)){let x;try{x=new URL(n||o),x.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(x.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:d.id.toString(),id:`${t.id}:${d.id}`,userId:u.user.id,...ie(i)})}catch(x){throw console.log(x),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{await e.context.internalAdapter.createOAuthUser(p.data,{...ie(i),id:`${t.id}:${d.id}`,providerId:t.id,accountId:d.id.toString(),userId:l})}catch{let g=new URL(n||o);throw g.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",g.toString()),e.redirect(g.toString())}if(!m&&!l)throw new Yt("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let f=await e.context.internalAdapter.createSession(m||l,e.request);if(!f){let g=new URL(n||o);throw g.searchParams.set("error","unable_to_create_session"),e.redirect(g.toString())}try{await P(e,f.id)}catch(g){e.context.logger.error("Unable to set session cookie",g);let A=new URL(n||o);throw A.searchParams.set("error","unable_to_create_session"),e.redirect(A.toString())}}catch{let f=new URL(n||o||"");throw f.searchParams.set("error","unable_to_create_session"),e.redirect(f.toString())}throw e.redirect(o)});import{APIError as M}from"better-call";var N=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Qe}from"zod";var de=()=>h("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return j(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,s=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+s*1e3<=Date.now()){let i=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:N(e.context.sessionConfig.expiresIn,"sec")});if(!i)return j(e),e.json(null,{status:401});let d=(i.expiresAt.valueOf()-Date.now())/1e3;return await P(e,i.id,!1,{maxAge:d}),e.json({session:i,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),er=async e=>await de()({...e,_flag:"json",headers:e.headers}),B=V(async e=>{let t=await er(e);if(!t?.session)throw new M("UNAUTHORIZED");return{session:t}}),Je=()=>h("/user/list-sessions",{method:"GET",use:[B],requireHeaders:!0},async e=>{let r=(await e.context.internalAdapter.listSessions(e.context.session.user.id)).filter(o=>o.expiresAt>new Date);return e.json(r)}),Xe=h("/user/revoke-session",{method:"POST",body:Qe.object({id:Qe.string()}),use:[B],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new M("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new M("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new M("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Ye=h("/user/revoke-sessions",{method:"POST",use:[B],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new M("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import"zod";import{APIError as tr}from"better-call";var et=h("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new tr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),j(e),e.json({success:!0})});import{z as I}from"zod";import{APIError as X}from"better-call";var tt=h("/forget-password",{method:"POST",body:I.object({email:I.string().email(),redirectTo:I.string()}),use:[T]},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 X("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,s=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),a=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${a}`,expiresAt:s});let c=`${e.context.baseURL}/reset-password/${a}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(c,o.user),e.json({status:!0})}),rt=h("/reset-password/:token",{method:"GET",query:I.object({callbackURL:I.string()}),use:[T]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),ot=h("/reset-password",{query:I.object({token:I.string()}).optional(),method:"POST",body:I.object({newPassword:I.string()})},async e=>{let t=e.query?.token;if(!t)throw new X("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new X("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let s=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(s)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:s,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(s,a))throw new X("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{TimeSpan as rr}from"oslo";import{createJWT as or,validateJWT as nr}from"oslo/jwt";import{z as O}from"zod";import{APIError as Y}from"better-call";async function ce(e,t){return await or("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new rr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var nt=h("/send-verification-email",{method:"POST",query:O.object({currentURL:O.string().optional()}).optional(),body:O.object({email:O.string().email(),callbackURL:O.string().optional()}),use:[T]},async e=>{if(!e.context.options.emailAndPassword?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new Y("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new Y("BAD_REQUEST",{message:"User not found"});let o=await ce(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailAndPassword.sendVerificationEmail(n,r.user,o),e.json({status:!0})}),st=h("/verify-email",{method:"GET",query:O.object({token:O.string(),callbackURL:O.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await nr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new Y("BAD_REQUEST",{message:"Invalid token"})}let n=O.object({email:O.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new Y("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});import{z as E}from"zod";import{APIError as S}from"better-call";var it=h("/user/update",{method:"POST",body:E.object({name:E.string().optional(),image:E.string().optional()}),use:[B,T]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),at=h("/user/change-password",{method:"POST",body:E.object({newPassword:E.string(),currentPassword:E.string(),revokeOtherSessions:E.boolean().optional()}),use:[B]},async e=>{let{newPassword:t,currentPassword:r,revokeOtherSessions:o}=e.body,n=e.context.session,s=e.context.password.config.minPasswordLength;if(t.length<s)throw e.context.logger.error("Password is too short"),new S("BAD_REQUEST",{message:"Password is too short"});let a=e.context.password.config.maxPasswordLength;if(t.length>a)throw e.context.logger.error("Password is too long"),new S("BAD_REQUEST",{message:"Password too long"});let i=(await e.context.internalAdapter.findAccounts(n.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!i||!i.password)throw new S("BAD_REQUEST",{message:"User does not have a password"});let d=await e.context.password.hash(t);if(!await e.context.password.verify(i.password,r))throw new S("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(i.id,{password:d}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new S("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await P(e,p.id)}return e.json(n.user)}),dt=h("/user/set-password",{method:"POST",body:E.object({newPassword:E.string()}),use:[B]},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 S("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new S("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(r.user.id)).find(i=>i.providerId==="credential"&&i.password),c=await e.context.password.hash(t);if(!a)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:c}),e.json(r.user);throw new S("BAD_REQUEST",{message:"user already has a password"})}),ct=h("/user/delete",{method:"POST",body:E.object({password:E.string()}),use:[B]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new S("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new S("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)});var lt=h("/csrf",{method:"GET",metadata:_},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t){let[s,a]=t.split("!")||[null,null];return{csrfToken:s}}let r=G(32,Z("a-z","0-9","A-Z")),o=await W(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:r}});var sr=(e="Unknown")=>`<!DOCTYPE html>
4
4
  <html lang="en">
5
5
  <head>
6
6
  <meta charset="UTF-8">
@@ -80,4 +80,4 @@ Error: `,f),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>`,ut=h("/error",{method:"GET",metadata:_},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(sr(t),{headers:{"Content-Type":"text/html"}})});var pt=h("/ok",{method:"GET",metadata:_},async e=>e.json({ok:!0}));import{z as $}from"zod";import{APIError as F}from"better-call";var ft=()=>h("/sign-up/email",{method:"POST",query:$.object({currentURL:$.string().optional()}).optional(),body:$.record($.string(),$.any()),use:[T]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new F("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:s,callbackURL:a,...c}=t;if(!$.string().email().safeParse(o).success)throw new F("BAD_REQUEST",{message:"Invalid email"});let d=e.context.password.config.minPasswordLength;if(n.length<d)throw e.context.logger.error("Password is too short"),new F("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new F("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new F("UNPROCESSABLE_ENTITY",{message:"The email has already been taken"});let u=Ze(e.context.options,c),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:s,...u,emailVerified:!1});if(!m)throw new F("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:N(60*60*24*30,"sec")});let g=await e.context.internalAdapter.createSession(m.id,e.request);if(!g)throw new F("BAD_REQUEST",{message:"Failed to create session"});if(await P(e,g.id),e.context.options.emailAndPassword.sendEmailVerificationOnSignUp){let A=await ce(e.context.secret,m.email),x=`${e.context.baseURL}/verify-email?token=${A}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailAndPassword.sendVerificationEmail?.(x,m,A)}return e.json({user:m,session:g},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:g}})});function mt(e){let t="127.0.0.1";if(process.env.NODE_ENV==="test")return t;let r=["x-client-ip","x-forwarded-for","cf-connecting-ip","fastly-client-ip","x-real-ip","x-cluster-client-ip","x-forwarded","forwarded-for","forwarded"];for(let o of r){let n=e.headers.get(o);if(typeof n=="string"){let s=n.split(",")[0].trim();if(s)return s}}return null}function ir(e,t,r){let o=Date.now(),n=t*1e3;return o-r.lastRequest<n&&r.count>=e}function ar(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 dr(e,t){let r=Date.now(),o=t*1e3;return Math.ceil((e+o-r)/1e3)}function cr(e,t){let r=t??"rateLimit",o=e.adapter;return{get:async n=>await o.findOne({model:r,where:[{field:"key",value:n}]}),set:async(n,s,a)=>{try{a?await o.update({model:t??"rateLimit",where:[{field:"key",value:n}],update:{count:s.count,lastRequest:s.lastRequest}}):await o.create({model:t??"rateLimit",data:{key:n,count:s.count,lastRequest:s.lastRequest}})}catch(c){w.error("Error setting rate limit",c)}}}}var gt=new Map;function lr(e){return 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 gt.get(r)},async set(r,o,n){gt.set(r,o)}}:cr(e,e.rateLimit.tableName)}async function ht(e,t){if(!t.rateLimit.enabled)return;let r=t.baseURL,o=e.url.replace(r,""),n=t.rateLimit.window,s=t.rateLimit.max,a=mt(e)+o,i=ur().find(u=>u.pathMatcher(o));i&&(n=i.window,s=i.max);for(let u of t.options.plugins||[])if(u.rateLimit){let m=u.rateLimit.find(f=>f.pathMatcher(o));if(m){n=m.window,s=m.max;break}}if(t.rateLimit.customRules){let u=t.rateLimit.customRules[o];u&&(n=u.window,s=u.max)}let d=lr(t),l=await d.get(a),p=Date.now();if(!l)await d.set(a,{key:a,count:1,lastRequest:p});else{let u=p-l.lastRequest;if(ir(s,n,l)){let m=dr(l.lastRequest,n);return ar(m)}else u>n*1e3?await d.set(a,{...l,count:1,lastRequest:p}):await d.set(a,{...l,count:l.count+1,lastRequest:p})}}function ur(){return[{pathMatcher(t){return t.startsWith("/sign-in")||t.startsWith("/sign-up")},window:10,max:7}]}import{APIError as ia}from"better-call";function le(e,t){let r=t.plugins?.reduce((c,i)=>({...c,...i.endpoints}),{}),o=t.plugins?.map(c=>c.middlewares?.map(i=>{let d=async l=>i.middleware({...l,context:{...e,...l.context}});return d.path=i.path,d.options=i.middleware.options,d.headers=i.middleware.headers,{path:i.path,middleware:d}})).filter(c=>c!==void 0).flat()||[],s={...{signInOAuth:He,callbackOAuth:We,getCSRFToken:lt,getSession:de(),signOut:et,signUpEmail:ft(),signInEmail:Ke,forgetPassword:tt,resetPassword:ot,verifyEmail:st,sendVerificationEmail:nt,changePassword:at,setPassword:dt,updateUser:it,deleteUser:ct,forgetPasswordCallback:rt,listSessions:Je(),revokeSession:Xe,revokeSessions:Ye},...r,ok:pt,error:ut},a={};for(let[c,i]of Object.entries(s))a[c]=async(d={})=>{let l=await e;for(let m of t.plugins||[])if(m.hooks?.before){for(let f of m.hooks.before)if(f.matcher({...i,...d,context:l})){let A=await f.handler({...d,context:{...l,...d?.context}});A&&"context"in A&&(l={...l,...A.context})}}let u=await i({...d,context:{...l,...d.context}});for(let m of t.plugins||[])if(m.hooks?.after){for(let f of m.hooks.after)if(f.matcher(d)){let A=Object.assign(d,{context:{...e,returned:u}}),x=await f.handler(A);x&&"response"in x&&(u=x.response)}}return u},a[c].path=i.path,a[c].method=i.method,a[c].options=i.options,a[c].headers=i.headers;return{api:a,middlewares:o}}var yt=(e,t)=>{let{api:r,middlewares:o}=le(e,t),n=new URL(e.baseURL).pathname;return fr(r,{extraContext:e,basePath:n,routerMiddleware:[{path:"/**",middleware:xe},...o],async onRequest(s){for(let a of e.options.plugins||[])if(a.onRequest){let c=await a.onRequest(s,e);if(c)return c}return ht(s,e)},async onResponse(s){for(let a of e.options.plugins||[])if(a.onResponse){let c=await a.onResponse(s,e);if(c)return c.response}return s},onError(s){if(t.onAPIError?.throw)throw s;if(t.onAPIError?.onError){t.onAPIError.onError(s,e);return}let a=t.logger?.verboseLogging?w:void 0;t.logger?.disabled!==!0&&(s instanceof pr?(s.status==="INTERNAL_SERVER_ERROR"&&w.error(s),a?.error(s.message)):w?.error(s))}})};var L=e=>{let t=e.plugins?.reduce((i,d)=>{let l=d.schema;if(!l)return i;for(let[p,u]of Object.entries(l))i[p]={fields:{...i[p]?.fields,...u.fields},tableName:u.tableName||p};return i},{}),r=e.rateLimit?.storage==="database",o={rateLimit:{tableName:e.rateLimit?.tableName||"rateLimit",fields:{key:{type:"string",fieldName:e.rateLimit?.fields?.key||"key"},count:{type:"number",fieldName:e.rateLimit?.fields?.count||"count"},lastRequest:{type:"number",fieldName:e.rateLimit?.fields?.lastRequest||"lastRequest"}}}},{user:n,session:s,account:a,...c}=t||{};return{user:{tableName:e.user?.modelName||"user",fields:{name:{type:"string",required:!0,fieldName:e.user?.fields?.name||"name"},email:{type:"string",unique:!0,required:!0,fieldName:e.user?.fields?.email||"email"},emailVerified:{type:"boolean",defaultValue:()=>!1,required:!0,fieldName:e.user?.fields?.emailVerified||"emailVerified"},image:{type:"string",required:!1,fieldName:e.user?.fields?.image||"image"},createdAt:{type:"date",defaultValue:()=>new Date,required:!0,fieldName:e.user?.fields?.createdAt||"createdAt"},updatedAt:{type:"date",defaultValue:()=>new Date,required:!0,fieldName:e.user?.fields?.updatedAt||"updatedAt"},...n?.fields,...e.user?.additionalFields},order:1},session:{tableName:e.session?.modelName||"session",fields:{expiresAt:{type:"date",required:!0,fieldName:e.session?.fields?.expiresAt||"expiresAt"},ipAddress:{type:"string",required:!1,fieldName:e.session?.fields?.ipAddress||"ipAddress"},userAgent:{type:"string",required:!1,fieldName:e.session?.fields?.userAgent||"userAgent"},userId:{type:"string",fieldName:e.session?.fields?.userId||"userId",references:{model:e.user?.modelName||"user",field:"id",onDelete:"cascade"},required:!0},...s?.fields,...e.session?.additionalFields},order:2},account:{tableName:e.account?.modelName||"account",fields:{accountId:{type:"string",required:!0,fieldName:e.account?.fields?.accountId||"accountId"},providerId:{type:"string",required:!0,fieldName:e.account?.fields?.providerId||"providerId"},userId:{type:"string",references:{model:e.user?.modelName||"user",field:"id",onDelete:"cascade"},required:!0,fieldName:e.account?.fields?.userId||"userId"},accessToken:{type:"string",required:!1,fieldName:e.account?.fields?.accessToken||"accessToken"},refreshToken:{type:"string",required:!1,fieldName:e.account?.fields?.refreshToken||"refreshToken"},idToken:{type:"string",required:!1,fieldName:e.account?.fields?.idToken||"idToken"},expiresAt:{type:"date",required:!1,fieldName:e.account?.fields?.expiresAt||"expiresAt"},password:{type:"string",required:!1,fieldName:e.account?.fields?.password||"password"},...a?.fields},order:3},verification:{tableName:e.verification?.modelName||"verification",fields:{identifier:{type:"string",required:!0,fieldName:e.verification?.fields?.identifier||"identifier"},value:{type:"string",required:!0,fieldName:e.verification?.fields?.value||"value"},expiresAt:{type:"date",required:!0,fieldName:e.verification?.fields?.expiresAt||"expiresAt"}},order:4},...c,...r?o:{}}};import{Kysely as wt,MssqlDialect as mr}from"kysely";import{MysqlDialect as bt,PostgresDialect as At,SqliteDialect as Rt}from"kysely";function kt(e){if("dialect"in e)return kt(e.dialect);if("createDriver"in e){if(e instanceof Rt)return"sqlite";if(e instanceof bt)return"mysql";if(e instanceof At)return"postgres";if(e instanceof mr)return"mssql"}return"aggregate"in e?"sqlite":"getConnection"in e?"mysql":"connect"in e?"postgres":null}var H=async e=>{let t=e.database;if("db"in t)return{kysely:t.db,databaseType:t.type};if("dialect"in t)return{kysely:new wt({dialect:t.dialect}),databaseType:t.type};let r,o=kt(t);return"createDriver"in t&&(r=t),"aggregate"in t&&(r=new Rt({database:t})),"getConnection"in t&&(r=new bt({pool:t})),"connect"in t&&(r=new At({pool:t})),{kysely:r?new wt({dialect:r}):null,databaseType:o}};import"kysely";function xt(e,t){let r=t.hooks,o=L(t.options);async function n(a,c,i){let d=a,l=o[c];for(let m of r||[]){let f=m[c]?.create?.before;if(f){let g=await f(a);if(g===!1)return null;typeof g=="object"&&"data"in g&&(d=g.data)}}let p=i?await i.fn(d):null,u=!i||i.executeMainFn?await e.create({model:l.tableName,data:{id:U(),...ue(l.fields,d)}}):p;for(let m of r||[]){let f=m[c]?.create?.after;f&&await f(u)}return pe(l.fields,u)}async function s(a,c,i,d){let l=a;for(let m of r||[]){let f=m[i]?.update?.before;if(f){let g=await f(a);if(g===!1)return null;l=typeof g=="object"?g.data:g}}let p=d?await d.fn(l):null,u=!d||d.executeMainFn?await e.update({model:o[i].tableName,update:ue(o[i].fields,l),where:c}):p;for(let m of r||[]){let f=m[i]?.update?.after;f&&await f(u)}return pe(o[i].fields,u)}return{createWithHooks:n,updateWithHooks:s}}var fe=(e,t)=>{let r=t.options,o=r.secondaryStorage,n=r.session?.expiresIn||60*60*24*7,s=L(r),{createWithHooks:a,updateWithHooks:c}=xt(e,t);return{createOAuthUser:async(i,d)=>{try{let l=await a(i,"user"),p=await a(d,"account");return{user:l,account:p}}catch(l){return console.log(l),null}},createUser:async i=>await a({id:U(),createdAt:new Date,updatedAt:new Date,emailVerified:!1,...i},"user"),createAccount:async i=>await a({id:U(),createdAt:new Date,updatedAt:new Date,...i},"account"),listSessions:async i=>await e.findMany({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]}),listUsers:async(i,d,l)=>await e.findMany({model:s.user.tableName,limit:i,offset:d,sortBy:l}),deleteUser:async i=>{await e.delete({model:s.account.tableName,where:[{field:s.account.fields.userId.fieldName||"userId",value:i}]}),await e.delete({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]}),await e.delete({model:s.user.tableName,where:[{field:"id",value:i}]})},createSession:async(i,d,l,p)=>{let u=d instanceof Request?d.headers:d,m={id:U(),userId:i,expiresAt:l?N(60*60*24,"sec"):N(n,"sec"),ipAddress:u?.get("x-forwarded-for")||"",userAgent:u?.get("user-agent")||"",...p};return await a(m,"session",o?{fn:async g=>{let A=await e.findOne({model:s.user.tableName,where:[{field:"id",value:i}]});return o.set(g.id,JSON.stringify({session:g,user:A}),n),g},executeMainFn:r.session?.storeSessionInDatabase}:void 0)},findSession:async i=>{if(o){let p=await o.get(i);if(p){let u=JSON.parse(p);return{session:{...u.session,expiresAt:new Date(u.session.expiresAt)},user:{...u.user,createdAt:new Date(u.user.createdAt),updatedAt:new Date(u.user.updatedAt)}}}}let d=await e.findOne({model:s.session.tableName,where:[{value:i,field:"id"}]});if(!d)return null;let l=await e.findOne({model:s.user.tableName,where:[{value:d.userId,field:"id"}]});return l?{session:d,user:l}:null},updateSession:async(i,d)=>await c(d,[{field:"id",value:i}],"session",o?{async fn(p){let u=await o.get(i),m=null;if(u){let f=JSON.parse(u);m={...f.session,...p},await o.set(i,JSON.stringify({session:m,user:f.user}),f.session.expiresAt?new Date(f.session.expiresAt).getTime():void 0)}else return null},executeMainFn:r.session?.storeSessionInDatabase}:void 0),deleteSession:async i=>{if(o){await o.delete(i),r.session?.storeSessionInDatabase&&await e.delete({model:s.session.tableName,where:[{field:"id",value:i}]});return}await e.delete({model:s.session.tableName,where:[{field:"id",value:i}]})},deleteSessions:async i=>{if(o){let d=await e.findMany({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]});for(let l of d)await o.delete(l.id);r.session?.storeSessionInDatabase&&await e.delete({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]});return}await e.delete({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]})},findUserByEmail:async(i,d)=>{let l=await e.findOne({model:s.user.tableName,where:[{value:i.toLowerCase(),field:s.user.fields.email.fieldName||"email"}]});if(!l)return null;if(d?.includeAccounts){let p=await e.findMany({model:s.account.tableName,where:[{value:l.id,field:s.account.fields.userId.fieldName||"userId"}]});return{user:l,accounts:p}}return{user:l,accounts:[]}},findUserById:async i=>await e.findOne({model:s.user.tableName,where:[{field:"id",value:i}]}),linkAccount:async i=>await a({id:U(),...i},"account"),updateUser:async(i,d)=>await c(d,[{field:"id",value:i}],"user"),updateUserByEmail:async(i,d)=>await c(d,[{field:"email",value:i}],"user"),updatePassword:async(i,d)=>await c({password:d},[{field:s.account.fields.userId.fieldName||"userId",value:i},{field:s.account.fields.providerId.fieldName||"providerId",value:"credential"}],"account"),findAccounts:async i=>await e.findMany({model:s.account.tableName,where:[{field:s.account.fields.userId.fieldName||"userId",value:i}]}),updateAccount:async(i,d)=>await c(d,[{field:"id",value:i}],"account"),createVerificationValue:async i=>await a({id:U(),...i},"verification"),findVerificationValue:async i=>await e.findOne({model:s.verification.tableName,where:[{field:s.verification.fields.identifier.fieldName||"identifier",value:i}]}),deleteVerificationValue:async i=>{await e.delete({model:s.verification.tableName,where:[{field:"id",value:i}]})},updateVerificationValue:async(i,d)=>await c(d,[{field:"id",value:i}],"verification")}};import{z as Ta}from"zod";function ee(e){if(!e)return{and:null,or:null};let t=e?.filter(o=>o.connector==="AND"||!o.connector).reduce((o,n)=>({...o,[n.field]:n.value}),{}),r=e?.filter(o=>o.connector==="OR").reduce((o,n)=>({...o,[n.field]:n.value}),{});return{and:Object.keys(t).length?t:null,or:Object.keys(r).length?r:null}}function te(e,t,r){for(let o in e)e[o]===0&&t[o]?.type==="boolean"&&r?.boolean&&(e[o]=!1),e[o]===1&&t[o]?.type==="boolean"&&r?.boolean&&(e[o]=!0),t[o]?.type==="date"&&(e[o]instanceof Date||(e[o]=new Date(e[o])));return e}function Tt(e,t){for(let r in e)typeof e[r]=="boolean"&&t?.boolean&&(e[r]=e[r]?1:0),e[r]instanceof Date&&(e[r]=e[r].toISOString());return e}var Ut=(e,t)=>({id:"kysely",async create(r){let{model:o,data:n,select:s}=r;t?.transform&&(n=Tt(n,t.transform));let a=await e.insertInto(o).values(n).returningAll().executeTakeFirst();if(t?.transform){let c=t.transform.schema[o];a=c?te(n,c,t.transform):a}return s?.length&&(a=a?s.reduce((i,d)=>a?.[d]?{...i,[d]:a[d]}:i,{}):null),a},async findOne(r){let{model:o,where:n,select:s}=r,{and:a,or:c}=ee(n),i=e.selectFrom(o).selectAll();c&&(i=i.where(l=>l.or(c))),a&&(i=i.where(l=>l.and(a)));let d=await i.executeTakeFirst();if(s?.length&&(d=d?s.reduce((p,u)=>d?.[u]?{...p,[u]:d[u]}:p,{}):null),t?.transform){let l=t.transform.schema[o];return d=d&&l?te(d,l,t.transform):d,d||null}return d||null},async findMany(r){let{model:o,where:n,limit:s,offset:a,sortBy:c}=r,i=e.selectFrom(o),{and:d,or:l}=ee(n);d&&(i=i.where(u=>u.and(d))),l&&(i=i.where(u=>u.or(l))),i=i.limit(s||100),a&&(i=i.offset(a)),c&&(i=i.orderBy(c.field,c.direction));let p=await i.selectAll().execute();if(t?.transform){let u=t.transform.schema[o];return u?p.map(m=>te(m,u,t.transform)):p}return p},async update(r){let{model:o,where:n,update:s}=r,{and:a,or:c}=ee(n);t?.transform&&(s=Tt(s,t.transform));let i=e.updateTable(o).set(s);a&&(i=i.where(l=>l.and(a))),c&&(i=i.where(l=>l.or(c)));let d=await i.returningAll().executeTakeFirst()||null;if(t?.transform){let l=t.transform.schema[o];return l?te(d,l,t.transform):d}return d},async delete(r){let{model:o,where:n}=r,{and:s,or:a}=ee(n),c=e.deleteFrom(o);s&&(c=c.where(i=>i.and(s))),a&&(c=c.where(i=>i.or(a))),await c.execute()}});async function vt(e,t){if(!e.database)throw new R("Database configuration is required");if("create"in e.database)return e.database;let{kysely:r,databaseType:o}=await H(e);if(!r)throw new R("Failed to initialize database adapter");let n=L(e),s={};for(let a of Object.values(n))s[a.tableName]=a.fields;return Ut(r,{transform:{schema:s,date:!0,boolean:o==="sqlite"}})}function ue(e,t){let r={id:t.id};for(let o in e){let n=e[o],s=t[o];r[n.fieldName||o]=s}return r}function pe(e,t){if(!t)return null;let r={id:t.id};for(let[o,n]of Object.entries(e))r[o]=t[n.fieldName||o];return r}import{defu as gr}from"defu";var me="better-auth-secret-123456789";var Et=async e=>{let t=await vt(e),r=e.plugins||[],o=yr(e),{kysely:n}=await H(e),s=z(e.baseURL,e.basePath);if(!s)throw new R("Base URL can not be empty. Please add `BETTER_AUTH_URL` in your environment variables or pass it your auth config.");let a=e.secret||process.env.BETTER_AUTH_SECRET||process.env.AUTH_SECRET||me;if(a===me&&process.env.NODE_ENV==="production")throw new R("You are using the default secret. Please set `BETTER_AUTH_SECRET` or `AUTH_SECRET` in your environment variables or pass `secret` in your auth config.");e={...e,secret:a,baseURL:s?new URL(s).origin:"",basePath:e.basePath||"/api/auth",plugins:r.concat(o)};let c=Oe(e),i=L(e),d=Object.keys(e.socialProviders||{}).map(u=>{let m=e.socialProviders?.[u];return m.enabled===!1?null:((!m.clientId||!m.clientSecret)&&w.warn(`Social provider ${u} is missing clientId or clientSecret`),ae[u](m))}).filter(u=>u!==null),l={appName:e.appName||"Better Auth",socialProviders:d,options:e,tables:i,trustedOrigins:wr(e),baseURL:s,sessionConfig:{updateAge:e.session?.updateAge||24*60*60,expiresIn:e.session?.expiresIn||60*60*24*7},secret:a,rateLimit:{...e.rateLimit,enabled:e.rateLimit?.enabled??process.env.NODE_ENV!=="development",window:e.rateLimit?.window||60,max:e.rateLimit?.max||100,storage:e.rateLimit?.storage||e.secondaryStorage?"secondary-storage":"memory"},authCookies:c,logger:ne({disabled:e.logger?.disabled||!1}),db:n,uuid:U,secondaryStorage:e.secondaryStorage,password:{hash:e.emailAndPassword?.password?.hash||ye,verify:e.emailAndPassword?.password?.verify||we,config:{minPasswordLength:e.emailAndPassword?.minPasswordLength||8,maxPasswordLength:e.emailAndPassword?.maxPasswordLength||128}},adapter:t,internalAdapter:fe(t,{options:e,hooks:e.databaseHooks?[e.databaseHooks]:[]}),createAuthCookie:Se(e)},{context:p}=hr(l);return p};function hr(e){let t=e.options,r=t.plugins||[],o=e,n=[];for(let s of r)if(s.init){let a=s.init(e);typeof a=="object"&&(a.options&&(a.options.databaseHooks&&n.push(a.options.databaseHooks),t=gr(t,a.options)),a.context&&(o={...o,...a.context}))}return n.push(t.databaseHooks),o.internalAdapter=fe(e.adapter,{options:t,hooks:n.filter(s=>s!==void 0)}),o.options=t,{context:o}}function yr(e){let t=[];return e.advanced?.crossSubDomainCookies?.enabled,t}function wr(e){let t=z(e.baseURL,e.basePath);if(!t)throw new R("Base URL can not be empty. Please add `BETTER_AUTH_URL` in your environment variables or pass it in your auth config.");let r=[new URL(t).origin];e.trustedOrigins&&r.push(...e.trustedOrigins);let o=process.env.BETTER_AUTH_TRUSTED_ORIGINS;return o&&r.push(...o.split(",")),r}var wd=e=>{let t=Et(e),{api:r}=le(t,e);return{handler:async o=>{let n=await t,s=n.options.basePath||"/api/auth",a=new URL(o.url);if(!n.options.baseURL){let i=z(void 0,s)||`${a.origin}${s}`;n.options.baseURL=i,n.baseURL=i}if(!n.options.baseURL)return new Response("Base URL not set",{status:400});if(a.pathname===s||a.pathname===`${s}/`)return new Response("Welcome to BetterAuth",{status:200});let{handler:c}=yt(n,e);return c(o)},api:r,options:e,$Infer:{}}};export{R as BetterAuthError,_ as HIDE_METADATA,Pe as MissingDependencyError,wd as betterAuth,sn as capitalizeFirstLetter,Se as createCookieGetter,ne as createLogger,j as deleteSessionCookie,U as generateId,Ee as generateState,Oe as getCookies,w as logger,so as parseSetCookieHeader,oe as parseState,P as setSessionCookie};
83
+ </html>`,ut=h("/error",{method:"GET",metadata:_},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(sr(t),{headers:{"Content-Type":"text/html"}})});var pt=h("/ok",{method:"GET",metadata:_},async e=>e.json({ok:!0}));import{z as $}from"zod";import{APIError as F}from"better-call";var ft=()=>h("/sign-up/email",{method:"POST",query:$.object({currentURL:$.string().optional()}).optional(),body:$.record($.string(),$.any()),use:[T]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new F("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:s,callbackURL:a,...c}=t;if(!$.string().email().safeParse(o).success)throw new F("BAD_REQUEST",{message:"Invalid email"});let d=e.context.password.config.minPasswordLength;if(n.length<d)throw e.context.logger.error("Password is too short"),new F("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new F("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new F("UNPROCESSABLE_ENTITY",{message:"The email has already been taken"});let u=Ze(e.context.options,c),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:s,...u,emailVerified:!1});if(!m)throw new F("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:N(60*60*24*30,"sec")});let g=await e.context.internalAdapter.createSession(m.id,e.request);if(!g)throw new F("BAD_REQUEST",{message:"Failed to create session"});if(await P(e,g.id),e.context.options.emailAndPassword.sendEmailVerificationOnSignUp){let A=await ce(e.context.secret,m.email),x=`${e.context.baseURL}/verify-email?token=${A}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailAndPassword.sendVerificationEmail?.(x,m,A)}return e.json({user:m,session:g},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:g}})});function mt(e){let t="127.0.0.1";if(process.env.NODE_ENV==="test")return t;let r=["x-client-ip","x-forwarded-for","cf-connecting-ip","fastly-client-ip","x-real-ip","x-cluster-client-ip","x-forwarded","forwarded-for","forwarded"];for(let o of r){let n=e.headers.get(o);if(typeof n=="string"){let s=n.split(",")[0].trim();if(s)return s}}return null}function ir(e,t,r){let o=Date.now(),n=t*1e3;return o-r.lastRequest<n&&r.count>=e}function ar(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 dr(e,t){let r=Date.now(),o=t*1e3;return Math.ceil((e+o-r)/1e3)}function cr(e,t){let r=t??"rateLimit",o=e.adapter;return{get:async n=>await o.findOne({model:r,where:[{field:"key",value:n}]}),set:async(n,s,a)=>{try{a?await o.update({model:t??"rateLimit",where:[{field:"key",value:n}],update:{count:s.count,lastRequest:s.lastRequest}}):await o.create({model:t??"rateLimit",data:{key:n,count:s.count,lastRequest:s.lastRequest}})}catch(c){w.error("Error setting rate limit",c)}}}}var gt=new Map;function lr(e){return 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 gt.get(r)},async set(r,o,n){gt.set(r,o)}}:cr(e,e.rateLimit.tableName)}async function ht(e,t){if(!t.rateLimit.enabled)return;let r=t.baseURL,o=e.url.replace(r,""),n=t.rateLimit.window,s=t.rateLimit.max,a=mt(e)+o,i=ur().find(u=>u.pathMatcher(o));i&&(n=i.window,s=i.max);for(let u of t.options.plugins||[])if(u.rateLimit){let m=u.rateLimit.find(f=>f.pathMatcher(o));if(m){n=m.window,s=m.max;break}}if(t.rateLimit.customRules){let u=t.rateLimit.customRules[o];u&&(n=u.window,s=u.max)}let d=lr(t),l=await d.get(a),p=Date.now();if(!l)await d.set(a,{key:a,count:1,lastRequest:p});else{let u=p-l.lastRequest;if(ir(s,n,l)){let m=dr(l.lastRequest,n);return ar(m)}else u>n*1e3?await d.set(a,{...l,count:1,lastRequest:p}):await d.set(a,{...l,count:l.count+1,lastRequest:p})}}function ur(){return[{pathMatcher(t){return t.startsWith("/sign-in")||t.startsWith("/sign-up")},window:10,max:7}]}import{APIError as ia}from"better-call";function le(e,t){let r=t.plugins?.reduce((c,i)=>({...c,...i.endpoints}),{}),o=t.plugins?.map(c=>c.middlewares?.map(i=>{let d=async l=>i.middleware({...l,context:{...e,...l.context}});return d.path=i.path,d.options=i.middleware.options,d.headers=i.middleware.headers,{path:i.path,middleware:d}})).filter(c=>c!==void 0).flat()||[],s={...{signInOAuth:He,callbackOAuth:We,getCSRFToken:lt,getSession:de(),signOut:et,signUpEmail:ft(),signInEmail:Ke,forgetPassword:tt,resetPassword:ot,verifyEmail:st,sendVerificationEmail:nt,changePassword:at,setPassword:dt,updateUser:it,deleteUser:ct,forgetPasswordCallback:rt,listSessions:Je(),revokeSession:Xe,revokeSessions:Ye},...r,ok:pt,error:ut},a={};for(let[c,i]of Object.entries(s))a[c]=async(d={})=>{let l=await e;for(let m of t.plugins||[])if(m.hooks?.before){for(let f of m.hooks.before)if(f.matcher({...i,...d,context:l})){let A=await f.handler({...d,context:{...l,...d?.context}});A&&"context"in A&&(l={...l,...A.context})}}let u=await i({...d,context:{...l,...d.context}});for(let m of t.plugins||[])if(m.hooks?.after){for(let f of m.hooks.after)if(f.matcher(d)){let A=Object.assign(d,{context:{...e,returned:u}}),x=await f.handler(A);x&&"response"in x&&(u=x.response)}}return u},a[c].path=i.path,a[c].method=i.method,a[c].options=i.options,a[c].headers=i.headers;return{api:a,middlewares:o}}var yt=(e,t)=>{let{api:r,middlewares:o}=le(e,t),n=new URL(e.baseURL).pathname;return fr(r,{extraContext:e,basePath:n,routerMiddleware:[{path:"/**",middleware:xe},...o],async onRequest(s){for(let a of e.options.plugins||[])if(a.onRequest){let c=await a.onRequest(s,e);if(c)return c}return ht(s,e)},async onResponse(s){for(let a of e.options.plugins||[])if(a.onResponse){let c=await a.onResponse(s,e);if(c)return c.response}return s},onError(s){if(t.onAPIError?.throw)throw s;if(t.onAPIError?.onError){t.onAPIError.onError(s,e);return}let a=t.logger?.verboseLogging?w:void 0;t.logger?.disabled!==!0&&(s instanceof pr?(s.status==="INTERNAL_SERVER_ERROR"&&w.error(s),a?.error(s.message)):w?.error(s))}})};var L=e=>{let t=e.plugins?.reduce((i,d)=>{let l=d.schema;if(!l)return i;for(let[p,u]of Object.entries(l))i[p]={fields:{...i[p]?.fields,...u.fields},tableName:u.tableName||p};return i},{}),r=e.rateLimit?.storage==="database",o={rateLimit:{tableName:e.rateLimit?.tableName||"rateLimit",fields:{key:{type:"string",fieldName:e.rateLimit?.fields?.key||"key"},count:{type:"number",fieldName:e.rateLimit?.fields?.count||"count"},lastRequest:{type:"number",fieldName:e.rateLimit?.fields?.lastRequest||"lastRequest"}}}},{user:n,session:s,account:a,...c}=t||{};return{user:{tableName:e.user?.modelName||"user",fields:{name:{type:"string",required:!0,fieldName:e.user?.fields?.name||"name"},email:{type:"string",unique:!0,required:!0,fieldName:e.user?.fields?.email||"email"},emailVerified:{type:"boolean",defaultValue:()=>!1,required:!0,fieldName:e.user?.fields?.emailVerified||"emailVerified"},image:{type:"string",required:!1,fieldName:e.user?.fields?.image||"image"},createdAt:{type:"date",defaultValue:()=>new Date,required:!0,fieldName:e.user?.fields?.createdAt||"createdAt"},updatedAt:{type:"date",defaultValue:()=>new Date,required:!0,fieldName:e.user?.fields?.updatedAt||"updatedAt"},...n?.fields,...e.user?.additionalFields},order:1},session:{tableName:e.session?.modelName||"session",fields:{expiresAt:{type:"date",required:!0,fieldName:e.session?.fields?.expiresAt||"expiresAt"},ipAddress:{type:"string",required:!1,fieldName:e.session?.fields?.ipAddress||"ipAddress"},userAgent:{type:"string",required:!1,fieldName:e.session?.fields?.userAgent||"userAgent"},userId:{type:"string",fieldName:e.session?.fields?.userId||"userId",references:{model:e.user?.modelName||"user",field:"id",onDelete:"cascade"},required:!0},...s?.fields,...e.session?.additionalFields},order:2},account:{tableName:e.account?.modelName||"account",fields:{accountId:{type:"string",required:!0,fieldName:e.account?.fields?.accountId||"accountId"},providerId:{type:"string",required:!0,fieldName:e.account?.fields?.providerId||"providerId"},userId:{type:"string",references:{model:e.user?.modelName||"user",field:"id",onDelete:"cascade"},required:!0,fieldName:e.account?.fields?.userId||"userId"},accessToken:{type:"string",required:!1,fieldName:e.account?.fields?.accessToken||"accessToken"},refreshToken:{type:"string",required:!1,fieldName:e.account?.fields?.refreshToken||"refreshToken"},idToken:{type:"string",required:!1,fieldName:e.account?.fields?.idToken||"idToken"},expiresAt:{type:"date",required:!1,fieldName:e.account?.fields?.expiresAt||"expiresAt"},password:{type:"string",required:!1,fieldName:e.account?.fields?.password||"password"},...a?.fields},order:3},verification:{tableName:e.verification?.modelName||"verification",fields:{identifier:{type:"string",required:!0,fieldName:e.verification?.fields?.identifier||"identifier"},value:{type:"string",required:!0,fieldName:e.verification?.fields?.value||"value"},expiresAt:{type:"date",required:!0,fieldName:e.verification?.fields?.expiresAt||"expiresAt"}},order:4},...c,...r?o:{}}};import{Kysely as wt,MssqlDialect as mr}from"kysely";import{MysqlDialect as bt,PostgresDialect as At,SqliteDialect as kt}from"kysely";function Rt(e){if("dialect"in e)return Rt(e.dialect);if("createDriver"in e){if(e instanceof kt)return"sqlite";if(e instanceof bt)return"mysql";if(e instanceof At)return"postgres";if(e instanceof mr)return"mssql"}return"aggregate"in e?"sqlite":"getConnection"in e?"mysql":"connect"in e?"postgres":null}var H=async e=>{let t=e.database;if("db"in t)return{kysely:t.db,databaseType:t.type};if("dialect"in t)return{kysely:new wt({dialect:t.dialect}),databaseType:t.type};let r,o=Rt(t);return"createDriver"in t&&(r=t),"aggregate"in t&&(r=new kt({database:t})),"getConnection"in t&&(r=new bt({pool:t})),"connect"in t&&(r=new At({pool:t})),{kysely:r?new wt({dialect:r}):null,databaseType:o}};import"kysely";function xt(e,t){let r=t.hooks,o=L(t.options);async function n(a,c,i){let d=a,l=o[c];for(let m of r||[]){let f=m[c]?.create?.before;if(f){let g=await f(a);if(g===!1)return null;typeof g=="object"&&"data"in g&&(d=g.data)}}let p=i?await i.fn(d):null,u=!i||i.executeMainFn?await e.create({model:l.tableName,data:{id:U(),...ue(l.fields,d)}}):p;for(let m of r||[]){let f=m[c]?.create?.after;f&&await f(u)}return pe(l.fields,u)}async function s(a,c,i,d){let l=a;for(let m of r||[]){let f=m[i]?.update?.before;if(f){let g=await f(a);if(g===!1)return null;l=typeof g=="object"?g.data:g}}let p=d?await d.fn(l):null,u=!d||d.executeMainFn?await e.update({model:o[i].tableName,update:ue(o[i].fields,l),where:c}):p;for(let m of r||[]){let f=m[i]?.update?.after;f&&await f(u)}return pe(o[i].fields,u)}return{createWithHooks:n,updateWithHooks:s}}var fe=(e,t)=>{let r=t.options,o=r.secondaryStorage,n=r.session?.expiresIn||60*60*24*7,s=L(r),{createWithHooks:a,updateWithHooks:c}=xt(e,t);return{createOAuthUser:async(i,d)=>{try{let l=await a(i,"user"),p=await a(d,"account");return{user:l,account:p}}catch(l){return console.log(l),null}},createUser:async i=>await a({id:U(),createdAt:new Date,updatedAt:new Date,emailVerified:!1,...i},"user"),createAccount:async i=>await a({id:U(),createdAt:new Date,updatedAt:new Date,...i},"account"),listSessions:async i=>await e.findMany({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]}),listUsers:async(i,d,l)=>await e.findMany({model:s.user.tableName,limit:i,offset:d,sortBy:l}),deleteUser:async i=>{await e.delete({model:s.account.tableName,where:[{field:s.account.fields.userId.fieldName||"userId",value:i}]}),await e.delete({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]}),await e.delete({model:s.user.tableName,where:[{field:"id",value:i}]})},createSession:async(i,d,l,p)=>{let u=d instanceof Request?d.headers:d,m={id:U(),userId:i,expiresAt:l?N(60*60*24,"sec"):N(n,"sec"),ipAddress:u?.get("x-forwarded-for")||"",userAgent:u?.get("user-agent")||"",...p};return await a(m,"session",o?{fn:async g=>{let A=await e.findOne({model:s.user.tableName,where:[{field:"id",value:i}]});return o.set(g.id,JSON.stringify({session:g,user:A}),n),g},executeMainFn:r.session?.storeSessionInDatabase}:void 0)},findSession:async i=>{if(o){let p=await o.get(i);if(p){let u=JSON.parse(p);return{session:{...u.session,expiresAt:new Date(u.session.expiresAt)},user:{...u.user,createdAt:new Date(u.user.createdAt),updatedAt:new Date(u.user.updatedAt)}}}}let d=await e.findOne({model:s.session.tableName,where:[{value:i,field:"id"}]});if(!d)return null;let l=await e.findOne({model:s.user.tableName,where:[{value:d.userId,field:"id"}]});return l?{session:d,user:l}:null},updateSession:async(i,d)=>await c(d,[{field:"id",value:i}],"session",o?{async fn(p){let u=await o.get(i),m=null;if(u){let f=JSON.parse(u);m={...f.session,...p},await o.set(i,JSON.stringify({session:m,user:f.user}),f.session.expiresAt?new Date(f.session.expiresAt).getTime():void 0)}else return null},executeMainFn:r.session?.storeSessionInDatabase}:void 0),deleteSession:async i=>{if(o){await o.delete(i),r.session?.storeSessionInDatabase&&await e.delete({model:s.session.tableName,where:[{field:"id",value:i}]});return}await e.delete({model:s.session.tableName,where:[{field:"id",value:i}]})},deleteSessions:async i=>{if(o){let d=await e.findMany({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]});for(let l of d)await o.delete(l.id);r.session?.storeSessionInDatabase&&await e.delete({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]});return}await e.delete({model:s.session.tableName,where:[{field:s.session.fields.userId.fieldName||"userId",value:i}]})},findUserByEmail:async(i,d)=>{let l=await e.findOne({model:s.user.tableName,where:[{value:i.toLowerCase(),field:s.user.fields.email.fieldName||"email"}]});if(!l)return null;if(d?.includeAccounts){let p=await e.findMany({model:s.account.tableName,where:[{value:l.id,field:s.account.fields.userId.fieldName||"userId"}]});return{user:l,accounts:p}}return{user:l,accounts:[]}},findUserById:async i=>await e.findOne({model:s.user.tableName,where:[{field:"id",value:i}]}),linkAccount:async i=>await a({id:U(),...i},"account"),updateUser:async(i,d)=>await c(d,[{field:"id",value:i}],"user"),updateUserByEmail:async(i,d)=>await c(d,[{field:"email",value:i}],"user"),updatePassword:async(i,d)=>await c({password:d},[{field:s.account.fields.userId.fieldName||"userId",value:i},{field:s.account.fields.providerId.fieldName||"providerId",value:"credential"}],"account"),findAccounts:async i=>await e.findMany({model:s.account.tableName,where:[{field:s.account.fields.userId.fieldName||"userId",value:i}]}),updateAccount:async(i,d)=>await c(d,[{field:"id",value:i}],"account"),createVerificationValue:async i=>await a({id:U(),...i},"verification"),findVerificationValue:async i=>await e.findOne({model:s.verification.tableName,where:[{field:s.verification.fields.identifier.fieldName||"identifier",value:i}]}),deleteVerificationValue:async i=>{await e.delete({model:s.verification.tableName,where:[{field:"id",value:i}]})},updateVerificationValue:async(i,d)=>await c(d,[{field:"id",value:i}],"verification")}};import{z as Ta}from"zod";function ee(e){if(!e)return{and:null,or:null};let t=e?.filter(o=>o.connector==="AND"||!o.connector).reduce((o,n)=>({...o,[n.field]:n.value}),{}),r=e?.filter(o=>o.connector==="OR").reduce((o,n)=>({...o,[n.field]:n.value}),{});return{and:Object.keys(t).length?t:null,or:Object.keys(r).length?r:null}}function te(e,t,r){for(let o in e)e[o]===0&&t[o]?.type==="boolean"&&r?.boolean&&(e[o]=!1),e[o]===1&&t[o]?.type==="boolean"&&r?.boolean&&(e[o]=!0),t[o]?.type==="date"&&(e[o]instanceof Date||(e[o]=new Date(e[o])));return e}function Tt(e,t){for(let r in e)typeof e[r]=="boolean"&&t?.boolean&&(e[r]=e[r]?1:0),e[r]instanceof Date&&(e[r]=e[r].toISOString());return e}var Ut=(e,t)=>({id:"kysely",async create(r){let{model:o,data:n,select:s}=r;t?.transform&&(n=Tt(n,t.transform));let a=await e.insertInto(o).values(n).returningAll().executeTakeFirst();if(t?.transform){let c=t.transform.schema[o];a=c?te(n,c,t.transform):a}return s?.length&&(a=a?s.reduce((i,d)=>a?.[d]?{...i,[d]:a[d]}:i,{}):null),a},async findOne(r){let{model:o,where:n,select:s}=r,{and:a,or:c}=ee(n),i=e.selectFrom(o).selectAll();c&&(i=i.where(l=>l.or(c))),a&&(i=i.where(l=>l.and(a)));let d=await i.executeTakeFirst();if(s?.length&&(d=d?s.reduce((p,u)=>d?.[u]?{...p,[u]:d[u]}:p,{}):null),t?.transform){let l=t.transform.schema[o];return d=d&&l?te(d,l,t.transform):d,d||null}return d||null},async findMany(r){let{model:o,where:n,limit:s,offset:a,sortBy:c}=r,i=e.selectFrom(o),{and:d,or:l}=ee(n);d&&(i=i.where(u=>u.and(d))),l&&(i=i.where(u=>u.or(l))),i=i.limit(s||100),a&&(i=i.offset(a)),c&&(i=i.orderBy(c.field,c.direction));let p=await i.selectAll().execute();if(t?.transform){let u=t.transform.schema[o];return u?p.map(m=>te(m,u,t.transform)):p}return p},async update(r){let{model:o,where:n,update:s}=r,{and:a,or:c}=ee(n);t?.transform&&(s=Tt(s,t.transform));let i=e.updateTable(o).set(s);a&&(i=i.where(l=>l.and(a))),c&&(i=i.where(l=>l.or(c)));let d=await i.returningAll().executeTakeFirst()||null;if(t?.transform){let l=t.transform.schema[o];return l?te(d,l,t.transform):d}return d},async delete(r){let{model:o,where:n}=r,{and:s,or:a}=ee(n),c=e.deleteFrom(o);s&&(c=c.where(i=>i.and(s))),a&&(c=c.where(i=>i.or(a))),await c.execute()}});async function vt(e,t){if(!e.database)throw new k("Database configuration is required");if("create"in e.database)return e.database;let{kysely:r,databaseType:o}=await H(e);if(!r)throw new k("Failed to initialize database adapter");let n=L(e),s={};for(let a of Object.values(n))s[a.tableName]=a.fields;return Ut(r,{transform:{schema:s,date:!0,boolean:o==="sqlite"}})}function ue(e,t){let r={id:t.id};for(let o in e){let n=e[o],s=t[o];r[n.fieldName||o]=s}return r}function pe(e,t){if(!t)return null;let r={id:t.id};for(let[o,n]of Object.entries(e))r[o]=t[n.fieldName||o];return r}import{defu as gr}from"defu";var me="better-auth-secret-123456789";var Et=async e=>{let t=await vt(e),r=e.plugins||[],o=yr(e),{kysely:n}=await H(e),s=z(e.baseURL,e.basePath);if(!s)throw new k("Base URL can not be empty. Please add `BETTER_AUTH_URL` in your environment variables or pass it your auth config.");let a=e.secret||process.env.BETTER_AUTH_SECRET||process.env.AUTH_SECRET||me;if(a===me&&process.env.NODE_ENV==="production")throw new k("You are using the default secret. Please set `BETTER_AUTH_SECRET` or `AUTH_SECRET` in your environment variables or pass `secret` in your auth config.");e={...e,secret:a,baseURL:s?new URL(s).origin:"",basePath:e.basePath||"/api/auth",plugins:r.concat(o)};let c=Oe(e),i=L(e),d=Object.keys(e.socialProviders||{}).map(u=>{let m=e.socialProviders?.[u];return m.enabled===!1?null:((!m.clientId||!m.clientSecret)&&w.warn(`Social provider ${u} is missing clientId or clientSecret`),ae[u](m))}).filter(u=>u!==null),l={appName:e.appName||"Better Auth",socialProviders:d,options:e,tables:i,trustedOrigins:wr(e),baseURL:s,sessionConfig:{updateAge:e.session?.updateAge||24*60*60,expiresIn:e.session?.expiresIn||60*60*24*7},secret:a,rateLimit:{...e.rateLimit,enabled:e.rateLimit?.enabled??process.env.NODE_ENV!=="development",window:e.rateLimit?.window||60,max:e.rateLimit?.max||100,storage:e.rateLimit?.storage||e.secondaryStorage?"secondary-storage":"memory"},authCookies:c,logger:ne({disabled:e.logger?.disabled||!1}),db:n,uuid:U,secondaryStorage:e.secondaryStorage,password:{hash:e.emailAndPassword?.password?.hash||ye,verify:e.emailAndPassword?.password?.verify||we,config:{minPasswordLength:e.emailAndPassword?.minPasswordLength||8,maxPasswordLength:e.emailAndPassword?.maxPasswordLength||128}},adapter:t,internalAdapter:fe(t,{options:e,hooks:e.databaseHooks?[e.databaseHooks]:[]}),createAuthCookie:Se(e)},{context:p}=hr(l);return p};function hr(e){let t=e.options,r=t.plugins||[],o=e,n=[];for(let s of r)if(s.init){let a=s.init(e);typeof a=="object"&&(a.options&&(a.options.databaseHooks&&n.push(a.options.databaseHooks),t=gr(t,a.options)),a.context&&(o={...o,...a.context}))}return n.push(t.databaseHooks),o.internalAdapter=fe(e.adapter,{options:t,hooks:n.filter(s=>s!==void 0)}),o.options=t,{context:o}}function yr(e){let t=[];return e.advanced?.crossSubDomainCookies?.enabled,t}function wr(e){let t=z(e.baseURL,e.basePath);if(!t)throw new k("Base URL can not be empty. Please add `BETTER_AUTH_URL` in your environment variables or pass it in your auth config.");let r=[new URL(t).origin];e.trustedOrigins&&r.push(...e.trustedOrigins);let o=process.env.BETTER_AUTH_TRUSTED_ORIGINS;return o&&r.push(...o.split(",")),r}var wd=e=>{let t=Et(e),{api:r}=le(t,e);return{handler:async o=>{let n=await t,s=n.options.basePath||"/api/auth",a=new URL(o.url);if(!n.options.baseURL){let i=z(void 0,s)||`${a.origin}${s}`;n.options.baseURL=i,n.baseURL=i}if(!n.options.baseURL)return new Response("Base URL not set",{status:400});if(a.pathname===s||a.pathname===`${s}/`)return new Response("Welcome to BetterAuth",{status:200});let{handler:c}=yt(n,e);return c(o)},api:r,options:e,$Infer:{}}};export{k as BetterAuthError,_ as HIDE_METADATA,Pe as MissingDependencyError,wd as betterAuth,sn as capitalizeFirstLetter,Se as createCookieGetter,ne as createLogger,j as deleteSessionCookie,U as generateId,Ee as generateState,Oe as getCookies,w as logger,so as parseSetCookieHeader,oe as parseState,P as setSessionCookie};
package/dist/plugins.js CHANGED
@@ -1,6 +1,6 @@
1
1
  var hr=Object.defineProperty;var wr=(e,t)=>{for(var r in t)hr(e,r,{get:t[r],enumerable:!0})};import{APIError as Xt}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as yr,createMiddleware as st,createMiddlewareCreator as br}from"better-call";var at=st(async()=>({})),C=br({use:[at,st(async()=>({}))]}),c=yr({use:[at]});import{APIError as ae}from"better-call";import{generateCodeVerifier as Nr}from"oslo/oauth2";import{z as Q}from"zod";import{generateState as Ar}from"oslo/oauth2";import{z as Be}from"zod";import{sha256 as dt}from"oslo/crypto";function Je(e,t){let r=new Uint8Array(e),o=new Uint8Array(t);if(r.length!==o.length)return!1;let n=0;for(let i=0;i<r.length;i++)n|=r[i]^o[i];return n===0}async function ct(e){let t=await dt(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ze(e,t){let r=await dt(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Je(r,o)}async function Le(e){let t=Ar(),r=JSON.stringify({code:t,callbackURL:e}),o=await ct(r);return{raw:r,hash:o}}function he(e){return Be.object({code:Be.string(),callbackURL:Be.string().optional(),currentURL:Be.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as dn}from"oslo";var $=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};async function b(e,t,r,o){let n=e.context.authCookies.sessionToken.options;n.maxAge=r?void 0:e.context.sessionConfig.expiresIn,await e.setSignedCookie(e.context.authCookies.sessionToken.name,t,e.context.secret,{...n,...o}),r&&await e.setSignedCookie(e.context.authCookies.dontRememberToken.name,"true",e.context.secret,e.context.authCookies.dontRememberToken.options)}function Oe(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}import{APIError as ut}from"better-call";import{createConsola as kr}from"consola";var ce=kr({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),Or=e=>({log:(...t)=>{!e?.disabled&&ce.log("",...t)},error:(...t)=>{!e?.disabled&&ce.error("",...t)},warn:(...t)=>{!e?.disabled&&ce.warn("",...t)},info:(...t)=>{!e?.disabled&&ce.info("",...t)},debug:(...t)=>{!e?.disabled&&ce.debug("",...t)},box:(...t)=>{!e?.disabled&&ce.box("",...t)},success:(...t)=>{!e?.disabled&&ce.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
2
- `)}}),A=Or();var z=C(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let i=new URL(t).origin;if(!n.includes(i))throw A.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new ut("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw A.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new ut("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as Ur}from"oslo/jwt";import{sha256 as Rr}from"oslo/crypto";function lt(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Ir}from"oslo/encoding";async function pt(e){let t=await Rr(new TextEncoder().encode(e));return Ir.encode(new Uint8Array(t),{includePadding:!1})}function mt(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function B({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let u=new URL(r);if(u.searchParams.set("response_type","code"),u.searchParams.set("client_id",t.clientId),u.searchParams.set("state",o),u.searchParams.set("scope",i.join(" ")),u.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await pt(n);u.searchParams.set("code_challenge_method","S256"),u.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,k)=>(p[k]=null,p),{});u.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return u}import{betterFetch as vr}from"@better-fetch/fetch";async function U({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let i=new URLSearchParams;i.set("grant_type","authorization_code"),i.set("code",e),t&&i.set("code_verifier",t),i.set("redirect_uri",r),i.set("client_id",o.clientId),i.set("client_secret",o.clientSecret);let{data:a,error:s}=await vr(n,{method:"POST",body:i,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(s)throw s;return mt(a)}function we(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var ft=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=e.scope||o||["email","name","openid"];return 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}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>U({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Ur(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Tr}from"@better-fetch/fetch";var gt=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return 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}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Tr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Er}from"@better-fetch/fetch";var ht=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await B({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})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Er("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as wt}from"@better-fetch/fetch";var yt=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 a=e.scope||o||["user:email"];return B({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>U({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await wt("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await wt("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as Sr}from"oslo/jwt";var bt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw A.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return B({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=Sr(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as Pr}from"@better-fetch/fetch";import{parseJWT as _r}from"oslo/jwt";var At=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=e.scope||n.scopes||["openid","profile","email","User.Read"];return B({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return U({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=_r(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Pr(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let u=await s.response.clone().arrayBuffer(),l=Buffer.from(u).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){A.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as Cr}from"@better-fetch/fetch";var kt=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return B({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})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await Cr("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var se={isAction:!1};function zr(e){return e.toString(2).padStart(8,"0")}function Br(e){return[...e].map(t=>zr(t)).join("")}function Ot(e){return parseInt(Br(e),2)}function Lr(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));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=Ot(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Ot(o);return n}function F(e,t){let r="";for(let o=0;o<e;o++)r+=t[Lr(t.length)];return r}function M(...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 P=e=>F(e||21,M("a-z","0-9","A-Z"));import{parseJWT as xr}from"oslo/jwt";var Rt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return B({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"]})},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return A.error("No idToken found in token"),null;let o=xr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Dr}from"@better-fetch/fetch";var It=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return B({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Dr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var jr={apple:ft,discord:gt,facebook:ht,github:yt,microsoft:At,google:bt,spotify:kt,twitch:Rt,twitter:It},vt=Object.keys(jr);var Fr=c("/sign-in/social",{method:"POST",requireHeaders:!0,query:Q.object({currentURL:Q.string().optional()}).optional(),body:Q.object({callbackURL:Q.string().optional(),provider:Q.enum(vt)}),use:[z]},async e=>{let t=e.context.socialProviders.find(d=>d.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 ae("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,i=await Le(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=Nr();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let s=await t.createAuthorizationURL({state:i.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:s.toString(),state:i,codeVerifier:a,redirect:!0})}),Mr=c("/sign-in/email",{method:"POST",body:Q.object({email:Q.string().email(),password:Q.string(),callbackURL:Q.string().optional(),dontRememberMe:Q.boolean().default(!1).optional()}),use:[z]},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 ae("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!Q.string().email().safeParse(t).success)throw new ae("BAD_REQUEST",{message:"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 ae("UNAUTHORIZED",{message:"Invalid email or password"});let i=n.accounts.find(u=>u.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new ae("UNAUTHORIZED",{message:"Invalid email or password"});let a=i?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new ae("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new ae("UNAUTHORIZED",{message:"Invalid email or password"});let d=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!d)throw e.context.logger.error("Failed to create session"),new ae("UNAUTHORIZED",{message:"Failed to create session"});return await b(e,d.id,e.body.dontRememberMe),e.json({user:n.user,session:d,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as $r}from"better-call";import{z as De}from"zod";import{z as w}from"zod";var ns=w.object({id:w.string(),providerId:w.string(),accountId:w.string(),userId:w.string(),accessToken:w.string().nullable().optional(),refreshToken:w.string().nullable().optional(),idToken:w.string().nullable().optional(),expiresAt:w.date().nullable().optional(),password:w.string().optional().nullable()}),xe=w.object({id:w.string(),email:w.string().transform(e=>e.toLowerCase()),emailVerified:w.boolean().default(!1),name:w.string(),image:w.string().optional(),createdAt:w.date().default(new Date),updatedAt:w.date().default(new Date)}),is=w.object({id:w.string(),userId:w.string(),expiresAt:w.date(),ipAddress:w.string().optional(),userAgent:w.string().optional()}),ss=w.object({id:w.string(),value:w.string(),expiresAt:w.date(),identifier:w.string()});function qr(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Ut(e,t){let r={...e.user?.additionalFields};return qr(t||{},{fields:r})}var Vr=c("/callback/:id",{method:"GET",query:De.object({state:De.string(),code:De.string().optional(),error:De.string().optional()}),metadata:se},async e=>{if(e.query.error||!e.query.code){let h=he(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${h}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(f=>f.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=he(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,i=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!i)throw A.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ze(e.query.state,i))throw A.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let s=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),d;try{d=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:s,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(f){throw e.context.logger.error(f),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let u=await t.getUserInfo(d).then(f=>f?.user),l=P(),p=xe.safeParse({...u,id:l});if(!u||p.success===!1)throw A.error("Unable to get user info",p.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let k=await e.context.internalAdapter.findUserByEmail(u.email,{includeAccounts:!0}).catch(f=>{throw A.error(`Better auth was unable to query your database.
3
- Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=k?.user.id;if(k){let f=k.accounts.find(I=>I.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,R=h?h.includes(t.id):!0;if(!f&&(!u.emailVerified||!R)){let I;try{I=new URL(n||o),I.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(I.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:u.id.toString(),id:`${t.id}:${u.id}`,userId:k.user.id,...we(d)})}catch(I){throw console.log(I),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{await e.context.internalAdapter.createOAuthUser(p.data,{...we(d),id:`${t.id}:${u.id}`,providerId:t.id,accountId:u.id.toString(),userId:l})}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",h.toString()),e.redirect(h.toString())}if(!m&&!l)throw new $r("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let f=await e.context.internalAdapter.createSession(m||l,e.request);if(!f){let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_session"),e.redirect(h.toString())}try{await b(e,f.id)}catch(h){e.context.logger.error("Unable to set session cookie",h);let R=new URL(n||o);throw R.searchParams.set("error","unable_to_create_session"),e.redirect(R.toString())}}catch{let f=new URL(n||o||"");throw f.searchParams.set("error","unable_to_create_session"),e.redirect(f.toString())}throw e.redirect(o)});import{APIError as Re}from"better-call";var q=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Tt}from"zod";var Et=()=>c("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return Oe(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,i=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+i*1e3<=Date.now()){let d=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:q(e.context.sessionConfig.expiresIn,"sec")});if(!d)return Oe(e),e.json(null,{status:401});let u=(d.expiresAt.valueOf()-Date.now())/1e3;return await b(e,d.id,!1,{maxAge:u}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),H=async e=>await Et()({...e,_flag:"json",headers:e.headers}),y=C(async e=>{let t=await H(e);if(!t?.session)throw new Re("UNAUTHORIZED");return{session:t}});var Qr=c("/user/revoke-session",{method:"POST",body:Tt.object({id:Tt.string()}),use:[y],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Re("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Re("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Re("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Hr=c("/user/revoke-sessions",{method:"POST",use:[y],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Re("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import"zod";import{APIError as Wr}from"better-call";var Kr=c("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Wr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),Oe(e),e.json({success:!0})});import{z as te}from"zod";import{APIError as je}from"better-call";var Jr=c("/forget-password",{method:"POST",body:te.object({email:te.string().email(),redirectTo:te.string()}),use:[z]},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 je("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=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),a=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${a}`,expiresAt:i});let s=`${e.context.baseURL}/reset-password/${a}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(s,o.user),e.json({status:!0})}),Gr=c("/reset-password/:token",{method:"GET",query:te.object({callbackURL:te.string()}),use:[z]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),Zr=c("/reset-password",{query:te.object({token:te.string()}).optional(),method:"POST",body:te.object({newPassword:te.string()})},async e=>{let t=e.query?.token;if(!t)throw new je("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new je("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let i=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(i)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:i,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(i,a))throw new je("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{TimeSpan as Yr}from"oslo";import{createJWT as Xr,validateJWT as eo}from"oslo/jwt";import{z as J}from"zod";import{APIError as Ne}from"better-call";async function Ge(e,t){return await Xr("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new Yr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var to=c("/send-verification-email",{method:"POST",query:J.object({currentURL:J.string().optional()}).optional(),body:J.object({email:J.string().email(),callbackURL:J.string().optional()}),use:[z]},async e=>{if(!e.context.options.emailAndPassword?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new Ne("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new Ne("BAD_REQUEST",{message:"User not found"});let o=await Ge(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailAndPassword.sendVerificationEmail(n,r.user,o),e.json({status:!0})}),ro=c("/verify-email",{method:"GET",query:J.object({token:J.string(),callbackURL:J.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await eo("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new Ne("BAD_REQUEST",{message:"Invalid token"})}let n=J.object({email:J.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new Ne("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});import{z as W}from"zod";import{APIError as G}from"better-call";var oo=c("/user/update",{method:"POST",body:W.object({name:W.string().optional(),image:W.string().optional()}),use:[y,z]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),no=c("/user/change-password",{method:"POST",body:W.object({newPassword:W.string(),currentPassword:W.string(),revokeOtherSessions:W.boolean().optional()}),use:[y]},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 G("BAD_REQUEST",{message:"Password is too short"});let a=e.context.password.config.maxPasswordLength;if(t.length>a)throw e.context.logger.error("Password is too long"),new G("BAD_REQUEST",{message:"Password too long"});let d=(await e.context.internalAdapter.findAccounts(n.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!d||!d.password)throw new G("BAD_REQUEST",{message:"User does not have a password"});let u=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new G("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:u}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new G("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await b(e,p.id)}return e.json(n.user)}),io=c("/user/set-password",{method:"POST",body:W.object({newPassword:W.string()}),use:[y]},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 G("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new G("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(r.user.id)).find(d=>d.providerId==="credential"&&d.password),s=await e.context.password.hash(t);if(!a)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:s}),e.json(r.user);throw new G("BAD_REQUEST",{message:"user already has a password"})}),so=c("/user/delete",{method:"POST",body:W.object({password:W.string()}),use:[y]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new G("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new G("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)});import{xchacha20poly1305 as St}from"@noble/ciphers/chacha";import{bytesToHex as ao,hexToBytes as co,utf8ToBytes as uo}from"@noble/ciphers/utils";import{managedNonce as Pt}from"@noble/ciphers/webcrypto";import{sha256 as _t}from"oslo/crypto";import{decodeHex as na,encodeHex as ia}from"oslo/encoding";import{scryptAsync as da}from"@noble/hashes/scrypt";async function K(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),i=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(i)))}var Fe=async({key:e,data:t})=>{let r=await _t(new TextEncoder().encode(e)),o=uo(t),n=Pt(St)(new Uint8Array(r));return ao(n.encrypt(o))},Me=async({key:e,data:t})=>{let r=await _t(new TextEncoder().encode(e)),o=co(t),n=Pt(St)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var lo=c("/csrf",{method:"GET",metadata:se},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t)return{csrfToken:t};let r=F(32,M("a-z","0-9","A-Z")),o=await K(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:r}});var po=(e="Unknown")=>`<!DOCTYPE html>
2
+ `)}}),A=Or();var z=C(async e=>{let t=e.body?.callbackURL||e.query?.callbackURL||e.query?.redirectTo||e.body?.redirectTo,r=e.headers?.get("referer"),o=e.query?.currentURL||r||e.context.baseURL,n=e.context.trustedOrigins;if(t?.includes("http")){let i=new URL(t).origin;if(!n.includes(i))throw A.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new ut("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw A.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new ut("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as Ur}from"oslo/jwt";import{sha256 as Rr}from"oslo/crypto";function lt(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Ir}from"oslo/encoding";async function pt(e){let t=await Rr(new TextEncoder().encode(e));return Ir.encode(new Uint8Array(t),{includePadding:!1})}function mt(e){return{tokenType:e.token_type,accessToken:e.access_token,refreshToken:e.refresh_token,accessTokenExpiresAt:e.expires_at?new Date((Date.now()+e.expires_in)*1e3):void 0,scopes:e?.scope?typeof e.scope=="string"?e.scope.split(" "):e.scope:[],idToken:e.id_token}}async function B({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){let u=new URL(r);if(u.searchParams.set("response_type","code"),u.searchParams.set("client_id",t.clientId),u.searchParams.set("state",o),u.searchParams.set("scope",i.join(" ")),u.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await pt(n);u.searchParams.set("code_challenge_method","S256"),u.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,k)=>(p[k]=null,p),{});u.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return u}import{betterFetch as vr}from"@better-fetch/fetch";async function U({code:e,codeVerifier:t,redirectURI:r,options:o,tokenEndpoint:n}){let i=new URLSearchParams;i.set("grant_type","authorization_code"),i.set("code",e),t&&i.set("code_verifier",t),i.set("redirect_uri",r),i.set("client_id",o.clientId),i.set("client_secret",o.clientSecret);let{data:a,error:s}=await vr(n,{method:"POST",body:i,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(s)throw s;return mt(a)}function we(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var ft=e=>{let t="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:r,scopes:o,redirectURI:n}){let i=e.scope||o||["email","name","openid"];return 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}`)},validateAuthorizationCode:async({code:r,codeVerifier:o,redirectURI:n})=>U({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Ur(r.idToken)?.payload;return o?{user:{id:o.sub,name:o.name,email:o.email,emailVerified:o.email_verified==="true"},data:o}:null}}};import{betterFetch as Tr}from"@better-fetch/fetch";var gt=e=>({id:"discord",name:"Discord",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["identify","email"];return 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}`)},validateAuthorizationCode:async({code:t,redirectURI:r})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Tr("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${t.accessToken}`}});if(o)return null;if(r.avatar===null){let n=r.discriminator==="0"?Number(BigInt(r.id)>>BigInt(22))%6:parseInt(r.discriminator)%5;r.image_url=`https://cdn.discordapp.com/embed/avatars/${n}.png`}else{let n=r.avatar.startsWith("a_")?"gif":"png";r.image_url=`https://cdn.discordapp.com/avatars/${r.id}/${r.avatar}.${n}`}return{user:{id:r.id,name:r.display_name||r.username||"",email:r.email,emailVerified:r.verified,image:r.image_url},data:r}}});import{betterFetch as Er}from"@better-fetch/fetch";var ht=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await B({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})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(t){let{data:r,error:o}=await Er("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:t.accessToken}});return o?null:{user:{id:r.id,name:r.name,email:r.email,emailVerified:r.email_verified},data:r}}});import{betterFetch as wt}from"@better-fetch/fetch";var yt=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 a=e.scope||o||["user:email"];return B({id:"github",options:e,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:a,state:r,redirectURI:i,codeVerifier:n})},validateAuthorizationCode:async({code:r,redirectURI:o})=>U({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await wt("https://api.github.com/user",{auth:{type:"Bearer",token:r.accessToken}});if(n)return null;let i=!1;if(!o.email){let{data:a,error:s}=await wt("https://api.github.com/user/emails",{auth:{type:"Bearer",token:r.accessToken}});s||(o.email=(a.find(d=>d.primary)??a[0])?.email,i=a.find(d=>d.email===o.email)?.verified??!1)}return{user:{id:o.id.toString(),name:o.name||o.login,email:o.email,image:o.avatar_url,emailVerified:i},data:o}}}};import{parseJWT as Sr}from"oslo/jwt";var bt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw A.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new $("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new $("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return B({id:"google",options:e,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:i,state:t,codeVerifier:o,redirectURI:n})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(t){if(!t.idToken)return null;let r=Sr(t.idToken)?.payload;return{user:{id:r.sub,name:r.name,email:r.email,image:r.picture,emailVerified:r.email_verified},data:r}}});import{betterFetch as Pr}from"@better-fetch/fetch";import{parseJWT as _r}from"oslo/jwt";var At=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=e.scope||n.scopes||["openid","profile","email","User.Read"];return B({id:"microsoft",options:e,authorizationEndpoint:r,state:n.state,codeVerifier:n.codeVerifier,scopes:i,redirectURI:n.redirectURI})},validateAuthorizationCode({code:n,codeVerifier:i,redirectURI:a}){return U({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=_r(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Pr(`https://graph.microsoft.com/v1.0/me/photos/${a}x${a}/$value`,{headers:{Authorization:`Bearer ${n.accessToken}`},async onResponse(s){if(!(e.disableProfilePhoto||!s.response.ok))try{let u=await s.response.clone().arrayBuffer(),l=Buffer.from(u).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){A.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as Cr}from"@better-fetch/fetch";var kt=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return B({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})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(t){let{data:r,error:o}=await Cr("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o?null:{user:{id:r.id,name:r.display_name,email:r.email,image:r.images[0]?.url,emailVerified:!1},data:r}}});import"@better-fetch/fetch";var se={isAction:!1};function zr(e){return e.toString(2).padStart(8,"0")}function Br(e){return[...e].map(t=>zr(t)).join("")}function Ot(e){return parseInt(Br(e),2)}function Lr(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));crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1);let n=Ot(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Ot(o);return n}function F(e,t){let r="";for(let o=0;o<e;o++)r+=t[Lr(t.length)];return r}function M(...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 P=e=>F(e||21,M("a-z","0-9","A-Z"));import{parseJWT as xr}from"oslo/jwt";var Rt=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return B({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})=>U({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let r=t.idToken;if(!r)return A.error("No idToken found in token"),null;let o=xr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Dr}from"@better-fetch/fetch";var It=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return B({id:"twitter",options:e,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:r,state:t.state,codeVerifier:t.codeVerifier,redirectURI:t.redirectURI})},validateAuthorizationCode:async({code:t,codeVerifier:r,redirectURI:o})=>U({code:t,codeVerifier:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Dr("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${t.accessToken}`}});return o||!r.data.email?null:{user:{id:r.data.id,name:r.data.name,email:r.data.email,image:r.data.profile_image_url,emailVerified:r.data.verified||!1},data:r}}});var jr={apple:ft,discord:gt,facebook:ht,github:yt,microsoft:At,google:bt,spotify:kt,twitch:Rt,twitter:It},vt=Object.keys(jr);var Fr=c("/sign-in/social",{method:"POST",requireHeaders:!0,query:Q.object({currentURL:Q.string().optional()}).optional(),body:Q.object({callbackURL:Q.string().optional(),provider:Q.enum(vt)}),use:[z]},async e=>{let t=e.context.socialProviders.find(d=>d.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 ae("NOT_FOUND",{message:"Provider not found"});let r=e.context.authCookies,o=e.query?.currentURL?new URL(e.query?.currentURL):null,n=e.body.callbackURL?.startsWith("http")?e.body.callbackURL:`${o?.origin}${e.body.callbackURL||""}`,i=await Le(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=Nr();await e.setSignedCookie(r.pkCodeVerifier.name,a,e.context.secret,r.pkCodeVerifier.options);let s=await t.createAuthorizationURL({state:i.raw,codeVerifier:a,redirectURI:`${e.context.baseURL}/callback/${t.id}`});return e.json({url:s.toString(),state:i,codeVerifier:a,redirect:!0})}),Mr=c("/sign-in/email",{method:"POST",body:Q.object({email:Q.string().email(),password:Q.string(),callbackURL:Q.string().optional(),dontRememberMe:Q.boolean().default(!1).optional()}),use:[z]},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 ae("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!Q.string().email().safeParse(t).success)throw new ae("BAD_REQUEST",{message:"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 ae("UNAUTHORIZED",{message:"Invalid email or password"});let i=n.accounts.find(u=>u.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new ae("UNAUTHORIZED",{message:"Invalid email or password"});let a=i?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new ae("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new ae("UNAUTHORIZED",{message:"Invalid email or password"});let d=await e.context.internalAdapter.createSession(n.user.id,e.headers,e.body.dontRememberMe);if(!d)throw e.context.logger.error("Failed to create session"),new ae("UNAUTHORIZED",{message:"Failed to create session"});return await b(e,d.id,e.body.dontRememberMe),e.json({user:n.user,session:d,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as $r}from"better-call";import{z as De}from"zod";import{z as w}from"zod";var ns=w.object({id:w.string(),providerId:w.string(),accountId:w.string(),userId:w.string(),accessToken:w.string().nullable().optional(),refreshToken:w.string().nullable().optional(),idToken:w.string().nullable().optional(),expiresAt:w.date().nullable().optional(),password:w.string().optional().nullable()}),xe=w.object({id:w.string(),email:w.string().transform(e=>e.toLowerCase()),emailVerified:w.boolean().default(!1),name:w.string(),image:w.string().optional(),createdAt:w.date().default(new Date),updatedAt:w.date().default(new Date)}),is=w.object({id:w.string(),userId:w.string(),expiresAt:w.date(),ipAddress:w.string().optional(),userAgent:w.string().optional()}),ss=w.object({id:w.string(),value:w.string(),expiresAt:w.date(),identifier:w.string()});function qr(e,t){let r=t.fields,o={};for(let n in r){if(n in e){if(r[n].input===!1){if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}continue}o[n]=e[n];continue}if(r[n].defaultValue){o[n]=r[n].defaultValue;continue}}return o}function Ut(e,t){let r={...e.user?.additionalFields};return qr(t||{},{fields:r})}var Vr=c("/callback/:id",{method:"GET",query:De.object({state:De.string(),code:De.string().optional(),error:De.string().optional()}),metadata:se},async e=>{if(e.query.error||!e.query.code){let h=he(e.query.state).data?.callbackURL||`${e.context.baseURL}/error`;throw e.context.logger.error(e.query.error,e.params.id),e.redirect(`${h}?error=${e.query.error||"oAuth_code_missing"}`)}let t=e.context.socialProviders.find(f=>f.id===e.params.id);if(!t)throw e.context.logger.error("Oauth provider with id",e.params.id,"not found"),e.redirect(`${e.context.baseURL}/error?error=oauth_provider_not_found`);let r=he(e.query.state);if(!r.success)throw e.context.logger.error("Unable to parse state"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let{data:{callbackURL:o,currentURL:n}}=r,i=await e.getSignedCookie(e.context.authCookies.state.name,e.context.secret);if(!i)throw A.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ze(e.query.state,i))throw A.error("OAuth state mismatch"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let s=await e.getSignedCookie(e.context.authCookies.pkCodeVerifier.name,e.context.secret),d;try{d=await t.validateAuthorizationCode({code:e.query.code,codeVerifier:s,redirectURI:`${e.context.baseURL}/callback/${t.id}`})}catch(f){throw e.context.logger.error(f),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`)}let u=await t.getUserInfo(d).then(f=>f?.user),l=P(),p=xe.safeParse({...u,id:l});if(!u||p.success===!1)throw A.error("Unable to get user info",p.error),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!o)throw e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);let k=await e.context.internalAdapter.findUserByEmail(u.email,{includeAccounts:!0}).catch(f=>{throw A.error(`Better auth was unable to query your database.
3
+ Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=k?.user.id;if(k){let f=k.accounts.find(I=>I.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,R=h?h.includes(t.id):!0;if(!f&&(!u.emailVerified||!R)){let I;try{I=new URL(n||o),I.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(I.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:u.id.toString(),id:`${t.id}:${u.id}`,userId:k.user.id,...we(d)})}catch(I){throw console.log(I),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{await e.context.internalAdapter.createOAuthUser(p.data,{...we(d),id:`${t.id}:${u.id}`,providerId:t.id,accountId:u.id.toString(),userId:l})}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.setHeader("Location",h.toString()),e.redirect(h.toString())}if(!m&&!l)throw new $r("INTERNAL_SERVER_ERROR",{message:"Unable to create user"});try{let f=await e.context.internalAdapter.createSession(m||l,e.request);if(!f){let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_session"),e.redirect(h.toString())}try{await b(e,f.id)}catch(h){e.context.logger.error("Unable to set session cookie",h);let R=new URL(n||o);throw R.searchParams.set("error","unable_to_create_session"),e.redirect(R.toString())}}catch{let f=new URL(n||o||"");throw f.searchParams.set("error","unable_to_create_session"),e.redirect(f.toString())}throw e.redirect(o)});import{APIError as Re}from"better-call";var q=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Tt}from"zod";var Et=()=>c("/session",{method:"GET",requireHeaders:!0},async e=>{try{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)return e.json(null,{status:401});let r=await e.context.internalAdapter.findSession(t);if(!r||r.session.expiresAt<new Date)return Oe(e),r&&await e.context.internalAdapter.deleteSession(r.session.id),e.json(null,{status:401});if(await e.getSignedCookie(e.context.authCookies.dontRememberToken.name,e.context.secret))return e.json(r);let n=e.context.sessionConfig.expiresIn,i=e.context.sessionConfig.updateAge;if(r.session.expiresAt.valueOf()-n*1e3+i*1e3<=Date.now()){let d=await e.context.internalAdapter.updateSession(r.session.id,{expiresAt:q(e.context.sessionConfig.expiresIn,"sec")});if(!d)return Oe(e),e.json(null,{status:401});let u=(d.expiresAt.valueOf()-Date.now())/1e3;return await b(e,d.id,!1,{maxAge:u}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),H=async e=>await Et()({...e,_flag:"json",headers:e.headers}),y=C(async e=>{let t=await H(e);if(!t?.session)throw new Re("UNAUTHORIZED");return{session:t}});var Qr=c("/user/revoke-session",{method:"POST",body:Tt.object({id:Tt.string()}),use:[y],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Re("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Re("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Re("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Hr=c("/user/revoke-sessions",{method:"POST",use:[y],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Re("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import"zod";import{APIError as Wr}from"better-call";var Kr=c("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Wr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),Oe(e),e.json({success:!0})});import{z as te}from"zod";import{APIError as je}from"better-call";var Jr=c("/forget-password",{method:"POST",body:te.object({email:te.string().email(),redirectTo:te.string()}),use:[z]},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 je("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=new Date(Date.now()+1e3*(e.context.options.emailAndPassword.resetPasswordTokenExpiresIn||n)),a=e.context.uuid();await e.context.internalAdapter.createVerificationValue({value:o.user.id,identifier:`reset-password:${a}`,expiresAt:i});let s=`${e.context.baseURL}/reset-password/${a}?callbackURL=${r}`;return await e.context.options.emailAndPassword.sendResetPassword(s,o.user),e.json({status:!0})}),Gr=c("/reset-password/:token",{method:"GET",query:te.object({callbackURL:te.string()}),use:[z]},async e=>{let{token:t}=e.params,r=e.query.callbackURL,o=r.startsWith("http")?r:`${e.context.options.baseURL}${r}`;if(!t||!r)throw e.redirect(`${e.context.baseURL}/error?error=INVALID_TOKEN`);let n=await e.context.internalAdapter.findVerificationValue(`reset-password:${t}`);throw!n||n.expiresAt<new Date?e.redirect(`${o}?error=INVALID_TOKEN`):e.redirect(`${o}?token=${t}`)}),Zr=c("/reset-password",{query:te.object({token:te.string()}).optional(),method:"POST",body:te.object({newPassword:te.string()})},async e=>{let t=e.query?.token;if(!t)throw new je("BAD_REQUEST",{message:"Token not found"});let{newPassword:r}=e.body,o=`reset-password:${t}`,n=await e.context.internalAdapter.findVerificationValue(o);if(!n||n.expiresAt<new Date)throw new je("BAD_REQUEST",{message:"Invalid token"});await e.context.internalAdapter.deleteVerificationValue(n.id);let i=n.value,a=await e.context.password.hash(r);if(!(await e.context.internalAdapter.findAccounts(i)).find(l=>l.providerId==="credential"))return await e.context.internalAdapter.createAccount({userId:i,providerId:"credential",password:a,accountId:e.context.uuid()}),e.json({status:!0});if(!await e.context.internalAdapter.updatePassword(i,a))throw new je("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{TimeSpan as Yr}from"oslo";import{createJWT as Xr,validateJWT as eo}from"oslo/jwt";import{z as J}from"zod";import{APIError as Ne}from"better-call";async function Ge(e,t){return await Xr("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new Yr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var to=c("/send-verification-email",{method:"POST",query:J.object({currentURL:J.string().optional()}).optional(),body:J.object({email:J.string().email(),callbackURL:J.string().optional()}),use:[z]},async e=>{if(!e.context.options.emailAndPassword?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new Ne("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new Ne("BAD_REQUEST",{message:"User not found"});let o=await Ge(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailAndPassword.sendVerificationEmail(n,r.user,o),e.json({status:!0})}),ro=c("/verify-email",{method:"GET",query:J.object({token:J.string(),callbackURL:J.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await eo("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new Ne("BAD_REQUEST",{message:"Invalid token"})}let n=J.object({email:J.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new Ne("BAD_REQUEST",{message:"User not found"});if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({status:!0})});import{z as W}from"zod";import{APIError as G}from"better-call";var oo=c("/user/update",{method:"POST",body:W.object({name:W.string().optional(),image:W.string().optional()}),use:[y,z]},async e=>{let{name:t,image:r}=e.body,o=e.context.session;if(!r&&!t)return e.json({user:o.user});let n=await e.context.internalAdapter.updateUserByEmail(o.user.email,{name:t,image:r});return e.json({user:n})}),no=c("/user/change-password",{method:"POST",body:W.object({newPassword:W.string(),currentPassword:W.string(),revokeOtherSessions:W.boolean().optional()}),use:[y]},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 G("BAD_REQUEST",{message:"Password is too short"});let a=e.context.password.config.maxPasswordLength;if(t.length>a)throw e.context.logger.error("Password is too long"),new G("BAD_REQUEST",{message:"Password too long"});let d=(await e.context.internalAdapter.findAccounts(n.user.id)).find(p=>p.providerId==="credential"&&p.password);if(!d||!d.password)throw new G("BAD_REQUEST",{message:"User does not have a password"});let u=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new G("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:u}),o){await e.context.internalAdapter.deleteSessions(n.user.id);let p=await e.context.internalAdapter.createSession(n.user.id,e.headers);if(!p)throw new G("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await b(e,p.id)}return e.json(n.user)}),io=c("/user/set-password",{method:"POST",body:W.object({newPassword:W.string()}),use:[y]},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 G("BAD_REQUEST",{message:"Password is too short"});let n=e.context.password.config.maxPasswordLength;if(t.length>n)throw e.context.logger.error("Password is too long"),new G("BAD_REQUEST",{message:"Password too long"});let a=(await e.context.internalAdapter.findAccounts(r.user.id)).find(d=>d.providerId==="credential"&&d.password),s=await e.context.password.hash(t);if(!a)return await e.context.internalAdapter.linkAccount({userId:r.user.id,providerId:"credential",accountId:r.user.id,password:s}),e.json(r.user);throw new G("BAD_REQUEST",{message:"user already has a password"})}),so=c("/user/delete",{method:"POST",body:W.object({password:W.string()}),use:[y]},async e=>{let{password:t}=e.body,r=e.context.session,n=(await e.context.internalAdapter.findAccounts(r.user.id)).find(a=>a.providerId==="credential"&&a.password);if(!n||!n.password)throw new G("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new G("BAD_REQUEST",{message:"Incorrect password"});return await e.context.internalAdapter.deleteUser(r.user.id),await e.context.internalAdapter.deleteSessions(r.user.id),e.json(null)});import{xchacha20poly1305 as St}from"@noble/ciphers/chacha";import{bytesToHex as ao,hexToBytes as co,utf8ToBytes as uo}from"@noble/ciphers/utils";import{managedNonce as Pt}from"@noble/ciphers/webcrypto";import{sha256 as _t}from"oslo/crypto";import{decodeHex as na,encodeHex as ia}from"oslo/encoding";import{scryptAsync as da}from"@noble/hashes/scrypt";async function K(e,t){let r=new TextEncoder,o={name:"HMAC",hash:"SHA-256"},n=await crypto.subtle.importKey("raw",r.encode(e),o,!1,["sign","verify"]),i=await crypto.subtle.sign(o.name,n,r.encode(t));return btoa(String.fromCharCode(...new Uint8Array(i)))}var Fe=async({key:e,data:t})=>{let r=await _t(new TextEncoder().encode(e)),o=uo(t),n=Pt(St)(new Uint8Array(r));return ao(n.encrypt(o))},Me=async({key:e,data:t})=>{let r=await _t(new TextEncoder().encode(e)),o=co(t),n=Pt(St)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var lo=c("/csrf",{method:"GET",metadata:se},async e=>{let t=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret);if(t){let[i,a]=t.split("!")||[null,null];return{csrfToken:i}}let r=F(32,M("a-z","0-9","A-Z")),o=await K(e.context.secret,r),n=`${r}!${o}`;return await e.setSignedCookie(e.context.authCookies.csrfToken.name,n,e.context.secret,e.context.authCookies.csrfToken.options),{csrfToken:r}});var po=(e="Unknown")=>`<!DOCTYPE html>
4
4
  <html lang="en">
5
5
  <head>
6
6
  <meta charset="UTF-8">
@@ -80,5 +80,5 @@ Error: `,f),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>`,mo=c("/error",{method:"GET",metadata:se},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(po(t),{headers:{"Content-Type":"text/html"}})});var fo=c("/ok",{method:"GET",metadata:se},async e=>e.json({ok:!0}));import{z as ye}from"zod";import{APIError as ue}from"better-call";var Ie=()=>c("/sign-up/email",{method:"POST",query:ye.object({currentURL:ye.string().optional()}).optional(),body:ye.record(ye.string(),ye.any()),use:[z]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!ye.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let u=e.context.password.config.minPasswordLength;if(n.length<u)throw e.context.logger.error("Password is too short"),new ue("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new ue("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new ue("UNPROCESSABLE_ENTITY",{message:"The email has already been taken"});let k=Ut(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...k,emailVerified:!1});if(!m)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:q(60*60*24*30,"sec")});let h=await e.context.internalAdapter.createSession(m.id,e.request);if(!h)throw new ue("BAD_REQUEST",{message:"Failed to create session"});if(await b(e,h.id),e.context.options.emailAndPassword.sendEmailVerificationOnSignUp){let R=await Ge(e.context.secret,m.email),I=`${e.context.baseURL}/verify-email?token=${R}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailAndPassword.sendVerificationEmail?.(I,m,R)}return e.json({user:m,session:h},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:h}})});var Ct=(e,t)=>{let r={};for(let[o,n]of Object.entries(e))r[o]=i=>n({...i,context:{...t,...i.context}}),r[o].path=n.path,r[o].method=n.method,r[o].options=n.options,r[o].headers=n.headers;return r};var jt={};wr(jt,{AccessControl:()=>ve,ParsingError:()=>le,Role:()=>be,adminAc:()=>Lt,createAccessControl:()=>zt,defaultAc:()=>qe,defaultRoles:()=>Ze,defaultStatements:()=>Bt,memberAc:()=>Dt,ownerAc:()=>xt,permissionFromString:()=>go});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},ve=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new be(t)}},be=class e{statements;constructor(t){this.statements=t}authorize(t,r){for(let[o,n]of Object.entries(t)){let i=this.statements[o];if(!i)return{success:!1,error:`You are not allowed to access resource: ${o}`};let a=r==="OR"?n.some(s=>i.includes(s)):n.every(s=>i.includes(s));return a?{success:a}:{success:!1,error:`unauthorized to access resource "${o}"`}}return{success:!1,error:"Not authorized"}}static fromString(t){let r=JSON.parse(t);if(typeof r!="object")throw new le("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new le("invalid resource identifier",o);if(!Array.isArray(n))throw new le("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new le("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var zt=e=>new ve(e),Bt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},qe=zt(Bt),Lt=qe.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),xt=qe.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),Dt=qe.newRole({organization:[],member:[],invitation:[]}),Ze={admin:Lt,owner:xt,member:Dt};var go=e=>be.fromString(e??"");var E=(e,t)=>({findOrganizationBySlug:async r=>await e.findOne({model:"organization",where:[{field:"slug",value:r}]}),createOrganization:async r=>{let o=await e.create({model:"organization",data:{...r.organization,metadata:r.organization.metadata?JSON.stringify(r.organization.metadata):void 0}}),n=await e.create({model:"member",data:{id:P(),organizationId:o.id,userId:r.user.id,createdAt:new Date,email:r.user.email,role:t?.creatorRole||"owner"}});return{...o,metadata:o.metadata?JSON.parse(o.metadata):void 0,members:[{...n,user:{id:r.user.id,name:r.user.name,email:r.user.email,image:r.user.image}}]}},findMemberByEmail:async r=>{let o=await e.findOne({model:"member",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberByOrgId:async r=>{let o=await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberById:async r=>{let o=await e.findOne({model:"member",where:[{field:"id",value:r}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},createMember:async r=>await e.create({model:"member",data:r}),updateMember:async(r,o)=>await e.update({model:"member",where:[{field:"id",value:r}],update:{role:o}}),deleteMember:async r=>await e.delete({model:"member",where:[{field:"id",value:r}]}),updateOrganization:async(r,o)=>await e.update({model:"organization",where:[{field:"id",value:r}],update:o}),deleteOrganization:async r=>(await e.delete({model:"member",where:[{field:"organizationId",value:r}]}),await e.delete({model:"invitation",where:[{field:"organizationId",value:r}]}),await e.delete({model:"organization",where:[{field:"id",value:r}]}),r),setActiveOrganization:async(r,o)=>await e.update({model:"session",where:[{field:"id",value:r}],update:{activeOrganizationId:o}}),findOrganizationById:async r=>await e.findOne({model:"organization",where:[{field:"id",value:r}]}),findFullOrganization:async(r,o)=>{let n=await e.findOne({model:"organization",where:[{field:"id",value:r}]});if(!n)return null;let i=await e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),a=await e.findMany({model:"member",where:[{field:"organizationId",value:r}]}),s=await Promise.all(a.map(async u=>{let l=await e.findOne({model:"user",where:[{field:"id",value:u.userId}]});if(!l)throw new $("Unexpected error: User not found for member");return{...u,user:{id:l.id,name:l.name,email:l.email,image:l.image}}}));return{...n,invitations:i,members:s}},listOrganizations:async r=>{let n=(await e.findMany({model:"member",where:[{field:"userId",value:r}]}))?.map(a=>a.organizationId);if(!n)return[];let i=[];for(let a of n){let s=await e.findOne({model:"organization",where:[{field:"id",value:a}]});s&&i.push(s)}return i},createInvitation:async({invitation:r,user:o})=>{let i=q(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:P(),email:r.email,role:r.role,organizationId:r.organizationId,status:"pending",expiresAt:i,inviterId:o.id}})},findInvitationById:async r=>await e.findOne({model:"invitation",where:[{field:"id",value:r}]}),findPendingInvitation:async r=>(await e.findMany({model:"invitation",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId},{field:"status",value:"pending"}]})).filter(n=>new Date(n.expiresAt)>new Date),updateInvitation:async r=>await e.update({model:"invitation",where:[{field:"id",value:r.invitationId}],update:{status:r.status}})});import"better-call";import{APIError as Cd,createRouter as zd}from"better-call";import{APIError as Ye}from"better-call";import{z as Nt}from"zod";var ho=C({body:Nt.object({csrfToken:Nt.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(e.context.trustedOrigins.includes(t.origin))return;let r=e.body?.csrfToken;if(!r)throw new Ye("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!o||!n||!i||o!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await K(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as de}from"better-call";var L=C(async e=>({})),j=C({use:[y]},async e=>({session:e.context.session}));import{z as V}from"zod";import{z as v}from"zod";var $e=v.enum(["admin","member","owner"]),wo=v.enum(["pending","accepted","rejected","canceled"]).default("pending"),rc=v.object({id:v.string(),name:v.string(),slug:v.string(),logo:v.string().optional(),metadata:v.record(v.string()).or(v.string().transform(e=>JSON.parse(e))).optional(),createdAt:v.date()}),oc=v.object({id:v.string(),email:v.string(),organizationId:v.string(),userId:v.string(),role:$e,createdAt:v.date()}),nc=v.object({id:v.string(),organizationId:v.string(),email:v.string(),role:$e,status:wo,inviterId:v.string(),expiresAt:v.date()});import{APIError as T}from"better-call";var Ft=c("/organization/invite-member",{method:"POST",use:[L,j],body:V.object({email:V.string(),role:$e,organizationId:V.string().optional(),resend:V.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw A.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new T("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new T("BAD_REQUEST",{message:"Organization not found"});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new T("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new T("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new T("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new T("BAD_REQUEST",{message:"User is already invited to this organization"});let u=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new T("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:u.id,role:u.role,email:u.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(u)}),Mt=c("/organization/accept-invitation",{method:"POST",body:V.object({invitationId:V.string()}),use:[L,j]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:P(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),qt=c("/organization/reject-invitation",{method:"POST",body:V.object({invitationId:V.string()}),use:[L,j]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),$t=c("/organization/cancel-invitation",{method:"POST",body:V.object({invitationId:V.string()}),use:[L,j]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new T("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new T("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),Vt=c("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:V.object({id:V.string()})},async e=>{let t=await H(e);if(!t)throw new T("UNAUTHORIZED",{message:"Not authenticated"});let r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new T("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new T("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as pe}from"zod";import{APIError as Ue}from"better-call";var Qt=c("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[L,j]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ue("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ue("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ue("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ue("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let u=null;if(e.body.memberIdOrEmail.includes("@")?u=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):u=await o.findMemberById(e.body.memberIdOrEmail),u?.organizationId!==r)throw new Ue("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(u.id),t.user.id===u.userId&&t.session.activeOrganizationId===u.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:u})}),Ht=c("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[L,j]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as S}from"zod";import{APIError as me}from"better-call";var Wt=c("/organization/create",{method:"POST",body:S.object({name:S.string(),slug:S.string(),userId:S.string().optional(),logo:S.string().optional(),metadata:S.record(S.string()).optional()}),use:[L,j]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new me("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=E(e.context.adapter,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new me("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new me("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:P(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),Kt=c("/organization/update",{method:"POST",body:S.object({data:S.object({name:S.string().optional(),slug:S.string().optional()}).partial(),orgId:S.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new me("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["update"]}).error)return e.json(null,{body:{message:"You are not allowed to update this organization"},status:403});let s=await o.updateOrganization(r,e.body.data);return e.json(s)}),Jt=c("/organization/delete",{method:"POST",body:S.object({orgId:S.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["delete"]}).error)throw new me("FORBIDDEN",{message:"You are not allowed to delete this organization"});return r===t.session.activeOrganizationId&&await o.setActiveOrganization(t.session.id,null),await o.deleteOrganization(r),e.json(r)}),Gt=c("/organization/get-full",{method:"GET",query:S.object({orgId:S.string().optional()}),requireHeaders:!0,use:[L,j]},async e=>{let t=e.context.session,r=e.query.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400});let n=await E(e.context.adapter,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new me("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Zt=c("/organization/activate",{method:"POST",body:S.object({orgId:S.string().nullable().optional()}),use:[j,L]},async e=>{let t=E(e.context.adapter,e.context.orgOptions),r=e.context.session,o=e.body.orgId;if(o===null)return r.session.activeOrganizationId&&await t.setActiveOrganization(r.session.id,null),e.json(null);if(!o){let a=r.session.activeOrganizationId;if(!a)return e.json(null);o=a}if(!await t.findMemberByOrgId({userId:r.user.id,organizationId:o}))throw await t.setActiveOrganization(r.session.id,null),new me("FORBIDDEN",{message:"You are not a member of this organization"});await t.setActiveOrganization(r.session.id,o);let i=await t.findFullOrganization(o,e.context.db||void 0);return e.json(i)}),Yt=c("/organization/list",{method:"GET",use:[L,j]},async e=>{let r=await E(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var Fc=e=>{let t={createOrganization:Wt,updateOrganization:Kt,deleteOrganization:Jt,setActiveOrganization:Zt,getFullOrganization:Gt,listOrganization:Yt,createInvitation:Ft,cancelInvitation:$t,acceptInvitation:Mt,getInvitation:Vt,rejectInvitation:qt,removeMember:Qt,updateMemberRole:Ht},r={...Ze,...e?.roles};return{id:"organization",endpoints:{...Ct(t,{orgOptions:e||{},roles:r,getSession:async n=>await H(n)}),hasPermission:c("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[j]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new Xt("BAD_REQUEST",{message:"No active organization"});let a=await E(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Xt("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import{z as We}from"zod";import{z as Se}from"zod";import{APIError as fe}from"better-call";var Ve="two-factor";var Qe="trust-device";import{z as er}from"zod";var ge=C({body:er.object({trustDevice:er.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(Ve),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let i=await e.context.adapter.findMany({model:"session",where:[{field:"userId",value:o}]});if(!i.length)throw new fe("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new fe("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await K(e.context.secret,s.id),u=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!u)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await b(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await K(e.context.secret,`${u.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:u})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:u}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Ee}from"better-call";function yo(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>F(e?.length??10,M("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function Xe(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():yo(),n=await Fe({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function bo(e,t){let r=await tr(e.backupCodes,t);return r?r.includes(e.code):!1}async function tr(e,t){let r=Buffer.from(await Me({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Se.array(Se.string()).safeParse(o);return n.success?n.data:null}var rr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:c("/two-factor/verify-backup-code",{method:"POST",body:Se.object({code:Se.string(),disableSession:Se.boolean().optional()}),use:[ge]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!bo({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Ee("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await b(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:c("/two-factor/generate-backup-codes",{method:"POST",use:[y]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Ee("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await Xe(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:c("/view/backup-codes",{method:"GET",use:[y]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=tr(n.backupCodes,r.context.secret);if(!i)throw new Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as He}from"better-call";import{TOTPController as Ao}from"oslo/otp";import{z as or}from"zod";import{TimeSpan as ko}from"oslo";var nr=(e,t)=>{let r={...e,period:new ko(e?.period||3,"m")},o=new Ao({digits:6,period:r.period}),n=c("/two-factor/send-otp",{method:"POST",use:[ge]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new He("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"totp isn't enabled"});let u=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,u),a.json({status:!0})}),i=c("/two-factor/verify-otp",{method:"POST",body:or.object({code:or.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new He("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"totp isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as Ae}from"better-call";import{TimeSpan as Oo}from"oslo";import{TOTPController as ir,createTOTPKeyURI as Ro}from"oslo/otp";import{z as sr}from"zod";var ar=(e,t)=>{let r={...e,digits:6,period:new Oo(e?.period||30,"s")},o=c("/totp/generate",{method:"POST",use:[y]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new ir(r).generate(Buffer.from(d.secret))}}),n=c("/two-factor/get-totp-uri",{method:"GET",use:[y]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Ro(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=c("/two-factor/verify-totp",{method:"POST",body:sr.object({code:sr.string()}),use:[ge]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!d.enabled)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});let u=new ir(r),l=await Me({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await u.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function et(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as dr}from"better-call";var Iu=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t==="/two-factor/enable"||t==="/two-factor/send-otp"||t==="/two-factor/disable",signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var Du=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=ar({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=rr({...e?.backupCodeOptions},t.twoFactorTable),n=nr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:c("/two-factor/enable",{method:"POST",body:We.object({password:We.string().min(8)}),use:[y]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new dr("BAD_REQUEST",{message:"Invalid password"});let u=F(16,M("a-z","0-9","-")),l=await Fe({key:i.context.secret,data:u}),p=await Xe(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:c("/two-factor/disable",{method:"POST",body:We.object({password:We.string().min(8)}),use:[y]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new dr("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:C(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),u=await i.getSignedCookie(d.name,i.context.secret);if(u){let[m,f]=u.split("!"),h=await K(i.context.secret,`${s.user.id}!${f}`);if(m===h){let R=await K(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${R}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await K(i.context.secret,s.session.id),p=i.context.createAuthCookie(Ve,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.options),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as _o,generateRegistrationOptions as Co,verifyAuthenticationResponse as zo,verifyRegistrationResponse as Bo}from"@simplewebauthn/server";import{APIError as Z}from"better-call";import{z as re}from"zod";import{WebAuthnError as Uo,startAuthentication as To,startRegistration as Eo}from"@simplewebauthn/browser";import{createFetch as Ju}from"@better-fetch/fetch";import"nanostores";import{betterFetch as Mu}from"@better-fetch/fetch";import{atom as sl}from"nanostores";import"@better-fetch/fetch";import{atom as Io,onMount as vo}from"nanostores";var tt=(e,t,r,o)=>{let n=Io({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let u=n.get();n.set({isPending:u.data===null,data:u.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():vo(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as So}from"nanostores";var Po=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await To(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch(s){console.log(s)}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Eo(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof Uo?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),vl=()=>{let e=So();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Po(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:tt(e,"/passkey/list-user-passkeys",t,{method:"GET",credentials:"include"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var Dl=e=>{let t=process.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:c("/passkey/generate-register-options",{method:"GET",use:[y],metadata:{client:!1}},async s=>{let d=s.context.session,u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(F(32,M("a-z","0-9")))),p;p=await Co({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let k=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,k,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:k,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:c("/passkey/generate-authenticate-options",{method:"POST",body:re.object({email:re.string().optional()}).optional()},async s=>{let d=await H(s),u=[];d&&(u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await _o({rpID:o.rpID,userVerification:"preferred",...u.length?{allowCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},k=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,k,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:k,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:c("/passkey/verify-registration",{method:"POST",body:re.object({response:re.any(),name:re.string().optional()}),use:[y]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new Z("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:k,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new Z("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let f=await Bo({response:u,expectedChallenge:k,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:h,registrationInfo:R}=f;if(!h||!R)return s.json(null,{status:400});let{credentialID:I,credentialPublicKey:ee,counter:ne,credentialDeviceType:O,credentialBackedUp:N}=R,ie=Buffer.from(ee).toString("base64"),D=P(),Ce={name:s.body.name,userId:m.id,webauthnUserID:D,id:I,publicKey:ie,counter:ne,deviceType:O,transports:u.response.transports.join(","),backedUp:N,createdAt:new Date},gr=await s.context.adapter.create({model:"passkey",data:Ce});return s.json(gr,{status:200})}catch(f){throw console.log(f),new Z("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:c("/passkey/verify-authentication",{method:"POST",body:re.object({response:re.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new Z("BAD_REQUEST",{message:"origin missing"});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new Z("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new Z("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:k}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:u.id}]});if(!m)throw new Z("UNAUTHORIZED",{message:"Passkey not found"});try{let f=await zo({response:u,expectedChallenge:k,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:m.id,credentialPublicKey:new Uint8Array(Buffer.from(m.publicKey,"base64")),counter:m.counter,transports:m.transports?.split(",")}}),{verified:h}=f;if(!h)throw new Z("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:m.id}],update:{counter:f.authenticationInfo.newCounter}});let R=await s.context.internalAdapter.createSession(m.userId,s.request);if(!R)throw new Z("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await b(s,R.id),s.json({session:R},{status:200})}catch(f){throw s.context.logger.error(f),new Z("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:c("/passkey/list-user-passkeys",{method:"GET",use:[y]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:c("/passkey/delete-passkey",{method:"POST",body:re.object({id:re.string()}),use:[y]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as Y}from"zod";import{APIError as Ke}from"better-call";var cr=()=>({id:"username",endpoints:{signInUsername:c("/sign-in/username",{method:"POST",body:Y.object({username:Y.string(),password:Y.string(),dontRememberMe:Y.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:"user",where:[{field:"username",value:e.body.username}]});if(!t)throw await e.context.password.hash(e.body.password),e.context.logger.error("User not found",{username:cr}),new Ke("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:"account",where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.type.fieldName||"providerId",value:"credential"}]});if(!r)throw new Ke("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:cr}),new Ke("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Ke("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:c("/sign-up/username",{method:"POST",body:Y.object({username:Y.string().min(3).max(20),name:Y.string(),email:Y.string().email(),password:Y.string(),image:Y.string().optional()})},async e=>{let t=await Ie()({...e,_flag:"json"}),r=await e.context.internalAdapter.updateUserByEmail(t.user?.email,{username:e.body.username});return e.json({user:r,session:t.session})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as Lo}from"better-call";var Hl=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await Lo("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as ke}from"zod";import{APIError as xo}from"better-call";var ep=e=>({id:"magic-link",endpoints:{signInMagicLink:c("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:ke.object({email:ke.string().email(),callbackURL:ke.string().optional()}),use:[z]},async t=>{let{email:r}=t.body,o=F(32,M("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new xo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:c("/magic-link/verify",{method:"GET",query:ke.object({token:ke.string(),callbackURL:ke.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let u=await t.context.internalAdapter.createSession(d,t.headers);if(!u)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await b(t,u.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as _}from"zod";import{APIError as x}from"better-call";function rt(e){return F(e,M("0-9"))}var lp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",otp:{code:"code",phoneNumber:"phoneNumber",createdAt:"createdAt",expiresIn:e?.otp?.expiresIn||300}};return{id:"phone-number",endpoints:{signInPhoneNumber:c("/sign-in/phone-number",{method:"POST",body:_.object({phoneNumber:_.string(),password:_.string(),dontRememberMe:_.boolean().optional()})},async r=>{let o=await r.context.adapter.findOne({model:"user",where:[{field:t.phoneNumber,value:r.body.phoneNumber}]});if(!o)throw await r.context.password.hash(r.body.password),new x("UNAUTHORIZED",{message:"Invalid email or password"});let n=await r.context.adapter.findOne({model:r.context.tables.account.tableName,where:[{field:r.context.tables.account.fields.userId.fieldName||"userId",value:o.id},{field:r.context.tables.account.fields.providerId.fieldName||"providerId",value:"credential"}]});if(!n)throw new x("UNAUTHORIZED",{message:"Invalid email or password"});let i=n?.password;if(!i)throw r.context.logger.warn("Unexpectedly password is missing for the user",o),new x("UNAUTHORIZED",{message:"Unexpected error"});if(!await r.context.password.verify(i,r.body.password))throw r.context.logger.error("Invalid password"),new x("UNAUTHORIZED",{message:"Invalid email or password"});let s=await r.context.internalAdapter.createSession(o.id,r.request);return s?(await r.setSignedCookie(r.context.authCookies.sessionToken.name,s.id,r.context.secret,r.body.dontRememberMe?{...r.context.authCookies.sessionToken.options,maxAge:void 0}:r.context.authCookies.sessionToken.options),r.json({user:o,session:s})):r.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpPhoneNumber:c("/sign-up/phone-number",{method:"POST",body:_.object({phoneNumber:_.string().min(3).max(20),name:_.string(),email:_.string().email(),password:_.string(),image:_.string().optional()})},async r=>{if(e?.phoneNumberValidator&&!e.phoneNumberValidator(r.body.phoneNumber))throw new x("BAD_REQUEST",{message:"Invalid phone number"});if(await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{field:t.phoneNumber,value:r.body.phoneNumber}]}))throw new x("BAD_REQUEST",{message:"Phone number already exists"});try{let n=await Ie()({...r,options:{...r.context.options},_flag:"json"});if(e?.otp?.sendOTPonSignUp){if(!e.otp.sendOTP)throw A.warn("sendOTP not implemented"),new x("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let a=rt(e?.otp?.otpLength||6);await r.context.internalAdapter.createVerificationValue({value:a,identifier:r.body.phoneNumber,expiresAt:q(t.otp.expiresIn,"sec")}),await e.otp.sendOTP(r.body.phoneNumber,a)}let i=await r.context.internalAdapter.updateUserByEmail(n.user.email,{[t.phoneNumber]:r.body.phoneNumber});return r.json({user:i,session:n.session})}catch(n){throw n instanceof x?n:new x("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}}),sendVerificationCode:c("/phone-number/send-verification-code",{method:"POST",body:_.object({phoneNumber:_.string()})},async r=>{if(!e?.otp?.sendOTP)throw A.warn("sendOTP not implemented"),new x("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=rt(e?.otp?.otpLength||6);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:q(t.otp.expiresIn,"sec")}),await e.otp.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:c("/phone-number/verify",{method:"POST",body:_.object({phoneNumber:_.string(),code:_.string()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new x("BAD_REQUEST",{message:"OTP expired"})):new x("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new x("BAD_REQUEST",{message:"Invalid OTP"});await r.context.internalAdapter.deleteVerificationValue(o.id);let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(!n)throw new x("NOT_FOUND",{message:"User with phone number not found"});let i=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});if(e?.enableAutoSignIn&&!await H(r)){let s=await r.context.internalAdapter.createSession(n.id,r.request);if(!s)throw new x("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await b(r,s.id),r.json({user:i,session:s})}return r.json({user:i,session:null})}),updatePhoneNumber:c("/phone-number/update",{method:"POST",body:_.object({phoneNumber:_.string()}),use:[y]},async r=>{if(e?.otp?.sendOTPonUpdate){if(!e.otp.sendOTP)throw A.warn("sendOTP not implemented"),new x("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let n=rt(e?.otp?.otpLength||6);await r.context.adapter.create({model:r.context.tables.verification.tableName,data:{code:n,phoneNumber:r.body.phoneNumber,createdAt:q(t.otp.expiresIn,"sec")}}),await e.otp.sendOTP(r.body.phoneNumber,n)}let o=await r.context.internalAdapter.updateUser(r.context.session.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!1});return r.json({user:o})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0}}}}}};import{z as ot}from"zod";var yp=e=>({id:"anonymous",endpoints:{signInAnonymous:c("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=lt(t.context.baseURL)}=e||{},o=P(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await b(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:c("/user/link-anonymous",{method:"POST",body:ot.object({email:ot.string().email().optional(),password:ot.string().min(6)}),use:[y]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await b(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});import{z as g}from"zod";var X=C(async e=>{let t=await H(e);if(!t?.session)throw new de("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new de("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),Ip=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/user/list-sessions"},handler:C(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:c("/admin/set-role",{method:"POST",body:g.object({userId:g.string(),role:g.string()}),use:[X]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:c("/admin/create-user",{method:"POST",body:g.object({email:g.string(),password:g.string(),name:g.string(),role:g.string(),data:g.optional(g.record(g.any()))}),use:[X]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new de("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new de("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:c("/admin/list-users",{method:"GET",use:[X],query:g.object({limit:g.string().or(g.number()).optional(),offset:g.string().or(g.number()).optional(),sortBy:g.string().optional(),sortDirection:g.enum(["asc","desc"]).optional()})},async t=>{let r=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0);return t.json({users:r})}),listUserSessions:c("/admin/list-user-sessions",{method:"POST",use:[X],body:g.object({userId:g.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:c("/admin/unban-user",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:c("/admin/ban-user",{method:"POST",body:g.object({userId:g.string(),banReason:g.string().optional(),banExpiresIn:g.number().optional()}),use:[X]},async t=>{if(t.body.userId===t.context.session.user.id)throw new de("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:c("/admin/impersonate-user",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new de("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?q(e.impersonationSessionDuration,"sec"):q(60*60,"sec")});if(!o)throw new de("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await b(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:c("/admin/revoke-user-session",{method:"POST",body:g.object({sessionId:g.string()}),use:[X]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:c("/admin/revoke-user-sessions",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:c("/admin/remove-user",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1,references:{model:"user",field:"id"}}}}}});import{z as oe}from"zod";import{APIError as Pe}from"better-call";import{betterFetch as nt}from"@better-fetch/fetch";import{generateCodeVerifier as Do}from"oslo/oauth2";import{parseJWT as jo}from"oslo/jwt";async function No(e,t,r){if(t==="oidc"&&e.idToken){let n=jo(e.idToken);if(n?.payload)return n.payload}return r?(await nt(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var Mp=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:c("/sign-in/oauth2",{method:"POST",query:oe.object({currentURL:oe.string().optional()}).optional(),body:oe.object({providerId:oe.string(),callbackURL:oe.string().optional()}),use:[z]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:u,redirectURI:l,responseType:p,pkce:k,prompt:m,accessType:f}=o,h=i,R=a;if(n){let D=await nt(n,{onError(Ce){A.error(Ce.error,{discoveryUrl:n})}});D.data&&(h=D.data.authorization_endpoint,R=D.data.token_endpoint)}if(!h||!R)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let I=t.query?.currentURL?new URL(t.query?.currentURL):null,ee=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${I?.origin}${t.body.callbackURL||""}`,ne=await Le(ee||I?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,ne.hash,t.context.secret,O.state.options);let N=Do();await t.setSignedCookie(O.pkCodeVerifier.name,N,t.context.secret,O.pkCodeVerifier.options);let ie=await B({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:h,state:ne.raw,codeVerifier:N,scopes:u||[],disablePkce:!k,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ie.searchParams.set("response_type",p),m&&ie.searchParams.set("prompt",m),f&&ie.searchParams.set("access_type",f),{url:ie.toString(),state:ne,codeVerifier:N,redirect:!0}}),oAuth2Callback:c("/oauth2/callback/:providerId",{method:"GET",query:oe.object({code:oe.string().optional(),error:oe.string().optional(),state:oe.string()})},async t=>{if(t.query.error||!t.query.code){let N=he(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${N}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o=await t.getSignedCookie(t.context.authCookies.pkCodeVerifier.name,t.context.secret),n,i=he(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,u=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw A.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await ze(a,p))throw A.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,f=r.userInfoUrl;if(r.discoveryUrl){let O=await nt(r.discoveryUrl,{method:"GET"});O.data&&(m=O.data.token_endpoint,f=O.data.userinfo_endpoint)}try{if(!m)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await U({code:u,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:m})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let h=r.getUserInfo?await r.getUserInfo(n):await No(n,r.type||"oauth2",f),R=P(),I=h?xe.safeParse({...h,id:R}):null;if(!I?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let ee=await t.context.internalAdapter.findUserByEmail(I.data.email).catch(O=>{throw A.error(`Better auth was unable to query your database.
83
+ </html>`,mo=c("/error",{method:"GET",metadata:se},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(po(t),{headers:{"Content-Type":"text/html"}})});var fo=c("/ok",{method:"GET",metadata:se},async e=>e.json({ok:!0}));import{z as ye}from"zod";import{APIError as ue}from"better-call";var Ie=()=>c("/sign-up/email",{method:"POST",query:ye.object({currentURL:ye.string().optional()}).optional(),body:ye.record(ye.string(),ye.any()),use:[z]},async e=>{if(!e.context.options.emailAndPassword?.enabled)throw new ue("BAD_REQUEST",{message:"Email and password sign up is not enabled"});let t=e.body,{name:r,email:o,password:n,image:i,callbackURL:a,...s}=t;if(!ye.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let u=e.context.password.config.minPasswordLength;if(n.length<u)throw e.context.logger.error("Password is too short"),new ue("BAD_REQUEST",{message:"Password is too short"});let l=e.context.password.config.maxPasswordLength;if(n.length>l)throw e.context.logger.error("Password is too long"),new ue("BAD_REQUEST",{message:"Password is too long"});if((await e.context.internalAdapter.findUserByEmail(o))?.user)throw e.context.logger.info(`Sign-up attempt for existing email: ${o}`),new ue("UNPROCESSABLE_ENTITY",{message:"The email has already been taken"});let k=Ut(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...k,emailVerified:!1});if(!m)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:q(60*60*24*30,"sec")});let h=await e.context.internalAdapter.createSession(m.id,e.request);if(!h)throw new ue("BAD_REQUEST",{message:"Failed to create session"});if(await b(e,h.id),e.context.options.emailAndPassword.sendEmailVerificationOnSignUp){let R=await Ge(e.context.secret,m.email),I=`${e.context.baseURL}/verify-email?token=${R}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailAndPassword.sendVerificationEmail?.(I,m,R)}return e.json({user:m,session:h},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:h}})});var Ct=(e,t)=>{let r={};for(let[o,n]of Object.entries(e))r[o]=i=>n({...i,context:{...t,...i.context}}),r[o].path=n.path,r[o].method=n.method,r[o].options=n.options,r[o].headers=n.headers;return r};var jt={};wr(jt,{AccessControl:()=>ve,ParsingError:()=>le,Role:()=>be,adminAc:()=>Lt,createAccessControl:()=>zt,defaultAc:()=>qe,defaultRoles:()=>Ze,defaultStatements:()=>Bt,memberAc:()=>Dt,ownerAc:()=>xt,permissionFromString:()=>go});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},ve=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new be(t)}},be=class e{statements;constructor(t){this.statements=t}authorize(t,r){for(let[o,n]of Object.entries(t)){let i=this.statements[o];if(!i)return{success:!1,error:`You are not allowed to access resource: ${o}`};let a=r==="OR"?n.some(s=>i.includes(s)):n.every(s=>i.includes(s));return a?{success:a}:{success:!1,error:`unauthorized to access resource "${o}"`}}return{success:!1,error:"Not authorized"}}static fromString(t){let r=JSON.parse(t);if(typeof r!="object")throw new le("statements is not an object",".");for(let[o,n]of Object.entries(r)){if(typeof o!="string")throw new le("invalid resource identifier",o);if(!Array.isArray(n))throw new le("actions is not an array",o);for(let i=0;i<n.length;i++)if(typeof n[i]!="string")throw new le("action is not a string",`${o}[${i}]`)}return new e(r)}toString(){return JSON.stringify(this.statements)}};var zt=e=>new ve(e),Bt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},qe=zt(Bt),Lt=qe.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),xt=qe.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),Dt=qe.newRole({organization:[],member:[],invitation:[]}),Ze={admin:Lt,owner:xt,member:Dt};var go=e=>be.fromString(e??"");var E=(e,t)=>({findOrganizationBySlug:async r=>await e.findOne({model:"organization",where:[{field:"slug",value:r}]}),createOrganization:async r=>{let o=await e.create({model:"organization",data:{...r.organization,metadata:r.organization.metadata?JSON.stringify(r.organization.metadata):void 0}}),n=await e.create({model:"member",data:{id:P(),organizationId:o.id,userId:r.user.id,createdAt:new Date,email:r.user.email,role:t?.creatorRole||"owner"}});return{...o,metadata:o.metadata?JSON.parse(o.metadata):void 0,members:[{...n,user:{id:r.user.id,name:r.user.name,email:r.user.email,image:r.user.image}}]}},findMemberByEmail:async r=>{let o=await e.findOne({model:"member",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberByOrgId:async r=>{let o=await e.findOne({model:"member",where:[{field:"userId",value:r.userId},{field:"organizationId",value:r.organizationId}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},findMemberById:async r=>{let o=await e.findOne({model:"member",where:[{field:"id",value:r}]});if(!o)return null;let n=await e.findOne({model:"user",where:[{field:"id",value:o.userId}]});return n?{...o,user:{id:n.id,name:n.name,email:n.email,image:n.image}}:null},createMember:async r=>await e.create({model:"member",data:r}),updateMember:async(r,o)=>await e.update({model:"member",where:[{field:"id",value:r}],update:{role:o}}),deleteMember:async r=>await e.delete({model:"member",where:[{field:"id",value:r}]}),updateOrganization:async(r,o)=>await e.update({model:"organization",where:[{field:"id",value:r}],update:o}),deleteOrganization:async r=>(await e.delete({model:"member",where:[{field:"organizationId",value:r}]}),await e.delete({model:"invitation",where:[{field:"organizationId",value:r}]}),await e.delete({model:"organization",where:[{field:"id",value:r}]}),r),setActiveOrganization:async(r,o)=>await e.update({model:"session",where:[{field:"id",value:r}],update:{activeOrganizationId:o}}),findOrganizationById:async r=>await e.findOne({model:"organization",where:[{field:"id",value:r}]}),findFullOrganization:async(r,o)=>{let n=await e.findOne({model:"organization",where:[{field:"id",value:r}]});if(!n)return null;let i=await e.findMany({model:"invitation",where:[{field:"organizationId",value:r}]}),a=await e.findMany({model:"member",where:[{field:"organizationId",value:r}]}),s=await Promise.all(a.map(async u=>{let l=await e.findOne({model:"user",where:[{field:"id",value:u.userId}]});if(!l)throw new $("Unexpected error: User not found for member");return{...u,user:{id:l.id,name:l.name,email:l.email,image:l.image}}}));return{...n,invitations:i,members:s}},listOrganizations:async r=>{let n=(await e.findMany({model:"member",where:[{field:"userId",value:r}]}))?.map(a=>a.organizationId);if(!n)return[];let i=[];for(let a of n){let s=await e.findOne({model:"organization",where:[{field:"id",value:a}]});s&&i.push(s)}return i},createInvitation:async({invitation:r,user:o})=>{let i=q(t?.invitationExpiresIn||1728e5);return await e.create({model:"invitation",data:{id:P(),email:r.email,role:r.role,organizationId:r.organizationId,status:"pending",expiresAt:i,inviterId:o.id}})},findInvitationById:async r=>await e.findOne({model:"invitation",where:[{field:"id",value:r}]}),findPendingInvitation:async r=>(await e.findMany({model:"invitation",where:[{field:"email",value:r.email},{field:"organizationId",value:r.organizationId},{field:"status",value:"pending"}]})).filter(n=>new Date(n.expiresAt)>new Date),updateInvitation:async r=>await e.update({model:"invitation",where:[{field:"id",value:r.invitationId}],update:{status:r.status}})});import"better-call";import{APIError as Cd,createRouter as zd}from"better-call";import{APIError as Ye}from"better-call";import{z as Nt}from"zod";var ho=C({body:Nt.object({csrfToken:Nt.string().optional()}).optional()},async e=>{if(e.request?.method!=="POST"||e.context.options.advanced?.disableCSRFCheck)return;let t=new URL(e.request.url);if(e.context.trustedOrigins.includes(t.origin))return;let r=e.body?.csrfToken;if(!r)throw new Ye("UNAUTHORIZED",{message:"CSRF Token is required"});let o=await e.getSignedCookie(e.context.authCookies.csrfToken.name,e.context.secret),[n,i]=o?.split("!")||[null,null];if(!r||!o||!n||!i||n!==r)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await K(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new Ye("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as de}from"better-call";var L=C(async e=>({})),j=C({use:[y]},async e=>({session:e.context.session}));import{z as V}from"zod";import{z as v}from"zod";var $e=v.enum(["admin","member","owner"]),wo=v.enum(["pending","accepted","rejected","canceled"]).default("pending"),rc=v.object({id:v.string(),name:v.string(),slug:v.string(),logo:v.string().optional(),metadata:v.record(v.string()).or(v.string().transform(e=>JSON.parse(e))).optional(),createdAt:v.date()}),oc=v.object({id:v.string(),email:v.string(),organizationId:v.string(),userId:v.string(),role:$e,createdAt:v.date()}),nc=v.object({id:v.string(),organizationId:v.string(),email:v.string(),role:$e,status:wo,inviterId:v.string(),expiresAt:v.date()});import{APIError as T}from"better-call";var Ft=c("/organization/invite-member",{method:"POST",use:[L,j],body:V.object({email:V.string(),role:$e,organizationId:V.string().optional(),resend:V.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw A.warn("Invitation email is not enabled. Pass `sendInvitationEmail` to the plugin options to enable it."),new T("BAD_REQUEST",{message:"Invitation email is not enabled"});let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)throw new T("BAD_REQUEST",{message:"Organization not found"});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new T("BAD_REQUEST",{message:"Role not found!"});if(i.authorize({invitation:["create"]}).error)throw new T("FORBIDDEN",{message:"You are not allowed to invite members"});if(await o.findMemberByEmail({email:e.body.email,organizationId:r}))throw new T("BAD_REQUEST",{message:"User is already a member of this organization"});if((await o.findPendingInvitation({email:e.body.email,organizationId:r})).length&&!e.body.resend)throw new T("BAD_REQUEST",{message:"User is already invited to this organization"});let u=await o.createInvitation({invitation:{role:e.body.role,email:e.body.email,organizationId:r},user:t.user}),l=await o.findOrganizationById(r);if(!l)throw new T("BAD_REQUEST",{message:"Organization not found"});return await e.context.orgOptions.sendInvitationEmail?.({id:u.id,role:u.role,email:u.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(u)}),Mt=c("/organization/accept-invitation",{method:"POST",body:V.object({invitationId:V.string()}),use:[L,j]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"accepted"}),i=await r.createMember({id:P(),organizationId:o.organizationId,userId:t.user.id,email:o.email,role:o.role,createdAt:new Date});return await r.setActiveOrganization(t.session.id,o.organizationId),n?e.json({invitation:n,member:i}):e.json(null,{status:400,body:{message:"Invitation not found!"}})}),qt=c("/organization/reject-invitation",{method:"POST",body:V.object({invitationId:V.string()}),use:[L,j]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o||o.expiresAt<new Date||o.status!=="pending")throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.updateInvitation({invitationId:e.body.invitationId,status:"rejected"});return e.json({invitation:n,member:null})}),$t=c("/organization/cancel-invitation",{method:"POST",body:V.object({invitationId:V.string()}),use:[L,j]},async e=>{let t=e.context.session,r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.body.invitationId);if(!o)throw new T("BAD_REQUEST",{message:"Invitation not found!"});let n=await r.findMemberByOrgId({userId:t.user.id,organizationId:o.organizationId});if(!n)throw new T("BAD_REQUEST",{message:"Member not found!"});if(e.context.roles[n.role].authorize({invitation:["cancel"]}).error)throw new T("FORBIDDEN",{message:"You are not allowed to cancel this invitation"});let a=await r.updateInvitation({invitationId:e.body.invitationId,status:"canceled"});return e.json(a)}),Vt=c("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:V.object({id:V.string()})},async e=>{let t=await H(e);if(!t)throw new T("UNAUTHORIZED",{message:"Not authenticated"});let r=E(e.context.adapter,e.context.orgOptions),o=await r.findInvitationById(e.query.id);if(!o||o.status!=="pending"||o.expiresAt<new Date)throw new T("BAD_REQUEST",{message:"Invitation not found!"});if(o.email!==t.user.email)throw new T("FORBIDDEN",{message:"You are not the recipient of the invitation"});let n=await r.findOrganizationById(o.organizationId);if(!n)throw new T("BAD_REQUEST",{message:"Organization not found"});let i=await r.findMemberByOrgId({userId:o.inviterId,organizationId:o.organizationId});if(!i)throw new T("BAD_REQUEST",{message:"Inviter is no longer a member of the organization"});return e.json({...o,organizationName:n.name,organizationSlug:n.slug,inviterEmail:i.email})});import{z as pe}from"zod";import{APIError as Ue}from"better-call";var Qt=c("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[L,j]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Ue("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Ue("BAD_REQUEST",{message:"Role not found!"});let a=t.user.email===e.body.memberIdOrEmail||n.id===e.body.memberIdOrEmail;if(a&&n.role===(e.context.orgOptions?.creatorRole||"owner"))throw new Ue("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Ue("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let u=null;if(e.body.memberIdOrEmail.includes("@")?u=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):u=await o.findMemberById(e.body.memberIdOrEmail),u?.organizationId!==r)throw new Ue("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(u.id),t.user.id===u.userId&&t.session.activeOrganizationId===u.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:u})}),Ht=c("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[L,j]},async e=>{let t=e.context.session,r=e.body.organizationId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"No active organization found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"Member not found!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({member:["update"]}).error||e.body.role==="owner"&&n.role!=="owner")return e.json(null,{body:{message:"You are not allowed to update this member"},status:403});let s=await o.updateMember(e.body.memberId,e.body.role);return s?e.json(s):e.json(null,{status:400,body:{message:"Member not found!"}})});import{z as S}from"zod";import{APIError as me}from"better-call";var Wt=c("/organization/create",{method:"POST",body:S.object({name:S.string(),slug:S.string(),userId:S.string().optional(),logo:S.string().optional(),metadata:S.record(S.string()).optional()}),use:[L,j]},async e=>{let t=e.context.session.user;if(!t)return e.json(null,{status:401});let r=e.context.orgOptions;if(!(typeof r?.allowUserToCreateOrganization=="function"?await r.allowUserToCreateOrganization(t):r?.allowUserToCreateOrganization===void 0?!0:r.allowUserToCreateOrganization))throw new me("FORBIDDEN",{message:"You are not allowed to create an organization"});let n=E(e.context.adapter,r),i=await n.listOrganizations(t.id);if(typeof r.organizationLimit=="number"?i.length>=r.organizationLimit:typeof r.organizationLimit=="function"?await r.organizationLimit(t):!1)throw new me("FORBIDDEN",{message:"You have reached the organization limit"});if(await n.findOrganizationBySlug(e.body.slug))throw new me("BAD_REQUEST",{message:"Organization with this slug already exists"});let d=await n.createOrganization({organization:{id:P(),slug:e.body.slug,name:e.body.name,logo:e.body.logo,createdAt:new Date,metadata:e.body.metadata},user:t});return e.json(d)}),Kt=c("/organization/update",{method:"POST",body:S.object({data:S.object({name:S.string().optional(),slug:S.string().optional()}).partial(),orgId:S.string().optional()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)throw new me("UNAUTHORIZED",{message:"User not found"});let r=e.body.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["update"]}).error)return e.json(null,{body:{message:"You are not allowed to update this organization"},status:403});let s=await o.updateOrganization(r,e.body.data);return e.json(s)}),Jt=c("/organization/delete",{method:"POST",body:S.object({orgId:S.string()}),requireHeaders:!0,use:[L]},async e=>{let t=await e.context.getSession(e);if(!t)return e.json(null,{status:401});let r=e.body.orgId;if(!r)return e.json(null,{status:400,body:{message:"Organization id not found!"}});let o=E(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)return e.json(null,{status:400,body:{message:"User is not a member of this organization!"}});let i=e.context.roles[n.role];if(!i)return e.json(null,{status:400,body:{message:"Role not found!"}});if(i.authorize({organization:["delete"]}).error)throw new me("FORBIDDEN",{message:"You are not allowed to delete this organization"});return r===t.session.activeOrganizationId&&await o.setActiveOrganization(t.session.id,null),await o.deleteOrganization(r),e.json(r)}),Gt=c("/organization/get-full",{method:"GET",query:S.object({orgId:S.string().optional()}),requireHeaders:!0,use:[L,j]},async e=>{let t=e.context.session,r=e.query.orgId||t.session.activeOrganizationId;if(!r)return e.json(null,{status:400});let n=await E(e.context.adapter,e.context.orgOptions).findFullOrganization(r,e.context.db||void 0);if(!n)throw new me("BAD_REQUEST",{message:"Organization not found"});return e.json(n)}),Zt=c("/organization/activate",{method:"POST",body:S.object({orgId:S.string().nullable().optional()}),use:[j,L]},async e=>{let t=E(e.context.adapter,e.context.orgOptions),r=e.context.session,o=e.body.orgId;if(o===null)return r.session.activeOrganizationId&&await t.setActiveOrganization(r.session.id,null),e.json(null);if(!o){let a=r.session.activeOrganizationId;if(!a)return e.json(null);o=a}if(!await t.findMemberByOrgId({userId:r.user.id,organizationId:o}))throw await t.setActiveOrganization(r.session.id,null),new me("FORBIDDEN",{message:"You are not a member of this organization"});await t.setActiveOrganization(r.session.id,o);let i=await t.findFullOrganization(o,e.context.db||void 0);return e.json(i)}),Yt=c("/organization/list",{method:"GET",use:[L,j]},async e=>{let r=await E(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var Fc=e=>{let t={createOrganization:Wt,updateOrganization:Kt,deleteOrganization:Jt,setActiveOrganization:Zt,getFullOrganization:Gt,listOrganization:Yt,createInvitation:Ft,cancelInvitation:$t,acceptInvitation:Mt,getInvitation:Vt,rejectInvitation:qt,removeMember:Qt,updateMemberRole:Ht},r={...Ze,...e?.roles};return{id:"organization",endpoints:{...Ct(t,{orgOptions:e||{},roles:r,getSession:async n=>await H(n)}),hasPermission:c("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[j]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new Xt("BAD_REQUEST",{message:"No active organization"});let a=await E(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new Xt("UNAUTHORIZED",{message:"You are not a member of this organization"});let d=r[a.role].authorize(n.body.permission);return d.error?n.json({error:d.error,success:!1},{status:403}):n.json({error:null,success:!0})})},schema:{session:{fields:{activeOrganizationId:{type:"string",required:!1}}},organization:{fields:{name:{type:"string",required:!0},slug:{type:"string",unique:!0},logo:{type:"string",required:!1},createdAt:{type:"date",required:!0},metadata:{type:"string",required:!1}}},member:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},userId:{type:"string",required:!0},email:{type:"string",required:!0},role:{type:"string",required:!0,defaultValue:"member"},createdAt:{type:"date",required:!0}}},invitation:{fields:{organizationId:{type:"string",required:!0,references:{model:"organization",field:"id"}},email:{type:"string",required:!0},role:{type:"string",required:!1},status:{type:"string",required:!0,defaultValue:"pending"},expiresAt:{type:"date",required:!0},inviterId:{type:"string",references:{model:"user",field:"id"},required:!0}}}},$Infer:{Organization:{},Invitation:{},Member:{},ActiveOrganization:{}}}};import{z as We}from"zod";import{z as Se}from"zod";import{APIError as fe}from"better-call";var Ve="two-factor";var Qe="trust-device";import{z as er}from"zod";var ge=C({body:er.object({trustDevice:er.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(Ve),r=await e.getSignedCookie(t.name,e.context.secret);if(!r)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let[o,n]=r.split("!");if(!o||!n)throw new fe("UNAUTHORIZED",{message:"invalid two factor cookie"});let i=await e.context.adapter.findMany({model:"session",where:[{field:"userId",value:o}]});if(!i.length)throw new fe("UNAUTHORIZED",{message:"invalid session"});let a=i.filter(s=>s.expiresAt>new Date);if(!a)throw new fe("UNAUTHORIZED",{message:"invalid session"});for(let s of a){let d=await K(e.context.secret,s.id),u=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!u)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await b(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await K(e.context.secret,`${u.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:u})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:u}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Ee}from"better-call";function yo(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>F(e?.length??10,M("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function Xe(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():yo(),n=await Fe({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function bo(e,t){let r=await tr(e.backupCodes,t);return r?r.includes(e.code):!1}async function tr(e,t){let r=Buffer.from(await Me({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Se.array(Se.string()).safeParse(o);return n.success?n.data:null}var rr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:c("/two-factor/verify-backup-code",{method:"POST",body:Se.object({code:Se.string(),disableSession:Se.boolean().optional()}),use:[ge]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!bo({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Ee("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await b(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:c("/two-factor/generate-backup-codes",{method:"POST",use:[y]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Ee("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await Xe(r.context.secret,e);return await r.context.adapter.update({model:t,update:{backupCodes:n.encryptedBackupCodes},where:[{field:"userId",value:r.context.session.user.id}]}),r.json({status:!0,backupCodes:n.backupCodes})}),viewBackupCodes:c("/view/backup-codes",{method:"GET",use:[y]},async r=>{let o=r.context.session.user,n=await r.context.adapter.findOne({model:t,where:[{field:"userId",value:o.id}]});if(!n)throw new Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=tr(n.backupCodes,r.context.secret);if(!i)throw new Ee("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as He}from"better-call";import{TOTPController as Ao}from"oslo/otp";import{z as or}from"zod";import{TimeSpan as ko}from"oslo";var nr=(e,t)=>{let r={...e,period:new ko(e?.period||3,"m")},o=new Ao({digits:6,period:r.period}),n=c("/two-factor/send-otp",{method:"POST",use:[ge]},async a=>{if(!e||!e.sendOTP)throw a.context.logger.error("send otp isn't configured. Please configure the send otp function on otp options."),new He("BAD_REQUEST",{message:"otp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"totp isn't enabled"});let u=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,u),a.json({status:!0})}),i=c("/two-factor/verify-otp",{method:"POST",body:or.object({code:or.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new He("BAD_REQUEST",{message:"two factor isn't enabled"});let d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new He("BAD_REQUEST",{message:"totp isn't enabled"});return await o.generate(Buffer.from(d.secret))===a.body.code?a.context.valid():a.context.invalid()});return{id:"otp",endpoints:{send2FaOTP:n,verifyOTP:i}}};import{APIError as Ae}from"better-call";import{TimeSpan as Oo}from"oslo";import{TOTPController as ir,createTOTPKeyURI as Ro}from"oslo/otp";import{z as sr}from"zod";var ar=(e,t)=>{let r={...e,digits:6,period:new Oo(e?.period||30,"s")},o=c("/totp/generate",{method:"POST",use:[y]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new ir(r).generate(Buffer.from(d.secret))}}),n=c("/two-factor/get-totp-uri",{method:"GET",use:[y]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!s.twoFactorEnabled)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Ro(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=c("/two-factor/verify-totp",{method:"POST",body:sr.object({code:sr.string()}),use:[ge]},async a=>{if(!e)throw a.context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp"),new Ae("BAD_REQUEST",{message:"totp isn't configured"});let s=a.context.session.user,d=await a.context.adapter.findOne({model:t,where:[{field:"userId",value:s.id}]});if(!d||!d.enabled)throw new Ae("BAD_REQUEST",{message:"totp isn't enabled"});let u=new ir(r),l=await Me({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await u.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function et(e,t){let o=(await e.context.internalAdapter.findAccounts(t.userId))?.find(a=>a.providerId==="credential"),n=o?.password;return!o||!n?!1:await e.context.password.verify(n,t.password)}import{APIError as dr}from"better-call";var Iu=(e={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:t=>t==="/two-factor/enable"||t==="/two-factor/send-otp"||t==="/two-factor/disable",signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(t){t.data?.twoFactorRedirect&&(e.redirect||e.twoFactorPage)&&typeof window<"u"&&(window.location.href=e.twoFactorPage)}}}]});var Du=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=ar({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=rr({...e?.backupCodeOptions},t.twoFactorTable),n=nr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:c("/two-factor/enable",{method:"POST",body:We.object({password:We.string().min(8)}),use:[y]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new dr("BAD_REQUEST",{message:"Invalid password"});let u=F(16,M("a-z","0-9","-")),l=await Fe({key:i.context.secret,data:u}),p=await Xe(i.context.secret,e?.backupCodeOptions);return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!0}),await i.context.adapter.create({model:t.twoFactorTable,data:{id:i.context.uuid(),secret:l,backupCodes:p.encryptedBackupCodes,userId:a.id}}),i.json({status:!0})}),disableTwoFactor:c("/two-factor/disable",{method:"POST",body:We.object({password:We.string().min(8)}),use:[y]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new dr("BAD_REQUEST",{message:"Invalid password"});return await i.context.internalAdapter.updateUser(a.id,{twoFactorEnabled:!1}),await i.context.adapter.delete({model:t.twoFactorTable,where:[{field:"userId",value:a.id}]}),i.json({status:!0})})},options:e,hooks:{after:[{matcher(i){return i.path==="/sign-in/email"||i.path==="/sign-in/username"},handler:C(async i=>{let a=i.context.returned;if(a?.status!==200)return;let s=await a.clone().json();if(!s.user.twoFactorEnabled)return;let d=i.context.createAuthCookie(Qe,{maxAge:30*24*60*60}),u=await i.getSignedCookie(d.name,i.context.secret);if(u){let[m,f]=u.split("!"),h=await K(i.context.secret,`${s.user.id}!${f}`);if(m===h){let R=await K(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${R}!${s.session.id}`,i.context.secret,d.options);return}}i.setCookie(i.context.authCookies.sessionToken.name,"",{path:"/",sameSite:"lax",httpOnly:!0,secure:!1,maxAge:0});let l=await K(i.context.secret,s.session.id),p=i.context.createAuthCookie(Ve,{maxAge:60*60*24});return await i.setSignedCookie(p.name,`${s.session.userId}!${l}`,i.context.secret,p.options),{response:new Response(JSON.stringify({twoFactorRedirect:!0}),{headers:i.responseHeader})}})}]},schema:{user:{fields:{twoFactorEnabled:{type:"boolean",required:!1,defaultValue:!1}}},twoFactor:{tableName:t.twoFactorTable,fields:{secret:{type:"string",required:!0,returned:!1},backupCodes:{type:"string",required:!0,returned:!1},userId:{type:"string",required:!0,returned:!1,references:{model:"user",field:"id"}}}}},rateLimit:[{pathMatcher(i){return i.startsWith("/two-factor/")},window:10,max:3}]}};import{generateAuthenticationOptions as _o,generateRegistrationOptions as Co,verifyAuthenticationResponse as zo,verifyRegistrationResponse as Bo}from"@simplewebauthn/server";import{APIError as Z}from"better-call";import{z as re}from"zod";import{WebAuthnError as Uo,startAuthentication as To,startRegistration as Eo}from"@simplewebauthn/browser";import{createFetch as Ju}from"@better-fetch/fetch";import"nanostores";import{betterFetch as Mu}from"@better-fetch/fetch";import{atom as sl}from"nanostores";import"@better-fetch/fetch";import{atom as Io,onMount as vo}from"nanostores";var tt=(e,t,r,o)=>{let n=Io({data:null,error:null,isPending:!1,isRefetching:!1}),i=()=>{let s=typeof o=="function"?o({data:n.get().data,error:n.get().error,isPending:n.get().isPending}):o;return r(t,{...s,onSuccess:async d=>{n.set({data:d.data,error:null,isPending:!1,isRefetching:!1}),await s?.onSuccess?.(d)},async onError(d){n.set({error:d.error,data:null,isPending:!1,isRefetching:!1}),await s?.onError?.(d)},async onRequest(d){let u=n.get();n.set({isPending:u.data===null,data:u.data,error:null,isRefetching:!0}),await s?.onRequest?.(d)}})};e=Array.isArray(e)?e:[e];let a=!1;for(let s of e)s.subscribe(()=>{a?i():vo(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as So}from"nanostores";var Po=(e,{_listPasskeys:t})=>({signIn:{passkey:async(n,i)=>{let a=await e("/passkey/generate-authenticate-options",{method:"POST",body:{email:n?.email}});if(!a.data)return a;try{let s=await To(a.data,n?.autoFill||!1),d=await e("/passkey/verify-authentication",{body:{response:s},...n?.fetchOptions,...i,method:"POST"});if(!d.data)return d}catch(s){console.log(s)}}},passkey:{addPasskey:async(n,i)=>{let a=await e("/passkey/generate-register-options",{method:"GET"});if(!a.data)return a;try{let s=await Eo(a.data),d=await e("/passkey/verify-registration",{...n?.fetchOptions,...i,body:{response:s,name:n?.name},method:"POST"});if(!d.data)return d;t.set(Math.random())}catch(s){return s instanceof Uo?s.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:s.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:s instanceof Error?s.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),vl=()=>{let e=So();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Po(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:tt(e,"/passkey/list-user-passkeys",t,{method:"GET",credentials:"include"}),_listPasskeys:e}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(t){return t==="/passkey/verify-registration"||t==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var Dl=e=>{let t=process.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new $("passkey rpID not found. Please provide a rpID in the options or set the BETTER_AUTH_URL environment variable.");let o={origin:null,...e,rpID:r,advanced:{webAuthnChallengeCookie:"better-auth-passkey",...e?.advanced}},n=new Date(Date.now()+1e3*60*5),i=new Date,a=Math.floor((n.getTime()-i.getTime())/1e3);return{id:"passkey",endpoints:{generatePasskeyRegistrationOptions:c("/passkey/generate-register-options",{method:"GET",use:[y],metadata:{client:!1}},async s=>{let d=s.context.session,u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(F(32,M("a-z","0-9")))),p;p=await Co({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let k=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,k,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:k,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:c("/passkey/generate-authenticate-options",{method:"POST",body:re.object({email:re.string().optional()}).optional()},async s=>{let d=await H(s),u=[];d&&(u=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await _o({rpID:o.rpID,userVerification:"preferred",...u.length?{allowCredentials:u.map(m=>({id:m.id,transports:m.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},k=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,k,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:k,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:c("/passkey/verify-registration",{method:"POST",body:re.object({response:re.any(),name:re.string().optional()}),use:[y]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new Z("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:k,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new Z("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let f=await Bo({response:u,expectedChallenge:k,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:h,registrationInfo:R}=f;if(!h||!R)return s.json(null,{status:400});let{credentialID:I,credentialPublicKey:ee,counter:ne,credentialDeviceType:O,credentialBackedUp:N}=R,ie=Buffer.from(ee).toString("base64"),D=P(),Ce={name:s.body.name,userId:m.id,webauthnUserID:D,id:I,publicKey:ie,counter:ne,deviceType:O,transports:u.response.transports.join(","),backedUp:N,createdAt:new Date},gr=await s.context.adapter.create({model:"passkey",data:Ce});return s.json(gr,{status:200})}catch(f){throw console.log(f),new Z("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:c("/passkey/verify-authentication",{method:"POST",body:re.object({response:re.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new Z("BAD_REQUEST",{message:"origin missing"});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new Z("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new Z("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:k}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:u.id}]});if(!m)throw new Z("UNAUTHORIZED",{message:"Passkey not found"});try{let f=await zo({response:u,expectedChallenge:k,expectedOrigin:d,expectedRPID:o.rpID,authenticator:{credentialID:m.id,credentialPublicKey:new Uint8Array(Buffer.from(m.publicKey,"base64")),counter:m.counter,transports:m.transports?.split(",")}}),{verified:h}=f;if(!h)throw new Z("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:m.id}],update:{counter:f.authenticationInfo.newCounter}});let R=await s.context.internalAdapter.createSession(m.userId,s.request);if(!R)throw new Z("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await b(s,R.id),s.json({session:R},{status:200})}catch(f){throw s.context.logger.error(f),new Z("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:c("/passkey/list-user-passkeys",{method:"GET",use:[y]},async s=>{let d=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:s.context.session.user.id}]});return s.json(d,{status:200})}),deletePasskey:c("/passkey/delete-passkey",{method:"POST",body:re.object({id:re.string()}),use:[y]},async s=>(await s.context.adapter.delete({model:"passkey",where:[{field:"id",value:s.body.id}]}),s.json(null,{status:200})))},schema:{passkey:{fields:{name:{type:"string",required:!1},publicKey:{type:"string",required:!0},userId:{type:"string",references:{model:"user",field:"id"},required:!0},webauthnUserID:{type:"string",required:!0},counter:{type:"number",required:!0},deviceType:{type:"string",required:!0},backedUp:{type:"boolean",required:!0},transports:{type:"string",required:!1},createdAt:{type:"date",defaultValue:new Date,required:!1}}}}}};import{z as Y}from"zod";import{APIError as Ke}from"better-call";var cr=()=>({id:"username",endpoints:{signInUsername:c("/sign-in/username",{method:"POST",body:Y.object({username:Y.string(),password:Y.string(),dontRememberMe:Y.boolean().optional()})},async e=>{let t=await e.context.adapter.findOne({model:"user",where:[{field:"username",value:e.body.username}]});if(!t)throw await e.context.password.hash(e.body.password),e.context.logger.error("User not found",{username:cr}),new Ke("UNAUTHORIZED",{message:"Invalid username or password"});let r=await e.context.adapter.findOne({model:"account",where:[{field:e.context.tables.account.fields.userId.fieldName||"userId",value:t.id},{field:e.context.tables.account.fields.type.fieldName||"providerId",value:"credential"}]});if(!r)throw new Ke("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:cr}),new Ke("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Ke("UNAUTHORIZED",{message:"Invalid username or password"});let i=await e.context.internalAdapter.createSession(t.id,e.request);return i?(await e.setSignedCookie(e.context.authCookies.sessionToken.name,i.id,e.context.secret,e.body.dontRememberMe?{...e.context.authCookies.sessionToken.options,maxAge:void 0}:e.context.authCookies.sessionToken.options),e.json({user:t,session:i})):e.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpUsername:c("/sign-up/username",{method:"POST",body:Y.object({username:Y.string().min(3).max(20),name:Y.string(),email:Y.string().email(),password:Y.string(),image:Y.string().optional()})},async e=>{let t=await Ie()({...e,_flag:"json"}),r=await e.context.internalAdapter.updateUserByEmail(t.user?.email,{username:e.body.username});return e.json({user:r,session:t.session})})},schema:{user:{fields:{username:{type:"string",required:!1,unique:!0,returned:!0}}}}});import{serializeSigned as Lo}from"better-call";var Hl=()=>({id:"bearer",hooks:{before:[{matcher(e){return!!(e.request?.headers.get("authorization")||e.headers?.get("authorization"))},handler:async e=>{let t=e.request?.headers.get("authorization")?.replace("Bearer ","")||e.headers?.get("authorization")?.replace("Bearer ","");if(!t)return;let r="";return t.includes(".")?r=t:r=await Lo("",t,e.context.secret),e.request&&e.request.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),e.headers&&e.headers.set("cookie",`${e.context.authCookies.sessionToken.name}=${r.replace("=","")}`),{context:e}}}]}});import{z as ke}from"zod";import{APIError as xo}from"better-call";var ep=e=>({id:"magic-link",endpoints:{signInMagicLink:c("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:ke.object({email:ke.string().email(),callbackURL:ke.string().optional()}),use:[z]},async t=>{let{email:r}=t.body,o=F(32,M("a-z","A-Z"));await t.context.internalAdapter.createVerificationValue({identifier:o,value:r,expiresAt:new Date(Date.now()+(e.expiresIn||60*5)*1e3)});let n=`${t.context.baseURL}/magic-link/verify?token=${o}&callbackURL=${t.body.callbackURL||"/"}`;try{await e.sendMagicLink({email:r,url:n,token:o})}catch(i){throw t.context.logger.error("Failed to send magic link",i),new xo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:c("/magic-link/verify",{method:"GET",query:ke.object({token:ke.string(),callbackURL:ke.string().optional()}),requireHeaders:!0},async t=>{let{token:r,callbackURL:o}=t.query,n=o?.startsWith("http")?o:o?`${t.context.options.baseURL}${o}`:t.context.options.baseURL,i=await t.context.internalAdapter.findVerificationValue(r);if(!i)throw t.redirect(`${n}?error=INVALID_TOKEN`);if(i.expiresAt<new Date)throw await t.context.internalAdapter.deleteVerificationValue(i.id),t.redirect(`${n}?error=EXPIRED_TOKEN`);await t.context.internalAdapter.deleteVerificationValue(i.id);let a=i.value,s=await t.context.internalAdapter.findUserByEmail(a),d=s?.user.id||"";if(!s){if(e.disableSignUp)throw t.redirect(`${n}?error=USER_NOT_FOUND`);if(d=(await t.context.internalAdapter.createUser({email:a,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let u=await t.context.internalAdapter.createSession(d,t.headers);if(!u)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await b(t,u.id),!o)return t.json({status:!0});throw t.redirect(o)})},rateLimit:[{pathMatcher(t){return t.startsWith("/sign-in/magic-link")||t.startsWith("/magic-link/verify")},window:e.rateLimit?.window||60,max:e.rateLimit?.max||5}]});import{z as _}from"zod";import{APIError as x}from"better-call";function rt(e){return F(e,M("0-9"))}var lp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",otp:{code:"code",phoneNumber:"phoneNumber",createdAt:"createdAt",expiresIn:e?.otp?.expiresIn||300}};return{id:"phone-number",endpoints:{signInPhoneNumber:c("/sign-in/phone-number",{method:"POST",body:_.object({phoneNumber:_.string(),password:_.string(),dontRememberMe:_.boolean().optional()})},async r=>{let o=await r.context.adapter.findOne({model:"user",where:[{field:t.phoneNumber,value:r.body.phoneNumber}]});if(!o)throw await r.context.password.hash(r.body.password),new x("UNAUTHORIZED",{message:"Invalid email or password"});let n=await r.context.adapter.findOne({model:r.context.tables.account.tableName,where:[{field:r.context.tables.account.fields.userId.fieldName||"userId",value:o.id},{field:r.context.tables.account.fields.providerId.fieldName||"providerId",value:"credential"}]});if(!n)throw new x("UNAUTHORIZED",{message:"Invalid email or password"});let i=n?.password;if(!i)throw r.context.logger.warn("Unexpectedly password is missing for the user",o),new x("UNAUTHORIZED",{message:"Unexpected error"});if(!await r.context.password.verify(i,r.body.password))throw r.context.logger.error("Invalid password"),new x("UNAUTHORIZED",{message:"Invalid email or password"});let s=await r.context.internalAdapter.createSession(o.id,r.request);return s?(await r.setSignedCookie(r.context.authCookies.sessionToken.name,s.id,r.context.secret,r.body.dontRememberMe?{...r.context.authCookies.sessionToken.options,maxAge:void 0}:r.context.authCookies.sessionToken.options),r.json({user:o,session:s})):r.json(null,{status:500,body:{message:"Failed to create session",status:500}})}),signUpPhoneNumber:c("/sign-up/phone-number",{method:"POST",body:_.object({phoneNumber:_.string().min(3).max(20),name:_.string(),email:_.string().email(),password:_.string(),image:_.string().optional()})},async r=>{if(e?.phoneNumberValidator&&!e.phoneNumberValidator(r.body.phoneNumber))throw new x("BAD_REQUEST",{message:"Invalid phone number"});if(await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{field:t.phoneNumber,value:r.body.phoneNumber}]}))throw new x("BAD_REQUEST",{message:"Phone number already exists"});try{let n=await Ie()({...r,options:{...r.context.options},_flag:"json"});if(e?.otp?.sendOTPonSignUp){if(!e.otp.sendOTP)throw A.warn("sendOTP not implemented"),new x("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let a=rt(e?.otp?.otpLength||6);await r.context.internalAdapter.createVerificationValue({value:a,identifier:r.body.phoneNumber,expiresAt:q(t.otp.expiresIn,"sec")}),await e.otp.sendOTP(r.body.phoneNumber,a)}let i=await r.context.internalAdapter.updateUserByEmail(n.user.email,{[t.phoneNumber]:r.body.phoneNumber});return r.json({user:i,session:n.session})}catch(n){throw n instanceof x?n:new x("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}}),sendVerificationCode:c("/phone-number/send-verification-code",{method:"POST",body:_.object({phoneNumber:_.string()})},async r=>{if(!e?.otp?.sendOTP)throw A.warn("sendOTP not implemented"),new x("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=rt(e?.otp?.otpLength||6);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:q(t.otp.expiresIn,"sec")}),await e.otp.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:c("/phone-number/verify",{method:"POST",body:_.object({phoneNumber:_.string(),code:_.string()})},async r=>{let o=await r.context.internalAdapter.findVerificationValue(r.body.phoneNumber);if(!o||o.expiresAt<new Date)throw o&&o.expiresAt<new Date?(await r.context.internalAdapter.deleteVerificationValue(o.id),new x("BAD_REQUEST",{message:"OTP expired"})):new x("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new x("BAD_REQUEST",{message:"Invalid OTP"});await r.context.internalAdapter.deleteVerificationValue(o.id);let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(!n)throw new x("NOT_FOUND",{message:"User with phone number not found"});let i=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});if(e?.enableAutoSignIn&&!await H(r)){let s=await r.context.internalAdapter.createSession(n.id,r.request);if(!s)throw new x("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await b(r,s.id),r.json({user:i,session:s})}return r.json({user:i,session:null})}),updatePhoneNumber:c("/phone-number/update",{method:"POST",body:_.object({phoneNumber:_.string()}),use:[y]},async r=>{if(e?.otp?.sendOTPonUpdate){if(!e.otp.sendOTP)throw A.warn("sendOTP not implemented"),new x("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let n=rt(e?.otp?.otpLength||6);await r.context.adapter.create({model:r.context.tables.verification.tableName,data:{code:n,phoneNumber:r.body.phoneNumber,createdAt:q(t.otp.expiresIn,"sec")}}),await e.otp.sendOTP(r.body.phoneNumber,n)}let o=await r.context.internalAdapter.updateUser(r.context.session.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!1});return r.json({user:o})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0}}}}}};import{z as ot}from"zod";var yp=e=>({id:"anonymous",endpoints:{signInAnonymous:c("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=lt(t.context.baseURL)}=e||{},o=P(),n=`temp-${o}@${r}`,i=await t.context.internalAdapter.createUser({id:o,email:n,emailVerified:!1,isAnonymous:!0,name:"Anonymous",createdAt:new Date,updatedAt:new Date});if(!i)return t.json(null,{status:500,body:{message:"Failed to create user",status:500}});let a=await t.context.internalAdapter.createSession(i.id,t.request);return a?(await b(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:c("/user/link-anonymous",{method:"POST",body:ot.object({email:ot.string().email().optional(),password:ot.string().min(6)}),use:[y]},async t=>{let r=t.context.session.user.id,{email:o,password:n}=t.body,i=null;if(o&&n&&(i=await t.context.internalAdapter.updateUser(r,{email:o})),!i)return t.json(null,{status:500,body:{message:"Failed to update user",status:500}});let a=await t.context.password.hash(n);if(!await t.context.internalAdapter.linkAccount({userId:i.id,providerId:"credential",password:a,accountId:i.id}))return t.json(null,{status:500,body:{message:"Failed to update account",status:500}});let d=await t.context.internalAdapter.createSession(i.id,t.request);return d?(await b(t,d.id),t.json({session:d,user:i})):t.json(null,{status:400,body:{message:"Could not create session"}})})},schema:{user:{fields:{isAnonymous:{type:"boolean",defaultValue:!0,required:!1}}}}});import{z as g}from"zod";var X=C(async e=>{let t=await H(e);if(!t?.session)throw new de("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new de("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),Ip=e=>({id:"admin",init(t){return{options:{databaseHooks:{user:{create:{async before(r){if(e?.defaultRole!==!1)return{data:{role:e?.defaultRole??"user",...r}}}}},session:{create:{async before(r){let o=await t.internalAdapter.findUserById(r.userId);if(o.banned){if(o.banExpires&&o.banExpires<Date.now()){await t.internalAdapter.updateUser(r.userId,{banned:!1,banReason:null,banExpires:null});return}return!1}}}}}}}},hooks:{after:[{matcher(t){return t.path==="/user/list-sessions"},handler:C(async t=>{let r=t.context.returned;if(r){let n=(await r.json()).filter(a=>!a.impersonatedBy),i=new Response(JSON.stringify(n),{status:200,statusText:"OK",headers:r.headers});return t.json({response:i})}})}]},endpoints:{setRole:c("/admin/set-role",{method:"POST",body:g.object({userId:g.string(),role:g.string()}),use:[X]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:c("/admin/create-user",{method:"POST",body:g.object({email:g.string(),password:g.string(),name:g.string(),role:g.string(),data:g.optional(g.record(g.any()))}),use:[X]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new de("BAD_REQUEST",{message:"User already exists"});let o=await t.context.internalAdapter.createUser({email:t.body.email,name:t.body.name,role:t.body.role,...t.body.data});if(!o)throw new de("INTERNAL_SERVER_ERROR",{message:"Failed to create user"});let n=await t.context.password.hash(t.body.password);return await t.context.internalAdapter.linkAccount({accountId:o.id,providerId:"credential",password:n,userId:o.id}),t.json({user:o})}),listUsers:c("/admin/list-users",{method:"GET",use:[X],query:g.object({limit:g.string().or(g.number()).optional(),offset:g.string().or(g.number()).optional(),sortBy:g.string().optional(),sortDirection:g.enum(["asc","desc"]).optional()})},async t=>{let r=await t.context.internalAdapter.listUsers(Number(t.query?.limit)||void 0,Number(t.query?.offset)||void 0,t.query?.sortBy?{field:t.query.sortBy,direction:t.query.sortDirection||"asc"}:void 0);return t.json({users:r})}),listUserSessions:c("/admin/list-user-sessions",{method:"POST",use:[X],body:g.object({userId:g.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:c("/admin/unban-user",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:c("/admin/ban-user",{method:"POST",body:g.object({userId:g.string(),banReason:g.string().optional(),banExpiresIn:g.number().optional()}),use:[X]},async t=>{if(t.body.userId===t.context.session.user.id)throw new de("BAD_REQUEST",{message:"You cannot ban yourself"});let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!0,banReason:t.body.banReason||e?.defaultBanReason||"No reason",banExpires:t.body.banExpiresIn?Date.now()+t.body.banExpiresIn*1e3:e?.defaultBanExpiresIn?Date.now()+e.defaultBanExpiresIn*1e3:void 0});return await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({user:r})}),impersonateUser:c("/admin/impersonate-user",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new de("NOT_FOUND",{message:"User not found"});let o=await t.context.internalAdapter.createSession(r.id,void 0,!0,{impersonatedBy:t.context.session.user.id,expiresAt:e?.impersonationSessionDuration?q(e.impersonationSessionDuration,"sec"):q(60*60,"sec")});if(!o)throw new de("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await b(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:c("/admin/revoke-user-session",{method:"POST",body:g.object({sessionId:g.string()}),use:[X]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:c("/admin/revoke-user-sessions",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:c("/admin/remove-user",{method:"POST",body:g.object({userId:g.string()}),use:[X]},async t=>(await t.context.internalAdapter.deleteUser(t.body.userId),t.json({success:!0})))},schema:{user:{fields:{role:{type:"string",required:!1},banned:{type:"boolean",defaultValue:!1,required:!1},banReason:{type:"string",required:!1},banExpires:{type:"number",required:!1}}},session:{fields:{impersonatedBy:{type:"string",required:!1,references:{model:"user",field:"id"}}}}}});import{z as oe}from"zod";import{APIError as Pe}from"better-call";import{betterFetch as nt}from"@better-fetch/fetch";import{generateCodeVerifier as Do}from"oslo/oauth2";import{parseJWT as jo}from"oslo/jwt";async function No(e,t,r){if(t==="oidc"&&e.idToken){let n=jo(e.idToken);if(n?.payload)return n.payload}return r?(await nt(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var Mp=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:c("/sign-in/oauth2",{method:"POST",query:oe.object({currentURL:oe.string().optional()}).optional(),body:oe.object({providerId:oe.string(),callbackURL:oe.string().optional()}),use:[z]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:u,redirectURI:l,responseType:p,pkce:k,prompt:m,accessType:f}=o,h=i,R=a;if(n){let D=await nt(n,{onError(Ce){A.error(Ce.error,{discoveryUrl:n})}});D.data&&(h=D.data.authorization_endpoint,R=D.data.token_endpoint)}if(!h||!R)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let I=t.query?.currentURL?new URL(t.query?.currentURL):null,ee=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${I?.origin}${t.body.callbackURL||""}`,ne=await Le(ee||I?.origin||t.context.options.baseURL),O=t.context.authCookies;await t.setSignedCookie(O.state.name,ne.hash,t.context.secret,O.state.options);let N=Do();await t.setSignedCookie(O.pkCodeVerifier.name,N,t.context.secret,O.pkCodeVerifier.options);let ie=await B({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:h,state:ne.raw,codeVerifier:N,scopes:u||[],disablePkce:!k,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&ie.searchParams.set("response_type",p),m&&ie.searchParams.set("prompt",m),f&&ie.searchParams.set("access_type",f),{url:ie.toString(),state:ne,codeVerifier:N,redirect:!0}}),oAuth2Callback:c("/oauth2/callback/:providerId",{method:"GET",query:oe.object({code:oe.string().optional(),error:oe.string().optional(),state:oe.string()})},async t=>{if(t.query.error||!t.query.code){let N=he(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${N}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(O=>O.providerId===t.params.providerId);if(!r)throw new Pe("BAD_REQUEST",{message:`No config found for provider ${t.params.providerId}`});let o=await t.getSignedCookie(t.context.authCookies.pkCodeVerifier.name,t.context.secret),n,i=he(t.query.state);if(!i.success)throw t.redirect(`${t.context.baseURL}/error?error=invalid_state`);let a=t.query.state,{data:{callbackURL:s,currentURL:d}}=i,u=t.query.code,l=i.data?.currentURL||`${t.context.baseURL}/error`,p=await t.getSignedCookie(t.context.authCookies.state.name,t.context.secret);if(!p)throw A.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await ze(a,p))throw A.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,f=r.userInfoUrl;if(r.discoveryUrl){let O=await nt(r.discoveryUrl,{method:"GET"});O.data&&(m=O.data.token_endpoint,f=O.data.userinfo_endpoint)}try{if(!m)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await U({code:u,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:m})}catch(O){throw t.context.logger.error(O),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let h=r.getUserInfo?await r.getUserInfo(n):await No(n,r.type||"oauth2",f),R=P(),I=h?xe.safeParse({...h,id:R}):null;if(!I?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let ee=await t.context.internalAdapter.findUserByEmail(I.data.email).catch(O=>{throw A.error(`Better auth was unable to query your database.
84
84
  Error: `,O),t.redirect(`${l}?error=internal_server_error`)}),ne=ee?.user.id||R;if(ee){let O=ee.accounts.find(D=>D.providerId===r.providerId),N=t.context.options.account?.accountLinking?.trustedProviders,ie=N?N.includes(r.providerId):!0;if(!O&&(!I?.data.emailVerified||!ie)){let D;try{D=new URL(l),D.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(D.toString())}if(!O)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:I.data.id,id:`${r.providerId}:${I.data.id}`,userId:ee.user.id,...we(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(I.data,{...we(n),id:`${r.providerId}:${I.data.id}`,providerId:r.providerId,accountId:I.data.id,userId:ne})}catch{let N=new URL(l);throw N.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",N.toString()),t.redirect(N.toString())}try{let O=await t.context.internalAdapter.createSession(ne||R,t.request);if(!O)throw t.redirect(`${l}?error=unable_to_create_session`);await b(t,O.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var ur={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},Vp=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var it=e=>({getAllKeys:async()=>await e.findMany({model:"jwks"}),getLatestKey:async()=>(await e.findMany({model:"jwks",sortBy:{field:"createdAt",direction:"desc"},limit:1}))[0],createJwk:async t=>await e.create({model:"jwks",data:{...t,createdAt:new Date}})});import{exportJWK as fr,generateKeyPair as Vo,importJWK as Qo,SignJWT as Ho}from"jose";import{createCipheriv as Fo,createDecipheriv as Mo,createHash as qo,randomBytes as $o}from"crypto";function lr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=qo("sha256").update(e).digest(),t}function pr(e,t){let r=lr(t),o=$o(12),n=Fo("aes-256-gcm",r,o),i=n.update(e,"utf8","base64");i+=n.final("base64");let a=n.getAuthTag();return{encryptedPrivateKey:i,iv:o.toString("base64"),authTag:a.toString("base64")}}function mr(e,t){let r=lr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=Mo("aes-256-gcm",r,a);d.setAuthTag(s);let u=d.update(o,"base64","utf8");return u+=d.final("utf8"),u}var em=e=>({id:"jwt",endpoints:{getJwks:c("/jwks",{method:"GET"},async t=>{let o=await it(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:c("/token",{method:"GET",requireHeaders:!0,use:[y]},async t=>{let r=it(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:u,privateKey:l}=await Vo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await fr(u),k=await fr(l),m=JSON.stringify(k),f={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(pr(m,t.context.options.secret)):m,createdAt:new Date};o=await r.createJwk(f)}let i=n?mr(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await Qo(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new Ho({...s,...t.context.session.session.impersonatedBy?{impersonatedBy:t.context.session.session.impersonatedBy}:{}}).setProtectedHeader({alg:e?.jwks?.keyPairConfig?.alg??"EdDSA"}).setIssuedAt().setIssuer(e?.jwt?.issuer??t.context.options.baseURL).setAudience(e?.jwt?.audience??t.context.options.baseURL).setExpirationTime(e?.jwt?.expirationTime??"15m").setSubject(t.context.session.user.id).sign(a);return t.json({token:d})})},schema:ur});export{se as HIDE_METADATA,jt as ac,Ip as admin,X as adminMiddleware,yp as anonymous,Hl as bearer,c as createAuthEndpoint,C as createAuthMiddleware,Mp as genericOAuth,Po as getPasskeyActions,em as jwt,ep as magicLink,at as optionsMiddleware,Fc as organization,Dl as passkey,vl as passkeyClient,lp as phoneNumber,Du as twoFactor,Iu as twoFactorClient,cr as username};
package/dist/social.js CHANGED
@@ -1,2 +1,2 @@
1
1
  import{parseJWT as L}from"oslo/jwt";import{sha256 as z}from"oslo/crypto";var m=class extends Error{constructor(r,e){super(r),this.name="BetterAuthError",this.message=r,this.cause=e,this.stack=""}};import{base64url as I}from"oslo/encoding";async function b(t){let r=await z(new TextEncoder().encode(t));return I.encode(new Uint8Array(r),{includePadding:!1})}function y(t){return{tokenType:t.token_type,accessToken:t.access_token,refreshToken:t.refresh_token,accessTokenExpiresAt:t.expires_at?new Date((Date.now()+t.expires_in)*1e3):void 0,scopes:t?.scope?typeof t.scope=="string"?t.scope.split(" "):t.scope:[],idToken:t.id_token}}async function c({id:t,options:r,authorizationEndpoint:e,state:i,codeVerifier:o,scopes:n,claims:s,disablePkce:l,redirectURI:d}){let p=new URL(e);if(p.searchParams.set("response_type","code"),p.searchParams.set("client_id",r.clientId),p.searchParams.set("state",i),p.searchParams.set("scope",n.join(" ")),p.searchParams.set("redirect_uri",r.redirectURI||d),!l&&o){let g=await b(o);p.searchParams.set("code_challenge_method","S256"),p.searchParams.set("code_challenge",g)}if(s){let g=s.reduce((h,O)=>(h[O]=null,h),{});p.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...g}}))}return p}import{betterFetch as E}from"@better-fetch/fetch";async function a({code:t,codeVerifier:r,redirectURI:e,options:i,tokenEndpoint:o}){let n=new URLSearchParams;n.set("grant_type","authorization_code"),n.set("code",t),r&&n.set("code_verifier",r),n.set("redirect_uri",e),n.set("client_id",i.clientId),n.set("client_secret",i.clientSecret);let{data:s,error:l}=await E(o,{method:"POST",body:n,headers:{"content-type":"application/x-www-form-urlencoded",accept:"application/json","user-agent":"better-auth"}});if(l)throw l;return y(s)}import{generateState as ue}from"oslo/oauth2";import{z as fe}from"zod";import{sha256 as se}from"oslo/crypto";var _=t=>{let r="https://appleid.apple.com/auth/token";return{id:"apple",name:"Apple",createAuthorizationURL({state:e,scopes:i,redirectURI:o}){let n=t.scope||i||["email","name","openid"];return new URL(`https://appleid.apple.com/auth/authorize?client_id=${t.clientId}&response_type=code&redirect_uri=${o||t.redirectURI}&scope=${n.join(" ")}&state=${e}`)},validateAuthorizationCode:async({code:e,codeVerifier:i,redirectURI:o})=>a({code:e,codeVerifier:i,redirectURI:t.redirectURI||o,options:t,tokenEndpoint:r}),async getUserInfo(e){if(!e.idToken)return null;let i=L(e.idToken)?.payload;return i?{user:{id:i.sub,name:i.name,email:i.email,emailVerified:i.email_verified==="true"},data:i}:null}}};import{betterFetch as B}from"@better-fetch/fetch";var v=t=>({id:"discord",name:"Discord",createAuthorizationURL({state:r,scopes:e,redirectURI:i}){let o=t.scope||e||["identify","email"];return new URL(`https://discord.com/api/oauth2/authorize?scope=${o.join("+")}&response_type=code&client_id=${t.clientId}&redirect_uri=${encodeURIComponent(t.redirectURI||i)}&state=${r}`)},validateAuthorizationCode:async({code:r,redirectURI:e})=>a({code:r,redirectURI:t.redirectURI||e,options:t,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(r){let{data:e,error:i}=await B("https://discord.com/api/users/@me",{headers:{authorization:`Bearer ${r.accessToken}`}});if(i)return null;if(e.avatar===null){let o=e.discriminator==="0"?Number(BigInt(e.id)>>BigInt(22))%6:parseInt(e.discriminator)%5;e.image_url=`https://cdn.discordapp.com/embed/avatars/${o}.png`}else{let o=e.avatar.startsWith("a_")?"gif":"png";e.image_url=`https://cdn.discordapp.com/avatars/${e.id}/${e.avatar}.${o}`}return{user:{id:e.id,name:e.display_name||e.username||"",email:e.email,emailVerified:e.verified,image:e.image_url},data:e}}});import{betterFetch as S}from"@better-fetch/fetch";var A=t=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:r,scopes:e,redirectURI:i}){let o=t.scope||e||["email","public_profile"];return await c({id:"facebook",options:t,authorizationEndpoint:"https://www.facebook.com/v21.0/dialog/oauth",scopes:o,state:r,redirectURI:i})},validateAuthorizationCode:async({code:r,redirectURI:e})=>a({code:r,redirectURI:t.redirectURI||e,options:t,tokenEndpoint:"https://graph.facebook.com/oauth/access_token"}),async getUserInfo(r){let{data:e,error:i}=await S("https://graph.facebook.com/me?fields=id,name,email,picture",{auth:{type:"Bearer",token:r.accessToken}});return i?null:{user:{id:e.id,name:e.name,email:e.email,emailVerified:e.email_verified},data:e}}});import{betterFetch as P}from"@better-fetch/fetch";var x=t=>{let r="https://github.com/login/oauth/access_token";return{id:"github",name:"Github",createAuthorizationURL({state:e,scopes:i,codeVerifier:o,redirectURI:n}){let s=t.scope||i||["user:email"];return c({id:"github",options:t,authorizationEndpoint:"https://github.com/login/oauth/authorize",scopes:s,state:e,redirectURI:n,codeVerifier:o})},validateAuthorizationCode:async({code:e,redirectURI:i})=>a({code:e,redirectURI:t.redirectURI||i,options:t,tokenEndpoint:r}),async getUserInfo(e){let{data:i,error:o}=await P("https://api.github.com/user",{auth:{type:"Bearer",token:e.accessToken}});if(o)return null;let n=!1;if(!i.email){let{data:s,error:l}=await P("https://api.github.com/user/emails",{auth:{type:"Bearer",token:e.accessToken}});l||(i.email=(s.find(d=>d.primary)??s[0])?.email,n=s.find(d=>d.email===i.email)?.verified??!1)}return{user:{id:i.id.toString(),name:i.name||i.login,email:i.email,image:i.avatar_url,emailVerified:n},data:i}}}};import{parseJWT as V}from"oslo/jwt";import{createConsola as C}from"consola";var u=C({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),$=t=>({log:(...r)=>{!t?.disabled&&u.log("",...r)},error:(...r)=>{!t?.disabled&&u.error("",...r)},warn:(...r)=>{!t?.disabled&&u.warn("",...r)},info:(...r)=>{!t?.disabled&&u.info("",...r)},debug:(...r)=>{!t?.disabled&&u.debug("",...r)},box:(...r)=>{!t?.disabled&&u.box("",...r)},success:(...r)=>{!t?.disabled&&u.success("",...r)},break:(...r)=>{!t?.disabled&&console.log(`
2
- `)}}),f=$();var U=t=>({id:"google",name:"Google",createAuthorizationURL({state:r,scopes:e,codeVerifier:i,redirectURI:o}){if(!t.clientId||!t.clientSecret)throw f.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new m("CLIENT_ID_AND_SECRET_REQUIRED");if(!i)throw new m("codeVerifier is required for Google");let n=t.scope||e||["email","profile"];return c({id:"google",options:t,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:n,state:r,codeVerifier:i,redirectURI:o})},validateAuthorizationCode:async({code:r,codeVerifier:e,redirectURI:i})=>a({code:r,codeVerifier:e,redirectURI:t.redirectURI||i,options:t,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(r){if(!r.idToken)return null;let e=V(r.idToken)?.payload;return{user:{id:e.sub,name:e.name,email:e.email,image:e.picture,emailVerified:e.email_verified},data:e}}});import{betterFetch as D}from"@better-fetch/fetch";import{parseJWT as F}from"oslo/jwt";var w=t=>{let r=t.tenantId||"common",e=`https://login.microsoftonline.com/${r}/oauth2/v2.0/authorize`,i=`https://login.microsoftonline.com/${r}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(o){let n=t.scope||o.scopes||["openid","profile","email","User.Read"];return c({id:"microsoft",options:t,authorizationEndpoint:e,state:o.state,codeVerifier:o.codeVerifier,scopes:n,redirectURI:o.redirectURI})},validateAuthorizationCode({code:o,codeVerifier:n,redirectURI:s}){return a({code:o,codeVerifier:n,redirectURI:t.redirectURI||s,options:t,tokenEndpoint:i})},async getUserInfo(o){if(!o.idToken)return null;let n=F(o.idToken)?.payload,s=t.profilePhotoSize||48;return await D(`https://graph.microsoft.com/v1.0/me/photos/${s}x${s}/$value`,{headers:{Authorization:`Bearer ${o.accessToken}`},async onResponse(l){if(!(t.disableProfilePhoto||!l.response.ok))try{let p=await l.response.clone().arrayBuffer(),g=Buffer.from(p).toString("base64");n.picture=`data:image/jpeg;base64, ${g}`}catch(d){f.error(d)}}}),{user:{id:n.sub,name:n.name,email:n.email,image:n.picture,emailVerified:!0},data:n}}}};import{betterFetch as G}from"@better-fetch/fetch";var R=t=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:r,scopes:e,codeVerifier:i,redirectURI:o}){let n=t.scope||e||["user-read-email"];return c({id:"spotify",options:t,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:n,state:r,codeVerifier:i,redirectURI:o})},validateAuthorizationCode:async({code:r,codeVerifier:e,redirectURI:i})=>a({code:r,codeVerifier:e,redirectURI:t.redirectURI||i,options:t,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(r){let{data:e,error:i}=await G("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${r.accessToken}`}});return i?null:{user:{id:e.id,name:e.display_name,email:e.email,image:e.images[0]?.url,emailVerified:!1},data:e}}});import"@better-fetch/fetch";import{parseJWT as j}from"oslo/jwt";var T=t=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:r,scopes:e,redirectURI:i}){let o=t.scope||e||["user:read:email","openid"];return c({id:"twitch",redirectURI:i,options:t,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:o,state:r,claims:t.claims||["email","email_verified","preferred_username"]})},validateAuthorizationCode:async({code:r,redirectURI:e})=>a({code:r,redirectURI:t.redirectURI||e,options:t,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(r){let e=r.idToken;if(!e)return f.error("No idToken found in token"),null;let i=j(e)?.payload;return{user:{id:i.sub,name:i.preferred_username,email:i.email,image:i.picture,emailVerified:!1},data:i}}});import{betterFetch as N}from"@better-fetch/fetch";var k=t=>({id:"twitter",name:"Twitter",createAuthorizationURL(r){let e=t.scope||r.scopes||["account_info.read"];return c({id:"twitter",options:t,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:e,state:r.state,codeVerifier:r.codeVerifier,redirectURI:r.redirectURI})},validateAuthorizationCode:async({code:r,codeVerifier:e,redirectURI:i})=>a({code:r,codeVerifier:e,redirectURI:t.redirectURI||i,options:t,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(r){let{data:e,error:i}=await N("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${r.accessToken}`}});return i||!e.data.email?null:{user:{id:e.data.id,name:e.data.name,email:e.data.email,image:e.data.profile_image_url,emailVerified:e.data.verified||!1},data:e}}});var H={apple:_,discord:v,facebook:A,github:x,microsoft:w,google:U,spotify:R,twitch:T,twitter:k},zt=Object.keys(H);export{_ as apple,v as discord,A as facebook,x as github,U as google,w as microsoft,zt as socialProviderList,H as socialProviders,R as spotify,T as twitch,k as twitter};
2
+ `)}}),f=$();var U=t=>({id:"google",name:"Google",createAuthorizationURL({state:r,scopes:e,codeVerifier:i,redirectURI:o}){if(!t.clientId||!t.clientSecret)throw f.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new m("CLIENT_ID_AND_SECRET_REQUIRED");if(!i)throw new m("codeVerifier is required for Google");let n=t.scope||e||["email","profile"];return c({id:"google",options:t,authorizationEndpoint:"https://accounts.google.com/o/oauth2/auth",scopes:n,state:r,codeVerifier:i,redirectURI:o})},validateAuthorizationCode:async({code:r,codeVerifier:e,redirectURI:i})=>a({code:r,codeVerifier:e,redirectURI:t.redirectURI||i,options:t,tokenEndpoint:"https://oauth2.googleapis.com/token"}),async getUserInfo(r){if(!r.idToken)return null;let e=V(r.idToken)?.payload;return{user:{id:e.sub,name:e.name,email:e.email,image:e.picture,emailVerified:e.email_verified},data:e}}});import{betterFetch as D}from"@better-fetch/fetch";import{parseJWT as F}from"oslo/jwt";var w=t=>{let r=t.tenantId||"common",e=`https://login.microsoftonline.com/${r}/oauth2/v2.0/authorize`,i=`https://login.microsoftonline.com/${r}/oauth2/v2.0/token`;return{id:"microsoft",name:"Microsoft EntraID",createAuthorizationURL(o){let n=t.scope||o.scopes||["openid","profile","email","User.Read"];return c({id:"microsoft",options:t,authorizationEndpoint:e,state:o.state,codeVerifier:o.codeVerifier,scopes:n,redirectURI:o.redirectURI})},validateAuthorizationCode({code:o,codeVerifier:n,redirectURI:s}){return a({code:o,codeVerifier:n,redirectURI:t.redirectURI||s,options:t,tokenEndpoint:i})},async getUserInfo(o){if(!o.idToken)return null;let n=F(o.idToken)?.payload,s=t.profilePhotoSize||48;return await D(`https://graph.microsoft.com/v1.0/me/photos/${s}x${s}/$value`,{headers:{Authorization:`Bearer ${o.accessToken}`},async onResponse(l){if(!(t.disableProfilePhoto||!l.response.ok))try{let p=await l.response.clone().arrayBuffer(),g=Buffer.from(p).toString("base64");n.picture=`data:image/jpeg;base64, ${g}`}catch(d){f.error(d)}}}),{user:{id:n.sub,name:n.name,email:n.email,image:n.picture,emailVerified:!0},data:n}}}};import{betterFetch as G}from"@better-fetch/fetch";var R=t=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:r,scopes:e,codeVerifier:i,redirectURI:o}){let n=t.scope||e||["user-read-email"];return c({id:"spotify",options:t,authorizationEndpoint:"https://accounts.spotify.com/authorize",scopes:n,state:r,codeVerifier:i,redirectURI:o})},validateAuthorizationCode:async({code:r,codeVerifier:e,redirectURI:i})=>a({code:r,codeVerifier:e,redirectURI:t.redirectURI||i,options:t,tokenEndpoint:"https://accounts.spotify.com/api/token"}),async getUserInfo(r){let{data:e,error:i}=await G("https://api.spotify.com/v1/me",{method:"GET",headers:{Authorization:`Bearer ${r.accessToken}`}});return i?null:{user:{id:e.id,name:e.display_name,email:e.email,image:e.images[0]?.url,emailVerified:!1},data:e}}});import"@better-fetch/fetch";import{parseJWT as j}from"oslo/jwt";var T=t=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:r,scopes:e,redirectURI:i}){let o=t.scope||e||["user:read:email","openid"];return c({id:"twitch",redirectURI:i,options:t,authorizationEndpoint:"https://id.twitch.tv/oauth2/authorize",scopes:o,state:r,claims:t.claims||["email","email_verified","preferred_username","picture"]})},validateAuthorizationCode:async({code:r,redirectURI:e})=>a({code:r,redirectURI:t.redirectURI||e,options:t,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(r){let e=r.idToken;if(!e)return f.error("No idToken found in token"),null;let i=j(e)?.payload;return{user:{id:i.sub,name:i.preferred_username,email:i.email,image:i.picture,emailVerified:!1},data:i}}});import{betterFetch as N}from"@better-fetch/fetch";var k=t=>({id:"twitter",name:"Twitter",createAuthorizationURL(r){let e=t.scope||r.scopes||["account_info.read"];return c({id:"twitter",options:t,authorizationEndpoint:"https://twitter.com/i/oauth2/authorize",scopes:e,state:r.state,codeVerifier:r.codeVerifier,redirectURI:r.redirectURI})},validateAuthorizationCode:async({code:r,codeVerifier:e,redirectURI:i})=>a({code:r,codeVerifier:e,redirectURI:t.redirectURI||i,options:t,tokenEndpoint:"https://id.twitch.tv/oauth2/token"}),async getUserInfo(r){let{data:e,error:i}=await N("https://api.x.com/2/users/me?user.fields=profile_image_url",{method:"GET",headers:{Authorization:`Bearer ${r.accessToken}`}});return i||!e.data.email?null:{user:{id:e.data.id,name:e.data.name,email:e.data.email,image:e.data.profile_image_url,emailVerified:e.data.verified||!1},data:e}}});var H={apple:_,discord:v,facebook:A,github:x,microsoft:w,google:U,spotify:R,twitch:T,twitter:k},zt=Object.keys(H);export{_ as apple,v as discord,A as facebook,x as github,U as google,w as microsoft,zt as socialProviderList,H as socialProviders,R as spotify,T as twitch,k as twitter};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-auth",
3
- "version": "0.4.12-beta.2",
3
+ "version": "0.4.12-beta.4",
4
4
  "description": "The most comprehensive authentication library for TypeScript.",
5
5
  "type": "module",
6
6
  "repository": {