# 機能設計書 111-FrameworkRouter

## 概要

本ドキュメントは、Bunのサーバーサイドレンダリングフレームワーク「Bake」において、ファイルシステムベースのルーティングを提供するFrameworkRouter機能の設計を記述する。

### 本機能の処理概要

FrameworkRouterは、ファイルシステムからルートを自動検出し、URLパターンマッチングを行うルーティングエンジンである。Next.jsのPages RouterおよびApp Routerのルーティング規約に対応し、動的ルート、キャッチオールルート、ルートグループなどの高度なルーティングパターンをサポートする。

**業務上の目的・背景**：モダンなWebアプリケーション開発では、ファイルシステムベースのルーティングが標準的なパターンとなっている。開発者がルート定義を手動で記述することなく、ファイル構造からルートを自動生成することで、開発効率を向上させ、ルーティングの一貫性を保証する。BunのBakeフレームワークは、Next.js互換のルーティングを提供することで、既存のNext.jsプロジェクトからの移行を容易にする。

**機能の利用シーン**：
- Bakeフレームワークを使用したサーバーサイドレンダリングアプリケーションの開発
- ファイルシステムからのルート自動検出と登録
- 動的パラメータを含むURLのマッチングと解析
- DevServerでのホットモジュールリプレースメント時のルート更新
- プロダクションビルドでのルートテーブルのシリアライズ

**主要な処理内容**：
1. ルートタイプ（Style）の設定に基づいたファイルパスの解析
2. Next.js Pages Router形式（`/pages/[id].tsx`）のパターン解析
3. Next.js App Router形式（`/app/[id]/page.tsx`）のパターン解析
4. 動的ルートパラメータ（`[param]`）の抽出
5. キャッチオールルート（`[...params]`、`[[...params]]`）のサポート
6. ルートグループ（`(group)`）によるURL非影響のディレクトリ構造化
7. 静的ルートと動的ルートの分離管理
8. URLパスとルートのマッチング処理
9. マッチしたパラメータのJavaScriptオブジェクト変換

**関連システム・外部連携**：
- Bakeフレームワーク（DevServer、HMR）との連携
- JavaScriptCoreとのバインディング（JSFrameworkRouter）
- Resolverによるファイルシステムスキャン

**権限による制御**：特になし（開発時・ビルド時に使用される内部機能）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はランタイム内部機能であり、直接的な画面は存在しない |

## 機能種別

ルーティング処理 / パターンマッチング / ファイルシステムスキャン

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| root | []const u8 | Yes | ルーターのルートディレクトリの絶対パス | 絶対パスであること |
| types | []Type | Yes | ルートタイプの配列（スタイル、拡張子等の設定） | - |
| style | Style | Yes | ルーティング規約（nextjs-pages, nextjs-app-ui, nextjs-app-routes） | 有効なスタイル名 |
| extensions | [][]const u8 | Yes | 対象ファイル拡張子 | - |
| allow_layouts | bool | Yes | レイアウトファイルの許可 | - |
| ignore_underscores | bool | No | アンダースコア始まりファイルの無視 | デフォルトfalse |
| ignore_dirs | [][]const u8 | No | 無視するディレクトリ | デフォルト[".git", "node_modules"] |

### 入力データソース

- ファイルシステム上のディレクトリ構造
- Resolverによるファイル情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| routes | []Route | 解析されたルート情報の配列 |
| static_routes | StaticRouteMap | 静的ルートのマップ（URL -> Route Index） |
| dynamic_routes | DynamicRouteMap | 動的ルートのマップ（EncodedPattern -> Route Index） |
| MatchedParams | struct | マッチしたパラメータのキー・バリューペア配列（最大64個） |

### 出力先

- メモリ上のルーティングテーブル
- DevServerへのルート情報提供
- JavaScriptへのマッチ結果返却

## 処理フロー

### 処理シーケンス

```
1. 初期化（initEmpty）
   └─ ルートディレクトリとタイプ配列からFrameworkRouterを作成
   └─ 各タイプのルートルートを作成

2. ファイルスキャン（scan / scanAll）
   └─ Resolverを使用してディレクトリを再帰的にスキャン
   └─ 各ファイルに対してスタイルに応じたパターン解析を実行

3. パターン解析（Style.parse）
   └─ ファイルパスからルートパターンを抽出
   └─ 動的セグメント、キャッチオール、グループを識別

4. ルート登録（insert）
   └─ 解析されたパターンをルートツリーに挿入
   └─ 静的/動的ルートを適切なマップに登録
   └─ 衝突検出を実行

5. マッチング（matchSlow）
   └─ リクエストURLに対してルートを検索
   └─ パラメータを抽出してMatchedParamsに格納
```

### フローチャート

```mermaid
flowchart TD
    A[FrameworkRouter初期化] --> B[ファイルシステムスキャン]
    B --> C{ファイルタイプ判定}
    C -->|ディレクトリ| D{無視対象?}
    D -->|No| E[再帰スキャン]
    D -->|Yes| B
    C -->|ファイル| F{拡張子チェック}
    F -->|対象外| B
    F -->|対象| G[Style.parse実行]
    G --> H{パース成功?}
    H -->|No| I[エラー記録]
    H -->|Yes| J{動的パラメータ有り?}
    J -->|Yes| K[EncodedPattern作成]
    J -->|No| L[StaticPattern作成]
    K --> M[insert実行]
    L --> M
    M --> N{衝突検出?}
    N -->|Yes| O[衝突エラー記録]
    N -->|No| P[ルート登録完了]
    I --> B
    O --> B
    P --> B
    E --> C
    B --> Q[スキャン完了]
    Q --> R[matchSlow実行可能]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | Next.js Pages Router規約 | `index`サフィックスはディレクトリのルートを表す | style=nextjs_pages |
| BR-002 | Next.js Pages Router規約 | `_layout`サフィックスはレイアウトを表す | style=nextjs_pages, allow_layouts=true |
| BR-003 | Next.js App Router規約 | `page.tsx`はページコンポーネント | style=nextjs_app_ui |
| BR-004 | Next.js App Router規約 | `layout.tsx`はレイアウトコンポーネント | style=nextjs_app_ui, allow_layouts=true |
| BR-005 | Next.js App Router規約 | `route.tsx`はAPIルート | style=nextjs_app_routes |
| BR-006 | 動的パラメータ | `[param]`形式は単一セグメントをキャプチャ | 全スタイル |
| BR-007 | キャッチオール | `[...params]`は残り全セグメントをキャプチャ | 全スタイル |
| BR-008 | オプショナルキャッチオール | `[[...params]]`はオプショナルなキャッチオール | 全スタイル |
| BR-009 | ルートグループ | `(group)`はURL構造に影響しない | App Routerスタイルのみ |
| BR-010 | パラメータ最大数 | 1ルートあたり最大64パラメータ | 全スタイル |

### 計算ロジック

パターンマッチングの優先順位：
1. 完全一致の静的ルート（static_routes）
2. 動的ルート（dynamic_routes）の順次マッチング
3. キャッチオールルートは最後にマッチ

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

本機能はデータベースを使用しない（メモリ上でルーティングテーブルを管理）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InvalidRoutePattern | パース失敗 | ルートパターンの構文エラー | TinyLogにエラー詳細を記録、該当ファイルをスキップ |
| RouteCollision | ルート衝突 | 同一の有効URLを持つ複数ファイル | 最初に登録されたルートを維持、衝突を報告 |
| OutOfMemory | メモリ不足 | アロケーション失敗 | bun.OOM!を返却 |
| MissingBracket | 構文エラー | `]`が不足 | パースエラーとして報告 |
| InvalidParamName | パラメータ名エラー | パラメータ名が空または不正文字を含む | パースエラーとして報告 |

### リトライ仕様

リトライは行わない。エラー発生時は該当ファイルをスキップして処理を継続。

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

本機能はトランザクションを使用しない。

## パフォーマンス要件

- ファイルスキャンは起動時およびHMR時に実行
- matchSlowは開発環境向けの線形探索アルゴリズム（O(n)）
- プロダクション向けには最適化されたSerializedフォーマットを使用予定

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

- ルートディレクトリ外へのパストラバーサルを防止
- ignore_dirsによる.gitやnode_modulesの除外
- パラメータ名に使用できない文字（`?*{}()=:#,`）のバリデーション

## 備考

- JavaScriptからのテスト用にJSFrameworkRouterバインディングを提供
- カスタムスタイル（javascript_defined）はTODO実装

---

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

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

### 推奨読解順序

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

FrameworkRouterの核心となるデータ構造から理解を始める。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FrameworkRouter.zig | `src/bake/FrameworkRouter.zig` | Route, Type, Part, EncodedPattern構造体の定義 |

**読解のコツ**: Zigの`union(enum)`は判別共用体であり、Partの各バリアント（text, param, catch_all等）がルートセグメントの種類を表す。

**主要処理フロー**:
- **10-11行目**: OpaqueFileId - ルートファイルのID（DevServerまたはビルドコンテキストで使用）
- **67-98行目**: Route構造体 - ルートノードの定義（親子・兄弟関係、ファイル参照）
- **101-121行目**: Type構造体 - ルートタイプ設定（スタイル、拡張子、無視設定）
- **180-343行目**: EncodedPattern - シリアライズ可能なルートパターン表現
- **380-441行目**: Part共用体 - ルートセグメントの種類（text, param, catch_all等）
- **459-511行目**: Style共用体 - ルーティング規約（nextjs_pages, nextjs_app_ui等）

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

ルーターの初期化とスキャン処理の流れを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FrameworkRouter.zig | `src/bake/FrameworkRouter.zig` | initEmpty, scan, scanAll関数 |

**主要処理フロー**:
- **123-153行目**: initEmpty - FrameworkRouterの初期化、各タイプのルートルートを作成
- **171-176行目**: scanAll - 全タイプのスキャンを実行
- **986-1001行目**: scan - 指定タイプのディレクトリをスキャン開始

#### Step 3: ファイルスキャンとパターン解析

ファイルシステムからルートを検出する処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FrameworkRouter.zig | `src/bake/FrameworkRouter.zig` | scanInner, Style.parse, parseNextJsPages, parseNextJsApp |

**主要処理フロー**:
- **1003-1147行目**: scanInner - ディレクトリを再帰スキャンし、各ファイルをパース
- **498-511行目**: Style.parse - スタイルに応じたパース処理の振り分け
- **515-533行目**: parseNextJsPages - Pages Routerスタイルのパース
- **537-583行目**: parseNextJsApp - App Routerスタイルのパース
- **585-686行目**: parseNextJsLikeRouteSegment - 動的セグメントの解析

#### Step 4: ルート登録処理

解析されたパターンをルートツリーに登録する処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FrameworkRouter.zig | `src/bake/FrameworkRouter.zig` | insert関数 |

**主要処理フロー**:
- **708-812行目**: insert - ルートツリーへの挿入処理
  - 既存ルートの探索とツリー構築
  - 静的/動的ルートマップへの登録
  - 衝突検出

#### Step 5: マッチング処理

URLからルートを検索する処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | FrameworkRouter.zig | `src/bake/FrameworkRouter.zig` | matchSlow, MatchedParams, EncodedPattern.matches |

**主要処理フロー**:
- **815-846行目**: MatchedParams - マッチしたパラメータを格納（最大64個）
- **851-866行目**: matchSlow - 静的ルート優先、動的ルート順次マッチング
- **275-332行目**: EncodedPattern.matches - パターンマッチングの実装

#### Step 6: JavaScriptバインディング

JavaScriptからルーターを使用するためのバインディングを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | FrameworkRouter.zig | `src/bake/FrameworkRouter.zig` | JSFrameworkRouter構造体 |

**主要処理フロー**:
- **1152-1383行目**: JSFrameworkRouter - JavaScriptCoreとのバインディング
  - constructor: JavaScriptからの初期化
  - match: URLマッチングとパラメータ返却
  - toJSON: ルートツリーのJSON変換

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

```
FrameworkRouter.initEmpty
    │
    └─ ルート配列初期化

FrameworkRouter.scanAll
    │
    └─ FrameworkRouter.scan (各タイプ)
           │
           └─ FrameworkRouter.scanInner (再帰)
                  │
                  ├─ Resolver.readDirInfoIgnoreError
                  │
                  └─ Style.parse
                         │
                         ├─ parseNextJsPages
                         │      └─ parseNextJsLikeRouteSegment
                         │
                         └─ parseNextJsApp
                                └─ parseNextJsLikeRouteSegment

FrameworkRouter.insert
    │
    ├─ ルートツリー探索/構築
    │
    ├─ InsertionContext.getFileIdForRouter
    │
    └─ static_routes / dynamic_routes への登録

FrameworkRouter.matchSlow
    │
    ├─ static_routes.get (完全一致)
    │
    └─ dynamic_routes.keys() (順次マッチング)
           │
           └─ EncodedPattern.matches
```

### データフロー図

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

ファイルシステム    ───▶  scan/scanInner     ───▶  ルートツリー構築
  │                         │
  ├─ /pages/index.tsx       ├─ Style.parse
  ├─ /pages/[id].tsx        ├─ パターン解析
  └─ /pages/[...slug].tsx   └─ insert実行
                                   │
                                   ▼
                            ┌─────────────────┐
                            │ FrameworkRouter │
                            │ ├─ routes       │
                            │ ├─ static_routes│
                            │ └─ dynamic_routes│
                            └─────────────────┘
                                   │
URLリクエスト        ───▶   matchSlow        ───▶  MatchedParams
  │                         │
  └─ /users/123             ├─ 静的ルート検索
                            └─ 動的パターンマッチ
                                   │
                                   ▼
                            { route: Route.Index,
                              params: [{key: "id", value: "123"}] }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FrameworkRouter.zig | `src/bake/FrameworkRouter.zig` | ソース | メインルーター実装 |
| DevServer.zig | `src/bake/DevServer.zig` | ソース | 開発サーバー（ルーター使用側） |
| hmr-module.ts | `src/bake/hmr-module.ts` | ソース | HMRモジュール |
| resolver.zig | `src/resolver/resolver.zig` | ソース | ファイルシステム解決 |
| bun.zig | `src/bun.zig` | ソース | 共通ユーティリティ |
| strings.zig | `src/strings.zig` | ソース | 文字列操作ユーティリティ |
