# 機能設計書 109-jsfetch

## 概要

本ドキュメントは、Nim標準ライブラリの`jsfetch`モジュールの機能設計を記述する。このモジュールは、JavaScriptバックエンド向けにFetch APIのサポートを提供する。

### 本機能の処理概要

`jsfetch`モジュールは、JavaScriptのFetch APIをNimから利用するためのラッパーを提供する。HTTPリクエストの送信とレスポンスの受信を非同期で行うことができ、モダンなWebアプリケーション開発に必要なネットワーク通信機能を実現する。

**業務上の目的・背景**：Web開発において、サーバーとの通信（REST API呼び出し、データ取得など）は必須の機能である。Fetch APIはXMLHttpRequestの後継として、よりシンプルで強力なインターフェースを提供する。本モジュールにより、NimのJavaScriptバックエンドでもFetch APIをネイティブに利用できる。

**機能の利用シーン**：REST API呼び出し、ファイルのダウンロード/アップロード、WebSocketのフォールバック、JSONデータの取得など。

**主要な処理内容**：
1. HTTPリクエストの送信（fetch関数）
2. リクエストオプションの設定（FetchOptions）
3. レスポンスの解析（Response型）
4. JSONデータの取得（json関数）
5. FormDataの送信

**関連システム・外部連携**：JavaScript Fetch API、Headers API、FormData API。

**権限による制御**：権限による制御は存在しないが、ブラウザのCORS（Cross-Origin Resource Sharing）ポリシーに従う。

## 関連画面

本モジュールは標準ライブラリであり、特定の画面との関連はない。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | - |

## 機能種別

ネットワーク通信 / JavaScript連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| url | cstring / Request | Yes | リクエスト先URL | 有効なURL |
| options | FetchOptions | No | リクエストオプション | - |
| metod | HttpMethod | No | HTTPメソッド | GET/POST/PUT/DELETE等 |
| body | cstring | No | リクエストボディ | - |
| headers | Headers | No | HTTPヘッダー | - |

### 入力データソース

プログラムコードからの直接呼び出し。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Future[Response] | Future | 非同期レスポンス |
| Response | ref object | HTTPレスポンス（status, headers, body等） |
| Future[cstring] | Future | テキストレスポンス |
| Future[JsObject] | Future | JSONレスポンス |
| Future[FormData] | Future | FormDataレスポンス |

### 出力先

呼び出し元への戻り値（非同期）。

## 処理フロー

### 処理シーケンス

```
1. FetchOptions作成
   └─ newFetchOptions/unsafeNewFetchOptions
   └─ メソッド、ボディ、ヘッダー等を設定

2. リクエスト送信
   └─ fetch(url, options)
   └─ JavaScriptのfetch()を呼び出し
   └─ Future[Response]を返却

3. レスポンス解析
   └─ await response
   └─ response.text() / response.json() / response.formData()
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{オプションあり?}
    B -->|Yes| C[newFetchOptions]
    B -->|No| D[デフォルトでfetch]
    C --> E[fetch url, options]
    D --> E
    E --> F[Future[Response]]
    F --> G[await]
    G --> H{レスポンス種別?}
    H -->|テキスト| I[response.text]
    H -->|JSON| J[response.json]
    H -->|FormData| K[response.formData]
    I --> L[Future[cstring]]
    J --> M[Future[JsObject]]
    K --> N[Future[FormData]]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | JSバックエンド限定 | JavaScriptバックエンドでのみ使用可能 | コンパイル時 |
| BR-02 | 非同期実行 | fetch関数は常にFutureを返す | 常時 |
| BR-03 | ボディ制限 | HEAD/GETメソッドではbodyは無視される | メソッドがHEAD/GET時 |
| BR-04 | CORS遵守 | ブラウザのCORSポリシーに従う | ブラウザ実行時 |

### 計算ロジック

**FetchOptions生成**:
```nim
result = FetchOptions(
  body: if metod notin {HttpHead, HttpGet}: body else: nil,
  mode: cstring($mode),
  credentials: cstring($credentials),
  ...
)
```

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

本モジュールはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| コンパイルエラー | ビルドエラー | JSバックエンド以外で使用 | JSバックエンドでコンパイル |
| NetworkError | JavaScript例外 | ネットワーク接続失敗 | try-exceptで捕捉 |
| TypeError | JavaScript例外 | 無効なURL | URLを検証 |

### リトライ仕様

アプリケーション側でリトライロジックを実装する必要がある。

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

トランザクション管理は不要（HTTPはステートレス）。

## パフォーマンス要件

- 非同期実行によりUIブロッキングなし
- ブラウザのネットワークスタックを使用

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

- CORSポリシーに従う
- HTTPS推奨
- 認証情報（credentials）の取り扱いに注意

## 備考

- JSバックエンド専用モジュール
- jsformdata、jsheadersモジュールを自動エクスポート
- MDN: https://developer.mozilla.org/docs/Web/API/Fetch_API

---

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

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

### 推奨読解順序

#### Step 1: 型定義を理解する

主要な型（FetchOptions、Response、Request）を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | jsfetch.nim | `lib/std/jsfetch.nim` | 2-3行目: JSバックエンド制限 |
| 1-2 | jsfetch.nim | `lib/std/jsfetch.nim` | 5-8行目: 依存モジュール |
| 1-3 | jsfetch.nim | `lib/std/jsfetch.nim` | 10-15行目: FetchOptions型 |
| 1-4 | jsfetch.nim | `lib/std/jsfetch.nim` | 46-52行目: Response型 |
| 1-5 | jsfetch.nim | `lib/std/jsfetch.nim` | 54-60行目: Request型 |

**読解のコツ**: FetchOptions型のフィールドは、JavaScript Fetch APIのオプションと1対1で対応している。`importjs`プラグマで"method"が"metod"にマッピングされている点に注意。

#### Step 2: 列挙型を理解する

モード、認証情報、キャッシュ等のオプション値を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | jsfetch.nim | `lib/std/jsfetch.nim` | 17-20行目: FetchModes |
| 2-2 | jsfetch.nim | `lib/std/jsfetch.nim` | 22-26行目: FetchCredentials |
| 2-3 | jsfetch.nim | `lib/std/jsfetch.nim` | 28-33行目: FetchCaches |
| 2-4 | jsfetch.nim | `lib/std/jsfetch.nim` | 35-38行目: FetchRedirects |
| 2-5 | jsfetch.nim | `lib/std/jsfetch.nim` | 40-45行目: FetchReferrerPolicies |

**読解のコツ**: 各列挙型は文字列値を持ち、JavaScript APIに直接マッピングされる。

#### Step 3: コンストラクタを理解する

Request/Response/FetchOptionsの作成方法を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | jsfetch.nim | `lib/std/jsfetch.nim` | 62-69行目: newResponse/newRequest |
| 3-2 | jsfetch.nim | `lib/std/jsfetch.nim` | 83-86行目: unsafeNewFetchOptions |
| 3-3 | jsfetch.nim | `lib/std/jsfetch.nim` | 88-106行目: newFetchOptions |

**主要処理フロー**:
- **83行目**: unsafeNewFetchOptionsは全てcstringで受け取る低レベルAPI
- **88-106行目**: newFetchOptionsは型安全なAPIで、HttpMethodから文字列への変換を行う

#### Step 4: fetch関数とレスポンス処理を理解する

メインのfetch関数とレスポンス取得を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | jsfetch.nim | `lib/std/jsfetch.nim` | 71-72行目: clone関数 |
| 4-2 | jsfetch.nim | `lib/std/jsfetch.nim` | 74-81行目: text/json/formData |
| 4-3 | jsfetch.nim | `lib/std/jsfetch.nim` | 108-112行目: fetch関数 |
| 4-4 | jsfetch.nim | `lib/std/jsfetch.nim` | 114-116行目: toCstring/$ |

**主要処理フロー**:
- **108行目**: シンプルなGETリクエスト用fetch
- **111行目**: オプション付きfetch
- **74-81行目**: レスポンスボディの各形式での取得

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

```
jsfetch.nim
    │
    ├─ 型定義
    │      ├─ FetchOptions {metod, body, mode, credentials, ...}
    │      ├─ Response {ok, status, headers, body, ...}
    │      └─ Request {url, headers, ...}
    │
    ├─ 列挙型
    │      ├─ FetchModes (cors, no-cors, same-origin)
    │      ├─ FetchCredentials (include, same-origin, omit)
    │      ├─ FetchCaches (default, no-store, reload, ...)
    │      ├─ FetchRedirects (follow, error, manual)
    │      └─ FetchReferrerPolicies (no-referrer, ...)
    │
    ├─ コンストラクタ
    │      ├─ newResponse ─── JavaScript: new Response()
    │      ├─ newRequest ─── JavaScript: new Request()
    │      ├─ unsafeNewFetchOptions ─── オブジェクトリテラル
    │      └─ newFetchOptions ─── 型安全なラッパー
    │
    ├─ fetch関数
    │      ├─ fetch(url) ─── JavaScript: fetch()
    │      └─ fetch(url, options) ─── JavaScript: fetch()
    │
    └─ レスポンス処理
           ├─ response.text() ─── Future[cstring]
           ├─ response.json() ─── Future[JsObject]
           ├─ response.formData() ─── Future[FormData]
           └─ response.clone() ─── Response
```

### データフロー図

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

URL + Options ─────────▶ fetch() ───────────────────▶ Future[Response]
                              │
                              └─▶ JavaScript: fetch()

Response ──────────────▶ text() ────────────────────▶ Future[cstring]
                              │
                              └─▶ JavaScript: response.text()

Response ──────────────▶ json() ────────────────────▶ Future[JsObject]
                              │
                              └─▶ JavaScript: response.json()

HttpMethod + body ─────▶ newFetchOptions ───────────▶ FetchOptions
                              │
                              ├─▶ metod変換 (HttpGet → "GET")
                              └─▶ body検証 (HEAD/GETならnil)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| jsfetch.nim | `lib/std/jsfetch.nim` | ソース | メインモジュール、Fetch API実装 |
| asyncjs.nim | `lib/std/asyncjs.nim` | 依存 | Future型、async/await |
| jsformdata.nim | `lib/std/jsformdata.nim` | 依存 | FormData型 |
| jsheaders.nim | `lib/std/jsheaders.nim` | 依存 | Headers型 |
| httpcore.nim | `lib/pure/httpcore.nim` | 依存 | HttpMethod型 |
| jsffi.nim | `lib/std/jsffi.nim` | 依存 | JsObject型 |
