Open7

Hono × Cloudflare D1を触ってみる

かいとかいと

Workers × Honoでプロジェクト作成をする

今回はhono-d1-appという名前で作成する

$ pnpm create hono@latest hono-d1-app
...
? Which template do you want to use? cloudflare-workers
? Do you want to install project dependencies? yes
? Which package manager do you want to use? pnpm

プロジェクトが作成できたので立ち上げて確認する

pnpm i
pnpm dev

https://localhost:8787/
でローカル環境が立ち上がったのでたたくとHello Hono!と返ってくることが確認できた

参考

https://hono.dev/getting-started/cloudflare-workers

かいとかいと

D1のセットアップ

新規DBを作成する

作成すると接続情報が出力される

$ pnpm wrangler d1 create hono-d1-app
 ⛅️ wrangler 3.51.2
-------------------
✅ Successfully created DB 'hono-d1-app' in region APAC
Created your new D1 database.

[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "hono-d1-app"
database_id = "xxx"

上記の接続情報をwrangler.tomlに追加する

作成されているか確認

Table一覧を出力してDBが作成されているか確認した

 pnpm wrangler d1 execute hono-d1-app --command='select name from sqlite_master where type="table"'

参考

https://developers.cloudflare.com/d1/get-started/#3-create-a-database

かいとかいと

Drizzleの導入

ライブラリインストール

terminal
pnpm add drizzle-orm
pnpm add -D drizzle-kit

schema作成

schema.ts
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";

export const users = sqliteTable("users", {
  userId: integer("userId", { mode: "number" })
    .primaryKey({ autoIncrement: true })
    .notNull(),
  userName: text("userName").notNull(),
});

schemaをもとにmigration用ファイルを作成したいが、driazzle.config.jsonを作成しないといけなさそう

terminal
 pnpm drizzle-kit generate:sqlite
drizzle-kit: v0.20.17
drizzle-orm: v0.30.8

No config path provided, using default 'drizzle.config.json'
/src/hono-d1-app/drizzle.config.json file does not exist

drizzle.config.jsonを作成した

drizzle.config.json
import type { Config } from "drizzle-kit";

export default {
  schema: "./schema.ts",
  out: "./migrations",
  driver: "d1",
  dbCredentials: {
    wranglerConfigPath: "./wrangler.toml",
    dbName: "hono-d1-app",
  },
} satisfies Config;

もう一度migrationを作成すると、./migrations/xxxにjsonファイルが作成されている

terminal
 pnpm drizzle-kit generate:sqlite

migrationファイルが作成されたので、migrationを実行する

terminal
pnpm  wrangler d1 migrations apply hono-d1-app --local

ローカルで実行したいので、--localをつけた

参考

https://orm.drizzle.team/docs/get-started-sqlite#cloudflare-d1

かいとかいと

drizzle studioでcloudflare d1を使ってみたい

https://orm.drizzle.team/drizzle-studio/overview

現在、上記で設定したdrizzle.config.jsはproduction用の設定にしているため、設定を変えないといけない。
ローカルではsqliteファイルを見るように設定する。

drizzle.config.ts
import type { Config } from 'drizzle-kit';

const cfConfig = {
  schema: './src/db/schema.ts',
  out: './src/db/migrations',
  driver: 'd1',
  dbCredentials: {
    wranglerConfigPath: '../wrangler.toml',
    dbName: 'hono-d1-app',
  },
  verbose: false,
  strict: true,
} satisfies Config;

const localConfig = {
  schema: './src/db/schema.ts',
  driver: 'better-sqlite',
  dbCredentials: {
    url: './.wrangler/state/v3/d1/miniflare-D1DatabaseObject/xxx.sqlite',
  },
} satisfies Config;

export default process.env.NODE_ENV === 'production' ? cfConfig : localConfig;

sqliteファイルは、.wrangler/state/v3/d1/miniflare-D1DatabaseObject/xxx.sqlite
にあるようなので、dbCredentialsに追加する
また、ローカルの時だけ、localConfigを見るようにした。

これで起動できる

terminal
$ pnpm drizzle-kit studio

cliで見るより、かなり見やすくなりました。

かいとかいと

できそうなこと

  • schemaを見る
  • 自由にSQLを書く
  • tableを見る
  • データを追加Tableに追加できる
かいとかいと

Relation

https://orm.drizzle.team/docs/rqb#one-to-many

schema.ts
export const User = sqliteTable("users", {
  userId: integer("id", { mode: "number" })
    .primaryKey({ autoIncrement: true })
    .notNull(),
  userName: text("userName").notNull(),
});

export const Post = sqliteTable("posts", {
  postId: integer("id", { mode: "number" })
    .primaryKey({ autoIncrement: true })
    .notNull(),
  title: text("title").notNull(),
  userId: integer("userId")
    .references(() => users.userId)
    .notNull(),
});

export const UserToPostsRelation = relations(User, ({ many }) => ({
  Posts: many(Post),
}));

export const PostsToUserRelations = relations(
  Posts,
  ({ one }) => ({
    user: one(User, {
      fields: [Post.userId],
      references: [User.id],
    }),
  }),
);

https://orm.drizzle.team/docs/rqb#include-relations
上記の形でRelationを作ることで、以下のように一緒に取得することができる

post.ts
const posts = await client.query.posts.findMany({
  with: {
    post: true,
  },
});