@ronaldroe/micro-flow 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -0
- package/README.md +581 -0
- package/index.js +1 -0
- package/package.json +53 -0
- package/src/classes/base.js +143 -0
- package/src/classes/events/broadcast.js +57 -0
- package/src/classes/events/event.js +144 -0
- package/src/classes/events/index.js +4 -0
- package/src/classes/events/step_event.js +28 -0
- package/src/classes/events/workflow_event.js +28 -0
- package/src/classes/index.js +5 -0
- package/src/classes/state.js +197 -0
- package/src/classes/steps/conditional_step.js +80 -0
- package/src/classes/steps/flow_control_step.js +69 -0
- package/src/classes/steps/index.js +4 -0
- package/src/classes/steps/logic_step.js +102 -0
- package/src/classes/steps/step.js +111 -0
- package/src/classes/workflow.js +379 -0
- package/src/enums/base_types.js +6 -0
- package/src/enums/conditional_step_comparators.js +27 -0
- package/src/enums/delay_types.js +38 -0
- package/src/enums/errors.js +25 -0
- package/src/enums/flow_control_types.js +12 -0
- package/src/enums/index.js +13 -0
- package/src/enums/logic_step_types.js +16 -0
- package/src/enums/loop_types.js +12 -0
- package/src/enums/step_event_names.js +22 -0
- package/src/enums/step_statuses.js +17 -0
- package/src/enums/step_types.js +14 -0
- package/src/enums/sub_step_types.js +130 -0
- package/src/enums/workflow_event_names.js +26 -0
- package/src/enums/workflow_statuses.js +21 -0
- package/src/index.js +2 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of delay types for DelayStep.
|
|
3
|
+
*
|
|
4
|
+
* @enum {string}
|
|
5
|
+
* @readonly
|
|
6
|
+
* @example
|
|
7
|
+
* import delay_types from 'micro-flow';
|
|
8
|
+
*
|
|
9
|
+
* const delayStep = new DelayStep({
|
|
10
|
+
* name: 'wait-5-seconds',
|
|
11
|
+
* delay_type: delay_types.RELATIVE,
|
|
12
|
+
* delay_duration: 5000
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
const delay_types = {
|
|
16
|
+
/**
|
|
17
|
+
* Delay until a specific absolute timestamp or Date.
|
|
18
|
+
* Use with delay_timestamp property.
|
|
19
|
+
* @type {string}
|
|
20
|
+
*/
|
|
21
|
+
ABSOLUTE: 'absolute',
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Delay using a cron expression for scheduled execution.
|
|
25
|
+
* Use with cron_expression property.
|
|
26
|
+
* @type {string}
|
|
27
|
+
*/
|
|
28
|
+
CRON: 'cron',
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Delay for a relative duration in milliseconds.
|
|
32
|
+
* Use with delay_duration property.
|
|
33
|
+
* @type {string}
|
|
34
|
+
*/
|
|
35
|
+
RELATIVE: 'relative',
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default delay_types;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error messages used in the micro-flow library.
|
|
3
|
+
*
|
|
4
|
+
* @enum {string}
|
|
5
|
+
* @readonly
|
|
6
|
+
*/
|
|
7
|
+
const errors = {
|
|
8
|
+
INVALID_STATE_PATH: 'The provided state path is invalid.\n',
|
|
9
|
+
INVALID_CONDITIONAL: 'Conditional properties are required for LogicStep.',
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Warning messages used in the micro-flow library.
|
|
14
|
+
* These are typically logged to the console to alert developers of potential issues.
|
|
15
|
+
*
|
|
16
|
+
* @enum {string}
|
|
17
|
+
* @readonly
|
|
18
|
+
*/
|
|
19
|
+
const warnings = {
|
|
20
|
+
DO_NOT_SET_STEPS_DIRECTLY: 'Using this.setState("steps", ...) is not recommended. ' +
|
|
21
|
+
'State will not be initialized correctly. Use workflow methods to manage steps instead.',
|
|
22
|
+
BROADCAST_FAILED: 'Broadcast failed or is not supported in this environment. The error has more detail:\n',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { errors, warnings };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { default as conditional_step_comparators } from './conditional_step_comparators.js';
|
|
2
|
+
export { default as delay_types } from './delay_types.js';
|
|
3
|
+
export * from './errors.js';
|
|
4
|
+
export { default as flow_control_types } from './flow_control_types.js';
|
|
5
|
+
export { default as logic_step_types } from './logic_step_types.js';
|
|
6
|
+
export { default as loop_types } from './loop_types.js';
|
|
7
|
+
export { default as step_event_names } from './step_event_names.js';
|
|
8
|
+
export { default as step_statuses } from './step_statuses.js';
|
|
9
|
+
export { default as step_types } from './step_types.js';
|
|
10
|
+
export { default as sub_step_types } from './sub_step_types.js';
|
|
11
|
+
export { default as workflow_event_names } from './workflow_event_names.js';
|
|
12
|
+
export { default as workflow_statuses } from './workflow_statuses.js';
|
|
13
|
+
export { default as base_types } from './base_types.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of logic step types for control flow operations.
|
|
3
|
+
* These types define different kinds of logic-based workflow steps.
|
|
4
|
+
*
|
|
5
|
+
* @enum {string}
|
|
6
|
+
* @readonly
|
|
7
|
+
*/
|
|
8
|
+
const LogicStepTypes = {
|
|
9
|
+
CONDITIONAL: 'conditional',
|
|
10
|
+
LOOP: 'loop',
|
|
11
|
+
FLOW_CONTROL: 'flow_control',
|
|
12
|
+
SWITCH: 'switch',
|
|
13
|
+
SKIP: 'skip'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default LogicStepTypes;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of step lifecycle event names.
|
|
3
|
+
* Steps emit these events during their execution lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* @enum {string}
|
|
6
|
+
* @readonly
|
|
7
|
+
*/
|
|
8
|
+
const step_event_names = {
|
|
9
|
+
CONDITIONAL_FALSE_BRANCH_EXECUTED: 'conditional_false_branch_executed',
|
|
10
|
+
CONDITIONAL_TRUE_BRANCH_EXECUTED: 'conditional_true_branch_executed',
|
|
11
|
+
DELAY_STEP_ABSOLUTE_COMPLETE: 'delay_step_absolute_complete',
|
|
12
|
+
DELAY_STEP_RELATIVE_COMPLETE: 'delay_step_relative_complete',
|
|
13
|
+
LOOP_ITERATION_COMPLETE: 'loop_iteration_complete',
|
|
14
|
+
STEP_COMPLETE: 'step_complete',
|
|
15
|
+
STEP_FAILED: 'step_failed',
|
|
16
|
+
STEP_RUNNING: 'step_running',
|
|
17
|
+
STEP_PENDING: 'step_pending',
|
|
18
|
+
STEP_WAITING: 'step_waiting',
|
|
19
|
+
STEP_RETRYING: 'step_retrying',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default step_event_names;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of possible step execution statuses.
|
|
3
|
+
* Steps transition through these statuses during their lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* @enum {string}
|
|
6
|
+
* @readonly
|
|
7
|
+
*/
|
|
8
|
+
const step_statuses = {
|
|
9
|
+
COMPLETE: 'complete',
|
|
10
|
+
FAILED: 'failed',
|
|
11
|
+
PENDING: 'pending',
|
|
12
|
+
QUEUED: 'queued',
|
|
13
|
+
RUNNING: 'running',
|
|
14
|
+
WAITING: 'waiting',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default step_statuses;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of step types used throughout the workflow system.
|
|
3
|
+
* These types categorize steps by their primary function.
|
|
4
|
+
*
|
|
5
|
+
* @enum {string}
|
|
6
|
+
* @readonly
|
|
7
|
+
*/
|
|
8
|
+
const step_types = {
|
|
9
|
+
ACTION: 'action',
|
|
10
|
+
LOGIC: 'logic',
|
|
11
|
+
DELAY: 'delay',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default step_types;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { readdirSync, readFileSync } from 'fs';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import { dirname, join } from 'path';
|
|
4
|
+
import logic_step_types from './logic_step_types.js';
|
|
5
|
+
import step_types from './step_types.js';
|
|
6
|
+
import { sub } from 'date-fns';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Generates a mapping of Step class names to their step_name identifiers by reading
|
|
13
|
+
* class files from the filesystem. This approach avoids circular dependencies that would
|
|
14
|
+
* occur if we imported the Step classes directly.
|
|
15
|
+
*
|
|
16
|
+
* The function parses each class file to extract:
|
|
17
|
+
* - The class name from the export statement
|
|
18
|
+
* - The static step_name property value
|
|
19
|
+
*
|
|
20
|
+
* When step_name references an enum (e.g., logic_step_types.CONDITIONAL), the function
|
|
21
|
+
* resolves the actual string value from the imported enum objects.
|
|
22
|
+
*
|
|
23
|
+
* The built-in classes directory is always scanned. Additional directories can be provided
|
|
24
|
+
* to scan for custom step classes. This is typically used via the workflow's sub_step_type_paths
|
|
25
|
+
* configuration option.
|
|
26
|
+
*
|
|
27
|
+
* @function generate_sub_step_types
|
|
28
|
+
* @param {string[]} [directories=[]] - An array of additional directory paths to scan for class files.
|
|
29
|
+
* The built-in classes directory is always included. Defaults to an empty array.
|
|
30
|
+
* @returns {Object.<string, string|null>} An object mapping class names to their step_name values.
|
|
31
|
+
* Classes without a step_name property are mapped to null.
|
|
32
|
+
* @example
|
|
33
|
+
* // Default usage (scans built-in classes only)
|
|
34
|
+
* const types = generate_sub_step_types();
|
|
35
|
+
* // Returns:
|
|
36
|
+
* // {
|
|
37
|
+
* // "Step": null,
|
|
38
|
+
* // "ConditionalStep": "conditional",
|
|
39
|
+
* // "LogicStep": "logic",
|
|
40
|
+
* // "DelayStep": "delay",
|
|
41
|
+
* // ...
|
|
42
|
+
* // }
|
|
43
|
+
*
|
|
44
|
+
* // With custom directories
|
|
45
|
+
* const types = generate_sub_step_types(['/path/to/custom/steps']);
|
|
46
|
+
*/
|
|
47
|
+
const generate_sub_step_types = (directories = []) => {
|
|
48
|
+
const types = {};
|
|
49
|
+
|
|
50
|
+
// Always include the classes directory, then append any additional directories
|
|
51
|
+
directories.push(join(__dirname, '../classes'));
|
|
52
|
+
|
|
53
|
+
// Combine all enums into one lookup object
|
|
54
|
+
const allEnums = {
|
|
55
|
+
logic_step_types,
|
|
56
|
+
step_types
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Scan each directory in the array
|
|
60
|
+
for (const dir of directories) {
|
|
61
|
+
// Read all files in the current directory
|
|
62
|
+
const files = readdirSync(dir).filter(file => file.endsWith('.js') && file !== 'index.js');
|
|
63
|
+
|
|
64
|
+
for (const file of files) {
|
|
65
|
+
const filePath = join(dir, file);
|
|
66
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
67
|
+
|
|
68
|
+
// Extract class name from the file content
|
|
69
|
+
const classNameMatch = content.match(/export default class (\w+)/);
|
|
70
|
+
if (!classNameMatch) continue;
|
|
71
|
+
|
|
72
|
+
const className = classNameMatch[1];
|
|
73
|
+
|
|
74
|
+
// Extract static step_name value
|
|
75
|
+
const stepNameMatch = content.match(/static step_name\s*=\s*['"`]?([^'"`;\n]+)['"`]?/);
|
|
76
|
+
|
|
77
|
+
if (stepNameMatch) {
|
|
78
|
+
let stepName = stepNameMatch[1].trim();
|
|
79
|
+
|
|
80
|
+
// Handle cases where step_name references an enum
|
|
81
|
+
// e.g., logic_step_types.CONDITIONAL or step_types.ACTION
|
|
82
|
+
if (stepName.includes('.')) {
|
|
83
|
+
const [enumName, enumKey] = stepName.split('.');
|
|
84
|
+
|
|
85
|
+
// Look up the actual value from the imported enums
|
|
86
|
+
if (allEnums[enumName] && allEnums[enumName][enumKey]) {
|
|
87
|
+
stepName = allEnums[enumName][enumKey];
|
|
88
|
+
} else {
|
|
89
|
+
stepName = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
types[className] = stepName;
|
|
94
|
+
} else {
|
|
95
|
+
types[className] = null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return types;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Pre-generated mapping of all built-in Step class names to their step_name identifiers.
|
|
105
|
+
* This is a singleton object exported as the default export.
|
|
106
|
+
*
|
|
107
|
+
* **Changed in recent version:** Previously exported as a function, now exported as a
|
|
108
|
+
* pre-generated object for improved performance and consistency.
|
|
109
|
+
*
|
|
110
|
+
* @constant {Object.<string, string|null>}
|
|
111
|
+
* @example
|
|
112
|
+
* import sub_step_types from 'micro-flow';
|
|
113
|
+
*
|
|
114
|
+
* console.log(sub_step_types);
|
|
115
|
+
* // {
|
|
116
|
+
* // "Step": null,
|
|
117
|
+
* // "ConditionalStep": "conditional",
|
|
118
|
+
* // "DelayStep": "delay",
|
|
119
|
+
* // "LoopStep": "loop",
|
|
120
|
+
* // ...
|
|
121
|
+
* // }
|
|
122
|
+
*
|
|
123
|
+
* // Check if a class name is a registered step type
|
|
124
|
+
* if (sub_step_types['ConditionalStep']) {
|
|
125
|
+
* console.log('ConditionalStep is a registered step type');
|
|
126
|
+
* }
|
|
127
|
+
*/
|
|
128
|
+
const sub_step_types = generate_sub_step_types();
|
|
129
|
+
|
|
130
|
+
export default sub_step_types;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of workflow lifecycle event names.
|
|
3
|
+
* Workflows emit these events during their creation and execution lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* @enum {string}
|
|
6
|
+
* @readonly
|
|
7
|
+
*/
|
|
8
|
+
const workflow_event_names = {
|
|
9
|
+
WORKFLOW_CANCELLED: 'workflow_cancelled',
|
|
10
|
+
WORKFLOW_COMPLETE: 'workflow_complete',
|
|
11
|
+
WORKFLOW_CREATED: 'workflow_created',
|
|
12
|
+
WORKFLOW_ERRORED: 'workflow_errored',
|
|
13
|
+
WORKFLOW_FAILED: 'workflow_failed',
|
|
14
|
+
WORKFLOW_PAUSED: 'workflow_paused',
|
|
15
|
+
WORKFLOW_RESUMED: 'workflow_resumed',
|
|
16
|
+
WORKFLOW_RUNNING: 'workflow_running',
|
|
17
|
+
WORKFLOW_STEP_ADDED: 'workflow_step_added',
|
|
18
|
+
WORKFLOW_STEP_MOVED: 'workflow_step_moved',
|
|
19
|
+
WORKFLOW_STEP_REMOVED: 'workflow_step_removed',
|
|
20
|
+
WORKFLOW_STEP_SHIFTED: 'workflow_step_shifted',
|
|
21
|
+
WORKFLOW_STEP_SKIPPED: 'workflow_step_skipped',
|
|
22
|
+
WORKFLOW_STEPS_ADDED: 'workflow_steps_added',
|
|
23
|
+
WORKFLOW_STEPS_CLEARED: 'workflow_steps_cleared',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default workflow_event_names;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enumeration of possible workflow execution statuses.
|
|
3
|
+
* Workflows transition through these statuses during their lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* @enum {string}
|
|
6
|
+
* @readonly
|
|
7
|
+
*/
|
|
8
|
+
const workflow_statuses = {
|
|
9
|
+
CANCELLED: 'cancelled',
|
|
10
|
+
COMPLETE: 'complete',
|
|
11
|
+
CREATED: 'created',
|
|
12
|
+
ERRORED: 'errored',
|
|
13
|
+
FROZEN: 'frozen',
|
|
14
|
+
FAILED: 'failed',
|
|
15
|
+
PAUSED: 'paused',
|
|
16
|
+
PENDING: 'pending',
|
|
17
|
+
RUNNING: 'running',
|
|
18
|
+
SKIPPED: 'skipped'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default workflow_statuses;
|
package/src/index.js
ADDED