数据库
适配器
【Adapters】
Better Auth 连接到数据库以存储数据。该数据库将用于存储诸如用户、会话等数据。插件还可以定义自己的数据库表来存储数据。
【Better Auth connects to a database to store data. The database will be used to store data such as users, sessions, and more. Plugins can also define their own database tables to store data.】
你可以通过在数据库选项中传入支持的数据库实例,将数据库连接传递给 Better Auth。你可以在其他关系型数据库文档中了解更多关于支持的数据库适配器的信息。
【You can pass a database connection to Better Auth by passing a supported database instance in the database options. You can learn more about supported database adapters in the Other relational databases documentation.】
Better Auth 也可以在没有任何数据库的情况下工作。更多详情,请参见 无状态会话管理。
命令行接口
【CLI】
Better Auth 附带一个 CLI 工具,用于管理数据库迁移和生成模式。
【Better Auth comes with a CLI tool to manage database migrations and generate schema.】
运行迁移
【Running Migrations】
CLI 会检查你的数据库,并提示你添加缺失的表或使用新列更新现有表。这仅支持内置的 Kysely 适配器。对于其他适配器,你可以使用 generate 命令来创建模式,并通过你的 ORM 处理迁移。
【The cli checks your database and prompts you to add missing tables or update existing ones with new columns. This is only supported for the built-in Kysely adapter. For other adapters, you can use the generate command to create the schema and handle the migration through your ORM.】
npx @better-auth/cli migrate针对 PostgreSQL 用户:migrate 命令支持非默认 schema。它会自动检测你的 search_path 配置,并在正确的 schema 中创建表。详情请参见 PostgreSQL 适配器。
生成模式
【Generating Schema】
Better Auth 还提供了一个 generate 命令,用于生成 Better Auth 所需的架构。generate 命令会创建 Better Auth 所需的架构。如果你使用的是像 Prisma 或 Drizzle 这样的数据库适配器,该命令将为你的 ORM 生成正确的架构。如果你使用的是内置的 Kysely 适配器,它将生成一个可以直接在数据库上运行的 SQL 文件。
【Better Auth also provides a generate command to generate the schema required by Better Auth. The generate command creates the schema required by Better Auth. If you're using a database adapter like Prisma or Drizzle, this command will generate the right schema for your ORM. If you're using the built-in Kysely adapter, it will generate an SQL file you can run directly on your database.】
npx @better-auth/cli generate有关 CLI 的更多信息,请参阅 CLI 文档。
【See the CLI documentation for more information on the CLI.】
如果你更喜欢手动添加表格,也可以这样做。Better Auth 所需的核心架构如下所述,你可以在插件文档中找到插件所需的其他架构。
编程迁移
【Programmatic Migrations】
在某些环境中(例如 Cloudflare Workers、无服务器函数或自定义部署设置),运行 CLI 可能不可行或不方便。在这些情况下,你可以在应用代码中以编程方式运行迁移。
【In some environments (like Cloudflare Workers, serverless functions, or custom deployment setups), running the CLI may not be possible or practical. In these cases, you can run migrations programmatically from within your application code.】
Better Auth 提供了一个 getMigrations 函数,你可以使用它以编程方式生成和运行迁移。这在以下情况下尤其有用:
【Better Auth provides a getMigrations function that you can use to generate and run migrations programmatically. This is particularly useful when:】
- 你正在部署到边缘环境(Cloudflare Workers、Deno Deploy 等)
- 你的环境变量仅在运行时可用(构建时不可用)
- 你需要在应用启动时或通过自定义端点运行迁移
使用 getMigrations
【Using getMigrations】
getMigrations 函数可以从 better-auth/db 获取,并且兼容内置的 Kysely 适配器(SQLite、PostgreSQL、MySQL、MSSQL)。
【The getMigrations function is available from better-auth/db and works with the built-in Kysely adapter (SQLite, PostgreSQL, MySQL, MSSQL).】
import { getMigrations } from "better-auth/db";
const { toBeCreated, toBeAdded, runMigrations, compileMigrations } = await getMigrations(authConfig);
// Check what migrations are needed
console.log("Tables to create:", toBeCreated);
console.log("Fields to add:", toBeAdded);
// Run migrations
await runMigrations();
// Or get the SQL to run manually
const sql = await compileMigrations();
console.log(sql);示例:Cloudflare Workers 迁移端点
【Example: Cloudflare Workers Migration Endpoint】
对于使用 D1(SQLite)的 Cloudflare Workers,你可以创建一个迁移端点,该端点会在 Worker 启动时运行,或者通过手动触发运行:
【For Cloudflare Workers using D1 (SQLite), you can create a migration endpoint that runs when your worker starts or through a manual trigger:】
import { Hono } from "hono";
import { auth } from "./auth"; // your auth instance
import { getMigrations } from "better-auth/db";
const app = new Hono<{ Bindings: Env }>();
// Migration endpoint - call this once to set up your database
app.post("/migrate", async (c) => {
const env = c.env;
// Create auth config with runtime environment
const authConfig = {
database: env.DB, // D1 database binding
// ... rest of your auth config
};
try {
const { toBeCreated, toBeAdded, runMigrations } = await getMigrations(authConfig);
if (toBeCreated.length === 0 && toBeAdded.length === 0) {
return c.json({ message: "No migrations needed" });
}
await runMigrations();
return c.json({
message: "Migrations completed successfully",
created: toBeCreated.map(t => t.table),
added: toBeAdded.map(t => t.table)
});
} catch (error) {
return c.json({ error: error instanceof Error ? error.message : String(error) }, 500);
}
});
// Your normal auth endpoints
app.on(["POST", "GET"], "/api/auth/*", (c) => {
return auth.handler(c.req.raw);
});
export default app;重要限制
编程迁移目前仅适用于:
- 使用 Kysely 适配器的内置数据库适配器(SQLite/D1、PostgreSQL、MySQL、MSSQL)
- 不适用于 Prisma 或 Drizzle ORM 适配器
【Programmatic migrations currently work only with:
- Built-in database adapters (SQLite/D1, PostgreSQL, MySQL, MSSQL) using the Kysely adapter
- Does not work with Prisma or Drizzle ORM adapters】
关于在 Cloudflare Workers 中使用 Prisma 或 Drizzle,请参阅下面的 Cloudflare Workers 部分。
使用 Prisma/Drizzle 的 Cloudflare Workers
【Cloudflare Workers with Prisma/Drizzle】
如果你在 Cloudflare Workers 中使用 Prisma 或 Drizzle,你有几种选择:
【If you're using Prisma or Drizzle with Cloudflare Workers, you have a few options:】
-
使用
cloudflare:workers导入(推荐用于较新的 Cloudflare 项目):Cloudflare 现在支持从
cloudflare:workers导入环境变量,这使你可以在顶层访问env:auth.ts import { env } from "cloudflare:workers"; import { drizzle } from "drizzle-orm/d1"; export const auth = betterAuth({ database: drizzle(env.DB), // ... rest of config });通过这种方法,你可以运行标准的 CLI 命令:
npx @better-auth/cli migrate # or npx @better-auth/cli generate -
使用带兼容性标志的
process.env:在你的
wrangler.toml中添加nodejs_compat_populate_process_env兼容性标志:wrangler.toml compatibility_flags = ["nodejs_compat_populate_process_env"]然后在你的认证配置中使用
process.env:auth.ts import { drizzle } from "drizzle-orm/d1"; export const auth = betterAuth({ database: drizzle(process.env.DB as any), // ... rest of config });设置完成后,按常规运行 CLI 命令:
npx @better-auth/cli generate -
本地生成模式并手动推送:
在本地使用模拟配置运行生成命令,然后使用你的 ORM 的 push/migrate 命令来应用架构。
请参阅 Hono 集成文档 查看在 Cloudflare Workers 中使用 Better Auth 的完整示例。
二级存储
【Secondary Storage】
Better Auth 中的二级存储允许你使用键值存储来管理会话数据、速率限制计数器等。当你希望将这些高密集记录的存储卸载到高性能存储甚至 RAM 时,这会非常有用。
【Secondary storage in Better Auth allows you to use key-value stores for managing session data, rate limiting counters, etc. This can be useful when you want to offload the storage of this intensive records to a high performance storage or even RAM.】
实现
【Implementation】
要使用二级存储,请实现 SecondaryStorage 接口:
【To use secondary storage, implement the SecondaryStorage interface:】
interface SecondaryStorage {
get: (key: string) => Promise<unknown>;
set: (key: string, value: string, ttl?: number) => Promise<void>;
delete: (key: string) => Promise<void>;
}然后,将你的实现提供给 betterAuth 函数:
【Then, provide your implementation to the betterAuth function:】
betterAuth({
// ... other options
secondaryStorage: {
// Your implementation here
},
});示例:Redis 实现
这是一个使用 Redis 的基本示例:
【Here's a basic example using Redis:】
import { createClient } from "redis";
import { betterAuth } from "better-auth";
const redis = createClient();
await redis.connect();
export const auth = betterAuth({
// ... other options
secondaryStorage: {
get: async (key) => {
return await redis.get(key);
},
set: async (key, value, ttl) => {
if (ttl) await redis.set(key, value, { EX: ttl });
// or for ioredis:
// if (ttl) await redis.set(key, value, 'EX', ttl)
else await redis.set(key, value);
},
delete: async (key) => {
await redis.del(key);
}
}
});此实现允许 Better Auth 使用 Redis 存储会话数据和速率限制计数器。你也可以为键名添加前缀。
【This implementation allows Better Auth to use Redis for storing session data and rate limiting counters. You can also add prefixes to the keys names.】
核心架构
【Core Schema】
Better Auth 需要数据库中存在以下表。类型以 typescript 格式表示。你可以在数据库中使用相应的类型。
【Better Auth requires the following tables to be present in the database. The types are in typescript format. You can use corresponding types in your database.】
用户
【User】
表名:user
【Table Name: user】
| Field Name | Type | Key | Description |
|---|---|---|---|
| id | string | Unique identifier for each user | |
| name | string | - | User's chosen display name |
| string | - | User's email address for communication and login | |
| emailVerified | boolean | - | Whether the user's email is verified |
| image | string | User's image url | |
| createdAt | Date | - | Timestamp of when the user account was created |
| updatedAt | Date | - | Timestamp of the last update to the user's information |
会话
【Session】
表名:session
【Table Name: session】
| Field Name | Type | Key | Description |
|---|---|---|---|
| id | string | Unique identifier for each session | |
| userId | string | The ID of the user | |
| token | string | - | The unique session token |
| expiresAt | Date | - | The time when the session expires |
| ipAddress | string | The IP address of the device | |
| userAgent | string | The user agent information of the device | |
| createdAt | Date | - | Timestamp of when the session was created |
| updatedAt | Date | - | Timestamp of when the session was updated |
账户
【Account】
表名:account
【Table Name: account】
| Field Name | Type | Key | Description |
|---|---|---|---|
| id | string | Unique identifier for each account | |
| userId | string | The ID of the user | |
| accountId | string | - | The ID of the account as provided by the SSO or equal to userId for credential accounts |
| providerId | string | - | The ID of the provider |
| accessToken | string | The access token of the account. Returned by the provider | |
| refreshToken | string | The refresh token of the account. Returned by the provider | |
| accessTokenExpiresAt | Date | The time when the access token expires | |
| refreshTokenExpiresAt | Date | The time when the refresh token expires | |
| scope | string | The scope of the account. Returned by the provider | |
| idToken | string | The ID token returned from the provider | |
| password | string | The password of the account. Mainly used for email and password authentication | |
| createdAt | Date | - | Timestamp of when the account was created |
| updatedAt | Date | - | Timestamp of when the account was updated |
验证
【Verification】
表名:verification
【Table Name: verification】
| Field Name | Type | Key | Description |
|---|---|---|---|
| id | string | Unique identifier for each verification | |
| identifier | string | - | The identifier for the verification request |
| value | string | - | The value to be verified |
| expiresAt | Date | - | The time when the verification request expires |
| createdAt | Date | - | Timestamp of when the verification request was created |
| updatedAt | Date | - | Timestamp of when the verification request was updated |
自定义表格
【Custom Tables】
Better Auth 允许你自定义核心架构的表名和列名。你还可以通过向用户表和会话表添加额外字段来扩展核心架构。
【Better Auth allows you to customize the table names and column names for the core schema. You can also extend the core schema by adding additional fields to the user and session tables.】
自定义表名
【Custom Table Names】
你可以通过在身份验证配置中使用 modelName 和 fields 属性来定制核心模式的表名和列名:
【You can customize the table names and column names for the core schema by using the modelName and fields properties in your auth config:】
export const auth = betterAuth({
user: {
modelName: "users",
fields: {
name: "full_name",
email: "email_address",
},
},
session: {
modelName: "user_sessions",
fields: {
userId: "user_id",
},
},
});你代码中的类型推断仍将使用原始字段名(例如,user.name,而不是 user.full_name)。
要自定义插件的表名和列名,你可以在插件配置中使用 schema 属性:
【To customize table names and column name for plugins, you can use the schema property in the plugin config:】
import { betterAuth } from "better-auth";
import { twoFactor } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
twoFactor({
schema: {
user: {
fields: {
twoFactorEnabled: "two_factor_enabled",
secret: "two_factor_secret",
},
},
},
}),
],
});扩展核心模式
【Extending Core Schema】
Better Auth 提供了一种类型安全的方式来扩展 user 和 session 模式。你可以在身份验证配置中添加自定义字段,CLI 将自动更新数据库模式。这些额外字段将在 useSession、signUp.email 以及其他处理用户或会话对象的端点中被正确推断。
【Better Auth provides a type-safe way to extend the user and session schemas. You can add custom fields to your auth config, and the CLI will automatically update the database schema. These additional fields will be properly inferred in functions like useSession, signUp.email, and other endpoints that work with user or session objects.】
要添加自定义字段,请在身份验证配置的 user 或 session 对象中使用 additionalFields 属性。additionalFields 对象使用字段名称作为键,每个值是一个包含以下内容的 FieldAttributes 对象:
【To add custom fields, use the additionalFields property in the user or session object of your auth config. The additionalFields object uses field names as keys, with each value being a FieldAttributes object containing:】
type:字段的数据类型(例如,“string”、“number”、“boolean”)。required:一个布尔值,表示该字段是否为必填项。defaultValue:字段的默认值(注意:这仅适用于 JavaScript 层;在数据库中,该字段将是可选的)。input:这决定了在创建新记录时是否可以提供一个值(默认值:true)。如果还有其他字段,例如role,在注册时不应由用户提供,则可以将其设置为false。
下面是一个如何在用户模式中添加额外字段的示例:
【Here's an example of how to extend the user schema with additional fields:】
import { betterAuth } from "better-auth";
export const auth = betterAuth({
user: {
additionalFields: {
role: {
type: ["user", "admin"],
required: false,
defaultValue: "user",
input: false, // don't allow user to set role
},
lang: {
type: "string",
required: false,
defaultValue: "en",
},
},
},
});现在你可以在应用逻辑中访问附加字段。
【Now you can access the additional fields in your application logic.】
//on signup
const res = await auth.api.signUpEmail({
email: "test@example.com",
password: "password",
name: "John Doe",
lang: "fr",
});
//user object
res.user.role; // > "admin"
res.user.lang; // > "fr"有关如何在客户端推断额外字段的更多信息,请参阅 TypeScript文档。
如果你正在使用社交/OAuth 提供商,你可能需要提供 mapProfileToUser 来将个人资料数据映射到用户对象。这样,你就可以从提供商的个人资料中填充其他字段。
【If you're using social / OAuth providers, you may want to provide mapProfileToUser to map the profile data to the user object. So, you can populate additional fields from the provider's profile.】
示例:将配置文件映射到用户的 firstName 和 lastName
import { betterAuth } from "better-auth";
export const auth = betterAuth({
socialProviders: {
github: {
clientId: "YOUR_GITHUB_CLIENT_ID",
clientSecret: "YOUR_GITHUB_CLIENT_SECRET",
mapProfileToUser: (profile) => {
return {
firstName: profile.name.split(" ")[0],
lastName: profile.name.split(" ")[1],
};
},
},
google: {
clientId: "YOUR_GOOGLE_CLIENT_ID",
clientSecret: "YOUR_GOOGLE_CLIENT_SECRET",
mapProfileToUser: (profile) => {
return {
firstName: profile.given_name,
lastName: profile.family_name,
};
},
},
},
});ID 生成
【ID Generation】
Better Auth 默认会为用户、会话和其他实体生成唯一的 ID。你可以使用 advanced.database.generateId 选项自定义 ID 生成行为。
【Better Auth by default will generate unique IDs for users, sessions, and other entities.
You can customize ID generation behavior using the advanced.database.generateId option.】
选项 1:让数据库生成 ID
【Option 1: Let Database Generate IDs】
将 generateId 设置为 false 允许数据库处理所有 ID 的生成:(除了 generateId 为 serial 的情况以及某些 generateId 为 uuid 的情况)
【Setting generateId to false allows your database handle all ID generation: (outside of generateId being serial and some cases of generateId being uuid)】
import { betterAuth } from "better-auth";
import { db } from "./db";
export const auth = betterAuth({
database: db,
advanced: {
database: {
generateId: false, // "serial" for auto-incrementing numeric IDs
},
},
});选项 2:自定义 ID 生成函数
【Option 2: Custom ID Generation Function】
使用函数来生成 ID。你可以从函数中返回 false 或 undefined,让数据库为特定模型生成 ID:
【Use a function to generate IDs. You can return false or undefined from the function to let the database generate the ID for specific models:】
import { betterAuth } from "better-auth";
import { db } from "./db";
export const auth = betterAuth({
database: db,
advanced: {
database: {
generateId: (options) => {
// Let database auto-generate for specific models
if (options.model === "user" || options.model === "users") {
return false; // Let database generate ID
}
// Generate UUIDs for other tables
return crypto.randomUUID();
},
},
},
});重要:从 generateId 函数返回 false 或 undefined 可以让数据库为该特定模型处理 ID 生成。将 generateId: false(不带函数)设置为 false 会禁用 所有 表的 ID 生成。
选项 3:一致的自定义 ID 生成器
【Option 3: Consistent Custom ID Generator】
为所有表生成相同类型的 ID:
【Generate the same type of ID for all tables:】
import { betterAuth } from "better-auth";
import { db } from "./db";
export const auth = betterAuth({
database: db,
advanced: {
database: {
generateId: () => crypto.randomUUID(),
},
},
});数字 ID
【Numeric IDs】
如果你更喜欢自动递增的数字 ID,可以将 advanced.database.generateId 选项设置为 "serial"。这样做会禁用 Better-Auth 为任何表生成 ID,并假设你的数据库会自动生成数字 ID。
【If you prefer auto-incrementing numeric IDs, you can set the advanced.database.generateId option to "serial".
Doing this will disable Better-Auth from generating IDs for any table, and will assume your
database will generate the numeric ID automatically.】
启用后,Better-Auth CLI 将为你的数据库生成或迁移带有 id 字段的架构,该字段为数值类型,并具有自动递增的属性。
【When enabled, the Better-Auth CLI will generate or migrate the schema with the id field as a numeric type for your database
with auto-incrementing attributes associated with it.】
import { betterAuth } from "better-auth";
import { db } from "./db";
export const auth = betterAuth({
database: db,
advanced: {
database: {
generateId: "serial",
},
},
});Better-Auth 将继续将数据库中 id 字段的类型推断为 string,但在从数据库获取或插入数据时会自动将其转换为数值类型。
当从 Better-Auth 获取 id 值时,很可能你会收到数字的字符串版本,这是正常的。同样,传递给 Better-Auth 的所有 id 值(例如通过端点的请求体)也预计是字符串。
UUID
【UUIDs】
如果你更喜欢在 id 字段使用 UUID,可以将 advanced.database.generateId 选项设置为 "uuid"。
默认情况下,Better-Auth 会为所有表的 id 字段生成 UUID,但对于使用 PostgreSQL 的适配器,我们允许数据库自动生成 UUID。
【If you prefer UUIDs for the id field, you can set the advanced.database.generateId option to "uuid".
By default, Better-Auth will generate UUIDs for the id field for all tables, except adapters that use PostgreSQL where we allow the
database to generate the UUID automatically.】
启用此选项后,Better-Auth CLI 将为你的数据库生成或迁移带有 id 字段为 UUID 类型的模式。如果不支持 uuid 类型,我们将为 id 字段生成普通的 string 类型。
【By enabling this option, the Better-Auth CLI will generate or migrate the schema with the id field as a UUID type for your database.
If the uuid type is not supported, we will generate a normal string type for the id field.】
混合 ID 类型
【Mixed ID Types】
如果你需要在不同的表中使用不同类型的 ID(例如,用户使用整数 ID,会话/账户/验证使用 UUID 字符串),请使用 generateId 回调函数。
【If you need different ID types across tables (e.g., integer IDs for users, UUID strings for sessions/accounts/verification), use a generateId callback function.】
import { betterAuth } from "better-auth";
import { db } from "./db";
export const auth = betterAuth({
database: db,
user: {
modelName: "users", // PostgreSQL: id serial primary key
},
session: {
modelName: "session", // PostgreSQL: id text primary key
},
advanced: {
database: {
// Do NOT set useNumberId - it's global and affects all tables
generateId: (options) => {
if (options.model === "user" || options.model === "users") {
return false; // Let PostgreSQL serial generate it
}
return crypto.randomUUID(); // UUIDs for session, account, verification
},
},
},
});此配置允许你:
- 对 users 表使用数据库自增(serial、auto_increment 等)
- 为所有其他表(session、account、verification)生成 UUID
- 保持与使用不同 ID 类型的现有架构的兼容性
【This configuration allows you to:
- Use database auto-increment (serial, auto_increment, etc.) for the users table
- Generate UUIDs for all other tables (session, account, verification)
- Maintain compatibility with existing schemas that use different ID types】
使用场景:当从其他身份验证提供商(例如 Clerk)迁移时特别有用,此时你已有使用整数 ID 的现有用户,但希望为新表使用 UUID 字符串。
数据库钩子
【Database Hooks】
数据库钩子允许你定义在 Better Auth 核心数据库操作生命周期中可执行的自定义逻辑。你可以为以下模型创建钩子:用户(user)、会话(session) 和 账户(account)。
【Database hooks allow you to define custom logic that can be executed during the lifecycle of core database operations in Better Auth. You can create hooks for the following models: user, session, and account.】
支持附加字段,但这些字段的完整类型推断尚不支持。 计划改进类型支持。
你可以定义两种类型的钩子:
【There are two types of hooks you can define:】
1. 钩子之前
【1. Before Hook】
- 目的:在创建、更新或删除相应实体(用户、会话或账户)之前调用此钩子。
- 行为:如果钩子返回
false,操作将被中止。如果它返回一个数据对象,它将替换原始负载。
2. 钩子之后
【2. After Hook】
- 目的:在相应实体被创建或更新后,会调用此钩子。
- 行为:在实体成功创建或更新后,你可以执行额外的操作或修改。
示例用法
import { betterAuth } from "better-auth";
export const auth = betterAuth({
databaseHooks: {
user: {
create: {
before: async (user, ctx) => {
// Modify the user object before it is created
return {
data: {
// Ensure to return Better-Auth named fields, not the original field names in your database.
...user,
firstName: user.name.split(" ")[0],
lastName: user.name.split(" ")[1],
},
};
},
after: async (user) => {
//perform additional actions, like creating a stripe customer
},
},
delete: {
before: async (user, ctx) => {
console.log(`User ${user.email} is being deleted`);
if (user.email.includes("admin")) {
return false; // Abort deletion
}
return true; // Allow deletion
},
after: async (user) => {
console.log(`User ${user.email} has been deleted`);
},
},
},
session: {
delete: {
before: async (session, ctx) => {
console.log(`Session ${session.token} is being deleted`);
if (session.userId === "admin-user-id") {
return false; // Abort deletion
}
return true; // Allow deletion
},
after: async (session) => {
console.log(`Session ${session.token} has been deleted`);
},
},
},
},
});抛出错误
【Throwing Errors】
如果你想阻止数据库钩子继续执行,可以使用从 better-auth/api 导入的 APIError 类来抛出错误。
【If you want to stop the database hook from proceeding, you can throw errors using the APIError class imported from better-auth/api.】
import { betterAuth } from "better-auth";
import { APIError } from "better-auth/api";
export const auth = betterAuth({
databaseHooks: {
user: {
create: {
before: async (user, ctx) => {
if (user.isAgreedToTerms === false) {
// Your special condition.
// Send the API error.
throw new APIError("BAD_REQUEST", {
message: "User must agree to the TOS before signing up.",
});
}
return {
data: user,
};
},
},
},
},
});使用上下文对象
【Using the Context Object】
作为传递给 hook 的第二个参数的上下文对象(ctx)包含有用的信息。对于 update hook,这包括当前的 session,你可以用它来访问已登录用户的详细信息。
【The context object (ctx), passed as the second argument to the hook, contains useful information. For update hooks, this includes the current session, which you can use to access the logged-in user's details.】
import { betterAuth } from "better-auth";
export const auth = betterAuth({
databaseHooks: {
user: {
update: {
before: async (data, ctx) => {
// You can access the session from the context object.
if (ctx.context.session) {
console.log("User update initiated by:", ctx.context.session.userId);
}
return { data };
},
},
},
},
});就像标准钩子一样,数据库钩子也提供一个 ctx 对象,它包含多种有用的属性。更多信息请参阅钩子文档。
【Much like standard hooks, database hooks also provide a ctx object that offers a variety of useful properties. Learn more in the Hooks Documentation.】
插件架构
【Plugins Schema】
插件可以在数据库中定义自己的表来存储额外的数据。它们也可以向核心表添加列以存储额外的数据。例如,双因素认证插件向 user 表添加了以下列:
【Plugins can define their own tables in the database to store additional data. They can also add columns to the core tables to store additional data. For example, the two factor authentication plugin adds the following columns to the user table:】
twoFactorEnabled:用户是否启用了双因素身份验证。twoFactorSecret:用于生成 TOTP 代码的密钥。twoFactorBackupCodes:用于账户恢复的加密备用验证码。
要向你的数据库添加新表和列,你有两种选择:
【To add new tables and columns to your database, you have two options:】
CLI:使用 migrate 或 generate 命令。这些命令会扫描您的数据库,并指导您添加任何缺失的表或列。
Manual Method:按照插件文档中的说明手动添加表和列。
这两种方法都可以确保你的数据库架构符合插件的要求。
【Both methods ensure your database schema stays up to date with your plugins' requirements.】
实验性连接
【Experimental Joins】
自从 Better-Auth 版本 1.4 起,我们引入了实验性的数据库关联支持。 这使得 Better-Auth 能够在单次请求中执行多个数据库查询,从而减少数据库往返次数。已有超过 50 个端点支持关联,我们也在不断增加更多支持。
【Since Better-Auth version 1.4 we've introduced experimental database joins support.
This allows Better-Auth to perform multiple database queries in a single request, reducing the number of database roundtrips.
Over 50 endpoints support joins, and we're constantly adding more. 】
在底层,我们的适配器系统原生支持连接,这意味着即使你没有启用实验性连接,它仍然会回退到执行多个数据库查询并合并结果。
【Under the hood, our adapter system supports joins natively, meaning even if you don't enable experimental joins, it will still fallback to making multiple database queries and combining the results.】
要启用连接,请使用以下内容更新你的身份验证配置:
【To enable joins, update your auth config with the following:】
export const auth = betterAuth({
experimental: { joins: true }
});Better-Auth 1.4 CLI 会为你生成 DrizzleORM 和 PrismaORM 的关系,所以如果你还没有这些,请务必通过运行我们的 migrate 或 generate CLI 命令来更新你的 schema,以确保与最新的必需 schema 保持同步。
【The Better-Auth 1.4 CLI will generate DrizzleORM and PrismaORM relationships for you so if you do not have those already
be sure to update your schema by running our migrate or generate CLI commands to be up-to-date with the latest required schema.】
阅读关于你所使用适配器的实验性连接的文档非常重要:
【It's very important to read the documentation regarding experimental joins for your given adapter:】