@fsai-flow/core 0.0.1

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 (113) hide show
  1. package/README.md +11 -0
  2. package/dist/README.md +11 -0
  3. package/dist/package.json +44 -0
  4. package/dist/src/index.d.ts +15 -0
  5. package/dist/src/index.js +29 -0
  6. package/dist/src/index.js.map +1 -0
  7. package/dist/src/lib/ActiveWebhooks.d.ts +59 -0
  8. package/dist/src/lib/ActiveWebhooks.js +184 -0
  9. package/dist/src/lib/ActiveWebhooks.js.map +1 -0
  10. package/dist/src/lib/ActiveWorkflows.d.ts +58 -0
  11. package/dist/src/lib/ActiveWorkflows.js +244 -0
  12. package/dist/src/lib/ActiveWorkflows.js.map +1 -0
  13. package/dist/src/lib/BinaryDataManager/FileSystem.d.ts +26 -0
  14. package/dist/src/lib/BinaryDataManager/FileSystem.js +179 -0
  15. package/dist/src/lib/BinaryDataManager/FileSystem.js.map +1 -0
  16. package/dist/src/lib/BinaryDataManager/index.d.ts +21 -0
  17. package/dist/src/lib/BinaryDataManager/index.js +146 -0
  18. package/dist/src/lib/BinaryDataManager/index.js.map +1 -0
  19. package/dist/src/lib/ChangeCase.d.ts +9 -0
  20. package/dist/src/lib/ChangeCase.js +43 -0
  21. package/dist/src/lib/ChangeCase.js.map +1 -0
  22. package/dist/src/lib/Constants.d.ts +14 -0
  23. package/dist/src/lib/Constants.js +19 -0
  24. package/dist/src/lib/Constants.js.map +1 -0
  25. package/dist/src/lib/Credentials.d.ts +27 -0
  26. package/dist/src/lib/Credentials.js +89 -0
  27. package/dist/src/lib/Credentials.js.map +1 -0
  28. package/dist/src/lib/FileSystem.d.ts +26 -0
  29. package/dist/src/lib/FileSystem.js +179 -0
  30. package/dist/src/lib/FileSystem.js.map +1 -0
  31. package/dist/src/lib/InputConnectionDataLegacy.d.ts +2 -0
  32. package/dist/src/lib/InputConnectionDataLegacy.js +79 -0
  33. package/dist/src/lib/InputConnectionDataLegacy.js.map +1 -0
  34. package/dist/src/lib/Interfaces.d.ts +148 -0
  35. package/dist/src/lib/Interfaces.js +3 -0
  36. package/dist/src/lib/Interfaces.js.map +1 -0
  37. package/dist/src/lib/LoadNodeParameterOptions.d.ts +39 -0
  38. package/dist/src/lib/LoadNodeParameterOptions.js +150 -0
  39. package/dist/src/lib/LoadNodeParameterOptions.js.map +1 -0
  40. package/dist/src/lib/NodeExecuteFunctions.d.ts +226 -0
  41. package/dist/src/lib/NodeExecuteFunctions.js +2483 -0
  42. package/dist/src/lib/NodeExecuteFunctions.js.map +1 -0
  43. package/dist/src/lib/NodesLoader/constants.d.ts +5 -0
  44. package/dist/src/lib/NodesLoader/constants.js +106 -0
  45. package/dist/src/lib/NodesLoader/constants.js.map +1 -0
  46. package/dist/src/lib/NodesLoader/custom-directory-loader.d.ts +9 -0
  47. package/dist/src/lib/NodesLoader/custom-directory-loader.js +36 -0
  48. package/dist/src/lib/NodesLoader/custom-directory-loader.js.map +1 -0
  49. package/dist/src/lib/NodesLoader/directory-loader.d.ts +66 -0
  50. package/dist/src/lib/NodesLoader/directory-loader.js +325 -0
  51. package/dist/src/lib/NodesLoader/directory-loader.js.map +1 -0
  52. package/dist/src/lib/NodesLoader/index.d.ts +5 -0
  53. package/dist/src/lib/NodesLoader/index.js +12 -0
  54. package/dist/src/lib/NodesLoader/index.js.map +1 -0
  55. package/dist/src/lib/NodesLoader/lazy-package-directory-loader.d.ts +7 -0
  56. package/dist/src/lib/NodesLoader/lazy-package-directory-loader.js +52 -0
  57. package/dist/src/lib/NodesLoader/lazy-package-directory-loader.js.map +1 -0
  58. package/dist/src/lib/NodesLoader/load-class-in-isolation.d.ts +1 -0
  59. package/dist/src/lib/NodesLoader/load-class-in-isolation.js +22 -0
  60. package/dist/src/lib/NodesLoader/load-class-in-isolation.js.map +1 -0
  61. package/dist/src/lib/NodesLoader/package-directory-loader.d.ts +17 -0
  62. package/dist/src/lib/NodesLoader/package-directory-loader.js +100 -0
  63. package/dist/src/lib/NodesLoader/package-directory-loader.js.map +1 -0
  64. package/dist/src/lib/NodesLoader/types.d.ts +14 -0
  65. package/dist/src/lib/NodesLoader/types.js +3 -0
  66. package/dist/src/lib/NodesLoader/types.js.map +1 -0
  67. package/dist/src/lib/UserSettings.d.ts +80 -0
  68. package/dist/src/lib/UserSettings.js +261 -0
  69. package/dist/src/lib/UserSettings.js.map +1 -0
  70. package/dist/src/lib/WorkflowExecute.d.ts +53 -0
  71. package/dist/src/lib/WorkflowExecute.js +835 -0
  72. package/dist/src/lib/WorkflowExecute.js.map +1 -0
  73. package/dist/src/lib/index.d.ts +21 -0
  74. package/dist/src/lib/index.js +146 -0
  75. package/dist/src/lib/index.js.map +1 -0
  76. package/dist/src/utils/crypto.d.ts +1 -0
  77. package/dist/src/utils/crypto.js +8 -0
  78. package/dist/src/utils/crypto.js.map +1 -0
  79. package/eslint.config.js +19 -0
  80. package/jest.config.ts +10 -0
  81. package/package.json +44 -0
  82. package/project.json +19 -0
  83. package/src/index.ts +27 -0
  84. package/src/lib/ActiveWebhooks.ts +245 -0
  85. package/src/lib/ActiveWorkflows.ts +304 -0
  86. package/src/lib/BinaryDataManager/FileSystem.ts +214 -0
  87. package/src/lib/BinaryDataManager/index.ts +187 -0
  88. package/src/lib/ChangeCase.ts +45 -0
  89. package/src/lib/Constants.ts +16 -0
  90. package/src/lib/Credentials.ts +108 -0
  91. package/src/lib/FileSystem.ts +214 -0
  92. package/src/lib/InputConnectionDataLegacy.ts +123 -0
  93. package/src/lib/Interfaces.ts +338 -0
  94. package/src/lib/LoadNodeParameterOptions.ts +235 -0
  95. package/src/lib/NodeExecuteFunctions.ts +3704 -0
  96. package/src/lib/NodesLoader/constants.ts +112 -0
  97. package/src/lib/NodesLoader/custom-directory-loader.ts +31 -0
  98. package/src/lib/NodesLoader/directory-loader.ts +458 -0
  99. package/src/lib/NodesLoader/index.ts +5 -0
  100. package/src/lib/NodesLoader/lazy-package-directory-loader.ts +55 -0
  101. package/src/lib/NodesLoader/load-class-in-isolation.ts +19 -0
  102. package/src/lib/NodesLoader/package-directory-loader.ts +107 -0
  103. package/src/lib/NodesLoader/types.ts +14 -0
  104. package/src/lib/UserSettings.ts +292 -0
  105. package/src/lib/WorkflowExecute.ts +1108 -0
  106. package/src/lib/index.ts +187 -0
  107. package/src/utils/crypto.ts +5 -0
  108. package/tests/Credentials.test.ts +88 -0
  109. package/tests/Helpers.ts +808 -0
  110. package/tests/WorkflowExecute.test.ts +1242 -0
  111. package/tsconfig.json +42 -0
  112. package/tsconfig.lib.json +10 -0
  113. package/tsconfig.spec.json +14 -0
@@ -0,0 +1,808 @@
1
+ /* eslint-disable @typescript-eslint/no-empty-function */
2
+ import { set } from 'lodash';
3
+
4
+ import {
5
+ ICredentialDataDecryptedObject,
6
+ ICredentialsHelper,
7
+ IDataObject,
8
+ IDeferredPromise,
9
+ IExecuteWorkflowInfo,
10
+ IHttpRequestOptions,
11
+ INodeCredentialsDetails,
12
+ INodeExecutionData,
13
+ INodeParameters,
14
+ INodeType,
15
+ INodeTypeData,
16
+ INodeTypes,
17
+ IRun,
18
+ ITaskData,
19
+ IWorkflowBase,
20
+ IWorkflowExecuteAdditionalData,
21
+ NodeConnectionTypes,
22
+ NodeHelpers,
23
+ NodeParameterValue,
24
+ WorkflowHooks,
25
+ } from '@fsai-flow/workflow';
26
+
27
+ import { Credentials, IExecuteFunctions } from '../src';
28
+
29
+ export class CredentialsHelper extends ICredentialsHelper {
30
+ async authenticate(
31
+ credentials: ICredentialDataDecryptedObject,
32
+ typeName: string,
33
+ requestParams: IHttpRequestOptions,
34
+ ): Promise<IHttpRequestOptions> {
35
+ return requestParams;
36
+ }
37
+
38
+ getParentTypes(name: string): string[] {
39
+ return [];
40
+ }
41
+
42
+ async getDecrypted(
43
+ nodeCredentials: INodeCredentialsDetails,
44
+ type: string,
45
+ ): Promise<ICredentialDataDecryptedObject> {
46
+ return {};
47
+ }
48
+
49
+ async getCredentials(
50
+ nodeCredentials: INodeCredentialsDetails,
51
+ type: string,
52
+ ): Promise<Credentials> {
53
+ return new Credentials({ id: null, name: '' }, '', [], '');
54
+ }
55
+
56
+ async updateCredentials(
57
+ nodeCredentials: INodeCredentialsDetails,
58
+ type: string,
59
+ data: ICredentialDataDecryptedObject,
60
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
61
+ ): Promise<void> {}
62
+ }
63
+
64
+ class NodeTypesClass implements INodeTypes {
65
+ nodeTypes: INodeTypeData = {
66
+ 'n8n-nodes-base.if': {
67
+ sourcePath: '',
68
+ type: {
69
+ description: {
70
+ displayName: 'If',
71
+ name: 'if',
72
+ group: ['transform'],
73
+ version: 1,
74
+ description: 'Splits a stream depending on defined compare operations.',
75
+ defaults: {
76
+ name: 'IF',
77
+ color: '#408000',
78
+ },
79
+ inputs: [NodeConnectionTypes.Main],
80
+ outputs: [NodeConnectionTypes.Main, NodeConnectionTypes.Main],
81
+ properties: [
82
+ {
83
+ displayName: 'Conditions',
84
+ name: 'conditions',
85
+ placeholder: 'Add Condition',
86
+ type: 'fixedCollection',
87
+ typeOptions: {
88
+ multipleValues: true,
89
+ },
90
+ description: 'The type of values to compare.',
91
+ default: {},
92
+ options: [
93
+ {
94
+ name: 'boolean',
95
+ displayName: 'Boolean',
96
+ values: [
97
+ {
98
+ displayName: 'Value 1',
99
+ name: 'value1',
100
+ type: 'boolean',
101
+ default: false,
102
+ description: 'The value to compare with the second one.',
103
+ },
104
+ {
105
+ displayName: 'Operation',
106
+ name: 'operation',
107
+ type: 'options',
108
+ options: [
109
+ {
110
+ name: 'Equal',
111
+ value: 'equal',
112
+ },
113
+ {
114
+ name: 'Not Equal',
115
+ value: 'notEqual',
116
+ },
117
+ ],
118
+ default: 'equal',
119
+ description: 'Operation to decide where the the data should be mapped to.',
120
+ },
121
+ {
122
+ displayName: 'Value 2',
123
+ name: 'value2',
124
+ type: 'boolean',
125
+ default: false,
126
+ description: 'The value to compare with the first one.',
127
+ },
128
+ ],
129
+ },
130
+ {
131
+ name: 'number',
132
+ displayName: 'Number',
133
+ values: [
134
+ {
135
+ displayName: 'Value 1',
136
+ name: 'value1',
137
+ type: 'number',
138
+ default: 0,
139
+ description: 'The value to compare with the second one.',
140
+ },
141
+ {
142
+ displayName: 'Operation',
143
+ name: 'operation',
144
+ type: 'options',
145
+ options: [
146
+ {
147
+ name: 'Smaller',
148
+ value: 'smaller',
149
+ },
150
+ {
151
+ name: 'Smaller Equal',
152
+ value: 'smallerEqual',
153
+ },
154
+ {
155
+ name: 'Equal',
156
+ value: 'equal',
157
+ },
158
+ {
159
+ name: 'Not Equal',
160
+ value: 'notEqual',
161
+ },
162
+ {
163
+ name: 'Larger',
164
+ value: 'larger',
165
+ },
166
+ {
167
+ name: 'Larger Equal',
168
+ value: 'largerEqual',
169
+ },
170
+ {
171
+ name: 'Is Empty',
172
+ value: 'isEmpty',
173
+ },
174
+ ],
175
+ default: 'smaller',
176
+ description: 'Operation to decide where the the data should be mapped to.',
177
+ },
178
+ {
179
+ displayName: 'Value 2',
180
+ name: 'value2',
181
+ type: 'number',
182
+ displayOptions: {
183
+ hide: {
184
+ operation: ['isEmpty'],
185
+ },
186
+ },
187
+ default: 0,
188
+ description: 'The value to compare with the first one.',
189
+ },
190
+ ],
191
+ },
192
+ {
193
+ name: 'string',
194
+ displayName: 'String',
195
+ values: [
196
+ {
197
+ displayName: 'Value 1',
198
+ name: 'value1',
199
+ type: 'string',
200
+ default: '',
201
+ description: 'The value to compare with the second one.',
202
+ },
203
+ {
204
+ displayName: 'Operation',
205
+ name: 'operation',
206
+ type: 'options',
207
+ options: [
208
+ {
209
+ name: 'Contains',
210
+ value: 'contains',
211
+ },
212
+ {
213
+ name: 'Ends With',
214
+ value: 'endsWith',
215
+ },
216
+ {
217
+ name: 'Equal',
218
+ value: 'equal',
219
+ },
220
+ {
221
+ name: 'Not Contains',
222
+ value: 'notContains',
223
+ },
224
+ {
225
+ name: 'Not Equal',
226
+ value: 'notEqual',
227
+ },
228
+ {
229
+ name: 'Regex',
230
+ value: 'regex',
231
+ },
232
+ {
233
+ name: 'Starts With',
234
+ value: 'startsWith',
235
+ },
236
+ {
237
+ name: 'Is Empty',
238
+ value: 'isEmpty',
239
+ },
240
+ ],
241
+ default: 'equal',
242
+ description: 'Operation to decide where the the data should be mapped to.',
243
+ },
244
+ {
245
+ displayName: 'Value 2',
246
+ name: 'value2',
247
+ type: 'string',
248
+ displayOptions: {
249
+ hide: {
250
+ operation: ['isEmpty', 'regex'],
251
+ },
252
+ },
253
+ default: '',
254
+ description: 'The value to compare with the first one.',
255
+ },
256
+ {
257
+ displayName: 'Regex',
258
+ name: 'value2',
259
+ type: 'string',
260
+ displayOptions: {
261
+ show: {
262
+ operation: ['regex'],
263
+ },
264
+ },
265
+ default: '',
266
+ placeholder: '/text/i',
267
+ description: 'The regex which has to match.',
268
+ },
269
+ ],
270
+ },
271
+ ],
272
+ },
273
+ {
274
+ displayName: 'Combine',
275
+ name: 'combineOperation',
276
+ type: 'options',
277
+ options: [
278
+ {
279
+ name: 'ALL',
280
+ description: 'Only if all conditions are meet it goes into "true" branch.',
281
+ value: 'all',
282
+ },
283
+ {
284
+ name: 'ANY',
285
+ description: 'If any of the conditions is meet it goes into "true" branch.',
286
+ value: 'any',
287
+ },
288
+ ],
289
+ default: 'all',
290
+ description:
291
+ 'If multiple rules got set this settings decides if it is true as soon as ANY condition matches or only if ALL get meet.',
292
+ },
293
+ ],
294
+ },
295
+ async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
296
+ const returnDataTrue: INodeExecutionData[] = [];
297
+ const returnDataFalse: INodeExecutionData[] = [];
298
+
299
+ const items = this.getInputData();
300
+
301
+ let item: INodeExecutionData;
302
+ let combineOperation: string;
303
+
304
+ // The compare operations
305
+ const compareOperationFunctions: {
306
+ [key: string]: (value1: NodeParameterValue, value2: NodeParameterValue) => boolean;
307
+ } = {
308
+ contains: (value1: NodeParameterValue, value2: NodeParameterValue) =>
309
+ (value1 || '').toString().includes((value2 || '').toString()),
310
+ notContains: (value1: NodeParameterValue, value2: NodeParameterValue) =>
311
+ !(value1 || '').toString().includes((value2 || '').toString()),
312
+ endsWith: (value1: NodeParameterValue, value2: NodeParameterValue) =>
313
+ (value1 as string).endsWith(value2 as string),
314
+ equal: (value1: NodeParameterValue, value2: NodeParameterValue) => value1 === value2,
315
+ notEqual: (value1: NodeParameterValue, value2: NodeParameterValue) => value1 !== value2,
316
+ larger: (value1: NodeParameterValue, value2: NodeParameterValue) =>
317
+ (value1 || 0) > (value2 || 0),
318
+ largerEqual: (value1: NodeParameterValue, value2: NodeParameterValue) =>
319
+ (value1 || 0) >= (value2 || 0),
320
+ smaller: (value1: NodeParameterValue, value2: NodeParameterValue) =>
321
+ (value1 || 0) < (value2 || 0),
322
+ smallerEqual: (value1: NodeParameterValue, value2: NodeParameterValue) =>
323
+ (value1 || 0) <= (value2 || 0),
324
+ startsWith: (value1: NodeParameterValue, value2: NodeParameterValue) =>
325
+ (value1 as string).startsWith(value2 as string),
326
+ isEmpty: (value1: NodeParameterValue) =>
327
+ [undefined, null, ''].includes(value1 as string),
328
+ regex: (value1: NodeParameterValue, value2: NodeParameterValue) => {
329
+ const regexMatch = (value2 || '')
330
+ .toString()
331
+ .match(new RegExp('^/(.*?)/([gimusy]*)$'));
332
+
333
+ let regex: RegExp;
334
+ if (!regexMatch) {
335
+ regex = new RegExp((value2 || '').toString());
336
+ } else if (regexMatch.length === 1) {
337
+ regex = new RegExp(regexMatch[1]);
338
+ } else {
339
+ regex = new RegExp(regexMatch[1], regexMatch[2]);
340
+ }
341
+
342
+ return !!(value1 || '').toString().match(regex);
343
+ },
344
+ };
345
+
346
+ // The different dataTypes to check the values in
347
+ const dataTypes = ['boolean', 'number', 'string'];
348
+
349
+ // Itterate over all items to check which ones should be output as via output "true" and
350
+ // which ones via output "false"
351
+ let dataType: string;
352
+ let compareOperationResult: boolean;
353
+ itemLoop: for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
354
+ item = items[itemIndex];
355
+
356
+ let compareData: INodeParameters;
357
+
358
+ combineOperation = this.getNodeParameter('combineOperation', itemIndex) as string;
359
+
360
+ // Check all the values of the different dataTypes
361
+ for (dataType of dataTypes) {
362
+ // Check all the values of the current dataType
363
+ for (compareData of this.getNodeParameter(
364
+ `conditions.${dataType}`,
365
+ itemIndex,
366
+ [],
367
+ ) as INodeParameters[]) {
368
+ // Check if the values passes
369
+ compareOperationResult = compareOperationFunctions[compareData['operation'] as string](
370
+ compareData['value1'] as NodeParameterValue,
371
+ compareData['value2'] as NodeParameterValue,
372
+ );
373
+
374
+ if (compareOperationResult === true && combineOperation === 'any') {
375
+ // If it passes and the operation is "any" we do not have to check any
376
+ // other ones as it should pass anyway. So go on with the next item.
377
+ returnDataTrue.push(item);
378
+ continue itemLoop;
379
+ } else if (compareOperationResult === false && combineOperation === 'all') {
380
+ // If it fails and the operation is "all" we do not have to check any
381
+ // other ones as it should be not pass anyway. So go on with the next item.
382
+ returnDataFalse.push(item);
383
+ continue itemLoop;
384
+ }
385
+ }
386
+ }
387
+
388
+ if (combineOperation === 'all') {
389
+ // If the operation is "all" it means the item did match all conditions
390
+ // so it passes.
391
+ returnDataTrue.push(item);
392
+ } else {
393
+ // If the operation is "any" it means the the item did not match any condition.
394
+ returnDataFalse.push(item);
395
+ }
396
+ }
397
+
398
+ return [returnDataTrue, returnDataFalse];
399
+ },
400
+ },
401
+ },
402
+ 'n8n-nodes-base.merge': {
403
+ sourcePath: '',
404
+ type: {
405
+ description: {
406
+ displayName: 'Merge',
407
+ name: 'merge',
408
+ icon: 'fa:clone',
409
+ group: ['transform'],
410
+ version: 1,
411
+ description: 'Merges data of multiple streams once data of both is available',
412
+ defaults: {
413
+ name: 'Merge',
414
+ color: '#00cc22',
415
+ },
416
+ inputs: [NodeConnectionTypes.Main, NodeConnectionTypes.Main],
417
+ outputs: [NodeConnectionTypes.Main],
418
+ properties: [
419
+ {
420
+ displayName: 'Mode',
421
+ name: 'mode',
422
+ type: 'options',
423
+ options: [
424
+ {
425
+ name: 'Append',
426
+ value: 'append',
427
+ description:
428
+ 'Combines data of both inputs. The output will contain items of input 1 and input 2.',
429
+ },
430
+ {
431
+ name: 'Pass-through',
432
+ value: 'passThrough',
433
+ description:
434
+ 'Passes through data of one input. The output will conain only items of the defined input.',
435
+ },
436
+ {
437
+ name: 'Wait',
438
+ value: 'wait',
439
+ description:
440
+ 'Waits till data of both inputs is available and will then output a single empty item.',
441
+ },
442
+ ],
443
+ default: 'append',
444
+ description:
445
+ 'How data should be merged. If it should simply<br />be appended or merged depending on a property.',
446
+ },
447
+ {
448
+ displayName: 'Output Data',
449
+ name: 'output',
450
+ type: 'options',
451
+ displayOptions: {
452
+ show: {
453
+ mode: ['passThrough'],
454
+ },
455
+ },
456
+ options: [
457
+ {
458
+ name: 'Input 1',
459
+ value: 'input1',
460
+ },
461
+ {
462
+ name: 'Input 2',
463
+ value: 'input2',
464
+ },
465
+ ],
466
+ default: 'input1',
467
+ description: 'Defines of which input the data should be used as output of node.',
468
+ },
469
+ ],
470
+ },
471
+ async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
472
+ // const itemsInput2 = this.getInputData(1);
473
+
474
+ const returnData: INodeExecutionData[] = [];
475
+
476
+ const mode = this.getNodeParameter('mode', 0) as string;
477
+
478
+ if (mode === 'append') {
479
+ // Simply appends the data
480
+ for (let i = 0; i < 2; i++) {
481
+ // eslint-disable-next-line prefer-spread
482
+ returnData.push.apply(returnData, this.getInputData(i));
483
+ }
484
+ } else if (mode === 'passThrough') {
485
+ const output = this.getNodeParameter('output', 0) as string;
486
+
487
+ if (output === 'input1') {
488
+ // eslint-disable-next-line prefer-spread
489
+ returnData.push.apply(returnData, this.getInputData(0));
490
+ } else {
491
+ // eslint-disable-next-line prefer-spread
492
+ returnData.push.apply(returnData, this.getInputData(1));
493
+ }
494
+ } else if (mode === 'wait') {
495
+ returnData.push({ json: {} });
496
+ }
497
+
498
+ return [returnData];
499
+ },
500
+ },
501
+ },
502
+ 'n8n-nodes-base.noOp': {
503
+ sourcePath: '',
504
+ type: {
505
+ description: {
506
+ displayName: 'No Operation, do nothing',
507
+ name: 'noOp',
508
+ icon: 'fa:arrow-right',
509
+ group: ['organization'],
510
+ version: 1,
511
+ description: 'No Operation',
512
+ defaults: {
513
+ name: 'NoOp',
514
+ color: '#b0b0b0',
515
+ },
516
+ inputs: [NodeConnectionTypes.Main],
517
+ outputs: [NodeConnectionTypes.Main],
518
+ properties: [],
519
+ },
520
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
521
+ const items = this.getInputData();
522
+ return this.prepareOutputData(items);
523
+ },
524
+ },
525
+ },
526
+ 'n8n-nodes-base.set': {
527
+ sourcePath: '',
528
+ type: {
529
+ description: {
530
+ displayName: 'Set',
531
+ name: 'set',
532
+ group: ['input'],
533
+ version: 1,
534
+ description: 'Sets a value',
535
+ defaults: {
536
+ name: 'Set',
537
+ color: '#0000FF',
538
+ },
539
+ inputs: [NodeConnectionTypes.Main],
540
+ outputs: [NodeConnectionTypes.Main],
541
+ properties: [
542
+ {
543
+ displayName: 'Keep Only Set',
544
+ name: 'keepOnlySet',
545
+ type: 'boolean',
546
+ default: false,
547
+ description:
548
+ 'If only the values set on this node should be<br />kept and all others removed.',
549
+ },
550
+ {
551
+ displayName: 'Values to Set',
552
+ name: 'values',
553
+ placeholder: 'Add Value',
554
+ type: 'fixedCollection',
555
+ typeOptions: {
556
+ multipleValues: true,
557
+ },
558
+ description: 'The value to set.',
559
+ default: {},
560
+ options: [
561
+ {
562
+ name: 'boolean',
563
+ displayName: 'Boolean',
564
+ values: [
565
+ {
566
+ displayName: 'Name',
567
+ name: 'name',
568
+ type: 'string',
569
+ default: 'propertyName',
570
+ description:
571
+ 'Name of the property to write data to.<br />Supports dot-notation.<br />Example: "data.person[0].name"',
572
+ },
573
+ {
574
+ displayName: 'Value',
575
+ name: 'value',
576
+ type: 'boolean',
577
+ default: false,
578
+ description: 'The boolean value to write in the property.',
579
+ },
580
+ ],
581
+ },
582
+ {
583
+ name: 'number',
584
+ displayName: 'Number',
585
+ values: [
586
+ {
587
+ displayName: 'Name',
588
+ name: 'name',
589
+ type: 'string',
590
+ default: 'propertyName',
591
+ description:
592
+ 'Name of the property to write data to.<br />Supports dot-notation.<br />Example: "data.person[0].name"',
593
+ },
594
+ {
595
+ displayName: 'Value',
596
+ name: 'value',
597
+ type: 'number',
598
+ default: 0,
599
+ description: 'The number value to write in the property.',
600
+ },
601
+ ],
602
+ },
603
+ {
604
+ name: 'string',
605
+ displayName: 'String',
606
+ values: [
607
+ {
608
+ displayName: 'Name',
609
+ name: 'name',
610
+ type: 'string',
611
+ default: 'propertyName',
612
+ description:
613
+ 'Name of the property to write data to.<br />Supports dot-notation.<br />Example: "data.person[0].name"',
614
+ },
615
+ {
616
+ displayName: 'Value',
617
+ name: 'value',
618
+ type: 'string',
619
+ default: '',
620
+ description: 'The string value to write in the property.',
621
+ },
622
+ ],
623
+ },
624
+ ],
625
+ },
626
+
627
+ {
628
+ displayName: 'Options',
629
+ name: 'options',
630
+ type: 'collection',
631
+ placeholder: 'Add Option',
632
+ default: {},
633
+ options: [
634
+ {
635
+ displayName: 'Dot Notation',
636
+ name: 'dotNotation',
637
+ type: 'boolean',
638
+ default: true,
639
+ description: `<p>By default, dot-notation is used in property names. This means that "a.b" will set the property "b" underneath "a" so { "a": { "b": value} }.</p><p>If that is not intended this can be deactivated, it will then set { "a.b": value } instead.</p>`,
640
+ },
641
+ ],
642
+ },
643
+ ],
644
+ },
645
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
646
+ const items = this.getInputData();
647
+
648
+ if (items.length === 0) {
649
+ items.push({ json: {} });
650
+ }
651
+
652
+ const returnData: INodeExecutionData[] = [];
653
+
654
+ let item: INodeExecutionData;
655
+ let keepOnlySet: boolean;
656
+ for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
657
+ keepOnlySet = this.getNodeParameter('keepOnlySet', itemIndex, false) as boolean;
658
+ item = items[itemIndex];
659
+ const options = this.getNodeParameter('options', itemIndex, {}) as IDataObject;
660
+
661
+ const newItem: INodeExecutionData = {
662
+ json: {},
663
+ };
664
+
665
+ if (keepOnlySet !== true) {
666
+ if (item.binary !== undefined) {
667
+ // Create a shallow copy of the binary data so that the old
668
+ // data references which do not get changed still stay behind
669
+ // but the incoming data does not get changed.
670
+ newItem.binary = {};
671
+ Object.assign(newItem.binary, item.binary);
672
+ }
673
+
674
+ newItem.json = JSON.parse(JSON.stringify(item.json));
675
+ }
676
+
677
+ // Add boolean values
678
+ (this.getNodeParameter('values.boolean', itemIndex, []) as INodeParameters[]).forEach(
679
+ (setItem) => {
680
+ if (options['dotNotation'] === false) {
681
+ newItem.json[setItem['name'] as string] = !!setItem['value'];
682
+ } else {
683
+ set(newItem.json, setItem['name'] as string, !!setItem['value']);
684
+ }
685
+ },
686
+ );
687
+
688
+ // Add number values
689
+ (this.getNodeParameter('values.number', itemIndex, []) as INodeParameters[]).forEach(
690
+ (setItem) => {
691
+ if (options['dotNotation'] === false) {
692
+ newItem.json[setItem['name'] as string] = setItem['value'];
693
+ } else {
694
+ set(newItem.json, setItem['name'] as string, setItem['value']);
695
+ }
696
+ },
697
+ );
698
+
699
+ // Add string values
700
+ (this.getNodeParameter('values.string', itemIndex, []) as INodeParameters[]).forEach(
701
+ (setItem) => {
702
+ if (options['dotNotation'] === false) {
703
+ newItem.json[setItem['name'] as string] = setItem['value'];
704
+ } else {
705
+ set(newItem.json, setItem['name'] as string, setItem['value']);
706
+ }
707
+ },
708
+ );
709
+
710
+ returnData.push(newItem);
711
+ }
712
+
713
+ return this.prepareOutputData(returnData);
714
+ },
715
+ },
716
+ },
717
+ 'n8n-nodes-base.start': {
718
+ sourcePath: '',
719
+ type: {
720
+ description: {
721
+ displayName: 'Start',
722
+ name: 'start',
723
+ group: ['input'],
724
+ version: 1,
725
+ description: 'Starts the workflow execution from this node',
726
+ defaults: {
727
+ name: 'Start',
728
+ color: '#553399',
729
+ },
730
+ inputs: [],
731
+ outputs: ['main'],
732
+ properties: [],
733
+ },
734
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
735
+ const items = this.getInputData();
736
+
737
+ return this.prepareOutputData(items);
738
+ },
739
+ },
740
+ },
741
+ };
742
+
743
+ async init(nodeTypes: INodeTypeData): Promise<void> {}
744
+
745
+ getAll(): INodeType[] {
746
+ return Object.values(this.nodeTypes).map((data) => NodeHelpers.getVersionedNodeType(data.type));
747
+ }
748
+
749
+ getByName(nodeType: string): INodeType {
750
+ return this.getByNameAndVersion(nodeType);
751
+ }
752
+
753
+ getByNameAndVersion(nodeType: string, version?: number): INodeType {
754
+ return NodeHelpers.getVersionedNodeType(this.nodeTypes[nodeType].type, version);
755
+ }
756
+ }
757
+
758
+ let nodeTypesInstance: NodeTypesClass | undefined;
759
+
760
+ export function NodeTypes(): NodeTypesClass {
761
+ if (nodeTypesInstance === undefined) {
762
+ nodeTypesInstance = new NodeTypesClass();
763
+ nodeTypesInstance.init({});
764
+ }
765
+
766
+ return nodeTypesInstance;
767
+ }
768
+
769
+ export function WorkflowExecuteAdditionalData(
770
+ waitPromise: IDeferredPromise<IRun>,
771
+ nodeExecutionOrder: string[],
772
+ ): IWorkflowExecuteAdditionalData {
773
+ const hookFunctions = {
774
+ nodeExecuteAfter: [
775
+ async (nodeName: string, data: ITaskData): Promise<void> => {
776
+ nodeExecutionOrder.push(nodeName);
777
+ },
778
+ ],
779
+ workflowExecuteAfter: [
780
+ async (fullRunData: IRun): Promise<void> => {
781
+ waitPromise.resolve(fullRunData);
782
+ },
783
+ ],
784
+ };
785
+
786
+ const workflowData: IWorkflowBase = {
787
+ name: '',
788
+ createdAt: new Date(),
789
+ updatedAt: new Date(),
790
+ active: true,
791
+ nodes: [],
792
+ connections: {},
793
+ };
794
+
795
+ return {
796
+ credentialsHelper: new CredentialsHelper(''),
797
+ hooks: new WorkflowHooks(hookFunctions, 'trigger', '1', workflowData),
798
+ executeWorkflow: async (workflowInfo: IExecuteWorkflowInfo): Promise<any> => {},
799
+ sendMessageToUI: (message: string) => {},
800
+ restApiUrl: '',
801
+ encryptionKey: 'test',
802
+ timezone: 'America/New_York',
803
+ webhookBaseUrl: 'webhook',
804
+ webhookWaitingBaseUrl: 'webhook-waiting',
805
+ webhookTestBaseUrl: 'webhook-test',
806
+ userId: '123',
807
+ };
808
+ }