@fsai-flow/workflow 0.0.2 → 0.1.0

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