Convex 集成

本文档来自 Convex 文档, 有关更多信息,请参阅其文档。

先决条件

创建 Convex 项目

要使用 Convex + Better Auth,您首先需要一个 Convex 项目。 如果您还没有,可以运行以下命令开始。

npm create convex@latest

请参阅 Convex 文档 以了解更多关于 Convex 的信息。

运行 convex dev

在设置过程中运行 CLI 将初始化您的 Convex 部署 (如果尚未存在),并在整个过程中保持生成的类型当前。保持其运行。

npx convex dev

Convex + Better Auth 的安装

以下文档假设您正在使用 Next.js。

如果您不使用 Next.js,请参阅 Convex 的安装指南

有关完整示例,请查看此 Github 仓库 中的 Next.js 的 Convex + Better Auth 示例。

安装

安装包

安装组件、Better Auth 的固定版本,并确保 Convex 的最新版本。

此组件需要 Convex 1.25.0 或更高版本。

npm install better-auth@1.3.8 --save-exact
npm install convex@latest @convex-dev/better-auth

注册组件

在您的 Convex 项目中注册 Better Auth 组件。

convex/convex.config.ts
import { defineApp } from "convex/server";
import betterAuth from "@convex-dev/better-auth/convex.config";

const app = defineApp();
app.use(betterAuth);

export default app;

添加 Convex 身份验证配置

添加一个 convex/auth.config.ts 文件,以将 Better Auth 配置为身份验证提供程序。

convex/auth.config.ts
export default {
    providers: [
        {
            domain: process.env.CONVEX_SITE_URL,
            applicationID: "convex",
        },
    ],
};

设置环境变量

生成一个用于加密和生成哈希的密钥。如果您安装了 openssl, 请使用以下命令,或者使用按钮生成随机值。或者以您喜欢的方式生成自己的密钥。

npx convex env set BETTER_AUTH_SECRET=$(openssl rand -base64 32)

将您的站点 URL 添加到您的 Convex 部署中。

npx convex env set SITE_URL http://localhost:3000

将环境变量添加到由 npx convex dev 创建的 .env.local 文件中。 它将被您的框架开发服务器拾取。

.env.local
# Deployment used by \`npx convex dev\`
CONVEX_DEPLOYMENT=dev:adjective-animal-123 # team: team-name, project: project-name

NEXT_PUBLIC_CONVEX_URL=https://adjective-animal-123.convex.cloud

# Same as NEXT_PUBLIC_CONVEX_URL but ends in .site
NEXT_PUBLIC_CONVEX_SITE_URL=https://adjective-animal-123.convex.site

# Your local site URL
SITE_URL=http://localhost:3000

创建 Better Auth 实例

创建一个 Better Auth 实例并初始化组件。

在您保存文件之前,会显示一些 TypeScript 错误。
convex/auth.ts
import { createClient, type GenericCtx } from "@convex-dev/better-auth";
import { convex } from "@convex-dev/better-auth/plugins";
import { components } from "./_generated/api";
import { DataModel } from "./_generated/dataModel";
import { query } from "./_generated/server";
import { betterAuth } from "better-auth";

const siteUrl = process.env.SITE_URL!;

// 组件客户端具有将 Convex 与 Better Auth 集成所需的方法,
// 以及通用使用的辅助方法。
export const authComponent = createClient<DataModel>(components.betterAuth);

export const createAuth = (
    ctx: GenericCtx<DataModel>,
        { optionsOnly } = { optionsOnly: false },
    ) => {
      return betterAuth({
        // 在仅生成选项时调用 createAuth 时禁用日志记录。
        // 这不是必需的,但没有它日志中会有很多噪音。
        logger: {
            disabled: optionsOnly,
        },
        baseURL: siteUrl,
        database: authComponent.adapter(ctx),
        // 配置简单的、非验证的电子邮件/密码以开始使用
        emailAndPassword: {
            enabled: true,
            requireEmailVerification: false,
        },
        plugins: [
            // Convex 插件是 Convex 兼容性所需的
            convex(),
        ],
    });
};

// 示例函数,用于获取当前用户
// 可以随意编辑、省略等。
export const getCurrentUser = query({
    args: {},
    handler: async (ctx) => {
        return authComponent.getAuthUser(ctx);
    },
});

创建 Better Auth 客户端实例

创建一个 Better Auth 客户端实例,用于从客户端与 Better Auth 服务器交互。

src/lib/auth-client.ts
import { createAuthClient } from "better-auth/react";
import { convexClient } from "@convex-dev/better-auth/client/plugins";

export const authClient = createAuthClient({
    plugins: [convexClient()],
});

挂载处理程序

在您的 Convex 部署上注册 Better Auth 路由处理程序。

convex/http.ts
import { httpRouter } from "convex/server";
import { authComponent, createAuth } from "./auth";

const http = httpRouter();

authComponent.registerRoutes(http, createAuth);

export default http;

设置路由处理程序,以将来自框架服务器的身份验证请求代理到您的 Convex 部署。

app/api/auth/[...all]/route.ts
import { nextJsHandler } from "@convex-dev/better-auth/nextjs";

export const { GET, POST } = nextJsHandler();

设置 Convex 客户端提供程序

使用 ConvexBetterAuthProvider 组件包装您的应用。

app/ConvexClientProvider.tsx
"use client";

import { ReactNode } from "react";
import { ConvexReactClient } from "convex/react";
import { authClient } from "@/lib/auth-client"; 
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react"; 

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!, {
  // 可选:在用户经过身份验证之前暂停查询
  expectAuth: true, 
});

export function ConvexClientProvider({ children }: { children: ReactNode }) {
  return (
    <ConvexBetterAuthProvider client={convex} authClient={authClient}>
      {children}
    </ConvexBetterAuthProvider>
  );
}

完成!

您现在已准备好开始使用 Convex 的 Better Auth。

使用

从服务器使用 Better Auth

要在服务器渲染、 服务器函数或任何其他 Next.js 服务器代码中使用 Better Auth 的 服务器 方法,请使用 Convex 函数 并从您的服务器代码调用该函数。

首先,一个用于从服务器代码调用 Convex 函数的令牌助手。

src/lib/auth-server.ts
import { createAuth } from "convex/auth";
import { getToken as getTokenNextjs } from "@convex-dev/better-auth/nextjs";

export const getToken = () => {
  return getTokenNextjs(createAuth);
};

这是一个使用 Better Auth 服务器方法的示例 Convex 函数,以及 调用 Convex 函数的服务器操作。

convex/users.ts
import { mutation } from "./_generated/server";
import { v } from "convex/values";
import { createAuth, authComponent } from "./auth";

export const updateUserPassword = mutation({
  args: {
    currentPassword: v.string(),
    newPassword: v.string(),
  },
  handler: async (ctx, args) => {
    await createAuth(ctx).api.changePassword({
      body: {
        currentPassword: args.currentPassword,
        newPassword: args.newPassword,
      },
      headers: await authComponent.getHeaders(ctx),
    });
  },
});
app/actions.ts
"use server";

import { fetchMutation } from "convex/nextjs";
import { api } from "../convex/_generated/api";
import { getToken } from "../lib/auth-server";

// 通过服务器函数的已身份验证的 mutation
export async function updatePassword({
  currentPassword,
  newPassword,
}: {
  currentPassword: string;
  newPassword: string;
}) {
  const token = await getToken();
  await fetchMutation(
    api.users.updatePassword,
    { currentPassword, newPassword },
    { token }
  );
}

本文档来自 Convex 文档, 有关更多信息,请参阅其文档。