n8n-nodes-confirm8 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +5 -0
- package/dist/credentials/ApiCustomCredentials.credentials.d.ts +9 -0
- package/dist/credentials/ApiCustomCredentials.credentials.js +66 -0
- package/dist/credentials/index.d.ts +1 -0
- package/dist/credentials/index.js +17 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +9 -0
- package/dist/nodes/ApiCustom/ApiAgentNode.node.d.ts +9 -0
- package/dist/nodes/ApiCustom/ApiAgentNode.node.js +599 -0
- package/dist/nodes/ApiCustom/ApiAgentTool.node.d.ts +19 -0
- package/dist/nodes/ApiCustom/ApiAgentTool.node.js +170 -0
- package/dist/nodes/ApiCustom/ApiCustom.node.d.ts +5 -0
- package/dist/nodes/ApiCustom/ApiCustom.node.js +973 -0
- package/dist/nodes/RegularNode.js +2 -1
- package/dist/nodes/index.d.ts +3 -0
- package/dist/nodes/index.js +19 -0
- package/package.json +32 -14
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApiAgentNode = void 0;
|
|
4
|
+
class ApiAgentNode {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.description = {
|
|
7
|
+
displayName: 'API Agent Node',
|
|
8
|
+
name: 'apiAgentNode',
|
|
9
|
+
icon: 'file:api-agent.svg',
|
|
10
|
+
group: ['transform'],
|
|
11
|
+
version: 1,
|
|
12
|
+
subtitle: '={{$parameter["resource"] + " - " + $parameter["operation"]}}',
|
|
13
|
+
description: 'AI-optimized node for API operations with batch processing and flexible input',
|
|
14
|
+
defaults: {
|
|
15
|
+
name: 'API Agent Node',
|
|
16
|
+
},
|
|
17
|
+
inputs: ['main'],
|
|
18
|
+
outputs: ['main'],
|
|
19
|
+
credentials: [
|
|
20
|
+
{
|
|
21
|
+
name: 'apiCustomCredentials',
|
|
22
|
+
required: true,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
properties: [
|
|
26
|
+
// Mode Selection
|
|
27
|
+
{
|
|
28
|
+
displayName: 'Mode',
|
|
29
|
+
name: 'mode',
|
|
30
|
+
type: 'options',
|
|
31
|
+
options: [
|
|
32
|
+
{
|
|
33
|
+
name: 'Simple',
|
|
34
|
+
value: 'simple',
|
|
35
|
+
description: 'Use dropdown menus to configure the operation',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'Advanced (JSON)',
|
|
39
|
+
value: 'advanced',
|
|
40
|
+
description: 'Provide complete JSON configuration for maximum flexibility',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Batch',
|
|
44
|
+
value: 'batch',
|
|
45
|
+
description: 'Process multiple operations in a single execution',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
default: 'simple',
|
|
49
|
+
description: 'Choose how to configure the API call',
|
|
50
|
+
},
|
|
51
|
+
// ===== SIMPLE MODE =====
|
|
52
|
+
{
|
|
53
|
+
displayName: 'Resource',
|
|
54
|
+
name: 'resource',
|
|
55
|
+
type: 'options',
|
|
56
|
+
noDataExpression: true,
|
|
57
|
+
displayOptions: {
|
|
58
|
+
show: {
|
|
59
|
+
mode: ['simple'],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
options: [
|
|
63
|
+
{
|
|
64
|
+
name: 'Users',
|
|
65
|
+
value: 'users',
|
|
66
|
+
description: 'Manage system users - create, retrieve, update, activate/deactivate users, manage tasks and permissions',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'Clients',
|
|
70
|
+
value: 'clients',
|
|
71
|
+
description: 'Manage clients - create, retrieve, update client information and status',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
name: 'Items',
|
|
75
|
+
value: 'items',
|
|
76
|
+
description: 'Manage inventory items - create, retrieve, update items and their status',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'Item Types',
|
|
80
|
+
value: 'itemTypes',
|
|
81
|
+
description: 'Manage item type categories and classifications',
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'Tasks',
|
|
85
|
+
value: 'tasks',
|
|
86
|
+
description: 'Manage checklists and tasks - create, assign, update task status',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
name: 'Services',
|
|
90
|
+
value: 'services',
|
|
91
|
+
description: 'Manage services offered - create, update service definitions and availability',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
name: 'Products',
|
|
95
|
+
value: 'products',
|
|
96
|
+
description: 'Manage product catalog - create, update products and pricing',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'Orders (WOS)',
|
|
100
|
+
value: 'wos',
|
|
101
|
+
description: 'Manage work orders - create, track, update service orders',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'Modalities',
|
|
105
|
+
value: 'modalities',
|
|
106
|
+
description: 'Manage order modalities - different types of service delivery methods',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'Tickets',
|
|
110
|
+
value: 'tickets',
|
|
111
|
+
description: 'Manage support tickets - create, track, resolve customer issues',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: 'Properties',
|
|
115
|
+
value: 'properties',
|
|
116
|
+
description: 'Manage properties - real estate or asset management',
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
default: 'users',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
displayName: 'Operation',
|
|
123
|
+
name: 'operation',
|
|
124
|
+
type: 'options',
|
|
125
|
+
noDataExpression: true,
|
|
126
|
+
displayOptions: {
|
|
127
|
+
show: {
|
|
128
|
+
mode: ['simple'],
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
options: [
|
|
132
|
+
{
|
|
133
|
+
name: 'Create',
|
|
134
|
+
value: 'create',
|
|
135
|
+
description: 'Create a new record. Requires JSON body with required fields.',
|
|
136
|
+
action: 'Create a new record',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: 'Get by ID',
|
|
140
|
+
value: 'get',
|
|
141
|
+
description: 'Retrieve a specific record by its unique identifier',
|
|
142
|
+
action: 'Get record by ID',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: 'Get by Username',
|
|
146
|
+
value: 'getByUsername',
|
|
147
|
+
description: 'Retrieve a user by username (users only)',
|
|
148
|
+
action: 'Get user by username',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'Get All',
|
|
152
|
+
value: 'getAll',
|
|
153
|
+
description: 'Retrieve list of all records. Supports pagination and filtering.',
|
|
154
|
+
action: 'Get all records',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: 'Update',
|
|
158
|
+
value: 'update',
|
|
159
|
+
description: 'Update an existing record. Provide ID and fields to update.',
|
|
160
|
+
action: 'Update record',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: 'Activate',
|
|
164
|
+
value: 'activate',
|
|
165
|
+
description: 'Set record status to active/enabled',
|
|
166
|
+
action: 'Activate record',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: 'Deactivate',
|
|
170
|
+
value: 'deactivate',
|
|
171
|
+
description: 'Set record status to inactive/disabled',
|
|
172
|
+
action: 'Deactivate record',
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: 'Delete',
|
|
176
|
+
value: 'delete',
|
|
177
|
+
description: 'Permanently delete a record',
|
|
178
|
+
action: 'Delete record',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'Link Tasks (Users)',
|
|
182
|
+
value: 'linkTasks',
|
|
183
|
+
description: 'Associate tasks with a user',
|
|
184
|
+
action: 'Link tasks to user',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: 'Unlink Tasks (Users)',
|
|
188
|
+
value: 'unlinkTasks',
|
|
189
|
+
description: 'Remove task associations from a user',
|
|
190
|
+
action: 'Unlink tasks from user',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'Get User Tasks',
|
|
194
|
+
value: 'getUserTasks',
|
|
195
|
+
description: 'Get all tasks assigned to a specific user',
|
|
196
|
+
action: 'Get user tasks',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'Get User Tickets',
|
|
200
|
+
value: 'getUserTickets',
|
|
201
|
+
description: 'Get all tickets owned by a specific user',
|
|
202
|
+
action: 'Get user tickets',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
name: 'Get User Permissions',
|
|
206
|
+
value: 'getUserPermissions',
|
|
207
|
+
description: 'Get permissions and access rights for a user',
|
|
208
|
+
action: 'Get user permissions',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: 'Upload Photo',
|
|
212
|
+
value: 'uploadPhoto',
|
|
213
|
+
description: 'Upload user profile photo (users only)',
|
|
214
|
+
action: 'Upload photo',
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: 'Upload Signature',
|
|
218
|
+
value: 'uploadSignature',
|
|
219
|
+
description: 'Upload user signature file (users only)',
|
|
220
|
+
action: 'Upload signature',
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
default: 'getAll',
|
|
224
|
+
},
|
|
225
|
+
// ID Field - Dynamic label based on resource
|
|
226
|
+
{
|
|
227
|
+
displayName: 'Record ID',
|
|
228
|
+
name: 'recordId',
|
|
229
|
+
type: 'string',
|
|
230
|
+
displayOptions: {
|
|
231
|
+
show: {
|
|
232
|
+
mode: ['simple'],
|
|
233
|
+
operation: ['get', 'update', 'activate', 'deactivate', 'delete', 'getUserTasks', 'getUserTickets', 'getUserPermissions', 'uploadPhoto', 'uploadSignature'],
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
default: '',
|
|
237
|
+
description: 'The unique identifier of the record to operate on',
|
|
238
|
+
required: true,
|
|
239
|
+
},
|
|
240
|
+
// Username field
|
|
241
|
+
{
|
|
242
|
+
displayName: 'Username',
|
|
243
|
+
name: 'username',
|
|
244
|
+
type: 'string',
|
|
245
|
+
displayOptions: {
|
|
246
|
+
show: {
|
|
247
|
+
mode: ['simple'],
|
|
248
|
+
operation: ['getByUsername'],
|
|
249
|
+
resource: ['users'],
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
default: '',
|
|
253
|
+
description: 'The username to search for',
|
|
254
|
+
required: true,
|
|
255
|
+
},
|
|
256
|
+
// Employee ID for unlinking tasks
|
|
257
|
+
{
|
|
258
|
+
displayName: 'Employee ID',
|
|
259
|
+
name: 'employeeId',
|
|
260
|
+
type: 'string',
|
|
261
|
+
displayOptions: {
|
|
262
|
+
show: {
|
|
263
|
+
mode: ['simple'],
|
|
264
|
+
operation: ['unlinkTasks'],
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
default: '',
|
|
268
|
+
description: 'The employee ID to unlink tasks from',
|
|
269
|
+
required: true,
|
|
270
|
+
},
|
|
271
|
+
// Request Body (JSON)
|
|
272
|
+
{
|
|
273
|
+
displayName: 'Request Body (JSON)',
|
|
274
|
+
name: 'requestBody',
|
|
275
|
+
type: 'json',
|
|
276
|
+
displayOptions: {
|
|
277
|
+
show: {
|
|
278
|
+
mode: ['simple'],
|
|
279
|
+
operation: ['create', 'update', 'linkTasks'],
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
default: '{}',
|
|
283
|
+
description: 'JSON object containing the data for the operation. Structure depends on the resource type.',
|
|
284
|
+
placeholder: '{\n "name": "John Doe",\n "email": "john@example.com"\n}',
|
|
285
|
+
},
|
|
286
|
+
// Query Parameters
|
|
287
|
+
{
|
|
288
|
+
displayName: 'Query Parameters',
|
|
289
|
+
name: 'queryParameters',
|
|
290
|
+
type: 'json',
|
|
291
|
+
displayOptions: {
|
|
292
|
+
show: {
|
|
293
|
+
mode: ['simple'],
|
|
294
|
+
operation: ['getAll'],
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
default: '{}',
|
|
298
|
+
description: 'Optional query parameters for filtering, pagination, sorting. Example: {"limit": 10, "offset": 0, "status": "active"}',
|
|
299
|
+
placeholder: '{\n "limit": 10,\n "offset": 0,\n "search": "keyword"\n}',
|
|
300
|
+
},
|
|
301
|
+
// ===== ADVANCED MODE =====
|
|
302
|
+
{
|
|
303
|
+
displayName: 'Configuration JSON',
|
|
304
|
+
name: 'configJson',
|
|
305
|
+
type: 'json',
|
|
306
|
+
displayOptions: {
|
|
307
|
+
show: {
|
|
308
|
+
mode: ['advanced'],
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
default: '{\n "method": "GET",\n "endpoint": "/users",\n "body": {},\n "queryParams": {}\n}',
|
|
312
|
+
description: 'Complete JSON configuration for the API call',
|
|
313
|
+
placeholder: '{\n "method": "POST",\n "endpoint": "/users",\n "body": {\n "username": "newuser",\n "email": "user@example.com"\n },\n "queryParams": {},\n "headers": {}\n}',
|
|
314
|
+
required: true,
|
|
315
|
+
},
|
|
316
|
+
// ===== BATCH MODE =====
|
|
317
|
+
{
|
|
318
|
+
displayName: 'Batch Operations',
|
|
319
|
+
name: 'batchOperations',
|
|
320
|
+
type: 'json',
|
|
321
|
+
displayOptions: {
|
|
322
|
+
show: {
|
|
323
|
+
mode: ['batch'],
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
default: '[\n {\n "method": "GET",\n "endpoint": "/users"\n },\n {\n "method": "POST",\n "endpoint": "/clients",\n "body": {"name": "New Client"}\n }\n]',
|
|
327
|
+
description: 'Array of operations to execute in sequence. Each operation is a complete configuration.',
|
|
328
|
+
placeholder: '[\n {\n "method": "GET",\n "endpoint": "/users/123"\n },\n {\n "method": "PUT",\n "endpoint": "/users/123",\n "body": {"status": "active"}\n }\n]',
|
|
329
|
+
required: true,
|
|
330
|
+
},
|
|
331
|
+
// Options
|
|
332
|
+
{
|
|
333
|
+
displayName: 'Options',
|
|
334
|
+
name: 'options',
|
|
335
|
+
type: 'collection',
|
|
336
|
+
placeholder: 'Add Option',
|
|
337
|
+
default: {},
|
|
338
|
+
options: [
|
|
339
|
+
{
|
|
340
|
+
displayName: 'Continue on Fail',
|
|
341
|
+
name: 'continueOnFail',
|
|
342
|
+
type: 'boolean',
|
|
343
|
+
default: false,
|
|
344
|
+
description: 'Whether to continue execution if this operation fails',
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
displayName: 'Timeout',
|
|
348
|
+
name: 'timeout',
|
|
349
|
+
type: 'number',
|
|
350
|
+
default: 30000,
|
|
351
|
+
description: 'Request timeout in milliseconds',
|
|
352
|
+
},
|
|
353
|
+
{
|
|
354
|
+
displayName: 'Return Full Response',
|
|
355
|
+
name: 'fullResponse',
|
|
356
|
+
type: 'boolean',
|
|
357
|
+
default: false,
|
|
358
|
+
description: 'Whether to return full response including headers and status code',
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
displayName: 'Custom Headers',
|
|
362
|
+
name: 'customHeaders',
|
|
363
|
+
type: 'json',
|
|
364
|
+
default: '{}',
|
|
365
|
+
description: 'Additional headers to include in the request',
|
|
366
|
+
placeholder: '{\n "X-Custom-Header": "value"\n}',
|
|
367
|
+
},
|
|
368
|
+
],
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
async execute() {
|
|
374
|
+
const items = this.getInputData();
|
|
375
|
+
const returnData = [];
|
|
376
|
+
const credentials = await this.getCredentials('apiCustomCredentials');
|
|
377
|
+
const baseUrl = credentials.baseUrl; // injected via credentials
|
|
378
|
+
// headers injected via credentials (Bearer + X-API-DOMAIN + X-APIKEY-TOKEN)
|
|
379
|
+
for (let i = 0; i < items.length; i++) {
|
|
380
|
+
try {
|
|
381
|
+
const mode = this.getNodeParameter('mode', i);
|
|
382
|
+
const options = this.getNodeParameter('options', i, {});
|
|
383
|
+
const customHeaders = options.customHeaders ? JSON.parse(options.customHeaders) : {};
|
|
384
|
+
if (mode === 'simple') {
|
|
385
|
+
const result = await this.executeSimpleMode(i, baseUrl, customHeaders, options, this);
|
|
386
|
+
returnData.push(result);
|
|
387
|
+
}
|
|
388
|
+
else if (mode === 'advanced') {
|
|
389
|
+
const result = await this.executeAdvancedMode(i, baseUrl, customHeaders, options, this);
|
|
390
|
+
returnData.push(result);
|
|
391
|
+
}
|
|
392
|
+
else if (mode === 'batch') {
|
|
393
|
+
const results = await this.executeBatchMode(i, baseUrl, customHeaders, options, this);
|
|
394
|
+
returnData.push(...results);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
const options = this.getNodeParameter('options', i, {});
|
|
399
|
+
if (options.continueOnFail) {
|
|
400
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
401
|
+
const statusCode = error instanceof Error && 'statusCode' in error ? error.statusCode : 500;
|
|
402
|
+
returnData.push({
|
|
403
|
+
error: errorMessage,
|
|
404
|
+
statusCode: statusCode,
|
|
405
|
+
resource: this.getNodeParameter('resource', i, ''),
|
|
406
|
+
operation: this.getNodeParameter('operation', i, ''),
|
|
407
|
+
});
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
throw error;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return [this.helpers.returnJsonArray(returnData)];
|
|
414
|
+
}
|
|
415
|
+
async executeSimpleMode(itemIndex, baseUrl, customHeaders, options, executeFunctions) {
|
|
416
|
+
const resource = executeFunctions.getNodeParameter('resource', itemIndex);
|
|
417
|
+
const operation = executeFunctions.getNodeParameter('operation', itemIndex);
|
|
418
|
+
let endpoint = '';
|
|
419
|
+
let method = 'GET';
|
|
420
|
+
let body = {};
|
|
421
|
+
let queryParams = {};
|
|
422
|
+
// Build endpoint based on resource and operation
|
|
423
|
+
const resourceMap = {
|
|
424
|
+
'users': '/users',
|
|
425
|
+
'clients': '/clients',
|
|
426
|
+
'items': '/items',
|
|
427
|
+
'itemTypes': '/itemTypes',
|
|
428
|
+
'tasks': '/tasks',
|
|
429
|
+
'services': '/services',
|
|
430
|
+
'products': '/products',
|
|
431
|
+
'wos': '/wos',
|
|
432
|
+
'modalities': '/modalities',
|
|
433
|
+
'tickets': '/tickets',
|
|
434
|
+
'properties': '/properties',
|
|
435
|
+
};
|
|
436
|
+
const baseEndpoint = resourceMap[resource] || '/users';
|
|
437
|
+
switch (operation) {
|
|
438
|
+
case 'create':
|
|
439
|
+
endpoint = baseEndpoint;
|
|
440
|
+
method = 'POST';
|
|
441
|
+
const createBody = executeFunctions.getNodeParameter('requestBody', itemIndex);
|
|
442
|
+
body = JSON.parse(createBody);
|
|
443
|
+
break;
|
|
444
|
+
case 'get':
|
|
445
|
+
const recordId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
446
|
+
endpoint = `${baseEndpoint}/${recordId}`;
|
|
447
|
+
method = 'GET';
|
|
448
|
+
break;
|
|
449
|
+
case 'getByUsername':
|
|
450
|
+
const username = executeFunctions.getNodeParameter('username', itemIndex);
|
|
451
|
+
endpoint = `${baseEndpoint}/${username}/user`;
|
|
452
|
+
method = 'GET';
|
|
453
|
+
break;
|
|
454
|
+
case 'getAll':
|
|
455
|
+
endpoint = baseEndpoint;
|
|
456
|
+
method = 'GET';
|
|
457
|
+
const queryParamsStr = executeFunctions.getNodeParameter('queryParameters', itemIndex, '{}');
|
|
458
|
+
queryParams = JSON.parse(queryParamsStr);
|
|
459
|
+
break;
|
|
460
|
+
case 'update':
|
|
461
|
+
const updateId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
462
|
+
endpoint = `${baseEndpoint}/${updateId}`;
|
|
463
|
+
method = 'PUT';
|
|
464
|
+
const updateBody = executeFunctions.getNodeParameter('requestBody', itemIndex);
|
|
465
|
+
body = JSON.parse(updateBody);
|
|
466
|
+
break;
|
|
467
|
+
case 'activate':
|
|
468
|
+
const activateId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
469
|
+
endpoint = `${baseEndpoint}/${activateId}/active`;
|
|
470
|
+
method = resource === 'users' ? 'PATCH' : 'PUT';
|
|
471
|
+
break;
|
|
472
|
+
case 'deactivate':
|
|
473
|
+
const deactivateId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
474
|
+
endpoint = `${baseEndpoint}/${deactivateId}/inactive`;
|
|
475
|
+
method = resource === 'users' ? 'PATCH' : 'PUT';
|
|
476
|
+
break;
|
|
477
|
+
case 'delete':
|
|
478
|
+
const deleteId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
479
|
+
endpoint = `${baseEndpoint}/${deleteId}`;
|
|
480
|
+
method = 'DELETE';
|
|
481
|
+
break;
|
|
482
|
+
case 'linkTasks':
|
|
483
|
+
endpoint = '/users/tasks';
|
|
484
|
+
method = 'POST';
|
|
485
|
+
const linkBody = executeFunctions.getNodeParameter('requestBody', itemIndex);
|
|
486
|
+
body = JSON.parse(linkBody);
|
|
487
|
+
break;
|
|
488
|
+
case 'unlinkTasks':
|
|
489
|
+
const employeeId = executeFunctions.getNodeParameter('employeeId', itemIndex);
|
|
490
|
+
endpoint = `/users/tasks/${employeeId}`;
|
|
491
|
+
method = 'DELETE';
|
|
492
|
+
break;
|
|
493
|
+
case 'getUserTasks':
|
|
494
|
+
const userTasksId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
495
|
+
endpoint = `/users/${userTasksId}/tasks`;
|
|
496
|
+
method = 'GET';
|
|
497
|
+
break;
|
|
498
|
+
case 'getUserTickets':
|
|
499
|
+
const userTicketsId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
500
|
+
endpoint = `/users/${userTicketsId}/tickets`;
|
|
501
|
+
method = 'GET';
|
|
502
|
+
break;
|
|
503
|
+
case 'getUserPermissions':
|
|
504
|
+
const userPermId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
505
|
+
endpoint = `/users/${userPermId}/permissions`;
|
|
506
|
+
method = 'GET';
|
|
507
|
+
break;
|
|
508
|
+
case 'uploadPhoto':
|
|
509
|
+
const photoUserId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
510
|
+
endpoint = `/users/${photoUserId}/photos`;
|
|
511
|
+
method = 'PATCH';
|
|
512
|
+
break;
|
|
513
|
+
case 'uploadSignature':
|
|
514
|
+
const sigUserId = executeFunctions.getNodeParameter('recordId', itemIndex);
|
|
515
|
+
endpoint = `/users/${sigUserId}/signatures`;
|
|
516
|
+
method = 'PATCH';
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
return await this.makeRequest(baseUrl, endpoint, method, body, queryParams, customHeaders, options, executeFunctions);
|
|
520
|
+
}
|
|
521
|
+
async executeAdvancedMode(itemIndex, baseUrl, customHeaders, options, executeFunctions) {
|
|
522
|
+
const configStr = executeFunctions.getNodeParameter('configJson', itemIndex);
|
|
523
|
+
const config = JSON.parse(configStr);
|
|
524
|
+
const method = config.method || 'GET';
|
|
525
|
+
const endpoint = config.endpoint || '/';
|
|
526
|
+
const body = config.body || {};
|
|
527
|
+
const queryParams = config.queryParams || {};
|
|
528
|
+
const additionalHeaders = config.headers || {};
|
|
529
|
+
const mergedHeaders = { ...customHeaders, ...additionalHeaders };
|
|
530
|
+
return await this.makeRequest(baseUrl, endpoint, method, body, queryParams, mergedHeaders, options, executeFunctions);
|
|
531
|
+
}
|
|
532
|
+
async executeBatchMode(itemIndex, baseUrl, customHeaders, options, executeFunctions) {
|
|
533
|
+
const batchStr = executeFunctions.getNodeParameter('batchOperations', itemIndex);
|
|
534
|
+
const batchOps = JSON.parse(batchStr);
|
|
535
|
+
const results = [];
|
|
536
|
+
for (const op of batchOps) {
|
|
537
|
+
try {
|
|
538
|
+
const method = op.method || 'GET';
|
|
539
|
+
const endpoint = op.endpoint || '/';
|
|
540
|
+
const body = op.body || {};
|
|
541
|
+
const queryParams = op.queryParams || {};
|
|
542
|
+
const additionalHeaders = op.headers || {};
|
|
543
|
+
const mergedHeaders = { ...customHeaders, ...additionalHeaders };
|
|
544
|
+
const result = await this.makeRequest(baseUrl, endpoint, method, body, queryParams, mergedHeaders, options, executeFunctions);
|
|
545
|
+
results.push({
|
|
546
|
+
...result,
|
|
547
|
+
_batchOperation: {
|
|
548
|
+
method,
|
|
549
|
+
endpoint,
|
|
550
|
+
success: true,
|
|
551
|
+
},
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
if (options.continueOnFail) {
|
|
556
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
557
|
+
results.push({
|
|
558
|
+
error: errorMessage,
|
|
559
|
+
_batchOperation: {
|
|
560
|
+
method: op.method,
|
|
561
|
+
endpoint: op.endpoint,
|
|
562
|
+
success: false,
|
|
563
|
+
},
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
throw error;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return results;
|
|
572
|
+
}
|
|
573
|
+
async makeRequest(baseUrl, endpoint, method, body, queryParams, customHeaders, options, executeFunctions) {
|
|
574
|
+
const url = new URL(`${baseUrl}${endpoint}`);
|
|
575
|
+
// Add query parameters
|
|
576
|
+
Object.keys(queryParams).forEach(key => {
|
|
577
|
+
url.searchParams.append(key, String(queryParams[key]));
|
|
578
|
+
});
|
|
579
|
+
const requestOptions = {
|
|
580
|
+
method: method,
|
|
581
|
+
url: url.toString(),
|
|
582
|
+
headers: {
|
|
583
|
+
'Content-Type': 'application/json',
|
|
584
|
+
...customHeaders,
|
|
585
|
+
},
|
|
586
|
+
json: true,
|
|
587
|
+
timeout: options.timeout || 30000,
|
|
588
|
+
};
|
|
589
|
+
if (method !== 'GET' && method !== 'DELETE' && Object.keys(body).length > 0) {
|
|
590
|
+
requestOptions.body = body;
|
|
591
|
+
}
|
|
592
|
+
if (options.fullResponse) {
|
|
593
|
+
requestOptions.returnFullResponse = true;
|
|
594
|
+
}
|
|
595
|
+
const responseData = await executeFunctions.helpers.httpRequestWithAuthentication.call(executeFunctions, 'apiCustomCredentials', requestOptions);
|
|
596
|
+
return responseData;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
exports.ApiAgentNode = ApiAgentNode;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription, IDataObject } from 'n8n-workflow';
|
|
2
|
+
/**
|
|
3
|
+
* AI Agent Tool node
|
|
4
|
+
*
|
|
5
|
+
* - Designed to be easy for LLMs to call (OpenAI-friendly schema)
|
|
6
|
+
* - Uses apiCustomCredentials to inject:
|
|
7
|
+
* Authorization: Bearer <token>
|
|
8
|
+
* X-API-DOMAIN: <domain>
|
|
9
|
+
* X-APIKEY-TOKEN: <apikey>
|
|
10
|
+
*/
|
|
11
|
+
export declare class ApiAgentTool implements INodeType {
|
|
12
|
+
description: INodeTypeDescription;
|
|
13
|
+
/**
|
|
14
|
+
* Tool schema + semantic auto-description
|
|
15
|
+
* The AI Agent uses this to decide WHEN to call the tool and HOW to format inputs.
|
|
16
|
+
*/
|
|
17
|
+
getToolDescription(): IDataObject;
|
|
18
|
+
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
19
|
+
}
|