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