# 機能設計書 52-create-jest

## 概要

本ドキュメントは、Jestテスティングフレームワークにおける `create-jest` パッケージの機能設計について記述する。このパッケージは、新規Jestプロジェクトの初期設定を対話的に行うためのCLIツールである。

### 本機能の処理概要

`create-jest` は、Jestの設定ファイル生成とpackage.jsonの修正を対話的に行い、開発者が迅速にJestテスト環境を構築できるようにする初期化ツールである。

**業務上の目的・背景**：Jestには多数の設定オプションがあり、初期設定は開発者にとって負担となる場合がある。このツールにより、プロジェクトに適したJest設定ファイルを自動生成し、テスト環境のセットアップ時間を大幅に短縮できる。また、ベストプラクティスに沿った設定を提供することで、設定ミスを防止する。

**機能の利用シーン**：
- 新規プロジェクトでJestを導入する際
- 既存プロジェクトにJestテスト環境を追加する際
- Jest設定ファイルを再生成・更新する際
- CI/CD環境でのプロジェクトテンプレート生成時

**主要な処理内容**：
1. 対話式質問による設定オプションの収集（TypeScript使用、テスト環境、カバレッジ等）
2. 既存のJest設定の検出と上書き確認
3. Jest設定ファイル（jest.config.js/ts/mjs）の生成
4. package.jsonのtestスクリプト追加とjestプロパティ削除
5. 設定ファイル形式（CommonJS/ESM/TypeScript）の自動判定

**関連システム・外部連携**：
- `jest-config`：デフォルト設定値と設定の説明文の取得
- `jest-util`：ユーティリティ関数（clearLine、tryRealpath）
- `prompts`：対話式プロンプトの実装
- `graceful-fs`：ファイルシステム操作

**権限による制御**：本ツールはファイルシステムへの書き込み権限が必要。package.jsonとjest.config.* ファイルへの書き込みを行う。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | CLIツールのため画面なし（ターミナル対話） |

## 機能種別

初期化処理 / ファイル生成 / 設定管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| rootDir | string | No | プロジェクトルートディレクトリ | 存在するディレクトリパス |

### 対話式質問項目

| 質問名 | 型 | デフォルト | 説明 |
|--------|-----|---------|------|
| scripts | boolean | true | package.jsonにtestスクリプトを追加するか |
| useTypescript | boolean | false | TypeScriptで設定ファイルを作成するか |
| environment | 'node' \| 'jsdom' | 'node' | テスト環境の選択 |
| coverage | boolean | false | カバレッジレポートを有効にするか |
| coverageProvider | 'v8' \| 'babel' | 'v8' | カバレッジプロバイダーの選択 |
| clearMocks | boolean | false | テスト前にモックを自動クリアするか |

### 入力データソース

- コマンドライン引数（rootDir）
- 対話式プロンプトへのユーザー入力
- 既存のpackage.jsonファイル

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| jest.config.js/ts/mjs | ファイル | Jest設定ファイル |
| package.json | ファイル | 修正されたpackage.json |

### 出力先

- `{rootDir}/jest.config.{js|ts|mjs}` - Jest設定ファイル
- `{rootDir}/package.json` - 修正されたpackage.json

## 処理フロー

### 処理シーケンス

```
1. rootDirの解決とリアルパス変換
   └─ tryRealpath()でシンボリックリンク解決

2. package.jsonの存在確認と読み込み
   └─ 存在しない場合はNotFoundPackageJsonErrorをスロー
   └─ JSONパースエラーの場合はMalformedPackageJsonErrorをスロー

3. 既存Jest設定の検出
   └─ package.jsonのjestプロパティ確認
   └─ jest.config.{js,ts,mjs,cjs,json}ファイルの存在確認

4. 既存設定がある場合は上書き確認
   └─ ユーザーが拒否した場合は処理中断

5. 対話式質問の実行
   └─ testスクリプト追加の質問（必要な場合のみ）
   └─ TypeScript使用の質問
   └─ テスト環境の質問
   └─ カバレッジの質問
   └─ カバレッジプロバイダーの質問
   └─ clearMocksの質問

6. 設定ファイル形式の決定
   └─ TypeScript選択時: .ts
   └─ package.jsonのtype="module"時: .mjs
   └─ その他: .js

7. package.jsonの修正と書き込み
   └─ testスクリプトの追加
   └─ jestプロパティの削除

8. Jest設定ファイルの生成と書き込み
   └─ generateConfigFile()で設定内容生成
   └─ ファイルに書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始: runCreate] --> B[rootDirの解決]
    B --> C{package.json存在?}
    C -->|No| D[NotFoundPackageJsonError]
    C -->|Yes| E[package.jsonパース]
    E --> F{パース成功?}
    F -->|No| G[MalformedPackageJsonError]
    F -->|Yes| H{既存Jest設定あり?}
    H -->|Yes| I[上書き確認プロンプト]
    I -->|拒否| J[処理中断]
    I -->|承認| K[質問リスト準備]
    H -->|No| K
    K --> L{testスクリプト必要?}
    L -->|Yes| M[testScript質問追加]
    L -->|No| N[対話式質問実行]
    M --> N
    N --> O{プロンプト中断?}
    O -->|Yes| J
    O -->|No| P[設定ファイル形式決定]
    P --> Q[package.json修正・書き込み]
    Q --> R[設定ファイル生成]
    R --> S[設定ファイル書き込み]
    S --> T[完了メッセージ表示]
    T --> U[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-01 | package.json必須 | rootDirにpackage.jsonが存在する必要がある | 常時 |
| BR-52-02 | 上書き確認 | 既存Jest設定がある場合は上書き確認を行う | jest設定が存在する場合 |
| BR-52-03 | testスクリプト条件 | scripts.test !== 'jest' の場合のみ質問 | package.jsonにscripts.testが設定済みの場合 |
| BR-52-04 | ファイル形式決定 | TypeScript > ESM(mjs) > CommonJS(js) の優先順 | 設定ファイル生成時 |
| BR-52-05 | jestプロパティ削除 | package.jsonのjestプロパティは削除される | 設定ファイル生成時 |

### 計算ロジック

設定ファイル形式の決定ロジック：
```typescript
const jestConfigFileExt = results.useTypescript
  ? JEST_CONFIG_EXT_TS     // '.ts'
  : projectPackageJson.type === 'module'
    ? JEST_CONFIG_EXT_MJS  // '.mjs'
    : JEST_CONFIG_EXT_JS;  // '.js'
```

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

本パッケージはデータベース操作を行わない。

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

該当なし

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NotFoundPackageJsonError | ファイルエラー | package.jsonが見つからない | rootDirを確認、npm initを先に実行 |
| MalformedPackageJsonError | パースエラー | package.jsonが不正なJSON | package.jsonの内容を修正 |
| - | 中断 | ユーザーがプロンプトをキャンセル | 再実行 |

### リトライ仕様

- ユーザー中断時は再実行で対応
- ファイル書き込みエラー時はエラーメッセージを表示して終了

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

- ファイル書き込みは個別に行われる（トランザクション制御なし）
- package.json修正後、設定ファイル書き込み前にエラーが発生した場合、package.jsonのみ変更された状態となる

## パフォーマンス要件

- 対話式ツールのため、ユーザー入力待ち時間が主なボトルネック
- ファイル読み書きは即座に完了する（ミリ秒オーダー）

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

- ファイルシステムへの書き込み権限が必要
- 生成される設定ファイルには機密情報は含まれない
- ユーザー入力のバリデーションはpromptsライブラリが担当

## 備考

- `npm create jest` または `npx create-jest` で実行可能
- Node.js ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0 が必要
- バージョン 30.2.0 時点の情報

---

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

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

### 推奨読解順序

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

まず、対話式質問の結果とpackage.jsonの型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `packages/create-jest/src/types.ts` | PromptsResultsとProjectPackageJsonの型定義 |

**主要処理フロー**:
- **10-14行目**: ProjectPackageJson型 - jest, scripts, typeプロパティ
- **16-23行目**: PromptsResults型 - 対話式質問の回答を格納

**読解のコツ**: この型定義が全体の入出力データ構造を規定している。

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

パッケージのエントリポイントとメイン処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/create-jest/src/index.ts` | runCreateとrunCLIのエクスポート |
| 2-2 | runCreate.ts | `packages/create-jest/src/runCreate.ts` | メイン処理ロジック |

**主要処理フロー**:
- **32-48行目**: runCLI関数 - CLIエントリポイント、エラーハンドリング
- **50-51行目**: rootDirの解決（tryRealpathでシンボリックリンク解決）
- **53-57行目**: package.json存在確認
- **63-69行目**: package.jsonのパースとエラーハンドリング
- **75-77行目**: 既存jest.config.*の検出（拡張子順序でチェック）
- **79-93行目**: 既存設定の上書き確認プロンプト
- **96-101行目**: testスクリプト質問の条件付き追加
- **113-117行目**: 対話式プロンプト実行（onCancelハンドラ付き）
- **126-136行目**: 設定ファイル拡張子の決定ロジック
- **140-150行目**: package.json修正と書き込み
- **152-158行目**: 設定ファイル生成と書き込み

**読解のコツ**: JEST_CONFIG_EXT_ORDER定数による拡張子チェック順序に注目。

#### Step 3: 質問定義を理解する

対話式質問の内容を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | questions.ts | `packages/create-jest/src/questions.ts` | promptsライブラリ用の質問定義 |

**主要処理フロー**:
- **10-16行目**: useTypescript質問 - TypeScript設定ファイル使用
- **17-26行目**: environment質問 - node/jsdom選択
- **27-32行目**: coverage質問 - カバレッジ有効化
- **33-42行目**: coverageProvider質問 - v8/babel選択
- **43-49行目**: clearMocks質問 - モック自動クリア
- **54-60行目**: testScriptQuestion - testスクリプト追加

**読解のコツ**: 各質問のname属性がPromptsResults型のプロパティに対応する。

#### Step 4: 設定ファイル生成を理解する

Jest設定ファイルの生成ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | generateConfigFile.ts | `packages/create-jest/src/generateConfigFile.ts` | 設定ファイル文字列の生成 |

**主要処理フロー**:
- **12-30行目**: stringifyOption関数 - 各設定項目を文字列化
- **32-35行目**: generateConfigFile関数の引数（results, generateEsm）
- **39-64行目**: 回答に基づくオーバーライド設定の構築
- **70-82行目**: 全設定項目のプロパティ文字列生成
- **84-88行目**: 設定ファイルヘッダーコメント
- **90-98行目**: JS/TS宣言とエクスポート形式の切り替え
- **100-107行目**: 最終的なファイル内容の組み立て

**読解のコツ**: jest-configのdefaultsとdescriptionsを使用して全設定項目（コメントアウト含む）を出力している。

#### Step 5: package.json修正を理解する

package.jsonの修正ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | modifyPackageJson.ts | `packages/create-jest/src/modifyPackageJson.ts` | package.json修正処理 |

**主要処理フロー**:
- **17-23行目**: scriptsへのtest追加処理
- **25行目**: jestプロパティの削除
- **27行目**: JSON.stringifyでインデント2スペースでフォーマット

#### Step 6: エラークラスを理解する

カスタムエラークラスを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | errors.ts | `packages/create-jest/src/errors.ts` | カスタムエラークラス |

**主要処理フロー**:
- **8-15行目**: NotFoundPackageJsonError - package.json未発見エラー
- **17-24行目**: MalformedPackageJsonError - JSONパースエラー

**読解のコツ**: Error.captureStackTraceで空のスタックトレースを設定し、ユーザーフレンドリーなエラー表示を実現。

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

```
bin/create-jest.js
    │
    └─ runCreate.ts
           │
           ├─ errors.ts
           │      ├─ NotFoundPackageJsonError
           │      └─ MalformedPackageJsonError
           │
           ├─ questions.ts
           │      └─ defaultQuestions, testScriptQuestion
           │
           ├─ modifyPackageJson.ts
           │      └─ modifyPackageJson()
           │
           ├─ generateConfigFile.ts
           │      └─ generateConfigFile()
           │
           └─ 外部依存
                  ├─ prompts (対話式プロンプト)
                  ├─ graceful-fs (ファイル操作)
                  ├─ jest-config (defaults, descriptions, constants)
                  └─ jest-util (clearLine, tryRealpath)
```

### データフロー図

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

CLI引数 ────────────────▶ runCreate() ────────────────────────▶ 完了メッセージ
(rootDir)                     │
                              │
package.json ───────────▶ JSONパース ──▶ 設定検出 ────────────▶ 修正package.json
                              │
                              ▼
ユーザー入力 ──────────▶ prompts質問 ──▶ PromptsResults ──────▶ jest.config.*
                              │
                              ▼
jest-config ────────────▶ defaults/descriptions ──────────────▶ 設定コメント
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/create-jest/src/index.ts` | ソース | エントリポイント、エクスポート |
| runCreate.ts | `packages/create-jest/src/runCreate.ts` | ソース | メイン処理ロジック |
| questions.ts | `packages/create-jest/src/questions.ts` | ソース | 対話式質問定義 |
| generateConfigFile.ts | `packages/create-jest/src/generateConfigFile.ts` | ソース | 設定ファイル生成 |
| modifyPackageJson.ts | `packages/create-jest/src/modifyPackageJson.ts` | ソース | package.json修正 |
| errors.ts | `packages/create-jest/src/errors.ts` | ソース | カスタムエラークラス |
| types.ts | `packages/create-jest/src/types.ts` | ソース | 型定義 |
| package.json | `packages/create-jest/package.json` | 設定 | パッケージメタデータ |
| bin/create-jest.js | `packages/create-jest/bin/create-jest.js` | スクリプト | CLI実行スクリプト |
