Cloudflare D1 × Hono × Drizzle ORM
プロジェクト作成
まずは Hono のセットアップを行います。
今回はbun
を使用しますが、他にnpm
,yarn
,deno
でも可能です。
bunx create-hono d1-hono-drizzle
次にテンプレートを求められますので、cloudflare-workers
を選択します。
✔ Using target directory … d1-hono-drizzle
? Which template do you want to use?
aws-lambda
bun
cloudflare-pages
> cloudflare-workers
deno
fastly
lambda-edge
(Use arrow keys to reveal more choices)
最後に依存関係のインストールをします。
bun i
D1 作成
以下のコマンドでd1
を作成します。
コマンドを実行する前に、ブラウザで Cloudflare にログインしておくと簡単に作成できます。
bunx wrangler d1 create d1-tutorial
上記コマンドを実行すると Cloudflare のサイトが開きますので、Allow
を選択します。
その後、ターミナルに以下の表示が出力されれば成功です。
「You have granted authorization to Wrangler!」と表示されているブラウザは閉じて大丈夫です。
database_id
は大事な値ですので、どこかに公開しないように注意してください。
✅ Successfully created DB 'd1-tutorial' in region APAC
Created your new D1 database.
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "d1-tutorial"
database_id = "4be0fb76-c927-4d34-a461-4e1f98796124"
ターミナルに出力されている[[d1_database]]
以下の情報をwrangler.toml
に貼り付けします。
name = "d1-hono-drizzle"
compatibility_date = "2023-12-01"
# [vars]
# MY_VAR = "my-variable"
# [[kv_namespaces]]
# binding = "MY_KV_NAMESPACE"
# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# [[r2_buckets]]
# binding = "MY_BUCKET"
# bucket_name = "my-bucket"
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "d1-tutorial"
database_id = "4be0fb76-c927-4d34-a461-4e1f98796124"
# [ai]
# binding = "AI"
以下のコマンドを実行し、
bun run dev
ターミナルに bindings に d1 の id が出力されていれば成功です。
Your worker has access to the following bindings:
- D1 Databases:
- DB: d1-tutorial (4be0fb76-c927-4d34-a461-4e1f98796124)
Drizzle 導入
以下のコマンドでインストールします。
drizzle-kit
は sql ファイルを生成するのに使います。
bun add drizzle-orm
bun add -D drizzle-kit
スキーマ定義作成
今回はschema.ts
という名前でファイルを作成しました。
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";
export const users = sqliteTable(
"users",
{
id: integer("id", { mode: "number" }).primaryKey({ autoIncrement: true }),
name: text("name").notNull(),
email: text("email").notNull(),
password: text("password").notNull(),
},
() => [],
);
drizzle config 作成
drizzle.config.ts
を作成し以下のように記入します。
import type { Config } from "drizzle-kit";
export default {
schema: "./schema.ts",
out: "./drizzle",
dialect: "sqlite",
} satisfies Config;
-
schema
- スキーマ定義をしたファイルを指定します。 -
out
- スキーマ定義から生成した sql ファイル等が出力されます。 -
dialect
-mysql
,postgresql
,singlestore
,sqlite
,turso
から選択します。D1 では SQLite です。
SQL ファイル生成
まずpackage.json
にスクリプトを追記します。
"generate": "drizzle-kit generate",
"local:migration": "wrangler d1 migrations apply d1-tutorial --local",
"remote:migration": "wrangler d1 migrations apply d1-tutorial --remote"
migration スクリプトのapply
の次の単語は自身で指定したデータベース名になります。
では以下のコマンドで SQL ファイルを生成します。
bun run generate
以下のような文言が出力されれば成功です。
1 tables
users 4 columns 0 indexes 0 fks
[✓] Your SQL migration file ➜ drizzle\0000_wooden_norman_osborn.sql 🚀
マイグレーション
次にローカルにマイグレーションをします。
まずwrangler.toml
に以下を追記します。
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "d1-tutorial"
database_id = "4be0fb76-c927-4d34-a461-4e1f98796124"
+ migrations_dir = "drizzle"
ディレクトリ先はdrizzle.config.ts
の out で指定したディレクトリを記入してください。
その次に以下のコマンドでマイグレーションを行います。
bun run local:migration
リクエストに対応できなくなる可能性がありますが続けますか?と聞かれるので、y
を押します。
Migrations to be applied:
┌───────────────────────────────┐
│ name │
├───────────────────────────────┤
│ 0000_wooden_norman_osborn.sql │
└───────────────────────────────┘
? About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? » (Y/n)
以下のように出力されれば成功です。
🌀 Mapping SQL input into an array of statements
🌀 Executing on local database d1-tutorial (4be0fb76-c927-4d34-a461-4e1f98796124) from .wrangler\state\v3\d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
┌───────────────────────────────┬────────┐
│ name │ status │
├───────────────────────────────┼────────┤
│ 0000_wooden_norman_osborn.sql │ ✅ │
└───────────────────────────────┴────────┘
CRUD 処理
Hono から D1 にアクセスし、CRUD を操作をするために以下のように修正します。
import { drizzle } from "drizzle-orm/d1";
import { Hono } from "hono";
import { users } from "../schema";
type Bindings = {
DB: D1Database;
};
const app = new Hono<{ Bindings: Bindings }>();
app.get("/", (c) => {
return c.text("Hello Hono!");
});
/*****************************************
* get users
*****************************************/
app.get("/users", async (c) => {
const db = drizzle(c.env.DB);
const result = await db.select().from(users).all();
return c.json(result);
});
/*****************************************
* create users
*****************************************/
app.post("/users", async (c) => {
const params = await c.req.json<typeof users.$inferSelect>();
const db = drizzle(c.env.DB);
const result = await db.insert(users).values({
name: params.name,
email: params.email,
password: params.password,
});
return c.json(result);
});
export default app;
以下の画像は Postman でユーザーの追加と取得をした結果になります。
ステータスコード 200 が返ってきていれば成功です。
デプロイ
マイグレーション
まず D1 を本番環境にマイグレーションします。
bun run remote:migration
ここでも続けていいですか?と聞かれるので、yes と答えて以下のように出力されれば成功です。
🌀 Mapping SQL input into an array of statements
🌀 Parsing 2 statements
🌀 Executing on remote database d1-tutorial (4be0fb76-c927-4d34-a461-4e1f98796124):
🌀 To execute on your local development database, remove the --remote flag from your wrangler command.
🚣 Executed 2 commands in 0.2992ms
┌───────────────────────────────┬────────┐
│ name │ status │
├───────────────────────────────┼────────┤
│ 0000_wooden_norman_osborn.sql │ ✅ │
└───────────────────────────────┴────────┘
Hono
次に Hono を Cloudflare Workers にデプロイします。
bun run deploy
こちらも以下のように出力されれば成功です。
Your worker has access to the following bindings:
- D1 Databases:
- DB: d1-tutorial (4be0fb76-c927-4d34-a461-4e1f98796124)
Total Upload: 75.18 KiB / gzip: 23.06 KiB
Uploaded d1-hono-drizzle (1.72 sec)
Published d1-hono-drizzle (3.90 sec)
https://d1-hono-drizzle.daichi2mori.workers.dev
Current Deployment ID: 112b727c-e61b-4389-b2d4-fb44fbb4c0e8
Current Version ID: 112b727c-e61b-4389-b2d4-fb44fbb4c0e8
CRUD 確認
本番環境に対しても以下のように成功しました。
Discussion