This is page 51 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 │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.mjs │ ├── proxy.ts │ ├── 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 │ │ │ │ │ └── username.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 -------------------------------------------------------------------------------- /docs/components/builder/social-provider.tsx: -------------------------------------------------------------------------------- ```typescript 1 | import { SVGProps } from "react"; 2 | 3 | export const socialProviders = { 4 | apple: { 5 | Icon: (props: SVGProps<any>) => ( 6 | <svg 7 | {...props} 8 | xmlns="http://www.w3.org/2000/svg" 9 | width="1em" 10 | height="1em" 11 | viewBox="0 0 24 24" 12 | > 13 | <path 14 | fill="currentColor" 15 | d="M17.05 20.28c-.98.95-2.05.8-3.08.35c-1.09-.46-2.09-.48-3.24 0c-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8c1.18-.24 2.31-.93 3.57-.84c1.51.12 2.65.72 3.4 1.8c-3.12 1.87-2.38 5.98.48 7.13c-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25c.29 2.58-2.34 4.5-3.74 4.25" 16 | ></path> 17 | </svg> 18 | ), 19 | stringIcon: `<svg 20 | xmlns="http://www.w3.org/2000/svg" 21 | width="1em" 22 | height="1em" 23 | viewBox="0 0 24 24" 24 | > 25 | <path 26 | fill="currentColor" 27 | d="M17.05 20.28c-.98.95-2.05.8-3.08.35c-1.09-.46-2.09-.48-3.24 0c-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8c1.18-.24 2.31-.93 3.57-.84c1.51.12 2.65.72 3.4 1.8c-3.12 1.87-2.38 5.98.48 7.13c-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25c.29 2.58-2.34 4.5-3.74 4.25" 28 | ></path> 29 | </svg>`, 30 | }, 31 | dropbox: { 32 | Icon: (props: SVGProps<any>) => ( 33 | <svg 34 | xmlns="http://www.w3.org/2000/svg" 35 | width="1em" 36 | height="1em" 37 | viewBox="0 0 24 24" 38 | {...props} 39 | > 40 | <g fill="none" fillRule="evenodd"> 41 | <path d="m12.594 23.258l-.012.002l-.071.035l-.02.004l-.014-.004l-.071-.036q-.016-.004-.024.006l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.016-.018m.264-.113l-.014.002l-.184.093l-.01.01l-.003.011l.018.43l.005.012l.008.008l.201.092q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.003-.011l.018-.43l-.003-.012l-.01-.01z"></path> 42 | <path 43 | fill="currentColor" 44 | d="m11.998 13.503l2.879 1.662c.426.246.923.34 1.365.34c.443 0 .94-.094 1.367-.34l.587-.34V17a1 1 0 0 1-.5.866l-5.196 3a1 1 0 0 1-1 0l-5.196-3a1 1 0 0 1-.5-.866v-2.172l.583.337c.426.246.923.34 1.366.34c.442 0 .939-.094 1.366-.34zM6.887 3.5c.434-.251 1.115-.274 1.594-.068l.138.068l3.379 1.95l3.379-1.95c.434-.251 1.115-.274 1.594-.068l.138.068l4.242 2.45c.447.257.476.664.09.942l-.09.057l-3.378 1.95l3.378 1.95c.447.258.476.665.09.943l-.09.057l-4.242 2.45c-.435.25-1.116.273-1.595.068l-.137-.068l-3.38-1.951l-3.378 1.95c-.435.252-1.116.274-1.595.07l-.137-.07l-4.243-2.449c-.447-.257-.476-.665-.09-.942l.09-.058L6.022 8.9L2.644 6.95c-.447-.257-.476-.665-.09-.942l.09-.058zm5.546 2.702c-.205-.119-.52-.136-.755-.051l-.111.05l-4.243 2.45c-.212.122-.236.313-.07.45l.07.05l4.243 2.449c.205.118.52.135.755.05l.111-.05l4.243-2.45c.212-.122.236-.312.07-.45l-.07-.05z" 45 | ></path> 46 | </g> 47 | </svg> 48 | ), 49 | stringIcon: `<svg 50 | xmlns="http://www.w3.org/2000/svg" 51 | width="1em" 52 | height="1em" 53 | viewBox="0 0 24 24" 54 | > 55 | <g fill="none" fillRule="evenodd"> 56 | <path d="m12.594 23.258l-.012.002l-.071.035l-.02.004l-.014-.004l-.071-.036q-.016-.004-.024.006l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.016-.018m.264-.113l-.014.002l-.184.093l-.01.01l-.003.011l.018.43l.005.012l.008.008l.201.092q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.003-.011l.018-.43l-.003-.012l-.01-.01z"></path> 57 | <path 58 | fill="currentColor" 59 | d="m11.998 13.503l2.879 1.662c.426.246.923.34 1.365.34c.443 0 .94-.094 1.367-.34l.587-.34V17a1 1 0 0 1-.5.866l-5.196 3a1 1 0 0 1-1 0l-5.196-3a1 1 0 0 1-.5-.866v-2.172l.583.337c.426.246.923.34 1.366.34c.442 0 .939-.094 1.366-.34zM6.887 3.5c.434-.251 1.115-.274 1.594-.068l.138.068l3.379 1.95l3.379-1.95c.434-.251 1.115-.274 1.594-.068l.138.068l4.242 2.45c.447.257.476.664.09.942l-.09.057l-3.378 1.95l3.378 1.95c.447.258.476.665.09.943l-.09.057l-4.242 2.45c-.435.25-1.116.273-1.595.068l-.137-.068l-3.38-1.951l-3.378 1.95c-.435.252-1.116.274-1.595.07l-.137-.07l-4.243-2.449c-.447-.257-.476-.665-.09-.942l.09-.058L6.022 8.9L2.644 6.95c-.447-.257-.476-.665-.09-.942l.09-.058zm5.546 2.702c-.205-.119-.52-.136-.755-.051l-.111.05l-4.243 2.45c-.212.122-.236.313-.07.45l.07.05l4.243 2.449c.205.118.52.135.755.05l.111-.05l4.243-2.45c.212-.122.236-.312.07-.45l-.07-.05z" 60 | ></path> 61 | </g> 62 | </svg>`, 63 | }, 64 | discord: { 65 | Icon: (props: SVGProps<any>) => ( 66 | <svg 67 | xmlns="http://www.w3.org/2000/svg" 68 | width="1em" 69 | height="1em" 70 | viewBox="0 0 24 24" 71 | {...props} 72 | > 73 | <path 74 | fill="currentColor" 75 | d="M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.1.1 0 0 0-.07.03c-.18.33-.39.76-.53 1.09a16.1 16.1 0 0 0-4.8 0c-.14-.34-.35-.76-.54-1.09c-.01-.02-.04-.03-.07-.03c-1.5.26-2.93.71-4.27 1.33c-.01 0-.02.01-.03.02c-2.72 4.07-3.47 8.03-3.1 11.95c0 .02.01.04.03.05c1.8 1.32 3.53 2.12 5.24 2.65c.03.01.06 0 .07-.02c.4-.55.76-1.13 1.07-1.74c.02-.04 0-.08-.04-.09c-.57-.22-1.11-.48-1.64-.78c-.04-.02-.04-.08-.01-.11c.11-.08.22-.17.33-.25c.02-.02.05-.02.07-.01c3.44 1.57 7.15 1.57 10.55 0c.02-.01.05-.01.07.01c.11.09.22.17.33.26c.04.03.04.09-.01.11c-.52.31-1.07.56-1.64.78c-.04.01-.05.06-.04.09c.32.61.68 1.19 1.07 1.74c.03.01.06.02.09.01c1.72-.53 3.45-1.33 5.25-2.65c.02-.01.03-.03.03-.05c.44-4.53-.73-8.46-3.1-11.95c-.01-.01-.02-.02-.04-.02M8.52 14.91c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12c0 1.17-.84 2.12-1.89 2.12m6.97 0c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12c0 1.17-.83 2.12-1.89 2.12" 76 | ></path> 77 | </svg> 78 | ), 79 | stringIcon: `<svg 80 | xmlns="http://www.w3.org/2000/svg" 81 | width="1em" 82 | height="1em" 83 | viewBox="0 0 24 24" 84 | > 85 | <path 86 | fill="currentColor" 87 | d="M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.1.1 0 0 0-.07.03c-.18.33-.39.76-.53 1.09a16.1 16.1 0 0 0-4.8 0c-.14-.34-.35-.76-.54-1.09c-.01-.02-.04-.03-.07-.03c-1.5.26-2.93.71-4.27 1.33c-.01 0-.02.01-.03.02c-2.72 4.07-3.47 8.03-3.1 11.95c0 .02.01.04.03.05c1.8 1.32 3.53 2.12 5.24 2.65c.03.01.06 0 .07-.02c.4-.55.76-1.13 1.07-1.74c.02-.04 0-.08-.04-.09c-.57-.22-1.11-.48-1.64-.78c-.04-.02-.04-.08-.01-.11c.11-.08.22-.17.33-.25c.02-.02.05-.02.07-.01c3.44 1.57 7.15 1.57 10.55 0c.02-.01.05-.01.07.01c.11.09.22.17.33.26c.04.03.04.09-.01.11c-.52.31-1.07.56-1.64.78c-.04.01-.05.06-.04.09c.32.61.68 1.19 1.07 1.74c.03.01.06.02.09.01c1.72-.53 3.45-1.33 5.25-2.65c.02-.01.03-.03.03-.05c.44-4.53-.73-8.46-3.1-11.95c-.01-.01-.02-.02-.04-.02M8.52 14.91c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12c0 1.17-.84 2.12-1.89 2.12m6.97 0c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12c0 1.17-.83 2.12-1.89 2.12" 88 | ></path> 89 | </svg>`, 90 | }, 91 | facebook: { 92 | Icon: (props: SVGProps<any>) => ( 93 | <svg 94 | xmlns="http://www.w3.org/2000/svg" 95 | width="1em" 96 | height="1em" 97 | viewBox="0 0 24 24" 98 | {...props} 99 | > 100 | <path 101 | d="M20 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h8.615v-6.96h-2.338v-2.725h2.338v-2c0-2.325 1.42-3.592 3.5-3.592c.699-.002 1.399.034 2.095.107v2.42h-1.435c-1.128 0-1.348.538-1.348 1.325v1.735h2.697l-.35 2.725h-2.348V21H20a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z" 102 | fill="currentColor" 103 | ></path> 104 | </svg> 105 | ), 106 | stringIcon: `<svg 107 | xmlns="http://www.w3.org/2000/svg" 108 | width="1em" 109 | height="1em" 110 | viewBox="0 0 24 24" 111 | > 112 | <path 113 | d="M20 3H4a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h8.615v-6.96h-2.338v-2.725h2.338v-2c0-2.325 1.42-3.592 3.5-3.592c.699-.002 1.399.034 2.095.107v2.42h-1.435c-1.128 0-1.348.538-1.348 1.325v1.735h2.697l-.35 2.725h-2.348V21H20a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z" 114 | fill="currentColor" 115 | ></path> 116 | </svg>`, 117 | }, 118 | github: { 119 | Icon: (props: SVGProps<any>) => ( 120 | <svg 121 | xmlns="http://www.w3.org/2000/svg" 122 | width="1em" 123 | height="1em" 124 | viewBox="0 0 24 24" 125 | {...props} 126 | > 127 | <path 128 | fill="currentColor" 129 | d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2" 130 | ></path> 131 | </svg> 132 | ), 133 | stringIcon: `<svg 134 | xmlns="http://www.w3.org/2000/svg" 135 | width="1em" 136 | height="1em" 137 | viewBox="0 0 24 24" 138 | > 139 | <path 140 | fill="currentColor" 141 | d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2" 142 | ></path> 143 | </svg>`, 144 | }, 145 | gitlab: { 146 | Icon: (props: SVGProps<any>) => ( 147 | <svg 148 | xmlns="http://www.w3.org/2000/svg" 149 | width="1em" 150 | height="1em" 151 | viewBox="0 0 24 24" 152 | {...props} 153 | > 154 | <path 155 | fill="currentColor" 156 | d="m22.749 9.769l-.031-.08l-3.027-7.9a.79.79 0 0 0-.782-.495a.8.8 0 0 0-.456.17a.8.8 0 0 0-.268.408L16.14 8.125H7.865L5.822 1.872a.8.8 0 0 0-.269-.409a.81.81 0 0 0-.926-.05c-.14.09-.25.22-.312.376L1.283 9.684l-.03.08a5.62 5.62 0 0 0 1.864 6.496l.01.008l.028.02l4.61 3.453l2.282 1.726l1.39 1.049a.935.935 0 0 0 1.13 0l1.389-1.05l2.281-1.726l4.639-3.473l.011-.01A5.62 5.62 0 0 0 22.75 9.77" 157 | ></path> 158 | </svg> 159 | ), 160 | stringIcon: `<svg 161 | xmlns="http://www.w3.org/2000/svg" 162 | width="1em" 163 | height="1em" 164 | viewBox="0 0 24 24" 165 | > 166 | <path 167 | fill="currentColor" 168 | d="m22.749 9.769l-.031-.08l-3.027-7.9a.79.79 0 0 0-.782-.495a.8.8 0 0 0-.456.17a.8.8 0 0 0-.268.408L16.14 8.125H7.865L5.822 1.872a.8.8 0 0 0-.269-.409a.81.81 0 0 0-.926-.05c-.14.09-.25.22-.312.376L1.283 9.684l-.03.08a5.62 5.62 0 0 0 1.864 6.496l.01.008l.028.02l4.61 3.453l2.282 1.726l1.39 1.049a.935.935 0 0 0 1.13 0l1.389-1.05l2.281-1.726l4.639-3.473l.011-.01A5.62 5.62 0 0 0 22.75 9.77" 169 | ></path> 170 | </svg>`, 171 | }, 172 | google: { 173 | Icon: (props: SVGProps<any>) => ( 174 | <svg 175 | xmlns="http://www.w3.org/2000/svg" 176 | width="0.98em" 177 | height="1em" 178 | viewBox="0 0 256 262" 179 | > 180 | <path 181 | fill="#4285F4" 182 | d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622l38.755 30.023l2.685.268c24.659-22.774 38.875-56.282 38.875-96.027" 183 | ></path> 184 | <path 185 | fill="#34A853" 186 | d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055c-34.523 0-63.824-22.773-74.269-54.25l-1.531.13l-40.298 31.187l-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1" 187 | ></path> 188 | <path 189 | fill="#FBBC05" 190 | d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82c0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602z" 191 | ></path> 192 | <path 193 | fill="#EB4335" 194 | d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0C79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251" 195 | ></path> 196 | </svg> 197 | ), 198 | stringIcon: `<svg xmlns="http://www.w3.org/2000/svg" width="0.98em" height="1em" viewBox="0 0 256 262"> 199 | <path fill="#4285F4" d="M255.878 133.451c0-10.734-.871-18.567-2.756-26.69H130.55v48.448h71.947c-1.45 12.04-9.283 30.172-26.69 42.356l-.244 1.622l38.755 30.023l2.685.268c24.659-22.774 38.875-56.282 38.875-96.027"></path> 200 | <path fill="#34A853" d="M130.55 261.1c35.248 0 64.839-11.605 86.453-31.622l-41.196-31.913c-11.024 7.688-25.82 13.055-45.257 13.055c-34.523 0-63.824-22.773-74.269-54.25l-1.531.13l-40.298 31.187l-.527 1.465C35.393 231.798 79.49 261.1 130.55 261.1"></path> 201 | <path fill="#FBBC05" d="M56.281 156.37c-2.756-8.123-4.351-16.827-4.351-25.82c0-8.994 1.595-17.697 4.206-25.82l-.073-1.73L15.26 71.312l-1.335.635C5.077 89.644 0 109.517 0 130.55s5.077 40.905 13.925 58.602z"></path> 202 | <path fill="#EB4335" d="M130.55 50.479c24.514 0 41.05 10.589 50.479 19.438l36.844-35.974C195.245 12.91 165.798 0 130.55 0C79.49 0 35.393 29.301 13.925 71.947l42.211 32.783c10.59-31.477 39.891-54.251 74.414-54.251"></path> 203 | </svg>`, 204 | }, 205 | linear: { 206 | Icon: (props: SVGProps<any>) => ( 207 | <svg 208 | xmlns="http://www.w3.org/2000/svg" 209 | width="1em" 210 | height="1em" 211 | viewBox="0 0 24 24" 212 | {...props} 213 | > 214 | <path 215 | fill="currentColor" 216 | d="M1.22541 61.5228c-.2225-.9485.90748-1.5459 1.59638-.857L39.3342 97.1782c.6889.6889.0915 1.8189-.857 1.5964C20.0515 94.4522 5.54779 79.9485 1.22541 61.5228ZM.00189135 46.8891c-.01764375.2833.08887215.5599.28957165.7606L52.3503 99.7085c.2007.2007.4773.3075.7606.2896 2.3692-.1476 4.6938-.46 6.9624-.9259.7645-.157 1.0301-1.0963.4782-1.6481L2.57595 39.4485c-.55186-.5519-1.49117-.2863-1.648174.4782-.465915 2.2686-.77832 4.5932-.92588465 6.9624ZM4.21093 29.7054c-.16649.3738-.08169.8106.20765 1.1l64.77602 64.776c.2894.2894.7262.3742 1.1.2077 1.7861-.7956 3.5171-1.6927 5.1855-2.684.5521-.328.6373-1.0867.1832-1.5407L8.43566 24.3367c-.45409-.4541-1.21271-.3689-1.54074.1832-.99132 1.6684-1.88843 3.3994-2.68399 5.1855ZM12.6587 18.074c-.3701-.3701-.393-.9637-.0443-1.3541C21.7795 6.45931 35.1114 0 49.9519 0 77.5927 0 100 22.4073 100 50.0481c0 14.8405-6.4593 28.1724-16.7199 37.3375-.3903.3487-.984.3258-1.3542-.0443L12.6587 18.074Z" 217 | /> 218 | </svg> 219 | ), 220 | stringIcon: `<svg 221 | xmlns="http://www.w3.org/2000/svg" 222 | fill="none" 223 | width="1em" 224 | height="1em" 225 | viewBox="0 0 24 24" 226 | > 227 | <path 228 | fill="currentColor" 229 | d="M1.22541 61.5228c-.2225-.9485.90748-1.5459 1.59638-.857L39.3342 97.1782c.6889.6889.0915 1.8189-.857 1.5964C20.0515 94.4522 5.54779 79.9485 1.22541 61.5228ZM.00189135 46.8891c-.01764375.2833.08887215.5599.28957165.7606L52.3503 99.7085c.2007.2007.4773.3075.7606.2896 2.3692-.1476 4.6938-.46 6.9624-.9259.7645-.157 1.0301-1.0963.4782-1.6481L2.57595 39.4485c-.55186-.5519-1.49117-.2863-1.648174.4782-.465915 2.2686-.77832 4.5932-.92588465 6.9624ZM4.21093 29.7054c-.16649.3738-.08169.8106.20765 1.1l64.77602 64.776c.2894.2894.7262.3742 1.1.2077 1.7861-.7956 3.5171-1.6927 5.1855-2.684.5521-.328.6373-1.0867.1832-1.5407L8.43566 24.3367c-.45409-.4541-1.21271-.3689-1.54074.1832-.99132 1.6684-1.88843 3.3994-2.68399 5.1855ZM12.6587 18.074c-.3701-.3701-.393-.9637-.0443-1.3541C21.7795 6.45931 35.1114 0 49.9519 0 77.5927 0 100 22.4073 100 50.0481c0 14.8405-6.4593 28.1724-16.7199 37.3375-.3903.3487-.984.3258-1.3542-.0443L12.6587 18.074Z" 230 | /> 231 | </svg>`, 232 | }, 233 | kakao: { 234 | Icon: (props: SVGProps<any>) => ( 235 | <svg 236 | xmlns="http://www.w3.org/2000/svg" 237 | width="1em" 238 | height="1em" 239 | viewBox="0 0 512 512" 240 | {...props} 241 | > 242 | <g> 243 | <path 244 | fill="currentColor" 245 | d="M 511.5,203.5 C 511.5,215.5 511.5,227.5 511.5,239.5C 504.002,286.989 482.002,326.489 445.5,358C 390.216,402.375 326.882,424.209 255.5,423.5C 239.751,423.476 224.085,422.643 208.5,421C 174.34,444.581 140.006,467.914 105.5,491C 95.6667,493.167 91.8333,489.333 94,479.5C 101.833,450.667 109.667,421.833 117.5,393C 85.5639,376.077 58.0639,353.577 35,325.5C 15.8353,299.834 4.00193,271.167 -0.5,239.5C -0.5,227.5 -0.5,215.5 -0.5,203.5C 7.09119,155.407 29.4245,115.574 66.5,84C 121.53,39.9708 184.53,18.4708 255.5,19.5C 326.47,18.4708 389.47,39.9708 444.5,84C 481.575,115.574 503.909,155.407 511.5,203.5 Z" 246 | /> 247 | </g> 248 | </svg> 249 | ), 250 | stringIcon: `<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 512 512"><g><path fill="currentColor" d="M 511.5,203.5 C 511.5,215.5 511.5,227.5 511.5,239.5C 504.002,286.989 482.002,326.489 445.5,358C 390.216,402.375 326.882,424.209 255.5,423.5C 239.751,423.476 224.085,422.643 208.5,421C 174.34,444.581 140.006,467.914 105.5,491C 95.6667,493.167 91.8333,489.333 94,479.5C 101.833,450.667 109.667,421.833 117.5,393C 85.5639,376.077 58.0639,353.577 35,325.5C 15.8353,299.834 4.00193,271.167 -0.5,239.5C -0.5,227.5 -0.5,215.5 -0.5,203.5C 7.09119,155.407 29.4245,115.574 66.5,84C 121.53,39.9708 184.53,18.4708 255.5,19.5C 326.47,18.4708 389.47,39.9708 444.5,84C 481.575,115.574 503.909,155.407 511.5,203.5 Z"/></g></svg>`, 251 | }, 252 | naver: { 253 | Icon: (props: SVGProps<any>) => ( 254 | <svg 255 | xmlns="http://www.w3.org/2000/svg" 256 | width="1em" 257 | height="1em" 258 | viewBox="0 0 24 24" 259 | {...props} 260 | > 261 | <path 262 | fill="currentColor" 263 | d="M16.273 12.845 7.376 0H0v24h7.726V11.156L16.624 24H24V0h-7.727v12.845Z" 264 | /> 265 | </svg> 266 | ), 267 | stringIcon: `<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="M16.273 12.845 7.376 0H0v24h7.726V11.156L16.624 24H24V0h-7.727v12.845Z"/></svg>`, 268 | }, 269 | linkedin: { 270 | Icon: (props: SVGProps<any>) => ( 271 | <svg 272 | xmlns="http://www.w3.org/2000/svg" 273 | width="1em" 274 | height="1em" 275 | viewBox="0 0 24 24" 276 | {...props} 277 | > 278 | <path 279 | fill="currentColor" 280 | d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2zm-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.32 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93zM6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37z" 281 | ></path> 282 | </svg> 283 | ), 284 | stringIcon: `<svg 285 | xmlns="http://www.w3.org/2000/svg" 286 | width="1em" 287 | height="1em" 288 | viewBox="0 0 24 24" 289 | > 290 | <path 291 | fill="currentColor" 292 | d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2zm-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.32 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93zM6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37z" 293 | ></path> 294 | </svg>`, 295 | }, 296 | microsoft: { 297 | Icon: (props: SVGProps<any>) => ( 298 | <svg 299 | xmlns="http://www.w3.org/2000/svg" 300 | width="1.2em" 301 | height="1.2em" 302 | viewBox="0 0 24 24" 303 | {...props} 304 | > 305 | <path 306 | fill="currentColor" 307 | d="M2 3h9v9H2zm9 19H2v-9h9zM21 3v9h-9V3zm0 19h-9v-9h9z" 308 | ></path> 309 | </svg> 310 | ), 311 | stringIcon: `<svg 312 | xmlns="http://www.w3.org/2000/svg" 313 | width="1em" 314 | height="1em" 315 | viewBox="0 0 24 24" 316 | > 317 | <path 318 | fill="currentColor" 319 | d="M2 3h9v9H2zm9 19H2v-9h9zM21 3v9h-9V3zm0 19h-9v-9h9z" 320 | ></path> 321 | </svg>`, 322 | }, 323 | twitch: { 324 | Icon: (props: SVGProps<any>) => ( 325 | <svg 326 | xmlns="http://www.w3.org/2000/svg" 327 | width="1em" 328 | height="1em" 329 | viewBox="0 0 24 24" 330 | {...props} 331 | > 332 | <path 333 | fill="currentColor" 334 | d="M11.64 5.93h1.43v4.28h-1.43m3.93-4.28H17v4.28h-1.43M7 2L3.43 5.57v12.86h4.28V22l3.58-3.57h2.85L20.57 12V2m-1.43 9.29l-2.85 2.85h-2.86l-2.5 2.5v-2.5H7.71V3.43h11.43Z" 335 | ></path> 336 | </svg> 337 | ), 338 | stringIcon: `<svg 339 | xmlns="http://www.w3.org/2000/svg" 340 | width="1.2em" 341 | height="1.2em" 342 | viewBox="0 0 24 24" 343 | > 344 | <path 345 | fill="currentColor" 346 | d="M11.64 5.93h1.43v4.28h-1.43m3.93-4.28H17v4.28h-1.43M7 2L3.43 5.57v12.86h4.28V22l3.58-3.57h2.85L20.57 12V2m-1.43 9.29l-2.85 2.85h-2.86l-2.5 2.5v-2.5H7.71V3.43h11.43Z" 347 | ></path> 348 | </svg>`, 349 | }, 350 | spotify: { 351 | Icon: (props: SVGProps<any>) => ( 352 | <svg 353 | xmlns="http://www.w3.org/2000/svg" 354 | width="1em" 355 | height="1em" 356 | viewBox="0 0 24 24" 357 | {...props} 358 | > 359 | <path 360 | fill="currentColor" 361 | d="M12.001 2c-5.5 0-10 4.5-10 10s4.5 10 10 10s10-4.5 10-10s-4.45-10-10-10m3.75 14.65c-2.35-1.45-5.3-1.75-8.8-.95c-.35.1-.65-.15-.75-.45c-.1-.35.15-.65.45-.75c3.8-.85 7.1-.5 9.7 1.1c.35.15.4.55.25.85c-.2.3-.55.4-.85.2m1-2.7c-2.7-1.65-6.8-2.15-9.95-1.15c-.4.1-.85-.1-.95-.5s.1-.85.5-.95c3.65-1.1 8.15-.55 11.25 1.35c.3.15.45.65.2 1s-.7.5-1.05.25M6.3 9.75c-.5.15-1-.15-1.15-.6c-.15-.5.15-1 .6-1.15c3.55-1.05 9.4-.85 13.1 1.35c.45.25.6.85.35 1.3c-.25.35-.85.5-1.3.25C14.7 9 9.35 8.8 6.3 9.75" 362 | ></path> 363 | </svg> 364 | ), 365 | stringIcon: `<svg 366 | xmlns="http://www.w3.org/2000/svg" 367 | width="1.2em" 368 | height="1.2em" 369 | viewBox="0 0 24 24" 370 | > 371 | <path 372 | fill="currentColor" 373 | d="M12.001 2c-5.5 0-10 4.5-10 10s4.5 10 10 10s10-4.5 10-10s-4.45-10-10-10m3.75 14.65c-2.35-1.45-5.3-1.75-8.8-.95c-.35.1-.65-.15-.75-.45c-.1-.35.15-.65.45-.75c3.8-.85 7.1-.5 9.7 1.1c.35.15.4.55.25.85c-.2.3-.55.4-.85.2m1-2.7c-2.7-1.65-6.8-2.15-9.95-1.15c-.4.1-.85-.1-.95-.5s.1-.85.5-.95c3.65-1.1 8.15-.55 11.25 1.35c.3.15.45.65.2 1s-.7.5-1.05.25M6.3 9.75c-.5.15-1-.15-1.15-.6c-.15-.5.15-1 .6-1.15c3.55-1.05 9.4-.85 13.1 1.35c.45.25.6.85.35 1.3c-.25.35-.85.5-1.3.25C14.7 9 9.35 8.8 6.3 9.75" 374 | ></path> 375 | </svg>`, 376 | }, 377 | tiktok: { 378 | Icon: (props?: SVGProps<any>) => ( 379 | <svg 380 | xmlns="http://www.w3.org/2000/svg" 381 | width="0.88em" 382 | height="1em" 383 | viewBox="0 0 448 512" 384 | {...props} 385 | > 386 | <path 387 | fill="currentColor" 388 | d="M412.19,118.66a109.27,109.27,0,0,1-9.45-5.5,132.87,132.87,0,0,1-24.27-20.62c-18.1-20.71-24.86-41.72-27.35-56.43h.1C349.14,23.9,350,16,350.13,16H267.69V334.78c0,4.28,0,8.51-.18,12.69,0,.52-.05,1-.08,1.56,0,.23,0,.47-.05.71,0,.06,0,.12,0,.18a70,70,0,0,1-35.22,55.56,68.8,68.8,0,0,1-34.11,9c-38.41,0-69.54-31.32-69.54-70s31.13-70,69.54-70a68.9,68.9,0,0,1,21.41,3.39l.1-83.94a153.14,153.14,0,0,0-118,34.52,161.79,161.79,0,0,0-35.3,43.53c-3.48,6-16.61,30.11-18.2,69.24-1,22.21,5.67,45.22,8.85,54.73v.2c2,5.6,9.75,24.71,22.38,40.82A167.53,167.53,0,0,0,115,470.66v-.2l.2.2C155.11,497.78,199.36,496,199.36,496c7.66-.31,33.32,0,62.46-13.81,32.32-15.31,50.72-38.12,50.72-38.12a158.46,158.46,0,0,0,27.64-45.93c7.46-19.61,9.95-43.13,9.95-52.53V176.49c1,.6,14.32,9.41,14.32,9.41s19.19,12.3,49.13,20.31c21.48,5.7,50.42,6.9,50.42,6.9V131.27C453.86,132.37,433.27,129.17,412.19,118.66Z" 389 | /> 390 | </svg> 391 | ), 392 | stringIcon: `<svg 393 | xmlns="http://www.w3.org/2000/svg" 394 | width="0.88em" 395 | height="1em" 396 | viewBox="0 0 448 512" 397 | {...props} 398 | > 399 | <path 400 | fill="currentColor" 401 | d="M412.19,118.66a109.27,109.27,0,0,1-9.45-5.5,132.87,132.87,0,0,1-24.27-20.62c-18.1-20.71-24.86-41.72-27.35-56.43h.1C349.14,23.9,350,16,350.13,16H267.69V334.78c0,4.28,0,8.51-.18,12.69,0,.52-.05,1-.08,1.56,0,.23,0,.47-.05.71,0,.06,0,.12,0,.18a70,70,0,0,1-35.22,55.56,68.8,68.8,0,0,1-34.11,9c-38.41,0-69.54-31.32-69.54-70s31.13-70,69.54-70a68.9,68.9,0,0,1,21.41,3.39l.1-83.94a153.14,153.14,0,0,0-118,34.52,161.79,161.79,0,0,0-35.3,43.53c-3.48,6-16.61,30.11-18.2,69.24-1,22.21,5.67,45.22,8.85,54.73v.2c2,5.6,9.75,24.71,22.38,40.82A167.53,167.53,0,0,0,115,470.66v-.2l.2.2C155.11,497.78,199.36,496,199.36,496c7.66-.31,33.32,0,62.46-13.81,32.32-15.31,50.72-38.12,50.72-38.12a158.46,158.46,0,0,0,27.64-45.93c7.46-19.61,9.95-43.13,9.95-52.53V176.49c1,.6,14.32,9.41,14.32,9.41s19.19,12.3,49.13,20.31c21.48,5.7,50.42,6.9,50.42,6.9V131.27C453.86,132.37,433.27,129.17,412.19,118.66Z" 402 | /> 403 | </svg>`, 404 | }, 405 | twitter: { 406 | Icon: (props?: SVGProps<any>) => ( 407 | <svg 408 | xmlns="http://www.w3.org/2000/svg" 409 | width="0.88em" 410 | height="1em" 411 | viewBox="0 0 448 512" 412 | {...props} 413 | > 414 | <path 415 | fill="currentColor" 416 | d="M64 32C28.7 32 0 60.7 0 96v320c0 35.3 28.7 64 64 64h320c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64zm297.1 84L257.3 234.6L379.4 396h-95.6L209 298.1L123.3 396H75.8l111-126.9L69.7 116h98l67.7 89.5l78.2-89.5zm-37.8 251.6L153.4 142.9h-28.3l171.8 224.7h26.3z" 417 | ></path> 418 | </svg> 419 | ), 420 | stringIcon: `<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 448 512"><path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96v320c0 35.3 28.7 64 64 64h320c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64zm297.1 84L257.3 234.6L379.4 396h-95.6L209 298.1L123.3 396H75.8l111-126.9L69.7 116h98l67.7 89.5l78.2-89.5zm-37.8 251.6L153.4 142.9h-28.3l171.8 224.7h26.3z"></path></svg>`, 421 | }, 422 | roblox: { 423 | Icon: (props?: SVGProps<any>) => ( 424 | <svg 425 | xmlns="http://www.w3.org/2000/svg" 426 | width="1.2em" 427 | height="1.2em" 428 | viewBox="0 0 267 267" 429 | {...props} 430 | > 431 | <path 432 | fill="currentColor" 433 | d="M 56.926 0.986 L 1.01 210.05 L 210.073 266.014 L 265.989 56.951 L 56.926 0.986 Z M 112.15 96.988 L 170.481 112.619 L 154.849 170.95 L 96.47 155.318 L 112.15 96.988 Z" 434 | ></path> 435 | </svg> 436 | ), 437 | stringIcon: `<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 267 267"><path xmlns="http://www.w3.org/2000/svg" fill="currentColor" d="M 56.926 0.986 L 1.01 210.05 L 210.073 266.014 L 265.989 56.951 L 56.926 0.986 Z M 112.15 96.988 L 170.481 112.619 L 154.849 170.95 L 96.47 155.318 L 112.15 96.988 Z"/></svg>`, 438 | }, 439 | vk: { 440 | Icon: (props?: SVGProps<any>) => ( 441 | <svg 442 | xmlns="http://www.w3.org/2000/svg" 443 | width="1.2em" 444 | height="1.2em" 445 | viewBox="0 0 20 20" 446 | {...props} 447 | > 448 | <path 449 | fill="currentColor" 450 | fillRule="evenodd" 451 | d="M17.802 12.298s1.617 1.597 2.017 2.336a.1.1 0 0 1 .018.035q.244.409.123.645c-.135.261-.592.392-.747.403h-2.858c-.199 0-.613-.052-1.117-.4c-.385-.269-.768-.712-1.139-1.145c-.554-.643-1.033-1.201-1.518-1.201a.6.6 0 0 0-.18.03c-.367.116-.833.639-.833 2.032c0 .436-.344.684-.585.684H9.674c-.446 0-2.768-.156-4.827-2.327C2.324 10.732.058 5.4.036 5.353c-.141-.345.155-.533.475-.533h2.886c.387 0 .513.234.601.444c.102.241.48 1.205 1.1 2.288c1.004 1.762 1.621 2.479 2.114 2.479a.53.53 0 0 0 .264-.07c.644-.354.524-2.654.494-3.128c0-.092-.001-1.027-.331-1.479c-.236-.324-.638-.45-.881-.496c.065-.094.203-.238.38-.323c.441-.22 1.238-.252 2.029-.252h.439c.858.012 1.08.067 1.392.146c.628.15.64.557.585 1.943c-.016.396-.033.842-.033 1.367c0 .112-.005.237-.005.364c-.019.711-.044 1.512.458 1.841a.4.4 0 0 0 .217.062c.174 0 .695 0 2.108-2.425c.62-1.071 1.1-2.334 1.133-2.429c.028-.053.112-.202.214-.262a.5.5 0 0 1 .236-.056h3.395c.37 0 .621.056.67.196c.082.227-.016.92-1.566 3.016c-.261.349-.49.651-.691.915c-1.405 1.844-1.405 1.937.083 3.337" 452 | clipRule="evenodd" 453 | /> 454 | </svg> 455 | ), 456 | stringIcon: `<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 448 512"><path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96v320c0 35.3 28.7 64 64 64h320c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64zm297.1 84L257.3 234.6L379.4 396h-95.6L209 298.1L123.3 396H75.8l111-126.9L69.7 116h98l67.7 89.5l78.2-89.5zm-37.8 251.6L153.4 142.9h-28.3l171.8 224.7h26.3z"></path></svg>`, 457 | }, 458 | zoom: { 459 | Icon: (props?: SVGProps<any>) => ( 460 | <svg 461 | xmlns="http://www.w3.org/2000/svg" 462 | width="1.2em" 463 | height="1.2em" 464 | viewBox="0 0 16 16" 465 | > 466 | <path 467 | fill="currentColor" 468 | fillRule="evenodd" 469 | d="M1.45 3.334C.648 3.334 0 3.982 0 4.783v4.986c0 1.6 1.298 2.898 2.898 2.898h6.986c.8 0 1.45-.649 1.45-1.45V6.233a2.9 2.9 0 0 0-2.899-2.899zM16 4.643v6.715c0 .544-.618.86-1.059.539l-2.059-1.498a1.33 1.33 0 0 1-.549-1.078V6.679c0-.427.204-.827.55-1.078l2.058-1.498a.667.667 0 0 1 1.059.54" 470 | clipRule="evenodd" 471 | ></path> 472 | </svg> 473 | ), 474 | stringIcon: `<svg 475 | xmlns="http://www.w3.org/2000/svg" 476 | width="1.2em" 477 | height="1.2em" 478 | viewBox="0 0 16 16" 479 | > 480 | <path 481 | fill="currentColor" 482 | fillRule="evenodd" 483 | d="M1.45 3.334C.648 3.334 0 3.982 0 4.783v4.986c0 1.6 1.298 2.898 2.898 2.898h6.986c.8 0 1.45-.649 1.45-1.45V6.233a2.9 2.9 0 0 0-2.899-2.899zM16 4.643v6.715c0 .544-.618.86-1.059.539l-2.059-1.498a1.33 1.33 0 0 1-.549-1.078V6.679c0-.427.204-.827.55-1.078l2.058-1.498a.667.667 0 0 1 1.059.54" 484 | clipRule="evenodd" 485 | ></path> 486 | </svg>`, 487 | }, 488 | }; 489 | ``` -------------------------------------------------------------------------------- /packages/core/src/types/init-options.ts: -------------------------------------------------------------------------------- ```typescript 1 | import type { Dialect, Kysely, MysqlPool, PostgresPool } from "kysely"; 2 | import type { Database } from "better-sqlite3"; 3 | import type { CookieOptions } from "better-call"; 4 | import type { LiteralUnion } from "./helper"; 5 | import type { 6 | DBFieldAttribute, 7 | DBPreservedModels, 8 | SecondaryStorage, 9 | } from "../db/type"; 10 | import type { Account, RateLimit, Session, User, Verification } from "../db"; 11 | import type { Database as BunDatabase } from "bun:sqlite"; 12 | import type { DatabaseSync } from "node:sqlite"; 13 | import type { DBAdapterDebugLogOption, DBAdapterInstance } from "../db/adapter"; 14 | import type { SocialProviderList, SocialProviders } from "../social-providers"; 15 | import type { Logger } from "../env"; 16 | import type { AuthContext, GenericEndpointContext } from "./context"; 17 | import type { AuthMiddleware } from "../middleware"; 18 | import type { BetterAuthPlugin } from ".."; 19 | 20 | type KyselyDatabaseType = "postgres" | "mysql" | "sqlite" | "mssql"; 21 | type OmitId<T extends { id: unknown }> = Omit<T, "id">; 22 | type Optional<T> = { 23 | [P in keyof T]?: T[P] | undefined; 24 | }; 25 | 26 | export type GenerateIdFn = (options: { 27 | model: LiteralUnion<DBPreservedModels, string>; 28 | size?: number; 29 | }) => string | false; 30 | 31 | export type BetterAuthRateLimitOptions = { 32 | /** 33 | * By default, rate limiting is only 34 | * enabled on production. 35 | */ 36 | enabled?: boolean; 37 | /** 38 | * Default window to use for rate limiting. The value 39 | * should be in seconds. 40 | * 41 | * @default 10 seconds 42 | */ 43 | window?: number; 44 | /** 45 | * The default maximum number of requests allowed within the window. 46 | * 47 | * @default 100 requests 48 | */ 49 | max?: number; 50 | /** 51 | * Custom rate limit rules to apply to 52 | * specific paths. 53 | */ 54 | customRules?: { 55 | [key: string]: 56 | | { 57 | /** 58 | * The window to use for the custom rule. 59 | */ 60 | window: number; 61 | /** 62 | * The maximum number of requests allowed within the window. 63 | */ 64 | max: number; 65 | } 66 | | false 67 | | ((request: Request) => 68 | | { window: number; max: number } 69 | | false 70 | | Promise< 71 | | { 72 | window: number; 73 | max: number; 74 | } 75 | | false 76 | >); 77 | }; 78 | /** 79 | * Storage configuration 80 | * 81 | * By default, rate limiting is stored in memory. If you passed a 82 | * secondary storage, rate limiting will be stored in the secondary 83 | * storage. 84 | * 85 | * @default "memory" 86 | */ 87 | storage?: "memory" | "database" | "secondary-storage"; 88 | /** 89 | * If database is used as storage, the name of the table to 90 | * use for rate limiting. 91 | * 92 | * @default "rateLimit" 93 | */ 94 | modelName?: string; 95 | /** 96 | * Custom field names for the rate limit table 97 | */ 98 | fields?: Record<keyof RateLimit, string>; 99 | /** 100 | * custom storage configuration. 101 | * 102 | * NOTE: If custom storage is used storage 103 | * is ignored 104 | */ 105 | customStorage?: { 106 | get: (key: string) => Promise<RateLimit | undefined>; 107 | set: (key: string, value: RateLimit) => Promise<void>; 108 | }; 109 | }; 110 | 111 | export type BetterAuthAdvancedOptions = { 112 | /** 113 | * Ip address configuration 114 | */ 115 | ipAddress?: { 116 | /** 117 | * List of headers to use for ip address 118 | * 119 | * Ip address is used for rate limiting and session tracking 120 | * 121 | * @example ["x-client-ip", "x-forwarded-for", "cf-connecting-ip"] 122 | * 123 | * @default 124 | * @link https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/utils/get-request-ip.ts#L8 125 | */ 126 | ipAddressHeaders?: string[]; 127 | /** 128 | * Disable ip tracking 129 | * 130 | * ⚠︎ This is a security risk and it may expose your application to abuse 131 | */ 132 | disableIpTracking?: boolean; 133 | }; 134 | /** 135 | * Use secure cookies 136 | * 137 | * @default false 138 | */ 139 | useSecureCookies?: boolean; 140 | /** 141 | * Disable trusted origins check 142 | * 143 | * ⚠︎ This is a security risk and it may expose your application to CSRF attacks 144 | */ 145 | disableCSRFCheck?: boolean; 146 | /** 147 | * Configure cookies to be cross subdomains 148 | */ 149 | crossSubDomainCookies?: { 150 | /** 151 | * Enable cross subdomain cookies 152 | */ 153 | enabled: boolean; 154 | /** 155 | * Additional cookies to be shared across subdomains 156 | */ 157 | additionalCookies?: string[]; 158 | /** 159 | * The domain to use for the cookies 160 | * 161 | * By default, the domain will be the root 162 | * domain from the base URL. 163 | */ 164 | domain?: string; 165 | }; 166 | /* 167 | * Allows you to change default cookie names and attributes 168 | * 169 | * default cookie names: 170 | * - "session_token" 171 | * - "session_data" 172 | * - "dont_remember" 173 | * 174 | * plugins can also add additional cookies 175 | */ 176 | cookies?: { 177 | [key: string]: { 178 | name?: string; 179 | attributes?: CookieOptions; 180 | }; 181 | }; 182 | defaultCookieAttributes?: CookieOptions; 183 | /** 184 | * Prefix for cookies. If a cookie name is provided 185 | * in cookies config, this will be overridden. 186 | * 187 | * @default 188 | * ```txt 189 | * "appName" -> which defaults to "better-auth" 190 | * ``` 191 | */ 192 | cookiePrefix?: string; 193 | /** 194 | * Database configuration. 195 | */ 196 | database?: { 197 | /** 198 | * The default number of records to return from the database 199 | * when using the `findMany` adapter method. 200 | * 201 | * @default 100 202 | */ 203 | defaultFindManyLimit?: number; 204 | /** 205 | * If your database auto increments number ids, set this to `true`. 206 | * 207 | * Note: If enabled, we will not handle ID generation (including if you use `generateId`), and it would be expected that your database will provide the ID automatically. 208 | * 209 | * @default false 210 | */ 211 | useNumberId?: boolean; 212 | /** 213 | * Custom generateId function. 214 | * 215 | * If not provided, random ids will be generated. 216 | * If set to false, the database's auto generated id will be used. 217 | */ 218 | generateId?: GenerateIdFn | false; 219 | }; 220 | }; 221 | 222 | export type BetterAuthOptions = { 223 | /** 224 | * The name of the application 225 | * 226 | * process.env.APP_NAME 227 | * 228 | * @default "Better Auth" 229 | */ 230 | appName?: string; 231 | /** 232 | * Base URL for the Better Auth. This is typically the 233 | * root URL where your application server is hosted. 234 | * If not explicitly set, 235 | * the system will check the following environment variable: 236 | * 237 | * process.env.BETTER_AUTH_URL 238 | */ 239 | baseURL?: string; 240 | /** 241 | * Base path for the Better Auth. This is typically 242 | * the path where the 243 | * Better Auth routes are mounted. 244 | * 245 | * @default "/api/auth" 246 | */ 247 | basePath?: string; 248 | /** 249 | * The secret to use for encryption, 250 | * signing and hashing. 251 | * 252 | * By default Better Auth will look for 253 | * the following environment variables: 254 | * process.env.BETTER_AUTH_SECRET, 255 | * process.env.AUTH_SECRET 256 | * If none of these environment 257 | * variables are set, 258 | * it will default to 259 | * "better-auth-secret-123456789". 260 | * 261 | * on production if it's not set 262 | * it will throw an error. 263 | * 264 | * you can generate a good secret 265 | * using the following command: 266 | * @example 267 | * ```bash 268 | * openssl rand -base64 32 269 | * ``` 270 | */ 271 | secret?: string; 272 | /** 273 | * Database configuration 274 | */ 275 | database?: 276 | | PostgresPool 277 | | MysqlPool 278 | | Database 279 | | Dialect 280 | | DBAdapterInstance 281 | | BunDatabase 282 | | DatabaseSync 283 | | { 284 | dialect: Dialect; 285 | type: KyselyDatabaseType; 286 | /** 287 | * casing for table names 288 | * 289 | * @default "camel" 290 | */ 291 | casing?: "snake" | "camel"; 292 | /** 293 | * Enable debug logs for the adapter 294 | * 295 | * @default false 296 | */ 297 | debugLogs?: DBAdapterDebugLogOption; 298 | /** 299 | * Whether to execute multiple operations in a transaction. 300 | * If the database doesn't support transactions, 301 | * set this to `false` and operations will be executed sequentially. 302 | * @default true 303 | */ 304 | transaction?: boolean; 305 | } 306 | | { 307 | /** 308 | * Kysely instance 309 | */ 310 | db: Kysely<any>; 311 | /** 312 | * Database type between postgres, mysql and sqlite 313 | */ 314 | type: KyselyDatabaseType; 315 | /** 316 | * casing for table names 317 | * 318 | * @default "camel" 319 | */ 320 | casing?: "snake" | "camel"; 321 | /** 322 | * Enable debug logs for the adapter 323 | * 324 | * @default false 325 | */ 326 | debugLogs?: DBAdapterDebugLogOption; 327 | /** 328 | * Whether to execute multiple operations in a transaction. 329 | * If the database doesn't support transactions, 330 | * set this to `false` and operations will be executed sequentially. 331 | * @default true 332 | */ 333 | transaction?: boolean; 334 | }; 335 | /** 336 | * Secondary storage configuration 337 | * 338 | * This is used to store session and rate limit data. 339 | */ 340 | secondaryStorage?: SecondaryStorage; 341 | /** 342 | * Email verification configuration 343 | */ 344 | emailVerification?: { 345 | /** 346 | * Send a verification email 347 | * @param data the data object 348 | * @param request the request object 349 | */ 350 | sendVerificationEmail?: ( 351 | /** 352 | * @param user the user to send the 353 | * verification email to 354 | * @param url the URL to send the verification email to 355 | * it contains the token as well 356 | * @param token the token to send the verification email to 357 | */ 358 | data: { 359 | user: User; 360 | url: string; 361 | token: string; 362 | }, 363 | /** 364 | * The request object 365 | */ 366 | request?: Request, 367 | ) => Promise<void>; 368 | /** 369 | * Send a verification email automatically 370 | * after sign up 371 | * 372 | * @default false 373 | */ 374 | sendOnSignUp?: boolean; 375 | /** 376 | * Send a verification email automatically 377 | * on sign in when the user's email is not verified 378 | * 379 | * @default false 380 | */ 381 | sendOnSignIn?: boolean; 382 | /** 383 | * Auto signin the user after they verify their email 384 | */ 385 | autoSignInAfterVerification?: boolean; 386 | /** 387 | * Number of seconds the verification token is 388 | * valid for. 389 | * @default 3600 seconds (1 hour) 390 | */ 391 | expiresIn?: number; 392 | /** 393 | * A function that is called when a user verifies their email 394 | * @param user the user that verified their email 395 | * @param request the request object 396 | */ 397 | onEmailVerification?: (user: User, request?: Request) => Promise<void>; 398 | /** 399 | * A function that is called when a user's email is updated to verified 400 | * @param user the user that verified their email 401 | * @param request the request object 402 | */ 403 | afterEmailVerification?: (user: User, request?: Request) => Promise<void>; 404 | }; 405 | /** 406 | * Email and password authentication 407 | */ 408 | emailAndPassword?: { 409 | /** 410 | * Enable email and password authentication 411 | * 412 | * @default false 413 | */ 414 | enabled: boolean; 415 | /** 416 | * Disable email and password sign up 417 | * 418 | * @default false 419 | */ 420 | disableSignUp?: boolean; 421 | /** 422 | * Require email verification before a session 423 | * can be created for the user. 424 | * 425 | * if the user is not verified, the user will not be able to sign in 426 | * and on sign in attempts, the user will be prompted to verify their email. 427 | */ 428 | requireEmailVerification?: boolean; 429 | /** 430 | * The maximum length of the password. 431 | * 432 | * @default 128 433 | */ 434 | maxPasswordLength?: number; 435 | /** 436 | * The minimum length of the password. 437 | * 438 | * @default 8 439 | */ 440 | minPasswordLength?: number; 441 | /** 442 | * send reset password 443 | */ 444 | sendResetPassword?: ( 445 | /** 446 | * @param user the user to send the 447 | * reset password email to 448 | * @param url the URL to send the reset password email to 449 | * @param token the token to send to the user (could be used instead of sending the url 450 | * if you need to redirect the user to custom route) 451 | */ 452 | data: { user: User; url: string; token: string }, 453 | /** 454 | * The request object 455 | */ 456 | request?: Request, 457 | ) => Promise<void>; 458 | /** 459 | * Number of seconds the reset password token is 460 | * valid for. 461 | * @default 1 hour (60 * 60) 462 | */ 463 | resetPasswordTokenExpiresIn?: number; 464 | /** 465 | * A callback function that is triggered 466 | * when a user's password is changed successfully. 467 | */ 468 | onPasswordReset?: ( 469 | data: { user: User }, 470 | request?: Request, 471 | ) => Promise<void>; 472 | /** 473 | * Password hashing and verification 474 | * 475 | * By default Scrypt is used for password hashing and 476 | * verification. You can provide your own hashing and 477 | * verification function. if you want to use a 478 | * different algorithm. 479 | */ 480 | password?: { 481 | hash?: (password: string) => Promise<string>; 482 | verify?: (data: { hash: string; password: string }) => Promise<boolean>; 483 | }; 484 | /** 485 | * Automatically sign in the user after sign up 486 | * 487 | * @default true 488 | */ 489 | autoSignIn?: boolean; 490 | /** 491 | * Whether to revoke all other sessions when resetting password 492 | * @default false 493 | */ 494 | revokeSessionsOnPasswordReset?: boolean; 495 | }; 496 | /** 497 | * list of social providers 498 | */ 499 | socialProviders?: SocialProviders; 500 | /** 501 | * List of Better Auth plugins 502 | */ 503 | plugins?: [] | BetterAuthPlugin[]; 504 | /** 505 | * User configuration 506 | */ 507 | user?: { 508 | /** 509 | * The model name for the user. Defaults to "user". 510 | */ 511 | modelName?: string; 512 | /** 513 | * Map fields 514 | * 515 | * @example 516 | * ```ts 517 | * { 518 | * userId: "user_id" 519 | * } 520 | * ``` 521 | */ 522 | fields?: Partial<Record<keyof OmitId<User>, string>>; 523 | /** 524 | * Additional fields for the user 525 | */ 526 | additionalFields?: { 527 | [key: string]: DBFieldAttribute; 528 | }; 529 | /** 530 | * Changing email configuration 531 | */ 532 | changeEmail?: { 533 | /** 534 | * Enable changing email 535 | * @default false 536 | */ 537 | enabled: boolean; 538 | /** 539 | * Send a verification email when the user changes their email. 540 | * @param data the data object 541 | * @param request the request object 542 | */ 543 | sendChangeEmailVerification?: ( 544 | data: { 545 | user: User; 546 | newEmail: string; 547 | url: string; 548 | token: string; 549 | }, 550 | request?: Request, 551 | ) => Promise<void>; 552 | }; 553 | /** 554 | * User deletion configuration 555 | */ 556 | deleteUser?: { 557 | /** 558 | * Enable user deletion 559 | */ 560 | enabled?: boolean; 561 | /** 562 | * Send a verification email when the user deletes their account. 563 | * 564 | * if this is not set, the user will be deleted immediately. 565 | * @param data the data object 566 | * @param request the request object 567 | */ 568 | sendDeleteAccountVerification?: ( 569 | data: { 570 | user: User; 571 | url: string; 572 | token: string; 573 | }, 574 | request?: Request, 575 | ) => Promise<void>; 576 | /** 577 | * A function that is called before a user is deleted. 578 | * 579 | * to interrupt with error you can throw `APIError` 580 | */ 581 | beforeDelete?: (user: User, request?: Request) => Promise<void>; 582 | /** 583 | * A function that is called after a user is deleted. 584 | * 585 | * This is useful for cleaning up user data 586 | */ 587 | afterDelete?: (user: User, request?: Request) => Promise<void>; 588 | /** 589 | * The expiration time for the delete token. 590 | * 591 | * @default 1 day (60 * 60 * 24) in seconds 592 | */ 593 | deleteTokenExpiresIn?: number; 594 | }; 595 | }; 596 | session?: { 597 | /** 598 | * The model name for the session. 599 | * 600 | * @default "session" 601 | */ 602 | modelName?: string; 603 | /** 604 | * Map fields 605 | * 606 | * @example 607 | * ```ts 608 | * { 609 | * userId: "user_id" 610 | * } 611 | */ 612 | fields?: Partial<Record<keyof OmitId<Session>, string>>; 613 | /** 614 | * Expiration time for the session token. The value 615 | * should be in seconds. 616 | * @default 7 days (60 * 60 * 24 * 7) 617 | */ 618 | expiresIn?: number; 619 | /** 620 | * How often the session should be refreshed. The value 621 | * should be in seconds. 622 | * If set 0 the session will be refreshed every time it is used. 623 | * @default 1 day (60 * 60 * 24) 624 | */ 625 | updateAge?: number; 626 | /** 627 | * Disable session refresh so that the session is not updated 628 | * regardless of the `updateAge` option. 629 | * 630 | * @default false 631 | */ 632 | disableSessionRefresh?: boolean; 633 | /** 634 | * Additional fields for the session 635 | */ 636 | additionalFields?: { 637 | [key: string]: DBFieldAttribute; 638 | }; 639 | /** 640 | * By default if secondary storage is provided 641 | * the session is stored in the secondary storage. 642 | * 643 | * Set this to true to store the session in the database 644 | * as well. 645 | * 646 | * Reads are always done from the secondary storage. 647 | * 648 | * @default false 649 | */ 650 | storeSessionInDatabase?: boolean; 651 | /** 652 | * By default, sessions are deleted from the database when secondary storage 653 | * is provided when session is revoked. 654 | * 655 | * Set this to true to preserve session records in the database, 656 | * even if they are deleted from the secondary storage. 657 | * 658 | * @default false 659 | */ 660 | preserveSessionInDatabase?: boolean; 661 | /** 662 | * Enable caching session in cookie 663 | */ 664 | cookieCache?: { 665 | /** 666 | * max age of the cookie 667 | * @default 5 minutes (5 * 60) 668 | */ 669 | maxAge?: number; 670 | /** 671 | * Enable caching session in cookie 672 | * @default false 673 | */ 674 | enabled?: boolean; 675 | }; 676 | /** 677 | * The age of the session to consider it fresh. 678 | * 679 | * This is used to check if the session is fresh 680 | * for sensitive operations. (e.g. deleting an account) 681 | * 682 | * If the session is not fresh, the user should be prompted 683 | * to sign in again. 684 | * 685 | * If set to 0, the session will be considered fresh every time. (⚠︎ not recommended) 686 | * 687 | * @default 1 day (60 * 60 * 24) 688 | */ 689 | freshAge?: number; 690 | }; 691 | account?: { 692 | /** 693 | * The model name for the account. Defaults to "account". 694 | */ 695 | modelName?: string; 696 | /** 697 | * Map fields 698 | */ 699 | fields?: Partial<Record<keyof OmitId<Account>, string>>; 700 | /** 701 | * Additional fields for the account 702 | */ 703 | additionalFields?: { 704 | [key: string]: DBFieldAttribute; 705 | }; 706 | /** 707 | * When enabled (true), the user account data (accessToken, idToken, refreshToken, etc.) 708 | * will be updated on sign in with the latest data from the provider. 709 | * 710 | * @default true 711 | */ 712 | updateAccountOnSignIn?: boolean; 713 | /** 714 | * Configuration for account linking. 715 | */ 716 | accountLinking?: { 717 | /** 718 | * Enable account linking 719 | * 720 | * @default true 721 | */ 722 | enabled?: boolean; 723 | /** 724 | * List of trusted providers 725 | */ 726 | trustedProviders?: Array< 727 | LiteralUnion<SocialProviderList[number] | "email-password", string> 728 | >; 729 | /** 730 | * If enabled (true), this will allow users to manually linking accounts with different email addresses than the main user. 731 | * 732 | * @default false 733 | * 734 | * ⚠️ Warning: enabling this might lead to account takeovers, so proceed with caution. 735 | */ 736 | allowDifferentEmails?: boolean; 737 | /** 738 | * If enabled (true), this will allow users to unlink all accounts. 739 | * 740 | * @default false 741 | */ 742 | allowUnlinkingAll?: boolean; 743 | /** 744 | * If enabled (true), this will update the user information based on the newly linked account 745 | * 746 | * @default false 747 | */ 748 | updateUserInfoOnLink?: boolean; 749 | }; 750 | /** 751 | * Encrypt OAuth tokens 752 | * 753 | * By default, OAuth tokens (access tokens, refresh tokens, ID tokens) are stored in plain text in the database. 754 | * This poses a security risk if your database is compromised, as attackers could gain access to user accounts 755 | * on external services. 756 | * 757 | * When enabled, tokens are encrypted using AES-256-GCM before storage, providing protection against: 758 | * - Database breaches and unauthorized access to raw token data 759 | * - Internal threats from database administrators or compromised credentials 760 | * - Token exposure in database backups and logs 761 | * @default false 762 | */ 763 | encryptOAuthTokens?: boolean; 764 | }; 765 | /** 766 | * Verification configuration 767 | */ 768 | verification?: { 769 | /** 770 | * Change the modelName of the verification table 771 | */ 772 | modelName?: string; 773 | /** 774 | * Map verification fields 775 | */ 776 | fields?: Partial<Record<keyof OmitId<Verification>, string>>; 777 | /** 778 | * disable cleaning up expired values when a verification value is 779 | * fetched 780 | */ 781 | disableCleanup?: boolean; 782 | }; 783 | /** 784 | * List of trusted origins. 785 | */ 786 | trustedOrigins?: 787 | | string[] 788 | | ((request: Request) => string[] | Promise<string[]>); 789 | /** 790 | * Rate limiting configuration 791 | */ 792 | rateLimit?: BetterAuthRateLimitOptions; 793 | /** 794 | * Advanced options 795 | */ 796 | advanced?: BetterAuthAdvancedOptions & { 797 | /** 798 | * @deprecated Please use `database.generateId` instead. 799 | */ 800 | generateId?: never; 801 | }; 802 | logger?: Logger; 803 | /** 804 | * allows you to define custom hooks that can be 805 | * executed during lifecycle of core database 806 | * operations. 807 | */ 808 | databaseHooks?: { 809 | /** 810 | * User hooks 811 | */ 812 | user?: { 813 | create?: { 814 | /** 815 | * Hook that is called before a user is created. 816 | * if the hook returns false, the user will not be created. 817 | * If the hook returns an object, it'll be used instead of the original data 818 | */ 819 | before?: ( 820 | user: User & Record<string, unknown>, 821 | context?: GenericEndpointContext, 822 | ) => Promise< 823 | | boolean 824 | | void 825 | | { 826 | data: Optional<User> & Record<string, any>; 827 | } 828 | >; 829 | /** 830 | * Hook that is called after a user is created. 831 | */ 832 | after?: ( 833 | user: User & Record<string, unknown>, 834 | context?: GenericEndpointContext, 835 | ) => Promise<void>; 836 | }; 837 | update?: { 838 | /** 839 | * Hook that is called before a user is updated. 840 | * if the hook returns false, the user will not be updated. 841 | * If the hook returns an object, it'll be used instead of the original data 842 | */ 843 | before?: ( 844 | user: Partial<User> & Record<string, unknown>, 845 | context?: GenericEndpointContext, 846 | ) => Promise< 847 | | boolean 848 | | void 849 | | { 850 | data: Optional<User & Record<string, any>>; 851 | } 852 | >; 853 | /** 854 | * Hook that is called after a user is updated. 855 | */ 856 | after?: ( 857 | user: User & Record<string, unknown>, 858 | context?: GenericEndpointContext, 859 | ) => Promise<void>; 860 | }; 861 | delete?: { 862 | /** 863 | * Hook that is called before a user is deleted. 864 | * if the hook returns false, the user will not be deleted. 865 | */ 866 | before?: ( 867 | user: User & Record<string, unknown>, 868 | context?: GenericEndpointContext, 869 | ) => Promise<boolean | void>; 870 | /** 871 | * Hook that is called after a user is deleted. 872 | */ 873 | after?: ( 874 | user: User & Record<string, unknown>, 875 | context?: GenericEndpointContext, 876 | ) => Promise<void>; 877 | }; 878 | }; 879 | /** 880 | * Session Hook 881 | */ 882 | session?: { 883 | create?: { 884 | /** 885 | * Hook that is called before a session is created. 886 | * if the hook returns false, the session will not be created. 887 | * If the hook returns an object, it'll be used instead of the original data 888 | */ 889 | before?: ( 890 | session: Session & Record<string, unknown>, 891 | context?: GenericEndpointContext, 892 | ) => Promise< 893 | | boolean 894 | | void 895 | | { 896 | data: Optional<Session> & Record<string, any>; 897 | } 898 | >; 899 | /** 900 | * Hook that is called after a session is created. 901 | */ 902 | after?: ( 903 | session: Session & Record<string, unknown>, 904 | context?: GenericEndpointContext, 905 | ) => Promise<void>; 906 | }; 907 | /** 908 | * Update hook 909 | */ 910 | update?: { 911 | /** 912 | * Hook that is called before a user is updated. 913 | * if the hook returns false, the session will not be updated. 914 | * If the hook returns an object, it'll be used instead of the original data 915 | */ 916 | before?: ( 917 | session: Partial<Session> & Record<string, unknown>, 918 | context?: GenericEndpointContext, 919 | ) => Promise< 920 | | boolean 921 | | void 922 | | { 923 | data: Optional<Session & Record<string, any>>; 924 | } 925 | >; 926 | /** 927 | * Hook that is called after a session is updated. 928 | */ 929 | after?: ( 930 | session: Session & Record<string, unknown>, 931 | context?: GenericEndpointContext, 932 | ) => Promise<void>; 933 | }; 934 | delete?: { 935 | /** 936 | * Hook that is called before a session is deleted. 937 | * if the hook returns false, the session will not be deleted. 938 | */ 939 | before?: ( 940 | session: Session & Record<string, unknown>, 941 | context?: GenericEndpointContext, 942 | ) => Promise<boolean | void>; 943 | /** 944 | * Hook that is called after a session is deleted. 945 | */ 946 | after?: ( 947 | session: Session & Record<string, unknown>, 948 | context?: GenericEndpointContext, 949 | ) => Promise<void>; 950 | }; 951 | }; 952 | /** 953 | * Account Hook 954 | */ 955 | account?: { 956 | create?: { 957 | /** 958 | * Hook that is called before a account is created. 959 | * If the hook returns false, the account will not be created. 960 | * If the hook returns an object, it'll be used instead of the original data 961 | */ 962 | before?: ( 963 | account: Account, 964 | context?: GenericEndpointContext, 965 | ) => Promise< 966 | | boolean 967 | | void 968 | | { 969 | data: Optional<Account> & Record<string, any>; 970 | } 971 | >; 972 | /** 973 | * Hook that is called after a account is created. 974 | */ 975 | after?: ( 976 | account: Account, 977 | context?: GenericEndpointContext, 978 | ) => Promise<void>; 979 | }; 980 | /** 981 | * Update hook 982 | */ 983 | update?: { 984 | /** 985 | * Hook that is called before a account is update. 986 | * If the hook returns false, the user will not be updated. 987 | * If the hook returns an object, it'll be used instead of the original data 988 | */ 989 | before?: ( 990 | account: Partial<Account> & Record<string, unknown>, 991 | context?: GenericEndpointContext, 992 | ) => Promise< 993 | | boolean 994 | | void 995 | | { 996 | data: Optional<Account & Record<string, any>>; 997 | } 998 | >; 999 | /** 1000 | * Hook that is called after a account is updated. 1001 | */ 1002 | after?: ( 1003 | account: Account & Record<string, unknown>, 1004 | context?: GenericEndpointContext, 1005 | ) => Promise<void>; 1006 | }; 1007 | delete?: { 1008 | /** 1009 | * Hook that is called before an account is deleted. 1010 | * if the hook returns false, the account will not be deleted. 1011 | */ 1012 | before?: ( 1013 | account: Account & Record<string, unknown>, 1014 | context?: GenericEndpointContext, 1015 | ) => Promise<boolean | void>; 1016 | /** 1017 | * Hook that is called after an account is deleted. 1018 | */ 1019 | after?: ( 1020 | account: Account & Record<string, unknown>, 1021 | context?: GenericEndpointContext, 1022 | ) => Promise<void>; 1023 | }; 1024 | }; 1025 | /** 1026 | * Verification Hook 1027 | */ 1028 | verification?: { 1029 | create?: { 1030 | /** 1031 | * Hook that is called before a verification is created. 1032 | * if the hook returns false, the verification will not be created. 1033 | * If the hook returns an object, it'll be used instead of the original data 1034 | */ 1035 | before?: ( 1036 | verification: Verification & Record<string, unknown>, 1037 | context?: GenericEndpointContext, 1038 | ) => Promise< 1039 | | boolean 1040 | | void 1041 | | { 1042 | data: Optional<Verification> & Record<string, any>; 1043 | } 1044 | >; 1045 | /** 1046 | * Hook that is called after a verification is created. 1047 | */ 1048 | after?: ( 1049 | verification: Verification & Record<string, unknown>, 1050 | context?: GenericEndpointContext, 1051 | ) => Promise<void>; 1052 | }; 1053 | update?: { 1054 | /** 1055 | * Hook that is called before a verification is updated. 1056 | * if the hook returns false, the verification will not be updated. 1057 | * If the hook returns an object, it'll be used instead of the original data 1058 | */ 1059 | before?: ( 1060 | verification: Partial<Verification> & Record<string, unknown>, 1061 | context?: GenericEndpointContext, 1062 | ) => Promise< 1063 | | boolean 1064 | | void 1065 | | { 1066 | data: Optional<Verification & Record<string, any>>; 1067 | } 1068 | >; 1069 | /** 1070 | * Hook that is called after a verification is updated. 1071 | */ 1072 | after?: ( 1073 | verification: Verification & Record<string, unknown>, 1074 | context?: GenericEndpointContext, 1075 | ) => Promise<void>; 1076 | }; 1077 | delete?: { 1078 | /** 1079 | * Hook that is called before a verification is deleted. 1080 | * if the hook returns false, the verification will not be deleted. 1081 | */ 1082 | before?: ( 1083 | verification: Verification & Record<string, unknown>, 1084 | context?: GenericEndpointContext, 1085 | ) => Promise<boolean | void>; 1086 | /** 1087 | * Hook that is called after a verification is deleted. 1088 | */ 1089 | after?: ( 1090 | verification: Verification & Record<string, unknown>, 1091 | context?: GenericEndpointContext, 1092 | ) => Promise<void>; 1093 | }; 1094 | }; 1095 | }; 1096 | /** 1097 | * API error handling 1098 | */ 1099 | onAPIError?: { 1100 | /** 1101 | * Throw an error on API error 1102 | * 1103 | * @default false 1104 | */ 1105 | throw?: boolean; 1106 | /** 1107 | * Custom error handler 1108 | * 1109 | * @param error 1110 | * @param ctx - Auth context 1111 | */ 1112 | onError?: (error: unknown, ctx: AuthContext) => void | Promise<void>; 1113 | /** 1114 | * The URL to redirect to on error 1115 | * 1116 | * When errorURL is provided, the error will be added to the URL as a query parameter 1117 | * and the user will be redirected to the errorURL. 1118 | * 1119 | * @default - "/api/auth/error" 1120 | */ 1121 | errorURL?: string; 1122 | }; 1123 | /** 1124 | * Hooks 1125 | */ 1126 | hooks?: { 1127 | /** 1128 | * Before a request is processed 1129 | */ 1130 | before?: AuthMiddleware; 1131 | /** 1132 | * After a request is processed 1133 | */ 1134 | after?: AuthMiddleware; 1135 | }; 1136 | /** 1137 | * Disabled paths 1138 | * 1139 | * Paths you want to disable. 1140 | */ 1141 | disabledPaths?: string[]; 1142 | /** 1143 | * Telemetry configuration 1144 | */ 1145 | telemetry?: { 1146 | /** 1147 | * Enable telemetry collection 1148 | * 1149 | * @default false 1150 | */ 1151 | enabled?: boolean; 1152 | /** 1153 | * Enable debug mode 1154 | * 1155 | * @default false 1156 | */ 1157 | debug?: boolean; 1158 | }; 1159 | }; 1160 | ```