# 機能設計書 21-フォーマットキャッシュ（--cache）

## 概要

本ドキュメントは、Prettier CLIにおける`--cache`オプションの機能設計を記述する。このオプションは変更されたファイルのみをフォーマットすることで、大規模プロジェクトにおけるフォーマット処理を高速化する。

### 本機能の処理概要

**業務上の目的・背景**：大規模なコードベースでは、全ファイルをフォーマットするのに多大な時間がかかる。特にCI/CDパイプラインやpre-commitフックでの実行において、変更されていないファイルを再フォーマットすることは無駄なリソース消費となる。本機能は、ファイルの変更状態を追跡し、変更があったファイルのみを処理対象とすることで、フォーマット処理の効率化を実現する。

**機能の利用シーン**：
- CI/CDパイプラインでの差分フォーマットチェック
- ローカル開発時の高速フォーマット実行
- pre-commitフックでの効率的なフォーマット処理
- 大規模モノレポでのフォーマット時間短縮

**主要な処理内容**：
1. キャッシュファイルの読み込みまたは初期化
2. 各ファイルの変更状態チェック（メタデータまたはコンテンツベース）
3. 変更されたファイルのみをフォーマット対象として選択
4. フォーマット成功後、キャッシュ情報を更新
5. 処理完了時にキャッシュファイルを永続化

**関連システム・外部連携**：
- `file-entry-cache`パッケージによるキャッシュ管理
- `find-cache-dir`パッケージによるキャッシュディレクトリ探索
- ファイルシステムによるメタデータ・コンテンツ取得

**権限による制御**：特になし。ファイルシステムへの読み書き権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 15 | Usage - CLI | 補助機能 | CLIでのキャッシュ機能を説明 |

## 機能種別

CRUD操作（キャッシュファイルの読み書き） / 計算処理（ハッシュ計算）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| --cache | boolean | No | キャッシュ機能の有効化 | デフォルト: false |
| --cache-location | path | No | キャッシュファイルのパス | 有効なファイルパス、ディレクトリ不可 |
| --cache-strategy | choice | No | キャッシュ戦略 | "metadata" または "content" |

### 入力データソース

- CLIコマンドライン引数
- ファイルシステム（対象ファイル、キャッシュファイル）
- Prettier設定ファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| キャッシュファイル | JSON | ファイル状態とオプションハッシュを保存 |
| フォーマット結果 | string | 変更されたファイルのフォーマット結果 |

### 出力先

- キャッシュファイル（デフォルト: `node_modules/.cache/prettier/.prettier-cache`）
- 標準出力またはファイル（フォーマット結果）

## 処理フロー

### 処理シーケンス

```
1. キャッシュオプションの検証
   └─ --cache-strategyは--cacheと併用必須

2. キャッシュファイルの初期化
   └─ FormatResultsCacheインスタンス生成
   └─ キャッシュ戦略（metadata/content）に基づく設定

3. ファイルごとの処理ループ
   └─ キャッシュ存在チェック
   └─ 変更状態の判定（メタデータまたはコンテンツハッシュ）
   └─ キャッシュヒット時はフォーマットスキップ
   └─ キャッシュミス時はフォーマット実行

4. キャッシュ更新
   └─ フォーマット成功時にキャッシュ設定
   └─ 差分発生時にキャッシュ削除

5. キャッシュ永続化
   └─ reconcile()でファイルに書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{--cache有効?}
    B -->|No| C[通常フォーマット]
    B -->|Yes| D[キャッシュ初期化]
    D --> E[ファイル取得]
    E --> F{キャッシュ存在?}
    F -->|Yes| G{オプション一致?}
    G -->|Yes| H[スキップ]
    G -->|No| I[フォーマット実行]
    F -->|No| I
    I --> J{成功?}
    J -->|Yes| K{差分あり?}
    K -->|Yes| L[キャッシュ削除]
    K -->|No| M[キャッシュ設定]
    J -->|No| N[エラー処理]
    H --> O{次のファイル?}
    L --> O
    M --> O
    N --> O
    O -->|Yes| E
    O -->|No| P[キャッシュ永続化]
    P --> Q[終了]
    C --> Q
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-21-1 | キャッシュ戦略排他 | --cache-strategyは--cacheなしでは使用不可 | --cache-strategy指定時 |
| BR-21-2 | stdin非対応 | 標準入力フォーマット時はキャッシュ使用不可 | stdin使用時 |
| BR-21-3 | オプション変更検出 | Prettierオプションが変わるとキャッシュ無効化 | フォーマット時 |
| BR-21-4 | バージョン変更検出 | PrettierまたはNodeバージョン変更でキャッシュ無効化 | フォーマット時 |

### 計算ロジック

**オプションハッシュ計算**：
```
hash = createHash(`${prettierVersion}_${nodeVersion}_${stringify(options)}`)
```

**キャッシュ有効性判定**：
- metadata戦略: ファイルのmtime（更新日時）を比較
- content戦略: ファイル内容のチェックサムを比較
- いずれの戦略でもオプションハッシュの一致が必須

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

### 操作別データベース影響一覧

本機能はデータベースを使用しない（ファイルベースのキャッシュ）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ConfigError | --cache-strategyを--cacheなしで指定 | エラーメッセージ表示、終了 |
| - | ConfigError | --cacheをstdinと併用 | エラーメッセージ表示、終了 |
| - | FileError | キャッシュファイルがディレクトリ | エラーメッセージ表示、終了 |
| - | JSONError | キャッシュファイルが無効なJSON | キャッシュファイル削除後リトライ |

### リトライ仕様

キャッシュファイルのフォーマットが無効な場合、ファイルを削除して再作成を試みる（v3.5.0以降）。

## トランザクション仕様

キャッシュの書き込みは`reconcile()`で一括実行。処理中断時は前回のキャッシュ状態が維持される。

## パフォーマンス要件

- キャッシュヒット時はフォーマット処理をスキップ
- 大規模プロジェクトで数秒〜数十秒の時間短縮を期待

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

- キャッシュファイルにはファイルパスとメタデータのみ保存（ソースコード内容は保存しない）
- キャッシュファイルのパーミッションは通常のファイル権限に従う

## 備考

- ESLintのLintResultsCacheを参考に実装されている
- file-entry-cacheパッケージを使用

---

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

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

キャッシュの保存形式とオプションハッシュの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | format-results-cache.js | `src/cli/format-results-cache.js` | FormatResultsCacheクラスの構造とfile-entry-cacheの使用方法 |

**読解のコツ**: `#fileEntryCache`がプライベートフィールドとして使用されている（ES2022の構文）。

#### Step 2: エントリーポイントを理解する

CLIオプションの定義とメイン処理の流れを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cli-options.evaluate.js | `src/cli/cli-options.evaluate.js` | cache, cacheLocation, cacheStrategyオプションの定義 |
| 2-2 | index.js | `src/cli/index.js` | キャッシュオプションの検証ロジック |

**主要処理フロー**:
1. **64-66行目**: cache関連オプションの定義
2. **65-67行目（index.js）**: --cache-strategyの--cache依存チェック
3. **103-104行目（index.js）**: stdinとの排他チェック

#### Step 3: キャッシュファイル探索を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | find-cache-file.js | `src/cli/find-cache-file.js` | デフォルトキャッシュパスの決定とバリデーション |

**主要処理フロー**:
- **10-14行目**: デフォルトキャッシュディレクトリの探索
- **16-34行目**: ユーザー指定パスのバリデーション

#### Step 4: フォーマット処理でのキャッシュ使用を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | format.js | `src/cli/format.js` | formatFiles関数内でのキャッシュ利用 |

**主要処理フロー**:
- **286-298行目**: FormatResultsCacheの初期化
- **367-370行目**: キャッシュ存在チェック
- **376-380行目**: キャッシュヒット時のスキップ処理
- **452-456行目**: キャッシュの更新/削除
- **468行目**: キャッシュの永続化

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

```
src/cli/index.js::run()
    │
    ├─ src/cli/index.js::main()
    │      ├─ キャッシュオプション検証
    │      └─ src/cli/format.js::formatFiles()
    │             │
    │             ├─ src/cli/find-cache-file.js::findCacheFile()
    │             │
    │             ├─ src/cli/format-results-cache.js::FormatResultsCache()
    │             │      ├─ getHashOfOptions()
    │             │      ├─ existsAvailableFormatResultsCache()
    │             │      ├─ setFormatResultsCache()
    │             │      └─ removeFormatResultsCache()
    │             │
    │             └─ FormatResultsCache::reconcile()
    │
    └─ 終了
```

### データフロー図

```
[入力]                    [処理]                         [出力]

CLIオプション ───────────▶ オプション検証 ───────────────▶ エラー or 続行
(--cache)

キャッシュファイル ──────▶ FormatResultsCache ──────────▶ キャッシュ状態
(.prettier-cache)              │
                               ▼
対象ファイル ───────────▶ 変更チェック ──────────────────▶ スキップ or フォーマット
                               │
                               ▼
フォーマット結果 ────────▶ キャッシュ更新 ───────────────▶ 更新されたキャッシュファイル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| format-results-cache.js | `src/cli/format-results-cache.js` | ソース | キャッシュ管理クラス |
| cli-options.evaluate.js | `src/cli/cli-options.evaluate.js` | ソース | CLIオプション定義 |
| find-cache-file.js | `src/cli/find-cache-file.js` | ソース | キャッシュファイルパス探索 |
| format.js | `src/cli/format.js` | ソース | フォーマット処理メイン |
| index.js | `src/cli/index.js` | ソース | CLIエントリーポイント |
| utilities.js | `src/cli/utilities.js` | ソース | ハッシュ計算ユーティリティ |
