# 通知設計書 11-クライアントナビゲーション通知

## 概要

本ドキュメントは、Bun DevServerにおけるクライアントナビゲーション通知の設計を記載する。クライアントがルートを移動した際にInspectorへ通知する機能である。

### 本通知の処理概要

クライアントナビゲーション通知は、HMR（Hot Module Reloading）接続されたクライアントがページ間を移動した際に、DevServerのInspectorへその情報を通知する機能である。

**業務上の目的・背景**：開発時にデバッグツールやInspectorがクライアントの現在位置を把握する必要がある。この通知により、デバッガフロントエンドはアクティブなルートを追跡でき、開発者はどのページで問題が発生しているかを特定できる。また、ルートバンドルインデックスを用いて詳細なホットアップデートイベントを受信可能にする。

**通知の送信タイミング**：クライアントがWebSocket経由で`set_url`メッセージを送信した際に発火する。具体的には、HMRソケットがURLパターンを受信し、それをルートバンドルインデックスに変換した後、Inspectorエージェントに通知する。

**通知の受信者**：BunFrontendDevServerAgentを通じてInspectorフロントエンド（デバッガUI）が受信する。開発者がデバッグツールを開いている場合にのみ有効となる。

**通知内容の概要**：DevServer ID、コネクションID、ナビゲート先のURL、ルートバンドルインデックスを含む。これによりInspectorはどのクライアントがどのルートにいるかを正確に把握できる。

**期待されるアクション**：Inspectorフロントエンドはナビゲーション情報を受け取り、UIを更新して現在のルート情報を表示する。開発者はこの情報を元に、特定のルートに関連するデバッグ作業を行える。

## 通知種別

アプリ内通知（WebSocket経由でのInspector連携）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 中 |
| リトライ | なし |

### 送信先決定ロジック

Inspectorエージェントが有効（`handle != null`）な場合にのみ通知が送信される。`inspector_connection_id`が正の値を持つクライアントのみが対象となる。

## 通知テンプレート

### WebSocket通知の場合

| 項目 | 内容 |
|-----|------|
| プロトコル | WebSocket (Binary) |
| メッセージタイプ | Inspector DevTools Protocol |
| フォーマット | C++ extern関数呼び出し |

### メッセージ構造

```cpp
notifyClientNavigated(
    devServerId: i32,      // DevServer識別子
    connectionId: i32,     // クライアント接続ID
    url: String,           // ナビゲート先URL
    routeBundleId: i32     // ルートバンドルインデックス（-1は未定義）
)
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| devServerId | DevServerの一意識別子 | DevServer.inspector_server_id | Yes |
| connectionId | クライアント接続ID | HmrSocket.inspector_connection_id | Yes |
| url | ナビゲート先URLパターン | WebSocketメッセージのset_urlペイロード | Yes |
| routeBundleId | ルートバンドルインデックス | DevServer.routeToBundleIndexSlow()の戻り値 | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| WebSocketメッセージ | `set_url`受信 | Inspector有効かつconnection_id > -1 | クライアントがルートを変更した時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Inspector無効 | `dev.inspector()`がnullの場合 |
| 接続ID未設定 | `inspector_connection_id`が-1以下の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[HmrSocket: set_urlメッセージ受信] --> B[URLパターンを抽出]
    B --> C[routeToBundleIndexSlowでルートバンドルインデックス取得]
    C --> D{Inspectorエージェント有効?}
    D -->|Yes| E{connection_id > -1?}
    D -->|No| F[処理終了]
    E -->|Yes| G[URL文字列をbun.Stringに変換]
    E -->|No| F
    G --> H[notifyClientNavigated呼び出し]
    H --> I[C++側でフロントエンドに送信]
    I --> J[処理終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

本通知はデータベースを使用しない。インメモリのDevServer構造体から情報を取得する。

| データ構造 | 用途 | 備考 |
|-----------|------|------|
| DevServer.inspector_server_id | DevServer識別 | DebuggerId型 |
| HmrSocket.inspector_connection_id | 接続識別 | i32型 |
| DevServer.route_bundles | ルートバンドル一覧 | RouteBundle配列 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Inspector未接続 | Inspectorハンドルがnull | 通知をスキップ |
| 接続ID未初期化 | connection_idが-1 | 通知をスキップ |
| ルート未発見 | URLパターンに対応するルートなし | routeBundleIdを-1として通知 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし |
| 1日あたり上限 | なし |

### 配信時間帯

開発サーバー稼働中は常時送信可能

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

- ナビゲーション情報はローカルホストからの接続のみに限定される（`is_from_localhost`チェック）
- DevServer内部通信のため、外部への情報漏洩リスクは低い
- Inspector接続はWebSocket `/bun:inspect`エンドポイント経由で行われる

## 備考

- この通知はBun DevServerのデバッグ機能の一部として実装されている
- React Fast Refreshなどのフレームワーク機能と連携して動作する

---

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

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

### 推奨読解順序

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

まず、通知で使用されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | InspectorBunFrontendDevServerAgent.zig | `src/bun.js/api/server/InspectorBunFrontendDevServerAgent.zig` | BunFrontendDevServerAgent構造体の定義、notifyClientNavigatedメソッドの実装 |
| 1-2 | HmrSocket.zig | `src/bake/DevServer/HmrSocket.zig` | HmrSocket構造体のinspector_connection_idフィールド |

**読解のコツ**: Zigコードでは`extern "c"`で宣言された関数がC++側との橋渡しとなる。

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

処理の起点となるファイル・関数を特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | HmrSocket.zig | `src/bake/DevServer/HmrSocket.zig` | onMessageメソッドでset_urlケースの処理を確認 |

**主要処理フロー**:
1. **107-131行目**: `set_url`メッセージ受信時の処理
2. **110-121行目**: Inspectorへの通知呼び出し
3. **264-276行目**: `notifyInspectorClientNavigation`ヘルパー関数

#### Step 3: Inspector連携層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | InspectorBunFrontendDevServerAgent.zig | `src/bun.js/api/server/InspectorBunFrontendDevServerAgent.zig` | notifyClientNavigatedメソッドの実装（68-83行目） |
| 3-2 | InspectorBunFrontendDevServerAgent.cpp | `src/bun.js/bindings/InspectorBunFrontendDevServerAgent.cpp` | C++側の実装 |

**主要処理フロー**:
- **68-83行目**: Zig側からC++関数を呼び出すラッパー実装

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

```
HmrSocket.onMessage()
    │
    ├─ IncomingMessageId.set_url ケース
    │      │
    │      ├─ dev.routeToBundleIndexSlow(pattern)
    │      │      └─ URLパターンからルートバンドルインデックスを検索
    │      │
    │      ├─ dev.inspector()
    │      │      └─ BunFrontendDevServerAgentを取得
    │      │
    │      └─ agent.notifyClientNavigated()
    │             │
    │             └─ InspectorBunFrontendDevServerAgent__notifyClientNavigated (C++)
    │                    └─ Inspector DevTools Protocolでフロントエンドに送信
    │
    └─ notifyInspectorClientNavigation() [ヘルパー関数]
           └─ 同様のagent.notifyClientNavigated()呼び出し
```

### データフロー図

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

WebSocket              HmrSocket                    Inspectorフロントエンド
set_urlメッセージ ───▶ onMessage() ───▶ agent.notifyClientNavigated() ───▶ DevTools UI
  │                        │                              │
  │                        │                              │
  ├─ URLパターン           ├─ ルートバンドル検索           └─ ナビゲーション
  └─ (バイナリ)            └─ 接続ID検証                      イベント表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| HmrSocket.zig | `src/bake/DevServer/HmrSocket.zig` | ソース | HMR WebSocket接続管理、メッセージ処理 |
| InspectorBunFrontendDevServerAgent.zig | `src/bun.js/api/server/InspectorBunFrontendDevServerAgent.zig` | ソース | Zig側のInspectorエージェントラッパー |
| InspectorBunFrontendDevServerAgent.cpp | `src/bun.js/bindings/InspectorBunFrontendDevServerAgent.cpp` | ソース | C++側のInspectorエージェント実装 |
| InspectorBunFrontendDevServerAgent.h | `src/bun.js/bindings/InspectorBunFrontendDevServerAgent.h` | ヘッダー | C++ヘッダー定義 |
| DevServer.zig | `src/bake/DevServer.zig` | ソース | DevServerメイン実装、inspector()メソッド |
