hono, prisma, zod, cloudflare

Naoki Tomita Naoki Tomita December 26th, 2025 #life #typescript

今年からプログラマーの仕事はぐっと減らし、リモートで週2,3日程度の範囲で受けています。ちょうど、fluct時代にお世話になったもっちーさんが独立してさっそく困っているということでお手伝いをしてました。【PR】もっちーさんはお手伝いを募集中!

1年ほどやってみての所感を放流しておきます。全体的にはAIに向いていて楽

Cloudflare

Cloudflareは以前かSimpleというよりEasyなのだがよくできてて好き。めんつゆ最高

DuckDBを使いたくて(Betaの)Cloudflare Containers使ったが、npm run dev から裏でdocker build/runが走ってすんなり使え、「お、wrangler.jsoncにBindingを記述したらコンテナがDIされた」と感心した。1

Hono

OpenAPI定義をどちらでやるか

@hono/zod-openapihono-openapi を使う2パターンがあって名前も似てて検索結果も混じりやすい。標準honoのapi2 に乗っかる方が好みなので、middlewareスタイルであるhono-openapiの方を利用した。とはいえ、実ハンドラーコードの前にどっかりopenapiの定義、その後どっかりzodの定義が重なるので見通しは微妙。

CIでopenapi.jsonを生成するのを入れてたが、ある時なぜかdescribeRoute()の記述が取れないハンドラーがあった。調べたら「onError()定義があるsub app」で起きるエッジケースだったようなので、PRを送った→※merge済

Prisma

型とスキーマ管理が欲しいし有名だから選択したけど…、若干後悔している。ORMはやっぱ自分の足元を撃ちますな。kyselyとかの方が良かったかなあ

現在、最新版がブロッカーになっていて辛い。あとバージョンあげるにしても、zod, hono-openapi, honoあたりまとめて+かつ作成されたtype/clientを共用しているfront側アプリなどまとめて上げるがんばりが必要でダルい

prisma generator(@prisma/generator-helper)は楽しい

protobufを思い出した。今回作るのがActive RecordっぽいCRUDハンドラーばかりだったので、まるっとgenereate。DMMF構造体がもっと(リレーションの情報とか)メタ情報が取れれば良いのだけど、モデル名・テーブル名・フィールド名だけでもけっこうやりたいことはできる

CIでのファイルの生成時(つまりcloudflare環境ではないnode環境)で、cloudflare:workers moduleが読まれると動かないので、遅延読み込みにするのをして対応したがもっといいやり方があるのかもしれない

const { getContainer } = await import('@cloudflare/containers')

実際こんな感じのgenerate祭りで成果物はほぼほぼ自動生成

                 ┌─▶ D1 migrations
                 │
 schema.prisma ──┼─▶ prisma client
                 ├─▶ ERD
                 ├─▶ zod schemata / types
                 └─▶ handlers(hono) ────▶ openapi.json
                                            └─▶ api/README.md

package.jsonのscriptsで依存順管理に、npm-run-all2を使った

  "scripts": {
    ...
    "generate": "run-s generate:*",
    "generate:cf-type": "wrangler types --env-interface CloudflareBindings",
    "generate:schema-format": "prisma format",
    "generate:schema-generates": "prisma generate",
    "generate:api-openapi.json": "npx --yes tsx doc/openapi-generator.ts",
    "generate:api-readme.md": "npx --yes openapi-to-md doc/openapi.json > doc/README.md"
  },

D1 migrationをどちらでやるか

prismaを使う場合、Cloudflare D1のマイグレーション管理のやり方は2パターンあるが、今回ターゲットがD1ということと+prismaのロックオンを避けたい気持ちでBのwranglerコマンドを使う方にした。

具体的には、schema.prismaをいい感じにしたあと、こんなので差分をmigrationファイルとして出力させて(必要なら微調整)

npx prisma migrate diff --from-local-d1 --to-schema-datamodel schema.prisma --script > db/migrations/0002_aaaaa.sql

ローカルで適用して確認、その後本番適用

find .wrangler/state/v3/d1/miniflare-D1DatabaseObject/ -type f -name '*.sqlite' -delete
npx wrangler --env test d1 migrations apply test-db --local
  1. 実稼働には、暖気設定とかがほしくなりそうではある。batchで暖気を入れている 

  2. honoのapiはmiddleware/handlerが、next呼ぶか/returnするかの違いってのが綺麗なデザインだなと思うところ。