@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
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 Starkey Software
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the βSoftwareβ), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED βAS ISβ, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
# Micro-Flow
|
|
2
|
+
|
|
3
|
+
A lightweight, flexible workflow orchestration library for Node.js and browser environments. Build complex, sequential processes with ease using an intuitive API that supports conditional logic, flow control, event handling, and state management.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- π **Simple & Intuitive** - Easy-to-understand API for building workflows
|
|
8
|
+
- π **Sequential Execution** - Run steps in order with automatic error handling
|
|
9
|
+
- πΏ **Conditional Logic** - Branch execution based on conditions
|
|
10
|
+
- π― **Flow Control** - Break, skip, or pause workflow execution
|
|
11
|
+
- π‘ **Event-Driven** - Listen to workflow and step lifecycle events
|
|
12
|
+
- πΎ **State Management** - Built-in global state with nested path access
|
|
13
|
+
- π’ **Cross-Tab/Worker Communication** - Broadcast messages between browser tabs/windows or between workers in your favorite JS runtime
|
|
14
|
+
- π **Universal** - Works in Node.js and all modern browsers
|
|
15
|
+
- β‘ **Minimal Dependencies** - Lightweight and simple
|
|
16
|
+
- π¨ **Framework Friendly** - Integrates seamlessly with React, Vue, your favorite framework and vanilla JS
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install --save micro-flow
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
### Node.js Example
|
|
27
|
+
|
|
28
|
+
```javascript
|
|
29
|
+
import { Workflow, Step } from 'micro-flow';
|
|
30
|
+
|
|
31
|
+
// Create a simple workflow
|
|
32
|
+
const workflow = new Workflow({
|
|
33
|
+
name: 'data-processor',
|
|
34
|
+
steps: [
|
|
35
|
+
new Step({
|
|
36
|
+
name: 'fetch-data',
|
|
37
|
+
callable: async () => {
|
|
38
|
+
const response = await fetch('https://api.example.com/data');
|
|
39
|
+
return response.json();
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
new Step({
|
|
43
|
+
name: 'process-data',
|
|
44
|
+
callable: async () => {
|
|
45
|
+
console.log('Processing data...');
|
|
46
|
+
return { processed: true };
|
|
47
|
+
}
|
|
48
|
+
}),
|
|
49
|
+
new Step({
|
|
50
|
+
name: 'save-results',
|
|
51
|
+
callable: async () => {
|
|
52
|
+
console.log('Saving results...');
|
|
53
|
+
return { saved: true };
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// Execute the workflow
|
|
60
|
+
const result = await workflow.execute();
|
|
61
|
+
console.log('Workflow complete!', result.results);
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Browser Example
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
import { Workflow, Step } from './micro-flow.js';
|
|
68
|
+
|
|
69
|
+
const workflow = new Workflow({
|
|
70
|
+
name: 'ui-update',
|
|
71
|
+
steps: [
|
|
72
|
+
new Step({
|
|
73
|
+
name: 'show-loading',
|
|
74
|
+
callable: async () => {
|
|
75
|
+
document.getElementById('loader').style.display = 'block';
|
|
76
|
+
}
|
|
77
|
+
}),
|
|
78
|
+
new Step({
|
|
79
|
+
name: 'fetch-data',
|
|
80
|
+
callable: async () => {
|
|
81
|
+
const response = await fetch('/api/data');
|
|
82
|
+
return response.json();
|
|
83
|
+
}
|
|
84
|
+
}),
|
|
85
|
+
new Step({
|
|
86
|
+
name: 'update-ui',
|
|
87
|
+
callable: async () => {
|
|
88
|
+
document.getElementById('content').textContent = 'Data loaded!';
|
|
89
|
+
document.getElementById('loader').style.display = 'none';
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
]
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
document.getElementById('loadBtn').addEventListener('click', () => {
|
|
96
|
+
workflow.execute();
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### React Example
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
import { Workflow, Step, State } from './micro-flow.js';
|
|
104
|
+
import { useState } from 'react';
|
|
105
|
+
|
|
106
|
+
function DataFetcher() {
|
|
107
|
+
const [data, setData] = useState(null);
|
|
108
|
+
const [loading, setLoading] = useState(false);
|
|
109
|
+
|
|
110
|
+
const fetchData = async () => {
|
|
111
|
+
const workflow = new Workflow({
|
|
112
|
+
name: 'fetch-workflow',
|
|
113
|
+
steps: [
|
|
114
|
+
new Step({
|
|
115
|
+
name: 'start',
|
|
116
|
+
callable: async () => {
|
|
117
|
+
setLoading(true);
|
|
118
|
+
}
|
|
119
|
+
}),
|
|
120
|
+
new Step({
|
|
121
|
+
name: 'fetch',
|
|
122
|
+
callable: async () => {
|
|
123
|
+
const res = await fetch('/api/data');
|
|
124
|
+
const json = await res.json();
|
|
125
|
+
setData(json);
|
|
126
|
+
}
|
|
127
|
+
}),
|
|
128
|
+
new Step({
|
|
129
|
+
name: 'complete',
|
|
130
|
+
callable: async () => {
|
|
131
|
+
setLoading(false);
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
]
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
await workflow.execute();
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
return (
|
|
141
|
+
<div>
|
|
142
|
+
<button onClick={fetchData} disabled={loading}>
|
|
143
|
+
{loading ? 'Loading...' : 'Fetch Data'}
|
|
144
|
+
</button>
|
|
145
|
+
{data && <pre>{JSON.stringify(data, null, 2)}</pre>}
|
|
146
|
+
</div>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Vue Example
|
|
152
|
+
|
|
153
|
+
```vue
|
|
154
|
+
<template>
|
|
155
|
+
<div>
|
|
156
|
+
<button @click="runWorkflow" :disabled="isRunning">
|
|
157
|
+
{{ isRunning ? 'Processing...' : 'Run Workflow' }}
|
|
158
|
+
</button>
|
|
159
|
+
<p>{{ result }}</p>
|
|
160
|
+
</div>
|
|
161
|
+
</template>
|
|
162
|
+
|
|
163
|
+
<script setup>
|
|
164
|
+
import { ref } from 'vue';
|
|
165
|
+
import { Workflow, Step } from './micro-flow.js';
|
|
166
|
+
|
|
167
|
+
const isRunning = ref(false);
|
|
168
|
+
const result = ref('');
|
|
169
|
+
|
|
170
|
+
const runWorkflow = async () => {
|
|
171
|
+
const workflow = new Workflow({
|
|
172
|
+
name: 'vue-workflow',
|
|
173
|
+
steps: [
|
|
174
|
+
new Step({
|
|
175
|
+
name: 'step-1',
|
|
176
|
+
callable: async () => {
|
|
177
|
+
isRunning.value = true;
|
|
178
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
179
|
+
return 'Step 1 complete';
|
|
180
|
+
}
|
|
181
|
+
}),
|
|
182
|
+
new Step({
|
|
183
|
+
name: 'step-2',
|
|
184
|
+
callable: async () => {
|
|
185
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
186
|
+
return 'Step 2 complete';
|
|
187
|
+
}
|
|
188
|
+
})
|
|
189
|
+
]
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const workflowResult = await workflow.execute();
|
|
193
|
+
result.value = 'Workflow complete!';
|
|
194
|
+
isRunning.value = false;
|
|
195
|
+
};
|
|
196
|
+
</script>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Core Concepts
|
|
200
|
+
|
|
201
|
+
### Workflows
|
|
202
|
+
|
|
203
|
+
Workflows are primary structures that execute a series of steps in sequence. They provide:
|
|
204
|
+
|
|
205
|
+
- Sequential step execution
|
|
206
|
+
- Error handling with `exit_on_error` option
|
|
207
|
+
- Pause and resume capabilities
|
|
208
|
+
- Event emission for monitoring
|
|
209
|
+
- Result collection
|
|
210
|
+
|
|
211
|
+
```javascript
|
|
212
|
+
import { Workflow } from 'micro-flow';
|
|
213
|
+
|
|
214
|
+
const workflow = new Workflow({
|
|
215
|
+
name: 'my-workflow',
|
|
216
|
+
exit_on_error: true, // Stop on first error
|
|
217
|
+
steps: [/* array of steps */]
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Steps
|
|
222
|
+
|
|
223
|
+
Steps are individual units of work that execute functions, other steps, or even entire workflows:
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
import { Step } from 'micro-flow';
|
|
227
|
+
|
|
228
|
+
const step = new Step({
|
|
229
|
+
name: 'my-step',
|
|
230
|
+
callable: async () => {
|
|
231
|
+
// Your async code here
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Conditional Steps
|
|
238
|
+
|
|
239
|
+
Execute different code paths based on conditions:
|
|
240
|
+
|
|
241
|
+
```javascript
|
|
242
|
+
import { ConditionalStep } from 'micro-flow';
|
|
243
|
+
|
|
244
|
+
const conditionalStep = new ConditionalStep({
|
|
245
|
+
name: 'environment-check',
|
|
246
|
+
conditional: {
|
|
247
|
+
subject: process.env.NODE_ENV,
|
|
248
|
+
operator: '===',
|
|
249
|
+
value: 'production'
|
|
250
|
+
},
|
|
251
|
+
true_callable: async () => {
|
|
252
|
+
return loadProductionConfig();
|
|
253
|
+
},
|
|
254
|
+
false_callable: async () => {
|
|
255
|
+
return loadDevelopmentConfig();
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Loop Steps
|
|
261
|
+
|
|
262
|
+
Iterate over collections or repeat while conditions are met:
|
|
263
|
+
|
|
264
|
+
```javascript
|
|
265
|
+
import { LoopStep, loop_types } from 'micro-flow';
|
|
266
|
+
|
|
267
|
+
// For-each loop
|
|
268
|
+
const forEachLoop = new LoopStep({
|
|
269
|
+
name: 'process-items',
|
|
270
|
+
loop_type: loop_types.FOR_EACH,
|
|
271
|
+
items: [1, 2, 3, 4, 5],
|
|
272
|
+
callable: async (item) => {
|
|
273
|
+
console.log('Processing:', item);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// While loop
|
|
278
|
+
const whileLoop = new LoopStep({
|
|
279
|
+
name: 'retry-until-success',
|
|
280
|
+
loop_type: loop_types.WHILE,
|
|
281
|
+
condition: () => retryCount < maxRetries,
|
|
282
|
+
callable: async () => {
|
|
283
|
+
await attemptOperation();
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Delay Steps
|
|
289
|
+
|
|
290
|
+
Delay workflow execution with various timing strategies:
|
|
291
|
+
|
|
292
|
+
```javascript
|
|
293
|
+
import { DelayStep, delay_types } from 'micro-flow';
|
|
294
|
+
|
|
295
|
+
// Relative delay (milliseconds)
|
|
296
|
+
const relativeDelay = new DelayStep({
|
|
297
|
+
name: 'wait-5-seconds',
|
|
298
|
+
delay_type: delay_types.RELATIVE,
|
|
299
|
+
delay_duration: 5000
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Absolute delay (specific time)
|
|
303
|
+
const absoluteDelay = new DelayStep({
|
|
304
|
+
name: 'wait-until-midnight',
|
|
305
|
+
delay_type: delay_types.ABSOLUTE,
|
|
306
|
+
delay_timestamp: new Date('2025-12-31T23:59:59')
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Cron-based delay (scheduled)
|
|
310
|
+
const cronDelay = new DelayStep({
|
|
311
|
+
name: 'daily-task',
|
|
312
|
+
delay_type: delay_types.CRON,
|
|
313
|
+
cron_expression: '0 9 * * *' // Every day at 9 AM
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Flow Control
|
|
318
|
+
|
|
319
|
+
Control workflow execution with break and skip logic:
|
|
320
|
+
|
|
321
|
+
```javascript
|
|
322
|
+
import { FlowControlStep, flow_control_types } from 'micro-flow';
|
|
323
|
+
|
|
324
|
+
const breakStep = new FlowControlStep({
|
|
325
|
+
name: 'error-check',
|
|
326
|
+
conditional: {
|
|
327
|
+
subject: errorCount,
|
|
328
|
+
operator: '>',
|
|
329
|
+
value: 0
|
|
330
|
+
},
|
|
331
|
+
flow_control_type: flow_control_types.BREAK
|
|
332
|
+
});
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### State Management
|
|
336
|
+
|
|
337
|
+
Access global state across all workflows and steps:
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
import { State } from 'micro-flow';
|
|
341
|
+
|
|
342
|
+
// Set values
|
|
343
|
+
State.set('user.name', 'John Doe');
|
|
344
|
+
State.set('config.timeout', 5000);
|
|
345
|
+
|
|
346
|
+
// Get values
|
|
347
|
+
const userName = State.get('user.name');
|
|
348
|
+
const timeout = State.get('config.timeout', 3000); // with default
|
|
349
|
+
|
|
350
|
+
// Delete values
|
|
351
|
+
State.delete('user.name');
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Events
|
|
355
|
+
|
|
356
|
+
Listen to workflow and step lifecycle events. You can do this using Node's EventEmitter syntax or the browser's CustomEvent syntax:
|
|
357
|
+
|
|
358
|
+
```javascript
|
|
359
|
+
import { State } from 'micro-flow';
|
|
360
|
+
|
|
361
|
+
const workflowEvents = State.get('events.workflow');
|
|
362
|
+
|
|
363
|
+
workflowEvents.on('workflow_complete', (data) => {
|
|
364
|
+
console.log(`Workflow ${data.name} completed in ${data.timing.execution_time_ms}ms`);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
const stepEvents = State.get('events.step');
|
|
368
|
+
|
|
369
|
+
stepEvents.on('step_failed', (data) => {
|
|
370
|
+
console.error(`Step ${data.name} failed:`, data.errors);
|
|
371
|
+
});
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Cross-Tab/Worker Communication
|
|
375
|
+
|
|
376
|
+
Broadcast messages between browser tabs and windows:
|
|
377
|
+
|
|
378
|
+
```javascript
|
|
379
|
+
import { Broadcast } from './micro-flow.js';
|
|
380
|
+
|
|
381
|
+
const broadcast = new Broadcast('my-channel');
|
|
382
|
+
|
|
383
|
+
// Send messages to other tabs
|
|
384
|
+
broadcast.send({ type: 'update', data: { userId: 123 } });
|
|
385
|
+
|
|
386
|
+
// Receive messages from other tabs
|
|
387
|
+
broadcast.onReceive((data) => {
|
|
388
|
+
console.log('Message from another tab:', data);
|
|
389
|
+
if (data.type === 'update') {
|
|
390
|
+
updateUI(data.data);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
// Clean up when done
|
|
395
|
+
broadcast.destroy();
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
## Use Cases
|
|
399
|
+
|
|
400
|
+
### Backend (Node.js)
|
|
401
|
+
|
|
402
|
+
- **Data Processing Pipelines** - ETL workflows, data transformation
|
|
403
|
+
- **API Integrations** - Multi-step API calls with retry logic
|
|
404
|
+
- **Task Automation** - Scheduled jobs, batch processing
|
|
405
|
+
- **Microservices Orchestration** - Coordinate service calls
|
|
406
|
+
- **Testing Workflows** - Integration test sequences
|
|
407
|
+
|
|
408
|
+
### Frontend (Browser)
|
|
409
|
+
|
|
410
|
+
- **Multi-Step Forms** - Registration, checkout, surveys
|
|
411
|
+
- **Data Fetching** - Sequential API calls with caching
|
|
412
|
+
- **Animation Sequences** - Complex UI animations
|
|
413
|
+
- **User Onboarding** - Step-by-step tutorials
|
|
414
|
+
- **State Machines** - UI state management
|
|
415
|
+
- **Cross-Tab Synchronization** - Auth state, shopping cart, notifications
|
|
416
|
+
- **Real-Time Collaboration** - Multi-tab editing, shared state
|
|
417
|
+
|
|
418
|
+
## Advanced Examples
|
|
419
|
+
|
|
420
|
+
### Node.js - Data Pipeline with Error Handling
|
|
421
|
+
|
|
422
|
+
```javascript
|
|
423
|
+
import { Workflow, Step, ConditionalStep, State } from 'micro-flow';
|
|
424
|
+
|
|
425
|
+
const pipeline = new Workflow({
|
|
426
|
+
name: 'data-pipeline',
|
|
427
|
+
exit_on_error: false,
|
|
428
|
+
steps: [
|
|
429
|
+
new Step({
|
|
430
|
+
name: 'extract',
|
|
431
|
+
callable: async () => {
|
|
432
|
+
const data = await fetchFromDatabase();
|
|
433
|
+
State.set('pipeline.raw', data);
|
|
434
|
+
return data;
|
|
435
|
+
}
|
|
436
|
+
}),
|
|
437
|
+
new ConditionalStep({
|
|
438
|
+
name: 'validate',
|
|
439
|
+
conditional: {
|
|
440
|
+
subject: State.get('pipeline.raw')?.length,
|
|
441
|
+
operator: '>',
|
|
442
|
+
value: 0
|
|
443
|
+
},
|
|
444
|
+
true_callable: async () => ({ valid: true }),
|
|
445
|
+
false_callable: async () => {
|
|
446
|
+
throw new Error('No data to process');
|
|
447
|
+
}
|
|
448
|
+
}),
|
|
449
|
+
new Step({
|
|
450
|
+
name: 'transform',
|
|
451
|
+
callable: async () => {
|
|
452
|
+
const raw = State.get('pipeline.raw');
|
|
453
|
+
const transformed = raw.map(transform);
|
|
454
|
+
State.set('pipeline.transformed', transformed);
|
|
455
|
+
return transformed;
|
|
456
|
+
}
|
|
457
|
+
}),
|
|
458
|
+
new Step({
|
|
459
|
+
name: 'load',
|
|
460
|
+
callable: async () => {
|
|
461
|
+
const data = State.get('pipeline.transformed');
|
|
462
|
+
await saveToDatabase(data);
|
|
463
|
+
return { saved: data.length };
|
|
464
|
+
}
|
|
465
|
+
})
|
|
466
|
+
]
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
await pipeline.execute();
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Browser - Multi-Step Form with Validation
|
|
473
|
+
|
|
474
|
+
```javascript
|
|
475
|
+
import { Workflow, ConditionalStep } from './micro-flow.js';
|
|
476
|
+
|
|
477
|
+
function createFormWorkflow(formData) {
|
|
478
|
+
return new Workflow({
|
|
479
|
+
name: 'form-submission',
|
|
480
|
+
steps: [
|
|
481
|
+
new ConditionalStep({
|
|
482
|
+
name: 'validate-email',
|
|
483
|
+
conditional: {
|
|
484
|
+
subject: /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email),
|
|
485
|
+
operator: '===',
|
|
486
|
+
value: true
|
|
487
|
+
},
|
|
488
|
+
true_callable: async () => ({ valid: true }),
|
|
489
|
+
false_callable: async () => {
|
|
490
|
+
throw new Error('Invalid email');
|
|
491
|
+
}
|
|
492
|
+
}),
|
|
493
|
+
new Step({
|
|
494
|
+
name: 'submit',
|
|
495
|
+
callable: async () => {
|
|
496
|
+
const response = await fetch('/api/submit', {
|
|
497
|
+
method: 'POST',
|
|
498
|
+
body: JSON.stringify(formData)
|
|
499
|
+
});
|
|
500
|
+
return response.json();
|
|
501
|
+
}
|
|
502
|
+
}),
|
|
503
|
+
new Step({
|
|
504
|
+
name: 'show-success',
|
|
505
|
+
callable: async () => {
|
|
506
|
+
document.getElementById('message').textContent = 'Success!';
|
|
507
|
+
}
|
|
508
|
+
})
|
|
509
|
+
]
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
## Documentation
|
|
515
|
+
|
|
516
|
+
Full documentation is available in the [docs](docs/) directory:
|
|
517
|
+
|
|
518
|
+
- [API Documentation](docs/index.md) - Complete API reference
|
|
519
|
+
- [Classes](docs/classes/) - Workflow, Step, State, and more
|
|
520
|
+
- [Events](docs/classes/events/) - Event system documentation
|
|
521
|
+
- [Enums](docs/enums/) - Status codes and constants
|
|
522
|
+
- [Examples](docs/examples/) - Comprehensive examples
|
|
523
|
+
|
|
524
|
+
### Quick Links
|
|
525
|
+
|
|
526
|
+
**Core Classes:**
|
|
527
|
+
- [Workflow API](docs/classes/workflow.md)
|
|
528
|
+
- [Step API](docs/classes/steps/step.md)
|
|
529
|
+
- [State Management](docs/classes/state.md)
|
|
530
|
+
|
|
531
|
+
**Logic Steps:**
|
|
532
|
+
- [LogicStep API](docs/classes/steps/logic_step.md)
|
|
533
|
+
- [ConditionalStep API](docs/classes/steps/conditional_step.md)
|
|
534
|
+
- [FlowControlStep API](docs/classes/steps/flow_control_step.md)
|
|
535
|
+
|
|
536
|
+
**Events:**
|
|
537
|
+
- [Event System](docs/classes/events/event.md)
|
|
538
|
+
- [WorkflowEvent API](docs/classes/events/workflow_event.md)
|
|
539
|
+
- [StepEvent API](docs/classes/events/step_event.md)
|
|
540
|
+
- [Broadcast API](docs/classes/events/broadcast.md)
|
|
541
|
+
|
|
542
|
+
**Enumerations:**
|
|
543
|
+
- [Step Types](docs/enums/step_types.md)
|
|
544
|
+
- [Step Statuses](docs/enums/step_statuses.md)
|
|
545
|
+
- [Workflow Statuses](docs/enums/workflow_statuses.md)
|
|
546
|
+
- [Delay Types](docs/enums/delay_types.md)
|
|
547
|
+
- [Loop Types](docs/enums/loop_types.md)
|
|
548
|
+
|
|
549
|
+
## Browser Compatibility
|
|
550
|
+
|
|
551
|
+
Micro-flow works in all modern browsers that support:
|
|
552
|
+
- ES6 Modules
|
|
553
|
+
- Async/await
|
|
554
|
+
- CustomEvent API
|
|
555
|
+
- EventTarget API
|
|
556
|
+
|
|
557
|
+
Supported browsers:
|
|
558
|
+
- Chrome/Edge 63+
|
|
559
|
+
- Firefox 60+
|
|
560
|
+
- Safari 11.1+
|
|
561
|
+
- Opera 50+
|
|
562
|
+
|
|
563
|
+
## Node.js Compatibility
|
|
564
|
+
|
|
565
|
+
Requires Node.js 14+ for full ES6 module support.
|
|
566
|
+
|
|
567
|
+
## Contributing
|
|
568
|
+
|
|
569
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
570
|
+
|
|
571
|
+
## Why Micro-Flow?
|
|
572
|
+
|
|
573
|
+
Micro-flow is designed to be:
|
|
574
|
+
|
|
575
|
+
- **Lightweight** - Small footprint, zero dependencies
|
|
576
|
+
- **Simple** - Easy to learn and use
|
|
577
|
+
- **Flexible** - Works in Node.js and browsers
|
|
578
|
+
- **Powerful** - Handles complex workflows with ease
|
|
579
|
+
- **Type-Safe Ready** - Can be extended with TypeScript definitions
|
|
580
|
+
|
|
581
|
+
Perfect for projects that need workflow orchestration without the complexity of enterprise solutions.
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/index.js';
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ronaldroe/micro-flow",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight, flexible workflow orchestration library for Node.js and browser environments. Build complex, sequential processes with ease using an intuitive API that supports conditional logic, flow control, event handling, and state management.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "node build.js",
|
|
8
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
9
|
+
"prepublishOnly": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"workflow",
|
|
13
|
+
"orchestration",
|
|
14
|
+
"state-machine",
|
|
15
|
+
"flow-control",
|
|
16
|
+
"event-driven",
|
|
17
|
+
"browser",
|
|
18
|
+
"nodejs",
|
|
19
|
+
"state-management",
|
|
20
|
+
"sequential",
|
|
21
|
+
"process-automation"
|
|
22
|
+
],
|
|
23
|
+
"author": "Starkey Software",
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"type": "module",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/starkeysoft/micro-flow.git"
|
|
29
|
+
},
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/starkeysoft/micro-flow/issues"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://github.com/starkeysoft/micro-flow#readme",
|
|
34
|
+
"files": [
|
|
35
|
+
"index.js",
|
|
36
|
+
"src/",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18.0.0"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"date-fns": "^4.1.0",
|
|
45
|
+
"node-schedule": "^2.1.1",
|
|
46
|
+
"uuid": "^13.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@vitest/coverage-v8": "^4.0.14",
|
|
50
|
+
"esbuild": "^0.27.0",
|
|
51
|
+
"vitest": "^4.0.14"
|
|
52
|
+
}
|
|
53
|
+
}
|