# 通知設計書 17-Unable to expand directory

## 概要

本ドキュメントは、Prettier CLI においてディレクトリの展開に失敗した場合に表示されるエラー通知「Unable to expand directory」について定義する設計書である。

### 本通知の処理概要

Prettier CLI がディレクトリとして認識されたパターンに対してグロブ展開（`/**/*` パターンで配下のすべてのファイルを検索）を実行した際にエラーが発生した場合、ユーザーに対してエラー内容を通知する。このエラーは `fast-glob` ライブラリがディレクトリを展開する過程で発生する内部エラーをキャッチして生成される。

**業務上の目的・背景**：開発者がディレクトリを指定してコードフォーマットを実行する際、ディレクトリ内のすべてのファイルを正しく展開することは処理の前提条件である。ファイルシステムの問題（権限不足、シンボリックリンクの問題等）が発生した場合、ユーザーに明確なエラーメッセージを提供することで、問題の特定と解決を支援する。

**通知の送信タイミング**：`prettier` コマンドを実行し、ディレクトリとして認識されたパターンに対して `fastGlob()` を実行した際にエラーが発生した時点で通知される。具体的には、`expand-patterns.js` の `expandPatternsInternal` 関数内の `try-catch` ブロックでエラーがキャッチされた時点で出力される（行119-127）。

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

**通知内容の概要**：「Unable to expand directory」という固定メッセージ、展開に失敗したディレクトリパターン、および `fast-glob` からのエラー詳細メッセージで構成される。

**期待されるアクション**：この通知を受け取った場合、ユーザーは以下のアクションを検討する必要がある。(1) 指定したディレクトリパスが正しいか確認、(2) ディレクトリにアクセスする権限があるか確認、(3) ディレクトリ内にアクセス不可能なファイルやサブディレクトリがないか確認。

## 通知種別

CLI 標準エラー出力（エラー通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（ディレクトリ展開エラー発生時に即座に出力） |
| 優先度 | 高（エラー通知） |
| リトライ | なし（一度きりの出力、ただし処理は継続） |

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

CLI 実行環境の標準エラー出力（`process.stderr`）に対して直接出力する。ログレベルが `error` 以上に設定されている場合のみ出力される（デフォルトで有効）。

## 通知テンプレート

### CLI出力通知の場合

| 項目 | 内容 |
|-----|------|
| 出力先 | 標準エラー出力（stderr） |
| 形式 | テキスト |
| カラー | プレフィックス `[error]` は赤色（picocolors.red） |

### 本文テンプレート

```
[error] Unable to expand directory: "{パターン}".
{エラーメッセージ}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| input | 元のディレクトリパターン | コマンドライン引数から取得 | Yes |
| message | エラー詳細メッセージ | `fastGlob()` が投げるエラーオブジェクトの `message` プロパティ | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| パターン展開 | ディレクトリ展開失敗 | `type === "dir"` のエントリに対して `fastGlob()` がエラーを投げた場合 | try-catch でキャッチされたエラー |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| ログレベルが `error` 未満 | `--log-level silent` 指定時は出力されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[expandPatternsInternal開始] --> B[パターンごとにループ]
    B --> C{パターン種別?}
    C -->|ディレクトリ| D[lstatSafe実行]
    D -->|存在 & isDirectory| E[type: dir エントリ作成]
    E --> F["glob: {prefix}/**/* 設定"]
    F --> G[fastGlob実行]
    G -->|成功| H[結果yield]
    G -->|失敗| I[エラーキャッチ]
    I --> J[errorMessages.globError.dir メッセージ生成]
    J --> K[yield error]
    K --> L[continue - 次のパターンへ]
    C -->|ファイル| M[type: file エントリ作成]
    C -->|グロブ| N[type: glob エントリ作成]
    H --> O[終了]
    L --> B
    M --> G
    N --> G
```

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

### 参照テーブル一覧

本通知はデータベースを使用しない。ファイルシステムのみを参照する。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| N/A | N/A | N/A |

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

該当なし

### 更新テーブル一覧

該当なし

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

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| EACCES | ディレクトリまたはサブディレクトリへのアクセス権限がない | 権限を確認・変更 |
| ELOOP | シンボリックリンクのループが検出された | シンボリックリンクの構成を確認 |
| fastGlobエラー | グロブ処理中のI/Oエラー等 | ディレクトリ構造とアクセス権限を確認 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

- 指定されたディレクトリパターンとエラーメッセージがコンソールに出力されるため、機密性の高いパス情報が含まれる場合は注意が必要
- 標準エラー出力への出力のみであり、ネットワーク送信は行わない

## 備考

- このエラーは `type === "dir"` のエントリ（ディレクトリとして認識されたパターン）に対してのみ発生する
- ディレクトリは `/**/*` パターンを付加して展開される
- `ignoreUnknown: true` が設定されるため、サポートされていないファイルは無視される
- `followSymbolicLinks: false` がデフォルト設定であり、シンボリックリンクは追跡されない
- 処理は中断されず、次のパターンの処理に継続する
- `format.js` でエラーを受け取り、`process.exitCode = 2` が設定される
- エラーメッセージは `errorMessages.globError.dir` として定義されている（行142）

---

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

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

### 推奨読解順序

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

パターンエントリの構造とエラーメッセージの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | expand-patterns.js | `src/cli/expand-patterns.js` | エントリオブジェクト構造とerrorMessages定義（行139-149） |

**読解のコツ**: `errorMessages.globError.dir` は "Unable to expand directory" として定義されている。

#### Step 2: ディレクトリ判定を理解する

パターンがディレクトリとして判定される条件を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | expand-patterns.js | `src/cli/expand-patterns.js` | ディレクトリ判定とエントリ作成（行89-102） |

**主要処理フロー**:
1. **行89**: `stat.isDirectory()` でディレクトリ判定
2. **行95**: 相対パスを計算
3. **行96**: パスをエスケープ
4. **行97-102**: `type: "dir"`, `glob: "{prefix}/**/*"`, `ignoreUnknown: true` エントリを作成

#### Step 3: エラー処理を理解する

fastGlobのエラーハンドリングを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | expand-patterns.js | `src/cli/expand-patterns.js` | fastGlob実行とエラーキャッチ（行116-127） |

**主要処理フロー**:
- **行120**: `fastGlob(glob, globOptions)` の実行
- **行121**: `catch ({ message })` でエラーをキャッチ
- **行124**: `errorMessages.globError[type]` を使用（`type === "dir"` の場合は "Unable to expand directory"）

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

```
src/cli/expand-patterns.js::expandPatternsInternal()  [行49]
    │
    ├─ パターンごとにループ [行64]
    │      │
    │      ├─ lstatSafe(absolutePath)  [行71]
    │      │      └─ ファイル情報取得
    │      │
    │      └─ stat.isDirectory() [行89]
    │             │
    │             ├─ path.relative(cwd, absolutePath) [行95]
    │             │
    │             └─ entries.push({ type: "dir", ... })  [行97-102]
    │                    │
    │                    └─ glob: `${prefix}/**/*`
    │
    └─ エントリごとにループ [行116]
           │
           ├─ fastGlob(glob, globOptions)  [行120]
           │      │
           │      └─ [エラー発生時]
           │             │
           │             └─ yield { error }  [行123-125]
           │                    │
           │                    ▼
           │             format.js で処理 [行308-312]
           │
           └─ continue  [行126]
```

### データフロー図

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

ディレクトリパス ────▶ lstatSafe()
                              │
                              ▼
                         [isDirectory() === true]
                              │
                              ▼
                         type: "dir" エントリ作成
                         glob: "{prefix}/**/*"
                              │
                              ▼
                         fastGlob() 実行
                              │
                              ▼
                         [エラー発生]
                              │
                              ├─ errorMessages.globError.dir 取得
                              │
                              ▼
                         yield { error }
                              │
                              ▼
                         format.js で context.logger.error()
                              │
                              ▼
                         "[error] Unable to expand directory: \"{パターン}\".
                          {エラーメッセージ}"
                              │
                              ▼
                         標準エラー出力 (stderr)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| expand-patterns.js | `src/cli/expand-patterns.js` | ソース | パターン展開とエラー生成 |
| format.js | `src/cli/format.js` | ソース | エラーのログ出力とexitCode設定 |
| logger.js | `src/cli/logger.js` | ソース | エラーログ出力機能 |
| utilities.js | `src/cli/utilities.js` | ソース | lstatSafe関数 |
| prettier-internal.js | `src/cli/prettier-internal.js` | ソース | fastGlobのエクスポート |
| directory-ignorer.js | `src/cli/directory-ignorer.js` | ソース | 無視するディレクトリパターンの定義 |
