@drizzle-adapter/d1

中文文档
2.0.1发布于 2026/11/07MITTypeScriptES Module近 30 天下载 2.1万

Cloudflare D1适配器实施 Drizzle适配器生态系统.

中文使用文档
文档目录20 节
  1. 概览
  2. 为什么是D1?
  3. 完美为:
  4. 安装
  5. 重要:适配器注册
  6. D1 兼容层
  7. 执行方法映射
  8. 交易兼容性
  9. 移徙因素
  10. 释放
  11. 使用量
  12. 云花岗工人设置
  13. 配置
  14. 关于连接的重要注释
  15. Schema 定义
  16. 基本 CRUD 操作
  17. 工人执行
  18. 最佳做法
  19. 捐款
  20. 相关软件包

@ 细雨适应器/ d1

Cloudflare D1适配器实施 Drizzle适配器生态系统.

概览

这个 @drizzle-adapter/d1 软件包为 Drizzle 适应器接口提供 Cloudflare D1 执行。 虽然你不直接与此软件包互动( 您使用 @drizzle-adapter/core 相反,它使得D1在Drizzle适应器生态系统中得到了支持.

为什么是D1?

D1为Cloudflare工人提供了独特的优势:

  • 边缘 SQLite: 为边缘所建的分布式 SQLite 数据库
  • 0 配置: 自动复制和分发
  • 全球业绩: 数据来自最接近的边缘位置
  • 云浮工人融合:与工人的土著融合
  • 自动缩放: 内置可伸缩性和可靠性
  • 成本效益: 以慷慨的自由等级纳入工人定价
  • SQLite 兼容性: 熟悉的 SQLite 接口和特性
  • 自动备份: 内置备份并恢复能力

完美为:

  1. 边缘应用程序: 数据来自最近的地点
  2. 云花岗工人:工人应用程序的土著数据库
  3. 全球应用自动全局分布
  4. 成本敏感项目: 列入工人定价
  5. 简单部署: 需要零配置

安装

# Install both the core package and the D1 adapter
pnpm install @drizzle-adapter/core @drizzle-adapter/d1

重要:适配器注册

适配器要正确使用 DrizzleAdapterFactory 操作,必须导入它进行自我注册的副作用:

// Import for side effects - adapter will self-register
import '@drizzle-adapter/d1';

// Now you can use the factory
import { DrizzleAdapterFactory } from '@drizzle-adapter/core';

D1 兼容层

这个适配器提供了几个兼容性增强,使D1与现有的Drizzle ORM代码无缝地工作:

执行方法映射

D1的 Drizzle 执行用途 run() 而不是标准 execute() 方法。 此适配器自动映射 execute() 改为 run() 兼容性:

// Both of these work identically
await client.execute(sql`SELECT * FROM users`);
await client.run(sql`SELECT * FROM users`);

交易兼容性

破门而入2.0.0: Cloudflare D1没有交互交易. transaction() 现在抛出 D1TransactionUnsupportedError 而不是在没有原子性的情况下运行回调。 召回从未被引用.

import { D1TransactionUnsupportedError } from '@drizzle-adapter/d1';

try {
  await client.transaction(async (tx) => { /* never runs */ });
} catch (caughtError) {
  if (caughtError instanceof D1TransactionUnsupportedError) {
    // use db.batch() instead
  }
}

用于原子操作,使用时 db.batch()。它是一个隐含的 SQL 交易(全部或无) :

import { sql } from 'drizzle-orm';

const results = await client.batch([
  client.insert(users).values({ name: 'John' }),
  client.run(sql`UPDATE posts SET published = 1 WHERE id = ${postId}`)
]);

移徙因素

  • 交易兼容性: 自2.0起, db.transaction() 掷出 D1TransactionUnsupportedError; 迁移到 db.batch()
  • 无回滚: 失败的操作无法自动回滚
  • 批量操作: 使用 db.batch() 用于需要原子化的操作
  • 处理错误: 对关键业务实施人工清理逻辑

释放

pnpm check && pnpm lint && pnpm test
pnpm --filter @drizzle-adapter/d1 publish --access public   # run from the repo root

使用量

云花岗工人设置

首先,设置您的 D1 数据库:

# Create a new D1 database
wrangler d1 create my-database

# Add to wrangler.toml
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-database-id"

配置

import { DrizzleAdapterFactory, TypeDrizzleDatabaseConfig } from '@drizzle-adapter/core';
import { D1Database } from '@cloudflare/workers-types';

interface Env {
  DB: D1Database;
}

const config: TypeDrizzleDatabaseConfig = {
  DATABASE_DRIVER: 'd1',
  DATABASE: env.DB
};

const factory = new DrizzleAdapterFactory();
const adapter = factory.create(config);

关于连接的重要注释

虽然D1在工人环境内运行,不需要传统的数据库连接,但这个适配器执行兼容性的标准连接接口. 这意味着您的代码在不同的数据库适配器中仍可移植:

// These connection operations are no-ops for D1 but ensure
// your code remains portable if you switch to another database
const connection = await adapter.getConnection();

const client = connection.getClient();

// Your database operations

await connection.disconnect(); // No-op for D1

Schema 定义

const dataTypes = adapter.getDataTypes();

const users = dataTypes.dbTable('users', {
  id: dataTypes.dbInteger('id').primaryKey().autoincrement(),
  name: dataTypes.dbText('name').notNull(),
  email: dataTypes.dbText('email').notNull().unique(),
  metadata: dataTypes.dbText('metadata'), // JSON stored as text
  createdAt: dataTypes.dbInteger('created_at')
    .default(sql`(unixepoch())`)
});

const posts = dataTypes.dbTable('posts', {
  id: dataTypes.dbInteger('id').primaryKey().autoincrement(),
  userId: dataTypes.dbInteger('user_id')
    .references(() => users.id),
  title: dataTypes.dbText('title').notNull(),
  content: dataTypes.dbText('content').notNull(),
  published: dataTypes.dbInteger('published').default(0),
  createdAt: dataTypes.dbInteger('created_at')
    .default(sql`(unixepoch())`)
});

基本 CRUD 操作

import { eq, and, or, desc, sql } from 'drizzle-orm';

const client = await adapter.getConnection().getClient();

// INSERT
// Single insert with returning
const [newUser] = await client
  .insert(users)
  .values({
    name: 'John Doe',
    email: '[email protected]',
    metadata: JSON.stringify({ role: 'user' })
  })
  .returning();

// Bulk insert
await client
  .insert(posts)
  .values([
    {
      userId: newUser.id,
      title: 'First Post',
      content: 'Hello, world!'
    },
    {
      userId: newUser.id,
      title: 'Second Post',
      content: 'Another post'
    }
  ]);

// SELECT
// Select all
const allUsers = await client
  .select()
  .from(users);

// Select with conditions
const user = await client
  .select()
  .from(users)
  .where(eq(users.email, '[email protected]'));

// Select with join
const userPosts = await client
  .select({
    userName: users.name,
    postTitle: posts.title,
    content: posts.content,
    metadata: users.metadata
  })
  .from(posts)
  .leftJoin(users, eq(posts.userId, users.id))
  .where(eq(posts.published, 1))
  .orderBy(desc(posts.createdAt));

// UPDATE
await client
  .update(users)
  .set({
    name: 'John Smith',
    metadata: JSON.stringify({ role: 'admin' })
  })
  .where(eq(users.id, newUser.id));

// DELETE
await client
  .delete(posts)
  .where(
    and(
      eq(posts.userId, newUser.id),
      eq(posts.published, 0)
    )
  );

工人执行

interface Env {
  DB: D1Database;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const factory = new DrizzleAdapterFactory();
    const adapter = factory.create({
      DATABASE_DRIVER: 'd1',
      DATABASE: env.DB
    });

    const client = await adapter.getConnection().getClient();
    const url = new URL(request.url);

    try {
      switch (url.pathname) {
        case '/users': {
          const users = await client
            .select()
            .from(users);
          return Response.json(users);
        }

        case '/posts': {
          const posts = await client
            .select({
              title: posts.title,
              content: posts.content,
              author: users.name
            })
            .from(posts)
            .leftJoin(users, eq(posts.userId, users.id))
            .where(eq(posts.published, 1))
            .orderBy(desc(posts.createdAt));
          return Response.json(posts);
        }

        default:
          return new Response('Not Found', { status: 404 });
      }
    } catch (error) {
      return new Response('Error', { status: 500 });
    }
  }
}

最佳做法

  1. 边缘优化: 查询会自动优化边缘执行
  2. JSON 处理: 将 JSON 数据作为 TEXT 存储,并根据需要进行解析/字符串
  3. 处理错误: 为边缘环境执行适当的错误处理
  4. 查询优化: 尽量减少每个请求的查询次数
  5. 可移动性: 将连接接口用于数据库可移植性

捐款

我们欢迎捐款! 请随意提交拉力请求 对于重大变动,请先开出一个问题来讨论你想要改变什么.

版本与发布记录

@drizzle-adapter/d1 共发布 19 个版本,首次发布于 2024/12/03;过去 12 个月发布了 3 个版本。

版本发布日期距今
2.0.1latest2026/11/076 天前
2.0.02026/10/1925 天前
1.1.12026/03/267 个月前
1.0.182025/08/181.2 年前
1.0.172025/07/171.3 年前
1.0.152025/07/121.3 年前

关于 @drizzle-adapter/d1 的常见问题

@drizzle-adapter/d1 是什么?

Cloudflare D1适配器实施 Drizzle适配器生态系统.

如何安装 @drizzle-adapter/d1?

在项目目录运行 npm install @drizzle-adapter/d1,或使用 pnpm add / yarn add / bun add。

@drizzle-adapter/d1 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@drizzle-adapter/d1 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@drizzle-adapter/d1 可以商用吗?

@drizzle-adapter/d1 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@drizzle-adapter/d1 的下载量有多少?

根据 npm 官方下载统计,@drizzle-adapter/d1 在 2026/10/13 – 2026/11/11 这 30 天内被下载 20,718 次,日均约 691 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@drizzle-adapter/d1 还在维护吗?

最新版本 2.0.1 发布于 2026/11/07(6 天前);至今共发布 19 个版本,其中过去 12 个月发布了 3 个;首次发布于 2024/12/03。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。