# 通知設計書 12-ファイル名 (cached)

## 概要

本ドキュメントは、Prettier CLI において `--cache` オプションと `--write` オプションを同時に使用した際、キャッシュから読み込まれたファイルに対して表示されるログ通知「ファイル名 (cached)」について定義する設計書である。

### 本通知の処理概要

Prettier CLI がフォーマット処理を実行する際、`--cache` オプションが有効な場合にフォーマット結果キャッシュを参照する。対象ファイルがキャッシュに存在し、かつファイル内容とオプション設定に変更がない場合、実際のフォーマット処理をスキップしてキャッシュから結果を取得する。この際、ユーザーに対してファイル名、処理時間、および「(unchanged) (cached)」というステータスを通知する。

**業務上の目的・背景**：大規模プロジェクトでは多数のファイルをフォーマットする必要があり、毎回すべてのファイルをパースしてフォーマットすることは時間がかかる。キャッシュ機能により、変更のないファイルの再フォーマットをスキップし、処理を高速化できる。この通知により、ユーザーはどのファイルがキャッシュから処理されたかを把握でき、キャッシュ機能が正しく動作していることを確認できる。CI/CDパイプラインにおいても、キャッシュによる処理時間短縮の効果を可視化できる。

**通知の送信タイミング**：`prettier --write --cache` コマンドを実行し、対象ファイルに対してキャッシュが有効であり、かつフォーマット結果に変更がない場合に通知される。具体的には、`format.js` の `formatFiles` 関数内で `isCacheExists === true` かつ `isDifferent === false` の条件を満たした時点で出力される。

**通知の受信者**：CLI を実行している開発者またはCI/CDシステム。標準出力（stdout）に出力されるため、ターミナルで実行している場合はリアルタイムで表示され、パイプライン実行時はログとして記録される。

**通知内容の概要**：グレー色で装飾されたファイル名、処理にかかった時間（ミリ秒単位）、「(unchanged)」ステータス、および「(cached)」という追加ステータス文字列で構成される。

**期待されるアクション**：この通知を受け取った場合、ユーザーは特にアクションを取る必要はない。キャッシュが有効に機能しており、対象ファイルのフォーマット処理がスキップされたことを確認するための情報提供である。キャッシュを無効化したい場合は `--no-cache` オプションを使用するか、キャッシュファイルを削除する。

## 通知種別

CLI 標準出力（ログ出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ファイル処理完了時に即座に出力） |
| 優先度 | 中（通常のログ出力） |
| リトライ | なし（一度きりの出力） |

### 送信先決定ロジック

CLI 実行環境の標準出力（`process.stdout`）に対して直接出力する。ログレベルが `log` 以上に設定されている場合のみ出力される（デフォルトで有効）。`--check` または `--list-different` オプションが同時に指定されている場合はこの通知は抑止される。

## 通知テンプレート

### CLI出力通知の場合

| 項目 | 内容 |
|-----|------|
| 出力先 | 標準出力（stdout） |
| 形式 | テキスト |
| カラー | ファイル名部分はグレー（picocolors.gray） |

### 本文テンプレート

```
{ファイル名} {処理時間}ms (unchanged) (cached)
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| fileNameToDisplay | 表示用ファイル名（現在の作業ディレクトリからの相対パス） | `path.relative(cwd, filename)` をPOSIX形式に正規化 | Yes |
| timeToDisplay | 処理時間（ミリ秒単位） | フォーマット処理開始時刻と完了時刻の差分を `Math.round()` | Yes |
| isCacheExists | キャッシュ存在フラグ | `FormatResultsCache.existsAvailableFormatResultsCache()` の戻り値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| CLI実行 | ファイルフォーマット完了 | `--write` と `--cache` オプションが指定されており、キャッシュが有効、かつフォーマット前後でファイル内容に変更がない場合 | `isCacheExists === true && isDifferent === false` の評価で判定 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `--cache` オプション未指定 | キャッシュが無効な場合はこの通知は発生しない |
| `--check` オプション指定時 | チェックモードでは変更なしファイルの通知は行わない |
| `--list-different` オプション指定時 | 差分一覧モードでは変更なしファイルの通知は行わない |
| パフォーマンステストモード | `--debug-benchmark` や `--debug-repeat` 指定時は早期リターンにより出力されない |
| ログレベルが `log` 未満 | `--log-level warn` や `--log-level error` 指定時は出力されない |
| キャッシュ無効 | ファイルが変更された、またはオプションが変更された場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[formatFiles開始] --> B[--cache オプション確認]
    B -->|有効| C[FormatResultsCache初期化]
    B -->|無効| D[通常処理へ]
    C --> E[ファイル読み込み]
    E --> F[existsAvailableFormatResultsCache呼び出し]
    F -->|キャッシュあり| G[result.formatted = input]
    F -->|キャッシュなし| H[format関数でフォーマット実行]
    G --> I[isDifferent判定]
    H --> I
    I -->|変更なし| J{--check or --list-different?}
    J -->|Yes| K[通知スキップ]
    J -->|No| L[ファイル名 + 時間 + unchanged + cached 出力]
    I -->|変更あり| M[ファイル書き込み・変更ありログ出力]
    D --> N[No.11の通知フロー]
    K --> O[終了]
    L --> O
    M --> O
    N --> O
```

## データベース参照・更新仕様

### 参照テーブル一覧

本通知はデータベースを使用しない。ファイルシステムとキャッシュファイルを参照する。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| FormatResultsCache | フォーマット結果のキャッシュ | ファイルベースのキャッシュ（node_modules/.cache/prettier/.prettier-cache） |

### テーブル別参照項目詳細

#### FormatResultsCache

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| fileDescriptor.notFound | ファイルがキャッシュに存在しないフラグ | ファイルパスをキーとして検索 |
| fileDescriptor.changed | ファイルが変更されたフラグ | ファイルの内容またはメタデータの変更を検出 |
| meta.data.hashOfOptions | オプションのハッシュ値 | Prettierバージョン、Node.jsバージョン、オプション設定から生成 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| FormatResultsCache | UPDATE | フォーマット結果のキャッシュを更新（変更なしファイルの場合） |

#### 送信ログテーブル

本通知ではログテーブルへの記録は行わない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| キャッシュファイル読み込みエラー | キャッシュファイルのフォーマットが不正な場合 | キャッシュファイルを削除して再作成 |
| 出力エラー | 標準出力への書き込みが失敗した場合 | Node.jsのストリームエラーとして伝播 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（CLI実行時に即座に出力）

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

- ファイル名がコンソールに出力されるため、機密性の高いファイル名やパスが含まれる場合は注意が必要
- キャッシュファイルにはファイルパスとオプションのハッシュ値が含まれる
- 標準出力への出力のみであり、ネットワーク送信は行わない

## 備考

- キャッシュは `file-entry-cache` ライブラリを使用して管理される
- キャッシュ戦略は `--cache-strategy` オプションで設定可能（`content` または `metadata`）
- デフォルトのキャッシュ戦略は `content`（ファイル内容のチェックサム）
- キャッシュファイルの場所は `--cache-location` オプションで変更可能
- Prettierバージョンまたは Node.jsバージョンが変わるとキャッシュは無効化される

---

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

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

### 推奨読解順序

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

まず、フォーマット結果キャッシュの仕組みと有効性判定ロジックを理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | format-results-cache.js | `src/cli/format-results-cache.js` | キャッシュの全体構造、`existsAvailableFormatResultsCache` メソッドの判定ロジック |

**読解のコツ**: `file-entry-cache` ライブラリの `createFromFile` でキャッシュを初期化。`fileDescriptor.notFound` と `fileDescriptor.changed` でファイルの変更を検出し、`hashOfOptions` でオプション設定の変更を検出する。

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

CLIからキャッシュ機能への導線を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.js | `src/cli/index.js` | `--cache` オプションのバリデーション（標準入力時の禁止等） |

**主要処理フロー**:
1. **行103-105**: 標準入力フォーマット時のキャッシュ禁止チェック
2. **行111-113**: ファイルパターンがある場合に `formatFiles` を呼び出し

#### Step 3: キャッシュ初期化を理解する

キャッシュの初期化処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | format.js | `src/cli/format.js` | キャッシュの初期化と参照処理（行286-298） |

**主要処理フロー**:
- **行287**: キャッシュファイルパスの取得
- **行288-292**: `--cache` オプション有効時にキャッシュインスタンス作成
- **行293-297**: キャッシュ無効時は既存キャッシュファイルを削除

#### Step 4: キャッシュ参照とログ出力を理解する

キャッシュの参照とログ出力のロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | format.js | `src/cli/format.js` | キャッシュ参照と `(cached)` 出力（行367-370, 435-436） |

**主要処理フロー**:
- **行367-370**: `existsAvailableFormatResultsCache` でキャッシュ有効性を判定
- **行376-377**: キャッシュ有効時は `result.formatted = input` でフォーマット処理をスキップ
- **行435-436**: `isCacheExists` が真の場合、`(cached)` を追加して出力

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

```
src/cli/index.js::run()
    │
    ├─ context.argv.cache チェック [行103]
    │
    └─ formatFiles()  [src/cli/format.js:272]
           │
           ├─ findCacheFile()  [src/cli/find-cache-file.js]
           │      └─ キャッシュファイルパス決定
           │
           ├─ new FormatResultsCache()  [行289-292]
           │      └─ file-entry-cache 初期化
           │
           ├─ existsAvailableFormatResultsCache()  [行367-370]
           │      │
           │      ├─ getFileDescriptor()
           │      │      └─ ファイル情報取得
           │      │
           │      └─ getHashOfOptions()
           │             └─ オプションハッシュ比較
           │
           └─ context.logger.log()  [行436]
                  └─ "(cached)" メッセージ出力
```

### データフロー図

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

--cache オプション ─────▶ FormatResultsCache 初期化
                                │
ファイルパス ─────────────▶ getFileDescriptor()
                                │
                                ▼
                         notFound / changed 判定
                                │
                                ▼
オプション設定 ───────────▶ hashOfOptions 生成・比較
                                │
                                ▼
                         [キャッシュ有効] ───▶ フォーマットスキップ
                                │
                                ▼
                         isDifferent === false
                                │
                                ▼
                         logger.log()
                                │
                                ▼
                         "{ファイル名} {時間}ms (unchanged) (cached)"
                                │
                                ▼
                         標準出力 (stdout)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.js | `src/cli/index.js` | ソース | CLIエントリーポイント、キャッシュオプション検証 |
| format.js | `src/cli/format.js` | ソース | フォーマット処理とキャッシュ参照・ログ出力のメインロジック |
| format-results-cache.js | `src/cli/format-results-cache.js` | ソース | フォーマット結果のキャッシュ管理クラス |
| find-cache-file.js | `src/cli/find-cache-file.js` | ソース | キャッシュファイルパスの決定 |
| logger.js | `src/cli/logger.js` | ソース | ログ出力機能 |
| utilities.js | `src/cli/utilities.js` | ソース | ユーティリティ関数（createHash等） |
