better-auth 0.5.3-beta.8 → 0.5.3-beta.9
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/access.js +1 -0
- package/dist/access.js.map +1 -0
- package/dist/adapters/drizzle.js +2 -1
- package/dist/adapters/drizzle.js.map +1 -0
- package/dist/adapters/kysely.js +1 -0
- package/dist/adapters/kysely.js.map +1 -0
- package/dist/adapters/mongodb.js +1 -0
- package/dist/adapters/mongodb.js.map +1 -0
- package/dist/adapters/prisma.js +1 -0
- package/dist/adapters/prisma.js.map +1 -0
- package/dist/api.js +2 -1
- package/dist/api.js.map +1 -0
- package/dist/client/plugins.js +1 -0
- package/dist/client/plugins.js.map +1 -0
- package/dist/client.js +2 -1
- package/dist/client.js.map +1 -0
- package/dist/cookies.js +2 -1
- package/dist/cookies.js.map +1 -0
- package/dist/crypto.js +1 -0
- package/dist/crypto.js.map +1 -0
- package/dist/db.js +2 -1
- package/dist/db.js.map +1 -0
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -0
- package/dist/next-js.js +1 -0
- package/dist/next-js.js.map +1 -0
- package/dist/node.js +1 -0
- package/dist/node.js.map +1 -0
- package/dist/oauth2.js +1 -0
- package/dist/oauth2.js.map +1 -0
- package/dist/plugins.js +2 -1
- package/dist/plugins.js.map +1 -0
- package/dist/react.js +2 -1
- package/dist/react.js.map +1 -0
- package/dist/social.js +2 -1
- package/dist/social.js.map +1 -0
- package/dist/solid-start.js +1 -0
- package/dist/solid-start.js.map +1 -0
- package/dist/solid.js +2 -1
- package/dist/solid.js.map +1 -0
- package/dist/svelte-kit.js +2 -1
- package/dist/svelte-kit.js.map +1 -0
- package/dist/svelte.js +2 -1
- package/dist/svelte.js.map +1 -0
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/vue.js +2 -1
- package/dist/vue.js.map +1 -0
- package/package.json +1 -1
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/index.ts","../src/api/middlewares/csrf.ts","../src/crypto/index.ts","../src/crypto/buffer.ts","../src/crypto/password.ts","../src/crypto/random.ts","../src/api/call.ts","../src/api/routes/sign-in.ts","../src/oauth2/state.ts","../src/crypto/hash.ts","../src/cookies/index.ts","../src/error/index.ts","../src/api/middlewares/redirect.ts","../src/utils/logger.ts","../src/social-providers/apple.ts","../src/oauth2/utils.ts","../src/oauth2/create-authorization-url.ts","../src/oauth2/validate-authorization-code.ts","../src/oauth2/get-account.ts","../src/social-providers/discord.ts","../src/social-providers/facebook.ts","../src/social-providers/github.ts","../src/social-providers/google.ts","../src/social-providers/microsoft-entra-id.ts","../src/social-providers/spotify.ts","../src/social-providers/twitch.ts","../src/utils/hide-metadata.ts","../src/utils/id.ts","../src/social-providers/twitter.ts","../src/social-providers/index.ts","../src/api/routes/email-verification.ts","../src/api/routes/session.ts","../src/utils/date.ts","../src/api/routes/callback.ts","../src/db/schema.ts","../src/api/routes/sign-out.ts","../src/api/routes/forget-password.ts","../src/api/routes/update-user.ts","../src/api/routes/csrf.ts","../src/api/routes/error.ts","../src/api/routes/ok.ts","../src/api/routes/sign-up.ts","../src/utils/get-request-ip.ts","../src/api/rate-limiter/index.ts"],"sourcesContent":["import { APIError, type Endpoint, createRouter, statusCode } from \"better-call\";\nimport type { AuthContext } from \"../init\";\nimport type { BetterAuthOptions } from \"../types\";\nimport type { UnionToIntersection } from \"../types/helper\";\nimport { csrfMiddleware } from \"./middlewares/csrf\";\nimport {\n\tcallbackOAuth,\n\tforgetPassword,\n\tforgetPasswordCallback,\n\tgetSession,\n\tlistSessions,\n\tresetPassword,\n\trevokeSession,\n\trevokeSessions,\n\tsendVerificationEmail,\n\tchangeEmail,\n\tsignInEmail,\n\tsignInOAuth,\n\tsignOut,\n\tverifyEmail,\n} from \"./routes\";\nimport { getCSRFToken } from \"./routes/csrf\";\nimport { ok } from \"./routes/ok\";\nimport { signUpEmail } from \"./routes/sign-up\";\nimport { error } from \"./routes/error\";\nimport { logger } from \"../utils/logger\";\nimport {\n\tchangePassword,\n\tdeleteUser,\n\tsetPassword,\n\tupdateUser,\n} from \"./routes/update-user\";\nimport type { BetterAuthPlugin } from \"../plugins\";\nimport { onRequestRateLimit } from \"./rate-limiter\";\n\nexport function getEndpoints<\n\tC extends AuthContext,\n\tOption extends BetterAuthOptions,\n>(ctx: Promise<C> | C, options: Option) {\n\tconst pluginEndpoints = options.plugins?.reduce(\n\t\t(acc, plugin) => {\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t...plugin.endpoints,\n\t\t\t};\n\t\t},\n\t\t{} as Record<string, any>,\n\t);\n\n\ttype PluginEndpoint = UnionToIntersection<\n\t\tOption[\"plugins\"] extends Array<infer T>\n\t\t\t? T extends BetterAuthPlugin\n\t\t\t\t? T extends {\n\t\t\t\t\t\tendpoints: infer E;\n\t\t\t\t\t}\n\t\t\t\t\t? E\n\t\t\t\t\t: {}\n\t\t\t\t: {}\n\t\t\t: {}\n\t>;\n\n\tconst middlewares =\n\t\toptions.plugins\n\t\t\t?.map((plugin) =>\n\t\t\t\tplugin.middlewares?.map((m) => {\n\t\t\t\t\tconst middleware = (async (context: any) => {\n\t\t\t\t\t\treturn m.middleware({\n\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\t\t\t...context.context,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}) as Endpoint;\n\t\t\t\t\tmiddleware.path = m.path;\n\t\t\t\t\tmiddleware.options = m.middleware.options;\n\t\t\t\t\tmiddleware.headers = m.middleware.headers;\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpath: m.path,\n\t\t\t\t\t\tmiddleware,\n\t\t\t\t\t};\n\t\t\t\t}),\n\t\t\t)\n\t\t\t.filter((plugin) => plugin !== undefined)\n\t\t\t.flat() || [];\n\n\tconst baseEndpoints = {\n\t\tsignInOAuth,\n\t\tcallbackOAuth,\n\t\tgetCSRFToken,\n\t\tgetSession: getSession<Option>(),\n\t\tsignOut,\n\t\tsignUpEmail: signUpEmail<Option>(),\n\t\tsignInEmail,\n\t\tforgetPassword,\n\t\tresetPassword,\n\t\tverifyEmail,\n\t\tsendVerificationEmail,\n\t\tchangeEmail,\n\t\tchangePassword,\n\t\tsetPassword,\n\t\tupdateUser: updateUser<Option>(),\n\t\tdeleteUser,\n\t\tforgetPasswordCallback,\n\t\tlistSessions: listSessions<Option>(),\n\t\trevokeSession,\n\t\trevokeSessions,\n\t};\n\tconst endpoints = {\n\t\t...baseEndpoints,\n\t\t...pluginEndpoints,\n\t\tok,\n\t\terror,\n\t};\n\tlet api: Record<string, any> = {};\n\tfor (const [key, value] of Object.entries(endpoints)) {\n\t\tapi[key] = async (context = {} as any) => {\n\t\t\tlet c = await ctx;\n\t\t\tfor (const plugin of options.plugins || []) {\n\t\t\t\tif (plugin.hooks?.before) {\n\t\t\t\t\tfor (const hook of plugin.hooks.before) {\n\t\t\t\t\t\tconst match = hook.matcher({\n\t\t\t\t\t\t\t...value,\n\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\tcontext: c,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tconst hookRes = await hook.handler({\n\t\t\t\t\t\t\t\t...context,\n\t\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\t...context?.context,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (hookRes && \"context\" in hookRes) {\n\t\t\t\t\t\t\t\tc = {\n\t\t\t\t\t\t\t\t\t...c,\n\t\t\t\t\t\t\t\t\t...hookRes.context,\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tlet endpointRes: any;\n\t\t\ttry {\n\t\t\t\t//@ts-ignore\n\t\t\t\tendpointRes = await value({\n\t\t\t\t\t...context,\n\t\t\t\t\tcontext: {\n\t\t\t\t\t\t...c,\n\t\t\t\t\t\t...context.context,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tif (e instanceof APIError) {\n\t\t\t\t\tconst afterPlugins = options.plugins\n\t\t\t\t\t\t?.map((plugin) => {\n\t\t\t\t\t\t\tif (plugin.hooks?.after) {\n\t\t\t\t\t\t\t\treturn plugin.hooks.after;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.filter((plugin) => plugin !== undefined)\n\t\t\t\t\t\t.flat();\n\n\t\t\t\t\tif (!afterPlugins?.length) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\n\t\t\t\t\tlet response = new Response(JSON.stringify(e.body), {\n\t\t\t\t\t\tstatus: statusCode[e.status],\n\t\t\t\t\t\theaders: e.headers,\n\t\t\t\t\t});\n\n\t\t\t\t\tfor (const hook of afterPlugins || []) {\n\t\t\t\t\t\tconst match = hook.matcher(context);\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tconst obj = Object.assign(context, {\n\t\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\t\t\t\treturned: response,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst hookRes = await hook.handler(obj);\n\t\t\t\t\t\t\tif (hookRes && \"response\" in hookRes) {\n\t\t\t\t\t\t\t\tresponse = hookRes.response as any;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn response;\n\t\t\t\t}\n\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\tlet response = endpointRes;\n\t\t\tfor (const plugin of options.plugins || []) {\n\t\t\t\tif (plugin.hooks?.after) {\n\t\t\t\t\tfor (const hook of plugin.hooks.after) {\n\t\t\t\t\t\tconst match = hook.matcher(context);\n\t\t\t\t\t\tif (match) {\n\t\t\t\t\t\t\tconst obj = Object.assign(context, {\n\t\t\t\t\t\t\t\tcontext: {\n\t\t\t\t\t\t\t\t\t...ctx,\n\t\t\t\t\t\t\t\t\treturned: response,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst hookRes = await hook.handler(obj);\n\t\t\t\t\t\t\tif (hookRes && \"response\" in hookRes) {\n\t\t\t\t\t\t\t\tresponse = hookRes.response as any;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn response;\n\t\t};\n\t\tapi[key].path = value.path;\n\t\tapi[key].method = value.method;\n\t\tapi[key].options = value.options;\n\t\tapi[key].headers = value.headers;\n\t}\n\treturn {\n\t\tapi: api as typeof endpoints & PluginEndpoint,\n\t\tmiddlewares,\n\t};\n}\n\nexport const router = <C extends AuthContext, Option extends BetterAuthOptions>(\n\tctx: C,\n\toptions: Option,\n) => {\n\tconst { api, middlewares } = getEndpoints(ctx, options);\n\tconst basePath = new URL(ctx.baseURL).pathname;\n\n\treturn createRouter(api, {\n\t\textraContext: ctx,\n\t\tbasePath,\n\t\trouterMiddleware: [\n\t\t\t{\n\t\t\t\tpath: \"/**\",\n\t\t\t\tmiddleware: csrfMiddleware,\n\t\t\t},\n\t\t\t...middlewares,\n\t\t],\n\t\tasync onRequest(req) {\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onRequest) {\n\t\t\t\t\tconst response = await plugin.onRequest(req, ctx);\n\t\t\t\t\tif (response) {\n\t\t\t\t\t\treturn response;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn onRequestRateLimit(req, ctx);\n\t\t},\n\t\tasync onResponse(res) {\n\t\t\tfor (const plugin of ctx.options.plugins || []) {\n\t\t\t\tif (plugin.onResponse) {\n\t\t\t\t\tconst response = await plugin.onResponse(res, ctx);\n\t\t\t\t\tif (response) {\n\t\t\t\t\t\treturn response.response;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\tonError(e) {\n\t\t\tif (options.onAPIError?.throw) {\n\t\t\t\tthrow e;\n\t\t\t}\n\t\t\tif (options.onAPIError?.onError) {\n\t\t\t\toptions.onAPIError.onError(e, ctx);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst log = options.logger?.verboseLogging ? logger : undefined;\n\t\t\tif (options.logger?.disabled !== true) {\n\t\t\t\tif (e instanceof APIError) {\n\t\t\t\t\tif (e.status === \"INTERNAL_SERVER_ERROR\") {\n\t\t\t\t\t\tlogger.error(e);\n\t\t\t\t\t}\n\t\t\t\t\tlog?.error(e.message);\n\t\t\t\t} else {\n\t\t\t\t\tlogger?.error(e);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t});\n};\n\nexport * from \"./routes\";\nexport * from \"./middlewares\";\nexport * from \"./call\";\nexport { APIError } from \"better-call\";\n","import { APIError } from \"better-call\";\nimport { z } from \"zod\";\nimport { hs256 } from \"../../crypto\";\nimport { createAuthMiddleware } from \"../call\";\n\nexport const csrfMiddleware = createAuthMiddleware(\n\t{\n\t\tbody: z\n\t\t\t.object({\n\t\t\t\tcsrfToken: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t},\n\tasync (ctx) => {\n\t\tif (\n\t\t\tctx.request?.method !== \"POST\" ||\n\t\t\tctx.context.options.advanced?.disableCSRFCheck\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tconst originHeader = ctx.headers?.get(\"origin\") || \"\";\n\t\t/**\n\t\t * If origin is the same as baseURL or if the\n\t\t * origin is in the trustedOrigins then we\n\t\t * don't need to check the CSRF token.\n\t\t */\n\t\tif (originHeader) {\n\t\t\tconst origin = new URL(originHeader).origin;\n\t\t\tif (ctx.context.trustedOrigins.includes(origin)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tconst csrfToken = ctx.body?.csrfToken;\n\t\tif (!csrfToken) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"CSRF Token is required\",\n\t\t\t});\n\t\t}\n\t\tconst csrfCookie = await ctx.getSignedCookie(\n\t\t\tctx.context.authCookies.csrfToken.name,\n\t\t\tctx.context.secret,\n\t\t);\n\t\tconst [token, hash] = csrfCookie?.split(\"!\") || [null, null];\n\t\tif (!csrfToken || !token || !hash || token !== csrfToken) {\n\t\t\tctx.setCookie(ctx.context.authCookies.csrfToken.name, \"\", {\n\t\t\t\tmaxAge: 0,\n\t\t\t});\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid CSRF Token\",\n\t\t\t});\n\t\t}\n\t\tconst expectedHash = await hs256(ctx.context.secret, token);\n\t\tif (hash !== expectedHash) {\n\t\t\tctx.setCookie(ctx.context.authCookies.csrfToken.name, \"\", {\n\t\t\t\tmaxAge: 0,\n\t\t\t});\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid CSRF Token\",\n\t\t\t});\n\t\t}\n\t},\n);\n","import { xchacha20poly1305 } from \"@noble/ciphers/chacha\";\nimport { bytesToHex, hexToBytes, utf8ToBytes } from \"@noble/ciphers/utils\";\nimport { managedNonce } from \"@noble/ciphers/webcrypto\";\nimport { sha256 } from \"oslo/crypto\";\nimport crypto from \"uncrypto\";\n\nexport async function hs256(secretKey: string, message: string) {\n\tconst enc = new TextEncoder();\n\tconst algorithm = { name: \"HMAC\", hash: \"SHA-256\" };\n\tconst key = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tenc.encode(secretKey),\n\t\talgorithm,\n\t\tfalse,\n\t\t[\"sign\", \"verify\"],\n\t);\n\tconst signature = await crypto.subtle.sign(\n\t\talgorithm.name,\n\t\tkey,\n\t\tenc.encode(message),\n\t);\n\treturn btoa(String.fromCharCode(...new Uint8Array(signature)));\n}\n\nexport type SymmetricEncryptOptions = {\n\tkey: string;\n\tdata: string;\n};\n\nexport const symmetricEncrypt = async ({\n\tkey,\n\tdata,\n}: SymmetricEncryptOptions) => {\n\tconst keyAsBytes = await sha256(new TextEncoder().encode(key));\n\tconst dataAsBytes = utf8ToBytes(data);\n\tconst chacha = managedNonce(xchacha20poly1305)(new Uint8Array(keyAsBytes));\n\treturn bytesToHex(chacha.encrypt(dataAsBytes));\n};\n\nexport type SymmetricDecryptOptions = {\n\tkey: string;\n\tdata: string;\n};\n\nexport const symmetricDecrypt = async ({\n\tkey,\n\tdata,\n}: SymmetricDecryptOptions) => {\n\tconst keyAsBytes = await sha256(new TextEncoder().encode(key));\n\tconst dataAsBytes = hexToBytes(data);\n\tconst chacha = managedNonce(xchacha20poly1305)(new Uint8Array(keyAsBytes));\n\treturn new TextDecoder().decode(chacha.decrypt(dataAsBytes));\n};\n\nexport * from \"./buffer\";\nexport * from \"./password\";\nexport * from \"./random\";\nexport * from \"./buffer\";\n","/**\n * Compare two buffers in constant time.\n */\nexport function constantTimeEqual(\n\ta: ArrayBuffer | Uint8Array,\n\tb: ArrayBuffer | Uint8Array,\n): boolean {\n\tconst aBuffer = new Uint8Array(a);\n\tconst bBuffer = new Uint8Array(b);\n\tif (aBuffer.length !== bBuffer.length) {\n\t\treturn false;\n\t}\n\tlet c = 0;\n\tfor (let i = 0; i < aBuffer.length; i++) {\n\t\tc |= aBuffer[i]! ^ bBuffer[i]!; // ^: XOR operator\n\t}\n\treturn c === 0;\n}\n","import { decodeHex, encodeHex } from \"oslo/encoding\";\nimport { constantTimeEqual } from \"./buffer\";\nimport { scryptAsync } from \"@noble/hashes/scrypt\";\nimport { getRandomValues } from \"uncrypto\";\n\nconst config = {\n\tN: 16384,\n\tr: 16,\n\tp: 1,\n\tdkLen: 64,\n};\n\nasync function generateKey(password: string, salt: string) {\n\treturn await scryptAsync(password.normalize(\"NFKC\"), salt, {\n\t\tN: config.N,\n\t\tp: config.p,\n\t\tr: config.r,\n\t\tdkLen: config.dkLen,\n\t\tmaxmem: 128 * config.N * config.r * 2,\n\t});\n}\n\nexport const hashPassword = async (password: string) => {\n\tconst salt = encodeHex(getRandomValues(new Uint8Array(16)));\n\tconst key = await generateKey(password, salt);\n\treturn `${salt}:${encodeHex(key)}`;\n};\n\nexport const verifyPassword = async (hash: string, password: string) => {\n\tconst [salt, key] = hash.split(\":\");\n\tconst targetKey = await generateKey(password, salt!);\n\treturn constantTimeEqual(targetKey, decodeHex(key!));\n};\n","//https://github.com/pilcrowOnPaper/oslo/blob/main/src/crypto/random.ts\nimport crypto from \"uncrypto\";\n\nexport function byteToBinary(byte: number): string {\n\treturn byte.toString(2).padStart(8, \"0\");\n}\n\nexport function bytesToBinary(bytes: Uint8Array): string {\n\treturn [...bytes].map((val) => byteToBinary(val)).join(\"\");\n}\n\nexport function bytesToInteger(bytes: Uint8Array): number {\n\treturn parseInt(bytesToBinary(bytes), 2);\n}\n\nexport function random(): number {\n\tconst buffer = new ArrayBuffer(8);\n\tconst bytes = crypto.getRandomValues(new Uint8Array(buffer));\n\n\t// sets the exponent value (11 bits) to 01111111111 (1023)\n\t// since the bias is 1023 (2 * (11 - 1) - 1), 1023 - 1023 = 0\n\t// 2^0 * (1 + [52 bit number between 0-1]) = number between 1-2\n\tbytes[0] = 63;\n\tbytes[1] = bytes[1]! | 240;\n\n\treturn new DataView(buffer).getFloat64(0) - 1;\n}\n\nexport function generateRandomInteger(max: number): number {\n\tif (max < 0 || !Number.isInteger(max)) {\n\t\tthrow new Error(\n\t\t\t\"Argument 'max' must be an integer greater than or equal to 0\",\n\t\t);\n\t}\n\tconst bitLength = (max - 1).toString(2).length;\n\tconst shift = bitLength % 8;\n\tconst bytes = new Uint8Array(Math.ceil(bitLength / 8));\n\n\tcrypto.getRandomValues(bytes);\n\n\t// This zeroes bits that can be ignored to increase the chance `result` < `max`.\n\t// For example, if `max` can be represented with 10 bits, the leading 6 bits of the random 16 bits (2 bytes) can be ignored.\n\tif (shift !== 0) {\n\t\tbytes[0] &= (1 << shift) - 1;\n\t}\n\tlet result = bytesToInteger(bytes);\n\twhile (result >= max) {\n\t\tcrypto.getRandomValues(bytes);\n\t\tif (shift !== 0) {\n\t\t\tbytes[0] &= (1 << shift) - 1;\n\t\t}\n\t\tresult = bytesToInteger(bytes);\n\t}\n\treturn result;\n}\n\nexport function generateRandomString(length: number, alphabet: string): string {\n\tlet result = \"\";\n\tfor (let i = 0; i < length; i++) {\n\t\tresult += alphabet[generateRandomInteger(alphabet.length)];\n\t}\n\treturn result;\n}\n\ntype AlphabetPattern = \"a-z\" | \"A-Z\" | \"0-9\" | \"-\" | \"_\";\n\nexport function alphabet(...patterns: AlphabetPattern[]): string {\n\tconst patternSet = new Set<AlphabetPattern>(patterns);\n\tlet result = \"\";\n\tfor (const pattern of patternSet) {\n\t\tif (pattern === \"a-z\") {\n\t\t\tresult += \"abcdefghijklmnopqrstuvwxyz\";\n\t\t} else if (pattern === \"A-Z\") {\n\t\t\tresult += \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n\t\t} else if (pattern === \"0-9\") {\n\t\t\tresult += \"0123456789\";\n\t\t} else {\n\t\t\tresult += pattern;\n\t\t}\n\t}\n\treturn result;\n}\n","import {\n\tAPIError,\n\ttype Endpoint,\n\ttype EndpointResponse,\n\tcreateEndpointCreator,\n\tcreateMiddleware,\n\tcreateMiddlewareCreator,\n} from \"better-call\";\nimport type { AuthContext } from \"../init\";\nimport type { BetterAuthOptions } from \"../types/options\";\n\nexport const optionsMiddleware = createMiddleware(async () => {\n\t/**\n\t * This will be passed on the instance of\n\t * the context. Used to infer the type\n\t * here.\n\t */\n\treturn {} as AuthContext;\n});\n\nexport const createAuthMiddleware = createMiddlewareCreator({\n\tuse: [\n\t\toptionsMiddleware,\n\t\t/**\n\t\t * Only use for post hooks\n\t\t */\n\t\tcreateMiddleware(async () => {\n\t\t\treturn {} as {\n\t\t\t\treturned?: Response;\n\t\t\t};\n\t\t}),\n\t],\n});\n\nexport const createAuthEndpoint = createEndpointCreator({\n\tuse: [optionsMiddleware],\n});\n\nexport type AuthEndpoint = Endpoint<\n\t(ctx: {\n\t\toptions: BetterAuthOptions;\n\t\tbody: any;\n\t\tquery: any;\n\t\tparams: any;\n\t\theaders: Headers;\n\t}) => Promise<EndpointResponse>\n>;\n\nexport type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;\n","import { APIError } from \"better-call\";\nimport { generateCodeVerifier } from \"oslo/oauth2\";\nimport { z } from \"zod\";\nimport { generateState } from \"../../oauth2/state\";\nimport { createAuthEndpoint } from \"../call\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { socialProviderList } from \"../../social-providers\";\nimport { createEmailVerificationToken } from \"./email-verification\";\nimport { logger } from \"../../utils\";\n\nexport const signInOAuth = createAuthEndpoint(\n\t\"/sign-in/social\",\n\t{\n\t\tmethod: \"POST\",\n\t\trequireHeaders: true,\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\t/**\n\t\t\t\t * Redirect to the current URL after the\n\t\t\t\t * user has signed in.\n\t\t\t\t */\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * Callback URL to redirect to after the user has signed in.\n\t\t\t */\n\t\t\tcallbackURL: z.string().optional(),\n\t\t\t/**\n\t\t\t * OAuth2 provider to use`\n\t\t\t */\n\t\t\tprovider: z.enum(socialProviderList),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (c) => {\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.body.provider,\n\t\t);\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Provider not found. Make sure to add the provider in your auth config\",\n\t\t\t\t{\n\t\t\t\t\tprovider: c.body.provider,\n\t\t\t\t},\n\t\t\t);\n\t\t\tthrow new APIError(\"NOT_FOUND\", {\n\t\t\t\tmessage: \"Provider not found\",\n\t\t\t});\n\t\t}\n\t\tconst cookie = c.context.authCookies;\n\t\tconst currentURL = c.query?.currentURL\n\t\t\t? new URL(c.query?.currentURL)\n\t\t\t: null;\n\n\t\tconst callbackURL = c.body.callbackURL?.startsWith(\"http\")\n\t\t\t? c.body.callbackURL\n\t\t\t: `${currentURL?.origin}${c.body.callbackURL || \"\"}`;\n\n\t\tconst state = await generateState(\n\t\t\tcallbackURL || currentURL?.origin || c.context.options.baseURL,\n\t\t);\n\t\tawait c.setSignedCookie(\n\t\t\tcookie.state.name,\n\t\t\tstate.hash,\n\t\t\tc.context.secret,\n\t\t\tcookie.state.options,\n\t\t);\n\t\tconst codeVerifier = generateCodeVerifier();\n\t\tawait c.setSignedCookie(\n\t\t\tcookie.pkCodeVerifier.name,\n\t\t\tcodeVerifier,\n\t\t\tc.context.secret,\n\t\t\tcookie.pkCodeVerifier.options,\n\t\t);\n\t\tconst url = await provider.createAuthorizationURL({\n\t\t\tstate: state.raw,\n\t\t\tcodeVerifier,\n\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t});\n\t\treturn c.json({\n\t\t\turl: url.toString(),\n\t\t\tstate: state,\n\t\t\tcodeVerifier,\n\t\t\tredirect: true,\n\t\t});\n\t},\n);\n\nexport const signInEmail = createAuthEndpoint(\n\t\"/sign-in/email\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\temail: z.string(),\n\t\t\tpassword: z.string(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t\t/**\n\t\t\t * If this is true the session will only be valid for the current browser session\n\t\t\t * @default false\n\t\t\t */\n\t\t\tdontRememberMe: z.boolean().default(false).optional(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options?.emailAndPassword?.enabled) {\n\t\t\tctx.context.logger.error(\n\t\t\t\t\"Email and password is not enabled. Make sure to enable it in the options on you `auth.ts` file. Check `https://better-auth.com/docs/authentication/email-password` for more!\",\n\t\t\t);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Email and password is not enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email, password } = ctx.body;\n\t\tconst isValidEmail = z.string().email().safeParse(email);\n\t\tif (!isValidEmail.success) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid email\",\n\t\t\t});\n\t\t}\n\t\tconst checkEmail = z.string().email().safeParse(email);\n\t\tif (!checkEmail.success) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid email\",\n\t\t\t});\n\t\t}\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\tincludeAccounts: true,\n\t\t});\n\n\t\tif (!user) {\n\t\t\tawait ctx.context.password.hash(password);\n\t\t\tctx.context.logger.error(\"User not found\", { email });\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid email or password\",\n\t\t\t});\n\t\t}\n\n\t\tconst credentialAccount = user.accounts.find(\n\t\t\t(a) => a.providerId === \"credential\",\n\t\t);\n\t\tif (!credentialAccount) {\n\t\t\tctx.context.logger.error(\"Credential account not found\", { email });\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid email or password\",\n\t\t\t});\n\t\t}\n\t\tconst currentPassword = credentialAccount?.password;\n\t\tif (!currentPassword) {\n\t\t\tctx.context.logger.error(\"Password not found\", { email });\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Unexpected error\",\n\t\t\t});\n\t\t}\n\t\tconst validPassword = await ctx.context.password.verify(\n\t\t\tcurrentPassword,\n\t\t\tpassword,\n\t\t);\n\t\tif (!validPassword) {\n\t\t\tctx.context.logger.error(\"Invalid password\");\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Invalid email or password\",\n\t\t\t});\n\t\t}\n\n\t\tif (\n\t\t\tctx.context.options?.emailAndPassword?.requireEmailVerification &&\n\t\t\t!user.user.emailVerified\n\t\t) {\n\t\t\tif (!ctx.context.options?.emailVerification?.sendVerificationEmail) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Email verification is required but no email verification handler is provided\",\n\t\t\t\t);\n\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\tmessage: \"Email is not verified.\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\tctx.context.secret,\n\t\t\t\tuser.user.email,\n\t\t\t);\n\t\t\tconst url = `${ctx.context.options.baseURL}/verify-email?token=${token}`;\n\t\t\tawait ctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\t\tuser.user,\n\t\t\t\turl,\n\t\t\t\ttoken,\n\t\t\t);\n\t\t\tctx.context.logger.error(\"Email not verified\", { email });\n\t\t\tthrow new APIError(\"FORBIDDEN\", {\n\t\t\t\tmessage:\n\t\t\t\t\t\"Email is not verified. Check your email for a verification link\",\n\t\t\t});\n\t\t}\n\n\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\tuser.user.id,\n\t\t\tctx.headers,\n\t\t\tctx.body.dontRememberMe,\n\t\t);\n\n\t\tif (!session) {\n\t\t\tctx.context.logger.error(\"Failed to create session\");\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: \"Failed to create session\",\n\t\t\t});\n\t\t}\n\n\t\tawait setSessionCookie(ctx, session.id, ctx.body.dontRememberMe);\n\t\treturn ctx.json({\n\t\t\tuser: user.user,\n\t\t\tsession,\n\t\t\tredirect: !!ctx.body.callbackURL,\n\t\t\turl: ctx.body.callbackURL,\n\t\t});\n\t},\n);\n","import { generateState as generateStateOAuth } from \"oslo/oauth2\";\nimport { z } from \"zod\";\nimport { hashToBase64 } from \"../crypto/hash\";\nimport { APIError } from \"better-call\";\n\nexport async function generateState(callbackURL?: string) {\n\tconst code = generateStateOAuth();\n\tconst raw = JSON.stringify({\n\t\tcode,\n\t\tcallbackURL,\n\t});\n\tconst hash = await hashToBase64(raw);\n\treturn { raw, hash };\n}\n\nexport function parseState(state: string) {\n\tconst data = z\n\t\t.object({\n\t\t\tcode: z.string(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t\tcurrentURL: z.string().optional(),\n\t\t})\n\t\t.safeParse(JSON.parse(state));\n\treturn data;\n}\n","import { sha256 } from \"oslo/crypto\";\nimport { constantTimeEqual } from \"./buffer\";\n\nexport async function hashToBase64(\n\tdata: string | ArrayBuffer,\n): Promise<string> {\n\tconst buffer = await sha256(\n\t\ttypeof data === \"string\" ? new TextEncoder().encode(data) : data,\n\t);\n\treturn Buffer.from(buffer).toString(\"base64\");\n}\n\nexport async function compareHash(\n\tdata: string | ArrayBuffer,\n\thash: string,\n): Promise<boolean> {\n\tconst buffer = await sha256(\n\t\ttypeof data === \"string\" ? new TextEncoder().encode(data) : data,\n\t);\n\tconst hashBuffer = Buffer.from(hash, \"base64\");\n\treturn constantTimeEqual(buffer, hashBuffer);\n}\n","import type { CookieOptions } from \"better-call\";\nimport { TimeSpan } from \"oslo\";\nimport type { BetterAuthOptions } from \"../types/options\";\nimport type { GenericEndpointContext } from \"../types/context\";\nimport { BetterAuthError } from \"../error\";\nimport { env, isProduction } from \"std-env\";\n\nexport function getCookies(options: BetterAuthOptions) {\n\tconst secure =\n\t\toptions.advanced?.useSecureCookies !== undefined\n\t\t\t? options.advanced?.useSecureCookies\n\t\t\t: options.baseURL !== undefined\n\t\t\t\t? options.baseURL.startsWith(\"https://\")\n\t\t\t\t\t? true\n\t\t\t\t\t: false\n\t\t\t\t: isProduction;\n\n\tconst secureCookiePrefix = secure ? \"__Secure-\" : \"\";\n\tconst cookiePrefix = \"better-auth\";\n\tconst sessionMaxAge =\n\t\toptions.session?.expiresIn || new TimeSpan(7, \"d\").seconds();\n\tconst crossSubdomainEnabled =\n\t\t!!options.advanced?.crossSubDomainCookies?.enabled;\n\n\tconst domain = crossSubdomainEnabled\n\t\t? options.advanced?.crossSubDomainCookies?.domain ||\n\t\t\t(options.baseURL ? new URL(options.baseURL).hostname : undefined)\n\t\t: undefined;\n\n\tif (crossSubdomainEnabled && !domain) {\n\t\tthrow new BetterAuthError(\n\t\t\t\"baseURL is required when crossSubdomainCookies are enabled\",\n\t\t);\n\t}\n\n\tconst sameSite = crossSubdomainEnabled ? \"none\" : \"lax\";\n\treturn {\n\t\tsessionToken: {\n\t\t\tname: `${secureCookiePrefix}${cookiePrefix}.session_token`,\n\t\t\toptions: {\n\t\t\t\thttpOnly: true,\n\t\t\t\tsameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsecure: !!secureCookiePrefix,\n\t\t\t\tmaxAge: sessionMaxAge,\n\t\t\t\t...(crossSubdomainEnabled ? { domain } : {}),\n\t\t\t} satisfies CookieOptions,\n\t\t},\n\t\tcsrfToken: {\n\t\t\tname: `${secureCookiePrefix}${cookiePrefix}.csrf_token`,\n\t\t\toptions: {\n\t\t\t\thttpOnly: true,\n\t\t\t\tsameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsecure: !!secureCookiePrefix,\n\t\t\t\tmaxAge: 60 * 60 * 24 * 7,\n\t\t\t\t...(crossSubdomainEnabled ? { domain } : {}),\n\t\t\t} satisfies CookieOptions,\n\t\t},\n\t\tstate: {\n\t\t\tname: `${secureCookiePrefix}${cookiePrefix}.state`,\n\t\t\toptions: {\n\t\t\t\thttpOnly: true,\n\t\t\t\tsameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsecure: !!secureCookiePrefix,\n\t\t\t\tmaxAge: 60 * 15,\n\t\t\t\t...(crossSubdomainEnabled ? { domain } : {}),\n\t\t\t} satisfies CookieOptions,\n\t\t},\n\t\tpkCodeVerifier: {\n\t\t\tname: `${secureCookiePrefix}${cookiePrefix}.pk_code_verifier`,\n\t\t\toptions: {\n\t\t\t\thttpOnly: true,\n\t\t\t\tsameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsecure: !!secureCookiePrefix,\n\t\t\t\tmaxAge: 60 * 15,\n\t\t\t\t...(crossSubdomainEnabled ? { domain } : {}),\n\t\t\t} as CookieOptions,\n\t\t},\n\t\tdontRememberToken: {\n\t\t\tname: `${secureCookiePrefix}${cookiePrefix}.dont_remember`,\n\t\t\toptions: {\n\t\t\t\thttpOnly: true,\n\t\t\t\tsameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsecure: !!secureCookiePrefix,\n\t\t\t\t//no max age so it expires when the browser closes\n\t\t\t\t...(crossSubdomainEnabled ? { domain } : {}),\n\t\t\t} as CookieOptions,\n\t\t},\n\t\tnonce: {\n\t\t\tname: `${secureCookiePrefix}${cookiePrefix}.nonce`,\n\t\t\toptions: {\n\t\t\t\thttpOnly: true,\n\t\t\t\tsameSite,\n\t\t\t\tpath: \"/\",\n\t\t\t\tsecure: !!secureCookiePrefix,\n\t\t\t\tmaxAge: 60 * 15,\n\t\t\t\t...(crossSubdomainEnabled ? { domain } : {}),\n\t\t\t} as CookieOptions,\n\t\t},\n\t};\n}\n\nexport function createCookieGetter(options: BetterAuthOptions) {\n\tconst secure =\n\t\toptions.advanced?.useSecureCookies !== undefined\n\t\t\t? options.advanced?.useSecureCookies\n\t\t\t: options.baseURL?.startsWith(\"https://\") || isProduction;\n\tconst secureCookiePrefix = secure ? \"__Secure-\" : \"\";\n\tconst cookiePrefix = \"better-auth\";\n\n\tconst domain =\n\t\toptions.advanced?.crossSubDomainCookies?.domain ||\n\t\t(options.baseURL ? new URL(options.baseURL).hostname : undefined);\n\n\tfunction getCookie(cookieName: string, opts?: CookieOptions) {\n\t\tconst crossSubdomainEnabled = options.advanced?.crossSubDomainCookies\n\t\t\t?.enabled\n\t\t\t? options.advanced.crossSubDomainCookies.additionalCookies?.includes(\n\t\t\t\t\tcookieName,\n\t\t\t\t)\n\t\t\t: undefined;\n\t\treturn {\n\t\t\tname:\n\t\t\t\tenv.NODE_ENV === \"production\"\n\t\t\t\t\t? `${secureCookiePrefix}${cookiePrefix}.${cookieName}`\n\t\t\t\t\t: `${cookiePrefix}.${cookieName}`,\n\t\t\toptions: {\n\t\t\t\tsecure: !!secureCookiePrefix,\n\t\t\t\tsameSite: \"lax\",\n\t\t\t\tpath: \"/\",\n\t\t\t\tmaxAge: 60 * 15, // 15 minutes in seconds\n\t\t\t\t...opts,\n\t\t\t\t...(crossSubdomainEnabled ? { domain } : {}),\n\t\t\t} as CookieOptions,\n\t\t};\n\t}\n\treturn getCookie;\n}\nexport type BetterAuthCookies = ReturnType<typeof getCookies>;\n\nexport async function setSessionCookie(\n\tctx: GenericEndpointContext,\n\tsessionToken: string,\n\tdontRememberMe?: boolean,\n\toverrides?: Partial<CookieOptions>,\n) {\n\tconst options = ctx.context.authCookies.sessionToken.options;\n\t//@ts-expect-error\n\toptions.maxAge = dontRememberMe\n\t\t? undefined\n\t\t: ctx.context.sessionConfig.expiresIn;\n\n\tawait ctx.setSignedCookie(\n\t\tctx.context.authCookies.sessionToken.name,\n\t\tsessionToken,\n\t\tctx.context.secret,\n\t\t{\n\t\t\t...options,\n\t\t\t...overrides,\n\t\t},\n\t);\n\tif (dontRememberMe) {\n\t\tawait ctx.setSignedCookie(\n\t\t\tctx.context.authCookies.dontRememberToken.name,\n\t\t\t\"true\",\n\t\t\tctx.context.secret,\n\t\t\tctx.context.authCookies.dontRememberToken.options,\n\t\t);\n\t}\n}\n\nexport function deleteSessionCookie(ctx: GenericEndpointContext) {\n\tctx.setCookie(ctx.context.authCookies.sessionToken.name, \"\", {\n\t\tmaxAge: 0,\n\t});\n\tctx.setCookie(ctx.context.authCookies.dontRememberToken.name, \"\", {\n\t\tmaxAge: 0,\n\t});\n}\n\ntype CookieAttributes = {\n\tvalue: string;\n\t[key: string]: string | boolean;\n};\n\nexport function parseSetCookieHeader(\n\theader: string,\n): Map<string, CookieAttributes> {\n\tconst cookieMap = new Map<string, CookieAttributes>();\n\n\t// Split the header into individual cookies\n\tconst cookies = header.split(\", \");\n\n\tcookies.forEach((cookie) => {\n\t\tconst [nameValue, ...attributes] = cookie.split(\"; \");\n\t\tconst [name, value] = nameValue.split(\"=\");\n\n\t\tconst cookieObj: CookieAttributes = { value };\n\n\t\tattributes.forEach((attr) => {\n\t\t\tconst [attrName, attrValue] = attr.split(\"=\");\n\t\t\tcookieObj[attrName.toLowerCase()] = attrValue || true;\n\t\t});\n\n\t\tcookieMap.set(name, cookieObj);\n\t});\n\n\treturn cookieMap;\n}\nexport function parseCookies(cookieHeader: string) {\n\tconst cookies = cookieHeader.split(\"; \");\n\tconst cookieMap = new Map<string, string>();\n\n\tcookies.forEach((cookie) => {\n\t\tconst [name, value] = cookie.split(\"=\");\n\t\tcookieMap.set(name, value);\n\t});\n\treturn cookieMap;\n}\n\nexport type EligibleCookies = (string & {}) | (keyof BetterAuthCookies & {});\n","export class BetterAuthError extends Error {\n\tconstructor(message: string, cause?: string) {\n\t\tsuper(message);\n\t\tthis.name = \"BetterAuthError\";\n\t\tthis.message = message;\n\t\tthis.cause = cause;\n\t}\n}\nexport class MissingDependencyError extends BetterAuthError {\n\tconstructor(pkgName: string) {\n\t\tsuper(\n\t\t\t`The package \"${pkgName}\" is required. Make sure it is installed.`,\n\t\t\tpkgName,\n\t\t);\n\t}\n}\n","import { APIError } from \"better-call\";\nimport { createAuthMiddleware } from \"../call\";\nimport { logger } from \"../../utils/logger\";\n\n/**\n * Middleware to validate callbackURL and currentURL against trustedOrigins,\n * preventing open redirect attacks.\n */\nexport const redirectURLMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst { body, query, headers, context } = ctx;\n\n\tconst callbackURL =\n\t\tbody?.callbackURL ||\n\t\tquery?.callbackURL ||\n\t\tquery?.redirectTo ||\n\t\tbody?.redirectTo;\n\tconst currentURL =\n\t\tquery?.currentURL || headers?.get(\"referer\") || context.baseURL;\n\tconst trustedOrigins = context.trustedOrigins;\n\n\tconst validateURL = (url: string | undefined, label: string) => {\n\t\tif (url?.startsWith(\"http\")) {\n\t\t\tconst isTrustedOrigin = trustedOrigins.some((origin) =>\n\t\t\t\turl.startsWith(origin),\n\t\t\t);\n\t\t\tif (!isTrustedOrigin) {\n\t\t\t\tlogger.error(`Invalid ${label}`, { [label]: url, trustedOrigins });\n\t\t\t\tthrow new APIError(\"FORBIDDEN\", { message: `Invalid ${label}` });\n\t\t\t}\n\t\t}\n\t};\n\n\tvalidateURL(callbackURL, \"callbackURL\");\n\tvalidateURL(currentURL, \"currentURL\");\n});\n","import { createConsola } from \"consola\";\n\nconst consola = createConsola({\n\tformatOptions: {\n\t\tdate: false,\n\t\tcolors: true,\n\t\tcompact: true,\n\t},\n\tdefaults: {\n\t\ttag: \"Better Auth\",\n\t},\n});\n\nexport const createLogger = (options?: {\n\tdisabled?: boolean;\n}) => {\n\treturn {\n\t\tlog: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.log(\"\", ...args);\n\t\t},\n\t\terror: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.error(\"\", ...args);\n\t\t},\n\t\twarn: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.warn(\"\", ...args);\n\t\t},\n\t\tinfo: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.info(\"\", ...args);\n\t\t},\n\t\tdebug: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.debug(\"\", ...args);\n\t\t},\n\t\tbox: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.box(\"\", ...args);\n\t\t},\n\t\tsuccess: (...args: any[]) => {\n\t\t\t!options?.disabled && consola.success(\"\", ...args);\n\t\t},\n\t\tbreak: (...args: any[]) => {\n\t\t\t!options?.disabled && console.log(\"\\n\");\n\t\t},\n\t};\n};\n\nexport const logger = createLogger();\n","import type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { parseJWT } from \"oslo/jwt\";\nimport { validateAuthorizationCode } from \"../oauth2\";\nexport interface AppleProfile {\n\t/**\n\t * The subject registered claim identifies the principal that’s the subject\n\t * of the identity token. Because this token is for your app, the value is\n\t * the unique identifier for the user.\n\t */\n\tsub: string;\n\t/**\n\t * A String value representing the user's email address.\n\t * The email address is either the user's real email address or the proxy\n\t * address, depending on their status private email relay service.\n\t */\n\temail: string;\n\t/**\n\t * A string or Boolean value that indicates whether the service verifies\n\t * the email. The value can either be a string (\"true\" or \"false\") or a\n\t * Boolean (true or false). The system may not verify email addresses for\n\t * Sign in with Apple at Work & School users, and this claim is \"false\" or\n\t * false for those users.\n\t */\n\temail_verified: true | \"true\";\n\t/**\n\t * A string or Boolean value that indicates whether the email that the user\n\t * shares is the proxy address. The value can either be a string (\"true\" or\n\t * \"false\") or a Boolean (true or false).\n\t */\n\tis_private_email: boolean;\n\t/**\n\t * An Integer value that indicates whether the user appears to be a real\n\t * person. Use the value of this claim to mitigate fraud. The possible\n\t * values are: 0 (or Unsupported), 1 (or Unknown), 2 (or LikelyReal). For\n\t * more information, see ASUserDetectionStatus. This claim is present only\n\t * in iOS 14 and later, macOS 11 and later, watchOS 7 and later, tvOS 14\n\t * and later. The claim isn’t present or supported for web-based apps.\n\t */\n\treal_user_status: number;\n\t/**\n\t * The user’s full name in the format provided during the authorization\n\t * process.\n\t */\n\tname: string;\n}\n\nexport interface AppleOptions extends ProviderOptions {}\n\nexport const apple = (options: AppleOptions) => {\n\tconst tokenEndpoint = \"https://appleid.apple.com/auth/token\";\n\treturn {\n\t\tid: \"apple\",\n\t\tname: \"Apple\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scope = options.scope || scopes || [\"email\", \"name\", \"openid\"];\n\t\t\treturn new URL(\n\t\t\t\t`https://appleid.apple.com/auth/authorize?client_id=${\n\t\t\t\t\toptions.clientId\n\t\t\t\t}&response_type=code&redirect_uri=${\n\t\t\t\t\tredirectURI || options.redirectURI\n\t\t\t\t}&scope=${_scope.join(\" \")}&state=${state}`,\n\t\t\t);\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst data = parseJWT(token.idToken)?.payload as AppleProfile | null;\n\t\t\tif (!data) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: data.sub,\n\t\t\t\t\tname: data.name,\n\t\t\t\t\temail: data.email,\n\t\t\t\t\temailVerified: data.email_verified === \"true\",\n\t\t\t\t},\n\t\t\t\tdata,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<AppleProfile>;\n};\n","import { sha256 } from \"oslo/crypto\";\nimport { base64url } from \"oslo/encoding\";\nimport type { OAuth2Tokens } from \"./types\";\n\nexport async function generateCodeChallenge(codeVerifier: string) {\n\tconst codeChallengeBytes = await sha256(\n\t\tnew TextEncoder().encode(codeVerifier),\n\t);\n\treturn base64url.encode(new Uint8Array(codeChallengeBytes), {\n\t\tincludePadding: false,\n\t});\n}\n\nexport function getOAuth2Tokens(data: Record<string, any>): OAuth2Tokens {\n\treturn {\n\t\ttokenType: data.token_type,\n\t\taccessToken: data.access_token,\n\t\trefreshToken: data.refresh_token,\n\t\taccessTokenExpiresAt: data.expires_at\n\t\t\t? new Date((Date.now() + data.expires_in) * 1000)\n\t\t\t: undefined,\n\t\tscopes: data?.scope\n\t\t\t? typeof data.scope === \"string\"\n\t\t\t\t? data.scope.split(\" \")\n\t\t\t\t: data.scope\n\t\t\t: [],\n\t\tidToken: data.id_token,\n\t};\n}\n","import type { ProviderOptions } from \"./types\";\nimport { generateCodeChallenge } from \"./utils\";\n\nexport async function createAuthorizationURL({\n\tid,\n\toptions,\n\tauthorizationEndpoint,\n\tstate,\n\tcodeVerifier,\n\tscopes,\n\tclaims,\n\tdisablePkce,\n\tredirectURI,\n}: {\n\tid: string;\n\toptions: ProviderOptions;\n\tredirectURI: string;\n\tauthorizationEndpoint: string;\n\tstate: string;\n\tcodeVerifier?: string;\n\tscopes: string[];\n\tdisablePkce?: boolean;\n\tclaims?: string[];\n}) {\n\tconst url = new URL(authorizationEndpoint);\n\turl.searchParams.set(\"response_type\", \"code\");\n\turl.searchParams.set(\"client_id\", options.clientId);\n\turl.searchParams.set(\"state\", state);\n\turl.searchParams.set(\"scope\", scopes.join(\" \"));\n\turl.searchParams.set(\"redirect_uri\", options.redirectURI || redirectURI);\n\n\tif (!disablePkce && codeVerifier) {\n\t\tconst codeChallenge = await generateCodeChallenge(codeVerifier);\n\t\turl.searchParams.set(\"code_challenge_method\", \"S256\");\n\t\turl.searchParams.set(\"code_challenge\", codeChallenge);\n\t}\n\tif (claims) {\n\t\tconst claimsObj = claims.reduce(\n\t\t\t(acc, claim) => {\n\t\t\t\tacc[claim] = null;\n\t\t\t\treturn acc;\n\t\t\t},\n\t\t\t{} as Record<string, null>,\n\t\t);\n\t\turl.searchParams.set(\n\t\t\t\"claims\",\n\t\t\tJSON.stringify({\n\t\t\t\tid_token: { email: null, email_verified: null, ...claimsObj },\n\t\t\t}),\n\t\t);\n\t}\n\treturn url;\n}\n","import { betterFetch } from \"@better-fetch/fetch\";\nimport type { ProviderOptions } from \"./types\";\nimport { getOAuth2Tokens } from \"./utils\";\n\nexport async function validateAuthorizationCode({\n\tcode,\n\tcodeVerifier,\n\tredirectURI,\n\toptions,\n\ttokenEndpoint,\n}: {\n\tcode: string;\n\tredirectURI: string;\n\toptions: ProviderOptions;\n\tcodeVerifier?: string;\n\ttokenEndpoint: string;\n}) {\n\tconst body = new URLSearchParams();\n\tbody.set(\"grant_type\", \"authorization_code\");\n\tbody.set(\"code\", code);\n\tcodeVerifier && body.set(\"code_verifier\", codeVerifier);\n\tbody.set(\"redirect_uri\", redirectURI);\n\tbody.set(\"client_id\", options.clientId);\n\tbody.set(\"client_secret\", options.clientSecret);\n\tconst { data, error } = await betterFetch<object>(tokenEndpoint, {\n\t\tmethod: \"POST\",\n\t\tbody: body,\n\t\theaders: {\n\t\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\t\taccept: \"application/json\",\n\t\t\t\"user-agent\": \"better-auth\",\n\t\t},\n\t});\n\tif (error) {\n\t\tthrow error;\n\t}\n\tconst tokens = getOAuth2Tokens(data);\n\treturn tokens;\n}\n","import type { OAuth2Tokens } from \".\";\n\nexport function getAccountTokens(tokens: OAuth2Tokens) {\n\tconst accessToken = tokens.accessToken;\n\tlet refreshToken = tokens.refreshToken;\n\tlet accessTokenExpiresAt = undefined;\n\ttry {\n\t\taccessTokenExpiresAt = tokens.accessTokenExpiresAt;\n\t} catch {}\n\treturn {\n\t\taccessToken,\n\t\trefreshToken,\n\t\texpiresAt: accessTokenExpiresAt,\n\t};\n}\n","import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { validateAuthorizationCode } from \"../oauth2\";\n\nexport interface DiscordProfile extends Record<string, any> {\n\t/** the user's id (i.e. the numerical snowflake) */\n\tid: string;\n\t/** the user's username, not unique across the platform */\n\tusername: string;\n\t/** the user's Discord-tag */\n\tdiscriminator: string;\n\t/** the user's display name, if it is set */\n\tglobal_name: string | null;\n\t/**\n\t * the user's avatar hash:\n\t * https://discord.com/developers/docs/reference#image-formatting\n\t */\n\tavatar: string | null;\n\t/** whether the user belongs to an OAuth2 application */\n\tbot?: boolean;\n\t/**\n\t * whether the user is an Official Discord System user (part of the urgent\n\t * message system)\n\t */\n\tsystem?: boolean;\n\t/** whether the user has two factor enabled on their account */\n\tmfa_enabled: boolean;\n\t/**\n\t * the user's banner hash:\n\t * https://discord.com/developers/docs/reference#image-formatting\n\t */\n\tbanner: string | null;\n\n\t/** the user's banner color encoded as an integer representation of hexadecimal color code */\n\taccent_color: number | null;\n\n\t/**\n\t * the user's chosen language option:\n\t * https://discord.com/developers/docs/reference#locales\n\t */\n\tlocale: string;\n\t/** whether the email on this account has been verified */\n\tverified: boolean;\n\t/** the user's email */\n\temail: string;\n\t/**\n\t * the flags on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-user-flags\n\t */\n\tflags: number;\n\t/**\n\t * the type of Nitro subscription on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-premium-types\n\t */\n\tpremium_type: number;\n\t/**\n\t * the public flags on a user's account:\n\t * https://discord.com/developers/docs/resources/user#user-object-user-flags\n\t */\n\tpublic_flags: number;\n\t/** undocumented field; corresponds to the user's custom nickname */\n\tdisplay_name: string | null;\n\t/**\n\t * undocumented field; corresponds to the Discord feature where you can e.g.\n\t * put your avatar inside of an ice cube\n\t */\n\tavatar_decoration: string | null;\n\t/**\n\t * undocumented field; corresponds to the premium feature where you can\n\t * select a custom banner color\n\t */\n\tbanner_color: string | null;\n\t/** undocumented field; the CDN URL of their profile picture */\n\timage_url: string;\n}\n\nexport interface DiscordOptions extends ProviderOptions {}\n\nexport const discord = (options: DiscordOptions) => {\n\treturn {\n\t\tid: \"discord\",\n\t\tname: \"Discord\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.scope || scopes || [\"identify\", \"email\"];\n\t\t\treturn new URL(\n\t\t\t\t`https://discord.com/api/oauth2/authorize?scope=${_scopes.join(\n\t\t\t\t\t\"+\",\n\t\t\t\t)}&response_type=code&client_id=${\n\t\t\t\t\toptions.clientId\n\t\t\t\t}&redirect_uri=${encodeURIComponent(\n\t\t\t\t\toptions.redirectURI || redirectURI,\n\t\t\t\t)}&state=${state}`,\n\t\t\t);\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://discord.com/api/oauth2/token\",\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tconst { data: profile, error } = await betterFetch<DiscordProfile>(\n\t\t\t\t\"https://discord.com/api/users/@me\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (profile.avatar === null) {\n\t\t\t\tconst defaultAvatarNumber =\n\t\t\t\t\tprofile.discriminator === \"0\"\n\t\t\t\t\t\t? Number(BigInt(profile.id) >> BigInt(22)) % 6\n\t\t\t\t\t\t: parseInt(profile.discriminator) % 5;\n\t\t\t\tprofile.image_url = `https://cdn.discordapp.com/embed/avatars/${defaultAvatarNumber}.png`;\n\t\t\t} else {\n\t\t\t\tconst format = profile.avatar.startsWith(\"a_\") ? \"gif\" : \"png\";\n\t\t\t\tprofile.image_url = `https://cdn.discordapp.com/avatars/${profile.id}/${profile.avatar}.${format}`;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.display_name || profile.username || \"\",\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\temailVerified: profile.verified,\n\t\t\t\t\timage: profile.image_url,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<DiscordProfile>;\n};\n","import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { createAuthorizationURL, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface FacebookProfile {\n\tid: string;\n\tname: string;\n\temail: string;\n\temail_verified: boolean;\n\tpicture: {\n\t\tdata: {\n\t\t\theight: number;\n\t\t\tis_silhouette: boolean;\n\t\t\turl: string;\n\t\t\twidth: number;\n\t\t};\n\t};\n}\nexport interface FacebookOptions extends ProviderOptions {}\nexport const facebook = (options: FacebookOptions) => {\n\treturn {\n\t\tid: \"facebook\",\n\t\tname: \"Facebook\",\n\t\tasync createAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.scope || scopes || [\"email\", \"public_profile\"];\n\t\t\treturn await createAuthorizationURL({\n\t\t\t\tid: \"facebook\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://www.facebook.com/v21.0/dialog/oauth\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://graph.facebook.com/oauth/access_token\",\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tconst { data: profile, error } = await betterFetch<FacebookProfile>(\n\t\t\t\t\"https://graph.facebook.com/me?fields=id,name,email,picture\",\n\t\t\t\t{\n\t\t\t\t\tauth: {\n\t\t\t\t\t\ttype: \"Bearer\",\n\t\t\t\t\t\ttoken: token.accessToken,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.picture.data.url,\n\t\t\t\t\temailVerified: profile.email_verified,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<FacebookProfile>;\n};\n","import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { createAuthorizationURL, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface GithubProfile {\n\tlogin: string;\n\tid: string;\n\tnode_id: string;\n\tavatar_url: string;\n\tgravatar_id: string;\n\turl: string;\n\thtml_url: string;\n\tfollowers_url: string;\n\tfollowing_url: string;\n\tgists_url: string;\n\tstarred_url: string;\n\tsubscriptions_url: string;\n\torganizations_url: string;\n\trepos_url: string;\n\tevents_url: string;\n\treceived_events_url: string;\n\ttype: string;\n\tsite_admin: boolean;\n\tname: string;\n\tcompany: string;\n\tblog: string;\n\tlocation: string;\n\temail: string;\n\thireable: boolean;\n\tbio: string;\n\ttwitter_username: string;\n\tpublic_repos: string;\n\tpublic_gists: string;\n\tfollowers: string;\n\tfollowing: string;\n\tcreated_at: string;\n\tupdated_at: string;\n\tprivate_gists: string;\n\ttotal_private_repos: string;\n\towned_private_repos: string;\n\tdisk_usage: string;\n\tcollaborators: string;\n\ttwo_factor_authentication: boolean;\n\tplan: {\n\t\tname: string;\n\t\tspace: string;\n\t\tprivate_repos: string;\n\t\tcollaborators: string;\n\t};\n\tfirst_name: string;\n\tlast_name: string;\n}\n\nexport interface GithubOptions extends ProviderOptions {}\nexport const github = (options: GithubOptions) => {\n\tconst tokenEndpoint = \"https://github.com/login/oauth/access_token\";\n\treturn {\n\t\tid: \"github\",\n\t\tname: \"Github\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.scope || scopes || [\"user:email\"];\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"github\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://github.com/login/oauth/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tredirectURI,\n\t\t\t\tcodeVerifier,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tconst { data: profile, error } = await betterFetch<GithubProfile>(\n\t\t\t\t\"https://api.github.com/user\",\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"User-Agent\": \"better-auth\",\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tlet emailVerified = false;\n\t\t\tif (!profile.email) {\n\t\t\t\tconst { data, error } = await betterFetch<\n\t\t\t\t\t{\n\t\t\t\t\t\temail: string;\n\t\t\t\t\t\tprimary: boolean;\n\t\t\t\t\t\tverified: boolean;\n\t\t\t\t\t\tvisibility: \"public\" | \"private\";\n\t\t\t\t\t}[]\n\t\t\t\t>(\"https://api.github.com/user/emails\", {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tauthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t\t\"User-Agent\": \"better-auth\",\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tif (!error) {\n\t\t\t\t\tprofile.email = (data.find((e) => e.primary) ?? data[0])\n\t\t\t\t\t\t?.email as string;\n\t\t\t\t\temailVerified =\n\t\t\t\t\t\tdata.find((e) => e.email === profile.email)?.verified ?? false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id.toString(),\n\t\t\t\t\tname: profile.name || profile.login,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.avatar_url,\n\t\t\t\t\temailVerified,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<GithubProfile>;\n};\n","import { parseJWT } from \"oslo/jwt\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { BetterAuthError } from \"../error\";\nimport { logger } from \"../utils/logger\";\nimport { createAuthorizationURL, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface GoogleProfile {\n\taud: string;\n\tazp: string;\n\temail: string;\n\temail_verified: boolean;\n\texp: number;\n\t/**\n\t * The family name of the user, or last name in most\n\t * Western languages.\n\t */\n\tfamily_name: string;\n\t/**\n\t * The given name of the user, or first name in most\n\t * Western languages.\n\t */\n\tgiven_name: string;\n\thd?: string;\n\tiat: number;\n\tiss: string;\n\tjti?: string;\n\tlocale?: string;\n\tname: string;\n\tnbf?: number;\n\tpicture: string;\n\tsub: string;\n}\n\nexport interface GoogleOptions extends ProviderOptions {}\n\nexport const google = (options: GoogleOptions) => {\n\treturn {\n\t\tid: \"google\",\n\t\tname: \"Google\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tif (!options.clientId || !options.clientSecret) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Client Id and Client Secret is required for Google. Make sure to provide them in the options.\",\n\t\t\t\t);\n\t\t\t\tthrow new BetterAuthError(\"CLIENT_ID_AND_SECRET_REQUIRED\");\n\t\t\t}\n\t\t\tif (!codeVerifier) {\n\t\t\t\tthrow new BetterAuthError(\"codeVerifier is required for Google\");\n\t\t\t}\n\t\t\tconst _scopes = options.scope || scopes || [\"email\", \"profile\"];\n\n\t\t\tconst url = createAuthorizationURL({\n\t\t\t\tid: \"google\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://accounts.google.com/o/oauth2/auth\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t\treturn url;\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://oauth2.googleapis.com/token\",\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst user = parseJWT(token.idToken)?.payload as GoogleProfile;\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: user.sub,\n\t\t\t\t\tname: user.name,\n\t\t\t\t\temail: user.email,\n\t\t\t\t\timage: user.picture,\n\t\t\t\t\temailVerified: user.email_verified,\n\t\t\t\t},\n\t\t\t\tdata: user,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<GoogleProfile>;\n};\n","import type { ProviderOptions } from \"../oauth2\";\nimport { validateAuthorizationCode, createAuthorizationURL } from \"../oauth2\";\nimport type { OAuthProvider } from \"../oauth2\";\nimport { betterFetch } from \"@better-fetch/fetch\";\nimport { parseJWT } from \"oslo/jwt\";\nimport { logger } from \"../utils/logger\";\n\nexport interface MicrosoftEntraIDProfile extends Record<string, any> {\n\tsub: string;\n\tname: string;\n\temail: string;\n\tpicture: string;\n}\n\nexport interface MicrosoftOptions extends ProviderOptions {\n\t/**\n\t * The tenant ID of the Microsoft account\n\t * @default \"common\"\n\t */\n\ttenantId?: string;\n\t/**\n\t * The size of the profile photo\n\t * @default 48\n\t */\n\tprofilePhotoSize?: 48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648;\n\t/**\n\t * Disable profile photo\n\t */\n\tdisableProfilePhoto?: boolean;\n}\n\nexport const microsoft = (options: MicrosoftOptions) => {\n\tconst tenant = options.tenantId || \"common\";\n\tconst authorizationEndpoint = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/authorize`;\n\tconst tokenEndpoint = `https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`;\n\treturn {\n\t\tid: \"microsoft\",\n\t\tname: \"Microsoft EntraID\",\n\t\tcreateAuthorizationURL(data) {\n\t\t\tconst scopes = options.scope ||\n\t\t\t\tdata.scopes || [\"openid\", \"profile\", \"email\", \"User.Read\"];\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"microsoft\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint,\n\t\t\t\tstate: data.state,\n\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\tscopes,\n\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode({ code, codeVerifier, redirectURI }) {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint,\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tif (!token.idToken) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst user = parseJWT(token.idToken)?.payload as MicrosoftEntraIDProfile;\n\t\t\tconst profilePhotoSize = options.profilePhotoSize || 48;\n\t\t\tawait betterFetch<ArrayBuffer>(\n\t\t\t\t`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,\n\t\t\t\t{\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t\tasync onResponse(context) {\n\t\t\t\t\t\tif (options.disableProfilePhoto || !context.response.ok) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst response = context.response.clone();\n\t\t\t\t\t\t\tconst pictureBuffer = await response.arrayBuffer();\n\t\t\t\t\t\t\tconst pictureBase64 =\n\t\t\t\t\t\t\t\tBuffer.from(pictureBuffer).toString(\"base64\");\n\t\t\t\t\t\t\tuser.picture = `data:image/jpeg;base64, ${pictureBase64}`;\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tlogger.error(e);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: user.sub,\n\t\t\t\t\tname: user.name,\n\t\t\t\t\temail: user.email,\n\t\t\t\t\timage: user.picture,\n\t\t\t\t\temailVerified: true,\n\t\t\t\t},\n\t\t\t\tdata: user,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider;\n};\n","import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { createAuthorizationURL, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface SpotifyProfile {\n\tid: string;\n\tdisplay_name: string;\n\temail: string;\n\timages: {\n\t\turl: string;\n\t}[];\n}\n\nexport interface SpotifyOptions extends ProviderOptions {}\n\nexport const spotify = (options: SpotifyOptions) => {\n\treturn {\n\t\tid: \"spotify\",\n\t\tname: \"Spotify\",\n\t\tcreateAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {\n\t\t\tconst _scopes = options.scope || scopes || [\"user-read-email\"];\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"spotify\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://accounts.spotify.com/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://accounts.spotify.com/api/token\",\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tconst { data: profile, error } = await betterFetch<SpotifyProfile>(\n\t\t\t\t\"https://api.spotify.com/v1/me\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.id,\n\t\t\t\t\tname: profile.display_name,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.images[0]?.url,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<SpotifyProfile>;\n};\n","import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { logger } from \"../utils\";\nimport { parseJWT } from \"oslo/jwt\";\nimport { createAuthorizationURL, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface TwitchProfile {\n\t/**\n\t * The sub of the user\n\t */\n\tsub: string;\n\t/**\n\t * The preferred username of the user\n\t */\n\tpreferred_username: string;\n\t/**\n\t * The email of the user\n\t */\n\temail: string;\n\t/**\n\t * The picture of the user\n\t */\n\tpicture: string;\n}\n\nexport interface TwitchOptions extends ProviderOptions {\n\tclaims?: string[];\n}\nexport const twitch = (options: TwitchOptions) => {\n\treturn {\n\t\tid: \"twitch\",\n\t\tname: \"Twitch\",\n\t\tcreateAuthorizationURL({ state, scopes, redirectURI }) {\n\t\t\tconst _scopes = options.scope || scopes || [\"user:read:email\", \"openid\"];\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"twitch\",\n\t\t\t\tredirectURI,\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://id.twitch.tv/oauth2/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate,\n\t\t\t\tclaims: options.claims || [\n\t\t\t\t\t\"email\",\n\t\t\t\t\t\"email_verified\",\n\t\t\t\t\t\"preferred_username\",\n\t\t\t\t\t\"picture\",\n\t\t\t\t],\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://id.twitch.tv/oauth2/token\",\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tconst idToken = token.idToken;\n\t\t\tif (!idToken) {\n\t\t\t\tlogger.error(\"No idToken found in token\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst profile = parseJWT(idToken)?.payload as TwitchProfile;\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.sub,\n\t\t\t\t\tname: profile.preferred_username,\n\t\t\t\t\temail: profile.email,\n\t\t\t\t\timage: profile.picture,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<TwitchProfile>;\n};\n","export const HIDE_METADATA = {\n\tisAction: false as const,\n};\n","import { nanoid } from \"nanoid\";\n\nexport const generateId = (size?: number) => {\n\treturn nanoid(size);\n};\n","import { betterFetch } from \"@better-fetch/fetch\";\nimport type { OAuthProvider, ProviderOptions } from \"../oauth2\";\nimport { createAuthorizationURL, validateAuthorizationCode } from \"../oauth2\";\n\nexport interface TwitterProfile {\n\tdata: {\n\t\t/**\n\t\t * Unique identifier of this user. This is returned as a string in order to avoid complications with languages and tools\n\t\t * that cannot handle large integers.\n\t\t */\n\t\tid: string;\n\t\t/** The friendly name of this user, as shown on their profile. */\n\t\tname: string;\n\t\t/** @note Email is currently unsupported by Twitter. */\n\t\temail?: string;\n\t\t/** The Twitter handle (screen name) of this user. */\n\t\tusername: string;\n\t\t/**\n\t\t * The location specified in the user's profile, if the user provided one.\n\t\t * As this is a freeform value, it may not indicate a valid location, but it may be fuzzily evaluated when performing searches with location queries.\n\t\t *\n\t\t * To return this field, add `user.fields=location` in the authorization request's query parameter.\n\t\t */\n\t\tlocation?: string;\n\t\t/**\n\t\t * This object and its children fields contain details about text that has a special meaning in the user's description.\n\t\t *\n\t\t *To return this field, add `user.fields=entities` in the authorization request's query parameter.\n\t\t */\n\t\tentities?: {\n\t\t\t/** Contains details about the user's profile website. */\n\t\t\turl: {\n\t\t\t\t/** Contains details about the user's profile website. */\n\t\t\t\turls: Array<{\n\t\t\t\t\t/** The start position (zero-based) of the recognized user's profile website. All start indices are inclusive. */\n\t\t\t\t\tstart: number;\n\t\t\t\t\t/** The end position (zero-based) of the recognized user's profile website. This end index is exclusive. */\n\t\t\t\t\tend: number;\n\t\t\t\t\t/** The URL in the format entered by the user. */\n\t\t\t\t\turl: string;\n\t\t\t\t\t/** The fully resolved URL. */\n\t\t\t\t\texpanded_url: string;\n\t\t\t\t\t/** The URL as displayed in the user's profile. */\n\t\t\t\t\tdisplay_url: string;\n\t\t\t\t}>;\n\t\t\t};\n\t\t\t/** Contains details about URLs, Hashtags, Cashtags, or mentions located within a user's description. */\n\t\t\tdescription: {\n\t\t\t\thashtags: Array<{\n\t\t\t\t\tstart: number;\n\t\t\t\t\tend: number;\n\t\t\t\t\ttag: string;\n\t\t\t\t}>;\n\t\t\t};\n\t\t};\n\t\t/**\n\t\t * Indicate if this user is a verified Twitter user.\n\t\t *\n\t\t * To return this field, add `user.fields=verified` in the authorization request's query parameter.\n\t\t */\n\t\tverified?: boolean;\n\t\t/**\n\t\t * The text of this user's profile description (also known as bio), if the user provided one.\n\t\t *\n\t\t * To return this field, add `user.fields=description` in the authorization request's query parameter.\n\t\t */\n\t\tdescription?: string;\n\t\t/**\n\t\t * The URL specified in the user's profile, if present.\n\t\t *\n\t\t * To return this field, add `user.fields=url` in the authorization request's query parameter.\n\t\t */\n\t\turl?: string;\n\t\t/** The URL to the profile image for this user, as shown on the user's profile. */\n\t\tprofile_image_url?: string;\n\t\tprotected?: boolean;\n\t\t/**\n\t\t * Unique identifier of this user's pinned Tweet.\n\t\t *\n\t\t * You can obtain the expanded object in `includes.tweets` by adding `expansions=pinned_tweet_id` in the authorization request's query parameter.\n\t\t */\n\t\tpinned_tweet_id?: string;\n\t\tcreated_at?: string;\n\t};\n\tincludes?: {\n\t\ttweets?: Array<{\n\t\t\tid: string;\n\t\t\ttext: string;\n\t\t}>;\n\t};\n\t[claims: string]: unknown;\n}\n\nexport interface TwitterOption extends ProviderOptions {}\n\nexport const twitter = (options: TwitterOption) => {\n\treturn {\n\t\tid: \"twitter\",\n\t\tname: \"Twitter\",\n\t\tcreateAuthorizationURL(data) {\n\t\t\tconst _scopes = options.scope || data.scopes || [\"account_info.read\"];\n\t\t\treturn createAuthorizationURL({\n\t\t\t\tid: \"twitter\",\n\t\t\t\toptions,\n\t\t\t\tauthorizationEndpoint: \"https://twitter.com/i/oauth2/authorize\",\n\t\t\t\tscopes: _scopes,\n\t\t\t\tstate: data.state,\n\t\t\t\tcodeVerifier: data.codeVerifier,\n\t\t\t\tredirectURI: data.redirectURI,\n\t\t\t});\n\t\t},\n\t\tvalidateAuthorizationCode: async ({ code, codeVerifier, redirectURI }) => {\n\t\t\treturn validateAuthorizationCode({\n\t\t\t\tcode,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: options.redirectURI || redirectURI,\n\t\t\t\toptions,\n\t\t\t\ttokenEndpoint: \"https://id.twitch.tv/oauth2/token\",\n\t\t\t});\n\t\t},\n\t\tasync getUserInfo(token) {\n\t\t\tconst { data: profile, error } = await betterFetch<TwitterProfile>(\n\t\t\t\t\"https://api.x.com/2/users/me?user.fields=profile_image_url\",\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${token.accessToken}`,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (error) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (!profile.data.email) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tuser: {\n\t\t\t\t\tid: profile.data.id,\n\t\t\t\t\tname: profile.data.name,\n\t\t\t\t\temail: profile.data.email,\n\t\t\t\t\timage: profile.data.profile_image_url,\n\t\t\t\t\temailVerified: profile.data.verified || false,\n\t\t\t\t},\n\t\t\t\tdata: profile,\n\t\t\t};\n\t\t},\n\t} satisfies OAuthProvider<TwitterProfile>;\n};\n","import type { Prettify } from \"../types\";\nimport { apple } from \"./apple\";\nimport { discord } from \"./discord\";\nimport { facebook } from \"./facebook\";\nimport { github } from \"./github\";\nimport { google } from \"./google\";\nimport { microsoft } from \"./microsoft-entra-id\";\nimport { spotify } from \"./spotify\";\nimport { twitch } from \"./twitch\";\nimport { twitter } from \"./twitter\";\n\nexport const socialProviders = {\n\tapple,\n\tdiscord,\n\tfacebook,\n\tgithub,\n\tmicrosoft,\n\tgoogle,\n\tspotify,\n\ttwitch,\n\ttwitter,\n};\n\nexport const socialProviderList = Object.keys(socialProviders) as [\n\t\"github\",\n\t...(keyof typeof socialProviders)[],\n];\n\nexport type SocialProviders = typeof socialProviders extends {\n\t[key in infer K]: infer V;\n}\n\t? V extends (options: infer V) => any\n\t\t? Partial<Record<K, Prettify<V & { enabled?: boolean }>>>\n\t\t: never\n\t: never;\n\nexport * from \"./github\";\nexport * from \"./google\";\nexport * from \"./apple\";\nexport * from \"./microsoft-entra-id\";\nexport * from \"./discord\";\nexport * from \"./spotify\";\nexport * from \"./twitch\";\nexport * from \"./facebook\";\nexport * from \"./twitter\";\n\nexport type SocialProviderList = typeof socialProviderList;\n","import { TimeSpan } from \"oslo\";\nimport { createJWT, validateJWT, type JWT } from \"oslo/jwt\";\nimport { z } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { getSessionFromCtx } from \"./session\";\n\nexport async function createEmailVerificationToken(\n\tsecret: string,\n\temail: string,\n\t/**\n\t * The email to update from\n\t */\n\tupdateTo?: string,\n) {\n\tconst token = await createJWT(\n\t\t\"HS256\",\n\t\tBuffer.from(secret),\n\t\t{\n\t\t\temail: email.toLowerCase(),\n\t\t\tupdateTo,\n\t\t},\n\t\t{\n\t\t\texpiresIn: new TimeSpan(1, \"h\"),\n\t\t\tissuer: \"better-auth\",\n\t\t\tsubject: \"verify-email\",\n\t\t\taudiences: [email],\n\t\t\tincludeIssuedTimestamp: true,\n\t\t},\n\t);\n\treturn token;\n}\n\nexport const sendVerificationEmail = createAuthEndpoint(\n\t\"/send-verification-email\",\n\t{\n\t\tmethod: \"POST\",\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\temail: z.string().email(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.emailVerification?.sendVerificationEmail) {\n\t\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email } = ctx.body;\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\tif (!user) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User not found\",\n\t\t\t});\n\t\t}\n\t\tconst token = await createEmailVerificationToken(ctx.context.secret, email);\n\t\tconst url = `${\n\t\t\tctx.context.baseURL\n\t\t}/verify-email?token=${token}&callbackURL=${\n\t\t\tctx.body.callbackURL || ctx.query?.currentURL || \"/\"\n\t\t}`;\n\t\tawait ctx.context.options.emailVerification.sendVerificationEmail(\n\t\t\tuser.user,\n\t\t\turl,\n\t\t\ttoken,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const verifyEmail = createAuthEndpoint(\n\t\"/verify-email\",\n\t{\n\t\tmethod: \"GET\",\n\t\tquery: z.object({\n\t\t\ttoken: z.string(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { token } = ctx.query;\n\t\tlet jwt: JWT;\n\t\ttry {\n\t\t\tjwt = await validateJWT(\"HS256\", Buffer.from(ctx.context.secret), token);\n\t\t} catch (e) {\n\t\t\tctx.context.logger.error(\"Failed to verify email\", e);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid token\",\n\t\t\t});\n\t\t}\n\t\tconst schema = z.object({\n\t\t\temail: z.string().email(),\n\t\t\tupdateTo: z.string().optional(),\n\t\t});\n\t\tconst parsed = schema.parse(jwt.payload);\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(\n\t\t\tparsed.email,\n\t\t);\n\t\tif (!user) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User not found\",\n\t\t\t});\n\t\t}\n\t\tif (parsed.updateTo) {\n\t\t\tconst session = await getSessionFromCtx(ctx);\n\t\t\tif (!session) {\n\t\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}?error=unauthorized`);\n\t\t\t\t}\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Session not found\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (session.user.email !== parsed.email) {\n\t\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\t\tthrow ctx.redirect(`${ctx.query.callbackURL}?error=unauthorized`);\n\t\t\t\t}\n\t\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\t\tmessage: \"Invalid session\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\t\tparsed.email,\n\t\t\t\t{\n\t\t\t\t\temail: parsed.updateTo,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t//send verification email to the new email\n\t\t\tawait ctx.context.options.emailVerification?.sendVerificationEmail?.(\n\t\t\t\tupdatedUser,\n\t\t\t\t`${ctx.context.baseURL}/verify-email?token=${token}`,\n\t\t\t\ttoken,\n\t\t\t);\n\n\t\t\tif (ctx.query.callbackURL) {\n\t\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t\t}\n\t\t\treturn ctx.json({\n\t\t\t\tuser: updatedUser,\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.updateUserByEmail(parsed.email, {\n\t\t\temailVerified: true,\n\t\t});\n\t\tif (ctx.query.callbackURL) {\n\t\t\tthrow ctx.redirect(ctx.query.callbackURL);\n\t\t}\n\t\treturn ctx.json({\n\t\t\tuser: null,\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n","import { APIError, type Context } from \"better-call\";\nimport { createAuthEndpoint, createAuthMiddleware } from \"../call\";\nimport { getDate } from \"../../utils/date\";\nimport { deleteSessionCookie, setSessionCookie } from \"../../cookies\";\nimport { z } from \"zod\";\nimport type {\n\tBetterAuthOptions,\n\tInferSession,\n\tInferUser,\n\tPrettify,\n} from \"../../types\";\n\nexport const getSession = <Option extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/session\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\trequireHeaders: true,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\ttry {\n\t\t\t\tconst sessionCookieToken = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.sessionToken.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\n\t\t\t\tif (!sessionCookieToken) {\n\t\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst session =\n\t\t\t\t\tawait ctx.context.internalAdapter.findSession(sessionCookieToken);\n\n\t\t\t\tif (!session || session.session.expiresAt < new Date()) {\n\t\t\t\t\tdeleteSessionCookie(ctx);\n\t\t\t\t\tif (session) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * if session expired clean up the session\n\t\t\t\t\t\t */\n\t\t\t\t\t\tawait ctx.context.internalAdapter.deleteSession(session.session.id);\n\t\t\t\t\t}\n\t\t\t\t\treturn ctx.json(null, {\n\t\t\t\t\t\tstatus: 401,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tconst dontRememberMe = await ctx.getSignedCookie(\n\t\t\t\t\tctx.context.authCookies.dontRememberToken.name,\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t);\n\t\t\t\t/**\n\t\t\t\t * We don't need to update the session if the user doesn't want to be remembered\n\t\t\t\t */\n\t\t\t\tif (dontRememberMe) {\n\t\t\t\t\treturn ctx.json(\n\t\t\t\t\t\tsession as unknown as {\n\t\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst expiresIn = ctx.context.sessionConfig.expiresIn;\n\t\t\t\tconst updateAge = ctx.context.sessionConfig.updateAge;\n\t\t\t\t/**\n\t\t\t\t * Calculate last updated date to throttle write updates to database\n\t\t\t\t * Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge\n\t\t\t\t *\n\t\t\t\t * e.g. ({expiry date} - 30 days) + 1 hour\n\t\t\t\t *\n\t\t\t\t * inspired by: https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/lib/actions/session.ts\n\t\t\t\t */\n\t\t\t\tconst sessionIsDueToBeUpdatedDate =\n\t\t\t\t\tsession.session.expiresAt.valueOf() -\n\t\t\t\t\texpiresIn * 1000 +\n\t\t\t\t\tupdateAge * 1000;\n\t\t\t\tconst shouldBeUpdated = sessionIsDueToBeUpdatedDate <= Date.now();\n\n\t\t\t\tif (shouldBeUpdated) {\n\t\t\t\t\tconst updatedSession =\n\t\t\t\t\t\tawait ctx.context.internalAdapter.updateSession(\n\t\t\t\t\t\t\tsession.session.id,\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\texpiresAt: getDate(ctx.context.sessionConfig.expiresIn, \"sec\"),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t);\n\t\t\t\t\tif (!updatedSession) {\n\t\t\t\t\t\t/**\n\t\t\t\t\t\t * Handle case where session update fails (e.g., concurrent deletion)\n\t\t\t\t\t\t */\n\t\t\t\t\t\tdeleteSessionCookie(ctx);\n\t\t\t\t\t\treturn ctx.json(null, { status: 401 });\n\t\t\t\t\t}\n\t\t\t\t\tconst maxAge =\n\t\t\t\t\t\t(updatedSession.expiresAt.valueOf() - Date.now()) / 1000;\n\t\t\t\t\tawait setSessionCookie(ctx, updatedSession.id, false, {\n\t\t\t\t\t\tmaxAge,\n\t\t\t\t\t});\n\t\t\t\t\treturn ctx.json({\n\t\t\t\t\t\tsession: updatedSession,\n\t\t\t\t\t\tuser: session.user,\n\t\t\t\t\t} as unknown as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\treturn ctx.json(\n\t\t\t\t\tsession as unknown as {\n\t\t\t\t\t\tsession: InferSession<Option>;\n\t\t\t\t\t\tuser: InferUser<Option>;\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tctx.context.logger.error(error);\n\t\t\t\treturn ctx.json(null, { status: 500 });\n\t\t\t}\n\t\t},\n\t);\n\nexport const getSessionFromCtx = async (ctx: Context<any, any>) => {\n\t//@ts-ignore\n\tconst session = await getSession()({\n\t\t...ctx,\n\t\t_flag: \"json\",\n\t\theaders: ctx.headers!,\n\t});\n\n\treturn session;\n};\n\nexport const sessionMiddleware = createAuthMiddleware(async (ctx) => {\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session?.session) {\n\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t}\n\treturn {\n\t\tsession,\n\t};\n});\n\n/**\n * user active sessions list\n */\nexport const listSessions = <Option extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/user/list-sessions\",\n\t\t{\n\t\t\tmethod: \"GET\",\n\t\t\tuse: [sessionMiddleware],\n\t\t\trequireHeaders: true,\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst sessions = await ctx.context.internalAdapter.listSessions(\n\t\t\t\tctx.context.session.user.id,\n\t\t\t);\n\t\t\tconst activeSessions = sessions.filter((session) => {\n\t\t\t\treturn session.expiresAt > new Date();\n\t\t\t});\n\t\t\treturn ctx.json(\n\t\t\t\tactiveSessions as unknown as Prettify<InferSession<Option>>[],\n\t\t\t);\n\t\t},\n\t);\n\n/**\n * revoke a single session\n */\nexport const revokeSession = createAuthEndpoint(\n\t\"/user/revoke-session\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tid: z.string(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t\trequireHeaders: true,\n\t},\n\tasync (ctx) => {\n\t\tconst id = ctx.body.id;\n\t\tconst findSession = await ctx.context.internalAdapter.findSession(id);\n\t\tif (!findSession) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Session not found\",\n\t\t\t});\n\t\t}\n\t\tif (findSession.session.userId !== ctx.context.session.user.id) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\");\n\t\t}\n\t\ttry {\n\t\t\tawait ctx.context.internalAdapter.deleteSession(id);\n\t\t} catch (error) {\n\t\t\tctx.context.logger.error(error);\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n/**\n * revoke all user sessions\n */\nexport const revokeSessions = createAuthEndpoint(\n\t\"/user/revoke-sessions\",\n\t{\n\t\tmethod: \"POST\",\n\t\tuse: [sessionMiddleware],\n\t\trequireHeaders: true,\n\t},\n\tasync (ctx) => {\n\t\ttry {\n\t\t\tawait ctx.context.internalAdapter.deleteSessions(\n\t\t\t\tctx.context.session.user.id,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tctx.context.logger.error(error);\n\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\");\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n","export const getDate = (span: number, unit: \"sec\" | \"ms\" = \"ms\") => {\n\treturn new Date(Date.now() + (unit === \"sec\" ? span * 1000 : span));\n};\n","import { z } from \"zod\";\nimport { userSchema } from \"../../db/schema\";\nimport { generateId } from \"../../utils/id\";\nimport { parseState } from \"../../oauth2/state\";\nimport { createAuthEndpoint } from \"../call\";\nimport { HIDE_METADATA } from \"../../utils/hide-metadata\";\nimport { getAccountTokens } from \"../../oauth2/get-account\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { logger } from \"../../utils/logger\";\nimport type { OAuth2Tokens } from \"../../oauth2\";\nimport { compareHash } from \"../../crypto/hash\";\nimport { createEmailVerificationToken } from \"./email-verification\";\n\nexport const callbackOAuth = createAuthEndpoint(\n\t\"/callback/:id\",\n\t{\n\t\tmethod: \"GET\",\n\t\tquery: z.object({\n\t\t\tstate: z.string(),\n\t\t\tcode: z.string().optional(),\n\t\t\terror: z.string().optional(),\n\t\t}),\n\t\tmetadata: HIDE_METADATA,\n\t},\n\tasync (c) => {\n\t\tif (c.query.error || !c.query.code) {\n\t\t\tconst parsedState = parseState(c.query.state);\n\t\t\tconst callbackURL =\n\t\t\t\tparsedState.data?.callbackURL || `${c.context.baseURL}/error`;\n\t\t\tc.context.logger.error(c.query.error, c.params.id);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${callbackURL}?error=${c.query.error || \"oAuth_code_missing\"}`,\n\t\t\t);\n\t\t}\n\n\t\tconst provider = c.context.socialProviders.find(\n\t\t\t(p) => p.id === c.params.id,\n\t\t);\n\n\t\tif (!provider) {\n\t\t\tc.context.logger.error(\n\t\t\t\t\"Oauth provider with id\",\n\t\t\t\tc.params.id,\n\t\t\t\t\"not found\",\n\t\t\t);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=oauth_provider_not_found`,\n\t\t\t);\n\t\t}\n\n\t\tconst parsedState = parseState(c.query.state);\n\t\tif (!parsedState.success) {\n\t\t\tc.context.logger.error(\"Unable to parse state\");\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\n\t\tconst {\n\t\t\tdata: { callbackURL, currentURL },\n\t\t} = parsedState;\n\n\t\tconst storedState = await c.getSignedCookie(\n\t\t\tc.context.authCookies.state.name,\n\t\t\tc.context.secret,\n\t\t);\n\n\t\tif (!storedState) {\n\t\t\tlogger.error(\"No stored state found\");\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\n\t\tconst isValidState = await compareHash(c.query.state, storedState);\n\t\tif (!isValidState) {\n\t\t\tlogger.error(\"OAuth state mismatch\");\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\t\tconst codeVerifier = await c.getSignedCookie(\n\t\t\tc.context.authCookies.pkCodeVerifier.name,\n\t\t\tc.context.secret,\n\t\t);\n\t\tlet tokens: OAuth2Tokens;\n\t\ttry {\n\t\t\ttokens = await provider.validateAuthorizationCode({\n\t\t\t\tcode: c.query.code,\n\t\t\t\tcodeVerifier,\n\t\t\t\tredirectURI: `${c.context.baseURL}/callback/${provider.id}`,\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tc.context.logger.error(e);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\t\tconst user = await provider.getUserInfo(tokens).then((res) => res?.user);\n\t\tconst id = generateId();\n\t\tconst data = userSchema.safeParse({\n\t\t\t...user,\n\t\t\tid,\n\t\t});\n\n\t\tif (!user || data.success === false) {\n\t\t\tlogger.error(\"Unable to get user info\", data.error);\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\t\tif (!callbackURL) {\n\t\t\tthrow c.redirect(\n\t\t\t\t`${c.context.baseURL}/error?error=please_restart_the_process`,\n\t\t\t);\n\t\t}\n\n\t\tfunction redirectOnError(error: string) {\n\t\t\tthrow c.redirect(\n\t\t\t\t`${\n\t\t\t\t\tcurrentURL || callbackURL || `${c.context.baseURL}/error`\n\t\t\t\t}?error=${error}`,\n\t\t\t);\n\t\t}\n\n\t\tconst dbUser = await c.context.internalAdapter\n\t\t\t.findUserByEmail(user.email, {\n\t\t\t\tincludeAccounts: true,\n\t\t\t})\n\t\t\t.catch((e) => {\n\t\t\t\tlogger.error(\n\t\t\t\t\t\"Better auth was unable to query your database.\\nError: \",\n\t\t\t\t\te,\n\t\t\t\t);\n\t\t\t\tthrow c.redirect(\n\t\t\t\t\t`${c.context.baseURL}/error?error=internal_server_error`,\n\t\t\t\t);\n\t\t\t});\n\n\t\tlet userId = dbUser?.user.id;\n\t\tif (dbUser) {\n\t\t\tconst hasBeenLinked = dbUser.accounts.find(\n\t\t\t\t(a) => a.providerId === provider.id,\n\t\t\t);\n\t\t\tif (!hasBeenLinked) {\n\t\t\t\tconst trustedProviders =\n\t\t\t\t\tc.context.options.account?.accountLinking?.trustedProviders;\n\t\t\t\tconst isTrustedProvider = trustedProviders?.includes(\n\t\t\t\t\tprovider.id as \"apple\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\t(!isTrustedProvider && !user.emailVerified) ||\n\t\t\t\t\t!c.context.options.account?.accountLinking?.enabled\n\t\t\t\t) {\n\t\t\t\t\tredirectOnError(\"account_not_linked\");\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tawait c.context.internalAdapter.linkAccount({\n\t\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\t\taccountId: user.id.toString(),\n\t\t\t\t\t\tid: `${provider.id}:${user.id}`,\n\t\t\t\t\t\tuserId: dbUser.user.id,\n\t\t\t\t\t\t...getAccountTokens(tokens),\n\t\t\t\t\t});\n\t\t\t\t} catch (e) {\n\t\t\t\t\tlogger.error(\"Unable to link account\", e);\n\t\t\t\t\tredirectOnError(\"unable_to_link_account\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tconst emailVerified = user.emailVerified || false;\n\t\t\t\tconst created = await c.context.internalAdapter.createOAuthUser(\n\t\t\t\t\t{\n\t\t\t\t\t\t...data.data,\n\t\t\t\t\t\temailVerified,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t...getAccountTokens(tokens),\n\t\t\t\t\t\tproviderId: provider.id,\n\t\t\t\t\t\taccountId: user.id.toString(),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tuserId = created?.user.id;\n\t\t\t\tif (\n\t\t\t\t\t!emailVerified &&\n\t\t\t\t\tcreated &&\n\t\t\t\t\tc.context.options.emailVerification?.sendOnSignUp\n\t\t\t\t) {\n\t\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\t\tc.context.secret,\n\t\t\t\t\t\tuser.email,\n\t\t\t\t\t);\n\t\t\t\t\tconst url = `${c.context.baseURL}/verify-email?token=${token}&callbackURL=${callbackURL}`;\n\t\t\t\t\tawait c.context.options.emailVerification?.sendVerificationEmail?.(\n\t\t\t\t\t\tcreated.user,\n\t\t\t\t\t\turl,\n\t\t\t\t\t\ttoken,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(\"Unable to create user\", e);\n\t\t\t\tredirectOnError(\"unable_to_create_user\");\n\t\t\t}\n\t\t}\n\n\t\tif (!userId) {\n\t\t\tredirectOnError(\"unable_to_create_user\");\n\t\t}\n\n\t\tconst session = await c.context.internalAdapter.createSession(\n\t\t\tuserId!,\n\t\t\tc.request,\n\t\t);\n\t\tif (!session) {\n\t\t\tredirectOnError(\"unable_to_create_session\");\n\t\t}\n\t\tawait setSessionCookie(c, session.id);\n\t\tthrow c.redirect(callbackURL);\n\t},\n);\n","import { z } from \"zod\";\nimport type { FieldAttribute } from \".\";\nimport type { BetterAuthOptions } from \"../types\";\n\nexport const accountSchema = z.object({\n\tid: z.string(),\n\tproviderId: z.string(),\n\taccountId: z.string(),\n\tuserId: z.string(),\n\taccessToken: z.string().nullable().optional(),\n\trefreshToken: z.string().nullable().optional(),\n\tidToken: z.string().nullable().optional(),\n\t/**\n\t * Access token expires at\n\t */\n\texpiresAt: z.date().nullable().optional(),\n\t/**\n\t * Password is only stored in the credential provider\n\t */\n\tpassword: z.string().optional().nullable(),\n});\n\nexport const userSchema = z.object({\n\tid: z.string(),\n\temail: z.string().transform((val) => val.toLowerCase()),\n\temailVerified: z.boolean().default(false),\n\tname: z.string(),\n\timage: z.string().optional(),\n\tcreatedAt: z.date().default(new Date()),\n\tupdatedAt: z.date().default(new Date()),\n});\n\nexport const sessionSchema = z.object({\n\tid: z.string(),\n\tuserId: z.string(),\n\texpiresAt: z.date(),\n\tipAddress: z.string().optional(),\n\tuserAgent: z.string().optional(),\n});\n\nexport const verificationSchema = z.object({\n\tid: z.string(),\n\tvalue: z.string(),\n\texpiresAt: z.date(),\n\tidentifier: z.string(),\n});\n\nexport type User = z.infer<typeof userSchema>;\nexport type Account = z.infer<typeof accountSchema>;\nexport type Session = z.infer<typeof sessionSchema>;\nexport type Verification = z.infer<typeof verificationSchema>;\n\nexport function parseOutputData<T extends Record<string, any>>(\n\tdata: T,\n\tschema: {\n\t\tfields: Record<string, FieldAttribute>;\n\t},\n) {\n\tconst fields = schema.fields;\n\tconst parsedData: Record<string, any> = {};\n\tfor (const key in data) {\n\t\tconst field = fields[key];\n\t\tif (!field) {\n\t\t\tparsedData[key] = data[key];\n\t\t\tcontinue;\n\t\t}\n\t\tif (field.returned === false) {\n\t\t\tcontinue;\n\t\t}\n\t\tparsedData[key] = data[key];\n\t}\n\treturn parsedData as T;\n}\n\nexport function getAllFields(options: BetterAuthOptions, table: string) {\n\tlet schema: Record<string, FieldAttribute> = {\n\t\t...(table === \"user\" ? options.user?.additionalFields : {}),\n\t\t...(table === \"session\" ? options.session?.additionalFields : {}),\n\t};\n\tfor (const plugin of options.plugins || []) {\n\t\tif (plugin.schema && plugin.schema[table]) {\n\t\t\tschema = {\n\t\t\t\t...schema,\n\t\t\t\t...plugin.schema[table].fields,\n\t\t\t};\n\t\t}\n\t}\n\treturn schema;\n}\n\nexport function parseUserOutput(options: BetterAuthOptions, user: User) {\n\tconst schema = getAllFields(options, \"user\");\n\treturn parseOutputData(user, { fields: schema });\n}\n\nexport function parseAccountOutput(\n\toptions: BetterAuthOptions,\n\taccount: Account,\n) {\n\tconst schema = getAllFields(options, \"account\");\n\treturn parseOutputData(account, { fields: schema });\n}\n\nexport function parseSessionOutput(\n\toptions: BetterAuthOptions,\n\tsession: Session,\n) {\n\tconst schema = getAllFields(options, \"session\");\n\treturn parseOutputData(session, { fields: schema });\n}\n\nexport function parseInputData<T extends Record<string, any>>(\n\tdata: T,\n\tschema: {\n\t\tfields: Record<string, FieldAttribute>;\n\t},\n) {\n\tconst fields = schema.fields;\n\tconst parsedData: Record<string, any> = {};\n\tfor (const key in fields) {\n\t\tif (key in data) {\n\t\t\tif (fields[key].input === false) {\n\t\t\t\tif (fields[key].defaultValue) {\n\t\t\t\t\tparsedData[key] = fields[key].defaultValue;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tparsedData[key] = data[key];\n\t\t\tcontinue;\n\t\t}\n\t\tif (fields[key].defaultValue) {\n\t\t\tparsedData[key] = fields[key].defaultValue;\n\t\t\tcontinue;\n\t\t}\n\t}\n\treturn parsedData as Partial<T>;\n}\n\nexport function parseUserInput(\n\toptions: BetterAuthOptions,\n\tuser?: Record<string, any>,\n) {\n\tconst schema = getAllFields(options, \"user\");\n\treturn parseInputData(user || {}, { fields: schema });\n}\n\nexport function parseAdditionalUserInput(\n\toptions: BetterAuthOptions,\n\tuser?: Record<string, any>,\n) {\n\tconst schema = getAllFields(options, \"user\");\n\treturn parseInputData(user || {}, { fields: schema });\n}\n\nexport function parseAccountInput(\n\toptions: BetterAuthOptions,\n\taccount: Partial<Account>,\n) {\n\tconst schema = getAllFields(options, \"account\");\n\treturn parseInputData(account, { fields: schema });\n}\n\nexport function parseSessionInput(\n\toptions: BetterAuthOptions,\n\tsession: Partial<Session>,\n) {\n\tconst schema = getAllFields(options, \"session\");\n\treturn parseInputData(session, { fields: schema });\n}\n","import { z } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { deleteSessionCookie } from \"../../cookies\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\n\nexport const signOut = createAuthEndpoint(\n\t\"/sign-out\",\n\t{\n\t\tmethod: \"POST\",\n\t},\n\tasync (ctx) => {\n\t\tconst sessionCookieToken = await ctx.getSignedCookie(\n\t\t\tctx.context.authCookies.sessionToken.name,\n\t\t\tctx.context.secret,\n\t\t);\n\t\tif (!sessionCookieToken) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Session not found\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteSession(sessionCookieToken);\n\t\tdeleteSessionCookie(ctx);\n\t\treturn ctx.json({\n\t\t\tsuccess: true,\n\t\t});\n\t},\n);\n","import { z } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\n\nexport const forgetPassword = createAuthEndpoint(\n\t\"/forget-password\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * The email address of the user to send a password reset email to.\n\t\t\t */\n\t\t\temail: z.string().email(),\n\t\t\t/**\n\t\t\t * The URL to redirect the user to reset their password.\n\t\t\t * If the token isn't valid or expired, it'll be redirected with a query parameter `?\n\t\t\t * error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?\n\t\t\t * token=VALID_TOKEN\n\t\t\t */\n\t\t\tredirectTo: z.string(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.emailAndPassword?.sendResetPassword) {\n\t\t\tctx.context.logger.error(\n\t\t\t\t\"Reset password isn't enabled.Please pass an emailAndPassword.sendResetPasswordToken function in your auth config!\",\n\t\t\t);\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Reset password isn't enabled\",\n\t\t\t});\n\t\t}\n\t\tconst { email, redirectTo } = ctx.body;\n\n\t\tconst user = await ctx.context.internalAdapter.findUserByEmail(email, {\n\t\t\tincludeAccounts: true,\n\t\t});\n\t\tif (!user) {\n\t\t\tctx.context.logger.error(\"Reset Password: User not found\", { email });\n\t\t\t//only on the server status is false for the client it's always true\n\t\t\t//to avoid leaking information\n\t\t\treturn ctx.json(\n\t\t\t\t{\n\t\t\t\t\tstatus: false,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tstatus: true,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\t\tconst defaultExpiresIn = 60 * 60 * 1;\n\t\tconst expiresAt = new Date(\n\t\t\tDate.now() +\n\t\t\t\t1000 *\n\t\t\t\t\t(ctx.context.options.emailAndPassword.resetPasswordTokenExpiresIn ||\n\t\t\t\t\t\tdefaultExpiresIn),\n\t\t);\n\t\tconst verificationToken = ctx.context.uuid();\n\t\tawait ctx.context.internalAdapter.createVerificationValue({\n\t\t\tvalue: user.user.id,\n\t\t\tidentifier: `reset-password:${verificationToken}`,\n\t\t\texpiresAt,\n\t\t});\n\t\tconst url = `${ctx.context.baseURL}/reset-password/${verificationToken}?callbackURL=${redirectTo}`;\n\t\tawait ctx.context.options.emailAndPassword.sendResetPassword(\n\t\t\tuser.user,\n\t\t\turl,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n\nexport const forgetPasswordCallback = createAuthEndpoint(\n\t\"/reset-password/:token\",\n\t{\n\t\tmethod: \"GET\",\n\t\tquery: z.object({\n\t\t\tcallbackURL: z.string(),\n\t\t}),\n\t\tuse: [redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { token } = ctx.params;\n\t\tconst callbackURL = ctx.query.callbackURL;\n\t\tconst redirectTo = callbackURL.startsWith(\"http\")\n\t\t\t? callbackURL\n\t\t\t: `${ctx.context.options.baseURL}${callbackURL}`;\n\t\tif (!token || !callbackURL) {\n\t\t\tthrow ctx.redirect(`${ctx.context.baseURL}/error?error=INVALID_TOKEN`);\n\t\t}\n\t\tconst verification =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(\n\t\t\t\t`reset-password:${token}`,\n\t\t\t);\n\t\tif (!verification || verification.expiresAt < new Date()) {\n\t\t\tthrow ctx.redirect(`${redirectTo}?error=INVALID_TOKEN`);\n\t\t}\n\t\tthrow ctx.redirect(`${redirectTo}?token=${token}`);\n\t},\n);\n\nexport const resetPassword = createAuthEndpoint(\n\t\"/reset-password\",\n\t{\n\t\tquery: z.optional(\n\t\t\tz.object({\n\t\t\t\ttoken: z.string().optional(),\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t}),\n\t\t),\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tnewPassword: z.string(),\n\t\t}),\n\t},\n\tasync (ctx) => {\n\t\tconst token =\n\t\t\tctx.query?.token ||\n\t\t\t(ctx.query?.currentURL\n\t\t\t\t? new URL(ctx.query.currentURL).searchParams.get(\"token\")\n\t\t\t\t: \"\");\n\t\tif (!token) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Token not found\",\n\t\t\t});\n\t\t}\n\t\tconst { newPassword } = ctx.body;\n\t\tconst id = `reset-password:${token}`;\n\t\tconst verification =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(id);\n\n\t\tif (!verification || verification.expiresAt < new Date()) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Invalid token\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteVerificationValue(verification.id);\n\t\tconst userId = verification.value;\n\t\tconst hashedPassword = await ctx.context.password.hash(newPassword);\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(userId);\n\t\tconst account = accounts.find((ac) => ac.providerId === \"credential\");\n\t\tif (!account) {\n\t\t\tawait ctx.context.internalAdapter.createAccount({\n\t\t\t\tuserId,\n\t\t\t\tproviderId: \"credential\",\n\t\t\t\tpassword: hashedPassword,\n\t\t\t\taccountId: ctx.context.uuid(),\n\t\t\t});\n\t\t\treturn ctx.json({\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\t\tconst updatedUser = await ctx.context.internalAdapter.updatePassword(\n\t\t\tuserId,\n\t\t\thashedPassword,\n\t\t);\n\t\tif (!updatedUser) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Failed to update password\",\n\t\t\t});\n\t\t}\n\t\treturn ctx.json({\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n","import { z, ZodObject, ZodOptional, ZodString } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { alphabet, generateRandomString } from \"../../crypto/random\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { sessionMiddleware } from \"./session\";\nimport { APIError } from \"better-call\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\nimport { createEmailVerificationToken } from \"./email-verification\";\nimport type { toZod } from \"../../types/to-zod\";\nimport type { AdditionalUserFieldsInput, BetterAuthOptions } from \"../../types\";\nimport { parseUserInput } from \"../../db/schema\";\n\nexport const updateUser = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/user/update\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tbody: z.record(z.string(), z.any()) as unknown as ZodObject<{\n\t\t\t\tname: ZodOptional<ZodString>;\n\t\t\t\timage: ZodOptional<ZodString>;\n\t\t\t}> &\n\t\t\t\ttoZod<AdditionalUserFieldsInput<O>>,\n\t\t\tuse: [sessionMiddleware, redirectURLMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tconst body = ctx.body as {\n\t\t\t\tname?: string;\n\t\t\t\timage?: string;\n\t\t\t\t[key: string]: any;\n\t\t\t};\n\n\t\t\tif (body.email) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"You can't update email\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst { name, image, ...rest } = body;\n\t\t\tconst session = ctx.context.session;\n\t\t\tif (!image && !name && Object.keys(rest).length === 0) {\n\t\t\t\treturn ctx.json({\n\t\t\t\t\tuser: session.user,\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst additionalFields = parseUserInput(ctx.context.options, rest);\n\t\t\tconst user = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\t\tsession.user.email,\n\t\t\t\t{\n\t\t\t\t\tname,\n\t\t\t\t\timage,\n\t\t\t\t\t...additionalFields,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tuser,\n\t\t\t});\n\t\t},\n\t);\n\nexport const changePassword = createAuthEndpoint(\n\t\"/user/change-password\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * The new password to set\n\t\t\t */\n\t\t\tnewPassword: z.string(),\n\t\t\t/**\n\t\t\t * The current password of the user\n\t\t\t */\n\t\t\tcurrentPassword: z.string(),\n\t\t\t/**\n\t\t\t * revoke all sessions that are not the\n\t\t\t * current one logged in by the user\n\t\t\t */\n\t\t\trevokeOtherSessions: z.boolean().optional(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { newPassword, currentPassword, revokeOtherSessions } = ctx.body;\n\t\tconst session = ctx.context.session;\n\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\tif (newPassword.length < minPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password is too short\",\n\t\t\t});\n\t\t}\n\n\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\n\t\tif (newPassword.length > maxPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password too long\",\n\t\t\t});\n\t\t}\n\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst account = accounts.find(\n\t\t\t(account) => account.providerId === \"credential\" && account.password,\n\t\t);\n\t\tif (!account || !account.password) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User does not have a password\",\n\t\t\t});\n\t\t}\n\t\tconst passwordHash = await ctx.context.password.hash(newPassword);\n\t\tconst verify = await ctx.context.password.verify(\n\t\t\taccount.password,\n\t\t\tcurrentPassword,\n\t\t);\n\t\tif (!verify) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Incorrect password\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.updateAccount(account.id, {\n\t\t\tpassword: passwordHash,\n\t\t});\n\t\tif (revokeOtherSessions) {\n\t\t\tawait ctx.context.internalAdapter.deleteSessions(session.user.id);\n\t\t\tconst newSession = await ctx.context.internalAdapter.createSession(\n\t\t\t\tsession.user.id,\n\t\t\t\tctx.headers,\n\t\t\t);\n\t\t\tif (!newSession) {\n\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\tmessage: \"Unable to create session\",\n\t\t\t\t});\n\t\t\t}\n\t\t\t// set the new session cookie\n\t\t\tawait setSessionCookie(ctx, newSession.id);\n\t\t}\n\n\t\treturn ctx.json(session.user);\n\t},\n);\n\nexport const setPassword = createAuthEndpoint(\n\t\"/user/set-password\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\t/**\n\t\t\t * The new password to set\n\t\t\t */\n\t\t\tnewPassword: z.string(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { newPassword } = ctx.body;\n\t\tconst session = ctx.context.session;\n\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\tif (newPassword.length < minPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password is too short\",\n\t\t\t});\n\t\t}\n\n\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\n\t\tif (newPassword.length > maxPasswordLength) {\n\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Password too long\",\n\t\t\t});\n\t\t}\n\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst account = accounts.find(\n\t\t\t(account) => account.providerId === \"credential\" && account.password,\n\t\t);\n\t\tconst passwordHash = await ctx.context.password.hash(newPassword);\n\t\tif (!account) {\n\t\t\tawait ctx.context.internalAdapter.linkAccount({\n\t\t\t\tuserId: session.user.id,\n\t\t\t\tproviderId: \"credential\",\n\t\t\t\taccountId: session.user.id,\n\t\t\t\tpassword: passwordHash,\n\t\t\t});\n\t\t\treturn ctx.json(session.user);\n\t\t}\n\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\tmessage: \"user already has a password\",\n\t\t});\n\t},\n);\n\nexport const deleteUser = createAuthEndpoint(\n\t\"/user/delete\",\n\t{\n\t\tmethod: \"POST\",\n\t\tbody: z.object({\n\t\t\tpassword: z.string(),\n\t\t}),\n\t\tuse: [sessionMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tconst { password } = ctx.body;\n\t\tconst session = ctx.context.session;\n\t\tconst accounts = await ctx.context.internalAdapter.findAccounts(\n\t\t\tsession.user.id,\n\t\t);\n\t\tconst account = accounts.find(\n\t\t\t(account) => account.providerId === \"credential\" && account.password,\n\t\t);\n\t\tif (!account || !account.password) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"User does not have a password\",\n\t\t\t});\n\t\t}\n\t\tconst verify = await ctx.context.password.verify(\n\t\t\taccount.password,\n\t\t\tpassword,\n\t\t);\n\t\tif (!verify) {\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Incorrect password\",\n\t\t\t});\n\t\t}\n\t\tawait ctx.context.internalAdapter.deleteUser(session.user.id);\n\t\tawait ctx.context.internalAdapter.deleteSessions(session.user.id);\n\t\tconst sessionCookie = ctx.context.authCookies.sessionToken;\n\t\tctx.setCookie(sessionCookie.name, \"\", {\n\t\t\tmaxAge: 0,\n\t\t});\n\t\treturn ctx.json(null);\n\t},\n);\n\nexport const changeEmail = createAuthEndpoint(\n\t\"/user/change-email\",\n\t{\n\t\tmethod: \"POST\",\n\t\tquery: z\n\t\t\t.object({\n\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t})\n\t\t\t.optional(),\n\t\tbody: z.object({\n\t\t\tnewEmail: z.string().email(),\n\t\t\tcallbackURL: z.string().optional(),\n\t\t}),\n\t\tuse: [sessionMiddleware, redirectURLMiddleware],\n\t},\n\tasync (ctx) => {\n\t\tif (!ctx.context.options.user?.changeEmail?.enabled) {\n\t\t\tctx.context.logger.error(\"Change email is disabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Change email is disabled\",\n\t\t\t});\n\t\t}\n\n\t\tif (ctx.body.newEmail === ctx.context.session.user.email) {\n\t\t\tctx.context.logger.error(\"Email is the same\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Email is the same\",\n\t\t\t});\n\t\t}\n\t\tconst existingUser = await ctx.context.internalAdapter.findUserByEmail(\n\t\t\tctx.body.newEmail,\n\t\t);\n\t\tif (existingUser) {\n\t\t\tctx.context.logger.error(\"Email already exists\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Couldn't update your email\",\n\t\t\t});\n\t\t}\n\t\t/**\n\t\t * If the email is not verified, we can update the email\n\t\t */\n\t\tif (ctx.context.session.user.emailVerified !== true) {\n\t\t\tconst updatedUser = await ctx.context.internalAdapter.updateUserByEmail(\n\t\t\t\tctx.context.session.user.email,\n\t\t\t\t{\n\t\t\t\t\temail: ctx.body.newEmail,\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn ctx.json({\n\t\t\t\tuser: updatedUser,\n\t\t\t\tstatus: true,\n\t\t\t});\n\t\t}\n\n\t\t/**\n\t\t * If the email is verified, we need to send a verification email\n\t\t */\n\t\tif (!ctx.context.options.user.changeEmail.sendChangeEmailVerification) {\n\t\t\tctx.context.logger.error(\"Verification email isn't enabled.\");\n\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\tmessage: \"Verification email isn't enabled\",\n\t\t\t});\n\t\t}\n\n\t\tconst token = await createEmailVerificationToken(\n\t\t\tctx.context.secret,\n\t\t\tctx.context.session.user.email,\n\t\t\tctx.body.newEmail,\n\t\t);\n\t\tconst url = `${\n\t\t\tctx.context.baseURL\n\t\t}/verify-email?token=${token}&callbackURL=${\n\t\t\tctx.body.callbackURL || ctx.query?.currentURL || \"/\"\n\t\t}`;\n\t\tawait ctx.context.options.user.changeEmail.sendChangeEmailVerification(\n\t\t\tctx.context.session.user,\n\t\t\tctx.body.newEmail,\n\t\t\turl,\n\t\t\ttoken,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tuser: null,\n\t\t\tstatus: true,\n\t\t});\n\t},\n);\n","import { alphabet, generateRandomString } from \"../../crypto/random\";\nimport { hs256 } from \"../../crypto\";\nimport { createAuthEndpoint } from \"../call\";\nimport { HIDE_METADATA } from \"../../utils/hide-metadata\";\n\nexport const getCSRFToken = createAuthEndpoint(\n\t\"/csrf\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: HIDE_METADATA,\n\t},\n\tasync (ctx) => {\n\t\tconst csrfCookie = await ctx.getSignedCookie(\n\t\t\tctx.context.authCookies.csrfToken.name,\n\t\t\tctx.context.secret,\n\t\t);\n\n\t\tif (csrfCookie) {\n\t\t\tconst [token, _] = csrfCookie.split(\"!\") || [null, null];\n\t\t\treturn ctx.json({\n\t\t\t\tcsrfToken: token,\n\t\t\t});\n\t\t}\n\n\t\tconst token = generateRandomString(32, alphabet(\"a-z\", \"0-9\", \"A-Z\"));\n\t\tconst hash = await hs256(ctx.context.secret, token);\n\t\tconst cookie = `${token}!${hash}`;\n\t\tawait ctx.setSignedCookie(\n\t\t\tctx.context.authCookies.csrfToken.name,\n\t\t\tcookie,\n\t\t\tctx.context.secret,\n\t\t\tctx.context.authCookies.csrfToken.options,\n\t\t);\n\t\treturn ctx.json({\n\t\t\tcsrfToken: token,\n\t\t});\n\t},\n);\n","import { HIDE_METADATA } from \"../../utils/hide-metadata\";\nimport { createAuthEndpoint } from \"../call\";\n\nconst html = (errorCode: string = \"Unknown\") => `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Authentication Error</title>\n <style>\n :root {\n --bg-color: #f8f9fa;\n --text-color: #212529;\n --accent-color: #000000;\n --error-color: #dc3545;\n --border-color: #e9ecef;\n }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n background-color: var(--bg-color);\n color: var(--text-color);\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n line-height: 1.5;\n }\n .error-container {\n background-color: #ffffff;\n border-radius: 12px;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);\n padding: 2.5rem;\n text-align: center;\n max-width: 90%;\n width: 400px;\n }\n h1 {\n color: var(--error-color);\n font-size: 1.75rem;\n margin-bottom: 1rem;\n font-weight: 600;\n }\n p {\n margin-bottom: 1.5rem;\n color: #495057;\n }\n .btn {\n background-color: var(--accent-color);\n color: #ffffff;\n text-decoration: none;\n padding: 0.75rem 1.5rem;\n border-radius: 6px;\n transition: all 0.3s ease;\n display: inline-block;\n font-weight: 500;\n border: 2px solid var(--accent-color);\n }\n .btn:hover {\n background-color: #131721;\n }\n .error-code {\n font-size: 0.875rem;\n color: #6c757d;\n margin-top: 1.5rem;\n padding-top: 1.5rem;\n border-top: 1px solid var(--border-color);\n }\n .icon {\n font-size: 3rem;\n margin-bottom: 1rem;\n }\n </style>\n</head>\n<body>\n <div class=\"error-container\">\n <div class=\"icon\">⚠️</div>\n <h1>Better Auth Error</h1>\n <p>We encountered an issue while processing your request. Please try again or contact the application owner if the problem persists.</p>\n <a href=\"/\" id=\"returnLink\" class=\"btn\">Return to Application</a>\n <div class=\"error-code\">Error Code: <span id=\"errorCode\">${errorCode}</span></div>\n </div>\n</body>\n</html>`;\n\nexport const error = createAuthEndpoint(\n\t\"/error\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: HIDE_METADATA,\n\t},\n\tasync (c) => {\n\t\tconst query =\n\t\t\tnew URL(c.request?.url || \"\").searchParams.get(\"error\") || \"Unknown\";\n\t\treturn new Response(html(query), {\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t},\n\t\t});\n\t},\n);\n","import { HIDE_METADATA } from \"../../utils/hide-metadata\";\nimport { createAuthEndpoint } from \"../call\";\n\nexport const ok = createAuthEndpoint(\n\t\"/ok\",\n\t{\n\t\tmethod: \"GET\",\n\t\tmetadata: HIDE_METADATA,\n\t},\n\tasync (ctx) => {\n\t\treturn ctx.json({\n\t\t\tok: true,\n\t\t});\n\t},\n);\n","import { z, ZodObject, ZodOptional, ZodString } from \"zod\";\nimport { createAuthEndpoint } from \"../call\";\nimport { createEmailVerificationToken } from \"./email-verification\";\nimport { setSessionCookie } from \"../../cookies\";\nimport { APIError } from \"better-call\";\nimport type {\n\tAdditionalUserFieldsInput,\n\tBetterAuthOptions,\n\tInferSession,\n\tInferUser,\n\tUser,\n} from \"../../types\";\nimport type { toZod } from \"../../types/to-zod\";\nimport { parseAdditionalUserInput } from \"../../db/schema\";\nimport { getDate } from \"../../utils/date\";\nimport { redirectURLMiddleware } from \"../middlewares/redirect\";\n\nexport const signUpEmail = <O extends BetterAuthOptions>() =>\n\tcreateAuthEndpoint(\n\t\t\"/sign-up/email\",\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\tquery: z\n\t\t\t\t.object({\n\t\t\t\t\tcurrentURL: z.string().optional(),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t\tbody: z.record(z.string(), z.any()) as unknown as ZodObject<{\n\t\t\t\tname: ZodString;\n\t\t\t\temail: ZodString;\n\t\t\t\tpassword: ZodString;\n\t\t\t\tcallbackURL: ZodOptional<ZodString>;\n\t\t\t}> &\n\t\t\t\ttoZod<AdditionalUserFieldsInput<O>>,\n\t\t\tuse: [redirectURLMiddleware],\n\t\t},\n\t\tasync (ctx) => {\n\t\t\tif (!ctx.context.options.emailAndPassword?.enabled) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Email and password sign up is not enabled\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst body = ctx.body as any as User & {\n\t\t\t\tpassword: string;\n\t\t\t\tcallbackURL?: string;\n\t\t\t} & {\n\t\t\t\t[key: string]: any;\n\t\t\t};\n\t\t\tconst { name, email, password, image, callbackURL, ...additionalFields } =\n\t\t\t\tbody;\n\t\t\tconst isValidEmail = z.string().email().safeParse(email);\n\n\t\t\tif (!isValidEmail.success) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Invalid email\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst minPasswordLength = ctx.context.password.config.minPasswordLength;\n\t\t\tif (password.length < minPasswordLength) {\n\t\t\t\tctx.context.logger.error(\"Password is too short\");\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Password is too short\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst maxPasswordLength = ctx.context.password.config.maxPasswordLength;\n\t\t\tif (password.length > maxPasswordLength) {\n\t\t\t\tctx.context.logger.error(\"Password is too long\");\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Password is too long\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst dbUser = await ctx.context.internalAdapter.findUserByEmail(email);\n\t\t\tif (dbUser?.user) {\n\t\t\t\tctx.context.logger.info(`Sign-up attempt for existing email: ${email}`);\n\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\tmessage: \"Failed to create user\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tconst additionalData = parseAdditionalUserInput(\n\t\t\t\tctx.context.options,\n\t\t\t\tadditionalFields as any,\n\t\t\t);\n\t\t\tlet createdUser: User;\n\t\t\ttry {\n\t\t\t\tcreatedUser = await ctx.context.internalAdapter.createUser({\n\t\t\t\t\temail: email.toLowerCase(),\n\t\t\t\t\tname,\n\t\t\t\t\timage,\n\t\t\t\t\t...additionalData,\n\t\t\t\t\temailVerified: false,\n\t\t\t\t});\n\t\t\t\tif (!createdUser) {\n\t\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\t\tmessage: \"Failed to create user\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\tmessage: \"Failed to create user\",\n\t\t\t\t\tdetails: e,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!createdUser) {\n\t\t\t\tthrow new APIError(\"UNPROCESSABLE_ENTITY\", {\n\t\t\t\t\tmessage: \"Failed to create user\",\n\t\t\t\t});\n\t\t\t}\n\t\t\t/**\n\t\t\t * Link the account to the user\n\t\t\t */\n\t\t\tconst hash = await ctx.context.password.hash(password);\n\t\t\tawait ctx.context.internalAdapter.linkAccount({\n\t\t\t\tuserId: createdUser.id,\n\t\t\t\tproviderId: \"credential\",\n\t\t\t\taccountId: createdUser.id,\n\t\t\t\tpassword: hash,\n\t\t\t\texpiresAt: getDate(60 * 60 * 24 * 30, \"sec\"),\n\t\t\t});\n\t\t\tif (ctx.context.options.emailVerification?.sendOnSignUp) {\n\t\t\t\tconst token = await createEmailVerificationToken(\n\t\t\t\t\tctx.context.secret,\n\t\t\t\t\tcreatedUser.email,\n\t\t\t\t);\n\t\t\t\tconst url = `${\n\t\t\t\t\tctx.context.baseURL\n\t\t\t\t}/verify-email?token=${token}&callbackURL=${\n\t\t\t\t\tbody.callbackURL || ctx.query?.currentURL || \"/\"\n\t\t\t\t}`;\n\t\t\t\tawait ctx.context.options.emailVerification?.sendVerificationEmail?.(\n\t\t\t\t\tcreatedUser,\n\t\t\t\t\turl,\n\t\t\t\t\ttoken,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\t!ctx.context.options.emailAndPassword.autoSignIn ||\n\t\t\t\tctx.context.options.emailAndPassword.requireEmailVerification\n\t\t\t) {\n\t\t\t\treturn ctx.json(\n\t\t\t\t\t{\n\t\t\t\t\t\tuser: createdUser as InferUser<O>,\n\t\t\t\t\t\tsession: null,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tbody: body.callbackURL\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\turl: body.callbackURL,\n\t\t\t\t\t\t\t\t\tredirect: true,\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t\t\t\t\tsession: null,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\tcreatedUser.id,\n\t\t\t\tctx.request,\n\t\t\t);\n\t\t\tif (!session) {\n\t\t\t\tthrow new APIError(\"BAD_REQUEST\", {\n\t\t\t\t\tmessage: \"Failed to create session\",\n\t\t\t\t});\n\t\t\t}\n\t\t\tawait setSessionCookie(ctx, session.id);\n\t\t\treturn ctx.json(\n\t\t\t\t{\n\t\t\t\t\tuser: createdUser as InferUser<O>,\n\t\t\t\t\tsession: session as InferSession<O>,\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbody: body.callbackURL\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\turl: body.callbackURL,\n\t\t\t\t\t\t\t\tredirect: true,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: {\n\t\t\t\t\t\t\t\tuser: createdUser,\n\t\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\t\t},\n\t);\n","import { isTest } from \"std-env\";\n\nexport function getIp(req: Request | Headers): string | null {\n\tconst testIP = \"127.0.0.1\";\n\tif (isTest) {\n\t\treturn testIP;\n\t}\n\tconst keys = [\n\t\t\"x-client-ip\",\n\t\t\"x-forwarded-for\",\n\t\t\"cf-connecting-ip\",\n\t\t\"fastly-client-ip\",\n\t\t\"x-real-ip\",\n\t\t\"x-cluster-client-ip\",\n\t\t\"x-forwarded\",\n\t\t\"forwarded-for\",\n\t\t\"forwarded\",\n\t];\n\tconst headers = req instanceof Request ? req.headers : req;\n\tfor (const key of keys) {\n\t\tconst value = headers.get(key);\n\t\tif (typeof value === \"string\") {\n\t\t\tconst ip = value.split(\",\")[0].trim();\n\t\t\tif (ip) return ip;\n\t\t}\n\t}\n\treturn null;\n}\n","import type { AuthContext, RateLimit } from \"../../types\";\nimport { getIp } from \"../../utils/get-request-ip\";\nimport { logger } from \"../../utils/logger\";\n\nfunction shouldRateLimit(\n\tmax: number,\n\twindow: number,\n\trateLimitData: RateLimit,\n) {\n\tconst now = Date.now();\n\tconst windowInMs = window * 1000;\n\tconst timeSinceLastRequest = now - rateLimitData.lastRequest;\n\treturn timeSinceLastRequest < windowInMs && rateLimitData.count >= max;\n}\n\nfunction rateLimitResponse(retryAfter: number) {\n\treturn new Response(\n\t\tJSON.stringify({\n\t\t\tmessage: \"Too many requests. Please try again later.\",\n\t\t}),\n\t\t{\n\t\t\tstatus: 429,\n\t\t\tstatusText: \"Too Many Requests\",\n\t\t\theaders: {\n\t\t\t\t\"X-Retry-After\": retryAfter.toString(),\n\t\t\t},\n\t\t},\n\t);\n}\n\nfunction getRetryAfter(lastRequest: number, window: number) {\n\tconst now = Date.now();\n\tconst windowInMs = window * 1000;\n\treturn Math.ceil((lastRequest + windowInMs - now) / 1000);\n}\n\nfunction createDBStorage(ctx: AuthContext, tableName?: string) {\n\tconst model = tableName ?? \"rateLimit\";\n\tconst db = ctx.adapter;\n\treturn {\n\t\tget: async (key: string) => {\n\t\t\tconst res = await db.findOne<RateLimit>({\n\t\t\t\tmodel,\n\t\t\t\twhere: [{ field: \"key\", value: key }],\n\t\t\t});\n\t\t\treturn res;\n\t\t},\n\t\tset: async (key: string, value: RateLimit, _update?: boolean) => {\n\t\t\ttry {\n\t\t\t\tif (_update) {\n\t\t\t\t\tawait db.update({\n\t\t\t\t\t\tmodel: tableName ?? \"rateLimit\",\n\t\t\t\t\t\twhere: [{ field: \"key\", value: key }],\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tcount: value.count,\n\t\t\t\t\t\t\tlastRequest: value.lastRequest,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait db.create({\n\t\t\t\t\t\tmodel: tableName ?? \"rateLimit\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tcount: value.count,\n\t\t\t\t\t\t\tlastRequest: value.lastRequest,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tlogger.error(\"Error setting rate limit\", e);\n\t\t\t}\n\t\t},\n\t};\n}\n\nconst memory = new Map<string, RateLimit>();\nexport function getRateLimitStorage(ctx: AuthContext) {\n\tif (ctx.rateLimit.storage === \"secondary-storage\") {\n\t\treturn {\n\t\t\tget: async (key: string) => {\n\t\t\t\tconst stringified = await ctx.options.secondaryStorage?.get(key);\n\t\t\t\treturn stringified ? (JSON.parse(stringified) as RateLimit) : undefined;\n\t\t\t},\n\t\t\tset: async (key: string, value: RateLimit) => {\n\t\t\t\tawait ctx.options.secondaryStorage?.set?.(key, JSON.stringify(value));\n\t\t\t},\n\t\t};\n\t}\n\tconst storage = ctx.rateLimit.storage;\n\tif (storage === \"memory\") {\n\t\treturn {\n\t\t\tasync get(key: string) {\n\t\t\t\treturn memory.get(key);\n\t\t\t},\n\t\t\tasync set(key: string, value: RateLimit, _update?: boolean) {\n\t\t\t\tmemory.set(key, value);\n\t\t\t},\n\t\t};\n\t}\n\treturn createDBStorage(ctx, ctx.rateLimit.tableName);\n}\n\nexport async function onRequestRateLimit(req: Request, ctx: AuthContext) {\n\tif (!ctx.rateLimit.enabled) {\n\t\treturn;\n\t}\n\n\tconst baseURL = ctx.baseURL;\n\tconst path = req.url.replace(baseURL, \"\");\n\tlet window = ctx.rateLimit.window;\n\tlet max = ctx.rateLimit.max;\n\tconst key = getIp(req) + path;\n\tconst specialRules = getDefaultSpecialRules();\n\tconst specialRule = specialRules.find((rule) => rule.pathMatcher(path));\n\n\tif (specialRule) {\n\t\twindow = specialRule.window;\n\t\tmax = specialRule.max;\n\t}\n\n\tfor (const plugin of ctx.options.plugins || []) {\n\t\tif (plugin.rateLimit) {\n\t\t\tconst matchedRule = plugin.rateLimit.find((rule) =>\n\t\t\t\trule.pathMatcher(path),\n\t\t\t);\n\t\t\tif (matchedRule) {\n\t\t\t\twindow = matchedRule.window;\n\t\t\t\tmax = matchedRule.max;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (ctx.rateLimit.customRules) {\n\t\tconst customRule = ctx.rateLimit.customRules[path];\n\t\tif (customRule) {\n\t\t\twindow = customRule.window;\n\t\t\tmax = customRule.max;\n\t\t}\n\t}\n\n\tconst storage = getRateLimitStorage(ctx);\n\tconst data = await storage.get(key);\n\tconst now = Date.now();\n\n\tif (!data) {\n\t\tawait storage.set(key, {\n\t\t\tkey,\n\t\t\tcount: 1,\n\t\t\tlastRequest: now,\n\t\t});\n\t} else {\n\t\tconst timeSinceLastRequest = now - data.lastRequest;\n\n\t\tif (shouldRateLimit(max, window, data)) {\n\t\t\tconst retryAfter = getRetryAfter(data.lastRequest, window);\n\t\t\treturn rateLimitResponse(retryAfter);\n\t\t} else if (timeSinceLastRequest > window * 1000) {\n\t\t\t// Reset the count if the window has passed since the last request\n\t\t\tawait storage.set(key, {\n\t\t\t\t...data,\n\t\t\t\tcount: 1,\n\t\t\t\tlastRequest: now,\n\t\t\t});\n\t\t} else {\n\t\t\tawait storage.set(key, {\n\t\t\t\t...data,\n\t\t\t\tcount: data.count + 1,\n\t\t\t\tlastRequest: now,\n\t\t\t});\n\t\t}\n\t}\n}\n\nfunction getDefaultSpecialRules() {\n\tconst specialRules = [\n\t\t{\n\t\t\tpathMatcher(path: string) {\n\t\t\t\treturn path.startsWith(\"/sign-in\") || path.startsWith(\"/sign-up\");\n\t\t\t},\n\t\t\twindow: 10,\n\t\t\tmax: 3,\n\t\t},\n\t];\n\treturn specialRules;\n}\n"],"mappings":"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","names":["APIError","createRouter","statusCode","APIError","z","xchacha20poly1305","bytesToHex","hexToBytes","utf8ToBytes","managedNonce","sha256","crypto","constantTimeEqual","a","b","aBuffer","bBuffer","c","decodeHex","encodeHex","scryptAsync","getRandomValues","crypto","byteToBinary","byte","bytesToBinary","bytes","val","bytesToInteger","generateRandomInteger","max","bitLength","shift","bytes","crypto","result","bytesToInteger","generateRandomString","length","alphabet","i","patterns","patternSet","pattern","hs256","secretKey","message","enc","algorithm","key","crypto","signature","createEndpointCreator","createMiddleware","createMiddlewareCreator","optionsMiddleware","createAuthMiddleware","createAuthEndpoint","csrfMiddleware","createAuthMiddleware","z","ctx","originHeader","origin","csrfToken","APIError","csrfCookie","token","hash","expectedHash","hs256","APIError","generateCodeVerifier","z","generateStateOAuth","z","sha256","hashToBase64","data","buffer","sha256","compareHash","hash","hashBuffer","constantTimeEqual","generateState","callbackURL","code","generateStateOAuth","raw","hash","hashToBase64","parseState","state","z","TimeSpan","BetterAuthError","message","cause","env","isProduction","setSessionCookie","ctx","sessionToken","dontRememberMe","overrides","options","deleteSessionCookie","APIError","createConsola","consola","createLogger","options","args","logger","redirectURLMiddleware","createAuthMiddleware","ctx","body","query","headers","context","callbackURL","currentURL","trustedOrigins","validateURL","url","label","origin","logger","APIError","parseJWT","sha256","base64url","generateCodeChallenge","codeVerifier","codeChallengeBytes","getOAuth2Tokens","data","createAuthorizationURL","id","options","authorizationEndpoint","state","codeVerifier","scopes","claims","disablePkce","redirectURI","url","codeChallenge","generateCodeChallenge","claimsObj","acc","claim","betterFetch","validateAuthorizationCode","code","codeVerifier","redirectURI","options","tokenEndpoint","body","data","error","betterFetch","getOAuth2Tokens","getAccountTokens","tokens","accessToken","refreshToken","accessTokenExpiresAt","apple","options","tokenEndpoint","state","scopes","redirectURI","_scope","code","codeVerifier","validateAuthorizationCode","token","data","parseJWT","betterFetch","discord","options","state","scopes","redirectURI","_scopes","code","validateAuthorizationCode","token","profile","error","betterFetch","defaultAvatarNumber","format","betterFetch","facebook","options","state","scopes","redirectURI","_scopes","createAuthorizationURL","code","validateAuthorizationCode","token","profile","error","betterFetch","betterFetch","github","options","tokenEndpoint","state","scopes","codeVerifier","redirectURI","_scopes","createAuthorizationURL","code","validateAuthorizationCode","token","profile","error","betterFetch","emailVerified","data","e","parseJWT","google","options","state","scopes","codeVerifier","redirectURI","logger","BetterAuthError","_scopes","createAuthorizationURL","code","validateAuthorizationCode","token","user","parseJWT","betterFetch","parseJWT","microsoft","options","tenant","authorizationEndpoint","tokenEndpoint","data","scopes","createAuthorizationURL","code","codeVerifier","redirectURI","validateAuthorizationCode","token","user","parseJWT","profilePhotoSize","betterFetch","context","pictureBuffer","pictureBase64","e","logger","betterFetch","spotify","options","state","scopes","codeVerifier","redirectURI","_scopes","createAuthorizationURL","code","validateAuthorizationCode","token","profile","error","betterFetch","HIDE_METADATA","nanoid","generateId","size","parseJWT","twitch","options","state","scopes","redirectURI","_scopes","createAuthorizationURL","code","validateAuthorizationCode","token","idToken","logger","profile","parseJWT","betterFetch","twitter","options","data","_scopes","createAuthorizationURL","code","codeVerifier","redirectURI","validateAuthorizationCode","token","profile","error","betterFetch","socialProviders","apple","discord","facebook","github","microsoft","google","spotify","twitch","twitter","socialProviderList","TimeSpan","createJWT","validateJWT","z","APIError","APIError","getDate","span","unit","z","getSession","createAuthEndpoint","ctx","sessionCookieToken","session","deleteSessionCookie","expiresIn","updateAge","updatedSession","getDate","maxAge","setSessionCookie","error","getSessionFromCtx","sessionMiddleware","createAuthMiddleware","APIError","listSessions","activeSessions","revokeSession","id","findSession","revokeSessions","createEmailVerificationToken","secret","email","updateTo","createJWT","TimeSpan","sendVerificationEmail","createAuthEndpoint","z","redirectURLMiddleware","ctx","APIError","user","token","url","verifyEmail","jwt","validateJWT","e","parsed","session","getSessionFromCtx","updatedUser","signInOAuth","createAuthEndpoint","z","socialProviderList","redirectURLMiddleware","c","provider","p","APIError","cookie","currentURL","callbackURL","state","generateState","codeVerifier","generateCodeVerifier","url","signInEmail","ctx","email","password","user","credentialAccount","a","currentPassword","logger","token","createEmailVerificationToken","session","setSessionCookie","z","z","accountSchema","userSchema","val","sessionSchema","verificationSchema","getAllFields","options","table","schema","plugin","parseInputData","data","schema","fields","parsedData","key","parseUserInput","options","user","getAllFields","parseAdditionalUserInput","callbackOAuth","createAuthEndpoint","z","HIDE_METADATA","c","callbackURL","parseState","provider","parsedState","currentURL","storedState","logger","compareHash","codeVerifier","tokens","e","user","res","id","generateId","data","userSchema","redirectOnError","error","dbUser","userId","a","getAccountTokens","emailVerified","created","token","createEmailVerificationToken","url","session","setSessionCookie","APIError","signOut","createAuthEndpoint","ctx","sessionCookieToken","APIError","deleteSessionCookie","z","APIError","forgetPassword","createAuthEndpoint","z","redirectURLMiddleware","ctx","APIError","email","redirectTo","user","defaultExpiresIn","expiresAt","verificationToken","url","forgetPasswordCallback","token","callbackURL","verification","resetPassword","newPassword","id","userId","hashedPassword","ac","z","APIError","updateUser","createAuthEndpoint","z","sessionMiddleware","redirectURLMiddleware","ctx","body","APIError","name","image","rest","session","additionalFields","parseUserInput","user","changePassword","newPassword","currentPassword","revokeOtherSessions","minPasswordLength","maxPasswordLength","account","passwordHash","newSession","setSessionCookie","setPassword","deleteUser","password","sessionCookie","changeEmail","updatedUser","token","createEmailVerificationToken","url","getCSRFToken","createAuthEndpoint","HIDE_METADATA","ctx","csrfCookie","token","_","generateRandomString","alphabet","hash","hs256","cookie","html","errorCode","error","createAuthEndpoint","HIDE_METADATA","c","query","ok","createAuthEndpoint","HIDE_METADATA","ctx","z","APIError","signUpEmail","createAuthEndpoint","z","redirectURLMiddleware","ctx","APIError","body","name","email","password","image","callbackURL","additionalFields","minPasswordLength","maxPasswordLength","additionalData","parseAdditionalUserInput","createdUser","e","hash","getDate","token","createEmailVerificationToken","url","session","setSessionCookie","isTest","getIp","req","testIP","keys","headers","key","value","ip","shouldRateLimit","max","window","rateLimitData","now","windowInMs","rateLimitResponse","retryAfter","getRetryAfter","lastRequest","createDBStorage","ctx","tableName","model","db","key","value","_update","e","logger","memory","getRateLimitStorage","stringified","onRequestRateLimit","req","baseURL","path","getIp","specialRule","getDefaultSpecialRules","rule","plugin","matchedRule","customRule","storage","data","timeSinceLastRequest","APIError","getEndpoints","ctx","options","pluginEndpoints","acc","plugin","middlewares","m","middleware","context","endpoints","signInOAuth","callbackOAuth","getCSRFToken","getSession","signOut","signUpEmail","signInEmail","forgetPassword","resetPassword","verifyEmail","sendVerificationEmail","changeEmail","changePassword","setPassword","updateUser","deleteUser","forgetPasswordCallback","listSessions","revokeSession","revokeSessions","ok","error","api","key","value","c","hook","hookRes","endpointRes","e","afterPlugins","response","statusCode","obj","router","basePath","createRouter","csrfMiddleware","req","onRequestRateLimit","res","log","logger"]}
|
package/dist/client/plugins.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
1
|
import{atom as d}from"nanostores";var c=class extends Error{path;constructor(n,a){super(n),this.path=a}},p=class{constructor(n){this.s=n;this.statements=n}statements;newRole(n){return new m(n)}},m=class t{statements;constructor(n){this.statements=n}authorize(n,a){for(let[i,e]of Object.entries(n)){let s=this.statements[i];if(!s)return{success:!1,error:`You are not allowed to access resource: ${i}`};let o=a==="OR"?e.some(r=>s.includes(r)):e.every(r=>s.includes(r));return o?{success:o}:{success:!1,error:`unauthorized to access resource "${i}"`}}return{success:!1,error:"Not authorized"}}static fromString(n){let a=JSON.parse(n);if(typeof a!="object")throw new c("statements is not an object",".");for(let[i,e]of Object.entries(a)){if(typeof i!="string")throw new c("invalid resource identifier",i);if(!Array.isArray(e))throw new c("actions is not an array",i);for(let s=0;s<e.length;s++)if(typeof e[s]!="string")throw new c("action is not a string",`${i}[${s}]`)}return new t(a)}toString(){return JSON.stringify(this.statements)}};var y=t=>new p(t),h={organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]},f=y(h),k=f.newRole({organization:["update"],invitation:["create","cancel"],member:["create","update","delete"]}),B=f.newRole({organization:["update","delete"],member:["create","update","delete"],invitation:["create","cancel"]}),F=f.newRole({organization:[],member:[],invitation:[]});import{createFetch as Z}from"@better-fetch/fetch";import{env as q}from"std-env";import"nanostores";import{betterFetch as D}from"@better-fetch/fetch";import{atom as pe}from"nanostores";import"@better-fetch/fetch";import{atom as S,onMount as O}from"nanostores";var l=(t,n,a,i)=>{let e=S({data:null,error:null,isPending:!1,isRefetching:!1}),s=()=>{let r=typeof i=="function"?i({data:e.get().data,error:e.get().error,isPending:e.get().isPending}):i;return a(n,{...r,onSuccess:async u=>{e.set({data:u.data,error:null,isPending:!1,isRefetching:!1}),await r?.onSuccess?.(u)},async onError(u){e.set({error:u.error,data:null,isPending:!1,isRefetching:!1}),await r?.onError?.(u)},async onRequest(u){let g=e.get();e.set({isPending:g.data===null,data:g.data,error:null,isRefetching:!0}),await r?.onRequest?.(u)}})};t=Array.isArray(t)?t:[t];let o=!1;for(let r of t)r.subscribe(()=>{o?s():O(e,()=>(s(),o=!0,()=>{e.off(),r.off()}))});return e};var ve=t=>{let n=d(void 0),a=d(!1),i=d(!1);return{id:"organization",$InferServerPlugin:{},getActions:e=>({$Infer:{ActiveOrganization:{},Organization:{},Invitation:{},Member:{}},organization:{setActive(s){n.set(s)},hasPermission:async s=>await e("/organization/has-permission",{method:"POST",body:{permission:s.permission},...s.fetchOptions})}}),getAtoms:e=>{let s=l(a,"/organization/list",e,{method:"GET"}),o=l([n,i],"/organization/activate",e,()=>({method:"POST",credentials:"include",body:{orgId:n.get()}}));return{_listOrg:a,_activeOrgSignal:i,activeOrganization:o,listOrganizations:s}},atomListeners:[{matcher(e){return e==="/organization/create"||e==="/organization/delete"},signal:"_listOrg"},{matcher(e){return e.startsWith("/organization")},signal:"_activeOrgSignal"}]}};var Ie=()=>({id:"username",$InferServerPlugin:{}});import{WebAuthnError as A,startAuthentication as T,startRegistration as b}from"@simplewebauthn/browser";import{atom as R}from"nanostores";var x=(t,{_listPasskeys:n})=>({signIn:{passkey:async(e,s)=>{let o=await t("/passkey/generate-authenticate-options",{method:"POST",body:{email:e?.email}});if(!o.data)return o;try{let r=await T(o.data,e?.autoFill||!1),u=await t("/passkey/verify-authentication",{body:{response:r},...e?.fetchOptions,...s,method:"POST"});if(!u.data)return u}catch(r){console.log(r)}}},passkey:{addPasskey:async(e,s)=>{let o=await t("/passkey/generate-register-options",{method:"GET"});if(!o.data)return o;try{let r=await b(o.data),u=await t("/passkey/verify-registration",{...e?.fetchOptions,...s,body:{response:r,name:e?.name},method:"POST"});if(!u.data)return u;n.set(Math.random())}catch(r){return r instanceof A?r.code==="ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED"?{data:null,error:{message:"previously registered",status:400,statusText:"BAD_REQUEST"}}:r.code==="ERROR_CEREMONY_ABORTED"?{data:null,error:{message:"registration cancelled",status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:r.message,status:400,statusText:"BAD_REQUEST"}}:{data:null,error:{message:r instanceof Error?r.message:"unknown error",status:500,statusText:"INTERNAL_SERVER_ERROR"}}}}},$Infer:{}}),$e=()=>{let t=R();return{id:"passkey",$InferServerPlugin:{},getActions:n=>x(n,{_listPasskeys:t}),getAtoms(n){return{listPasskeys:l(t,"/passkey/list-user-passkeys",n,{method:"GET",credentials:"include"}),_listPasskeys:t}},pathMethods:{"/passkey/register":"POST","/passkey/authenticate":"POST"},atomListeners:[{matcher(n){return n==="/passkey/verify-registration"||n==="/passkey/delete-passkey"},signal:"_listPasskeys"}]}};var Ne=(t={redirect:!0,twoFactorPage:"/"})=>({id:"two-factor",$InferServerPlugin:{},atomListeners:[{matcher:n=>n.startsWith("/two-factor/"),signal:"_sessionSignal"}],pathMethods:{"/two-factor/disable":"POST","/two-factor/enable":"POST","/two-factor/send-otp":"POST","/two-factor/generate-backup-codes":"POST"},fetchPlugins:[{id:"two-factor",name:"two-factor",hooks:{async onSuccess(n){n.data?.twoFactorRedirect&&(t.redirect||t.twoFactorPage)&&typeof window<"u"&&(window.location.href=t.twoFactorPage)}}}]});var We=()=>({id:"magic-link",$InferServerPlugin:{}});var Ge=()=>({id:"phoneNumber",$InferServerPlugin:{},atomListeners:[{matcher(t){return t==="/phone-number/update"||t==="/phone-number/verify"},signal:"_sessionSignal"}]});var He=()=>({id:"anonymous",$InferServerPlugin:{},pathMethods:{"/sign-in/anonymous":"POST"}});var Je=t=>({id:"additional-fields-client",$InferServerPlugin:{}});var Ve=()=>({id:"better-auth-client",$InferServerPlugin:{},pathMethods:{"/admin/list-users":"GET"}});var Ye=()=>({id:"generic-oauth-client",$InferServerPlugin:{}});var et=()=>({id:"multi-session",$InferServerPlugin:{},pathMethods:{"/multi-session/sign-out-device-sessions":"POST"},atomListeners:[{matcher(t){return t==="/multi-session/set-active"},signal:"_sessionSignal"}]});export{Ve as adminClient,He as anonymousClient,Ye as genericOAuthClient,x as getPasskeyActions,Je as inferAdditionalFields,We as magicLinkClient,et as multiSessionClient,ve as organizationClient,$e as passkeyClient,Ge as phoneNumberClient,Ne as twoFactorClient,Ie as usernameClient};
|
|
2
|
+
//# sourceMappingURL=plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/organization/client.ts","../../src/plugins/organization/access/src/access.ts","../../src/plugins/organization/access/statement.ts","../../src/client/config.ts","../../src/utils/url.ts","../../src/client/fetch-plugins.ts","../../src/client/session-atom.ts","../../src/client/query.ts","../../src/plugins/username/client.ts","../../src/plugins/passkey/client.ts","../../src/plugins/two-factor/client.ts","../../src/plugins/magic-link/client.ts","../../src/plugins/phone-number/client.ts","../../src/plugins/anonymous/client.ts","../../src/plugins/additional-fields/client.ts","../../src/plugins/admin/client.ts","../../src/plugins/generic-oauth/client.ts","../../src/plugins/multi-session/client.ts"],"sourcesContent":["import { atom } from \"nanostores\";\nimport type {\n\tInvitation,\n\tMember,\n\tOrganization,\n} from \"../../plugins/organization/schema\";\nimport type { Prettify } from \"../../types/helper\";\nimport { defaultStatements, type AccessControl, type Role } from \"./access\";\nimport type { BetterAuthClientPlugin } from \"../../client/types\";\nimport type { organization } from \"./organization\";\nimport type { BetterFetchOption } from \"@better-fetch/fetch\";\nimport { useAuthQuery } from \"../../client\";\n\ninterface OrganizationClientOptions {\n\tac: AccessControl;\n\troles?: {\n\t\t[key in \"admin\" | \"member\" | \"owner\"]?: Role<any>;\n\t};\n}\n\nexport const organizationClient = <O extends OrganizationClientOptions>(\n\toptions?: O,\n) => {\n\tconst activeOrgId = atom<string | null | undefined>(undefined);\n\tconst _listOrg = atom<boolean>(false);\n\tconst _activeOrgSignal = atom<boolean>(false);\n\n\ttype DefaultStatements = typeof defaultStatements;\n\ttype Statements = O[\"ac\"] extends AccessControl<infer S>\n\t\t? S extends Record<string, Array<any>>\n\t\t\t? S & DefaultStatements\n\t\t\t: DefaultStatements\n\t\t: DefaultStatements;\n\treturn {\n\t\tid: \"organization\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof organization>,\n\t\tgetActions: ($fetch) => ({\n\t\t\t$Infer: {\n\t\t\t\tActiveOrganization: {} as Prettify<\n\t\t\t\t\tOrganization & {\n\t\t\t\t\t\tmembers: Prettify<\n\t\t\t\t\t\t\tMember & {\n\t\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\t\t\temail: string;\n\t\t\t\t\t\t\t\t\timage: string;\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>[];\n\t\t\t\t\t\tinvitations: Invitation[];\n\t\t\t\t\t}\n\t\t\t\t>,\n\t\t\t\tOrganization: {} as Organization,\n\t\t\t\tInvitation: {} as Invitation,\n\t\t\t\tMember: {} as Member,\n\t\t\t},\n\t\t\torganization: {\n\t\t\t\tsetActive(orgId: string | null) {\n\t\t\t\t\tactiveOrgId.set(orgId);\n\t\t\t\t},\n\t\t\t\thasPermission: async (data: {\n\t\t\t\t\tpermission: Partial<{\n\t\t\t\t\t\t//@ts-expect-error fix this later\n\t\t\t\t\t\t[key in keyof Statements]: Statements[key][number][];\n\t\t\t\t\t}>;\n\t\t\t\t\tfetchOptions?: BetterFetchOption;\n\t\t\t\t}) => {\n\t\t\t\t\treturn await $fetch<{\n\t\t\t\t\t\tsuccess: boolean;\n\t\t\t\t\t}>(\"/organization/has-permission\", {\n\t\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tpermission: data.permission,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t...data.fetchOptions,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t}),\n\t\tgetAtoms: ($fetch) => {\n\t\t\tconst listOrganizations = useAuthQuery<Organization[]>(\n\t\t\t\t_listOrg,\n\t\t\t\t\"/organization/list\",\n\t\t\t\t$fetch,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t},\n\t\t\t);\n\t\t\tconst activeOrganization = useAuthQuery<\n\t\t\t\tPrettify<\n\t\t\t\t\tOrganization & {\n\t\t\t\t\t\tmembers: (Member & {\n\t\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\t\tid: string;\n\t\t\t\t\t\t\t\tname: string;\n\t\t\t\t\t\t\t\temail: string;\n\t\t\t\t\t\t\t\timage: string;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t})[];\n\t\t\t\t\t\tinvitations: Invitation[];\n\t\t\t\t\t}\n\t\t\t\t>\n\t\t\t>(\n\t\t\t\t[activeOrgId, _activeOrgSignal],\n\t\t\t\t\"/organization/activate\",\n\t\t\t\t$fetch,\n\t\t\t\t() => ({\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t\tbody: {\n\t\t\t\t\t\torgId: activeOrgId.get(),\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\t_listOrg,\n\t\t\t\t_activeOrgSignal,\n\t\t\t\tactiveOrganization,\n\t\t\t\tlistOrganizations,\n\t\t\t};\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/organization/create\" || path === \"/organization/delete\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_listOrg\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn path.startsWith(\"/organization\");\n\t\t\t\t},\n\t\t\t\tsignal: \"_activeOrgSignal\",\n\t\t\t},\n\t\t],\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { StatementsPrimitive as Statements, Subset } from \"./types\";\n\nexport class ParsingError extends Error {\n\tpublic readonly path: string;\n\tconstructor(message: string, path: string) {\n\t\tsuper(message);\n\t\tthis.path = path;\n\t}\n}\n\ntype Connector = \"OR\" | \"AND\";\n\nexport class AccessControl<TStatements extends Statements = Statements> {\n\tprivate readonly statements: TStatements;\n\tconstructor(private readonly s: TStatements) {\n\t\tthis.statements = s;\n\t}\n\tpublic newRole<K extends keyof TStatements>(\n\t\tstatements: Subset<K, TStatements>,\n\t) {\n\t\treturn new Role<Subset<K, TStatements>>(statements);\n\t}\n}\n\nexport type AuthortizeResponse =\n\t| { success: false; error: string }\n\t| { success: true; error?: never };\n\nexport class Role<TStatements extends Statements> {\n\tpublic readonly statements: TStatements;\n\n\tconstructor(statements: TStatements) {\n\t\tthis.statements = statements;\n\t}\n\n\tpublic authorize<K extends keyof TStatements>(\n\t\trequest: Subset<K, TStatements>,\n\t\tconnector?: Connector,\n\t): AuthortizeResponse {\n\t\tfor (const [requestedResource, requestedActions] of Object.entries(\n\t\t\trequest,\n\t\t)) {\n\t\t\tconst allowedActions = this.statements[requestedResource];\n\t\t\tif (!allowedActions) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: `You are not allowed to access resource: ${requestedResource}`,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst success =\n\t\t\t\tconnector === \"OR\"\n\t\t\t\t\t? (requestedActions as string[]).some((requestedAction) =>\n\t\t\t\t\t\t\tallowedActions.includes(requestedAction),\n\t\t\t\t\t\t)\n\t\t\t\t\t: (requestedActions as string[]).every((requestedAction) =>\n\t\t\t\t\t\t\tallowedActions.includes(requestedAction),\n\t\t\t\t\t\t);\n\t\t\tif (success) {\n\t\t\t\treturn { success };\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: `unauthorized to access resource \"${requestedResource}\"`,\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: \"Not authorized\",\n\t\t};\n\t}\n\n\tstatic fromString<TStatements extends Statements>(s: string) {\n\t\tconst statements = JSON.parse(s) as TStatements;\n\n\t\tif (typeof statements !== \"object\") {\n\t\t\tthrow new ParsingError(\"statements is not an object\", \".\");\n\t\t}\n\t\tfor (const [resource, actions] of Object.entries(statements)) {\n\t\t\tif (typeof resource !== \"string\") {\n\t\t\t\tthrow new ParsingError(\"invalid resource identifier\", resource);\n\t\t\t}\n\t\t\tif (!Array.isArray(actions)) {\n\t\t\t\tthrow new ParsingError(\"actions is not an array\", resource);\n\t\t\t}\n\t\t\tfor (let i = 0; i < actions.length; i++) {\n\t\t\t\tif (typeof actions[i] !== \"string\") {\n\t\t\t\t\tthrow new ParsingError(\"action is not a string\", `${resource}[${i}]`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn new Role<TStatements>(statements);\n\t}\n\n\tpublic toString(): string {\n\t\treturn JSON.stringify(this.statements);\n\t}\n}\n","import { AccessControl } from \"./src/access\";\nimport type { StatementsPrimitive } from \"./src/types\";\n\nexport const createAccessControl = <S extends StatementsPrimitive>(\n\tstatements: S,\n) => {\n\treturn new AccessControl<S>(statements);\n};\n\nexport const defaultStatements = {\n\torganization: [\"update\", \"delete\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n\tinvitation: [\"create\", \"cancel\"],\n} as const;\n\nexport const defaultAc = createAccessControl(defaultStatements);\n\nexport const adminAc = defaultAc.newRole({\n\torganization: [\"update\"],\n\tinvitation: [\"create\", \"cancel\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n});\n\nexport const ownerAc = defaultAc.newRole({\n\torganization: [\"update\", \"delete\"],\n\tmember: [\"create\", \"update\", \"delete\"],\n\tinvitation: [\"create\", \"cancel\"],\n});\n\nexport const memberAc = defaultAc.newRole({\n\torganization: [],\n\tmember: [],\n\tinvitation: [],\n});\n\nexport const defaultRoles = {\n\tadmin: adminAc,\n\towner: ownerAc,\n\tmember: memberAc,\n};\n","import { createFetch } from \"@better-fetch/fetch\";\nimport { getBaseURL } from \"../utils/url\";\nimport { type Atom } from \"nanostores\";\nimport type { AtomListener, ClientOptions } from \"./types\";\nimport { addCurrentURL, csrfPlugin, redirectPlugin } from \"./fetch-plugins\";\n\nexport const getClientConfig = <O extends ClientOptions>(options?: O) => {\n\tconst $fetch = createFetch({\n\t\tbaseURL: getBaseURL(options?.fetchOptions?.baseURL || options?.baseURL),\n\t\tcredentials: \"include\",\n\t\tmethod: \"GET\",\n\t\t...options?.fetchOptions,\n\t\tplugins: options?.disableDefaultFetchPlugins\n\t\t\t? options.fetchOptions?.plugins\n\t\t\t: [\n\t\t\t\t\t...(!options?.disableCSRFTokenCheck ? [csrfPlugin] : []),\n\t\t\t\t\tredirectPlugin,\n\t\t\t\t\taddCurrentURL,\n\t\t\t\t\t...(options?.fetchOptions?.plugins?.filter(\n\t\t\t\t\t\t(pl) => pl !== undefined,\n\t\t\t\t\t) || []),\n\t\t\t\t\t...(options?.plugins\n\t\t\t\t\t\t?.flatMap((plugin) => plugin.fetchPlugins)\n\t\t\t\t\t\t.filter((pl) => pl !== undefined) || []),\n\t\t\t\t],\n\t});\n\n\tconst plugins = options?.plugins || [];\n\tlet pluginsActions = {} as Record<string, any>;\n\tlet pluginsAtoms = {} as Record<string, Atom<any>>;\n\tlet pluginPathMethods: Record<string, \"POST\" | \"GET\"> = {\n\t\t\"/sign-out\": \"POST\",\n\t\t\"/user/revoke-sessions\": \"POST\",\n\t};\n\tconst atomListeners: AtomListener[] = [\n\t\t{\n\t\t\tsignal: \"_sessionSignal\",\n\t\t\tmatcher(path) {\n\t\t\t\treturn (\n\t\t\t\t\tpath === \"/sign-out\" ||\n\t\t\t\t\tpath === \"/user/update\" ||\n\t\t\t\t\tpath.startsWith(\"/sign-in\") ||\n\t\t\t\t\tpath.startsWith(\"/sign-up\")\n\t\t\t\t);\n\t\t\t},\n\t\t},\n\t];\n\tfor (const plugin of plugins) {\n\t\tif (plugin.getActions) {\n\t\t\tObject.assign(pluginsActions, plugin.getActions?.($fetch));\n\t\t}\n\t\tif (plugin.getAtoms) {\n\t\t\tObject.assign(pluginsAtoms, plugin.getAtoms?.($fetch));\n\t\t}\n\t\tif (plugin.pathMethods) {\n\t\t\tObject.assign(pluginPathMethods, plugin.pathMethods);\n\t\t}\n\t\tif (plugin.atomListeners) {\n\t\t\tatomListeners.push(...plugin.atomListeners);\n\t\t}\n\t}\n\treturn {\n\t\tpluginsActions,\n\t\tpluginsAtoms,\n\t\tpluginPathMethods,\n\t\tatomListeners,\n\t\t$fetch,\n\t};\n};\n","import { env } from \"std-env\";\nimport { BetterAuthError } from \"../error\";\n\nfunction checkHasPath(url: string): boolean {\n\ttry {\n\t\tconst parsedUrl = new URL(url);\n\t\treturn parsedUrl.pathname !== \"/\";\n\t} catch (error) {\n\t\tthrow new BetterAuthError(\n\t\t\t`Invalid base URL: ${url}. Please provide a valid base URL.`,\n\t\t);\n\t}\n}\n\nfunction withPath(url: string, path = \"/api/auth\") {\n\tconst hasPath = checkHasPath(url);\n\tif (hasPath) {\n\t\treturn url;\n\t}\n\tpath = path.startsWith(\"/\") ? path : `/${path}`;\n\treturn `${url}${path}`;\n}\n\nexport function getBaseURL(url?: string, path?: string) {\n\tif (url) {\n\t\treturn withPath(url, path);\n\t}\n\tconst fromEnv =\n\t\tenv.BETTER_AUTH_URL ||\n\t\tenv.NEXT_PUBLIC_BETTER_AUTH_URL ||\n\t\tenv.PUBLIC_BETTER_AUTH_URL ||\n\t\tenv.NUXT_PUBLIC_BETTER_AUTH_URL ||\n\t\tenv.NUXT_PUBLIC_AUTH_URL ||\n\t\t(env.BASE_URL !== \"/\" ? env.BASE_URL : undefined);\n\n\tif (fromEnv) {\n\t\treturn withPath(fromEnv, path);\n\t}\n\n\tif (typeof window !== \"undefined\") {\n\t\treturn withPath(window.location.origin, path);\n\t}\n\treturn undefined;\n}\n\nexport function getOrigin(url: string) {\n\tconst parsedUrl = new URL(url);\n\treturn parsedUrl.origin.replace(\"http://\", \"\").replace(\"https://\", \"\");\n}\n","import { type BetterFetchPlugin, betterFetch } from \"@better-fetch/fetch\";\nimport { BetterAuthError } from \"../error\";\n\nexport const redirectPlugin = {\n\tid: \"redirect\",\n\tname: \"Redirect\",\n\thooks: {\n\t\tonSuccess(context) {\n\t\t\tif (context.data?.url && context.data?.redirect) {\n\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\twindow.location.href = context.data.url;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n\nexport const addCurrentURL = {\n\tid: \"add-current-url\",\n\tname: \"Add current URL\",\n\thooks: {\n\t\tonRequest(context) {\n\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\tconst url = new URL(context.url);\n\t\t\t\turl.searchParams.set(\"currentURL\", window.location.href);\n\t\t\t\tcontext.url = url;\n\t\t\t}\n\t\t\treturn context;\n\t\t},\n\t},\n} satisfies BetterFetchPlugin;\n\nexport const csrfPlugin = {\n\tid: \"csrf\",\n\tname: \"CSRF Check\",\n\tasync init(url, options) {\n\t\tif (options?.method !== \"GET\") {\n\t\t\toptions = options || {};\n\t\t\tconst { data, error } = await betterFetch<{\n\t\t\t\tcsrfToken: string;\n\t\t\t}>(\"/csrf\", {\n\t\t\t\tbody: undefined,\n\t\t\t\tbaseURL: options.baseURL,\n\t\t\t\tplugins: [],\n\t\t\t\tmethod: \"GET\",\n\t\t\t\tcredentials: \"include\",\n\t\t\t\tcustomFetchImpl: options.customFetchImpl,\n\t\t\t});\n\t\t\tif (error) {\n\t\t\t\tif (error.status === 404) {\n\t\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\t\"CSRF route not found. Make sure the server is running and the base URL is correct and includes the path (e.g. http://localhost:3000/api/auth).\",\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (error.status === 429) {\n\t\t\t\t\treturn new Response(\n\t\t\t\t\t\tJSON.stringify({\n\t\t\t\t\t\t\tmessage: \"Too many requests. Please try again later.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstatus: 429,\n\t\t\t\t\t\t\tstatusText: \"Too Many Requests\",\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow new BetterAuthError(\n\t\t\t\t\t\"Failed to fetch CSRF token: \" + error.message,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst csrfToken = data?.csrfToken;\n\t\t\toptions.body = {\n\t\t\t\t...options?.body,\n\t\t\t\tcsrfToken: csrfToken,\n\t\t\t};\n\t\t}\n\t\toptions.credentials = \"include\";\n\t\treturn { url, options };\n\t},\n} satisfies BetterFetchPlugin;\n","import type { BetterFetch } from \"@better-fetch/fetch\";\nimport { atom } from \"nanostores\";\nimport type { Prettify } from \"../types/helper\";\nimport type {\n\tClientOptions,\n\tInferSessionFromClient,\n\tInferUserFromClient,\n} from \"./types\";\nimport { useAuthQuery } from \"./query\";\n\nexport function getSessionAtom<Option extends ClientOptions>(\n\t$fetch: BetterFetch,\n) {\n\ttype UserWithAdditionalFields = InferUserFromClient<Option>;\n\ttype SessionWithAdditionalFields = InferSessionFromClient<Option>;\n\tconst $signal = atom<boolean>(false);\n\tconst session = useAuthQuery<{\n\t\tuser: Prettify<UserWithAdditionalFields>;\n\t\tsession: Prettify<SessionWithAdditionalFields>;\n\t}>($signal, \"/session\", $fetch, {\n\t\tmethod: \"GET\",\n\t});\n\treturn {\n\t\t$session: session,\n\t\t_sessionSignal: $signal,\n\t\t$Infer: {} as {\n\t\t\tSession: {\n\t\t\t\tsession: SessionWithAdditionalFields;\n\t\t\t\tuser: UserWithAdditionalFields;\n\t\t\t};\n\t\t},\n\t};\n}\n","import {\n\tBetterFetchError,\n\ttype BetterFetch,\n\ttype BetterFetchOption,\n} from \"@better-fetch/fetch\";\nimport { atom, onMount, type PreinitializedWritableAtom } from \"nanostores\";\n\nexport const useAuthQuery = <T>(\n\tinitializedAtom:\n\t\t| PreinitializedWritableAtom<any>\n\t\t| PreinitializedWritableAtom<any>[],\n\tpath: string,\n\t$fetch: BetterFetch,\n\toptions?:\n\t\t| ((value: {\n\t\t\t\tdata: null | T;\n\t\t\t\terror: null | BetterFetchError;\n\t\t\t\tisPending: boolean;\n\t\t }) => BetterFetchOption)\n\t\t| BetterFetchOption,\n) => {\n\tconst value = atom<{\n\t\tdata: null | T;\n\t\terror: null | BetterFetchError;\n\t\tisPending: boolean;\n\t\tisRefetching: boolean;\n\t}>({\n\t\tdata: null,\n\t\terror: null,\n\t\tisPending: false,\n\t\tisRefetching: false,\n\t});\n\n\tconst fn = () => {\n\t\tconst opts =\n\t\t\ttypeof options === \"function\"\n\t\t\t\t? options({\n\t\t\t\t\t\tdata: value.get().data,\n\t\t\t\t\t\terror: value.get().error,\n\t\t\t\t\t\tisPending: value.get().isPending,\n\t\t\t\t\t})\n\t\t\t\t: options;\n\t\treturn $fetch<T>(path, {\n\t\t\t...opts,\n\t\t\tonSuccess: async (context) => {\n\t\t\t\tvalue.set({\n\t\t\t\t\tdata: context.data,\n\t\t\t\t\terror: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t\tisRefetching: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onSuccess?.(context);\n\t\t\t},\n\t\t\tasync onError(context) {\n\t\t\t\tvalue.set({\n\t\t\t\t\terror: context.error,\n\t\t\t\t\tdata: null,\n\t\t\t\t\tisPending: false,\n\t\t\t\t\tisRefetching: false,\n\t\t\t\t});\n\t\t\t\tawait opts?.onError?.(context);\n\t\t\t},\n\t\t\tasync onRequest(context) {\n\t\t\t\tconst currentValue = value.get();\n\t\t\t\tvalue.set({\n\t\t\t\t\tisPending: currentValue.data === null,\n\t\t\t\t\tdata: currentValue.data,\n\t\t\t\t\terror: null,\n\t\t\t\t\tisRefetching: true,\n\t\t\t\t});\n\t\t\t\tawait opts?.onRequest?.(context);\n\t\t\t},\n\t\t});\n\t};\n\n\tinitializedAtom = Array.isArray(initializedAtom)\n\t\t? initializedAtom\n\t\t: [initializedAtom];\n\tlet isMounted = false;\n\tfor (const initAtom of initializedAtom) {\n\t\tinitAtom.subscribe(() => {\n\t\t\tif (isMounted) {\n\t\t\t\tfn();\n\t\t\t} else {\n\t\t\t\tonMount(value, () => {\n\t\t\t\t\tfn();\n\t\t\t\t\tisMounted = true;\n\t\t\t\t\treturn () => {\n\t\t\t\t\t\tvalue.off();\n\t\t\t\t\t\tinitAtom.off();\n\t\t\t\t\t};\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t}\n\treturn value;\n};\n","import type { username } from \".\";\nimport type { BetterAuthClientPlugin } from \"../../client/types\";\n\nexport const usernameClient = () => {\n\treturn {\n\t\tid: \"username\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof username>,\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { BetterFetch, BetterFetchOption } from \"@better-fetch/fetch\";\nimport {\n\tWebAuthnError,\n\tstartAuthentication,\n\tstartRegistration,\n} from \"@simplewebauthn/browser\";\nimport type {\n\tPublicKeyCredentialCreationOptionsJSON,\n\tPublicKeyCredentialRequestOptionsJSON,\n} from \"@simplewebauthn/types\";\nimport type { Session } from \"inspector\";\nimport type { User } from \"../../db/schema\";\nimport type { passkey as passkeyPl, Passkey } from \"../../plugins\";\nimport type { BetterAuthClientPlugin } from \"../../client/types\";\nimport { useAuthQuery } from \"../../client\";\nimport { atom } from \"nanostores\";\n\nexport const getPasskeyActions = (\n\t$fetch: BetterFetch,\n\t{\n\t\t_listPasskeys,\n\t}: {\n\t\t_listPasskeys: ReturnType<typeof atom<any>>;\n\t},\n) => {\n\tconst signInPasskey = async (\n\t\topts?: {\n\t\t\tautoFill?: boolean;\n\t\t\temail?: string;\n\t\t\tfetchOptions?: BetterFetchOption;\n\t\t},\n\t\toptions?: BetterFetchOption,\n\t) => {\n\t\tconst response = await $fetch<PublicKeyCredentialRequestOptionsJSON>(\n\t\t\t\"/passkey/generate-authenticate-options\",\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\tbody: {\n\t\t\t\t\temail: opts?.email,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\tif (!response.data) {\n\t\t\treturn response;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startAuthentication(\n\t\t\t\tresponse.data,\n\t\t\t\topts?.autoFill || false,\n\t\t\t);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tsession: Session;\n\t\t\t\tuser: User;\n\t\t\t}>(\"/passkey/verify-authentication\", {\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t},\n\t\t\t\t...opts?.fetchOptions,\n\t\t\t\t...options,\n\t\t\t\tmethod: \"POST\",\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.log(e);\n\t\t}\n\t};\n\n\tconst registerPasskey = async (\n\t\topts?: {\n\t\t\tfetchOptions?: BetterFetchOption;\n\t\t\t/**\n\t\t\t * The name of the passkey. This is used to\n\t\t\t * identify the passkey in the UI.\n\t\t\t */\n\t\t\tname?: string;\n\t\t},\n\t\tfetchOpts?: BetterFetchOption,\n\t) => {\n\t\tconst options = await $fetch<PublicKeyCredentialCreationOptionsJSON>(\n\t\t\t\"/passkey/generate-register-options\",\n\t\t\t{\n\t\t\t\tmethod: \"GET\",\n\t\t\t},\n\t\t);\n\t\tif (!options.data) {\n\t\t\treturn options;\n\t\t}\n\t\ttry {\n\t\t\tconst res = await startRegistration(options.data);\n\t\t\tconst verified = await $fetch<{\n\t\t\t\tpasskey: Passkey;\n\t\t\t}>(\"/passkey/verify-registration\", {\n\t\t\t\t...opts?.fetchOptions,\n\t\t\t\t...fetchOpts,\n\t\t\t\tbody: {\n\t\t\t\t\tresponse: res,\n\t\t\t\t\tname: opts?.name,\n\t\t\t\t},\n\t\t\t\tmethod: \"POST\",\n\t\t\t});\n\t\t\tif (!verified.data) {\n\t\t\t\treturn verified;\n\t\t\t}\n\t\t\t_listPasskeys.set(Math.random());\n\t\t} catch (e) {\n\t\t\tif (e instanceof WebAuthnError) {\n\t\t\t\tif (e.code === \"ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"previously registered\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (e.code === \"ERROR_CEREMONY_ABORTED\") {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tdata: null,\n\t\t\t\t\t\terror: {\n\t\t\t\t\t\t\tmessage: \"registration cancelled\",\n\t\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t\t},\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tdata: null,\n\t\t\t\t\terror: {\n\t\t\t\t\t\tmessage: e.message,\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tstatusText: \"BAD_REQUEST\",\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tdata: null,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: e instanceof Error ? e.message : \"unknown error\",\n\t\t\t\t\tstatus: 500,\n\t\t\t\t\tstatusText: \"INTERNAL_SERVER_ERROR\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t};\n\n\treturn {\n\t\tsignIn: {\n\t\t\t/**\n\t\t\t * Sign in with a registered passkey\n\t\t\t */\n\t\t\tpasskey: signInPasskey,\n\t\t},\n\t\tpasskey: {\n\t\t\t/**\n\t\t\t * Add a passkey to the user account\n\t\t\t */\n\t\t\taddPasskey: registerPasskey,\n\t\t},\n\t\t/**\n\t\t * Inferred Internal Types\n\t\t */\n\t\t$Infer: {} as {\n\t\t\tPasskey: Passkey;\n\t\t},\n\t};\n};\n\nexport const passkeyClient = () => {\n\tconst _listPasskeys = atom<any>();\n\treturn {\n\t\tid: \"passkey\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof passkeyPl>,\n\t\tgetActions: ($fetch) =>\n\t\t\tgetPasskeyActions($fetch, {\n\t\t\t\t_listPasskeys,\n\t\t\t}),\n\t\tgetAtoms($fetch) {\n\t\t\tconst listPasskeys = useAuthQuery<Passkey[]>(\n\t\t\t\t_listPasskeys,\n\t\t\t\t\"/passkey/list-user-passkeys\",\n\t\t\t\t$fetch,\n\t\t\t\t{\n\t\t\t\t\tmethod: \"GET\",\n\t\t\t\t\tcredentials: \"include\",\n\t\t\t\t},\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tlistPasskeys,\n\t\t\t\t_listPasskeys,\n\t\t\t};\n\t\t},\n\t\tpathMethods: {\n\t\t\t\"/passkey/register\": \"POST\",\n\t\t\t\"/passkey/authenticate\": \"POST\",\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/passkey/verify-registration\" ||\n\t\t\t\t\t\tpath === \"/passkey/delete-passkey\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_listPasskeys\",\n\t\t\t},\n\t\t],\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { BetterAuthClientPlugin } from \"../../client/types\";\nimport type { twoFactor as twoFa } from \"../../plugins/two-factor\";\n\nexport const twoFactorClient = (\n\toptions: {\n\t\ttwoFactorPage: string;\n\t\t/**\n\t\t * Redirect to the two factor page. If twoFactorPage\n\t\t * is not set this will redirect to the root path.\n\t\t * @default true\n\t\t */\n\t\tredirect?: boolean;\n\t} = {\n\t\tredirect: true,\n\t\ttwoFactorPage: \"/\",\n\t},\n) => {\n\treturn {\n\t\tid: \"two-factor\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof twoFa>,\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher: (path) => path.startsWith(\"/two-factor/\"),\n\t\t\t\tsignal: \"_sessionSignal\",\n\t\t\t},\n\t\t],\n\t\tpathMethods: {\n\t\t\t\"/two-factor/disable\": \"POST\",\n\t\t\t\"/two-factor/enable\": \"POST\",\n\t\t\t\"/two-factor/send-otp\": \"POST\",\n\t\t\t\"/two-factor/generate-backup-codes\": \"POST\",\n\t\t},\n\t\tfetchPlugins: [\n\t\t\t{\n\t\t\t\tid: \"two-factor\",\n\t\t\t\tname: \"two-factor\",\n\t\t\t\thooks: {\n\t\t\t\t\tasync onSuccess(context) {\n\t\t\t\t\t\tif (context.data?.twoFactorRedirect) {\n\t\t\t\t\t\t\tif (options.redirect || options.twoFactorPage) {\n\t\t\t\t\t\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\t\t\t\t\t\twindow.location.href = options.twoFactorPage;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t],\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { magicLink } from \".\";\nimport type { BetterAuthClientPlugin } from \"../../client/types\";\n\nexport const magicLinkClient = () => {\n\treturn {\n\t\tid: \"magic-link\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof magicLink>,\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { phoneNumber } from \".\";\nimport type { BetterAuthClientPlugin } from \"../../client/types\";\n\nexport const phoneNumberClient = () => {\n\treturn {\n\t\tid: \"phoneNumber\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof phoneNumber>,\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn (\n\t\t\t\t\t\tpath === \"/phone-number/update\" || path === \"/phone-number/verify\"\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tsignal: \"_sessionSignal\",\n\t\t\t},\n\t\t],\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { anonymous } from \".\";\nimport type { BetterAuthClientPlugin } from \"../../client/types\";\n\nexport const anonymousClient = () => {\n\treturn {\n\t\tid: \"anonymous\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof anonymous>,\n\t\tpathMethods: {\n\t\t\t\"/sign-in/anonymous\": \"POST\",\n\t\t},\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { NeverToUnknown } from \"@prisma/client/runtime/library\";\nimport type { FieldAttribute } from \"../../db\";\nimport type { BetterAuthClientPlugin, BetterAuthOptions } from \"../../types\";\nimport type { BetterAuthPlugin } from \"../../types\";\n\nexport const inferAdditionalFields = <\n\tT,\n\tS extends {\n\t\tuser?: {\n\t\t\t[key: string]: FieldAttribute;\n\t\t};\n\t\tsession?: {\n\t\t\t[key: string]: FieldAttribute;\n\t\t};\n\t} = {},\n>(\n\tschema?: S,\n) => {\n\ttype Opts = T extends BetterAuthOptions\n\t\t? T\n\t\t: T extends {\n\t\t\t\t\toptions: BetterAuthOptions;\n\t\t\t\t}\n\t\t\t? T[\"options\"]\n\t\t\t: never;\n\n\ttype Plugin = Opts extends never\n\t\t? S extends {\n\t\t\t\tuser?: {\n\t\t\t\t\t[key: string]: FieldAttribute;\n\t\t\t\t};\n\t\t\t\tsession?: {\n\t\t\t\t\t[key: string]: FieldAttribute;\n\t\t\t\t};\n\t\t\t}\n\t\t\t? {\n\t\t\t\t\tid: \"additional-fields-client\";\n\t\t\t\t\tschema: {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tfields: S[\"user\"] extends object ? S[\"user\"] : {};\n\t\t\t\t\t\t};\n\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\tfields: S[\"session\"] extends object ? S[\"session\"] : {};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t: never\n\t\t: Opts extends BetterAuthOptions\n\t\t\t? {\n\t\t\t\t\tid: \"additional-fields\";\n\t\t\t\t\tschema: {\n\t\t\t\t\t\tuser: {\n\t\t\t\t\t\t\tfields: Opts[\"user\"] extends {\n\t\t\t\t\t\t\t\tadditionalFields: infer U;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t? U\n\t\t\t\t\t\t\t\t: {};\n\t\t\t\t\t\t};\n\t\t\t\t\t\tsession: {\n\t\t\t\t\t\t\tfields: Opts[\"session\"] extends {\n\t\t\t\t\t\t\t\tadditionalFields: infer U;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t? U\n\t\t\t\t\t\t\t\t: {};\n\t\t\t\t\t\t};\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t: never;\n\n\treturn {\n\t\tid: \"additional-fields-client\",\n\t\t$InferServerPlugin: {} as Plugin extends BetterAuthPlugin\n\t\t\t? Plugin\n\t\t\t: undefined,\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { admin } from \".\";\nimport type { BetterAuthClientPlugin } from \"../../types\";\n\nexport const adminClient = () => {\n\treturn {\n\t\tid: \"better-auth-client\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof admin>,\n\t\tpathMethods: {\n\t\t\t\"/admin/list-users\": \"GET\",\n\t\t},\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { genericOAuth } from \".\";\nimport type { BetterAuthClientPlugin } from \"../../types\";\n\nexport const genericOAuthClient = () => {\n\treturn {\n\t\tid: \"generic-oauth-client\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof genericOAuth>,\n\t} satisfies BetterAuthClientPlugin;\n};\n","import type { multiSession } from \".\";\nimport type { BetterAuthClientPlugin } from \"../../types\";\n\nexport const multiSessionClient = () => {\n\treturn {\n\t\tid: \"multi-session\",\n\t\t$InferServerPlugin: {} as ReturnType<typeof multiSession>,\n\t\tpathMethods: {\n\t\t\t\"/multi-session/sign-out-device-sessions\": \"POST\",\n\t\t},\n\t\tatomListeners: [\n\t\t\t{\n\t\t\t\tmatcher(path) {\n\t\t\t\t\treturn path === \"/multi-session/set-active\";\n\t\t\t\t},\n\t\t\t\tsignal: \"_sessionSignal\",\n\t\t\t},\n\t\t],\n\t} satisfies BetterAuthClientPlugin;\n};\n"],"mappings":"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","names":["atom","ParsingError","message","path","AccessControl","s","statements","Role","_Role","request","connector","requestedResource","requestedActions","allowedActions","success","requestedAction","resource","actions","i","createAccessControl","statements","AccessControl","defaultStatements","defaultAc","adminAc","ownerAc","memberAc","createFetch","env","betterFetch","atom","atom","onMount","useAuthQuery","initializedAtom","path","$fetch","options","value","fn","opts","context","currentValue","isMounted","initAtom","organizationClient","options","activeOrgId","atom","_listOrg","_activeOrgSignal","$fetch","orgId","data","listOrganizations","useAuthQuery","activeOrganization","path","usernameClient","WebAuthnError","startAuthentication","startRegistration","atom","getPasskeyActions","$fetch","_listPasskeys","opts","options","response","res","startAuthentication","verified","e","fetchOpts","startRegistration","WebAuthnError","passkeyClient","useAuthQuery","path","twoFactorClient","options","path","context","magicLinkClient","phoneNumberClient","path","anonymousClient","inferAdditionalFields","schema","adminClient","genericOAuthClient","multiSessionClient","path"]}
|