# 機能設計書 76-ファイルプロバイダー管理

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおける外部ストレージプロバイダー（S3、GCS等）との連携管理機能について記載する。

### 本機能の処理概要

ファイルプロバイダー管理機能は、ファイルのアップロード・ダウンロード・削除を行う外部ストレージサービスとの連携を抽象化し、統一的なインターフェースを提供する機能である。プロバイダーの登録、初期化、各種ファイル操作の委譲を行う。

**業務上の目的・背景**：
ECサイトではファイルストレージとして様々なサービス（AWS S3、Google Cloud Storage、Azure Blob Storage等）が使用される。本機能は、これらのストレージサービスを統一的なインターフェースで操作できるようにし、ストレージサービスの切り替えや複数サービスの併用を容易にする。

**機能の利用シーン**：
- AWS S3を使用したファイル保存
- Google Cloud Storageを使用したファイル保存
- ローカルファイルシステムを使用したファイル保存（開発環境）
- 事前署名URL（Presigned URL）の生成
- ストリーミングアップロード・ダウンロード

**主要な処理内容**：
1. プロバイダーの登録・初期化
2. ファイルアップロードの委譲
3. ファイル削除の委譲
4. ダウンロードURL生成の委譲
5. 事前署名アップロードURL生成の委譲
6. ストリーミング操作の委譲

**関連システム・外部連携**：
- AWS S3（s3-file-provider）
- Google Cloud Storage（対応プロバイダー）
- ローカルファイルシステム（local-file-provider）
- その他カスタムプロバイダー

**権限による制御**：
- プロバイダー登録は起動時の設定で制御
- ファイル操作は呼び出し元の認証・認可に依存

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 直接の関連画面なし（バックエンド基盤機能） |

## 機能種別

インフラ基盤 / プロバイダー抽象化

## 入力仕様

### プロバイダーインターフェース（IFileProvider）

| メソッド名 | パラメータ | 戻り値 | 説明 |
|-----------|-----------|--------|------|
| upload | ProviderUploadFileDTO | Promise<ProviderFileResultDTO> | ファイルアップロード |
| delete | ProviderDeleteFileDTO / ProviderDeleteFileDTO[] | Promise<void> | ファイル削除 |
| getPresignedDownloadUrl | ProviderGetFileDTO | Promise<string> | ダウンロードURL取得 |
| getPresignedUploadUrl | ProviderGetPresignedUploadUrlDTO | Promise<ProviderFileResultDTO> | アップロードURL取得（オプション） |
| getDownloadStream | ProviderGetFileDTO | Promise<Readable> | ダウンロードストリーム取得 |
| getAsBuffer | ProviderGetFileDTO | Promise<Buffer> | ファイルバッファ取得 |
| getUploadStream | ProviderUploadStreamDTO | Promise<{writeStream, promise, url, fileKey}> | アップロードストリーム取得 |

### 入力データソース

- モジュール設定（medusa-config.js）
- ファイルモジュールサービスからの呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| key | string | ストレージ内のファイルキー |
| url | string | ファイルアクセスURL |

### 出力先

- 呼び出し元サービス
- 外部ストレージサービス

## 処理フロー

### 処理シーケンス

```
【プロバイダー初期化】
1. モジュール起動
   └─ FileProviderService初期化
2. コンテナからプロバイダー取得
   └─ file_provider_xxx キーで登録されたプロバイダー
3. プロバイダー検証
   └─ 1つのみ登録されていることを確認
4. プロバイダー保持
   └─ this.fileProvider_に保存

【ファイル操作】
1. サービスメソッド呼び出し
   └─ upload / delete / getPresignedDownloadUrl等
2. プロバイダーへ委譲
   └─ this.fileProvider_.[method]()
3. 結果返却
   └─ プロバイダーからの結果をそのまま返却
```

### フローチャート

```mermaid
flowchart TD
    A[モジュール起動] --> B[FileProviderService初期化]
    B --> C[コンテナからプロバイダー検索]
    C --> D{1つのみ?}
    D -->|No| E[エラー: 1プロバイダーのみ]
    D -->|Yes| F[プロバイダー保持]
    F --> G[準備完了]

    H[ファイル操作リクエスト] --> I{メソッド種別}
    I -->|upload| J[provider.upload]
    I -->|delete| K[provider.delete]
    I -->|getPresignedDownloadUrl| L[provider.getPresignedDownloadUrl]
    I -->|getPresignedUploadUrl| M{機能サポート?}
    M -->|No| N[エラー: 未サポート]
    M -->|Yes| O[provider.getPresignedUploadUrl]
    J --> P[結果返却]
    K --> P
    L --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-76-01 | 単一プロバイダー | ファイルモジュールは1つのプロバイダーのみ | モジュール初期化時 |
| BR-76-02 | 事前署名URL任意 | getPresignedUploadUrlはオプション機能 | 機能呼び出し時 |
| BR-76-03 | ファイル名必須 | 事前署名URL取得時はファイル名必須 | getPresignedUploadUrl呼び出し時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | DBへの直接操作なし（プロバイダーへ委譲） |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | INVALID_DATA | 複数プロバイダー登録 | 設定で1つのみに制限 |
| 400 | INVALID_DATA | getPresignedUploadUrl未サポート | 対応プロバイダーを使用 |
| 400 | INVALID_DATA | ファイル名未指定（事前署名URL） | ファイル名を指定 |
| 500 | INTERNAL_ERROR | プロバイダー操作エラー | プロバイダー設定確認 |

### リトライ仕様

プロバイダー内部のリトライ実装に依存。FileProviderServiceはリトライなし。

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

- ファイル操作はストレージ操作のため、DBトランザクションなし
- プロバイダー内部のトランザクション実装に依存

## パフォーマンス要件

- ストリーミング操作によるメモリ効率的な大容量ファイル処理
- 事前署名URLによるサーバー負荷軽減

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

- 事前署名URLの有効期限管理
- プロバイダー認証情報の安全な管理
- 公開/非公開ファイルのアクセス制御

## 備考

- プロバイダーは起動時に1つのみ登録可能
- プロバイダーの実装はIFileProviderインターフェースに準拠
- カスタムプロバイダーの実装も可能

---

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

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

### 推奨読解順序

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

プロバイダーインターフェースを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types/index.ts | `packages/core/types/src/file/provider.ts` | IFileProviderインターフェース定義 |

**読解のコツ**: IFileProviderの各メソッドシグネチャを確認。getPresignedUploadUrlがオプショナルであることに注意。

#### Step 2: プロバイダーサービスを理解する

FileProviderServiceの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | file-provider-service.ts | `packages/modules/file/src/services/file-provider-service.ts` | プロバイダーラッパー |

**主要処理フロー**:
1. **12-28行目**: コンストラクタ - プロバイダー検索と単一検証
2. **16-18行目**: file_provider_プレフィックスでプロバイダー検索
3. **20-25行目**: 1つのみの検証
4. **37-41行目**: upload - プロバイダーへ委譲
5. **43-48行目**: delete - プロバイダーへ委譲
6. **51-54行目**: getPresignedDownloadUrl - プロバイダーへ委譲
7. **57-75行目**: getPresignedUploadUrl - サポート確認と委譲

#### Step 3: モジュールサービスとの連携を理解する

FileModuleServiceからの呼び出しを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | file-module-service.ts | `packages/modules/file/src/services/file-module-service.ts` | モジュールサービス |

**主要処理フロー**:
- **32-34行目**: getProvider - プロバイダーサービス取得
- **42-57行目**: createFiles - upload呼び出し
- **80-89行目**: deleteFiles - delete呼び出し
- **91-100行目**: retrieveFile - getPresignedDownloadUrl呼び出し

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

```
FileModuleService
    │
    └─ FileProviderService (ラッパー)
           │
           ├─ upload()
           │      └─ IFileProvider.upload()
           │
           ├─ delete()
           │      └─ IFileProvider.delete()
           │
           ├─ getPresignedDownloadUrl()
           │      └─ IFileProvider.getPresignedDownloadUrl()
           │
           ├─ getPresignedUploadUrl()
           │      ├─ サポート確認
           │      └─ IFileProvider.getPresignedUploadUrl()
           │
           ├─ getDownloadStream()
           │      └─ IFileProvider.getDownloadStream()
           │
           ├─ getAsBuffer()
           │      └─ IFileProvider.getAsBuffer()
           │
           └─ getUploadStream()
                  └─ IFileProvider.getUploadStream()
```

### データフロー図

```
[設定]                    [初期化]                            [実行時]

medusa-config.js          FileProviderService
  │                         │
  ├─> provider設定          ├─> コンテナ検索                   upload/delete/...
  │   {                     │   file_provider_xxx              │
  │     resolve: "@medusa   │                                  ├─> FileProviderService
  │       js/file-s3"       ├─> プロバイダー保持                │   [ラッパー]
  │   }                     │   this.fileProvider_             │
  │                         │                                  └─> IFileProvider
  └─> モジュール登録         └─> 準備完了                           [実プロバイダー]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| file-provider-service.ts | `packages/modules/file/src/services/file-provider-service.ts` | ソース | プロバイダーラッパー |
| file-module-service.ts | `packages/modules/file/src/services/file-module-service.ts` | ソース | モジュールサービス |
| provider.ts | `packages/core/types/src/file/provider.ts` | ソース | IFileProviderインターフェース |
| local-file.ts | `packages/modules/providers/file-local/src/services/local-file.ts` | ソース | ローカルファイルプロバイダー実装 |
| s3-file.ts | `packages/modules/providers/file-s3/src/services/s3-file.ts` | ソース | S3プロバイダー実装 |
