# 機能設計書 28-bun why

## 概要

本ドキュメントは、Bunパッケージマネージャーの `bun why` コマンドの機能設計を記述する。このコマンドは、特定のパッケージがインストールされている理由（依存元）を表示する。

### 本機能の処理概要

`bun why` は、指定されたパッケージがどのパッケージから依存されているかを逆引きで表示し、依存関係の階層構造を視覚化する機能を提供する。

**業務上の目的・背景**：大規模なプロジェクトでは、依存関係が複雑に絡み合い、特定のパッケージがなぜインストールされているのか把握困難になる。この機能により、パッケージの削除可否の判断や、依存関係の整理に役立つ情報を得られる。

**機能の利用シーン**：
- 不要なパッケージを削除する前の影響調査
- セキュリティ脆弱性のあるパッケージの依存元特定
- 依存関係の整理・最適化
- パッケージサイズの削減検討

**主要な処理内容**：
1. 引数の解析（パッケージ名、ワイルドカード対応）
2. lockfileの読み込み
3. 対象パッケージの特定（複数バージョン対応）
4. 逆依存関係の構築
5. 依存ツリーの表示

**関連システム・外部連携**：ローカルファイルシステムのみ。

**権限による制御**：特別な権限は不要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | why | 主画面 | パッケージの依存元を表示 |

## 機能種別

データ連携（ファイルシステム操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| package | string | Yes | 検索するパッケージ名（glob対応） | - |
| --top | boolean | No | トップレベルの依存元のみ表示 | - |
| --depth | number | No | 表示する深さの制限（デフォルト: 100） | - |

### 入力データソース

- bun.lockb / bun.lock（lockfile）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| パッケージ名@バージョン | string | 対象パッケージ |
| 依存元ツリー | tree | 逆依存関係のツリー構造 |
| 依存種別 | string | dev/peer/optional等 |
| バージョン指定 | string | 依存元が要求するバージョン |

### 出力先

標準出力（コンソール）- ツリー形式

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数の解析
   └─ パッケージ名、--top、--depthを取得
2. lockfileの読み込み
   └─ Lockfile.loadFromCwdで読み込み
3. 深さ制限の設定
   ├─ --top: 深さ1
   ├─ --depth: 指定値
   └─ デフォルト: 100
4. 逆依存関係マップの構築
   └─ 各パッケージの依存元を記録
5. 対象パッケージの検索
   ├─ 完全一致検索
   └─ glob（ワイルドカード）検索
6. バージョン情報の収集
   └─ 同名パッケージの全バージョンを収集
7. 依存ツリーの表示
   └─ 再帰的にツリーを出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[引数解析]
    B --> C[lockfile読み込み]
    C --> D{lockfile存在?}
    D -->|No| E[エラー: lockfile必須]
    D -->|Yes| F[深さ制限設定]
    F --> G[逆依存関係マップ構築]
    G --> H{パッケージ名にglob?}
    H -->|Yes| I[glob検索]
    H -->|No| J[完全一致検索]
    I --> K{マッチあり?}
    J --> K
    K -->|No| L[エラー: パッケージ未発見]
    K -->|Yes| M[バージョン情報収集]
    M --> N[各バージョンについて]
    N --> O[依存ツリー表示]
    O --> P{次のバージョン?}
    P -->|Yes| N
    P -->|No| Q[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-28-01 | lockfile必須 | lockfileが存在する必要がある | 常時 |
| BR-28-02 | glob対応 | `*`を使用したパターンマッチをサポート | パッケージ名に`*`含む |
| BR-28-03 | バージョン指定 | `package@version`形式でバージョン指定可能 | @を含む場合 |
| BR-28-04 | 循環検出 | 循環依存を検出して*circularと表示 | 循環依存時 |
| BR-28-05 | 依存種別表示 | dev/peer/optional等の依存種別を表示 | 常時 |

### 計算ロジック

**Glob検索**:
```
GlobPattern types:
- exact: 完全一致
- prefix: 前方一致（*が末尾）
- suffix: 後方一致（*が先頭）
- middle: 中間一致（*が中間）
- contains: 部分一致（*が両端）
```

**依存種別判定**:
```
if behavior.dev -> "dev"
if behavior.optional and behavior.peer -> "optional peer"
if behavior.optional -> "optional"
if behavior.peer -> "peer"
else -> "prod" (表示なし)
```

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

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

本機能はデータベースを使用しない。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | LockfileNotFound | lockfileが見つからない | bun installを実行 |
| - | PackageNotFound | 指定パッケージがlockfileにない | パッケージ名を確認 |
| - | InvalidGlob | 無効なglob形式 | glob構文を確認 |

### リトライ仕様

リトライ処理は実装されていない。

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

トランザクション管理なし。読み取り専用の処理。

## パフォーマンス要件

- パッケージ数に依存
- 通常は即座に完了

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

特別なセキュリティ考慮事項なし。

## 備考

- `bun pm why`としても実行可能
- ワークスペースパッケージは青色で表示
- 循環依存は黄色で警告表示

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | why_command.zig | `src/cli/why_command.zig` | DependentInfo構造体（13-19行目）で依存元情報を管理 |
| 1-2 | why_command.zig | `src/cli/why_command.zig` | DependencyType enum（22-28行目）で依存種別を定義 |
| 1-3 | why_command.zig | `src/cli/why_command.zig` | GlobPattern構造体（72-188行目）でパターンマッチを定義 |

**読解のコツ**: DependentInfoがツリー表示の各ノードに対応する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | why_command.zig | `src/cli/why_command.zig` | exec関数（213-231行目）がエントリーポイント |
| 2-2 | why_command.zig | `src/cli/why_command.zig` | execWithManager関数（242-375行目）がメイン処理 |

**主要処理フロー**:
1. **243-244行目**: lockfileの読み込み
2. **246-252行目**: 深さ制限の設定
3. **260-270行目**: アリーナアロケータの初期化
4. **272行目**: 逆依存関係マップの初期化
5. **274行目**: GlobPatternの初期化
6. **276-335行目**: パッケージ走査と逆依存関係の構築
7. **342-374行目**: 対象パッケージの表示

#### Step 3: ツリー表示を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | why_command.zig | `src/cli/why_command.zig` | printPackageWithType関数（377-405行目） |
| 3-2 | why_command.zig | `src/cli/why_command.zig` | printDependencyTree関数（429-477行目） |

**主要処理フロー**:
- **377-405行目**: 依存種別とパッケージ情報の表示
- **437-443行目**: 循環依存の検出
- **451-476行目**: 再帰的なツリー表示

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

```
WhyCommand.exec
    │
    ├─ PackageManager.CommandLineArguments.parse
    │
    ├─ PackageManager.init
    │
    └─ execWithManager
           ├─ lockfile.loadFromCwd
           ├─ GlobPattern.init
           ├─ 逆依存関係マップ構築（ループ）
           │      └─ GlobPattern.matchesName
           ├─ printPackageWithType
           └─ printDependencyTree（再帰）
                  └─ compareDependents（ソート用）
```

### データフロー図

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

パッケージ名 ───▶ GlobPattern解析
     │                  │
     ▼                  ▼
lockfile ──────▶ 逆依存関係マップ構築
                       │
                       ▼
              パッケージ検索 ───▶ マッチしたパッケージ
                       │
                       ▼
              ツリー構築 ─────▶ 依存ツリー
                       │
                       ▼
              表示処理 ─────▶ 標準出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| why_command.zig | `src/cli/why_command.zig` | ソース | whyコマンドのメイン実装 |
| pm_why_command.zig | `src/cli/pm_why_command.zig` | ソース | pm why経由の実装 |
| PackageManager.zig | `src/install/PackageManager.zig` | ソース | パッケージマネージャー |
| lockfile.zig | `src/install/lockfile.zig` | ソース | lockfile読み込み |
| Semver.zig | `src/Semver.zig` | ソース | バージョン比較 |
