@fsai-flow/workflow 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/README.md +31 -0
  2. package/dist/package.json +42 -0
  3. package/dist/src/index.d.ts +21 -0
  4. package/dist/src/index.js +33 -0
  5. package/dist/src/index.js.map +1 -0
  6. package/dist/src/lib/Constants.d.ts +68 -0
  7. package/dist/src/lib/Constants.js +106 -0
  8. package/dist/src/lib/Constants.js.map +1 -0
  9. package/dist/src/lib/DeferredPromise.d.ts +6 -0
  10. package/dist/src/lib/DeferredPromise.js +11 -0
  11. package/dist/src/lib/DeferredPromise.js.map +1 -0
  12. package/dist/src/lib/Expression.d.ts +65 -0
  13. package/dist/src/lib/Expression.js +215 -0
  14. package/dist/src/lib/Expression.js.map +1 -0
  15. package/dist/src/lib/Interfaces.d.ts +1579 -0
  16. package/dist/src/lib/Interfaces.js +44 -0
  17. package/dist/src/lib/Interfaces.js.map +1 -0
  18. package/dist/src/lib/LoggerProxy.d.ts +9 -0
  19. package/dist/src/lib/LoggerProxy.js +40 -0
  20. package/dist/src/lib/LoggerProxy.js.map +1 -0
  21. package/dist/src/lib/MetadataUtils.d.ts +4 -0
  22. package/dist/src/lib/MetadataUtils.js +27 -0
  23. package/dist/src/lib/MetadataUtils.js.map +1 -0
  24. package/dist/src/lib/NodeErrors.d.ts +82 -0
  25. package/dist/src/lib/NodeErrors.js +289 -0
  26. package/dist/src/lib/NodeErrors.js.map +1 -0
  27. package/dist/src/lib/NodeHelpers.d.ts +198 -0
  28. package/dist/src/lib/NodeHelpers.js +1348 -0
  29. package/dist/src/lib/NodeHelpers.js.map +1 -0
  30. package/dist/src/lib/ObservableObject.d.ts +5 -0
  31. package/dist/src/lib/ObservableObject.js +61 -0
  32. package/dist/src/lib/ObservableObject.js.map +1 -0
  33. package/dist/src/lib/RoutingNode.d.ts +18 -0
  34. package/dist/src/lib/RoutingNode.js +508 -0
  35. package/dist/src/lib/RoutingNode.js.map +1 -0
  36. package/dist/src/lib/TelemetryHelpers.d.ts +3 -0
  37. package/dist/src/lib/TelemetryHelpers.js +69 -0
  38. package/dist/src/lib/TelemetryHelpers.js.map +1 -0
  39. package/dist/src/lib/TypeValidation.d.ts +21 -0
  40. package/dist/src/lib/TypeValidation.js +385 -0
  41. package/dist/src/lib/TypeValidation.js.map +1 -0
  42. package/dist/src/lib/VersionedNodeType.d.ts +9 -0
  43. package/dist/src/lib/VersionedNodeType.js +26 -0
  44. package/dist/src/lib/VersionedNodeType.js.map +1 -0
  45. package/dist/src/lib/Workflow.d.ts +248 -0
  46. package/dist/src/lib/Workflow.js +904 -0
  47. package/dist/src/lib/Workflow.js.map +1 -0
  48. package/dist/src/lib/WorkflowDataProxy.d.ts +87 -0
  49. package/dist/src/lib/WorkflowDataProxy.js +556 -0
  50. package/dist/src/lib/WorkflowDataProxy.js.map +1 -0
  51. package/dist/src/lib/WorkflowErrors.d.ts +9 -0
  52. package/dist/src/lib/WorkflowErrors.js +18 -0
  53. package/dist/src/lib/WorkflowErrors.js.map +1 -0
  54. package/dist/src/lib/WorkflowHooks.d.ts +11 -0
  55. package/dist/src/lib/WorkflowHooks.js +34 -0
  56. package/dist/src/lib/WorkflowHooks.js.map +1 -0
  57. package/dist/src/lib/errors/base/base.error.d.ts +30 -0
  58. package/dist/src/lib/errors/base/base.error.js +45 -0
  59. package/dist/src/lib/errors/base/base.error.js.map +1 -0
  60. package/dist/src/lib/errors/base/operational.error.d.ts +15 -0
  61. package/dist/src/lib/errors/base/operational.error.js +19 -0
  62. package/dist/src/lib/errors/base/operational.error.js.map +1 -0
  63. package/dist/src/lib/errors/error.types.d.ts +11 -0
  64. package/dist/src/lib/errors/error.types.js +3 -0
  65. package/dist/src/lib/errors/error.types.js.map +1 -0
  66. package/dist/src/lib/errors/index.d.ts +1 -0
  67. package/dist/src/lib/errors/index.js +6 -0
  68. package/dist/src/lib/errors/index.js.map +1 -0
  69. package/dist/src/lib/result.d.ts +19 -0
  70. package/dist/src/lib/result.js +36 -0
  71. package/dist/src/lib/result.js.map +1 -0
  72. package/dist/src/lib/utils.d.ts +50 -0
  73. package/dist/src/lib/utils.js +119 -0
  74. package/dist/src/lib/utils.js.map +1 -0
  75. package/package.json +5 -1
  76. package/src/lib/Interfaces.ts +28 -33
  77. package/src/lib/Workflow.ts +1 -1
  78. package/src/lib/WorkflowDataProxy.ts +1 -1
  79. package/src/lib/utils.ts +99 -120
@@ -0,0 +1,1348 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cronNodeOptions = void 0;
4
+ exports.getConnectionTypes = getConnectionTypes;
5
+ exports.isSubNodeType = isSubNodeType;
6
+ exports.getSpecialNodeParameters = getSpecialNodeParameters;
7
+ exports.displayParameter = displayParameter;
8
+ exports.displayParameterPath = displayParameterPath;
9
+ exports.getContext = getContext;
10
+ exports.getParamterDependencies = getParamterDependencies;
11
+ exports.getParamterResolveOrder = getParamterResolveOrder;
12
+ exports.getNodeParameters = getNodeParameters;
13
+ exports.prepareOutputData = prepareOutputData;
14
+ exports.getNodeWebhooks = getNodeWebhooks;
15
+ exports.getNodeWebhooksBasic = getNodeWebhooksBasic;
16
+ exports.getNodeWebhookPath = getNodeWebhookPath;
17
+ exports.getNodeWebhookUrl = getNodeWebhookUrl;
18
+ exports.getNodeParametersIssues = getNodeParametersIssues;
19
+ exports.nodeIssuesToString = nodeIssuesToString;
20
+ exports.addToIssuesIfMissing = addToIssuesIfMissing;
21
+ exports.getParameterValueByPath = getParameterValueByPath;
22
+ exports.getParameterIssues = getParameterIssues;
23
+ exports.mergeIssues = mergeIssues;
24
+ exports.mergeNodeProperties = mergeNodeProperties;
25
+ exports.getVersionedNodeType = getVersionedNodeType;
26
+ exports.getVersionedNodeTypeAll = getVersionedNodeTypeAll;
27
+ exports.isNodeTypeVersioned = isNodeTypeVersioned;
28
+ exports.getParameterValue = getParameterValue;
29
+ /* eslint-disable @typescript-eslint/no-unsafe-call */
30
+ /* eslint-disable @typescript-eslint/no-unsafe-return */
31
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
32
+ /* eslint-disable no-console */
33
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
34
+ /* eslint-disable @typescript-eslint/no-use-before-define */
35
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
36
+ /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
37
+ /* eslint-disable no-param-reassign */
38
+ /* eslint-disable no-continue */
39
+ /* eslint-disable prefer-spread */
40
+ /* eslint-disable no-restricted-syntax */
41
+ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
42
+ /* eslint-disable import/no-cycle */
43
+ // eslint-disable-next-line import/no-extraneous-dependencies
44
+ const lodash_1 = require("lodash");
45
+ const Interfaces_1 = require("./Interfaces");
46
+ function getConnectionTypes(connections) {
47
+ return connections
48
+ .map((connection) => {
49
+ if (typeof connection === 'string') {
50
+ return connection;
51
+ }
52
+ return connection.type;
53
+ })
54
+ .filter((connection) => connection !== undefined);
55
+ }
56
+ exports.cronNodeOptions = [
57
+ {
58
+ name: 'item',
59
+ displayName: 'Item',
60
+ values: [
61
+ {
62
+ displayName: 'Mode',
63
+ name: 'mode',
64
+ type: 'options',
65
+ options: [
66
+ {
67
+ name: 'Every Minute',
68
+ value: 'everyMinute',
69
+ },
70
+ {
71
+ name: 'Every Hour',
72
+ value: 'everyHour',
73
+ },
74
+ {
75
+ name: 'Every Day',
76
+ value: 'everyDay',
77
+ },
78
+ {
79
+ name: 'Every Week',
80
+ value: 'everyWeek',
81
+ },
82
+ {
83
+ name: 'Every Month',
84
+ value: 'everyMonth',
85
+ },
86
+ {
87
+ name: 'Every X',
88
+ value: 'everyX',
89
+ },
90
+ {
91
+ name: 'Custom',
92
+ value: 'custom',
93
+ },
94
+ ],
95
+ default: 'everyDay',
96
+ description: 'How often to trigger.',
97
+ },
98
+ {
99
+ displayName: 'Hour',
100
+ name: 'hour',
101
+ type: 'number',
102
+ typeOptions: {
103
+ minValue: 0,
104
+ maxValue: 23,
105
+ },
106
+ displayOptions: {
107
+ hide: {
108
+ mode: ['custom', 'everyHour', 'everyMinute', 'everyX'],
109
+ },
110
+ },
111
+ default: 14,
112
+ description: 'The hour of the day to trigger (24h format)',
113
+ },
114
+ {
115
+ displayName: 'Minute',
116
+ name: 'minute',
117
+ type: 'number',
118
+ typeOptions: {
119
+ minValue: 0,
120
+ maxValue: 59,
121
+ },
122
+ displayOptions: {
123
+ hide: {
124
+ mode: ['custom', 'everyMinute', 'everyX'],
125
+ },
126
+ },
127
+ default: 0,
128
+ description: 'The minute of the day to trigger',
129
+ },
130
+ {
131
+ displayName: 'Day of Month',
132
+ name: 'dayOfMonth',
133
+ type: 'number',
134
+ displayOptions: {
135
+ show: {
136
+ mode: ['everyMonth'],
137
+ },
138
+ },
139
+ typeOptions: {
140
+ minValue: 1,
141
+ maxValue: 31,
142
+ },
143
+ default: 1,
144
+ description: 'The day of the month to trigger',
145
+ },
146
+ {
147
+ displayName: 'Weekday',
148
+ name: 'weekday',
149
+ type: 'options',
150
+ displayOptions: {
151
+ show: {
152
+ mode: ['everyWeek'],
153
+ },
154
+ },
155
+ options: [
156
+ {
157
+ name: 'Monday',
158
+ value: '1',
159
+ },
160
+ {
161
+ name: 'Tuesday',
162
+ value: '2',
163
+ },
164
+ {
165
+ name: 'Wednesday',
166
+ value: '3',
167
+ },
168
+ {
169
+ name: 'Thursday',
170
+ value: '4',
171
+ },
172
+ {
173
+ name: 'Friday',
174
+ value: '5',
175
+ },
176
+ {
177
+ name: 'Saturday',
178
+ value: '6',
179
+ },
180
+ {
181
+ name: 'Sunday',
182
+ value: '0',
183
+ },
184
+ ],
185
+ default: '1',
186
+ description: 'The weekday to trigger',
187
+ },
188
+ {
189
+ displayName: 'Cron Expression',
190
+ name: 'cronExpression',
191
+ type: 'string',
192
+ displayOptions: {
193
+ show: {
194
+ mode: ['custom'],
195
+ },
196
+ },
197
+ default: '* * * * * *',
198
+ description: 'Use custom cron expression. Values and ranges as follows:<ul><li>Seconds: 0-59</li><li>Minutes: 0 - 59</li><li>Hours: 0 - 23</li><li>Day of Month: 1 - 31</li><li>Months: 0 - 11 (Jan - Dec)</li><li>Day of Week: 0 - 6 (Sun - Sat)</li></ul>',
199
+ },
200
+ {
201
+ displayName: 'Value',
202
+ name: 'value',
203
+ type: 'number',
204
+ typeOptions: {
205
+ minValue: 0,
206
+ maxValue: 1000,
207
+ },
208
+ displayOptions: {
209
+ show: {
210
+ mode: ['everyX'],
211
+ },
212
+ },
213
+ default: 2,
214
+ description: 'All how many X minutes/hours it should trigger',
215
+ },
216
+ {
217
+ displayName: 'Unit',
218
+ name: 'unit',
219
+ type: 'options',
220
+ displayOptions: {
221
+ show: {
222
+ mode: ['everyX'],
223
+ },
224
+ },
225
+ options: [
226
+ {
227
+ name: 'Minutes',
228
+ value: 'minutes',
229
+ },
230
+ {
231
+ name: 'Hours',
232
+ value: 'hours',
233
+ },
234
+ {
235
+ name: 'Seconds',
236
+ value: 'seconds',
237
+ },
238
+ ],
239
+ default: 'hours',
240
+ description: 'If it should trigger all X minutes or hours',
241
+ },
242
+ ],
243
+ },
244
+ ];
245
+ function isSubNodeType(typeDescription) {
246
+ if (!typeDescription?.outputs || typeof typeDescription.outputs === 'string') {
247
+ return false;
248
+ }
249
+ const outputTypes = getConnectionTypes(typeDescription.outputs);
250
+ return outputTypes
251
+ ? outputTypes.filter((output) => output !== Interfaces_1.NodeConnectionTypes.Main).length > 0
252
+ : false;
253
+ }
254
+ /**
255
+ * Gets special parameters which should be added to nodeTypes depending
256
+ * on their type or configuration
257
+ *
258
+ * @export
259
+ * @param {INodeType} nodeType
260
+ * @returns
261
+ */
262
+ function getSpecialNodeParameters(nodeType) {
263
+ if (nodeType.description.polling === true) {
264
+ return [
265
+ {
266
+ displayName: 'Poll Times',
267
+ name: 'pollTimes',
268
+ type: 'fixedCollection',
269
+ typeOptions: {
270
+ multipleValues: true,
271
+ multipleValueButtonText: 'Add Poll Time',
272
+ },
273
+ default: { item: [{ mode: 'everyMinute' }] },
274
+ description: 'Time at which polling should occur',
275
+ placeholder: 'Add Poll Time',
276
+ options: [
277
+ {
278
+ name: 'item',
279
+ displayName: 'Item',
280
+ values: [
281
+ {
282
+ displayName: 'Mode',
283
+ name: 'mode',
284
+ type: 'options',
285
+ options: [
286
+ {
287
+ name: 'Every Minute',
288
+ value: 'everyMinute',
289
+ },
290
+ {
291
+ name: 'Every Hour',
292
+ value: 'everyHour',
293
+ },
294
+ {
295
+ name: 'Every Day',
296
+ value: 'everyDay',
297
+ },
298
+ {
299
+ name: 'Every Week',
300
+ value: 'everyWeek',
301
+ },
302
+ {
303
+ name: 'Every Month',
304
+ value: 'everyMonth',
305
+ },
306
+ {
307
+ name: 'Every X',
308
+ value: 'everyX',
309
+ },
310
+ {
311
+ name: 'Custom',
312
+ value: 'custom',
313
+ },
314
+ ],
315
+ default: 'everyDay',
316
+ description: 'How often to trigger.',
317
+ },
318
+ {
319
+ displayName: 'Hour',
320
+ name: 'hour',
321
+ type: 'number',
322
+ typeOptions: {
323
+ minValue: 0,
324
+ maxValue: 23,
325
+ },
326
+ displayOptions: {
327
+ hide: {
328
+ mode: ['custom', 'everyHour', 'everyMinute', 'everyX'],
329
+ },
330
+ },
331
+ default: 14,
332
+ description: 'The hour of the day to trigger (24h format)',
333
+ },
334
+ {
335
+ displayName: 'Minute',
336
+ name: 'minute',
337
+ type: 'number',
338
+ typeOptions: {
339
+ minValue: 0,
340
+ maxValue: 59,
341
+ },
342
+ displayOptions: {
343
+ hide: {
344
+ mode: ['custom', 'everyMinute', 'everyX'],
345
+ },
346
+ },
347
+ default: 0,
348
+ description: 'The minute of the day to trigger',
349
+ },
350
+ {
351
+ displayName: 'Day of Month',
352
+ name: 'dayOfMonth',
353
+ type: 'number',
354
+ displayOptions: {
355
+ show: {
356
+ mode: ['everyMonth'],
357
+ },
358
+ },
359
+ typeOptions: {
360
+ minValue: 1,
361
+ maxValue: 31,
362
+ },
363
+ default: 1,
364
+ description: 'The day of the month to trigger',
365
+ },
366
+ {
367
+ displayName: 'Weekday',
368
+ name: 'weekday',
369
+ type: 'options',
370
+ displayOptions: {
371
+ show: {
372
+ mode: ['everyWeek'],
373
+ },
374
+ },
375
+ options: [
376
+ {
377
+ name: 'Monday',
378
+ value: '1',
379
+ },
380
+ {
381
+ name: 'Tuesday',
382
+ value: '2',
383
+ },
384
+ {
385
+ name: 'Wednesday',
386
+ value: '3',
387
+ },
388
+ {
389
+ name: 'Thursday',
390
+ value: '4',
391
+ },
392
+ {
393
+ name: 'Friday',
394
+ value: '5',
395
+ },
396
+ {
397
+ name: 'Saturday',
398
+ value: '6',
399
+ },
400
+ {
401
+ name: 'Sunday',
402
+ value: '0',
403
+ },
404
+ ],
405
+ default: '1',
406
+ description: 'The weekday to trigger',
407
+ },
408
+ {
409
+ displayName: 'Cron Expression',
410
+ name: 'cronExpression',
411
+ type: 'string',
412
+ displayOptions: {
413
+ show: {
414
+ mode: ['custom'],
415
+ },
416
+ },
417
+ default: '* * * * * *',
418
+ description: 'Use custom cron expression. Values and ranges as follows:<ul><li>Seconds: 0-59</li><li>Minutes: 0 - 59</li><li>Hours: 0 - 23</li><li>Day of Month: 1 - 31</li><li>Months: 0 - 11 (Jan - Dec)</li><li>Day of Week: 0 - 6 (Sun - Sat)</li></ul>',
419
+ },
420
+ {
421
+ displayName: 'Value',
422
+ name: 'value',
423
+ type: 'number',
424
+ typeOptions: {
425
+ minValue: 0,
426
+ maxValue: 1000,
427
+ },
428
+ displayOptions: {
429
+ show: {
430
+ mode: ['everyX'],
431
+ },
432
+ },
433
+ default: 2,
434
+ description: 'All how many X minutes/hours it should trigger',
435
+ },
436
+ {
437
+ displayName: 'Unit',
438
+ name: 'unit',
439
+ type: 'options',
440
+ displayOptions: {
441
+ show: {
442
+ mode: ['everyX'],
443
+ },
444
+ },
445
+ options: [
446
+ {
447
+ name: 'Minutes',
448
+ value: 'minutes',
449
+ },
450
+ {
451
+ name: 'Hours',
452
+ value: 'hours',
453
+ },
454
+ {
455
+ name: 'Seconds',
456
+ value: 'seconds',
457
+ },
458
+ ],
459
+ default: 'hours',
460
+ description: 'If it should trigger all X minutes or hours',
461
+ },
462
+ ],
463
+ },
464
+ ],
465
+ },
466
+ ];
467
+ }
468
+ return [];
469
+ }
470
+ /**
471
+ * Returns if the parameter should be displayed or not
472
+ *
473
+ * @export
474
+ * @param {INodeParameters} nodeValues The data on the node which decides if the parameter
475
+ * should be displayed
476
+ * @param {(INodeProperties | INodeCredentialDescription)} parameter The parameter to check if it should be displayed
477
+ * @param {INodeParameters} [nodeValuesRoot] The root node-parameter-data
478
+ * @returns
479
+ */
480
+ function displayParameter(nodeValues, parameter, nodeValuesRoot) {
481
+ if (!parameter.displayOptions) {
482
+ return true;
483
+ }
484
+ nodeValuesRoot = nodeValuesRoot || nodeValues;
485
+ let value;
486
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
487
+ const values = [];
488
+ if (parameter.displayOptions.show) {
489
+ // All the defined rules have to match to display parameter
490
+ for (const propertyName of Object.keys(parameter.displayOptions.show)) {
491
+ if (propertyName.charAt(0) === '/') {
492
+ // Get the value from the root of the node
493
+ value = (0, lodash_1.get)(nodeValuesRoot, propertyName.slice(1));
494
+ }
495
+ else {
496
+ // Get the value from current level
497
+ value = (0, lodash_1.get)(nodeValues, propertyName);
498
+ }
499
+ values.length = 0;
500
+ if (!Array.isArray(value)) {
501
+ values.push(value);
502
+ }
503
+ else {
504
+ values.push.apply(values, value);
505
+ }
506
+ if (values.some((v) => typeof v === 'string' && v.charAt(0) === '=')) {
507
+ return true;
508
+ }
509
+ if (values.length === 0 ||
510
+ !parameter.displayOptions.show[propertyName].some((v) => values.includes(v))) {
511
+ return false;
512
+ }
513
+ }
514
+ }
515
+ if (parameter.displayOptions.hide) {
516
+ // Any of the defined hide rules have to match to hide the parameter
517
+ for (const propertyName of Object.keys(parameter.displayOptions.hide)) {
518
+ if (propertyName.charAt(0) === '/') {
519
+ // Get the value from the root of the node
520
+ value = (0, lodash_1.get)(nodeValuesRoot, propertyName.slice(1));
521
+ }
522
+ else {
523
+ // Get the value from current level
524
+ value = (0, lodash_1.get)(nodeValues, propertyName);
525
+ }
526
+ values.length = 0;
527
+ if (!Array.isArray(value)) {
528
+ values.push(value);
529
+ }
530
+ else {
531
+ values.push.apply(values, value);
532
+ }
533
+ if (values.length !== 0 &&
534
+ parameter.displayOptions.hide[propertyName].some((v) => values.includes(v))) {
535
+ return false;
536
+ }
537
+ }
538
+ }
539
+ return true;
540
+ }
541
+ /**
542
+ * Returns if the given parameter should be displayed or not considering the path
543
+ * to the properties
544
+ *
545
+ * @export
546
+ * @param {INodeParameters} nodeValues The data on the node which decides if the parameter
547
+ * should be displayed
548
+ * @param {(INodeProperties | INodeCredentialDescription)} parameter The parameter to check if it should be displayed
549
+ * @param {string} path The path to the property
550
+ * @returns
551
+ */
552
+ function displayParameterPath(nodeValues, parameter, path) {
553
+ let resolvedNodeValues = nodeValues;
554
+ if (path !== '') {
555
+ resolvedNodeValues = (0, lodash_1.get)(nodeValues, path);
556
+ }
557
+ // Get the root parameter data
558
+ let nodeValuesRoot = nodeValues;
559
+ if (path && path.split('.').indexOf('parameters') === 0) {
560
+ nodeValuesRoot = (0, lodash_1.get)(nodeValues, 'parameters');
561
+ }
562
+ return displayParameter(resolvedNodeValues, parameter, nodeValuesRoot);
563
+ }
564
+ /**
565
+ * Returns the context data
566
+ *
567
+ * @export
568
+ * @param {IRunExecutionData} runExecutionData The run execution data
569
+ * @param {string} type The data type. "node"/"flow"
570
+ * @param {INode} [node] If type "node" is set the node to return the context of has to be supplied
571
+ * @returns {IContextObject}
572
+ */
573
+ function getContext(runExecutionData, type, node) {
574
+ if (runExecutionData.executionData === undefined) {
575
+ // TODO: Should not happen leave it for test now
576
+ throw new Error('The "executionData" is not initialized!');
577
+ }
578
+ let key;
579
+ if (type === 'flow') {
580
+ key = 'flow';
581
+ }
582
+ else if (type === 'node') {
583
+ if (node === undefined) {
584
+ throw new Error(`The request data of context type "node" the node parameter has to be set!`);
585
+ }
586
+ key = `node:${node.name}`;
587
+ }
588
+ else {
589
+ throw new Error(`The context type "${type}" is not know. Only "flow" and node" are supported!`);
590
+ }
591
+ if (runExecutionData.executionData.contextData[key] === undefined) {
592
+ // eslint-disable-next-line no-param-reassign
593
+ runExecutionData.executionData.contextData[key] = {};
594
+ }
595
+ return runExecutionData.executionData.contextData[key];
596
+ }
597
+ /**
598
+ * Returns which parameters are dependent on which
599
+ *
600
+ * @export
601
+ * @param {INodeProperties[]} nodePropertiesArray
602
+ * @returns {IParameterDependencies}
603
+ */
604
+ function getParamterDependencies(nodePropertiesArray) {
605
+ const dependencies = {};
606
+ let displayRule;
607
+ let parameterName;
608
+ for (const nodeProperties of nodePropertiesArray) {
609
+ if (dependencies[nodeProperties.name] === undefined) {
610
+ dependencies[nodeProperties.name] = [];
611
+ }
612
+ if (nodeProperties.displayOptions === undefined) {
613
+ // Does not have any dependencies
614
+ continue;
615
+ }
616
+ for (displayRule of Object.keys(nodeProperties.displayOptions)) {
617
+ // @ts-ignore
618
+ for (parameterName of Object.keys(nodeProperties.displayOptions[displayRule])) {
619
+ if (!dependencies[nodeProperties.name].includes(parameterName)) {
620
+ dependencies[nodeProperties.name].push(parameterName);
621
+ }
622
+ }
623
+ }
624
+ }
625
+ return dependencies;
626
+ }
627
+ /**
628
+ * Returns in which order the parameters should be resolved
629
+ * to have the parameters available they depend on
630
+ *
631
+ * @export
632
+ * @param {INodeProperties[]} nodePropertiesArray
633
+ * @param {IParameterDependencies} parameterDependencies
634
+ * @returns {number[]}
635
+ */
636
+ function getParamterResolveOrder(nodePropertiesArray, parameterDependencies) {
637
+ const executionOrder = [];
638
+ const indexToResolve = Array.from({ length: nodePropertiesArray.length }, (v, k) => k);
639
+ const resolvedParamters = [];
640
+ let index;
641
+ let property;
642
+ let lastIndexLength = indexToResolve.length;
643
+ let lastIndexReduction = -1;
644
+ let iterations = 0;
645
+ while (indexToResolve.length !== 0) {
646
+ iterations += 1;
647
+ index = indexToResolve.shift();
648
+ property = nodePropertiesArray[index];
649
+ if (parameterDependencies[property.name].length === 0) {
650
+ // Does not have any dependencies so simply add
651
+ executionOrder.push(index);
652
+ resolvedParamters.push(property.name);
653
+ continue;
654
+ }
655
+ // Parameter has dependencies
656
+ for (const dependency of parameterDependencies[property.name]) {
657
+ if (!resolvedParamters.includes(dependency)) {
658
+ if (dependency.charAt(0) === '/') {
659
+ // Assume that root level depenencies are resolved
660
+ continue;
661
+ }
662
+ // Dependencies for that paramter are still missing so
663
+ // try to add again later
664
+ indexToResolve.push(index);
665
+ continue;
666
+ }
667
+ }
668
+ // All dependencies got found so add
669
+ executionOrder.push(index);
670
+ resolvedParamters.push(property.name);
671
+ if (indexToResolve.length < lastIndexLength) {
672
+ lastIndexReduction = iterations;
673
+ }
674
+ if (iterations > lastIndexReduction + nodePropertiesArray.length) {
675
+ throw new Error('Could not resolve parameter depenencies. Max iterations reached! Hint: If `displayOptions` are specified in any child parameter of a parent `collection` or `fixedCollection`, remove the `displayOptions` from the child parameter.');
676
+ }
677
+ lastIndexLength = indexToResolve.length;
678
+ }
679
+ return executionOrder;
680
+ }
681
+ /**
682
+ * Returns the node parameter values. Depending on the settings it either just returns the none
683
+ * default values or it applies all the default values.
684
+ *
685
+ * @export
686
+ * @param {INodeProperties[]} nodePropertiesArray The properties which exist and their settings
687
+ * @param {INodeParameters} nodeValues The node parameter data
688
+ * @param {boolean} returnDefaults If default values get added or only none default values returned
689
+ * @param {boolean} returnNoneDisplayed If also values which should not be displayed should be returned
690
+ * @param {boolean} [onlySimpleTypes=false] If only simple types should be resolved
691
+ * @param {boolean} [dataIsResolved=false] If nodeValues are already fully resolved (so that all default values got added already)
692
+ * @param {INodeParameters} [nodeValuesRoot] The root node-parameter-data
693
+ * @returns {(INodeParameters | null)}
694
+ */
695
+ function getNodeParameters(nodePropertiesArray, nodeValues, returnDefaults, returnNoneDisplayed, onlySimpleTypes = false, dataIsResolved = false, nodeValuesRoot, parentType, parameterDependencies) {
696
+ if (parameterDependencies === undefined) {
697
+ parameterDependencies = getParamterDependencies(nodePropertiesArray);
698
+ }
699
+ // Get the parameter names which get used multiple times as for this
700
+ // ones we have to always check which ones get displayed and which ones not
701
+ const duplicateParameterNames = [];
702
+ const parameterNames = [];
703
+ for (const nodeProperties of nodePropertiesArray) {
704
+ if (parameterNames.includes(nodeProperties.name)) {
705
+ if (!duplicateParameterNames.includes(nodeProperties.name)) {
706
+ duplicateParameterNames.push(nodeProperties.name);
707
+ }
708
+ }
709
+ else {
710
+ parameterNames.push(nodeProperties.name);
711
+ }
712
+ }
713
+ const nodeParameters = {};
714
+ const nodeParametersFull = {};
715
+ let nodeValuesDisplayCheck = nodeParametersFull;
716
+ if (!dataIsResolved && !returnNoneDisplayed) {
717
+ nodeValuesDisplayCheck = getNodeParameters(nodePropertiesArray, nodeValues, true, true, true, true, nodeValuesRoot, parentType, parameterDependencies);
718
+ }
719
+ nodeValuesRoot = nodeValuesRoot || nodeValuesDisplayCheck;
720
+ // Go through the parameters in order of their dependencies
721
+ const parameterItterationOrderIndex = getParamterResolveOrder(nodePropertiesArray, parameterDependencies);
722
+ for (const parameterIndex of parameterItterationOrderIndex) {
723
+ const nodeProperties = nodePropertiesArray[parameterIndex];
724
+ if (nodeValues[nodeProperties.name] === undefined &&
725
+ (!returnDefaults || parentType === 'collection')) {
726
+ // The value is not defined so go to the next
727
+ continue;
728
+ }
729
+ if (!returnNoneDisplayed &&
730
+ !displayParameter(nodeValuesDisplayCheck, nodeProperties, nodeValuesRoot)) {
731
+ if (!returnNoneDisplayed || !returnDefaults) {
732
+ continue;
733
+ }
734
+ }
735
+ if (!['collection', 'fixedCollection'].includes(nodeProperties.type)) {
736
+ // Is a simple property so can be set as it is
737
+ if (duplicateParameterNames.includes(nodeProperties.name)) {
738
+ if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, nodeValuesRoot)) {
739
+ continue;
740
+ }
741
+ }
742
+ if (returnDefaults) {
743
+ // Set also when it has the default value
744
+ if (['boolean', 'number', 'options'].includes(nodeProperties.type)) {
745
+ // Boolean, numbers and options are special as false and 0 are valid values
746
+ // and should not be replaced with default value
747
+ nodeParameters[nodeProperties.name] =
748
+ nodeValues[nodeProperties.name] !== undefined
749
+ ? nodeValues[nodeProperties.name]
750
+ : nodeProperties.default;
751
+ }
752
+ else {
753
+ nodeParameters[nodeProperties.name] =
754
+ nodeValues[nodeProperties.name] || nodeProperties.default;
755
+ }
756
+ nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
757
+ }
758
+ else if ((nodeValues[nodeProperties.name] !== nodeProperties.default &&
759
+ typeof nodeValues[nodeProperties.name] !== 'object') ||
760
+ (typeof nodeValues[nodeProperties.name] === 'object' &&
761
+ !(0, lodash_1.isEqual)(nodeValues[nodeProperties.name], nodeProperties.default)) ||
762
+ (nodeValues[nodeProperties.name] !== undefined && parentType === 'collection')) {
763
+ // Set only if it is different to the default value
764
+ nodeParameters[nodeProperties.name] = nodeValues[nodeProperties.name];
765
+ nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
766
+ continue;
767
+ }
768
+ }
769
+ if (onlySimpleTypes) {
770
+ // It is only supposed to resolve the simple types. So continue.
771
+ continue;
772
+ }
773
+ // Is a complex property so check lower levels
774
+ let tempValue;
775
+ if (nodeProperties.type === 'collection') {
776
+ // Is collection
777
+ if (nodeProperties.typeOptions !== undefined &&
778
+ nodeProperties.typeOptions.multipleValues === true) {
779
+ // Multiple can be set so will be an array
780
+ // Return directly the values like they are
781
+ if (nodeValues[nodeProperties.name] !== undefined) {
782
+ nodeParameters[nodeProperties.name] = nodeValues[nodeProperties.name];
783
+ }
784
+ else if (returnDefaults) {
785
+ // Does not have values defined but defaults should be returned
786
+ if (Array.isArray(nodeProperties.default)) {
787
+ nodeParameters[nodeProperties.name] = JSON.parse(JSON.stringify(nodeProperties.default));
788
+ }
789
+ else {
790
+ // As it is probably wrong for many nodes, do we keep on returning an empty array if
791
+ // anything else than an array is set as default
792
+ nodeParameters[nodeProperties.name] = [];
793
+ }
794
+ }
795
+ nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
796
+ }
797
+ else if (nodeValues[nodeProperties.name] !== undefined) {
798
+ // Has values defined so get them
799
+ const tempNodeParameters = getNodeParameters(nodeProperties.options, nodeValues[nodeProperties.name], returnDefaults, returnNoneDisplayed, false, false, nodeValuesRoot, nodeProperties.type);
800
+ if (tempNodeParameters !== null) {
801
+ nodeParameters[nodeProperties.name] = tempNodeParameters;
802
+ nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
803
+ }
804
+ }
805
+ else if (returnDefaults) {
806
+ // Does not have values defined but defaults should be returned
807
+ nodeParameters[nodeProperties.name] = JSON.parse(JSON.stringify(nodeProperties.default));
808
+ nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
809
+ }
810
+ }
811
+ else if (nodeProperties.type === 'fixedCollection') {
812
+ // Is fixedCollection
813
+ const collectionValues = {};
814
+ let tempNodeParameters;
815
+ let tempNodePropertiesArray;
816
+ let nodePropertyOptions;
817
+ let propertyValues = nodeValues[nodeProperties.name];
818
+ if (returnDefaults) {
819
+ if (propertyValues === undefined) {
820
+ propertyValues = JSON.parse(JSON.stringify(nodeProperties.default));
821
+ }
822
+ }
823
+ // Iterate over all collections
824
+ for (const itemName of Object.keys(propertyValues || {})) {
825
+ if (nodeProperties.typeOptions !== undefined &&
826
+ nodeProperties.typeOptions.multipleValues === true) {
827
+ // Multiple can be set so will be an array
828
+ const tempArrayValue = [];
829
+ // Iterate over all items as it contains multiple ones
830
+ for (const nodeValue of propertyValues[itemName]) {
831
+ nodePropertyOptions = nodeProperties.options.find(
832
+ // eslint-disable-next-line @typescript-eslint/no-shadow
833
+ (nodePropertyOptions) => nodePropertyOptions.name === itemName);
834
+ if (nodePropertyOptions === undefined) {
835
+ throw new Error(`Could not find property option "${itemName}" for "${nodeProperties.name}"`);
836
+ }
837
+ tempNodePropertiesArray = nodePropertyOptions.values;
838
+ tempValue = getNodeParameters(tempNodePropertiesArray, nodeValue, returnDefaults, returnNoneDisplayed, false, false, nodeValuesRoot, nodeProperties.type);
839
+ if (tempValue !== null) {
840
+ tempArrayValue.push(tempValue);
841
+ }
842
+ }
843
+ collectionValues[itemName] = tempArrayValue;
844
+ }
845
+ else {
846
+ // Only one can be set so is an object of objects
847
+ tempNodeParameters = {};
848
+ // Get the options of the current item
849
+ // eslint-disable-next-line @typescript-eslint/no-shadow
850
+ const nodePropertyOptions = nodeProperties.options.find((data) => data.name === itemName);
851
+ if (nodePropertyOptions !== undefined) {
852
+ tempNodePropertiesArray = nodePropertyOptions.values;
853
+ tempValue = getNodeParameters(tempNodePropertiesArray, nodeValues[nodeProperties.name][itemName], returnDefaults, returnNoneDisplayed, false, false, nodeValuesRoot, nodeProperties.type);
854
+ if (tempValue !== null) {
855
+ Object.assign(tempNodeParameters, tempValue);
856
+ }
857
+ }
858
+ if (Object.keys(tempNodeParameters).length !== 0) {
859
+ collectionValues[itemName] = tempNodeParameters;
860
+ }
861
+ }
862
+ }
863
+ if (Object.keys(collectionValues).length !== 0 || returnDefaults) {
864
+ // Set only if value got found
865
+ if (returnDefaults) {
866
+ // Set also when it has the default value
867
+ if (collectionValues === undefined) {
868
+ nodeParameters[nodeProperties.name] = JSON.parse(JSON.stringify(nodeProperties.default));
869
+ }
870
+ else {
871
+ nodeParameters[nodeProperties.name] = collectionValues;
872
+ }
873
+ nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
874
+ }
875
+ else if (collectionValues !== nodeProperties.default) {
876
+ // Set only if values got found and it is not the default
877
+ nodeParameters[nodeProperties.name] = collectionValues;
878
+ nodeParametersFull[nodeProperties.name] = nodeParameters[nodeProperties.name];
879
+ }
880
+ }
881
+ }
882
+ }
883
+ return nodeParameters;
884
+ }
885
+ /**
886
+ * Brings the output data in a format that can be returned from a node
887
+ *
888
+ * @export
889
+ * @param {INodeExecutionData[]} outputData
890
+ * @param {number} [outputIndex=0]
891
+ * @returns {Promise<INodeExecutionData[][]>}
892
+ */
893
+ async function prepareOutputData(outputData, outputIndex = 0) {
894
+ // TODO: Check if node has output with that index
895
+ const returnData = [];
896
+ for (let i = 0; i < outputIndex; i++) {
897
+ returnData.push([]);
898
+ }
899
+ returnData.push(outputData);
900
+ return returnData;
901
+ }
902
+ /**
903
+ * Returns all the webhooks which should be created for the give node
904
+ *
905
+ * @export
906
+ *
907
+ * @param {INode} node
908
+ * @returns {IWebhookData[]}
909
+ */
910
+ function getNodeWebhooks(workflow, node, additionalData, ignoreRestartWehbooks = false) {
911
+ if (node.disabled === true) {
912
+ // Node is disabled so webhooks will also not be enabled
913
+ return [];
914
+ }
915
+ const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
916
+ if (nodeType.description.webhooks === undefined) {
917
+ // Node does not have any webhooks so return
918
+ return [];
919
+ }
920
+ const workflowId = workflow.id || '__UNSAVED__';
921
+ const mode = 'internal';
922
+ const returnData = [];
923
+ for (const webhookDescription of nodeType.description.webhooks) {
924
+ if (ignoreRestartWehbooks && webhookDescription.restartWebhook === true) {
925
+ continue;
926
+ }
927
+ let nodeWebhookPath = workflow.expression.getSimpleParameterValue(node, webhookDescription.path, mode, {});
928
+ if (nodeWebhookPath === undefined) {
929
+ // TODO: Use a proper logger
930
+ console.error(`No webhook path could be found for node "${node.name}" in workflow "${workflowId}".`);
931
+ continue;
932
+ }
933
+ nodeWebhookPath = nodeWebhookPath.toString();
934
+ if (nodeWebhookPath.startsWith('/')) {
935
+ nodeWebhookPath = nodeWebhookPath.slice(1);
936
+ }
937
+ if (nodeWebhookPath.endsWith('/')) {
938
+ nodeWebhookPath = nodeWebhookPath.slice(0, -1);
939
+ }
940
+ const isFullPath = workflow.expression.getSimpleParameterValue(node, webhookDescription.isFullPath, 'internal', {}, false);
941
+ const restartWebhook = workflow.expression.getSimpleParameterValue(node, webhookDescription.restartWebhook, 'internal', {}, false);
942
+ const path = getNodeWebhookPath(workflowId, node, nodeWebhookPath, isFullPath, restartWebhook);
943
+ const httpMethod = workflow.expression.getSimpleParameterValue(node, webhookDescription.httpMethod, mode, {}, 'GET');
944
+ if (httpMethod === undefined) {
945
+ // TODO: Use a proper logger
946
+ console.error(`The webhook "${path}" for node "${node.name}" in workflow "${workflowId}" could not be added because the httpMethod is not defined.`);
947
+ continue;
948
+ }
949
+ let webhookId;
950
+ if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
951
+ webhookId = node.webhookId;
952
+ }
953
+ returnData.push({
954
+ httpMethod: httpMethod.toString(),
955
+ node: node.name,
956
+ path,
957
+ webhookDescription,
958
+ workflowId,
959
+ workflowExecuteAdditionalData: additionalData,
960
+ webhookId,
961
+ });
962
+ }
963
+ return returnData;
964
+ }
965
+ function getNodeWebhooksBasic(workflow, node) {
966
+ if (node.disabled === true) {
967
+ // Node is disabled so webhooks will also not be enabled
968
+ return [];
969
+ }
970
+ const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion);
971
+ if (nodeType.description.webhooks === undefined) {
972
+ // Node does not have any webhooks so return
973
+ return [];
974
+ }
975
+ const workflowId = workflow.id || '__UNSAVED__';
976
+ const mode = 'internal';
977
+ const returnData = [];
978
+ for (const webhookDescription of nodeType.description.webhooks) {
979
+ let nodeWebhookPath = workflow.expression.getSimpleParameterValue(node, webhookDescription.path, mode, {});
980
+ if (nodeWebhookPath === undefined) {
981
+ // TODO: Use a proper logger
982
+ console.error(`No webhook path could be found for node "${node.name}" in workflow "${workflowId}".`);
983
+ continue;
984
+ }
985
+ nodeWebhookPath = nodeWebhookPath.toString();
986
+ if (nodeWebhookPath.startsWith('/')) {
987
+ nodeWebhookPath = nodeWebhookPath.slice(1);
988
+ }
989
+ if (nodeWebhookPath.endsWith('/')) {
990
+ nodeWebhookPath = nodeWebhookPath.slice(0, -1);
991
+ }
992
+ const isFullPath = workflow.expression.getSimpleParameterValue(node, webhookDescription.isFullPath, mode, {}, false);
993
+ const path = getNodeWebhookPath(workflowId, node, nodeWebhookPath, isFullPath);
994
+ const httpMethod = workflow.expression.getSimpleParameterValue(node, webhookDescription.httpMethod, mode, {});
995
+ if (httpMethod === undefined) {
996
+ // TODO: Use a proper logger
997
+ console.error(`The webhook "${path}" for node "${node.name}" in workflow "${workflowId}" could not be added because the httpMethod is not defined.`);
998
+ continue;
999
+ }
1000
+ // @ts-ignore
1001
+ returnData.push({
1002
+ httpMethod: httpMethod.toString(),
1003
+ node: node.name,
1004
+ path,
1005
+ webhookDescription,
1006
+ workflowId,
1007
+ });
1008
+ }
1009
+ return returnData;
1010
+ }
1011
+ /**
1012
+ * Returns the webhook path
1013
+ *
1014
+ * @export
1015
+ * @param {string} workflowId
1016
+ * @param {string} nodeTypeName
1017
+ * @param {string} path
1018
+ * @returns {string}
1019
+ */
1020
+ function getNodeWebhookPath(workflowId, node, path, isFullPath, restartWebhook) {
1021
+ let webhookPath = '';
1022
+ if (restartWebhook === true) {
1023
+ return path;
1024
+ }
1025
+ if (node.webhookId === undefined) {
1026
+ webhookPath = `${workflowId}/${encodeURIComponent(node.name.toLowerCase())}/${path}`;
1027
+ }
1028
+ else {
1029
+ if (isFullPath === true) {
1030
+ return path;
1031
+ }
1032
+ webhookPath = `${node.webhookId}/${path}`;
1033
+ }
1034
+ return webhookPath;
1035
+ }
1036
+ /**
1037
+ * Returns the webhook URL
1038
+ *
1039
+ * @export
1040
+ * @param {string} baseUrl
1041
+ * @param {string} workflowId
1042
+ * @param {string} nodeTypeName
1043
+ * @param {string} path
1044
+ * @param {boolean} isFullPath
1045
+ * @returns {string}
1046
+ */
1047
+ function getNodeWebhookUrl(baseUrl, workflowId, node, path, isFullPath) {
1048
+ if ((path.startsWith(':') || path.includes('/:')) && node.webhookId) {
1049
+ // setting this to false to prefix the webhookId
1050
+ isFullPath = false;
1051
+ }
1052
+ if (path.startsWith('/')) {
1053
+ path = path.slice(1);
1054
+ }
1055
+ return `${baseUrl}/${getNodeWebhookPath(workflowId, node, path, isFullPath)}`;
1056
+ }
1057
+ /**
1058
+ * Returns all the parameter-issues of the node
1059
+ *
1060
+ * @export
1061
+ * @param {INodeProperties[]} nodePropertiesArray The properties of the node
1062
+ * @param {INode} node The data of the node
1063
+ * @returns {(INodeIssues | null)}
1064
+ */
1065
+ function getNodeParametersIssues(nodePropertiesArray, node) {
1066
+ const foundIssues = {};
1067
+ let propertyIssues;
1068
+ if (node.disabled === true) {
1069
+ // Ignore issues on disabled nodes
1070
+ return null;
1071
+ }
1072
+ for (const nodeProperty of nodePropertiesArray) {
1073
+ propertyIssues = getParameterIssues(nodeProperty, node.parameters, '');
1074
+ mergeIssues(foundIssues, propertyIssues);
1075
+ }
1076
+ if (Object.keys(foundIssues).length === 0) {
1077
+ return null;
1078
+ }
1079
+ return foundIssues;
1080
+ }
1081
+ /**
1082
+ * Returns the issues of the node as string
1083
+ *
1084
+ * @export
1085
+ * @param {INodeIssues} issues The issues of the node
1086
+ * @param {INode} node The node
1087
+ * @returns {string[]}
1088
+ */
1089
+ function nodeIssuesToString(issues, node) {
1090
+ const nodeIssues = [];
1091
+ if (issues.execution !== undefined) {
1092
+ nodeIssues.push(`Execution Error.`);
1093
+ }
1094
+ const objectProperties = ['parameters', 'credentials'];
1095
+ let issueText;
1096
+ let parameterName;
1097
+ for (const propertyName of objectProperties) {
1098
+ if (issues[propertyName] !== undefined) {
1099
+ for (parameterName of Object.keys(issues[propertyName])) {
1100
+ for (issueText of issues[propertyName][parameterName]) {
1101
+ nodeIssues.push(issueText);
1102
+ }
1103
+ }
1104
+ }
1105
+ }
1106
+ if (issues.typeUnknown !== undefined) {
1107
+ if (node !== undefined) {
1108
+ nodeIssues.push(`Node Type "${node.type}" is not known.`);
1109
+ }
1110
+ else {
1111
+ nodeIssues.push(`Node Type is not known.`);
1112
+ }
1113
+ }
1114
+ return nodeIssues;
1115
+ }
1116
+ /**
1117
+ * Adds an issue if the parameter is not defined
1118
+ *
1119
+ * @export
1120
+ * @param {INodeIssues} foundIssues The already found issues
1121
+ * @param {INodeProperties} nodeProperties The properties of the node
1122
+ * @param {NodeParameterValue} value The value of the parameter
1123
+ */
1124
+ function addToIssuesIfMissing(foundIssues, nodeProperties, value) {
1125
+ // TODO: Check what it really has when undefined
1126
+ if ((nodeProperties.type === 'string' && (value === '' || value === undefined)) ||
1127
+ (nodeProperties.type === 'multiOptions' && Array.isArray(value) && value.length === 0) ||
1128
+ (nodeProperties.type === 'dateTime' && value === undefined)) {
1129
+ // Parameter is requried but empty
1130
+ if (foundIssues.parameters === undefined) {
1131
+ foundIssues.parameters = {};
1132
+ }
1133
+ if (foundIssues.parameters[nodeProperties.name] === undefined) {
1134
+ foundIssues.parameters[nodeProperties.name] = [];
1135
+ }
1136
+ foundIssues.parameters[nodeProperties.name].push(`Parameter "${nodeProperties.displayName}" is required.`);
1137
+ }
1138
+ }
1139
+ /**
1140
+ * Returns the parameter value
1141
+ *
1142
+ * @export
1143
+ * @param {INodeParameters} nodeValues The values of the node
1144
+ * @param {string} parameterName The name of the parameter to return the value of
1145
+ * @param {string} path The path to the properties
1146
+ * @returns
1147
+ */
1148
+ function getParameterValueByPath(nodeValues, parameterName, path) {
1149
+ return (0, lodash_1.get)(nodeValues, path ? `${path}.${parameterName}` : parameterName);
1150
+ }
1151
+ /**
1152
+ * Returns all the issues with the given node-values
1153
+ *
1154
+ * @export
1155
+ * @param {INodeProperties} nodeProperties The properties of the node
1156
+ * @param {INodeParameters} nodeValues The values of the node
1157
+ * @param {string} path The path to the properties
1158
+ * @returns {INodeIssues}
1159
+ */
1160
+ function getParameterIssues(nodeProperties, nodeValues, path) {
1161
+ const foundIssues = {};
1162
+ let value;
1163
+ if (nodeProperties.required === true) {
1164
+ if (displayParameterPath(nodeValues, nodeProperties, path)) {
1165
+ value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
1166
+ if (
1167
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
1168
+ nodeProperties.typeOptions !== undefined &&
1169
+ nodeProperties.typeOptions.multipleValues !== undefined) {
1170
+ // Multiple can be set so will be an array
1171
+ if (Array.isArray(value)) {
1172
+ for (const singleValue of value) {
1173
+ addToIssuesIfMissing(foundIssues, nodeProperties, singleValue);
1174
+ }
1175
+ }
1176
+ }
1177
+ else {
1178
+ // Only one can be set so will be a single value
1179
+ addToIssuesIfMissing(foundIssues, nodeProperties, value);
1180
+ }
1181
+ }
1182
+ }
1183
+ // Check if there are any child parameters
1184
+ if (nodeProperties.options === undefined) {
1185
+ // There are none so nothing else to check
1186
+ return foundIssues;
1187
+ }
1188
+ // Check the child parameters
1189
+ // Important:
1190
+ // Checks the child properties only if the property is defined on current level.
1191
+ // That means that the required flag works only for the current level only. If
1192
+ // it is set on a lower level it means that the property is only required in case
1193
+ // the parent property got set.
1194
+ let basePath = path ? `${path}.` : '';
1195
+ const checkChildNodeProperties = [];
1196
+ // Collect all the properties to check
1197
+ if (nodeProperties.type === 'collection') {
1198
+ for (const option of nodeProperties.options) {
1199
+ checkChildNodeProperties.push({
1200
+ basePath,
1201
+ data: option,
1202
+ });
1203
+ }
1204
+ }
1205
+ else if (nodeProperties.type === 'fixedCollection') {
1206
+ basePath = basePath ? `${basePath}.` : `${nodeProperties.name}.`;
1207
+ let propertyOptions;
1208
+ for (propertyOptions of nodeProperties.options) {
1209
+ // Check if the option got set and if not skip it
1210
+ value = getParameterValueByPath(nodeValues, propertyOptions.name, basePath.slice(0, -1));
1211
+ if (value === undefined) {
1212
+ continue;
1213
+ }
1214
+ if (
1215
+ // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
1216
+ nodeProperties.typeOptions !== undefined &&
1217
+ nodeProperties.typeOptions.multipleValues !== undefined) {
1218
+ // Multiple can be set so will be an array of objects
1219
+ if (Array.isArray(value)) {
1220
+ for (let i = 0; i < value.length; i++) {
1221
+ for (const option of propertyOptions.values) {
1222
+ checkChildNodeProperties.push({
1223
+ basePath: `${basePath}${propertyOptions.name}[${i}]`,
1224
+ data: option,
1225
+ });
1226
+ }
1227
+ }
1228
+ }
1229
+ }
1230
+ else {
1231
+ // Only one can be set so will be an object
1232
+ for (const option of propertyOptions.values) {
1233
+ checkChildNodeProperties.push({
1234
+ basePath: basePath + propertyOptions.name,
1235
+ data: option,
1236
+ });
1237
+ }
1238
+ }
1239
+ }
1240
+ }
1241
+ else {
1242
+ // For all other types there is nothing to check so return
1243
+ return foundIssues;
1244
+ }
1245
+ let propertyIssues;
1246
+ for (const optionData of checkChildNodeProperties) {
1247
+ propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath);
1248
+ mergeIssues(foundIssues, propertyIssues);
1249
+ }
1250
+ return foundIssues;
1251
+ }
1252
+ /**
1253
+ * Merges multiple NodeIssues together
1254
+ *
1255
+ * @export
1256
+ * @param {INodeIssues} destination The issues to merge into
1257
+ * @param {(INodeIssues | null)} source The issues to merge
1258
+ * @returns
1259
+ */
1260
+ function mergeIssues(destination, source) {
1261
+ if (source === null) {
1262
+ // Nothing to merge
1263
+ return;
1264
+ }
1265
+ if (source.execution === true) {
1266
+ destination.execution = true;
1267
+ }
1268
+ const objectProperties = ['parameters', 'credentials'];
1269
+ let destinationProperty;
1270
+ for (const propertyName of objectProperties) {
1271
+ if (source[propertyName] !== undefined) {
1272
+ if (destination[propertyName] === undefined) {
1273
+ destination[propertyName] = {};
1274
+ }
1275
+ let parameterName;
1276
+ for (parameterName of Object.keys(source[propertyName])) {
1277
+ destinationProperty = destination[propertyName];
1278
+ if (destinationProperty[parameterName] === undefined) {
1279
+ destinationProperty[parameterName] = [];
1280
+ }
1281
+ destinationProperty[parameterName].push.apply(destinationProperty[parameterName], source[propertyName][parameterName]);
1282
+ }
1283
+ }
1284
+ }
1285
+ if (source.typeUnknown === true) {
1286
+ destination.typeUnknown = true;
1287
+ }
1288
+ }
1289
+ /**
1290
+ * Merges the given node properties
1291
+ *
1292
+ * @export
1293
+ * @param {INodeProperties[]} mainProperties
1294
+ * @param {INodeProperties[]} addProperties
1295
+ */
1296
+ function mergeNodeProperties(mainProperties, addProperties) {
1297
+ let existingIndex;
1298
+ for (const property of addProperties) {
1299
+ existingIndex = mainProperties.findIndex((element) => element.name === property.name);
1300
+ if (existingIndex === -1) {
1301
+ // Property does not exist yet, so add
1302
+ mainProperties.push(property);
1303
+ }
1304
+ else {
1305
+ // Property exists already, so overwrite
1306
+ mainProperties[existingIndex] = property;
1307
+ }
1308
+ }
1309
+ }
1310
+ function getVersionedNodeType(object, version) {
1311
+ if (isNodeTypeVersioned(object)) {
1312
+ return object.getNodeType(version);
1313
+ }
1314
+ return object;
1315
+ }
1316
+ function getVersionedNodeTypeAll(object) {
1317
+ if (isNodeTypeVersioned(object)) {
1318
+ return Object.values(object.nodeVersions).map((element) => {
1319
+ element.description.name = object.description.name;
1320
+ return element;
1321
+ });
1322
+ }
1323
+ return [object];
1324
+ }
1325
+ function isNodeTypeVersioned(object) {
1326
+ return !!('getNodeType' in object);
1327
+ }
1328
+ /**
1329
+ * Returns the parameter value from the node parameters
1330
+ *
1331
+ * @export
1332
+ * @param {INodeParameters} nodeParameters The node parameters
1333
+ * @param {string} parameterName The name of the parameter to get
1334
+ * @param {number} [index=0] The index of the parameter value if it's an array
1335
+ * @returns {NodeParameterValue | undefined} The parameter value
1336
+ */
1337
+ function getParameterValue(nodeParameters, parameterName, index = 0) {
1338
+ const value = nodeParameters[parameterName];
1339
+ if (value === undefined) {
1340
+ return undefined;
1341
+ }
1342
+ if (Array.isArray(value)) {
1343
+ const arrayValue = value[index];
1344
+ return typeof arrayValue === 'object' ? undefined : arrayValue;
1345
+ }
1346
+ return typeof value === 'object' ? undefined : value;
1347
+ }
1348
+ //# sourceMappingURL=NodeHelpers.js.map