# 機能設計書 17-Vercel Postgres アダプター

## 概要

本ドキュメントは、Payload CMSにおけるVercel Postgres アダプター（`@payloadcms/db-vercel-postgres`）の設計を定義する。Vercel PostgresおよびローカルPostgreSQLとの接続、CRUD操作、スキーマ管理をDrizzle ORMを通じて提供する。

### 本機能の処理概要

Vercel Postgres アダプターは、Payload CMSとVercel Postgres間のインターフェースを提供するデータベースアダプターである。VercelのサーバーレスPostgreSQL環境に最適化されており、ローカル開発時には標準のpgモジュールに自動的に切り替える機能を持つ。

**業務上の目的・背景**：Vercel上でのデプロイにおいて、Vercel Postgresとのシームレスな統合を提供する。ローカル開発時にはVercel Postgresが使用できないため、自動的にpgモジュールを使用することで、開発体験を損なうことなく本番環境との互換性を維持する。

**機能の利用シーン**：
- Vercelへのデプロイ時のデータベース接続
- ローカル開発環境での自動フォールバック
- サーバーレス環境での効率的なコネクション管理
- リードレプリカを活用したスケーラブルな読み取り処理

**主要な処理内容**：
1. 接続管理：Vercel Postgres / pgモジュールの自動切り替え
2. スキーマ管理：Drizzle ORM経由のスキーマ生成
3. CRUD操作：PostgreSQL互換のデータ操作
4. マイグレーション：スキーマ変更のマイグレーション生成・実行

**関連システム・外部連携**：
- @vercel/postgres
- pg（node-postgres）
- Drizzle ORM
- @payloadcms/drizzle

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （該当なし） | - | データベース層のため画面連携なし |

## 機能種別

データベースアダプター / ORM統合

## 入力仕様

### アダプター設定パラメータ

| パラメータ名 | 型 | 必須 | 説明 | デフォルト |
|-------------|-----|-----|------|-----------|
| pool | VercelPostgresPoolConfig | No | Vercel Postgres接続プール設定 | 環境変数から検出 |
| connectionString | string | No | 接続文字列（プール設定に含む） | POSTGRES_URL |
| idType | 'serial' / 'uuid' | No | ID生成タイプ | 'serial' |
| allowIDOnCreate | boolean | No | create時にカスタムIDを許可 | false |
| blocksAsJSON | boolean | No | ブロックをJSON列で保存 | false |
| disableCreateDatabase | boolean | No | 自動DB作成を無効化 | false |
| forceUseVercelPostgres | boolean | No | ローカルでもVercel Postgres使用を強制 | false |
| extensions | string[] | No | 有効にするPostgreSQL拡張機能 | [] |
| schemaName | string | No | データベーススキーマ名 | 'public' |
| localesSuffix | string | No | ロケールテーブルの接尾辞 | '_locales' |
| relationshipsSuffix | string | No | リレーションテーブルの接尾辞 | '_rels' |
| versionsSuffix | string | No | バージョンテーブルの接尾辞 | '_v' |
| transactionOptions | PgTransactionConfig / false | No | トランザクションオプション | undefined |
| readReplicas | string[] | No | リードレプリカの接続文字列配列 | undefined |
| tablesFilter | string[] | No | 対象テーブルのフィルター | undefined |
| logger | DrizzleConfig['logger'] | No | ロガー設定 | false |
| prodMigrations | MigrationConfig[] | No | 本番用マイグレーション定義 | undefined |

## 出力仕様

PayloadのドキュメントフォーマットでJSON形式のデータを返却。

## 処理フロー

### 初期化処理

```
1. vercelPostgresAdapter()呼び出し
   └─ アダプター設定オブジェクトを受け取る

2. IDタイプ設定
   └─ serial→'number'、uuid→'text'に変換

3. スキーマ名処理
   └─ schemaName指定時はpgSchema使用
   └─ 未指定時はpgTable、pgEnumを直接使用

4. createDatabaseAdapter()
   └─ 共通アダプターインターフェースでラップ

5. connect()実行
   └─ ローカル判定（localhost/127.0.0.1）
   └─ ローカル：pg.Poolで接続
   └─ 本番：VercelPoolで接続
   └─ drizzle()でDrizzleインスタンス生成
```

### 接続判定ロジック

```
接続先判定:
1. forceUseVercelPostgres = true の場合
   └─ 常にVercelPoolを使用

2. connectionStringがlocalhost/127.0.0.1の場合
   └─ pg.Poolを使用（ローカル開発）

3. それ以外
   └─ VercelPoolを使用
   └─ poolOptions未指定時はsql（環境変数から自動検出）
```

### リードレプリカ設定

```
リードレプリカ設定:
1. readReplicaOptions配列を取得
2. 各接続文字列でVercelPoolを作成
3. drizzle()でDrizzleインスタンス生成
4. withReplicas()でメインDBと統合
```

## ビジネスルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | IDタイプデフォルト | idType='serial'がデフォルト | 全コレクション |
| BR-02 | ローカル自動切替 | localhost/127.0.0.1はpgモジュール使用 | forceUseVercelPostgres=false |
| BR-03 | 環境変数検出 | poolOptions未指定時はPOSTGRES_URLを使用 | Vercel環境 |
| BR-04 | 自動DB作成 | DB未存在時は自動作成（disableCreateDatabase=false時） | 初回接続 |

## データベース操作仕様

### 接続処理

```typescript
// ローカル判定ロジック
const connectionString = this.poolOptions?.connectionString ?? process.env.POSTGRES_URL

if (
  !this.forceUseVercelPostgres &&
  connectionString &&
  ['127.0.0.1', 'localhost'].includes(new URL(connectionString).hostname)
) {
  // ローカル: pg.Pool使用
  client = new pg.Pool(this.poolOptions ?? { connectionString })
} else {
  // 本番: VercelPool使用
  client = this.poolOptions ? new VercelPool(this.poolOptions) : sql
}

this.drizzle = drizzle({ client, logger, schema: this.schema })
```

### 環境変数

| 変数名 | 説明 | 必須 |
|--------|------|------|
| POSTGRES_URL | PostgreSQL接続文字列（Vercelが自動設定） | Yes |
| PAYLOAD_DROP_DATABASE | trueでテーブル削除 | No |
| NODE_ENV | 環境判定（production/development） | No |
| PAYLOAD_MIGRATING | マイグレーション実行中フラグ | No |

## パフォーマンス要件

- Vercel Postgresの接続プーリング活用
- リードレプリカによる読み取りスケーリング
- サーバーレス環境に最適化された接続管理

## セキュリティ考慮事項

- Vercel環境変数による認証情報管理
- SSL接続の強制（Vercel Postgres）
- 接続文字列の安全な取り扱い

---

## コードリーディングガイド

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/db-vercel-postgres/src/index.ts` | ソース | アダプターエントリーポイント |
| types.ts | `packages/db-vercel-postgres/src/types.ts` | ソース | 型定義 |
| connect.ts | `packages/db-vercel-postgres/src/connect.ts` | ソース | 接続処理・環境判定 |

### 推奨リーディング順序

1. **types.ts** - Args型とVercelPostgresAdapter型の定義を確認
2. **index.ts** - vercelPostgresAdapter()関数でアダプター構造を理解
3. **connect.ts** - 接続判定ロジック（ローカル/Vercel切り替え）を確認

### 主要処理フロー

#### index.ts

- **69行目**: vercelPostgresAdapter関数（エントリーポイント）
- **70-72行目**: IDタイプ初期化（serial→'number'、uuid→'text'）
- **85-89行目**: pgSchema設定（schemaName指定時）
- **91-94行目**: extensions配列をオブジェクトに変換
- **105-217行目**: createDatabaseAdapterでアダプター生成
- **123行目**: forceUseVercelPostgresオプション
- **201行目**: packageNameは'@payloadcms/db-vercel-postgres'

#### connect.ts

- **23-40行目**: ローカル/Vercel接続判定ロジック
- **28-37行目**: localhost/127.0.0.1判定でpg.Pool使用
- **38-40行目**: それ以外はVercelPool使用
- **44-48行目**: drizzle()でDrizzleインスタンス生成
- **50-61行目**: リードレプリカ設定処理
- **72-82行目**: データベース未存在時の自動作成

### プログラム呼び出し階層図

```
vercelPostgresAdapter()
├── createDatabaseAdapter() - 共通アダプターラッパー
├── connect()
│   ├── pg.Pool() or VercelPool() - クライアント作成
│   ├── drizzle() - Drizzleインスタンス生成
│   ├── withReplicas() - リードレプリカ統合
│   ├── createExtensions() - PostgreSQL拡張機能作成
│   ├── pushDevSchema() - 開発環境スキーマ同期
│   └── migrate() - 本番マイグレーション実行
└── @payloadcms/drizzle - CRUD操作群
    ├── find()
    ├── create()
    ├── update()
    └── delete()
```

### データフロー図

```
[Payload CMS]
     │
     ▼
[vercelPostgresAdapter]
     │
     ├──[接続判定]──┐
     │             │
     ▼             ▼
[pg.Pool]    [VercelPool]
(ローカル)     (Vercel)
     │             │
     └──────┬──────┘
            ▼
     [drizzle-orm]
            │
            ▼
  [PostgreSQL Database]
```

### PostgreSQLアダプターとの違い

| 機能 | PostgreSQLアダプター | Vercel Postgresアダプター |
|------|---------------------|-------------------------|
| パッケージ | @payloadcms/db-postgres | @payloadcms/db-vercel-postgres |
| 接続ライブラリ | pg (node-postgres) | @vercel/postgres + pg |
| ローカル対応 | pg直接使用 | 自動判定で切り替え |
| forceUseVercelPostgres | - | あり |
| 再接続ロジック | connectWithReconnect | なし（Vercel管理） |
