better-auth 0.4.13 → 0.4.14-beta.2

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/plugins.js CHANGED
@@ -1,6 +1,6 @@
1
- var gr=Object.defineProperty;var hr=(e,t)=>{for(var r in t)gr(e,r,{get:t[r],enumerable:!0})};import{APIError as Yt}from"better-call";import{z as Te}from"zod";import{createEndpointCreator as wr,createMiddleware as it,createMiddlewareCreator as yr}from"better-call";var st=it(async()=>({})),_=yr({use:[st,it(async()=>({}))]}),c=wr({use:[st]});import{APIError as K}from"better-call";import{generateCodeVerifier as Vr}from"oslo/oauth2";import{z as q}from"zod";import{generateState as br}from"oslo/oauth2";import{z as Be}from"zod";import{sha256 as at}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 dt(e){let t=await at(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function ze(e,t){let r=await at(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Je(r,o)}import"better-call";async function Le(e){let t=br(),r=JSON.stringify({code:t,callbackURL:e}),o=await dt(r);return{raw:r,hash:o}}function we(e){return Be.object({code:Be.string(),callbackURL:Be.string().optional(),currentURL:Be.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as ln}from"oslo";var j=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};async function y(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 ct}from"better-call";import{createConsola as Ar}from"consola";var de=Ar({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),kr=e=>({log:(...t)=>{!e?.disabled&&de.log("",...t)},error:(...t)=>{!e?.disabled&&de.error("",...t)},warn:(...t)=>{!e?.disabled&&de.warn("",...t)},info:(...t)=>{!e?.disabled&&de.info("",...t)},debug:(...t)=>{!e?.disabled&&de.debug("",...t)},box:(...t)=>{!e?.disabled&&de.box("",...t)},success:(...t)=>{!e?.disabled&&de.success("",...t)},break:(...t)=>{!e?.disabled&&console.log(`
2
- `)}}),b=kr();var 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 b.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new ct("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw b.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new ct("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as Ir}from"oslo/jwt";import{sha256 as Rr}from"oslo/crypto";function ut(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as Or}from"oslo/encoding";async function lt(e){let t=await Rr(new TextEncoder().encode(e));return Or.encode(new Uint8Array(t),{includePadding:!1})}function pt(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 z({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 lt(n);u.searchParams.set("code_challenge_method","S256"),u.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,R)=>(p[R]=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 pt(a)}function ye(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var mt=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=Ir(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 Ur}from"@better-fetch/fetch";var ft=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 Ur("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 Tr}from"@better-fetch/fetch";var gt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await z({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 Tr("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 ht}from"@better-fetch/fetch";var wt=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 z({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 ht("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 ht("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 Er}from"oslo/jwt";var yt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw b.error("Client Id and Client Secret is required for Google. Make sure to provide them in the options."),new j("CLIENT_ID_AND_SECRET_REQUIRED");if(!o)throw new j("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return z({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=Er(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 Sr}from"@better-fetch/fetch";import{parseJWT as Pr}from"oslo/jwt";var bt=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 z({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=Pr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await Sr(`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){b.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as _r}from"@better-fetch/fetch";var At=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return z({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 _r("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 ne={isAction:!1};function Cr(e){return e.toString(2).padStart(8,"0")}function zr(e){return[...e].map(t=>Cr(t)).join("")}function kt(e){return parseInt(zr(e),2)}function Br(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=kt(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=kt(o);return n}function N(e,t){let r="";for(let o=0;o<e;o++)r+=t[Br(t.length)];return r}function F(...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}import{nanoid as Lr}from"nanoid";var P=e=>Lr(e);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 z({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 b.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 Ot=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return z({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:mt,discord:ft,facebook:gt,github:wt,microsoft:bt,google:yt,spotify:At,twitch:Rt,twitter:Ot},vt=Object.keys(jr);import{TimeSpan as Nr}from"oslo";import{createJWT as Fr,validateJWT as Mr}from"oslo/jwt";import{z as H}from"zod";import{APIError as xe}from"better-call";async function ce(e,t){return await Fr("HS256",Buffer.from(e),{email:t.toLowerCase()},{expiresIn:new Nr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var qr=c("/send-verification-email",{method:"POST",query:H.object({currentURL:H.string().optional()}).optional(),body:H.object({email:H.string().email(),callbackURL:H.string().optional()}),use:[C]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled. Pass `sendVerificationEmail` in `emailAndPassword` options to enable it."),new xe("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new xe("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.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),$r=c("/verify-email",{method:"GET",query:H.object({token:H.string(),callbackURL:H.string().optional()})},async e=>{let{token:t}=e.query,r;try{r=await Mr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new xe("BAD_REQUEST",{message:"Invalid token"})}let n=H.object({email:H.string().email()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new xe("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})});var Qr=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:[C]},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 K("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=Vr();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})}),Wr=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:[C]},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 K("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 K("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 K("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!n.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw b.error("Email verification is required but no email verification handler is provided"),new K("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let u=await ce(e.context.secret,n.user.email),l=`${e.context.options.baseURL}/verify-email?token=${u}`;throw await e.context.options.emailVerification.sendVerificationEmail(n.user,l,u),e.context.logger.error("Email not verified",{email:t}),new K("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let i=n.accounts.find(u=>u.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new K("UNAUTHORIZED",{message:"Invalid email or password"});let a=i?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new K("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new K("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 K("UNAUTHORIZED",{message:"Failed to create session"});return await y(e,d.id,e.body.dontRememberMe),e.json({user:n.user,session:d,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as Kr}from"better-call";import{z as je}from"zod";import{z as w}from"zod";var bs=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()}),De=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)}),As=w.object({id:w.string(),userId:w.string(),expiresAt:w.date(),ipAddress:w.string().optional(),userAgent:w.string().optional()}),ks=w.object({id:w.string(),value:w.string(),expiresAt:w.date(),identifier:w.string()});function Hr(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 It(e,t){let r={...e.user?.additionalFields};return Hr(t||{},{fields:r})}var Jr=c("/callback/:id",{method:"GET",query:je.object({state:je.string(),code:je.string().optional(),error:je.string().optional()}),metadata:ne},async e=>{if(e.query.error||!e.query.code){let h=we(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=we(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 b.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await ze(e.query.state,i))throw b.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=De.safeParse({...u,id:l});if(!u||p.success===!1)throw b.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 R=await e.context.internalAdapter.findUserByEmail(u.email,{includeAccounts:!0}).catch(f=>{throw b.error(`Better auth was unable to query your database.
3
- Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=R?.user.id;if(R){let f=R.accounts.find(O=>O.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,k=h?h.includes(t.id):!0;if(!f&&(!u.emailVerified||!k)){let O;try{O=new URL(n||o),O.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(O.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:u.id.toString(),id:`${t.id}:${u.id}`,userId:R.user.id,...ye(d)})}catch(O){throw console.log(O),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{let f=u.emailVerified,h=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:f},{...ye(d),id:`${t.id}:${u.id}`,providerId:t.id,accountId:u.id.toString()});if(!f&&h&&e.context.options.emailVerification?.sendOnSignUp){let k=await ce(e.context.secret,u.email),O=`${e.context.baseURL}/verify-email?token=${k}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(h.user,O,k)}}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.redirect(h.toString())}if(!m&&!l)throw new Kr("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 y(e,f.id)}catch(h){e.context.logger.error("Unable to set session cookie",h);let k=new URL(n||o);throw k.searchParams.set("error","unable_to_create_session"),e.redirect(k.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 ve}from"better-call";var $=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Ut}from"zod";var Tt=()=>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:$(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 y(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})}}),V=async e=>await Tt()({...e,_flag:"json",headers:e.headers}),A=_(async e=>{let t=await V(e);if(!t?.session)throw new ve("UNAUTHORIZED");return{session:t}});var Gr=c("/user/revoke-session",{method:"POST",body:Ut.object({id:Ut.string()}),use:[A],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new ve("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new ve("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),Zr=c("/user/revoke-sessions",{method:"POST",use:[A],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new ve("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import"zod";import{APIError as Yr}from"better-call";var Xr=c("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new Yr("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),Oe(e),e.json({success:!0})});import{z as ee}from"zod";import{APIError as Ne}from"better-call";var eo=c("/forget-password",{method:"POST",body:ee.object({email:ee.string().email(),redirectTo:ee.string()}),use:[C]},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 Ne("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(o.user,s),e.json({status:!0})}),to=c("/reset-password/:token",{method:"GET",query:ee.object({callbackURL:ee.string()}),use:[C]},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}`)}),ro=c("/reset-password",{query:ee.object({token:ee.string()}).optional(),method:"POST",body:ee.object({newPassword:ee.string()})},async e=>{let t=e.query?.token;if(!t)throw new Ne("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 Ne("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 Ne("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{z as Q}from"zod";import{APIError as J}from"better-call";var oo=c("/user/update",{method:"POST",body:Q.object({name:Q.string().optional(),image:Q.string().optional()}),use:[A,C]},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:Q.object({newPassword:Q.string(),currentPassword:Q.string(),revokeOtherSessions:Q.boolean().optional()}),use:[A]},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 J("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 J("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 J("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 J("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 J("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await y(e,p.id)}return e.json(n.user)}),io=c("/user/set-password",{method:"POST",body:Q.object({newPassword:Q.string()}),use:[A]},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 J("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 J("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 J("BAD_REQUEST",{message:"user already has a password"})}),so=c("/user/delete",{method:"POST",body:Q.object({password:Q.string()}),use:[A]},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 J("BAD_REQUEST",{message:"User does not have a password"});if(!await e.context.password.verify(n.password,t))throw new J("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 Et}from"@noble/ciphers/chacha";import{bytesToHex as ao,hexToBytes as co,utf8ToBytes as uo}from"@noble/ciphers/utils";import{managedNonce as St}from"@noble/ciphers/webcrypto";import{sha256 as Pt}from"oslo/crypto";import{decodeHex as ma,encodeHex as fa}from"oslo/encoding";import{scryptAsync as wa}from"@noble/hashes/scrypt";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"]),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 Pt(new TextEncoder().encode(e)),o=uo(t),n=St(Et)(new Uint8Array(r));return ao(n.encrypt(o))},Me=async({key:e,data:t})=>{let r=await Pt(new TextEncoder().encode(e)),o=co(t),n=St(Et)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var lo=c("/csrf",{method:"GET",metadata:ne},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 e.json({csrfToken:i})}let r=N(32,F("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),e.json({csrfToken:r})});var po=(e="Unknown")=>`<!DOCTYPE html>
1
+ var yr=Object.defineProperty;var br=(e,t)=>{for(var r in t)yr(e,r,{get:t[r],enumerable:!0})};import{APIError as tr}from"better-call";import{z as Ee}from"zod";import{createEndpointCreator as Ar,createMiddleware as at,createMiddlewareCreator as kr}from"better-call";var dt=at(async()=>({})),E=kr({use:[dt,at(async()=>({}))]}),u=Ar({use:[dt]});import{APIError as G}from"better-call";import{generateCodeVerifier as eo}from"oslo/oauth2";import{z as K}from"zod";import{generateState as Rr}from"oslo/oauth2";import{z as Le}from"zod";import{sha256 as ct}from"oslo/crypto";function Ze(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 ut(e){let t=await ct(typeof e=="string"?new TextEncoder().encode(e):e);return Buffer.from(t).toString("base64")}async function Be(e,t){let r=await ct(typeof e=="string"?new TextEncoder().encode(e):e),o=Buffer.from(t,"base64");return Ze(r,o)}import"better-call";async function De(e){let t=Rr(),r=JSON.stringify({code:t,callbackURL:e}),o=await ut(r);return{raw:r,hash:o}}function we(e){return Le.object({code:Le.string(),callbackURL:Le.string().optional(),currentURL:Le.string().optional()}).safeParse(JSON.parse(e))}import{TimeSpan as gn}from"oslo";var M=class extends Error{constructor(t,r){super(t),this.name="BetterAuthError",this.message=t,this.cause=r,this.stack=""}};async function A(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 Ue(e){e.setCookie(e.context.authCookies.sessionToken.name,"",{maxAge:0}),e.setCookie(e.context.authCookies.dontRememberToken.name,"",{maxAge:0})}function lt(e){let t=new Map;return e.split(", ").forEach(o=>{let[n,...i]=o.split("; "),[a,s]=n.split("="),d={value:s};i.forEach(c=>{let[l,p]=c.split("=");d[l.toLowerCase()]=p||!0}),t.set(a,d)}),t}function xe(e){let t=e.split("; "),r=new Map;return t.forEach(o=>{let[n,i]=o.split("=");r.set(n,i)}),r}import{APIError as pt}from"better-call";import{createConsola as Or}from"consola";var ce=Or({formatOptions:{date:!1,colors:!0,compact:!0},defaults:{tag:"Better Auth"}}),Ur=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
+ `)}}),k=Ur();var S=E(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 k.error("Invalid callback URL",{callbackURL:t,trustedOrigins:n}),new pt("FORBIDDEN",{message:"Invalid callback URL"})}if(o!==e.context.baseURL){let i=new URL(o).origin;if(!n.includes(i))throw k.error("Invalid current URL",{currentURL:o,trustedOrigins:n}),new pt("FORBIDDEN",{message:"Invalid callback URL"})}});import{parseJWT as Er}from"oslo/jwt";import{sha256 as Ir}from"oslo/crypto";function mt(e){return new URL(e).origin.replace("http://","").replace("https://","")}import{base64url as vr}from"oslo/encoding";async function ft(e){let t=await Ir(new TextEncoder().encode(e));return vr.encode(new Uint8Array(t),{includePadding:!1})}function gt(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 z({id:e,options:t,authorizationEndpoint:r,state:o,codeVerifier:n,scopes:i,claims:a,disablePkce:s,redirectURI:d}){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",i.join(" ")),c.searchParams.set("redirect_uri",t.redirectURI||d),!s&&n){let l=await ft(n);c.searchParams.set("code_challenge_method","S256"),c.searchParams.set("code_challenge",l)}if(a){let l=a.reduce((p,y)=>(p[y]=null,p),{});c.searchParams.set("claims",JSON.stringify({id_token:{email:null,email_verified:null,...l}}))}return c}import{betterFetch as Tr}from"@better-fetch/fetch";async function v({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 Tr(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 gt(a)}function ye(e){let t=e.accessToken,r=e.refreshToken,o;try{o=e.accessTokenExpiresAt}catch{}return{accessToken:t,refreshToken:r,expiresAt:o}}var ht=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})=>v({code:r,codeVerifier:o,redirectURI:e.redirectURI||n,options:e,tokenEndpoint:t}),async getUserInfo(r){if(!r.idToken)return null;let o=Er(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 Sr}from"@better-fetch/fetch";var wt=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})=>v({code:t,redirectURI:e.redirectURI||r,options:e,tokenEndpoint:"https://discord.com/api/oauth2/token"}),async getUserInfo(t){let{data:r,error:o}=await Sr("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 Pr}from"@better-fetch/fetch";var yt=e=>({id:"facebook",name:"Facebook",async createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["email","public_profile"];return await z({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})=>v({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 Pr("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 bt}from"@better-fetch/fetch";var At=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 z({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})=>v({code:r,redirectURI:e.redirectURI||o,options:e,tokenEndpoint:t}),async getUserInfo(r){let{data:o,error:n}=await bt("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 bt("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 Cr}from"oslo/jwt";var kt=e=>({id:"google",name:"Google",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){if(!e.clientId||!e.clientSecret)throw k.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(!o)throw new M("codeVerifier is required for Google");let i=e.scope||r||["email","profile"];return z({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})=>v({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=Cr(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 _r}from"@better-fetch/fetch";import{parseJWT as zr}from"oslo/jwt";var Rt=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 z({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 v({code:n,codeVerifier:i,redirectURI:e.redirectURI||a,options:e,tokenEndpoint:o})},async getUserInfo(n){if(!n.idToken)return null;let i=zr(n.idToken)?.payload,a=e.profilePhotoSize||48;return await _r(`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 c=await s.response.clone().arrayBuffer(),l=Buffer.from(c).toString("base64");i.picture=`data:image/jpeg;base64, ${l}`}catch(d){k.error(d)}}}),{user:{id:i.sub,name:i.name,email:i.email,image:i.picture,emailVerified:!0},data:i}}}};import{betterFetch as Br}from"@better-fetch/fetch";var Ot=e=>({id:"spotify",name:"Spotify",createAuthorizationURL({state:t,scopes:r,codeVerifier:o,redirectURI:n}){let i=e.scope||r||["user-read-email"];return z({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})=>v({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 Br("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 Lr(e){return e.toString(2).padStart(8,"0")}function Dr(e){return[...e].map(t=>Lr(t)).join("")}function Ut(e){return parseInt(Dr(e),2)}function xr(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=Ut(o);for(;n>=e;)crypto.getRandomValues(o),r!==0&&(o[0]&=(1<<r)-1),n=Ut(o);return n}function q(e,t){let r="";for(let o=0;o<e;o++)r+=t[xr(t.length)];return r}function $(...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}import{nanoid as jr}from"nanoid";var _=e=>jr(e);import{parseJWT as Nr}from"oslo/jwt";var It=e=>({id:"twitch",name:"Twitch",createAuthorizationURL({state:t,scopes:r,redirectURI:o}){let n=e.scope||r||["user:read:email","openid"];return z({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})=>v({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 k.error("No idToken found in token"),null;let o=Nr(r)?.payload;return{user:{id:o.sub,name:o.preferred_username,email:o.email,image:o.picture,emailVerified:!1},data:o}}});import{betterFetch as Fr}from"@better-fetch/fetch";var vt=e=>({id:"twitter",name:"Twitter",createAuthorizationURL(t){let r=e.scope||t.scopes||["account_info.read"];return z({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})=>v({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 Fr("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 Mr={apple:ht,discord:wt,facebook:yt,github:At,microsoft:Rt,google:kt,spotify:Ot,twitch:It,twitter:vt},Tt=Object.keys(Mr);import{TimeSpan as Jr}from"oslo";import{createJWT as Gr,validateJWT as Zr}from"oslo/jwt";import{z as W}from"zod";import{APIError as be}from"better-call";import{APIError as Ie}from"better-call";var Q=(e,t="ms")=>new Date(Date.now()+(t==="sec"?e*1e3:e));import{z as Et}from"zod";var St=()=>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 Ue(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 Ue(e),e.json(null,{status:401});let c=(d.expiresAt.valueOf()-Date.now())/1e3;return await A(e,d.id,!1,{maxAge:c}),e.json({session:d,user:r.user})}return e.json(r)}catch(t){return e.context.logger.error(t),e.json(null,{status:500})}}),N=async e=>await St()({...e,_flag:"json",headers:e.headers}),w=E(async e=>{let t=await N(e);if(!t?.session)throw new Ie("UNAUTHORIZED");return{session:t}});var qr=u("/user/revoke-session",{method:"POST",body:Et.object({id:Et.string()}),use:[w],requireHeaders:!0},async e=>{let t=e.body.id,r=await e.context.internalAdapter.findSession(t);if(!r)throw new Ie("BAD_REQUEST",{message:"Session not found"});if(r.session.userId!==e.context.session.user.id)throw new Ie("UNAUTHORIZED");try{await e.context.internalAdapter.deleteSession(t)}catch(o){throw e.context.logger.error(o),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})}),$r=u("/user/revoke-sessions",{method:"POST",use:[w],requireHeaders:!0},async e=>{try{await e.context.internalAdapter.deleteSessions(e.context.session.user.id)}catch(t){throw e.context.logger.error(t),new Ie("INTERNAL_SERVER_ERROR")}return e.json({status:!0})});import{z as B}from"zod";import{APIError as V}from"better-call";var Vr=u("/user/update",{method:"POST",body:B.object({name:B.string().optional(),image:B.string().optional()}),use:[w,S]},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})}),Hr=u("/user/change-password",{method:"POST",body:B.object({newPassword:B.string(),currentPassword:B.string(),revokeOtherSessions:B.boolean().optional()}),use:[w]},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 V("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 V("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 V("BAD_REQUEST",{message:"User does not have a password"});let c=await e.context.password.hash(t);if(!await e.context.password.verify(d.password,r))throw new V("BAD_REQUEST",{message:"Incorrect password"});if(await e.context.internalAdapter.updateAccount(d.id,{password:c}),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 V("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});await A(e,p.id)}return e.json(n.user)}),Qr=u("/user/set-password",{method:"POST",body:B.object({newPassword:B.string()}),use:[w]},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 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 V("BAD_REQUEST",{message:"user already has a password"})}),Wr=u("/user/delete",{method:"POST",body:B.object({password:B.string()}),use:[w]},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 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)}),Kr=u("/user/change-email",{method:"POST",query:B.object({currentURL:B.string().optional()}).optional(),body:B.object({newEmail:B.string(),callbackURL:B.string().optional()}),use:[w,S]},async e=>{if(e.context.options.user?.changeEmail?.disable===!0)throw e.context.logger.error("Change email is disabled."),new V("BAD_REQUEST",{message:"Change email is disabled"});if(e.context.options.user?.changeEmail?.sendVerificationEmail===!1){let o=await e.context.internalAdapter.updateUserByEmail(e.context.session.user.email,{email:e.body.newEmail});return e.json({user:o,status:!0})}if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new V("BAD_REQUEST",{message:"Verification email isn't enabled"});let t=await re(e.context.secret,e.context.session.user.email,e.body.newEmail),r=`${e.context.baseURL}/verify-email?token=${t}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(e.context.session.user,r,t),e.json({user:null,status:!0})});async function re(e,t,r){return await Gr("HS256",Buffer.from(e),{email:t.toLowerCase(),updateTo:r},{expiresIn:new Jr(1,"h"),issuer:"better-auth",subject:"verify-email",audiences:[t],includeIssuedTimestamp:!0})}var Yr=u("/send-verification-email",{method:"POST",query:W.object({currentURL:W.string().optional()}).optional(),body:W.object({email:W.string().email(),callbackURL:W.string().optional()}),use:[S]},async e=>{if(!e.context.options.emailVerification?.sendVerificationEmail)throw e.context.logger.error("Verification email isn't enabled."),new be("BAD_REQUEST",{message:"Verification email isn't enabled"});let{email:t}=e.body,r=await e.context.internalAdapter.findUserByEmail(t);if(!r)throw new be("BAD_REQUEST",{message:"User not found"});let o=await re(e.context.secret,t),n=`${e.context.baseURL}/verify-email?token=${o}&callbackURL=${e.body.callbackURL||e.query?.currentURL||"/"}`;return await e.context.options.emailVerification.sendVerificationEmail(r.user,n,o),e.json({status:!0})}),Xr=u("/verify-email",{method:"GET",query:W.object({token:W.string(),callbackURL:W.string().optional()}),use:[S]},async e=>{let{token:t}=e.query,r;try{r=await Zr("HS256",Buffer.from(e.context.secret),t)}catch(a){throw e.context.logger.error("Failed to verify email",a),new be("BAD_REQUEST",{message:"Invalid token"})}let n=W.object({email:W.string().email(),updateTo:W.string().optional()}).parse(r.payload);if(!await e.context.internalAdapter.findUserByEmail(n.email))throw new be("BAD_REQUEST",{message:"User not found"});if(n.updateTo){let a=await N(e);if(!a)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Session not found"});if(a.user.email!==n.email)throw e.query.callbackURL?e.redirect(`${e.query.callbackURL}?error=unauthorized`):new be("UNAUTHORIZED",{message:"Invalid session"});let s=await e.context.internalAdapter.updateUserByEmail(n.email,{email:n.updateTo,emailVerified:!0});if(e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:s,status:!0})}if(await e.context.internalAdapter.updateUserByEmail(n.email,{emailVerified:!0}),e.query.callbackURL)throw e.redirect(e.query.callbackURL);return e.json({user:null,status:!0})});var to=u("/sign-in/social",{method:"POST",requireHeaders:!0,query:K.object({currentURL:K.string().optional()}).optional(),body:K.object({callbackURL:K.string().optional(),provider:K.enum(Tt)}),use:[S]},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 G("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 De(n||o?.origin||e.context.options.baseURL);await e.setSignedCookie(r.state.name,i.hash,e.context.secret,r.state.options);let a=eo();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})}),ro=u("/sign-in/email",{method:"POST",body:K.object({email:K.string().email(),password:K.string(),callbackURL:K.string().optional(),dontRememberMe:K.boolean().default(!1).optional()}),use:[S]},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 G("BAD_REQUEST",{message:"Email and password is not enabled"});let{email:t,password:r}=e.body;if(!K.string().email().safeParse(t).success)throw new G("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 G("UNAUTHORIZED",{message:"Invalid email or password"});if(e.context.options?.emailAndPassword?.requireEmailVerification&&!n.user.emailVerified){if(!e.context.options?.emailVerification?.sendVerificationEmail)throw k.error("Email verification is required but no email verification handler is provided"),new G("INTERNAL_SERVER_ERROR",{message:"Email is not verified."});let c=await re(e.context.secret,n.user.email),l=`${e.context.options.baseURL}/verify-email?token=${c}`;throw await e.context.options.emailVerification.sendVerificationEmail(n.user,l,c),e.context.logger.error("Email not verified",{email:t}),new G("FORBIDDEN",{message:"Email is not verified. Check your email for a verification link"})}let i=n.accounts.find(c=>c.providerId==="credential");if(!i)throw e.context.logger.error("Credential account not found",{email:t}),new G("UNAUTHORIZED",{message:"Invalid email or password"});let a=i?.password;if(!a)throw e.context.logger.error("Password not found",{email:t}),new G("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(a,r))throw e.context.logger.error("Invalid password"),new G("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 G("UNAUTHORIZED",{message:"Failed to create session"});return await A(e,d.id,e.body.dontRememberMe),e.json({user:n.user,session:d,redirect:!!e.body.callbackURL,url:e.body.callbackURL})});import{APIError as no}from"better-call";import{z as Ne}from"zod";import{z as b}from"zod";var Hs=b.object({id:b.string(),providerId:b.string(),accountId:b.string(),userId:b.string(),accessToken:b.string().nullable().optional(),refreshToken:b.string().nullable().optional(),idToken:b.string().nullable().optional(),expiresAt:b.date().nullable().optional(),password:b.string().optional().nullable()}),je=b.object({id:b.string(),email:b.string().transform(e=>e.toLowerCase()),emailVerified:b.boolean().default(!1),name:b.string(),image:b.string().optional(),createdAt:b.date().default(new Date),updatedAt:b.date().default(new Date)}),Qs=b.object({id:b.string(),userId:b.string(),expiresAt:b.date(),ipAddress:b.string().optional(),userAgent:b.string().optional()}),Ws=b.object({id:b.string(),value:b.string(),expiresAt:b.date(),identifier:b.string()});function oo(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 Pt(e,t){let r={...e.user?.additionalFields};return oo(t||{},{fields:r})}var io=u("/callback/:id",{method:"GET",query:Ne.object({state:Ne.string(),code:Ne.string().optional(),error:Ne.string().optional()}),metadata:se},async e=>{if(e.query.error||!e.query.code){let h=we(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=we(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 k.error("No stored state found"),e.redirect(`${e.context.baseURL}/error?error=please_restart_the_process`);if(!await Be(e.query.state,i))throw k.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 c=await t.getUserInfo(d).then(f=>f?.user),l=_(),p=je.safeParse({...c,id:l});if(!c||p.success===!1)throw k.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 y=await e.context.internalAdapter.findUserByEmail(c.email,{includeAccounts:!0}).catch(f=>{throw k.error(`Better auth was unable to query your database.
3
+ Error: `,f),e.redirect(`${e.context.baseURL}/error?error=internal_server_error`)}),m=y?.user.id;if(y){let f=y.accounts.find(O=>O.providerId===t.id),h=e.context.options.account?.accountLinking?.trustedProviders,R=h?h.includes(t.id):!0;if(!f&&(!c.emailVerified||!R)){let O;try{O=new URL(n||o),O.searchParams.set("error","account_not_linked")}catch{throw e.redirect(`${e.context.baseURL}/error?error=account_not_linked`)}throw e.redirect(O.toString())}if(!f)try{await e.context.internalAdapter.linkAccount({providerId:t.id,accountId:c.id.toString(),id:`${t.id}:${c.id}`,userId:y.user.id,...ye(d)})}catch(O){throw console.log(O),e.redirect(`${e.context.baseURL}/error?error=failed_linking_account`)}}else try{let f=c.emailVerified,h=await e.context.internalAdapter.createOAuthUser({...p.data,emailVerified:f},{...ye(d),id:`${t.id}:${c.id}`,providerId:t.id,accountId:c.id.toString()});if(!f&&h&&e.context.options.emailVerification?.sendOnSignUp){let R=await re(e.context.secret,c.email),O=`${e.context.baseURL}/verify-email?token=${R}&callbackURL=${o}`;await e.context.options.emailVerification?.sendVerificationEmail?.(h.user,O,R)}}catch{let h=new URL(n||o);throw h.searchParams.set("error","unable_to_create_user"),e.redirect(h.toString())}if(!m&&!l)throw new no("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 A(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"zod";import{APIError as so}from"better-call";var ao=u("/sign-out",{method:"POST"},async e=>{let t=await e.getSignedCookie(e.context.authCookies.sessionToken.name,e.context.secret);if(!t)throw new so("BAD_REQUEST",{message:"Session not found"});return await e.context.internalAdapter.deleteSession(t),Ue(e),e.json({success:!0})});import{z as Z}from"zod";import{APIError as Fe}from"better-call";var co=u("/forget-password",{method:"POST",body:Z.object({email:Z.string().email(),redirectTo:Z.string()}),use:[S]},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 Fe("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(o.user,s),e.json({status:!0})}),uo=u("/reset-password/:token",{method:"GET",query:Z.object({callbackURL:Z.string()}),use:[S]},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}`)}),lo=u("/reset-password",{query:Z.optional(Z.object({token:Z.string()})),method:"POST",body:Z.object({newPassword:Z.string()})},async e=>{let t=e.query?.token;if(!t)throw new Fe("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 Fe("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 Fe("BAD_REQUEST",{message:"Failed to update password"});return e.json({status:!0})});import{xchacha20poly1305 as Ct}from"@noble/ciphers/chacha";import{bytesToHex as po,hexToBytes as mo,utf8ToBytes as fo}from"@noble/ciphers/utils";import{managedNonce as _t}from"@noble/ciphers/webcrypto";import{sha256 as zt}from"oslo/crypto";import{decodeHex as Ra,encodeHex as Oa}from"oslo/encoding";import{scryptAsync as va}from"@noble/hashes/scrypt";async function J(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 Me=async({key:e,data:t})=>{let r=await zt(new TextEncoder().encode(e)),o=fo(t),n=_t(Ct)(new Uint8Array(r));return po(n.encrypt(o))},qe=async({key:e,data:t})=>{let r=await zt(new TextEncoder().encode(e)),o=mo(t),n=_t(Ct)(new Uint8Array(r));return new TextDecoder().decode(n.decrypt(o))};var go=u("/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 e.json({csrfToken:i})}let r=q(32,$("a-z","0-9","A-Z")),o=await J(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),e.json({csrfToken:r})});var ho=(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:ne},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:ne},async e=>e.json({ok:!0}));import{z as be}from"zod";import{APIError as ue}from"better-call";var Ge=()=>c("/sign-up/email",{method:"POST",query:be.object({currentURL:be.string().optional()}).optional(),body:be.record(be.string(),be.any()),use:[C]},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(!be.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:"Failed to create user"});let R=It(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...R,emailVerified:!1});if(!m)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:$(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let k=await ce(e.context.secret,m.email),O=`${e.context.baseURL}/verify-email?token=${k}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(m,O,k)}if(!e.context.options.emailAndPassword.autoSignIn)return e.json({user:m,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:null}});let h=await e.context.internalAdapter.createSession(m.id,e.request);if(!h)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await y(e,h.id),e.json({user:m,session:h},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:h}})});var _t=(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 Dt={};hr(Dt,{AccessControl:()=>Ie,ParsingError:()=>le,Role:()=>Ae,adminAc:()=>Bt,createAccessControl:()=>Ct,defaultAc:()=>qe,defaultRoles:()=>Ze,defaultStatements:()=>zt,memberAc:()=>xt,ownerAc:()=>Lt,permissionFromString:()=>go});var le=class extends Error{path;constructor(t,r){super(t),this.path=r}},Ie=class{constructor(t){this.s=t;this.statements=t}statements;newRole(t){return new Ae(t)}},Ae=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 Ct=e=>new Ie(e),zt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},qe=Ct(zt),Bt=qe.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),Lt=qe.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),xt=qe.newRole({organization:[],member:[],invitation:[]}),Ze={admin:Bt,owner:Lt,member:xt};var go=e=>Ae.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 j("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=$(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 jd,createRouter as Nd}from"better-call";import{APIError as Ye}from"better-call";import{z as jt}from"zod";var ho=_({body:jt.object({csrfToken:jt.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 W(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 ie}from"better-call";var B=_(async e=>({})),x=_({use:[A]},async e=>({session:e.context.session}));import{z as M}from"zod";import{z as I}from"zod";var $e=I.enum(["admin","member","owner"]),wo=I.enum(["pending","accepted","rejected","canceled"]).default("pending"),dc=I.object({id:I.string(),name:I.string(),slug:I.string(),logo:I.string().optional(),metadata:I.record(I.string()).or(I.string().transform(e=>JSON.parse(e))).optional(),createdAt:I.date()}),cc=I.object({id:I.string(),email:I.string(),organizationId:I.string(),userId:I.string(),role:$e,createdAt:I.date()}),uc=I.object({id:I.string(),organizationId:I.string(),email:I.string(),role:$e,status:wo,inviterId:I.string(),expiresAt:I.date()});import{APIError as T}from"better-call";var Nt=c("/organization/invite-member",{method:"POST",use:[B,x],body:M.object({email:M.string(),role:$e,organizationId:M.string().optional(),resend:M.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw b.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)}),Ft=c("/organization/accept-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},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!"}})}),Mt=c("/organization/reject-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},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})}),qt=c("/organization/cancel-invitation",{method:"POST",body:M.object({invitationId:M.string()}),use:[B,x]},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)}),$t=c("/organization/get-invitation",{method:"GET",use:[B],requireHeaders:!0,query:M.object({id:M.string()})},async e=>{let t=await V(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 Vt=c("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[B,x]},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})}),Qt=c("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[B,x]},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:[B,x]},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)}),Ht=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:[B]},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)}),Kt=c("/organization/delete",{method:"POST",body:S.object({orgId:S.string()}),requireHeaders:!0,use:[B]},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)}),Jt=c("/organization/get-full",{method:"GET",query:S.object({orgId:S.string().optional()}),requireHeaders:!0,use:[B,x]},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)}),Gt=c("/organization/activate",{method:"POST",body:S.object({orgId:S.string().nullable().optional()}),use:[x,B]},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)}),Zt=c("/organization/list",{method:"GET",use:[B,x]},async e=>{let r=await E(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var Wc=e=>{let t={createOrganization:Wt,updateOrganization:Ht,deleteOrganization:Kt,setActiveOrganization:Gt,getFullOrganization:Jt,listOrganization:Zt,createInvitation:Nt,cancelInvitation:qt,acceptInvitation:Ft,getInvitation:$t,rejectInvitation:Mt,removeMember:Vt,updateMemberRole:Qt},r={...Ze,...e?.roles};return{id:"organization",endpoints:{..._t(t,{orgOptions:e||{},roles:r,getSession:async n=>await V(n)}),hasPermission:c("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Te.object({permission:Te.record(Te.string(),Te.array(Te.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new Yt("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 Yt("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 He}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 Xt}from"zod";var ge=_({body:Xt.object({trustDevice:Xt.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 W(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 y(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await W(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(()=>N(e?.length??10,F("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 er(e.backupCodes,t);return r?r.includes(e.code):!1}async function er(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 tr=(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 y(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:c("/two-factor/generate-backup-codes",{method:"POST",use:[A]},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:[A]},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=er(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 We}from"better-call";import{TOTPController as Ao}from"oslo/otp";import{z as rr}from"zod";import{TimeSpan as ko}from"oslo";var or=(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 We("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 We("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:rr.object({code:rr.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new We("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 We("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 ke}from"better-call";import{TimeSpan as Ro}from"oslo";import{TOTPController as nr,createTOTPKeyURI as Oo}from"oslo/otp";import{z as ir}from"zod";var sr=(e,t)=>{let r={...e,digits:6,period:new Ro(e?.period||30,"s")},o=c("/totp/generate",{method:"POST",use:[A]},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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new nr(r).generate(Buffer.from(d.secret))}}),n=c("/two-factor/get-totp-uri",{method:"GET",use:[A]},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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:Oo(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=c("/two-factor/verify-totp",{method:"POST",body:ir.object({code:ir.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 ke("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 ke("BAD_REQUEST",{message:"totp isn't enabled"});let u=new nr(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 ar}from"better-call";var Pu=(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 $u=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=sr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=tr({...e?.backupCodeOptions},t.twoFactorTable),n=or({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:c("/two-factor/enable",{method:"POST",body:He.object({password:He.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new ar("BAD_REQUEST",{message:"Invalid password"});let u=N(16,F("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:He.object({password:He.string().min(8)}),use:[A]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await et(i,{password:s,userId:a.id}))throw new ar("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:_(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 W(i.context.secret,`${s.user.id}!${f}`);if(m===h){let k=await W(i.context.secret,`${s.user.id}!${s.session.id}`);await i.setSignedCookie(d.name,`${k}!${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 W(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 G}from"better-call";import{z as te}from"zod";import{WebAuthnError as Uo,startAuthentication as To,startRegistration as Eo}from"@simplewebauthn/browser";import{createFetch as tl}from"@better-fetch/fetch";import"nanostores";import{betterFetch as Hu}from"@better-fetch/fetch";import{atom as pl}from"nanostores";import"@better-fetch/fetch";import{atom as vo,onMount as Io}from"nanostores";var tt=(e,t,r,o)=>{let n=vo({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():Io(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:{}}),_l=()=>{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 $l=e=>{let t=process.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new j("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:[A],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(N(32,F("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 R=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,R,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:R,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:te.object({email:te.string().optional()}).optional()},async s=>{let d=await V(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||""}},R=P();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,R,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:R,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:c("/passkey/verify-registration",{method:"POST",body:te.object({response:te.any(),name:te.string().optional()}),use:[A]},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 G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:R,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new G("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let f=await Bo({response:u,expectedChallenge:R,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:h,registrationInfo:k}=f;if(!h||!k)return s.json(null,{status:400});let{credentialID:O,credentialPublicKey:X,counter:ae,credentialDeviceType:v,credentialBackedUp:D}=k,oe=Buffer.from(X).toString("base64"),L=P(),Ce={name:s.body.name,userId:m.id,webauthnUserID:L,id:O,publicKey:oe,counter:ae,deviceType:v,transports:u.response.transports.join(","),backedUp:D,createdAt:new Date},fr=await s.context.adapter.create({model:"passkey",data:Ce});return s.json(fr,{status:200})}catch(f){throw console.log(f),new G("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:c("/passkey/verify-authentication",{method:"POST",body:te.object({response:te.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new G("BAD_REQUEST",{message:"origin missing"});let u=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new G("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new G("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:R}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:u.id}]});if(!m)throw new G("UNAUTHORIZED",{message:"Passkey not found"});try{let f=await zo({response:u,expectedChallenge:R,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 G("UNAUTHORIZED",{message:"Authentication failed"});await s.context.adapter.update({model:"passkey",where:[{field:"id",value:m.id}],update:{counter:f.authenticationInfo.newCounter}});let k=await s.context.internalAdapter.createSession(m.userId,s.request);if(!k)throw new G("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await y(s,k.id),s.json({session:k},{status:200})}catch(f){throw s.context.logger.error(f),new G("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:c("/passkey/list-user-passkeys",{method:"GET",use:[A]},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:te.object({id:te.string()}),use:[A]},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 Z}from"zod";import{APIError as Ke}from"better-call";var dr=()=>({id:"username",endpoints:{signInUsername:c("/sign-in/username",{method:"POST",body:Z.object({username:Z.string(),password:Z.string(),dontRememberMe:Z.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:dr}),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:dr}),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:Z.object({username:Z.string().min(3).max(20),name:Z.string(),email:Z.string().email(),password:Z.string(),image:Z.string().optional()})},async e=>{let t=await Ge()({...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 Yl=()=>({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 Re}from"zod";import{APIError as xo}from"better-call";var sp=e=>({id:"magic-link",endpoints:{signInMagicLink:c("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Re.object({email:Re.string().email(),callbackURL:Re.string().optional()}),use:[C]},async t=>{let{email:r}=t.body,o=N(32,F("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:Re.object({token:Re.string(),callbackURL:Re.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,emailVerified:!0,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 y(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 he}from"zod";import{APIError as se}from"better-call";function Do(e){return N(e,F("0-9"))}var hp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:c("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw b.warn("sendOTP not implemented"),new se("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Do(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:$(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:c("/phone-number/verify",{method:"POST",body:he.object({phoneNumber:he.string(),code:he.string(),disableSession:he.boolean().optional(),updatePhoneNumber:he.boolean().optional()})},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 se("BAD_REQUEST",{message:"OTP expired"})):new se("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new se("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let a=await V(r);if(!a)throw new se("UNAUTHORIZED",{message:"Session not found"});let s=await r.context.internalAdapter.updateUser(a.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:s,session:a.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(!n)if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new se("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new se("BAD_REQUEST",{message:"Phone number not found"});let i=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});if(!r.body.disableSession){let a=await r.context.internalAdapter.createSession(n.id,r.request);if(!a)throw new se("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await y(r,a.id),r.json({user:i,session:a})}return r.json({user:i,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as rt}from"zod";var Op=e=>({id:"anonymous",endpoints:{signInAnonymous:c("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=ut(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 y(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:rt.object({email:rt.string().email().optional(),password:rt.string().min(6)}),use:[A]},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 y(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 Y=_(async e=>{let t=await V(e);if(!t?.session)throw new ie("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new ie("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),Sp=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:_(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:[Y]},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:[Y]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new ie("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 ie("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:[Y],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:[Y],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:[Y]},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:[Y]},async t=>{if(t.body.userId===t.context.session.user.id)throw new ie("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:[Y]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new ie("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?$(e.impersonationSessionDuration,"sec"):$(60*60,"sec")});if(!o)throw new ie("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await y(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:[Y]},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:[Y]},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:[Y]},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 re}from"zod";import{APIError as Pe}from"better-call";import{betterFetch as ot}from"@better-fetch/fetch";import{generateCodeVerifier as jo}from"oslo/oauth2";import{parseJWT as No}from"oslo/jwt";async function Fo(e,t,r){if(t==="oidc"&&e.idToken){let n=No(e.idToken);if(n?.payload)return n.payload}return r?(await ot(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var Wp=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:c("/sign-in/oauth2",{method:"POST",query:re.object({currentURL:re.string().optional()}).optional(),body:re.object({providerId:re.string(),callbackURL:re.string().optional()}),use:[C]},async t=>{let{providerId:r}=t.body,o=e.config.find(L=>L.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:R,prompt:m,accessType:f}=o,h=i,k=a;if(n){let L=await ot(n,{onError(Ce){b.error(Ce.error,{discoveryUrl:n})}});L.data&&(h=L.data.authorization_endpoint,k=L.data.token_endpoint)}if(!h||!k)throw new Pe("BAD_REQUEST",{message:"Invalid OAuth configuration."});let O=t.query?.currentURL?new URL(t.query?.currentURL):null,X=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${O?.origin}${t.body.callbackURL||""}`,ae=await Le(X||O?.origin||t.context.options.baseURL),v=t.context.authCookies;await t.setSignedCookie(v.state.name,ae.hash,t.context.secret,v.state.options);let D=jo();await t.setSignedCookie(v.pkCodeVerifier.name,D,t.context.secret,v.pkCodeVerifier.options);let oe=await z({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:h,state:ae.raw,codeVerifier:D,scopes:u||[],disablePkce:!R,redirectURI:`${t.context.baseURL}/oauth2/callback/${r}`});return p&&p!=="code"&&oe.searchParams.set("response_type",p),m&&oe.searchParams.set("prompt",m),f&&oe.searchParams.set("access_type",f),{url:oe.toString(),state:ae,codeVerifier:D,redirect:!0}}),oAuth2Callback:c("/oauth2/callback/:providerId",{method:"GET",query:re.object({code:re.string().optional(),error:re.string().optional(),state:re.string()})},async t=>{if(t.query.error||!t.query.code){let D=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${D}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(v=>v.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=we(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 b.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await ze(a,p))throw b.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,f=r.userInfoUrl;if(r.discoveryUrl){let v=await ot(r.discoveryUrl,{method:"GET"});v.data&&(m=v.data.token_endpoint,f=v.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(v){throw t.context.logger.error(v),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 Fo(n,r.type||"oauth2",f),k=P(),O=h?De.safeParse({...h,id:k}):null;if(!O?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let X=await t.context.internalAdapter.findUserByEmail(O.data.email).catch(v=>{throw b.error(`Better auth was unable to query your database.
84
- Error: `,v),t.redirect(`${l}?error=internal_server_error`)}),ae=X?.user.id||k;if(X){let v=X.accounts.find(L=>L.providerId===r.providerId),D=t.context.options.account?.accountLinking?.trustedProviders,oe=D?D.includes(r.providerId):!0;if(!v&&(!O?.data.emailVerified||!oe)){let L;try{L=new URL(l),L.searchParams.set("error","account_not_linked")}catch{throw t.redirect(`${l}?error=account_not_linked`)}throw t.redirect(L.toString())}if(!v)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:O.data.id,id:`${r.providerId}:${O.data.id}`,userId:X.user.id,...ye(n)})}catch(L){throw console.log(L),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(O.data,{...ye(n),id:`${r.providerId}:${O.data.id}`,providerId:r.providerId,accountId:O.data.id})}catch{let D=new URL(l);throw D.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",D.toString()),t.redirect(D.toString())}try{let v=await t.context.internalAdapter.createSession(ae||k,t.request);if(!v)throw t.redirect(`${l}?error=unable_to_create_session`);await y(t,v.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var cr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},Jp=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var nt=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 mr,generateKeyPair as Qo,importJWK as Wo,SignJWT as Ho}from"jose";import{createCipheriv as Mo,createDecipheriv as qo,createHash as $o,randomBytes as Vo}from"crypto";function ur(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=$o("sha256").update(e).digest(),t}function lr(e,t){let r=ur(t),o=Vo(12),n=Mo("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 pr(e,t){let r=ur(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=qo("aes-256-gcm",r,a);d.setAuthTag(s);let u=d.update(o,"base64","utf8");return u+=d.final("utf8"),u}var im=e=>({id:"jwt",endpoints:{getJwks:c("/jwks",{method:"GET"},async t=>{let o=await nt(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:[A]},async t=>{let r=nt(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:u,privateKey:l}=await Qo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await mr(u),R=await mr(l),m=JSON.stringify(R),f={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(lr(m,t.context.options.secret)):m,createdAt:new Date};o=await r.createJwk(f)}let i=n?pr(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await Wo(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:cr});export{ne as HIDE_METADATA,Dt as ac,Sp as admin,Y as adminMiddleware,Op as anonymous,Yl as bearer,c as createAuthEndpoint,_ as createAuthMiddleware,Wp as genericOAuth,Po as getPasskeyActions,im as jwt,sp as magicLink,st as optionsMiddleware,Wc as organization,$l as passkey,_l as passkeyClient,hp as phoneNumber,$u as twoFactor,Pu as twoFactorClient,dr as username};
83
+ </html>`,wo=u("/error",{method:"GET",metadata:se},async e=>{let t=new URL(e.request?.url||"").searchParams.get("error")||"Unknown";return new Response(ho(t),{headers:{"Content-Type":"text/html"}})});var yo=u("/ok",{method:"GET",metadata:se},async e=>e.json({ok:!0}));import{z as Ae}from"zod";import{APIError as ue}from"better-call";var Ye=()=>u("/sign-up/email",{method:"POST",query:Ae.object({currentURL:Ae.string().optional()}).optional(),body:Ae.record(Ae.string(),Ae.any()),use:[S]},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(!Ae.string().email().safeParse(o).success)throw new ue("BAD_REQUEST",{message:"Invalid email"});let c=e.context.password.config.minPasswordLength;if(n.length<c)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:"Failed to create user"});let y=Pt(e.context.options,s),m=await e.context.internalAdapter.createUser({email:o.toLowerCase(),name:r,image:i,...y,emailVerified:!1});if(!m)throw new ue("BAD_REQUEST",{message:"Failed to create user"});let f=await e.context.password.hash(n);if(await e.context.internalAdapter.linkAccount({userId:m.id,providerId:"credential",accountId:m.id,password:f,expiresAt:Q(60*60*24*30,"sec")}),e.context.options.emailVerification?.sendOnSignUp){let R=await re(e.context.secret,m.email),O=`${e.context.baseURL}/verify-email?token=${R}&callbackURL=${t.callbackURL||e.query?.currentURL||"/"}`;await e.context.options.emailVerification?.sendVerificationEmail?.(m,O,R)}if(!e.context.options.emailAndPassword.autoSignIn)return e.json({user:m,session:null},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:null}});let h=await e.context.internalAdapter.createSession(m.id,e.request);if(!h)throw new ue("BAD_REQUEST",{message:"Failed to create session"});return await A(e,h.id),e.json({user:m,session:h},{body:t.callbackURL?{url:t.callbackURL,redirect:!0}:{user:m,session:h}})});var Bt=(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 Ft={};br(Ft,{AccessControl:()=>ve,ParsingError:()=>le,Role:()=>ke,adminAc:()=>xt,createAccessControl:()=>Lt,defaultAc:()=>$e,defaultRoles:()=>Xe,defaultStatements:()=>Dt,memberAc:()=>Nt,ownerAc:()=>jt,permissionFromString:()=>bo});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 ke(t)}},ke=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 Lt=e=>new ve(e),Dt={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},$e=Lt(Dt),xt=$e.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),jt=$e.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),Nt=$e.newRole({organization:[],member:[],invitation:[]}),Xe={admin:xt,owner:jt,member:Nt};var bo=e=>ke.fromString(e??"");var P=(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:_(),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 c=>{let l=await e.findOne({model:"user",where:[{field:"id",value:c.userId}]});if(!l)throw new M("Unexpected error: User not found for member");return{...c,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:_(),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 Wd,createRouter as Kd,statusCode as Jd}from"better-call";import{APIError as et}from"better-call";import{z as Mt}from"zod";var Ao=E({body:Mt.object({csrfToken:Mt.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 et("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 et("UNAUTHORIZED",{message:"Invalid CSRF Token"});let a=await J(e.context.secret,n);if(i!==a)throw e.setCookie(e.context.authCookies.csrfToken.name,"",{maxAge:0}),new et("UNAUTHORIZED",{message:"Invalid CSRF Token"})});import{APIError as F}from"better-call";var L=E(async e=>({})),x=E({use:[w]},async e=>({session:e.context.session}));import{z as H}from"zod";import{z as I}from"zod";var Ve=I.enum(["admin","member","owner"]),ko=I.enum(["pending","accepted","rejected","canceled"]).default("pending"),yc=I.object({id:I.string(),name:I.string(),slug:I.string(),logo:I.string().optional(),metadata:I.record(I.string()).or(I.string().transform(e=>JSON.parse(e))).optional(),createdAt:I.date()}),bc=I.object({id:I.string(),email:I.string(),organizationId:I.string(),userId:I.string(),role:Ve,createdAt:I.date()}),Ac=I.object({id:I.string(),organizationId:I.string(),email:I.string(),role:Ve,status:ko,inviterId:I.string(),expiresAt:I.date()});import{APIError as T}from"better-call";var qt=u("/organization/invite-member",{method:"POST",use:[L,x],body:H.object({email:H.string(),role:Ve,organizationId:H.string().optional(),resend:H.boolean().optional()})},async e=>{if(!e.context.orgOptions.sendInvitationEmail)throw k.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=P(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 c=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:c.id,role:c.role,email:c.email,organization:l,inviter:{...n,user:t.user}},e.request),e.json(c)}),$t=u("/organization/accept-invitation",{method:"POST",body:H.object({invitationId:H.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(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:_(),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!"}})}),Vt=u("/organization/reject-invitation",{method:"POST",body:H.object({invitationId:H.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(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})}),Ht=u("/organization/cancel-invitation",{method:"POST",body:H.object({invitationId:H.string()}),use:[L,x]},async e=>{let t=e.context.session,r=P(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)}),Qt=u("/organization/get-invitation",{method:"GET",use:[L],requireHeaders:!0,query:H.object({id:H.string()})},async e=>{let t=await N(e);if(!t)throw new T("UNAUTHORIZED",{message:"Not authenticated"});let r=P(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 Te}from"better-call";var Wt=u("/organization/remove-member",{method:"POST",body:pe.object({memberIdOrEmail:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},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=P(e.context.adapter,e.context.orgOptions),n=await o.findMemberByOrgId({userId:t.user.id,organizationId:r});if(!n)throw new Te("BAD_REQUEST",{message:"Member not found!"});let i=e.context.roles[n.role];if(!i)throw new Te("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 Te("BAD_REQUEST",{message:"You cannot leave the organization as the owner"});if(!(a||i.authorize({member:["delete"]}).success))throw new Te("UNAUTHORIZED",{message:"You are not allowed to delete this member"});let c=null;if(e.body.memberIdOrEmail.includes("@")?c=await o.findMemberByEmail({email:e.body.memberIdOrEmail,organizationId:r}):c=await o.findMemberById(e.body.memberIdOrEmail),c?.organizationId!==r)throw new Te("BAD_REQUEST",{message:"Member not found!"});return await o.deleteMember(c.id),t.user.id===c.userId&&t.session.activeOrganizationId===c.organizationId&&await o.setActiveOrganization(t.session.id,null),e.json({member:c})}),Kt=u("/organization/update-member-role",{method:"POST",body:pe.object({role:pe.enum(["admin","member","owner"]),memberId:pe.string(),organizationId:pe.string().optional()}),use:[L,x]},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=P(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 C}from"zod";import{APIError as me}from"better-call";var Jt=u("/organization/create",{method:"POST",body:C.object({name:C.string(),slug:C.string(),userId:C.string().optional(),logo:C.string().optional(),metadata:C.record(C.string()).optional()}),use:[L,x]},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=P(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:_(),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)}),Gt=u("/organization/update",{method:"POST",body:C.object({data:C.object({name:C.string().optional(),slug:C.string().optional()}).partial(),orgId:C.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=P(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)}),Zt=u("/organization/delete",{method:"POST",body:C.object({orgId:C.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=P(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)}),Yt=u("/organization/get-full",{method:"GET",query:C.object({orgId:C.string().optional()}),requireHeaders:!0,use:[L,x]},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 P(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)}),Xt=u("/organization/activate",{method:"POST",body:C.object({orgId:C.string().nullable().optional()}),use:[x,L]},async e=>{let t=P(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)}),er=u("/organization/list",{method:"GET",use:[L,x]},async e=>{let r=await P(e.context.adapter,e.context.orgOptions).listOrganizations(e.context.session.user.id);return e.json(r)});var ru=e=>{let t={createOrganization:Jt,updateOrganization:Gt,deleteOrganization:Zt,setActiveOrganization:Xt,getFullOrganization:Yt,listOrganization:er,createInvitation:qt,cancelInvitation:Ht,acceptInvitation:$t,getInvitation:Qt,rejectInvitation:Vt,removeMember:Wt,updateMemberRole:Kt},r={...Xe,...e?.roles};return{id:"organization",endpoints:{...Bt(t,{orgOptions:e||{},roles:r,getSession:async n=>await N(n)}),hasPermission:u("/organization/has-permission",{method:"POST",requireHeaders:!0,body:Ee.object({permission:Ee.record(Ee.string(),Ee.array(Ee.string()))}),use:[x]},async n=>{if(!n.context.session.session.activeOrganizationId)throw new tr("BAD_REQUEST",{message:"No active organization"});let a=await P(n.context.adapter).findMemberByOrgId({userId:n.context.session.user.id,organizationId:n.context.session.session.activeOrganizationId||""});if(!a)throw new tr("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 Ke}from"zod";import{z as Pe}from"zod";import{APIError as fe}from"better-call";var He="two-factor";var Qe="trust-device";import{z as rr}from"zod";var ge=E({body:rr.object({trustDevice:rr.boolean().optional()})},async e=>{let t=e.context.createAuthCookie(He),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 J(e.context.secret,s.id),c=await e.context.adapter.findOne({model:"user",where:[{field:"id",value:s.userId}]});if(!c)throw new fe("UNAUTHORIZED",{message:"invalid session"});if(d===n)return{valid:async()=>{if(await A(e,s.id,!1),e.body.trustDevice){let l=e.context.createAuthCookie(Qe,{maxAge:2592e3}),p=await J(e.context.secret,`${c.id}!${s.id}`);await e.setSignedCookie(l.name,`${p}!${s.id}`,e.context.secret,l.options)}return e.json({session:s,user:c})},invalid:async()=>{throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})},session:{id:s.id,userId:s.userId,expiresAt:s.expiresAt,user:c}}}throw new fe("UNAUTHORIZED",{message:"invalid two factor authentication"})});import{APIError as Se}from"better-call";function Ro(e){return Array.from({length:e?.amount??10}).fill(null).map(()=>q(e?.length??10,$("a-z","0-9"))).map(t=>`${t.slice(0,5)}-${t.slice(5)}`)}async function tt(e,t){let r=e,o=t?.customBackupCodesGenerate?t.customBackupCodesGenerate():Ro(),n=await Me({data:JSON.stringify(o),key:r});return{backupCodes:o,encryptedBackupCodes:n}}async function Oo(e,t){let r=await or(e.backupCodes,t);return r?r.includes(e.code):!1}async function or(e,t){let r=Buffer.from(await qe({key:t,data:e})).toString("utf-8"),o=JSON.parse(r),n=Pe.array(Pe.string()).safeParse(o);return n.success?n.data:null}var nr=(e,t)=>({id:"backup_code",endpoints:{verifyBackupCode:u("/two-factor/verify-backup-code",{method:"POST",body:Pe.object({code:Pe.string(),disableSession:Pe.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 Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});if(!Oo({backupCodes:n.backupCodes,code:r.body.code},r.context.secret))throw new Se("BAD_REQUEST",{message:"Invalid backup code"});return r.body.disableSession||await A(r,r.context.session.id),r.json({user:o,session:r.context.session})}),generateBackupCodes:u("/two-factor/generate-backup-codes",{method:"POST",use:[w]},async r=>{if(!r.context.session.user.twoFactorEnabled)throw new Se("BAD_REQUEST",{message:"Two factor isn't enabled"});let n=await tt(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:u("/view/backup-codes",{method:"GET",use:[w]},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 Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});let i=or(n.backupCodes,r.context.secret);if(!i)throw new Se("BAD_REQUEST",{message:"Backup codes aren't enabled"});return r.json({status:!0,backupCodes:i})})}});import{APIError as We}from"better-call";import{TOTPController as Uo}from"oslo/otp";import{z as ir}from"zod";import{TimeSpan as Io}from"oslo";var sr=(e,t)=>{let r={...e,period:new Io(e?.period||3,"m")},o=new Uo({digits:6,period:r.period}),n=u("/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 We("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 We("BAD_REQUEST",{message:"totp isn't enabled"});let c=await o.generate(Buffer.from(d.secret));return await e.sendOTP(s,c),a.json({status:!0})}),i=u("/two-factor/verify-otp",{method:"POST",body:ir.object({code:ir.string()}),use:[ge]},async a=>{let s=a.context.session.user;if(!s.twoFactorEnabled)throw new We("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 We("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 Re}from"better-call";import{TimeSpan as vo}from"oslo";import{TOTPController as ar,createTOTPKeyURI as To}from"oslo/otp";import{z as dr}from"zod";var cr=(e,t)=>{let r={...e,digits:6,period:new vo(e?.period||30,"s")},o=u("/totp/generate",{method:"POST",use:[w]},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 Re("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 Re("BAD_REQUEST",{message:"totp isn't enabled"});return{code:await new ar(r).generate(Buffer.from(d.secret))}}),n=u("/two-factor/get-totp-uri",{method:"GET",use:[w]},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 Re("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 Re("BAD_REQUEST",{message:"totp isn't enabled"});return{totpURI:To(e?.issuer||"BetterAuth",s.email,Buffer.from(d.secret),r)}}),i=u("/two-factor/verify-totp",{method:"POST",body:dr.object({code:dr.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 Re("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 Re("BAD_REQUEST",{message:"totp isn't enabled"});let c=new ar(r),l=await qe({key:a.context.secret,data:d.secret}),p=Buffer.from(l);return await c.verify(a.body.code,p)?a.context.valid():a.context.invalid()});return{id:"totp",endpoints:{generateTOTP:o,viewTOTPURI:n,verifyTOTP:i}}};async function rt(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 ur}from"better-call";var Fu=(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 Xu=e=>{let t={twoFactorTable:e?.twoFactorTable||"twoFactor"},r=cr({issuer:e?.issuer||"better-auth",...e?.totpOptions},t.twoFactorTable),o=nr({...e?.backupCodeOptions},t.twoFactorTable),n=sr({...e?.otpOptions},t.twoFactorTable);return{id:"two-factor",endpoints:{...r.endpoints,...n.endpoints,...o.endpoints,enableTwoFactor:u("/two-factor/enable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new ur("BAD_REQUEST",{message:"Invalid password"});let c=q(16,$("a-z","0-9","-")),l=await Me({key:i.context.secret,data:c}),p=await tt(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:u("/two-factor/disable",{method:"POST",body:Ke.object({password:Ke.string().min(8)}),use:[w]},async i=>{let a=i.context.session.user,{password:s}=i.body;if(!await rt(i,{password:s,userId:a.id}))throw new ur("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:E(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}),c=await i.getSignedCookie(d.name,i.context.secret);if(c){let[m,f]=c.split("!"),h=await J(i.context.secret,`${s.user.id}!${f}`);if(m===h){let R=await J(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 J(i.context.secret,s.session.id),p=i.context.createAuthCookie(He,{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 Lo,generateRegistrationOptions as Do,verifyAuthenticationResponse as xo,verifyRegistrationResponse as jo}from"@simplewebauthn/server";import{APIError as Y}from"better-call";import{z as oe}from"zod";import{WebAuthnError as Po,startAuthentication as Co,startRegistration as _o}from"@simplewebauthn/browser";import{createFetch as ll}from"@better-fetch/fetch";import"nanostores";import{betterFetch as ol}from"@better-fetch/fetch";import{atom as Rl}from"nanostores";import"@better-fetch/fetch";import{atom as Eo,onMount as So}from"nanostores";var ot=(e,t,r,o)=>{let n=Eo({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 c=n.get();n.set({isPending:c.data===null,data:c.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():So(n,()=>(i(),a=!0,()=>{n.off(),s.off()}))});return n};import{atom as zo}from"nanostores";var Bo=(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 Co(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 _o(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 Po?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:{}}),Ml=()=>{let e=zo();return{id:"passkey",$InferServerPlugin:{},getActions:t=>Bo(t,{_listPasskeys:e}),getAtoms(t){return{listPasskeys:ot(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 Xl=e=>{let t=process.env.BETTER_AUTH_URL,r=e?.rpID||t?.replace("http://","").replace("https://","").split(":")[0]||"localhost";if(!r)throw new M("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:u("/passkey/generate-register-options",{method:"GET",use:[w],metadata:{client:!1}},async s=>{let d=s.context.session,c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}),l=new Uint8Array(Buffer.from(q(32,$("a-z","0-9")))),p;p=await Do({rpName:o.rpName||s.context.appName,rpID:o.rpID,userID:l,userName:d.user.email||d.user.id,attestationType:"none",excludeCredentials:c.map(m=>({id:m.id,transports:m.transports?.split(",")})),authenticatorSelection:{residentKey:"preferred",userVerification:"preferred",authenticatorAttachment:"platform"}});let y=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,y,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:y,value:JSON.stringify({expectedChallenge:p.challenge,userData:{id:d.user.id}}),expiresAt:n}),s.json(p,{status:200})}),generatePasskeyAuthenticationOptions:u("/passkey/generate-authenticate-options",{method:"POST",body:oe.object({email:oe.string().optional()}).optional()},async s=>{let d=await N(s),c=[];d&&(c=await s.context.adapter.findMany({model:"passkey",where:[{field:"userId",value:d.user.id}]}));let l=await Lo({rpID:o.rpID,userVerification:"preferred",...c.length?{allowCredentials:c.map(m=>({id:m.id,transports:m.transports?.split(",")}))}:{}}),p={expectedChallenge:l.challenge,userData:{id:d?.user.id||""}},y=_();return await s.setSignedCookie(o.advanced.webAuthnChallengeCookie,y,s.context.secret,{secure:!0,httpOnly:!0,sameSite:"lax",maxAge:a}),await s.context.internalAdapter.createVerificationValue({identifier:y,value:JSON.stringify(p),expiresAt:n}),s.json(l,{status:200})}),verifyPasskeyRegistration:u("/passkey/verify-registration",{method:"POST",body:oe.object({response:oe.any(),name:oe.string().optional()}),use:[w]},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)return s.json(null,{status:400});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new Y("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)return s.json(null,{status:400});let{expectedChallenge:y,userData:m}=JSON.parse(p.value);if(m.id!==s.context.session.user.id)throw new Y("UNAUTHORIZED",{message:"You are not authorized to register this passkey"});try{let f=await jo({response:c,expectedChallenge:y,expectedOrigin:d,expectedRPID:e?.rpID}),{verified:h,registrationInfo:R}=f;if(!h||!R)return s.json(null,{status:400});let{credentialID:O,credentialPublicKey:te,counter:de,credentialDeviceType:U,credentialBackedUp:j}=R,ie=Buffer.from(te).toString("base64"),D=_(),ze={name:s.body.name,userId:m.id,webauthnUserID:D,id:O,publicKey:ie,counter:de,deviceType:U,transports:c.response.transports.join(","),backedUp:j,createdAt:new Date},wr=await s.context.adapter.create({model:"passkey",data:ze});return s.json(wr,{status:200})}catch(f){throw console.log(f),new Y("INTERNAL_SERVER_ERROR",{message:"Failed to verify registration"})}}),verifyPasskeyAuthentication:u("/passkey/verify-authentication",{method:"POST",body:oe.object({response:oe.any()})},async s=>{let d=e?.origin||s.headers?.get("origin")||"";if(!d)throw new Y("BAD_REQUEST",{message:"origin missing"});let c=s.body.response,l=await s.getSignedCookie(o.advanced.webAuthnChallengeCookie,s.context.secret);if(!l)throw new Y("BAD_REQUEST",{message:"Challenge not found"});let p=await s.context.internalAdapter.findVerificationValue(l);if(!p)throw new Y("BAD_REQUEST",{message:"Challenge not found"});let{expectedChallenge:y}=JSON.parse(p.value),m=await s.context.adapter.findOne({model:"passkey",where:[{field:"id",value:c.id}]});if(!m)throw new Y("UNAUTHORIZED",{message:"Passkey not found"});try{let f=await xo({response:c,expectedChallenge:y,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 Y("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 Y("INTERNAL_SERVER_ERROR",{message:"Unable to create session"});return await A(s,R.id),s.json({session:R},{status:200})}catch(f){throw s.context.logger.error(f),new Y("BAD_REQUEST",{message:"Failed to verify authentication"})}}),listPasskeys:u("/passkey/list-user-passkeys",{method:"GET",use:[w]},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:u("/passkey/delete-passkey",{method:"POST",body:oe.object({id:oe.string()}),use:[w]},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 X}from"zod";import{APIError as Je}from"better-call";var lr=()=>({id:"username",endpoints:{signInUsername:u("/sign-in/username",{method:"POST",body:X.object({username:X.string(),password:X.string(),dontRememberMe:X.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:lr}),new Je("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 Je("UNAUTHORIZED",{message:"Invalid username or password"});let o=r?.password;if(!o)throw e.context.logger.error("Password not found",{username:lr}),new Je("UNAUTHORIZED",{message:"Unexpected error"});if(!await e.context.password.verify(o,e.body.password))throw e.context.logger.error("Invalid password"),new Je("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:u("/sign-up/username",{method:"POST",body:X.object({username:X.string().min(3).max(20),name:X.string(),email:X.string().email(),password:X.string(),image:X.string().optional()})},async e=>{let t=await Ye()({...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 No}from"better-call";var dp=()=>({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 No("",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 Oe}from"zod";import{APIError as Fo}from"better-call";var hp=e=>({id:"magic-link",endpoints:{signInMagicLink:u("/sign-in/magic-link",{method:"POST",requireHeaders:!0,body:Oe.object({email:Oe.string().email(),callbackURL:Oe.string().optional()}),use:[S]},async t=>{let{email:r}=t.body,o=q(32,$("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 Fo("INTERNAL_SERVER_ERROR",{message:"Failed to send magic link"})}return t.json({status:!0})}),magicLinkVerify:u("/magic-link/verify",{method:"GET",query:Oe.object({token:Oe.string(),callbackURL:Oe.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,emailVerified:!0,name:a})).id,!d)throw t.redirect(`${n}?error=USER_NOT_CREATED`)}let c=await t.context.internalAdapter.createSession(d,t.headers);if(!c)throw t.redirect(`${n}?error=SESSION_NOT_CREATED`);if(await A(t,c.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 he}from"zod";import{APIError as ae}from"better-call";function Mo(e){return q(e,$("0-9"))}var vp=e=>{let t={phoneNumber:"phoneNumber",phoneNumberVerified:"phoneNumberVerified",code:"code",createdAt:"createdAt",expiresIn:e?.expiresIn||300,otpLength:e?.otpLength||6};return{id:"phone-number",endpoints:{sendPhoneNumberOTP:u("/phone-number/send-otp",{method:"POST",body:he.object({phoneNumber:he.string()})},async r=>{if(!e?.sendOTP)throw k.warn("sendOTP not implemented"),new ae("NOT_IMPLEMENTED",{message:"sendOTP not implemented"});let o=Mo(t.otpLength);return await r.context.internalAdapter.createVerificationValue({value:o,identifier:r.body.phoneNumber,expiresAt:Q(t.expiresIn,"sec")}),await e.sendOTP(r.body.phoneNumber,o),r.json({code:o},{body:{message:"Code sent"}})}),verifyPhoneNumber:u("/phone-number/verify",{method:"POST",body:he.object({phoneNumber:he.string(),code:he.string(),disableSession:he.boolean().optional(),updatePhoneNumber:he.boolean().optional()})},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 ae("BAD_REQUEST",{message:"OTP expired"})):new ae("BAD_REQUEST",{message:"OTP not found"});if(o.value!==r.body.code)throw new ae("BAD_REQUEST",{message:"Invalid OTP"});if(await r.context.internalAdapter.deleteVerificationValue(o.id),r.body.updatePhoneNumber){let a=await N(r);if(!a)throw new ae("UNAUTHORIZED",{message:"Session not found"});let s=await r.context.internalAdapter.updateUser(a.user.id,{[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0});return r.json({user:s,session:a.session})}let n=await r.context.adapter.findOne({model:r.context.tables.user.tableName,where:[{value:r.body.phoneNumber,field:t.phoneNumber}]});if(!n)if(e?.signUpOnVerification){if(n=await r.context.internalAdapter.createUser({email:`temp-${r.body.phoneNumber}`,name:r.body.phoneNumber,[t.phoneNumber]:r.body.phoneNumber,[t.phoneNumberVerified]:!0}),!n)throw new ae("INTERNAL_SERVER_ERROR",{message:"Failed to create user"})}else throw new ae("BAD_REQUEST",{message:"Phone number not found"});let i=await r.context.internalAdapter.updateUser(n.id,{[t.phoneNumberVerified]:!0});if(!r.body.disableSession){let a=await r.context.internalAdapter.createSession(n.id,r.request);if(!a)throw new ae("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(r,a.id),r.json({user:i,session:a})}return r.json({user:i,session:null})})},schema:{user:{fields:{phoneNumber:{type:"string",required:!1,unique:!0,returned:!0},phoneNumberVerified:{type:"boolean",required:!1,returned:!0,input:!1}}}}}};import{z as nt}from"zod";var zp=e=>({id:"anonymous",endpoints:{signInAnonymous:u("/sign-in/anonymous",{method:"POST"},async t=>{let{emailDomainName:r=mt(t.context.baseURL)}=e||{},o=_(),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 A(t,a.id),t.json({user:i,session:a})):t.json(null,{status:400,body:{message:"Could not create session"}})}),linkAnonymous:u("/user/link-anonymous",{method:"POST",body:nt.object({email:nt.string().email().optional(),password:nt.string().min(6)}),use:[w]},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 A(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 ee=E(async e=>{let t=await N(e);if(!t?.session)throw new F("UNAUTHORIZED");let r=t.user;if(r.role!=="admin")throw new F("FORBIDDEN",{message:"Only admins can access this endpoint"});return{session:{user:r,session:t.session}}}),Np=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:E(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:u("/admin/set-role",{method:"POST",body:g.object({userId:g.string(),role:g.string()}),use:[ee]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{role:t.body.role});return t.json({user:r})}),createUser:u("/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:[ee]},async t=>{if(await t.context.internalAdapter.findUserByEmail(t.body.email))throw new F("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 F("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:u("/admin/list-users",{method:"GET",use:[ee],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:u("/admin/list-user-sessions",{method:"POST",use:[ee],body:g.object({userId:g.string()})},async t=>({sessions:await t.context.internalAdapter.listSessions(t.body.userId)})),unbanUser:u("/admin/unban-user",{method:"POST",body:g.object({userId:g.string()}),use:[ee]},async t=>{let r=await t.context.internalAdapter.updateUser(t.body.userId,{banned:!1});return t.json({user:r})}),banUser:u("/admin/ban-user",{method:"POST",body:g.object({userId:g.string(),banReason:g.string().optional(),banExpiresIn:g.number().optional()}),use:[ee]},async t=>{if(t.body.userId===t.context.session.user.id)throw new F("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:u("/admin/impersonate-user",{method:"POST",body:g.object({userId:g.string()}),use:[ee]},async t=>{let r=await t.context.internalAdapter.findUserById(t.body.userId);if(!r)throw new F("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 F("INTERNAL_SERVER_ERROR",{message:"Failed to create session"});return await A(t,o.id,!0),t.json({session:o,user:r})}),revokeUserSession:u("/admin/revoke-user-session",{method:"POST",body:g.object({sessionId:g.string()}),use:[ee]},async t=>(await t.context.internalAdapter.deleteSession(t.body.sessionId),t.json({success:!0}))),revokeUserSessions:u("/admin/revoke-user-sessions",{method:"POST",body:g.object({userId:g.string()}),use:[ee]},async t=>(await t.context.internalAdapter.deleteSessions(t.body.userId),t.json({success:!0}))),removeUser:u("/admin/remove-user",{method:"POST",body:g.object({userId:g.string()}),use:[ee]},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 ne}from"zod";import{APIError as Ce}from"better-call";import{betterFetch as it}from"@better-fetch/fetch";import{generateCodeVerifier as qo}from"oslo/oauth2";import{parseJWT as $o}from"oslo/jwt";async function Vo(e,t,r){if(t==="oidc"&&e.idToken){let n=$o(e.idToken);if(n?.payload)return n.payload}return r?(await it(r,{method:"GET",headers:{Authorization:`Bearer ${e.accessToken}`}})).data:null}var rm=e=>({id:"generic-oauth",endpoints:{signInWithOAuth2:u("/sign-in/oauth2",{method:"POST",query:ne.object({currentURL:ne.string().optional()}).optional(),body:ne.object({providerId:ne.string(),callbackURL:ne.string().optional()}),use:[S]},async t=>{let{providerId:r}=t.body,o=e.config.find(D=>D.providerId===r);if(!o)throw new Ce("BAD_REQUEST",{message:`No config found for provider ${r}`});let{discoveryUrl:n,authorizationUrl:i,tokenUrl:a,clientId:s,clientSecret:d,scopes:c,redirectURI:l,responseType:p,pkce:y,prompt:m,accessType:f}=o,h=i,R=a;if(n){let D=await it(n,{onError(ze){k.error(ze.error,{discoveryUrl:n})}});D.data&&(h=D.data.authorization_endpoint,R=D.data.token_endpoint)}if(!h||!R)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let O=t.query?.currentURL?new URL(t.query?.currentURL):null,te=t.body.callbackURL?.startsWith("http")?t.body.callbackURL:`${O?.origin}${t.body.callbackURL||""}`,de=await De(te||O?.origin||t.context.options.baseURL),U=t.context.authCookies;await t.setSignedCookie(U.state.name,de.hash,t.context.secret,U.state.options);let j=qo();await t.setSignedCookie(U.pkCodeVerifier.name,j,t.context.secret,U.pkCodeVerifier.options);let ie=await z({id:r,options:{clientId:s,clientSecret:d,redirectURI:l},authorizationEndpoint:h,state:de.raw,codeVerifier:j,scopes:c||[],disablePkce:!y,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:de,codeVerifier:j,redirect:!0}}),oAuth2Callback:u("/oauth2/callback/:providerId",{method:"GET",query:ne.object({code:ne.string().optional(),error:ne.string().optional(),state:ne.string()})},async t=>{if(t.query.error||!t.query.code){let j=we(t.query.state).data?.currentURL||`${t.context.baseURL}/error`;throw t.context.logger.error(t.query.error,t.params.providerId),t.redirect(`${j}?error=${t.query.error||"oAuth_code_missing"}`)}let r=e.config.find(U=>U.providerId===t.params.providerId);if(!r)throw new Ce("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=we(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,c=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 k.error("No stored state found"),t.redirect(`${l}?error=please_restart_the_process`);if(!await Be(a,p))throw k.error("OAuth code mismatch"),t.redirect(`${l}?error=please_restart_the_process`);let m=r.tokenUrl,f=r.userInfoUrl;if(r.discoveryUrl){let U=await it(r.discoveryUrl,{method:"GET"});U.data&&(m=U.data.token_endpoint,f=U.data.userinfo_endpoint)}try{if(!m)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});n=await v({code:c,codeVerifier:o,redirectURI:`${t.context.baseURL}/oauth2/callback/${r.providerId}`,options:{clientId:r.clientId,clientSecret:r.clientSecret},tokenEndpoint:m})}catch(U){throw t.context.logger.error(U),t.redirect(`${l}?error=oauth_code_verification_failed`)}if(!n)throw new Ce("BAD_REQUEST",{message:"Invalid OAuth configuration."});let h=r.getUserInfo?await r.getUserInfo(n):await Vo(n,r.type||"oauth2",f),R=_(),O=h?je.safeParse({...h,id:R}):null;if(!O?.success)throw t.redirect(`${l}?error=oauth_user_info_invalid`);let te=await t.context.internalAdapter.findUserByEmail(O.data.email).catch(U=>{throw k.error(`Better auth was unable to query your database.
84
+ Error: `,U),t.redirect(`${l}?error=internal_server_error`)}),de=te?.user.id||R;if(te){let U=te.accounts.find(D=>D.providerId===r.providerId),j=t.context.options.account?.accountLinking?.trustedProviders,ie=j?j.includes(r.providerId):!0;if(!U&&(!O?.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(!U)try{await t.context.internalAdapter.linkAccount({providerId:r.providerId,accountId:O.data.id,id:`${r.providerId}:${O.data.id}`,userId:te.user.id,...ye(n)})}catch(D){throw console.log(D),t.redirect(`${l}?error=failed_linking_account`)}}else try{await t.context.internalAdapter.createOAuthUser(O.data,{...ye(n),id:`${r.providerId}:${O.data.id}`,providerId:r.providerId,accountId:O.data.id})}catch{let j=new URL(l);throw j.searchParams.set("error","unable_to_create_user"),t.setHeader("Location",j.toString()),t.redirect(j.toString())}try{let U=await t.context.internalAdapter.createSession(de||R,t.request);if(!U)throw t.redirect(`${l}?error=unable_to_create_session`);await A(t,U.id)}catch{throw t.redirect(`${l}?error=unable_to_create_session`)}throw t.redirect(s||d||"")})}});import{z as _e}from"zod";var pr={jwks:{fields:{publicKey:{type:"string",required:!0},privateKey:{type:"string",required:!0},createdAt:{type:"date",required:!0}}}},im=_e.object({id:_e.string(),publicKey:_e.string(),privateKey:_e.string(),createdAt:_e.date()});var st=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 hr,generateKeyPair as Jo,importJWK as Go,SignJWT as Zo}from"jose";import{createCipheriv as Ho,createDecipheriv as Qo,createHash as Wo,randomBytes as Ko}from"crypto";function mr(e){let t;return Buffer.byteLength(e,"utf8")===32?t=Buffer.from(e,"utf8"):t=Wo("sha256").update(e).digest(),t}function fr(e,t){let r=mr(t),o=Ko(12),n=Ho("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 gr(e,t){let r=mr(t),{encryptedPrivateKey:o,iv:n,authTag:i}=e,a=Buffer.from(n,"base64"),s=Buffer.from(i,"base64"),d=Qo("aes-256-gcm",r,a);d.setAuthTag(s);let c=d.update(o,"base64","utf8");return c+=d.final("utf8"),c}var gm=e=>({id:"jwt",endpoints:{getJwks:u("/jwks",{method:"GET"},async t=>{let o=await st(t.context.adapter).getAllKeys();return t.json({keys:o.map(n=>({...JSON.parse(n.publicKey),kid:n.id}))})}),getToken:u("/token",{method:"GET",requireHeaders:!0,use:[w]},async t=>{let r=st(t.context.adapter),o=await r.getLatestKey(),n=!e?.jwks?.disablePrivateKeyEncryption;if(o===void 0){let{publicKey:c,privateKey:l}=await Jo(e?.jwks?.keyPairConfig?.alg??"EdDSA",e?.jwks?.keyPairConfig??{crv:"Ed25519"}),p=await hr(c),y=await hr(l),m=JSON.stringify(y),f={id:crypto.randomUUID(),publicKey:JSON.stringify(p),privateKey:n?JSON.stringify(fr(m,t.context.options.secret)):m,createdAt:new Date};o=await r.createJwk(f)}let i=n?gr(JSON.parse(o.privateKey),t.context.options.secret):o.privateKey,a=await Go(JSON.parse(i)),s=e?.jwt?.definePayload?await e?.jwt.definePayload(t.context.session.user):t.context.session.user,d=await new Zo({...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:pr});import{z as Ge}from"zod";var Am=e=>{let t={maximumSessions:5,...e},r=o=>o.includes("_multi-");return{id:"multi-session",endpoints:{listDeviceSessions:u("/multi-session/list-device-sessions",{method:"GET",requireHeaders:!0},async o=>{let n=o.headers?.get("cookie");if(!n)return o.json([]);let i=Object.fromEntries(xe(n)),a=[],s=Object.entries(i).filter(([c])=>r(c)).map(async([c])=>{let l=await o.getSignedCookie(c,o.context.secret);if(!l)return null;let p=await o.context.internalAdapter.findSession(l);return!p||p.session.expiresAt<=new Date?(o.setCookie(c,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),null):p}),d=(await Promise.all(s)).filter(Boolean);return a.push(...d.filter((c,l,p)=>l===p.findIndex(y=>y.user.id===c.user.id))),o.json(a)}),setActiveSession:u("/multi-session/set-active",{method:"POST",body:Ge.object({sessionId:Ge.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new F("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);if(!s||s.session.expiresAt<new Date)throw o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),new F("UNAUTHORIZED",{message:"Invalid session id"});return await o.setSignedCookie(o.context.authCookies.sessionToken.name,n,o.context.secret,o.context.authCookies.sessionToken.options),o.json(s)}),DeviceSession:u("/multi-session/revoke",{method:"POST",body:Ge.object({sessionId:Ge.string()}),requireHeaders:!0,use:[w]},async o=>{let n=o.body.sessionId,i=`${o.context.authCookies.sessionToken.name}_multi-${n}`;if(!await o.getSignedCookie(i,o.context.secret))throw new F("UNAUTHORIZED",{message:"Invalid session id"});let s=await o.context.internalAdapter.findSession(n);return!s||s.session.expiresAt<new Date?(o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0})):(await o.context.internalAdapter.deleteSession(n),o.setCookie(i,"",{...o.context.authCookies.sessionToken.options,maxAge:0}),o.json({success:!0}))})},hooks:{after:[{matcher:()=>!0,handler:E(async o=>{if(!o.context.returned||!(o.context.returned instanceof Response))return;let n=o.context.returned.headers.get("set-cookie");if(!n)return;let i=lt(n),a=o.context.authCookies.sessionToken,s=i.get(a.name)?.value;if(!s)return;let d=xe(o.headers?.get("cookie")||""),c=s.split(".")[0],l=`${a.name}_multi-${c}`;if(i.get(l)||d.get(l))return;let p=Object.keys(d).filter(r).length,y=Object.keys(i).filter(f=>f.includes("session_token")).length;if(p+y>t.maximumSessions)throw new F("UNAUTHORIZED",{message:"Maximum number of device sessions reached."});await o.setSignedCookie(l,c,o.context.secret,a.options);let m=o.context.returned;return m.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:m}})},{matcher:o=>o.path==="/sign-out",handler:E(async o=>{let n=o.headers?.get("cookie");if(!n)return;let i=Object.fromEntries(xe(n));await Promise.all(Object.entries(i).map(async([s,d])=>{r(s)&&(o.setCookie(s,"",{maxAge:0}),await o.context.internalAdapter.deleteSession(s.split("_multi-")[1]))}));let a=o.context.returned;return a?.headers.append("Set-Cookie",o.responseHeader.get("set-cookie")),{response:a}})}]}}};export{se as HIDE_METADATA,Ft as ac,Np as admin,ee as adminMiddleware,zp as anonymous,dp as bearer,u as createAuthEndpoint,E as createAuthMiddleware,rm as genericOAuth,Bo as getPasskeyActions,gm as jwt,hp as magicLink,Am as multiSession,dt as optionsMiddleware,ru as organization,Xl as passkey,Ml as passkeyClient,vp as phoneNumber,Xu as twoFactor,Fu as twoFactorClient,lr as username};
package/dist/react.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as _better_fetch_fetch from '@better-fetch/fetch';
3
3
  import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.js';
4
4
  import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
5
5
  import { useStore } from '@nanostores/react';
6
- import './auth-C6fr77co.js';
6
+ import './auth-BTj2ofMy.js';
7
7
  import 'kysely';
8
8
  import './schema-Dkt0LqYs.js';
9
9
  import 'better-call';
@@ -1,4 +1,4 @@
1
- import { a as Auth } from './auth-C6fr77co.js';
1
+ import { a as Auth } from './auth-BTj2ofMy.js';
2
2
  import 'zod';
3
3
  import 'kysely';
4
4
  import './schema-Dkt0LqYs.js';
package/dist/solid.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as _better_fetch_fetch from '@better-fetch/fetch';
3
3
  import { U as UnionToIntersection, P as Prettify, S as StripEmptyObjects } from './helper-DPDj8Nix.js';
4
4
  import { ClientOptions, InferClientAPI, InferActions, InferAdditionalFromClient, BetterAuthClientPlugin, IsSignal } from './types.js';
5
5
  import { Accessor } from 'solid-js';
6
- import './auth-C6fr77co.js';
6
+ import './auth-BTj2ofMy.js';
7
7
  import 'kysely';
8
8
  import './schema-Dkt0LqYs.js';
9
9
  import 'better-call';
@@ -1,4 +1,4 @@
1
- import { a as Auth, B as BetterAuthOptions } from './auth-C6fr77co.js';
1
+ import { a as Auth, B as BetterAuthOptions } from './auth-BTj2ofMy.js';
2
2
  import 'zod';
3
3
  import 'kysely';
4
4
  import './schema-Dkt0LqYs.js';