d1zzle — Cloudflare D1 専用の型安全 ORM(OSS)

Drizzle の書き味そのままに、Cloudflare D1 と Workers だけを対象に作り直した ORM。バンドルサイズを minified で 43% 削減しました。

担当範囲
設計・実装・メンテナンス(個人 OSS)
期間
開発・公開中
技術スタック
TypeScript Cloudflare D1 Cloudflare Workers vitest

なぜ自作したのか

Cloudflare D1 で開発していると、汎用 ORM の「他のデータベースにも対応するための層」が そのまま Worker のバンドルに乗ってきます。方言(dialect)の間接層、トランザクションと セーブポイントのサブシステム、同期ドライバと非同期ドライバの両方を覆う prepared statement の抽象 — これらは SQLite のエントリポイントから到達可能なため、どんな バンドラでも tree-shaking では落とせません。tree-shaking が消せるのは到達不能な コードであって、汎用的なコードではないからです。

d1zzle は、それをソースの時点で取り除いたライブラリです。API は Drizzle から そのまま受け継いでいるので、既存の知識で書けます。

import { drizzle, eq, integer, sqliteTable, text } from 'd1zzle';

export const users = sqliteTable('users', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  email: text('email').notNull().unique(),
  name: text('name'),
});

const db = drizzle(env.DB);
const one = await db.select().from(users).where(eq(users.id, 1)).get();

効果

ドライバ・スキーマ DSL・1 本の select().from().where() を含む Worker を esbuild で バンドルした比較です。

minifiedgzipped
drizzle-orm/d1 + drizzle-orm/sqlite-core77.8 kB22.2 kB
d1zzle44.1 kB15.3 kB
−43%−31%

対象を 1 つに絞ると、削れるものが増えるだけでなく、他のデータベースに対応物がない D1 固有の機能を第一級で扱えるようになります。D1 の位置指定リードパス、 バインドパラメータの上限、Sessions API、課金カウンタといった要素が、抽象化の 向こう側ではなく API の表面に出てきます。

実プロダクトでの利用

d1zzle は「作って公開して終わり」のライブラリではなく、あるくとまるの 本番環境で全面採用しています。認証基盤の Better Auth も、d1zzle のネイティブ アダプタ(d1zzle/better-auth)経由で同じ ORM の上に乗せています。使いながら 見つかった癖は利用側リポジトリのノートに書き出し、ライブラリ本体の改善に戻す サイクルで運用しています。