tale-js-sdk 0.1.4 → 1.1.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/dist/acl/index.js CHANGED
@@ -1,747 +1,683 @@
1
- import { getAppToken } from '../token.js';
2
- import { ApiError, ConfigurationError, NetworkError } from '../errors.js';
3
- // ===== ACL Record 管理 =====
1
+ import { getAppToken } from "../token.js";
2
+ import { ApiError, ConfigurationError, NetworkError } from "../errors.js";
3
+ // ==================== Helper Functions ====================
4
4
  /**
5
- * Creates a new ACL record in the Tale application.
5
+ * Parses standard API response format: { code, msg, data }
6
+ */
7
+ function parseApiResponse(json, errorMessage, statusCode) {
8
+ if (typeof json !== 'object' || json === null) {
9
+ throw new ApiError(`Invalid response: ${errorMessage} - not an object`, statusCode);
10
+ }
11
+ const response = json;
12
+ if (response.code !== 200) {
13
+ const errorMsg = typeof response.msg === "string" ? response.msg : errorMessage;
14
+ throw new ApiError(errorMsg, statusCode, response.code);
15
+ }
16
+ if (!response.data) {
17
+ throw new ApiError(`Invalid response: ${errorMessage} - missing data`, statusCode);
18
+ }
19
+ return response.data;
20
+ }
21
+ // ==================== ACL Record Management (v2) ====================
22
+ /**
23
+ * Gets an ACL record by ID.
6
24
  *
7
- * @param recordData - ACL record data to create
8
- * @param options - Optional configuration for the request
9
- * @returns Promise resolving to the created ACL record information
25
+ * @param recordId - Record ID
26
+ * @param options - Optional configuration
27
+ * @returns Promise resolving to ACL record information
10
28
  * @throws {ConfigurationError} When required environment variables are missing
11
- * @throws {ApiError} When API request fails or returns invalid response
29
+ * @throws {ApiError} When API request fails
12
30
  * @throws {NetworkError} When network request fails
13
31
  *
14
32
  * @example
15
33
  * ```typescript
16
- * import { createRecord } from '@tale/client';
34
+ * import { getAclRecord } from '@tale/client';
17
35
  *
18
36
  * try {
19
- * const result = await createRecord({
20
- * template_id: 'template_user_read',
21
- * subject_type: 'user',
22
- * subject_id: 'user_123',
23
- * resource_type: 'document',
24
- * resource_id: 'doc_456',
25
- * effect_type: 'allow',
26
- * priority: 50,
27
- * description: 'Allow user to read document'
28
- * });
29
- * console.log('ACL record created:', result.record.record_id);
37
+ * const record = await getAclRecord('record_id_here');
38
+ * console.log('Record effect:', record.effect_type);
30
39
  * } catch (error) {
31
- * console.error('Failed to create ACL record:', error.message);
40
+ * console.error('Failed to get ACL record:', error.message);
32
41
  * }
33
42
  * ```
34
43
  */
35
- export async function createRecord(recordData, options) {
36
- // Validate required fields
37
- if (!recordData.template_id || recordData.template_id.trim() === '') {
38
- throw new ApiError('template_id is required for ACL record creation', 400, '9400');
39
- }
40
- if (!recordData.subject_type || !['user', 'role', 'group'].includes(recordData.subject_type)) {
41
- throw new ApiError('subject_type is required and must be one of: user, role, group', 400, '9400');
42
- }
43
- if (!recordData.resource_type || recordData.resource_type.trim() === '') {
44
- throw new ApiError('resource_type is required for ACL record creation', 400, '9400');
45
- }
46
- if (!recordData.subject_id && !recordData.subject_identifier) {
47
- throw new ApiError('Either subject_id or subject_identifier is required', 400, '9400');
48
- }
49
- if (!recordData.resource_id && !recordData.resource_identifier) {
50
- throw new ApiError('Either resource_id or resource_identifier is required', 400, '9400');
51
- }
52
- if (!recordData.effect_type || !['allow', 'deny', 'inherit'].includes(recordData.effect_type)) {
53
- throw new ApiError('effect_type is required and must be one of: allow, deny, inherit', 400, '9400');
44
+ export async function getAclRecord(recordId, options) {
45
+ if (!recordId || recordId.trim() === "") {
46
+ throw new ApiError("record_id is required", 400, "9400");
54
47
  }
55
- // Use provided app token or get one from token service
56
- const token = options?.appToken ?? await getAppToken(options);
57
- // Determine base URL
48
+ const token = options?.appToken ?? (await getAppToken(options));
58
49
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
59
50
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
60
51
  if (!base) {
61
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
52
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
62
53
  }
63
- const url = String(base).replace(/\/+$/, '') + '/acl/v1/records';
64
- // Validate priority range
65
- if (recordData.priority !== undefined && (recordData.priority < 0 || recordData.priority > 100)) {
66
- throw new ApiError('priority must be between 0 and 100', 400, '9400');
67
- }
68
- // Set default priority if not provided
69
- const finalRecordData = {
70
- ...recordData,
71
- priority: recordData.priority ?? 50
72
- };
54
+ const url = String(base).replace(/\/+$/, "") +
55
+ `/acl/v2/records/${encodeURIComponent(recordId)}`;
73
56
  let response;
74
57
  try {
75
58
  response = await globalThis.fetch(url, {
76
- method: 'POST',
59
+ method: "GET",
77
60
  headers: {
78
- 'Content-Type': 'application/json',
79
- 'x-t-token': token,
61
+ "Content-Type": "application/json",
62
+ "x-t-token": token,
80
63
  },
81
- body: JSON.stringify(finalRecordData),
82
64
  });
83
65
  }
84
66
  catch (error) {
85
- throw new NetworkError(`Failed to create ACL record: ${error instanceof Error ? error.message : 'Unknown error'}`);
67
+ throw new NetworkError(`Failed to get ACL record: ${error instanceof Error ? error.message : "Unknown error"}`);
68
+ }
69
+ const json = await response.json();
70
+ return parseApiResponse(json, "Failed to get ACL record", response.status);
71
+ }
72
+ /**
73
+ * Lists ACL records with pagination and optional filtering.
74
+ *
75
+ * @param options - Optional parameters for pagination and filtering
76
+ * @returns Promise resolving to paginated ACL record list
77
+ * @throws {ConfigurationError} When required environment variables are missing
78
+ * @throws {ApiError} When API request fails
79
+ * @throws {NetworkError} When network request fails
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * import { listAclRecords } from '@tale/client';
84
+ *
85
+ * try {
86
+ * const result = await listAclRecords({
87
+ * page: 0,
88
+ * size: 20,
89
+ * resource_type: 'document'
90
+ * });
91
+ * console.log(`Found ${result.totalElements} records`);
92
+ * } catch (error) {
93
+ * console.error('Failed to list ACL records:', error.message);
94
+ * }
95
+ * ```
96
+ */
97
+ export async function listAclRecords(options) {
98
+ const token = options?.appToken ?? (await getAppToken(options));
99
+ const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
100
+ const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
101
+ if (!base) {
102
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
86
103
  }
87
- let json;
104
+ const url = new URL(String(base).replace(/\/+$/, "") + "/acl/v2/records");
105
+ // 分离 AclOptions 字段,只保留请求参数
106
+ const { appToken, baseUrl, ...requestParams } = options || {};
107
+ const queryParams = {
108
+ page: 0,
109
+ size: 20,
110
+ ...requestParams,
111
+ };
112
+ Object.entries(queryParams).forEach(([key, value]) => {
113
+ if (value !== undefined) {
114
+ url.searchParams.append(key, String(value));
115
+ }
116
+ });
117
+ let response;
88
118
  try {
89
- const responseJson = await response.json();
90
- json = responseJson;
119
+ response = await globalThis.fetch(url.toString(), {
120
+ method: "GET",
121
+ headers: {
122
+ "Content-Type": "application/json",
123
+ "x-t-token": token,
124
+ },
125
+ });
91
126
  }
92
127
  catch (error) {
93
- throw new ApiError(`Failed to parse ACL record creation response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
128
+ throw new NetworkError(`Failed to list ACL records: ${error instanceof Error ? error.message : "Unknown error"}`);
94
129
  }
95
- // Handle API errors
96
- if (json.code !== 200) {
97
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL record creation failed';
98
- throw new ApiError(errorMsg, response.status, json.code);
130
+ const json = await response.json();
131
+ const data = parseApiResponse(json, "Failed to list ACL records", response.status);
132
+ if (!Array.isArray(data.content)) {
133
+ throw new ApiError("Invalid ACL records response: content is not an array", response.status);
99
134
  }
100
- // Validate response structure
101
- if (!json.data || !json.data.record) {
102
- throw new ApiError('Invalid ACL record creation response: missing record data', response.status);
103
- }
104
- return json.data;
135
+ return data;
105
136
  }
106
137
  /**
107
- * Updates an existing ACL record by ID.
138
+ * Creates a new ACL record.
108
139
  *
109
- * @param recordId - ACL record ID to update
110
- * @param updateData - ACL record information to update
111
- * @param options - Optional configuration for the request
112
- * @returns Promise resolving to the updated ACL record information
140
+ * @param request - ACL record creation request
141
+ * @param options - Optional configuration
142
+ * @returns Promise resolving to created ACL record
113
143
  * @throws {ConfigurationError} When required environment variables are missing
114
- * @throws {ApiError} When API request fails or returns invalid response
144
+ * @throws {ApiError} When API request fails
115
145
  * @throws {NetworkError} When network request fails
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * import { createAclRecord } from '@tale/client';
150
+ *
151
+ * try {
152
+ * const record = await createAclRecord({
153
+ * subject_type: 'user',
154
+ * subject_id: 'user123',
155
+ * resource_type: 'document',
156
+ * resource_id: 'doc456',
157
+ * effect_type: 'allow'
158
+ * });
159
+ * console.log('Record created:', record.record_id);
160
+ * } catch (error) {
161
+ * console.error('Failed to create ACL record:', error.message);
162
+ * }
163
+ * ```
116
164
  */
117
- export async function updateRecord(recordId, updateData, options) {
118
- // Validate required fields
119
- if (!recordId || recordId.trim() === '') {
120
- throw new ApiError('record_id is required for ACL record update', 400, '9400');
165
+ export async function createAclRecord(request, options) {
166
+ if (!request.subject_type || request.subject_type.trim() === "") {
167
+ throw new ApiError("subject_type is required", 400, "9400");
121
168
  }
122
- if (updateData.effect_type && !['allow', 'deny', 'inherit'].includes(updateData.effect_type)) {
123
- throw new ApiError('effect_type must be one of: allow, deny, inherit', 400, '9400');
169
+ if (!request.resource_type || request.resource_type.trim() === "") {
170
+ throw new ApiError("resource_type is required", 400, "9400");
124
171
  }
125
- // Validate priority range
126
- if (updateData.priority !== undefined && (updateData.priority < 0 || updateData.priority > 100)) {
127
- throw new ApiError('priority must be between 0 and 100', 400, '9400');
172
+ if (!request.effect_type || request.effect_type.trim() === "") {
173
+ throw new ApiError("effect_type is required", 400, "9400");
128
174
  }
129
- // Use provided app token or get one from token service
130
- const token = options?.appToken ?? await getAppToken(options);
131
- // Determine base URL
175
+ const token = options?.appToken ?? (await getAppToken(options));
132
176
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
133
177
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
134
178
  if (!base) {
135
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
179
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
136
180
  }
137
- const url = String(base).replace(/\/+$/, '') + `/acl/v1/records/${encodeURIComponent(recordId)}`;
181
+ const url = String(base).replace(/\/+$/, "") + "/acl/v2/records";
138
182
  let response;
139
183
  try {
140
184
  response = await globalThis.fetch(url, {
141
- method: 'PUT',
185
+ method: "POST",
142
186
  headers: {
143
- 'Content-Type': 'application/json',
144
- 'x-t-token': token,
187
+ "Content-Type": "application/json",
188
+ "x-t-token": token,
145
189
  },
146
- body: JSON.stringify(updateData),
190
+ body: JSON.stringify(request),
147
191
  });
148
192
  }
149
193
  catch (error) {
150
- throw new NetworkError(`Failed to update ACL record: ${error instanceof Error ? error.message : 'Unknown error'}`);
151
- }
152
- let json;
153
- try {
154
- const responseJson = await response.json();
155
- json = responseJson;
156
- }
157
- catch (error) {
158
- throw new ApiError(`Failed to parse ACL record update response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
159
- }
160
- // Handle API errors
161
- if (json.code !== 200) {
162
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL record update failed';
163
- throw new ApiError(errorMsg, response.status, json.code);
194
+ throw new NetworkError(`Failed to create ACL record: ${error instanceof Error ? error.message : "Unknown error"}`);
164
195
  }
165
- // Validate response structure
166
- if (!json.data || !json.data.record) {
167
- throw new ApiError('Invalid ACL record update response: missing record data', response.status);
168
- }
169
- return json.data;
196
+ const json = await response.json();
197
+ return parseApiResponse(json, "Failed to create ACL record", response.status);
170
198
  }
171
199
  /**
172
- * Deletes an ACL record by ID.
200
+ * Batch creates ACL records.
173
201
  *
174
- * @param recordId - ACL record ID to delete
175
- * @param options - Optional configuration for the request
176
- * @returns Promise resolving to the deletion result
202
+ * @param requests - Array of ACL record creation requests
203
+ * @param options - Optional configuration
204
+ * @returns Promise resolving to batch creation response with success/failure details
177
205
  * @throws {ConfigurationError} When required environment variables are missing
178
- * @throws {ApiError} When API request fails or returns invalid response
206
+ * @throws {ApiError} When API request fails
179
207
  * @throws {NetworkError} When network request fails
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * import { batchCreateAclRecords } from '@tale/client';
212
+ *
213
+ * try {
214
+ * const result = await batchCreateAclRecords([
215
+ * {
216
+ * subject_type: 'user',
217
+ * subject_id: 'user1',
218
+ * resource_type: 'document',
219
+ * effect_type: 'allow'
220
+ * },
221
+ * {
222
+ * subject_type: 'user',
223
+ * subject_id: 'user2',
224
+ * resource_type: 'document',
225
+ * effect_type: 'deny'
226
+ * }
227
+ * ]);
228
+ * console.log(`Created ${result.success_count}, Failed ${result.failure_count}`);
229
+ * } catch (error) {
230
+ * console.error('Failed to batch create ACL records:', error.message);
231
+ * }
232
+ * ```
180
233
  */
181
- export async function deleteRecord(recordId, options) {
182
- // Validate required fields
183
- if (!recordId || recordId.trim() === '') {
184
- throw new ApiError('record_id is required for ACL record deletion', 400, '9400');
185
- }
186
- // Use provided app token or get one from token service
187
- const token = options?.appToken ?? await getAppToken(options);
188
- // Determine base URL
234
+ export async function batchCreateAclRecords(requests, options) {
235
+ if (!Array.isArray(requests) || requests.length === 0) {
236
+ throw new ApiError("requests is required and must be a non-empty array", 400, "9400");
237
+ }
238
+ const token = options?.appToken ?? (await getAppToken(options));
189
239
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
190
240
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
191
241
  if (!base) {
192
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
242
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
193
243
  }
194
- const url = String(base).replace(/\/+$/, '') + `/acl/v1/records/${encodeURIComponent(recordId)}`;
244
+ const url = String(base).replace(/\/+$/, "") + "/acl/v2/records/batch";
195
245
  let response;
196
246
  try {
197
247
  response = await globalThis.fetch(url, {
198
- method: 'DELETE',
248
+ method: "POST",
199
249
  headers: {
200
- 'Content-Type': 'application/json',
201
- 'x-t-token': token,
250
+ "Content-Type": "application/json",
251
+ "x-t-token": token,
202
252
  },
253
+ body: JSON.stringify(requests),
203
254
  });
204
255
  }
205
256
  catch (error) {
206
- throw new NetworkError(`Failed to delete ACL record: ${error instanceof Error ? error.message : 'Unknown error'}`);
207
- }
208
- let json;
209
- try {
210
- const responseJson = await response.json();
211
- json = responseJson;
212
- }
213
- catch (error) {
214
- throw new ApiError(`Failed to parse ACL record deletion response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
257
+ throw new NetworkError(`Failed to batch create ACL records: ${error instanceof Error ? error.message : "Unknown error"}`);
215
258
  }
216
- // Handle API errors
217
- if (json.code !== 200) {
218
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL record deletion failed';
219
- throw new ApiError(errorMsg, response.status, json.code);
220
- }
221
- // Validate response structure
222
- if (!json.data || json.data.deleted !== true) {
223
- throw new ApiError('Invalid ACL record deletion response: deletion not confirmed', response.status);
224
- }
225
- return json.data;
259
+ const json = await response.json();
260
+ return parseApiResponse(json, "Failed to batch create ACL records", response.status);
226
261
  }
227
262
  /**
228
- * Retrieves ACL record information by ID.
263
+ * Updates an existing ACL record.
229
264
  *
230
- * @param recordId - ACL record ID to query
231
- * @param options - Optional configuration for the request
232
- * @returns Promise resolving to the ACL record information
265
+ * @param recordId - Record ID to update
266
+ * @param request - Update request with fields to modify
267
+ * @param options - Optional configuration
268
+ * @returns Promise resolving to updated ACL record
233
269
  * @throws {ConfigurationError} When required environment variables are missing
234
- * @throws {ApiError} When API request fails or returns invalid response
270
+ * @throws {ApiError} When API request fails
235
271
  * @throws {NetworkError} When network request fails
272
+ *
273
+ * @example
274
+ * ```typescript
275
+ * import { updateAclRecord } from '@tale/client';
276
+ *
277
+ * try {
278
+ * const record = await updateAclRecord('record_id_here', {
279
+ * effect_type: 'deny',
280
+ * priority: 100
281
+ * });
282
+ * console.log('Record updated:', record.record_id);
283
+ * } catch (error) {
284
+ * console.error('Failed to update ACL record:', error.message);
285
+ * }
286
+ * ```
236
287
  */
237
- export async function getRecordById(recordId, options) {
238
- // Validate required fields
239
- if (!recordId || recordId.trim() === '') {
240
- throw new ApiError('record_id is required for ACL record query', 400, '9400');
241
- }
242
- // Use provided app token or get one from token service
243
- const token = options?.appToken ?? await getAppToken(options);
244
- // Determine base URL
288
+ export async function updateAclRecord(recordId, request, options) {
289
+ if (!recordId || recordId.trim() === "") {
290
+ throw new ApiError("record_id is required", 400, "9400");
291
+ }
292
+ const token = options?.appToken ?? (await getAppToken(options));
245
293
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
246
294
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
247
295
  if (!base) {
248
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
296
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
249
297
  }
250
- const url = String(base).replace(/\/+$/, '') + `/acl/v1/records/${encodeURIComponent(recordId)}`;
298
+ const url = String(base).replace(/\/+$/, "") +
299
+ `/acl/v2/records/${encodeURIComponent(recordId)}`;
251
300
  let response;
252
301
  try {
253
302
  response = await globalThis.fetch(url, {
254
- method: 'GET',
303
+ method: "PUT",
255
304
  headers: {
256
- 'Content-Type': 'application/json',
257
- 'x-t-token': token,
305
+ "Content-Type": "application/json",
306
+ "x-t-token": token,
258
307
  },
308
+ body: JSON.stringify(request),
259
309
  });
260
310
  }
261
311
  catch (error) {
262
- throw new NetworkError(`Failed to get ACL record: ${error instanceof Error ? error.message : 'Unknown error'}`);
263
- }
264
- let json;
265
- try {
266
- const responseJson = await response.json();
267
- json = responseJson;
268
- }
269
- catch (error) {
270
- throw new ApiError(`Failed to parse ACL record response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
271
- }
272
- // Handle API errors
273
- if (json.code !== 200) {
274
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL record retrieval failed';
275
- throw new ApiError(errorMsg, response.status, json.code);
312
+ throw new NetworkError(`Failed to update ACL record: ${error instanceof Error ? error.message : "Unknown error"}`);
276
313
  }
277
- // Validate response structure
278
- if (!json.data || !json.data.record) {
279
- throw new ApiError('Invalid ACL record response: missing record data', response.status);
280
- }
281
- return json.data;
314
+ const json = await response.json();
315
+ return parseApiResponse(json, "Failed to update ACL record", response.status);
282
316
  }
283
317
  /**
284
- * Lists ACL records with pagination and filtering.
318
+ * Deletes an ACL record.
285
319
  *
286
- * @param options - Optional parameters for pagination, filtering, and configuration
287
- * @returns Promise resolving to paginated ACL record list with metadata
320
+ * @param recordId - Record ID to delete
321
+ * @param options - Optional configuration
322
+ * @returns Promise that resolves when deletion is successful
288
323
  * @throws {ConfigurationError} When required environment variables are missing
289
- * @throws {ApiError} When API request fails or returns invalid response
324
+ * @throws {ApiError} When API request fails
290
325
  * @throws {NetworkError} When network request fails
326
+ *
327
+ * @example
328
+ * ```typescript
329
+ * import { deleteAclRecord } from '@tale/client';
330
+ *
331
+ * try {
332
+ * await deleteAclRecord('record_id_here');
333
+ * console.log('ACL record deleted successfully');
334
+ * } catch (error) {
335
+ * console.error('Failed to delete ACL record:', error.message);
336
+ * }
337
+ * ```
291
338
  */
292
- export async function listRecords(options) {
293
- // Use provided app token or get one from token service
294
- const token = options?.appToken ?? await getAppToken(options);
295
- // Determine base URL
339
+ export async function deleteAclRecord(recordId, options) {
340
+ if (!recordId || recordId.trim() === "") {
341
+ throw new ApiError("record_id is required", 400, "9400");
342
+ }
343
+ const token = options?.appToken ?? (await getAppToken(options));
296
344
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
297
345
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
298
346
  if (!base) {
299
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
300
- }
301
- // Build URL with query parameters
302
- const url = new URL(String(base).replace(/\/+$/, '') + '/acl/v1/records');
303
- // Add query parameters with defaults
304
- const queryParams = {
305
- page: 0,
306
- size: 20,
307
- sort_by: 'priority',
308
- sort_direction: 'desc',
309
- ...options
310
- };
311
- // Add parameters to URL
312
- if (queryParams.template_id) {
313
- url.searchParams.append('template_id', queryParams.template_id);
314
- }
315
- if (queryParams.subject_type) {
316
- url.searchParams.append('subject_type', queryParams.subject_type);
317
- }
318
- if (queryParams.subject_id) {
319
- url.searchParams.append('subject_id', queryParams.subject_id);
320
- }
321
- if (queryParams.subject_identifier) {
322
- url.searchParams.append('subject_identifier', queryParams.subject_identifier);
323
- }
324
- if (queryParams.resource_type) {
325
- url.searchParams.append('resource_type', queryParams.resource_type);
326
- }
327
- if (queryParams.resource_id) {
328
- url.searchParams.append('resource_id', queryParams.resource_id);
329
- }
330
- if (queryParams.resource_identifier) {
331
- url.searchParams.append('resource_identifier', queryParams.resource_identifier);
332
- }
333
- if (queryParams.page !== undefined) {
334
- url.searchParams.append('page', String(queryParams.page));
335
- }
336
- if (queryParams.size !== undefined) {
337
- url.searchParams.append('size', String(queryParams.size));
338
- }
339
- if (queryParams.sort_by) {
340
- url.searchParams.append('sort', `${queryParams.sort_by},${queryParams.sort_direction || 'desc'}`);
347
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
341
348
  }
349
+ const url = String(base).replace(/\/+$/, "") +
350
+ `/acl/v2/records/${encodeURIComponent(recordId)}`;
342
351
  let response;
343
352
  try {
344
- response = await globalThis.fetch(url.toString(), {
345
- method: 'GET',
353
+ response = await globalThis.fetch(url, {
354
+ method: "DELETE",
346
355
  headers: {
347
- 'Content-Type': 'application/json',
348
- 'x-t-token': token,
356
+ "Content-Type": "application/json",
357
+ "x-t-token": token,
349
358
  },
350
359
  });
351
360
  }
352
361
  catch (error) {
353
- throw new NetworkError(`Failed to list ACL records: ${error instanceof Error ? error.message : 'Unknown error'}`);
354
- }
355
- let json;
356
- try {
357
- const responseJson = await response.json();
358
- json = responseJson;
359
- }
360
- catch (error) {
361
- throw new ApiError(`Failed to parse ACL records list response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
362
+ throw new NetworkError(`Failed to delete ACL record: ${error instanceof Error ? error.message : "Unknown error"}`);
362
363
  }
363
- // Handle API errors
364
- if (json.code !== 200) {
365
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL records list retrieval failed';
366
- throw new ApiError(errorMsg, response.status, json.code);
364
+ const json = await response.json();
365
+ // Delete response may not have data field, handle differently
366
+ if (typeof json !== 'object' || json === null) {
367
+ throw new ApiError("Invalid ACL record deletion response", response.status);
367
368
  }
368
- // Validate response structure
369
- if (!json.data || !Array.isArray(json.data.content)) {
370
- throw new ApiError('Invalid ACL records list response: missing required data', response.status);
369
+ const apiResponse = json;
370
+ if (apiResponse.code !== 200) {
371
+ const errorMsg = typeof apiResponse.msg === "string" ? apiResponse.msg : "Failed to delete ACL record";
372
+ throw new ApiError(errorMsg, response.status, apiResponse.code);
371
373
  }
372
- return json.data;
373
374
  }
374
- // ===== ACL Template 管理 =====
375
+ // ==================== ACL Template Management ====================
375
376
  /**
376
- * Creates a new ACL template in the Tale application.
377
+ * Gets an ACL template by ID or code.
377
378
  *
378
- * @param templateData - ACL template data to create
379
- * @param options - Optional configuration for the request
380
- * @returns Promise resolving to the created ACL template information
379
+ * @param templateId - Template ID or code
380
+ * @param options - Optional configuration
381
+ * @returns Promise resolving to ACL template information
381
382
  * @throws {ConfigurationError} When required environment variables are missing
382
- * @throws {ApiError} When API request fails or returns invalid response
383
+ * @throws {ApiError} When API request fails
383
384
  * @throws {NetworkError} When network request fails
384
385
  *
385
386
  * @example
386
387
  * ```typescript
387
- * import { createTemplate } from '@tale/client';
388
+ * import { getAclTemplate } from '@tale/client';
388
389
  *
389
390
  * try {
390
- * const result = await createTemplate({
391
- * template_name: 'User Document Read Template',
392
- * template_code: 'user_doc_read',
393
- * subject_type: 'user',
394
- * resource_type: 'document',
395
- * effect_type: 'allow',
396
- * default_priority: 30,
397
- * description: 'Template for allowing users to read documents'
398
- * });
399
- * console.log('ACL template created:', result.template.template_id);
391
+ * const template = await getAclTemplate('template_code_here');
392
+ * console.log('Template name:', template.template_name);
400
393
  * } catch (error) {
401
- * console.error('Failed to create ACL template:', error.message);
394
+ * console.error('Failed to get ACL template:', error.message);
402
395
  * }
403
396
  * ```
404
397
  */
405
- export async function createTemplate(templateData, options) {
406
- // Validate required fields
407
- if (!templateData.template_name || templateData.template_name.trim() === '') {
408
- throw new ApiError('template_name is required for ACL template creation', 400, '9400');
409
- }
410
- if (!templateData.template_code || templateData.template_code.trim() === '') {
411
- throw new ApiError('template_code is required for ACL template creation', 400, '9400');
412
- }
413
- if (templateData.effect_type && !['allow', 'deny', 'inherit'].includes(templateData.effect_type)) {
414
- throw new ApiError('effect_type must be one of: allow, deny, inherit', 400, '9400');
398
+ export async function getAclTemplate(templateId, options) {
399
+ if (!templateId || templateId.trim() === "") {
400
+ throw new ApiError("template_id is required", 400, "9400");
415
401
  }
416
- // Validate default priority range
417
- if (templateData.default_priority !== undefined && (templateData.default_priority < 0 || templateData.default_priority > 100)) {
418
- throw new ApiError('default_priority must be between 0 and 100', 400, '9400');
419
- }
420
- // Use provided app token or get one from token service
421
- const token = options?.appToken ?? await getAppToken(options);
422
- // Determine base URL
402
+ const token = options?.appToken ?? (await getAppToken(options));
423
403
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
424
404
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
425
405
  if (!base) {
426
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
427
- }
428
- const url = String(base).replace(/\/+$/, '') + '/acl/v1/templates';
429
- // Set default values
430
- const finalTemplateData = {
431
- ...templateData,
432
- default_priority: templateData.default_priority ?? 50,
433
- effect_type: templateData.effect_type ?? 'allow'
434
- };
406
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
407
+ }
408
+ const url = String(base).replace(/\/+$/, "") +
409
+ `/acl/v1/templates/${encodeURIComponent(templateId)}`;
435
410
  let response;
436
411
  try {
437
412
  response = await globalThis.fetch(url, {
438
- method: 'POST',
413
+ method: "GET",
439
414
  headers: {
440
- 'Content-Type': 'application/json',
441
- 'x-t-token': token,
415
+ "Content-Type": "application/json",
416
+ "x-t-token": token,
442
417
  },
443
- body: JSON.stringify(finalTemplateData),
444
418
  });
445
419
  }
446
420
  catch (error) {
447
- throw new NetworkError(`Failed to create ACL template: ${error instanceof Error ? error.message : 'Unknown error'}`);
421
+ throw new NetworkError(`Failed to get ACL template: ${error instanceof Error ? error.message : "Unknown error"}`);
448
422
  }
449
- let json;
450
- try {
451
- const responseJson = await response.json();
452
- json = responseJson;
453
- }
454
- catch (error) {
455
- throw new ApiError(`Failed to parse ACL template creation response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
456
- }
457
- // Handle API errors
423
+ const json = (await response.json());
458
424
  if (json.code !== 200) {
459
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL template creation failed';
425
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to get ACL template";
460
426
  throw new ApiError(errorMsg, response.status, json.code);
461
427
  }
462
- // Validate response structure
463
- if (!json.data || !json.data.template) {
464
- throw new ApiError('Invalid ACL template creation response: missing template data', response.status);
428
+ if (!json.data) {
429
+ throw new ApiError("Invalid ACL template response: missing data", response.status);
465
430
  }
466
431
  return json.data;
467
432
  }
468
433
  /**
469
- * Updates an existing ACL template by ID.
434
+ * Lists ACL templates with pagination and optional filtering.
470
435
  *
471
- * @param templateId - ACL template ID or code to update
472
- * @param updateData - ACL template information to update
473
- * @param options - Optional configuration for the request
474
- * @returns Promise resolving to the updated ACL template information
436
+ * @param options - Optional parameters for pagination and filtering
437
+ * @returns Promise resolving to paginated ACL template list
475
438
  * @throws {ConfigurationError} When required environment variables are missing
476
- * @throws {ApiError} When API request fails or returns invalid response
439
+ * @throws {ApiError} When API request fails
477
440
  * @throws {NetworkError} When network request fails
441
+ *
442
+ * @example
443
+ * ```typescript
444
+ * import { listAclTemplates } from '@tale/client';
445
+ *
446
+ * try {
447
+ * const result = await listAclTemplates({
448
+ * page: 0,
449
+ * size: 20,
450
+ * resource_type: 'document'
451
+ * });
452
+ * console.log(`Found ${result.totalElements} templates`);
453
+ * } catch (error) {
454
+ * console.error('Failed to list ACL templates:', error.message);
455
+ * }
456
+ * ```
478
457
  */
479
- export async function updateTemplate(templateId, updateData, options) {
480
- // Validate required fields
481
- if (!templateId || templateId.trim() === '') {
482
- throw new ApiError('template_id is required for ACL template update', 400, '9400');
483
- }
484
- if (updateData.effect_type && !['allow', 'deny', 'inherit'].includes(updateData.effect_type)) {
485
- throw new ApiError('effect_type must be one of: allow, deny, inherit', 400, '9400');
486
- }
487
- // Validate default priority range
488
- if (updateData.default_priority !== undefined && (updateData.default_priority < 0 || updateData.default_priority > 100)) {
489
- throw new ApiError('default_priority must be between 0 and 100', 400, '9400');
490
- }
491
- // Use provided app token or get one from token service
492
- const token = options?.appToken ?? await getAppToken(options);
493
- // Determine base URL
458
+ export async function listAclTemplates(options) {
459
+ const token = options?.appToken ?? (await getAppToken(options));
494
460
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
495
461
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
496
462
  if (!base) {
497
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
463
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
498
464
  }
499
- const url = String(base).replace(/\/+$/, '') + `/acl/v1/templates/${encodeURIComponent(templateId)}`;
465
+ const url = new URL(String(base).replace(/\/+$/, "") + "/acl/v1/templates");
466
+ // 分离 AclOptions 字段,只保留请求参数
467
+ const { appToken, baseUrl, ...requestParams } = options || {};
468
+ const queryParams = {
469
+ page: 0,
470
+ size: 20,
471
+ sort_by: "createdAt",
472
+ sort_direction: "desc",
473
+ ...requestParams,
474
+ };
475
+ Object.entries(queryParams).forEach(([key, value]) => {
476
+ if (value !== undefined) {
477
+ url.searchParams.append(key === "sortBy" ? "sort_by" : key === "sortDirection" ? "sort_direction" : key, String(value));
478
+ }
479
+ });
500
480
  let response;
501
481
  try {
502
- response = await globalThis.fetch(url, {
503
- method: 'PUT',
482
+ response = await globalThis.fetch(url.toString(), {
483
+ method: "GET",
504
484
  headers: {
505
- 'Content-Type': 'application/json',
506
- 'x-t-token': token,
485
+ "Content-Type": "application/json",
486
+ "x-t-token": token,
507
487
  },
508
- body: JSON.stringify(updateData),
509
488
  });
510
489
  }
511
490
  catch (error) {
512
- throw new NetworkError(`Failed to update ACL template: ${error instanceof Error ? error.message : 'Unknown error'}`);
491
+ throw new NetworkError(`Failed to list ACL templates: ${error instanceof Error ? error.message : "Unknown error"}`);
513
492
  }
514
- let json;
515
- try {
516
- const responseJson = await response.json();
517
- json = responseJson;
518
- }
519
- catch (error) {
520
- throw new ApiError(`Failed to parse ACL template update response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
521
- }
522
- // Handle API errors
493
+ const json = (await response.json());
523
494
  if (json.code !== 200) {
524
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL template update failed';
495
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to list ACL templates";
525
496
  throw new ApiError(errorMsg, response.status, json.code);
526
497
  }
527
- // Validate response structure
528
- if (!json.data || !json.data.template) {
529
- throw new ApiError('Invalid ACL template update response: missing template data', response.status);
498
+ if (!json.data || !Array.isArray(json.data.content)) {
499
+ throw new ApiError("Invalid ACL templates response: missing data", response.status);
530
500
  }
531
501
  return json.data;
532
502
  }
533
503
  /**
534
- * Deletes an ACL template by ID.
504
+ * Creates a new ACL template.
535
505
  *
536
- * @param templateId - ACL template ID or code to delete
537
- * @param options - Optional configuration for the request
538
- * @returns Promise resolving to the deletion result
506
+ * @param request - ACL template creation request
507
+ * @param options - Optional configuration
508
+ * @returns Promise resolving to created ACL template
539
509
  * @throws {ConfigurationError} When required environment variables are missing
540
- * @throws {ApiError} When API request fails or returns invalid response
510
+ * @throws {ApiError} When API request fails
541
511
  * @throws {NetworkError} When network request fails
512
+ *
513
+ * @example
514
+ * ```typescript
515
+ * import { createAclTemplate } from '@tale/client';
516
+ *
517
+ * try {
518
+ * const template = await createAclTemplate({
519
+ * template_name: 'Document Access',
520
+ * template_code: 'doc_access',
521
+ * subject_type: 'user',
522
+ * resource_type: 'document',
523
+ * effect_type: 'allow'
524
+ * });
525
+ * console.log('Template created:', template.template_id);
526
+ * } catch (error) {
527
+ * console.error('Failed to create ACL template:', error.message);
528
+ * }
529
+ * ```
542
530
  */
543
- export async function deleteTemplate(templateId, options) {
544
- // Validate required fields
545
- if (!templateId || templateId.trim() === '') {
546
- throw new ApiError('template_id is required for ACL template deletion', 400, '9400');
547
- }
548
- // Use provided app token or get one from token service
549
- const token = options?.appToken ?? await getAppToken(options);
550
- // Determine base URL
531
+ export async function createAclTemplate(request, options) {
532
+ if (!request.template_name || request.template_name.trim() === "") {
533
+ throw new ApiError("template_name is required", 400, "9400");
534
+ }
535
+ if (!request.template_code || request.template_code.trim() === "") {
536
+ throw new ApiError("template_code is required", 400, "9400");
537
+ }
538
+ const token = options?.appToken ?? (await getAppToken(options));
551
539
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
552
540
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
553
541
  if (!base) {
554
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
542
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
555
543
  }
556
- const url = String(base).replace(/\/+$/, '') + `/acl/v1/templates/${encodeURIComponent(templateId)}`;
544
+ const url = String(base).replace(/\/+$/, "") + "/acl/v1/templates";
557
545
  let response;
558
546
  try {
559
547
  response = await globalThis.fetch(url, {
560
- method: 'DELETE',
548
+ method: "POST",
561
549
  headers: {
562
- 'Content-Type': 'application/json',
563
- 'x-t-token': token,
550
+ "Content-Type": "application/json",
551
+ "x-t-token": token,
564
552
  },
553
+ body: JSON.stringify(request),
565
554
  });
566
555
  }
567
556
  catch (error) {
568
- throw new NetworkError(`Failed to delete ACL template: ${error instanceof Error ? error.message : 'Unknown error'}`);
569
- }
570
- let json;
571
- try {
572
- const responseJson = await response.json();
573
- json = responseJson;
574
- }
575
- catch (error) {
576
- throw new ApiError(`Failed to parse ACL template deletion response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
557
+ throw new NetworkError(`Failed to create ACL template: ${error instanceof Error ? error.message : "Unknown error"}`);
577
558
  }
578
- // Handle API errors
559
+ const json = (await response.json());
579
560
  if (json.code !== 200) {
580
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL template deletion failed';
561
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to create ACL template";
581
562
  throw new ApiError(errorMsg, response.status, json.code);
582
563
  }
583
- // Validate response structure
584
- if (!json.data || json.data.deleted !== true) {
585
- throw new ApiError('Invalid ACL template deletion response: deletion not confirmed', response.status);
564
+ if (!json.data) {
565
+ throw new ApiError("Invalid ACL template creation response: missing data", response.status);
586
566
  }
587
567
  return json.data;
588
568
  }
589
569
  /**
590
- * Retrieves ACL template information by ID or code.
570
+ * Updates an existing ACL template.
591
571
  *
592
- * @param templateId - ACL template ID or code to query
593
- * @param options - Optional configuration for the request
594
- * @returns Promise resolving to the ACL template information
572
+ * @param templateId - Template ID or code to update
573
+ * @param request - Update request with fields to modify
574
+ * @param options - Optional configuration
575
+ * @returns Promise resolving to updated ACL template
595
576
  * @throws {ConfigurationError} When required environment variables are missing
596
- * @throws {ApiError} When API request fails or returns invalid response
577
+ * @throws {ApiError} When API request fails
597
578
  * @throws {NetworkError} When network request fails
579
+ *
580
+ * @example
581
+ * ```typescript
582
+ * import { updateAclTemplate } from '@tale/client';
583
+ *
584
+ * try {
585
+ * const template = await updateAclTemplate('template_code_here', {
586
+ * template_name: 'Updated Template Name',
587
+ * effect_type: 'deny'
588
+ * });
589
+ * console.log('Template updated:', template.template_id);
590
+ * } catch (error) {
591
+ * console.error('Failed to update ACL template:', error.message);
592
+ * }
593
+ * ```
598
594
  */
599
- export async function getTemplateById(templateId, options) {
600
- // Validate required fields
601
- if (!templateId || templateId.trim() === '') {
602
- throw new ApiError('template_id is required for ACL template query', 400, '9400');
603
- }
604
- // Use provided app token or get one from token service
605
- const token = options?.appToken ?? await getAppToken(options);
606
- // Determine base URL
595
+ export async function updateAclTemplate(templateId, request, options) {
596
+ if (!templateId || templateId.trim() === "") {
597
+ throw new ApiError("template_id is required", 400, "9400");
598
+ }
599
+ const token = options?.appToken ?? (await getAppToken(options));
607
600
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
608
601
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
609
602
  if (!base) {
610
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
603
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
611
604
  }
612
- const url = String(base).replace(/\/+$/, '') + `/acl/v1/templates/${encodeURIComponent(templateId)}`;
605
+ const url = String(base).replace(/\/+$/, "") +
606
+ `/acl/v1/templates/${encodeURIComponent(templateId)}`;
613
607
  let response;
614
608
  try {
615
609
  response = await globalThis.fetch(url, {
616
- method: 'GET',
610
+ method: "PUT",
617
611
  headers: {
618
- 'Content-Type': 'application/json',
619
- 'x-t-token': token,
612
+ "Content-Type": "application/json",
613
+ "x-t-token": token,
620
614
  },
615
+ body: JSON.stringify(request),
621
616
  });
622
617
  }
623
618
  catch (error) {
624
- throw new NetworkError(`Failed to get ACL template: ${error instanceof Error ? error.message : 'Unknown error'}`);
625
- }
626
- let json;
627
- try {
628
- const responseJson = await response.json();
629
- json = responseJson;
619
+ throw new NetworkError(`Failed to update ACL template: ${error instanceof Error ? error.message : "Unknown error"}`);
630
620
  }
631
- catch (error) {
632
- throw new ApiError(`Failed to parse ACL template response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
633
- }
634
- // Handle API errors
621
+ const json = (await response.json());
635
622
  if (json.code !== 200) {
636
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL template retrieval failed';
623
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to update ACL template";
637
624
  throw new ApiError(errorMsg, response.status, json.code);
638
625
  }
639
- // Validate response structure
640
- if (!json.data || !json.data.template) {
641
- throw new ApiError('Invalid ACL template response: missing template data', response.status);
626
+ if (!json.data) {
627
+ throw new ApiError("Invalid ACL template update response: missing data", response.status);
642
628
  }
643
629
  return json.data;
644
630
  }
645
631
  /**
646
- * Lists ACL templates with pagination and filtering.
632
+ * Deletes an ACL template.
647
633
  *
648
- * @param options - Optional parameters for pagination, filtering, and configuration
649
- * @returns Promise resolving to paginated ACL template list with metadata
634
+ * @param templateId - Template ID or code to delete
635
+ * @param options - Optional configuration
636
+ * @returns Promise that resolves when deletion is successful
650
637
  * @throws {ConfigurationError} When required environment variables are missing
651
- * @throws {ApiError} When API request fails or returns invalid response
638
+ * @throws {ApiError} When API request fails
652
639
  * @throws {NetworkError} When network request fails
640
+ *
641
+ * @example
642
+ * ```typescript
643
+ * import { deleteAclTemplate } from '@tale/client';
644
+ *
645
+ * try {
646
+ * await deleteAclTemplate('template_code_here');
647
+ * console.log('ACL template deleted successfully');
648
+ * } catch (error) {
649
+ * console.error('Failed to delete ACL template:', error.message);
650
+ * }
651
+ * ```
653
652
  */
654
- export async function listTemplates(options) {
655
- // Use provided app token or get one from token service
656
- const token = options?.appToken ?? await getAppToken(options);
657
- // Determine base URL
653
+ export async function deleteAclTemplate(templateId, options) {
654
+ if (!templateId || templateId.trim() === "") {
655
+ throw new ApiError("template_id is required", 400, "9400");
656
+ }
657
+ const token = options?.appToken ?? (await getAppToken(options));
658
658
  const env = globalThis?.process?.env ?? import.meta?.env ?? undefined;
659
659
  const base = options?.baseUrl ?? env?.TALE_BASE_URL ?? undefined;
660
660
  if (!base) {
661
- throw new ConfigurationError('Missing required environment variable: TALE_BASE_URL');
662
- }
663
- // Build URL with query parameters
664
- const url = new URL(String(base).replace(/\/+$/, '') + '/acl/v1/templates');
665
- // Add query parameters with defaults
666
- const queryParams = {
667
- page: 0,
668
- size: 20,
669
- sort_by: 'created_at',
670
- sort_direction: 'desc',
671
- ...options
672
- };
673
- // Add parameters to URL
674
- if (queryParams.resource_type) {
675
- url.searchParams.append('resource_type', queryParams.resource_type);
676
- }
677
- if (queryParams.subject_type) {
678
- url.searchParams.append('subject_type', queryParams.subject_type);
679
- }
680
- if (queryParams.page !== undefined) {
681
- url.searchParams.append('page', String(queryParams.page));
682
- }
683
- if (queryParams.size !== undefined) {
684
- url.searchParams.append('size', String(queryParams.size));
685
- }
686
- if (queryParams.sort_by) {
687
- url.searchParams.append('sort_by', queryParams.sort_by);
688
- }
689
- if (queryParams.sort_direction) {
690
- url.searchParams.append('sort_direction', queryParams.sort_direction);
661
+ throw new ConfigurationError("Missing required environment variable: TALE_BASE_URL");
691
662
  }
663
+ const url = String(base).replace(/\/+$/, "") +
664
+ `/acl/v1/templates/${encodeURIComponent(templateId)}`;
692
665
  let response;
693
666
  try {
694
- response = await globalThis.fetch(url.toString(), {
695
- method: 'GET',
667
+ response = await globalThis.fetch(url, {
668
+ method: "DELETE",
696
669
  headers: {
697
- 'Content-Type': 'application/json',
698
- 'x-t-token': token,
670
+ "Content-Type": "application/json",
671
+ "x-t-token": token,
699
672
  },
700
673
  });
701
674
  }
702
675
  catch (error) {
703
- throw new NetworkError(`Failed to list ACL templates: ${error instanceof Error ? error.message : 'Unknown error'}`);
704
- }
705
- let json;
706
- try {
707
- const responseJson = await response.json();
708
- json = responseJson;
709
- }
710
- catch (error) {
711
- throw new ApiError(`Failed to parse ACL templates list response: ${error instanceof Error ? error.message : 'Invalid JSON'}`, response.status);
676
+ throw new NetworkError(`Failed to delete ACL template: ${error instanceof Error ? error.message : "Unknown error"}`);
712
677
  }
713
- // Handle API errors
678
+ const json = (await response.json());
714
679
  if (json.code !== 200) {
715
- const errorMsg = typeof json.msg === 'string' ? json.msg : 'ACL templates list retrieval failed';
680
+ const errorMsg = typeof json.msg === "string" ? json.msg : "Failed to delete ACL template";
716
681
  throw new ApiError(errorMsg, response.status, json.code);
717
682
  }
718
- // Validate response structure
719
- if (!json.data || !Array.isArray(json.data.content)) {
720
- throw new ApiError('Invalid ACL templates list response: missing required data', response.status);
721
- }
722
- return json.data;
723
683
  }
724
- // ===== ACL 核心工具函数 (AclCoreUtils) =====
725
- /**
726
- * ACL 核心工具函数,包含跨应用通用的业务逻辑
727
- */
728
- export const AclCoreUtils = {
729
- /**
730
- * 验证优先级范围
731
- */
732
- validatePriority(priority) {
733
- return priority >= 0 && priority <= 100;
734
- },
735
- /**
736
- * 获取可用的效果类型
737
- */
738
- getEffectTypes() {
739
- return ['allow', 'deny', 'inherit'];
740
- },
741
- /**
742
- * 获取可用的主体类型
743
- */
744
- getSubjectTypes() {
745
- return ['user', 'role', 'group'];
746
- }
747
- };