#
tokens: 49595/50000 122/1091 files (page 2/67)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 2 of 67. Use http://codebase.md/better-auth/better-auth?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .gitattributes
├── .github
│   ├── CODEOWNERS
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.yml
│   │   └── feature_request.yml
│   ├── renovate.json5
│   └── workflows
│       ├── ci.yml
│       ├── e2e.yml
│       ├── preview.yml
│       └── release.yml
├── .gitignore
├── .npmrc
├── .nvmrc
├── .vscode
│   └── settings.json
├── banner-dark.png
├── banner.png
├── biome.json
├── bump.config.ts
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── demo
│   ├── expo-example
│   │   ├── .env.example
│   │   ├── .gitignore
│   │   ├── app.config.ts
│   │   ├── assets
│   │   │   ├── bg-image.jpeg
│   │   │   ├── fonts
│   │   │   │   └── SpaceMono-Regular.ttf
│   │   │   ├── icon.png
│   │   │   └── images
│   │   │       ├── adaptive-icon.png
│   │   │       ├── favicon.png
│   │   │       ├── logo.png
│   │   │       ├── partial-react-logo.png
│   │   │       ├── react-logo.png
│   │   │       ├── [email protected]
│   │   │       ├── [email protected]
│   │   │       └── splash.png
│   │   ├── babel.config.js
│   │   ├── components.json
│   │   ├── expo-env.d.ts
│   │   ├── index.ts
│   │   ├── metro.config.js
│   │   ├── nativewind-env.d.ts
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── app
│   │   │   │   ├── _layout.tsx
│   │   │   │   ├── api
│   │   │   │   │   └── auth
│   │   │   │   │       └── [...route]+api.ts
│   │   │   │   ├── dashboard.tsx
│   │   │   │   ├── forget-password.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   └── sign-up.tsx
│   │   │   ├── components
│   │   │   │   ├── icons
│   │   │   │   │   └── google.tsx
│   │   │   │   └── ui
│   │   │   │       ├── avatar.tsx
│   │   │   │       ├── button.tsx
│   │   │   │       ├── card.tsx
│   │   │   │       ├── dialog.tsx
│   │   │   │       ├── input.tsx
│   │   │   │       ├── separator.tsx
│   │   │   │       └── text.tsx
│   │   │   ├── global.css
│   │   │   └── lib
│   │   │       ├── auth-client.ts
│   │   │       ├── auth.ts
│   │   │       ├── icons
│   │   │       │   ├── iconWithClassName.ts
│   │   │       │   └── X.tsx
│   │   │       └── utils.ts
│   │   ├── tailwind.config.js
│   │   └── tsconfig.json
│   └── nextjs
│       ├── .env.example
│       ├── .gitignore
│       ├── app
│       │   ├── (auth)
│       │   │   ├── forget-password
│       │   │   │   └── page.tsx
│       │   │   ├── reset-password
│       │   │   │   └── page.tsx
│       │   │   ├── sign-in
│       │   │   │   ├── loading.tsx
│       │   │   │   └── page.tsx
│       │   │   └── two-factor
│       │   │       ├── otp
│       │   │       │   └── page.tsx
│       │   │       └── page.tsx
│       │   ├── accept-invitation
│       │   │   └── [id]
│       │   │       ├── invitation-error.tsx
│       │   │       └── page.tsx
│       │   ├── admin
│       │   │   └── page.tsx
│       │   ├── api
│       │   │   └── auth
│       │   │       └── [...all]
│       │   │           └── route.ts
│       │   ├── apps
│       │   │   └── register
│       │   │       └── page.tsx
│       │   ├── client-test
│       │   │   └── page.tsx
│       │   ├── dashboard
│       │   │   ├── change-plan.tsx
│       │   │   ├── client.tsx
│       │   │   ├── organization-card.tsx
│       │   │   ├── page.tsx
│       │   │   ├── upgrade-button.tsx
│       │   │   └── user-card.tsx
│       │   ├── device
│       │   │   ├── approve
│       │   │   │   └── page.tsx
│       │   │   ├── denied
│       │   │   │   └── page.tsx
│       │   │   ├── layout.tsx
│       │   │   ├── page.tsx
│       │   │   └── success
│       │   │       └── page.tsx
│       │   ├── favicon.ico
│       │   ├── features.tsx
│       │   ├── fonts
│       │   │   ├── GeistMonoVF.woff
│       │   │   └── GeistVF.woff
│       │   ├── globals.css
│       │   ├── layout.tsx
│       │   ├── oauth
│       │   │   └── authorize
│       │   │       ├── concet-buttons.tsx
│       │   │       └── page.tsx
│       │   ├── page.tsx
│       │   └── pricing
│       │       └── page.tsx
│       ├── components
│       │   ├── account-switch.tsx
│       │   ├── blocks
│       │   │   └── pricing.tsx
│       │   ├── logo.tsx
│       │   ├── one-tap.tsx
│       │   ├── sign-in-btn.tsx
│       │   ├── sign-in.tsx
│       │   ├── sign-up.tsx
│       │   ├── theme-provider.tsx
│       │   ├── theme-toggle.tsx
│       │   ├── tier-labels.tsx
│       │   ├── ui
│       │   │   ├── accordion.tsx
│       │   │   ├── alert-dialog.tsx
│       │   │   ├── alert.tsx
│       │   │   ├── aspect-ratio.tsx
│       │   │   ├── avatar.tsx
│       │   │   ├── badge.tsx
│       │   │   ├── breadcrumb.tsx
│       │   │   ├── button.tsx
│       │   │   ├── calendar.tsx
│       │   │   ├── card.tsx
│       │   │   ├── carousel.tsx
│       │   │   ├── chart.tsx
│       │   │   ├── checkbox.tsx
│       │   │   ├── collapsible.tsx
│       │   │   ├── command.tsx
│       │   │   ├── context-menu.tsx
│       │   │   ├── copy-button.tsx
│       │   │   ├── dialog.tsx
│       │   │   ├── drawer.tsx
│       │   │   ├── dropdown-menu.tsx
│       │   │   ├── form.tsx
│       │   │   ├── hover-card.tsx
│       │   │   ├── input-otp.tsx
│       │   │   ├── input.tsx
│       │   │   ├── label.tsx
│       │   │   ├── menubar.tsx
│       │   │   ├── navigation-menu.tsx
│       │   │   ├── pagination.tsx
│       │   │   ├── password-input.tsx
│       │   │   ├── popover.tsx
│       │   │   ├── progress.tsx
│       │   │   ├── radio-group.tsx
│       │   │   ├── resizable.tsx
│       │   │   ├── scroll-area.tsx
│       │   │   ├── select.tsx
│       │   │   ├── separator.tsx
│       │   │   ├── sheet.tsx
│       │   │   ├── skeleton.tsx
│       │   │   ├── slider.tsx
│       │   │   ├── sonner.tsx
│       │   │   ├── switch.tsx
│       │   │   ├── table.tsx
│       │   │   ├── tabs.tsx
│       │   │   ├── tabs2.tsx
│       │   │   ├── textarea.tsx
│       │   │   ├── toast.tsx
│       │   │   ├── toaster.tsx
│       │   │   ├── toggle-group.tsx
│       │   │   ├── toggle.tsx
│       │   │   └── tooltip.tsx
│       │   └── wrapper.tsx
│       ├── components.json
│       ├── hooks
│       │   └── use-toast.ts
│       ├── lib
│       │   ├── auth-client.ts
│       │   ├── auth-types.ts
│       │   ├── auth.ts
│       │   ├── email
│       │   │   ├── invitation.tsx
│       │   │   ├── resend.ts
│       │   │   └── reset-password.tsx
│       │   ├── metadata.ts
│       │   ├── shared.ts
│       │   └── utils.ts
│       ├── middleware.ts
│       ├── next.config.ts
│       ├── package.json
│       ├── postcss.config.mjs
│       ├── public
│       │   ├── __og.png
│       │   ├── _og.png
│       │   ├── favicon
│       │   │   ├── android-chrome-192x192.png
│       │   │   ├── android-chrome-512x512.png
│       │   │   ├── apple-touch-icon.png
│       │   │   ├── favicon-16x16.png
│       │   │   ├── favicon-32x32.png
│       │   │   ├── favicon.ico
│       │   │   ├── light
│       │   │   │   ├── android-chrome-192x192.png
│       │   │   │   ├── android-chrome-512x512.png
│       │   │   │   ├── apple-touch-icon.png
│       │   │   │   ├── favicon-16x16.png
│       │   │   │   ├── favicon-32x32.png
│       │   │   │   ├── favicon.ico
│       │   │   │   └── site.webmanifest
│       │   │   └── site.webmanifest
│       │   ├── logo.svg
│       │   └── og.png
│       ├── README.md
│       ├── tailwind.config.ts
│       ├── tsconfig.json
│       └── turbo.json
├── docker-compose.yml
├── docs
│   ├── .env.example
│   ├── .gitignore
│   ├── app
│   │   ├── api
│   │   │   ├── ai-chat
│   │   │   │   └── route.ts
│   │   │   ├── analytics
│   │   │   │   ├── conversation
│   │   │   │   │   └── route.ts
│   │   │   │   ├── event
│   │   │   │   │   └── route.ts
│   │   │   │   └── feedback
│   │   │   │       └── route.ts
│   │   │   ├── chat
│   │   │   │   └── route.ts
│   │   │   ├── og
│   │   │   │   └── route.tsx
│   │   │   ├── og-release
│   │   │   │   └── route.tsx
│   │   │   ├── search
│   │   │   │   └── route.ts
│   │   │   └── support
│   │   │       └── route.ts
│   │   ├── blog
│   │   │   ├── _components
│   │   │   │   ├── _layout.tsx
│   │   │   │   ├── blog-list.tsx
│   │   │   │   ├── changelog-layout.tsx
│   │   │   │   ├── default-changelog.tsx
│   │   │   │   ├── fmt-dates.tsx
│   │   │   │   ├── icons.tsx
│   │   │   │   ├── stat-field.tsx
│   │   │   │   └── support.tsx
│   │   │   ├── [[...slug]]
│   │   │   │   └── page.tsx
│   │   │   └── layout.tsx
│   │   ├── changelogs
│   │   │   ├── _components
│   │   │   │   ├── _layout.tsx
│   │   │   │   ├── changelog-layout.tsx
│   │   │   │   ├── default-changelog.tsx
│   │   │   │   ├── fmt-dates.tsx
│   │   │   │   ├── grid-pattern.tsx
│   │   │   │   ├── icons.tsx
│   │   │   │   └── stat-field.tsx
│   │   │   ├── [[...slug]]
│   │   │   │   └── page.tsx
│   │   │   └── layout.tsx
│   │   ├── community
│   │   │   ├── _components
│   │   │   │   ├── header.tsx
│   │   │   │   └── stats.tsx
│   │   │   └── page.tsx
│   │   ├── docs
│   │   │   ├── [[...slug]]
│   │   │   │   ├── page.client.tsx
│   │   │   │   └── page.tsx
│   │   │   ├── layout.tsx
│   │   │   └── lib
│   │   │       └── get-llm-text.ts
│   │   ├── global.css
│   │   ├── layout.config.tsx
│   │   ├── layout.tsx
│   │   ├── llms.txt
│   │   │   ├── [...slug]
│   │   │   │   └── route.ts
│   │   │   └── route.ts
│   │   ├── not-found.tsx
│   │   ├── page.tsx
│   │   ├── reference
│   │   │   └── route.ts
│   │   ├── sitemap.xml
│   │   ├── static.json
│   │   │   └── route.ts
│   │   └── v1
│   │       ├── _components
│   │       │   └── v1-text.tsx
│   │       ├── bg-line.tsx
│   │       └── page.tsx
│   ├── assets
│   │   ├── Geist.ttf
│   │   └── GeistMono.ttf
│   ├── components
│   │   ├── ai-chat-modal.tsx
│   │   ├── anchor-scroll-fix.tsx
│   │   ├── api-method-tabs.tsx
│   │   ├── api-method.tsx
│   │   ├── banner.tsx
│   │   ├── blocks
│   │   │   └── features.tsx
│   │   ├── builder
│   │   │   ├── beam.tsx
│   │   │   ├── code-tabs
│   │   │   │   ├── code-editor.tsx
│   │   │   │   ├── code-tabs.tsx
│   │   │   │   ├── index.tsx
│   │   │   │   ├── tab-bar.tsx
│   │   │   │   └── theme.ts
│   │   │   ├── index.tsx
│   │   │   ├── sign-in.tsx
│   │   │   ├── sign-up.tsx
│   │   │   ├── social-provider.tsx
│   │   │   ├── store.ts
│   │   │   └── tabs.tsx
│   │   ├── display-techstack.tsx
│   │   ├── divider-text.tsx
│   │   ├── docs
│   │   │   ├── docs.client.tsx
│   │   │   ├── docs.tsx
│   │   │   ├── layout
│   │   │   │   ├── nav.tsx
│   │   │   │   ├── theme-toggle.tsx
│   │   │   │   ├── toc-thumb.tsx
│   │   │   │   └── toc.tsx
│   │   │   ├── page.client.tsx
│   │   │   ├── page.tsx
│   │   │   ├── shared.tsx
│   │   │   └── ui
│   │   │       ├── button.tsx
│   │   │       ├── collapsible.tsx
│   │   │       ├── popover.tsx
│   │   │       └── scroll-area.tsx
│   │   ├── endpoint.tsx
│   │   ├── features.tsx
│   │   ├── floating-ai-search.tsx
│   │   ├── fork-button.tsx
│   │   ├── generate-apple-jwt.tsx
│   │   ├── generate-secret.tsx
│   │   ├── github-stat.tsx
│   │   ├── icons.tsx
│   │   ├── landing
│   │   │   ├── gradient-bg.tsx
│   │   │   ├── grid-pattern.tsx
│   │   │   ├── hero.tsx
│   │   │   ├── section-svg.tsx
│   │   │   ├── section.tsx
│   │   │   ├── spotlight.tsx
│   │   │   └── testimonials.tsx
│   │   ├── logo-context-menu.tsx
│   │   ├── logo.tsx
│   │   ├── markdown-renderer.tsx
│   │   ├── markdown.tsx
│   │   ├── mdx
│   │   │   ├── add-to-cursor.tsx
│   │   │   └── database-tables.tsx
│   │   ├── message-feedback.tsx
│   │   ├── mobile-search-icon.tsx
│   │   ├── nav-bar.tsx
│   │   ├── nav-link.tsx
│   │   ├── nav-mobile.tsx
│   │   ├── promo-card.tsx
│   │   ├── resource-card.tsx
│   │   ├── resource-grid.tsx
│   │   ├── resource-section.tsx
│   │   ├── ripple.tsx
│   │   ├── search-dialog.tsx
│   │   ├── side-bar.tsx
│   │   ├── sidebar-content.tsx
│   │   ├── techstack-icons.tsx
│   │   ├── theme-provider.tsx
│   │   ├── theme-toggler.tsx
│   │   └── ui
│   │       ├── accordion.tsx
│   │       ├── alert-dialog.tsx
│   │       ├── alert.tsx
│   │       ├── aside-link.tsx
│   │       ├── aspect-ratio.tsx
│   │       ├── avatar.tsx
│   │       ├── background-beams.tsx
│   │       ├── background-boxes.tsx
│   │       ├── badge.tsx
│   │       ├── breadcrumb.tsx
│   │       ├── button.tsx
│   │       ├── calendar.tsx
│   │       ├── callout.tsx
│   │       ├── card.tsx
│   │       ├── carousel.tsx
│   │       ├── chart.tsx
│   │       ├── checkbox.tsx
│   │       ├── code-block.tsx
│   │       ├── collapsible.tsx
│   │       ├── command.tsx
│   │       ├── context-menu.tsx
│   │       ├── dialog.tsx
│   │       ├── drawer.tsx
│   │       ├── dropdown-menu.tsx
│   │       ├── dynamic-code-block.tsx
│   │       ├── fade-in.tsx
│   │       ├── form.tsx
│   │       ├── hover-card.tsx
│   │       ├── input-otp.tsx
│   │       ├── input.tsx
│   │       ├── label.tsx
│   │       ├── menubar.tsx
│   │       ├── navigation-menu.tsx
│   │       ├── pagination.tsx
│   │       ├── popover.tsx
│   │       ├── progress.tsx
│   │       ├── radio-group.tsx
│   │       ├── resizable.tsx
│   │       ├── scroll-area.tsx
│   │       ├── select.tsx
│   │       ├── separator.tsx
│   │       ├── sheet.tsx
│   │       ├── sidebar.tsx
│   │       ├── skeleton.tsx
│   │       ├── slider.tsx
│   │       ├── sonner.tsx
│   │       ├── sparkles.tsx
│   │       ├── switch.tsx
│   │       ├── table.tsx
│   │       ├── tabs.tsx
│   │       ├── textarea.tsx
│   │       ├── toggle-group.tsx
│   │       ├── toggle.tsx
│   │       ├── tooltip-docs.tsx
│   │       ├── tooltip.tsx
│   │       └── use-copy-button.tsx
│   ├── components.json
│   ├── content
│   │   ├── blogs
│   │   │   ├── 0-supabase-auth-to-planetscale-migration.mdx
│   │   │   ├── 1-3.mdx
│   │   │   ├── authjs-joins-better-auth.mdx
│   │   │   └── seed-round.mdx
│   │   ├── changelogs
│   │   │   ├── 1-2.mdx
│   │   │   └── 1.0.mdx
│   │   └── docs
│   │       ├── adapters
│   │       │   ├── community-adapters.mdx
│   │       │   ├── drizzle.mdx
│   │       │   ├── mongo.mdx
│   │       │   ├── mssql.mdx
│   │       │   ├── mysql.mdx
│   │       │   ├── other-relational-databases.mdx
│   │       │   ├── postgresql.mdx
│   │       │   ├── prisma.mdx
│   │       │   └── sqlite.mdx
│   │       ├── authentication
│   │       │   ├── apple.mdx
│   │       │   ├── atlassian.mdx
│   │       │   ├── cognito.mdx
│   │       │   ├── discord.mdx
│   │       │   ├── dropbox.mdx
│   │       │   ├── email-password.mdx
│   │       │   ├── facebook.mdx
│   │       │   ├── figma.mdx
│   │       │   ├── github.mdx
│   │       │   ├── gitlab.mdx
│   │       │   ├── google.mdx
│   │       │   ├── huggingface.mdx
│   │       │   ├── kakao.mdx
│   │       │   ├── kick.mdx
│   │       │   ├── line.mdx
│   │       │   ├── linear.mdx
│   │       │   ├── linkedin.mdx
│   │       │   ├── microsoft.mdx
│   │       │   ├── naver.mdx
│   │       │   ├── notion.mdx
│   │       │   ├── other-social-providers.mdx
│   │       │   ├── paypal.mdx
│   │       │   ├── reddit.mdx
│   │       │   ├── roblox.mdx
│   │       │   ├── salesforce.mdx
│   │       │   ├── slack.mdx
│   │       │   ├── spotify.mdx
│   │       │   ├── tiktok.mdx
│   │       │   ├── twitch.mdx
│   │       │   ├── twitter.mdx
│   │       │   ├── vk.mdx
│   │       │   └── zoom.mdx
│   │       ├── basic-usage.mdx
│   │       ├── comparison.mdx
│   │       ├── concepts
│   │       │   ├── api.mdx
│   │       │   ├── cli.mdx
│   │       │   ├── client.mdx
│   │       │   ├── cookies.mdx
│   │       │   ├── database.mdx
│   │       │   ├── email.mdx
│   │       │   ├── hooks.mdx
│   │       │   ├── oauth.mdx
│   │       │   ├── plugins.mdx
│   │       │   ├── rate-limit.mdx
│   │       │   ├── session-management.mdx
│   │       │   ├── typescript.mdx
│   │       │   └── users-accounts.mdx
│   │       ├── examples
│   │       │   ├── astro.mdx
│   │       │   ├── next-js.mdx
│   │       │   ├── nuxt.mdx
│   │       │   ├── remix.mdx
│   │       │   └── svelte-kit.mdx
│   │       ├── guides
│   │       │   ├── auth0-migration-guide.mdx
│   │       │   ├── browser-extension-guide.mdx
│   │       │   ├── clerk-migration-guide.mdx
│   │       │   ├── create-a-db-adapter.mdx
│   │       │   ├── next-auth-migration-guide.mdx
│   │       │   ├── optimizing-for-performance.mdx
│   │       │   ├── saml-sso-with-okta.mdx
│   │       │   ├── supabase-migration-guide.mdx
│   │       │   └── your-first-plugin.mdx
│   │       ├── installation.mdx
│   │       ├── integrations
│   │       │   ├── astro.mdx
│   │       │   ├── convex.mdx
│   │       │   ├── elysia.mdx
│   │       │   ├── expo.mdx
│   │       │   ├── express.mdx
│   │       │   ├── fastify.mdx
│   │       │   ├── hono.mdx
│   │       │   ├── lynx.mdx
│   │       │   ├── nestjs.mdx
│   │       │   ├── next.mdx
│   │       │   ├── nitro.mdx
│   │       │   ├── nuxt.mdx
│   │       │   ├── remix.mdx
│   │       │   ├── solid-start.mdx
│   │       │   ├── svelte-kit.mdx
│   │       │   ├── tanstack.mdx
│   │       │   └── waku.mdx
│   │       ├── introduction.mdx
│   │       ├── meta.json
│   │       ├── plugins
│   │       │   ├── 2fa.mdx
│   │       │   ├── admin.mdx
│   │       │   ├── anonymous.mdx
│   │       │   ├── api-key.mdx
│   │       │   ├── autumn.mdx
│   │       │   ├── bearer.mdx
│   │       │   ├── captcha.mdx
│   │       │   ├── community-plugins.mdx
│   │       │   ├── device-authorization.mdx
│   │       │   ├── dodopayments.mdx
│   │       │   ├── dub.mdx
│   │       │   ├── email-otp.mdx
│   │       │   ├── generic-oauth.mdx
│   │       │   ├── have-i-been-pwned.mdx
│   │       │   ├── jwt.mdx
│   │       │   ├── last-login-method.mdx
│   │       │   ├── magic-link.mdx
│   │       │   ├── mcp.mdx
│   │       │   ├── multi-session.mdx
│   │       │   ├── oauth-proxy.mdx
│   │       │   ├── oidc-provider.mdx
│   │       │   ├── one-tap.mdx
│   │       │   ├── one-time-token.mdx
│   │       │   ├── open-api.mdx
│   │       │   ├── organization.mdx
│   │       │   ├── passkey.mdx
│   │       │   ├── phone-number.mdx
│   │       │   ├── polar.mdx
│   │       │   ├── siwe.mdx
│   │       │   ├── sso.mdx
│   │       │   ├── stripe.mdx
│   │       │   └── username.mdx
│   │       └── reference
│   │           ├── contributing.mdx
│   │           ├── faq.mdx
│   │           ├── options.mdx
│   │           ├── resources.mdx
│   │           ├── security.mdx
│   │           └── telemetry.mdx
│   ├── hooks
│   │   └── use-mobile.ts
│   ├── ignore-build.sh
│   ├── lib
│   │   ├── blog.ts
│   │   ├── chat
│   │   │   └── inkeep-qa-schema.ts
│   │   ├── constants.ts
│   │   ├── export-search-indexes.ts
│   │   ├── inkeep-analytics.ts
│   │   ├── is-active.ts
│   │   ├── metadata.ts
│   │   ├── source.ts
│   │   └── utils.ts
│   ├── next.config.js
│   ├── package.json
│   ├── postcss.config.js
│   ├── proxy.ts
│   ├── public
│   │   ├── avatars
│   │   │   └── beka.jpg
│   │   ├── blogs
│   │   │   ├── authjs-joins.png
│   │   │   ├── seed-round.png
│   │   │   └── supabase-ps.png
│   │   ├── branding
│   │   │   ├── better-auth-brand-assets.zip
│   │   │   ├── better-auth-logo-dark.png
│   │   │   ├── better-auth-logo-dark.svg
│   │   │   ├── better-auth-logo-light.png
│   │   │   ├── better-auth-logo-light.svg
│   │   │   ├── better-auth-logo-wordmark-dark.png
│   │   │   ├── better-auth-logo-wordmark-dark.svg
│   │   │   ├── better-auth-logo-wordmark-light.png
│   │   │   └── better-auth-logo-wordmark-light.svg
│   │   ├── extension-id.png
│   │   ├── favicon
│   │   │   ├── android-chrome-192x192.png
│   │   │   ├── android-chrome-512x512.png
│   │   │   ├── apple-touch-icon.png
│   │   │   ├── favicon-16x16.png
│   │   │   ├── favicon-32x32.png
│   │   │   ├── favicon.ico
│   │   │   ├── light
│   │   │   │   ├── android-chrome-192x192.png
│   │   │   │   ├── android-chrome-512x512.png
│   │   │   │   ├── apple-touch-icon.png
│   │   │   │   ├── favicon-16x16.png
│   │   │   │   ├── favicon-32x32.png
│   │   │   │   ├── favicon.ico
│   │   │   │   └── site.webmanifest
│   │   │   └── site.webmanifest
│   │   ├── images
│   │   │   └── blogs
│   │   │       └── better auth (1).png
│   │   ├── logo.png
│   │   ├── logo.svg
│   │   ├── LogoDark.webp
│   │   ├── LogoLight.webp
│   │   ├── og.png
│   │   ├── open-api-reference.png
│   │   ├── people-say
│   │   │   ├── code-with-antonio.jpg
│   │   │   ├── dagmawi-babi.png
│   │   │   ├── dax.png
│   │   │   ├── dev-ed.png
│   │   │   ├── egoist.png
│   │   │   ├── guillermo-rauch.png
│   │   │   ├── jonathan-wilke.png
│   │   │   ├── josh-tried-coding.jpg
│   │   │   ├── kitze.jpg
│   │   │   ├── lazar-nikolov.png
│   │   │   ├── nizzy.png
│   │   │   ├── omar-mcadam.png
│   │   │   ├── ryan-vogel.jpg
│   │   │   ├── saltyatom.jpg
│   │   │   ├── sebastien-chopin.png
│   │   │   ├── shreyas-mididoddi.png
│   │   │   ├── tech-nerd.png
│   │   │   ├── theo.png
│   │   │   ├── vybhav-bhargav.png
│   │   │   └── xavier-pladevall.jpg
│   │   ├── plus.svg
│   │   ├── release-og
│   │   │   ├── 1-2.png
│   │   │   ├── 1-3.png
│   │   │   └── changelog-og.png
│   │   └── v1-og.png
│   ├── README.md
│   ├── scripts
│   │   ├── endpoint-to-doc
│   │   │   ├── index.ts
│   │   │   ├── input.ts
│   │   │   ├── output.mdx
│   │   │   └── readme.md
│   │   └── sync-orama.ts
│   ├── source.config.ts
│   ├── tailwind.config.js
│   ├── tsconfig.json
│   └── turbo.json
├── e2e
│   ├── integration
│   │   ├── package.json
│   │   ├── playwright.config.ts
│   │   ├── solid-vinxi
│   │   │   ├── .gitignore
│   │   │   ├── app.config.ts
│   │   │   ├── e2e
│   │   │   │   ├── test.spec.ts
│   │   │   │   └── utils.ts
│   │   │   ├── package.json
│   │   │   ├── public
│   │   │   │   └── favicon.ico
│   │   │   ├── src
│   │   │   │   ├── app.tsx
│   │   │   │   ├── entry-client.tsx
│   │   │   │   ├── entry-server.tsx
│   │   │   │   ├── global.d.ts
│   │   │   │   ├── lib
│   │   │   │   │   ├── auth-client.ts
│   │   │   │   │   └── auth.ts
│   │   │   │   └── routes
│   │   │   │       ├── [...404].tsx
│   │   │   │       ├── api
│   │   │   │       │   └── auth
│   │   │   │       │       └── [...all].ts
│   │   │   │       └── index.tsx
│   │   │   └── tsconfig.json
│   │   ├── test-utils
│   │   │   ├── package.json
│   │   │   └── src
│   │   │       └── playwright.ts
│   │   └── vanilla-node
│   │       ├── e2e
│   │       │   ├── app.ts
│   │       │   ├── domain.spec.ts
│   │       │   ├── postgres-js.spec.ts
│   │       │   ├── test.spec.ts
│   │       │   └── utils.ts
│   │       ├── index.html
│   │       ├── package.json
│   │       ├── src
│   │       │   ├── main.ts
│   │       │   └── vite-env.d.ts
│   │       ├── tsconfig.json
│   │       └── vite.config.ts
│   └── smoke
│       ├── package.json
│       ├── test
│       │   ├── bun.spec.ts
│       │   ├── cloudflare.spec.ts
│       │   ├── deno.spec.ts
│       │   ├── fixtures
│       │   │   ├── bun-simple.ts
│       │   │   ├── cloudflare
│       │   │   │   ├── .gitignore
│       │   │   │   ├── drizzle
│       │   │   │   │   ├── 0000_clean_vector.sql
│       │   │   │   │   └── meta
│       │   │   │   │       ├── _journal.json
│       │   │   │   │       └── 0000_snapshot.json
│       │   │   │   ├── drizzle.config.ts
│       │   │   │   ├── package.json
│       │   │   │   ├── src
│       │   │   │   │   ├── auth-schema.ts
│       │   │   │   │   ├── db.ts
│       │   │   │   │   └── index.ts
│       │   │   │   ├── test
│       │   │   │   │   ├── apply-migrations.ts
│       │   │   │   │   ├── env.d.ts
│       │   │   │   │   └── index.test.ts
│       │   │   │   ├── tsconfig.json
│       │   │   │   ├── vitest.config.ts
│       │   │   │   ├── worker-configuration.d.ts
│       │   │   │   └── wrangler.json
│       │   │   ├── deno-simple.ts
│       │   │   ├── tsconfig-exact-optional-property-types
│       │   │   │   ├── package.json
│       │   │   │   ├── src
│       │   │   │   │   ├── index.ts
│       │   │   │   │   └── user-additional-fields.ts
│       │   │   │   └── tsconfig.json
│       │   │   ├── tsconfig-verbatim-module-syntax-node10
│       │   │   │   ├── package.json
│       │   │   │   ├── src
│       │   │   │   │   └── index.ts
│       │   │   │   └── tsconfig.json
│       │   │   └── vite
│       │   │       ├── package.json
│       │   │       ├── src
│       │   │       │   ├── client.ts
│       │   │       │   └── server.ts
│       │   │       ├── tsconfig.json
│       │   │       └── vite.config.ts
│       │   ├── ssr.ts
│       │   ├── typecheck.spec.ts
│       │   └── vite.spec.ts
│       └── tsconfig.json
├── LICENSE.md
├── package.json
├── packages
│   ├── better-auth
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── __snapshots__
│   │   │   │   └── init.test.ts.snap
│   │   │   ├── adapters
│   │   │   │   ├── adapter-factory
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── test
│   │   │   │   │   │   ├── __snapshots__
│   │   │   │   │   │   │   └── adapter-factory.test.ts.snap
│   │   │   │   │   │   └── adapter-factory.test.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── create-test-suite.ts
│   │   │   │   ├── drizzle-adapter
│   │   │   │   │   ├── drizzle-adapter.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── test
│   │   │   │   │       ├── .gitignore
│   │   │   │   │       ├── adapter.drizzle.mysql.test.ts
│   │   │   │   │       ├── adapter.drizzle.pg.test.ts
│   │   │   │   │       ├── adapter.drizzle.sqlite.test.ts
│   │   │   │   │       └── generate-schema.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── kysely-adapter
│   │   │   │   │   ├── bun-sqlite-dialect.ts
│   │   │   │   │   ├── dialect.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── kysely-adapter.ts
│   │   │   │   │   ├── node-sqlite-dialect.ts
│   │   │   │   │   ├── test
│   │   │   │   │   │   ├── adapter.kysely.mssql.test.ts
│   │   │   │   │   │   ├── adapter.kysely.mysql.test.ts
│   │   │   │   │   │   ├── adapter.kysely.pg.test.ts
│   │   │   │   │   │   ├── adapter.kysely.sqlite.test.ts
│   │   │   │   │   │   └── node-sqlite-dialect.test.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── memory-adapter
│   │   │   │   │   ├── adapter.memory.test.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── memory-adapter.ts
│   │   │   │   ├── mongodb-adapter
│   │   │   │   │   ├── adapter.mongo-db.test.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── mongodb-adapter.ts
│   │   │   │   ├── prisma-adapter
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── prisma-adapter.ts
│   │   │   │   │   └── test
│   │   │   │   │       ├── .gitignore
│   │   │   │   │       ├── base.prisma
│   │   │   │   │       ├── generate-auth-config.ts
│   │   │   │   │       ├── generate-prisma-schema.ts
│   │   │   │   │       ├── get-prisma-client.ts
│   │   │   │   │       ├── prisma.mysql.test.ts
│   │   │   │   │       ├── prisma.pg.test.ts
│   │   │   │   │       ├── prisma.sqlite.test.ts
│   │   │   │   │       └── push-prisma-schema.ts
│   │   │   │   ├── test-adapter.ts
│   │   │   │   ├── test.ts
│   │   │   │   ├── tests
│   │   │   │   │   ├── auth-flow.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── normal.ts
│   │   │   │   │   ├── number-id.ts
│   │   │   │   │   ├── performance.ts
│   │   │   │   │   └── transactions.ts
│   │   │   │   └── utils.ts
│   │   │   ├── api
│   │   │   │   ├── check-endpoint-conflicts.test.ts
│   │   │   │   ├── index.test.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── middlewares
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── origin-check.test.ts
│   │   │   │   │   └── origin-check.ts
│   │   │   │   ├── rate-limiter
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── rate-limiter.test.ts
│   │   │   │   ├── routes
│   │   │   │   │   ├── account.test.ts
│   │   │   │   │   ├── account.ts
│   │   │   │   │   ├── callback.ts
│   │   │   │   │   ├── email-verification.test.ts
│   │   │   │   │   ├── email-verification.ts
│   │   │   │   │   ├── error.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── ok.ts
│   │   │   │   │   ├── reset-password.test.ts
│   │   │   │   │   ├── reset-password.ts
│   │   │   │   │   ├── session-api.test.ts
│   │   │   │   │   ├── session.ts
│   │   │   │   │   ├── sign-in.test.ts
│   │   │   │   │   ├── sign-in.ts
│   │   │   │   │   ├── sign-out.test.ts
│   │   │   │   │   ├── sign-out.ts
│   │   │   │   │   ├── sign-up.test.ts
│   │   │   │   │   ├── sign-up.ts
│   │   │   │   │   ├── update-user.test.ts
│   │   │   │   │   └── update-user.ts
│   │   │   │   ├── to-auth-endpoints.test.ts
│   │   │   │   └── to-auth-endpoints.ts
│   │   │   ├── auth.test.ts
│   │   │   ├── auth.ts
│   │   │   ├── call.test.ts
│   │   │   ├── client
│   │   │   │   ├── client-ssr.test.ts
│   │   │   │   ├── client.test.ts
│   │   │   │   ├── config.ts
│   │   │   │   ├── fetch-plugins.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── lynx
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── lynx-store.ts
│   │   │   │   ├── parser.ts
│   │   │   │   ├── path-to-object.ts
│   │   │   │   ├── plugins
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── infer-plugin.ts
│   │   │   │   ├── proxy.ts
│   │   │   │   ├── query.ts
│   │   │   │   ├── react
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── react-store.ts
│   │   │   │   ├── session-atom.ts
│   │   │   │   ├── solid
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── solid-store.ts
│   │   │   │   ├── svelte
│   │   │   │   │   └── index.ts
│   │   │   │   ├── test-plugin.ts
│   │   │   │   ├── types.ts
│   │   │   │   ├── url.test.ts
│   │   │   │   ├── vanilla.ts
│   │   │   │   └── vue
│   │   │   │       ├── index.ts
│   │   │   │       └── vue-store.ts
│   │   │   ├── cookies
│   │   │   │   ├── check-cookies.ts
│   │   │   │   ├── cookie-utils.ts
│   │   │   │   ├── cookies.test.ts
│   │   │   │   └── index.ts
│   │   │   ├── crypto
│   │   │   │   ├── buffer.ts
│   │   │   │   ├── hash.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── jwt.ts
│   │   │   │   ├── password.test.ts
│   │   │   │   ├── password.ts
│   │   │   │   └── random.ts
│   │   │   ├── db
│   │   │   │   ├── db.test.ts
│   │   │   │   ├── field.ts
│   │   │   │   ├── get-migration.ts
│   │   │   │   ├── get-schema.ts
│   │   │   │   ├── get-tables.test.ts
│   │   │   │   ├── get-tables.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── internal-adapter.test.ts
│   │   │   │   ├── internal-adapter.ts
│   │   │   │   ├── schema.ts
│   │   │   │   ├── secondary-storage.test.ts
│   │   │   │   ├── to-zod.ts
│   │   │   │   ├── utils.ts
│   │   │   │   └── with-hooks.ts
│   │   │   ├── index.ts
│   │   │   ├── init.test.ts
│   │   │   ├── init.ts
│   │   │   ├── integrations
│   │   │   │   ├── next-js.ts
│   │   │   │   ├── node.ts
│   │   │   │   ├── react-start.ts
│   │   │   │   ├── solid-start.ts
│   │   │   │   └── svelte-kit.ts
│   │   │   ├── oauth2
│   │   │   │   ├── index.ts
│   │   │   │   ├── link-account.test.ts
│   │   │   │   ├── link-account.ts
│   │   │   │   ├── state.ts
│   │   │   │   └── utils.ts
│   │   │   ├── plugins
│   │   │   │   ├── access
│   │   │   │   │   ├── access.test.ts
│   │   │   │   │   ├── access.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── additional-fields
│   │   │   │   │   ├── additional-fields.test.ts
│   │   │   │   │   └── client.ts
│   │   │   │   ├── admin
│   │   │   │   │   ├── access
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── statement.ts
│   │   │   │   │   ├── admin.test.ts
│   │   │   │   │   ├── admin.ts
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── error-codes.ts
│   │   │   │   │   ├── has-permission.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── schema.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── anonymous
│   │   │   │   │   ├── anon.test.ts
│   │   │   │   │   ├── client.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── api-key
│   │   │   │   │   ├── api-key.test.ts
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── rate-limit.ts
│   │   │   │   │   ├── routes
│   │   │   │   │   │   ├── create-api-key.ts
│   │   │   │   │   │   ├── delete-all-expired-api-keys.ts
│   │   │   │   │   │   ├── delete-api-key.ts
│   │   │   │   │   │   ├── get-api-key.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── list-api-keys.ts
│   │   │   │   │   │   ├── update-api-key.ts
│   │   │   │   │   │   └── verify-api-key.ts
│   │   │   │   │   ├── schema.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── bearer
│   │   │   │   │   ├── bearer.test.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── captcha
│   │   │   │   │   ├── captcha.test.ts
│   │   │   │   │   ├── constants.ts
│   │   │   │   │   ├── error-codes.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── utils.ts
│   │   │   │   │   └── verify-handlers
│   │   │   │   │       ├── captchafox.ts
│   │   │   │   │       ├── cloudflare-turnstile.ts
│   │   │   │   │       ├── google-recaptcha.ts
│   │   │   │   │       ├── h-captcha.ts
│   │   │   │   │       └── index.ts
│   │   │   │   ├── custom-session
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── custom-session.test.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── device-authorization
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── device-authorization.test.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── schema.ts
│   │   │   │   ├── email-otp
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── email-otp.test.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── generic-oauth
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── generic-oauth.test.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── haveibeenpwned
│   │   │   │   │   ├── haveibeenpwned.test.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── jwt
│   │   │   │   │   ├── adapter.ts
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── jwt.test.ts
│   │   │   │   │   ├── schema.ts
│   │   │   │   │   ├── sign.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── last-login-method
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── custom-prefix.test.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── last-login-method.test.ts
│   │   │   │   ├── magic-link
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── magic-link.test.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── mcp
│   │   │   │   │   ├── authorize.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── mcp.test.ts
│   │   │   │   ├── multi-session
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── multi-session.test.ts
│   │   │   │   ├── oauth-proxy
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── oauth-proxy.test.ts
│   │   │   │   ├── oidc-provider
│   │   │   │   │   ├── authorize.ts
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── oidc.test.ts
│   │   │   │   │   ├── schema.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── ui.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── one-tap
│   │   │   │   │   ├── client.ts
│   │   │   │   │   └── index.ts
│   │   │   │   ├── one-time-token
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── one-time-token.test.ts
│   │   │   │   │   └── utils.ts
│   │   │   │   ├── open-api
│   │   │   │   │   ├── generator.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── logo.ts
│   │   │   │   │   └── open-api.test.ts
│   │   │   │   ├── organization
│   │   │   │   │   ├── access
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── statement.ts
│   │   │   │   │   ├── adapter.ts
│   │   │   │   │   ├── call.ts
│   │   │   │   │   ├── client.test.ts
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── error-codes.ts
│   │   │   │   │   ├── has-permission.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── organization-hook.test.ts
│   │   │   │   │   ├── organization.test.ts
│   │   │   │   │   ├── organization.ts
│   │   │   │   │   ├── permission.ts
│   │   │   │   │   ├── routes
│   │   │   │   │   │   ├── crud-access-control.test.ts
│   │   │   │   │   │   ├── crud-access-control.ts
│   │   │   │   │   │   ├── crud-invites.ts
│   │   │   │   │   │   ├── crud-members.test.ts
│   │   │   │   │   │   ├── crud-members.ts
│   │   │   │   │   │   ├── crud-org.test.ts
│   │   │   │   │   │   ├── crud-org.ts
│   │   │   │   │   │   └── crud-team.ts
│   │   │   │   │   ├── schema.ts
│   │   │   │   │   ├── team.test.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── passkey
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── passkey.test.ts
│   │   │   │   ├── phone-number
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── phone-number-error.ts
│   │   │   │   │   └── phone-number.test.ts
│   │   │   │   ├── siwe
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── schema.ts
│   │   │   │   │   ├── siwe.test.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── sso
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── sso.test.ts
│   │   │   │   ├── two-factor
│   │   │   │   │   ├── backup-codes
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── client.ts
│   │   │   │   │   ├── constant.ts
│   │   │   │   │   ├── error-code.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── otp
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── schema.ts
│   │   │   │   │   ├── totp
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── two-factor.test.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── utils.ts
│   │   │   │   │   └── verify-two-factor.ts
│   │   │   │   └── username
│   │   │   │       ├── client.ts
│   │   │   │       ├── error-codes.ts
│   │   │   │       ├── index.ts
│   │   │   │       ├── schema.ts
│   │   │   │       └── username.test.ts
│   │   │   ├── social-providers
│   │   │   │   └── index.ts
│   │   │   ├── social.test.ts
│   │   │   ├── test-utils
│   │   │   │   ├── headers.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── state.ts
│   │   │   │   └── test-instance.ts
│   │   │   ├── types
│   │   │   │   ├── adapter.ts
│   │   │   │   ├── api.ts
│   │   │   │   ├── helper.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── models.ts
│   │   │   │   ├── plugins.ts
│   │   │   │   └── types.test.ts
│   │   │   └── utils
│   │   │       ├── await-object.ts
│   │   │       ├── boolean.ts
│   │   │       ├── clone.ts
│   │   │       ├── constants.ts
│   │   │       ├── date.ts
│   │   │       ├── ensure-utc.ts
│   │   │       ├── get-request-ip.ts
│   │   │       ├── hashing.ts
│   │   │       ├── hide-metadata.ts
│   │   │       ├── id.ts
│   │   │       ├── import-util.ts
│   │   │       ├── index.ts
│   │   │       ├── is-atom.ts
│   │   │       ├── is-promise.ts
│   │   │       ├── json.ts
│   │   │       ├── merger.ts
│   │   │       ├── middleware-response.ts
│   │   │       ├── misc.ts
│   │   │       ├── password.ts
│   │   │       ├── plugin-helper.ts
│   │   │       ├── shim.ts
│   │   │       ├── time.ts
│   │   │       ├── url.ts
│   │   │       └── wildcard.ts
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   └── vitest.config.ts
│   ├── cli
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── commands
│   │   │   │   ├── generate.ts
│   │   │   │   ├── info.ts
│   │   │   │   ├── init.ts
│   │   │   │   ├── login.ts
│   │   │   │   ├── mcp.ts
│   │   │   │   ├── migrate.ts
│   │   │   │   └── secret.ts
│   │   │   ├── generators
│   │   │   │   ├── auth-config.ts
│   │   │   │   ├── drizzle.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── kysely.ts
│   │   │   │   ├── prisma.ts
│   │   │   │   └── types.ts
│   │   │   ├── index.ts
│   │   │   └── utils
│   │   │       ├── add-svelte-kit-env-modules.ts
│   │   │       ├── check-package-managers.ts
│   │   │       ├── format-ms.ts
│   │   │       ├── get-config.ts
│   │   │       ├── get-package-info.ts
│   │   │       ├── get-tsconfig-info.ts
│   │   │       └── install-dependencies.ts
│   │   ├── test
│   │   │   ├── __snapshots__
│   │   │   │   ├── auth-schema-mysql-enum.txt
│   │   │   │   ├── auth-schema-mysql-number-id.txt
│   │   │   │   ├── auth-schema-mysql-passkey-number-id.txt
│   │   │   │   ├── auth-schema-mysql-passkey.txt
│   │   │   │   ├── auth-schema-mysql.txt
│   │   │   │   ├── auth-schema-number-id.txt
│   │   │   │   ├── auth-schema-pg-enum.txt
│   │   │   │   ├── auth-schema-pg-passkey.txt
│   │   │   │   ├── auth-schema-sqlite-enum.txt
│   │   │   │   ├── auth-schema-sqlite-number-id.txt
│   │   │   │   ├── auth-schema-sqlite-passkey-number-id.txt
│   │   │   │   ├── auth-schema-sqlite-passkey.txt
│   │   │   │   ├── auth-schema-sqlite.txt
│   │   │   │   ├── auth-schema.txt
│   │   │   │   ├── migrations.sql
│   │   │   │   ├── schema-mongodb.prisma
│   │   │   │   ├── schema-mysql-custom.prisma
│   │   │   │   ├── schema-mysql.prisma
│   │   │   │   ├── schema-numberid.prisma
│   │   │   │   └── schema.prisma
│   │   │   ├── generate-all-db.test.ts
│   │   │   ├── generate.test.ts
│   │   │   ├── get-config.test.ts
│   │   │   ├── info.test.ts
│   │   │   └── migrate.test.ts
│   │   ├── tsconfig.json
│   │   ├── tsconfig.test.json
│   │   └── tsdown.config.ts
│   ├── core
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── async_hooks
│   │   │   │   └── index.ts
│   │   │   ├── context
│   │   │   │   ├── index.ts
│   │   │   │   └── transaction.ts
│   │   │   ├── db
│   │   │   │   ├── adapter
│   │   │   │   │   └── index.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── plugin.ts
│   │   │   │   ├── schema
│   │   │   │   │   ├── account.ts
│   │   │   │   │   ├── rate-limit.ts
│   │   │   │   │   ├── session.ts
│   │   │   │   │   ├── shared.ts
│   │   │   │   │   ├── user.ts
│   │   │   │   │   └── verification.ts
│   │   │   │   └── type.ts
│   │   │   ├── env
│   │   │   │   ├── color-depth.ts
│   │   │   │   ├── env-impl.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── logger.test.ts
│   │   │   │   └── logger.ts
│   │   │   ├── error
│   │   │   │   ├── codes.ts
│   │   │   │   └── index.ts
│   │   │   ├── index.ts
│   │   │   ├── middleware
│   │   │   │   └── index.ts
│   │   │   ├── oauth2
│   │   │   │   ├── client-credentials-token.ts
│   │   │   │   ├── create-authorization-url.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── oauth-provider.ts
│   │   │   │   ├── refresh-access-token.ts
│   │   │   │   ├── utils.ts
│   │   │   │   └── validate-authorization-code.ts
│   │   │   ├── social-providers
│   │   │   │   ├── apple.ts
│   │   │   │   ├── atlassian.ts
│   │   │   │   ├── cognito.ts
│   │   │   │   ├── discord.ts
│   │   │   │   ├── dropbox.ts
│   │   │   │   ├── facebook.ts
│   │   │   │   ├── figma.ts
│   │   │   │   ├── github.ts
│   │   │   │   ├── gitlab.ts
│   │   │   │   ├── google.ts
│   │   │   │   ├── huggingface.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── kakao.ts
│   │   │   │   ├── kick.ts
│   │   │   │   ├── line.ts
│   │   │   │   ├── linear.ts
│   │   │   │   ├── linkedin.ts
│   │   │   │   ├── microsoft-entra-id.ts
│   │   │   │   ├── naver.ts
│   │   │   │   ├── notion.ts
│   │   │   │   ├── paypal.ts
│   │   │   │   ├── reddit.ts
│   │   │   │   ├── roblox.ts
│   │   │   │   ├── salesforce.ts
│   │   │   │   ├── slack.ts
│   │   │   │   ├── spotify.ts
│   │   │   │   ├── tiktok.ts
│   │   │   │   ├── twitch.ts
│   │   │   │   ├── twitter.ts
│   │   │   │   ├── vk.ts
│   │   │   │   └── zoom.ts
│   │   │   ├── types
│   │   │   │   ├── context.ts
│   │   │   │   ├── cookie.ts
│   │   │   │   ├── helper.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── init-options.ts
│   │   │   │   ├── plugin-client.ts
│   │   │   │   └── plugin.ts
│   │   │   └── utils
│   │   │       ├── error-codes.ts
│   │   │       └── index.ts
│   │   ├── tsconfig.json
│   │   └── tsdown.config.ts
│   ├── expo
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── client.ts
│   │   │   ├── expo.test.ts
│   │   │   └── index.ts
│   │   ├── tsconfig.json
│   │   └── tsdown.config.ts
│   ├── sso
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── client.ts
│   │   │   ├── index.ts
│   │   │   ├── oidc.test.ts
│   │   │   └── saml.test.ts
│   │   ├── tsconfig.json
│   │   └── tsdown.config.ts
│   ├── stripe
│   │   ├── CHANGELOG.md
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── client.ts
│   │   │   ├── hooks.ts
│   │   │   ├── index.ts
│   │   │   ├── schema.ts
│   │   │   ├── stripe.test.ts
│   │   │   ├── types.ts
│   │   │   └── utils.ts
│   │   ├── tsconfig.json
│   │   ├── tsdown.config.ts
│   │   └── vitest.config.ts
│   └── telemetry
│       ├── package.json
│       ├── src
│       │   ├── detectors
│       │   │   ├── detect-auth-config.ts
│       │   │   ├── detect-database.ts
│       │   │   ├── detect-framework.ts
│       │   │   ├── detect-project-info.ts
│       │   │   ├── detect-runtime.ts
│       │   │   └── detect-system-info.ts
│       │   ├── index.ts
│       │   ├── project-id.ts
│       │   ├── telemetry.test.ts
│       │   ├── types.ts
│       │   └── utils
│       │       ├── hash.ts
│       │       ├── id.ts
│       │       ├── import-util.ts
│       │       └── package-json.ts
│       ├── tsconfig.json
│       └── tsdown.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── README.md
├── SECURITY.md
├── tsconfig.json
└── turbo.json
```

# Files

--------------------------------------------------------------------------------
/packages/better-auth/src/client/session-atom.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { BetterFetch } from "@better-fetch/fetch";
 2 | import { atom } from "nanostores";
 3 | import { useAuthQuery } from "./query";
 4 | import type { Session, User } from "../types";
 5 | 
 6 | export function getSessionAtom($fetch: BetterFetch) {
 7 | 	const $signal = atom<boolean>(false);
 8 | 	const session = useAuthQuery<{
 9 | 		user: User;
10 | 		session: Session;
11 | 	}>($signal, "/get-session", $fetch, {
12 | 		method: "GET",
13 | 	});
14 | 	return {
15 | 		session,
16 | 		$sessionSignal: $signal,
17 | 	};
18 | }
19 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/api/routes/sign-out.test.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { describe, expect } from "vitest";
 2 | import { getTestInstance } from "../../test-utils/test-instance";
 3 | 
 4 | describe("sign-out", async (it) => {
 5 | 	const { signInWithTestUser, client } = await getTestInstance();
 6 | 
 7 | 	it("should sign out", async () => {
 8 | 		const { runWithUser } = await signInWithTestUser();
 9 | 		await runWithUser(async () => {
10 | 			const res = await client.signOut();
11 | 			expect(res.data).toMatchObject({
12 | 				success: true,
13 | 			});
14 | 		});
15 | 	});
16 | });
17 | 
```

--------------------------------------------------------------------------------
/e2e/smoke/test/fixtures/cloudflare/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "esnext",
 4 |     "lib": ["esnext"],
 5 |     "module": "esnext",
 6 |     "outDir": "./dist",
 7 |     "moduleResolution": "bundler",
 8 |     "types": [
 9 |       "@cloudflare/workers-types/2023-07-01",
10 |       "@cloudflare/workers-types/experimental",
11 |       "@cloudflare/vitest-pool-workers"
12 |     ],
13 |     "noEmit": true,
14 |     "isolatedModules": true,
15 |     "forceConsistentCasingInFileNames": true,
16 |     "skipLibCheck": true,
17 |     "strict": true
18 |   }
19 | }
20 | 
```

--------------------------------------------------------------------------------
/e2e/integration/solid-vinxi/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "better-auth-solid-vinxi-e2e",
 3 |   "private": true,
 4 |   "type": "module",
 5 |   "scripts": {
 6 |     "dev": "vinxi dev",
 7 |     "build": "vinxi build",
 8 |     "start": "vinxi start"
 9 |   },
10 |   "dependencies": {
11 |     "@solidjs/router": "^0.15.3",
12 |     "@solidjs/start": "^1.1.7",
13 |     "better-auth": "workspace:*",
14 |     "better-sqlite3": "^12.2.0",
15 |     "solid-js": "^1.9.7",
16 |     "vinxi": "^0.5.8"
17 |   },
18 |   "devDependencies": {
19 |     "@better-auth/test-utils": "workspace:*"
20 |   }
21 | }
22 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/phone-number/client.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { phoneNumber } from ".";
 2 | import type { BetterAuthClientPlugin } from "@better-auth/core";
 3 | 
 4 | export const phoneNumberClient = () => {
 5 | 	return {
 6 | 		id: "phoneNumber",
 7 | 		$InferServerPlugin: {} as ReturnType<typeof phoneNumber>,
 8 | 		atomListeners: [
 9 | 			{
10 | 				matcher(path) {
11 | 					return (
12 | 						path === "/phone-number/update" || path === "/phone-number/verify"
13 | 					);
14 | 				},
15 | 				signal: "$sessionSignal",
16 | 			},
17 | 		],
18 | 	} satisfies BetterAuthClientPlugin;
19 | };
20 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/device-authorization/client.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { deviceAuthorization } from ".";
 2 | import type { BetterAuthClientPlugin } from "@better-auth/core";
 3 | 
 4 | export const deviceAuthorizationClient = () => {
 5 | 	return {
 6 | 		id: "device-authorization",
 7 | 		$InferServerPlugin: {} as ReturnType<typeof deviceAuthorization>,
 8 | 		pathMethods: {
 9 | 			"/device/code": "POST",
10 | 			"/device/token": "POST",
11 | 			"/device": "GET",
12 | 			"/device/approve": "POST",
13 | 			"/device/deny": "POST",
14 | 		},
15 | 	} satisfies BetterAuthClientPlugin;
16 | };
17 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/phone-number/phone-number-error.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { defineErrorCodes } from "@better-auth/core/utils";
 2 | 
 3 | export const ERROR_CODES = defineErrorCodes({
 4 | 	INVALID_PHONE_NUMBER: "Invalid phone number",
 5 | 	PHONE_NUMBER_EXIST: "Phone number already exists",
 6 | 	INVALID_PHONE_NUMBER_OR_PASSWORD: "Invalid phone number or password",
 7 | 	UNEXPECTED_ERROR: "Unexpected error",
 8 | 	OTP_NOT_FOUND: "OTP not found",
 9 | 	OTP_EXPIRED: "OTP expired",
10 | 	INVALID_OTP: "Invalid OTP",
11 | 	PHONE_NUMBER_NOT_VERIFIED: "Phone number not verified",
12 | });
13 | 
```

--------------------------------------------------------------------------------
/e2e/smoke/test/fixtures/tsconfig-exact-optional-property-types/src/user-additional-fields.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { betterAuth } from "better-auth";
 2 | import Database from "better-sqlite3";
 3 | 
 4 | const auth = betterAuth({
 5 | 	database: new Database("./sqlite.db"),
 6 | 	trustedOrigins: [],
 7 | 	emailAndPassword: {
 8 | 		enabled: true,
 9 | 	},
10 | 	user: {
11 | 		additionalFields: {
12 | 			timeZone: {
13 | 				type: "string",
14 | 				required: true,
15 | 			},
16 | 		},
17 | 	},
18 | });
19 | 
20 | // expect no error here because timeZone is optional
21 | await auth.api.signUpEmail({
22 | 	body: {
23 | 		email: "",
24 | 		password: "",
25 | 		name: "",
26 | 		timeZone: "",
27 | 	},
28 | });
29 | 
```

--------------------------------------------------------------------------------
/packages/cli/src/commands/secret.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { logger } from "better-auth";
 2 | import chalk from "chalk";
 3 | import { Command } from "commander";
 4 | import Crypto from "crypto";
 5 | 
 6 | export const generateSecret = new Command("secret").action(() => {
 7 | 	const secret = generateSecretHash();
 8 | 	logger.info(`\nAdd the following to your .env file: 
 9 | ${
10 | 	chalk.gray("# Auth Secret") + chalk.green(`\nBETTER_AUTH_SECRET=${secret}`)
11 | }`);
12 | });
13 | 
14 | export const generateSecretHash = () => {
15 | 	return Crypto.randomBytes(32).toString("hex");
16 | };
17 | 
```

--------------------------------------------------------------------------------
/packages/cli/src/generators/kysely.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { getMigrations } from "better-auth/db";
 2 | import type { SchemaGenerator } from "./types";
 3 | 
 4 | export const generateMigrations: SchemaGenerator = async ({
 5 | 	options,
 6 | 	file,
 7 | }) => {
 8 | 	const { compileMigrations } = await getMigrations(options);
 9 | 	const migrations = await compileMigrations();
10 | 	return {
11 | 		code: migrations.trim() === ";" ? "" : migrations,
12 | 		fileName:
13 | 			file ||
14 | 			`./better-auth_migrations/${new Date()
15 | 				.toISOString()
16 | 				.replace(/:/g, "-")}.sql`,
17 | 	};
18 | };
19 | 
```

--------------------------------------------------------------------------------
/demo/expo-example/src/lib/utils.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { type ClassValue, clsx } from "clsx";
 2 | import { PressableStateCallbackType } from "react-native";
 3 | import { twMerge } from "tailwind-merge";
 4 | 
 5 | export function cn(...inputs: ClassValue[]) {
 6 | 	return twMerge(clsx(inputs));
 7 | }
 8 | export function isTextChildren(
 9 | 	children:
10 | 		| React.ReactNode
11 | 		| ((state: PressableStateCallbackType) => React.ReactNode),
12 | ) {
13 | 	return Array.isArray(children)
14 | 		? children.every((child) => typeof child === "string")
15 | 		: typeof children === "string";
16 | }
17 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/crypto/buffer.ts:
--------------------------------------------------------------------------------

```typescript
 1 | /**
 2 |  * Compare two buffers in constant time.
 3 |  */
 4 | export function constantTimeEqual(
 5 | 	a: ArrayBuffer | Uint8Array,
 6 | 	b: ArrayBuffer | Uint8Array,
 7 | ): boolean {
 8 | 	const aBuffer = new Uint8Array(a);
 9 | 	const bBuffer = new Uint8Array(b);
10 | 	let c = aBuffer.length ^ bBuffer.length;
11 | 	const length = Math.max(aBuffer.length, bBuffer.length);
12 | 	for (let i = 0; i < length; i++) {
13 | 		c |=
14 | 			(i < aBuffer.length ? aBuffer[i]! : 0) ^
15 | 			(i < bBuffer.length ? bBuffer[i]! : 0);
16 | 	}
17 | 	return c === 0;
18 | }
19 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/utils/await-object.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export async function awaitObject<T extends Record<string, Promise<any>>>(
 2 | 	promises: T,
 3 | ): Promise<{ [K in keyof T]: Awaited<T[K]> }> {
 4 | 	const entries = Object.entries(promises) as [keyof T, T[keyof T]][];
 5 | 	const results = await Promise.all(entries.map(([, promise]) => promise));
 6 | 
 7 | 	const resolved: Partial<{ [K in keyof T]: Awaited<T[K]> }> = {};
 8 | 	entries.forEach(([key], index) => {
 9 | 		resolved[key] = results[index];
10 | 	});
11 | 
12 | 	return resolved as { [K in keyof T]: Awaited<T[K]> };
13 | }
14 | 
```

--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------

```yaml
 1 | packages:
 2 |   - packages/**
 3 |   - docs
 4 |   - demo/*
 5 |   - e2e/**
 6 | 
 7 | catalog:
 8 |   '@better-fetch/fetch': 1.1.18
 9 |   better-call: 1.0.19
10 |   typescript: ^5.9.2
11 |   tsdown: ^0.15.6
12 |   vitest: ^3.2.4
13 | 
14 | catalogs:
15 |   react18:
16 |     '@types/react': ^19.1.12
17 |     '@types/react-dom': ^19.1.9
18 |     react: 19.1.1
19 |     react-dom: 19.1.1
20 | 
21 | neverBuiltDependencies: []
22 | 
23 | overrides:
24 |   brace-expansion@>=1.0.0 <=1.1.11: '>=1.1.12'
25 |   cookie@<0.7.0: '>=0.7.0'
26 |   esbuild@<=0.24.2: '>=0.25.0'
27 |   miniflare>zod: ^3.25.1
28 |   zod: ^4.1.5
29 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "strict": true,
 4 |     "target": "esnext",
 5 |     "module": "esnext",
 6 |     "moduleResolution": "bundler",
 7 |     "downlevelIteration": true,
 8 |     "baseUrl": ".",
 9 |     "esModuleInterop": true,
10 |     "skipLibCheck": true,
11 |     "verbatimModuleSyntax": true,
12 |     "noUncheckedIndexedAccess": true,
13 |     "exactOptionalPropertyTypes": false,
14 |     "incremental": true,
15 |     "noErrorTruncation": true,
16 |     "types": ["node", "bun"]
17 |   },
18 |   "exclude": ["**/dist/**", "**/node_modules/**"]
19 | }
20 | 
```

--------------------------------------------------------------------------------
/docs/components/logo.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { SVGProps } from "react";
 2 | import { cn } from "@/lib/utils";
 3 | export const Logo = (props: SVGProps<any>) => {
 4 | 	return (
 5 | 		<svg
 6 | 			width="60"
 7 | 			height="45"
 8 | 			viewBox="0 0 60 45"
 9 | 			fill="none"
10 | 			className={cn("w-5 h-5", props.className)}
11 | 			xmlns="http://www.w3.org/2000/svg"
12 | 		>
13 | 			<path
14 | 				fillRule="evenodd"
15 | 				clipRule="evenodd"
16 | 				d="M0 0H15V15H30V30H15V45H0V30V15V0ZM45 30V15H30V0H45H60V15V30V45H45H30V30H45Z"
17 | 				className="fill-black dark:fill-white"
18 | 			/>
19 | 		</svg>
20 | 	);
21 | };
22 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/adapters/prisma-adapter/test/push-prisma-schema.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { execSync } from "node:child_process";
 2 | import { createRequire } from "node:module";
 3 | import { join } from "node:path";
 4 | 
 5 | export async function pushPrismaSchema(
 6 | 	dialect: "sqlite" | "postgresql" | "mysql",
 7 | ) {
 8 | 	const node = process.execPath;
 9 | 	const cli = createRequire(import.meta.url).resolve("prisma");
10 | 	execSync(`${node} ${cli} db push --schema ./schema-${dialect}.prisma`, {
11 | 		stdio: "ignore", // use `inherit` if you want to see the output
12 | 		cwd: join(import.meta.dirname),
13 | 	});
14 | }
15 | 
```

--------------------------------------------------------------------------------
/e2e/integration/solid-vinxi/src/entry-server.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | // @refresh reload
 2 | import { createHandler, StartServer } from "@solidjs/start/server";
 3 | 
 4 | export default createHandler(() => (
 5 | 	<StartServer
 6 | 		document={({ assets, children, scripts }) => (
 7 | 			<html lang="en">
 8 | 				<head>
 9 | 					<meta charset="utf-8" />
10 | 					<meta name="viewport" content="width=device-width, initial-scale=1" />
11 | 					<link rel="icon" href="/favicon.ico" />
12 | 					{assets}
13 | 				</head>
14 | 				<body>
15 | 					<div id="app">{children}</div>
16 | 					{scripts}
17 | 				</body>
18 | 			</html>
19 | 		)}
20 | 	/>
21 | ));
22 | 
```

--------------------------------------------------------------------------------
/packages/telemetry/src/detectors/detect-project-info.ts:
--------------------------------------------------------------------------------

```typescript
 1 | // https://github.com/zkochan/packages/blob/main/which-pm-runs/index.js
 2 | import { env } from "@better-auth/core/env";
 3 | 
 4 | export function detectPackageManager() {
 5 | 	const userAgent = env.npm_config_user_agent;
 6 | 	if (!userAgent) {
 7 | 		return undefined;
 8 | 	}
 9 | 
10 | 	const pmSpec = userAgent.split(" ")[0]!;
11 | 	const separatorPos = pmSpec.lastIndexOf("/");
12 | 	const name = pmSpec.substring(0, separatorPos);
13 | 
14 | 	return {
15 | 		name: name === "npminstall" ? "cnpm" : name,
16 | 		version: pmSpec.substring(separatorPos + 1),
17 | 	};
18 | }
19 | 
```

--------------------------------------------------------------------------------
/packages/core/src/db/schema/verification.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import * as z from "zod";
 2 | import { coreSchema } from "./shared";
 3 | 
 4 | export const verificationSchema = coreSchema.extend({
 5 | 	value: z.string(),
 6 | 	expiresAt: z.date(),
 7 | 	identifier: z.string(),
 8 | });
 9 | 
10 | /**
11 |  * Verification schema type used by better-auth, note that it's possible that verification could have additional fields
12 |  *
13 |  * todo: we should use generics to extend this type with additional fields from plugins and options in the future
14 |  */
15 | export type Verification = z.infer<typeof verificationSchema>;
16 | 
```

--------------------------------------------------------------------------------
/packages/core/src/types/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export type * from "./helper";
 2 | export type {
 3 | 	BetterAuthAdvancedOptions,
 4 | 	GenerateIdFn,
 5 | 	BetterAuthRateLimitOptions,
 6 | 	BetterAuthOptions,
 7 | } from "./init-options";
 8 | export type { BetterAuthCookies } from "./cookie";
 9 | export type {
10 | 	AuthContext,
11 | 	GenericEndpointContext,
12 | 	InternalAdapter,
13 | } from "./context";
14 | export type { BetterAuthPlugin, HookEndpointContext } from "./plugin";
15 | export type {
16 | 	BetterAuthClientPlugin,
17 | 	BetterAuthClientOptions,
18 | 	ClientStore,
19 | 	ClientAtomListener,
20 | } from "./plugin-client";
21 | 
```

--------------------------------------------------------------------------------
/docs/app/blog/_components/fmt-dates.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { cn } from "@/lib/utils";
 2 | 
 3 | const dateFormatter = new Intl.DateTimeFormat("en-US", {
 4 | 	year: "numeric",
 5 | 	month: "short",
 6 | 	day: "numeric",
 7 | 	timeZone: "UTC",
 8 | });
 9 | 
10 | export function FormattedDate({
11 | 	date,
12 | 	...props
13 | }: React.ComponentPropsWithoutRef<"time"> & { date: string | Date }) {
14 | 	date = typeof date === "string" ? new Date(date) : date;
15 | 
16 | 	return (
17 | 		<time
18 | 			className={cn(props.className, "")}
19 | 			dateTime={date.toISOString()}
20 | 			{...props}
21 | 		>
22 | 			{dateFormatter.format(date)}
23 | 		</time>
24 | 	);
25 | }
26 | 
```

--------------------------------------------------------------------------------
/docs/app/changelogs/_components/fmt-dates.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { cn } from "@/lib/utils";
 2 | 
 3 | const dateFormatter = new Intl.DateTimeFormat("en-US", {
 4 | 	year: "numeric",
 5 | 	month: "short",
 6 | 	day: "numeric",
 7 | 	timeZone: "UTC",
 8 | });
 9 | 
10 | export function FormattedDate({
11 | 	date,
12 | 	...props
13 | }: React.ComponentPropsWithoutRef<"time"> & { date: string | Date }) {
14 | 	date = typeof date === "string" ? new Date(date) : date;
15 | 
16 | 	return (
17 | 		<time
18 | 			className={cn(props.className, "")}
19 | 			dateTime={date.toISOString()}
20 | 			{...props}
21 | 		>
22 | 			{dateFormatter.format(date)}
23 | 		</time>
24 | 	);
25 | }
26 | 
```

--------------------------------------------------------------------------------
/e2e/smoke/test/fixtures/bun-simple.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { betterAuth } from "better-auth";
 2 | import Database from "bun:sqlite";
 3 | import { getMigrations } from "better-auth/db";
 4 | 
 5 | const database = new Database(":memory:");
 6 | 
 7 | export const auth = betterAuth({
 8 | 	baseURL: "http://localhost:4000",
 9 | 	database,
10 | 	emailAndPassword: {
11 | 		enabled: true,
12 | 	},
13 | 	logger: {
14 | 		level: "debug",
15 | 	},
16 | });
17 | 
18 | const { runMigrations } = await getMigrations(auth.options);
19 | 
20 | await runMigrations();
21 | 
22 | const server = Bun.serve({
23 | 	fetch: auth.handler,
24 | 	port: 0,
25 | });
26 | 
27 | console.log(server.port);
28 | 
```

--------------------------------------------------------------------------------
/docs/components/resource-grid.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { cn } from "@/lib/utils";
 2 | import { ResourceCard } from "./resource-card";
 3 | 
 4 | interface ResourceGridProps {
 5 | 	resources: {
 6 | 		title: string;
 7 | 		description: string;
 8 | 		href: string;
 9 | 		tags?: string[];
10 | 	}[];
11 | 	className?: string;
12 | }
13 | 
14 | export function ResourceGrid({ resources, className }: ResourceGridProps) {
15 | 	return (
16 | 		<div className={cn("grid gap-4 sm:grid-cols-2 lg:grid-cols-3", className)}>
17 | 			{resources.map((resource) => (
18 | 				<ResourceCard key={resource.href} {...resource} />
19 | 			))}
20 | 		</div>
21 | 	);
22 | }
23 | 
```

--------------------------------------------------------------------------------
/docs/components/docs/shared.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import type { ReactNode } from "react";
 2 | import { Slot } from "@radix-ui/react-slot";
 3 | 
 4 | export interface BaseLayoutProps {
 5 | 	children?: ReactNode;
 6 | }
 7 | 
 8 | export function replaceOrDefault(
 9 | 	obj:
10 | 		| {
11 | 				enabled?: boolean;
12 | 				component?: ReactNode;
13 | 		  }
14 | 		| undefined,
15 | 	def: ReactNode,
16 | 	customComponentProps?: object,
17 | 	disabled?: ReactNode,
18 | ): ReactNode {
19 | 	if (obj?.enabled === false) return disabled;
20 | 	if (obj?.component !== undefined)
21 | 		return <Slot {...customComponentProps}>{obj.component}</Slot>;
22 | 
23 | 	return def;
24 | }
25 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/test-utils/state.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import * as fs from "fs";
 2 | import path from "path";
 3 | 
 4 | export type State = "IDLE" | "RUNNING";
 5 | 
 6 | export function makeTestState(dirname: string) {
 7 | 	const stateFilePath = path.join(dirname, "./state.txt");
 8 | 
 9 | 	function getState(): State {
10 | 		try {
11 | 			return fs
12 | 				.readFileSync(stateFilePath, "utf-8")
13 | 				.split("\n")[0]!
14 | 				.trim() as State;
15 | 		} catch {
16 | 			return "IDLE";
17 | 		}
18 | 	}
19 | 
20 | 	function setState(state: State) {
21 | 		fs.writeFileSync(stateFilePath, state, "utf-8");
22 | 	}
23 | 
24 | 	return { stateFilePath, getState, setState };
25 | }
26 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/captcha/error-codes.ts:
--------------------------------------------------------------------------------

```typescript
 1 | // These error codes are returned by the API
 2 | import { defineErrorCodes } from "@better-auth/core/utils";
 3 | 
 4 | export const EXTERNAL_ERROR_CODES = defineErrorCodes({
 5 | 	VERIFICATION_FAILED: "Captcha verification failed",
 6 | 	MISSING_RESPONSE: "Missing CAPTCHA response",
 7 | 	UNKNOWN_ERROR: "Something went wrong",
 8 | });
 9 | 
10 | // These error codes are only visible in the server logs
11 | export const INTERNAL_ERROR_CODES = defineErrorCodes({
12 | 	MISSING_SECRET_KEY: "Missing secret key",
13 | 	SERVICE_UNAVAILABLE: "CAPTCHA service unavailable",
14 | });
15 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/components/theme-toggle.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | import { Moon, Sun } from "lucide-react";
 3 | import { useTheme } from "next-themes";
 4 | 
 5 | import { Button } from "@/components/ui/button";
 6 | 
 7 | export function ThemeToggle() {
 8 | 	const { setTheme, theme } = useTheme();
 9 | 
10 | 	return (
11 | 		<Button
12 | 			variant="ghost"
13 | 			size="icon"
14 | 			onClick={() => setTheme(theme === "light" ? "dark" : "light")}
15 | 		>
16 | 			<Sun className="h-6 w-[1.3rem] dark:hidden" color="#000" />
17 | 			<Moon className="hidden h-5 w-5 dark:block" />
18 | 			<span className="sr-only">Toggle theme</span>
19 | 		</Button>
20 | 	);
21 | }
22 | 
```

--------------------------------------------------------------------------------
/docs/proxy.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { NextRequest, NextResponse } from "next/server";
 2 | import { isMarkdownPreferred, rewritePath } from "fumadocs-core/negotiation";
 3 | 
 4 | const { rewrite: rewriteLLM } = rewritePath("/docs/*path", "/llms.txt/*path");
 5 | 
 6 | export function proxy(request: NextRequest) {
 7 | 	if (isMarkdownPreferred(request)) {
 8 | 		const result = rewriteLLM(request.nextUrl.pathname);
 9 | 
10 | 		if (result) {
11 | 			return NextResponse.rewrite(new URL(result, request.nextUrl));
12 | 		}
13 | 	}
14 | 
15 | 	return NextResponse.next();
16 | }
17 | 
18 | export const config = {
19 | 	matcher: "/docs/:path*",
20 | };
21 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/username/error-codes.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { defineErrorCodes } from "@better-auth/core/utils";
 2 | 
 3 | export const USERNAME_ERROR_CODES = defineErrorCodes({
 4 | 	INVALID_USERNAME_OR_PASSWORD: "Invalid username or password",
 5 | 	EMAIL_NOT_VERIFIED: "Email not verified",
 6 | 	UNEXPECTED_ERROR: "Unexpected error",
 7 | 	USERNAME_IS_ALREADY_TAKEN: "Username is already taken. Please try another.",
 8 | 	USERNAME_TOO_SHORT: "Username is too short",
 9 | 	USERNAME_TOO_LONG: "Username is too long",
10 | 	INVALID_USERNAME: "Username is invalid",
11 | 	INVALID_DISPLAY_USERNAME: "Display username is invalid",
12 | });
13 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/siwe/schema.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { BetterAuthPluginDBSchema } from "@better-auth/core/db";
 2 | 
 3 | export const schema = {
 4 | 	walletAddress: {
 5 | 		fields: {
 6 | 			userId: {
 7 | 				type: "string",
 8 | 				references: {
 9 | 					model: "user",
10 | 					field: "id",
11 | 				},
12 | 				required: true,
13 | 			},
14 | 			address: {
15 | 				type: "string",
16 | 				required: true,
17 | 			},
18 | 			chainId: {
19 | 				type: "number",
20 | 				required: true,
21 | 			},
22 | 			isPrimary: {
23 | 				type: "boolean",
24 | 				defaultValue: false,
25 | 			},
26 | 			createdAt: {
27 | 				type: "date",
28 | 				required: true,
29 | 			},
30 | 		},
31 | 	},
32 | } satisfies BetterAuthPluginDBSchema;
33 | 
```

--------------------------------------------------------------------------------
/packages/cli/src/utils/check-package-managers.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { exec } from "child_process";
 2 | 
 3 | function checkCommand(command: string): Promise<boolean> {
 4 | 	return new Promise((resolve) => {
 5 | 		exec(`${command} --version`, (error) => {
 6 | 			if (error) {
 7 | 				resolve(false); // Command not found or error occurred
 8 | 			} else {
 9 | 				resolve(true); // Command exists
10 | 			}
11 | 		});
12 | 	});
13 | }
14 | 
15 | export async function checkPackageManagers(): Promise<{
16 | 	hasPnpm: boolean;
17 | 	hasBun: boolean;
18 | }> {
19 | 	const hasPnpm = await checkCommand("pnpm");
20 | 	const hasBun = await checkCommand("bun");
21 | 
22 | 	return {
23 | 		hasPnpm,
24 | 		hasBun,
25 | 	};
26 | }
27 | 
```

--------------------------------------------------------------------------------
/packages/core/src/db/schema/user.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import * as z from "zod";
 2 | import { coreSchema } from "./shared";
 3 | 
 4 | export const userSchema = coreSchema.extend({
 5 | 	email: z.string().transform((val) => val.toLowerCase()),
 6 | 	emailVerified: z.boolean().default(false),
 7 | 	name: z.string(),
 8 | 	image: z.string().nullish(),
 9 | });
10 | 
11 | /**
12 |  * User schema type used by better-auth, note that it's possible that user could have additional fields
13 |  *
14 |  * todo: we should use generics to extend this type with additional fields from plugins and options in the future
15 |  */
16 | export type User = z.infer<typeof userSchema>;
17 | 
```

--------------------------------------------------------------------------------
/packages/core/src/db/schema/session.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import * as z from "zod";
 2 | import { coreSchema } from "./shared";
 3 | 
 4 | export const sessionSchema = coreSchema.extend({
 5 | 	userId: z.coerce.string(),
 6 | 	expiresAt: z.date(),
 7 | 	token: z.string(),
 8 | 	ipAddress: z.string().nullish(),
 9 | 	userAgent: z.string().nullish(),
10 | });
11 | 
12 | /**
13 |  * Session schema type used by better-auth, note that it's possible that session could have additional fields
14 |  *
15 |  * todo: we should use generics to extend this type with additional fields from plugins and options in the future
16 |  */
17 | export type Session = z.infer<typeof sessionSchema>;
18 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/email-otp/utils.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { createHash } from "@better-auth/utils/hash";
 2 | import { base64Url } from "@better-auth/utils/base64";
 3 | export const defaultKeyHasher = async (otp: string) => {
 4 | 	const hash = await createHash("SHA-256").digest(
 5 | 		new TextEncoder().encode(otp),
 6 | 	);
 7 | 	const hashed = base64Url.encode(new Uint8Array(hash), {
 8 | 		padding: false,
 9 | 	});
10 | 	return hashed;
11 | };
12 | 
13 | export function splitAtLastColon(input: string): [string, string] {
14 | 	const idx = input.lastIndexOf(":");
15 | 	if (idx === -1) {
16 | 		return [input, ""];
17 | 	}
18 | 	return [input.slice(0, idx), input.slice(idx + 1)];
19 | }
20 | 
```

--------------------------------------------------------------------------------
/demo/expo-example/src/lib/auth.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { betterAuth } from "better-auth";
 2 | import { expo } from "@better-auth/expo";
 3 | import { Pool } from "pg";
 4 | 
 5 | export const auth = betterAuth({
 6 | 	database: new Pool({
 7 | 		connectionString: process.env.DATABASE_URL,
 8 | 	}),
 9 | 	emailAndPassword: {
10 | 		enabled: true,
11 | 	},
12 | 	plugins: [expo()],
13 | 	socialProviders: {
14 | 		github: {
15 | 			clientId: process.env.GITHUB_CLIENT_ID!,
16 | 			clientSecret: process.env.GITHUB_CLIENT_SECRET!,
17 | 		},
18 | 		google: {
19 | 			clientId: process.env.GOOGLE_CLIENT_ID!,
20 | 			clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
21 | 		},
22 | 	},
23 | 	trustedOrigins: ["exp://"],
24 | });
25 | 
```

--------------------------------------------------------------------------------
/docs/hooks/use-mobile.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import * as React from "react";
 2 | 
 3 | const MOBILE_BREAKPOINT = 768;
 4 | 
 5 | export function useIsMobile() {
 6 | 	const [isMobile, setIsMobile] = React.useState<boolean | undefined>(
 7 | 		undefined,
 8 | 	);
 9 | 
10 | 	React.useEffect(() => {
11 | 		const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
12 | 		const onChange = () => {
13 | 			setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
14 | 		};
15 | 		mql.addEventListener("change", onChange);
16 | 		setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
17 | 		return () => mql.removeEventListener("change", onChange);
18 | 	}, []);
19 | 
20 | 	return !!isMobile;
21 | }
22 | 
```

--------------------------------------------------------------------------------
/e2e/smoke/test/fixtures/deno-simple.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { betterAuth } from "better-auth";
 2 | import { DatabaseSync } from "node:sqlite";
 3 | import { getMigrations } from "better-auth/db";
 4 | 
 5 | const database = new DatabaseSync(":memory:");
 6 | 
 7 | export const auth = betterAuth({
 8 | 	baseURL: "http://localhost:4000",
 9 | 	database,
10 | 	emailAndPassword: {
11 | 		enabled: true,
12 | 	},
13 | 	logger: {
14 | 		level: "debug",
15 | 	},
16 | });
17 | 
18 | const { runMigrations } = await getMigrations(auth.options);
19 | 
20 | await runMigrations();
21 | 
22 | Deno.serve(
23 | 	{
24 | 		port: 0,
25 | 		onListen: ({ port }) => {
26 | 			console.log(`Listening on http://localhost:${port}`);
27 | 		},
28 | 	},
29 | 	auth.handler,
30 | );
31 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/two-factor/error-code.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { defineErrorCodes } from "@better-auth/core/utils";
 2 | 
 3 | export const TWO_FACTOR_ERROR_CODES = defineErrorCodes({
 4 | 	OTP_NOT_ENABLED: "OTP not enabled",
 5 | 	OTP_HAS_EXPIRED: "OTP has expired",
 6 | 	TOTP_NOT_ENABLED: "TOTP not enabled",
 7 | 	TWO_FACTOR_NOT_ENABLED: "Two factor isn't enabled",
 8 | 	BACKUP_CODES_NOT_ENABLED: "Backup codes aren't enabled",
 9 | 	INVALID_BACKUP_CODE: "Invalid backup code",
10 | 	INVALID_CODE: "Invalid code",
11 | 	TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE:
12 | 		"Too many attempts. Please request a new code.",
13 | 	INVALID_TWO_FACTOR_COOKIE: "Invalid two factor cookie",
14 | });
15 | 
```

--------------------------------------------------------------------------------
/e2e/integration/solid-vinxi/src/lib/auth.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { betterAuth } from "better-auth";
 2 | import Database from "better-sqlite3";
 3 | import { getMigrations } from "better-auth/db";
 4 | 
 5 | const database = new Database(":memory:");
 6 | const baseURL = process.env.BASE_URL || "http://localhost:3000";
 7 | 
 8 | export const auth = betterAuth({
 9 | 	database,
10 | 	baseURL,
11 | 	emailAndPassword: {
12 | 		enabled: true,
13 | 	},
14 | });
15 | 
16 | const { runMigrations } = await getMigrations(auth.options);
17 | 
18 | await runMigrations();
19 | // Create an example user
20 | await auth.api.signUpEmail({
21 | 	body: {
22 | 		name: "Test User",
23 | 		email: "[email protected]",
24 | 		password: "password123",
25 | 	},
26 | });
27 | 
```

--------------------------------------------------------------------------------
/docs/lib/source.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { changelogCollection, docs, blogCollection } from "@/.source";
 2 | import { getPageTree } from "@/components/sidebar-content";
 3 | import { loader } from "fumadocs-core/source";
 4 | import { createMDXSource } from "fumadocs-mdx";
 5 | 
 6 | export let source = loader({
 7 | 	baseUrl: "/docs",
 8 | 	source: docs.toFumadocsSource(),
 9 | });
10 | 
11 | source = { ...source, pageTree: getPageTree() };
12 | 
13 | export const changelogs = loader({
14 | 	baseUrl: "/changelogs",
15 | 	source: createMDXSource(changelogCollection),
16 | });
17 | 
18 | export const blogs = loader({
19 | 	baseUrl: "/blogs",
20 | 	source: createMDXSource(blogCollection),
21 | });
22 | 
```

--------------------------------------------------------------------------------
/e2e/integration/solid-vinxi/src/routes/[...404].tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { A } from "@solidjs/router";
 2 | 
 3 | export default function NotFound() {
 4 | 	return (
 5 | 		<main class="text-center mx-auto text-gray-700 p-4">
 6 | 			<h1 class="max-6-xs text-6xl text-sky-700 font-thin uppercase my-16">
 7 | 				Not Found
 8 | 			</h1>
 9 | 			<p class="mt-8">
10 | 				Visit{" "}
11 | 				<a
12 | 					href="https://solidjs.com"
13 | 					target="_blank"
14 | 					class="text-sky-600 hover:underline"
15 | 				>
16 | 					solidjs.com
17 | 				</a>{" "}
18 | 				to learn how to build Solid apps.
19 | 			</p>
20 | 			<p class="my-4">
21 | 				<A href="/" class="text-sky-600 hover:underline">
22 | 					Home
23 | 				</A>
24 | 			</p>
25 | 		</main>
26 | 	);
27 | }
28 | 
```

--------------------------------------------------------------------------------
/packages/core/src/oauth2/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export type {
 2 | 	OAuth2Tokens,
 3 | 	OAuthProvider,
 4 | 	OAuth2UserInfo,
 5 | 	ProviderOptions,
 6 | } from "./oauth-provider";
 7 | 
 8 | export { generateCodeChallenge, getOAuth2Tokens } from "./utils";
 9 | export { createAuthorizationURL } from "./create-authorization-url";
10 | export {
11 | 	createAuthorizationCodeRequest,
12 | 	validateAuthorizationCode,
13 | 	validateToken,
14 | } from "./validate-authorization-code";
15 | export {
16 | 	createRefreshAccessTokenRequest,
17 | 	refreshAccessToken,
18 | } from "./refresh-access-token";
19 | export {
20 | 	clientCredentialsToken,
21 | 	createClientCredentialsTokenRequest,
22 | } from "./client-credentials-token";
23 | 
```

--------------------------------------------------------------------------------
/packages/telemetry/src/detectors/detect-framework.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { getPackageVersion } from "../utils/package-json";
 2 | 
 3 | const FRAMEWORKS: Record<string, string> = {
 4 | 	next: "next",
 5 | 	nuxt: "nuxt",
 6 | 	"@remix-run/server-runtime": "remix",
 7 | 	astro: "astro",
 8 | 	"@sveltejs/kit": "sveltekit",
 9 | 	"solid-start": "solid-start",
10 | 	"tanstack-start": "tanstack-start",
11 | 	hono: "hono",
12 | 	express: "express",
13 | 	elysia: "elysia",
14 | 	expo: "expo",
15 | };
16 | 
17 | export async function detectFramework() {
18 | 	for (const [pkg, name] of Object.entries(FRAMEWORKS)) {
19 | 		const version = await getPackageVersion(pkg);
20 | 		if (version) return { name, version };
21 | 	}
22 | 	return undefined;
23 | }
24 | 
```

--------------------------------------------------------------------------------
/docs/content/docs/integrations/solid-start.mdx:
--------------------------------------------------------------------------------

```markdown
 1 | ---
 2 | title: SolidStart Integration
 3 | description: Integrate Better Auth with SolidStart.
 4 | ---
 5 | 
 6 | Before you start, make sure you have a Better Auth instance configured. If you haven't done that yet, check out the [installation](/docs/installation).
 7 | 
 8 | ### Mount the handler
 9 | 
10 | We need to mount the handler to SolidStart server. Put the following code in your `*auth.ts` file inside `/routes/api/auth` folder.
11 | 
12 | ```ts title="*auth.ts"
13 | import { auth } from "~/lib/auth";
14 | import { toSolidStartHandler } from "better-auth/solid-start";
15 | 
16 | export const { GET, POST } = toSolidStartHandler(auth);
17 | ```
```

--------------------------------------------------------------------------------
/packages/better-auth/src/client/plugins/infer-plugin.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { BetterAuthClientPlugin } from "@better-auth/core";
 2 | import type { BetterAuthOptions } from "@better-auth/core";
 3 | 
 4 | export const InferServerPlugin = <
 5 | 	AuthOrOption extends
 6 | 		| BetterAuthOptions
 7 | 		| {
 8 | 				options: BetterAuthOptions;
 9 | 		  },
10 | 	ID extends string,
11 | >() => {
12 | 	type Option = AuthOrOption extends { options: infer O } ? O : AuthOrOption;
13 | 	type Plugin = Option["plugins"] extends Array<infer P>
14 | 		? P extends {
15 | 				id: ID;
16 | 			}
17 | 			? P
18 | 			: never
19 | 		: never;
20 | 	return {
21 | 		id: "infer-server-plugin",
22 | 		$InferServerPlugin: {} as Plugin,
23 | 	} satisfies BetterAuthClientPlugin;
24 | };
25 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/oauth2/utils.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { symmetricDecrypt, symmetricEncrypt } from "../crypto";
 2 | import type { AuthContext } from "@better-auth/core";
 3 | 
 4 | export function decryptOAuthToken(token: string, ctx: AuthContext) {
 5 | 	if (!token) return token;
 6 | 	if (ctx.options.account?.encryptOAuthTokens) {
 7 | 		return symmetricDecrypt({
 8 | 			key: ctx.secret,
 9 | 			data: token,
10 | 		});
11 | 	}
12 | 	return token;
13 | }
14 | 
15 | export function setTokenUtil(
16 | 	token: string | null | undefined,
17 | 	ctx: AuthContext,
18 | ) {
19 | 	if (ctx.options.account?.encryptOAuthTokens && token) {
20 | 		return symmetricEncrypt({
21 | 			key: ctx.secret,
22 | 			data: token,
23 | 		});
24 | 	}
25 | 	return token;
26 | }
27 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/components/ui/label.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import * as React from "react";
 4 | import * as LabelPrimitive from "@radix-ui/react-label";
 5 | 
 6 | import { cn } from "@/lib/utils";
 7 | 
 8 | function Label({
 9 | 	className,
10 | 	...props
11 | }: React.ComponentProps<typeof LabelPrimitive.Root>) {
12 | 	return (
13 | 		<LabelPrimitive.Root
14 | 			data-slot="label"
15 | 			className={cn(
16 | 				"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
17 | 				className,
18 | 			)}
19 | 			{...props}
20 | 		/>
21 | 	);
22 | }
23 | 
24 | export { Label };
25 | 
```

--------------------------------------------------------------------------------
/docs/components/ui/label.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import * as React from "react";
 4 | import * as LabelPrimitive from "@radix-ui/react-label";
 5 | 
 6 | import { cn } from "@/lib/utils";
 7 | 
 8 | function Label({
 9 | 	className,
10 | 	...props
11 | }: React.ComponentProps<typeof LabelPrimitive.Root>) {
12 | 	return (
13 | 		<LabelPrimitive.Root
14 | 			data-slot="label"
15 | 			className={cn(
16 | 				"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
17 | 				className,
18 | 			)}
19 | 			{...props}
20 | 		/>
21 | 	);
22 | }
23 | 
24 | export { Label };
25 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/client/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { BetterAuthOptions, BetterAuthPlugin } from "@better-auth/core";
 2 | import type { BetterAuthClientPlugin } from "@better-auth/core";
 3 | export * from "./vanilla";
 4 | export * from "./query";
 5 | export * from "./types";
 6 | 
 7 | export const InferPlugin = <T extends BetterAuthPlugin>() => {
 8 | 	return {
 9 | 		id: "infer-server-plugin",
10 | 		$InferServerPlugin: {} as T,
11 | 	} satisfies BetterAuthClientPlugin;
12 | };
13 | 
14 | export function InferAuth<O extends { options: BetterAuthOptions }>() {
15 | 	return {} as O["options"];
16 | }
17 | 
18 | // @ts-expect-error
19 | export type * from "nanostores";
20 | export type * from "@better-fetch/fetch";
21 | 
```

--------------------------------------------------------------------------------
/e2e/smoke/test/fixtures/cloudflare/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "cloudflare",
 3 |   "private": true,
 4 |   "dependencies": {
 5 |     "better-auth": "workspace:*",
 6 |     "drizzle-orm": "^0.44.5",
 7 |     "hono": "^4.9.7"
 8 |   },
 9 |   "devDependencies": {
10 |     "@cloudflare/vitest-pool-workers": "^0.8.69",
11 |     "@cloudflare/workers-types": "^4.20250903.0",
12 |     "drizzle-kit": "^0.31.4",
13 |     "wrangler": "4.33.2"
14 |   },
15 |   "scripts": {
16 |     "check": "tsc && wrangler deploy --dry-run",
17 |     "dev": "wrangler dev",
18 |     "migrate:local": "wrangler d1 migrations apply db --local",
19 |     "cf-typegen": "wrangler types --env-interface CloudflareBindings",
20 |     "e2e:smoke": "vitest"
21 |   }
22 | }
23 | 
```

--------------------------------------------------------------------------------
/e2e/integration/vanilla-node/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "useDefineForClassFields": true,
 5 |     "module": "ESNext",
 6 |     "lib": ["ES2022", "DOM", "DOM.Iterable"],
 7 |     "skipLibCheck": true,
 8 |     "moduleResolution": "bundler",
 9 |     "allowImportingTsExtensions": true,
10 |     "verbatimModuleSyntax": true,
11 |     "esModuleInterop": true,
12 |     "moduleDetection": "force",
13 |     "noEmit": true,
14 |     "strict": true,
15 |     "noUnusedLocals": true,
16 |     "noUnusedParameters": true,
17 |     "erasableSyntaxOnly": true,
18 |     "noFallthroughCasesInSwitch": true,
19 |     "noUncheckedSideEffectImports": true
20 |   },
21 |   "include": ["src", "e2e"]
22 | }
23 | 
```

--------------------------------------------------------------------------------
/e2e/smoke/test/fixtures/cloudflare/vitest.config.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import {
 2 | 	defineWorkersProject,
 3 | 	readD1Migrations,
 4 | } from "@cloudflare/vitest-pool-workers/config";
 5 | import path from "node:path";
 6 | 
 7 | export default defineWorkersProject(async () => {
 8 | 	const migrationsPath = path.join(__dirname, "drizzle");
 9 | 	const migrations = await readD1Migrations(migrationsPath);
10 | 
11 | 	return {
12 | 		test: {
13 | 			setupFiles: ["./test/apply-migrations.ts"],
14 | 			poolOptions: {
15 | 				workers: {
16 | 					singleWorker: true,
17 | 					wrangler: { configPath: "./wrangler.json" },
18 | 					miniflare: {
19 | 						d1Databases: ["DB"],
20 | 						bindings: { TEST_MIGRATIONS: migrations },
21 | 					},
22 | 				},
23 | 			},
24 | 		},
25 | 	};
26 | });
27 | 
```

--------------------------------------------------------------------------------
/packages/telemetry/src/detectors/detect-database.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { getPackageVersion } from "../utils/package-json";
 2 | import type { DetectionInfo } from "../types";
 3 | 
 4 | const DATABASES: Record<string, string> = {
 5 | 	pg: "postgresql",
 6 | 	mysql: "mysql",
 7 | 	mariadb: "mariadb",
 8 | 	sqlite3: "sqlite",
 9 | 	"better-sqlite3": "sqlite",
10 | 	"@prisma/client": "prisma",
11 | 	mongoose: "mongodb",
12 | 	mongodb: "mongodb",
13 | 	"drizzle-orm": "drizzle",
14 | };
15 | 
16 | export async function detectDatabase(): Promise<DetectionInfo | undefined> {
17 | 	for (const [pkg, name] of Object.entries(DATABASES)) {
18 | 		const version = await getPackageVersion(pkg);
19 | 		if (version) return { name, version };
20 | 	}
21 | 	return undefined;
22 | }
23 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/turbo.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "$schema": "https://turborepo.org/schema.json",
 3 |   "extends": ["//"],
 4 |   "tasks": {
 5 |     "build": {
 6 |       "env": [
 7 |         "TURSO_DATABASE_URL",
 8 |         "TURSO_AUTH_TOKEN",
 9 |         "RESEND_API_KEY",
10 |         "BETTER_AUTH_EMAIL",
11 |         "BETTER_AUTH_SECRET",
12 |         "BETTER_AUTH_URL",
13 |         "GITHUB_CLIENT_SECRET",
14 |         "GITHUB_CLIENT_ID",
15 |         "GOOGLE_CLIENT_ID",
16 |         "GOOGLE_CLIENT_SECRET",
17 |         "DISCORD_CLIENT_ID",
18 |         "DISCORD_CLIENT_SECRET",
19 |         "MICROSOFT_CLIENT_ID",
20 |         "MICROSOFT_CLIENT_SECRET",
21 |         "STRIPE_KEY",
22 |         "STRIPE_WEBHOOK_SECRET"
23 |       ]
24 |     }
25 |   }
26 | }
27 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/utils/json.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { logger } from "@better-auth/core/env";
 2 | 
 3 | export function safeJSONParse<T>(data: unknown): T | null {
 4 | 	function reviver(_: string, value: any): any {
 5 | 		if (typeof value === "string") {
 6 | 			const iso8601Regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/;
 7 | 			if (iso8601Regex.test(value)) {
 8 | 				const date = new Date(value);
 9 | 				if (!isNaN(date.getTime())) {
10 | 					return date;
11 | 				}
12 | 			}
13 | 		}
14 | 		return value;
15 | 	}
16 | 	try {
17 | 		if (typeof data !== "string") {
18 | 			return data as T;
19 | 		}
20 | 		return JSON.parse(data, reviver);
21 | 	} catch (e) {
22 | 		logger.error("Error parsing JSON", { error: e });
23 | 		return null;
24 | 	}
25 | }
26 | 
```

--------------------------------------------------------------------------------
/docs/app/blog/layout.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { Metadata } from "next";
 2 | 
 3 | export const metadata: Metadata = {
 4 | 	title: "Blog - Better Auth",
 5 | 	description: "Latest updates, articles, and insights about Better Auth",
 6 | };
 7 | 
 8 | interface BlogLayoutProps {
 9 | 	children: React.ReactNode;
10 | }
11 | 
12 | export default function BlogLayout({ children }: BlogLayoutProps) {
13 | 	return (
14 | 		<div
15 | 			className="relative flex min-h-screen flex-col"
16 | 			style={{
17 | 				scrollbarWidth: "none",
18 | 				scrollbarColor: "transparent transparent",
19 | 				//@ts-expect-error
20 | 				"&::-webkit-scrollbar": {
21 | 					display: "none",
22 | 				},
23 | 			}}
24 | 		>
25 | 			<main className="flex-1">{children}</main>
26 | 		</div>
27 | 	);
28 | }
29 | 
```

--------------------------------------------------------------------------------
/docs/app/community/_components/header.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | export default function CommunityHeader() {
 2 | 	return (
 3 | 		<div className="h-full flex flex-col justify-center items-center text-white">
 4 | 			<div className="max-w-6xl mx-auto px-4 py-16">
 5 | 				<div className="text-center">
 6 | 					<h1 className="text-4xl tracking-tighter md:text-5xl mt-3 font-normal mb-6 text-stone-800 dark:text-white">
 7 | 						Open Source Community
 8 | 					</h1>
 9 | 					<p className="dark:text-gray-400 max-w-md mx-auto text-stone-800">
10 | 						join <span className="italic font-bold">better-auth</span> community
11 | 						to get help, share ideas, and stay up to date.
12 | 					</p>
13 | 				</div>
14 | 			</div>
15 | 		</div>
16 | 	);
17 | }
18 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/cookies/check-cookies.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { parseCookies } from "../cookies";
 2 | import type { AuthContext } from "@better-auth/core";
 3 | 
 4 | export const checkAuthCookie = async (
 5 | 	request: Request | Headers,
 6 | 	auth: {
 7 | 		$context: Promise<AuthContext>;
 8 | 	},
 9 | ) => {
10 | 	const headers = request instanceof Headers ? request : request.headers;
11 | 	const cookies = headers.get("cookie");
12 | 	if (!cookies) {
13 | 		return null;
14 | 	}
15 | 	const ctx = await auth.$context;
16 | 	const cookieName = ctx.authCookies.sessionToken.name;
17 | 	const parsedCookie = parseCookies(cookies);
18 | 	const sessionToken = parsedCookie.get(cookieName);
19 | 	if (sessionToken) {
20 | 		return sessionToken;
21 | 	}
22 | 	return null;
23 | };
24 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/two-factor/schema.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { BetterAuthPluginDBSchema } from "@better-auth/core/db";
 2 | 
 3 | export const schema = {
 4 | 	user: {
 5 | 		fields: {
 6 | 			twoFactorEnabled: {
 7 | 				type: "boolean",
 8 | 				required: false,
 9 | 				defaultValue: false,
10 | 				input: false,
11 | 			},
12 | 		},
13 | 	},
14 | 	twoFactor: {
15 | 		fields: {
16 | 			secret: {
17 | 				type: "string",
18 | 				required: true,
19 | 				returned: false,
20 | 			},
21 | 			backupCodes: {
22 | 				type: "string",
23 | 				required: true,
24 | 				returned: false,
25 | 			},
26 | 			userId: {
27 | 				type: "string",
28 | 				required: true,
29 | 				returned: false,
30 | 				references: {
31 | 					model: "user",
32 | 					field: "id",
33 | 				},
34 | 			},
35 | 		},
36 | 	},
37 | } satisfies BetterAuthPluginDBSchema;
38 | 
```

--------------------------------------------------------------------------------
/docs/public/branding/better-auth-logo-dark.svg:
--------------------------------------------------------------------------------

```
1 | <svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
2 | <rect width="500" height="500" fill="black"/>
3 | <rect x="69" y="121" width="86.9879" height="259" fill="white"/>
4 | <rect x="337.575" y="121" width="92.4247" height="259" fill="white"/>
5 | <rect x="427.282" y="121" width="83.4555" height="174.52" transform="rotate(90 427.282 121)" fill="white"/>
6 | <rect x="430" y="296.544" width="83.4555" height="177.238" transform="rotate(90 430 296.544)" fill="white"/>
7 | <rect x="252.762" y="204.455" width="92.0888" height="96.7741" transform="rotate(90 252.762 204.455)" fill="white"/>
8 | </svg>
9 | 
```

--------------------------------------------------------------------------------
/docs/public/branding/better-auth-logo-light.svg:
--------------------------------------------------------------------------------

```
1 | <svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
2 | <rect width="500" height="500" fill="white"/>
3 | <rect x="69" y="121" width="86.9879" height="259" fill="black"/>
4 | <rect x="337.575" y="121" width="92.4247" height="259" fill="black"/>
5 | <rect x="427.282" y="121" width="83.4555" height="174.52" transform="rotate(90 427.282 121)" fill="black"/>
6 | <rect x="430" y="296.544" width="83.4555" height="177.238" transform="rotate(90 430 296.544)" fill="black"/>
7 | <rect x="252.762" y="204.455" width="92.0888" height="96.7741" transform="rotate(90 252.762 204.455)" fill="black"/>
8 | </svg>
9 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2017",
 4 |     "lib": ["dom", "dom.iterable", "esnext"],
 5 |     "allowJs": true,
 6 |     "skipLibCheck": true,
 7 |     "strict": true,
 8 |     "noEmit": true,
 9 |     "esModuleInterop": true,
10 |     "module": "esnext",
11 |     "moduleResolution": "bundler",
12 |     "resolveJsonModule": true,
13 |     "isolatedModules": true,
14 |     "jsx": "preserve",
15 |     "incremental": true,
16 |     "plugins": [
17 |       {
18 |         "name": "next"
19 |       }
20 |     ],
21 |     "paths": {
22 |       "@/*": ["./*"]
23 |     }
24 |   },
25 |   "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26 |   "exclude": ["node_modules", "components/ui/**/*.tsx"]
27 | }
28 | 
```

--------------------------------------------------------------------------------
/docs/app/llms.txt/[...slug]/route.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { type NextRequest, NextResponse } from "next/server";
 2 | import { source } from "@/lib/source";
 3 | import { notFound } from "next/navigation";
 4 | import { getLLMText } from "@/app/docs/lib/get-llm-text";
 5 | 
 6 | export const revalidate = false;
 7 | 
 8 | export async function GET(
 9 | 	_req: NextRequest,
10 | 	{ params }: { params: Promise<{ slug: string[] }> },
11 | ) {
12 | 	const slug = (await params).slug;
13 | 	const page = source.getPage(slug);
14 | 	if (!page) notFound();
15 | 
16 | 	return new NextResponse(await getLLMText(page), {
17 | 		headers: {
18 | 			"Content-Type": "text/markdown",
19 | 		},
20 | 	});
21 | }
22 | 
23 | export function generateStaticParams() {
24 | 	return source.generateParams();
25 | }
26 | 
```

--------------------------------------------------------------------------------
/docs/components/landing/section-svg.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { Plus } from "lucide-react";
 2 | 
 3 | const SectionSvg = ({ crossesOffset }: { crossesOffset: string }) => {
 4 | 	return (
 5 | 		<>
 6 | 			<Plus
 7 | 				className={`hidden absolute -top-[0.3125rem] h-6 w-6 ${
 8 | 					crossesOffset && crossesOffset
 9 | 				} pointer-events-none lg:block lg:left-[3.275rem] text-neutral-300 dark:text-neutral-600 translate-y-[.5px]`}
10 | 			/>
11 | 
12 | 			<Plus
13 | 				className={`hidden absolute -top-[0.3125rem] h-6 w-6 right-[1.4625rem] ${
14 | 					crossesOffset && crossesOffset
15 | 				} pointer-events-none lg:block lg:right-[2.7750rem] text-neutral-300 dark:text-neutral-600 translate-y-[.5px]`}
16 | 			/>
17 | 		</>
18 | 	);
19 | };
20 | 
21 | export default SectionSvg;
22 | 
```

--------------------------------------------------------------------------------
/docs/components/builder/code-tabs/tab-bar.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { CodeTab } from "./code-tabs";
 2 | 
 3 | interface File {
 4 | 	id: string;
 5 | 	name: string;
 6 | 	content: string;
 7 | }
 8 | 
 9 | interface TabBarProps {
10 | 	files: File[];
11 | 	activeFileId: string;
12 | 	onTabClick: (fileId: string) => void;
13 | 	onTabClose: (fileId: string) => void;
14 | }
15 | 
16 | export function TabBar({
17 | 	files,
18 | 	activeFileId,
19 | 	onTabClick,
20 | 	onTabClose,
21 | }: TabBarProps) {
22 | 	return (
23 | 		<div className="flex bg-muted border-b border-border">
24 | 			{files.map((file) => (
25 | 				<CodeTab
26 | 					key={file.id}
27 | 					fileName={file.name}
28 | 					isActive={file.id === activeFileId}
29 | 					onClick={() => onTabClick(file.id)}
30 | 					onClose={() => onTabClose(file.id)}
31 | 				/>
32 | 			))}
33 | 		</div>
34 | 	);
35 | }
36 | 
```

--------------------------------------------------------------------------------
/packages/cli/src/utils/get-tsconfig-info.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import path from "path";
 2 | import fs from "fs";
 3 | 
 4 | export function stripJsonComments(jsonString: string): string {
 5 | 	return jsonString
 6 | 		.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (m, g) =>
 7 | 			g ? "" : m,
 8 | 		)
 9 | 		.replace(/,(?=\s*[}\]])/g, "");
10 | }
11 | export function getTsconfigInfo(cwd?: string, flatPath?: string) {
12 | 	let tsConfigPath: string;
13 | 	if (flatPath) {
14 | 		tsConfigPath = flatPath;
15 | 	} else {
16 | 		tsConfigPath = cwd
17 | 			? path.join(cwd, "tsconfig.json")
18 | 			: path.join("tsconfig.json");
19 | 	}
20 | 	try {
21 | 		const text = fs.readFileSync(tsConfigPath, "utf-8");
22 | 		return JSON.parse(stripJsonComments(text));
23 | 	} catch (error) {
24 | 		throw error;
25 | 	}
26 | }
27 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/crypto/hash.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { constantTimeEqual } from "./buffer";
 2 | import { createHash } from "@better-auth/utils/hash";
 3 | import { base64 } from "@better-auth/utils/base64";
 4 | 
 5 | export async function hashToBase64(
 6 | 	data: string | ArrayBuffer,
 7 | ): Promise<string> {
 8 | 	const buffer = await createHash("SHA-256").digest(data);
 9 | 	return base64.encode(buffer);
10 | }
11 | 
12 | export async function compareHash(
13 | 	data: string | ArrayBuffer,
14 | 	hash: string,
15 | ): Promise<boolean> {
16 | 	const buffer = await createHash("SHA-256").digest(
17 | 		typeof data === "string" ? new TextEncoder().encode(data) : data,
18 | 	);
19 | 	const hashBuffer = base64.decode(hash);
20 | 	return constantTimeEqual(buffer, hashBuffer);
21 | }
22 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/admin/schema.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { type BetterAuthPluginDBSchema } from "@better-auth/core/db";
 2 | 
 3 | export const schema = {
 4 | 	user: {
 5 | 		fields: {
 6 | 			role: {
 7 | 				type: "string",
 8 | 				required: false,
 9 | 				input: false,
10 | 			},
11 | 			banned: {
12 | 				type: "boolean",
13 | 				defaultValue: false,
14 | 				required: false,
15 | 				input: false,
16 | 			},
17 | 			banReason: {
18 | 				type: "string",
19 | 				required: false,
20 | 				input: false,
21 | 			},
22 | 			banExpires: {
23 | 				type: "date",
24 | 				required: false,
25 | 				input: false,
26 | 			},
27 | 		},
28 | 	},
29 | 	session: {
30 | 		fields: {
31 | 			impersonatedBy: {
32 | 				type: "string",
33 | 				required: false,
34 | 			},
35 | 		},
36 | 	},
37 | } satisfies BetterAuthPluginDBSchema;
38 | 
39 | export type AdminSchema = typeof schema;
40 | 
```

--------------------------------------------------------------------------------
/demo/expo-example/src/components/ui/separator.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import * as SeparatorPrimitive from "@rn-primitives/separator";
 2 | import * as React from "react";
 3 | import { cn } from "@/lib/utils";
 4 | 
 5 | const Separator = React.forwardRef<
 6 | 	SeparatorPrimitive.RootRef,
 7 | 	SeparatorPrimitive.RootProps
 8 | >(
 9 | 	(
10 | 		{ className, orientation = "horizontal", decorative = true, ...props },
11 | 		ref,
12 | 	) => (
13 | 		<SeparatorPrimitive.Root
14 | 			ref={ref}
15 | 			decorative={decorative}
16 | 			orientation={orientation}
17 | 			className={cn(
18 | 				"shrink-0 bg-border",
19 | 				orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
20 | 				className,
21 | 			)}
22 | 			{...props}
23 | 		/>
24 | 	),
25 | );
26 | Separator.displayName = SeparatorPrimitive.Root.displayName;
27 | 
28 | export { Separator };
29 | 
```

--------------------------------------------------------------------------------
/docs/components/ui/separator.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import * as React from "react";
 4 | import * as SeparatorPrimitive from "@radix-ui/react-separator";
 5 | 
 6 | import { cn } from "@/lib/utils";
 7 | 
 8 | function Separator({
 9 | 	className,
10 | 	orientation = "horizontal",
11 | 	decorative = true,
12 | 	...props
13 | }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
14 | 	return (
15 | 		<SeparatorPrimitive.Root
16 | 			data-slot="separator-root"
17 | 			decorative={decorative}
18 | 			orientation={orientation}
19 | 			className={cn(
20 | 				"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
21 | 				className,
22 | 			)}
23 | 			{...props}
24 | 		/>
25 | 	);
26 | }
27 | 
28 | export { Separator };
29 | 
```

--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "biome.enabled": true,
 3 |   "editor.defaultFormatter": "biomejs.biome",
 4 |   "[typescript]": {
 5 |     "editor.defaultFormatter": "biomejs.biome"
 6 |   },
 7 |   "[jsonc]": {
 8 |     "editor.defaultFormatter": "biomejs.biome"
 9 |   },
10 |   "[svelte]": {
11 |     "editor.defaultFormatter": "biomejs.biome"
12 |   },
13 |   "[vue]": {
14 |     "editor.defaultFormatter": "biomejs.biome"
15 |   },
16 |   "[json]": {
17 |     "editor.defaultFormatter": "biomejs.biome"
18 |   },
19 |   "typescript.tsdk": "node_modules/typescript/lib",
20 |   "[astro]": {
21 |     "editor.defaultFormatter": "biomejs.biome"
22 |   },
23 |   "[typescriptreact]": {
24 |     "editor.defaultFormatter": "biomejs.biome"
25 |   },
26 |   "[mdx]": {
27 |     "editor.defaultFormatter": "unifiedjs.vscode-mdx"
28 |   }
29 | }
30 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/admin/access/statement.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { createAccessControl } from "../../access";
 2 | 
 3 | export const defaultStatements = {
 4 | 	user: [
 5 | 		"create",
 6 | 		"list",
 7 | 		"set-role",
 8 | 		"ban",
 9 | 		"impersonate",
10 | 		"delete",
11 | 		"set-password",
12 | 		"get",
13 | 		"update",
14 | 	],
15 | 	session: ["list", "revoke", "delete"],
16 | } as const;
17 | 
18 | export const defaultAc = createAccessControl(defaultStatements);
19 | 
20 | export const adminAc = defaultAc.newRole({
21 | 	user: [
22 | 		"create",
23 | 		"list",
24 | 		"set-role",
25 | 		"ban",
26 | 		"impersonate",
27 | 		"delete",
28 | 		"set-password",
29 | 		"get",
30 | 		"update",
31 | 	],
32 | 	session: ["list", "revoke", "delete"],
33 | });
34 | 
35 | export const userAc = defaultAc.newRole({
36 | 	user: [],
37 | 	session: [],
38 | });
39 | 
40 | export const defaultRoles = {
41 | 	admin: adminAc,
42 | 	user: userAc,
43 | };
44 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/captcha/constants.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { Provider } from "./types";
 2 | 
 3 | export const defaultEndpoints = [
 4 | 	"/sign-up/email",
 5 | 	"/sign-in/email",
 6 | 	"/forget-password",
 7 | ];
 8 | 
 9 | export const Providers = {
10 | 	CLOUDFLARE_TURNSTILE: "cloudflare-turnstile",
11 | 	GOOGLE_RECAPTCHA: "google-recaptcha",
12 | 	HCAPTCHA: "hcaptcha",
13 | 	CAPTCHAFOX: "captchafox",
14 | } as const;
15 | 
16 | export const siteVerifyMap: Record<Provider, string> = {
17 | 	[Providers.CLOUDFLARE_TURNSTILE]:
18 | 		"https://challenges.cloudflare.com/turnstile/v0/siteverify",
19 | 	[Providers.GOOGLE_RECAPTCHA]:
20 | 		"https://www.google.com/recaptcha/api/siteverify",
21 | 	[Providers.HCAPTCHA]: "https://api.hcaptcha.com/siteverify",
22 | 	[Providers.CAPTCHAFOX]: "https://api.captchafox.com/siteverify",
23 | };
24 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/integrations/node.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { toNodeHandler as toNode } from "better-call/node";
 2 | import type { Auth } from "../auth";
 3 | import type { IncomingHttpHeaders } from "http";
 4 | 
 5 | export const toNodeHandler = (
 6 | 	auth:
 7 | 		| {
 8 | 				handler: Auth["handler"];
 9 | 		  }
10 | 		| Auth["handler"],
11 | ) => {
12 | 	return "handler" in auth ? toNode(auth.handler) : toNode(auth);
13 | };
14 | 
15 | export function fromNodeHeaders(nodeHeaders: IncomingHttpHeaders): Headers {
16 | 	const webHeaders = new Headers();
17 | 	for (const [key, value] of Object.entries(nodeHeaders)) {
18 | 		if (value !== undefined) {
19 | 			if (Array.isArray(value)) {
20 | 				value.forEach((v) => webHeaders.append(key, v));
21 | 			} else {
22 | 				webHeaders.set(key, value);
23 | 			}
24 | 		}
25 | 	}
26 | 	return webHeaders;
27 | }
28 | 
```

--------------------------------------------------------------------------------
/packages/telemetry/src/project-id.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { generateId } from "./utils/id";
 2 | import { hashToBase64 } from "./utils/hash";
 3 | import { getNameFromLocalPackageJson } from "./utils/package-json";
 4 | 
 5 | let projectIdCached: string | null = null;
 6 | 
 7 | export async function getProjectId(
 8 | 	baseUrl: string | undefined,
 9 | ): Promise<string> {
10 | 	if (projectIdCached) return projectIdCached;
11 | 
12 | 	const projectName = await getNameFromLocalPackageJson();
13 | 	if (projectName) {
14 | 		projectIdCached = await hashToBase64(
15 | 			baseUrl ? baseUrl + projectName : projectName,
16 | 		);
17 | 		return projectIdCached;
18 | 	}
19 | 
20 | 	if (baseUrl) {
21 | 		projectIdCached = await hashToBase64(baseUrl);
22 | 		return projectIdCached;
23 | 	}
24 | 
25 | 	projectIdCached = generateId(32);
26 | 	return projectIdCached;
27 | }
28 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/test-utils/headers.ts:
--------------------------------------------------------------------------------

```typescript
 1 | /**
 2 |  * converts set cookie containing headers to
 3 |  * cookie containing headers
 4 |  */
 5 | export function convertSetCookieToCookie(headers: Headers): Headers {
 6 | 	const setCookieHeaders: string[] = [];
 7 | 	headers.forEach((value, name) => {
 8 | 		if (name.toLowerCase() === "set-cookie") {
 9 | 			setCookieHeaders.push(value);
10 | 		}
11 | 	});
12 | 
13 | 	if (setCookieHeaders.length === 0) {
14 | 		return headers;
15 | 	}
16 | 
17 | 	const existingCookies = headers.get("cookie") || "";
18 | 	const cookies = existingCookies ? existingCookies.split("; ") : [];
19 | 
20 | 	setCookieHeaders.forEach((setCookie) => {
21 | 		const cookiePair = setCookie.split(";")[0]!;
22 | 		cookies.push(cookiePair.trim());
23 | 	});
24 | 
25 | 	headers.set("cookie", cookies.join("; "));
26 | 
27 | 	return headers;
28 | }
29 | 
```

--------------------------------------------------------------------------------
/docs/components/ui/progress.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import * as React from "react";
 4 | import * as ProgressPrimitive from "@radix-ui/react-progress";
 5 | 
 6 | import { cn } from "@/lib/utils";
 7 | 
 8 | function Progress({
 9 | 	className,
10 | 	value,
11 | 	...props
12 | }: React.ComponentProps<typeof ProgressPrimitive.Root>) {
13 | 	return (
14 | 		<ProgressPrimitive.Root
15 | 			data-slot="progress"
16 | 			className={cn(
17 | 				"bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",
18 | 				className,
19 | 			)}
20 | 			{...props}
21 | 		>
22 | 			<ProgressPrimitive.Indicator
23 | 				data-slot="progress-indicator"
24 | 				className="bg-primary h-full w-full flex-1 transition-all"
25 | 				style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
26 | 			/>
27 | 		</ProgressPrimitive.Root>
28 | 	);
29 | }
30 | 
31 | export { Progress };
32 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/components/ui/toaster.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import { useToast } from "@/hooks/use-toast";
 4 | import {
 5 | 	Toast,
 6 | 	ToastClose,
 7 | 	ToastDescription,
 8 | 	ToastProvider,
 9 | 	ToastTitle,
10 | 	ToastViewport,
11 | } from "@/components/ui/toast";
12 | 
13 | export function Toaster() {
14 | 	const { toasts } = useToast();
15 | 
16 | 	return (
17 | 		<ToastProvider>
18 | 			{toasts.map(function ({ id, title, description, action, ...props }) {
19 | 				return (
20 | 					<Toast key={id} {...props}>
21 | 						<div className="grid gap-1">
22 | 							{title && <ToastTitle>{title}</ToastTitle>}
23 | 							{description && (
24 | 								<ToastDescription>{description}</ToastDescription>
25 | 							)}
26 | 						</div>
27 | 						{action}
28 | 						<ToastClose />
29 | 					</Toast>
30 | 				);
31 | 			})}
32 | 			<ToastViewport />
33 | 		</ToastProvider>
34 | 	);
35 | }
36 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/components/ui/textarea.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import * as React from "react";
 2 | 
 3 | import { cn } from "@/lib/utils";
 4 | 
 5 | export interface TextareaProps
 6 | 	extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
 7 | 
 8 | const Textarea = ({
 9 | 	ref,
10 | 	className,
11 | 	...props
12 | }: TextareaProps & {
13 | 	ref: React.RefObject<HTMLTextAreaElement>;
14 | }) => {
15 | 	return (
16 | 		<textarea
17 | 			className={cn(
18 | 				"flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
19 | 				className,
20 | 			)}
21 | 			ref={ref}
22 | 			{...props}
23 | 		/>
24 | 	);
25 | };
26 | Textarea.displayName = "Textarea";
27 | 
28 | export { Textarea };
29 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/client/client-ssr.test.ts:
--------------------------------------------------------------------------------

```typescript
 1 | // @vitest-environment node
 2 | import { expect, it, vi } from "vitest";
 3 | import { createAuthClient as createVueClient } from "./vue";
 4 | 
 5 | it("should call '/api/auth' for vue client", async () => {
 6 | 	const customFetchImpl = vi.fn(async (url: string | Request | URL) => {
 7 | 		expect(url).toBe("/api/auth/get-session");
 8 | 		return new Response();
 9 | 	});
10 | 	process.env.BETTER_AUTH_URL = "http://localhost:3000";
11 | 	// use DisposableStack when Node.js 24 is the minimum requirement
12 | 	using _ = {
13 | 		[Symbol.dispose]() {
14 | 			process.env.BETTER_AUTH_URL = undefined;
15 | 		},
16 | 	};
17 | 	const client = createVueClient({
18 | 		fetchOptions: {
19 | 			customFetchImpl,
20 | 		},
21 | 	});
22 | 	await client.getSession();
23 | 	expect(customFetchImpl).toBeCalled();
24 | });
25 | 
```

--------------------------------------------------------------------------------
/docs/components/fork-button.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import Link from "next/link";
 2 | import { Button } from "./ui/button";
 3 | import { GitHubLogoIcon } from "@radix-ui/react-icons";
 4 | import { ExternalLink } from "lucide-react";
 5 | 
 6 | export function ForkButton({ url }: { url: string }) {
 7 | 	return (
 8 | 		<div className="flex items-center gap-2 my-2">
 9 | 			<Link href={`https://codesandbox.io/p/github/${url}`} target="_blank">
10 | 				<Button className="gap-2" variant="outline" size="sm">
11 | 					<ExternalLink size={12} />
12 | 					Open in Stackblitz
13 | 				</Button>
14 | 			</Link>
15 | 			<Link href={`https://github.com/${url}`} target="_blank">
16 | 				<Button className="gap-2" variant="secondary" size="sm">
17 | 					<GitHubLogoIcon />
18 | 					View on GitHub
19 | 				</Button>
20 | 			</Link>
21 | 		</div>
22 | 	);
23 | }
24 | 
```

--------------------------------------------------------------------------------
/docs/components/mobile-search-icon.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import { Search } from "lucide-react";
 4 | import { useSearchContext } from "fumadocs-ui/provider";
 5 | import { Button } from "@/components/ui/button";
 6 | import { cn } from "@/lib/utils";
 7 | 
 8 | interface MobileSearchIconProps {
 9 | 	className?: string;
10 | }
11 | 
12 | export function MobileSearchIcon({ className }: MobileSearchIconProps) {
13 | 	const { setOpenSearch } = useSearchContext();
14 | 
15 | 	const handleSearchClick = () => {
16 | 		setOpenSearch(true);
17 | 	};
18 | 
19 | 	return (
20 | 		<Button
21 | 			variant="ghost"
22 | 			size="icon"
23 | 			aria-label="Search"
24 | 			onClick={handleSearchClick}
25 | 			className={cn(
26 | 				"flex ring-0 shrink-0 md:hidden size-9 hover:bg-transparent",
27 | 				className,
28 | 			)}
29 | 		>
30 | 			<Search className="size-4" />
31 | 		</Button>
32 | 	);
33 | }
34 | 
```

--------------------------------------------------------------------------------
/packages/stripe/src/client.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { BetterAuthClientPlugin } from "better-auth";
 2 | import type { stripe } from "./index";
 3 | 
 4 | export const stripeClient = <
 5 | 	O extends {
 6 | 		subscription: boolean;
 7 | 	},
 8 | >(
 9 | 	options?: O,
10 | ) => {
11 | 	return {
12 | 		id: "stripe-client",
13 | 		$InferServerPlugin: {} as ReturnType<
14 | 			typeof stripe<
15 | 				O["subscription"] extends true
16 | 					? {
17 | 							stripeClient: any;
18 | 							stripeWebhookSecret: string;
19 | 							subscription: {
20 | 								enabled: true;
21 | 								plans: [];
22 | 							};
23 | 						}
24 | 					: {
25 | 							stripeClient: any;
26 | 							stripeWebhookSecret: string;
27 | 						}
28 | 			>
29 | 		>,
30 | 		pathMethods: {
31 | 			"/subscription/restore": "POST",
32 | 			"/subscription/billing-portal": "POST",
33 | 		},
34 | 	} satisfies BetterAuthClientPlugin;
35 | };
36 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/components/ui/separator.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import * as React from "react";
 4 | import * as SeparatorPrimitive from "@radix-ui/react-separator";
 5 | 
 6 | import { cn } from "@/lib/utils";
 7 | 
 8 | const Separator = ({
 9 | 	ref,
10 | 	className,
11 | 	orientation = "horizontal",
12 | 	decorative = true,
13 | 	...props
14 | }: React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> & {
15 | 	ref: React.RefObject<React.ElementRef<typeof SeparatorPrimitive.Root>>;
16 | }) => (
17 | 	<SeparatorPrimitive.Root
18 | 		ref={ref}
19 | 		decorative={decorative}
20 | 		orientation={orientation}
21 | 		className={cn(
22 | 			"shrink-0 bg-border",
23 | 			orientation === "horizontal" ? "h-px w-full" : "h-full w-px",
24 | 			className,
25 | 		)}
26 | 		{...props}
27 | 	/>
28 | );
29 | Separator.displayName = SeparatorPrimitive.Root.displayName;
30 | 
31 | export { Separator };
32 | 
```

--------------------------------------------------------------------------------
/docs/components/ui/textarea.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import * as React from "react";
 2 | 
 3 | import { cn } from "@/lib/utils";
 4 | 
 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
 6 | 	return (
 7 | 		<textarea
 8 | 			data-slot="textarea"
 9 | 			className={cn(
10 | 				"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
11 | 				className,
12 | 			)}
13 | 			{...props}
14 | 		/>
15 | 	);
16 | }
17 | 
18 | export { Textarea };
19 | 
```

--------------------------------------------------------------------------------
/docs/app/changelogs/_components/grid-pattern.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import { cn } from "@/lib/utils";
 4 | 
 5 | function GridPatterns() {
 6 | 	return (
 7 | 		<div
 8 | 			className={cn(
 9 | 				"pointer-events-none",
10 | 				"fixed inset-y-0 left-0 z-0",
11 | 				"w-1/2 h-full",
12 | 				"overflow-hidden",
13 | 			)}
14 | 			aria-hidden="true"
15 | 		>
16 | 			<div className="absolute opacity-40 inset-0 w-full h-full bg-[radial-gradient(circle_at_center,rgba(0,0,0,0.04)_1px,transparent_1px)] dark:bg-[radial-gradient(circle_at_center,rgba(255,255,255,0.04)_1px,transparent_1px)] bg-[length:8px_8px]" />
17 | 			<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-br opacity-40 from-white/40 via-transparent to-white/10 dark:from-white/10 dark:to-transparent mix-blend-screen" />
18 | 		</div>
19 | 	);
20 | }
21 | 
22 | export { GridPatterns };
23 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/types/plugins.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { UnionToIntersection } from "./helper";
 2 | 
 3 | import type { BetterAuthPluginDBSchema } from "@better-auth/core/db";
 4 | import type { BetterAuthOptions, BetterAuthPlugin } from "@better-auth/core";
 5 | 
 6 | export type InferOptionSchema<S extends BetterAuthPluginDBSchema> =
 7 | 	S extends Record<string, { fields: infer Fields }>
 8 | 		? {
 9 | 				[K in keyof S]?: {
10 | 					modelName?: string;
11 | 					fields?: {
12 | 						[P in keyof Fields]?: string;
13 | 					};
14 | 				};
15 | 			}
16 | 		: never;
17 | 
18 | export type InferPluginErrorCodes<O extends BetterAuthOptions> =
19 | 	O["plugins"] extends Array<infer P>
20 | 		? UnionToIntersection<
21 | 				P extends BetterAuthPlugin
22 | 					? P["$ERROR_CODES"] extends Record<string, any>
23 | 						? P["$ERROR_CODES"]
24 | 						: {}
25 | 					: {}
26 | 			>
27 | 		: {};
28 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/adapters/prisma-adapter/test/generate-auth-config.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import fs from "fs/promises";
 2 | import type { BetterAuthOptions } from "@better-auth/core";
 3 | import path from "path";
 4 | 
 5 | export const generateAuthConfigFile = async (_options: BetterAuthOptions) => {
 6 | 	const options = { ..._options };
 7 | 	// biome-ignore lint/performance/noDelete: perf doesn't matter here.
 8 | 	delete options.database;
 9 | 	let code = `import { betterAuth } from "../../../auth";
10 | import { prismaAdapter } from "../prisma-adapter";		
11 | import { PrismaClient } from "@prisma/client";
12 | const db = new PrismaClient();
13 | 
14 | export const auth = betterAuth({
15 |     database: prismaAdapter(db, {
16 | 	    provider: 'sqlite'
17 |     }),
18 |     ${JSON.stringify(options, null, 2).slice(1, -1)}
19 | })`;
20 | 
21 | 	await fs.writeFile(path.join(import.meta.dirname, "auth.ts"), code);
22 | };
23 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/api/routes/ok.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { HIDE_METADATA } from "../../utils/hide-metadata";
 2 | import { createAuthEndpoint } from "@better-auth/core/middleware";
 3 | 
 4 | export const ok = createAuthEndpoint(
 5 | 	"/ok",
 6 | 	{
 7 | 		method: "GET",
 8 | 		metadata: {
 9 | 			...HIDE_METADATA,
10 | 			openapi: {
11 | 				description: "Check if the API is working",
12 | 				responses: {
13 | 					"200": {
14 | 						description: "API is working",
15 | 						content: {
16 | 							"application/json": {
17 | 								schema: {
18 | 									type: "object",
19 | 									properties: {
20 | 										ok: {
21 | 											type: "boolean",
22 | 											description: "Indicates if the API is working",
23 | 										},
24 | 									},
25 | 									required: ["ok"],
26 | 								},
27 | 							},
28 | 						},
29 | 					},
30 | 				},
31 | 			},
32 | 		},
33 | 	},
34 | 	async (ctx) => {
35 | 		return ctx.json({
36 | 			ok: true,
37 | 		});
38 | 	},
39 | );
40 | 
```

--------------------------------------------------------------------------------
/e2e/smoke/test/fixtures/tsconfig-exact-optional-property-types/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { betterAuth } from "better-auth";
 2 | import { organization } from "better-auth/plugins";
 3 | import { nextCookies } from "better-auth/next-js";
 4 | import Database from "better-sqlite3";
 5 | import { createAuthClient } from "better-auth/react";
 6 | import {
 7 | 	inferAdditionalFields,
 8 | 	organizationClient,
 9 | } from "better-auth/client/plugins";
10 | 
11 | const auth = betterAuth({
12 | 	database: new Database("./sqlite.db"),
13 | 	trustedOrigins: [],
14 | 	emailAndPassword: {
15 | 		enabled: true,
16 | 	},
17 | 	plugins: [organization(), nextCookies()],
18 | 	user: {
19 | 		additionalFields: {},
20 | 	},
21 | });
22 | const authClient = createAuthClient({
23 | 	baseURL: "http://localhost:3000",
24 | 	plugins: [inferAdditionalFields<typeof auth>(), organizationClient()],
25 | });
26 | 
27 | authClient.useActiveOrganization();
28 | authClient.useSession();
29 | 
```

--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "baseUrl": ".",
 4 |     "target": "ESNext",
 5 |     "lib": ["dom", "dom.iterable", "esnext"],
 6 |     "allowJs": true,
 7 |     "skipLibCheck": true,
 8 |     "strict": true,
 9 |     "forceConsistentCasingInFileNames": true,
10 |     "noEmit": true,
11 |     "esModuleInterop": true,
12 |     "module": "esnext",
13 |     "moduleResolution": "bundler",
14 |     "resolveJsonModule": true,
15 |     "isolatedModules": true,
16 |     "jsx": "react-jsx",
17 |     "incremental": true,
18 |     "paths": {
19 |       "@/.source": ["./.source/index.ts"],
20 |       "@/*": ["./*"]
21 |     },
22 |     "plugins": [
23 |       {
24 |         "name": "next"
25 |       }
26 |     ]
27 |   },
28 |   "include": [
29 |     "next-env.d.ts",
30 |     "**/*.ts",
31 |     "**/*.tsx",
32 |     ".next/types/**/*.ts",
33 |     ".next/dev/types/**/*.ts"
34 |   ],
35 |   "exclude": ["node_modules"]
36 | }
37 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/types/adapter.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type {
 2 | 	DBAdapter,
 3 | 	DBTransactionAdapter,
 4 | 	Where,
 5 | 	DBAdapterSchemaCreation,
 6 | 	DBAdapterInstance,
 7 | } from "@better-auth/core/db/adapter";
 8 | 
 9 | export type { Where };
10 | 
11 | /**
12 |  * Adapter Interface
13 |  *
14 |  * @deprecated Use `DBAdapter` from `@better-auth/core/db/adapter` instead.
15 |  */
16 | export type Adapter = DBAdapter;
17 | 
18 | /**
19 |  * @deprecated Use `DBTransactionAdapter` from `@better-auth/core/db/adapter` instead.
20 |  */
21 | export type TransactionAdapter = DBTransactionAdapter;
22 | 
23 | /**
24 |  * @deprecated Use `DBAdapterSchemaCreation` from `@better-auth/core/db/adapter` instead.
25 |  */
26 | export type AdapterSchemaCreation = DBAdapterSchemaCreation;
27 | 
28 | /**
29 |  * @deprecated Use `DBAdapterInstance` from `@better-auth/core/db/adapter` instead.
30 |  */
31 | export type AdapterInstance = DBAdapterInstance;
32 | 
```

--------------------------------------------------------------------------------
/docs/components/docs/ui/button.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { cva } from "class-variance-authority";
 2 | 
 3 | export const buttonVariants = cva(
 4 | 	"inline-flex items-center justify-center rounded-md p-2 text-sm font-medium transition-colors duration-100 disabled:pointer-events-none disabled:opacity-50",
 5 | 	{
 6 | 		variants: {
 7 | 			color: {
 8 | 				primary:
 9 | 					"bg-fd-primary text-fd-primary-foreground hover:bg-fd-primary/80",
10 | 				outline: "border hover:bg-fd-accent hover:text-fd-accent-foreground",
11 | 				ghost: "hover:bg-fd-accent hover:text-fd-accent-foreground",
12 | 				secondary:
13 | 					"border bg-fd-secondary text-fd-secondary-foreground hover:bg-fd-accent hover:text-fd-accent-foreground",
14 | 			},
15 | 			size: {
16 | 				sm: "gap-1 p-0.5 text-xs",
17 | 				icon: "p-1.5 [&_svg]:size-5",
18 | 				"icon-sm": "p-1.5 [&_svg]:size-4.5",
19 | 			},
20 | 		},
21 | 	},
22 | );
23 | 
```

--------------------------------------------------------------------------------
/demo/expo-example/src/components/ui/text.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import * as Slot from "@rn-primitives/slot";
 2 | import { SlottableTextProps, TextRef } from "@rn-primitives/types";
 3 | import * as React from "react";
 4 | import { Text as RNText } from "react-native";
 5 | import { cn } from "@/lib/utils";
 6 | 
 7 | const TextClassContext = React.createContext<string | undefined>(undefined);
 8 | 
 9 | const Text = React.forwardRef<TextRef, SlottableTextProps>(
10 | 	({ className, asChild = false, ...props }, ref) => {
11 | 		const textClass = React.useContext(TextClassContext);
12 | 		const Component = asChild ? Slot.Text : RNText;
13 | 		return (
14 | 			<Component
15 | 				className={cn(
16 | 					"text-base text-foreground web:select-text",
17 | 					textClass,
18 | 					className,
19 | 				)}
20 | 				ref={ref}
21 | 				{...props}
22 | 			/>
23 | 		);
24 | 	},
25 | );
26 | Text.displayName = "Text";
27 | 
28 | export { Text, TextClassContext };
29 | 
```

--------------------------------------------------------------------------------
/docs/lib/metadata.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { Metadata } from "next/types";
 2 | 
 3 | export function createMetadata(override: Metadata): Metadata {
 4 | 	return {
 5 | 		...override,
 6 | 		openGraph: {
 7 | 			title: override.title ?? undefined,
 8 | 			description: override.description ?? undefined,
 9 | 			url: "https://better-auth.com",
10 | 			images: "https://better-auth.com/og.png",
11 | 			siteName: "Better Auth",
12 | 			...override.openGraph,
13 | 		},
14 | 		twitter: {
15 | 			card: "summary_large_image",
16 | 			creator: "@beakcru",
17 | 			title: override.title ?? undefined,
18 | 			description: override.description ?? undefined,
19 | 			images: "https://better-auth.com/og.png",
20 | 			...override.twitter,
21 | 		},
22 | 	};
23 | }
24 | 
25 | export const baseUrl =
26 | 	process.env.NODE_ENV === "development"
27 | 		? new URL("http://localhost:3000")
28 | 		: new URL(`https://${process.env.VERCEL_URL!}`);
29 | 
```

--------------------------------------------------------------------------------
/demo/expo-example/src/app/_layout.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { Slot } from "expo-router";
 2 | import "../global.css";
 3 | import { SafeAreaProvider } from "react-native-safe-area-context";
 4 | import { ImageBackground, View } from "react-native";
 5 | import { StyleSheet } from "react-native";
 6 | 
 7 | export default function RootLayout() {
 8 | 	return (
 9 | 		<SafeAreaProvider>
10 | 			<ImageBackground
11 | 				className="z-0 flex items-center justify-center"
12 | 				source={require("../../assets/bg-image.jpeg")}
13 | 				resizeMode="cover"
14 | 				style={{
15 | 					...(StyleSheet.absoluteFill as any),
16 | 					width: "100%",
17 | 				}}
18 | 			>
19 | 				<View
20 | 					style={{
21 | 						position: "absolute",
22 | 						top: 0,
23 | 						left: 0,
24 | 						right: 0,
25 | 						bottom: 0,
26 | 						backgroundColor: "black",
27 | 						opacity: 0.2,
28 | 					}}
29 | 				/>
30 | 				<Slot />
31 | 			</ImageBackground>
32 | 		</SafeAreaProvider>
33 | 	);
34 | }
35 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/utils/hashing.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { keccak_256 } from "@noble/hashes/sha3.js";
 2 | import { utf8ToBytes } from "@noble/hashes/utils.js";
 3 | 
 4 | /**
 5 |  * TS implementation of ERC-55 ("Mixed-case checksum address encoding") using @noble/hashes
 6 |  * @param address - The address to convert to a checksum address
 7 |  * @returns The checksummed address
 8 |  */
 9 | export function toChecksumAddress(address: string) {
10 | 	address = address.toLowerCase().replace("0x", "");
11 | 	// Hash the address (treat it as UTF-8) and return as a hex string
12 | 	const hash = [...keccak_256(utf8ToBytes(address))]
13 | 		.map((v) => v.toString(16).padStart(2, "0"))
14 | 		.join("");
15 | 	let ret = "0x";
16 | 
17 | 	for (let i = 0; i < 40; i++) {
18 | 		if (parseInt(hash[i]!, 16) >= 8) {
19 | 			ret += address[i]!.toUpperCase();
20 | 		} else {
21 | 			ret += address[i]!;
22 | 		}
23 | 	}
24 | 
25 | 	return ret;
26 | }
27 | 
```

--------------------------------------------------------------------------------
/docs/components/ui/collapsible.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
 4 | 
 5 | function Collapsible({
 6 | 	...props
 7 | }: React.ComponentProps<typeof CollapsiblePrimitive.Root>) {
 8 | 	return <CollapsiblePrimitive.Root data-slot="collapsible" {...props} />;
 9 | }
10 | 
11 | function CollapsibleTrigger({
12 | 	...props
13 | }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleTrigger>) {
14 | 	return (
15 | 		<CollapsiblePrimitive.CollapsibleTrigger
16 | 			data-slot="collapsible-trigger"
17 | 			{...props}
18 | 		/>
19 | 	);
20 | }
21 | 
22 | function CollapsibleContent({
23 | 	...props
24 | }: React.ComponentProps<typeof CollapsiblePrimitive.CollapsibleContent>) {
25 | 	return (
26 | 		<CollapsiblePrimitive.CollapsibleContent
27 | 			data-slot="collapsible-content"
28 | 			{...props}
29 | 		/>
30 | 	);
31 | }
32 | 
33 | export { Collapsible, CollapsibleTrigger, CollapsibleContent };
34 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/jwt/adapter.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { BetterAuthOptions } from "@better-auth/core";
 2 | import type { DBAdapter } from "@better-auth/core/db/adapter";
 3 | import type { Jwk } from "./types";
 4 | 
 5 | export const getJwksAdapter = (adapter: DBAdapter<BetterAuthOptions>) => {
 6 | 	return {
 7 | 		getAllKeys: async () => {
 8 | 			return await adapter.findMany<Jwk>({
 9 | 				model: "jwks",
10 | 			});
11 | 		},
12 | 		getLatestKey: async () => {
13 | 			const key = await adapter.findMany<Jwk>({
14 | 				model: "jwks",
15 | 				sortBy: {
16 | 					field: "createdAt",
17 | 					direction: "desc",
18 | 				},
19 | 				limit: 1,
20 | 			});
21 | 
22 | 			return key[0];
23 | 		},
24 | 		createJwk: async (webKey: Omit<Jwk, "id">) => {
25 | 			const jwk = await adapter.create<Omit<Jwk, "id">, Jwk>({
26 | 				model: "jwks",
27 | 				data: {
28 | 					...webKey,
29 | 					createdAt: new Date(),
30 | 				},
31 | 			});
32 | 
33 | 			return jwk;
34 | 		},
35 | 	};
36 | };
37 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/components/ui/progress.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import * as React from "react";
 4 | import * as ProgressPrimitive from "@radix-ui/react-progress";
 5 | 
 6 | import { cn } from "@/lib/utils";
 7 | 
 8 | const Progress = ({
 9 | 	ref,
10 | 	className,
11 | 	value,
12 | 	...props
13 | }: React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root> & {
14 | 	ref: React.RefObject<React.ElementRef<typeof ProgressPrimitive.Root>>;
15 | }) => (
16 | 	<ProgressPrimitive.Root
17 | 		ref={ref}
18 | 		className={cn(
19 | 			"relative h-2 w-full overflow-hidden rounded-full bg-primary/20",
20 | 			className,
21 | 		)}
22 | 		{...props}
23 | 	>
24 | 		<ProgressPrimitive.Indicator
25 | 			className="h-full w-full flex-1 bg-primary transition-all"
26 | 			style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
27 | 		/>
28 | 	</ProgressPrimitive.Root>
29 | );
30 | Progress.displayName = ProgressPrimitive.Root.displayName;
31 | 
32 | export { Progress };
33 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/lib/metadata.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { Metadata } from "next/types";
 2 | 
 3 | export function createMetadata(override: Metadata): Metadata {
 4 | 	return {
 5 | 		...override,
 6 | 		openGraph: {
 7 | 			title: override.title ?? undefined,
 8 | 			description: override.description ?? undefined,
 9 | 			url: "https://demo.better-auth.com",
10 | 			images: "https://demo.better-auth.com/og.png",
11 | 			siteName: "Better Auth",
12 | 			...override.openGraph,
13 | 		},
14 | 		twitter: {
15 | 			card: "summary_large_image",
16 | 			creator: "@beakcru",
17 | 			title: override.title ?? undefined,
18 | 			description: override.description ?? undefined,
19 | 			images: "https://demo.better-auth.com/og.png",
20 | 			...override.twitter,
21 | 		},
22 | 	};
23 | }
24 | 
25 | export const baseUrl =
26 | 	process.env.NODE_ENV === "development"
27 | 		? new URL("http://localhost:3000")
28 | 		: new URL(`https://${process.env.VERCEL_URL!}`);
29 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/access/types.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { LiteralString } from "../../types/helper";
 2 | import type { AuthorizeResponse, createAccessControl } from "./access";
 3 | 
 4 | export type SubArray<T extends unknown[] | readonly unknown[] | any[]> =
 5 | 	T[number][];
 6 | 
 7 | export type Subset<
 8 | 	K extends keyof R,
 9 | 	R extends Record<
10 | 		string | LiteralString,
11 | 		readonly string[] | readonly LiteralString[]
12 | 	>,
13 | > = {
14 | 	[P in K]: SubArray<R[P]>;
15 | };
16 | 
17 | export type Statements = {
18 | 	readonly [resource: string]: readonly LiteralString[];
19 | };
20 | 
21 | export type AccessControl<TStatements extends Statements = Statements> =
22 | 	ReturnType<typeof createAccessControl<TStatements>>;
23 | 
24 | export type Role<TStatements extends Statements = Record<string, any>> = {
25 | 	authorize: (request: any, connector?: "OR" | "AND") => AuthorizeResponse;
26 | 	statements: TStatements;
27 | };
28 | 
```

--------------------------------------------------------------------------------
/packages/core/src/middleware/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { createEndpoint, createMiddleware } from "better-call";
 2 | import type { AuthContext } from "../types";
 3 | 
 4 | export const optionsMiddleware = createMiddleware(async () => {
 5 | 	/**
 6 | 	 * This will be passed on the instance of
 7 | 	 * the context. Used to infer the type
 8 | 	 * here.
 9 | 	 */
10 | 	return {} as AuthContext;
11 | });
12 | 
13 | export const createAuthMiddleware = createMiddleware.create({
14 | 	use: [
15 | 		optionsMiddleware,
16 | 		/**
17 | 		 * Only use for post hooks
18 | 		 */
19 | 		createMiddleware(async () => {
20 | 			return {} as {
21 | 				returned?: unknown;
22 | 				responseHeaders?: Headers;
23 | 			};
24 | 		}),
25 | 	],
26 | });
27 | 
28 | export const createAuthEndpoint = createEndpoint.create({
29 | 	use: [optionsMiddleware],
30 | });
31 | 
32 | export type AuthEndpoint = ReturnType<typeof createAuthEndpoint>;
33 | export type AuthMiddleware = ReturnType<typeof createAuthMiddleware>;
34 | 
```

--------------------------------------------------------------------------------
/docs/scripts/sync-orama.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { sync, type OramaDocument } from "fumadocs-core/search/orama-cloud";
 2 | import * as fs from "node:fs/promises";
 3 | import { CloudManager } from "@oramacloud/client";
 4 | import * as process from "node:process";
 5 | import "dotenv/config";
 6 | 
 7 | const filePath = ".next/server/app/static.json.body";
 8 | 
 9 | async function main() {
10 | 	const apiKey = process.env.ORAMA_PRIVATE_API_KEY;
11 | 
12 | 	if (!apiKey) {
13 | 		console.log("no api key for Orama found, skipping");
14 | 		return;
15 | 	}
16 | 
17 | 	const content = await fs.readFile(filePath);
18 | 	const records = JSON.parse(content.toString()) as OramaDocument[];
19 | 	const manager = new CloudManager({ api_key: apiKey });
20 | 
21 | 	await sync(manager, {
22 | 		index: process.env.ORAMA_INDEX_ID!,
23 | 		documents: records,
24 | 		autoDeploy: true,
25 | 	});
26 | 
27 | 	console.log(`search updated: ${records.length} records`);
28 | }
29 | 
30 | void main();
31 | 
```

--------------------------------------------------------------------------------
/docs/app/api/analytics/conversation/route.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import {
 2 | 	logConversationToAnalytics,
 3 | 	type InkeepMessage,
 4 | } from "@/lib/inkeep-analytics";
 5 | import { NextRequest, NextResponse } from "next/server";
 6 | 
 7 | export const runtime = "edge";
 8 | 
 9 | export async function POST(req: NextRequest) {
10 | 	try {
11 | 		const { messages }: { messages: InkeepMessage[] } = await req.json();
12 | 
13 | 		if (!messages || !Array.isArray(messages)) {
14 | 			return NextResponse.json(
15 | 				{ error: "Messages array is required" },
16 | 				{ status: 400 },
17 | 			);
18 | 		}
19 | 
20 | 		const result = await logConversationToAnalytics({
21 | 			type: "openai",
22 | 			messages,
23 | 			properties: {
24 | 				source: "better-auth-docs",
25 | 				timestamp: new Date().toISOString(),
26 | 			},
27 | 		});
28 | 
29 | 		return NextResponse.json(result);
30 | 	} catch (error) {
31 | 		return NextResponse.json(
32 | 			{ error: "Failed to log conversation" },
33 | 			{ status: 500 },
34 | 		);
35 | 	}
36 | }
37 | 
```

--------------------------------------------------------------------------------
/docs/components/ui/sonner.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import { useTheme } from "next-themes";
 4 | import { Toaster as Sonner, ToasterProps } from "sonner";
 5 | 
 6 | const Toaster = ({ ...props }: ToasterProps) => {
 7 | 	const { theme = "system" } = useTheme();
 8 | 
 9 | 	return (
10 | 		<Sonner
11 | 			theme={theme as ToasterProps["theme"]}
12 | 			className="toaster group"
13 | 			toastOptions={{
14 | 				classNames: {
15 | 					toast:
16 | 						"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
17 | 					description: "group-[.toast]:text-muted-foreground",
18 | 					actionButton:
19 | 						"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground font-medium",
20 | 					cancelButton:
21 | 						"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground font-medium",
22 | 				},
23 | 			}}
24 | 			{...props}
25 | 		/>
26 | 	);
27 | };
28 | 
29 | export { Toaster };
30 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/plugins/api-key/routes/delete-all-expired-api-keys.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { createAuthEndpoint } from "@better-auth/core/middleware";
 2 | import type { AuthContext } from "@better-auth/core";
 3 | 
 4 | export function deleteAllExpiredApiKeysEndpoint({
 5 | 	deleteAllExpiredApiKeys,
 6 | }: {
 7 | 	deleteAllExpiredApiKeys(
 8 | 		ctx: AuthContext,
 9 | 		byPassLastCheckTime?: boolean,
10 | 	): Promise<void>;
11 | }) {
12 | 	return createAuthEndpoint(
13 | 		"/api-key/delete-all-expired-api-keys",
14 | 		{
15 | 			method: "POST",
16 | 			metadata: {
17 | 				SERVER_ONLY: true,
18 | 				client: false,
19 | 			},
20 | 		},
21 | 		async (ctx) => {
22 | 			try {
23 | 				await deleteAllExpiredApiKeys(ctx.context, true);
24 | 			} catch (error) {
25 | 				ctx.context.logger.error(
26 | 					"[API KEY PLUGIN] Failed to delete expired API keys:",
27 | 					error,
28 | 				);
29 | 				return ctx.json({
30 | 					success: false,
31 | 					error: error,
32 | 				});
33 | 			}
34 | 
35 | 			return ctx.json({ success: true, error: null });
36 | 		},
37 | 	);
38 | }
39 | 
```

--------------------------------------------------------------------------------
/docs/app/api/analytics/feedback/route.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { submitFeedbackToAnalytics } from "@/lib/inkeep-analytics";
 2 | import { NextRequest, NextResponse } from "next/server";
 3 | 
 4 | export const runtime = "edge";
 5 | 
 6 | export async function POST(req: NextRequest) {
 7 | 	try {
 8 | 		const { messageId, type, reasons } = await req.json();
 9 | 
10 | 		if (!messageId || !type) {
11 | 			return NextResponse.json(
12 | 				{ error: "messageId and type are required" },
13 | 				{ status: 400 },
14 | 			);
15 | 		}
16 | 
17 | 		if (type !== "positive" && type !== "negative") {
18 | 			return NextResponse.json(
19 | 				{ error: "type must be 'positive' or 'negative'" },
20 | 				{ status: 400 },
21 | 			);
22 | 		}
23 | 
24 | 		const result = await submitFeedbackToAnalytics({
25 | 			messageId,
26 | 			type,
27 | 			reasons,
28 | 		});
29 | 
30 | 		return NextResponse.json(result);
31 | 	} catch (error) {
32 | 		return NextResponse.json(
33 | 			{ error: "Failed to submit feedback" },
34 | 			{ status: 500 },
35 | 		);
36 | 	}
37 | }
38 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/components/ui/sonner.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | "use client";
 2 | 
 3 | import { useTheme } from "next-themes";
 4 | import { Toaster as Sonner } from "sonner";
 5 | 
 6 | type ToasterProps = React.ComponentProps<typeof Sonner>;
 7 | 
 8 | const Toaster = ({ ...props }: ToasterProps) => {
 9 | 	const { theme = "system" } = useTheme();
10 | 
11 | 	return (
12 | 		<Sonner
13 | 			theme={theme as ToasterProps["theme"]}
14 | 			className="toaster group"
15 | 			toastOptions={{
16 | 				classNames: {
17 | 					toast:
18 | 						"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
19 | 					description: "group-[.toast]:text-muted-foreground",
20 | 					actionButton:
21 | 						"group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
22 | 					cancelButton:
23 | 						"group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
24 | 				},
25 | 			}}
26 | 			{...props}
27 | 		/>
28 | 	);
29 | };
30 | 
31 | export { Toaster };
32 | 
```

--------------------------------------------------------------------------------
/packages/core/src/utils/error-codes.ts:
--------------------------------------------------------------------------------

```typescript
 1 | type UpperLetter =
 2 | 	| "A"
 3 | 	| "B"
 4 | 	| "C"
 5 | 	| "D"
 6 | 	| "E"
 7 | 	| "F"
 8 | 	| "G"
 9 | 	| "H"
10 | 	| "I"
11 | 	| "J"
12 | 	| "K"
13 | 	| "L"
14 | 	| "M"
15 | 	| "N"
16 | 	| "O"
17 | 	| "P"
18 | 	| "Q"
19 | 	| "R"
20 | 	| "S"
21 | 	| "T"
22 | 	| "U"
23 | 	| "V"
24 | 	| "W"
25 | 	| "X"
26 | 	| "Y"
27 | 	| "Z";
28 | type SpecialCharacter = "_";
29 | 
30 | type IsValidUpperSnakeCase<S extends string> = S extends `${infer F}${infer R}`
31 | 	? F extends UpperLetter | SpecialCharacter
32 | 		? IsValidUpperSnakeCase<R>
33 | 		: false
34 | 	: true;
35 | 
36 | type InvalidKeyError<K extends string> =
37 | 	`Invalid error code key: "${K}" - must only contain uppercase letters (A-Z) and underscores (_)`;
38 | 
39 | type ValidateErrorCodes<T> = {
40 | 	[K in keyof T]: K extends string
41 | 		? IsValidUpperSnakeCase<K> extends false
42 | 			? InvalidKeyError<K>
43 | 			: T[K]
44 | 		: T[K];
45 | };
46 | 
47 | export function defineErrorCodes<const T extends Record<string, string>>(
48 | 	codes: ValidateErrorCodes<T>,
49 | ): T {
50 | 	return codes as T;
51 | }
52 | 
```

--------------------------------------------------------------------------------
/packages/stripe/src/utils.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import type { StripeOptions } from "./types";
 2 | 
 3 | export async function getPlans(options: StripeOptions) {
 4 | 	return typeof options?.subscription?.plans === "function"
 5 | 		? await options.subscription?.plans()
 6 | 		: options.subscription?.plans;
 7 | }
 8 | 
 9 | export async function getPlanByPriceInfo(
10 | 	options: StripeOptions,
11 | 	priceId: string,
12 | 	priceLookupKey: string | null,
13 | ) {
14 | 	return await getPlans(options).then((res) =>
15 | 		res?.find(
16 | 			(plan) =>
17 | 				plan.priceId === priceId ||
18 | 				plan.annualDiscountPriceId === priceId ||
19 | 				(priceLookupKey &&
20 | 					(plan.lookupKey === priceLookupKey ||
21 | 						plan.annualDiscountLookupKey === priceLookupKey)),
22 | 		),
23 | 	);
24 | }
25 | 
26 | export async function getPlanByName(options: StripeOptions, name: string) {
27 | 	return await getPlans(options).then((res) =>
28 | 		res?.find((plan) => plan.name.toLowerCase() === name.toLowerCase()),
29 | 	);
30 | }
31 | 
```

--------------------------------------------------------------------------------
/packages/cli/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
 1 | # @better-auth/cli
 2 | 
 3 | ## 1.3.4
 4 | 
 5 | ### Patch Changes
 6 | 
 7 | - 2bd2fa9: Added support for listing organization members with pagination, sorting, and filtering, and improved client inference for additional organization fields. Also fixed date handling in rate limits and tokens, improved Notion OAuth user extraction, and ensured session is always set in context.
 8 | 
 9 |   Organization
10 | 
11 |   - Added listMembers API with pagination, sorting, and filtering.
12 |   - Added membersLimit param to getFullOrganization.
13 |   - Improved client inference for additional fields in organization schemas.
14 |   - Bug Fixes
15 |   - Fixed date handling by casting DB values to Date objects before using date methods.
16 |   - Fixed Notion OAuth to extract user info correctly.
17 |   - Ensured session is set in context when reading from cookie cach
18 | 
19 | - Updated dependencies [2bd2fa9]
20 |   - [email protected]
21 | 
```

--------------------------------------------------------------------------------
/packages/expo/CHANGELOG.md:
--------------------------------------------------------------------------------

```markdown
 1 | # @better-auth/expo
 2 | 
 3 | ## 1.3.4
 4 | 
 5 | ### Patch Changes
 6 | 
 7 | - 2bd2fa9: Added support for listing organization members with pagination, sorting, and filtering, and improved client inference for additional organization fields. Also fixed date handling in rate limits and tokens, improved Notion OAuth user extraction, and ensured session is always set in context.
 8 | 
 9 |   Organization
10 | 
11 |   - Added listMembers API with pagination, sorting, and filtering.
12 |   - Added membersLimit param to getFullOrganization.
13 |   - Improved client inference for additional fields in organization schemas.
14 |   - Bug Fixes
15 |   - Fixed date handling by casting DB values to Date objects before using date methods.
16 |   - Fixed Notion OAuth to extract user info correctly.
17 |   - Ensured session is set in context when reading from cookie cach
18 | 
19 | - Updated dependencies [2bd2fa9]
20 |   - [email protected]
21 | 
```

--------------------------------------------------------------------------------
/.github/renovate.json5:
--------------------------------------------------------------------------------

```
 1 | {
 2 |   $schema: 'https://docs.renovatebot.com/renovate-schema.json',
 3 |   extends: [
 4 |     'config:recommended',
 5 |     'schedule:weekly',
 6 |     'group:allNonMajor',
 7 |     ':disablePeerDependencies',
 8 |     'customManagers:biomeVersions',
 9 |     'helpers:pinGitHubActionDigestsToSemver',
10 |   ],
11 |   labels: [
12 |     'dependencies',
13 |   ],
14 |   rangeStrategy: 'bump',
15 |   postUpdateOptions: [
16 |     'pnpmDedupe',
17 |   ],
18 |   ignorePaths: [
19 |     '**/node_modules/**',
20 |   ],
21 |   packageRules: [
22 |     {
23 |       groupName: 'github-actions',
24 |       matchManagers: [
25 |         'github-actions',
26 |       ],
27 |     },
28 |     {
29 |       groupName: 'better-auth dependencies',
30 |       matchManagers: [
31 |         'npm',
32 |       ],
33 |       matchFileNames: [
34 |         'packages/better-auth/**',
35 |       ],
36 |     },
37 |   ],
38 |   ignoreDeps: [
39 |     '@biomejs/biome',
40 |     '@types/node',
41 |     'drizzle-orm',
42 |     'node',
43 |     'npm',
44 |     'pnpm',
45 |   ],
46 | }
47 | 
```

--------------------------------------------------------------------------------
/packages/telemetry/src/types.ts:
--------------------------------------------------------------------------------

```typescript
 1 | export interface DetectionInfo {
 2 | 	name: string;
 3 | 	version: string | null;
 4 | }
 5 | 
 6 | export interface SystemInfo {
 7 | 	// Software information
 8 | 	systemPlatform: string;
 9 | 	systemRelease: string;
10 | 	systemArchitecture: string;
11 | 
12 | 	// Machine information
13 | 	cpuCount: number;
14 | 	cpuModel: string | null;
15 | 	cpuSpeed: number | null;
16 | 	memory: number;
17 | 
18 | 	// Environment information
19 | 	isDocker: boolean;
20 | 	isTTY: boolean;
21 | 	isWSL: boolean;
22 | 	isCI: boolean;
23 | }
24 | 
25 | export interface AuthConfigInfo {
26 | 	options: any;
27 | 	plugins: string[];
28 | }
29 | 
30 | export interface ProjectInfo {
31 | 	isGit: boolean;
32 | 	packageManager: DetectionInfo | null;
33 | }
34 | 
35 | export interface TelemetryEvent {
36 | 	type: string;
37 | 	anonymousId?: string;
38 | 	payload: Record<string, any>;
39 | }
40 | 
41 | export interface TelemetryContext {
42 | 	customTrack?: (event: TelemetryEvent) => Promise<void>;
43 | 	database?: string;
44 | 	adapter?: string;
45 | 	skipTestCheck?: boolean;
46 | }
47 | 
```

--------------------------------------------------------------------------------
/demo/nextjs/app/pricing/page.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import { Pricing } from "@/components/blocks/pricing";
 2 | 
 3 | const demoPlans = [
 4 | 	{
 5 | 		name: "Plus",
 6 | 		price: "20",
 7 | 		yearlyPrice: "16",
 8 | 		period: "per month",
 9 | 		features: [
10 | 			"Up to 10 projects",
11 | 			"Basic analytics",
12 | 			"48-hour support response time",
13 | 			"Limited API access",
14 | 		],
15 | 		description: "Perfect for individuals and small projects",
16 | 		buttonText: "Start Free Trial",
17 | 		href: "/sign-up",
18 | 		isPopular: false,
19 | 	},
20 | 	{
21 | 		name: "Pro",
22 | 		price: "50",
23 | 		yearlyPrice: "40",
24 | 		period: "per month",
25 | 		features: [
26 | 			"Unlimited projects",
27 | 			"Advanced analytics",
28 | 			"24-hour support response time",
29 | 			"Full API access",
30 | 			"Priority support",
31 | 		],
32 | 		description: "Ideal for growing teams and businesses",
33 | 		buttonText: "Get Started",
34 | 		href: "/sign-up",
35 | 		isPopular: true,
36 | 	},
37 | ];
38 | 
39 | export default function Page() {
40 | 	return <Pricing plans={demoPlans} />;
41 | }
42 | 
```

--------------------------------------------------------------------------------
/packages/cli/src/utils/install-dependencies.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { exec } from "child_process";
 2 | 
 3 | export function installDependencies({
 4 | 	dependencies,
 5 | 	packageManager,
 6 | 	cwd,
 7 | }: {
 8 | 	dependencies: string[];
 9 | 	packageManager: "npm" | "pnpm" | "bun" | "yarn";
10 | 	cwd: string;
11 | }): Promise<boolean> {
12 | 	let installCommand: string;
13 | 	switch (packageManager) {
14 | 		case "npm":
15 | 			installCommand = "npm install --force";
16 | 			break;
17 | 		case "pnpm":
18 | 			installCommand = "pnpm install";
19 | 			break;
20 | 		case "bun":
21 | 			installCommand = "bun install";
22 | 			break;
23 | 		case "yarn":
24 | 			installCommand = "yarn install";
25 | 			break;
26 | 		default:
27 | 			throw new Error("Invalid package manager");
28 | 	}
29 | 	const command = `${installCommand} ${dependencies.join(" ")}`;
30 | 
31 | 	return new Promise((resolve, reject) => {
32 | 		exec(command, { cwd }, (error, stdout, stderr) => {
33 | 			if (error) {
34 | 				reject(new Error(stderr));
35 | 				return;
36 | 			}
37 | 			resolve(true);
38 | 		});
39 | 	});
40 | }
41 | 
```

--------------------------------------------------------------------------------
/docs/components/mdx/add-to-cursor.tsx:
--------------------------------------------------------------------------------

```typescript
 1 | import Link from "next/link";
 2 | 
 3 | export const AddToCursor = () => {
 4 | 	return (
 5 | 		<div className="w-max">
 6 | 			<Link
 7 | 				href="cursor://anysphere.cursor-deeplink/mcp/install?name=Better%20Auth&config=eyJ1cmwiOiJodHRwczovL21jcC5jaG9ua2llLmFpL2JldHRlci1hdXRoL2JldHRlci1hdXRoLWJ1aWxkZXIvbWNwIn0%3D"
 8 | 				className="dark:hidden"
 9 | 			>
10 | 				<img
11 | 					src="https://cursor.com/deeplink/mcp-install-dark.svg"
12 | 					alt="Add Better Auth MCP to Cursor"
13 | 					height="32"
14 | 				/>
15 | 			</Link>
16 | 
17 | 			<Link
18 | 				href="cursor://anysphere.cursor-deeplink/mcp/install?name=Better%20Auth&config=eyJ1cmwiOiJodHRwczovL21jcC5jaG9ua2llLmFpL2JldHRlci1hdXRoL2JldHRlci1hdXRoLWJ1aWxkZXIvbWNwIn0%3D"
19 | 				className="dark:block hidden"
20 | 			>
21 | 				<img
22 | 					src="https://cursor.com/deeplink/mcp-install-light.svg"
23 | 					alt="Add Better Auth MCP to Cursor"
24 | 					height="32"
25 | 				/>
26 | 			</Link>
27 | 		</div>
28 | 	);
29 | };
30 | 
```

--------------------------------------------------------------------------------
/packages/better-auth/src/adapters/memory-adapter/adapter.memory.test.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { getAuthTables } from "../../db";
 2 | import { testAdapter } from "../test-adapter";
 3 | import { memoryAdapter } from "./memory-adapter";
 4 | import {
 5 | 	performanceTestSuite,
 6 | 	normalTestSuite,
 7 | 	transactionsTestSuite,
 8 | 	authFlowTestSuite,
 9 | 	numberIdTestSuite,
10 | } from "../tests";
11 | let db: Record<string, any[]> = {};
12 | 
13 | const { execute } = await testAdapter({
14 | 	adapter: () => {
15 | 		return memoryAdapter(db);
16 | 	},
17 | 	runMigrations: (options) => {
18 | 		db = {};
19 | 		const authTables = getAuthTables(options);
20 | 		const allModels = Object.keys(authTables);
21 | 		for (const model of allModels) {
22 | 			const modelName = authTables[model]?.modelName || model;
23 | 			db[modelName] = [];
24 | 		}
25 | 	},
26 | 	tests: [
27 | 		normalTestSuite(),
28 | 		transactionsTestSuite({ disableTests: { ALL: true } }),
29 | 		authFlowTestSuite(),
30 | 		numberIdTestSuite(),
31 | 		performanceTestSuite(),
32 | 	],
33 | 	async onFinish() {},
34 | });
35 | 
36 | execute();
37 | 
```

--------------------------------------------------------------------------------
/docs/app/api/analytics/event/route.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { logEventToAnalytics } from "@/lib/inkeep-analytics";
 2 | import { NextRequest, NextResponse } from "next/server";
 3 | 
 4 | export const runtime = "edge";
 5 | 
 6 | export async function POST(req: NextRequest) {
 7 | 	try {
 8 | 		const { type, entityType, messageId, conversationId } = await req.json();
 9 | 
10 | 		if (!type || !entityType) {
11 | 			return NextResponse.json(
12 | 				{ error: "type and entityType are required" },
13 | 				{ status: 400 },
14 | 			);
15 | 		}
16 | 
17 | 		if (entityType !== "message" && entityType !== "conversation") {
18 | 			return NextResponse.json(
19 | 				{ error: "entityType must be 'message' or 'conversation'" },
20 | 				{ status: 400 },
21 | 			);
22 | 		}
23 | 
24 | 		const result = await logEventToAnalytics({
25 | 			type,
26 | 			entityType,
27 | 			messageId,
28 | 			conversationId,
29 | 		});
30 | 
31 | 		return NextResponse.json(result);
32 | 	} catch (error) {
33 | 		return NextResponse.json({ error: "Failed to log event" }, { status: 500 });
34 | 	}
35 | }
36 | 
```
Page 2/67FirstPrevNextLast