@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,786 @@
1
+ import { getAppToken } from "../token.js";
2
+ import { ApiError, ConfigurationError, NetworkError } from "../errors.js";
3
+ /**
4
+ * Creates a new user in the Tale application.
5
+ *
6
+ * @param userData - User data to create the new user
7
+ * @param options - Optional configuration for the request
8
+ * @returns Promise resolving to the created user information
9
+ * @throws {ConfigurationError} When required environment variables are missing
10
+ * @throws {ApiError} When API request fails or returns invalid response
11
+ * @throws {NetworkError} When network request fails
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { createUser } from '@tale/client';
16
+ *
17
+ * try {
18
+ * const result = await createUser({
19
+ * username: 'john_doe',
20
+ * nickname: 'John Doe',
21
+ * email: 'john@example.com'
22
+ * });
23
+ * console.log('User created:', result.user.user_id);
24
+ * } catch (error) {
25
+ * console.error('Failed to create user:', error.message);
26
+ * }
27
+ * ```
28
+ */
29
+ export async function createUser(userData, options) {
30
+ // Validate required fields
31
+ if (!userData.username || userData.username.trim() === "") {
32
+ throw new ApiError("username is required", 400, "9400");
33
+ }
34
+ // Use provided app token or get one from token service
35
+ const token = options?.appToken ?? (await getAppToken(options));
36
+ // Determine base URL
37
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
38
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
39
+ if (!base) {
40
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
41
+ }
42
+ const url = String(base).replace(/\/+$/, "") + "/account/v1/user";
43
+ let response;
44
+ try {
45
+ response = await globalThis.fetch(url, {
46
+ method: "POST",
47
+ headers: {
48
+ "Content-Type": "application/json",
49
+ "x-t-token": token,
50
+ },
51
+ body: JSON.stringify(userData),
52
+ });
53
+ }
54
+ catch (error) {
55
+ throw new NetworkError(`Failed to create user: ${error instanceof Error ? error.message : "Unknown error"}`);
56
+ }
57
+ let json;
58
+ try {
59
+ const responseJson = await response.json();
60
+ json = responseJson;
61
+ }
62
+ catch (error) {
63
+ throw new ApiError(`Failed to parse user creation response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
64
+ }
65
+ // Handle API errors
66
+ if (json.code !== 200) {
67
+ const errorMsg = typeof json.msg === "string" ? json.msg : "User creation failed";
68
+ throw new ApiError(errorMsg, response.status, json.code);
69
+ }
70
+ // Validate response structure
71
+ if (!json.data || !json.data.user || !json.data.app) {
72
+ throw new ApiError("Invalid user creation response: missing required data", response.status);
73
+ }
74
+ return json.data;
75
+ }
76
+ /**
77
+ * Retrieves user information by ID or open ID.
78
+ *
79
+ * @param userId - Optional user ID (open_id) to query. If not provided, returns current user info
80
+ * @param options - Optional parameters for inclusion flags and configuration
81
+ * @returns Promise resolving to the user information
82
+ * @throws {ConfigurationError} When required environment variables are missing
83
+ * @throws {ApiError} When API request fails or returns invalid response
84
+ * @throws {NetworkError} When network request fails
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * import { getUserById } from '@tale/client';
89
+ *
90
+ * try {
91
+ * const result = await getUserById('user_open_id_here');
92
+ * console.log('User info:', result.user.username);
93
+ * } catch (error) {
94
+ * console.error('Failed to get user:', error.message);
95
+ * }
96
+ * ```
97
+ */
98
+ export async function getUserById(userId, options) {
99
+ // Use provided app token or get one from token service
100
+ const token = options?.appToken ?? (await getAppToken(options));
101
+ // Determine base URL
102
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
103
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
104
+ if (!base) {
105
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
106
+ }
107
+ // Build URL with query parameters
108
+ const url = new URL(String(base).replace(/\/+$/, "") + "/account/v1/user");
109
+ // Add query parameters
110
+ const queryParams = {
111
+ user_id: userId,
112
+ include_rbac: true,
113
+ include_login_methods: true,
114
+ include_user_groups: true,
115
+ include_acl: false,
116
+ ...options,
117
+ };
118
+ Object.entries(queryParams).forEach(([key, value]) => {
119
+ if (value !== undefined) {
120
+ url.searchParams.append(key, String(value));
121
+ }
122
+ });
123
+ let response;
124
+ try {
125
+ response = await globalThis.fetch(url.toString(), {
126
+ method: "GET",
127
+ headers: {
128
+ "Content-Type": "application/json",
129
+ "x-t-token": token,
130
+ },
131
+ });
132
+ }
133
+ catch (error) {
134
+ throw new NetworkError(`Failed to get user: ${error instanceof Error ? error.message : "Unknown error"}`);
135
+ }
136
+ let json;
137
+ try {
138
+ const responseJson = await response.json();
139
+ json = responseJson;
140
+ }
141
+ catch (error) {
142
+ throw new ApiError(`Failed to parse user response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
143
+ }
144
+ // Handle API errors
145
+ if (json.code !== 200) {
146
+ const errorMsg = typeof json.msg === "string" ? json.msg : "User retrieval failed";
147
+ throw new ApiError(errorMsg, response.status, json.code);
148
+ }
149
+ // Validate response structure
150
+ if (!json.data || !json.data.user || !json.data.app) {
151
+ throw new ApiError("Invalid user response: missing required data", response.status);
152
+ }
153
+ return json.data;
154
+ }
155
+ /**
156
+ * Deletes a user by ID or open ID.
157
+ *
158
+ * @param userId - User ID (open_id) to delete
159
+ * @param options - Optional configuration for the request
160
+ * @returns Promise resolving to the deletion result
161
+ * @throws {ConfigurationError} When required environment variables are missing
162
+ * @throws {ApiError} When API request fails or returns invalid response
163
+ * @throws {NetworkError} When network request fails
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * import { deleteUser } from '@tale/client';
168
+ *
169
+ * try {
170
+ * const result = await deleteUser('user_open_id_here');
171
+ * console.log('User deleted:', result.deleted);
172
+ * } catch (error) {
173
+ * console.error('Failed to delete user:', error.message);
174
+ * }
175
+ * ```
176
+ */
177
+ export async function deleteUser(userId, options) {
178
+ // Validate required fields
179
+ if (!userId || userId.trim() === "") {
180
+ throw new ApiError("user_id is required for deletion", 400, "9400");
181
+ }
182
+ // Use provided app token or get one from token service
183
+ const token = options?.appToken ?? (await getAppToken(options));
184
+ // Determine base URL
185
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
186
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
187
+ if (!base) {
188
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
189
+ }
190
+ const url = String(base).replace(/\/+$/, "") +
191
+ `/account/v1/users/${encodeURIComponent(userId)}`;
192
+ let response;
193
+ try {
194
+ response = await globalThis.fetch(url, {
195
+ method: "DELETE",
196
+ headers: {
197
+ "Content-Type": "application/json",
198
+ "x-t-token": token,
199
+ },
200
+ });
201
+ }
202
+ catch (error) {
203
+ throw new NetworkError(`Failed to delete user: ${error instanceof Error ? error.message : "Unknown error"}`);
204
+ }
205
+ let json;
206
+ try {
207
+ const responseJson = await response.json();
208
+ json = responseJson;
209
+ }
210
+ catch (error) {
211
+ throw new ApiError(`Failed to parse user deletion response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
212
+ }
213
+ // Handle API errors
214
+ if (json.code !== 200) {
215
+ const errorMsg = typeof json.msg === "string" ? json.msg : "User deletion failed";
216
+ throw new ApiError(errorMsg, response.status, json.code);
217
+ }
218
+ // Validate response structure
219
+ if (!json.data || json.data.deleted !== true) {
220
+ throw new ApiError("Invalid user deletion response: deletion not confirmed", response.status);
221
+ }
222
+ return json.data;
223
+ }
224
+ /**
225
+ * Lists users with pagination, filtering, and search capabilities.
226
+ *
227
+ * @param options - Optional parameters for pagination, filtering, and configuration
228
+ * @returns Promise resolving to paginated user list with metadata
229
+ * @throws {ConfigurationError} When required environment variables are missing
230
+ * @throws {ApiError} When API request fails or returns invalid response
231
+ * @throws {NetworkError} When network request fails
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * import { listUsers } from '@tale/client';
236
+ *
237
+ * try {
238
+ * const result = await listUsers({
239
+ * page: 0,
240
+ * size: 20,
241
+ * keyword: 'john',
242
+ * sort_by: 'username',
243
+ * sort_direction: 'asc'
244
+ * });
245
+ * console.log(`Found ${result.totalElements} users`);
246
+ * console.log('First user:', result.content[0].user.username);
247
+ * } catch (error) {
248
+ * console.error('Failed to list users:', error.message);
249
+ * }
250
+ * ```
251
+ */
252
+ export async function listUsers(options) {
253
+ // Use provided app token or get one from token service
254
+ const token = options?.appToken ?? (await getAppToken(options));
255
+ // Determine base URL
256
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
257
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
258
+ if (!base) {
259
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
260
+ }
261
+ // Build URL with query parameters
262
+ const url = new URL(String(base).replace(/\/+$/, "") + "/account/v1/users");
263
+ // Add query parameters with defaults
264
+ const queryParams = {
265
+ page: 0,
266
+ size: 20,
267
+ sort_by: "createdAt",
268
+ sort_direction: "desc",
269
+ include_attributes: false,
270
+ ...options,
271
+ };
272
+ // Handle array parameters (need to be comma-separated)
273
+ if (queryParams.user_groups && queryParams.user_groups.length > 0) {
274
+ url.searchParams.append("user_groups", queryParams.user_groups.join(","));
275
+ }
276
+ if (queryParams.user_roles && queryParams.user_roles.length > 0) {
277
+ url.searchParams.append("user_roles", queryParams.user_roles.join(","));
278
+ }
279
+ if (queryParams.user_ids && queryParams.user_ids.length > 0) {
280
+ url.searchParams.append("user_ids", queryParams.user_ids.join(","));
281
+ }
282
+ // Add other parameters
283
+ if (queryParams.page !== undefined) {
284
+ url.searchParams.append("page", String(queryParams.page));
285
+ }
286
+ if (queryParams.size !== undefined) {
287
+ url.searchParams.append("size", String(queryParams.size));
288
+ }
289
+ if (queryParams.sort_by) {
290
+ url.searchParams.append("sort_by", queryParams.sort_by);
291
+ }
292
+ if (queryParams.sort_direction) {
293
+ url.searchParams.append("sort_direction", queryParams.sort_direction);
294
+ }
295
+ if (queryParams.keyword) {
296
+ url.searchParams.append("keyword", queryParams.keyword);
297
+ }
298
+ if (queryParams.include_attributes !== undefined) {
299
+ url.searchParams.append("include_attributes", String(queryParams.include_attributes));
300
+ }
301
+ let response;
302
+ try {
303
+ response = await globalThis.fetch(url.toString(), {
304
+ method: "GET",
305
+ headers: {
306
+ "Content-Type": "application/json",
307
+ "x-t-token": token,
308
+ },
309
+ });
310
+ }
311
+ catch (error) {
312
+ throw new NetworkError(`Failed to list users: ${error instanceof Error ? error.message : "Unknown error"}`);
313
+ }
314
+ let json;
315
+ try {
316
+ const responseJson = await response.json();
317
+ json = responseJson;
318
+ }
319
+ catch (error) {
320
+ throw new ApiError(`Failed to parse users list response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
321
+ }
322
+ // Handle API errors
323
+ if (json.code !== 200) {
324
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Users list retrieval failed";
325
+ throw new ApiError(errorMsg, response.status, json.code);
326
+ }
327
+ // Validate response structure
328
+ if (!json.data || !Array.isArray(json.data.content)) {
329
+ throw new ApiError("Invalid users list response: missing required data", response.status);
330
+ }
331
+ return json.data;
332
+ }
333
+ /**
334
+ * Updates user information by user ID or open ID.
335
+ *
336
+ * @param userId - User ID (open_id) to update
337
+ * @param userData - User data to update
338
+ * @param options - Optional configuration for the request
339
+ * @returns Promise resolving to the update result
340
+ * @throws {ConfigurationError} When required environment variables are missing
341
+ * @throws {ApiError} When API request fails or returns invalid response
342
+ * @throws {NetworkError} When network request fails
343
+ *
344
+ * @example
345
+ * ```typescript
346
+ * import { updateUser } from '@tale/client';
347
+ *
348
+ * try {
349
+ * const result = await updateUser('user_open_id_here', {
350
+ * nick_name: 'John Doe',
351
+ * email: 'john@example.com'
352
+ * });
353
+ * console.log('User updated:', result.success);
354
+ * } catch (error) {
355
+ * console.error('Failed to update user:', error.message);
356
+ * }
357
+ * ```
358
+ */
359
+ export async function updateUser(userId, userData, options) {
360
+ // Validate required fields
361
+ if (!userId || userId.trim() === "") {
362
+ throw new ApiError("userId is required for update", 400, "9400");
363
+ }
364
+ // Use provided app token or get one from token service
365
+ const token = options?.appToken ?? (await getAppToken(options));
366
+ // Determine base URL
367
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
368
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
369
+ if (!base) {
370
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
371
+ }
372
+ const url = String(base).replace(/\/+$/, "") +
373
+ `/account/v1/user/${encodeURIComponent(userId)}`;
374
+ let response;
375
+ try {
376
+ response = await globalThis.fetch(url, {
377
+ method: "PUT",
378
+ headers: {
379
+ "Content-Type": "application/json",
380
+ "x-t-token": token,
381
+ },
382
+ body: JSON.stringify(userData),
383
+ });
384
+ }
385
+ catch (error) {
386
+ throw new NetworkError(`Failed to update user: ${error instanceof Error ? error.message : "Unknown error"}`);
387
+ }
388
+ let json;
389
+ try {
390
+ const responseJson = await response.json();
391
+ json = responseJson;
392
+ }
393
+ catch (error) {
394
+ throw new ApiError(`Failed to parse user update response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
395
+ }
396
+ // Handle API errors
397
+ if (json.code !== 200) {
398
+ const errorMsg = typeof json.msg === "string" ? json.msg : "User update failed";
399
+ throw new ApiError(errorMsg, response.status, json.code);
400
+ }
401
+ return {
402
+ success: true,
403
+ user_id: userId,
404
+ };
405
+ }
406
+ /**
407
+ * Updates user password.
408
+ *
409
+ * @param passwordData - Password data including user_id and encrypted password
410
+ * @param options - Optional configuration for the request
411
+ * @returns Promise resolving to the update result
412
+ * @throws {ConfigurationError} When required environment variables are missing
413
+ * @throws {ApiError} When API request fails or returns invalid response
414
+ * @throws {NetworkError} When network request fails
415
+ *
416
+ * @example
417
+ * ```typescript
418
+ * import { updateUserPassword } from '@tale/client';
419
+ *
420
+ * try {
421
+ * const result = await updateUserPassword({
422
+ * user_id: 'user_open_id_here',
423
+ * password_encrypted: 'encrypted_password_here'
424
+ * });
425
+ * console.log('Password updated:', result.success);
426
+ * } catch (error) {
427
+ * console.error('Failed to update password:', error.message);
428
+ * }
429
+ * ```
430
+ */
431
+ export async function updateUserPassword(passwordData, options) {
432
+ // Validate required fields
433
+ if (!passwordData.user_id || passwordData.user_id.trim() === "") {
434
+ throw new ApiError("user_id is required for password update", 400, "9400");
435
+ }
436
+ if (!passwordData.password_encrypted ||
437
+ passwordData.password_encrypted.trim() === "") {
438
+ throw new ApiError("password_encrypted is required", 400, "9400");
439
+ }
440
+ // Use provided app token or get one from token service
441
+ const token = options?.appToken ?? (await getAppToken(options));
442
+ // Determine base URL
443
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
444
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
445
+ if (!base) {
446
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
447
+ }
448
+ const url = String(base).replace(/\/+$/, "") + "/account/v1/user/password";
449
+ let response;
450
+ try {
451
+ response = await globalThis.fetch(url, {
452
+ method: "POST",
453
+ headers: {
454
+ "Content-Type": "application/json",
455
+ "x-t-token": token,
456
+ },
457
+ body: JSON.stringify(passwordData),
458
+ });
459
+ }
460
+ catch (error) {
461
+ throw new NetworkError(`Failed to update user password: ${error instanceof Error ? error.message : "Unknown error"}`);
462
+ }
463
+ let json;
464
+ try {
465
+ const responseJson = await response.json();
466
+ json = responseJson;
467
+ }
468
+ catch (error) {
469
+ throw new ApiError(`Failed to parse password update response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
470
+ }
471
+ // Handle API errors
472
+ if (json.code !== 200) {
473
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Password update failed";
474
+ throw new ApiError(errorMsg, response.status, json.code);
475
+ }
476
+ return {
477
+ success: true,
478
+ user_id: passwordData.user_id,
479
+ };
480
+ }
481
+ /**
482
+ * Uploads user avatar image.
483
+ *
484
+ * @param file - File object to upload as avatar
485
+ * @param userId - User ID (open_id) of the user
486
+ * @param options - Optional configuration for the request
487
+ * @returns Promise resolving to the upload result with avatar OSS key
488
+ * @throws {ConfigurationError} When required environment variables are missing
489
+ * @throws {ApiError} When API request fails or returns invalid response
490
+ * @throws {NetworkError} When network request fails
491
+ *
492
+ * @example
493
+ * ```typescript
494
+ * import { uploadAvatar } from '@tale/client';
495
+ *
496
+ * try {
497
+ * const fileInput = document.querySelector('input[type="file"]');
498
+ * const file = fileInput.files[0];
499
+ * const result = await uploadAvatar(file, 'user_open_id_here');
500
+ * console.log('Avatar uploaded:', result.avatar_oss_key);
501
+ * } catch (error) {
502
+ * console.error('Failed to upload avatar:', error.message);
503
+ * }
504
+ * ```
505
+ */
506
+ export async function uploadAvatar(file, userId, options) {
507
+ // Validate required fields
508
+ if (!file) {
509
+ throw new ApiError("file is required for avatar upload", 400, "9400");
510
+ }
511
+ if (!userId || userId.trim() === "") {
512
+ throw new ApiError("userId is required for avatar upload", 400, "9400");
513
+ }
514
+ // Use provided app token or get one from token service
515
+ const token = options?.appToken ?? (await getAppToken(options));
516
+ // Determine base URL
517
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
518
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
519
+ if (!base) {
520
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
521
+ }
522
+ const url = String(base).replace(/\/+$/, "") + "/account/v1/user/avatar/upload";
523
+ // Create FormData
524
+ const formData = new FormData();
525
+ formData.append("file", file);
526
+ formData.append("user_open_id", userId);
527
+ let response;
528
+ try {
529
+ response = await globalThis.fetch(url, {
530
+ method: "POST",
531
+ headers: {
532
+ "x-t-token": token,
533
+ },
534
+ body: formData,
535
+ });
536
+ }
537
+ catch (error) {
538
+ throw new NetworkError(`Failed to upload avatar: ${error instanceof Error ? error.message : "Unknown error"}`);
539
+ }
540
+ let json;
541
+ try {
542
+ const responseJson = await response.json();
543
+ json = responseJson;
544
+ }
545
+ catch (error) {
546
+ throw new ApiError(`Failed to parse avatar upload response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
547
+ }
548
+ // Handle API errors
549
+ if (json.code !== 200) {
550
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Avatar upload failed";
551
+ throw new ApiError(errorMsg, response.status, json.code);
552
+ }
553
+ // Validate response structure
554
+ if (!json.data || !json.data.avatar_oss_key) {
555
+ throw new ApiError("Invalid avatar upload response: missing avatar_oss_key", response.status);
556
+ }
557
+ return json.data;
558
+ }
559
+ /**
560
+ * Gets presigned URL for avatar access.
561
+ *
562
+ * @param ossKey - OSS key of the avatar
563
+ * @param options - Optional configuration for the request
564
+ * @returns Promise resolving to presigned URL information
565
+ * @throws {ConfigurationError} When required environment variables are missing
566
+ * @throws {ApiError} When API request fails or returns invalid response
567
+ * @throws {NetworkError} When network request fails
568
+ *
569
+ * @example
570
+ * ```typescript
571
+ * import { getAvatarPresignedUrl } from '@tale/client';
572
+ *
573
+ * try {
574
+ * const result = await getAvatarPresignedUrl('avatars/user123.jpg');
575
+ * console.log('Presigned URL:', result.presignedUrl);
576
+ * console.log('Expires in:', result.expireTimeInSeconds, 'seconds');
577
+ * } catch (error) {
578
+ * console.error('Failed to get presigned URL:', error.message);
579
+ * }
580
+ * ```
581
+ */
582
+ export async function getAvatarPresignedUrl(ossKey, options) {
583
+ // Validate required fields
584
+ if (!ossKey || ossKey.trim() === "") {
585
+ throw new ApiError("ossKey is required", 400, "9400");
586
+ }
587
+ // Use provided app token or get one from token service
588
+ const token = options?.appToken ?? (await getAppToken(options));
589
+ // Determine base URL
590
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
591
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
592
+ if (!base) {
593
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
594
+ }
595
+ const url = new URL(String(base).replace(/\/+$/, "") + "/cms/file/getPresignedUrl");
596
+ url.searchParams.append("ossKey", ossKey);
597
+ let response;
598
+ try {
599
+ response = await globalThis.fetch(url.toString(), {
600
+ method: "GET",
601
+ headers: {
602
+ "Content-Type": "application/json",
603
+ "x-t-token": token,
604
+ },
605
+ });
606
+ }
607
+ catch (error) {
608
+ throw new NetworkError(`Failed to get avatar presigned URL: ${error instanceof Error ? error.message : "Unknown error"}`);
609
+ }
610
+ let json;
611
+ try {
612
+ const responseJson = await response.json();
613
+ json = responseJson;
614
+ }
615
+ catch (error) {
616
+ throw new ApiError(`Failed to parse presigned URL response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
617
+ }
618
+ // Handle API errors
619
+ if (json.code !== 200) {
620
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to get presigned URL";
621
+ throw new ApiError(errorMsg, response.status, json.code);
622
+ }
623
+ // Validate response structure
624
+ if (!json.data || !json.data.presignedUrl) {
625
+ throw new ApiError("Invalid presigned URL response: missing presignedUrl", response.status);
626
+ }
627
+ return json.data;
628
+ }
629
+ /**
630
+ * Updates user frozen status (freeze or unfreeze a user account).
631
+ *
632
+ * @param userId - User ID (open_id) to update frozen status
633
+ * @param frozenData - Frozen status data including is_frozen flag and optional remark
634
+ * @param options - Optional configuration for the request
635
+ * @returns Promise resolving to the updated frozen status information
636
+ * @throws {ConfigurationError} When required environment variables are missing
637
+ * @throws {ApiError} When API request fails or returns invalid response
638
+ * @throws {NetworkError} When network request fails
639
+ *
640
+ * @example
641
+ * ```typescript
642
+ * import { updateUserFrozenStatus } from '@tale/client';
643
+ *
644
+ * try {
645
+ * // Freeze a user account
646
+ * const result = await updateUserFrozenStatus('user_open_id_here', {
647
+ * is_frozen: true,
648
+ * remark: 'Violated community guidelines'
649
+ * });
650
+ * console.log('User frozen:', result.is_frozen);
651
+ *
652
+ * // Unfreeze a user account
653
+ * const unfrozenResult = await updateUserFrozenStatus('user_open_id_here', {
654
+ * is_frozen: false,
655
+ * remark: 'Account reactivated'
656
+ * });
657
+ * console.log('User unfrozen:', !unfrozenResult.is_frozen);
658
+ * } catch (error) {
659
+ * console.error('Failed to update frozen status:', error.message);
660
+ * }
661
+ * ```
662
+ */
663
+ export async function updateUserFrozenStatus(userId, frozenData, options) {
664
+ // Validate required fields
665
+ if (!userId || userId.trim() === "") {
666
+ throw new ApiError("userId is required for updating frozen status", 400, "9400");
667
+ }
668
+ if (frozenData.is_frozen === undefined || frozenData.is_frozen === null) {
669
+ throw new ApiError("is_frozen is required", 400, "9400");
670
+ }
671
+ // Use provided app token or get one from token service
672
+ const token = options?.appToken ?? (await getAppToken(options));
673
+ // Determine base URL
674
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
675
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
676
+ if (!base) {
677
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
678
+ }
679
+ const url = String(base).replace(/\/+$/, "") +
680
+ `/account/v1/user/${encodeURIComponent(userId)}/frozen-status`;
681
+ let response;
682
+ try {
683
+ response = await globalThis.fetch(url, {
684
+ method: "PUT",
685
+ headers: {
686
+ "Content-Type": "application/json",
687
+ "x-t-token": token,
688
+ },
689
+ body: JSON.stringify(frozenData),
690
+ });
691
+ }
692
+ catch (error) {
693
+ throw new NetworkError(`Failed to update user frozen status: ${error instanceof Error ? error.message : "Unknown error"}`);
694
+ }
695
+ let json;
696
+ try {
697
+ const responseJson = await response.json();
698
+ json = responseJson;
699
+ }
700
+ catch (error) {
701
+ throw new ApiError(`Failed to parse frozen status update response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
702
+ }
703
+ // Handle API errors
704
+ if (json.code !== 200) {
705
+ const errorMsg = typeof json.msg === "string"
706
+ ? json.msg
707
+ : "Failed to update frozen status";
708
+ throw new ApiError(errorMsg, response.status, json.code);
709
+ }
710
+ // Validate response structure
711
+ if (!json.data || json.data.user_id === undefined) {
712
+ throw new ApiError("Invalid frozen status update response: missing required data", response.status);
713
+ }
714
+ return json.data;
715
+ }
716
+ /**
717
+ * Gets user frozen status by user ID.
718
+ *
719
+ * @param userId - User ID (open_id) to query frozen status
720
+ * @param options - Optional configuration for the request
721
+ * @returns Promise resolving to the user frozen status information
722
+ * @throws {ConfigurationError} When required environment variables are missing
723
+ * @throws {ApiError} When API request fails or returns invalid response
724
+ * @throws {NetworkError} When network request fails
725
+ *
726
+ * @example
727
+ * ```typescript
728
+ * import { getUserFrozenStatus } from '@tale/client';
729
+ *
730
+ * try {
731
+ * const status = await getUserFrozenStatus('user_open_id_here');
732
+ * console.log('User is frozen:', status.is_frozen);
733
+ * console.log('Remark:', status.remark);
734
+ * console.log('Last updated:', status.updated_at);
735
+ * } catch (error) {
736
+ * console.error('Failed to get frozen status:', error.message);
737
+ * }
738
+ * ```
739
+ */
740
+ export async function getUserFrozenStatus(userId, options) {
741
+ // Validate required fields
742
+ if (!userId || userId.trim() === "") {
743
+ throw new ApiError("userId is required for getting frozen status", 400, "9400");
744
+ }
745
+ // Use provided app token or get one from token service
746
+ const token = options?.appToken ?? (await getAppToken(options));
747
+ // Determine base URL
748
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
749
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
750
+ if (!base) {
751
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
752
+ }
753
+ const url = String(base).replace(/\/+$/, "") +
754
+ `/account/v1/user/${encodeURIComponent(userId)}/frozen-status`;
755
+ let response;
756
+ try {
757
+ response = await globalThis.fetch(url, {
758
+ method: "GET",
759
+ headers: {
760
+ "Content-Type": "application/json",
761
+ "x-t-token": token,
762
+ },
763
+ });
764
+ }
765
+ catch (error) {
766
+ throw new NetworkError(`Failed to get user frozen status: ${error instanceof Error ? error.message : "Unknown error"}`);
767
+ }
768
+ let json;
769
+ try {
770
+ const responseJson = await response.json();
771
+ json = responseJson;
772
+ }
773
+ catch (error) {
774
+ throw new ApiError(`Failed to parse frozen status response: ${error instanceof Error ? error.message : "Invalid JSON"}`, response.status);
775
+ }
776
+ // Handle API errors
777
+ if (json.code !== 200) {
778
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to get frozen status";
779
+ throw new ApiError(errorMsg, response.status, json.code);
780
+ }
781
+ // Validate response structure
782
+ if (!json.data || json.data.user_id === undefined) {
783
+ throw new ApiError("Invalid frozen status response: missing required data", response.status);
784
+ }
785
+ return json.data;
786
+ }