# 機能設計書 19-bunx

## 概要

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

### 本機能の処理概要

bunxは、npmパッケージを一時的にインストールして実行するCLIコマンドである。npxと互換性があり、グローバルインストールなしでCLIツールを実行できる。

**業務上の目的・背景**：開発ツールやCLIユーティリティを一時的に使用したい場合、グローバルインストールせずに実行できることが便利である。bunxは、npxと同等の機能を高速に提供する。

**機能の利用シーン**：
- create-react-app等のscaffoldingツールの実行
- eslint、prettier等のLinterの一時実行
- 特定バージョンのツールを試す
- CI/CDでのツール実行

**主要な処理内容**：
1. パッケージ名の解析
2. ローカルnode_modulesから既存バイナリを検索
3. キャッシュから既存インストールを検索
4. 必要に応じてパッケージをインストール
5. パッケージのバイナリを実行
6. 引数を渡して実行

**関連システム・外部連携**：
- npmレジストリ
- ファイルシステム（キャッシュディレクトリ）
- 子プロセス実行

**権限による制御**：特に権限による制御は行わない。

## 関連画面

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

## 機能種別

パッケージ実行 / ネットワーク通信 / プロセス管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| package | string | Yes | 実行するパッケージ名 | 有効なパッケージ名[@バージョン] |
| args | string[] | No | パッケージに渡す引数 | - |
| --bun / -b | boolean | No | Bunランタイムで実行を強制 | - |
| --silent | boolean | No | インストールログを抑制 | - |
| --verbose | boolean | No | 詳細ログを出力 | - |
| --no-install | boolean | No | インストールせず既存のみ使用 | - |
| --package / -p | string | No | パッケージ名を明示的に指定 | パッケージ名 |

### 入力データソース

- コマンドライン引数
- ローカルnode_modules/.bin
- 一時キャッシュディレクトリ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| stdout | stream | 実行したコマンドの標準出力 |
| stderr | stream | 実行したコマンドの標準エラー出力 |
| exit_code | number | 実行したコマンドの終了コード |

### 出力先

- 標準出力/標準エラー出力
- プロセス終了コード

## 処理フロー

### 処理シーケンス

```
1. CLI引数のパース
   └─ パッケージ名と引数を分離
2. パッケージ名の正規化
   └─ tsc → typescript 等の変換
3. ローカル検索
   └─ node_modules/.binから検索
4. キャッシュ検索
   └─ 一時ディレクトリから検索
5. キャッシュ有効性確認
   └─ 1日以上経過していればstale
6. パッケージインストール（必要時）
   └─ bun addでキャッシュにインストール
7. バイナリ実行
   └─ 検出したバイナリを引数付きで実行
8. 終了コード転送
   └─ 実行結果の終了コードで終了
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[CLI引数パース]
    B --> C[パッケージ名正規化]
    C --> D{ローカルnode_modulesにあり?}
    D -->|Yes| E[バイナリパス取得]
    D -->|No| F{キャッシュにあり?}
    F -->|Yes| G{キャッシュ有効?}
    F -->|No| H[パッケージインストール]
    G -->|Yes| E
    G -->|No, --no-install| I[警告: stale使用]
    G -->|No| H
    H --> J[バイナリパス取得]
    I --> E
    J --> E
    E --> K[バイナリ実行]
    K --> L[終了コード転送]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | tsc変換 | tsc → typescript パッケージへ変換 | tsc指定時 |
| BR-02 | キャッシュ有効期限 | 1日（24時間）でstale判定 | キャッシュ参照時 |
| BR-03 | create-プレフィックス | bun create xはcreate-xとして実行 | create使用時 |
| BR-04 | バイナリ名推定 | パッケージ名からバイナリ名を推定 | 常時 |
| BR-05 | キャッシュパス | /tmp/bunx-{uid}-{package@version}/ | 常時 |

### 計算ロジック

- キャッシュ有効期限: ファイルのmtimeから24時間以上経過でstale
- バイナリ名推定: package.jsonのbinフィールドを解析

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | PackageNotFound | パッケージが存在しない | パッケージ名を確認 |
| - | NoBinFound | パッケージにバイナリがない | パッケージを確認 |
| - | InstallFailed | インストールに失敗 | ネットワーク確認 |

### リトライ仕様

インストール失敗時はリトライしない。

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

キャッシュへのインストールは他のbunxプロセスと競合する可能性がある。

## パフォーマンス要件

- ローカル/キャッシュからの実行は即座に開始
- インストール時はbun addの高速性を活用

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

- 実行するパッケージのpostinstallスクリプトに注意
- キャッシュディレクトリはユーザーIDで分離

## 備考

- `bun x` でも同様に動作

---

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

### 推奨読解順序

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

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

**主要処理フロー**:
1. **1行目**: debug出力の設定
2. **3-136行目**: BunxCommand構造体とOptions構造体
3. **7-130行目**: Options.parse関数（CLI引数解析）
4. **138-176行目**: addCreatePrefix関数
5. **178-181行目**: キャッシュ有効期限定数
6. **183-325行目**: バイナリ名取得関数群
7. **332-863行目**: exec関数（メイン処理）

#### Step 2: バイナリ検索を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bunx_command.zig | `src/cli/bunx_command.zig` | getBinName、getBinNameFromSubpath関数 |

**主要処理フロー**:
- **183-251行目**: getBinNameFromSubpath関数
- **253-257行目**: getBinNameFromProjectDirectory関数
- **259-306行目**: getBinNameFromTempDirectory関数
- **308-325行目**: getBinName関数

#### Step 3: 実行処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | bunx_command.zig | `src/cli/bunx_command.zig` | exec関数の後半 |

**主要処理フロー**:
- **550-686行目**: 既存バイナリ検索と実行
- **697-712行目**: パッケージインストール
- **713-798行目**: bun addサブプロセス実行
- **800-862行目**: インストール後のバイナリ検索と実行

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

```
BunxCommand.exec
    │
    ├─ Options.parse
    │      └─ CLI引数解析
    │
    ├─ UpdateRequest.parse
    │      └─ パッケージ名解析
    │
    ├─ Run.configureEnvForRun
    │      └─ 環境変数設定
    │
    ├─ bun.which
    │      └─ PATHからバイナリ検索
    │
    ├─ getBinName
    │      ├─ getBinNameFromProjectDirectory
    │      └─ getBinNameFromTempDirectory
    │
    ├─ bun.spawnSync (bun add)
    │      └─ パッケージインストール
    │
    └─ Run.runBinary
           └─ バイナリ実行（noreturn）
```

### データフロー図

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

パッケージ名 ───────▶ パッケージ解析 ──────────────▶ UpdateRequest
                            │
                            ▼
node_modules ───────▶ ローカル検索 ─────────────────▶ バイナリパス?
                            │
                            ▼ (なし)
キャッシュ ─────────▶ キャッシュ検索 ────────────────▶ バイナリパス?
                            │
                            ▼ (なし or stale)
                     bun add ──────────────────────▶ キャッシュにインストール
                            │
                            ▼
                     バイナリ実行 ──────────────────▶ stdout/stderr/exit_code
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bunx_command.zig | `src/cli/bunx_command.zig` | ソース | CLIエントリーポイント、実行処理 |
| run_command.zig | `src/cli/run_command.zig` | ソース | バイナリ実行（Run.runBinary） |
| add_command.zig | `src/cli/add_command.zig` | ソース | パッケージインストール |
| PackageManager.zig | `src/install/PackageManager.zig` | ソース | UpdateRequest.parse |
