# 機能設計書 44-sea

## 概要

本ドキュメントは、Node.jsの`sea`モジュールの機能設計を記載する。SEA（Single Executable Application）は、Node.jsアプリケーションを単一の実行可能ファイルにバンドルする機能であり、このモジュールはSEAアプリケーション内でアセットにアクセスするためのAPIを提供する。

### 本機能の処理概要

seaモジュールは、シングル実行可能アプリケーション内に埋め込まれたアセット（リソースファイル）へのアクセスを可能にする。SEAとして生成されたバイナリ内から、ビルド時に埋め込まれた静的ファイルやデータを取得できる。

**業務上の目的・背景**：従来、Node.jsアプリケーションの配布にはNode.jsランタイムのインストールが必要だった。SEA機能により、Node.jsランタイムとアプリケーションコードを単一の実行可能ファイルにバンドルでき、エンドユーザーはNode.jsをインストールすることなくアプリケーションを実行できる。これにより、デスクトップアプリケーション、CLIツール、IoTデバイス向けソフトウェアの配布が容易になる。seaモジュールは、そのSEAバイナリ内に埋め込まれたアセットにアクセスするためのAPIを提供する。

**機能の利用シーン**：
- SEAアプリケーション内での設定ファイルの読み込み
- 埋め込まれたテンプレートやリソースの取得
- バンドルされた静的データへのアクセス
- アプリケーションがSEA環境で実行されているかの判定

**主要な処理内容**：
1. `isSea()`: 現在の実行環境がSEAかどうかを判定
2. `getAsset()`: 埋め込まれたアセットを文字列またはArrayBufferとして取得
3. `getRawAsset()`: アセットを生のArrayBufferとして取得（変更不可）
4. `getAssetAsBlob()`: アセットをBlobオブジェクトとして取得
5. `getAssetKeys()`: 埋め込まれたアセットのキー一覧を取得

**関連システム・外部連携**：
- Node.js SEAビルドシステム（`node --experimental-sea-config`）
- ファイルシステム（ビルド時のアセット読み込み）
- C++バインディング（internalBinding('sea')）

**権限による制御**：
- SEA環境外では各関数がエラーをスロー
- アセットキーが存在しない場合はエラー

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面機能マッピングに該当なし |

## 機能種別

ユーティリティ / リソースアクセス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | String | Yes | アセットのキー（ビルド設定で指定した名前） | 文字列であること |
| encoding | String | No | getAsset用のエンコーディング指定 | 有効なTextDecoderエンコーディング |
| options | Object | No | getAssetAsBlob用のBlobオプション | Blobコンストラクタのオプション |

### 入力データソース

SEAビルド時に埋め込まれたアセットブロブ（C++バインディング経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| isSea | Boolean | SEA環境かどうか |
| asset | String/ArrayBuffer | getAssetの戻り値（エンコーディング指定有無による） |
| rawAsset | ArrayBuffer | getRawAssetの戻り値（読み取り専用） |
| blob | Blob | getAssetAsBlobの戻り値 |
| keys | Array<String> | getAssetKeysの戻り値（アセットキーの配列） |

### 出力先

呼び出し元への戻り値

## 処理フロー

### 処理シーケンス

```
1. SEA環境チェック
   └─ isSea()でC++側の判定結果を取得
2. アセット取得（getAsset/getRawAsset）
   └─ キーのバリデーション
   └─ C++側からアセットデータを取得
   └─ エンコーディング指定があればTextDecoderでデコード
   └─ なければArrayBufferのコピーを返却
3. Blob取得（getAssetAsBlob）
   └─ getRawAssetでデータ取得
   └─ Blobオブジェクトにラップして返却
4. キー一覧取得（getAssetKeys）
   └─ C++側からキー配列を取得
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{関数種別}
    B -->|isSea| C[C++側のisSea呼び出し]
    C --> D[Boolean返却]
    B -->|getAsset| E[validateString key]
    B -->|getRawAsset| F[validateString key]
    B -->|getAssetAsBlob| G[getRawAsset呼び出し]
    B -->|getAssetKeys| H[C++側のgetAssetKeys呼び出し]
    E --> I{isSea?}
    F --> I
    I -->|No| J[ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION]
    I -->|Yes| K[getAssetInternal key]
    K --> L{アセット存在?}
    L -->|No| M[ERR_SINGLE_EXECUTABLE_APPLICATION_ASSET_NOT_FOUND]
    L -->|Yes| N{encoding指定?}
    N -->|Yes| O[TextDecoder.decode]
    N -->|No| P[ArrayBuffer.slice]
    O --> Q[String返却]
    P --> R[ArrayBuffer返却]
    G --> S[new Blob]
    S --> T[Blob返却]
    H --> U{isSea?}
    U -->|No| J
    U -->|Yes| V[keys配列返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | SEA環境限定 | getAsset/getRawAsset/getAssetKeysはSEA環境でのみ動作 | 常時 |
| BR-02 | アセット不変性 | getRawAssetの戻り値は変更不可（変更するとクラッシュの可能性） | getRawAsset使用時 |
| BR-03 | アセットコピー | getAssetはArrayBufferのコピーを返却 | encoding未指定時 |
| BR-04 | キー必須 | アセット取得にはビルド時に設定したキーが必要 | getAsset/getRawAsset/getAssetAsBlob |

### 計算ロジック

特になし

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

### 操作別データベース影響一覧

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ERR_NOT_IN_SINGLE_EXECUTABLE_APPLICATION | 環境エラー | SEA環境外でのAPI呼び出し | SEAとしてビルド・実行する |
| ERR_SINGLE_EXECUTABLE_APPLICATION_ASSET_NOT_FOUND | 未検出 | 指定キーのアセットが存在しない | キー名を確認、ビルド設定を確認 |
| TypeError | 型エラー | keyが文字列でない | 文字列を渡す |

### リトライ仕様

リトライ不要（環境・設定エラーは再試行しても解決しない）

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

該当なし

## パフォーマンス要件

- getRawAssetは直接メモリアクセスで高速（ただし変更不可）
- getAssetはコピーを作成するため若干のオーバーヘッド
- 大きなアセットはBlobとして取得し、ストリーム処理を推奨

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

- アセットはビルド時に埋め込まれ、実行時の変更は不可
- SEA環境外からはアセットにアクセス不可
- getRawAssetの戻り値を変更するとプロセスクラッシュの可能性

## 備考

- SEA機能は実験的機能
- ビルドには`node --experimental-sea-config config.json`を使用
- アセットはsea-config.jsonで定義

---

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

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

### 推奨読解順序

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

モジュールのインポートとエラー定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sea.js | `lib/sea.js` | 1-14行目のインポート定義 |

**読解のコツ**: `internalBinding('sea')`から取得する`isSea`、`getAsset`（内部名`getAssetInternal`）、`getAssetKeys`（内部名`getAssetKeysInternal`）が主要なC++バインディングであることを把握する。

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

公開APIの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sea.js | `lib/sea.js` | 84-90行目のmodule.exports |

**主要処理フロー**:
1. **84行目**: `isSea` - C++から直接インポート
2. **85行目**: `getAsset` - エンコーディング対応版
3. **86行目**: `getRawAsset` - 生のArrayBuffer版
4. **87行目**: `getAssetAsBlob` - Blob版
5. **88行目**: `getAssetKeys` - キー一覧取得

#### Step 3: getRawAsset関数を理解する

最も基本的なアセット取得関数を読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | sea.js | `lib/sea.js` | 23-35行目のgetRawAsset関数 |

**主要処理フロー**:
- **24行目**: キーを文字列としてバリデーション
- **26-28行目**: SEA環境でなければエラー
- **30行目**: C++バインディングからアセット取得
- **31-33行目**: アセットが見つからなければエラー
- **34行目**: 生のArrayBufferを返却（変更不可）

#### Step 4: getAsset関数を理解する

エンコーディング対応版のアセット取得関数を読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | sea.js | `lib/sea.js` | 46-56行目のgetAsset関数 |

**主要処理フロー**:
- **47-49行目**: encodingがある場合はバリデーション
- **50行目**: getRawAssetでアセット取得
- **51-52行目**: encodingがなければArrayBufferのコピーを返却
- **54-55行目**: encodingがあればTextDecoderでデコード

#### Step 5: getAssetAsBlob関数を理解する

Blob版のアセット取得関数を読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | sea.js | `lib/sea.js` | 66-69行目のgetAssetAsBlob関数 |

**主要処理フロー**:
- **67行目**: getRawAssetでアセット取得
- **68行目**: Blobにラップして返却

#### Step 6: getAssetKeys関数を理解する

キー一覧取得関数を読む。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | sea.js | `lib/sea.js` | 76-82行目のgetAssetKeys関数 |

**主要処理フロー**:
- **77-79行目**: SEA環境でなければエラー
- **81行目**: C++バインディングからキー配列を取得（または空配列）

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

```
require('node:sea')
    │
    └─ lib/sea.js
           │
           ├─ isSea()  ─────────────────▶ internalBinding('sea').isSea
           │
           ├─ getAsset(key, encoding)
           │      │
           │      ├─ validateString(key)
           │      ├─ getRawAsset(key)
           │      │      └─ getAssetInternal(key)  ▶ C++バインディング
           │      │
           │      └─ encoding指定時
           │             └─ new TextDecoder(encoding).decode()
           │
           ├─ getRawAsset(key)
           │      │
           │      ├─ validateString(key)
           │      ├─ isSea()チェック
           │      └─ getAssetInternal(key)  ▶ C++バインディング
           │
           ├─ getAssetAsBlob(key, options)
           │      │
           │      ├─ getRawAsset(key)
           │      └─ new Blob([asset], options)
           │
           └─ getAssetKeys()
                  │
                  ├─ isSea()チェック
                  └─ getAssetKeysInternal()  ▶ C++バインディング
```

### データフロー図

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

key                   ┌───────────────────────┐
"config.json"    ───▶│  getRawAsset(key)     │
                      │  ├─ SEA環境チェック    │
                      │  └─ C++からデータ取得  │───▶  ArrayBuffer
                      └───────────────────────┘       (読み取り専用)

key + encoding       ┌───────────────────────┐
"config.json"   ───▶│  getAsset(key, enc)   │
+ "utf-8"            │  ├─ getRawAsset()     │
                     │  └─ TextDecoder.decode│───▶  String
                     └───────────────────────┘

key + options        ┌───────────────────────┐
"image.png"     ───▶│  getAssetAsBlob(key)  │
+ {type: 'image/png'}│  ├─ getRawAsset()     │
                     │  └─ new Blob()        │───▶  Blob
                     └───────────────────────┘

(なし)               ┌───────────────────────┐
                ───▶│  getAssetKeys()       │───▶  ["config.json",
                     │  └─ C++からキー配列取得│       "image.png", ...]
                     └───────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sea.js | `lib/sea.js` | ソース | SEAモジュールの主要実装 |
| encoding.js | `lib/internal/encoding.js` | ソース | TextDecoderの提供 |
| validators.js | `lib/internal/validators.js` | ソース | validateString関数の提供 |
| errors.js | `lib/internal/errors.js` | ソース | エラーコード定義 |
| blob.js | `lib/internal/blob.js` | ソース | Blobクラスの提供 |
