fs-object-storage 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -29,13 +29,16 @@ jobs:
29
29
  publish-npm:
30
30
  needs: build
31
31
  runs-on: ubuntu-latest
32
+ permissions:
33
+ id-token: write # OIDC認証に必須
34
+ contents: read
32
35
  steps:
33
36
  - uses: actions/checkout@v4
34
37
  - uses: actions/setup-node@v4
35
38
  with:
36
- node-version: '16.x'
39
+ node-version: '20.x'
37
40
  registry-url: https://registry.npmjs.org/
41
+ - run: npm install -g npm@latest
38
42
  - run: npm ci
39
- - run: npm publish
40
- env:
41
- NODE_AUTH_TOKEN: ${{secrets.npm_token}}
43
+ - name: Publish to NPM with Trusted Publishing
44
+ run: npm publish --access public
package/README.md CHANGED
@@ -24,10 +24,10 @@ npm install fs-object-storage
24
24
  ### 基本的な使用方法
25
25
 
26
26
  ```javascript
27
- import { FsMinioClient } from 'fs-object-storage';
27
+ import { ObjectStorage } from 'fs-object-storage';
28
28
 
29
29
  // MinIO/S3クライアントの設定
30
- const client = new FsMinioClient({
30
+ const fs = new ObjectStorage({
31
31
  endPoint: 'localhost',
32
32
  port: 9000,
33
33
  useSSL: false,
@@ -38,18 +38,18 @@ const client = new FsMinioClient({
38
38
  // ファイル操作(fs互換)
39
39
  try {
40
40
  // ファイル書き込み
41
- await client.writeFile('/mybucket/path/to/file.txt', 'Hello, World!');
41
+ await fs.writeFile('/mybucket/path/to/file.txt', 'Hello, World!');
42
42
 
43
43
  // ファイル読み込み
44
- const data = await client.readFile('/mybucket/path/to/file.txt', 'utf8');
44
+ const data = await fs.readFile('/mybucket/path/to/file.txt', 'utf8');
45
45
  console.log(data); // "Hello, World!"
46
46
 
47
47
  // ファイル存在確認
48
- const exists = await client.exists('/mybucket/path/to/file.txt');
48
+ const exists = await fs.exists('/mybucket/path/to/file.txt');
49
49
  console.log(exists); // true
50
50
 
51
51
  // ディレクトリ一覧
52
- const files = await client.readdir('/mybucket/path');
52
+ const files = await fs.readdir('/mybucket/path');
53
53
  console.log(files); // ['to/']
54
54
 
55
55
  } catch (error) {
@@ -64,11 +64,11 @@ import fs from 'fs';
64
64
 
65
65
  // 大容量ファイルのアップロード
66
66
  const readStream = fs.createReadStream('./large-file.zip');
67
- const writeStream = await client.createWriteStream('/mybucket/uploads/large-file.zip');
67
+ const writeStream = await fs.createWriteStream('/mybucket/uploads/large-file.zip');
68
68
  readStream.pipe(writeStream);
69
69
 
70
70
  // ダウンロードストリーム
71
- const downloadStream = await client.createReadStream('/mybucket/uploads/large-file.zip');
71
+ const downloadStream = await fs.createReadStream('/mybucket/uploads/large-file.zip');
72
72
  const localWriteStream = fs.createWriteStream('./downloaded-file.zip');
73
73
  downloadStream.pipe(localWriteStream);
74
74
  ```
@@ -111,7 +111,7 @@ npm run test:all
111
111
  ### コンストラクタ
112
112
 
113
113
  ```javascript
114
- new FsMinioClient(options)
114
+ new ObjectStorage(options)
115
115
  ```
116
116
 
117
117
  **options**:
@@ -127,28 +127,28 @@ new FsMinioClient(options)
127
127
  ファイルを読み込みます。
128
128
 
129
129
  ```javascript
130
- const data = await client.readFile('/bucket/file.txt', 'utf8');
130
+ const data = await fs.readFile('/bucket/file.txt', 'utf8');
131
131
  ```
132
132
 
133
133
  #### `writeFile(path, data, options?)`
134
134
  ファイルを書き込みます。
135
135
 
136
136
  ```javascript
137
- await client.writeFile('/bucket/file.txt', 'データ');
137
+ await fs.writeFile('/bucket/file.txt', 'データ');
138
138
  ```
139
139
 
140
140
  #### `exists(path)`
141
141
  ファイル/ディレクトリの存在を確認します。
142
142
 
143
143
  ```javascript
144
- const exists = await client.exists('/bucket/file.txt');
144
+ const exists = await fs.exists('/bucket/file.txt');
145
145
  ```
146
146
 
147
147
  #### `stat(path)`
148
148
  ファイル/ディレクトリの統計情報を取得します。
149
149
 
150
150
  ```javascript
151
- const stats = await client.stat('/bucket/file.txt');
151
+ const stats = await fs.stat('/bucket/file.txt');
152
152
  console.log(stats.size, stats.isFile(), stats.isDirectory());
153
153
  ```
154
154
 
@@ -156,14 +156,14 @@ console.log(stats.size, stats.isFile(), stats.isDirectory());
156
156
  ファイルを削除します。
157
157
 
158
158
  ```javascript
159
- await client.unlink('/bucket/file.txt');
159
+ await fs.unlink('/bucket/file.txt');
160
160
  ```
161
161
 
162
162
  #### `copyFile(src, dest)`
163
163
  ファイルをコピーします。
164
164
 
165
165
  ```javascript
166
- await client.copyFile('/bucket/src.txt', '/bucket/dest.txt');
166
+ await fs.copyFile('/bucket/src.txt', '/bucket/dest.txt');
167
167
  ```
168
168
 
169
169
  ### ディレクトリ操作メソッド
@@ -172,21 +172,21 @@ await client.copyFile('/bucket/src.txt', '/bucket/dest.txt');
172
172
  ディレクトリの内容を一覧します。
173
173
 
174
174
  ```javascript
175
- const files = await client.readdir('/bucket/directory');
175
+ const files = await fs.readdir('/bucket/directory');
176
176
  ```
177
177
 
178
178
  #### `mkdir(path, options?)`
179
179
  ディレクトリを作成します。
180
180
 
181
181
  ```javascript
182
- await client.mkdir('/bucket/new-directory', { recursive: true });
182
+ await fs.mkdir('/bucket/new-directory', { recursive: true });
183
183
  ```
184
184
 
185
185
  #### `rmdir(path)`
186
186
  空のディレクトリを削除します。
187
187
 
188
188
  ```javascript
189
- await client.rmdir('/bucket/empty-directory');
189
+ await fs.rmdir('/bucket/empty-directory');
190
190
  ```
191
191
 
192
192
  ### ストリーム操作メソッド
@@ -195,14 +195,14 @@ await client.rmdir('/bucket/empty-directory');
195
195
  読み込みストリームを作成します。
196
196
 
197
197
  ```javascript
198
- const stream = await client.createReadStream('/bucket/file.txt');
198
+ const stream = await fs.createReadStream('/bucket/file.txt');
199
199
  ```
200
200
 
201
201
  #### `createWriteStream(path)`
202
202
  書き込みストリームを作成します。
203
203
 
204
204
  ```javascript
205
- const stream = await client.createWriteStream('/bucket/file.txt');
205
+ const stream = await fs.createWriteStream('/bucket/file.txt');
206
206
  ```
207
207
 
208
208
  ## 🗺️ パス形式
@@ -223,7 +223,7 @@ MinIOのエラーは自動的にfs互換のエラーコードに変換されま
223
223
 
224
224
  ```javascript
225
225
  try {
226
- await client.readFile('/bucket/nonexistent.txt');
226
+ await fs.readFile('/bucket/nonexistent.txt');
227
227
  } catch (error) {
228
228
  console.log(error.code); // 'ENOENT'
229
229
  console.log(error.errno); // -2
@@ -252,7 +252,7 @@ try {
252
252
 
253
253
  本ライブラリは以下のコンポーネントで構成されています:
254
254
 
255
- - **FsMinioClient**: メインのfs互換クライアント
255
+ - **ObjectStorage**: メインのfs互換クライアント
256
256
  - **ErrorHandler**: MinIO→fs エラー変換
257
257
  - **PathConverter**: ファイルパス⇔バケット/キー変換
258
258
  - **StreamConverter**: ストリーム/データ形式変換
@@ -284,4 +284,4 @@ MIT
284
284
 
285
285
  - **ドキュメント**: [`docs/`](./docs/) フォルダ
286
286
  - **GitHub Issues**: バグ報告・機能要求
287
- - **サンプルコード**: [`samples/`](./samples/) フォルダ"
287
+ - **サンプルコード**: [`samples/`](./samples/) フォルダ
@@ -0,0 +1,312 @@
1
+ # fs-object-storage API リファレンス
2
+
3
+ ## 概要
4
+ `fs-object-storage`は、Node.js標準の`fs`モジュールと互換性のあるAPIを提供しながら、バックエンドでMinIO/S3オブジェクトストレージを使用するライブラリです。
5
+
6
+ ## インストール・セットアップ
7
+
8
+ ### 依存関係
9
+ ```bash
10
+ npm install minio
11
+ ```
12
+
13
+ ### 基本的な使用方法
14
+ ```javascript
15
+ import { ObjectStorage } from './src/index.js';
16
+
17
+ const fs = new ObjectStorage({
18
+ endpoint: 'localhost:9000',
19
+ accessKey: 'minioadmin',
20
+ secretKey: 'minioadmin123',
21
+ bucket: 'my-app-bucket',
22
+ useSSL: false,
23
+ prefix: 'app-data' // オプション:全てのキーにプレフィックスを追加
24
+ });
25
+
26
+ // 初期化(バケット作成など)
27
+ await fs.initialize();
28
+ ```
29
+
30
+ ## コンストラクター
31
+
32
+ ### `new ObjectStorage(options)`
33
+
34
+ MinIOクライアントインスタンスを作成します。
35
+
36
+ **パラメーター:**
37
+ - `options` (Object) - 設定オプション
38
+ - `endpoint` (string) - MinIOエンドポイント (例: 'localhost:9000')
39
+ - `accessKey` (string) - アクセスキー
40
+ - `secretKey` (string) - シークレットキー
41
+ - `bucket` (string) - 使用するバケット名
42
+ - `useSSL` (boolean, optional) - SSL使用フラグ(デフォルト: false)
43
+ - `region` (string, optional) - リージョン(デフォルト: 'us-east-1')
44
+ - `prefix` (string, optional) - 全キーに追加するプレフィックス
45
+
46
+ ## ファイル操作メソッド
47
+
48
+ ### `readFile(filePath, options)`
49
+
50
+ ファイルの内容を読み取ります。
51
+
52
+ ```javascript
53
+ // テキストファイルを読む
54
+ const content = await fs.readFile('/data/hello.txt', 'utf8');
55
+
56
+ // バイナリファイルを読む
57
+ const buffer = await fs.readFile('/images/photo.jpg');
58
+ ```
59
+
60
+ **パラメーター:**
61
+ - `filePath` (string) - ファイルパス
62
+ - `options` (string|Object, optional) - エンコーディングまたはオプション
63
+ - `encoding` (string) - テキストエンコーディング
64
+
65
+ **戻り値:** `Promise<Buffer|string>` - ファイル内容
66
+
67
+ ### `writeFile(filePath, data, options)`
68
+
69
+ ファイルにデータを書き込みます。
70
+
71
+ ```javascript
72
+ // テキストファイルを書く
73
+ await fs.writeFile('/data/hello.txt', 'Hello World!', 'utf8');
74
+
75
+ // バイナリファイルを書く
76
+ const buffer = Buffer.from([0x89, 0x50, 0x4E, 0x47]);
77
+ await fs.writeFile('/images/test.png', buffer);
78
+ ```
79
+
80
+ **パラメーター:**
81
+ - `filePath` (string) - ファイルパス
82
+ - `data` (string|Buffer|Uint8Array) - 書き込むデータ
83
+ - `options` (string|Object, optional) - エンコーディングまたはオプション
84
+
85
+ **戻り値:** `Promise<void>`
86
+
87
+ ### `exists(filePath)`
88
+
89
+ ファイルの存在を確認します。
90
+
91
+ ```javascript
92
+ const fileExists = await fs.exists('/data/hello.txt');
93
+ console.log(fileExists); // true または false
94
+ ```
95
+
96
+ **パラメーター:**
97
+ - `filePath` (string) - ファイルパス
98
+
99
+ **戻り値:** `Promise<boolean>` - ファイル存在フラグ
100
+
101
+ ### `stat(filePath)`
102
+
103
+ ファイルの統計情報を取得します。
104
+
105
+ ```javascript
106
+ const stats = await fs.stat('/data/hello.txt');
107
+ console.log('ファイルサイズ:', stats.size);
108
+ console.log('更新日時:', stats.mtime);
109
+ console.log('ファイルかどうか:', stats.isFile());
110
+ ```
111
+
112
+ **パラメーター:**
113
+ - `filePath` (string) - ファイルパス
114
+
115
+ **戻り値:** `Promise<Object>` - fs.Stats風オブジェクト
116
+
117
+ ### `unlink(filePath)`
118
+
119
+ ファイルを削除します。
120
+
121
+ ```javascript
122
+ await fs.unlink('/data/old-file.txt');
123
+ ```
124
+
125
+ **パラメーター:**
126
+ - `filePath` (string) - ファイルパス
127
+
128
+ **戻り値:** `Promise<void>`
129
+
130
+ ## ディレクトリ操作メソッド
131
+
132
+ ### `readdir(dirPath, options)`
133
+
134
+ ディレクトリの内容を一覧表示します。
135
+
136
+ ```javascript
137
+ // ファイル名の配列を取得
138
+ const files = await fs.readdir('/data');
139
+
140
+ // Direntオブジェクトの配列を取得
141
+ const entries = await fs.readdir('/data', { withFileTypes: true });
142
+ ```
143
+
144
+ **パラメーター:**
145
+ - `dirPath` (string) - ディレクトリパス
146
+ - `options` (Object, optional) - オプション
147
+ - `withFileTypes` (boolean) - Direntオブジェクトを返すかどうか
148
+
149
+ **戻り値:** `Promise<string[]|Object[]>` - ファイル名またはDirentオブジェクトの配列
150
+
151
+ ### `mkdir(dirPath, options)`
152
+
153
+ ディレクトリを作成します。
154
+
155
+ ```javascript
156
+ // 単一ディレクトリ作成
157
+ await fs.mkdir('/new-folder');
158
+
159
+ // 再帰的作成(親ディレクトリも作成)
160
+ await fs.mkdir('/deep/nested/folder', { recursive: true });
161
+ ```
162
+
163
+ **パラメーター:**
164
+ - `dirPath` (string) - ディレクトリパス
165
+ - `options` (Object, optional) - オプション
166
+ - `recursive` (boolean) - 親ディレクトリも作成するかどうか
167
+
168
+ **戻り値:** `Promise<void>`
169
+
170
+ ### `rmdir(dirPath)`
171
+
172
+ 空のディレクトリを削除します。
173
+
174
+ ```javascript
175
+ await fs.rmdir('/empty-folder');
176
+ ```
177
+
178
+ **パラメーター:**
179
+ - `dirPath` (string) - ディレクトリパス
180
+
181
+ **戻り値:** `Promise<void>`
182
+
183
+ ## ストリーム操作メソッド
184
+
185
+ ### `createReadStream(filePath, options)`
186
+
187
+ 読み取りストリームを作成します。
188
+
189
+ ```javascript
190
+ const readStream = await fs.createReadStream('/large-file.txt');
191
+
192
+ readStream.on('data', (chunk) => {
193
+ console.log('受信:', chunk.length, 'バイト');
194
+ });
195
+
196
+ readStream.on('end', () => {
197
+ console.log('読み取り完了');
198
+ });
199
+ ```
200
+
201
+ **パラメーター:**
202
+ - `filePath` (string) - ファイルパス
203
+ - `options` (Object, optional) - ストリームオプション
204
+
205
+ **戻り値:** `Promise<Readable>` - 読み取りストリーム
206
+
207
+ ### `createWriteStream(filePath, options)`
208
+
209
+ 書き込みストリームを作成します。
210
+
211
+ ```javascript
212
+ const writeStream = fs.createWriteStream('/output.txt');
213
+
214
+ writeStream.write('Hello ');
215
+ writeStream.write('World!');
216
+ writeStream.end();
217
+ ```
218
+
219
+ **パラメーター:**
220
+ - `filePath` (string) - ファイルパス
221
+ - `options` (Object, optional) - ストリームオプション
222
+
223
+ **戻り値:** `Writable` - 書き込みストリーム
224
+
225
+ ## 高度な操作
226
+
227
+ ### `copyFile(srcPath, destPath)`
228
+
229
+ ファイルをコピーします。
230
+
231
+ ```javascript
232
+ await fs.copyFile('/source.txt', '/destination.txt');
233
+ ```
234
+
235
+ **パラメーター:**
236
+ - `srcPath` (string) - コピー元ファイルパス
237
+ - `destPath` (string) - コピー先ファイルパス
238
+
239
+ **戻り値:** `Promise<void>`
240
+
241
+ ## エラーハンドリング
242
+
243
+ ライブラリは標準的なNode.js `fs`モジュールと同じエラーコードを使用します:
244
+
245
+ ```javascript
246
+ try {
247
+ await fs.readFile('/nonexistent.txt');
248
+ } catch (error) {
249
+ if (error.code === 'ENOENT') {
250
+ console.log('ファイルが見つかりません');
251
+ } else if (error.code === 'EACCES') {
252
+ console.log('アクセス権限がありません');
253
+ }
254
+ }
255
+ ```
256
+
257
+ ### 主要なエラーコード
258
+ - `ENOENT` - ファイル/ディレクトリが存在しない
259
+ - `EACCES` - アクセス権限拒否
260
+ - `EEXIST` - ファイル/ディレクトリが既に存在
261
+ - `ENOTDIR` - ディレクトリではない
262
+ - `ENOTEMPTY` - ディレクトリが空でない
263
+
264
+ ## パス変換について
265
+
266
+ ファイルシステムパスは自動的にMinIOオブジェクトキーに変換されます:
267
+
268
+ ```javascript
269
+ // ファイルシステムパス → MinIOキー
270
+ '/data/users/123/profile.json' → 'data/users/123/profile.json'
271
+
272
+ // プレフィックス付きの場合
273
+ // prefix: 'app-data'
274
+ '/data/file.txt' → 'app-data/data/file.txt'
275
+ ```
276
+
277
+ ## 仮想ディレクトリ
278
+
279
+ MinIOにはディレクトリの概念がないため、プレフィックスベースの仮想ディレクトリを実装しています:
280
+
281
+ - ディレクトリマーカー(空のオブジェクト)を使用
282
+ - `readdir()`は共通プレフィックスでオブジェクトを検索
283
+ - `mkdir()`はディレクトリマーカーオブジェクトを作成
284
+
285
+ ## パフォーマンス考慮事項
286
+
287
+ - 大きなファイルにはストリームAPIを使用することを推奨
288
+ - 同期APIは提供していません(全て非同期)
289
+ - バッチ操作は個別に実装する必要があります
290
+
291
+ ## トラブルシューティング
292
+
293
+ ### よくある問題
294
+
295
+ 1. **接続エラー**
296
+ ```javascript
297
+ // 接続設定を確認
298
+ console.log('MinIOエンドポイント:', fs.endpoint);
299
+ // MinIOサーバーが起動しているか確認
300
+ ```
301
+
302
+ 2. **認証エラー**
303
+ ```javascript
304
+ // アクセスキー・シークレットキーを確認
305
+ // MinIOコンソールで権限を確認
306
+ ```
307
+
308
+ 3. **バケット存在エラー**
309
+ ```javascript
310
+ // initialize()を呼び出してバケットを作成
311
+ await fs.initialize();
312
+ ```
@@ -0,0 +1,179 @@
1
+ # fs-object-storage アーキテクチャ設計
2
+
3
+ ## 概要
4
+ Node.js fsモジュール互換のAPIを提供しながら、バックエンドでMinIO/S3オブジェクトストレージを使用するライブラリ。
5
+
6
+ ## アーキテクチャ
7
+
8
+ ### レイヤー構造
9
+ ```
10
+ ┌─────────────────────────────────────┐
11
+ │ fs 互換 API レイヤー │
12
+ │ (readFile, writeFile, exists, etc.) │
13
+ ├─────────────────────────────────────┤
14
+ │ パス変換レイヤー │
15
+ │ (/path/to/file → bucket/key) │
16
+ ├─────────────────────────────────────┤
17
+ │ ストリーム変換レイヤー │
18
+ │ (Buffer/String ↔ MinIO Stream) │
19
+ ├─────────────────────────────────────┤
20
+ │ エラー変換レイヤー │
21
+ │ (MinIO Error → fs Error) │
22
+ ├─────────────────────────────────────┤
23
+ │ MinIO クライアント │
24
+ │ (Low-level object operations) │
25
+ └─────────────────────────────────────┘
26
+ ```
27
+
28
+ ## 主要コンポーネント
29
+
30
+ ### 1. ObjectStorage
31
+ - メインのクライアントクラス
32
+ - fs互換APIの提供
33
+ - 設定管理(bucket名、接続情報等)
34
+
35
+ ### 2. PathConverter
36
+ - ファイルシステムパス → MinIOオブジェクトキー変換
37
+ - 仮想ディレクトリ実装(プレフィックスベース)
38
+ - パス正規化
39
+
40
+ ### 3. StreamConverter
41
+ - Buffer/String → MinIO readable stream
42
+ - MinIO readable stream → Buffer/String
43
+ - 非同期ストリーム処理
44
+
45
+ ### 4. ErrorHandler
46
+ - MinIOエラー → fs-style エラー変換
47
+ - 適切なerror.codeの設定
48
+ - エラーメッセージの正規化
49
+
50
+ ### 5. MetadataManager
51
+ - ファイルメタデータの管理
52
+ - 仮想ディレクトリ情報
53
+ - タイムスタンプ、サイズ等の stat 情報
54
+
55
+ ## API設計
56
+
57
+ ### 基本原則
58
+ - fs モジュールとの完全互換性
59
+ - 同期/非同期両方のAPIサポート
60
+ - Promise ベースの実装
61
+ - TypeScript サポート
62
+
63
+ ### 実装対象メソッド(優先度順)
64
+
65
+ #### Phase 1: 基本ファイル操作
66
+ - [x] `readFile(path, options)` - ファイル読み込み
67
+ - [x] `writeFile(path, data, options)` - ファイル書き込み
68
+ - [x] `exists(path)` - ファイル存在確認
69
+ - [x] `stat(path)` - ファイル情報取得
70
+ - [x] `unlink(path)` - ファイル削除
71
+
72
+ #### Phase 2: ディレクトリ操作
73
+ - [ ] `readdir(path)` - ディレクトリ一覧
74
+ - [ ] `mkdir(path)` - ディレクトリ作成
75
+ - [ ] `rmdir(path)` - ディレクトリ削除
76
+
77
+ #### Phase 3: ストリーム操作
78
+ - [ ] `createReadStream(path)` - 読み込みストリーム
79
+ - [ ] `createWriteStream(path)` - 書き込みストリーム
80
+
81
+ #### Phase 4: 高度な操作
82
+ - [ ] `copyFile(src, dest)` - ファイルコピー
83
+ - [ ] `rename(oldPath, newPath)` - ファイル移動/リネーム
84
+
85
+ ## パス変換仕様
86
+
87
+ ### ファイルシステムパス → MinIOキー
88
+ ```javascript
89
+ // 例:
90
+ '/data/users/123/profile.json'
91
+ → bucket: 'myapp', key: 'data/users/123/profile.json'
92
+
93
+ '/images/avatar.png'
94
+ → bucket: 'myapp', key: 'images/avatar.png'
95
+ ```
96
+
97
+ ### 仮想ディレクトリ実装
98
+ - MinIOにディレクトリ概念はないため、プレフィックスベースで実装
99
+ - 空の「ディレクトリマーカー」オブジェクトを作成
100
+ - readdir では共通プレフィックスでオブジェクト一覧を取得
101
+
102
+ ## エラーハンドリング
103
+
104
+ ### MinIOエラー → fsエラー変換マッピング
105
+ ```javascript
106
+ const errorMapping = {
107
+ 'NoSuchKey': { code: 'ENOENT', errno: -2 },
108
+ 'AccessDenied': { code: 'EACCES', errno: -13 },
109
+ 'BucketNotFound': { code: 'ENOENT', errno: -2 },
110
+ 'InvalidBucketName': { code: 'EINVAL', errno: -22 },
111
+ };
112
+ ```
113
+
114
+ ## 設定例
115
+ ```javascript
116
+ const fs = new ObjectStorage({
117
+ endpoint: 'localhost:9000',
118
+ accessKey: 'minioadmin',
119
+ secretKey: 'minioadmin',
120
+ bucket: 'myapp',
121
+ useSSL: false
122
+ });
123
+
124
+ // fs互換API
125
+ await fs.writeFile('/data/test.txt', 'Hello World');
126
+ const content = await fs.readFile('/data/test.txt', 'utf8');
127
+ ```
128
+
129
+ ## 実装フェーズ計画
130
+
131
+ ### Phase 1: 基本実装 (目標: 2-3日)
132
+ 1. プロジェクト構造セットアップ
133
+ 2. FsMinioClient基本クラス作成
134
+ 3. 基本ファイル操作(read/write/exists/stat/unlink)実装
135
+ 4. 基本的なエラーハンドリング
136
+
137
+ ### Phase 2: ディレクトリ機能 (目標: 1-2日)
138
+ 1. PathConverter実装
139
+ 2. 仮想ディレクトリ機能
140
+ 3. readdir, mkdir, rmdir実装
141
+
142
+ ### Phase 3: ストリーム機能 (目標: 1-2日)
143
+ 1. StreamConverter実装
144
+ 2. createReadStream, createWriteStream実装
145
+ 3. 大きなファイル対応
146
+
147
+ ### Phase 4: 完成 (目標: 1日)
148
+ 1. 高度な機能(copy, rename等)
149
+ 2. TypeScript型定義
150
+ 3. 詳細テスト
151
+ 4. ドキュメント整備
152
+
153
+ ## テスト戦略
154
+
155
+ ### 単体テスト
156
+ - 各コンポーネントの独立テスト
157
+ - モックを使用したMinIOクライアント分離
158
+
159
+ ### 統合テスト
160
+ - 実際のMinIOコンテナを使用
161
+ - End-to-endテストシナリオ
162
+
163
+ ### パフォーマンステスト
164
+ - 大きなファイルの読み書き
165
+ - 同時接続数の確認
166
+ - メモリ使用量の監視
167
+
168
+ ### `new ObjectStorage(options)`
169
+ ```javascript
170
+ const fs = new ObjectStorage({
171
+ endpoint: 'localhost:9000',
172
+ accessKey: 'minioadmin',
173
+ secretKey: 'minioadmin',
174
+ bucket: 'myapp',
175
+ useSSL: false
176
+ });
177
+
178
+ // 以降のclientをfsに統一
179
+ ```