# 画面設計書 12-link

## 概要

本ドキュメントは、Bun CLIの `bun link` コマンドの画面設計書です。ローカルnpmパッケージをグローバルに登録したり、登録済みのパッケージをプロジェクトにリンクする機能の仕様を定義します。

### 本画面の処理概要

`bun link` コマンドは、ローカル開発中のパッケージをグローバルシンボリックリンクとして登録し、他のプロジェクトから参照可能にする機能を提供します。npmやyarnの同等機能と互換性があります。

**業務上の目的・背景**：複数のパッケージを同時開発するmonorepo環境や、ライブラリを開発しながらアプリケーションでテストする場合に、パッケージをnpmに公開せずにローカルで相互参照できるようにします。これにより開発イテレーションを高速化し、公開前のテストが容易になります。

**画面へのアクセス方法**：ターミナルで以下のいずれかを実行します：
- `bun link`：現在のパッケージをグローバル登録
- `bun link <package-name>`：グローバル登録済みパッケージを現在のプロジェクトにリンク

**主要な操作・処理内容**：
1. 引数なしの場合：現在のpackage.jsonのパッケージをグローバルディレクトリにシンボリックリンク登録
2. 引数ありの場合：指定パッケージをnode_modulesにシンボリックリンクとしてインストール
3. バイナリがある場合はグローバルbinディレクトリにもリンクを作成

**画面遷移**：単独で実行されるCLIコマンドです。リンク完了後、後続の使用方法がターミナルに表示されます。

**権限による表示制御**：グローバルディレクトリへの書き込み権限が必要です。Windows環境ではジャンクションを使用するため管理者権限が必要な場合があります。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 20 | bun link | 主機能 | ローカルnpmパッケージのグローバル登録とリンク |
| 42 | グローバルキャッシュ | 補助機能 | リンク先のグローバルキャッシュへの登録 |

## 画面種別

コマンド実行（成功/エラーメッセージ出力）

## URL/ルーティング

```
bun link [package-name]
```

## 入出力項目

### 入力項目（コマンドライン引数）

| 項目名 | 型 | 必須 | 説明 |
|--------|-----|------|------|
| package-name | string | いいえ | リンクするパッケージ名（省略時は現在のパッケージを登録） |
| --global-dir | string | いいえ | グローバルディレクトリのパス |
| --silent | boolean | いいえ | 出力を抑制する |

### 出力項目

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 成功メッセージ | string | 登録完了時の使用方法ガイド |
| エラーメッセージ | string | 処理失敗時の詳細情報 |

## 表示項目

### 成功時出力（グローバル登録）

```
Success! Registered "{package-name}"

To use {package-name} in a project, run:
  bun link {package-name}

Or add it in dependencies in your package.json file:
  "{package-name}": "link:{package-name}"
```

## イベント仕様

### 1-グローバル登録（引数なし）

コマンド実行時の処理フロー：

1. `LinkCommand.exec()` がエントリーポイントとして呼び出される
2. コマンドライン引数を解析し、位置引数の有無を確認
3. 引数がない場合、`link()` 関数でグローバル登録処理を実行
4. package.jsonからパッケージ名を取得
5. グローバルディレクトリ（~/.bun/install/global/node_modules）をセットアップ
6. 現在のディレクトリへのシンボリックリンクを作成
7. バイナリがあればグローバルbinにもリンクを作成

### 2-プロジェクトへのリンク（引数あり）

1. 引数ありの場合、`updatePackageJSONAndInstallWithManager()` を呼び出し
2. グローバルに登録されたパッケージをプロジェクトのnode_modulesにリンク
3. package.jsonのdependenciesを更新

## データベース更新仕様

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

本コマンドはファイルシステム操作のみを行います。

| 操作（イベント） | 対象 | 操作種別 | 概要 |
|----------------|------|---------|------|
| グローバル登録 | グローバルnode_modules | シンボリックリンク作成 | パッケージディレクトリへのリンク作成 |
| グローバルbin登録 | グローバルbinディレクトリ | シンボリックリンク作成 | 実行可能ファイルへのリンク作成 |
| プロジェクトリンク | ローカルnode_modules | シンボリックリンク作成 | グローバルパッケージへのリンク作成 |
| package.json更新 | package.json | UPDATE | dependenciesにlink:形式で追加 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| LINK_001 | 情報 | bun link v{version} | コマンド開始時 |
| LINK_002 | 成功 | Success! Registered "{name}" | グローバル登録成功時 |
| LINK_003 | エラー | package.json missing "name" | nameフィールドがない場合 |
| LINK_004 | エラー | invalid package.json name "{name}" | 名前が不正な場合 |
| LINK_005 | エラー | failed to read "{path}" for linking | package.json読み込み失敗 |
| LINK_006 | エラー | failed to create symlink/junction to node_modules in global dir | リンク作成失敗 |
| LINK_007 | エラー | failed to create scope in global dir | スコープディレクトリ作成失敗 |
| LINK_008 | エラー | failed to link bin | バイナリリンク失敗 |

## 例外処理

| 例外条件 | 処理内容 | エラーコード |
|---------|---------|------------|
| package.json未検出 | 自動作成を試行、失敗時はエラー終了 | 1 |
| nameフィールド不在 | エラーメッセージを表示して終了 | 1 |
| 無効なパッケージ名 | エラーメッセージを表示して終了 | 1 |
| グローバルディレクトリ作成失敗 | エラーメッセージを表示して終了 | 1 |
| シンボリックリンク作成失敗 | エラーメッセージを表示して終了 | 1 |

## 備考

- Windows環境ではシンボリックリンクの代わりにジャンクション（UV_FS_SYMLINK_JUNCTION）を使用
- スコープ付きパッケージ（@org/name形式）は自動的にスコープディレクトリを作成
- 既存のリンクがある場合は上書きされる
- グローバルディレクトリは `~/.bun/install/global` がデフォルト

---

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

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

### 推奨読解順序

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

linkコマンドではLockfileとPackageの構造体が使用されます。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | link_command.zig | `src/cli/link_command.zig` | Lockfile.Package構造体の使用（L29）：パッケージ情報の格納 |
| 1-2 | install.zig | `src/install/install.zig` | Bin.Linker構造体：バイナリリンク処理を担当 |

**読解のコツ**: linkコマンドは位置引数の有無で2つの異なるモード（登録/リンク）を持つ。

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

処理の起点となるexec関数を確認します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | link_command.zig | `src/cli/link_command.zig` | exec関数（L2-4）：link関数への委譲 |
| 2-2 | link_command.zig | `src/cli/link_command.zig` | link関数（L7-190）：メイン処理ロジック |

**主要処理フロー**:
1. **L8**: コマンドライン引数を.linkモードで解析
2. **L9-16**: PackageManagerを初期化（package.jsonがなければ作成を試行）
3. **L24**: 位置引数の数で処理を分岐

#### Step 3: グローバル登録処理を理解する

引数なしの場合のグローバル登録処理を読み解きます。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | link_command.zig | `src/cli/link_command.zig` | グローバル登録（L24-185）：位置引数が1の場合の処理 |

**主要処理フロー**:
- **L32-56**: package.jsonを解析してパッケージ名を取得・検証
- **L59-74**: グローバルnode_modulesディレクトリをセットアップ
- **L77-124**: シンボリックリンク（またはジャンクション）を作成
- **L127-163**: バイナリがあればBin.Linkerでbinリンクを作成
- **L168-182**: 成功メッセージと使用方法を出力

#### Step 4: プロジェクトリンク処理を理解する

引数ありの場合のプロジェクトリンク処理を読み解きます。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | link_command.zig | `src/cli/link_command.zig` | プロジェクトリンク（L186-189）：updatePackageJSONAndInstallWithManager呼び出し |

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

```
LinkCommand.exec()
    │
    └─ link()
           │
           ├─ CommandLineArguments.parse(.link)
           │
           ├─ PackageManager.init()
           │      └─ attemptToCreatePackageJSON() [package.jsonがない場合]
           │
           ├─ [引数なし: グローバル登録]
           │      │
           │      ├─ File.toSource() - package.json読み込み
           │      │
           │      ├─ Lockfile.Package.parse() - パッケージ情報解析
           │      │
           │      ├─ Options.openGlobalDir() - グローバルディレクトリ取得
           │      │
           │      ├─ manager.setupGlobalDir() - ディレクトリセットアップ
           │      │
           │      ├─ node_modules.symLink() [POSIX]
           │      │   または
           │      │   symlinkUV() with JUNCTION [Windows]
           │      │
           │      └─ Bin.Linker.link() - バイナリリンク
           │
           └─ [引数あり: プロジェクトリンク]
                  │
                  └─ manager.updatePackageJSONAndInstallWithManager()
```

### データフロー図

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

package.json ───────────▶ Package.parse() ─────────────────┐
                                                           │
                         ┌────────────────────────────────▶│
                         │                                 │
グローバルディレクトリ ──▶ setupGlobalDir() ──────────────▶│
設定                                                       │
                                                           ▼
                                               シンボリックリンク作成
                                                           │
                         ┌─────────────────────────────────┘
                         │
                         ▼
[グローバルnode_modules]         [グローバルbin]
~/.bun/install/global/           ~/.bun/bin/
node_modules/{pkg} ──▶ cwd       {bin-name} ──▶ node_modules/{pkg}/{bin}

                                                      │
                                                      ▼
                                               [成功メッセージ]
                                               Success! Registered...
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| link_command.zig | `src/cli/link_command.zig` | ソース | linkコマンドのメイン実装 |
| install.zig | `src/install/install.zig` | ソース | PackageManager、Bin.Linker定義 |
| lockfile.zig | `src/install/lockfile.zig` | ソース | Lockfile.Package定義 |
| sys.zig | `src/sys.zig` | ソース | ファイルシステム操作ユーティリティ |
| sys_uv.zig | `src/sys_uv.zig` | ソース | Windows用ジャンクション作成（symlinkUV） |
