创建你的第一个插件
在本指南中,我们将引导你完成创建第一个 Better Auth 插件的步骤。
【In this guide, we’ll walk you through the steps of creating your first Better Auth plugin.】
本指南假设你已经 完成了 Better Auth 的基本设置,并准备好创建你的第一个插件。
规划你的想法
【Plan your idea】
在开始之前,你必须知道你打算创建什么插件。
【Before beginning, you must know what plugin you intend to create.】
在本指南中,我们将创建一个生日插件来记录用户的出生日期。
服务器插件优先
【Server plugin first】
更好的身份验证插件是成对工作的:一个 服务器插件和一个 客户端插件。服务器插件构成了身份验证系统的基础,而客户端插件则提供方便的前端 API 来与服务器实现进行交互。
你可以在我们的 文档中了解更多关于服务器/客户端插件的信息。
创建服务器插件
【Creating the server plugin】
继续去找到一个合适的位置来创建你的生日插件文件夹,并在其中创建一个 index.ts 文件。
在 index.ts 文件中,我们将导出一个表示我们服务器插件的函数。这将是我们稍后在 auth.ts 文件中添加到插件列表中的内容。
import { createAuthClient } from "better-auth/client";
import type { BetterAuthPlugin } from "better-auth";
export const birthdayPlugin = () =>
({
id: "birthdayPlugin",
} satisfies BetterAuthPlugin);Although this does nothing, you have technically just made yourself your first plugin, congratulations! 🎉
定义模式
【Defining a schema】
为了保存每个用户的生日数据,我们必须在 user 模型之上创建一个模式。
【In order to save each user’s birthday data, we must create a schema on top of the user model.】
在此创建模式后,这也允许 Better Auth 的命令行工具生成更新数据库所需的模式。
你可以在这里了解更多关于 插件模式的信息。
//...
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)
},
},
},
},
} satisfies BetterAuthPlugin);授权逻辑
【Authorization logic】
在这个示例指南中,我们将设置身份验证逻辑,以检查并确保注册的用户年龄超过 5 岁。但相同的概念也可以应用于验证用户同意服务条款(TOS)或类似的事情。
【For this example guide, we’ll set up authentication logic to check and ensure that the user who signs-up is older than 5. But the same concept could be applied for something like verifying users agreeing to the TOS or anything alike.】
为此,我们将使用 Hooks,它允许我们在操作执行之前或之后运行代码。
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)在我们的例子中,我们希望匹配所有访问注册路径的请求:
【In our case we want to match any requests going to the signup path:】
{
matcher: (context) => context.path.startsWith("/sign-up/email"),
//...
}对于我们的逻辑,我们将编写以下代码来检查用户的生日是否使他们年龄超过 5 岁。
【And for our logic, we’ll write the following code to check the if user’s birthday makes them above 5 years old.】
import { APIError } from "better-auth/api";
import { createAuthMiddleware } from "better-auth/plugins";{
//...
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 岁以上用户的授权!
【We’ve now successfully written code to ensure authorization for users above 5!】
客户端插件
【Client Plugin】
我们快到终点了!🏁
【We’re close to the finish line! 🏁】
既然我们已经创建了服务器插件,下一步就是开发客户端插件。由于这个插件的前端 API 不多,所以没有太多事情要做!
【Now that we have created our server plugin, the next step is to develop our client plugin. Since there isn’t much frontend APIs going on for this plugin, there isn’t much to do!】
首先,让我们先创建我们的 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;
};What we’ve done is allow the client plugin to infer the types defined by our schema from the server plugin.
就这样!这就是生日客户插件所需的一切。🎂
【And that’s it! This is all it takes for the birthday client plugin. 🎂】
启动你的插件!
【Initiate your plugin!】
现在 client 和 server 插件都已准备就绪,最后一步是将它们分别导入到你的 auth-client.ts 和 server.ts 文件中,以初始化插件。
【Both the client and server plugins are now ready, the last step is to import them to both your auth-client.ts and your server.ts files respectively to initiate the plugin.】
服务器启动
【Server initiation】
import { betterAuth } from "better-auth";
import { birthdayPlugin } from "./birthday-plugin";
export const auth = betterAuth({
plugins: [
birthdayPlugin(),
]
});客户启动
【Client initiation】
import { createAuthClient } from "better-auth/client";
import { birthdayClientPlugin } from "./birthday-plugin/client";
const authClient = createAuthClient({
plugins: [
birthdayClientPlugin()
]
});哦,对,架构图!
【Oh yeah, the schemas!】
别忘了在你的 user 表模型中添加 birthday 字段!
【Don’t forget to add your birthday field to your user table model! 】
或者,使用 generate 命令行工具命令:
npx @better-auth/cli@latest generate总结
【Wrapping Up】
恭喜你!你已经成功创建了你的第一个 Better Auth 插件。我们强烈建议你访问我们的 插件文档以了解更多信息。
如果你有想与社区分享的插件,请随时通过我们的 Discord 服务器告诉我们,或者通过 拉取请求,我们可能会将其添加到 社区插件列表中!