DB スキーマ詳細
DB Schema Details
1. Prisma スキーマ(prisma/schema.prisma)
Prisma Schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL") // Prisma CLI / migrate diff 用(実行時は D1 アダプタ)
}
model Term {
id Int @id @default(autoincrement())
name String @unique
abbreviation String?
category String?
description String
descriptionImageKey String?
descriptionImageSlimKey String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
実行時は@prisma/adapter-d1とenv.DB(D1Database)を使用する。providerは"sqlite"のまま(D1 は SQLite 互換)。DATABASE_URLはアプリの D1 接続には使わない。
2. ER 図
ER Diagram
アプリが管理するデータは Term テーブル 1 本。画像ファイルは R2 に格納し、D1 にはキー文字列のみ保持する。
%%{init: {'theme': 'default', 'themeVariables': {'fontSize': '13px'}}}%%
erDiagram
Term {
int id PK "AUTOINCREMENT"
string name UK "NOT NULL / UNIQUE"
string abbreviation "nullable"
string category "nullable"
string description "NOT NULL"
string descriptionImageKey "nullable / R2 original key"
string descriptionImageSlimKey "nullable / R2 slim key"
datetime createdAt "DEFAULT CURRENT_TIMESTAMP"
datetime updatedAt "Auto-updated"
}
PK = Primary Key / UK = Unique Key / nullable フィールドは Prisma では String?
R2 画像キーの仕組み
R2 Image Key Structure
%%{init: {'theme': 'default', 'themeVariables': {'fontSize': '13px', 'lineColor': '#9ca3af', 'edgeLabelBackground': '#fff'}}}%%
flowchart LR
Upload["画像アップロード\nPOST /api/terms/:id/image"]
R2O["R2\nterms/original/{key}"]
Queue["Queues\naws-glossary-image-optimize"]
Worker["画像最適化 Worker"]
R2S["R2\nterms/slim/{key}.webp"]
DB["D1 Term テーブル\ndescriptionImageKey\ndescriptionImageSlimKey"]
Upload -->|"R2 put"| R2O
Upload -->|"produce"| Queue
Queue -->|"consume"| Worker
Worker -->|"WebP 生成 → put"| R2S
Worker -->|"slim-key 書き込み"| DB
R2O -->|"original key 保存"| DB
style R2O fill:#f0fdf4,stroke:#22c55e,color:#15803d
style R2S fill:#f0fdf4,stroke:#22c55e,color:#15803d
style DB fill:#eff6ff,stroke:#3b82f6,color:#1d4ed8
style Queue fill:#fdf4ff,stroke:#c026d3,color:#7e22ce
スリムキーが存在しない場合、GET /api/media/:key はオリジナルキーの URL を返す
3. テーブル定義
Table Definitions
Term テーブル
Term Table
| カラム名 | 型 | 制約 | 説明 |
|---|---|---|---|
| id | INTEGER | PK NOT NULL AUTOINCREMENT | 主キー |
| name | TEXT | UNIQUE NOT NULL | 用語名(重複登録防止) |
| abbreviation | TEXT | nullable | 略称・略語(例: EC2, S3) |
| category | TEXT | nullable | カテゴリ(例: Compute, Storage) |
| description | TEXT | NOT NULL | 用語の説明文 |
| descriptionImageKey | TEXT | nullable | R2 オリジナル画像キー(terms/original/…) |
| descriptionImageSlimKey | TEXT | nullable | R2 軽量版キー(terms/slim/….webp)。Worker が生成後に書き込む |
| createdAt | DATETIME | NOT NULL DEFAULT NOW | 作成日時 |
| updatedAt | DATETIME | NOT NULL AUTO UPDATE | 最終更新日時 |
4. マイグレーション管理(wrangler d1 migrations)
Migration Management
Prisma Migrate の代わりに prisma migrate diff で SQL を生成し、prisma/migrations/ に手動で配置する。適用は wrangler d1 migrations apply で行う。
マイグレーションファイル構成
Migration File Structure
prisma/
├── migrations/
│ ├── 0001_init.sql
│ ├── 0002_description_image_key.sql
│ └── 0003_description_image_slim_key.sql
└── schema.prisma
0001_init.sql
-- CreateTable
CREATE TABLE "Term" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL,
"abbreviation" TEXT,
"category" TEXT,
"description" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "Term_name_key" ON "Term"("name");
マイグレーション実行コマンド
Migration Commands
# ローカル D1 にマイグレーションを適用
pnpm wrangler d1 migrations apply aws-glossary-db --local
# 本番 D1 にマイグレーションを適用
pnpm wrangler d1 migrations apply aws-glossary-db --remote
# マイグレーション状態の確認
pnpm wrangler d1 migrations list aws-glossary-db --local
スキーマ変更時の手順
Schema Change Procedure
# 1. schema.prisma を編集
# 2. 差分 SQL を確認(新規ファイルを prisma/migrations/0004_xxx.sql で追加)
pnpm prisma migrate diff \
--from-empty \
--to-schema-datamodel prisma/schema.prisma \
--script
# 3. ローカル D1 に適用して動作確認
pnpm wrangler d1 migrations apply aws-glossary-db --local
# 4. Prisma Client を再生成
pnpm prisma generate
# 5. 本番に適用
pnpm wrangler d1 migrations apply aws-glossary-db --remote
5. D1 データベースのセットアップ手順
D1 Database Setup
# 1. D1 データベースを作成
pnpm wrangler d1 create aws-glossary-db
# → 出力例(この database_id を wrangler.toml に貼り付ける):
# [[d1_databases]]
# binding = "DB"
# database_name = "aws-glossary-db"
# database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# 2. ローカルにマイグレーション適用
pnpm wrangler d1 migrations apply aws-glossary-db --local
# 3. シードデータ投入(ローカル)
pnpm wrangler d1 execute aws-glossary-db --local --file=prisma/seed.sql
6. 環境変数・バインディング設定
Environment Variables & Binding Configuration
D1 Database
env.DB
binding = "DB"
全 CRUD 操作・Prisma アダプタ経由
全 CRUD 操作・Prisma アダプタ経由
R2 Bucket
env.TERM_IMAGES
binding = "TERM_IMAGES"
画像アップロード・プロキシ配信
画像アップロード・プロキシ配信
Queues Producer
env.IMAGE_OPTIMIZE_QUEUE
binding = "IMAGE_OPTIMIZE_QUEUE"
画像最適化ジョブをプロデュース
画像最適化ジョブをプロデュース
Secret
ADMIN_PASSWORD_HASH
管理者パスワードの HMAC ハッシュ
wrangler secret put で設定wrangler.toml
name = "aws-glossary"
main = ".open-next/worker.js"
compatibility_date = "2024-09-23"
compatibility_flags = ["nodejs_compat", "global_fetch_strictly_public"]
[assets]
directory = ".open-next/assets"
binding = "ASSETS"
[[services]]
binding = "WORKER_SELF_REFERENCE"
service = "aws-glossary"
[[d1_databases]]
binding = "DB"
database_name = "aws-glossary-db"
database_id = "<D1_DATABASE_ID>"
migrations_dir = "prisma/migrations"
[[r2_buckets]]
binding = "TERM_IMAGES"
bucket_name = "aws-glossary-images"
# ローカルは Miniflare の in-memory R2(remote=true は付けない)
[[queues.producers]]
binding = "IMAGE_OPTIMIZE_QUEUE"
queue = "aws-glossary-image-optimize"
.dev.vars(ローカル開発用・gitignore 対象)
# wrangler dev が読み込む環境変数
# D1 は wrangler.toml のバインディングで管理するため DATABASE_URL は不要
# 管理者パスワードなど必要な変数をここに追記する
D1 はDATABASE_URLではなくenv.DB(D1Database オブジェクト)としてバインディング経由でアクセスする。.envのDATABASE_URLは Prisma CLI 用のみ。
7. シードデータ(prisma/seed.sql)
Seed Data
マスターデータは prisma/seed-data.ts に定義し、pnpm db:seed:generate で prisma/seed.sql を生成する。生成 SQL は name 一意で UPSERT(既存行の説明も更新できる)。
pnpm db:seed:generate # seed-data.ts → seed.sql を再生成
pnpm db:seed:local # ローカル D1 へ投入
# pnpm db:seed:remote # リモート D1 へ投入(本番データに影響するため注意)
8. テストと D1
Testing & D1
-
Unit
Vitest —
src/**/*.test.{ts,tsx}(ソースと同ディレクトリにコロケーション)
スキーマ・Zod・Jotai atoms など DB に依存しない検証。tests/unit/は使用しない。 -
Integration
Vitest + @cloudflare/vitest-pool-workers —
pnpm test:integration
wrangler.integration.toml上の D1 に対し Prisma 経由でlistTerms等を検証する。 -
E2E
Playwright —
pnpm test:e2e
playwright.config.tsのwebServerでpnpm dev:e2e(マイグレーション+シード後のnext dev)を起動して実行する。