# 機能設計書 7-プラグインシステム

## 概要

本ドキュメントは、Bunランタイムにおけるカスタムローダーやリゾルバを拡張可能にするプラグインシステムの設計仕様を定義する。

### 本機能の処理概要

本機能は、Bun.plugin() APIを通じてカスタムローダーとリゾルバを登録し、モジュール解決や読み込み処理を拡張する機能を提供する。esbuildと互換性のあるプラグインAPIにより、既存のエコシステムを活用できる。

**業務上の目的・背景**：標準でサポートされていないファイル形式の読み込みや、カスタムなモジュール解決ロジックが必要な場合がある。プラグインシステムにより、これらの拡張を柔軟に実現できる。

**機能の利用シーン**：カスタムファイル形式（.yaml, .graphql等）の読み込み、仮想モジュールの作成、import文のリライト、コンパイル時変換など。

**主要な処理内容**：
1. プラグイン登録（Bun.plugin()）
2. onResolveコールバックによるモジュール解決のカスタマイズ
3. onLoadコールバックによるファイル読み込みのカスタマイズ
4. 名前空間によるプラグイン適用範囲の制御
5. フィルターによる対象ファイルの絞り込み

**関連システム・外部連携**：モジュールリゾルバ、トランスパイラ、バンドラー

**権限による制御**：特になし

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | run | 補助機能 | Bun.plugin()によるカスタムローダーの適用 |

## 機能種別

拡張機能 / フック処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | プラグイン名 | 空でないこと |
| setup | function | Yes | プラグイン設定関数 | 関数であること |

### 入力データソース

- JavaScriptコード（Bun.plugin()呼び出し）
- プリロードスクリプト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| resolved_path | string | onResolveで返す解決パス |
| contents | string | onLoadで返すファイル内容 |
| loader | string | 使用するローダー種別 |

### 出力先

- モジュールローダー
- トランスパイラ

## 処理フロー

### 処理シーケンス

```
1. プラグイン登録
   └─ Bun.plugin()でプラグインを登録
2. setup関数実行
   └─ buildオブジェクトを渡してsetup関数を呼び出し
3. フック登録
   └─ onResolve/onLoadコールバックを内部に登録
4. モジュール解決時
   └─ フィルターにマッチするとonResolveコールバック実行
5. ファイル読み込み時
   └─ フィルターにマッチするとonLoadコールバック実行
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[Bun.plugin呼び出し]
    B --> C[setup関数実行]
    C --> D[onResolve/onLoad登録]
    D --> E[待機]
    E --> F{import/require発生}
    F -->|Yes| G{フィルターマッチ?}
    G -->|Yes| H[onResolveコールバック]
    G -->|No| I[通常のモジュール解決]
    H --> J{パス返却?}
    J -->|Yes| K{onLoadマッチ?}
    J -->|No| I
    K -->|Yes| L[onLoadコールバック]
    K -->|No| M[通常のファイル読み込み]
    L --> N[コンテンツ返却]
    I --> O[通常処理]
    M --> O
    N --> O
    O --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | フィルター形式 | フィルターは正規表現または文字列グロブ | onResolve/onLoad登録時 |
| BR-02 | 名前空間 | 名前空間でプラグイン適用範囲を制御（file, node, bun等） | モジュール解決時 |
| BR-03 | 実行順序 | プラグインは登録順に実行される | 複数プラグイン時 |
| BR-04 | プリロード | preloadで指定されたスクリプトでプラグインを早期登録可能 | アプリ起動時 |

### 計算ロジック

該当なし

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| PLUGIN_ERROR | プラグインエラー | プラグインがエラーを投げた | プラグインを修正 |
| INVALID_FILTER | フィルターエラー | 不正な正規表現 | フィルターを修正 |

### リトライ仕様

該当なし

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

該当なし

## パフォーマンス要件

- プラグインコールバック: 10ms以内推奨
- フィルターマッチング: 1ms以内

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

- プラグインは任意のコードを実行可能なため、信頼できるプラグインのみ使用
- プラグインからのファイルシステムアクセスは制限なし

## 備考

esbuildプラグインとの互換性を意識した設計だが、一部のAPIは未サポートの場合がある。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | transpiler.zig | `src/transpiler.zig` | PluginRunner構造体でプラグイン実行の仕組みを理解 |

**読解のコツ**: PluginRunner構造体がglobal_objectとallocatorを保持し、プラグインコールバックの実行環境を管理する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | transpiler.zig | `src/transpiler.zig` | extractNamespace()で名前空間の抽出処理を理解 |

**主要処理フロー**:
1. **62-71行目**: extractNamespace()でspecifierからnamespaceを抽出
2. **73-83行目**: couldBePlugin()でプラグイン適用可能かを判定

#### Step 3: onResolve処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | transpiler.zig | `src/transpiler.zig` | onResolve()メソッドでモジュール解決フックを理解 |

**主要処理フロー**:
- **85-185行目**: onResolve()でプラグインのonResolveコールバックを実行
- global.runOnResolvePlugins()でJavaScript側のプラグインを呼び出し
- pathとnamespaceを返却してモジュール解決をカスタマイズ

#### Step 4: JavaScript API側を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | JSGlobalObject.zig | `src/bun.js/bindings/JSGlobalObject.zig` | runOnResolvePluginsの呼び出し元を確認 |

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

```
Bun.plugin() JavaScript API
    │
    ├─ プラグイン登録
    │      └─ setup関数実行
    │             ├─ build.onResolve() → 内部登録
    │             └─ build.onLoad() → 内部登録
    │
    └─ モジュール読み込み時
           │
           ├─ PluginRunner.onResolve()
           │      └─ global.runOnResolvePlugins()
           │             └─ JavaScriptコールバック実行
           │
           └─ PluginRunner.onLoad()
                  └─ JavaScriptコールバック実行
```

### データフロー図

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

import "virtual:x" ───▶ extractNamespace() ───▶ namespace
                              │
                              ▼
                    couldBePlugin() ───▶ true
                              │
                              ▼
                    onResolve() ───▶ 解決パス
                              │
                              ▼
                    onLoad() ───▶ コンテンツ + ローダー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| transpiler.zig | `src/transpiler.zig` | ソース | PluginRunner実装 |
| JSGlobalObject.zig | `src/bun.js/bindings/JSGlobalObject.zig` | ソース | JavaScript側API定義 |
| BunObject.zig | `src/bun.js/api/BunObject.zig` | ソース | Bun.plugin API |
| ModuleLoader.zig | `src/bun.js/ModuleLoader.zig` | ソース | モジュールローダー統合 |
