# 機能設計書 20-bun link

## 概要

本ドキュメントは、Bunランタイムが提供するパッケージリンク機能「bun link」の設計を記述する。

### 本機能の処理概要

bun linkは、ローカルパッケージをグローバルにリンクし、他のプロジェクトから参照可能にするCLIコマンドである。npm linkと同等の機能を提供し、ローカル開発中のパッケージを他のプロジェクトでテストできる。

**業務上の目的・背景**：ライブラリやツールの開発時、npmへ公開する前にローカル環境でテストする必要がある。bun linkは、開発中のパッケージを他のプロジェクトからシンボリックリンク経由で参照できるようにする。

**機能の利用シーン**：
- ローカルパッケージの開発とテスト
- monorepo内でのパッケージ参照
- ライブラリ公開前のインテグレーションテスト
- フォークしたパッケージのローカル使用

**主要な処理内容**：
1. パッケージのグローバル登録（引数なしのbun link）
2. 登録済みパッケージの参照追加（bun link <package-name>）
3. package.jsonからパッケージ名取得
4. グローバルディレクトリへのシンボリックリンク作成
5. バイナリのグローバルリンク

**関連システム・外部連携**：
- ファイルシステム（シンボリックリンク/ジャンクション）
- グローバルディレクトリ

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | link | 主画面 | bun linkコマンドの実行インターフェース |

## 機能種別

パッケージ管理 / ファイル操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| package_name | string | No | リンクするパッケージ名（省略時は現在のパッケージを登録） | 有効なパッケージ名 |

### 入力データソース

- コマンドライン引数
- package.json（現在のディレクトリ）
- グローバルディレクトリの既存リンク

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| global_link | Symlink | グローバルディレクトリへのシンボリックリンク |
| bin_links | Symlink[] | バイナリへのリンク（binフィールド存在時） |
| node_modules_link | Symlink | プロジェクトのnode_modulesへのリンク（パッケージ名指定時） |

### 出力先

- グローバルnode_modulesディレクトリ（~/.bun/install/global/node_modules）
- グローバルbinディレクトリ
- プロジェクトのnode_modules（パッケージ名指定時）

## 処理フロー

### 処理シーケンス

**ケース1: 引数なし（bun link）- パッケージを登録**
```
1. package.jsonの読み込み
   └─ 現在ディレクトリのpackage.jsonを解析
2. パッケージ名取得
   └─ nameフィールドを取得、検証
3. グローバルディレクトリ準備
   └─ 必要に応じてディレクトリ作成
4. 既存リンク削除
   └─ 同名のリンクがあれば削除
5. シンボリックリンク作成
   └─ 現在ディレクトリへのリンクを作成
6. バイナリリンク作成
   └─ binフィールドがあればバイナリもリンク
7. 完了メッセージ
   └─ 使用方法を表示
```

**ケース2: パッケージ名指定（bun link <package>）- リンクを使用**
```
1. グローバルリンクの確認
   └─ 指定パッケージが登録済みか確認
2. package.jsonへの追加
   └─ 依存関係として"link:<package>"を追加
3. インストール実行
   └─ updatePackageJSONAndInstallを実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[CLI引数パース]
    B --> C{パッケージ名指定?}
    C -->|No| D[package.json読み込み]
    C -->|Yes| E[リンク使用処理]
    D --> F{nameフィールドあり?}
    F -->|No| G[エラー: name未設定]
    F -->|Yes| H[グローバルディレクトリ準備]
    H --> I[既存リンク削除]
    I --> J[シンボリックリンク作成]
    J --> K{binフィールドあり?}
    K -->|Yes| L[バイナリリンク作成]
    K -->|No| M[成功メッセージ]
    L --> M
    E --> N[package.json更新]
    N --> O[インストール実行]
    O --> P[終了]
    M --> P
    G --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 名前必須 | package.jsonにnameフィールドが必要 | bun link（登録時） |
| BR-02 | 名前検証 | NPM命名規則に従うパッケージ名 | 常時 |
| BR-03 | スコープ対応 | @org/packageのスコープ付きパッケージ対応 | スコープ付きパッケージ時 |
| BR-04 | Windows対応 | Windowsではジャンクション使用 | Windows環境時 |

### 計算ロジック

- グローバルディレクトリパス: Options.openGlobalDirで取得
- スコープディレクトリ: @付きパッケージの場合、スコープディレクトリを作成

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

本機能はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | MissingName | package.jsonにnameがない | nameフィールドを追加 |
| - | InvalidName | パッケージ名が不正 | 正しい形式の名前を使用 |
| - | PermissionDenied | グローバルディレクトリに書き込めない | 権限を確認 |
| - | LinkFailed | シンボリックリンク作成に失敗 | エラー内容を確認 |

### リトライ仕様

リトライは行わない。

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

シンボリックリンクの作成はアトミックではない。

## パフォーマンス要件

シンボリックリンク操作は高速。

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

- グローバルディレクトリへの書き込み権限が必要
- リンク先のパッケージのコードがそのまま実行される

## 備考

- `bun unlink` でリンクを解除可能

---

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | link_command.zig | `src/cli/link_command.zig` | LinkCommand.exec関数 |

**主要処理フロー**:
1. **1-6行目**: LinkCommand構造体とexec関数定義
2. **7-190行目**: link関数（メイン処理）
3. **7-16行目**: CLI引数パースとPackageManager初期化
4. **18-22行目**: バージョン情報出力

#### Step 2: パッケージ登録処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | link_command.zig | `src/cli/link_command.zig` | 引数なし時の処理（24-186行目） |

**主要処理フロー**:
- **27-30行目**: lockfile初期化
- **32-56行目**: package.json解析とname取得
- **58-74行目**: グローバルディレクトリ準備
- **76-91行目**: スコープディレクトリ作成
- **93-123行目**: シンボリックリンク/ジャンクション作成
- **126-163行目**: バイナリリンク作成
- **168-182行目**: 成功メッセージ出力

#### Step 3: リンク使用処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | link_command.zig | `src/cli/link_command.zig` | パッケージ名指定時の処理 |

**主要処理フロー**:
- **188行目**: updatePackageJSONAndInstallWithManager呼び出し

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

```
LinkCommand.exec
    │
    └─ link
           │
           ├─ CommandLineArguments.parse
           │      └─ CLI引数解析
           │
           ├─ PackageManager.init
           │      └─ 初期化、package.json読み込み
           │
           ├─ (引数なし) パッケージ登録
           │      ├─ Lockfile.Package.parse
           │      │      └─ package.json解析
           │      ├─ Options.openGlobalDir
           │      │      └─ グローバルディレクトリ取得
           │      ├─ setupGlobalDir
           │      │      └─ ディレクトリ準備
           │      ├─ symLink / symlinkUV
           │      │      └─ シンボリックリンク作成
           │      └─ Bin.Linker.link
           │             └─ バイナリリンク
           │
           └─ (引数あり) リンク使用
                  └─ updatePackageJSONAndInstallWithManager
```

### データフロー図

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

(引数なし)
package.json ───────▶ パッケージ解析 ──────────────▶ パッケージ情報
                            │
                            ▼
                     グローバルDir準備 ─────────────▶ ディレクトリ作成
                            │
                            ▼
現在ディレクトリ ───▶ シンボリックリンク ───────────▶ グローバルリンク
                            │
                            ▼
binフィールド ──────▶ バイナリリンク ────────────────▶ グローバルbinリンク

(引数あり)
パッケージ名 ───────▶ package.json更新 ──────────────▶ 依存関係追加
                            │
                            ▼
                     インストール実行 ─────────────▶ node_modules/リンク
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| link_command.zig | `src/cli/link_command.zig` | ソース | CLIエントリーポイント、リンク処理 |
| PackageManager.zig | `src/install/PackageManager.zig` | ソース | パッケージ管理、インストール処理 |
| lockfile.zig | `src/install/lockfile.zig` | ソース | Lockfile.Package.parse |
| Bin.zig | `src/install/Bin.zig` | ソース | Bin.Linker（バイナリリンク） |
