d1-drizzle-schema について
Cloudflare D1 固有の SQLite 制約に対応した Drizzle ORM スキーマを作成するスキルです。テーブル設計から設定、マイグレーション、文書化までを案内します。
主な機能
- 01D1 対応の Drizzle スキーマ生成
- 02D1 の型と制限への対応
- 03リレーション定義と推論型の出力
- 04Drizzle 設定テンプレートの提供
- 05マイグレーションスクリプトとスキーマ文書の追加
活用シーン
- 01Cloudflare D1 データベースのテーブル設計
- 02一括挿入時のパラメーター上限への対処
- 03スキーマ構造とマイグレーション手順の記録
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill d1-drizzle-schemaインストール後、Claude Code で/d1-drizzle-schemaを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/drizzle-config-template.tsschema-template.tsreferences/column-patterns.mdd1-specifics.md詳細
D1 Drizzle スキーマ
Cloudflare D1 用の正しい Drizzle ORM スキーマを生成します。D1 は SQLite ベースですが、標準的な SQLite のパターンを使うと微妙なバグにつながる重要な違いがあります。このスキルでは、D1 の制約に正しく対応するスキーマを生成します。
D1 の重要な違い
| 機能 | 標準の SQLite | D1 |
|---|---|---|
| 外部キー | デフォルトで OFF | 常に ON(無効化できません) |
| Boolean 型 | なし | なし — integer({ mode: 'boolean' }) を使用 |
| Datetime 型 | なし | なし — integer({ mode: 'timestamp' }) を使用 |
| バインドパラメーターの最大数 | 約 999 | 100(一括挿入に影響します) |
| JSON サポート | 拡張機能 | 常に利用可能(json_extract、->、->>) |
| 並行処理 | 複数ライター | シングルスレッド(一度に 1 つのクエリ) |
ワークフロー
ステップ 1:データモデルを記述する
要件を確認します。どのテーブルが必要か、どのようなリレーションがあるか、何にインデックスを設定する必要があるかを整理します。既存の説明に基づいて作業する場合は、スキーマを直接推定します。
ステップ 2:Drizzle スキーマを生成する
D1 に適したカラムパターンを使ってスキーマファイルを作成します。
import { sqliteTable, text, integer, real, index, uniqueIndex } from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
// UUID primary key (preferred for D1)
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
// Text fields
name: text('name').notNull(),
email: text('email').notNull(),
// Enum (stored as TEXT, validated at schema level)
role: text('role', { enum: ['admin', 'editor', 'viewer'] }).notNull().default('viewer'),
// Boolean (D1 has no BOOL — stored as INTEGER 0/1)
emailVerified: integer('email_verified', { mode: 'boolean' }).notNull().default(false),
// Timestamp (D1 has no DATETIME — stored as unix seconds)
createdAt: integer('created_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
updatedAt: integer('updated_at', { mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
// Typed JSON (stored as TEXT, Drizzle auto-serialises)
preferences: text('preferences', { mode: 'json' }).$type<UserPreferences>(),
// Foreign key (always enforced in D1)
organisationId: text('organisation_id').references(() => organisations.id, { onDelete: 'cascade' }),
}, (table) => ({
emailIdx: uniqueIndex('users_email_idx').on(table.email),
orgIdx: index('users_org_idx').on(table.organisationId),
}))
型の完全なリファレンスについては、references/column-patterns.md を参照してください。
ステップ 3:リレーションを追加する
Drizzle のリレーションはクエリビルダーのヘルパーであり、外部キー制約とは別のものです。
import { relations } from 'drizzle-orm'
export const usersRelations = relations(users, ({ one, many }) => ({
organisation: one(organisations, {
fields: [users.organisationId],
references: [organisations.id],
}),
posts: many(posts),
}))
ステップ 4:型をエクスポートする
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert
ステップ 5:Drizzle の設定を行う
assets/drizzle-config-template.ts を drizzle.config.ts にコピーし、スキーマのパスを更新します。
ステップ 6:マイグレーションスクリプトを追加する
package.json に追加します。
{
"db:generate": "drizzle-kit generate",
"db:migrate:local": "wrangler d1 migrations apply DB --local",
"db:migrate:remote": "wrangler d1 migrations apply DB --remote"
}
テストの前に、必ずローカルとリモートの両方で実行してください。
ステップ 7:DATABASE_SCHEMA.md を生成する
今後のセッションに備えて、スキーマを文書化します。
- テーブル、カラム、型、制約
- リレーションと外部キー
- インデックスとその目的
- マイグレーションのワークフロー
一括挿入のパターン
D1 のバインドパラメーター数は 100 に制限されています。バッチサイズを計算します。
const BATCH_SIZE = Math.floor(100 / COLUMNS_PER_ROW)
for (let i = 0; i < rows.length; i += BATCH_SIZE) {
await db.insert(table).values(rows.slice(i, i + BATCH_SIZE))
}
D1 ランタイムの使用方法
import { drizzle } from 'drizzle-orm/d1'
import * as schema from './schema'
// In Worker fetch handler:
const db = drizzle(env.DB, { schema })
// Query patterns
const all = await db.select().from(schema.users).all() // Array<User>
const one = await db.select().from(schema.users).where(eq(schema.users.id, id)).get() // User | undefined
const count = await db.select({ count: sql`count(*)` }).from(schema.users).get()
リファレンスファイル
| タイミング | 参照先 |
|---|---|
| D1 と SQLite の違い、JSON クエリ、制限 | references/d1-specifics.md |
| Drizzle と D1 のカラム型パターン | references/column-patterns.md |
アセット
| ファイル | 用途 |
|---|---|
| assets/drizzle-config-template.ts | D1 用の Drizzle 設定ファイルのひな形 |
| assets/schema-template.ts | D1 でよく使われるパターンを網羅したスキーマの例 |