はじめに
前回までにCloudflare WorkersからD1に接続するまで実施しました。
アプリケーションはHonoで実行していたんですが、ORMないと色々不便だな😅と感じ、ORMを探していました。TypeScriptのORMというと、prismaが思い浮かぶのですが、D1とは相性が悪いみたいで採用を見送りました。ざんねん😢
よくよく調べてみるとdrizzleというORMが相性いいみたいで今回採用してみました!!
Drizzleとは
TypeScriptのORMです。Prismaと比べて計量でシンプルさとパフォーマンスを重視したORMです。
サーバレス環境やコンパクトなプロジェクトに適しています!
特徴 | Prisma | Drizzle ORM |
---|---|---|
エコシステム | 非常にリッチ、フル機能 | シンプルで必要最小限 |
型安全性 | 自動生成された型で強力にサポート | サポートあり(Prismaほど自動ではない) |
パフォーマンス | より多機能なため、やや重め | 軽量で高速 |
学習コスト | 中程度〜高め | 低め |
サーバーレス対応 | Prisma Data Proxyで対応 | 非常に適している |
マイグレーション | Prisma Migrateで強力にサポート | 基本的なサポート |
ドキュメント | 非常に豊富 | シンプルでコンパクト |
0.準備(プロジェクト作成〜D1でDB作成まで)
今回の本題とは異なりますが、プロジェクト作成、D1にDBを作成します。
下記を参考に実施してみてください!!⭐️
プロジェクト作成〜D1でDB作成まで
~/develop$ npm create cloudflare@latest
> npx
> create-cloudflare
using create-cloudflare version 2.23.0
╭ Create an application with Cloudflare Step 1 of 3
│
├ In which directory do you want to create your application?
│ dir ./sample-drizzle
│
├ What would you like to start with?
│ category Framework Starter
│
╰ Which development framework do you want to use?
○ Analog
○ Angular
○ Astro
○ Docusaurus
○ Gatsby
● Hono
○ Next
○ Nuxt
○ Qwik
○ React
○ Remix
○ Solid
○ Svelte
○ Vue
1. migrationの実施
では実際にmigrationを実施するための作業をしていきましょう!!
1-1. 環境変数の設定
#:schema node_modules/wrangler/config-schema.json
name = "XXXX" ## 今回作成したプロジェクト名を設定してください。
main = "src/index.ts"
compatibility_date = "2024-08-06"
account_id = "XXXXXX" ## アカウントIDを設定
workers_dev = true
[[d1_databases]]
binding = "D1"
database_name = "sample" ## DBの名称
database_id = "XXXXX" ## DBのid
1-2. スキーマ定義
今回はuserテーブルを作っておきます。
npm install drizzle-orm
npm install drizzle-kit --save-dev
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
// usersテーブルのスキーマを定義
export const users = sqliteTable("users", {
id: integer("id").primaryKey().notNull(), // ユーザーID(主キー)
username: text("username").notNull(), // ユーザー名(必須)
email: text("email").notNull().unique(), // メールアドレス(必須、ユニーク)
password: text("password").notNull(), // パスワード(必須)
isActive: integer("is_active").default(1), // アクティブフラグ(デフォルトで1 = true)
createdAt: text("created_at").default("CURRENT_TIMESTAMP"), // 作成日時
});
d1はsqliteの亜種のようです。そのため、bool値が使えないようなので注意⚠️
1-3. migrationファイルの作成
スキーマからmigrationファイルを作成していきましょう!
1-3-1. マイグレーション先の設定ファイル
import type { Config } from "drizzle-kit";
export default {
schema: "./src/schema.ts", // スキーマ定義ファイル
out: "./drizzle/migrations", // マイグレーションファイルの出力ディレクトリ
dialect: "sqlite", // SQLiteを使用
} satisfies Config;
マイグレーション先の設定ファイルを作成します。
プロジェクトルート配下に作成してください!
1-3-2. マイグレーションファイルの生成
~/develop/sample-drizzle (master)$ npx drizzle-kit generate
No config path provided, using default 'drizzle.config.ts'
Reading config file '/Users/kawamurakouji/develop/sample-drizzle/drizzle.config.ts'
1 tables
users 6 columns 1 indexes 0 fks
[✓] Your SQL migration file ➜ drizzle/migrations/0000_foamy_clint_barton.sql 🚀
これでマイグレーションファイルが作成されました。
1-3-3. マイグレーションの実行
npx wrangler d1 execute <database-name> --file=./drizzle/migrations/<migration-file>.sql --remote
上記はサーバに直接migrationを流す方法です。--remote
を外すだけで良いです。
npx wrangler d1 execute <database-name> --file=./drizzle/migrations/<migration-file>.sql
1-3-4. DBにTBLが作成されているかを確認する。
~/develop/sample-drizzle (master)$ npx wrangler d1 execute sample --command="SELECT name FROM sqlite_master WHERE type='table';" --remote
⛅️ wrangler 3.70.0
-------------------
🌀 Executing on remote database sample (be1170e4-6823-4cfb-ac73-7b295e08cfd6):
🌀 To execute on your local development database, remove the --remote flag from your wrangler command.
🚣 Executed 1 commands in 0.1765ms
┌────────┐
│ name │
├────────┤
│ _cf_KV │
├────────┤
│ users │
└────────┘
問題なくできていそうですね。
1-4. DBにデータをinsertする
1-4-1. insert文を作成する
INSERT INTO users (username, email, password, is_active)
VALUES
('jane_doe', 'jane@example.com', 'anotherpassword', 1),
('alice', 'alice@example.com', 'password123', 1),
('bob', 'bob@example.com', 'mypassword', 1);
1-4-2. insert文を実行する
npx wrangler d1 execute <database-name> --file=./insert_data.sql --remote
1-5. APIを作成する
import { Hono } from "hono";
import { drizzle } from "drizzle-orm/d1"; // D1専用のドライバーを使用
import { users } from "./schema";
import type { D1Database } from "@cloudflare/workers-types";
type Bindings = {
DB: D1Database;
};
const app = new Hono<{ Bindings: Bindings }>();
// 全てのユーザーを取得するエンドポイント
app.get("/users", async (c) => {
try {
const db = drizzle(c.env.DB); // D1専用ドライバーで初期化
const allUsers = await db.select().from(users).execute(); // クエリの実行
return c.json(allUsers);
} catch (error) {
return c.json(
{ error: "Failed to retrieve users" },
500,
);
}
});
export default app;
npm run deploy
1-6. APIを実行する
GET: ${URL}/users
[
{
"id": 1,
"username": "jane_doe",
"email": "jane@example.com",
"password": "anotherpassword",
"isActive": 1,
"createdAt": "CURRENT_TIMESTAMP"
},
{
"id": 2,
"username": "alice",
"email": "alice@example.com",
"password": "password123",
"isActive": 1,
"createdAt": "CURRENT_TIMESTAMP"
},
{
"id": 3,
"username": "bob",
"email": "bob@example.com",
"password": "mypassword",
"isActive": 1,
"createdAt": "CURRENT_TIMESTAMP"
}
]
取得できましたね。createdAtは想定外の表示になりましたが、これはご愛嬌ですね😅