# 機能設計書：36-リダイレクト

## 1. 機能概要

### 1.1 機能の目的
リダイレクトプラグイン（@payloadcms/plugin-redirects）は、Payload CMSにURLリダイレクト管理機能を追加するプラグインである。コンテンツ管理者がURL転送ルールを定義し、サイト内のURL変更やコンテンツ移動に対応したリダイレクト処理を実現する。

### 1.2 機能の範囲
- リダイレクトコレクションの自動生成
- 内部リンク（関連ドキュメント参照）とカスタムURL両対応
- HTTPステータスコード（301/302/303/307/308）の選択
- 多言語対応（英語、スペイン語、フランス語、日本語、スウェーデン語）
- フィールドカスタマイズとコレクションオーバーライド

### 1.3 関連する業務フロー
- サイトリニューアル時のURL移行
- コンテンツ削除・移動時のリダイレクト設定
- SEO対策としてのURL正規化
- 一時的なコンテンツ移動対応

## 2. 機能詳細

### 2.1 プラグイン初期化

#### 処理フロー
```
redirectsPlugin(config)
    ↓
翻訳のマージ (deepMergeSimple)
    ↓
フィールド定義生成
    ↓
redirectsコレクション生成
    ↓
既存コレクションに追加
```

#### 設定オプション
```typescript
type RedirectsPluginConfig = {
  collections?: string[]                    // リダイレクト先として選択可能なコレクション
  overrides?: {                             // コレクション設定のオーバーライド
    fields?: FieldsOverride
  } & Partial<Omit<CollectionConfig, 'fields'>>
  redirectTypeFieldOverride?: Partial<SelectField>  // リダイレクトタイプフィールドのカスタマイズ
  redirectTypes?: ('301'|'302'|'303'|'307'|'308')[] // 使用可能なリダイレクトタイプ
}
```

### 2.2 生成されるコレクション

#### redirectsコレクション構造
| フィールド名 | 型 | 説明 |
|-------------|-----|------|
| from | text | リダイレクト元URL（必須、ユニーク、インデックス付き） |
| to.type | radio | リダイレクト先タイプ（reference/custom） |
| to.reference | relationship | 内部ドキュメント参照（type=reference時） |
| to.url | text | カスタムURL（type=custom時） |
| type | select | HTTPステータスコード（redirectTypes指定時のみ） |

#### デフォルト列設定
```typescript
defaultColumns: ['from', 'to.type', 'createdAt']
```

### 2.3 リダイレクトタイプ

| コード | ラベル | 用途 |
|--------|--------|------|
| 301 | Permanent | 恒久的なURL変更（SEO推奨） |
| 302 | Temporary | 一時的なリダイレクト |
| 303 | See Other | POSTリクエスト後のリダイレクト |
| 307 | Temporary Redirect | 一時的（HTTPメソッド維持） |
| 308 | Permanent Redirect | 恒久的（HTTPメソッド維持） |

### 2.4 条件付きフィールド表示

```typescript
// to.reference: type=reference時のみ表示
admin: {
  condition: (_, siblingData) => siblingData?.type === 'reference',
}

// to.url: type=custom時のみ表示
admin: {
  condition: (_, siblingData) => siblingData?.type === 'custom',
}
```

### 2.5 アクセス制御

```typescript
access: {
  read: () => true,  // デフォルト: 全員読み取り可能
  ...pluginConfig?.overrides?.access,  // オーバーライド可能
}
```

## 3. データモデル

### 3.1 Redirect型
```typescript
interface Redirect {
  id: string
  from: string
  to: {
    type: 'reference' | 'custom'
    reference?: {
      relationTo: string
      value: string | Document
    }
    url?: string
  }
  type?: '301' | '302' | '303' | '307' | '308'
  createdAt: string
  updatedAt: string
}
```

### 3.2 ER図
```
+------------------+
|    redirects     |
+------------------+
| id (PK)          |
| from (UNIQUE)    |
| to_type          |
| to_reference     |----> [関連コレクション]
| to_url           |
| type             |
| createdAt        |
| updatedAt        |
+------------------+
```

## 4. インターフェース仕様

### 4.1 プラグイン使用例
```typescript
import { redirectsPlugin } from '@payloadcms/plugin-redirects'

export default buildConfig({
  plugins: [
    redirectsPlugin({
      collections: ['pages', 'posts'],
      redirectTypes: ['301', '302'],
      overrides: {
        slug: 'my-redirects',
        access: {
          create: ({ req }) => req.user?.role === 'admin',
        },
      },
    }),
  ],
})
```

### 4.2 エクスポート
```typescript
// メインエクスポート
export { redirectsPlugin } from './index.js'

// リダイレクトタイプ定数
export { redirectOptions, redirectTypes } from './redirectTypes.js'

// 翻訳
export { translations as redirectsTranslations } from './translations/index.js'

// 型定義
export type { RedirectsPluginConfig, FieldsOverride } from './types.js'
```

## 5. 画面設計

### 5.1 管理画面

#### リダイレクト一覧画面
- パス: `/admin/collections/redirects`
- デフォルト列: from, to.type, createdAt
- 機能: 検索、ソート、ページネーション

#### リダイレクト編集画面
- パス: `/admin/collections/redirects/{id}`
- フィールド:
  - From URL（テキスト入力）
  - To URL Type（ラジオボタン: Internal link / Custom URL）
  - Document to redirect to（関係フィールド、type=reference時）
  - Custom URL（テキスト入力、type=custom時）
  - Redirect Type（セレクト、redirectTypes指定時のみ）

### 5.2 UIフロー
```
リダイレクト一覧
    ↓ [新規作成]
リダイレクト作成画面
    ↓ [From URL入力]
    ↓ [To URL Type選択]
        ├── Internal link → ドキュメント選択
        └── Custom URL → URL入力
    ↓ [保存]
リダイレクト一覧（更新）
```

## 6. ビジネスロジック

### 6.1 フィールドオーバーライド
```typescript
// カスタムフィールド追加例
overrides: {
  fields: ({ defaultFields }) => [
    ...defaultFields,
    {
      name: 'priority',
      type: 'number',
      defaultValue: 0,
    },
  ],
}
```

### 6.2 翻訳キー
| キー | 英語 | 日本語 |
|------|------|--------|
| plugin-redirects:customUrl | Custom URL | カスタムURL |
| plugin-redirects:documentToRedirect | Document to redirect to | リダイレクト先ドキュメント |
| plugin-redirects:fromUrl | From URL | リダイレクト元URL |
| plugin-redirects:internalLink | Internal link | 内部リンク |
| plugin-redirects:redirectType | Redirect Type | リダイレクトタイプ |
| plugin-redirects:toUrlType | To URL Type | リダイレクト先タイプ |

## 7. エラー処理

### 7.1 バリデーション
- `from`フィールド: 必須、ユニーク制約
- `to.reference`: type=reference時に必須
- `to.url`: type=custom時に必須

### 7.2 エラーケース
| エラー | 原因 | 対処 |
|--------|------|------|
| 重複エラー | 同一fromURLが既存 | 既存レコードを編集または削除 |
| 参照エラー | 存在しないドキュメント参照 | 有効なドキュメントを選択 |

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

### 8.1 アクセス制御
- デフォルトでread: () => trueのため、本番環境では適切なアクセス制御をオーバーライドで設定
- 作成・更新・削除権限は管理者に限定推奨

### 8.2 入力検証
- fromフィールドのURL形式検証（アプリケーション側で実装）
- オープンリダイレクト攻撃防止のため、customURL時の検証が必要

## 9. パフォーマンス考慮事項

### 9.1 インデックス
- `from`フィールドにindex: trueを設定
- ユニーク制約によりデータベースインデックスが自動作成

### 9.2 キャッシュ戦略
- リダイレクトルールは頻繁に変更されないため、アプリケーション側でキャッシュ推奨
- Next.jsミドルウェアでのキャッシュ実装例が一般的

## 10. 非機能要件対応

### 10.1 多言語対応
- 5言語（en, es, fr, ja, sv）の翻訳を内蔵
- deepMergeSimpleによる翻訳マージで拡張可能

### 10.2 拡張性
- FieldsOverrideによるフィールドカスタマイズ
- CollectionConfigオーバーライドによる完全なカスタマイズ

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

### 11.1 推奨読解順序

1. **型定義の理解**
   - `packages/plugin-redirects/src/types.ts` (1-11行目)
   - RedirectsPluginConfig型を確認

2. **リダイレクトタイプの確認**
   - `packages/plugin-redirects/src/redirectTypes.ts` (1-24行目)
   - 定数と選択肢の定義

3. **プラグイン本体**
   - `packages/plugin-redirects/src/index.ts` (12-127行目)
   - 翻訳マージ → フィールド生成 → コレクション追加の流れ

4. **翻訳設定**
   - `packages/plugin-redirects/src/translations/index.ts` (1-19行目)
   - 多言語対応の構造

### 11.2 プログラム呼び出し階層図
```
redirectsPlugin(config)
├── deepMergeSimple(translations, ...)
│   └── @payloadcms/translations
├── redirectOptions.filter(...)
│   └── redirectTypes.ts
└── return Config
    └── collections: [..., redirectsCollection]
```

### 11.3 データフロー図
```
[設定オブジェクト]
      ↓
redirectsPlugin
      ↓
+------------------+
| 翻訳マージ        |
+------------------+
      ↓
+------------------+
| フィールド生成    |
| - from           |
| - to (group)     |
| - type (select)  |
+------------------+
      ↓
+------------------+
| コレクション生成  |
+------------------+
      ↓
[拡張されたConfig]
```

### 11.4 関連ファイル一覧
| ファイルパス | 役割 |
|-------------|------|
| packages/plugin-redirects/src/index.ts | プラグインメイン実装 |
| packages/plugin-redirects/src/types.ts | 型定義 |
| packages/plugin-redirects/src/redirectTypes.ts | リダイレクトタイプ定数 |
| packages/plugin-redirects/src/translations/index.ts | 翻訳エントリーポイント |
| packages/plugin-redirects/src/translations/languages/en.ts | 英語翻訳 |
| packages/plugin-redirects/src/translations/languages/ja.ts | 日本語翻訳 |
| packages/plugin-redirects/package.json | パッケージ設定 |

## 12. 変更履歴

| 日付 | バージョン | 変更内容 |
|------|-----------|----------|
| 2026-03-01 | 1.0 | 初版作成 |
