@gravito/nebula 4.0.0 → 4.1.0

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.
package/dist/index.d.ts CHANGED
@@ -1,72 +1,147 @@
1
- import { PlanetCore, GravitoOrbit } from '@gravito/core';
1
+ import { GravitoOrbit, PlanetCore } from '@gravito/core';
2
2
 
3
3
  /**
4
- * 底層儲存介面
4
+ * StorageStore defines the low-level contract for storage backends.
5
5
  *
6
- * 所有儲存後端 (Local, S3, GCS ) 必須實作此介面
6
+ * All storage drivers (Local, S3, Memory, etc.) must implement this interface.
7
+ * It focuses on raw I/O operations without higher-level logic like hooks.
7
8
  *
8
9
  * @public
9
- * @since 4.0.0
10
10
  */
11
11
  interface StorageStore {
12
12
  /**
13
+ * Persists data to the storage backend.
14
+ *
13
15
  * 儲存檔案
14
- * @param key - 檔案路徑 (例如: 'avatars/user1.jpg')
15
- * @param data - 檔案內容
16
+ * @param key - Unique identifier or path for the file
17
+ * @param data - Content to be stored
18
+ * @param options - Optional upload options (content-type, metadata, cache-control, etc.)
19
+ * @throws {Error} If the backend fails to write the data
16
20
  */
17
- put(key: string, data: Blob | Buffer | string): Promise<void>;
21
+ put(key: string, data: Blob | Buffer | string, options?: PutOptions): Promise<void>;
18
22
  /**
23
+ * Retrieves data from the storage backend.
24
+ *
19
25
  * 讀取檔案
20
- * @param key - 檔案路徑
21
- * @returns 檔案內容,若不存在則回傳 null
26
+ * @param key - Unique identifier or path for the file
27
+ * @returns The file content as a Blob, or null if the key does not exist
22
28
  */
23
29
  get(key: string): Promise<Blob | null>;
24
30
  /**
31
+ * Removes data from the storage backend.
32
+ *
25
33
  * 刪除檔案
26
- * @param key - 檔案路徑
27
- * @returns 是否成功刪除 (若檔案不存在則回傳 false)
34
+ * @param key - Unique identifier or path for the file
35
+ * @returns True if the file was successfully deleted, false if it didn't exist
28
36
  */
29
37
  delete(key: string): Promise<boolean>;
30
38
  /**
39
+ * Verifies the existence of a file.
40
+ *
31
41
  * 檢查檔案是否存在
32
- * @param key - 檔案路徑
42
+ * @param key - Unique identifier or path for the file
43
+ * @returns True if the file exists, false otherwise
33
44
  */
34
45
  exists(key: string): Promise<boolean>;
35
46
  /**
47
+ * Duplicates a file within the same storage backend.
48
+ *
36
49
  * 複製檔案
37
- * @param from - 來源路徑
38
- * @param to - 目標路徑
50
+ * @param from - Source identifier
51
+ * @param to - Destination identifier
52
+ * @throws {Error} If the source file is missing or copy fails
39
53
  */
40
54
  copy(from: string, to: string): Promise<void>;
41
55
  /**
56
+ * Relocates or renames a file within the same storage backend.
57
+ *
42
58
  * 移動/重命名檔案
43
- * @param from - 來源路徑
44
- * @param to - 目標路徑
59
+ * @param from - Current identifier
60
+ * @param to - New identifier
61
+ * @throws {Error} If the source file is missing or move fails
45
62
  */
46
63
  move(from: string, to: string): Promise<void>;
47
64
  /**
65
+ * Enumerates files and directories.
66
+ *
48
67
  * 列出檔案 (可選實作,需要 RuntimeAdapter 支援)
49
- * @param prefix - 路徑前綴 (例如: 'uploads/')
68
+ * @param prefix - Optional path prefix to filter results
69
+ * @returns An async iterable of storage items
50
70
  */
51
71
  list?(prefix?: string): AsyncIterable<StorageItem>;
52
72
  /**
73
+ * Lists files with pagination support.
74
+ *
75
+ * 分頁列舉檔案(適合大型儲存空間)
76
+ * Recommended for large storage backends (S3, GCS) to prevent OOM.
77
+ * Provides cursor-based pagination for efficient large-scale file enumeration.
78
+ *
79
+ * @param prefix - Optional path prefix to filter results
80
+ * @param options - Pagination and filtering options
81
+ * @returns Paginated list result with cursor for next page
82
+ */
83
+ listPaginated?(prefix: string, options?: ListOptions): Promise<ListResult>;
84
+ /**
85
+ * Retrieves technical information about a file.
86
+ *
53
87
  * 取得檔案元資料
54
- * @param key - 檔案路徑
88
+ * @param key - Unique identifier or path for the file
89
+ * @returns Metadata object or null if file not found
55
90
  */
56
91
  getMetadata(key: string): Promise<StorageMetadata | null>;
57
92
  /**
93
+ * Updates custom metadata for a file.
94
+ *
95
+ * 更新自定義 Metadata(可選實作)
96
+ * Note: This method only updates custom metadata, not system metadata like size or mimeType.
97
+ *
98
+ * @param key - Unique identifier or path for the file
99
+ * @param metadata - Custom metadata to set (key-value pairs)
100
+ * @throws {Error} If the file does not exist or operation fails
101
+ */
102
+ setMetadata?(key: string, metadata: Record<string, string>): Promise<void>;
103
+ /**
104
+ * Generates a publicly accessible URL for the file.
105
+ *
58
106
  * 取得公開 URL
59
- * @param key - 檔案路徑
107
+ * @param key - Unique identifier or path for the file
108
+ * @returns The URL string
60
109
  */
61
110
  getUrl(key: string): string;
62
111
  /**
112
+ * Generates a time-limited, authorized URL.
113
+ *
63
114
  * 取得有時效的簽名 URL (可選實作)
64
- * @param key - 檔案路徑
65
- * @param expiresIn - 過期時間 (秒)
115
+ * @param key - Unique identifier or path for the file
116
+ * @param expiresIn - Duration in seconds until the URL expires
117
+ * @returns A promise resolving to the signed URL string
66
118
  */
67
119
  getSignedUrl?(key: string, expiresIn: number): Promise<string>;
120
+ /**
121
+ * Writes data from a readable stream.
122
+ *
123
+ * 串流寫入檔案(可選實作)
124
+ * Useful for handling large files without loading entire content into memory.
125
+ *
126
+ * @param key - Unique identifier or path for the file
127
+ * @param stream - Readable stream containing the data
128
+ * @throws {Error} If the backend fails to write the stream
129
+ */
130
+ putStream?(key: string, stream: ReadableStream<Uint8Array>): Promise<void>;
131
+ /**
132
+ * Reads data as a readable stream.
133
+ *
134
+ * 串流讀取檔案(可選實作)
135
+ * Useful for handling large files without loading entire content into memory.
136
+ *
137
+ * @param key - Unique identifier or path for the file
138
+ * @returns A readable stream of the file content, or null if the key does not exist
139
+ */
140
+ getStream?(key: string): Promise<ReadableStream<Uint8Array> | null>;
68
141
  }
69
142
  /**
143
+ * StorageMetadata represents technical details of a stored file.
144
+ *
70
145
  * 檔案元資料
71
146
  * @public
72
147
  */
@@ -81,8 +156,28 @@ interface StorageMetadata {
81
156
  lastModified?: Date;
82
157
  /** ETag (用於快取驗證) */
83
158
  etag?: string;
159
+ /** 自定義 Metadata (S3 風格) */
160
+ customMetadata?: Record<string, string>;
84
161
  }
85
162
  /**
163
+ * PutOptions provides additional options for file uploads.
164
+ *
165
+ * 檔案上傳選項
166
+ * @public
167
+ */
168
+ interface PutOptions {
169
+ /** Content-Type header (MIME type) */
170
+ contentType?: string;
171
+ /** 自定義 metadata (key-value pairs) */
172
+ metadata?: Record<string, string>;
173
+ /** Cache-Control header (用於 CDN) */
174
+ cacheControl?: string;
175
+ /** Content-Disposition header (下載檔名控制) */
176
+ contentDisposition?: string;
177
+ }
178
+ /**
179
+ * StorageItem represents an entry in a file listing.
180
+ *
86
181
  * 檔案清單項目
87
182
  * @public
88
183
  */
@@ -96,31 +191,81 @@ interface StorageItem {
96
191
  /** 最後修改時間 */
97
192
  lastModified?: Date;
98
193
  }
194
+ /**
195
+ * ListOptions provides pagination and filtering options for file listing.
196
+ *
197
+ * 列舉選項(分頁與過濾)
198
+ * @public
199
+ */
200
+ interface ListOptions {
201
+ /** 最大回傳數量(預設: 1000) */
202
+ maxResults?: number;
203
+ /** 分頁游標(繼續上次的列舉) */
204
+ cursor?: string;
205
+ /** 是否包含子目錄(預設: true) */
206
+ recursive?: boolean;
207
+ }
208
+ /**
209
+ * ListResult contains paginated file listing results.
210
+ *
211
+ * 分頁列舉結果
212
+ * @public
213
+ */
214
+ interface ListResult {
215
+ /** 檔案清單項目 */
216
+ items: StorageItem[];
217
+ /** 下一頁游標(null 表示沒有更多結果) */
218
+ nextCursor: string | null;
219
+ /** 是否還有更多結果 */
220
+ hasMore: boolean;
221
+ /** 本次回傳的項目數量 */
222
+ count: number;
223
+ }
99
224
 
100
225
  /**
226
+ * OrbitNebulaStoreConfig defines the configuration for a single storage disk.
227
+ *
228
+ * It supports multiple driver types, each with its own specific configuration requirements.
229
+ *
101
230
  * 單一磁碟配置
102
231
  * @public
103
232
  */
104
233
  type OrbitNebulaStoreConfig = {
234
+ /** Local filesystem driver */
105
235
  driver: 'local';
236
+ /** Root directory for file storage */
106
237
  root: string;
238
+ /** Base URL for generating public links */
107
239
  baseUrl?: string;
108
240
  } | {
241
+ /** Volatile in-memory driver */
109
242
  driver: 'memory';
110
243
  } | {
244
+ /** No-op driver for disabling storage */
111
245
  driver: 'null';
112
246
  } | {
247
+ /** Custom driver implementation */
113
248
  driver: 'custom';
249
+ /** The custom store instance */
114
250
  store: StorageStore;
115
251
  };
116
252
  /**
253
+ * OrbitNebulaOptions defines the global configuration for the Nebula orbit.
254
+ *
255
+ * It allows configuring multiple disks, the default disk, and how the service
256
+ * is exposed in the Gravito context.
257
+ *
117
258
  * OrbitNebula 配置選項
118
259
  * @public
119
260
  */
120
261
  interface OrbitNebulaOptions {
262
+ /** The name of the default disk to use when none is specified */
121
263
  default?: string;
264
+ /** The key used to expose the StorageManager in the context (default: 'storage') */
122
265
  exposeAs?: string;
266
+ /** A map of disk names to their respective configurations */
123
267
  disks?: Record<string, OrbitNebulaStoreConfig>;
268
+ /** Execution mode for storage hooks */
124
269
  eventsMode?: 'sync' | 'async';
125
270
  /** @deprecated 使用 disks.local 替代 */
126
271
  local?: {
@@ -131,30 +276,184 @@ interface OrbitNebulaOptions {
131
276
  provider?: StorageStore;
132
277
  }
133
278
  /**
279
+ * StorageHooks defines the internal interface for triggering Gravito hooks.
280
+ *
134
281
  * Hooks 回調介面
135
282
  * @internal
136
283
  */
137
284
  interface StorageHooks {
285
+ /** Applies a filter hook to a value */
138
286
  applyFilter<T>(hook: string, value: T, context?: Record<string, unknown>): Promise<T>;
287
+ /** Executes an action hook */
139
288
  doAction(hook: string, context?: Record<string, unknown>): Promise<void>;
140
289
  }
141
290
 
291
+ /**
292
+ * StorageRepository wraps a StorageStore to provide high-level features.
293
+ *
294
+ * It implements the Repository pattern, adding cross-cutting concerns like
295
+ * hooks (filters and actions) to the raw store operations. This allows for
296
+ * global behaviors like image resizing on upload or logging on deletion.
297
+ *
298
+ * @public
299
+ */
142
300
  declare class StorageRepository {
143
301
  private readonly store;
144
302
  private readonly hooks?;
145
303
  constructor(store: StorageStore, hooks?: StorageHooks | undefined);
146
- put(key: string, data: Blob | Buffer | string): Promise<void>;
304
+ /**
305
+ * Stores content and triggers upload hooks.
306
+ *
307
+ * Applies the `storage:upload` filter to the data before storage and
308
+ * fires the `storage:uploaded` action upon success.
309
+ *
310
+ * @param key - The destination path
311
+ * @param data - The content to store
312
+ * @param options - Optional upload options (content-type, metadata, cache-control, etc.)
313
+ * @throws {Error} If the underlying store fails to persist the data
314
+ */
315
+ put(key: string, data: Blob | Buffer | string, options?: PutOptions): Promise<void>;
316
+ /**
317
+ * Retrieves content and triggers hit/miss hooks.
318
+ *
319
+ * Fires `storage:hit` if the file exists, or `storage:miss` otherwise.
320
+ *
321
+ * @param key - The path of the file to retrieve
322
+ * @returns The file content as a Blob, or null if not found
323
+ */
147
324
  get(key: string): Promise<Blob | null>;
325
+ /**
326
+ * Deletes a file and triggers the deleted hook.
327
+ *
328
+ * Fires `storage:deleted` only if the file was actually removed.
329
+ *
330
+ * @param key - The path of the file to delete
331
+ * @returns True if deleted, false if file didn't exist
332
+ */
148
333
  delete(key: string): Promise<boolean>;
334
+ /**
335
+ * Checks for file existence.
336
+ *
337
+ * @param key - The path to check
338
+ * @returns True if exists, false otherwise
339
+ */
149
340
  exists(key: string): Promise<boolean>;
341
+ /**
342
+ * Copies a file and triggers the copied hook.
343
+ *
344
+ * Fires `storage:copied` upon successful completion.
345
+ *
346
+ * @param from - Source path
347
+ * @param to - Destination path
348
+ * @throws {Error} If source missing or operation fails
349
+ */
150
350
  copy(from: string, to: string): Promise<void>;
351
+ /**
352
+ * Moves a file and triggers the moved hook.
353
+ *
354
+ * Fires `storage:moved` upon successful completion.
355
+ *
356
+ * @param from - Current path
357
+ * @param to - New path
358
+ * @throws {Error} If source missing or operation fails
359
+ */
151
360
  move(from: string, to: string): Promise<void>;
361
+ /**
362
+ * Lists files using an async generator.
363
+ *
364
+ * @param prefix - Path prefix to filter by
365
+ * @returns Async iterable of storage items
366
+ * @throws {Error} If the underlying driver does not support listing
367
+ */
152
368
  list(prefix?: string): AsyncIterable<StorageItem>;
369
+ /**
370
+ * Lists files with pagination support.
371
+ *
372
+ * 分頁列舉檔案
373
+ * Recommended for large storage backends to prevent OOM.
374
+ * Provides cursor-based pagination for efficient enumeration.
375
+ *
376
+ * @param prefix - Path prefix to filter by
377
+ * @param options - Pagination and filtering options
378
+ * @returns Paginated list result with cursor for next page
379
+ * @throws {Error} If the underlying driver does not support paginated listing
380
+ */
381
+ listPaginated(prefix: string, options?: ListOptions): Promise<ListResult>;
382
+ /**
383
+ * Retrieves file metadata.
384
+ *
385
+ * @param key - Path of the file
386
+ * @returns Metadata object or null if not found
387
+ */
153
388
  getMetadata(key: string): Promise<StorageMetadata | null>;
389
+ /**
390
+ * Updates custom metadata for a file.
391
+ *
392
+ * 更新自定義 Metadata
393
+ *
394
+ * @param key - Path of the file
395
+ * @param metadata - Custom metadata to set
396
+ * @throws {Error} If the underlying driver does not support metadata updates
397
+ */
398
+ setMetadata(key: string, metadata: Record<string, string>): Promise<void>;
399
+ /**
400
+ * Generates a public URL.
401
+ *
402
+ * @param key - Path of the file
403
+ * @returns URL string
404
+ */
154
405
  getUrl(key: string): string;
406
+ /**
407
+ * Generates a temporary signed URL.
408
+ *
409
+ * @param key - Path of the file
410
+ * @param expiresIn - Expiration in seconds
411
+ * @returns Signed URL string
412
+ * @throws {Error} If the underlying driver does not support signed URLs
413
+ */
155
414
  getSignedUrl(key: string, expiresIn: number): Promise<string>;
415
+ /**
416
+ * Stores content from a readable stream and triggers upload hooks.
417
+ *
418
+ * 串流上傳並觸發 hooks
419
+ * Useful for handling large files without loading entire content into memory.
420
+ * Applies the `storage:upload` filter and fires the `storage:uploaded` action.
421
+ *
422
+ * @param key - The destination path
423
+ * @param stream - Readable stream containing the data
424
+ * @throws {Error} If the underlying driver does not support stream writing
425
+ */
426
+ putStream(key: string, stream: ReadableStream<Uint8Array>): Promise<void>;
427
+ /**
428
+ * Retrieves content as a readable stream and triggers hit/miss hooks.
429
+ *
430
+ * 串流讀取並觸發 hooks
431
+ * Useful for handling large files without loading entire content into memory.
432
+ * Fires `storage:hit` if the file exists, or `storage:miss` otherwise.
433
+ *
434
+ * @param key - Path of the file
435
+ * @returns Readable stream of file content, or null if not found
436
+ * @throws {Error} If the underlying driver does not support stream reading
437
+ */
438
+ getStream(key: string): Promise<ReadableStream<Uint8Array> | null>;
156
439
  }
157
440
 
441
+ /**
442
+ * StorageManager acts as the central hub for multi-disk storage management.
443
+ *
444
+ * It implements the Manager pattern to coordinate multiple storage repositories (disks).
445
+ * It provides a unified API that delegates to the default disk or a specifically
446
+ * requested disk. It also handles the lazy initialization of storage stores.
447
+ *
448
+ * @example
449
+ * ```typescript
450
+ * const manager = new StorageManager(factory, { default: 'local' });
451
+ * await manager.put('hello.txt', 'world'); // Uses default 'local' disk
452
+ * await manager.disk('s3').put('backup.zip', data); // Uses 's3' disk
453
+ * ```
454
+ *
455
+ * @public
456
+ */
158
457
  declare class StorageManager {
159
458
  private readonly storeFactory;
160
459
  private readonly options;
@@ -165,62 +464,439 @@ declare class StorageManager {
165
464
  default: string;
166
465
  prefix?: string;
167
466
  }, hooks?: StorageHooks | undefined);
467
+ /**
468
+ * Accesses a specific storage disk by name.
469
+ *
470
+ * If no name is provided, the default disk configured during initialization is returned.
471
+ * Repositories are lazily initialized and cached for subsequent access.
472
+ *
473
+ * @param name - The unique identifier of the disk to access
474
+ * @returns A repository instance for the requested disk
475
+ * @throws {Error} If the requested disk is not configured or factory fails
476
+ */
168
477
  disk(name?: string): StorageRepository;
169
478
  private resolveStore;
170
- put(key: string, data: Blob | Buffer | string): Promise<void>;
479
+ /**
480
+ * Stores content at the specified key on the default disk.
481
+ *
482
+ * @param key - The destination path/identifier
483
+ * @param data - The content to store
484
+ * @param options - Optional upload options (content-type, metadata, cache-control, etc.)
485
+ * @returns A promise that resolves when the operation completes
486
+ * @throws {Error} If the storage operation fails on the default disk
487
+ */
488
+ put(key: string, data: Blob | Buffer | string, options?: PutOptions): Promise<void>;
489
+ /**
490
+ * Retrieves content from the specified key on the default disk.
491
+ *
492
+ * @param key - The path/identifier of the file to retrieve
493
+ * @returns The file content as a Blob, or null if not found
494
+ */
171
495
  get(key: string): Promise<Blob | null>;
496
+ /**
497
+ * Removes a file from the default disk.
498
+ *
499
+ * @param key - The path/identifier of the file to delete
500
+ * @returns True if the file was deleted, false if it didn't exist
501
+ */
172
502
  delete(key: string): Promise<boolean>;
503
+ /**
504
+ * Checks if a file exists on the default disk.
505
+ *
506
+ * @param key - The path/identifier to check
507
+ * @returns True if the file exists, false otherwise
508
+ */
173
509
  exists(key: string): Promise<boolean>;
510
+ /**
511
+ * Creates a copy of a file on the default disk.
512
+ *
513
+ * @param from - The source path
514
+ * @param to - The destination path
515
+ * @throws {Error} If the source file does not exist or copy fails
516
+ */
174
517
  copy(from: string, to: string): Promise<void>;
518
+ /**
519
+ * Moves or renames a file on the default disk.
520
+ *
521
+ * @param from - The current path
522
+ * @param to - The new path
523
+ * @throws {Error} If the source file does not exist or move fails
524
+ */
175
525
  move(from: string, to: string): Promise<void>;
526
+ /**
527
+ * Lists files and directories under a given prefix on the default disk.
528
+ *
529
+ * @param prefix - The directory or path prefix to list
530
+ * @returns An async iterable of storage items
531
+ * @throws {Error} If the default disk driver does not support listing
532
+ */
176
533
  list(prefix?: string): AsyncIterable<StorageItem>;
534
+ /**
535
+ * Retrieves metadata for a specific file on the default disk.
536
+ *
537
+ * @param key - The path/identifier of the file
538
+ * @returns Metadata object or null if file not found
539
+ */
177
540
  getMetadata(key: string): Promise<StorageMetadata | null>;
541
+ /**
542
+ * Generates a public URL for a file on the default disk.
543
+ *
544
+ * @param key - The path/identifier of the file
545
+ * @returns The absolute or relative URL string
546
+ */
178
547
  getUrl(key: string): string;
548
+ /**
549
+ * Generates a temporary, signed URL for a file on the default disk.
550
+ *
551
+ * @param key - The path/identifier of the file
552
+ * @param expiresIn - Expiration time in seconds
553
+ * @returns A promise resolving to the signed URL string
554
+ * @throws {Error} If the default disk driver does not support signed URLs
555
+ */
179
556
  getSignedUrl(key: string, expiresIn: number): Promise<string>;
557
+ /**
558
+ * Stores content from a readable stream on the default disk.
559
+ *
560
+ * 串流上傳到預設磁碟
561
+ * Useful for handling large files without loading entire content into memory.
562
+ *
563
+ * @param key - The destination path
564
+ * @param stream - Readable stream containing the data
565
+ * @throws {Error} If the default disk driver does not support stream writing
566
+ */
567
+ putStream(key: string, stream: ReadableStream<Uint8Array>): Promise<void>;
568
+ /**
569
+ * Retrieves content as a readable stream from the default disk.
570
+ *
571
+ * 從預設磁碟串流讀取
572
+ * Useful for handling large files without loading entire content into memory.
573
+ *
574
+ * @param key - The path/identifier of the file
575
+ * @returns Readable stream of file content, or null if not found
576
+ * @throws {Error} If the default disk driver does not support stream reading
577
+ */
578
+ getStream(key: string): Promise<ReadableStream<Uint8Array> | null>;
579
+ /**
580
+ * Lists files with pagination support on the default disk.
581
+ *
582
+ * 在預設磁碟上分頁列舉檔案
583
+ * Recommended for large storage backends to prevent OOM.
584
+ *
585
+ * @param prefix - Path prefix to filter by
586
+ * @param options - Pagination and filtering options
587
+ * @returns Paginated list result with cursor for next page
588
+ * @throws {Error} If the default disk driver does not support paginated listing
589
+ */
590
+ listPaginated(prefix: string, options?: ListOptions): Promise<ListResult>;
591
+ /**
592
+ * Updates custom metadata for a file on the default disk.
593
+ *
594
+ * 更新預設磁碟上檔案的自定義 Metadata
595
+ *
596
+ * @param key - The path/identifier of the file
597
+ * @param metadata - Custom metadata to set
598
+ * @throws {Error} If the default disk driver does not support metadata updates
599
+ */
600
+ setMetadata(key: string, metadata: Record<string, string>): Promise<void>;
180
601
  }
181
602
 
603
+ /**
604
+ * LocalStore implements storage on the local filesystem.
605
+ *
606
+ * It uses the Gravito RuntimeAdapter to perform file operations, ensuring
607
+ * compatibility across different environments (Node.js, Bun, etc.). It includes
608
+ * built-in protection against path traversal attacks.
609
+ *
610
+ * @example
611
+ * ```typescript
612
+ * const store = new LocalStore('./uploads', '/public/files');
613
+ * await store.put('avatars/user.png', data);
614
+ * ```
615
+ *
616
+ * @public
617
+ */
182
618
  declare class LocalStore implements StorageStore {
183
619
  private readonly rootDir;
184
620
  private readonly baseUrl;
185
621
  private runtime;
186
622
  constructor(rootDir: string, baseUrl?: string);
187
- put(key: string, data: Blob | Buffer | string): Promise<void>;
623
+ /**
624
+ * Writes data to a file on the local disk.
625
+ *
626
+ * Automatically creates parent directories if they don't exist.
627
+ *
628
+ * @param key - Relative path from the root directory
629
+ * @param data - Content to write
630
+ * @param options - Optional upload options (note: customMetadata not persisted in LocalStore)
631
+ * @throws {Error} If the key is invalid or path is outside root
632
+ */
633
+ put(key: string, data: Blob | Buffer | string, options?: PutOptions): Promise<void>;
634
+ /**
635
+ * Reads a file from the local disk as a Blob.
636
+ *
637
+ * @param key - Relative path from the root directory
638
+ * @returns File content as Blob, or null if not found
639
+ * @throws {Error} If the key is invalid or path is outside root
640
+ */
188
641
  get(key: string): Promise<Blob | null>;
642
+ /**
643
+ * Deletes a file from the local disk.
644
+ *
645
+ * @param key - Relative path from the root directory
646
+ * @returns True if deleted, false if file didn't exist
647
+ * @throws {Error} If the key is invalid or path is outside root
648
+ */
189
649
  delete(key: string): Promise<boolean>;
650
+ /**
651
+ * Checks if a file exists on the local disk.
652
+ *
653
+ * @param key - Relative path from the root directory
654
+ * @returns True if exists, false otherwise
655
+ */
190
656
  exists(key: string): Promise<boolean>;
657
+ /**
658
+ * Copies a file on the local disk.
659
+ *
660
+ * @param from - Source relative path
661
+ * @param to - Destination relative path
662
+ * @throws {Error} If source missing or operation fails
663
+ */
191
664
  copy(from: string, to: string): Promise<void>;
665
+ /**
666
+ * Moves a file on the local disk.
667
+ *
668
+ * @param from - Current relative path
669
+ * @param to - New relative path
670
+ * @throws {Error} If source missing or operation fails
671
+ */
192
672
  move(from: string, to: string): Promise<void>;
193
- list(prefix?: string): AsyncIterable<StorageItem>;
673
+ /**
674
+ * @internal
675
+ * @throws {Error} Always, as not yet implemented
676
+ */
677
+ list(_prefix?: string): AsyncIterable<StorageItem>;
678
+ /**
679
+ * Retrieves file metadata from the local filesystem.
680
+ *
681
+ * @param key - Relative path from the root directory
682
+ * @returns Metadata object or null if not found
683
+ */
194
684
  getMetadata(key: string): Promise<StorageMetadata | null>;
685
+ /**
686
+ * Generates a public URL based on the configured base URL.
687
+ *
688
+ * @param key - Relative path from the root directory
689
+ * @returns URL string
690
+ */
195
691
  getUrl(key: string): string;
692
+ /**
693
+ * Writes data from a readable stream to a file on the local disk.
694
+ *
695
+ * 串流寫入檔案
696
+ * Automatically creates parent directories if they don't exist.
697
+ * Useful for handling large files without loading entire content into memory.
698
+ *
699
+ * @param key - Relative path from the root directory
700
+ * @param stream - Readable stream containing the data
701
+ * @throws {Error} If the key is invalid or path is outside root
702
+ */
703
+ putStream(key: string, stream: ReadableStream<Uint8Array>): Promise<void>;
704
+ /**
705
+ * Reads a file from the local disk as a readable stream.
706
+ *
707
+ * 串流讀取檔案
708
+ * Useful for handling large files without loading entire content into memory.
709
+ *
710
+ * @param key - Relative path from the root directory
711
+ * @returns Readable stream of file content, or null if not found
712
+ * @throws {Error} If the key is invalid or path is outside root
713
+ */
714
+ getStream(key: string): Promise<ReadableStream<Uint8Array> | null>;
196
715
  private normalizeKey;
197
716
  private resolvePath;
198
717
  private ensureDirectory;
199
718
  private guessMimeType;
200
719
  }
201
720
 
721
+ /**
722
+ * MemoryStore implements a volatile, in-memory storage backend.
723
+ *
724
+ * It is primarily intended for testing, caching, or temporary data that
725
+ * does not need to persist across application restarts. All data is stored
726
+ * in a Map as Blobs.
727
+ *
728
+ * @example
729
+ * ```typescript
730
+ * const store = new MemoryStore();
731
+ * await store.put('test.txt', 'hello');
732
+ * ```
733
+ *
734
+ * @public
735
+ */
202
736
  declare class MemoryStore implements StorageStore {
203
737
  private files;
204
- put(key: string, data: Blob | Buffer | string): Promise<void>;
738
+ /**
739
+ * Stores data in the internal Map.
740
+ *
741
+ * Converts input data to a Blob before storage.
742
+ *
743
+ * @param key - Unique identifier for the file
744
+ * @param data - Content to store
745
+ * @param options - Optional upload options (content-type, metadata, etc.)
746
+ */
747
+ put(key: string, data: Blob | Buffer | string, options?: PutOptions): Promise<void>;
748
+ /**
749
+ * Retrieves a Blob from the internal Map.
750
+ *
751
+ * @param key - Unique identifier for the file
752
+ * @returns The Blob content, or null if not found
753
+ */
205
754
  get(key: string): Promise<Blob | null>;
755
+ /**
756
+ * Removes a file from memory.
757
+ *
758
+ * @param key - Unique identifier for the file
759
+ * @returns True if deleted, false if not found
760
+ */
206
761
  delete(key: string): Promise<boolean>;
762
+ /**
763
+ * Checks if a key exists in the internal Map.
764
+ *
765
+ * @param key - Unique identifier to check
766
+ * @returns True if exists, false otherwise
767
+ */
207
768
  exists(key: string): Promise<boolean>;
769
+ /**
770
+ * Copies a file within memory.
771
+ *
772
+ * @param from - Source key
773
+ * @param to - Destination key
774
+ * @throws {Error} If source file is missing
775
+ */
208
776
  copy(from: string, to: string): Promise<void>;
777
+ /**
778
+ * Moves a file within memory.
779
+ *
780
+ * @param from - Current key
781
+ * @param to - New key
782
+ * @throws {Error} If source file is missing
783
+ */
209
784
  move(from: string, to: string): Promise<void>;
785
+ /**
786
+ * Lists all files currently in memory.
787
+ *
788
+ * @param prefix - Optional key prefix to filter by
789
+ * @returns Async iterable of storage items
790
+ */
210
791
  list(prefix?: string): AsyncIterable<StorageItem>;
792
+ /**
793
+ * Retrieves metadata for an in-memory file.
794
+ *
795
+ * @param key - Unique identifier for the file
796
+ * @returns Metadata object or null if not found
797
+ */
211
798
  getMetadata(key: string): Promise<StorageMetadata | null>;
799
+ /**
800
+ * Generates a dummy URL for the in-memory file.
801
+ *
802
+ * @param key - Unique identifier for the file
803
+ * @returns A string starting with /memory/
804
+ */
212
805
  getUrl(key: string): string;
806
+ /**
807
+ * Stores data from a readable stream in memory.
808
+ *
809
+ * 串流寫入記憶體
810
+ * Reads the entire stream into memory before storing.
811
+ *
812
+ * @param key - Unique identifier for the file
813
+ * @param stream - Readable stream containing the data
814
+ */
815
+ putStream(key: string, stream: ReadableStream<Uint8Array>): Promise<void>;
816
+ /**
817
+ * Reads an in-memory file as a readable stream.
818
+ *
819
+ * 串流讀取記憶體檔案
820
+ *
821
+ * @param key - Unique identifier for the file
822
+ * @returns Readable stream of file content, or null if not found
823
+ */
824
+ getStream(key: string): Promise<ReadableStream<Uint8Array> | null>;
825
+ /**
826
+ * Updates custom metadata for an in-memory file.
827
+ *
828
+ * 更新自定義 Metadata
829
+ *
830
+ * @param key - Unique identifier for the file
831
+ * @param metadata - Custom metadata to set
832
+ * @throws {Error} If file does not exist
833
+ */
834
+ setMetadata(key: string, metadata: Record<string, string>): Promise<void>;
835
+ /**
836
+ * Lists files with pagination support.
837
+ *
838
+ * 分頁列舉記憶體中的檔案
839
+ * Provides cursor-based pagination for consistent API with other drivers.
840
+ *
841
+ * @param prefix - Key prefix to filter by
842
+ * @param options - Pagination and filtering options
843
+ * @returns Paginated list result
844
+ */
845
+ listPaginated(prefix?: string, options?: ListOptions): Promise<ListResult>;
213
846
  }
214
847
 
848
+ /**
849
+ * NullStore implements the Null Object pattern for storage.
850
+ *
851
+ * It provides a no-op implementation of the StorageStore interface. All write
852
+ * operations succeed silently without doing anything, and all read operations
853
+ * return null or empty results. This is useful for disabling storage without
854
+ * changing application logic.
855
+ *
856
+ * @example
857
+ * ```typescript
858
+ * const store = new NullStore();
859
+ * await store.put('anything', 'data'); // Does nothing
860
+ * ```
861
+ *
862
+ * @public
863
+ */
215
864
  declare class NullStore implements StorageStore {
865
+ /**
866
+ * No-op: does not store any data.
867
+ */
216
868
  put(_key: string, _data: Blob | Buffer | string): Promise<void>;
869
+ /**
870
+ * Always returns null.
871
+ */
217
872
  get(_key: string): Promise<Blob | null>;
873
+ /**
874
+ * Always returns false.
875
+ */
218
876
  delete(_key: string): Promise<boolean>;
877
+ /**
878
+ * Always returns false.
879
+ */
219
880
  exists(_key: string): Promise<boolean>;
881
+ /**
882
+ * No-op: does not copy anything.
883
+ */
220
884
  copy(_from: string, _to: string): Promise<void>;
885
+ /**
886
+ * No-op: does not move anything.
887
+ */
221
888
  move(_from: string, _to: string): Promise<void>;
889
+ /**
890
+ * Always yields nothing.
891
+ */
222
892
  list(_prefix?: string): AsyncIterable<StorageItem>;
893
+ /**
894
+ * Always returns null.
895
+ */
223
896
  getMetadata(_key: string): Promise<StorageMetadata | null>;
897
+ /**
898
+ * Generates a dummy URL starting with /null/.
899
+ */
224
900
  getUrl(key: string): string;
225
901
  }
226
902
 
@@ -232,7 +908,9 @@ type OrbitStorageOptions = OrbitNebulaOptions;
232
908
  /**
233
909
  * OrbitNebula provides a unified file storage abstraction for Gravito.
234
910
  *
235
- * It supports multiple backends (local, S3, etc.) via the StorageManager.
911
+ * It implements the Galaxy Architecture's Orbit pattern, acting as a bridge between
912
+ * the PlanetCore micro-kernel and various storage backends. It manages the lifecycle
913
+ * of the StorageManager and integrates with the core's hook system.
236
914
  *
237
915
  * @example
238
916
  * ```typescript
@@ -246,33 +924,51 @@ type OrbitStorageOptions = OrbitNebulaOptions;
246
924
  * ```
247
925
  *
248
926
  * @public
249
- * @since 3.0.0 (Refactored in 4.0.0)
250
927
  */
251
928
  declare class OrbitNebula implements GravitoOrbit {
252
929
  private options?;
253
930
  private manager?;
254
931
  constructor(options?: OrbitNebulaOptions | undefined);
255
932
  /**
256
- * Install storage service into PlanetCore.
933
+ * Bootstraps the storage service and registers it with PlanetCore.
934
+ *
935
+ * This method initializes the StorageManager, configures the default disk,
936
+ * and registers the storage service in the IoC container and middleware.
257
937
  *
258
- * @param core - The PlanetCore instance.
938
+ * @param core - The PlanetCore instance to install into
939
+ * @throws {Error} If configuration is missing or default disk cannot be initialized
259
940
  */
260
941
  install(core: PlanetCore): void;
261
942
  /**
262
- * Get the installed StorageManager instance.
943
+ * Retrieves the initialized StorageManager instance.
263
944
  *
264
- * @returns The StorageManager instance.
265
- * @throws {Error} If not installed.
945
+ * Use this to access storage operations directly from the orbit instance
946
+ * after it has been installed.
947
+ *
948
+ * @returns The active StorageManager instance
949
+ * @throws {Error} If called before the orbit is installed
266
950
  */
267
951
  getStorage(): StorageManager;
268
952
  private createStoreFactory;
269
953
  }
270
954
  /**
271
- * Functional API for installing OrbitNebula.
955
+ * Factory function for quick OrbitNebula installation.
956
+ *
957
+ * Provides a functional approach to adding storage capabilities to a Gravito application.
272
958
  *
273
- * @param core - The PlanetCore instance.
274
- * @param options - Storage options.
275
- * @returns The StorageManager instance.
959
+ * @param core - The PlanetCore instance
960
+ * @param options - Storage configuration options
961
+ * @returns The initialized StorageManager instance
962
+ *
963
+ * @example
964
+ * ```typescript
965
+ * const storage = orbitStorage(core, {
966
+ * default: 'local',
967
+ * disks: {
968
+ * local: { driver: 'local', root: './uploads' }
969
+ * }
970
+ * });
971
+ * ```
276
972
  */
277
973
  declare function orbitStorage(core: PlanetCore, options: OrbitNebulaOptions): StorageManager;
278
974
  /** @deprecated Use OrbitNebula instead */
@@ -284,4 +980,4 @@ declare module '@gravito/core' {
284
980
  }
285
981
  }
286
982
 
287
- export { LocalStore as LocalStorageProvider, LocalStore, MemoryStore, NullStore, OrbitNebula, type OrbitNebulaOptions, type OrbitNebulaStoreConfig, OrbitStorage, type OrbitStorageOptions, type StorageHooks, type StorageItem, StorageManager, type StorageMetadata, type StorageProvider, StorageRepository, type StorageStore, orbitStorage as default };
983
+ export { type ListOptions, type ListResult, LocalStore as LocalStorageProvider, LocalStore, MemoryStore, NullStore, OrbitNebula, type OrbitNebulaOptions, type OrbitNebulaStoreConfig, OrbitStorage, type OrbitStorageOptions, type PutOptions, type StorageHooks, type StorageItem, StorageManager, type StorageMetadata, type StorageProvider, StorageRepository, type StorageStore, orbitStorage as default };