LoginSignup
8
2

More than 1 year has passed since last update.

先月あたりにalphaバージョンが公開されたCloudFlare D1をHonoと組み合わせて使います。
Honoは今回初めて使ったのですが、かなりシンプルで使いやすく今後も使っていきたい気分になりました。

Hono v2.6.2 + CloudFlare D1(Alpha) で記事を書いています。

CloudFlare D1はAlpha版です。現在も頻繁に更新があるため、記事執筆時点と情報が異なる可能性があります。

CloudFlare WorkersとHonoをセットアップ

以下のコードで準備完了です。簡単ですね。

npx wrangler init donesample
cd donesample
npm install hono

申し訳程度にHello worldも書いてみます。

src/index.ts
import { Hono } from "hono";

const app = new Hono();
app.get("/", (c) => c.text("Hello"));

export default app;

実行は以下のコマンドで。

npm start

# curl localhost:8787
# -> Hello

D1を使う

公式のドキュメントを参考に実装します。

データベースを作成する

wranglerコマンドから作成できます。

npx wrangler d1 create myfirstdone

出力は以下です。alphaバージョンなので注意書きがあります。

🚧 D1 is currently in open alpha and is not recommended for production data and traffic.
Please report any bugs to https://github.com/cloudflare/wrangler2/issues/new/choose.
To request features, visit https://community.cloudflare.com/c/developers/d1.
To give feedback, visit https://discord.gg/cloudflaredev
✅ Successfully created DB 'myfirstdone3'!

Add the following to your wrangler.toml to connect to it from a Worker:

[[ d1_databases ]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "myfirstdone"
database_id = "fddb99d1-b44d-4334-a84e-2a67e57d59ac"

wrangler.tomlを確認するとD1データベースの定義が追加されているはずです。なければさきほどのコンソールの出力をもとに追加してください。

wrangler.toml
# ...

[[ d1_databases ]]
binding = "DB"
database_name = "myfirstdone"
database_id = "3b9c4f9b-e4d1-4176-8d44-378e97c7aa46"

データベースのセットアップ

db/schema.sql を作成します。

db/schema.sql
DROP TABLE IF EXISTS Urls;
CREATE TABLE Urls (
    ID INT,
    Url TEXT,
    Description TEXT,
    PRIMARY KEY (`Id`)
);
INSERT INTO Urls(
    ID,
    Url,
    Description
) VALUES
    (9999999, 'https://google.com', 'Test url'),
    (9999998, 'https://yahoo.co.jp', 'Test url2')
;

以下のコマンドでSQLを実行します。

wrangler d1 execute myfirstdone --local --file=./db/schema.sql

HonoからD1内のデータを取得する

Honoの公式サンプルをもとにBindingを定義します。

準備

wranglerコマンドから作成した場合は D1Database というクラスが定義されているので、以下のように追記します。

src/binding.d.ts
export interface Bindings {
  DB: D1Database;
}

declare global {
  function getMiniflareBindings(): Bindings;
}

APIを実装

URLを記録するAPIを例に実装します。

src/urls.ts
import { Hono } from 'hono';
import { Bindings } from './bindings';

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

interface Url {
  Id: number;
  Url: string;
  Description: string;
}

urls.get("/", async (ctx) => {
  const env = ctx.env;
  const stmt = env.DB.prepare("SELECT * from Urls");
  const { results } = await stmt.all<Url>();
  return ctx.json({ message: results?.map((r) => r.Url) });
});

export default urls;

Honoクラスのインスタンスを作成する際にBindingsを渡さないと、D1の各種メソッドにアクセスする際に型補完が動作しなくなるので注意です。

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

さきほど定義したBindingsに DB経由で prepare all メソッドで結果にアクセスできます。

  const stmt = env.DB.prepare("SELECT * FROM Urls");
  const { results } = await stmt.all<Url>();

変数も割り当て可能です。

env.DB.prepare("SELECT * FROM Urls WHERE Id = ? AND Url = ?").bind(id, url);

all メソッドでSQLのクエリを実行し結果を取得可能ですが、ほかにもいくつか同類のメソッドがあります。利用ケースにあわせて選択しましょう。以下がメソッド一覧です。

  • stmt.first( [column] )
  • stmt.all()
  • stmt.raw()
  • stmt.run()
  • db.dump()
  • db.exec()
  • db.batch()

APIルーティングを追加

以下のように追加します。簡単で良いですね。

src/index.ts
import { Hono } from 'hono';

import urls from './urls';
import { Bindings } from './bindings'

const app = new Hono<{ Bindings: Bindings }>();
app.route("/urls", urls);

export default app;

APIの動作確認

以下のコマンドで開発環境を起動します。

npx wrangler dev --local --persist

起動後、以下のコマンドを実行して開発環境のデータベースをセットアップします。

wrangler d1 execute myfirstdone --file=./db/schema.sql

APIを実行します。

curl -i http://localhost:8787/urls

# -> {"message":["https://google.com","https://yahoo.co.jp"]}

デプロイ

デプロイはとても簡単です。

npx wrangler publish

DBの初期化などクエリの実行も開発環境とほぼ同じです。

wrangler d1 execute myfirstdone --file=./db/schema.sql

DBのマイグレーション

なんとマイグレーション機能もwranglerコマンドに実装されていました。

以下のコマンドを実行すると migrations ディレクトリが作成されて、 0000_hoge.sql というファイルが作成されます。

wrangler d1 migrations create myfirstdone hoge

実行後のSQLファイルの中身は以下です。

-- Migration number: 0000 	 2022-12-18T08:10:32.404Z

SQLファイルを良い感じに書き換えてから以下のコマンドで、マイグレーションを実行します。差分管理もしてくれるので、最後に適用したマイグレーション以降を実行してくれます。実行履歴はDB側に記録している?

wrangler d1 migrations apply --local myfirstdone

便利な機能

任意のSQLクエリを実行する

以下のコマンドで任意のSQLを実行可能です。 --local フラグの有無で実行先も簡単に切り替えられるので気軽に実行できてしまいます。

wrangler d1 execute myfirstdone --local --command='SELECT * FROM Urls'

DBのバックアップ

以下のコマンドでバックアップも作成可能です。定期的にCloudFlare側で実行されるバックアップもあります。

wrangler d1 backup create myfirstdone

最後に

まだalpha版ということですが現状でも全然使いやすい感じで開発体験も良かったです。 wrangler d1 コマンドも結構整備されていて、標準的なオペレーションは一通りできそうで個人的にはポイント高かったです。

alpha版ということによる制限もありますが、これが正式リリース後どのくらい緩和されるのかが楽しみです。データベースの容量制限なんかは特に気になります。あとはお値段。

異なるリージョンからアクセスがあったときのデータ同期も検証したかったのですが、とりあえず記事にしたかったのでまた後日。データベースの外に露出させるインタフェースは読み取り専用、という運用ならだいぶ良い感じに運用できるかもしれません。

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2