55このドキュメントは v2 から v3 への移行計画を立案するための下地(テンプレート)である。各派生プロジェクトはユーザー固有のスキーマ、独自拡張、データ量を持つため、このドキュメントをそのまま実行するのではなく、Phase 1 の事前評価結果を踏まえてプロジェクト固有の移行計画を作成すること。
66
77計画立案の流れ:
8+
891 . このドキュメント全体を読み、フェーズ構成と行動規約を把握する
9102 . Phase 1(バックアップと事前評価)を実行し、ユーザーのスキーマ・データ・独自拡張を分析する
10113 . 分析結果に基づき、各フェーズの具体的なタスクとチェックポイントをプロジェクト固有の計画として文書化する
3132
3233以下のファイルはユーザー固有のカスタマイズを含まない基盤コードであり、v3 キットからそのままコピーする。変換や手書きは不要。
3334
34- | コピー元(v3 キット) | 備考 |
35- | ----------------------| ------|
36- | ` pnpm-workspace.yaml ` | — |
37- | ` oxlintrc.json ` | — |
38- | ` .oxfmtrc.json ` | — |
39- | ` .dockerignore ` | — |
40- | ` packages/db/src/client.ts ` | Proxy 遅延初期化 + globalThis シングルトン |
41- | ` packages/db/src/migrate.ts ` | マイグレーションランナーコアロジック |
42- | ` packages/db/src/dsql-compat.ts ` | SQL 変換 + バリデーション |
43- | ` packages/db/src/cli.ts ` | CLI エントリポイント |
44- | ` packages/db/src/check-dsql-compat.ts ` | drizzle-kit generate 後処理 |
45- | ` packages/db/drizzle.config.ts ` | — |
46- | ` packages/db/package.json ` | — |
47- | ` packages/db/tsconfig.json ` | — |
48- | ` packages/shared-types/package.json ` | — |
49- | ` packages/shared-types/tsconfig.json ` | — |
50- | ` apps/cdk/lib/constructs/database.ts ` | DSQL CfnCluster + IAM 認証 |
51- | ` apps/cdk/lib/constructs/dsql-migrator/ ` | Dockerfile, handler.ts, index.ts 一式 |
52- | ` scripts/dsql.sh ` | 開発用 DSQL クラスタの作成・削除 |
35+ | コピー元(v3 キット) | 備考 |
36+ | ---------------------------------------- | ------------------------------------------ |
37+ | ` pnpm-workspace.yaml ` | — |
38+ | ` oxlintrc.json ` | — |
39+ | ` .oxfmtrc.json ` | — |
40+ | ` .dockerignore ` | — |
41+ | ` packages/db/src/client.ts ` | Proxy 遅延初期化 + globalThis シングルトン |
42+ | ` packages/db/src/migrate.ts ` | マイグレーションランナーコアロジック |
43+ | ` packages/db/src/dsql-compat.ts ` | SQL 変換 + バリデーション |
44+ | ` packages/db/src/cli.ts ` | CLI エントリポイント |
45+ | ` packages/db/src/check-dsql-compat.ts ` | drizzle-kit generate 後処理 |
46+ | ` packages/db/drizzle.config.ts ` | — |
47+ | ` packages/db/package.json ` | — |
48+ | ` packages/db/tsconfig.json ` | — |
49+ | ` packages/shared-types/package.json ` | — |
50+ | ` packages/shared-types/tsconfig.json ` | — |
51+ | ` apps/cdk/lib/constructs/database.ts ` | DSQL CfnCluster + IAM 認証 |
52+ | ` apps/cdk/lib/constructs/dsql-migrator/ ` | Dockerfile, handler.ts, index.ts 一式 |
53+ | ` scripts/dsql.sh ` | 開発用 DSQL クラスタの作成・削除 |
5354
5455以下はユーザー固有の変換が必要なため、コピーではなく手書き・変換する:
5556
56- | ファイル | 理由 |
57- | ---------| ------|
58- | ` packages/db/src/schema.ts ` | ユーザーが追加したテーブル・カラムを含む |
59- | ` packages/db/migrations/ ` | ユーザーのスキーマに対応した初期マイグレーション SQL。v3 キットの ` 0001_initial.sql ` はサンプルスキーマ用なのでコピーしない |
60- | ` packages/shared-types/src/job-payload.ts ` | ユーザーが追加したジョブ型を含む |
61- | ` apps/async-job/src/handler.ts ` | ユーザーが追加したジョブの switch 分岐を含む |
62- | ` apps/async-job/src/jobs/ ` | ユーザーが追加したジョブハンドラを含む |
63- | ` apps/webapp/Dockerfile ` | v3 キットをベースに、ユーザーが追加した依存やビルド引数を反映する |
64- | ` apps/async-job/Dockerfile ` | 同上 |
65- | ` apps/webapp/next.config.ts ` | v3 では ` transpilePackages: ['@repo/db', '@repo/shared-types'] ` の追加が必要。ユーザーの既存設定を保持しつつマージする |
57+ | ファイル | 理由 |
58+ | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
59+ | ` packages/db/src/schema.ts ` | ユーザーが追加したテーブル・カラムを含む |
60+ | ` packages/db/migrations/ ` | ユーザーのスキーマに対応した初期マイグレーション SQL。v3 キットの ` 0001_initial.sql ` はサンプルスキーマ用なのでコピーしない |
61+ | ` packages/shared-types/src/job-payload.ts ` | ユーザーが追加したジョブ型を含む |
62+ | ` apps/async-job/src/handler.ts ` | ユーザーが追加したジョブの switch 分岐を含む |
63+ | ` apps/async-job/src/jobs/ ` | ユーザーが追加したジョブハンドラを含む |
64+ | ` apps/webapp/Dockerfile ` | v3 キットをベースに、ユーザーが追加した依存やビルド引数を反映する |
65+ | ` apps/async-job/Dockerfile ` | 同上 |
66+ | ` apps/webapp/next.config.ts ` | v3 では ` transpilePackages: ['@repo/db', '@repo/shared-types'] ` の追加が必要。ユーザーの既存設定を保持しつつマージする |
6667
6768## Phase 1: バックアップと事前評価
6869
@@ -91,16 +92,17 @@ pg_dump --data-only -h <aurora-endpoint> -U <user> -d <db> > data-v2.sql
9192
9293schema.prisma を主たるデータソースとする。理由: Prisma スキーマはモデル定義が構造化されており、フィールド型・リレーション・デフォルト値の対応関係が明確。ダンプ SQL は PostgreSQL の DDL がそのまま含まれ、DSQL 非互換パターンの分離が困難。schema-v2.sql はインデックスや実行時に追加された制約の確認に補助的に使う。
9394
94- | 検出対象 | DSQL での対処 | 判断基準 |
95- | ---------| -------------| ---------|
96- | ` SERIAL ` / ` BIGSERIAL ` 主キー | ` uuid().defaultRandom() ` または IDENTITY 列 | 既存データに外部参照がある場合は UUID 変換時に参照元も更新が必要 |
97- | ` ENUM ` 型 | ` text() ` + Zod バリデーション | 既存の ENUM 値を洗い出し、Zod スキーマに列挙する |
98- | ` JSON ` / ` JSONB ` カラム | ` text() ` + アプリ層でシリアライズ | 既存データの JSON 構造を確認し、型定義を作成する |
99- | 外部キー制約(` @relation ` ) | 削除(Drizzle ` relations() ` で代替) | アプリ層で参照整合性を担保する必要があるか評価 |
100- | インデックス(` @@index ` ) | ` CREATE INDEX ASYNC ` に変換 | — |
101- | ` Decimal ` / ` Float ` 型 | Drizzle は ` string ` を返す(Prisma は ` number ` ) | アプリコードで数値演算している箇所を特定 |
102- | ` @updatedAt ` | ` .$onUpdate(() => new Date()) ` | — |
103- | ` zod-prisma-types ` 等の生成 Zod スキーマ | 手書きまたは ` drizzle-zod ` で置き換え | 生成ファイルの一覧を特定 |
95+ | 検出対象 | DSQL での対処 | 判断基準 |
96+ | ---------------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
97+ | ` SERIAL ` / ` BIGSERIAL ` 主キー | ` uuid().defaultRandom() ` または IDENTITY 列 | 既存データに外部参照がある場合は UUID 変換時に参照元も更新が必要 |
98+ | ` ENUM ` 型 | ` text() ` + Zod バリデーション | 既存の ENUM 値を洗い出し、Zod スキーマに列挙する |
99+ | ` JSON ` / ` JSONB ` カラム | ` text() ` + アプリ層でシリアライズ | 既存データの JSON 構造を確認し、型定義を作成する。** Prisma は Json 型を自動で parse/stringify するが、Drizzle の text() は手動変換が必要。** Phase 3-4 で全ての読み書き箇所に ` JSON.parse ` /` JSON.stringify ` を追加すること |
100+ | 外部キー制約(` @relation ` ) | 削除(Drizzle ` relations() ` で代替) | ** ` onDelete: Cascade ` / ` onDelete: SetNull ` に依存する削除ロジックを特定すること。** DSQL は FK をサポートしないため、cascade 削除はアプリ層で ` db.transaction() ` 内の明示的な削除に変換が必要 |
101+ | ` String[] ` 型 | ` text() ` + JSON シリアライズ | ** ` pg_dump ` は PostgreSQL 配列リテラル ` {} ` 形式で出力する。** Phase 5-2 のデータ移行時に JSON 配列 ` [] ` に変換が必要(` JSON.parse('{}') ` はオブジェクトを返すため) |
102+ | インデックス(` @@index ` ) | ` CREATE INDEX ASYNC ` に変換 | — |
103+ | ` Decimal ` / ` Float ` 型 | Drizzle は ` string ` を返す(Prisma は ` number ` ) | アプリコードで数値演算している箇所を特定 |
104+ | ` @updatedAt ` | ` .$onUpdate(() => new Date()) ` | — |
105+ | ` zod-prisma-types ` 等の生成 Zod スキーマ | 手書きまたは ` drizzle-zod ` で置き換え | 生成ファイルの一覧を特定 |
104106
105107各テーブルの行数も記録する — 3,000行超のテーブルは Phase 5-2 でバッチ移行が必要。
106108
@@ -135,6 +137,7 @@ v3 キットのディレクトリ構造を参照し、ユーザーのプロジ
135137- ` packages/shared-types/ ` を新規作成
136138
137139ユーザーが追加した独自コードの配置先を判断する:
140+
138141- DB アクセスを含む共有ロジック → ` packages/ ` 配下に抽出を検討
139142- webapp 固有のロジック → ` apps/webapp/ ` に残す
140143- 非同期ジョブ → ` apps/async-job/src/jobs/ ` に移動し、ペイロード型を ` packages/shared-types/ ` に追加
@@ -163,6 +166,7 @@ rg 'npm |npx ' -g '!node_modules' -g '!pnpm-lock.yaml'
163166```
164167
165168主な変換:
169+
166170- ` npm ci ` → ` pnpm install --frozen-lockfile `
167171- ` npm run <script> ` → ` pnpm run <script> `
168172- ` npx <cmd> ` → ` pnpm exec <cmd> `
@@ -212,10 +216,13 @@ pnpm --filter @repo/db run generate
212216ユーザーのコードベースで Prisma を import している全ファイルを特定し(` rg '@prisma|from.*prisma' --type ts ` )、Drizzle API に変換する。v3 キットの Server Action 実装を参照パターンとして使うこと。
213217
214218主な変換ポイント:
219+
215220- ` import { prisma } from '@/lib/prisma' ` → ` import { db } from '@repo/db/client' `
216221- ` import { ... } from '@prisma/client' ` → ` import { ... } from '@repo/db/schema' `
217222- v2 の ` prisma.ts ` (リトライ拡張付き PrismaClient)は削除。DSQL は IAM 認証で接続し、Aurora v2 のコールドスタート・idle timeout 問題がないためリトライロジックは不要
218223- ` next.config.ts ` に ` transpilePackages: ['@repo/db', '@repo/shared-types'] ` を追加(ユーザーの既存設定を保持しつつマージ)
224+ - ** Json カラムの全使用箇所を洗い出す** (` rg 'Json|\.json\b' --type ts ` でスキーマ定義と読み書き箇所を特定)。Prisma は Json 型を自動で parse/stringify するが、Drizzle の ` text() ` は手動変換が必要。読み出し時に ` JSON.parse() ` 、書き込み時に ` JSON.stringify() ` を追加すること
225+ - ** Prisma の nested create(暗黙トランザクション)を ` db.transaction() ` に変換する。** 特に ` onDelete: Cascade ` に依存していた削除ロジックは、` db.transaction() ` 内で子テーブルを先に削除してから親テーブルを削除するように書き換えること
219226
220227### 3-5. クリーンアップ
221228
@@ -234,6 +241,7 @@ bash scripts/dsql.sh create --region <region>
234241このスクリプトは開発用 DSQL クラスタを作成し、` packages/db/.env ` に接続情報を自動で書き込む。
235242
236243検証手順:
244+
2372451 . マイグレーションを実行してスキーマが DSQL に通ることを確認:
238246 ``` bash
239247 pnpm --filter @repo/db run migrate
@@ -245,6 +253,7 @@ bash scripts/dsql.sh create --region <region>
2452533 . 問題があればスキーマやアプリコードを修正し、再検証する
246254
247255検証完了後、開発用クラスタは残しておく(Phase 5 の本番移行完了後に削除):
256+
248257``` bash
249258# Phase 5 完了後に実行
250259bash scripts/dsql.sh delete --region < region>
@@ -264,10 +273,12 @@ v3 キットの CDK コードを参照し、ユーザーの CDK コードを更
264273### 4-1. Dockerfile の更新
265274
266275webapp と async-job の Dockerfile を v3 のパターンに更新する。v3 キットの Dockerfile をベースに、ユーザーが追加した独自の依存やビルド引数を反映する。主な変更点:
276+
267277- ` npm ci ` → pnpm workspaces 対応(` corepack enable ` + ` pnpm install --frozen-lockfile ` )
268278- ` npx prisma generate ` の削除
269279- esbuild の ESM 出力(` --format=esm ` 、出力ファイルは ` .mjs ` 拡張子)
270280- モノレポルートからのビルドコンテキスト
281+ - ** ` .dockerignore ` に ` **/.env.local ` を含めること。** ` COPY apps/webapp/ ` で` .env.local ` が Docker イメージに混入すると、Next.js がビルド時・ランタイムで読み込み、Lambda 環境変数より優先される(例:` AMPLIFY_APP_ORIGIN=http://localhost:3011 ` が Cognito コールバックを localhost に向ける)
271282
272283### 4-2. CDK Construct の更新
273284
@@ -312,6 +323,7 @@ docker build --platform linux/arm64 -f apps/webapp/Dockerfile -t test-webapp:loc
312323```
313324
314325確認事項:
326+
315327- esbuild の出力が ` .mjs ` 拡張子であること
316328- ` @aws/aurora-dsql-node-postgres-connector ` がバンドルに含まれていること(` --external:@aws-sdk/* ` で除外されないこと)
317329- migrations/ ディレクトリが正しくコピーされていること
@@ -327,6 +339,7 @@ pnpm --filter @repo/db run migrate
327339```
328340
329341確認事項:
342+
330343- マイグレーションが成功し、` _migrations ` テーブルにレコードが挿入されること
331344- 再実行で冪等(既に適用済みのマイグレーションがスキップされること)
332345
@@ -339,6 +352,7 @@ cd apps/webapp && pnpm run dev
339352```
340353
341354確認事項:
355+
342356- サインインページが表示されること
343357- Cognito Managed Login でログインできること
344358- Todo の CRUD(作成・完了・編集・削除)が動作すること
@@ -385,6 +399,12 @@ pnpm --filter @repo/db run migrate
385399
386400Phase 1-3 で記録した各テーブルの行数に基づいて移行方法を選択する。
387401
402+ ` pg_dump --data-only ` で取得したダンプを DSQL に投入する場合、以下の変換が必要:
403+
404+ - ` pg_dump ` のプリアンブル(` SET ` 、` SELECT pg_catalog.* ` 、` \restrict ` 、` \unrestrict ` )を除去
405+ - ` _prisma_migrations ` テーブルのデータを除去(Drizzle は ` _migrations ` テーブルを使用)
406+ - ** ` String[] ` 型カラム** : ` pg_dump ` は PostgreSQL 配列リテラル ` {} ` 形式で出力する。Drizzle では ` text ` 型に JSON 文字列 ` [] ` として格納するため、` {} ` → ` [] ` に変換が必要。変換しないと ` JSON.parse('{}') ` がオブジェクト ` {} ` を返し、配列として扱う箇所でエラーになる
407+
388408v3 のマイグレーションランナーは ` .ts ` ファイルをサポートしている。` packages/db/migrations/ ` にデータ移行用の ` .ts ` ファイルを作成し、以下の形式で実装する:
389409
390410``` typescript
@@ -422,6 +442,7 @@ SELECT count(*) FROM "TableName";
4224421 . ** CDK を更新** : Aurora v2 リソース定義を削除(RETAIN が設定されているため実リソースは残る)。webapp と async-job の環境変数を DSQL エンドポイントに変更。Lambda 関数から VPC 設定を削除。Phase 4-2 で特定した VPC 依存の独自 Construct がある場合は、ここで VPC 依存を解消する。
423443
4244442 . ** デプロイ** (本番環境ではメンテナンスウィンドウを推奨):
445+
425446 ``` bash
426447 cd apps/cdk && pnpm exec cdk deploy --all
427448 ```
0 commit comments