@turinhub/tale-js-sdk 1.3.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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/acl/index.d.ts +295 -0
  4. package/dist/acl/index.js +653 -0
  5. package/dist/acl/types.d.ts +142 -0
  6. package/dist/acl/types.js +1 -0
  7. package/dist/auth/index.d.ts +166 -0
  8. package/dist/auth/index.js +522 -0
  9. package/dist/auth/types.d.ts +127 -0
  10. package/dist/auth/types.js +1 -0
  11. package/dist/cms/file.d.ts +398 -0
  12. package/dist/cms/file.js +800 -0
  13. package/dist/cms/folder.d.ts +128 -0
  14. package/dist/cms/folder.js +294 -0
  15. package/dist/cms/index.d.ts +3 -0
  16. package/dist/cms/index.js +6 -0
  17. package/dist/cms/types.d.ts +157 -0
  18. package/dist/cms/types.js +1 -0
  19. package/dist/common/types.d.ts +91 -0
  20. package/dist/common/types.js +2 -0
  21. package/dist/errors.d.ts +52 -0
  22. package/dist/errors.js +109 -0
  23. package/dist/index.d.ts +13 -0
  24. package/dist/index.js +12 -0
  25. package/dist/rbac/acl.d.ts +152 -0
  26. package/dist/rbac/acl.js +723 -0
  27. package/dist/rbac/index.d.ts +464 -0
  28. package/dist/rbac/index.js +1121 -0
  29. package/dist/rbac/rbac.d.ts +198 -0
  30. package/dist/rbac/rbac.js +984 -0
  31. package/dist/rbac/types.d.ts +125 -0
  32. package/dist/rbac/types.js +1 -0
  33. package/dist/rbac/user-group.d.ts +122 -0
  34. package/dist/rbac/user-group.js +570 -0
  35. package/dist/status.d.ts +40 -0
  36. package/dist/status.js +56 -0
  37. package/dist/task/index.d.ts +163 -0
  38. package/dist/task/index.js +495 -0
  39. package/dist/task/types.d.ts +116 -0
  40. package/dist/task/types.js +1 -0
  41. package/dist/task-type/index.d.ts +92 -0
  42. package/dist/task-type/index.js +256 -0
  43. package/dist/task-type/types.d.ts +54 -0
  44. package/dist/task-type/types.js +1 -0
  45. package/dist/token.d.ts +21 -0
  46. package/dist/token.js +114 -0
  47. package/dist/user/index.d.ts +267 -0
  48. package/dist/user/index.js +786 -0
  49. package/dist/user/types.d.ts +145 -0
  50. package/dist/user/types.js +1 -0
  51. package/dist/user-attribute/index.d.ts +186 -0
  52. package/dist/user-attribute/index.js +615 -0
  53. package/dist/user-attribute/types.d.ts +109 -0
  54. package/dist/user-attribute/types.js +1 -0
  55. package/dist/user-group/index.d.ts +231 -0
  56. package/dist/user-group/index.js +566 -0
  57. package/dist/user-group/types.d.ts +50 -0
  58. package/dist/user-group/types.js +1 -0
  59. package/package.json +50 -0
@@ -0,0 +1,800 @@
1
+ import { getAppToken } from "../token.js";
2
+ import { ApiError, ConfigurationError, NetworkError } from "../errors.js";
3
+ // ==================== Helper Functions ====================
4
+ /**
5
+ * Parses standard API response format: { code, msg, data }
6
+ */
7
+ function parseApiResponse(json, errorMessage, statusCode) {
8
+ if (typeof json !== "object" || json === null) {
9
+ throw new ApiError(`Invalid response: ${errorMessage} - not an object`, statusCode);
10
+ }
11
+ const response = json;
12
+ if (response.code !== 200) {
13
+ const errorMsg = typeof response.msg === "string" ? response.msg : errorMessage;
14
+ throw new ApiError(errorMsg, statusCode, response.code);
15
+ }
16
+ if (!response.data) {
17
+ throw new ApiError(`Invalid response: ${errorMessage} - missing data`, statusCode);
18
+ }
19
+ return response.data;
20
+ }
21
+ // ==================== File API Functions ====================
22
+ /**
23
+ * Gets a file by ID.
24
+ *
25
+ * @param fileId - File ID (UUID)
26
+ * @param options - Optional configuration
27
+ * @returns Promise resolving to file information
28
+ * @throws {ConfigurationError} When required environment variables are missing
29
+ * @throws {ApiError} When API request fails
30
+ * @throws {NetworkError} When network request fails
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * import { getFile } from '@tale/client';
35
+ *
36
+ * try {
37
+ * const file = await getFile('file_id_here');
38
+ * console.log('File name:', file.file_name);
39
+ * console.log('File type:', file.file_type);
40
+ * } catch (error) {
41
+ * console.error('Failed to get file:', error.message);
42
+ * }
43
+ * ```
44
+ */
45
+ export async function getFile(fileId, options) {
46
+ if (!fileId || fileId.trim() === "") {
47
+ throw new ApiError("fileId is required", 400, "9400");
48
+ }
49
+ const token = options?.appToken ?? (await getAppToken(options));
50
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
51
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
52
+ if (!base) {
53
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
54
+ }
55
+ const url = String(base).replace(/\/+$/, "") +
56
+ `/cms/v1/files/${encodeURIComponent(fileId)}`;
57
+ let response;
58
+ try {
59
+ response = await globalThis.fetch(url, {
60
+ method: "GET",
61
+ headers: {
62
+ "Content-Type": "application/json",
63
+ "x-t-token": token,
64
+ },
65
+ });
66
+ }
67
+ catch (error) {
68
+ throw new NetworkError(`Failed to get file: ${error instanceof Error ? error.message : "Unknown error"}`);
69
+ }
70
+ const json = await response.json();
71
+ return parseApiResponse(json, "Failed to get file", response.status);
72
+ }
73
+ /**
74
+ * Lists files with pagination.
75
+ *
76
+ * @param options - Optional parameters for pagination and filtering
77
+ * @returns Promise resolving to paginated file list
78
+ * @throws {ConfigurationError} When required environment variables are missing
79
+ * @throws {ApiError} When API request fails
80
+ * @throws {NetworkError} When network request fails
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * import { listFiles } from '@tale/client';
85
+ *
86
+ * try {
87
+ * const result = await listFiles({
88
+ * folder_id: 'folder_id_here',
89
+ * page: 0,
90
+ * size: 20,
91
+ * sort_by: 'createdAt'
92
+ * });
93
+ * console.log(`Found ${result.total} files`);
94
+ * } catch (error) {
95
+ * console.error('Failed to list files:', error.message);
96
+ * }
97
+ * ```
98
+ */
99
+ export async function listFiles(options) {
100
+ const token = options?.appToken ?? (await getAppToken(options));
101
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
102
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
103
+ if (!base) {
104
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
105
+ }
106
+ const { appToken, baseUrl, folder_id, ...requestParams } = options || {};
107
+ // If folder_id is provided, use folder-based endpoint
108
+ let url;
109
+ if (folder_id) {
110
+ url =
111
+ String(base).replace(/\/+$/, "") +
112
+ `/cms/v1/folders/${encodeURIComponent(folder_id)}/files`;
113
+ }
114
+ else {
115
+ url = String(base).replace(/\/+$/, "") + "/cms/v1/files";
116
+ }
117
+ const urlObj = new URL(url);
118
+ const queryParams = {
119
+ page: 0,
120
+ size: 10,
121
+ sort_by: "createdAt",
122
+ include_attachments: false,
123
+ ...requestParams,
124
+ };
125
+ Object.entries(queryParams).forEach(([key, value]) => {
126
+ if (value !== undefined) {
127
+ urlObj.searchParams.append(key, String(value));
128
+ }
129
+ });
130
+ let response;
131
+ try {
132
+ response = await globalThis.fetch(urlObj.toString(), {
133
+ method: "GET",
134
+ headers: {
135
+ "Content-Type": "application/json",
136
+ "x-t-token": token,
137
+ },
138
+ });
139
+ }
140
+ catch (error) {
141
+ throw new NetworkError(`Failed to list files: ${error instanceof Error ? error.message : "Unknown error"}`);
142
+ }
143
+ const json = await response.json();
144
+ return parseApiResponse(json, "Failed to list files", response.status);
145
+ }
146
+ /**
147
+ * Creates a new file.
148
+ *
149
+ * @param request - File creation request
150
+ * @param options - Optional configuration
151
+ * @returns Promise resolving to created file
152
+ * @throws {ConfigurationError} When required environment variables are missing
153
+ * @throws {ApiError} When API request fails
154
+ * @throws {NetworkError} When network request fails
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * import { createFile } from '@tale/client';
159
+ *
160
+ * try {
161
+ * const file = await createFile({
162
+ * folder_id: 'folder_id_here',
163
+ * file_name: 'My Document',
164
+ * file_type: 'markdown',
165
+ * content: '# Hello World'
166
+ * });
167
+ * console.log('File created:', file.id);
168
+ * } catch (error) {
169
+ * console.error('Failed to create file:', error.message);
170
+ * }
171
+ * ```
172
+ */
173
+ export async function createFile(request, options) {
174
+ if (!request.folder_id || request.folder_id.trim() === "") {
175
+ throw new ApiError("folder_id is required", 400, "9400");
176
+ }
177
+ if (!request.file_name || request.file_name.trim() === "") {
178
+ throw new ApiError("file_name is required", 400, "9400");
179
+ }
180
+ if (!request.file_type || request.file_type.trim() === "") {
181
+ throw new ApiError("file_type is required", 400, "9400");
182
+ }
183
+ const token = options?.appToken ?? (await getAppToken(options));
184
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
185
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
186
+ if (!base) {
187
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
188
+ }
189
+ const url = String(base).replace(/\/+$/, "") + "/cms/v1/files";
190
+ let response;
191
+ try {
192
+ response = await globalThis.fetch(url, {
193
+ method: "POST",
194
+ headers: {
195
+ "Content-Type": "application/json",
196
+ "x-t-token": token,
197
+ },
198
+ body: JSON.stringify(request),
199
+ });
200
+ }
201
+ catch (error) {
202
+ throw new NetworkError(`Failed to create file: ${error instanceof Error ? error.message : "Unknown error"}`);
203
+ }
204
+ const json = await response.json();
205
+ return parseApiResponse(json, "Failed to create file", response.status);
206
+ }
207
+ /**
208
+ * Updates an existing file.
209
+ *
210
+ * @param fileId - File ID to update
211
+ * @param request - Update request with fields to modify
212
+ * @param options - Optional configuration
213
+ * @returns Promise resolving to updated file
214
+ * @throws {ConfigurationError} When required environment variables are missing
215
+ * @throws {ApiError} When API request fails
216
+ * @throws {NetworkError} When network request fails
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * import { updateFile } from '@tale/client';
221
+ *
222
+ * try {
223
+ * const file = await updateFile('file_id_here', {
224
+ * file_name: 'Updated Name',
225
+ * remark: 'Updated remark'
226
+ * });
227
+ * console.log('File updated:', file.file_name);
228
+ * } catch (error) {
229
+ * console.error('Failed to update file:', error.message);
230
+ * }
231
+ * ```
232
+ */
233
+ export async function updateFile(fileId, request, options) {
234
+ if (!fileId || fileId.trim() === "") {
235
+ throw new ApiError("fileId is required", 400, "9400");
236
+ }
237
+ const token = options?.appToken ?? (await getAppToken(options));
238
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
239
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
240
+ if (!base) {
241
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
242
+ }
243
+ const url = String(base).replace(/\/+$/, "") +
244
+ `/cms/v1/files/${encodeURIComponent(fileId)}`;
245
+ let response;
246
+ try {
247
+ response = await globalThis.fetch(url, {
248
+ method: "PUT",
249
+ headers: {
250
+ "Content-Type": "application/json",
251
+ "x-t-token": token,
252
+ },
253
+ body: JSON.stringify(request),
254
+ });
255
+ }
256
+ catch (error) {
257
+ throw new NetworkError(`Failed to update file: ${error instanceof Error ? error.message : "Unknown error"}`);
258
+ }
259
+ const json = await response.json();
260
+ return parseApiResponse(json, "Failed to update file", response.status);
261
+ }
262
+ /**
263
+ * Updates the Markdown content of a file.
264
+ *
265
+ * @param fileId - File ID to update
266
+ * @param content - New Markdown content
267
+ * @param options - Optional configuration
268
+ * @returns Promise resolving to updated file
269
+ * @throws {ConfigurationError} When required environment variables are missing
270
+ * @throws {ApiError} When API request fails
271
+ * @throws {NetworkError} When network request fails
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * import { updateFileContent } from '@tale/client';
276
+ *
277
+ * try {
278
+ * const file = await updateFileContent('file_id_here', '# New Content');
279
+ * console.log('Content updated:', file.content);
280
+ * } catch (error) {
281
+ * console.error('Failed to update content:', error.message);
282
+ * }
283
+ * ```
284
+ */
285
+ export async function updateFileContent(fileId, content, options) {
286
+ if (!fileId || fileId.trim() === "") {
287
+ throw new ApiError("fileId is required", 400, "9400");
288
+ }
289
+ if (content === undefined || content === null) {
290
+ throw new ApiError("content is required", 400, "9400");
291
+ }
292
+ const token = options?.appToken ?? (await getAppToken(options));
293
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
294
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
295
+ if (!base) {
296
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
297
+ }
298
+ const url = String(base).replace(/\/+$/, "") +
299
+ `/cms/v1/files/${encodeURIComponent(fileId)}/content`;
300
+ let response;
301
+ try {
302
+ response = await globalThis.fetch(url, {
303
+ method: "PUT",
304
+ headers: {
305
+ "Content-Type": "application/json",
306
+ "x-t-token": token,
307
+ },
308
+ body: JSON.stringify({ content }),
309
+ });
310
+ }
311
+ catch (error) {
312
+ throw new NetworkError(`Failed to update file content: ${error instanceof Error ? error.message : "Unknown error"}`);
313
+ }
314
+ const json = await response.json();
315
+ return parseApiResponse(json, "Failed to update file content", response.status);
316
+ }
317
+ /**
318
+ * Deletes a file.
319
+ *
320
+ * @param fileId - File ID to delete
321
+ * @param options - Optional configuration
322
+ * @returns Promise that resolves when deletion is successful
323
+ * @throws {ConfigurationError} When required environment variables are missing
324
+ * @throws {ApiError} When API request fails
325
+ * @throws {NetworkError} When network request fails
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * import { deleteFile } from '@tale/client';
330
+ *
331
+ * try {
332
+ * await deleteFile('file_id_here');
333
+ * console.log('File deleted successfully');
334
+ * } catch (error) {
335
+ * console.error('Failed to delete file:', error.message);
336
+ * }
337
+ * ```
338
+ */
339
+ export async function deleteFile(fileId, options) {
340
+ if (!fileId || fileId.trim() === "") {
341
+ throw new ApiError("fileId is required", 400, "9400");
342
+ }
343
+ const token = options?.appToken ?? (await getAppToken(options));
344
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
345
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
346
+ if (!base) {
347
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
348
+ }
349
+ const url = String(base).replace(/\/+$/, "") +
350
+ `/cms/v1/files/${encodeURIComponent(fileId)}`;
351
+ let response;
352
+ try {
353
+ response = await globalThis.fetch(url, {
354
+ method: "DELETE",
355
+ headers: {
356
+ "Content-Type": "application/json",
357
+ "x-t-token": token,
358
+ },
359
+ });
360
+ }
361
+ catch (error) {
362
+ throw new NetworkError(`Failed to delete file: ${error instanceof Error ? error.message : "Unknown error"}`);
363
+ }
364
+ const json = (await response.json());
365
+ if (json.code !== 200) {
366
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to delete file";
367
+ throw new ApiError(errorMsg, response.status, json.code);
368
+ }
369
+ }
370
+ /**
371
+ * Gets a presigned URL for file download.
372
+ *
373
+ * @param fileId - File ID
374
+ * @param expireTimeInSeconds - Expiration time in seconds (default: 3600)
375
+ * @param options - Optional configuration
376
+ * @returns Promise resolving to presigned URL information
377
+ * @throws {ConfigurationError} When required environment variables are missing
378
+ * @throws {ApiError} When API request fails
379
+ * @throws {NetworkError} When network request fails
380
+ *
381
+ * @example
382
+ * ```typescript
383
+ * import { getFilePresignedUrl } from '@tale/client';
384
+ *
385
+ * try {
386
+ * const result = await getFilePresignedUrl('file_id_here', 3600);
387
+ * console.log('Presigned URL:', result.presigned_url);
388
+ * // Now you can download the file directly
389
+ * } catch (error) {
390
+ * console.error('Failed to get presigned URL:', error.message);
391
+ * }
392
+ * ```
393
+ */
394
+ export async function getFilePresignedUrl(fileId, expireTimeInSeconds = 3600, options) {
395
+ if (!fileId || fileId.trim() === "") {
396
+ throw new ApiError("fileId is required", 400, "9400");
397
+ }
398
+ const token = options?.appToken ?? (await getAppToken(options));
399
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
400
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
401
+ if (!base) {
402
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
403
+ }
404
+ const url = String(base).replace(/\/+$/, "") +
405
+ `/cms/v1/files/${encodeURIComponent(fileId)}/presigned-url`;
406
+ const urlObj = new URL(url);
407
+ if (expireTimeInSeconds !== undefined) {
408
+ urlObj.searchParams.append("expireTimeInSeconds", String(expireTimeInSeconds));
409
+ }
410
+ let response;
411
+ try {
412
+ response = await globalThis.fetch(urlObj.toString(), {
413
+ method: "GET",
414
+ headers: {
415
+ "Content-Type": "application/json",
416
+ "x-t-token": token,
417
+ },
418
+ });
419
+ }
420
+ catch (error) {
421
+ throw new NetworkError(`Failed to get presigned URL: ${error instanceof Error ? error.message : "Unknown error"}`);
422
+ }
423
+ const json = await response.json();
424
+ return parseApiResponse(json, "Failed to get presigned URL", response.status);
425
+ }
426
+ /**
427
+ * Batch gets presigned URLs for multiple files.
428
+ *
429
+ * @param fileIds - Array of file IDs (max 10)
430
+ * @param expireTimeInSeconds - Expiration time in seconds (default: 3600)
431
+ * @param options - Optional configuration
432
+ * @returns Promise resolving to array of presigned URL information or errors
433
+ * @throws {ConfigurationError} When required environment variables are missing
434
+ * @throws {ApiError} When API request fails
435
+ * @throws {NetworkError} When network request fails
436
+ *
437
+ * @example
438
+ * ```typescript
439
+ * import { batchGetFilePresignedUrl } from '@tale/client';
440
+ *
441
+ * try {
442
+ * const results = await batchGetFilePresignedUrl(
443
+ * ['file_id_1', 'file_id_2'],
444
+ * 3600
445
+ * );
446
+ * results.forEach(result => {
447
+ * if (result.error) {
448
+ * console.error('Error for file:', result.file_id, result.error);
449
+ * } else {
450
+ * console.log('URL:', result.presigned_url);
451
+ * }
452
+ * });
453
+ * } catch (error) {
454
+ * console.error('Failed to batch get presigned URLs:', error.message);
455
+ * }
456
+ * ```
457
+ */
458
+ export async function batchGetFilePresignedUrl(fileIds, expireTimeInSeconds = 3600, options) {
459
+ if (!fileIds || fileIds.length === 0) {
460
+ throw new ApiError("fileIds is required", 400, "9400");
461
+ }
462
+ if (fileIds.length > 10) {
463
+ throw new ApiError("Too many file IDs, max 10 allowed", 400, "9400");
464
+ }
465
+ const token = options?.appToken ?? (await getAppToken(options));
466
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
467
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
468
+ if (!base) {
469
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
470
+ }
471
+ const url = String(base).replace(/\/+$/, "") + "/cms/v1/files/batch-presigned-url";
472
+ let response;
473
+ try {
474
+ response = await globalThis.fetch(url, {
475
+ method: "POST",
476
+ headers: {
477
+ "Content-Type": "application/json",
478
+ "x-t-token": token,
479
+ },
480
+ body: JSON.stringify({
481
+ file_ids: fileIds,
482
+ expire_time_in_seconds: expireTimeInSeconds,
483
+ }),
484
+ });
485
+ }
486
+ catch (error) {
487
+ throw new NetworkError(`Failed to batch get presigned URLs: ${error instanceof Error ? error.message : "Unknown error"}`);
488
+ }
489
+ const json = await response.json();
490
+ return parseApiResponse(json, "Failed to batch get presigned URLs", response.status);
491
+ }
492
+ /**
493
+ * Gets OSS object metadata.
494
+ *
495
+ * @param ossKey - OSS key
496
+ * @param options - Optional configuration
497
+ * @returns Promise resolving to OSS metadata
498
+ * @throws {ConfigurationError} When required environment variables are missing
499
+ * @throws {ApiError} When API request fails
500
+ * @throws {NetworkError} When network request fails
501
+ *
502
+ * @example
503
+ * ```typescript
504
+ * import { getOssMetadata } from '@tale/client';
505
+ *
506
+ * try {
507
+ * const metadata = await getOssMetadata('cms/appkey/folder/fileid.pdf');
508
+ * console.log('File size:', metadata.content_length);
509
+ * console.log('Content type:', metadata.content_type);
510
+ * } catch (error) {
511
+ * console.error('Failed to get OSS metadata:', error.message);
512
+ * }
513
+ * ```
514
+ */
515
+ export async function getOssMetadata(ossKey, options) {
516
+ if (!ossKey || ossKey.trim() === "") {
517
+ throw new ApiError("ossKey is required", 400, "9400");
518
+ }
519
+ const token = options?.appToken ?? (await getAppToken(options));
520
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
521
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
522
+ if (!base) {
523
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
524
+ }
525
+ const url = new URL(String(base).replace(/\/+$/, "") + "/cms/v1/oss/metadata");
526
+ url.searchParams.append("key", ossKey);
527
+ let response;
528
+ try {
529
+ response = await globalThis.fetch(url.toString(), {
530
+ method: "GET",
531
+ headers: {
532
+ "Content-Type": "application/json",
533
+ "x-t-token": token,
534
+ },
535
+ });
536
+ }
537
+ catch (error) {
538
+ throw new NetworkError(`Failed to get OSS metadata: ${error instanceof Error ? error.message : "Unknown error"}`);
539
+ }
540
+ const json = await response.json();
541
+ return parseApiResponse(json, "Failed to get OSS metadata", response.status);
542
+ }
543
+ /**
544
+ * Gets upload authorization for a new file (presets OSS key + presigned upload URL).
545
+ *
546
+ * @param request - Upload authorization request
547
+ * @param options - Optional configuration
548
+ * @returns Promise resolving to upload authorization response
549
+ * @throws {ConfigurationError} When required environment variables are missing
550
+ * @throws {ApiError} When API request fails
551
+ * @throws {NetworkError} When network request fails
552
+ *
553
+ * @example
554
+ * ```typescript
555
+ * import { getUploadAuthorization } from '@tale/client';
556
+ *
557
+ * try {
558
+ * const auth = await getUploadAuthorization({
559
+ * folder_id: 'folder_id_here',
560
+ * file_name: 'document.pdf',
561
+ * file_type: 'pdf'
562
+ * });
563
+ * console.log('OSS Key:', auth.oss_key);
564
+ * console.log('Upload URL:', auth.presigned_url);
565
+ * console.log('File ID:', auth.file_id);
566
+ * // Use presigned_url to upload the file directly to OSS
567
+ * } catch (error) {
568
+ * console.error('Failed to get upload authorization:', error.message);
569
+ * }
570
+ * ```
571
+ */
572
+ export async function getUploadAuthorization(request, options) {
573
+ if (!request.folder_id || request.folder_id.trim() === "") {
574
+ throw new ApiError("folder_id is required", 400, "9400");
575
+ }
576
+ if (!request.file_name || request.file_name.trim() === "") {
577
+ throw new ApiError("file_name is required", 400, "9400");
578
+ }
579
+ if (!request.file_type || request.file_type.trim() === "") {
580
+ throw new ApiError("file_type is required", 400, "9400");
581
+ }
582
+ const token = options?.appToken ?? (await getAppToken(options));
583
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
584
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
585
+ if (!base) {
586
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
587
+ }
588
+ const url = String(base).replace(/\/+$/, "") + "/cms/v1/files/upload-authorization";
589
+ let response;
590
+ try {
591
+ response = await globalThis.fetch(url, {
592
+ method: "POST",
593
+ headers: {
594
+ "Content-Type": "application/json",
595
+ "x-t-token": token,
596
+ },
597
+ body: JSON.stringify(request),
598
+ });
599
+ }
600
+ catch (error) {
601
+ throw new NetworkError(`Failed to get upload authorization: ${error instanceof Error ? error.message : "Unknown error"}`);
602
+ }
603
+ const json = await response.json();
604
+ return parseApiResponse(json, "Failed to get upload authorization", response.status);
605
+ }
606
+ /**
607
+ * Gets STS credentials for uploading to an existing file.
608
+ *
609
+ * @param fileId - File ID
610
+ * @param fileExtension - File extension (e.g., ".pdf")
611
+ * @param durationSeconds - Credential duration in seconds (default: 1800)
612
+ * @param options - Optional configuration
613
+ * @returns Promise resolving to STS credentials
614
+ * @throws {ConfigurationError} When required environment variables are missing
615
+ * @throws {ApiError} When API request fails
616
+ * @throws {NetworkError} When network request fails
617
+ *
618
+ * @example
619
+ * ```typescript
620
+ * import { getFileStsCredentials } from '@tale/client';
621
+ *
622
+ * try {
623
+ * const credentials = await getFileStsCredentials('file_id_here', '.pdf', 1800);
624
+ * console.log('Access Key ID:', credentials.access_key_id);
625
+ * console.log('Secret Access Key:', credentials.secret_access_key);
626
+ * console.log('Session Token:', credentials.session_token);
627
+ * console.log('Upload Path:', credentials.upload_path);
628
+ * // Use these credentials to upload with OSS SDK
629
+ * } catch (error) {
630
+ * console.error('Failed to get STS credentials:', error.message);
631
+ * }
632
+ * ```
633
+ */
634
+ export async function getFileStsCredentials(fileId, fileExtension, durationSeconds = 1800, options) {
635
+ if (!fileId || fileId.trim() === "") {
636
+ throw new ApiError("fileId is required", 400, "9400");
637
+ }
638
+ if (!fileExtension || fileExtension.trim() === "") {
639
+ throw new ApiError("fileExtension is required", 400, "9400");
640
+ }
641
+ const token = options?.appToken ?? (await getAppToken(options));
642
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
643
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
644
+ if (!base) {
645
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
646
+ }
647
+ const url = String(base).replace(/\/+$/, "") +
648
+ `/cms/v1/files/${encodeURIComponent(fileId)}/sts-credentials`;
649
+ let response;
650
+ try {
651
+ response = await globalThis.fetch(url, {
652
+ method: "POST",
653
+ headers: {
654
+ "Content-Type": "application/json",
655
+ "x-t-token": token,
656
+ },
657
+ body: JSON.stringify({
658
+ file_extension: fileExtension,
659
+ duration_seconds: durationSeconds,
660
+ }),
661
+ });
662
+ }
663
+ catch (error) {
664
+ throw new NetworkError(`Failed to get STS credentials: ${error instanceof Error ? error.message : "Unknown error"}`);
665
+ }
666
+ const json = await response.json();
667
+ return parseApiResponse(json, "Failed to get STS credentials", response.status);
668
+ }
669
+ /**
670
+ * Marks file upload as complete and updates OSS information.
671
+ *
672
+ * @param fileId - File ID
673
+ * @param request - Upload completion information
674
+ * @param options - Optional configuration
675
+ * @returns Promise resolving to success message
676
+ * @throws {ConfigurationError} When required environment variables are missing
677
+ * @throws {ApiError} When API request fails
678
+ * @throws {NetworkError} When network request fails
679
+ *
680
+ * @example
681
+ * ```typescript
682
+ * import { fileUploadComplete } from '@tale/client';
683
+ *
684
+ * try {
685
+ * const result = await fileUploadComplete('file_id_here', {
686
+ * oss_key: 'cms/appkey/folder/fileid.pdf',
687
+ * file_size: 12345,
688
+ * etag: 'abc123'
689
+ * });
690
+ * console.log('Upload complete:', result.message);
691
+ * } catch (error) {
692
+ * console.error('Failed to mark upload complete:', error.message);
693
+ * }
694
+ * ```
695
+ */
696
+ export async function fileUploadComplete(fileId, request, options) {
697
+ if (!fileId || fileId.trim() === "") {
698
+ throw new ApiError("fileId is required", 400, "9400");
699
+ }
700
+ if (!request.oss_key || request.oss_key.trim() === "") {
701
+ throw new ApiError("oss_key is required", 400, "9400");
702
+ }
703
+ if (!request.file_size && request.file_size !== 0) {
704
+ throw new ApiError("file_size is required", 400, "9400");
705
+ }
706
+ if (!request.etag || request.etag.trim() === "") {
707
+ throw new ApiError("etag is required", 400, "9400");
708
+ }
709
+ const token = options?.appToken ?? (await getAppToken(options));
710
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
711
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
712
+ if (!base) {
713
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
714
+ }
715
+ const url = String(base).replace(/\/+$/, "") +
716
+ `/cms/v1/files/${encodeURIComponent(fileId)}/upload-complete`;
717
+ let response;
718
+ try {
719
+ response = await globalThis.fetch(url, {
720
+ method: "POST",
721
+ headers: {
722
+ "Content-Type": "application/json",
723
+ "x-t-token": token,
724
+ },
725
+ body: JSON.stringify(request),
726
+ });
727
+ }
728
+ catch (error) {
729
+ throw new NetworkError(`Failed to mark upload complete: ${error instanceof Error ? error.message : "Unknown error"}`);
730
+ }
731
+ const json = await response.json();
732
+ return parseApiResponse(json, "Failed to mark upload complete", response.status);
733
+ }
734
+ /**
735
+ * Sets a preview image for a file.
736
+ *
737
+ * @param fileId - File ID
738
+ * @param imageFile - Image file to upload (File or Blob)
739
+ * @param options - Optional configuration
740
+ * @returns Promise resolving to updated file
741
+ * @throws {ConfigurationError} When required environment variables are missing
742
+ * @throws {ApiError} When API request fails
743
+ * @throws {NetworkError} When network request fails
744
+ *
745
+ * @example
746
+ * ```typescript
747
+ * import { setFilePreviewImage } from '@tale/client';
748
+ *
749
+ * try {
750
+ * // Get file from input element
751
+ * const input = document.getElementById('previewInput');
752
+ * const file = input.files[0];
753
+ *
754
+ * const updatedFile = await setFilePreviewImage('file_id_here', file);
755
+ * console.log('Preview image set:', updatedFile.preview_image_url);
756
+ * } catch (error) {
757
+ * console.error('Failed to set preview image:', error.message);
758
+ * }
759
+ * ```
760
+ */
761
+ export async function setFilePreviewImage(fileId, imageFile, options) {
762
+ if (!fileId || fileId.trim() === "") {
763
+ throw new ApiError("fileId is required", 400, "9400");
764
+ }
765
+ if (!imageFile) {
766
+ throw new ApiError("imageFile is required", 400, "9400");
767
+ }
768
+ const token = options?.appToken ?? (await getAppToken(options));
769
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
770
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
771
+ if (!base) {
772
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
773
+ }
774
+ const url = String(base).replace(/\/+$/, "") +
775
+ `/cms/v1/files/${encodeURIComponent(fileId)}/preview-image`;
776
+ // Create FormData
777
+ const formData = new FormData();
778
+ // Handle File type which extends Blob
779
+ if (typeof File !== "undefined" && imageFile instanceof File) {
780
+ formData.append("file", imageFile, imageFile.name);
781
+ }
782
+ else {
783
+ formData.append("file", imageFile);
784
+ }
785
+ let response;
786
+ try {
787
+ response = await globalThis.fetch(url, {
788
+ method: "POST",
789
+ headers: {
790
+ "x-t-token": token,
791
+ },
792
+ body: formData,
793
+ });
794
+ }
795
+ catch (error) {
796
+ throw new NetworkError(`Failed to set preview image: ${error instanceof Error ? error.message : "Unknown error"}`);
797
+ }
798
+ const json = await response.json();
799
+ return parseApiResponse(json, "Failed to set preview image", response.status);
800
+ }