diff --git a/apps/web/.env.test b/apps/web/.env.test index 485b227f41f..ec040f4182f 100644 --- a/apps/web/.env.test +++ b/apps/web/.env.test @@ -7,7 +7,7 @@ PORT=3002 QUICK_CREATE_ENABLED=true RATE_LIMIT_ENABLED=false SECRET_PASSWORD=abcdef1234567890abcdef1234567890 -SMTP_HOST=localhost +SMTP_HOST=0.0.0.0 SMTP_PORT=1025 SMTP_REJECT_UNAUTHORIZED=false SUPPORT_EMAIL=support@rallly.co diff --git a/apps/web/package.json b/apps/web/package.json index f26b7e12765..a997aa59e98 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -62,7 +62,7 @@ "@vercel/functions": "^3.3.6", "ai": "^6.0.87", "arctic": "^3.7.0", - "better-auth": "^1.4.7", + "better-auth": "^1.6.0", "calendar-link": "^2.6.0", "class-variance-authority": "^0.7.1", "color-hash": "^2.0.2", diff --git a/apps/web/src/lib/auth.ts b/apps/web/src/lib/auth.ts index a357fbc5d07..89983b43da6 100644 --- a/apps/web/src/lib/auth.ts +++ b/apps/web/src/lib/auth.ts @@ -4,11 +4,11 @@ import { absoluteUrl } from "@rallly/utils/absolute-url"; import type { BetterAuthPlugin } from "better-auth"; import { APIError, betterAuth } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; +import { createAuthMiddleware } from "better-auth/api"; import { admin, anonymous, captcha, - createAuthMiddleware, emailOTP, genericOAuth, lastLoginMethod, @@ -35,56 +35,61 @@ const baseURL = absoluteUrl("/api/better-auth"); const logger = createLogger("auth"); -const plugins: BetterAuthPlugin[] = []; - -if (env.TURNSTILE_SECRET_KEY) { - plugins.push( - captcha({ - provider: "cloudflare-turnstile", - secretKey: env.TURNSTILE_SECRET_KEY, - endpoints: ["/sign-up/email"], - }), +if (env.OIDC_ISSUER_URL) { + logger.info( + "OIDC_ISSUER_URL is no longer used. You can remove it from your environment variables.", ); } -if (env.OIDC_CLIENT_ID && env.OIDC_CLIENT_SECRET && env.OIDC_DISCOVERY_URL) { - if (env.OIDC_ISSUER_URL) { - logger.info( - "OIDC_ISSUER_URL is no longer used. You can remove it from your environment variables.", - ); - } - plugins.push( - genericOAuth({ - config: [ - { - providerId: "oidc", - discoveryUrl: env.OIDC_DISCOVERY_URL, - clientId: env.OIDC_CLIENT_ID, - clientSecret: env.OIDC_CLIENT_SECRET, - scopes: ["openid", "profile", "email"], - redirectURI: absoluteUrl("/api/auth/callback/oidc"), - pkce: true, - mapProfileToUser(profile) { - return { - name: getValueByPath(profile, env.OIDC_NAME_CLAIM_PATH) as string, - email: getValueByPath( - profile, - env.OIDC_EMAIL_CLAIM_PATH, - ) as string, - image: getValueByPath( - profile, - env.OIDC_PICTURE_CLAIM_PATH, - ) as string, - }; - }, - }, - ], - }), - ); -} +// Conditional plugins are typed as BetterAuthPlugin[] — they don't add user +// fields so losing their specific types doesn't affect session type inference. +const conditionalPlugins: BetterAuthPlugin[] = [ + ...(env.TURNSTILE_SECRET_KEY + ? [ + captcha({ + provider: "cloudflare-turnstile", + secretKey: env.TURNSTILE_SECRET_KEY, + endpoints: ["/sign-up/email"], + }), + ] + : []), + ...(env.OIDC_CLIENT_ID && env.OIDC_CLIENT_SECRET && env.OIDC_DISCOVERY_URL + ? [ + genericOAuth({ + config: [ + { + providerId: "oidc", + discoveryUrl: env.OIDC_DISCOVERY_URL, + clientId: env.OIDC_CLIENT_ID, + clientSecret: env.OIDC_CLIENT_SECRET, + scopes: ["openid", "profile", "email"], + redirectURI: absoluteUrl("/api/auth/callback/oidc"), + pkce: true, + mapProfileToUser(profile) { + return { + name: getValueByPath( + profile, + env.OIDC_NAME_CLAIM_PATH, + ) as string, + email: getValueByPath( + profile, + env.OIDC_EMAIL_CLAIM_PATH, + ) as string, + image: getValueByPath( + profile, + env.OIDC_PICTURE_CLAIM_PATH, + ) as string, + }; + }, + }, + ], + }), + ] + : []), +]; export const authLib = betterAuth({ - appName: "Rallly", + appName: env.APP_NAME, secret: env.SECRET_PASSWORD, experimental: { joins: true, @@ -92,6 +97,12 @@ export const authLib = betterAuth({ emailAndPassword: { enabled: env.EMAIL_LOGIN_ENABLED !== "false", requireEmailVerification: true, + onExistingUserSignUp: async ({ user }, request) => { + await authLib.api.sendVerificationOTP({ + body: { email: user.email, type: "email-verification" }, + request, + }); + }, sendResetPassword: async ({ user, url }) => { const locale = "locale" in user ? (user.locale as string) : await getLocale(); @@ -118,7 +129,6 @@ export const authLib = betterAuth({ transaction: false, // when set to true, there is an issue where the after() hook is called before the user is actually created in the database }), plugins: [ - ...plugins, admin(), anonymous({ emailDomainName: "rallly.co", @@ -164,6 +174,7 @@ export const authLib = betterAuth({ } }, }), + ...conditionalPlugins, ], socialProviders: { google: diff --git a/apps/web/tests/authentication.spec.ts b/apps/web/tests/authentication.spec.ts index 31c321586e4..f1ca9715bc0 100644 --- a/apps/web/tests/authentication.spec.ts +++ b/apps/web/tests/authentication.spec.ts @@ -40,7 +40,9 @@ test.describe.serial(() => { }); test.describe("Existing User", () => { - test("can't register with the same email", async ({ page }) => { + test("sends OTP to existing user when registering with existing email", async ({ + page, + }) => { await page.goto("/register"); await page.getByText("Create Your Account").waitFor(); @@ -53,9 +55,15 @@ test.describe.serial(() => { await page.getByRole("button", { name: "Continue", exact: true }).click(); - await expect( - page.getByText("A user with that email already exists"), - ).toBeVisible(); + // Should show the verification code prompt (not an error) to prevent email enumeration + await page.getByRole("heading", { name: "Finish Logging In" }).waitFor(); + + // The existing user should have received a sign-in OTP + const code = await getCode(testUserEmail); + await page.getByPlaceholder("Enter your 6-digit code").fill(code); + + // Existing user should be signed in + await expect(page.getByText("Test User")).toBeVisible(); }); test("can login with password", async ({ page }) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f0a443f1b2f..78a8823f936 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -320,8 +320,8 @@ importers: specifier: ^3.7.0 version: 3.7.0 better-auth: - specifier: ^1.4.7 - version: 1.4.18(@prisma/client@7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(mysql2@3.15.3)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.18.0)(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.11)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) + specifier: ^1.6.0 + version: 1.6.0(@opentelemetry/api@1.9.0)(@prisma/client@7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(mysql2@3.15.3)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.18.0)(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.11)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) calendar-link: specifier: ^2.6.0 version: 2.11.0 @@ -1716,23 +1716,79 @@ packages: '@types/react': optional: true - '@better-auth/core@1.4.18': - resolution: {integrity: sha512-q+awYgC7nkLEBdx2sW0iJjkzgSHlIxGnOpsN1r/O1+a4m7osJNHtfK2mKJSL1I+GfNyIlxJF8WvD/NLuYMpmcg==} + '@better-auth/core@1.6.0': + resolution: {integrity: sha512-LmdPTyKRDn6iCcXBGlOHOyzpJl1W/3w64zrEbhhHaWmtdpzQWlY8awlWBoDTL9eL4TAusr9dDvwIbMYTvEqaeA==} peerDependencies: - '@better-auth/utils': 0.3.0 + '@better-auth/utils': 0.4.0 '@better-fetch/fetch': 1.1.21 - better-call: 1.1.8 + '@cloudflare/workers-types': '>=4' + '@opentelemetry/api': ^1.9.0 + better-call: 1.3.5 jose: ^6.1.0 kysely: ^0.28.5 nanostores: ^1.0.1 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + + '@better-auth/drizzle-adapter@1.6.0': + resolution: {integrity: sha512-iMgvZlrL4FI63CGaxLqE5rgA2Q9VVmc2fQIP7N5E79nGAEpHtztstHFPlen9RDLRJA4xa3wuyVaPSILylwE+LA==} + peerDependencies: + '@better-auth/core': ^1.6.0 + '@better-auth/utils': 0.4.0 + drizzle-orm: '>=0.41.0' + peerDependenciesMeta: + drizzle-orm: + optional: true + + '@better-auth/kysely-adapter@1.6.0': + resolution: {integrity: sha512-ZLEp2j3jquX7wrPQ7tPOSRAjmMoHhdrsgkuH9Bp/fgNZV7M1eiwAY6fHRGKad6KIldoI+iazMUIm60v11fIHCg==} + peerDependencies: + '@better-auth/core': ^1.6.0 + '@better-auth/utils': 0.4.0 + kysely: ^0.27.0 || ^0.28.0 + peerDependenciesMeta: + kysely: + optional: true + + '@better-auth/memory-adapter@1.6.0': + resolution: {integrity: sha512-FbLmz6ujltw8RDUkBzutwIfoV+q9Mu0gLVrfhDAb9INe+jLcaQikiIjFdVwPzpx+bOs6bWTDfylrlI6+Ytxs3Q==} + peerDependencies: + '@better-auth/core': ^1.6.0 + '@better-auth/utils': 0.4.0 + + '@better-auth/mongo-adapter@1.6.0': + resolution: {integrity: sha512-EYZwMpcpoaLRnfhEr+k+MTKS8SKi51TWh1b7bLSy+yHLL0PdbadFsGYZPgzLbZEaq4kUP0asMzXxA+blutjOQQ==} + peerDependencies: + '@better-auth/core': ^1.6.0 + '@better-auth/utils': 0.4.0 + mongodb: ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + mongodb: + optional: true + + '@better-auth/prisma-adapter@1.6.0': + resolution: {integrity: sha512-8x/aqR1NckGiC49P02cxuH0wLzbJXvE/v2NnMEFo6h3uWq4ESYL0jTY9vNlFeVIKDyGSzrbteofzzG+yQv0wAQ==} + peerDependencies: + '@better-auth/core': ^1.6.0 + '@better-auth/utils': 0.4.0 + '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 + prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + '@prisma/client': + optional: true + prisma: + optional: true - '@better-auth/telemetry@1.4.18': - resolution: {integrity: sha512-e5rDF8S4j3Um/0LIVATL2in9dL4lfO2fr2v1Wio4qTMRbfxqnUDTa+6SZtwdeJrbc4O+a3c+IyIpjG9Q/6GpfQ==} + '@better-auth/telemetry@1.6.0': + resolution: {integrity: sha512-JrJyx1ioswEAh8rB7mVxEFIDLl6AK3W3rtqc2MK6BgvcmKveWJ730Eoi/PNvi0b4tFk4kczmuQITm69uMbnTvQ==} peerDependencies: - '@better-auth/core': 1.4.18 + '@better-auth/core': ^1.6.0 + '@better-auth/utils': 0.4.0 + '@better-fetch/fetch': 1.1.21 - '@better-auth/utils@0.3.0': - resolution: {integrity: sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==} + '@better-auth/utils@0.4.0': + resolution: {integrity: sha512-RpMtLUIQAEWMgdPLNVbIF5ON2mm+CH0U3rCdUCU1VyeAUui4m38DyK7/aXMLZov2YDjG684pS1D0MBllrmgjQA==} '@better-fetch/fetch@1.1.21': resolution: {integrity: sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==} @@ -5700,8 +5756,8 @@ packages: resolution: {integrity: sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==} engines: {node: '>=10.0.0'} - better-auth@1.4.18: - resolution: {integrity: sha512-bnyifLWBPcYVltH3RhS7CM62MoelEqC6Q+GnZwfiDWNfepXoQZBjEvn4urcERC7NTKgKq5zNBM8rvPvRBa6xcg==} + better-auth@1.6.0: + resolution: {integrity: sha512-reEK4X37w/X0Wi0ZpNSo6w3j9F2tsA7ebWn2AmWTzkceiatkxcadRg9aK+Mirw2PY56GQqX9dBgqBG6XMNU/Zg==} peerDependencies: '@lynx-js/react': '*' '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 @@ -5762,8 +5818,8 @@ packages: vue: optional: true - better-call@1.1.8: - resolution: {integrity: sha512-XMQ2rs6FNXasGNfMjzbyroSwKwYbZ/T3IxruSS6U2MJRsSYh3wYtG3o6H00ZlKZ/C/UPOAD97tqgQJNsxyeTXw==} + better-call@1.3.5: + resolution: {integrity: sha512-kOFJkBP7utAQLEYrobZm3vkTH8mXq5GNgvjc5/XEST1ilVHaxXUXfeDeFlqoETMtyqS4+3/h4ONX2i++ebZrvA==} peerDependencies: zod: ^4.0.0 peerDependenciesMeta: @@ -7742,8 +7798,8 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - kysely@0.28.11: - resolution: {integrity: sha512-zpGIFg0HuoC893rIjYX1BETkVWdDnzTzF5e0kWXJFg5lE0k1/LfNWBejrcnOFu8Q2Rfq/hTDTU7XLUM8QOrpzg==} + kysely@0.28.15: + resolution: {integrity: sha512-r2clcf7HLWvDXaVUEvQymXJY4i3bSOIV3xsL/Upy3ZfSv5HeKsk9tsqbBptLvth5qHEIhxeHTA2jNLyQABkLBA==} engines: {node: '>=20.0.0'} lcm@0.0.3: @@ -8345,8 +8401,8 @@ packages: engines: {node: ^18 || >=20} hasBin: true - nanostores@1.1.0: - resolution: {integrity: sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA==} + nanostores@1.2.0: + resolution: {integrity: sha512-F0wCzbsH80G7XXo0Jd9/AVQC7ouWY6idUCTnMwW5t/Rv9W8qmO6endavDwg7TNp5GbugwSukFMVZqzPSrSMndg==} engines: {node: ^20.0.0 || >=22.0.0} negotiator@0.6.3: @@ -9516,8 +9572,8 @@ packages: resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} engines: {node: '>= 0.8.0'} - set-cookie-parser@2.7.2: - resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} + set-cookie-parser@3.1.0: + resolution: {integrity: sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==} set-function-length@1.2.2: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} @@ -12123,24 +12179,58 @@ snapshots: optionalDependencies: '@types/react': 19.2.13 - '@better-auth/core@1.4.18(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.0)': + '@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0)': dependencies: - '@better-auth/utils': 0.3.0 + '@better-auth/utils': 0.4.0 '@better-fetch/fetch': 1.1.21 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.39.0 '@standard-schema/spec': 1.1.0 - better-call: 1.1.8(zod@4.3.6) + better-call: 1.3.5(zod@4.3.6) jose: 6.1.3 - kysely: 0.28.11 - nanostores: 1.1.0 + kysely: 0.28.15 + nanostores: 1.2.0 zod: 4.3.6 - '@better-auth/telemetry@1.4.18(@better-auth/core@1.4.18(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.0))': + '@better-auth/drizzle-adapter@1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)': + dependencies: + '@better-auth/core': 1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.4.0 + + '@better-auth/kysely-adapter@1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)(kysely@0.28.15)': + dependencies: + '@better-auth/core': 1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.4.0 + optionalDependencies: + kysely: 0.28.15 + + '@better-auth/memory-adapter@1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)': dependencies: - '@better-auth/core': 1.4.18(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.0) - '@better-auth/utils': 0.3.0 + '@better-auth/core': 1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.4.0 + + '@better-auth/mongo-adapter@1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)': + dependencies: + '@better-auth/core': 1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.4.0 + + '@better-auth/prisma-adapter@1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)(@prisma/client@7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))': + dependencies: + '@better-auth/core': 1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.4.0 + optionalDependencies: + '@prisma/client': 7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3) + prisma: 7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + + '@better-auth/telemetry@1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)': + dependencies: + '@better-auth/core': 1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/utils': 0.4.0 '@better-fetch/fetch': 1.1.21 - '@better-auth/utils@0.3.0': {} + '@better-auth/utils@0.4.0': + dependencies: + '@noble/hashes': 2.0.1 '@better-fetch/fetch@1.1.21': {} @@ -16500,19 +16590,24 @@ snapshots: basic-ftp@5.1.0: {} - better-auth@1.4.18(@prisma/client@7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(mysql2@3.15.3)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.18.0)(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.11)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): + better-auth@1.6.0(@opentelemetry/api@1.9.0)(@prisma/client@7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(mysql2@3.15.3)(next@16.2.1(@babel/core@7.29.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.58.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(pg@8.18.0)(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.11)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)): dependencies: - '@better-auth/core': 1.4.18(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.0) - '@better-auth/telemetry': 1.4.18(@better-auth/core@1.4.18(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.0)) - '@better-auth/utils': 0.3.0 + '@better-auth/core': 1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0) + '@better-auth/drizzle-adapter': 1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0) + '@better-auth/kysely-adapter': 1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)(kysely@0.28.15) + '@better-auth/memory-adapter': 1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0) + '@better-auth/mongo-adapter': 1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0) + '@better-auth/prisma-adapter': 1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)(@prisma/client@7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3))(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)) + '@better-auth/telemetry': 1.6.0(@better-auth/core@1.6.0(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21)(@opentelemetry/api@1.9.0)(better-call@1.3.5(zod@4.3.6))(jose@6.1.3)(kysely@0.28.15)(nanostores@1.2.0))(@better-auth/utils@0.4.0)(@better-fetch/fetch@1.1.21) + '@better-auth/utils': 0.4.0 '@better-fetch/fetch': 1.1.21 '@noble/ciphers': 2.1.1 '@noble/hashes': 2.0.1 - better-call: 1.1.8(zod@4.3.6) + better-call: 1.3.5(zod@4.3.6) defu: 6.1.4 jose: 6.1.3 - kysely: 0.28.11 - nanostores: 1.1.0 + kysely: 0.28.15 + nanostores: 1.2.0 zod: 4.3.6 optionalDependencies: '@prisma/client': 7.3.0(prisma@7.3.0(@types/react@19.2.13)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(typescript@5.9.3) @@ -16523,13 +16618,16 @@ snapshots: react: 19.2.4 react-dom: 19.2.4(react@19.2.4) vitest: 4.0.18(@opentelemetry/api@1.9.0)(@types/node@24.10.11)(jiti@2.6.1)(jsdom@26.1.0)(lightningcss@1.30.2)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - '@cloudflare/workers-types' + - '@opentelemetry/api' - better-call@1.1.8(zod@4.3.6): + better-call@1.3.5(zod@4.3.6): dependencies: - '@better-auth/utils': 0.3.0 + '@better-auth/utils': 0.4.0 '@better-fetch/fetch': 1.1.21 rou3: 0.7.12 - set-cookie-parser: 2.7.2 + set-cookie-parser: 3.1.0 optionalDependencies: zod: 4.3.6 @@ -18881,7 +18979,7 @@ snapshots: kleur@3.0.3: {} - kysely@0.28.11: {} + kysely@0.28.15: {} lcm@0.0.3: dependencies: @@ -19750,7 +19848,7 @@ snapshots: nanoid@5.1.6: {} - nanostores@1.1.0: {} + nanostores@1.2.0: {} negotiator@0.6.3: {} @@ -21186,7 +21284,7 @@ snapshots: transitivePeerDependencies: - supports-color - set-cookie-parser@2.7.2: {} + set-cookie-parser@3.1.0: {} set-function-length@1.2.2: dependencies: