diff --git a/examples/react/start-basic-better-auth/.env.example b/examples/react/start-basic-better-auth/.env.example new file mode 100644 index 0000000000..17c68d690a --- /dev/null +++ b/examples/react/start-basic-better-auth/.env.example @@ -0,0 +1,10 @@ +# Better Auth Configuration +# Generate a secure secret with: openssl rand -base64 32 +BETTER_AUTH_SECRET=your-secret-key-here-min-32-chars-long + +# Better Auth URL (base URL, no /api/auth suffix) +BETTER_AUTH_URL=http://localhost:10000 + +# GitHub OAuth Configuration (https://github.com/settings/developers) +GITHUB_CLIENT_ID=your-github-client-id +GITHUB_CLIENT_SECRET=your-github-client-secret diff --git a/examples/react/start-basic-better-auth/.gitignore b/examples/react/start-basic-better-auth/.gitignore new file mode 100644 index 0000000000..3479e16707 --- /dev/null +++ b/examples/react/start-basic-better-auth/.gitignore @@ -0,0 +1,6 @@ +node_modules +dist +.env +*.local +.DS_Store +.tanstack diff --git a/examples/react/start-basic-better-auth/README.md b/examples/react/start-basic-better-auth/README.md new file mode 100644 index 0000000000..fc15980da7 --- /dev/null +++ b/examples/react/start-basic-better-auth/README.md @@ -0,0 +1,66 @@ +# TanStack Start - Better Auth Example + +A TanStack Start example demonstrating authentication with Better Auth. + +- [TanStack Router Docs](https://tanstack.com/router) +- [Better Auth Documentation](https://www.better-auth.com/) + +## Start a new project based on this example + +To start a new project based on this example, run: + +```sh +npx gitpick TanStack/router/tree/main/examples/react/start-basic-better-auth start-basic-better-auth +``` + +## Setup + +This example requires environment variables for Better Auth configuration. Copy the `.env.example` file to `.env` and fill in your GitHub OAuth credentials: + +```sh +cp .env.example .env +``` + +### GitHub OAuth Setup + +1. Go to [GitHub Developer Settings](https://github.com/settings/developers) +2. Click "New OAuth App" +3. Fill in: + - Application name: Your app name + - Homepage URL: `http://localhost:10000` + - Authorization callback URL: `http://localhost:10000/api/auth/callback/github` +4. Copy the Client ID and Client Secret to your `.env` file + +## Getting Started + +From your terminal: + +```sh +pnpm install +pnpm dev +``` + +This starts your app in development mode, rebuilding assets on file changes. + +## Build + +To build the app for production: + +```sh +pnpm build +``` + +## Authentication Configuration + +This example demonstrates how to integrate Better Auth with TanStack Start. Check the source code for examples of: + +- Configuring social authentication providers +- Protecting routes with authentication +- Accessing session data in server functions + +### Key Files + +- `src/utils/auth.ts` - Better Auth server configuration +- `src/utils/auth-client.ts` - Better Auth client setup +- `src/routes/__root.tsx` - Session fetching and navigation +- `src/routes/protected.tsx` - Example of a protected route diff --git a/examples/react/start-basic-better-auth/package.json b/examples/react/start-basic-better-auth/package.json new file mode 100644 index 0000000000..92f96882fd --- /dev/null +++ b/examples/react/start-basic-better-auth/package.json @@ -0,0 +1,30 @@ +{ + "name": "tanstack-start-example-basic-better-auth", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "start": "pnpx srvx --prod -s ../client dist/server/server.js" + }, + "dependencies": { + "@tanstack/react-router": "^1.170.17", + "@tanstack/react-router-devtools": "^1.167.0", + "@tanstack/react-start": "^1.168.27", + "better-auth": "^1.6.23", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@tailwindcss/vite": "^4.2.2", + "@types/node": "^22.5.4", + "@types/react": "^19.0.8", + "@types/react-dom": "^19.0.3", + "@vitejs/plugin-react": "^6.0.1", + "tailwindcss": "^4.2.2", + "typescript": "^6.0.2", + "vite": "^8.0.14" + } +} diff --git a/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx new file mode 100644 index 0000000000..260c2ea41f --- /dev/null +++ b/examples/react/start-basic-better-auth/src/components/DefaultCatchBoundary.tsx @@ -0,0 +1,53 @@ +import { + ErrorComponent, + Link, + rootRouteId, + useMatch, + useRouter, +} from '@tanstack/react-router' +import type { ErrorComponentProps } from '@tanstack/react-router' + +export function DefaultCatchBoundary({ error }: ErrorComponentProps) { + const router = useRouter() + const isRoot = useMatch({ + strict: false, + select: (state) => state.id === rootRouteId, + }) + + console.error('DefaultCatchBoundary Error:', error) + + return ( +
+ +
+ + {isRoot ? ( + + Home + + ) : ( + { + e.preventDefault() + window.history.back() + }} + > + Go Back + + )} +
+
+ ) +} diff --git a/examples/react/start-basic-better-auth/src/components/NotFound.tsx b/examples/react/start-basic-better-auth/src/components/NotFound.tsx new file mode 100644 index 0000000000..8805751110 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/components/NotFound.tsx @@ -0,0 +1,26 @@ +import type { ReactNode } from 'react' +import { Link } from '@tanstack/react-router' + +export function NotFound({ children }: { children?: ReactNode }) { + return ( +
+
+ {children ||

The page you are looking for does not exist.

} +
+

+ + + Start Over + +

+
+ ) +} diff --git a/examples/react/start-basic-better-auth/src/routeTree.gen.ts b/examples/react/start-basic-better-auth/src/routeTree.gen.ts new file mode 100644 index 0000000000..2f59e4ba33 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routeTree.gen.ts @@ -0,0 +1,122 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as ProtectedRouteImport } from './routes/protected' +import { Route as LoginRouteImport } from './routes/login' +import { Route as IndexRouteImport } from './routes/index' +import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$' + +const ProtectedRoute = ProtectedRouteImport.update({ + id: '/protected', + path: '/protected', + getParentRoute: () => rootRouteImport, +} as any) +const LoginRoute = LoginRouteImport.update({ + id: '/login', + path: '/login', + getParentRoute: () => rootRouteImport, +} as any) +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) +const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({ + id: '/api/auth/$', + path: '/api/auth/$', + getParentRoute: () => rootRouteImport, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/login': typeof LoginRoute + '/protected': typeof ProtectedRoute + '/api/auth/$': typeof ApiAuthSplatRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/login': typeof LoginRoute + '/protected': typeof ProtectedRoute + '/api/auth/$': typeof ApiAuthSplatRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/login': typeof LoginRoute + '/protected': typeof ProtectedRoute + '/api/auth/$': typeof ApiAuthSplatRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' | '/login' | '/protected' | '/api/auth/$' + fileRoutesByTo: FileRoutesByTo + to: '/' | '/login' | '/protected' | '/api/auth/$' + id: '__root__' | '/' | '/login' | '/protected' | '/api/auth/$' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + LoginRoute: typeof LoginRoute + ProtectedRoute: typeof ProtectedRoute + ApiAuthSplatRoute: typeof ApiAuthSplatRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/protected': { + id: '/protected' + path: '/protected' + fullPath: '/protected' + preLoaderRoute: typeof ProtectedRouteImport + parentRoute: typeof rootRouteImport + } + '/login': { + id: '/login' + path: '/login' + fullPath: '/login' + preLoaderRoute: typeof LoginRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/api/auth/$': { + id: '/api/auth/$' + path: '/api/auth/$' + fullPath: '/api/auth/$' + preLoaderRoute: typeof ApiAuthSplatRouteImport + parentRoute: typeof rootRouteImport + } + } +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + LoginRoute: LoginRoute, + ProtectedRoute: ProtectedRoute, + ApiAuthSplatRoute: ApiAuthSplatRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +import type { getRouter } from './router.tsx' +import type { createStart } from '@tanstack/react-start' +declare module '@tanstack/react-start' { + interface Register { + ssr: true + router: Awaited> + } +} diff --git a/examples/react/start-basic-better-auth/src/router.tsx b/examples/react/start-basic-better-auth/src/router.tsx new file mode 100644 index 0000000000..8490d717b6 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/router.tsx @@ -0,0 +1,19 @@ +import { createRouter } from '@tanstack/react-router' +import { routeTree } from './routeTree.gen' +import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' +import { NotFound } from './components/NotFound' +import type { RouterContext } from './routes/__root' + +export function getRouter() { + const router = createRouter({ + routeTree, + defaultPreload: 'intent', + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + scrollRestoration: true, + context: { + session: null, + } satisfies RouterContext, + }) + return router +} diff --git a/examples/react/start-basic-better-auth/src/routes/__root.tsx b/examples/react/start-basic-better-auth/src/routes/__root.tsx new file mode 100644 index 0000000000..823a1bd822 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/__root.tsx @@ -0,0 +1,130 @@ +/// +import type { ReactNode } from 'react' +import { + HeadContent, + Link, + Outlet, + Scripts, + createRootRouteWithContext, + useRouter, +} from '@tanstack/react-router' +import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' +import { createServerFn } from '@tanstack/react-start' +import { getRequestHeaders } from '@tanstack/react-start/server' +import { auth, type AuthSession } from '~/utils/auth' +import { authClient } from '~/utils/auth-client' +import appCss from '~/styles/app.css?url' + +export interface RouterContext { + session: AuthSession | null +} + +const fetchSession = createServerFn({ method: 'GET' }).handler(async () => { + const headers = getRequestHeaders() + const session = await auth.api.getSession({ headers }) + return session +}) + +export const Route = createRootRouteWithContext()({ + beforeLoad: async () => { + const session = await fetchSession() + return { + session, + } + }, + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + { + title: 'TanStack Start Auth Example', + }, + ], + links: [{ rel: 'stylesheet', href: appCss }], + }), + component: RootComponent, +}) + +function RootComponent() { + return ( + + + + ) +} + +function RootDocument({ children }: { children: ReactNode }) { + return ( + + + + + + +
{children}
+ + + + + ) +} + +function NavBar() { + const router = useRouter() + const routeContext = Route.useRouteContext() + + const handleSignOut = async () => { + try { + await authClient.signOut() + await router.navigate({ to: '/' }) + } catch (error) { + console.error('Sign out failed:', error) + } finally { + await router.invalidate() + } + } + + return ( + + ) +} diff --git a/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts b/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts new file mode 100644 index 0000000000..440657cbbd --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/api/auth/$.ts @@ -0,0 +1,15 @@ +import { createFileRoute } from '@tanstack/react-router' +import { auth } from '~/utils/auth' + +/** + * Better Auth API route handler + * Handles all auth routes: /api/auth/* + */ +export const Route = createFileRoute('/api/auth/$')({ + server: { + handlers: { + GET: ({ request }) => auth.handler(request), + POST: ({ request }) => auth.handler(request), + }, + }, +}) diff --git a/examples/react/start-basic-better-auth/src/routes/index.tsx b/examples/react/start-basic-better-auth/src/routes/index.tsx new file mode 100644 index 0000000000..751559ba7c --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/index.tsx @@ -0,0 +1,50 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/')({ + component: Home, +}) + +function Home() { + const { session } = Route.useRouteContext() + const user = session?.user + + return ( +
+

+ TanStack Start Better Auth Example +

+

+ This example demonstrates Better Auth integration with TanStack Start + using GitHub OAuth. +

+ +
+

Auth Status

+ + {session ? ( +
+

Authenticated

+ {user?.image && ( + Avatar + )} +

+ Name: {user?.name ?? 'N/A'} +

+

+ Email: {user?.email ?? 'N/A'} +

+
+ ) : ( +

+ You are not signed in. Click "Sign In" in the navigation bar to + authenticate with GitHub. +

+ )} +
+
+ ) +} diff --git a/examples/react/start-basic-better-auth/src/routes/login.tsx b/examples/react/start-basic-better-auth/src/routes/login.tsx new file mode 100644 index 0000000000..78a839fb72 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/login.tsx @@ -0,0 +1,43 @@ +import { createFileRoute, redirect } from '@tanstack/react-router' +import { authClient } from '~/utils/auth-client' + +export const Route = createFileRoute('/login')({ + beforeLoad: ({ context }) => { + if (context.session) { + throw redirect({ to: '/' }) + } + }, + component: Login, +}) + +function Login() { + const handleGitHubSignIn = () => { + authClient.signIn.social({ + provider: 'github', + callbackURL: '/', + }) + } + + return ( +
+

Sign In

+ +
+ + +

+ You'll be redirected to GitHub to complete the sign-in process. +

+
+
+ ) +} diff --git a/examples/react/start-basic-better-auth/src/routes/protected.tsx b/examples/react/start-basic-better-auth/src/routes/protected.tsx new file mode 100644 index 0000000000..61126f67d5 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/routes/protected.tsx @@ -0,0 +1,64 @@ +import { createFileRoute, redirect } from '@tanstack/react-router' + +export const Route = createFileRoute('/protected')({ + beforeLoad: ({ context }) => { + if (!context.session) { + throw redirect({ to: '/login' }) + } + }, + component: Protected, +}) + +function Protected() { + const { session } = Route.useRouteContext() + const user = session?.user + + return ( +
+

Protected Page

+

+ This page is only accessible to authenticated users. +

+ +
+

+ Welcome, {user?.name ?? 'User'}! +

+ + {user && ( +
+

+ Email: {user?.email ?? 'N/A'} +

+ {user?.image && ( +
+ Avatar: + User avatar +
+ )} +
+ )} +
+ +
+

Session Data (Debug)

+
+          {JSON.stringify(
+            {
+              user: {
+                name: user?.name,
+                email: user?.email,
+              },
+            },
+            null,
+            2,
+          )}
+        
+
+
+ ) +} diff --git a/examples/react/start-basic-better-auth/src/styles/app.css b/examples/react/start-basic-better-auth/src/styles/app.css new file mode 100644 index 0000000000..f1d8c73cdc --- /dev/null +++ b/examples/react/start-basic-better-auth/src/styles/app.css @@ -0,0 +1 @@ +@import "tailwindcss"; diff --git a/examples/react/start-basic-better-auth/src/utils/auth-client.ts b/examples/react/start-basic-better-auth/src/utils/auth-client.ts new file mode 100644 index 0000000000..fc6c795bfd --- /dev/null +++ b/examples/react/start-basic-better-auth/src/utils/auth-client.ts @@ -0,0 +1,3 @@ +import { createAuthClient } from 'better-auth/react' + +export const authClient = createAuthClient() diff --git a/examples/react/start-basic-better-auth/src/utils/auth.ts b/examples/react/start-basic-better-auth/src/utils/auth.ts new file mode 100644 index 0000000000..79d65ec088 --- /dev/null +++ b/examples/react/start-basic-better-auth/src/utils/auth.ts @@ -0,0 +1,43 @@ +import { betterAuth } from 'better-auth' +import { tanstackStartCookies } from 'better-auth/tanstack-start' + +const clientId = process.env.GITHUB_CLIENT_ID +const clientSecret = process.env.GITHUB_CLIENT_SECRET + +if (!clientId || !clientSecret) { + console.warn( + 'Missing GITHUB_CLIENT_ID and/or GITHUB_CLIENT_SECRET environment variables. ' + + 'GitHub sign-in will not work until you copy .env.example to .env and fill in your GitHub OAuth credentials.', + ) +} + +/** + * Better Auth configuration for TanStack Start with GitHub + */ +export const auth = betterAuth({ + // Base URL and trusted origins are required for OAuth callbacks and CSRF protection + baseURL: process.env.BETTER_AUTH_URL, + trustedOrigins: process.env.BETTER_AUTH_URL + ? [process.env.BETTER_AUTH_URL] + : [], + socialProviders: { + github: { + clientId: clientId ?? '', + clientSecret: clientSecret ?? '', + }, + }, + plugins: [ + // Must be last plugin in the array + tanstackStartCookies(), + ], + // Stateless sessions (no database required) + session: { + cookieCache: { + enabled: true, + maxAge: 60 * 60 * 24 * 7, + }, + }, +}) + +// Export session type for use in router context +export type AuthSession = typeof auth.$Infer.Session diff --git a/examples/react/start-basic-better-auth/tsconfig.json b/examples/react/start-basic-better-auth/tsconfig.json new file mode 100644 index 0000000000..e14d7324df --- /dev/null +++ b/examples/react/start-basic-better-auth/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true, + "paths": { + "~/*": ["./src/*"] + } + }, + "include": ["**/*.ts", "**/*.tsx", "**/*.d.ts"] +} diff --git a/examples/react/start-basic-better-auth/vite.config.ts b/examples/react/start-basic-better-auth/vite.config.ts new file mode 100644 index 0000000000..90f81aedf7 --- /dev/null +++ b/examples/react/start-basic-better-auth/vite.config.ts @@ -0,0 +1,15 @@ +import { tanstackStart } from '@tanstack/react-start/plugin/vite' +import { defineConfig } from 'vite' +import viteReact from '@vitejs/plugin-react' +import tailwindcss from '@tailwindcss/vite' + +export default defineConfig({ + server: { + port: 10000, + strictPort: true, + }, + resolve: { + tsconfigPaths: true, + }, + plugins: [tailwindcss(), tanstackStart(), viteReact()], +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96847b4044..88c06a7e29 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9195,6 +9195,52 @@ importers: specifier: ^8.0.14 version: 8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0) + examples/react/start-basic-better-auth: + dependencies: + '@tanstack/react-router': + specifier: workspace:* + version: link:../../../packages/react-router + '@tanstack/react-router-devtools': + specifier: workspace:^ + version: link:../../../packages/react-router-devtools + '@tanstack/react-start': + specifier: workspace:* + version: link:../../../packages/react-start + better-auth: + specifier: ^1.6.23 + version: 1.6.23(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(@tanstack/react-start@packages+react-start)(mysql2@3.15.3)(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)(vitest@4.1.4)(vue@3.5.25(typescript@6.0.2)) + react: + specifier: ^19.2.3 + version: 19.2.3 + react-dom: + specifier: ^19.2.3 + version: 19.2.3(react@19.2.3) + devDependencies: + '@tailwindcss/vite': + specifier: ^4.2.2 + version: 4.2.2(vite@8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0)) + '@types/node': + specifier: 25.0.9 + version: 25.0.9 + '@types/react': + specifier: ^19.2.8 + version: 19.2.9 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.9) + '@vitejs/plugin-react': + specifier: ^6.0.1 + version: 6.0.1(vite@8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0)) + tailwindcss: + specifier: ^4.2.2 + version: 4.2.2 + typescript: + specifier: ^6.0.2 + version: 6.0.2 + vite: + specifier: ^8.0.14 + version: 8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0) + examples/react/start-basic-cloudflare: dependencies: '@tanstack/react-router': @@ -14085,6 +14131,23 @@ packages: '@opentelemetry/api': optional: true + '@better-auth/core@1.6.23': + resolution: {integrity: sha512-beEhOs0uVeOxYOZKUfIEBd/nQV2Bd4/6wyLxZ0OFkn6CMTK2Vi+hXuZLnyPBeB6RdHpebEoJWiHqwHxBIxgPDQ==} + peerDependencies: + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@cloudflare/workers-types': '>=4' + '@opentelemetry/api': ^1.9.0 + better-call: 1.3.7 + jose: ^6.1.0 + kysely: ^0.28.5 || ^0.29.0 + nanostores: ^1.0.1 + peerDependenciesMeta: + '@cloudflare/workers-types': + optional: true + '@opentelemetry/api': + optional: true + '@better-auth/drizzle-adapter@1.6.19': resolution: {integrity: sha512-57C9ePorPmIEez6dHuQMz3hCTkYim0lfVRIoRtX7PiVfiRFB2bjXseQwrCJfQmkgMFlkp1s/c9nKgAjc2EvAIg==} peerDependencies: @@ -14095,6 +14158,16 @@ packages: drizzle-orm: optional: true + '@better-auth/drizzle-adapter@1.6.23': + resolution: {integrity: sha512-2+/PTVfIP9E7iz6af8TB3lhnowHUj9ljC66kECmHaFEdUqPgzHoWux9epotKwO7XDg2ui4ttWQ8CMeNFLvQeKQ==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + drizzle-orm: ^0.45.2 + peerDependenciesMeta: + drizzle-orm: + optional: true + '@better-auth/kysely-adapter@1.6.19': resolution: {integrity: sha512-DlmvllEd0nv8JL+plX3JB3WTmqDFnGFOmjmIiUDHo8R3PTAvC0ZaJq3Jk+LQLN5PyVQSUzXZKtvTQYaqRHzBaw==} peerDependencies: @@ -14105,12 +14178,28 @@ packages: kysely: optional: true + '@better-auth/kysely-adapter@1.6.23': + resolution: {integrity: sha512-zbNJsMbG09exfkGyvFqBLLqWoMPAUWjxCuUnEK5AsjbYoZeIjj/QGZgdf4CapVWryKxjA9Q6Jlr6fbiPpC3VAg==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + kysely: ^0.28.17 || ^0.29.0 + peerDependenciesMeta: + kysely: + optional: true + '@better-auth/memory-adapter@1.6.19': resolution: {integrity: sha512-cZ8iLRG/T8Oi/CqE9FTHj3z8pIOqRsINi50trWxPNwyY/Eyb7YCljrBi0PuqgIdyVs7BWfrrtEYTpO4ddfuwEw==} peerDependencies: '@better-auth/core': ^1.6.19 '@better-auth/utils': 0.4.2 + '@better-auth/memory-adapter@1.6.23': + resolution: {integrity: sha512-krIiR0pIVkaKlAzm690n5bcMW4NGbqeMg0HQSD9fz/KcQF/eWLqcq9gG/BhHTj2i/y96qH+W5JWPmaSOS5iTgQ==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + '@better-auth/mongo-adapter@1.6.19': resolution: {integrity: sha512-8AReXqhMGiGQIPEpGbmAhh+R4g70TsAVvzwdd6Aj4q+LTSwd3tqC89TFJ4eX8KSplxm9PFBZ6g6gsRmDd7urQg==} peerDependencies: @@ -14121,6 +14210,16 @@ packages: mongodb: optional: true + '@better-auth/mongo-adapter@1.6.23': + resolution: {integrity: sha512-7+QdevitGlKBbP6JbiSk5SBnzPsKV/mDrQBGBn8hwByQLeJwqpqbuBPw7ZI8vzUlFfAAnyFiqwP3Eb8mxnp7pA==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + mongodb: ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + mongodb: + optional: true + '@better-auth/prisma-adapter@1.6.19': resolution: {integrity: sha512-pXZBhR7/bzJb48IUHlGMyz9SM9h1OCO5GIIuHEllJYt8MKgrjtsnXfUkwZh6pAUEIp3WxBEYMMK96bfkqHiWEg==} peerDependencies: @@ -14134,6 +14233,19 @@ packages: prisma: optional: true + '@better-auth/prisma-adapter@1.6.23': + resolution: {integrity: sha512-2qSdzidq4tkb1eS5TTqb4Nzg0mdZWm3Qky9SYeXeb8PpVQbC2sxqJhEM5mK7y12uU6I8hc64wO9f7AFVNL+6UQ==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + '@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.6.19': resolution: {integrity: sha512-bBaB6SMIsrD3WutDdm5YQ1bQyinANTimHD8RtpLWhNh/jIXvzgwVVCrDFqA256vcGC/ZRCydmtW8ZrUqNMW9Og==} peerDependencies: @@ -14141,6 +14253,13 @@ packages: '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 + '@better-auth/telemetry@1.6.23': + resolution: {integrity: sha512-/R2Kb+z2BpDOOWwVHqOk+c0VNpuwfCv4Hp5Yr9003WIZPax/zyNraGLB9CFE8qF2gZW8Dsz419k4I8CPrGzpDA==} + peerDependencies: + '@better-auth/core': ^1.6.23 + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@better-auth/utils@0.4.2': resolution: {integrity: sha512-AUxrvu+HaaODsUyzDxFgwd/8RZ1yZaYo42LXKSrU2oGgR38pS1ij8nqQKNgtTWoYGpNevNXtCfgTy6loHveW9A==} @@ -20715,6 +20834,68 @@ packages: vue: optional: true + better-auth@1.6.23: + resolution: {integrity: sha512-4vOaRd9UiKGKm9R+ej0jjU1es3MiJIiNc9Qq3VCnYqOZ4/nb5272QqTxWYoDxyUXl5x6A2x2we5KZKQO9teTQQ==} + peerDependencies: + '@lynx-js/react': '*' + '@prisma/client': ^5.0.0 || ^6.0.0 || ^7.0.0 + '@sveltejs/kit': ^2.0.0 + '@tanstack/react-start': workspace:* + '@tanstack/solid-start': workspace:* + better-sqlite3: ^12.0.0 + drizzle-kit: '>=0.31.4' + drizzle-orm: ^0.45.2 + mongodb: ^6.0.0 || ^7.0.0 + mysql2: ^3.0.0 + next: ^14.0.0 || ^15.0.0 || ^16.0.0 + pg: ^8.0.0 + prisma: ^5.0.0 || ^6.0.0 || ^7.0.0 + react: ^19.2.3 + react-dom: ^19.2.3 + solid-js: 1.9.12 + svelte: ^4.0.0 || ^5.0.0 + vitest: ^2.0.0 || ^3.0.0 || ^4.0.0 + vue: ^3.0.0 + peerDependenciesMeta: + '@lynx-js/react': + optional: true + '@prisma/client': + optional: true + '@sveltejs/kit': + optional: true + '@tanstack/react-start': + optional: true + '@tanstack/solid-start': + optional: true + better-sqlite3: + optional: true + drizzle-kit: + optional: true + drizzle-orm: + optional: true + mongodb: + optional: true + mysql2: + optional: true + next: + optional: true + pg: + optional: true + prisma: + optional: true + react: + optional: true + react-dom: + optional: true + solid-js: + optional: true + svelte: + optional: true + vitest: + optional: true + vue: + optional: true + better-call@1.3.6: resolution: {integrity: sha512-no1jI+h6Bkxs1NVBo4rONbVIzsPjZ8IUu7IHaJBiFwVX1XEQGN8KpHots5fSWmXe9nNyLuLIcgx6WEUcE6EDaA==} peerDependencies: @@ -20723,6 +20904,14 @@ packages: zod: optional: true + better-call@1.3.7: + resolution: {integrity: sha512-Al51/hjp2SSp6CRTa3F2ptcx4yQVS1xWKoY6jcVXqNYOap6mHFP2jUBn5EwIL4iIed1/Sq4hlQ+Umm6EflZG+w==} + peerDependencies: + zod: ^4.0.0 + peerDependenciesMeta: + zod: + optional: true + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -27628,11 +27817,28 @@ snapshots: nanostores: 1.3.0 zod: 4.4.3 + '@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0)': + dependencies: + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@opentelemetry/semantic-conventions': 1.41.1 + '@standard-schema/spec': 1.1.0 + better-call: 1.3.7(zod@4.4.3) + jose: 6.1.3 + kysely: 0.29.2 + nanostores: 1.3.0 + zod: 4.4.3 + '@better-auth/drizzle-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 + '@better-auth/drizzle-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-auth/kysely-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(kysely@0.29.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) @@ -27640,16 +27846,33 @@ snapshots: optionalDependencies: kysely: 0.29.2 + '@better-auth/kysely-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(kysely@0.29.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + optionalDependencies: + kysely: 0.29.2 + '@better-auth/memory-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 + '@better-auth/memory-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-auth/mongo-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 + '@better-auth/mongo-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-auth/prisma-adapter@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) @@ -27658,12 +27881,26 @@ snapshots: '@prisma/client': 7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2) prisma: 7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2) + '@better-auth/prisma-adapter@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + optionalDependencies: + '@prisma/client': 7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2) + prisma: 7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2) + '@better-auth/telemetry@1.6.19(@better-auth/core@1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': dependencies: '@better-auth/core': 1.6.19(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.6(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) '@better-auth/utils': 0.4.2 '@better-fetch/fetch': 1.3.1 + '@better-auth/telemetry@1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)': + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@better-auth/utils@0.4.2': dependencies: '@noble/hashes': 2.0.1 @@ -34737,6 +34974,39 @@ snapshots: - '@cloudflare/workers-types' - '@opentelemetry/api' + better-auth@1.6.23(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(@tanstack/react-start@packages+react-start)(mysql2@3.15.3)(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.12)(vitest@4.1.4)(vue@3.5.25(typescript@6.0.2)): + dependencies: + '@better-auth/core': 1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0) + '@better-auth/drizzle-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2) + '@better-auth/kysely-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(kysely@0.29.2) + '@better-auth/memory-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2) + '@better-auth/mongo-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2) + '@better-auth/prisma-adapter': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@prisma/client@7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2))(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2)) + '@better-auth/telemetry': 1.6.23(@better-auth/core@1.6.23(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(better-call@1.3.7(zod@4.4.3))(jose@6.1.3)(kysely@0.29.2)(nanostores@1.3.0))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1) + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + '@noble/ciphers': 2.2.0 + '@noble/hashes': 2.0.1 + better-call: 1.3.7(zod@4.4.3) + defu: 6.1.4 + jose: 6.1.3 + kysely: 0.29.2 + nanostores: 1.3.0 + zod: 4.4.3 + optionalDependencies: + '@prisma/client': 7.0.0(prisma@7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2))(typescript@6.0.2) + '@tanstack/react-start': link:packages/react-start + mysql2: 3.15.3 + prisma: 7.0.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@6.0.2) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + solid-js: 1.9.12 + vitest: 4.1.4(@types/node@25.0.9)(@vitest/ui@4.1.4)(jsdom@29.1.1(@noble/hashes@2.0.1))(msw@2.7.0(@types/node@25.0.9)(typescript@6.0.2))(vite@8.0.14(@types/node@25.0.9)(esbuild@0.27.4)(jiti@2.7.0)(sass@1.97.2)(terser@5.37.0)(tsx@4.20.3)(yaml@2.9.0)) + vue: 3.5.25(typescript@6.0.2) + transitivePeerDependencies: + - '@cloudflare/workers-types' + - '@opentelemetry/api' + better-call@1.3.6(zod@4.4.3): dependencies: '@better-auth/utils': 0.4.2 @@ -34746,6 +35016,15 @@ snapshots: optionalDependencies: zod: 4.4.3 + better-call@1.3.7(zod@4.4.3): + dependencies: + '@better-auth/utils': 0.4.2 + '@better-fetch/fetch': 1.3.1 + rou3: 0.7.12 + set-cookie-parser: 3.1.0 + optionalDependencies: + zod: 4.4.3 + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2