目的
データベースCloudflare D1とAstroのサイトを連携します
今回の投稿の前半ではローカルのDBと接続し、別投稿の後半ではリモートのDB、つまりCloudflareのサーバー上のDBと接続します
つくるもの
こちらをベースにします
メモ(「タイトル」と「内容」のセット)をデータベースから取得し、表示することが今回の実装部分です
本編
全体の流れは、
- データベースを作成
- データベース定義を記述し、テーブルを追加するSQLファイルを生成
- SQLファイルを実行し、データベースにテーブルを追加
- テーブルにデータを追加
- Astroのエンドポイントにデータベースへのアクセス処理を追加
こんな感じです
パッケージのインストール
データベース関連のパッケージdrizzle-orm
、drizzle-kit
とbetter-sqlite3
、CloudflareのCLIwrangler
をインストールします
npm install drizzle-orm drizzle-kit
npm install better-sqlite3
npm install wrangler
データベースの準備
データベースの定義を作成
データベースの定義を作成し、SQLファイルを生成します
import { text, integer, sqliteTable } from 'drizzle-orm/sqlite-core';
export const memos = sqliteTable('memos', {
id: integer('id', { mode: 'number' }).primaryKey({ autoIncrement: true }),
title: text('title'),
content: text('content'),
});
npx drizzle-kit generate --schema=./src/db/schema.ts --dialect=sqlite
↓ 実行結果
> npx drizzle-kit generate --schema=./src/db/schema.ts --dialect=sqlite
drizzle-kit: v0.22.7
drizzle-orm: v0.31.2
1 tables
memos 3 columns 0 indexes 0 fks
[✓] Your SQL migration file ➜ drizzle\0000_flippant_sprite.sql 🚀
drizzle\0000_flippant_sprite.sql
が生成され、以降の工程ではこれを使います
CREATE TABLE `memos` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`title` text,
`content` text
);
CLIでログインする
npx wrangler login
でCLI経由でCloudflareにログインします
npx wrangler login
↓ 実行結果
> npx wrangler login
⛅️ wrangler 3.61.0
-------------------
Attempting to login via OAuth...
Opening a link in your default browser: https://dash.cloudflare.com/oauth2/auth?response_type=code&client_id=XXXXXXXXX
Successfully logged in.
√ Would you like to help improve Wrangler by sending usage metrics to Cloudflare? ... no
Your choice has been saved in the following file: C:\Users\XXXXX\AppData\Roaming\xdg.config\.wrangler\metrics.json.
You can override the user level setting for a project in `wrangler.toml`:
- to disable sending metrics for a project: `send_metrics = false`
- to enable sending metrics for a project: `send_metrics = true`
以下のようにWebブラウザのログイン画面を経由します
データベースを作成する
CLIでデータベースを作成します
npx wrangler d1 create DB20240622
↓ 実行結果
> npx wrangler d1 create DB20240622
⛅️ wrangler 3.61.0
-------------------
✅ Successfully created DB 'DB20240622' in region APAC
Created your new D1 database.
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "DB20240622"
database_id = "xxxx-xxxx-xxxx-xxxx-xxxx"
実行すると、Cloudflareのダッシュボードから、DB20240622
というデータベースがつくられていることが確認できます
データベースのコンフィグファイルを作成
前述の操作で出力された設定記述をwrangler.toml
を作成して、記載します
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "DB20240622"
database_id = "xxxx-xxxx-xxxx-xxxx-xxxx"
SQLファイルを実行
以下のコマンドで作成済みのSQLファイルを実行します
--local
がローカルに対する操作を意味し、--remote
だとCloudflareサーバー上の本番のデータベースに対して操作します
npx wrangler d1 execute DB20240622 --local --file=./drizzle/0000_flippant_sprite.sql
↓ 実行結果
> npx wrangler d1 execute DB20240622 --local --file=./drizzle/0000_flippant_sprite.sql
⛅️ wrangler 3.61.0
-------------------
🌀 Executing on local database DB20240622 (9c560d0f-03b8-477b-93dc-9da3f3fc3c3e) from .wrangler\state\v3\d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
Drizzle Studio向けにデータベース情報をセットする
drizzle.config.ts
を作成し、url
に前述のコマンドで作成された.wrangler/state/v3/d1/miniflare-D1DatabaseObject/XXXX.sqlite
を設定します
import { defineConfig } from "drizzle-kit"
export default defineConfig({
dialect: "sqlite",
dbCredentials: {
url: ".wrangler/state/v3/d1/miniflare-D1DatabaseObject/5f5a9139cd06e3a10deff13ceaa03bbc42bab7d3570f17a28f257aac74162e52.sqlite",
},
})
データベースをDrizzle Studioで確認する
drizzle-kit
に含まれているDrizzle Studioを使い、Webブラウザからデータベースにアクセスしてみます
コマンドは以下の通りです
npx drizzle-kit studio
↓ 実行結果
> npx drizzle-kit studio
drizzle-kit: v0.22.7
drizzle-orm: v0.31.2
No config path provided, using default path
Reading config file 'E:\github\20240622\drizzle.config.ts'
Warning Drizzle Studio is currently in Beta. If you find anything that is not
working as expected or should be improved, feel free to create an issue on GitHub: https://github.com/drizzle-team/drizzle-kit-mirror/issues/new or write to us
on Discord: https://discord.gg/WcRKz2FFxN
Drizzle Studio is up and running on https://local.drizzle.studio
https://local.drizzle.studio
にアクセスすると、以下のようにデータベースを確認できます
作成済みのmemos
テーブルが存在することがわかります
データベースにデータを追加しておく
続いて、データを追加してみます
npx wrangler d1 execute DB20240622 --local --command="insert into memos (title,content) values('Learn D1','contentcontent')"
↓ 実行結果
> npx wrangler d1 execute DB20240622 --local --command="insert into memos (title,content) values('Learn D1','contentcontent')"
⛅️ wrangler 3.61.0
-------------------
🌀 Executing on local database DB20240622 (xxx-xxx-xx-xxxx-xxxx) from .wrangler\state\v3\d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
Drizzle Studioで確認すると、データが追加されています
ついでに、もう1件のデータを追加しておきました
Astroからデータベースへアクセス
AstroにCloudflareアダプター追加
Cloudflareにアクセスできるようにアダプターを追加します
@astrojs/cloudflare
を追加し、その後、astro.config.mjs
へ設定を追加します
npx astro add @astrojs/cloudflare
↓ 実行結果
> npx astro add @astrojs/cloudflare
✔ Resolving packages...
Astro will run the following command:
If you skip this step, you can always run it yourself later
╭──────────────────────────────────────────╮
│ npm install @astrojs/cloudflare@^11.0.0 │
╰──────────────────────────────────────────╯
√ Continue? ... yes
✔ Installing dependencies...
Check our deployment docs for @astrojs/cloudflare to update your "adapter" config.
success Configuration up-to-date.
設定は以下のように、adapter: cloudflare()
を追加します
import { defineConfig } from 'astro/config';
import vue from "@astrojs/vue";
import cloudflare from "@astrojs/cloudflare";
// https://astro.build/config
export default defineConfig({
integrations: [vue()],
output: 'server',
adapter: cloudflare()
});
エンドポイントへデータベースへのアクセス処理を追加
エンドポイントの処理では、locals.runtime.env
から環境変数にアクセスできます
このとき、.env.d.ts
に記述を追加しないといけない気がしますが、今のところは追加しなくとも動いているので、ひとまず無視しておきます
.env.d.tsに必要な気がする記載
/// <reference types="astro/client" />
type D1Database = import("@cloudflare/workers-types").D1Database;
type ENV = {
DB: D1Database;
};
// use a default runtime configuration (advanced mode).
type Runtime = import("@astrojs/cloudflare").Runtime<ENV>;
declare namespace App {
interface Locals extends Runtime {}
}
必要そうだったら、上記をご参考にどうぞ
src/pages/v1/memo.ts
は以下のように書きました
データベースにデータが存在しなければダミーデータを使用するようにしていますが、書き方が適切かどうかはわかりません、適当です
import { drizzle } from 'drizzle-orm/d1';
import { memos } from "../../db/schema";
import type { Runtime } from '@astrojs/cloudflare';
export async function GET({ locals }: { locals: Runtime }) {
const envDB = locals.runtime.env.DB as D1Database;
const db = drizzle(envDB);
let memo = await db.select().from(memos);
if (!memo || (Array.isArray(memo) && memo.length === 0)) {
memo = [{ id: 1, title: "DUMMY1", content: "content1" }, { id: 2, title: "DUMMY2", content: "content2" }]
}
return new Response(
JSON.stringify({
body: { memos: memo }
}), { status: 200 }
);
}
動作確認
動作確認をしてみます
npm run dev
よさそうです
まとめ
以上で、ローカルのデータベースにアクセスして、データを取得することができました
後半ではリモートの、Cloudflareのデータベースに対して、処理をおこなってみます