Create your first plugin

在本指南中,我们将引导您完成创建第一个 Better Auth 插件的步骤。

本指南假设您已 设置 Better Auth 的基础,并准备好创建您的第一个插件。

规划您的想法

在开始之前,您必须知道打算创建什么插件。

在本指南中,我们将创建一个 生日插件 来跟踪用户的出生日期。

先创建服务器插件

Better Auth 插件以一对形式运行:一个 服务器插件 和一个 客户端插件。 服务器插件构成了您的认证系统的基础,而客户端插件提供了方便的前端 API 来与您的服务器实现交互。

您可以在我们的 文档 中阅读更多关于服务器/客户端插件的信息。

创建服务器插件

继续找到合适的位置来创建您的生日插件文件夹,并在其中创建一个 index.ts 文件。

index.ts

index.ts 文件中,我们将导出一个代表服务器插件的函数。 这将是稍后添加到 auth.ts 文件中插件列表的内容。

index.ts
import { createAuthClient } from "better-auth/client";
import type { BetterAuthPlugin } from "better-auth";

export const birthdayPlugin = () =>
  ({
    id: "birthdayPlugin",
  } satisfies BetterAuthPlugin);

虽然这什么都不做,但您技术上已经创建了您的第一个插件,恭喜!🎉

定义模式

为了保存每个用户的生日数据,我们必须在 user 模型之上创建一个模式。

通过在这里创建模式,这还允许 Better Auth 的 CLI 生成更新数据库所需的模式。

您可以在 此处 了解更多关于插件模式的信息。

index.ts
//...
export const birthdayPlugin = () =>
  ({
    id: "birthdayPlugin",
    schema: {
      user: {
        fields: {
          birthday: {
            type: "date", // string, number, boolean, date
            required: true, // if the field should be required on a new record. (default: false)
            unique: false, // if the field should be unique. (default: false)
            references: null // if the field is a reference to another table. (default: null)
          },
        },
      },
    },
  } satisfies BetterAuthPlugin);

授权逻辑

对于本示例指南,我们将设置认证逻辑来检查并确保注册的用户年龄超过 5 岁。 但同样的概念可以应用于验证用户同意服务条款或其他类似情况。

为此,我们将利用 钩子,它允许我们在执行操作的 beforeafter 运行代码。

index.ts
export const birthdayPlugin = () => ({
    //...
    // 在我们的情况下,我们想要编写授权逻辑,
    // 这意味着我们想要在之前拦截它。
    hooks: {
      before: [
        {
          matcher: (context) => /* ... */,
          handler: createAuthMiddleware(async (ctx) => {
            //...
          }),
        },
      ],
    },
} satisfies BetterAuthPlugin)

在我们的情况下,我们想要匹配任何发送到注册路径的请求:

Before hook
{
  matcher: (context) => context.path.startsWith("/sign-up/email"),
  //...
}

对于我们的逻辑,我们将编写以下代码来检查用户的生日是否使他们超过 5 岁。

Imports
import { APIError } from "better-auth/api";
import { createAuthMiddleware } from "better-auth/plugins";
Before hook
{
  //...
  handler: createAuthMiddleware(async (ctx) => {
    const { birthday } = ctx.body;
    if(!(birthday instanceof Date)) {
      throw new APIError("BAD_REQUEST", { message: "Birthday must be of type Date." });
    }

    const today = new Date();
    const fiveYearsAgo = new Date(today.setFullYear(today.getFullYear() - 5));

    if(birthday >= fiveYearsAgo) {
      throw new APIError("BAD_REQUEST", { message: "User must be above 5 years old." });
    }

    return { context: ctx };
  }),
}

已授权! 🔒

我们现在已经成功编写了确保超过 5 岁用户的授权代码!

客户端插件

我们离终点线很近了!🏁

现在我们已经创建了服务器插件,下一步是开发客户端插件。 由于这个插件没有太多前端 API,所以没有太多事情要做!

首先,让我们先创建 client.ts 文件:

index.ts
client.ts

然后,添加以下代码:

client.ts
import { BetterAuthClientPlugin } from "better-auth";
import type { birthdayPlugin } from "./index"; // make sure to import the server plugin as a type

type BirthdayPlugin = typeof birthdayPlugin;

export const birthdayClientPlugin = () => {
  return {
    id: "birthdayPlugin",
    $InferServerPlugin: {} as ReturnType<BirthdayPlugin>,
  } satisfies BetterAuthClientPlugin;
};

我们所做的就是允许客户端插件从服务器插件推断由我们的模式定义的类型。

就是这样!这就是生日客户端插件所需的一切。🎂

初始化您的插件!

客户端和服务器插件现在都已准备就绪,最后一步是将它们分别导入到您的 auth-client.tsserver.ts 文件中以初始化插件。

服务器初始化

server.ts
import { betterAuth } from "better-auth";
import { birthdayPlugin } from "./birthday-plugin";
 
export const auth = betterAuth({
    plugins: [
      birthdayPlugin(),
    ]
});

客户端初始化

auth-client.ts
import { createAuthClient } from "better-auth/client";
import { birthdayClientPlugin } from "./birthday-plugin/client";
 
const authClient = createAuthClient({
    plugins: [
      birthdayClientPlugin()
    ]
});

哦,对了,模式!

不要忘记将您的 birthday 字段添加到 user 表模型中!

或者,使用 generate CLI 命令

npx @better-auth/cli@latest generate

总结

恭喜!您已经成功创建了第一个 Better Auth 插件。 我们强烈推荐您访问我们的 插件文档 以获取更多信息。

如果您有一个想与社区分享的插件,请随时通过 我们的 Discord 服务器 或通过 拉取请求 告知我们,我们可能会将其添加到 社区插件 列表中!

On this page