# 機能設計書 110-jsformdata

## 概要

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

### 本機能の処理概要

`jsformdata`モジュールは、JavaScriptのFormData APIをNimから利用するためのラッパーを提供する。HTMLフォームデータの構築、ファイルアップロード、マルチパートフォームデータの送信など、Web開発で必要なフォーム操作を実現する。

**業務上の目的・背景**：Web開発において、フォームデータの送信（ファイルアップロード、ユーザー入力の送信など）は基本的な機能である。FormData APIは、HTMLフォーム要素を使わずにプログラマティックにフォームデータを構築し、fetch等で送信できる。本モジュールにより、NimのJavaScriptバックエンドでもFormData APIをネイティブに利用できる。

**機能の利用シーン**：ファイルアップロード、マルチパートフォーム送信、REST APIへのフォームデータ送信、動的フォーム構築など。

**主要な処理内容**：
1. FormDataオブジェクトの作成（`newFormData`）
2. キー・値ペアの追加（`add`、`[]=`）
3. 値の取得（`[]`、`getAll`）
4. キーの削除（`delete`）
5. キーの存在確認（`hasKey`）

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

**権限による制御**：権限による制御は存在しない。

## 関連画面

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

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

## 機能種別

データ操作 / JavaScript連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | cstring | Yes | フィールド名 | - |
| value | SomeNumber / bool / cstring / Blob | Yes | フィールド値 | - |
| filename | cstring | No | ファイル名（Blob用） | - |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| FormData | ref object | FormDataオブジェクト |
| cstring | cstring | 単一の値 |
| seq[cstring] | seq | 指定キーの全ての値 |
| seq[tuple] | seq | 全キー・値ペア |
| bool | bool | キーの存在 |
| int | int | エントリ数 |

### 出力先

呼び出し元への戻り値。

## 処理フロー

### 処理シーケンス

```
1. FormData作成
   └─ newFormData()
   └─ JavaScript: new FormData()

2. 値の追加
   └─ add(name, value) / [name] = value
   └─ append: 重複キー許可
   └─ set: 既存キーを上書き

3. 値の取得
   └─ [name]: 最初の値を取得
   └─ getAll(name): 全ての値を取得

4. 削除・確認
   └─ delete(name): 全ての同名キーを削除
   └─ hasKey(name): キー存在確認
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[newFormData]
    B --> C{操作種類?}
    C -->|追加| D{重複許可?}
    D -->|Yes| E[add/append]
    D -->|No| F[put/set]
    C -->|取得| G{単一/全部?}
    G -->|単一| H[`[]`]
    G -->|全部| I[getAll]
    C -->|削除| J[delete]
    C -->|確認| K[hasKey]
    E --> L[FormData]
    F --> L
    H --> M[cstring]
    I --> N[seq[cstring]]
    J --> L
    K --> O[bool]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | JSバックエンド限定 | JavaScriptバックエンドでのみ使用可能 | コンパイル時 |
| BR-02 | 重複キー | add関数は重複キーを許可、順序を保持 | add呼び出し時 |
| BR-03 | 上書き | `[]=`/put関数は既存キーを上書き | `[]=`/put呼び出し時 |
| BR-04 | 削除範囲 | delete関数は同名の全キーを削除 | delete呼び出し時 |

### 計算ロジック

**add（重複許可）**:
```nim
# JavaScript: formData.append(name, value)
# 同じキーの複数値を保持
```

**put/`[]=`（上書き）**:
```nim
# JavaScript: formData.set(name, value)
# 既存の同名キーを全て削除してから追加
```

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| コンパイルエラー | ビルドエラー | JSバックエンド以外で使用 | JSバックエンドでコンパイル |

### リトライ仕様

リトライは不要。

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

トランザクション管理は不要。

## パフォーマンス要件

- JavaScriptエンジンのFormData実装に依存
- ネイティブAPI呼び出しのため高速

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

- アップロードファイルのサイズ・種類の検証はアプリケーション側で実施
- 機密データの取り扱いに注意

## 備考

- JSバックエンド専用モジュール
- jsfetchモジュールと組み合わせて使用
- MDN: https://developer.mozilla.org/en-US/docs/Web/API/FormData

---

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

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

### 推奨読解順序

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

FormData型の定義を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | jsformdata.nim | `lib/std/jsformdata.nim` | 1-3行目: モジュールコメントとJSバックエンド制限 |
| 1-2 | jsformdata.nim | `lib/std/jsformdata.nim` | 5行目: Blobのimport |
| 1-3 | jsformdata.nim | `lib/std/jsformdata.nim` | 7行目: FormData型定義 |

**読解のコツ**: FormData型は`ref object of JsRoot`として定義されており、JavaScriptオブジェクトとして扱われる。

#### Step 2: コンストラクタと基本操作を理解する

FormDataの作成と値の追加を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | jsformdata.nim | `lib/std/jsformdata.nim` | 9行目: newFormData |
| 2-2 | jsformdata.nim | `lib/std/jsformdata.nim` | 11-19行目: add関数（append） |

**主要処理フロー**:
- **9行目**: `importjs: "new FormData()"`でJavaScriptのnew FormData()を呼び出し
- **11行目**: add(name, value)はappendにマッピング
- **16行目**: add(name, value, filename)でファイル名指定可能

#### Step 3: 削除と検索を理解する

値の削除と検索操作を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | jsformdata.nim | `lib/std/jsformdata.nim` | 21-24行目: delete関数 |
| 3-2 | jsformdata.nim | `lib/std/jsformdata.nim` | 26-27行目: getAll関数 |
| 3-3 | jsformdata.nim | `lib/std/jsformdata.nim` | 29-30行目: hasKey関数 |

**主要処理フロー**:
- **21行目**: deleteは同名の全キーを削除
- **26行目**: getAllは同名キーの全値を取得

#### Step 4: イテレーションとユーティリティを理解する

keys、values、pairsとユーティリティ関数を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | jsformdata.nim | `lib/std/jsformdata.nim` | 32-33行目: keys関数 |
| 4-2 | jsformdata.nim | `lib/std/jsformdata.nim` | 35-36行目: values関数 |
| 4-3 | jsformdata.nim | `lib/std/jsformdata.nim` | 38-39行目: pairs関数 |
| 4-4 | jsformdata.nim | `lib/std/jsformdata.nim` | 41-45行目: put関数（set） |
| 4-5 | jsformdata.nim | `lib/std/jsformdata.nim` | 47-48行目: `[]`アクセサ |
| 4-6 | jsformdata.nim | `lib/std/jsformdata.nim` | 50-52行目: clear関数 |
| 4-7 | jsformdata.nim | `lib/std/jsformdata.nim` | 54-58行目: toCstring, `$`, len |

**主要処理フロー**:
- **32行目**: keysはArray.from(formData.keys())で配列化
- **38行目**: pairsはentries()を使用
- **50行目**: clearは全キーを削除するカスタム実装

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

```
jsformdata.nim
    │
    ├─ 型定義
    │      └─ FormData (ref object of JsRoot)
    │
    ├─ コンストラクタ
    │      └─ newFormData ─── JavaScript: new FormData()
    │
    ├─ 追加
    │      ├─ add(name, value) ─── JavaScript: append()
    │      ├─ add(name, value, filename) ─── JavaScript: append()
    │      ├─ put(name, value, filename) ─── JavaScript: set()
    │      └─ `[]=`(name, value) ─── JavaScript: set()
    │
    ├─ 取得
    │      ├─ `[]`(name) ─── JavaScript: get()
    │      ├─ getAll(name) ─── JavaScript: getAll()
    │      └─ hasKey(name) ─── JavaScript: has()
    │
    ├─ イテレーション
    │      ├─ keys() ─── JavaScript: Array.from(keys())
    │      ├─ values() ─── JavaScript: Array.from(values())
    │      └─ pairs() ─── JavaScript: Array.from(entries())
    │
    ├─ 削除
    │      ├─ delete(name) ─── JavaScript: delete()
    │      └─ clear() ─── 全キーを削除
    │
    └─ ユーティリティ
           ├─ len() ─── Array.from(entries()).length
           ├─ toCstring() ─── JSON.stringify()
           └─ `$`() ─── toCstring()
```

### データフロー図

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

(初期化)
───────────────────────▶ newFormData ───────────────▶ FormData

name + value ──────────▶ add() ─────────────────────▶ FormData (追加)
                              │
                              └─▶ JavaScript: append()

name + value ──────────▶ `[]=` / put() ─────────────▶ FormData (上書き)
                              │
                              └─▶ JavaScript: set()

name ──────────────────▶ `[]` ──────────────────────▶ cstring
                              │
                              └─▶ JavaScript: get()

name ──────────────────▶ getAll() ──────────────────▶ seq[cstring]
                              │
                              └─▶ JavaScript: getAll()

FormData ──────────────▶ keys() ────────────────────▶ seq[cstring]
                              │
                              └─▶ JavaScript: Array.from(keys())

FormData ──────────────▶ pairs() ───────────────────▶ seq[tuple]
                              │
                              └─▶ JavaScript: Array.from(entries())
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| jsformdata.nim | `lib/std/jsformdata.nim` | ソース | メインモジュール、FormData API実装 |
| dom.nim | `lib/std/dom.nim` | 依存 | Blob型 |
