@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.
- package/LICENSE +21 -0
- package/README.md +56 -0
- package/dist/acl/index.d.ts +295 -0
- package/dist/acl/index.js +653 -0
- package/dist/acl/types.d.ts +142 -0
- package/dist/acl/types.js +1 -0
- package/dist/auth/index.d.ts +166 -0
- package/dist/auth/index.js +522 -0
- package/dist/auth/types.d.ts +127 -0
- package/dist/auth/types.js +1 -0
- package/dist/cms/file.d.ts +398 -0
- package/dist/cms/file.js +800 -0
- package/dist/cms/folder.d.ts +128 -0
- package/dist/cms/folder.js +294 -0
- package/dist/cms/index.d.ts +3 -0
- package/dist/cms/index.js +6 -0
- package/dist/cms/types.d.ts +157 -0
- package/dist/cms/types.js +1 -0
- package/dist/common/types.d.ts +91 -0
- package/dist/common/types.js +2 -0
- package/dist/errors.d.ts +52 -0
- package/dist/errors.js +109 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +12 -0
- package/dist/rbac/acl.d.ts +152 -0
- package/dist/rbac/acl.js +723 -0
- package/dist/rbac/index.d.ts +464 -0
- package/dist/rbac/index.js +1121 -0
- package/dist/rbac/rbac.d.ts +198 -0
- package/dist/rbac/rbac.js +984 -0
- package/dist/rbac/types.d.ts +125 -0
- package/dist/rbac/types.js +1 -0
- package/dist/rbac/user-group.d.ts +122 -0
- package/dist/rbac/user-group.js +570 -0
- package/dist/status.d.ts +40 -0
- package/dist/status.js +56 -0
- package/dist/task/index.d.ts +163 -0
- package/dist/task/index.js +495 -0
- package/dist/task/types.d.ts +116 -0
- package/dist/task/types.js +1 -0
- package/dist/task-type/index.d.ts +92 -0
- package/dist/task-type/index.js +256 -0
- package/dist/task-type/types.d.ts +54 -0
- package/dist/task-type/types.js +1 -0
- package/dist/token.d.ts +21 -0
- package/dist/token.js +114 -0
- package/dist/user/index.d.ts +267 -0
- package/dist/user/index.js +786 -0
- package/dist/user/types.d.ts +145 -0
- package/dist/user/types.js +1 -0
- package/dist/user-attribute/index.d.ts +186 -0
- package/dist/user-attribute/index.js +615 -0
- package/dist/user-attribute/types.d.ts +109 -0
- package/dist/user-attribute/types.js +1 -0
- package/dist/user-group/index.d.ts +231 -0
- package/dist/user-group/index.js +566 -0
- package/dist/user-group/types.d.ts +50 -0
- package/dist/user-group/types.js +1 -0
- 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
|
+
}
|