@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,116 @@
1
+ import type { CommonOptions, Attachment } from "../common/types.js";
2
+ /**
3
+ * UserTask entity (matches backend UserTaskVO)
4
+ */
5
+ export interface UserTask {
6
+ task_id: string;
7
+ app_id: string;
8
+ user_id: string;
9
+ task_title: string;
10
+ task_input: Record<string, unknown>;
11
+ task_output: Record<string, unknown>;
12
+ task_type: string;
13
+ task_status: string;
14
+ parent_task_id?: string;
15
+ created_at: string;
16
+ updated_at: string;
17
+ attachments?: Attachment[];
18
+ sub_tasks?: UserTask[];
19
+ }
20
+ /**
21
+ * Request for creating a user task
22
+ */
23
+ export interface CreateUserTaskRequest {
24
+ user_id: string;
25
+ task_title: string;
26
+ task_input?: Record<string, unknown>;
27
+ task_output?: Record<string, unknown>;
28
+ task_type?: string;
29
+ task_status?: string;
30
+ parent_task_id?: string;
31
+ remark?: string;
32
+ }
33
+ /**
34
+ * Request for updating a user task
35
+ */
36
+ export interface UpdateUserTaskRequest {
37
+ task_title?: string;
38
+ task_input?: Record<string, unknown>;
39
+ task_output?: Record<string, unknown>;
40
+ task_status?: string;
41
+ remark?: string;
42
+ }
43
+ /**
44
+ * Request for batch creating user tasks
45
+ */
46
+ export interface BatchCreateUserTasksRequest {
47
+ tasks: CreateUserTaskRequest[];
48
+ }
49
+ /**
50
+ * Request for batch querying user tasks
51
+ */
52
+ export interface BatchQueryUserTasksRequest {
53
+ task_ids: string[];
54
+ user_ids?: string[];
55
+ task_status?: string;
56
+ include_attachments?: boolean;
57
+ include_sub_tasks?: boolean;
58
+ }
59
+ /**
60
+ * Request for listing user tasks
61
+ */
62
+ export interface ListUserTasksRequest {
63
+ page?: number;
64
+ size?: number;
65
+ sort?: string;
66
+ user_ids?: string;
67
+ task_status?: string;
68
+ task_type?: string;
69
+ include_attachments?: boolean;
70
+ include_sub_tasks?: boolean;
71
+ }
72
+ /**
73
+ * Request for updating task status
74
+ */
75
+ export interface UpdateTaskStatusRequest {
76
+ task_status: string;
77
+ }
78
+ /**
79
+ * Result of a single task creation in batch
80
+ */
81
+ export interface UserTaskCreateResult {
82
+ index: number;
83
+ success: boolean;
84
+ task_id?: string;
85
+ message?: string;
86
+ }
87
+ /**
88
+ * Response for batch task creation
89
+ */
90
+ export interface BatchCreateUserTasksResponse {
91
+ success_count: number;
92
+ failure_count: number;
93
+ results: UserTaskCreateResult[];
94
+ }
95
+ /**
96
+ * Task statistics response
97
+ */
98
+ export interface TaskStatistics {
99
+ pending_count: number;
100
+ running_count: number;
101
+ completed_count: number;
102
+ failed_count: number;
103
+ cancelled_count: number;
104
+ total_count: number;
105
+ }
106
+ /**
107
+ * Task status response
108
+ */
109
+ export interface TaskStatusResponse {
110
+ task_status: string;
111
+ }
112
+ /**
113
+ * Options for user task operations
114
+ */
115
+ export interface UserTaskOptions extends CommonOptions {
116
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,92 @@
1
+ import type { TaskType, CreateTaskTypeRequest, UpdateTaskTypeRequest, ListTaskTypesRequest, TaskTypeOptions } from "./types.js";
2
+ import type { PageResponse } from "../common/types.js";
3
+ export type { TaskType, CreateTaskTypeRequest, UpdateTaskTypeRequest, ListTaskTypesRequest, TaskTypeOptions, };
4
+ /**
5
+ * Creates a new task type.
6
+ *
7
+ * @param request - Task type creation request
8
+ * @param options - Optional configuration
9
+ * @returns Promise resolving to created task type
10
+ * @throws {ConfigurationError} When required environment variables are missing
11
+ * @throws {ApiError} When API request fails
12
+ * @throws {NetworkError} When network request fails
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const taskType = await createTaskType({
17
+ * type_code: "daily_review",
18
+ * type_name: "Daily Review",
19
+ * description: "Daily review tasks",
20
+ * allow_multiple: true,
21
+ * is_enabled: true,
22
+ * });
23
+ * ```
24
+ */
25
+ export declare function createTaskType(request: CreateTaskTypeRequest, options?: TaskTypeOptions): Promise<TaskType>;
26
+ /**
27
+ * Updates an existing task type.
28
+ *
29
+ * @param typeId - Task type ID
30
+ * @param request - Task type update request
31
+ * @param options - Optional configuration
32
+ * @returns Promise resolving to updated task type
33
+ * @throws {ConfigurationError} When required environment variables are missing
34
+ * @throws {ApiError} When API request fails
35
+ * @throws {NetworkError} When network request fails
36
+ */
37
+ export declare function updateTaskType(typeId: string, request: UpdateTaskTypeRequest, options?: TaskTypeOptions): Promise<TaskType>;
38
+ /**
39
+ * Deletes a task type.
40
+ *
41
+ * @param typeId - Task type ID
42
+ * @param options - Optional configuration
43
+ * @throws {ConfigurationError} When required environment variables are missing
44
+ * @throws {ApiError} When API request fails
45
+ * @throws {NetworkError} When network request fails
46
+ */
47
+ export declare function deleteTaskType(typeId: string, options?: TaskTypeOptions): Promise<void>;
48
+ /**
49
+ * Gets a task type by ID or code.
50
+ *
51
+ * @param typeId - Task type ID or code
52
+ * @param options - Optional configuration
53
+ * @returns Promise resolving to task type
54
+ * @throws {ConfigurationError} When required environment variables are missing
55
+ * @throws {ApiError} When API request fails
56
+ * @throws {NetworkError} When network request fails
57
+ */
58
+ export declare function getTaskType(typeId: string, options?: TaskTypeOptions): Promise<TaskType>;
59
+ /**
60
+ * Lists task types with pagination and optional filtering.
61
+ *
62
+ * @param request - List request parameters
63
+ * @param options - Optional configuration
64
+ * @returns Promise resolving to paginated list of task types
65
+ * @throws {ConfigurationError} When required environment variables are missing
66
+ * @throws {ApiError} When API request fails
67
+ * @throws {NetworkError} When network request fails
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const result = await listTaskTypes({
72
+ * page: 0,
73
+ * size: 20,
74
+ * is_enabled: true,
75
+ * sort_by: "createdAt",
76
+ * sort_direction: "desc",
77
+ * });
78
+ * console.log(result.content); // Array of task types
79
+ * console.log(result.total); // Total count
80
+ * ```
81
+ */
82
+ export declare function listTaskTypes(request?: ListTaskTypesRequest & TaskTypeOptions): Promise<PageResponse<TaskType>>;
83
+ /**
84
+ * Lists all enabled task types (no pagination).
85
+ *
86
+ * @param options - Optional configuration
87
+ * @returns Promise resolving to array of enabled task types
88
+ * @throws {ConfigurationError} When required environment variables are missing
89
+ * @throws {ApiError} When API request fails
90
+ * @throws {NetworkError} When network request fails
91
+ */
92
+ export declare function listEnabledTaskTypes(options?: TaskTypeOptions): Promise<TaskType[]>;
@@ -0,0 +1,256 @@
1
+ import { getAppToken } from "../token.js";
2
+ import { ApiError, ConfigurationError, NetworkError } from "../errors.js";
3
+ // ==================== Helper Functions ====================
4
+ function parseApiResponse(json, errorMessage, statusCode) {
5
+ if (typeof json !== "object" || json === null) {
6
+ throw new ApiError(`Invalid response: ${errorMessage} - not an object`, statusCode);
7
+ }
8
+ const response = json;
9
+ if (response.code !== 200) {
10
+ const errorMsg = typeof response.msg === "string" ? response.msg : errorMessage;
11
+ throw new ApiError(errorMsg, statusCode, response.code);
12
+ }
13
+ if (!response.data) {
14
+ throw new ApiError(`Invalid response: ${errorMessage} - missing data`, statusCode);
15
+ }
16
+ return response.data;
17
+ }
18
+ function getBaseUrl(options) {
19
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
20
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
21
+ if (!base) {
22
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
23
+ }
24
+ return String(base).replace(/\/+$/, "");
25
+ }
26
+ // ==================== TaskType CRUD Operations ====================
27
+ /**
28
+ * Creates a new task type.
29
+ *
30
+ * @param request - Task type creation request
31
+ * @param options - Optional configuration
32
+ * @returns Promise resolving to created task type
33
+ * @throws {ConfigurationError} When required environment variables are missing
34
+ * @throws {ApiError} When API request fails
35
+ * @throws {NetworkError} When network request fails
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * const taskType = await createTaskType({
40
+ * type_code: "daily_review",
41
+ * type_name: "Daily Review",
42
+ * description: "Daily review tasks",
43
+ * allow_multiple: true,
44
+ * is_enabled: true,
45
+ * });
46
+ * ```
47
+ */
48
+ export async function createTaskType(request, options) {
49
+ const token = options?.appToken ?? (await getAppToken(options));
50
+ const base = getBaseUrl(options);
51
+ const url = new URL(base + "/task-type/v1/types");
52
+ let response;
53
+ try {
54
+ response = await globalThis.fetch(url.toString(), {
55
+ method: "POST",
56
+ headers: {
57
+ "Content-Type": "application/json",
58
+ "x-t-token": token,
59
+ },
60
+ body: JSON.stringify(request),
61
+ });
62
+ }
63
+ catch (error) {
64
+ throw new NetworkError(`Failed to create task type: ${error instanceof Error ? error.message : "Unknown error"}`);
65
+ }
66
+ const json = await response.json();
67
+ return parseApiResponse(json, "Failed to create task type", response.status);
68
+ }
69
+ /**
70
+ * Updates an existing task type.
71
+ *
72
+ * @param typeId - Task type ID
73
+ * @param request - Task type update request
74
+ * @param options - Optional configuration
75
+ * @returns Promise resolving to updated task type
76
+ * @throws {ConfigurationError} When required environment variables are missing
77
+ * @throws {ApiError} When API request fails
78
+ * @throws {NetworkError} When network request fails
79
+ */
80
+ export async function updateTaskType(typeId, request, options) {
81
+ const token = options?.appToken ?? (await getAppToken(options));
82
+ const base = getBaseUrl(options);
83
+ const url = new URL(base + `/task-type/v1/types/${encodeURIComponent(typeId)}`);
84
+ let response;
85
+ try {
86
+ response = await globalThis.fetch(url.toString(), {
87
+ method: "PUT",
88
+ headers: {
89
+ "Content-Type": "application/json",
90
+ "x-t-token": token,
91
+ },
92
+ body: JSON.stringify(request),
93
+ });
94
+ }
95
+ catch (error) {
96
+ throw new NetworkError(`Failed to update task type: ${error instanceof Error ? error.message : "Unknown error"}`);
97
+ }
98
+ const json = await response.json();
99
+ return parseApiResponse(json, "Failed to update task type", response.status);
100
+ }
101
+ /**
102
+ * Deletes a task type.
103
+ *
104
+ * @param typeId - Task type ID
105
+ * @param options - Optional configuration
106
+ * @throws {ConfigurationError} When required environment variables are missing
107
+ * @throws {ApiError} When API request fails
108
+ * @throws {NetworkError} When network request fails
109
+ */
110
+ export async function deleteTaskType(typeId, options) {
111
+ const token = options?.appToken ?? (await getAppToken(options));
112
+ const base = getBaseUrl(options);
113
+ const url = new URL(base + `/task-type/v1/types/${encodeURIComponent(typeId)}`);
114
+ let response;
115
+ try {
116
+ response = await globalThis.fetch(url.toString(), {
117
+ method: "DELETE",
118
+ headers: {
119
+ "Content-Type": "application/json",
120
+ "x-t-token": token,
121
+ },
122
+ });
123
+ }
124
+ catch (error) {
125
+ throw new NetworkError(`Failed to delete task type: ${error instanceof Error ? error.message : "Unknown error"}`);
126
+ }
127
+ const json = await response.json();
128
+ if (typeof json !== "object" || json === null) {
129
+ throw new ApiError("Invalid task type deletion response", response.status);
130
+ }
131
+ const apiResponse = json;
132
+ if (apiResponse.code !== 200) {
133
+ const errorMsg = typeof apiResponse.msg === "string"
134
+ ? apiResponse.msg
135
+ : "Failed to delete task type";
136
+ throw new ApiError(errorMsg, response.status, apiResponse.code);
137
+ }
138
+ }
139
+ /**
140
+ * Gets a task type by ID or code.
141
+ *
142
+ * @param typeId - Task type ID or code
143
+ * @param options - Optional configuration
144
+ * @returns Promise resolving to task type
145
+ * @throws {ConfigurationError} When required environment variables are missing
146
+ * @throws {ApiError} When API request fails
147
+ * @throws {NetworkError} When network request fails
148
+ */
149
+ export async function getTaskType(typeId, options) {
150
+ const token = options?.appToken ?? (await getAppToken(options));
151
+ const base = getBaseUrl(options);
152
+ const url = new URL(base + `/task-type/v1/types/${encodeURIComponent(typeId)}`);
153
+ let response;
154
+ try {
155
+ response = await globalThis.fetch(url.toString(), {
156
+ method: "GET",
157
+ headers: {
158
+ "Content-Type": "application/json",
159
+ "x-t-token": token,
160
+ },
161
+ });
162
+ }
163
+ catch (error) {
164
+ throw new NetworkError(`Failed to get task type: ${error instanceof Error ? error.message : "Unknown error"}`);
165
+ }
166
+ const json = await response.json();
167
+ return parseApiResponse(json, "Failed to get task type", response.status);
168
+ }
169
+ /**
170
+ * Lists task types with pagination and optional filtering.
171
+ *
172
+ * @param request - List request parameters
173
+ * @param options - Optional configuration
174
+ * @returns Promise resolving to paginated list of task types
175
+ * @throws {ConfigurationError} When required environment variables are missing
176
+ * @throws {ApiError} When API request fails
177
+ * @throws {NetworkError} When network request fails
178
+ *
179
+ * @example
180
+ * ```typescript
181
+ * const result = await listTaskTypes({
182
+ * page: 0,
183
+ * size: 20,
184
+ * is_enabled: true,
185
+ * sort_by: "createdAt",
186
+ * sort_direction: "desc",
187
+ * });
188
+ * console.log(result.content); // Array of task types
189
+ * console.log(result.total); // Total count
190
+ * ```
191
+ */
192
+ export async function listTaskTypes(request) {
193
+ const token = request?.appToken ?? (await getAppToken(request));
194
+ const base = getBaseUrl(request);
195
+ const url = new URL(base + "/task-type/v2/types");
196
+ const { appToken, baseUrl, ...requestParams } = request || {};
197
+ const queryParams = {
198
+ page: 0,
199
+ size: 20,
200
+ sort: "createdAt,desc",
201
+ ...requestParams,
202
+ };
203
+ Object.entries(queryParams).forEach(([key, value]) => {
204
+ if (value !== undefined) {
205
+ url.searchParams.append(key, String(value));
206
+ }
207
+ });
208
+ let response;
209
+ try {
210
+ response = await globalThis.fetch(url.toString(), {
211
+ method: "GET",
212
+ headers: {
213
+ "Content-Type": "application/json",
214
+ "x-t-token": token,
215
+ },
216
+ });
217
+ }
218
+ catch (error) {
219
+ throw new NetworkError(`Failed to list task types: ${error instanceof Error ? error.message : "Unknown error"}`);
220
+ }
221
+ const json = await response.json();
222
+ return parseApiResponse(json, "Failed to list task types", response.status);
223
+ }
224
+ /**
225
+ * Lists all enabled task types (no pagination).
226
+ *
227
+ * @param options - Optional configuration
228
+ * @returns Promise resolving to array of enabled task types
229
+ * @throws {ConfigurationError} When required environment variables are missing
230
+ * @throws {ApiError} When API request fails
231
+ * @throws {NetworkError} When network request fails
232
+ */
233
+ export async function listEnabledTaskTypes(options) {
234
+ const token = options?.appToken ?? (await getAppToken(options));
235
+ const base = getBaseUrl(options);
236
+ const url = new URL(base + "/task-type/v1/types/enabled");
237
+ let response;
238
+ try {
239
+ response = await globalThis.fetch(url.toString(), {
240
+ method: "GET",
241
+ headers: {
242
+ "Content-Type": "application/json",
243
+ "x-t-token": token,
244
+ },
245
+ });
246
+ }
247
+ catch (error) {
248
+ throw new NetworkError(`Failed to list enabled task types: ${error instanceof Error ? error.message : "Unknown error"}`);
249
+ }
250
+ const json = await response.json();
251
+ const result = parseApiResponse(json, "Failed to list enabled task types", response.status);
252
+ if (!Array.isArray(result)) {
253
+ throw new ApiError("Invalid enabled task types response: not an array", response.status);
254
+ }
255
+ return result;
256
+ }
@@ -0,0 +1,54 @@
1
+ import type { CommonOptions } from "../common/types.js";
2
+ /**
3
+ * TaskType entity (matches backend TaskTypeVO)
4
+ */
5
+ export interface TaskType {
6
+ type_id: string;
7
+ app_id: string;
8
+ type_code: string;
9
+ type_name: string;
10
+ description?: string;
11
+ allow_multiple: boolean;
12
+ is_enabled: boolean;
13
+ parent_task_type_id?: string;
14
+ created_at: string;
15
+ updated_at: string;
16
+ remark?: string;
17
+ }
18
+ /**
19
+ * Request for creating a task type
20
+ * Note: type_code is auto-generated by the backend
21
+ */
22
+ export interface CreateTaskTypeRequest {
23
+ type_name: string;
24
+ description?: string;
25
+ allow_multiple?: boolean;
26
+ is_enabled?: boolean;
27
+ parent_task_type_id?: string;
28
+ remark?: string;
29
+ }
30
+ /**
31
+ * Request for updating a task type
32
+ */
33
+ export interface UpdateTaskTypeRequest {
34
+ type_name?: string;
35
+ description?: string;
36
+ allow_multiple?: boolean;
37
+ is_enabled?: boolean;
38
+ parent_task_type_id?: string;
39
+ remark?: string;
40
+ }
41
+ /**
42
+ * Request for listing task types
43
+ */
44
+ export interface ListTaskTypesRequest {
45
+ page?: number;
46
+ size?: number;
47
+ sort?: string;
48
+ is_enabled?: boolean;
49
+ }
50
+ /**
51
+ * Options for task type operations
52
+ */
53
+ export interface TaskTypeOptions extends CommonOptions {
54
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { TaleSdkError, ConfigurationError, ApiError, EnvironmentError, TokenError, NetworkError, ValidationError, isTaleSdkError, createErrorFromUnknown } from "./errors.js";
2
+ export { TaleSdkError, ConfigurationError, ApiError, EnvironmentError, TokenError, NetworkError, ValidationError, isTaleSdkError, createErrorFromUnknown, };
3
+ export type AppTokenData = {
4
+ type: string;
5
+ app_key: string;
6
+ app_name: string;
7
+ token: string;
8
+ status: string;
9
+ expired_at: string;
10
+ };
11
+ export type AppTokenJson = {
12
+ data: AppTokenData;
13
+ code: number;
14
+ msg: string;
15
+ };
16
+ export type TokenRequestOptions = {
17
+ baseUrl?: string;
18
+ appKey?: string;
19
+ appSecret?: string;
20
+ };
21
+ export declare function getAppToken(options?: TokenRequestOptions): Promise<string>;
package/dist/token.js ADDED
@@ -0,0 +1,114 @@
1
+ import { TaleSdkError, ConfigurationError, ApiError, EnvironmentError, TokenError, NetworkError, ValidationError, isTaleSdkError, createErrorFromUnknown, } from "./errors.js";
2
+ export { TaleSdkError, ConfigurationError, ApiError, EnvironmentError, TokenError, NetworkError, ValidationError, isTaleSdkError, createErrorFromUnknown, };
3
+ let cached;
4
+ let expiryTimer;
5
+ let inFlight;
6
+ let inFlightKey;
7
+ function getEnv() {
8
+ return (globalThis?.process?.env ?? import.meta?.env ?? undefined);
9
+ }
10
+ function clearCache() {
11
+ cached = undefined;
12
+ if (expiryTimer) {
13
+ clearTimeout(expiryTimer);
14
+ expiryTimer = undefined;
15
+ }
16
+ }
17
+ function scheduleExpiry(expiredAt) {
18
+ const t = new Date(expiredAt).getTime();
19
+ const safetyMs = 10000;
20
+ const fallbackMs = 10 * 60 * 1000;
21
+ const now = Date.now();
22
+ // 修复时间戳溢出问题
23
+ let delay;
24
+ if (Number.isFinite(t)) {
25
+ const rawDelay = t - now - safetyMs;
26
+ // 检查是否在 32 位有符号整数范围内(-2^31 到 2^31-1,即 -2147483648 到 2147483647)
27
+ // Node.js setTimeout 的最大延迟值受限于系统,通常在 32 位范围内
28
+ const maxSafeDelay = 2147483647; // 最大 32 位有符号整数
29
+ if (rawDelay > maxSafeDelay) {
30
+ // 如果延迟时间过大,使用回退延迟
31
+ console.warn(`Token expiry delay too large (${rawDelay}ms), using fallback delay`);
32
+ delay = fallbackMs;
33
+ }
34
+ else {
35
+ delay = Math.max(rawDelay, 0);
36
+ }
37
+ }
38
+ else {
39
+ delay = fallbackMs;
40
+ }
41
+ if (expiryTimer)
42
+ clearTimeout(expiryTimer);
43
+ expiryTimer = setTimeout(clearCache, delay);
44
+ const unref = expiryTimer?.unref;
45
+ if (typeof unref === "function")
46
+ unref.call(expiryTimer);
47
+ }
48
+ async function fetchAppToken(options) {
49
+ const env = getEnv();
50
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
51
+ const appKey = options?.appKey ?? env?.TALE_APP_KEY ?? undefined;
52
+ const appSecret = options?.appSecret ?? env?.TALE_APP_SECRET ?? undefined;
53
+ if (!base || !appKey || !appSecret) {
54
+ throw new ConfigurationError("Missing required environment variables: TALE_BASE_URL, TALE_APP_KEY, TALE_APP_SECRET");
55
+ }
56
+ const url = String(base).replace(/\/+$/, "") + "/app/v1/token";
57
+ let response;
58
+ try {
59
+ response = await globalThis.fetch(url, {
60
+ method: "POST",
61
+ headers: { "Content-Type": "application/json" },
62
+ body: JSON.stringify({ app_key: appKey, app_secret: appSecret }),
63
+ });
64
+ }
65
+ catch (error) {
66
+ throw new ApiError(`Failed to fetch token: ${error instanceof Error ? error.message : "Unknown error"}`);
67
+ }
68
+ const json = (await response.json());
69
+ if (json?.code !== 200 || !json?.data?.token) {
70
+ const errorMsg = typeof json?.msg === "string" ? json.msg : "Token request failed";
71
+ throw new ApiError(errorMsg, json?.code);
72
+ }
73
+ return json;
74
+ }
75
+ function isTokenValid(info) {
76
+ if (!info)
77
+ return false;
78
+ const t = new Date(info.expired_at).getTime();
79
+ return Number.isFinite(t) && t > Date.now();
80
+ }
81
+ function isServerEnv() {
82
+ const hasWindow = typeof globalThis.window !== "undefined" &&
83
+ typeof globalThis.window.document !== "undefined";
84
+ const hasNode = typeof globalThis.process !== "undefined" &&
85
+ !!globalThis.process.versions?.node;
86
+ return !hasWindow && hasNode;
87
+ }
88
+ export async function getAppToken(options) {
89
+ if (!isServerEnv()) {
90
+ throw new EnvironmentError("getAppToken is server-only");
91
+ }
92
+ if (isTokenValid(cached)) {
93
+ return cached.token;
94
+ }
95
+ const env = getEnv();
96
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
97
+ const appKey = options?.appKey ?? env?.TALE_APP_KEY ?? undefined;
98
+ const appSecret = options?.appSecret ?? env?.TALE_APP_SECRET ?? undefined;
99
+ const reqKey = JSON.stringify([base, appKey, appSecret]);
100
+ if (!inFlight || inFlightKey !== reqKey) {
101
+ inFlight = fetchAppToken(options);
102
+ inFlightKey = reqKey;
103
+ }
104
+ try {
105
+ const json = await inFlight;
106
+ cached = json.data;
107
+ scheduleExpiry(cached.expired_at);
108
+ return cached.token;
109
+ }
110
+ finally {
111
+ inFlight = undefined;
112
+ inFlightKey = undefined;
113
+ }
114
+ }