@lark-apaas/dataloom 0.1.1-alpha.1 → 0.1.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +812 -1
  2. package/lib/DataloomClient.d.ts +3 -4
  3. package/lib/DataloomClient.d.ts.map +1 -1
  4. package/lib/DataloomClient.js +7 -2
  5. package/lib/index.d.ts +1 -1
  6. package/lib/index.d.ts.map +1 -1
  7. package/lib/index.js +1 -1
  8. package/lib/service/services/DataloomServiceBase.d.ts.map +1 -1
  9. package/lib/service/services/DataloomServiceBase.js +1 -1
  10. package/lib/service/services/session-service/index.d.ts.map +1 -1
  11. package/lib/service/services/session-service/index.js +26 -0
  12. package/lib/service/utils/logger.d.ts +2 -2
  13. package/lib/service/utils/logger.d.ts.map +1 -1
  14. package/lib/service/utils/types.d.ts +2 -2
  15. package/lib/service/utils/types.d.ts.map +1 -1
  16. package/lib/storage/StorageClient.d.ts +9 -2
  17. package/lib/storage/StorageClient.d.ts.map +1 -1
  18. package/lib/storage/StorageClient.js +12 -3
  19. package/lib/storage/libs/errors.d.ts +9 -3
  20. package/lib/storage/libs/errors.d.ts.map +1 -1
  21. package/lib/storage/libs/errors.js +3 -3
  22. package/lib/storage/libs/fetch.d.ts +6 -6
  23. package/lib/storage/libs/fetch.d.ts.map +1 -1
  24. package/lib/storage/libs/fetch.js +21 -2
  25. package/lib/storage/libs/helpers.d.ts +4 -4
  26. package/lib/storage/libs/helpers.d.ts.map +1 -1
  27. package/lib/storage/libs/helpers.js +27 -14
  28. package/lib/storage/libs/index.d.ts +0 -1
  29. package/lib/storage/libs/index.d.ts.map +1 -1
  30. package/lib/storage/libs/index.js +0 -1
  31. package/lib/storage/libs/types.d.ts +4 -3
  32. package/lib/storage/libs/types.d.ts.map +1 -1
  33. package/lib/storage/packages/StorageFileApi.d.ts +1 -1
  34. package/lib/storage/packages/StorageFileApi.d.ts.map +1 -1
  35. package/lib/storage/packages/StorageFileApi.js +6 -1
  36. package/lib/storage/utils/logger.d.ts +2 -2
  37. package/lib/storage/utils/logger.d.ts.map +1 -1
  38. package/lib/utils/fetch.d.ts +1 -2
  39. package/lib/utils/fetch.d.ts.map +1 -1
  40. package/lib/utils/fetch.js +1 -1
  41. package/lib/utils/slardar.d.ts +2 -0
  42. package/lib/utils/slardar.d.ts.map +1 -0
  43. package/lib/utils/slardar.js +15 -0
  44. package/lib/utils/types.d.ts +3 -2
  45. package/lib/utils/types.d.ts.map +1 -1
  46. package/package.json +4 -1
  47. package/lib/storage/packages/StorageBucketApi.d.ts +0 -121
  48. package/lib/storage/packages/StorageBucketApi.d.ts.map +0 -1
  49. package/lib/storage/packages/StorageBucketApi.js +0 -135
package/README.md CHANGED
@@ -1,3 +1,814 @@
1
1
  # @lark-apaas/dataloom
2
2
 
3
- Dataloom client SDK for @lark-apaas (storage + service). Migrated from @data-loom/js.
3
+ 面向 `@lark-apaas` 的浏览器端 Dataloom SDK,当前聚焦于 `service` `storage`
4
+ 两部分能力。该包由原 `@data-loom/js` 相关能力迁移并精简而来,仅保留当前客户端实际需要的功能。
5
+
6
+ ## 功能概览
7
+
8
+ 当前 SDK 提供以下能力:
9
+
10
+ - `service.user`:用户检索与批量查询
11
+ - `service.session`:登录跳转、登出、当前用户信息、个人中心跳转
12
+ - `storage`:基于 `bucketId` 的文件上传、下载、移动、复制、删除、签名链接等能力
13
+
14
+ 当前版本仅支持浏览器环境,不提供 Node.js 兼容垫片。
15
+
16
+ ## 运行环境
17
+
18
+ 使用前请确认运行环境满足以下条件:
19
+
20
+ - 浏览器环境
21
+ - 可用的 `fetch` / `Headers` / `Request` / `Response`
22
+ - 页面中可访问 `window.location`
23
+ - 页面中可访问 `document.cookie`
24
+
25
+ ## 安装
26
+
27
+ ```bash
28
+ pnpm add @lark-apaas/dataloom
29
+ ```
30
+
31
+ ## 导出内容
32
+
33
+ 包根入口当前导出:
34
+
35
+ - `DataloomClient`
36
+ - `createClient`
37
+ - `DataloomClientOptions`
38
+
39
+ 示例:
40
+
41
+ ```ts
42
+ import { createClient } from '@lark-apaas/dataloom';
43
+ ```
44
+
45
+ ## 快速开始
46
+
47
+ ```ts
48
+ import { createClient } from '@lark-apaas/dataloom';
49
+
50
+ const client = createClient(
51
+ 'https://example.com',
52
+ 'dataloom-key',
53
+ {
54
+ global: {
55
+ brandName: 'miaoda',
56
+ appId: 'app_xxx',
57
+ },
58
+ },
59
+ );
60
+ ```
61
+
62
+ 创建完成后,可以通过以下入口访问能力:
63
+
64
+ - `client.service.user`
65
+ - `client.service.session`
66
+ - `client.storage.from(bucketId)`
67
+
68
+ ## 初始化
69
+
70
+ ### `createClient(...)`
71
+
72
+ ```ts
73
+ createClient(
74
+ dataloomUrl: string,
75
+ dataloomKey: string,
76
+ options?: DataloomClientOptions,
77
+ )
78
+ ```
79
+
80
+ #### 入参
81
+
82
+ | 参数 | 类型 | 必填 | 说明 |
83
+ | --- | --- | --- | --- |
84
+ | `dataloomUrl` | `string` | 是 | Dataloom 服务地址 |
85
+ | `dataloomKey` | `string` | 是 | 访问 Dataloom 的 key |
86
+ | `options` | `DataloomClientOptions` | 否 | 初始化配置 |
87
+
88
+ #### 返回
89
+
90
+ | 返回值 | 类型 | 说明 |
91
+ | --- | --- | --- |
92
+ | 返回结果 | `DataloomClient` | SDK 客户端实例 |
93
+
94
+ ### `DataloomClientOptions`
95
+
96
+ 当前支持的 `global` 配置如下:
97
+
98
+ ```ts
99
+ type DataloomClientOptions = {
100
+ global?: {
101
+ brandName: string;
102
+ appId: string;
103
+ fetch?: typeof fetch;
104
+ headers?: Record<string, string>;
105
+ enableDataloomLog?: boolean;
106
+ requestRateLimit?: number;
107
+ onError?: (error: any, instance: any) => void;
108
+ };
109
+ };
110
+ ```
111
+
112
+ #### `global` 配置项
113
+
114
+ | 字段 | 类型 | 必填 | 说明 |
115
+ | --- | --- | --- | --- |
116
+ | `brandName` | `string` | 是 | 品牌标识,供 session / profile 逻辑使用 |
117
+ | `appId` | `string` | 是 | 业务 appId,供 service / storage 请求使用 |
118
+ | `fetch` | `typeof fetch` | 否 | 自定义 fetch 实现 |
119
+ | `headers` | `Record<string, string>` | 否 | 额外请求头 |
120
+ | `enableDataloomLog` | `boolean` | 否 | 是否开启请求日志 |
121
+ | `requestRateLimit` | `number` | 否 | 5 秒窗口内最大请求数 |
122
+ | `onError` | `(error, instance) => void` | 否 | 请求失败时的全局钩子 |
123
+
124
+ 完整示例:
125
+
126
+ ```ts
127
+ const client = createClient(
128
+ 'https://example.com',
129
+ 'dataloom-key',
130
+ {
131
+ global: {
132
+ brandName: 'miaoda',
133
+ appId: 'app_xxx',
134
+ headers: {
135
+ 'x-custom-header': 'demo',
136
+ },
137
+ enableDataloomLog: false,
138
+ requestRateLimit: 5,
139
+ onError(error, instance) {
140
+ console.error('[dataloom error]', error, instance);
141
+ },
142
+ },
143
+ },
144
+ );
145
+ ```
146
+
147
+ ## Service API
148
+
149
+ ## `client.service.user`
150
+
151
+ 用户相关 API。
152
+
153
+ ### `search(params)`
154
+
155
+ 按关键字搜索用户。
156
+
157
+ ```ts
158
+ const result = await client.service.user.search({
159
+ name: 'Alice',
160
+ pageSize: 10,
161
+ });
162
+ ```
163
+
164
+ #### 入参
165
+
166
+ | 参数 | 类型 | 必填 | 说明 |
167
+ | --- | --- | --- | --- |
168
+ | `params.name` | `string` | 是 | 搜索关键字 |
169
+ | `params.pageSize` | `number` | 否 | 返回数量 |
170
+
171
+ #### 返回
172
+
173
+ | 字段 | 类型 | 说明 |
174
+ | --- | --- | --- |
175
+ | `data.user_list` | `User[]` | 用户列表 |
176
+ | `data.user_list[].user_id` | `string` | 用户 ID |
177
+ | `data.user_list[].email` | `string` | 邮箱 |
178
+ | `data.user_list[].name` | `string` | 展示名称 |
179
+ | `data.user_list[].avatar` | `string` | 头像地址 |
180
+ | `data.user_list[].status` | `UserStatus` | 用户状态 |
181
+ | `error` | `ErrorShape \| null` | 错误信息 |
182
+ | `status` | `number` | HTTP 状态码 |
183
+ | `statusText` | `string` | HTTP 状态文本 |
184
+
185
+ ### `getByIds(ids)`
186
+
187
+ 按用户 ID 批量获取用户信息。
188
+
189
+ ```ts
190
+ const result = await client.service.user.getByIds([1, 2, 3]);
191
+ ```
192
+
193
+ #### 入参
194
+
195
+ | 参数 | 类型 | 必填 | 说明 |
196
+ | --- | --- | --- | --- |
197
+ | `ids` | `string[] \| number[]` | 是 | 用户 ID 列表 |
198
+
199
+ #### 返回
200
+
201
+ | 字段 | 类型 | 说明 |
202
+ | --- | --- | --- |
203
+ | `data.user_list` | `User[]` | 用户列表,顺序与入参 `ids` 一致 |
204
+ | `data.user_list[].user_id` | `string` | 用户 ID;未命中时为空字符串 |
205
+ | `data.user_list[].email` | `string` | 邮箱;未命中时为空字符串 |
206
+ | `data.user_list[].name` | `string` | 用户名称;未命中时为空字符串 |
207
+ | `data.user_list[].avatar` | `string` | 头像地址;未命中时为空字符串 |
208
+ | `data.user_list[].status` | `UserStatus` | 用户状态 |
209
+ | `error` | `ErrorShape \| null` | 错误信息 |
210
+ | `status` | `number` | HTTP 状态码 |
211
+ | `statusText` | `string` | HTTP 状态文本 |
212
+
213
+ ## `client.service.session`
214
+
215
+ 会话相关 API,仅支持浏览器环境。
216
+
217
+ ### `redirectToLogin(options?)`
218
+
219
+ 跳转到登录页。
220
+
221
+ ```ts
222
+ client.service.session.redirectToLogin();
223
+
224
+ client.service.session.redirectToLogin({
225
+ newTab: true,
226
+ returnUrl: 'https://example.com/callback',
227
+ });
228
+ ```
229
+
230
+ #### 入参
231
+
232
+ | 参数 | 类型 | 必填 | 说明 |
233
+ | --- | --- | --- | --- |
234
+ | `options.returnUrl` | `string` | 否 | 登录完成后的回跳地址,默认使用当前页面地址 |
235
+ | `options.newTab` | `boolean` | 否 | 是否在新标签页打开,默认 `false` |
236
+
237
+ #### 返回
238
+
239
+ | 字段 | 类型 | 说明 |
240
+ | --- | --- | --- |
241
+ | `data` | `'success' \| null` | 成功时返回 `'success'` |
242
+ | `error` | `ErrorShape \| null` | 非浏览器环境下返回错误 |
243
+ | `status` | `number` | 状态码 |
244
+ | `statusText` | `string` | 状态文本 |
245
+
246
+ #### 说明
247
+
248
+ - 若当前页面路径以 `/spark` 开头,会生成 `/spark/faas/...` 登录地址
249
+ - 否则生成 `/app/...` 登录地址
250
+
251
+ ### `signOut()`
252
+
253
+ 退出当前登录态。
254
+
255
+ ```ts
256
+ await client.service.session.signOut();
257
+ ```
258
+
259
+ #### 入参
260
+
261
+ 无。
262
+
263
+ #### 返回
264
+
265
+ | 字段 | 类型 | 说明 |
266
+ | --- | --- | --- |
267
+ | `data` | `null` | 成功时通常为空 |
268
+ | `error` | `ErrorShape \| null` | 错误信息 |
269
+ | `status` | `number` | 状态码 |
270
+ | `statusText` | `string` | 状态文本 |
271
+
272
+ ### `getUrlWithBizSource()`
273
+
274
+ 获取带 `biz_source` 参数的当前页面 URL。
275
+
276
+ ```ts
277
+ const currentUrl = client.service.session.getUrlWithBizSource();
278
+ ```
279
+
280
+ #### 入参
281
+
282
+ 无。
283
+
284
+ #### 返回
285
+
286
+ | 返回值 | 类型 | 说明 |
287
+ | --- | --- | --- |
288
+ | 返回结果 | `string` | 带 `biz_source` 的当前页面 URL;非浏览器环境返回空字符串 |
289
+
290
+ ### `getUserInfo()`
291
+
292
+ 获取当前登录用户信息。
293
+
294
+ ```ts
295
+ const result = await client.service.session.getUserInfo();
296
+ ```
297
+
298
+ #### 入参
299
+
300
+ 无。
301
+
302
+ #### 返回
303
+
304
+ | 字段 | 类型 | 说明 |
305
+ | --- | --- | --- |
306
+ | `data.user_info` | `UserBaseInfo` | 当前用户信息 |
307
+ | `data.user_info.user_id` | `number \| undefined` | 用户 ID |
308
+ | `data.user_info.name` | `I18ns \| undefined` | 多语言名称 |
309
+ | `data.user_info.avatar` | `Avatar \| undefined` | 头像信息 |
310
+ | `data.user_info.email` | `string \| undefined` | 邮箱 |
311
+ | `data.user_info.phone_number` | `string \| undefined` | 脱敏手机号 |
312
+ | `error` | `ErrorShape \| null` | 错误信息 |
313
+ | `status` | `number` | 状态码 |
314
+ | `statusText` | `string` | 状态文本 |
315
+
316
+ ### `navigateToUserProfile(options?)`
317
+
318
+ 跳转到用户个人中心页。
319
+
320
+ ```ts
321
+ client.service.session.navigateToUserProfile();
322
+
323
+ client.service.session.navigateToUserProfile({ newTab: true });
324
+ ```
325
+
326
+ #### 入参
327
+
328
+ | 参数 | 类型 | 必填 | 说明 |
329
+ | --- | --- | --- | --- |
330
+ | `options.newTab` | `boolean` | 否 | 是否在新标签页打开,默认 `false` |
331
+
332
+ #### 返回
333
+
334
+ | 字段 | 类型 | 说明 |
335
+ | --- | --- | --- |
336
+ | `data` | `'success' \| null` | 成功时返回 `'success'` |
337
+ | `error` | `ErrorShape \| null` | 非浏览器环境下返回错误 |
338
+ | `status` | `number` | 状态码 |
339
+ | `statusText` | `string` | 状态文本 |
340
+
341
+ ## Storage API
342
+
343
+ Storage 能力以 bucket 为作用域,需要先通过 `from(bucketId)` 获取文件操作实例。
344
+
345
+ ```ts
346
+ const storage = client.storage.from('assets');
347
+ ```
348
+
349
+ ## `client.storage.from(bucketId)`
350
+
351
+ #### 入参
352
+
353
+ | 参数 | 类型 | 必填 | 说明 |
354
+ | --- | --- | --- | --- |
355
+ | `bucketId` | `string` | 是 | 目标 bucket 标识 |
356
+
357
+ #### 返回
358
+
359
+ | 返回值 | 类型 | 说明 |
360
+ | --- | --- | --- |
361
+ | 返回结果 | `StorageFileApi` | bucket 级文件操作实例 |
362
+
363
+ ### `upload(path, fileBody, fileOptions?)`
364
+
365
+ 上传文件。
366
+
367
+ ```ts
368
+ const file = new File(['hello'], 'hello.txt', { type: 'text/plain' });
369
+
370
+ await client.storage.from('assets').upload('docs/hello.txt', file, {
371
+ contentType: 'text/plain',
372
+ upsert: true,
373
+ });
374
+ ```
375
+
376
+ 也支持以下重载形式:
377
+
378
+ ```ts
379
+ await client.storage.from('assets').upload(file, {
380
+ filePath: 'docs/hello.txt',
381
+ contentType: 'text/plain',
382
+ });
383
+ ```
384
+
385
+ #### 入参
386
+
387
+ | 参数 | 类型 | 必填 | 说明 |
388
+ | --- | --- | --- | --- |
389
+ | `path` | `string` | 条件必填 | 目标文件路径,使用重载 1 时必填 |
390
+ | `fileBody` | `FileBody` | 是 | 文件内容,支持 `Blob`、`File`、`ArrayBuffer`、`FormData`、`string` 等 |
391
+ | `fileOptions.cacheControl` | `string \| number` | 否 | 浏览器/CDN 缓存时间 |
392
+ | `fileOptions.contentType` | `string` | 否 | 文件内容类型 |
393
+ | `fileOptions.upsert` | `boolean` | 否 | 是否允许覆盖 |
394
+ | `fileOptions.duplex` | `string` | 否 | 流式上传配置 |
395
+ | `fileOptions.metadata` | `Record<string, any>` | 否 | 附加元数据 |
396
+ | `fileOptions.headers` | `Record<string, string>` | 否 | 附加请求头 |
397
+ | `fileOptions.filePath` | `string` | 条件必填 | 使用重载 2 时的目标路径 |
398
+ | `fileOptions.contentDisposition` | `string` | 否 | 下载时的文件名响应头 |
399
+
400
+ #### 返回
401
+
402
+ | 字段 | 类型 | 说明 |
403
+ | --- | --- | --- |
404
+ | `data.id` | `string` | 文件 ID |
405
+ | `data.file_path` | `string` | 文件路径 |
406
+ | `data.bucket_id` | `string` | bucket ID |
407
+ | `data.download_url` | `string` | 下载地址 |
408
+ | `error` | `StorageError \| null` | 错误信息 |
409
+
410
+ ### `uploadFile(fileBody, fileOptions?)`
411
+
412
+ 与 `upload(fileBody, { filePath })` 类似。
413
+
414
+ #### 入参
415
+
416
+ | 参数 | 类型 | 必填 | 说明 |
417
+ | --- | --- | --- | --- |
418
+ | `fileBody` | `FileBody` | 是 | 文件内容 |
419
+ | `fileOptions.filePath` | `string` | 否 | 上传目标路径 |
420
+ | `fileOptions.cacheControl` | `string \| number` | 否 | 缓存时间 |
421
+ | `fileOptions.contentType` | `string` | 否 | 内容类型 |
422
+ | `fileOptions.upsert` | `boolean` | 否 | 是否允许覆盖 |
423
+ | `fileOptions.contentDisposition` | `string` | 否 | 下载响应头文件名 |
424
+
425
+ #### 返回
426
+
427
+ 与 `upload` 相同。
428
+
429
+ ### `update(path, fileBody, fileOptions?)`
430
+
431
+ 更新已存在的文件。
432
+
433
+ #### 入参
434
+
435
+ | 参数 | 类型 | 必填 | 说明 |
436
+ | --- | --- | --- | --- |
437
+ | `path` | `string` | 是 | 文件路径 |
438
+ | `fileBody` | `FileBody` | 是 | 文件内容 |
439
+ | `fileOptions` | `FileOptions` | 否 | 更新配置 |
440
+
441
+ #### 返回
442
+
443
+ 与 `upload` 相同。
444
+
445
+ ### `list(path?, options?)`
446
+
447
+ 列出目录下文件。
448
+
449
+ #### 入参
450
+
451
+ | 参数 | 类型 | 必填 | 说明 |
452
+ | --- | --- | --- | --- |
453
+ | `path` | `string` | 否 | 目录前缀 |
454
+ | `options.limit` | `number` | 否 | 返回条数 |
455
+ | `options.offset` | `number` | 否 | 偏移量 |
456
+ | `options.sortBy` | `SortBy` | 否 | 排序配置 |
457
+ | `options.search` | `string` | 否 | 搜索关键字 |
458
+
459
+ #### 返回
460
+
461
+ | 字段 | 类型 | 说明 |
462
+ | --- | --- | --- |
463
+ | `data` | `FileObject[]` | 文件列表 |
464
+ | `error` | `StorageError \| null` | 错误信息 |
465
+
466
+ ### `download(path)`
467
+
468
+ 下载文件。
469
+
470
+ #### 入参
471
+
472
+ | 参数 | 类型 | 必填 | 说明 |
473
+ | --- | --- | --- | --- |
474
+ | `path` | `string` | 是 | 文件路径 |
475
+
476
+ #### 返回
477
+
478
+ | 字段 | 类型 | 说明 |
479
+ | --- | --- | --- |
480
+ | `data` | `Blob \| null` | 下载结果 |
481
+ | `error` | `StorageError \| null` | 错误信息 |
482
+
483
+ ### `createSignedUrl(path, expiresIn)`
484
+
485
+ 创建单个文件的签名链接。
486
+
487
+ #### 入参
488
+
489
+ | 参数 | 类型 | 必填 | 说明 |
490
+ | --- | --- | --- | --- |
491
+ | `path` | `string` | 是 | 文件路径 |
492
+ | `expiresIn` | `number` | 是 | 过期时间,单位秒 |
493
+
494
+ #### 返回
495
+
496
+ | 字段 | 类型 | 说明 |
497
+ | --- | --- | --- |
498
+ | `data.signedUrl` | `string` | 签名链接 |
499
+ | `error` | `StorageError \| null` | 错误信息 |
500
+
501
+ ### `createSignedUrls(paths, expiresIn)`
502
+
503
+ 批量创建签名链接。
504
+
505
+ #### 入参
506
+
507
+ | 参数 | 类型 | 必填 | 说明 |
508
+ | --- | --- | --- | --- |
509
+ | `paths` | `string[]` | 是 | 文件路径列表 |
510
+ | `expiresIn` | `number` | 是 | 过期时间,单位秒 |
511
+
512
+ #### 返回
513
+
514
+ | 字段 | 类型 | 说明 |
515
+ | --- | --- | --- |
516
+ | `data` | `{ path: string \| null; signedUrl: string; error: string \| null }[]` | 签名链接列表 |
517
+ | `error` | `StorageError \| null` | 错误信息 |
518
+
519
+ ### `remove(paths)`
520
+
521
+ 删除文件。
522
+
523
+ #### 入参
524
+
525
+ | 参数 | 类型 | 必填 | 说明 |
526
+ | --- | --- | --- | --- |
527
+ | `paths` | `string[]` | 是 | 文件路径列表 |
528
+
529
+ #### 返回
530
+
531
+ | 字段 | 类型 | 说明 |
532
+ | --- | --- | --- |
533
+ | `data` | `FileObject[]` | 删除结果 |
534
+ | `error` | `StorageError \| null` | 错误信息 |
535
+
536
+ ### `move(fromPath, toPath)`
537
+
538
+ 移动文件。
539
+
540
+ #### 入参
541
+
542
+ | 参数 | 类型 | 必填 | 说明 |
543
+ | --- | --- | --- | --- |
544
+ | `fromPath` | `string` | 是 | 原路径 |
545
+ | `toPath` | `string` | 是 | 目标路径 |
546
+
547
+ #### 返回
548
+
549
+ | 字段 | 类型 | 说明 |
550
+ | --- | --- | --- |
551
+ | `data` | `{ message: string } \| null` | 移动结果 |
552
+ | `error` | `StorageError \| null` | 错误信息 |
553
+
554
+ ### `copy(fromPath, toPath)`
555
+
556
+ 复制文件。
557
+
558
+ #### 入参
559
+
560
+ | 参数 | 类型 | 必填 | 说明 |
561
+ | --- | --- | --- | --- |
562
+ | `fromPath` | `string` | 是 | 原路径 |
563
+ | `toPath` | `string` | 是 | 目标路径 |
564
+
565
+ #### 返回
566
+
567
+ | 字段 | 类型 | 说明 |
568
+ | --- | --- | --- |
569
+ | `data` | `FileObjectV2 \| null` | 复制结果 |
570
+ | `error` | `StorageError \| null` | 错误信息 |
571
+
572
+ ### `copyFromUrl(url, path, options?)`
573
+
574
+ 将外部 URL 文件复制到 bucket 中。
575
+
576
+ #### 入参
577
+
578
+ | 参数 | 类型 | 必填 | 说明 |
579
+ | --- | --- | --- | --- |
580
+ | `url` | `string` | 是 | 外部资源地址 |
581
+ | `path` | `string` | 是 | 目标路径 |
582
+ | `options.cacheControl` | `string \| number` | 否 | 缓存时间 |
583
+ | `options.contentType` | `string` | 否 | 文件类型 |
584
+ | `options.upsert` | `boolean` | 否 | 是否允许覆盖 |
585
+
586
+ #### 返回
587
+
588
+ | 字段 | 类型 | 说明 |
589
+ | --- | --- | --- |
590
+ | `data` | `UploadFileData \| null` | 复制结果 |
591
+ | `error` | `StorageError \| null` | 错误信息 |
592
+
593
+ ## 错误处理
594
+
595
+ 大多数异步 API 都返回统一结构:
596
+
597
+ ```ts
598
+ {
599
+ data: T | null;
600
+ error: ErrorShape | null;
601
+ status?: number;
602
+ statusText?: string;
603
+ }
604
+ ```
605
+
606
+ 推荐使用方式:
607
+
608
+ ```ts
609
+ const result = await client.service.user.search({ name: 'Alice' });
610
+
611
+ if (result.error) {
612
+ console.error(result.error.message);
613
+ return;
614
+ }
615
+
616
+ console.log(result.data);
617
+ ```
618
+
619
+ Storage 相关错误类型也可以从包根入口获取,例如:
620
+
621
+ ```ts
622
+ import {
623
+ StorageApiError,
624
+ StorageError,
625
+ StorageUnknownError,
626
+ } from '@lark-apaas/dataloom';
627
+ ```
628
+
629
+ ### Service 错误结构
630
+
631
+ Service 异常响应中的 `error` 字段结构如下:
632
+
633
+ | 字段 | 类型 | 说明 |
634
+ | --- | --- | --- |
635
+ | `code` | `number` | 错误码 |
636
+ | `message` | `string` | 错误信息 |
637
+ | `details` | `string` | 详细描述 |
638
+ | `hint` | `string \| null` | 补充提示 |
639
+
640
+ 对应类型:
641
+
642
+ ```ts
643
+ type DataloomServiceError = {
644
+ code: number;
645
+ details: string;
646
+ hint: string | null;
647
+ message: string;
648
+ };
649
+ ```
650
+
651
+ ### Storage 错误类型
652
+
653
+ Storage 使用异常对象表达错误,常见类型如下:
654
+
655
+ | 类型 | 继承关系 | 说明 | 关键字段 |
656
+ | --- | --- | --- | --- |
657
+ | `StorageError` | `Error` | Storage 基础错误类型 | `message` |
658
+ | `StorageApiError` | `StorageError` | 服务端 API 返回错误 | `message`、`status`、`statusCode` |
659
+ | `StorageUnknownError` | `StorageError` | 未知错误或非预期异常包装 | `message`、`originalError` |
660
+
661
+ ## Slardar 上报说明
662
+
663
+ `dataloom` 已接入 `@lark-apaas/internal-slardar`,用于在 SDK 内部关键错误节点发生异常时上报日志,便于排查线上问题。
664
+
665
+ ### 上报范围
666
+
667
+ 当前已覆盖的主要场景包括:
668
+
669
+ - client 统一请求失败入口(`onRequestError`)
670
+ - `service.session` 在非浏览器环境下的错误调用
671
+ - `storage` 侧高层 unknown error catch 分支
672
+ - `storage/libs/fetch.ts` 中的底层请求失败
673
+ - `storage/libs/fetch.ts` 中的响应 JSON 解析失败
674
+
675
+ ### 上报字段
676
+
677
+ Slardar 上报时会附带一组分类字段,当前常见字段如下:
678
+
679
+ | 字段 | 类型 | 说明 |
680
+ | --- | --- | --- |
681
+ | `source` | `string` | 固定为 `dataloom` |
682
+ | `module` | `string` | 出错模块,例如 `client`、`session-service`、`storage-file-api`、`storage-fetch` |
683
+ | `method` | `string` | 出错方法名,部分场景存在 |
684
+ | `phase` | `string` | 出错阶段,例如 `request`、`response-json-parse`、`blob` |
685
+ | `type` | `string` | 错误类别,例如 `runtime`、`unknown` |
686
+ | `appId` | `string` | 当前 appId,部分场景存在 |
687
+
688
+ ### 降级保证
689
+
690
+ Slardar 上报逻辑不会影响 `dataloom` 本身行为:
691
+
692
+ - `@lark-apaas/internal-slardar` 自身已做容错
693
+ - `dataloom` 内部的 `reportDataloomException(...)` 也额外包裹了 `try/catch`
694
+
695
+ 因此即使 Slardar SDK 未加载、调用失败、或上报逻辑本身抛错,也不会中断正常业务流程。
696
+
697
+ ## 核心类型附录
698
+
699
+ 以下是 README 中高频出现的核心返回结构,便于不翻源码时快速理解字段。
700
+
701
+ ### `User`
702
+
703
+ | 字段 | 类型 | 说明 |
704
+ | --- | --- | --- |
705
+ | `user_id` | `string` | 用户 ID |
706
+ | `email` | `string` | 邮箱 |
707
+ | `name` | `string` | 用户名称 |
708
+ | `avatar` | `string` | 头像地址 |
709
+ | `status` | `UserStatus` | 用户状态 |
710
+
711
+ ### `UserBaseInfo`
712
+
713
+ | 字段 | 类型 | 说明 |
714
+ | --- | --- | --- |
715
+ | `user_id` | `number \| undefined` | 用户 ID |
716
+ | `name` | `I18ns \| undefined` | 多语言名称 |
717
+ | `avatar` | `Avatar \| undefined` | 头像信息 |
718
+ | `email` | `string \| undefined` | 邮箱 |
719
+ | `phone_number` | `string \| undefined` | 脱敏手机号 |
720
+ | `tenant_name` | `string \| undefined` | 租户名称 |
721
+
722
+ ### `Avatar`
723
+
724
+ | 字段 | 类型 | 说明 |
725
+ | --- | --- | --- |
726
+ | `source` | `string \| undefined` | 头像来源 |
727
+ | `image.large` | `string \| undefined` | 大图地址 |
728
+ | `color` | `string \| undefined` | 头像主题色 |
729
+
730
+ ### `I18n` / `I18ns`
731
+
732
+ | 字段 | 类型 | 说明 |
733
+ | --- | --- | --- |
734
+ | `language_code` | `number` | 语言编码 |
735
+ | `text` | `string` | 文本内容 |
736
+
737
+ 说明:
738
+
739
+ - `I18n` 表示单条多语言内容
740
+ - `I18ns` 表示 `I18n[]`
741
+
742
+ ### `UploadFileData`
743
+
744
+ | 字段 | 类型 | 说明 |
745
+ | --- | --- | --- |
746
+ | `id` | `string` | 文件 ID |
747
+ | `file_path` | `string` | 文件路径 |
748
+ | `bucket_id` | `string` | bucket ID |
749
+ | `download_url` | `string` | 下载地址 |
750
+
751
+ ### `FileObject`
752
+
753
+ | 字段 | 类型 | 说明 |
754
+ | --- | --- | --- |
755
+ | `id` | `string` | 文件 ID |
756
+ | `name` | `string` | 文件名称 |
757
+ | `bucket_id` | `string` | bucket ID |
758
+ | `owner` | `string` | 所有者 |
759
+ | `created_at` | `string` | 创建时间 |
760
+ | `updated_at` | `string` | 更新时间 |
761
+ | `created_by` | `string` | 创建人 |
762
+ | `updated_by` | `string` | 更新人 |
763
+ | `last_accessed_at` | `string \| undefined` | 最后访问时间 |
764
+ | `metadata` | `Record<string, any>` | 元数据 |
765
+ | `buckets` | `Bucket` | 所属 bucket 信息 |
766
+
767
+ ### `FileObjectV2`
768
+
769
+ | 字段 | 类型 | 说明 |
770
+ | --- | --- | --- |
771
+ | `id` | `string` | 文件 ID |
772
+ | `version` | `string` | 版本号 |
773
+ | `name` | `string` | 文件名称 |
774
+ | `bucket_id` | `string` | bucket ID |
775
+ | `created_at` | `string` | 创建时间 |
776
+ | `updated_at` | `string` | 更新时间 |
777
+ | `last_accessed_at` | `string` | 最后访问时间 |
778
+ | `size` | `number \| undefined` | 文件大小 |
779
+ | `cache_control` | `string \| undefined` | 缓存控制 |
780
+ | `content_type` | `string \| undefined` | 内容类型 |
781
+ | `etag` | `string \| undefined` | ETag |
782
+ | `last_modified` | `string \| undefined` | 最后修改时间 |
783
+ | `metadata` | `Record<string, any> \| undefined` | 元数据 |
784
+
785
+ ### `Bucket`
786
+
787
+ | 字段 | 类型 | 说明 |
788
+ | --- | --- | --- |
789
+ | `id` | `string` | bucket ID |
790
+ | `type` | `'STANDARD' \| 'ANALYTICS' \| undefined` | bucket 类型 |
791
+ | `name` | `string` | bucket 名称 |
792
+ | `owner` | `string` | 所有者 |
793
+ | `file_size_limit` | `number \| undefined` | 文件大小限制 |
794
+ | `allowed_mime_types` | `string[] \| undefined` | 允许的 MIME 类型 |
795
+ | `created_at` | `string` | 创建时间 |
796
+ | `updated_at` | `string` | 更新时间 |
797
+ | `public` | `boolean` | 是否公开 |
798
+
799
+ ## 开发
800
+
801
+ ```bash
802
+ pnpm build
803
+ pnpm test
804
+ pnpm lint
805
+ pnpm check
806
+ ```
807
+
808
+ ## 测试
809
+
810
+ - 测试框架:`vitest`
811
+ - 运行环境:`jsdom`
812
+ - 覆盖率范围:`src/**/*.ts`
813
+
814
+ 覆盖率已排除构建产物,报告会聚焦真实源码,而不是 `lib` 目录中的生成文件。