Drizzle ORM 适配器

将 Better Auth 与 Drizzle ORM 集成。

Drizzle ORM 是一个功能强大且灵活的 Node.js 和 TypeScript ORM。它提供了一个简单直观的 API 来操作数据库,支持包括 MySQL、PostgreSQL、SQLite 等多种数据库。

在开始之前,请确保你已经安装并配置了 Drizzle。更多信息请参见 Drizzle 文档

安装

要使用 Drizzle 适配器,你需要安装 @better-auth/drizzle-adapter 包:

npm install @better-auth/drizzle-adapter

示例用法

你可以按如下方式使用 Drizzle 适配器连接你的数据库。

auth.ts
import { betterAuth } from "better-auth";
import { drizzleAdapter } from "@better-auth/drizzle-adapter";
import { db } from "./database.ts";

export const auth = betterAuth({
  database: drizzleAdapter(db, { 
    provider: "sqlite", // 或者 "pg" 或 "mysql"
  }), 
  //... 你的其他配置
});

模式生成与迁移

Better Auth CLI 允许你根据 Better Auth 配置和插件来生成或迁移数据库模式。

生成 Better Auth 所需的数据库模式,运行以下命令:

npx auth@latest generate

生成并应用迁移,运行以下命令:

npx drizzle-kit generate # 生成迁移文件

联接

当 Better-Auth 需要在单个查询中从多个表获取相关数据时,数据库联接非常有用。 /get-session/get-full-organization 等端点都能从此功能中获益良多, 根据数据库延迟的不同,性能提升可达 2 到 3 倍。

Drizzle 适配器从 1.4.0 版本开始原生支持联接。 要启用此功能,请在 auth 配置中将 advanced.database.joins 设置为 true

auth.ts
import { betterAuth } from "better-auth";

export const auth = betterAuth({
  advanced: {
    database: {
      joins: true,
    },
  },
});

请确保你的 Drizzle 模式定义了必要的关联关系。 如果你在 Drizzle 模式中没有看到任何关联关系,可以使用 relation 函数手动添加关联, 或运行最新版本的 CLI 命令 npx auth@latest generate 生成包含关联的 Drizzle 模式。

此外,你需要将每个关联关系通过 drizzle 适配器的模式对象传入。

当一个表拥有指向同一张表的多个外键时,每一对关联都必须使用匹配的 relationName。 CLI 会自动生成这些名称。如果你是用较旧版本的 CLI 生成的模式,请重新生成,或者在两侧都添加匹配的名称。

relationName 前缀遵循你的表命名:在 usePlural: true 时使用复数形式(tests_userId),否则使用单数形式(test_userId)。两侧必须保持完全一致。

schema.ts
export const usersRelations = relations(users, ({ many }) => ({
  testsByUserId: many(tests, { relationName: "tests_userId" }),
  testsByManagerId: many(tests, { relationName: "tests_managerId" }),
}));

export const testsRelations = relations(tests, ({ one }) => ({
  user: one(users, {
    fields: [tests.userId],
    references: [users.id],
    relationName: "tests_userId",
  }),
  manager: one(users, {
    fields: [tests.managerId],
    references: [users.id],
    relationName: "tests_managerId",
  }),
}));

不要为同一个外键同时保留单数和复数别名(例如同时使用 userusers)。Drizzle 会将它们视为不同的关联,因而无法推断联接应该使用哪一个反向关联。

修改表名

Drizzle 适配器期望你定义的模式与表名一致。例如,如果 Drizzle 模式将 user 表映射为 users,你需要手动传入模式并映射到 user 表。

import { betterAuth } from "better-auth";
import { db } from "./drizzle";
import { drizzleAdapter } from "@better-auth/drizzle-adapter";
import { schema } from "./schema";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "sqlite", // 或 "pg" 或 "mysql"
    schema: { 
      ...schema, 
      user: schema.users, 
    }, 
  }),
});

你可以像上例这样修改提供的模式值, 也可以直接修改 auth 配置的 modelName 属性。 例如:

import { betterAuth } from "better-auth";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "sqlite", // 或 "pg" 或 "mysql"
    schema,
  }),
  user: {
    modelName: "users", 
  }
});

修改字段名

我们基于你传入 Drizzle 模式的属性映射字段名。 例如,如果你想将 email 字段修改为 email_address, 只需修改 Drizzle 模式为:

export const user = mysqlTable("user", {
  // 修改字段名但不改变模式属性名
  // 这样 Drizzle 和 Better Auth 仍使用原始字段名,
  // 而数据库使用修改后的字段名
  email: varchar("email_address", { length: 255 }).notNull().unique(), 
  // ... 其他字段
});

你可以像上例一样修改 Drizzle 模式, 也可以直接修改 auth 配置的 fields 属性。 例如:

import { betterAuth } from "better-auth";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "sqlite", // 或 "pg" 或 "mysql"
    schema,
  }),
  user: {
    fields: {
      email: "email_address", 
    }
  }
});

使用复数表名

如果你的所有表名都是复数形式,你可以直接传入 usePlural 选项:

import { betterAuth } from "better-auth";

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    ...
    usePlural: true, 
  }),
});

自定义 Schema 命名空间

如果你使用 PostgreSQL,并且想要使用自定义 Schema 命名空间生成模式, 可以将 schemaName 选项传递给 Drizzle 适配器。

export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: "pg",
    schemaName: "auth", 
  }),
});

然后使用 Better Auth CLI 时,它将生成类似如下的模式:

npx @better-auth/cli@latest generate
export const authSchema = pgSchema("auth");

export const user = authSchema.table("user", {...});
export const session = authSchema.table("session", {...});

下面介绍的 @better-auth/drizzle-adapter/relations-v2 适配器同样支持 schemaName 选项。

Drizzle Relations v2

当前的 Drizzle 适配器使用 Drizzle Relations v1。 要使用 Drizzle Relations v2,你需要使用 @better-auth/drizzle-adapter/relations-v2 适配器。

安装适配器:

npm install @better-auth/drizzle-adapter

更新导入以使用 relations-v2 适配器:

auth.ts
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from '@better-auth/drizzle-adapter/relations-v2'; 
import { db } from './database.ts';
import * as schema from './schema.ts';

export const auth = betterAuth({
	database: drizzleAdapter(db, {
		provider: 'sqlite', // or "pg" or "mysql"
		schema,
	}),
	//... the rest of your config
});

然后使用 Better Auth CLI 重新生成你的模式:

npx auth@latest generate

升级到 Relations v2 时,不需要运行数据库迁移。数据库结构保持不变——只有关联定义发生变化。 模式生成器会自动输出新的 v2 格式。

生成的 auth 模式会使用 defineRelationsPart 导出关联关系,该方法旨在与应用自己的 defineRelations 合并使用。将两者传递给 drizzle 实例——从 Drizzle v1 RC 开始,不再需要 schema

db.ts
import { drizzle } from 'drizzle-orm/...';
// generated relations from auth CLI (uses defineRelationsPart)
import { authRelations } from './auth-schema.ts';
// your app's own relations (uses defineRelations)
import { relations } from './app-schema.ts';

export const db = drizzle({
	client,
	// authRelations uses defineRelationsPart,
	// so it must come after the main relations
	relations: { ...relations, ...authRelations }, 
});

defineRelationsPart 是一种部分关联定义,必须展开在完整的 defineRelations 条目之后。详情请参阅 Drizzle 关于关联部分的文档

其他信息

  • 如果你在寻找性能改进或优化建议,可以查阅我们的指南 性能优化