该命令会输出一个 worker-configuration.d.ts
文件。
使用 Drizzle 和 SQLite Durable Objects 快速入门
This guide assumes familiarity with:
基本文件结构
这是项目的基本文件结构。在 src/db
目录中,我们在 schema.ts
中有表定义。在 drizzle
文件夹中,有 SQL 迁移文件和快照。
📦 <project root>
├ 📂 drizzle
├ 📂 src
│ ├ 📂 db
│ │ └ 📜 schema.ts
│ └ 📜 index.ts
├ 📜 .env
├ 📜 drizzle.config.ts
├ 📜 package.json
└ 📜 tsconfig.json
第 1 步 - 安装必需的包
npm
yarn
pnpm
bun
npm i drizzle-orm dotenv
npm i -D drizzle-kit wrangler @cloudflare/workers-types
第 2 步 - 设置 wrangler.toml
你需要有一个用于 D1 数据库的 wrangler.toml
文件,内容大致如下:
#:schema node_modules/wrangler/config-schema.json
name = "sqlite-durable-objects"
main = "src/index.ts"
compatibility_date = "2024-11-12"
compatibility_flags = [ "nodejs_compat" ]
# 绑定一个 Durable Object。Durable Object 是基于 actor 模型的按需伸缩计算原语。
# Durable Object 可以持续存在。适用于需要长时间运行“服务器”的场景,如实时应用。
# 文档:https://developers.cloudflare.com/workers/wrangler/configuration/#durable-objects
[[durable_objects.bindings]]
name = "MY_DURABLE_OBJECT"
class_name = "MyDurableObject"
# Durable Object 迁移。
# 文档:https://developers.cloudflare.com/workers/wrangler/configuration/#migrations
[[migrations]]
tag = "v1"
new_sqlite_classes = ["MyDurableObject"]
# 需要规则以便在后续步骤中导入迁移
[[rules]]
type = "Text"
globs = ["**/*.sql"]
fallthrough = true
第 3 步 - 连接 Drizzle ORM 到数据库
/// <reference types="@cloudflare/workers-types" />
import { drizzle, type DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite';
import { DurableObject } from 'cloudflare:workers'
export class MyDurableObject extends DurableObject {
storage: DurableObjectStorage;
db: DrizzleSqliteDODatabase;
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.storage = ctx.storage;
this.db = drizzle(this.storage, { logger: false });
}
}
第 4 步 - 生成 wrangler 类型
npm
yarn
pnpm
bun
npx wrangler types
第 5 步 - 创建一个表
Create a schema.ts
file in the src/db
directory and declare your table:
import { int, sqliteTable, text } from "drizzle-orm/sqlite-core";
export const usersTable = sqliteTable("users_table", {
id: int().primaryKey({ autoIncrement: true }),
name: text().notNull(),
age: int().notNull(),
email: text().notNull().unique(),
});
第 6 步 - 设置 Drizzle 配置文件
Drizzle 配置 是一个由 Drizzle Kit 使用的配置文件,包含有关数据库连接、迁移文件夹和模式文件的所有信息。
在项目根目录下创建 drizzle.config.ts
文件,并添加以下内容:
import 'dotenv/config';
import { defineConfig } from 'drizzle-kit';
export default defineConfig({
out: './drizzle',
schema: './src/db/schema.ts',
dialect: 'sqlite',
driver: 'durable-sqlite',
});
第 7 步 - 应用数据库变更
生成迁移:
npx drizzle-kit generate
迁移只能从 Cloudflare Workers 应用。 为此,我们在 MyDurableObject 中定义迁移功能:
/// <reference types="@cloudflare/workers-types" />
import { drizzle, type DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite';
import { DurableObject } from 'cloudflare:workers'
import { migrate } from 'drizzle-orm/durable-sqlite/migrator';
import migrations from '../drizzle/migrations';
export class MyDurableObject extends DurableObject {
storage: DurableObjectStorage;
db: DrizzleSqliteDODatabase;
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.storage = ctx.storage;
this.db = drizzle(this.storage, { logger: false });
}
async migrate() {
migrate(this.db, migrations);
}
}
第 8 步 - 迁移并查询数据库
/// <reference types="@cloudflare/workers-types" />
import { drizzle, DrizzleSqliteDODatabase } from 'drizzle-orm/durable-sqlite';
import { DurableObject } from 'cloudflare:workers'
import { migrate } from 'drizzle-orm/durable-sqlite/migrator';
import migrations from '../drizzle/migrations';
import { usersTable } from './db/schema';
export class MyDurableObject extends DurableObject {
storage: DurableObjectStorage;
db: DrizzleSqliteDODatabase<any>;
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.storage = ctx.storage;
this.db = drizzle(this.storage, { logger: false });
// 确保所有迁移在接受查询前完成。
// 否则你需要在任何访问 Drizzle 数据库 this.db 的函数中调用 `this.migrate()`。
ctx.blockConcurrencyWhile(async () => {
await this._migrate();
});
}
async insertAndList(user: typeof usersTable.$inferInsert) {
await this.insert(user);
return this.select();
}
async insert(user: typeof usersTable.$inferInsert) {
await this.db.insert(usersTable).values(user);
}
async select() {
return this.db.select().from(usersTable);
}
async _migrate() {
migrate(this.db, migrations);
}
}
export default {
/**
* 这是 Cloudflare Worker 的标准 fetch 处理器
*
* @param request - Client 发送到 Worker 的请求
* @param env - 用于引用 wrangler.toml 中声明绑定的接口
* @param ctx - Worker 的执行上下文
* @returns 返回给客户端的响应
*/
async fetch(request: Request, env: Env): Promise<Response> {
const id: DurableObjectId = env.MY_DURABLE_OBJECT.idFromName('durable-object');
const stub = env.MY_DURABLE_OBJECT.get(id);
// 选项 A - 最大性能。
// 优先将所有数据库交互封装在一次 Durable Object 调用中
// 以获得最大性能,因为 DO 内的数据库访问非常快。
const usersAll = await stub.insertAndList({
name: 'John',
age: 30,
email: 'john@example.com',
});
console.log('新用户已创建。正在从数据库获取所有用户:', users);
// 选项 B - 慢速,但在某些调试场景下可能有用。
// 你也可以直接调用单个 Drizzle 查询(如果暴露了的话),
// 但请记住每次查询都是对 Durable Object 实例的一次往返。
await stub.insert({
name: 'John',
age: 30,
email: 'john@example.com',
});
console.log('新用户已创建!');
const users = await stub.select();
console.log('正在从数据库获取所有用户:', users);
return Response.json(users);
}
}