@fsai-flow/workflow 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/.eslintrc.json +33 -0
  2. package/README.md +11 -0
  3. package/dist/README.md +11 -0
  4. package/dist/package.json +42 -0
  5. package/dist/src/index.d.ts +21 -0
  6. package/dist/src/index.js +33 -0
  7. package/dist/src/index.js.map +1 -0
  8. package/dist/src/lib/Constants.d.ts +68 -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 +6 -0
  12. package/dist/src/lib/DeferredPromise.js +11 -0
  13. package/dist/src/lib/DeferredPromise.js.map +1 -0
  14. package/dist/src/lib/Expression.d.ts +65 -0
  15. package/dist/src/lib/Expression.js +215 -0
  16. package/dist/src/lib/Expression.js.map +1 -0
  17. package/dist/src/lib/Interfaces.d.ts +1569 -0
  18. package/dist/src/lib/Interfaces.js +44 -0
  19. package/dist/src/lib/Interfaces.js.map +1 -0
  20. package/dist/src/lib/LoggerProxy.d.ts +9 -0
  21. package/dist/src/lib/LoggerProxy.js +40 -0
  22. package/dist/src/lib/LoggerProxy.js.map +1 -0
  23. package/dist/src/lib/MetadataUtils.d.ts +4 -0
  24. package/dist/src/lib/MetadataUtils.js +27 -0
  25. package/dist/src/lib/MetadataUtils.js.map +1 -0
  26. package/dist/src/lib/NodeErrors.d.ts +82 -0
  27. package/dist/src/lib/NodeErrors.js +289 -0
  28. package/dist/src/lib/NodeErrors.js.map +1 -0
  29. package/dist/src/lib/NodeHelpers.d.ts +198 -0
  30. package/dist/src/lib/NodeHelpers.js +1348 -0
  31. package/dist/src/lib/NodeHelpers.js.map +1 -0
  32. package/dist/src/lib/ObservableObject.d.ts +5 -0
  33. package/dist/src/lib/ObservableObject.js +61 -0
  34. package/dist/src/lib/ObservableObject.js.map +1 -0
  35. package/dist/src/lib/RoutingNode.d.ts +18 -0
  36. package/dist/src/lib/RoutingNode.js +508 -0
  37. package/dist/src/lib/RoutingNode.js.map +1 -0
  38. package/dist/src/lib/TelemetryHelpers.d.ts +3 -0
  39. package/dist/src/lib/TelemetryHelpers.js +69 -0
  40. package/dist/src/lib/TelemetryHelpers.js.map +1 -0
  41. package/dist/src/lib/TypeValidation.d.ts +21 -0
  42. package/dist/src/lib/TypeValidation.js +385 -0
  43. package/dist/src/lib/TypeValidation.js.map +1 -0
  44. package/dist/src/lib/VersionedNodeType.d.ts +9 -0
  45. package/dist/src/lib/VersionedNodeType.js +26 -0
  46. package/dist/src/lib/VersionedNodeType.js.map +1 -0
  47. package/dist/src/lib/Workflow.d.ts +248 -0
  48. package/dist/src/lib/Workflow.js +901 -0
  49. package/dist/src/lib/Workflow.js.map +1 -0
  50. package/dist/src/lib/WorkflowDataProxy.d.ts +87 -0
  51. package/dist/src/lib/WorkflowDataProxy.js +556 -0
  52. package/dist/src/lib/WorkflowDataProxy.js.map +1 -0
  53. package/dist/src/lib/WorkflowErrors.d.ts +9 -0
  54. package/dist/src/lib/WorkflowErrors.js +18 -0
  55. package/dist/src/lib/WorkflowErrors.js.map +1 -0
  56. package/dist/src/lib/WorkflowHooks.d.ts +11 -0
  57. package/dist/src/lib/WorkflowHooks.js +34 -0
  58. package/dist/src/lib/WorkflowHooks.js.map +1 -0
  59. package/dist/src/lib/errors/base/base.error.d.ts +30 -0
  60. package/dist/src/lib/errors/base/base.error.js +45 -0
  61. package/dist/src/lib/errors/base/base.error.js.map +1 -0
  62. package/dist/src/lib/errors/base/operational.error.d.ts +15 -0
  63. package/dist/src/lib/errors/base/operational.error.js +19 -0
  64. package/dist/src/lib/errors/base/operational.error.js.map +1 -0
  65. package/dist/src/lib/errors/error.types.d.ts +11 -0
  66. package/dist/src/lib/errors/error.types.js +3 -0
  67. package/dist/src/lib/errors/error.types.js.map +1 -0
  68. package/dist/src/lib/errors/index.d.ts +1 -0
  69. package/dist/src/lib/errors/index.js +6 -0
  70. package/dist/src/lib/errors/index.js.map +1 -0
  71. package/dist/src/lib/result.d.ts +19 -0
  72. package/dist/src/lib/result.js +36 -0
  73. package/dist/src/lib/result.js.map +1 -0
  74. package/dist/src/lib/utils.d.ts +50 -0
  75. package/dist/src/lib/utils.js +110 -0
  76. package/dist/src/lib/utils.js.map +1 -0
  77. package/eslint.config.js +19 -0
  78. package/jest.config.ts +10 -0
  79. package/package.json +40 -0
  80. package/project.json +19 -0
  81. package/src/index.ts +33 -0
  82. package/src/lib/Constants.ts +124 -0
  83. package/src/lib/DeferredPromise.ts +14 -0
  84. package/src/lib/Expression.ts +375 -0
  85. package/src/lib/Interfaces.ts +2229 -0
  86. package/src/lib/LoggerProxy.ts +43 -0
  87. package/src/lib/MetadataUtils.ts +34 -0
  88. package/src/lib/NodeErrors.ts +332 -0
  89. package/src/lib/NodeHelpers.ts +1666 -0
  90. package/src/lib/ObservableObject.ts +77 -0
  91. package/src/lib/RoutingNode.ts +862 -0
  92. package/src/lib/TelemetryHelpers.ts +86 -0
  93. package/src/lib/TypeValidation.ts +431 -0
  94. package/src/lib/VersionedNodeType.ts +30 -0
  95. package/src/lib/Workflow.ts +1266 -0
  96. package/src/lib/WorkflowDataProxy.ts +708 -0
  97. package/src/lib/WorkflowErrors.ts +18 -0
  98. package/src/lib/WorkflowHooks.ts +51 -0
  99. package/src/lib/errors/base/base.error.ts +68 -0
  100. package/src/lib/errors/base/operational.error.ts +21 -0
  101. package/src/lib/errors/error.types.ts +14 -0
  102. package/src/lib/errors/index.ts +1 -0
  103. package/src/lib/result.ts +34 -0
  104. package/src/lib/utils.ts +132 -0
  105. package/tests/Helpers.ts +667 -0
  106. package/tests/NodeHelpers.test.ts +3053 -0
  107. package/tests/ObservableObject.test.ts +171 -0
  108. package/tests/RoutingNode.test.ts +1680 -0
  109. package/tests/Workflow.test.ts +1284 -0
  110. package/tests/WorkflowDataProxy.test.ts +199 -0
  111. package/tsconfig.json +27 -0
  112. package/tsconfig.lib.json +11 -0
  113. package/tsconfig.spec.json +14 -0
@@ -0,0 +1,14 @@
1
+ // From: https://gist.github.com/compulim/8b49b0a744a3eeb2205e2b9506201e50
2
+ export interface IDeferredPromise<T> {
3
+ promise: () => Promise<T>;
4
+ reject: (error: Error) => void;
5
+ resolve: (result: T) => void;
6
+ }
7
+
8
+ export async function createDeferredPromise<T>(): Promise<IDeferredPromise<T>> {
9
+ return new Promise<IDeferredPromise<T>>((resolveCreate) => {
10
+ const promise = new Promise<T>((resolve, reject) => {
11
+ resolveCreate({ promise: async () => promise, resolve, reject });
12
+ });
13
+ });
14
+ }
@@ -0,0 +1,375 @@
1
+ // @ts-ignore
2
+ import * as tmpl from 'riot-tmpl';
3
+ import { DateTime, Duration, Interval } from 'luxon';
4
+
5
+ // eslint-disable-next-line import/no-cycle
6
+ import {
7
+ INode,
8
+ INodeExecutionData,
9
+ INodeParameters,
10
+ IRunExecutionData,
11
+ IWorkflowDataProxyAdditionalKeys,
12
+ NodeParameterValue,
13
+ Workflow,
14
+ WorkflowDataProxy,
15
+ WorkflowExecuteMode,
16
+ } from '..';
17
+
18
+ // @ts-ignore
19
+
20
+ // Set it to use double curly brackets instead of single ones
21
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
22
+ tmpl.brackets.set('{{ }}');
23
+
24
+ // Make sure that it does not always print an error when it could not resolve
25
+ // a variable
26
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
27
+ tmpl.tmpl.errorHandler = () => { };
28
+
29
+ export class Expression {
30
+ workflow: Workflow;
31
+
32
+ constructor(workflow: Workflow) {
33
+ this.workflow = workflow;
34
+ }
35
+
36
+ /**
37
+ * Converts an object to a string in a way to make it clear that
38
+ * the value comes from an object
39
+ *
40
+ * @param {object} value
41
+ * @returns {string}
42
+ * @memberof Workflow
43
+ */
44
+ convertObjectValueToString(value: object): string {
45
+ const typeName = Array.isArray(value) ? 'Array' : 'Object';
46
+ return `[${typeName}: ${JSON.stringify(value)}]`;
47
+ }
48
+
49
+ /**
50
+ * Resolves the paramter value. If it is an expression it will execute it and
51
+ * return the result. For everything simply the supplied value will be returned.
52
+ *
53
+ * @param {NodeParameterValue} parameterValue
54
+ * @param {(IRunExecutionData | null)} runExecutionData
55
+ * @param {number} runIndex
56
+ * @param {number} itemIndex
57
+ * @param {string} activeNodeName
58
+ * @param {INodeExecutionData[]} connectionInputData
59
+ * @param {boolean} [returnObjectAsString=false]
60
+ * @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
61
+ * @memberof Workflow
62
+ */
63
+ resolveSimpleParameterValue(
64
+ parameterValue: NodeParameterValue,
65
+ siblingParameters: INodeParameters,
66
+ runExecutionData: IRunExecutionData | null,
67
+ runIndex: number,
68
+ itemIndex: number,
69
+ activeNodeName: string,
70
+ connectionInputData: INodeExecutionData[],
71
+ mode: WorkflowExecuteMode,
72
+ additionalKeys: IWorkflowDataProxyAdditionalKeys,
73
+ returnObjectAsString = false,
74
+ selfData = {},
75
+ ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
76
+ // Check if it is an expression
77
+ if (typeof parameterValue !== 'string' || parameterValue.charAt(0) !== '=') {
78
+ // Is no expression so return value
79
+ return parameterValue;
80
+ }
81
+
82
+ // Is an expression
83
+
84
+ // Remove the equal sign
85
+ // eslint-disable-next-line no-param-reassign
86
+ parameterValue = parameterValue.substr(1);
87
+
88
+ // Generate a data proxy which allows to query workflow data
89
+ const dataProxy = new WorkflowDataProxy(
90
+ this.workflow,
91
+ runExecutionData,
92
+ runIndex,
93
+ itemIndex,
94
+ activeNodeName,
95
+ connectionInputData,
96
+ siblingParameters,
97
+ mode,
98
+ additionalKeys,
99
+ -1,
100
+ selfData,
101
+ );
102
+ const data = dataProxy.getDataProxy();
103
+
104
+ // Support only a subset of process properties
105
+ // @ts-ignore
106
+ data.process = {
107
+ arch: process.arch,
108
+ env: process.env,
109
+ platform: process.platform,
110
+ pid: process.pid,
111
+ ppid: process.ppid,
112
+ release: process.release,
113
+ version: process.pid,
114
+ versions: process.versions,
115
+ };
116
+
117
+ // @ts-ignore
118
+ data.document = {};
119
+
120
+ // @ts-ignore
121
+ data.DateTime = DateTime;
122
+ data['Interval'] = Interval;
123
+ data['Duration'] = Duration;
124
+
125
+ // @ts-ignore
126
+ data.constructor = {};
127
+
128
+ // Execute the expression
129
+ try {
130
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call
131
+ const returnValue = tmpl.tmpl(parameterValue, data);
132
+ if (typeof returnValue === 'function') {
133
+ throw new Error('Expression resolved to a function. Please add "()"');
134
+ } else if (returnValue !== null && typeof returnValue === 'object') {
135
+ if (returnObjectAsString) {
136
+ return this.convertObjectValueToString(returnValue);
137
+ }
138
+ }
139
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
140
+ return returnValue;
141
+ } catch (e: any) {
142
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions, @typescript-eslint/no-unsafe-member-access
143
+ throw new Error(`Expression is not valid: ${e.message}`);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Resolves value of parameter. But does not work for workflow-data.
149
+ *
150
+ * @param {INode} node
151
+ * @param {(string | undefined)} parameterValue
152
+ * @param {string} [defaultValue]
153
+ * @returns {(string | undefined)}
154
+ * @memberof Workflow
155
+ */
156
+ getSimpleParameterValue(
157
+ node: INode,
158
+ parameterValue: string | boolean | undefined,
159
+ mode: WorkflowExecuteMode,
160
+ additionalKeys: IWorkflowDataProxyAdditionalKeys,
161
+ defaultValue?: boolean | number | string,
162
+ ): boolean | number | string | undefined {
163
+ if (parameterValue === undefined) {
164
+ // Value is not set so return the default
165
+ return defaultValue;
166
+ }
167
+
168
+ // Get the value of the node (can be an expression)
169
+ const runIndex = 0;
170
+ const itemIndex = 0;
171
+ const connectionInputData: INodeExecutionData[] = [];
172
+ const runData: IRunExecutionData = {
173
+ resultData: {
174
+ runData: {},
175
+ },
176
+ };
177
+
178
+ return this.getParameterValue(
179
+ parameterValue,
180
+ runData,
181
+ runIndex,
182
+ itemIndex,
183
+ node.name,
184
+ connectionInputData,
185
+ mode,
186
+ additionalKeys,
187
+ ) as boolean | number | string | undefined;
188
+ }
189
+
190
+ /**
191
+ * Resolves value of complex parameter. But does not work for workflow-data.
192
+ *
193
+ * @param {INode} node
194
+ * @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])} parameterValue
195
+ * @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined)} [defaultValue]
196
+ * @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined)}
197
+ * @memberof Workflow
198
+ */
199
+ getComplexParameterValue(
200
+ node: INode,
201
+ parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[],
202
+ mode: WorkflowExecuteMode,
203
+ additionalKeys: IWorkflowDataProxyAdditionalKeys,
204
+ defaultValue:
205
+ | NodeParameterValue
206
+ | INodeParameters
207
+ | NodeParameterValue[]
208
+ | INodeParameters[]
209
+ | undefined = undefined,
210
+ selfData = {},
211
+ ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | undefined {
212
+ if (parameterValue === undefined) {
213
+ // Value is not set so return the default
214
+ return defaultValue;
215
+ }
216
+
217
+ // Get the value of the node (can be an expression)
218
+ const runIndex = 0;
219
+ const itemIndex = 0;
220
+ const connectionInputData: INodeExecutionData[] = [];
221
+ const runData: IRunExecutionData = {
222
+ resultData: {
223
+ runData: {},
224
+ },
225
+ };
226
+
227
+ // Resolve the "outer" main values
228
+ const returnData = this.getParameterValue(
229
+ parameterValue,
230
+ runData,
231
+ runIndex,
232
+ itemIndex,
233
+ node.name,
234
+ connectionInputData,
235
+ mode,
236
+ additionalKeys,
237
+ false,
238
+ selfData,
239
+ );
240
+
241
+ // Resolve the "inner" values
242
+ return this.getParameterValue(
243
+ returnData,
244
+ runData,
245
+ runIndex,
246
+ itemIndex,
247
+ node.name,
248
+ connectionInputData,
249
+ mode,
250
+ additionalKeys,
251
+ false,
252
+ selfData,
253
+ );
254
+ }
255
+
256
+ /**
257
+ * Returns the resolved node parameter value. If it is an expression it will execute it and
258
+ * return the result. If the value to resolve is an array or object it will do the same
259
+ * for all of the items and values.
260
+ *
261
+ * @param {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])} parameterValue
262
+ * @param {(IRunExecutionData | null)} runExecutionData
263
+ * @param {number} runIndex
264
+ * @param {number} itemIndex
265
+ * @param {string} activeNodeName
266
+ * @param {INodeExecutionData[]} connectionInputData
267
+ * @param {boolean} [returnObjectAsString=false]
268
+ * @returns {(NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[])}
269
+ * @memberof Workflow
270
+ */
271
+ getParameterValue(
272
+ parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[],
273
+ runExecutionData: IRunExecutionData | null,
274
+ runIndex: number,
275
+ itemIndex: number,
276
+ activeNodeName: string,
277
+ connectionInputData: INodeExecutionData[],
278
+ mode: WorkflowExecuteMode,
279
+ additionalKeys: IWorkflowDataProxyAdditionalKeys,
280
+ returnObjectAsString = false,
281
+ selfData = {},
282
+ ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] {
283
+ // Helper function which returns true when the parameter is a complex one or array
284
+ const isComplexParameter = (
285
+ value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[],
286
+ ) => {
287
+ return typeof value === 'object';
288
+ };
289
+
290
+ // Helper function which resolves a parameter value depending on if it is simply or not
291
+ const resolveParameterValue = (
292
+ value: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[],
293
+ siblingParameters: INodeParameters,
294
+ ) => {
295
+ if (isComplexParameter(value)) {
296
+ return this.getParameterValue(
297
+ value,
298
+ runExecutionData,
299
+ runIndex,
300
+ itemIndex,
301
+ activeNodeName,
302
+ connectionInputData,
303
+ mode,
304
+ additionalKeys,
305
+ returnObjectAsString,
306
+ selfData,
307
+ );
308
+ }
309
+ return this.resolveSimpleParameterValue(
310
+ value as NodeParameterValue,
311
+ siblingParameters,
312
+ runExecutionData,
313
+ runIndex,
314
+ itemIndex,
315
+ activeNodeName,
316
+ connectionInputData,
317
+ mode,
318
+ additionalKeys,
319
+ returnObjectAsString,
320
+ selfData,
321
+ );
322
+ };
323
+
324
+ // Check if it value is a simple one that we can get it resolved directly
325
+ if (!isComplexParameter(parameterValue)) {
326
+ return this.resolveSimpleParameterValue(
327
+ parameterValue as NodeParameterValue,
328
+ {},
329
+ runExecutionData,
330
+ runIndex,
331
+ itemIndex,
332
+ activeNodeName,
333
+ connectionInputData,
334
+ mode,
335
+ additionalKeys,
336
+ returnObjectAsString,
337
+ selfData,
338
+ );
339
+ }
340
+
341
+ // The parameter value is complex so resolve depending on type
342
+
343
+ if (Array.isArray(parameterValue)) {
344
+ // Data is an array
345
+ const returnData = [];
346
+ // eslint-disable-next-line no-restricted-syntax
347
+ for (const item of parameterValue) {
348
+ returnData.push(resolveParameterValue(item, {}));
349
+ }
350
+
351
+ if (returnObjectAsString && typeof returnData === 'object') {
352
+ return this.convertObjectValueToString(returnData);
353
+ }
354
+
355
+ return returnData as NodeParameterValue[] | INodeParameters[];
356
+ }
357
+ if (parameterValue === null || parameterValue === undefined) {
358
+ return parameterValue;
359
+ }
360
+ // Data is an object
361
+ const returnData: INodeParameters = {};
362
+ // eslint-disable-next-line no-restricted-syntax
363
+ for (const key of Object.keys(parameterValue)) {
364
+ returnData[key] = resolveParameterValue(
365
+ (parameterValue as INodeParameters)[key],
366
+ parameterValue as INodeParameters,
367
+ );
368
+ }
369
+
370
+ if (returnObjectAsString && typeof returnData === 'object') {
371
+ return this.convertObjectValueToString(returnData);
372
+ }
373
+ return returnData;
374
+ }
375
+ }