# 機能設計書 74-@babel/helper-plugin-utils

## 概要

本ドキュメントは、@babel/helper-plugin-utilsの機能設計について記載する。このパッケージは、Babelプラグイン開発用のユーティリティ関数を提供するヘルパーモジュールである。

### 本機能の処理概要

**業務上の目的・背景**：Babelプラグインの開発において、異なるBabelバージョン間の互換性を維持することは重要な課題である。本パッケージは、プラグイン作成者がBabelのAPIの変更を意識せずにプラグインを開発できるよう、declare関数を提供する。これにより、Babel 7の初期ベータ版から最新版まで、さらにはBabel 8まで一貫した方法でプラグインを定義できる。

**機能の利用シーン**：Babelプラグインやプリセットを開発する際に使用される。ほぼすべての公式Babelプラグインがこのパッケージのdeclare関数を使用してプラグインを定義している。特に、api.assertVersionメソッドを使用してプラグインが要求するBabelバージョンを宣言する際に、古いBabelバージョンでもこのメソッドが利用可能になるようポリフィルを提供する。

**主要な処理内容**：
1. declare関数によるプラグインファクトリのラップ
2. APIポリフィルの提供（assertVersion等）
3. バージョン不一致時の詳細なエラーメッセージ生成
4. Babel 7ベータ版との互換性のためのAPIオブジェクトコピー

**関連システム・外部連携**：@babel/coreのPluginAPI、PluginObject、PresetAPI、PresetObject型と連携する。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | プラグイン開発時に使用 |

## 機能種別

ユーティリティ関数 / プラグイン開発支援

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| builder | function | Yes | プラグインファクトリ関数（api, options, dirname）=> PluginObject | 関数であること |
| api | PluginAPI | Yes | Babel API オブジェクト | @babel/coreから提供 |
| options | object | No | プラグインオプション | - |
| dirname | string | No | 設定ファイルのディレクトリパス | - |

### 入力データソース

@babel/coreのプラグインシステムから呼び出される

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| wrappedBuilder | function | ポリフィル適用済みのプラグインファクトリ |
| PluginObject | object | プラグイン定義オブジェクト |

### 出力先

@babel/coreのプラグインシステムに対して返却

## 処理フロー

### 処理シーケンス

```
1. declare関数呼び出し
   └─ builderファクトリ関数を受け取る
2. ラップされたファクトリ関数を返却
3. プラグイン初期化時（@babel/coreから呼び出し）
   ├─ APIポリフィルの適用チェック
   │   └─ 存在しないAPIメソッドをポリフィルで補完
   ├─ Babel 7ベータ版対応のAPIオブジェクトコピー
   └─ builder関数の実行
4. PluginObjectの返却
```

### フローチャート

```mermaid
flowchart TD
    A[declare関数呼び出し] --> B[builderを受け取り]
    B --> C[ラップ関数を返却]
    C --> D[プラグイン初期化時]
    D --> E{APIポリフィル必要?}
    E -->|Yes| F[APIオブジェクトをクローン]
    F --> G[ポリフィルを適用]
    G --> H[builder実行]
    E -->|No| H
    H --> I[PluginObject返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-74-01 | APIポリフィル | 存在しないAPIメソッドはポリフィルで提供 | api[name]がfalsy時 |
| BR-74-02 | バージョン範囲形式 | assertVersionは数値または文字列のsemver範囲 | assertVersion呼び出し時 |
| BR-74-03 | 整数バージョン | 数値の場合は整数のみ許容 | assertVersionに数値指定時 |
| BR-74-04 | Babel 7プロトタイプ対応 | Babel 7ベータ版のプロトタイプチェーン問題を修正 | version.startsWith("7.")時 |

### 計算ロジック

**バージョン範囲変換**：
```
整数N → "^N.0.0-0"
例: 7 → "^7.0.0-0"
```

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

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

データベース操作なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| BABEL_VERSION_UNSUPPORTED | バージョンエラー | assertVersionの条件を満たさない | @babel/coreを更新する |
| - | 型エラー | rangeが文字列/整数以外 | semver形式の文字列か整数を指定 |
| - | 型エラー | 整数が小数 | 整数を指定 |

### リトライ仕様

リトライ対象外（設定エラーのため）

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

トランザクション処理なし

## パフォーマンス要件

軽量なラッパー関数のため、オーバーヘッドは極めて小さい

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

特になし

## 備考

- declarePresetはプリセット用のエイリアス
- Babel 7.0.0-beta.41以前のバージョンとの互換性を維持
- スタックトレース制限を一時的に25に引き上げてデバッグを支援

---

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

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

### 推奨読解順序

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

まず、使用される型定義とポリフィル構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/babel-helper-plugin-utils/src/index.ts` | 型定義のインポート（1-7行目） |
| 1-2 | index.ts | `packages/babel-helper-plugin-utils/src/index.ts` | APIPolyfillFactory型とapiPolyfills定義（9-24行目） |

**読解のコツ**: APIPolyfillFactory型は、PluginAPIの特定のメソッドを遅延生成するファクトリ関数の型を定義している。apiPolyfillsオブジェクトは、ポリフィルが必要なAPIメソッドのマップ。

#### Step 2: declare関数を理解する

メインのdeclare関数の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/babel-helper-plugin-utils/src/index.ts` | declare関数の定義（26-52行目） |

**主要処理フロー**:
1. **26-36行目**: declare関数のシグネチャ定義（ジェネリクスでState、Optionを受け取る）
2. **37行目**: ラップされたファクトリ関数を返却
3. **40-47行目**: apiPolyfillsをループしてポリフィル適用をチェック
4. **43行目**: api[name]が存在しない場合のみポリフィルを適用
5. **45-46行目**: clonedApiを作成してポリフィルを設定
6. **50行目**: builder関数を実行してPluginObjectを返却

#### Step 3: copyApiObject関数を理解する

Babel 7ベータ版との互換性のためのAPIオブジェクトコピーロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/babel-helper-plugin-utils/src/index.ts` | copyApiObject関数（58-82行目） |

**主要処理フロー**:
- **64-65行目**: Babel 7系の場合のみプロトタイプを確認
- **66-75行目**: プロトタイプにversion、transform、template、typesがある場合は正規化
- **78-81行目**: スプレッド演算子でprotoとapiをマージ

#### Step 4: throwVersionError関数を理解する

バージョン不一致時のエラー処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `packages/babel-helper-plugin-utils/src/index.ts` | throwVersionError関数（84-129行目） |

**主要処理フロー**:
- **85-89行目**: 整数の場合はsemver範囲に変換
- **95-101行目**: スタックトレース制限を一時的に25に引き上げ
- **103-118行目**: Babel 7とBabel 8でエラーメッセージを分岐
- **124-128行目**: BABEL_VERSION_UNSUPPORTEDコードを付加してスロー

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

```
@babel/helper-plugin-utils/src/index.ts
    │
    ├─ declare()
    │      ├─ apiPolyfills.assertVersion() - ポリフィル関数
    │      │      └─ throwVersionError() - エラーハンドリング
    │      └─ copyApiObject() - Babel 7互換性対応
    │
    └─ declarePreset() - declare()のエイリアス
```

### データフロー図

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

builder関数 ───▶ declare() ───▶ ラップ関数返却
                     │
                     ▼
             @babel/core呼び出し時
                     │
      ┌──────────────┼──────────────┐
      ▼              ▼              ▼
 ポリフィル確認  APIコピー    builder実行
      │              │              │
      └──────────────┼──────────────┘
                     ▼
              PluginObject返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/babel-helper-plugin-utils/src/index.ts` | ソース | モジュールのメイン実装 |
| package.json | `packages/babel-helper-plugin-utils/package.json` | 設定 | パッケージメタデータと依存関係 |
