@h-ai/storage 0.1.0-alpha.67 → 0.1.0-alpha.68

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/browser.d.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  export { ClientDownloadOptions, ClientUploadOptions, UploadProgress, downloadAndSave, downloadWithPresignedUrl, formatFileSize, getFileExtension, getMimeType, uploadWithPresignedUrl } from './client/index.js';
2
2
  import { z } from 'zod';
3
+ export { STORAGE_DELETE_MAX_KEYS, STORAGE_KEY_MAX_BYTES, StorageDeleteKeysSchema, StorageKeyIssue, StorageKeySchema, StoragePrefixSchema, StoragePresignExpiresInSchema, getStorageKeyIssue } from './schemas.js';
3
4
  import * as _h_ai_core from '@h-ai/core';
4
- import { HaiResult } from '@h-ai/core';
5
+ import { HaiResult, HaiError } from '@h-ai/core';
5
6
  import { Buffer } from 'node:buffer';
6
7
 
7
8
  /**
8
- * @h-ai/storage — 错误码 + 配置 Schema
9
+ * @h-ai/storage — 存储配置 Schema
9
10
  * @module storage-config
10
11
  */
11
12
 
@@ -15,13 +16,39 @@ import { Buffer } from 'node:buffer';
15
16
  * 支持的存储类型:
16
17
  * - `s3` - S3 协议对象存储(兼容 AWS S3、MinIO、RustFS、阿里云 OSS 等)
17
18
  * - `local` - 本地文件存储(仅后端)
19
+ * @example
20
+ * ```ts
21
+ * import { StorageTypeSchema } from '@h-ai/storage'
22
+ *
23
+ * const value = StorageTypeSchema.parse('local')
24
+ * void value
25
+ * ```
18
26
  */
19
27
  declare const StorageTypeSchema: z.ZodEnum<{
20
28
  s3: "s3";
21
29
  local: "local";
22
30
  }>;
23
- /** 存储类型 */
31
+ /**
32
+ * 存储类型
33
+ * @example
34
+ * ```ts
35
+ * import type { StorageType } from '@h-ai/storage'
36
+ *
37
+ * const value: StorageType = 's3'
38
+ * void value
39
+ * ```
40
+ */
24
41
  type StorageType = z.infer<typeof StorageTypeSchema>;
42
+ /**
43
+ * StorageOperationLogConfigSchema 的数据约束与操作契约。
44
+ * @example
45
+ * ```ts
46
+ * import { StorageOperationLogConfigSchema } from '@h-ai/storage'
47
+ *
48
+ * const value = StorageOperationLogConfigSchema.parse({ read: false, write: true, maxLength: 500, level: 'debug' })
49
+ * void value
50
+ * ```
51
+ */
25
52
  declare const StorageOperationLogConfigSchema: z.ZodObject<{
26
53
  read: z.ZodDefault<z.ZodBoolean>;
27
54
  write: z.ZodDefault<z.ZodBoolean>;
@@ -32,12 +59,29 @@ declare const StorageOperationLogConfigSchema: z.ZodObject<{
32
59
  trace: "trace";
33
60
  }>>;
34
61
  }, z.core.$strip>;
62
+ /**
63
+ * StorageOperationLogConfig 的数据约束与操作契约。
64
+ * @example
65
+ * ```ts
66
+ * import { StorageOperationLogConfigSchema, type StorageOperationLogConfig } from '@h-ai/storage'
67
+ *
68
+ * const value: StorageOperationLogConfig = StorageOperationLogConfigSchema.parse({ read: false, write: true, maxLength: 500, level: 'debug' })
69
+ * void value
70
+ * ```
71
+ */
35
72
  type StorageOperationLogConfig = z.infer<typeof StorageOperationLogConfigSchema>;
36
73
  /**
37
74
  * S3 存储配置 Schema
38
75
  *
39
76
  * 支持标准 AWS S3 以及兼容 S3 协议的存储服务(MinIO、RustFS、阿里云 OSS 等)。
40
77
  * 必填字段:bucket、region、accessKeyId、secretAccessKey。
78
+ * @example
79
+ * ```ts
80
+ * import { S3ConfigSchema } from '@h-ai/storage'
81
+ *
82
+ * const value = S3ConfigSchema.parse({ type: 's3', bucket: 'uploads', region: 'us-east-1', accessKeyId: process.env.HAI_STORAGE_ACCESS_KEY_ID, secretAccessKey: process.env.HAI_STORAGE_SECRET_ACCESS_KEY })
83
+ * void value
84
+ * ```
41
85
  */
42
86
  declare const S3ConfigSchema: z.ZodObject<{
43
87
  operationLog: z.ZodOptional<z.ZodObject<{
@@ -60,12 +104,28 @@ declare const S3ConfigSchema: z.ZodObject<{
60
104
  prefix: z.ZodDefault<z.ZodString>;
61
105
  publicUrl: z.ZodOptional<z.ZodString>;
62
106
  }, z.core.$strip>;
63
- /** S3 配置类型(parse 后,所有字段已填充默认值) */
107
+ /**
108
+ * S3 配置类型(parse 后,带默认值的字段已填充,optional 字段仍可缺省)
109
+ * @example
110
+ * ```ts
111
+ * import { S3ConfigSchema, type S3Config } from '@h-ai/storage'
112
+ *
113
+ * const value: S3Config = S3ConfigSchema.parse({ type: 's3', bucket: 'uploads', region: 'us-east-1', accessKeyId: process.env.HAI_STORAGE_ACCESS_KEY_ID, secretAccessKey: process.env.HAI_STORAGE_SECRET_ACCESS_KEY })
114
+ * void value
115
+ * ```
116
+ */
64
117
  type S3Config = z.infer<typeof S3ConfigSchema>;
65
118
  /**
66
119
  * 本地存储配置 Schema
67
120
  *
68
121
  * 基于本地文件系统,仅后端可用。必填字段:root。
122
+ * @example
123
+ * ```ts
124
+ * import { LocalConfigSchema } from '@h-ai/storage'
125
+ *
126
+ * const value = LocalConfigSchema.parse({ type: 'local', root: './data/uploads' })
127
+ * void value
128
+ * ```
69
129
  */
70
130
  declare const LocalConfigSchema: z.ZodObject<{
71
131
  operationLog: z.ZodOptional<z.ZodObject<{
@@ -83,40 +143,27 @@ declare const LocalConfigSchema: z.ZodObject<{
83
143
  directoryMode: z.ZodDefault<z.ZodNumber>;
84
144
  fileMode: z.ZodDefault<z.ZodNumber>;
85
145
  }, z.core.$strip>;
86
- /** 本地配置类型(parse 后,所有字段已填充默认值) */
146
+ /**
147
+ * 本地配置类型(parse 后,带默认值的字段已填充,optional 字段仍可缺省)
148
+ * @example
149
+ * ```ts
150
+ * import { LocalConfigSchema, type LocalConfig } from '@h-ai/storage'
151
+ *
152
+ * const value: LocalConfig = LocalConfigSchema.parse({ type: 'local', root: './data/uploads' })
153
+ * void value
154
+ * ```
155
+ */
87
156
  type LocalConfig = z.infer<typeof LocalConfigSchema>;
88
157
  /**
89
158
  * 统一存储配置 Schema
90
159
  *
91
160
  * 支持 S3 和本地文件两种类型的配置验证。
92
- *
93
161
  * @example
94
162
  * ```ts
95
- * // S3 配置
96
- * const s3Config = StorageConfigSchema.parse({
97
- * type: 's3',
98
- * bucket: 'my-bucket',
99
- * region: 'us-east-1',
100
- * accessKeyId: 'AKIAXXXXXXXX',
101
- * secretAccessKey: 'xxxxx'
102
- * })
103
- *
104
- * // MinIO 配置
105
- * const minioConfig = StorageConfigSchema.parse({
106
- * type: 's3',
107
- * bucket: 'my-bucket',
108
- * region: 'us-east-1',
109
- * endpoint: 'http://localhost:9000',
110
- * accessKeyId: 'minioadmin',
111
- * secretAccessKey: 'minioadmin',
112
- * forcePathStyle: true
113
- * })
163
+ * import { StorageConfigSchema } from '@h-ai/storage'
114
164
  *
115
- * // 本地存储配置
116
- * const localConfig = StorageConfigSchema.parse({
117
- * type: 'local',
118
- * root: '/data/uploads'
119
- * })
165
+ * const value = StorageConfigSchema.parse({ type: 'local', root: './data/uploads' })
166
+ * void value
120
167
  * ```
121
168
  */
122
169
  declare const StorageConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -155,21 +202,38 @@ declare const StorageConfigSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
155
202
  directoryMode: z.ZodDefault<z.ZodNumber>;
156
203
  fileMode: z.ZodDefault<z.ZodNumber>;
157
204
  }, z.core.$strip>], "type">;
158
- /** 存储配置类型(parse 后的完整配置) */
205
+ /**
206
+ * 存储配置类型(parse 后的完整配置)
207
+ * @example
208
+ * ```ts
209
+ * import { StorageConfigSchema, type StorageConfig } from '@h-ai/storage'
210
+ *
211
+ * const value: StorageConfig = StorageConfigSchema.parse({ type: 'local', root: './data/uploads' })
212
+ * void value
213
+ * ```
214
+ */
159
215
  type StorageConfig = z.infer<typeof StorageConfigSchema>;
160
- /** 存储配置输入类型(parse 前,允许省略带默认值的字段) */
216
+ /**
217
+ * 存储配置输入类型(parse 前,允许省略带默认值的字段)
218
+ * @example
219
+ * ```ts
220
+ * import type { StorageConfigInput } from '@h-ai/storage'
221
+ *
222
+ * const value: StorageConfigInput = { type: 'local', root: './data/uploads' }
223
+ * void value
224
+ * ```
225
+ */
161
226
  type StorageConfigInput = z.input<typeof StorageConfigSchema>;
162
227
  /**
163
228
  * 签名 URL 配置 Schema
164
229
  *
165
230
  * 用于控制 `storage.presign.getUrl()` 生成的下载签名 URL 参数。
166
- *
167
231
  * @example
168
232
  * ```ts
169
- * const url = await storage.presign.getUrl('report.pdf', {
170
- * expiresIn: 600, // 10 分钟过期
171
- * responseContentDisposition: 'attachment; filename="report.pdf"',
172
- * })
233
+ * import { PresignOptionsSchema } from '@h-ai/storage'
234
+ *
235
+ * const value = PresignOptionsSchema.parse({ expiresIn: 60 })
236
+ * void value
173
237
  * ```
174
238
  */
175
239
  declare const PresignOptionsSchema: z.ZodObject<{
@@ -177,19 +241,27 @@ declare const PresignOptionsSchema: z.ZodObject<{
177
241
  responseContentType: z.ZodOptional<z.ZodString>;
178
242
  responseContentDisposition: z.ZodOptional<z.ZodString>;
179
243
  }, z.core.$strip>;
180
- /** 签名 URL 配置类型(parse 后) */
181
- type PresignOptions = z.infer<typeof PresignOptionsSchema>;
244
+ /**
245
+ * 签名 URL 输入选项,允许省略带默认值的字段。
246
+ * @example
247
+ * ```ts
248
+ * import type { PresignOptions } from '@h-ai/storage'
249
+ *
250
+ * const value: PresignOptions = { expiresIn: 60, responseContentType: 'text/plain' }
251
+ * void value
252
+ * ```
253
+ */
254
+ type PresignOptions = z.input<typeof PresignOptionsSchema>;
182
255
  /**
183
256
  * 上传签名 URL 配置 Schema
184
257
  *
185
258
  * 继承 PresignOptionsSchema 并扩展上传专属参数,用于 `storage.presign.putUrl()`。
186
- *
187
259
  * @example
188
260
  * ```ts
189
- * const url = await storage.presign.putUrl('uploads/avatar.png', {
190
- * contentType: 'image/png',
191
- * expiresIn: 300,
192
- * })
261
+ * import { PresignUploadOptionsSchema } from '@h-ai/storage'
262
+ *
263
+ * const value = PresignUploadOptionsSchema.parse({ contentType: 'text/plain' })
264
+ * void value
193
265
  * ```
194
266
  */
195
267
  declare const PresignUploadOptionsSchema: z.ZodObject<{
@@ -198,9 +270,29 @@ declare const PresignUploadOptionsSchema: z.ZodObject<{
198
270
  responseContentDisposition: z.ZodOptional<z.ZodString>;
199
271
  contentType: z.ZodDefault<z.ZodString>;
200
272
  }, z.core.$strip>;
201
- /** 上传签名 URL 配置类型(parse 后) */
202
- type PresignUploadOptions = z.infer<typeof PresignUploadOptionsSchema>;
273
+ /**
274
+ * 上传签名 URL 输入选项,省略 contentType 时使用 application/octet-stream。
275
+ * @example
276
+ * ```ts
277
+ * import type { PresignUploadOptions } from '@h-ai/storage'
278
+ *
279
+ * const value: PresignUploadOptions = { expiresIn: 60, contentType: 'text/plain' }
280
+ * void value
281
+ * ```
282
+ */
283
+ type PresignUploadOptions = z.input<typeof PresignUploadOptionsSchema>;
203
284
 
285
+ /**
286
+ * HaiStorageError 的数据约束与操作契约。
287
+ * @example
288
+ * ```ts
289
+ * import { HaiStorageError } from '@h-ai/storage'
290
+ * import { err } from '@h-ai/core'
291
+ *
292
+ * const result = err(HaiStorageError.NOT_FOUND, 'File missing')
293
+ * if (!result.success) void result.error.code
294
+ * ```
295
+ */
204
296
  declare const HaiStorageError: {
205
297
  readonly CONNECTION_FAILED: _h_ai_core.HaiErrorDef;
206
298
  readonly OPERATION_FAILED: _h_ai_core.HaiErrorDef;
@@ -219,11 +311,79 @@ declare const HaiStorageError: {
219
311
  readonly DOWNLOAD_FAILED: _h_ai_core.HaiErrorDef;
220
312
  readonly CHECKSUM_FAILED: _h_ai_core.HaiErrorDef;
221
313
  readonly INVALID_CHECKSUM: _h_ai_core.HaiErrorDef;
314
+ readonly UNSUPPORTED_OPERATION: _h_ai_core.HaiErrorDef;
315
+ readonly INVALID_LIST_OPTIONS: _h_ai_core.HaiErrorDef;
316
+ };
317
+ /**
318
+ * 批量删除中未确认完成的一项;key 始终使用调用方视角,不含 Provider prefix。
319
+ * @example
320
+ * ```ts
321
+ * import type { StorageDeleteFailure } from '@h-ai/storage'
322
+ *
323
+ * const value: StorageDeleteFailure = { key: 'private.txt', code: 'AccessDenied', retryable: false, outcome: 'failed' }
324
+ * void value
325
+ * ```
326
+ */
327
+ interface StorageDeleteFailure {
328
+ /** 调用方提交的文件键。 */
329
+ key: string;
330
+ /** 渠道/框架错误标识,不包含渠道原始 Message。 */
331
+ code: string;
332
+ /** 是否属于可重试的瞬时故障;未知结果重试前仍需考虑并发上传/版本语义。 */
333
+ retryable: boolean;
334
+ /** failed 为已知失败,unknown 为已发送但结果未知,notAttempted 为尚未发送。 */
335
+ outcome: 'failed' | 'unknown' | 'notAttempted';
336
+ }
337
+ /**
338
+ * 批量删除进度;任一失败不能宣称全部删除完成。
339
+ * @example
340
+ * ```ts
341
+ * import type { StorageDeleteSummary } from '@h-ai/storage'
342
+ *
343
+ * const value: StorageDeleteSummary = { deletedKeys: ['a.txt'], failures: [] }
344
+ * void value
345
+ * ```
346
+ */
347
+ interface StorageDeleteSummary {
348
+ /** 已确认删除或本来就不存在的唯一文件键。 */
349
+ deletedKeys: string[];
350
+ /** 失败、未知及尚未尝试的唯一文件键。 */
351
+ failures: StorageDeleteFailure[];
352
+ }
353
+ /**
354
+ * 批量删除结果;失败仍遵守 HaiResult,部分进度置于 error.ext.deleteMany。
355
+ * @example
356
+ * ```ts
357
+ * import { storage, type StorageDeleteResult } from '@h-ai/storage'
358
+ *
359
+ * async function remove() {
360
+ * const result: StorageDeleteResult = await storage.file.deleteMany(['a.txt', 'b.txt'])
361
+ * return result.success ? result.data : result.error.ext?.deleteMany
362
+ * }
363
+ * ```
364
+ */
365
+ type StorageDeleteResult = {
366
+ success: true;
367
+ data: StorageDeleteSummary;
368
+ } | {
369
+ success: false;
370
+ error: HaiError & {
371
+ ext?: Record<string, unknown> & {
372
+ deleteMany?: StorageDeleteSummary;
373
+ };
374
+ };
222
375
  };
223
376
  /**
224
377
  * 文件元数据接口
225
378
  *
226
379
  * 表示存储中单个文件的元信息,由 put/head/copy/list 等操作返回。
380
+ * @example
381
+ * ```ts
382
+ * import type { FileMetadata } from '@h-ai/storage'
383
+ *
384
+ * const value: FileMetadata = { key: 'a.txt', size: 5, contentType: 'text/plain', lastModified: new Date() }
385
+ * void value
386
+ * ```
227
387
  */
228
388
  interface FileMetadata {
229
389
  /** 文件键/路径(不含配置 prefix,对用户透明) */
@@ -243,6 +403,13 @@ interface FileMetadata {
243
403
  * 列表选项
244
404
  *
245
405
  * 用于控制 `storage.dir.list()` 的过滤、分页和目录模拟行为。
406
+ * @example
407
+ * ```ts
408
+ * import type { ListOptions } from '@h-ai/storage'
409
+ *
410
+ * const value: ListOptions = { prefix: 'reports/', delimiter: '/', maxKeys: 100 }
411
+ * void value
412
+ * ```
246
413
  */
247
414
  interface ListOptions {
248
415
  /** 前缀过滤(只返回以此前缀开头的文件) */
@@ -250,23 +417,30 @@ interface ListOptions {
250
417
  /**
251
418
  * 分页标记(从上次 ListResult.nextContinuationToken 获取)
252
419
  *
253
- * 注意:本地存储目前不支持此字段,仅 S3 Provider 有效。
420
+ * Local 游标绑定根目录、prefix 和 delimiter,可跨实例使用;不得跨查询或 provider 混用。
254
421
  */
255
422
  continuationToken?: string;
256
- /** 每页最大数量(默认 1000) */
423
+ /** 每页逻辑条目上限(1–1000,默认 1000);files 和 commonPrefixes 合计计数。 */
257
424
  maxKeys?: number;
258
- /** 分隔符(用于模拟目录结构,通常为 '/';传入后子目录作为 commonPrefixes 返回) */
425
+ /** 分隔符,通常为 '/';从 prefix 之后首次出现的位置折叠 commonPrefixes,空字符串表示不折叠。 */
259
426
  delimiter?: string;
260
427
  }
261
428
  /**
262
429
  * 列表结果
263
430
  *
264
431
  * 包含当前页的文件列表、目录前缀、分页信息。
432
+ * @example
433
+ * ```ts
434
+ * import type { ListResult } from '@h-ai/storage'
435
+ *
436
+ * const value: ListResult = { files: [], commonPrefixes: ['reports/'], isTruncated: false }
437
+ * void value
438
+ * ```
265
439
  */
266
440
  interface ListResult {
267
441
  /** 当前页文件元数据列表 */
268
442
  files: FileMetadata[];
269
- /** 公共前缀(使用 delimiter 时由子目录路径组成) */
443
+ /** 公共前缀:由实际匹配文件按 delimiter 折叠,不包含 Local 空物理目录。 */
270
444
  commonPrefixes: string[];
271
445
  /** 下一页标记;无后续页时为 undefined */
272
446
  nextContinuationToken?: string;
@@ -277,6 +451,13 @@ interface ListResult {
277
451
  * 上传选项
278
452
  *
279
453
  * 用于控制 `storage.file.put()` 的元数据与缓存行为。
454
+ * @example
455
+ * ```ts
456
+ * import type { UploadOptions } from '@h-ai/storage'
457
+ *
458
+ * const value: UploadOptions = { ifNoneMatch: '*', contentType: 'text/plain', signal: new AbortController().signal }
459
+ * void value
460
+ * ```
280
461
  */
281
462
  interface UploadOptions {
282
463
  /** 仅当 key 不存在时原子写入;S3 使用标准 If-None-Match,后端不支持时返回错误。 */
@@ -297,6 +478,13 @@ interface UploadOptions {
297
478
  *
298
479
  * 用于控制 `storage.file.get()` 的范围读取。
299
480
  * 两个字段均为字节偏移(含),与 HTTP Range 语义一致。
481
+ * @example
482
+ * ```ts
483
+ * import type { DownloadOptions } from '@h-ai/storage'
484
+ *
485
+ * const value: DownloadOptions = { rangeStart: 0, rangeEnd: 99 }
486
+ * void value
487
+ * ```
300
488
  */
301
489
  interface DownloadOptions {
302
490
  /** 取消读取。 */
@@ -311,6 +499,13 @@ interface DownloadOptions {
311
499
  *
312
500
  * 用于控制 `storage.file.copy()` 的目标文件元数据。
313
501
  * 提供任意字段时,S3 Provider 会使用 MetadataDirective='REPLACE' 覆盖源文件元数据。
502
+ * @example
503
+ * ```ts
504
+ * import type { CopyOptions } from '@h-ai/storage'
505
+ *
506
+ * const value: CopyOptions = { contentType: 'text/plain', metadata: { category: 'reports' } }
507
+ * void value
508
+ * ```
314
509
  */
315
510
  interface CopyOptions {
316
511
  /** 目标文件的内容类型(不指定时继承源文件) */
@@ -318,17 +513,56 @@ interface CopyOptions {
318
513
  /** 目标文件的自定义元数据(不指定时继承源文件) */
319
514
  metadata?: Record<string, string>;
320
515
  }
321
- /** 文件内容;异步字节流支持 Node Readable 等,不将整个文件载入内存。 */
516
+ /**
517
+ * 文件内容;异步字节流支持 Node Readable 等,不将整个文件载入内存。
518
+ * @example
519
+ * ```ts
520
+ * import type { StorageData } from '@h-ai/storage'
521
+ *
522
+ * const value: StorageData = new TextEncoder().encode('hello')
523
+ * void value
524
+ * ```
525
+ */
322
526
  type StorageData = Buffer | Uint8Array | string | AsyncIterable<Uint8Array>;
323
- /** 常见 checksum 算法;MD5/SHA-1 仅用于兼容性完整性校验,不用于安全认证。 */
527
+ /**
528
+ * 常见 checksum 算法;MD5/SHA-1 仅用于兼容性完整性校验,不用于安全认证。
529
+ * @example
530
+ * ```ts
531
+ * import type { ChecksumAlgorithm } from '@h-ai/storage'
532
+ *
533
+ * const value: ChecksumAlgorithm = 'sha256'
534
+ * void value
535
+ * ```
536
+ */
324
537
  type ChecksumAlgorithm = 'sha256' | 'sha384' | 'sha512' | 'sha1' | 'md5';
325
- /** checksum 计算选项;默认 SHA-256、小写 hex。 */
538
+ /**
539
+ * checksum 计算选项;默认 SHA-256、小写 hex。
540
+ * @example
541
+ * ```ts
542
+ * import type { ChecksumOptions } from '@h-ai/storage'
543
+ *
544
+ * const value: ChecksumOptions = { algorithm: 'sha256', encoding: 'hex' }
545
+ * void value
546
+ * ```
547
+ */
326
548
  interface ChecksumOptions {
327
549
  algorithm?: ChecksumAlgorithm;
328
550
  encoding?: 'hex' | 'base64';
329
551
  signal?: AbortSignal;
330
552
  }
331
- /** Node 端无状态 checksum 工具,不依赖 storage.init;流输入仅消费一次。 */
553
+ /**
554
+ * Node 端无状态 checksum 工具,不依赖 storage.init;流输入仅消费一次。
555
+ * @example
556
+ * ```ts
557
+ * import type { ChecksumOperations } from '@h-ai/storage'
558
+ *
559
+ * async function inspect(operations: ChecksumOperations) {
560
+ * const result = await operations.generate('hello')
561
+ * if (!result.success) return result.error.message
562
+ * return result.data
563
+ * }
564
+ * ```
565
+ */
332
566
  interface ChecksumOperations {
333
567
  generate: (data: StorageData, options?: ChecksumOptions) => Promise<HaiResult<string>>;
334
568
  verify: (data: StorageData, expected: string, options?: ChecksumOptions) => Promise<HaiResult<boolean>>;
@@ -337,6 +571,16 @@ interface ChecksumOperations {
337
571
  * 文件操作接口
338
572
  *
339
573
  * 提供文件的读写操作。
574
+ * @example
575
+ * ```ts
576
+ * import type { FileOperations } from '@h-ai/storage'
577
+ *
578
+ * async function inspect(operations: FileOperations) {
579
+ * const result = await operations.getStream('reports/a.txt')
580
+ * if (!result.success) return result.error.message
581
+ * for await (const chunk of result.data) void chunk.byteLength
582
+ * }
583
+ * ```
340
584
  */
341
585
  interface FileOperations {
342
586
  /**
@@ -366,6 +610,7 @@ interface FileOperations {
366
610
  * const result = await storage.file.get('uploads/a.txt')
367
611
  * if (result.success) {
368
612
  * const buffer = result.data
613
+ * void buffer
369
614
  * }
370
615
  * ```
371
616
  */
@@ -373,6 +618,19 @@ interface FileOperations {
373
618
  /**
374
619
  * 读取字节流,支持 Range 与取消;消费方负责及时迭代或关闭流。
375
620
  * @throws 迭代期间的 I/O/取消错误;初始请求失败通过 HaiResult 返回。
621
+ * @example
622
+ * ```ts
623
+ * import { storage } from '@h-ai/storage'
624
+ *
625
+ * const result = await storage.file.getStream('reports/a.txt')
626
+ * if (!result.success) throw new Error(result.error.message)
627
+ * try {
628
+ * for await (const chunk of result.data) void chunk.byteLength
629
+ * } catch (error) {
630
+ * // 初始请求成功后,迭代仍可能因 I/O/取消失败。
631
+ * throw error
632
+ * }
633
+ * ```
376
634
  */
377
635
  getStream: (key: string, options?: DownloadOptions) => Promise<HaiResult<AsyncIterable<Uint8Array>>>;
378
636
  /**
@@ -410,7 +668,10 @@ interface FileOperations {
410
668
  * @returns 删除结果
411
669
  * @example
412
670
  * ```ts
413
- * await storage.file.delete('uploads/a.txt')
671
+ * import { storage } from '@h-ai/storage'
672
+ *
673
+ * const result = await storage.file.delete('uploads/a.txt')
674
+ * if (!result.success) throw new Error(result.error.message)
414
675
  * ```
415
676
  */
416
677
  delete: (key: string) => Promise<HaiResult<void>>;
@@ -418,13 +679,15 @@ interface FileOperations {
418
679
  * 批量删除文件
419
680
  *
420
681
  * @param keys - 文件键/路径列表
421
- * @returns 删除结果
682
+ * @returns 全部成功时返回进度;任一失败时 success=false,进度在 error.ext.deleteMany
422
683
  * @example
423
684
  * ```ts
424
- * await storage.file.deleteMany(['a.txt', 'b.txt'])
685
+ * const result = await storage.file.deleteMany(['a.txt', 'b.txt'])
686
+ * const progress = result.success ? result.data : result.error.ext?.deleteMany
687
+ * void progress
425
688
  * ```
426
689
  */
427
- deleteMany: (keys: string[]) => Promise<HaiResult<void>>;
690
+ deleteMany: (keys: string[]) => Promise<StorageDeleteResult>;
428
691
  /**
429
692
  * 复制文件
430
693
  *
@@ -434,7 +697,11 @@ interface FileOperations {
434
697
  * @returns 目标文件元数据
435
698
  * @example
436
699
  * ```ts
437
- * await storage.file.copy('a.txt', 'b.txt')
700
+ * import { storage } from '@h-ai/storage'
701
+ *
702
+ * const result = await storage.file.copy('a.txt', 'b.txt')
703
+ * if (!result.success) throw new Error(result.error.message)
704
+ * void result.data.key
438
705
  * ```
439
706
  */
440
707
  copy: (sourceKey: string, destKey: string, options?: CopyOptions) => Promise<HaiResult<FileMetadata>>;
@@ -443,6 +710,16 @@ interface FileOperations {
443
710
  * 目录操作接口
444
711
  *
445
712
  * 提供目录(前缀)的列表操作。
713
+ * @example
714
+ * ```ts
715
+ * import type { DirOperations } from '@h-ai/storage'
716
+ *
717
+ * async function inspect(operations: DirOperations) {
718
+ * const page = await operations.list({ prefix: 'reports/', maxKeys: 100 })
719
+ * if (!page.success) return page.error.message
720
+ * return page.data.files
721
+ * }
722
+ * ```
446
723
  */
447
724
  interface DirOperations {
448
725
  /**
@@ -466,7 +743,10 @@ interface DirOperations {
466
743
  * @returns 删除结果
467
744
  * @example
468
745
  * ```ts
469
- * await storage.dir.delete('uploads/tmp/')
746
+ * import { storage } from '@h-ai/storage'
747
+ *
748
+ * const result = await storage.dir.delete('uploads/tmp/')
749
+ * if (!result.success) throw new Error(result.error.message)
470
750
  * ```
471
751
  */
472
752
  delete: (prefix: string) => Promise<HaiResult<void>>;
@@ -474,7 +754,18 @@ interface DirOperations {
474
754
  /**
475
755
  * 签名 URL 操作接口
476
756
  *
477
- * 提供生成临时授权 URL 的功能,支持前端直接上传下载。
757
+ * S3 provider 提供临时授权 URL,支持前端直接上传下载。
758
+ * local 的 getUrl/putUrl 返回 UNSUPPORTED_OPERATION,publicUrl 返回 null。
759
+ * @example
760
+ * ```ts
761
+ * import type { PresignOperations } from '@h-ai/storage'
762
+ *
763
+ * async function inspect(operations: PresignOperations) {
764
+ * const signed = await operations.putUrl('reports/a.txt', { contentType: 'text/plain', expiresIn: 300 })
765
+ * if (!signed.success) return signed.error.message
766
+ * return signed.data
767
+ * }
768
+ * ```
478
769
  */
479
770
  interface PresignOperations {
480
771
  /**
@@ -482,10 +773,13 @@ interface PresignOperations {
482
773
  *
483
774
  * @param key - 文件键/路径
484
775
  * @param options - 签名选项
485
- * @returns 签名 URL
776
+ * @returns 成功时为可访问的 S3 签名 URL;local 返回 UNSUPPORTED_OPERATION。
486
777
  * @example
487
778
  * ```ts
488
779
  * const result = await storage.presign.getUrl('a.txt', { expiresIn: 60 })
780
+ * if (!result.success) throw new Error(result.error.message)
781
+ * const downloadUrl = result.data
782
+ * void downloadUrl
489
783
  * ```
490
784
  */
491
785
  getUrl: (key: string, options?: PresignOptions) => Promise<HaiResult<string>>;
@@ -494,10 +788,13 @@ interface PresignOperations {
494
788
  *
495
789
  * @param key - 文件键/路径
496
790
  * @param options - 上传签名选项
497
- * @returns 签名 URL
791
+ * @returns 成功时为可访问的 S3 签名 URL;local 返回 UNSUPPORTED_OPERATION。
498
792
  * @example
499
793
  * ```ts
500
794
  * const result = await storage.presign.putUrl('a.txt', { contentType: 'text/plain' })
795
+ * if (!result.success) throw new Error(result.error.message)
796
+ * const uploadUrl = result.data
797
+ * void uploadUrl
501
798
  * ```
502
799
  */
503
800
  putUrl: (key: string, options?: PresignUploadOptions) => Promise<HaiResult<string>>;
@@ -505,10 +802,11 @@ interface PresignOperations {
505
802
  * 获取公开访问 URL(如果配置了 publicUrl)
506
803
  *
507
804
  * @param key - 文件键/路径
508
- * @returns 公开 URL,如果未配置 publicUrl 则返回 null
805
+ * @returns 公开 URL;S3 未配置 publicUrl 或 local provider 均返回 null。
509
806
  * @example
510
807
  * ```ts
511
808
  * const url = storage.presign.publicUrl('a.txt')
809
+ * void url
512
810
  * ```
513
811
  */
514
812
  publicUrl: (key: string) => string | null;
@@ -524,6 +822,23 @@ interface PresignOperations {
524
822
  * - `storage.presign` — 签名 URL 操作
525
823
  * - `storage.config` — 当前脱敏配置快照(未初始化时为 null)
526
824
  * - `storage.isInitialized` — 初始化状态
825
+ * @example
826
+ * ```ts
827
+ * import { storage } from '@h-ai/storage'
828
+ *
829
+ * const initialized = await storage.init({ type: 'local', root: './data/uploads' })
830
+ * if (!initialized.success) throw new Error(initialized.error.message)
831
+ * try {
832
+ * const uploaded = await storage.file.put('reports/a.txt', 'hello', { ifNoneMatch: '*' })
833
+ * if (!uploaded.success) throw new Error(uploaded.error.message)
834
+ * const downloaded = await storage.file.get('reports/a.txt')
835
+ * if (!downloaded.success) throw new Error(downloaded.error.message)
836
+ * void downloaded.data
837
+ * } finally {
838
+ * const closed = await storage.close()
839
+ * if (!closed.success) throw new Error(closed.error.message)
840
+ * }
841
+ * ```
527
842
  */
528
843
  interface StorageFunctions {
529
844
  /** 无状态 checksum 生成与校验,Node 专用,无需初始化。 */
@@ -534,13 +849,30 @@ interface StorageFunctions {
534
849
  * 已有连接时会先 close 再重新初始化。
535
850
  *
536
851
  * @param config - 存储配置(支持省略带默认值的字段)
537
- * @returns 成功 ok(undefined);失败返回 err(含 StorageError)
852
+ * @returns 成功 ok(undefined);失败返回 err(含 HaiStorageError 定义的错误信息)
853
+ * @example
854
+ * ```ts
855
+ * import { storage } from '@h-ai/storage'
856
+ *
857
+ * const initialized = await storage.init({ type: 'local', root: './data/uploads' })
858
+ * if (!initialized.success) throw new Error(initialized.error.message)
859
+ * const closed = await storage.close()
860
+ * if (!closed.success) throw new Error(closed.error.message)
861
+ * ```
538
862
  */
539
863
  init: (config: StorageConfigInput) => Promise<HaiResult<void>>;
540
864
  /**
541
865
  * 关闭存储连接并释放资源
542
866
  *
543
- * 重复调用不会报错。
867
+ * 等待初始化并合并并发关闭;失败时操作不可用,资源保留供 close/init 重试。
868
+ * @returns 所有资源释放成功才返回成功;未初始化时同样成功。
869
+ * @example
870
+ * ```ts
871
+ * import { storage } from '@h-ai/storage'
872
+ *
873
+ * const closed = await storage.close()
874
+ * if (!closed.success) throw new Error(closed.error.message)
875
+ * ```
544
876
  */
545
877
  close: () => Promise<HaiResult<void>>;
546
878
  /** 当前脱敏后的存储配置快照;未初始化或已关闭时为 null */
@@ -554,31 +886,5 @@ interface StorageFunctions {
554
886
  /** 签名 URL 操作接口(getUrl / putUrl / publicUrl) */
555
887
  readonly presign: PresignOperations;
556
888
  }
557
- /**
558
- * 存储 Provider 接口
559
- *
560
- * 由各具体存储实现(S3、Local)实现此接口。
561
- */
562
- interface StorageProvider {
563
- /** Provider 名称标识(如 's3'、'local') */
564
- readonly name: string;
565
- /**
566
- * 建立与存储服务的连接
567
- *
568
- * @param config - 经 Schema 校验后的完整配置
569
- * @returns 连接结果
570
- */
571
- connect: (config: StorageConfig) => Promise<HaiResult<void>>;
572
- /** 关闭连接并释放资源 */
573
- close: () => Promise<void>;
574
- /** 检查是否已连接 */
575
- isConnected: () => boolean;
576
- /** 文件操作接口 */
577
- readonly file: FileOperations;
578
- /** 目录操作接口 */
579
- readonly dir: DirOperations;
580
- /** 签名 URL 操作接口 */
581
- readonly presign: PresignOperations;
582
- }
583
889
 
584
- export { type ChecksumAlgorithm, type ChecksumOperations, type ChecksumOptions, type CopyOptions, type DirOperations, type DownloadOptions, type FileMetadata, type FileOperations, HaiStorageError, type ListOptions, type ListResult, type LocalConfig, LocalConfigSchema, type PresignOperations, type PresignOptions, PresignOptionsSchema, type PresignUploadOptions, PresignUploadOptionsSchema, type S3Config, S3ConfigSchema, type StorageConfig, type StorageConfigInput, StorageConfigSchema, type StorageData, type StorageFunctions, type StorageOperationLogConfig, StorageOperationLogConfigSchema, type StorageProvider, type StorageType, StorageTypeSchema, type UploadOptions };
890
+ export { type ChecksumAlgorithm, type ChecksumOperations, type ChecksumOptions, type CopyOptions, type DirOperations, type DownloadOptions, type FileMetadata, type FileOperations, HaiStorageError, type ListOptions, type ListResult, type LocalConfig, LocalConfigSchema, type PresignOperations, type PresignOptions, PresignOptionsSchema, type PresignUploadOptions, PresignUploadOptionsSchema, type S3Config, S3ConfigSchema, type StorageConfig, type StorageConfigInput, StorageConfigSchema, type StorageData, type StorageDeleteFailure, type StorageDeleteResult, type StorageDeleteSummary, type StorageFunctions, type StorageOperationLogConfig, StorageOperationLogConfigSchema, type StorageType, StorageTypeSchema, type UploadOptions };