へんてこのブログ

日々気づいたことや、最近やっていることを書いています

Hono + Prisma + Cloudflare D1のローカル開発環境を構築する

やりたいことは、HonoとPrisma(SQLite)とCloudflare D1を組み合わせた開発環境を、ローカルで構築することです。 最終的にはCloudflare WorkersとCloudflare D1で構築したAPIサーバーを立てることが目標ですが、まずはローカルで一通り動くまでやりたい。

プロジェクトの作成

まずはおもむろにHonoプロジェクトを作成します。

yarn create hono

色々聞かれますが、いい感じに答えます。今回はHonoをCloudflare Workersに載せることを見越しているので、Workersを選択します。

色々終わったらとりあえずローカルサーバーを立ち上げます。

yarn dev

http://localhost:8787 をブラウザで開いたらいい感じに動いてました。簡単だね。

Prismaのインストール

次はDBを用意したいので、Prismaを入れます。

yarn add -D prisma

インストールできたら、今回はCloudflare D1で動かしたいのでSQLiteでPrismaを初期化します。

yarn prisma init --datasource-provider sqlite

prisma/schema.prisma が作成されるので、適当にモデルを追記します。今回はTodosモデルを入れました。

model Todos {
  id           Int     @id @default(autoincrement())
  title        String
  description  String
}

Cloudflare D1用の設定を追加

ここからはCloudflare D1用の設定をやっていきます。最初なんでローカルなのにCloudflareの設定しないといけないのか謎だったけど、開発環境がwrangler使ってるからなんだね、理解。

まずはPrismaでCloudflare D1を扱う用のadapterをインストールする。ついでにClientもインストールしておく。

yarn add @prisma/client @prisma/adapter-d1

prisma/schema.prisma のclient記述にAdapterの追記を行う。

generator client {
  provider = "prisma-client-js"
  previewFeatures = ["driverAdapters"]
}

Cloudflare D1のローカルDBを作成する

次はローカルにDBを作っていきます。作るといってもSQLiteの場合はファイルだけど。

wrangler.toml に以下を追記します。ついでに compatibility_flags = ["nodejs_compat"] もアンコメントしておきます。理由は特に分かってません。

compatibility_flags = ["nodejs_compat"]

[[d1_databases]]
binding = "DB"
database_name = "d1-database"
database_id = "1"

database_nameには好きなデータベース名をつけましょう。database_idにはlocalなので空文字でなければいいみたいです。

そしてmigrationファイルを作っていきます。

yarn wrangler d1 migrations create d1-database create_todos_table

これで migrations/0001_create_todos_table.sql みたいな空ファイルが生成されます。

このSQLファイルに対して、Prismaのmigrationを実行してSQLを入れてあげましょう。

yarn prisma migrate diff --from-empty --to-schema-datamodel ./prisma/schema.prisma --script --ou
tput migrations/0001_create_todos_table.sql

これでこんなのが生成されました。良さそうですね。

-- CreateTable
CREATE TABLE "Todos" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "title" TEXT NOT NULL,
    "description" TEXT NOT NULL
);

ちなみに次回以降のカラム追加時のmigrateでは、以下のように --from-empty 部分を --from-local-d1 にしましょう。

yarn prisma migrate diff --from-local-d1 --to-schema-datamodel ./prisma/schema.prisma --script --ou
tput migrations/0002_add_status_to_todos.sql

次にこのmigrationをapplyしましょう。--localをつけるのを忘れずに。

yarn wrangler d1 migrations apply d1-database --local

これでDBの設定は終了です。

コードからDBを参照してみる

src/index.ts を編集して、DBを参照してみましょう。 PrismaD1などのアダプターをimportして、PrismaClientを生成することで、Todosテーブルを参照可能です。

import { Hono } from 'hono'
import { PrismaClient } from '@prisma/client';
import { PrismaD1 } from '@prisma/adapter-d1';

type Bindings = {
  DB: D1Database;
};

const app = new Hono<{Bindings: Bindings}>()

app.get('/', async (c) => {
  const adapter = new PrismaD1(c.env.DB);
  const prisma = new PrismaClient({ adapter });

  await prisma.todos.create({
    data: {
      title: 'example title',
      description: 'example description',
    }
  });

  const todos = await prisma.todos.findMany();
  return c.json({ todos: todos })
})

export default app

これでサーバーを立ち上げて、アクセスするごとにTodoが増えたら完了です。

yarn dev

さいごに

この方法だとPrisma StudioがClientエラーになってしまう。おそらくAdapterが設定されておらず、D1のDBを参照できてないと思われる。どうすればいいのかわからないので誰か教えて欲しい。

参考リンク