创建你的第一个插件

在本文中,我们将引导你创建你的第一个 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, // 如果该字段在新记录上是必需的。(默认值:false)
            unique: false, // 如果该字段应该是唯一的。(默认值:false)
            reference: null // 如果该字段是对另一个表的引用。(默认值:null)
          },
        },
      },
    },
  } satisfies BetterAuthPlugin);

授权逻辑

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

为此,我们将利用 钩子(Hooks),它允许我们在执行动作 之前之后 运行代码。

index.ts
export const birthdayPlugin = () => ({
    //...
    // In our case, we want to write authorization logic,
    // meaning we want to intercept it `before` hand.
    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"; // 确保将服务器插件作为类型导入
 
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