drizzle を使ってマイグレーションをする際、戸惑ったのでメモしておきます
Cloudflare D1 では wrangler を使うことで、SQL ファイルでマイグレーションを行うことができます
ローカル環境、本番環境、どちらも操作することができます
また Cloudflare D1 を利用する際、ORM に drizzle-orm を使うことができます
かなり型に気を遣って、安全性の考えらている ORM です
drizzle を使う場合、型付け用のスキーマ定義ファイルを作成する必要があります
例えば、こんな感じ
import { sqliteTable, integer, text } from 'drizzle-orm'export const article = sqliteTable('article', {id: integer().primaryKey(),title: text(),body: text(),created_at: text(),updated_at: text()})
で、今回はマイグレーションを簡単にしたいなあと思うわけなんですけど、
マイグレーションを行う際は、おそらく以下の2つになるかと思います
drizzle のスキーマ定義を使って、D1 用の SQL ファイルを生成する
D1 用の SQL ファイルから、drizzle のスキーマ定義を作成する
drizzle 主体で考えたい場合は 1 で問題ないんですけど、どうやらこういったトリガーは定義できないみたいです
以下は、更新時間を自動的にアップデートするものです
CREATE TRIGGER update_article AFTER UPDATE ON articleBEGINUPDATE article SET updated_at = datetime('now') WHERE id = NEW.id;END;
こういったトリガーを使う場合は、別途 SQL ファイルを作成して、それを適用する必要があるみたいです
定義が2つあるのは、ちょっと面倒だなあと思ったので、今回は 2 で行なうことにしました
(まあ、こっちもイバラの道なんですけどね...)
drizzle のスキーマ定義を作成する場合は、sqlite3 が必要になるので、事前に apt 等でインストールしておきます
また、npm の drizzle-kit が必要になるので、インストールしておきます
yarn add -D drizzle-kit実は drizzle.config.ts だったり、いろいろお膳立てが必要で面倒なので、
自動でやってくれるように、以下のようなシェルスクリプトを作ってみました
まず、ファイル配置ですが、以下のようなものを想定しています
project├── migrations│ ├── 0001_create_article.sql│ ├── 0002_create_user.sql│ └── 0003_create_comment.sql├── drizzle│ ├── generate_schema.sh│ ├── relations.ts (★生成されるもの)│ └── schema.ts (★生成されるもの)├── node_modules├── package.json└── yarn.lock
generate_schema.sh は以下のようになります
#!/bin/sh# Search sqlite3 commandsqlite3_command=$(which sqlite3)if [ -z "$sqlite3_command" ]; thenecho "'sqlite3' command not found"exit 1fi# Move current directory to the directory of the scriptcd "$(dirname "$0")"# Generate workspaceif [ ! -d workspace ]; thenmkdir -p workspacefi# Concat all migration SQL filesfind ../migrations -name "*.sql" -type f | sort | xargs cat > workspace/migrations.sql# Move to workspacecd workspace# Convert the SQL file to a SQLite databasesqlite3 -init migrations.sql migrations.db ".exit"# Generate drizzle.config.tscat <<EOF > drizzle.config.tsimport { defineConfig } from 'drizzle-kit'export default defineConfig({dialect: "sqlite",dbCredentials: {url: "file:./migrations.db",},out: "./drizzle"})EOF# Generate the schema../../node_modules/.bin/drizzle-kit pull --config drizzle.config.ts# Copy relations.ts and schema.tscp -f drizzle/relations.ts ../relations.tscp -f drizzle/schema.ts ../schema.ts# Remove workspacecd ..rm -rf workspace
これでスキーマを自動で生成してくれます 🎉
...が、なんだかなあ。参考程度に使ってみてください 🙇♂️
おわりに
もうちょっとベストプラクティスがあるような気もしますけどね。ムズイ 🐶