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