n8n-nodes-qlik-cloud 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.
@@ -0,0 +1,424 @@
1
+ import type {
2
+ IExecuteFunctions,
3
+ INodeExecutionData,
4
+ INodeType,
5
+ INodeTypeDescription,
6
+ GenericValue,
7
+ IGetNodeParameterOptions,
8
+ } from 'n8n-workflow';
9
+ import { NodeOperationError } from 'n8n-workflow';
10
+
11
+ import { qlikApiRequest } from '../shared/transport';
12
+ import { appDescription } from './resources/apps/index';
13
+ import { assistantDescription } from './resources/assistants/index';
14
+ import { auditDescription } from './resources/audits/index';
15
+ import { itemDescription } from './resources/items/index';
16
+
17
+ export class QlikCloud implements INodeType {
18
+ description: INodeTypeDescription = {
19
+ displayName: 'Qlik Cloud',
20
+ name: 'qlikCloud',
21
+ icon: 'file:qlik.svg',
22
+ group: ['transform'],
23
+ version: 1,
24
+ subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}',
25
+ description: 'Interact with Qlik Cloud APIs (Apps, Items, Audits, Assistants)',
26
+ defaults: {
27
+ name: 'Qlik Cloud',
28
+ },
29
+ inputs: ['main'],
30
+ outputs: ['main'],
31
+ credentials: [
32
+ {
33
+ name: 'qlikCloudApi',
34
+ required: true,
35
+ },
36
+ ],
37
+ properties: [
38
+ {
39
+ displayName: 'Resource',
40
+ name: 'resource',
41
+ type: 'options',
42
+ noDataExpression: true,
43
+ options: [
44
+ {
45
+ name: 'Apps',
46
+ value: 'apps',
47
+ description: 'Manage Qlik Cloud applications',
48
+ },
49
+ {
50
+ name: 'Assistants',
51
+ value: 'assistants',
52
+ description: 'Interact with AI assistants',
53
+ },
54
+ {
55
+ name: 'Audits',
56
+ value: 'audits',
57
+ description: 'Access audit logs and events',
58
+ },
59
+ {
60
+ name: 'Items',
61
+ value: 'items',
62
+ description: 'Manage items in Qlik Cloud',
63
+ },
64
+ ],
65
+ default: 'apps',
66
+ },
67
+ ...appDescription,
68
+ ...assistantDescription,
69
+ ...auditDescription,
70
+ ...itemDescription,
71
+ ],
72
+ };
73
+
74
+ async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
75
+ const items = this.getInputData();
76
+ let responseData;
77
+ const returnData: INodeExecutionData[] = [];
78
+
79
+ const resource = this.getNodeParameter('resource', 0) as string;
80
+ const operation = this.getNodeParameter('operation', 0) as string;
81
+
82
+ for (let i = 0; i < items.length; i++) {
83
+ try {
84
+ if (resource === 'apps') {
85
+ responseData = await this.handleAppsResource(operation);
86
+ } else if (resource === 'assistants') {
87
+ responseData = await this.handleAssistantsResource(operation);
88
+ } else if (resource === 'audits') {
89
+ responseData = await this.handleAuditsResource(operation);
90
+ } else if (resource === 'items') {
91
+ responseData = await this.handleItemsResource(operation);
92
+ }
93
+
94
+ const executionData = this.helpers.constructExecutionMetaData(
95
+ this.helpers.returnJsonArray(responseData as GenericValue[]),
96
+ { itemData: { item: i } },
97
+ );
98
+ returnData.push(...executionData);
99
+ } catch (error) {
100
+ if (this.continueOnFail()) {
101
+ returnData.push({
102
+ json: { error: (error as Error).message },
103
+ pairedItem: i,
104
+ });
105
+ } else {
106
+ throw error;
107
+ }
108
+ }
109
+ }
110
+
111
+ return [returnData];
112
+ }
113
+
114
+ private async handleAppsResource(operation: string): Promise<any> {
115
+ if (operation === 'getAll') {
116
+ const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
117
+ const limit = returnAll ? undefined : (this.getNodeParameter('limit', 0) as number);
118
+ const options = this.getNodeParameter('options', 0) as any;
119
+
120
+ const qs: any = {};
121
+ if (limit) {
122
+ qs.limit = limit;
123
+ }
124
+ if (options.name) {
125
+ qs.name = options.name;
126
+ }
127
+ if (options.spaceId) {
128
+ qs.spaceId = options.spaceId;
129
+ }
130
+
131
+ const response = await qlikApiRequest.call(this, 'GET', '/api/v1/apps', undefined, qs);
132
+ return response.data || response;
133
+ }
134
+
135
+ if (operation === 'get') {
136
+ const appId = this.getNodeParameter('appId', 0) as string;
137
+ return await qlikApiRequest.call(this, 'GET', `/api/v1/apps/${appId}`);
138
+ }
139
+
140
+ if (operation === 'create') {
141
+ const name = this.getNodeParameter('name', 0) as string;
142
+ const options = this.getNodeParameter('options', 0) as any;
143
+
144
+ const body = { attributes: { name } };
145
+ if (options.description) {
146
+ (body.attributes as any).description = options.description;
147
+ }
148
+ if (options.locale) {
149
+ (body.attributes as any).locale = options.locale;
150
+ }
151
+ if (options.spaceId) {
152
+ (body.attributes as any).spaceId = options.spaceId;
153
+ }
154
+
155
+ return await qlikApiRequest.call(this, 'POST', '/api/v1/apps', body);
156
+ }
157
+
158
+ if (operation === 'update') {
159
+ const appId = this.getNodeParameter('appId', 0) as string;
160
+ const body = this.getNodeParameter('body', 0) as any;
161
+ return await qlikApiRequest.call(this, 'PUT', `/api/v1/apps/${appId}`, body);
162
+ }
163
+
164
+ if (operation === 'delete') {
165
+ const appId = this.getNodeParameter('appId', 0) as string;
166
+ await qlikApiRequest.call(this, 'DELETE', `/api/v1/apps/${appId}`);
167
+ return { success: true };
168
+ }
169
+
170
+ if (operation === 'copy') {
171
+ const appId = this.getNodeParameter('appId', 0) as string;
172
+ const name = this.getNodeParameter('name', 0) as string;
173
+ const options = this.getNodeParameter('options', 0) as any;
174
+
175
+ const body = { attributes: { name } };
176
+ if (options.description) {
177
+ (body.attributes as any).description = options.description;
178
+ }
179
+ if (options.spaceId) {
180
+ (body.attributes as any).spaceId = options.spaceId;
181
+ }
182
+
183
+ return await qlikApiRequest.call(this, 'POST', `/api/v1/apps/${appId}/copy`, body);
184
+ }
185
+
186
+ if (operation === 'export') {
187
+ const appId = this.getNodeParameter('appId', 0) as string;
188
+ return await qlikApiRequest.call(this, 'POST', `/api/v1/apps/${appId}/export`, {});
189
+ }
190
+
191
+ if (operation === 'publish') {
192
+ const appId = this.getNodeParameter('appId', 0) as string;
193
+ const options = this.getNodeParameter('publishOptions', 0) as any;
194
+
195
+ const body: any = {};
196
+ if (options.spaceId) {
197
+ body.spaceId = options.spaceId;
198
+ }
199
+
200
+ return await qlikApiRequest.call(this, 'POST', `/api/v1/apps/${appId}/publish`, body);
201
+ }
202
+
203
+ if (operation === 'privileges') {
204
+ return await qlikApiRequest.call(this, 'GET', '/api/v1/apps/privileges');
205
+ }
206
+
207
+ throw new NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
208
+ }
209
+
210
+ private async handleAssistantsResource(operation: string): Promise<any> {
211
+ if (operation === 'getAll') {
212
+ const options = this.getNodeParameter('options', 0) as any;
213
+
214
+ const qs: any = {};
215
+ if (options.limit) {
216
+ qs.limit = options.limit;
217
+ }
218
+
219
+ return await qlikApiRequest.call(this, 'GET', '/api/v1/assistants', undefined, qs);
220
+ }
221
+
222
+ if (operation === 'get') {
223
+ const assistantId = this.getNodeParameter('assistantId', 0) as string;
224
+ return await qlikApiRequest.call(this, 'GET', `/api/v1/assistants/${assistantId}`);
225
+ }
226
+
227
+ if (operation === 'create') {
228
+ const name = this.getNodeParameter('name', 0) as string;
229
+ const options = this.getNodeParameter('options', 0) as any;
230
+
231
+ const body: any = { name };
232
+ if (options.description) {
233
+ body.description = options.description;
234
+ }
235
+
236
+ return await qlikApiRequest.call(this, 'POST', '/api/v1/assistants', body);
237
+ }
238
+
239
+ if (operation === 'search') {
240
+ const assistantId = this.getNodeParameter('assistantId', 0) as string;
241
+ const query = this.getNodeParameter('query', 0) as string;
242
+ const options = this.getNodeParameter('options', 0) as any;
243
+
244
+ const body: any = { text: query };
245
+ if (options.topN) {
246
+ body.topN = options.topN;
247
+ }
248
+ if (options.mode) {
249
+ body.mode = options.mode;
250
+ }
251
+
252
+ return await qlikApiRequest.call(
253
+ this,
254
+ 'POST',
255
+ `/api/v1/assistants/${assistantId}/actions/search`,
256
+ body,
257
+ );
258
+ }
259
+
260
+ if (operation === 'delete') {
261
+ const assistantId = this.getNodeParameter('assistantId', 0) as string;
262
+ await qlikApiRequest.call(this, 'DELETE', `/api/v1/assistants/${assistantId}`);
263
+ return { success: true };
264
+ }
265
+
266
+ throw new NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
267
+ }
268
+
269
+ private async handleAuditsResource(operation: string): Promise<any> {
270
+ if (operation === 'getAll') {
271
+ const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
272
+ const limit = returnAll ? undefined : (this.getNodeParameter('limit', 0) as number);
273
+ const options = this.getNodeParameter('options', 0) as any;
274
+
275
+ const qs: any = {};
276
+ if (limit) {
277
+ qs.limit = limit;
278
+ }
279
+ if (options.eventType) {
280
+ qs.eventType = options.eventType;
281
+ }
282
+ if (options.userId) {
283
+ qs.userId = options.userId;
284
+ }
285
+ if (options.source) {
286
+ qs.source = options.source;
287
+ }
288
+ if (options.eventTime) {
289
+ qs.eventTime = options.eventTime;
290
+ }
291
+ if (options.sort) {
292
+ qs.sort = options.sort;
293
+ }
294
+
295
+ const response = await qlikApiRequest.call(this, 'GET', '/api/v1/audits', undefined, qs);
296
+ return response.data || response;
297
+ }
298
+
299
+ if (operation === 'get') {
300
+ const auditId = this.getNodeParameter('auditId', 0) as string;
301
+ return await qlikApiRequest.call(this, 'GET', `/api/v1/audits/${auditId}`);
302
+ }
303
+
304
+ if (operation === 'getSources') {
305
+ const response = await qlikApiRequest.call(this, 'GET', '/api/v1/audits/sources');
306
+ return response.data || response;
307
+ }
308
+
309
+ if (operation === 'getTypes') {
310
+ const response = await qlikApiRequest.call(this, 'GET', '/api/v1/audits/types');
311
+ return response.data || response;
312
+ }
313
+
314
+ if (operation === 'getSettings') {
315
+ const response = await qlikApiRequest.call(this, 'GET', '/api/v1/audits/settings');
316
+ return response.data || response;
317
+ }
318
+
319
+ throw new NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
320
+ }
321
+
322
+ private async handleItemsResource(operation: string): Promise<any> {
323
+ if (operation === 'getAll') {
324
+ const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
325
+ const limit = returnAll ? undefined : (this.getNodeParameter('limit', 0) as number);
326
+ const options = this.getNodeParameter('options', 0) as any;
327
+
328
+ const qs: any = {};
329
+ if (limit) {
330
+ qs.limit = limit;
331
+ }
332
+ if (options.name) {
333
+ qs.name = options.name;
334
+ }
335
+ if (options.resourceType) {
336
+ qs.resourceType = options.resourceType;
337
+ }
338
+ if (options.spaceId) {
339
+ qs.spaceId = options.spaceId;
340
+ }
341
+ if (options.ownerId) {
342
+ qs.ownerId = options.ownerId;
343
+ }
344
+ if (options.sort) {
345
+ qs.sort = options.sort;
346
+ }
347
+
348
+ const response = await qlikApiRequest.call(this, 'GET', '/api/v1/items', undefined, qs);
349
+ return response.data || response;
350
+ }
351
+
352
+ if (operation === 'get') {
353
+ const itemId = this.getNodeParameter('itemId', 0) as string;
354
+ return await qlikApiRequest.call(this, 'GET', `/api/v1/items/${itemId}`);
355
+ }
356
+
357
+ if (operation === 'update') {
358
+ const itemId = this.getNodeParameter('itemId', 0) as string;
359
+ const body = this.getNodeParameter('body', 0) as any;
360
+ return await qlikApiRequest.call(this, 'PUT', `/api/v1/items/${itemId}`, body);
361
+ }
362
+
363
+ if (operation === 'delete') {
364
+ const itemId = this.getNodeParameter('itemId', 0) as string;
365
+ await qlikApiRequest.call(this, 'DELETE', `/api/v1/items/${itemId}`);
366
+ return { success: true };
367
+ }
368
+
369
+ if (operation === 'collections') {
370
+ const itemId = this.getNodeParameter('itemId', 0) as string;
371
+ const options = this.getNodeParameter('options', 0) as any;
372
+
373
+ const qs: any = {};
374
+ if (options.limit) {
375
+ qs.limit = options.limit;
376
+ }
377
+
378
+ const response = await qlikApiRequest.call(
379
+ this,
380
+ 'GET',
381
+ `/api/v1/items/${itemId}/collections`,
382
+ undefined,
383
+ qs,
384
+ );
385
+ return response.data || response;
386
+ }
387
+
388
+ if (operation === 'publishedItems') {
389
+ const itemId = this.getNodeParameter('itemId', 0) as string;
390
+ const options = this.getNodeParameter('options', 0) as any;
391
+
392
+ const qs: any = {};
393
+ if (options.limit) {
394
+ qs.limit = options.limit;
395
+ }
396
+
397
+ const response = await qlikApiRequest.call(
398
+ this,
399
+ 'GET',
400
+ `/api/v1/items/${itemId}/publisheditems`,
401
+ undefined,
402
+ qs,
403
+ );
404
+ return response.data || response;
405
+ }
406
+
407
+ if (operation === 'settings') {
408
+ const settingsOperation = this.getNodeParameter('settingsOperation', 0) as string;
409
+
410
+ if (settingsOperation === 'get') {
411
+ const response = await qlikApiRequest.call(this, 'GET', '/api/v1/items/settings');
412
+ return response.data || response;
413
+ }
414
+
415
+ if (settingsOperation === 'patch') {
416
+ const body = this.getNodeParameter('body', 0) as any;
417
+ const response = await qlikApiRequest.call(this, 'PATCH', '/api/v1/items/settings', body);
418
+ return response.data || response;
419
+ }
420
+ }
421
+
422
+ throw new NodeOperationError(this.getNode(), `Unknown operation: ${operation}`);
423
+ }
424
+ }