# アーキテクチャ設計書

## 概要

本ドキュメントは、Prettierプロジェクトのアーキテクチャ設計を記載したものです。Prettierは、JavaScript、TypeScript、CSS、HTML、Markdown、YAML、GraphQLなど多数の言語に対応したコードフォーマッターです。プラグインベースのアーキテクチャを採用し、各言語の解析・整形処理を独立したモジュールとして構成しています。

## システム全体構成

### アーキテクチャ概要図

[アーキテクチャ構成図.md](./アーキテクチャ構成図.md) を参照してください。

### システム境界と外部連携

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| ファイルシステム | Node.js fs API | ソースコードの読み書き、設定ファイルの読み込み |
| EditorConfig | editorconfig-without-wasm | エディタ設定の読み込み・適用 |
| npm/yarn パッケージ | ESM/CommonJS import | 外部プラグインの動的読み込み |
| stdin/stdout | Node.js process | CLI経由でのテキスト入出力 |

## レイヤー構成

### アーキテクチャスタイル

**パイプライン・アーキテクチャ + プラグインアーキテクチャ**

Prettierは、コードフォーマットを以下のパイプラインで処理します：
1. 入力テキスト -> Parser -> AST
2. AST -> Printer -> IR (Intermediate Representation / Document)
3. IR -> Document Printer -> 出力テキスト

各言語の処理はプラグインとして独立しており、パーサーとプリンターを提供します。

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| CLI Layer | コマンドライン引数の解析、ファイル操作、ユーザーインターフェース | `src/cli/index.js`, `src/cli/format.js`, `src/cli/context.js` |
| API Layer | 公開API、プラグインのロード、フォーマット機能の提供 | `src/index.js`, `src/standalone.js` |
| Core Layer | フォーマット処理のオーケストレーション、オプション正規化 | `src/main/core.js`, `src/main/ast-to-doc.js`, `src/main/parser-and-printer.js` |
| Document Layer | 中間表現(IR)の定義、ドキュメントからテキストへの変換 | `src/document/builders/`, `src/document/printer/printer.js` |
| Plugin Layer | 各言語のパーサー、プリンター、オプション定義 | `src/language-*/`, `src/plugins/` |
| Config Layer | 設定ファイルの検索・読み込み・マージ | `src/config/resolve-config.js`, `src/config/prettier-config/` |
| Utilities Layer | 共通ユーティリティ関数 | `src/utilities/`, `src/common/` |

### レイヤー間の依存関係ルール

- **CLI Layer** -> API Layer, Utilities Layer
- **API Layer** -> Core Layer, Config Layer, Plugin Layer
- **Core Layer** -> Document Layer, Plugin Layer, Utilities Layer
- **Document Layer** -> Utilities Layer
- **Plugin Layer** -> Document Layer, Utilities Layer
- **Config Layer** -> Utilities Layer

依存の方向は上位レイヤーから下位レイヤーへの一方向です。下位レイヤーから上位レイヤーへの直接参照は禁止されています。

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| JavaScript/TypeScript | JS/TS/JSX/TSX/Flowのパース・整形 | `src/language-js/` |
| CSS | CSS/SCSS/Less/PostCSSのパース・整形 | `src/language-css/` |
| HTML | HTML/Vue/Angular/LWCのパース・整形 | `src/language-html/` |
| Markdown | Markdown/MDXのパース・整形 | `src/language-markdown/` |
| YAML | YAMLのパース・整形 | `src/language-yaml/` |
| GraphQL | GraphQLのパース・整形 | `src/language-graphql/` |
| JSON | JSON/JSON5のパース・整形 | `src/language-json/` |
| Handlebars | Handlebars/Glimmerテンプレートのパース・整形 | `src/language-handlebars/` |

### パッケージ構造

```
src/
├── cli/                    # CLIレイヤー
│   ├── index.js           # CLIエントリーポイント
│   ├── format.js          # ファイルフォーマット処理
│   ├── context.js         # CLI実行コンテキスト
│   └── options/           # CLIオプション解析
├── common/                 # 共通コンポーネント
│   ├── ast-path.js        # AST走査用パスオブジェクト
│   ├── errors.js          # カスタムエラークラス
│   └── end-of-line.js     # 改行コード処理
├── config/                 # 設定レイヤー
│   ├── resolve-config.js  # 設定解決
│   ├── prettier-config/   # Prettier設定ファイル処理
│   └── editorconfig/      # EditorConfig処理
├── document/               # ドキュメント(IR)レイヤー
│   ├── builders/          # IRビルダー関数
│   ├── printer/           # IR -> テキスト変換
│   └── utilities/         # ドキュメントユーティリティ
├── main/                   # コアレイヤー
│   ├── core.js            # フォーマットコア処理
│   ├── ast-to-doc.js      # AST -> IR変換
│   ├── parser-and-printer.js # パーサー・プリンター解決
│   ├── plugins/           # プラグイン管理
│   └── comments/          # コメント処理
├── plugins/                # ビルトインプラグインエントリー
├── language-js/            # JavaScript言語プラグイン
│   ├── parse/             # パーサー実装
│   ├── print/             # プリンター実装
│   ├── comments/          # コメント処理
│   └── embed/             # 埋め込み言語処理
├── language-css/           # CSS言語プラグイン
├── language-html/          # HTML言語プラグイン
├── language-markdown/      # Markdown言語プラグイン
├── language-yaml/          # YAML言語プラグイン
├── language-graphql/       # GraphQL言語プラグイン
├── language-json/          # JSON言語プラグイン
├── language-handlebars/    # Handlebars言語プラグイン
├── utilities/              # 共通ユーティリティ
├── universal/              # ブラウザ/Node.js互換レイヤー
├── index.js               # Node.js APIエントリーポイント
├── index.cjs              # CommonJSエントリーポイント
└── standalone.js          # スタンドアロン(ブラウザ)エントリーポイント
```

### コンポーネント依存関係

**主要コンポーネントの依存関係：**

1. **index.js (API)** -> core.js, plugins/index.js, resolve-config.js
2. **core.js** -> ast-to-doc.js, parse.js, document/printer
3. **ast-to-doc.js** -> AstPath, comments/attach.js, multiparser.js
4. **parser-and-printer.js** -> プラグインからパーサー/プリンターを解決
5. **各language-*モジュール** -> document/builders, utilities

## ミドルウェア構成

### データベース

本プロジェクトはデータベースを使用しません。コードフォーマッターとして、入力テキストを変換し出力するのみです。

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| file-entry-cache | 11.1.2 | フォーマット結果のキャッシュ（--cacheオプション使用時） | 永続 |
| find-cache-directory | 6.0.0 | キャッシュディレクトリの検出 | N/A |

CLIの`--cache`オプション使用時に、フォーマット済みファイルのハッシュをキャッシュし、変更のないファイルの再フォーマットをスキップします。

### メッセージキュー

本プロジェクトはメッセージキューを使用しません。

### 検索エンジン

本プロジェクトは検索エンジンを使用しません。

### その他ミドルウェア

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| fast-glob | 3.3.3 | ファイルパターンマッチング |
| micromatch | 4.0.8 | Glob パターンマッチング |
| ignore | 7.0.5 | .prettierignore処理 |
| picocolors | 1.1.1 | ターミナル出力の色付け |

## データフロー

### リクエスト処理の流れ

**API経由のフォーマット処理：**

1. `format(text, options)` または `formatWithCursor(text, options)` が呼び出される
2. `normalizeFormatOptions(options)` でオプションを正規化
3. `loadBuiltinPlugins()` と `loadPlugins(plugins)` でプラグインをロード
4. `resolveParser(options)` で適切なパーサーを選択
5. `parseText(text, options)` でテキストをASTにパース
6. `printAstToDoc(ast, options)` でASTを中間表現(IR/Document)に変換
7. `printDocToString(doc, options)` でDocumentを最終テキストに変換
8. フォーマット済みテキストを返却

### 非同期処理の流れ

**CLI経由のバッチ処理：**

1. `run()` でCLI起動、引数解析
2. `Context` オブジェクトで実行コンテキストを管理
3. `formatFiles(context)` でファイル一覧を取得
4. `fast-glob` で対象ファイルをパターンマッチング
5. 各ファイルを並列でフォーマット
6. 結果をstdout/ファイルに出力

### データ永続化の流れ

**設定ファイルの読み込み：**

1. `resolveConfigFile(filePath)` で設定ファイルパスを検索
2. プロジェクトルートから親ディレクトリを遡って検索
3. `.prettierrc`, `.prettierrc.json`, `.prettierrc.js` 等を優先度順に検索
4. `loadPrettierConfig(file, options)` で設定を読み込み
5. オプションで `editorconfig` も読み込みマージ
6. `overrides` フィールドでファイルパターン別設定をマージ

## 横断的関心事

### 認証・認可

本プロジェクトは認証・認可機能を持ちません。ローカルで動作するCLIツール/ライブラリです。

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| CLIログ | `src/cli/logger.js` カスタムロガー | stderr |
| デバッグログ | `--log-level debug` オプション | stderr |

ログレベル：`silent`, `error`, `warn`, `log`, `debug`

### エラーハンドリング

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| ConfigError | 設定ファイルのパースエラー | エラーメッセージを出力し終了 |
| UndefinedParserError | パーサー未指定/不明 | エラーメッセージを出力し終了 |
| SyntaxError | パース失敗 | エラー位置を示すcode frameを表示 |
| InvalidDocError | 不正なDocument IR | 内部エラーとして報告 |

エラーハンドリングは `src/common/errors.js` でカスタムエラークラスを定義し、CLI層で統一的にキャッチ・表示します。

### トランザクション管理

本プロジェクトはデータベースを使用しないため、トランザクション管理は不要です。

ファイル書き込み時は、`--write` オプション使用時に直接ファイルを上書きします。アトミックな書き込みは保証されません。

## 設計原則・コーディング規約

### 適用している設計原則

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| Single Responsibility | 各language-*モジュール | 言語ごとにパーサー/プリンターを分離 |
| Open/Closed | プラグインシステム | 新言語サポートはプラグイン追加で対応 |
| Dependency Inversion | parser-and-printer.js | プラグインからパーサー/プリンターを動的解決 |
| Separation of Concerns | Document IR | パース、整形、出力を分離 |

### コーディング規約

- **ESM (ES Modules)** を使用（`"type": "module"`）
- **ESLint** によるコード品質チェック
- **Prettier** 自身によるフォーマット
- **CSpell** によるスペルチェック
- **TypeScript** 型定義（`.d.ts`）による型安全性

主要な規約：
- ファイル名はケバブケース（例: `resolve-config.js`）
- クラスよりも関数を優先
- 非同期処理は `async/await` を使用
- Node.js v20以上をサポート

## 備考

### プラグインインターフェース

外部プラグインは以下のインターフェースを実装する必要があります：

```javascript
{
  languages: [...],      // 対応言語定義
  parsers: { ... },      // パーサー実装
  printers: { ... },     // プリンター実装
  options: { ... },      // カスタムオプション定義
}
```

### Document IR (Intermediate Representation)

Prettierの中間表現は以下のビルダー関数で構築されます：

- `line`, `softline`, `hardline` - 改行
- `group`, `conditionalGroup` - グループ化
- `indent`, `dedent` - インデント
- `fill`, `join` - 並列配置
- `ifBreak` - 条件付き出力

この中間表現により、行幅に応じた最適なレイアウト決定が可能になります。

### ブラウザ対応

`standalone.js` エントリーポイントにより、ブラウザ環境でも動作可能です。この場合、ファイルシステムアクセスは利用できず、プラグインは明示的にバンドルする必要があります。
