# 機能設計書 23-bun patch

## 概要

本ドキュメントは、Bunパッケージマネージャーの `bun patch` コマンドの機能設計を記述する。このコマンドは、インストール済みのnpmパッケージにパッチを適用する準備を行う。

### 本機能の処理概要

`bun patch` は、node_modules内のパッケージを編集可能な状態にし、後でパッチファイルとして保存できるように準備する機能を提供する。pnpmやyarnのpatch機能と互換性のあるワークフローを実現する。

**業務上の目的・背景**：依存パッケージにバグがあった場合や、一時的な修正が必要な場合、パッケージのソースコードを直接編集して修正する必要がある。しかし、node_modulesは通常キャッシュからハードリンクされており、直接編集するとキャッシュ自体が破損する可能性がある。`bun patch` はパッケージをキャッシュからコピーし、安全に編集できる状態にする。

**機能の利用シーン**：
- 依存パッケージのバグを一時的に修正する場合
- アップストリームへのPR作成前にローカルでテストする場合
- 特定環境向けにパッケージの動作を調整する場合
- セキュリティ修正を即座に適用する場合

**主要な処理内容**：
1. 引数の解析（パッケージ名@バージョン または node_modulesパス）
2. lockfileからパッケージ情報を取得
3. グローバルキャッシュのパス計算
4. キャッシュからnode_modulesフォルダにパッケージをコピー（ハードリンク解除）
5. 編集対象フォルダとcommitコマンドの案内を表示

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

**権限による制御**：node_modulesディレクトリへの書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 15 | patch | 主画面 | パッケージのパッチ適用準備 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| package | string | Yes | パッケージ名（例: is-even）またはパッケージ名@バージョン（例: is-even@1.0.0）またはnode_modulesパス | lockfileに存在すること |

### 入力データソース

- bun.lockb / bun.lock（lockfile）
- グローバルキャッシュディレクトリ
- node_modulesディレクトリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 編集フォルダパス | string | パッチを適用するために編集するフォルダ |
| commitコマンド | string | 編集完了後に実行するコマンド |

### 出力先

- 標準出力（コンソール）
- node_modulesディレクトリ（ファイルコピー）

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数の解析
   └─ パッケージ指定方法を判定（パス or 名前@バージョン）
2. lockfileの読み込み
   └─ Lockfile.loadFromCwdで現在のlockfileを読み込み
3. パッケージ情報の特定
   ├─ パス指定時: package.jsonからパッケージ名・バージョンを取得
   └─ 名前指定時: lockfileからパッケージIDを検索
4. キャッシュディレクトリの計算
   └─ computeCacheDirAndSubpathでキャッシュパスを取得
5. 既存パッチ情報の確認
   └─ patchedDependenciesに既存パッチがあるか確認
6. パッケージのコピー
   └─ overwritePackageInNodeModulesFolderでキャッシュからコピー
7. 案内の表示
   └─ 編集フォルダとbun patch --commitコマンドを表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[引数解析]
    B --> C{引数形式?}
    C -->|パス| D[package.json解析]
    C -->|名前@バージョン| E[lockfileから検索]
    D --> F{複数バージョン存在?}
    E --> F
    F -->|Yes| G[バージョン選択を促す]
    F -->|No| H[キャッシュパス計算]
    G --> Z[エラー終了]
    H --> I{既存パッチあり?}
    I -->|Yes| J[パッチハッシュを含めて計算]
    I -->|No| K[通常のキャッシュパス]
    J --> L[node_modulesにコピー]
    K --> L
    L --> M{ワークスペースルート?}
    M -->|Yes| N[相対パスで案内表示]
    M -->|No| O[絶対パスで案内表示]
    N --> P[終了]
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-23-01 | lockfile必須 | lockfileが存在する必要がある | 常時 |
| BR-23-02 | パッケージ存在確認 | 指定パッケージがlockfileに存在する必要がある | 常時 |
| BR-23-03 | 複数バージョン禁止 | 同名パッケージが複数バージョン存在する場合はバージョン指定が必要 | 名前のみ指定時 |
| BR-23-04 | ハードリンク解除 | キャッシュからコピーすることでハードリンクを解除 | 常時 |

### 計算ロジック

**引数形式判定**:
```
if "node_modules/" in argument:
    return .path
else:
    return .name_and_version
```

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

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

本機能はデータベースを使用しない。ファイルシステムのみを操作する。

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | LockfileNotFound | lockfileが見つからない | bun installを実行 |
| - | PackageNotFound | 指定パッケージがlockfileにない | パッケージ名を確認 |
| - | MultipleVersions | 複数バージョンが存在 | バージョンを指定 |
| - | CacheReadError | キャッシュからの読み込み失敗 | キャッシュをクリア |

### リトライ仕様

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

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

トランザクション管理なし。コピー処理が途中で失敗した場合、不完全な状態になる可能性がある。

## パフォーマンス要件

パッケージサイズに依存。一般的なパッケージで数秒以内に完了。

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

- キャッシュディレクトリへの読み取りアクセスが必要
- node_modulesへの書き込みアクセスが必要

## 備考

- pnpm patch / yarn patch との互換性を意識した設計
- ワークスペース環境では相対パスの扱いに注意

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | patchPackage.zig | `src/install/PackageManager/patchPackage.zig` | PatchArgKind enum（952-961行目）で引数形式を定義 |

**読解のコツ**: Zigのenum定義とメソッドの組み合わせに注目。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | patch_command.zig | `src/cli/patch_command.zig` | exec関数がupdatePackageJSONAndInstallCatchErrorを呼び出し |
| 2-2 | patchPackage.zig | `src/install/PackageManager/patchPackage.zig` | preparePatch関数（544行目〜）がメイン処理 |

**主要処理フロー**:
1. **546行目**: 引数を取得
2. **548行目**: PatchArgKind.fromArgで引数形式を判定
3. **556-568行目**: ワークスペースルートでない場合のパス調整
4. **570-703行目**: 引数形式に応じたキャッシュ情報取得
5. **709-715行目**: overwritePackageInNodeModulesFolderでコピー
6. **717-724行目**: 案内表示

#### Step 3: パッケージ検索を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | patchPackage.zig | `src/install/PackageManager/patchPackage.zig` | pkgInfoForNameAndVersion関数（796-942行目） |

**主要処理フロー**:
- **807行目**: パッケージ名のハッシュ計算
- **814-827行目**: lockfileから一致するパッケージを検索
- **836-867行目**: バージョン指定時の処理
- **873-917行目**: バージョン未指定で単一一致の場合
- **919-941行目**: 複数バージョン存在時のエラー表示

#### Step 4: コピー処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | patchPackage.zig | `src/install/PackageManager/patchPackage.zig` | overwritePackageInNodeModulesFolder関数（729-773行目） |

**主要処理フロー**:
- **734行目**: 既存ディレクトリを削除
- **758-762行目**: 除外ディレクトリ（node_modules, .git等）の定義
- **764-772行目**: FileCopierでコピー実行

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

```
PatchCommand.exec
    │
    └─ updatePackageJSONAndInstallCatchError
           │
           └─ preparePatch
                  ├─ PatchArgKind.fromArg
                  ├─ Lockfile.loadFromCwd
                  ├─ pkgInfoForNameAndVersion (名前指定時)
                  │      └─ nodeModulesFolderForDependencyID
                  ├─ computeCacheDirAndSubpath
                  └─ overwritePackageInNodeModulesFolder
                         └─ FileCopier.copy
```

### データフロー図

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

パッケージ指定 ───▶ 引数形式判定
     │                  │
     ▼                  ▼
lockfile ──────▶ パッケージ検索 ───▶ パッケージID
                       │
                       ▼
キャッシュ ─────▶ パス計算 ─────▶ キャッシュパス
                       │
                       ▼
              ファイルコピー ───▶ node_modules
                       │
                       ▼
              案内表示 ─────▶ 標準出力
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| patch_command.zig | `src/cli/patch_command.zig` | ソース | patchコマンドのエントリーポイント |
| patchPackage.zig | `src/install/PackageManager/patchPackage.zig` | ソース | パッチ準備処理の実装 |
| lockfile.zig | `src/install/lockfile.zig` | ソース | lockfileの読み込み |
| PackageManager.zig | `src/install/PackageManager.zig` | ソース | キャッシュパス計算 |
| FileCopier.zig | `src/install/FileCopier.zig` | ソース | ファイルコピー処理 |
