@ronaldroe/micro-flow 0.0.9
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 +527 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +7 -0
- package/dist/src/classes/base.js +4 -0
- package/dist/src/classes/base.js.map +7 -0
- package/dist/src/classes/events/broadcast.js +2 -0
- package/dist/src/classes/events/broadcast.js.map +7 -0
- package/dist/src/classes/events/event.js +2 -0
- package/dist/src/classes/events/event.js.map +7 -0
- package/dist/src/classes/events/index.js +2 -0
- package/dist/src/classes/events/index.js.map +7 -0
- package/dist/src/classes/events/state_event.js +2 -0
- package/dist/src/classes/events/state_event.js.map +7 -0
- package/dist/src/classes/events/step_event.js +2 -0
- package/dist/src/classes/events/step_event.js.map +7 -0
- package/dist/src/classes/events/workflow_event.js +2 -0
- package/dist/src/classes/events/workflow_event.js.map +7 -0
- package/dist/src/classes/index.js +2 -0
- package/dist/src/classes/index.js.map +7 -0
- package/dist/src/classes/state.js +2 -0
- package/dist/src/classes/state.js.map +7 -0
- package/dist/src/classes/steps/case.js +2 -0
- package/dist/src/classes/steps/case.js.map +7 -0
- package/dist/src/classes/steps/conditional_step.js +2 -0
- package/dist/src/classes/steps/conditional_step.js.map +7 -0
- package/dist/src/classes/steps/delay_step.js +2 -0
- package/dist/src/classes/steps/delay_step.js.map +7 -0
- package/dist/src/classes/steps/flow_control_step.js +2 -0
- package/dist/src/classes/steps/flow_control_step.js.map +7 -0
- package/dist/src/classes/steps/index.js +2 -0
- package/dist/src/classes/steps/index.js.map +7 -0
- package/dist/src/classes/steps/logic_step.js +2 -0
- package/dist/src/classes/steps/logic_step.js.map +7 -0
- package/dist/src/classes/steps/loop_step.js +2 -0
- package/dist/src/classes/steps/loop_step.js.map +7 -0
- package/dist/src/classes/steps/step.js +2 -0
- package/dist/src/classes/steps/step.js.map +7 -0
- package/dist/src/classes/steps/switch_step.js +2 -0
- package/dist/src/classes/steps/switch_step.js.map +7 -0
- package/dist/src/classes/workflow.js +2 -0
- package/dist/src/classes/workflow.js.map +7 -0
- package/dist/src/classes/workflow.test.js +2 -0
- package/dist/src/classes/workflow.test.js.map +7 -0
- package/dist/src/enums/base_types.js +2 -0
- package/dist/src/enums/base_types.js.map +7 -0
- package/dist/src/enums/conditional_step_comparators.js +2 -0
- package/dist/src/enums/conditional_step_comparators.js.map +7 -0
- package/dist/src/enums/delay_types.js +2 -0
- package/dist/src/enums/delay_types.js.map +7 -0
- package/dist/src/enums/errors.js +6 -0
- package/dist/src/enums/errors.js.map +7 -0
- package/dist/src/enums/flow_control_types.js +2 -0
- package/dist/src/enums/flow_control_types.js.map +7 -0
- package/dist/src/enums/index.js +2 -0
- package/dist/src/enums/index.js.map +7 -0
- package/dist/src/enums/logic_step_types.js +2 -0
- package/dist/src/enums/logic_step_types.js.map +7 -0
- package/dist/src/enums/loop_types.js +2 -0
- package/dist/src/enums/loop_types.js.map +7 -0
- package/dist/src/enums/state_event_names.js +2 -0
- package/dist/src/enums/state_event_names.js.map +7 -0
- package/dist/src/enums/step_event_names.js +2 -0
- package/dist/src/enums/step_event_names.js.map +7 -0
- package/dist/src/enums/step_statuses.js +2 -0
- package/dist/src/enums/step_statuses.js.map +7 -0
- package/dist/src/enums/step_types.js +2 -0
- package/dist/src/enums/step_types.js.map +7 -0
- package/dist/src/enums/sub_step_types.js +2 -0
- package/dist/src/enums/sub_step_types.js.map +7 -0
- package/dist/src/enums/workflow_event_names.js +2 -0
- package/dist/src/enums/workflow_event_names.js.map +7 -0
- package/dist/src/enums/workflow_statuses.js +2 -0
- package/dist/src/enums/workflow_statuses.js.map +7 -0
- package/package.json +58 -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 +5 -0
- package/src/classes/events/state_event.js +28 -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 +301 -0
- package/src/classes/steps/case.js +70 -0
- package/src/classes/steps/conditional_step.js +90 -0
- package/src/classes/steps/delay_step.js +103 -0
- package/src/classes/steps/flow_control_step.js +70 -0
- package/src/classes/steps/index.js +8 -0
- package/src/classes/steps/logic_step.js +148 -0
- package/src/classes/steps/loop_step.js +147 -0
- package/src/classes/steps/step.js +129 -0
- package/src/classes/steps/switch_step.js +64 -0
- package/src/classes/workflow.js +383 -0
- package/src/enums/base_types.js +6 -0
- package/src/enums/conditional_step_comparators.js +57 -0
- package/src/enums/delay_types.js +31 -0
- package/src/enums/errors.js +27 -0
- package/src/enums/flow_control_types.js +12 -0
- package/src/enums/index.js +14 -0
- package/src/enums/logic_step_types.js +16 -0
- package/src/enums/loop_types.js +14 -0
- package/src/enums/state_event_names.js +17 -0
- package/src/enums/step_event_names.js +25 -0
- package/src/enums/step_statuses.js +17 -0
- package/src/enums/step_types.js +15 -0
- package/src/enums/sub_step_types.js +20 -0
- package/src/enums/workflow_event_names.js +27 -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,527 @@
|
|
|
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 backend runtimes like 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
|
+
### Callables
|
|
238
|
+
|
|
239
|
+
Most step types accept a `callable` parameter. Callables are the individual actions a step can take.
|
|
240
|
+
|
|
241
|
+
A callable can be any async function, another step, or even a whole workflow. That flexibility allows for everything from very simple workflows to large, modularized flows broken down into logical units for execution.
|
|
242
|
+
|
|
243
|
+
### State Management
|
|
244
|
+
|
|
245
|
+
Access global state across all workflows and steps:
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
import { State } from 'micro-flow';
|
|
249
|
+
|
|
250
|
+
// Set values
|
|
251
|
+
State.set('user.name', 'John Doe');
|
|
252
|
+
State.set('config.timeout', 5000);
|
|
253
|
+
|
|
254
|
+
// Get values
|
|
255
|
+
const userName = State.get('user.name');
|
|
256
|
+
const timeout = State.get('config.timeout', 3000); // with default
|
|
257
|
+
|
|
258
|
+
// Delete values
|
|
259
|
+
State.delete('user.name');
|
|
260
|
+
|
|
261
|
+
// Merge objects into state
|
|
262
|
+
State.merge({ settings: { theme: 'dark', lang: 'en' } });
|
|
263
|
+
|
|
264
|
+
// Iterate over collections
|
|
265
|
+
State.set('users', [{ name: 'Alice' }, { name: 'Bob' }]);
|
|
266
|
+
State.each('users', (user, index) => {
|
|
267
|
+
console.log(`User ${index}: ${user.name}`);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Freeze state (make immutable)
|
|
271
|
+
State.freeze();
|
|
272
|
+
|
|
273
|
+
// Reset state to defaults
|
|
274
|
+
State.reset();
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Events
|
|
278
|
+
|
|
279
|
+
Listen to workflow, step, and state lifecycle events. You can do this using Node's EventEmitter syntax or the browser's CustomEvent syntax. Both work in any environment:
|
|
280
|
+
|
|
281
|
+
```javascript
|
|
282
|
+
import { State } from 'micro-flow';
|
|
283
|
+
|
|
284
|
+
const workflowEvents = State.get('events.workflow');
|
|
285
|
+
|
|
286
|
+
workflowEvents.on('workflow_complete', (data) => {
|
|
287
|
+
console.log(`Workflow ${data.name} completed in ${data.timing.execution_time_ms}ms`);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const stepEvents = State.get('events.step');
|
|
291
|
+
|
|
292
|
+
stepEvents.on('step_failed', (data) => {
|
|
293
|
+
console.error(`Step ${data.name} failed:`, data.errors);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
const stateEvents = State.get('events.state');
|
|
297
|
+
|
|
298
|
+
stateEvents.on('set', (data) => {
|
|
299
|
+
console.log('State modified:', data.state);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
stateEvents.on('deleted', (data) => {
|
|
303
|
+
console.log('State property deleted');
|
|
304
|
+
});
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Cross-Tab/Worker Communication
|
|
308
|
+
|
|
309
|
+
Broadcast messages between browser tabs and windows or across workers in your favorite JS runtime:
|
|
310
|
+
|
|
311
|
+
```javascript
|
|
312
|
+
import { Broadcast } from './micro-flow.js';
|
|
313
|
+
|
|
314
|
+
const broadcast = new Broadcast('my-channel');
|
|
315
|
+
|
|
316
|
+
// Send messages to other tabs
|
|
317
|
+
broadcast.send({ type: 'update', data: { userId: 123 } });
|
|
318
|
+
|
|
319
|
+
// Receive messages from other tabs
|
|
320
|
+
broadcast.onReceive((data) => {
|
|
321
|
+
console.log('Message from another tab:', data);
|
|
322
|
+
if (data.type === 'update') {
|
|
323
|
+
updateUI(data.data);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// Clean up when done
|
|
328
|
+
broadcast.destroy();
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## Use Cases
|
|
332
|
+
|
|
333
|
+
### Backend (Node.js)
|
|
334
|
+
|
|
335
|
+
- **Data Processing Pipelines** - ETL workflows, data transformation
|
|
336
|
+
- **API Integrations** - Multi-step API calls with retry logic
|
|
337
|
+
- **Task Automation** - Scheduled jobs, batch processing
|
|
338
|
+
- **Microservices Orchestration** - Coordinate service calls
|
|
339
|
+
- **Testing Workflows** - Integration test sequences
|
|
340
|
+
|
|
341
|
+
### Frontend (Browser)
|
|
342
|
+
|
|
343
|
+
- **Multi-Step Forms** - Registration, checkout, surveys
|
|
344
|
+
- **Data Fetching** - Sequential API calls with caching
|
|
345
|
+
- **Animation Sequences** - Complex UI animations
|
|
346
|
+
- **User Onboarding** - Step-by-step tutorials
|
|
347
|
+
- **State Machines** - UI state management
|
|
348
|
+
- **Cross-Tab Synchronization** - Auth state, shopping cart, notifications
|
|
349
|
+
- **Real-Time Collaboration** - Multi-tab editing, shared state
|
|
350
|
+
|
|
351
|
+
## Advanced Examples
|
|
352
|
+
|
|
353
|
+
### Node.js - Data Pipeline with Error Handling
|
|
354
|
+
|
|
355
|
+
```javascript
|
|
356
|
+
import { Workflow, Step, ConditionalStep, State } from 'micro-flow';
|
|
357
|
+
|
|
358
|
+
const pipeline = new Workflow({
|
|
359
|
+
name: 'data-pipeline',
|
|
360
|
+
exit_on_error: false,
|
|
361
|
+
steps: [
|
|
362
|
+
new Step({
|
|
363
|
+
name: 'extract',
|
|
364
|
+
callable: async () => {
|
|
365
|
+
const data = await fetchFromDatabase();
|
|
366
|
+
State.set('pipeline.raw', data);
|
|
367
|
+
return data;
|
|
368
|
+
}
|
|
369
|
+
}),
|
|
370
|
+
new ConditionalStep({
|
|
371
|
+
name: 'validate',
|
|
372
|
+
conditional: {
|
|
373
|
+
subject: State.get('pipeline.raw')?.length,
|
|
374
|
+
operator: '>',
|
|
375
|
+
value: 0
|
|
376
|
+
},
|
|
377
|
+
true_callable: async () => ({ valid: true }),
|
|
378
|
+
false_callable: async () => {
|
|
379
|
+
throw new Error('No data to process');
|
|
380
|
+
}
|
|
381
|
+
}),
|
|
382
|
+
new Step({
|
|
383
|
+
name: 'transform',
|
|
384
|
+
callable: async () => {
|
|
385
|
+
const raw = State.get('pipeline.raw');
|
|
386
|
+
const transformed = raw.map(transform);
|
|
387
|
+
State.set('pipeline.transformed', transformed);
|
|
388
|
+
return transformed;
|
|
389
|
+
}
|
|
390
|
+
}),
|
|
391
|
+
new Step({
|
|
392
|
+
name: 'load',
|
|
393
|
+
callable: async () => {
|
|
394
|
+
const data = State.get('pipeline.transformed');
|
|
395
|
+
await saveToDatabase(data);
|
|
396
|
+
return { saved: data.length };
|
|
397
|
+
}
|
|
398
|
+
})
|
|
399
|
+
]
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
await pipeline.execute();
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Browser - Multi-Step Form with Validation
|
|
406
|
+
|
|
407
|
+
```javascript
|
|
408
|
+
import { Workflow, ConditionalStep } from './micro-flow.js';
|
|
409
|
+
|
|
410
|
+
function createFormWorkflow(formData) {
|
|
411
|
+
return new Workflow({
|
|
412
|
+
name: 'form-submission',
|
|
413
|
+
steps: [
|
|
414
|
+
new ConditionalStep({
|
|
415
|
+
name: 'validate-email',
|
|
416
|
+
conditional: {
|
|
417
|
+
subject: /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email),
|
|
418
|
+
operator: '===',
|
|
419
|
+
value: true
|
|
420
|
+
},
|
|
421
|
+
true_callable: async () => ({ valid: true }),
|
|
422
|
+
false_callable: async () => {
|
|
423
|
+
throw new Error('Invalid email');
|
|
424
|
+
}
|
|
425
|
+
}),
|
|
426
|
+
new Step({
|
|
427
|
+
name: 'submit',
|
|
428
|
+
callable: async () => {
|
|
429
|
+
const response = await fetch('/api/submit', {
|
|
430
|
+
method: 'POST',
|
|
431
|
+
body: JSON.stringify(formData)
|
|
432
|
+
});
|
|
433
|
+
return response.json();
|
|
434
|
+
}
|
|
435
|
+
}),
|
|
436
|
+
new Step({
|
|
437
|
+
name: 'show-success',
|
|
438
|
+
callable: async () => {
|
|
439
|
+
document.getElementById('message').textContent = 'Success!';
|
|
440
|
+
}
|
|
441
|
+
})
|
|
442
|
+
]
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Documentation
|
|
448
|
+
|
|
449
|
+
Full documentation is available in the [docs](docs/) directory:
|
|
450
|
+
|
|
451
|
+
- [API Documentation](docs/index.md) - Complete API reference
|
|
452
|
+
- [Classes](docs/classes/) - Workflow, Step, State, and more
|
|
453
|
+
- [Events](docs/classes/events/) - Event system documentation
|
|
454
|
+
- [Enums](docs/enums/) - Status codes and constants
|
|
455
|
+
- [Examples](docs/examples/) - Comprehensive examples
|
|
456
|
+
|
|
457
|
+
### Quick Links
|
|
458
|
+
|
|
459
|
+
**Core Classes:**
|
|
460
|
+
- [Workflow API](docs/classes/workflow.md)
|
|
461
|
+
- [Step API](docs/classes/steps/step.md)
|
|
462
|
+
- [State Management](docs/classes/state.md)
|
|
463
|
+
|
|
464
|
+
**Logic Steps:**
|
|
465
|
+
- [LogicStep API](docs/classes/steps/logic_step.md)
|
|
466
|
+
- [ConditionalStep API](docs/classes/steps/conditional_step.md)
|
|
467
|
+
- [FlowControlStep API](docs/classes/steps/flow_control_step.md)
|
|
468
|
+
- [CaseStep API](docs/classes/steps/case.md)
|
|
469
|
+
- [SwitchStep API](docs/classes/steps/switch_step.md)
|
|
470
|
+
- [LoopStep API](docs/classes/steps/loop_step.md)
|
|
471
|
+
- [DelayStep API](docs/classes/steps/delay_step.md)
|
|
472
|
+
|
|
473
|
+
**Events:**
|
|
474
|
+
- [Event System](docs/classes/events/event.md)
|
|
475
|
+
- [WorkflowEvent API](docs/classes/events/workflow_event.md)
|
|
476
|
+
- [StepEvent API](docs/classes/events/step_event.md)
|
|
477
|
+
- [StateEvent API](docs/classes/events/state_event.md)
|
|
478
|
+
- [Broadcast API](docs/classes/events/broadcast.md)
|
|
479
|
+
|
|
480
|
+
**Enumerations:**
|
|
481
|
+
- [Base Types](docs/enums/base_types.md)
|
|
482
|
+
- [Step Types](docs/enums/step_types.md)
|
|
483
|
+
- [Sub Step Types](docs/enums/sub_step_types.md)
|
|
484
|
+
- [Logic Step Types](docs/enums/logic_step_types.md)
|
|
485
|
+
- [Conditional Step Comparators](docs/enums/conditional_step_comparators.md)
|
|
486
|
+
- [Flow Control Types](docs/enums/flow_control_types.md)
|
|
487
|
+
- [Step Statuses](docs/enums/step_statuses.md)
|
|
488
|
+
- [Workflow Statuses](docs/enums/workflow_statuses.md)
|
|
489
|
+
- [Step Event Names](docs/enums/step_event_names.md)
|
|
490
|
+
- [Workflow Event Names](docs/enums/workflow_event_names.md)
|
|
491
|
+
- [State Event Names](docs/enums/state_event_names.md)
|
|
492
|
+
- [Delay Types](docs/enums/delay_types.md)
|
|
493
|
+
- [Loop Types](docs/enums/loop_types.md)
|
|
494
|
+
- [Errors and Warnings](docs/enums/errors.md)
|
|
495
|
+
|
|
496
|
+
## Browser Compatibility
|
|
497
|
+
|
|
498
|
+
Micro-flow works in all modern browsers that support:
|
|
499
|
+
- ES6 Modules
|
|
500
|
+
- Async/await
|
|
501
|
+
- CustomEvent API
|
|
502
|
+
- EventTarget API
|
|
503
|
+
|
|
504
|
+
Supported browsers:
|
|
505
|
+
- Chrome/Edge 63+
|
|
506
|
+
- Firefox 60+
|
|
507
|
+
- Safari 11.1+
|
|
508
|
+
- Opera 50+
|
|
509
|
+
|
|
510
|
+
## Node.js Compatibility
|
|
511
|
+
|
|
512
|
+
Requires Node.js 14+ for full ES6 module support.
|
|
513
|
+
|
|
514
|
+
## Contributing
|
|
515
|
+
|
|
516
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
517
|
+
|
|
518
|
+
## Why Micro-Flow?
|
|
519
|
+
|
|
520
|
+
Micro-flow is designed to be:
|
|
521
|
+
|
|
522
|
+
- **Lightweight** - Small footprint, minimal dependencies
|
|
523
|
+
- **Simple** - Easy to learn and use
|
|
524
|
+
- **Flexible** - Works in Node.js and browsers
|
|
525
|
+
- **Powerful** - Handles complex workflows with ease
|
|
526
|
+
|
|
527
|
+
Perfect for projects that need workflow orchestration without the complexity of enterprise solutions.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var h=Object.defineProperty;var a=(i,t)=>h(i,"name",{value:t,configurable:!0});import{v4 as p}from"uuid";import{base_types as o}from"../enums/index.js";import e from"./state.js";class r{static{a(this,"Base")}constructor({name:t,base_type:s=o.STEP}){this.id=p(),this.name=t??`${s}-${this.id}`,this.base_type=s,this.timing={cancel_time:null,complete_time:null,end_time:null,execution_time_ms:null,start_time:null}}async execute(){throw new Error("Execute method not implemented")}log(t,s=null){if(!t||!e.get(`events.${this.base_type}`))throw new Error("Invalid event name or event emitter not found");if(e.get(`events.${this.base_type}`).emit(t,this),e.get("log_suppress"))return;const n=s?`
|
|
2
|
+
[${this.base_type.toUpperCase()} - ${this.name}] ${s}`:`
|
|
3
|
+
[${this.base_type.toUpperCase()} - ${this.name}] Event: ${t}`,m=t.endsWith("_failed")?"error":"log";console[m](n)}markAsComplete(){this.timing.complete_time=new Date,this.status=e.get("statuses")[this.base_type].COMPLETE,this.timing.execution_time_ms=this.timing.complete_time-this.timing.start_time,this.steps_by_id&&delete this.steps_by_id,this.log(e.get(`event_names.${this.base_type}`)[`${this.base_type.toUpperCase()}_COMPLETE`],`${this.base_type.charAt(0).toUpperCase()+this.base_type.slice(1)} "${this.name}" complete.`)}markAsFailed(){this.timing.complete_time=new Date,this.status=e.get("statuses")[this.base_type].FAILED,this.timing.execution_time_ms=this.timing.complete_time-this.timing.start_time,this.log(e.get(`event_names.${this.base_type}`)[`${this.base_type.toUpperCase()}_FAILED`],`${this.base_type.charAt(0).toUpperCase()+this.base_type.slice(1)} "${this.name}" failed.`)}markAsWaiting(){}markAsPending(){}markAsRunning(){this.timing.start_time=new Date,this.status=e.get("statuses")[this.base_type].RUNNING,this.log(e.get(`event_names.${this.base_type}`)[`${this.base_type.toUpperCase()}_RUNNING`],`${this.base_type.charAt(0).toUpperCase()+this.base_type.slice(1)} "${this.name}" started.`)}getState(t){return e.get(t)}setState(t,s){e.set(t,s)}deleteState(t){e.delete(t)}}export{r as default};
|
|
4
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/classes/base.js"],
|
|
4
|
+
"sourcesContent": ["import { v4 as uuidv4 } from 'uuid';\nimport { base_types } from '../enums/index.js';\nimport State from './state.js';\n\n/**\n * Base class for workflows and steps.\n * Provides common functionality for timing, status management, logging, and state access.\n * @class Base\n */\nexport default class Base {\n /**\n * Creates a new Base instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the instance.\n * @param {string} [options.base_type=base_types.STEP] - Type of the base instance.\n */\n constructor({ name, base_type = base_types.STEP }) {\n this.id = uuidv4();\n this.name = name ?? `${base_type}-${this.id}`;\n\n this.base_type = base_type;\n this.timing = {\n cancel_time: null,\n complete_time: null,\n end_time: null,\n execution_time_ms: null,\n start_time: null,\n }\n }\n\n /**\n * Executes the instance. Must be overridden by subclasses.\n * @async\n * @throws {Error} Throws if not implemented in subclass.\n */\n async execute() {\n throw new Error('Execute method not implemented');\n }\n\n /**\n * Logs an event and emits it to the appropriate event emitter.\n * @param {string} event_name - Name of the event to log.\n * @param {string} [message=null] - Optional message to log.\n * @throws {Error} Throws if event name is invalid or event emitter not found.\n */\n log(event_name, message = null) {\n if (!event_name || !State.get(`events.${this.base_type}`)) {\n throw new Error('Invalid event name or event emitter not found');\n }\n\n State.get(`events.${this.base_type}`).emit(event_name, this);\n if (State.get('log_suppress')) {\n return;\n }\n\n const logMessage = message ? `\\n[${this.base_type.toUpperCase()} - ${this.name}] ${message}` : `\\n[${this.base_type.toUpperCase()} - ${this.name}] Event: ${event_name}`;\n const logType = event_name.endsWith('_failed') ? 'error' : 'log';\n\n console[logType](logMessage);\n }\n\n /**\n * Marks the instance as complete and calculates execution time.\n */\n markAsComplete() {\n this.timing.complete_time = new Date();\n this.status = State.get('statuses')[this.base_type].COMPLETE;\n this.timing.execution_time_ms = this.timing.complete_time - this.timing.start_time;\n\n if (this.steps_by_id) {\n delete this.steps_by_id;\n }\n\n this.log(\n State.get(`event_names.${this.base_type}`)[`${this.base_type.toUpperCase()}_COMPLETE`],\n `${this.base_type.charAt(0).toUpperCase() + this.base_type.slice(1)} \"${this.name}\" complete.`\n );\n }\n\n /**\n * Marks the instance as failed and calculates execution time.\n */\n markAsFailed() {\n this.timing.complete_time = new Date();\n this.status = State.get('statuses')[this.base_type].FAILED;\n this.timing.execution_time_ms = this.timing.complete_time - this.timing.start_time;\n\n this.log(\n State.get(`event_names.${this.base_type}`)[`${this.base_type.toUpperCase()}_FAILED`],\n `${this.base_type.charAt(0).toUpperCase() + this.base_type.slice(1)} \"${this.name}\" failed.`\n );\n }\n\n /**\n * Marks the instance as waiting. To be implemented by subclasses.\n */\n markAsWaiting() { }\n\n /**\n * Marks the instance as pending. To be implemented by subclasses.\n */\n markAsPending() { }\n\n /**\n * Marks the instance as running and sets the start time.\n */\n markAsRunning() {\n this.timing.start_time = new Date();\n this.status = State.get('statuses')[this.base_type].RUNNING;\n\n this.log(\n State.get(`event_names.${this.base_type}`)[`${this.base_type.toUpperCase()}_RUNNING`],\n `${this.base_type.charAt(0).toUpperCase() + this.base_type.slice(1)} \"${this.name}\" started.`\n );\n }\n\n // State management methods\n /**\n * Gets a value from the global state.\n * @param {string} path - Path to the state property.\n * @returns {*} The state value at the specified path.\n */\n getState(path) {\n return State.get(path);\n }\n\n /**\n * Sets a value in the global state.\n * @param {string} path - Path to the state property.\n * @param {*} value - Value to set.\n */\n setState(path, value) {\n State.set(path, value);\n }\n\n /**\n * Deletes a property from the global state.\n * @param {string} path - Path to the state property to delete.\n */\n deleteState(path) {\n State.delete(path);\n }\n}\n"],
|
|
5
|
+
"mappings": "+EAAA,OAAS,MAAMA,MAAc,OAC7B,OAAS,cAAAC,MAAkB,oBAC3B,OAAOC,MAAW,aAOlB,MAAOC,CAAmB,CAT1B,MAS0B,CAAAC,EAAA,aAOxB,YAAY,CAAE,KAAAC,EAAM,UAAAC,EAAYL,EAAW,IAAK,EAAG,CACjD,KAAK,GAAKD,EAAO,EACjB,KAAK,KAAOK,GAAQ,GAAGC,CAAS,IAAI,KAAK,EAAE,GAE3C,KAAK,UAAYA,EACjB,KAAK,OAAS,CACZ,YAAa,KACb,cAAe,KACf,SAAU,KACV,kBAAmB,KACnB,WAAY,IACd,CACF,CAOA,MAAM,SAAU,CACd,MAAM,IAAI,MAAM,gCAAgC,CAClD,CAQA,IAAIC,EAAYC,EAAU,KAAM,CAC9B,GAAI,CAACD,GAAc,CAACL,EAAM,IAAI,UAAU,KAAK,SAAS,EAAE,EACtD,MAAM,IAAI,MAAM,+CAA+C,EAIjE,GADAA,EAAM,IAAI,UAAU,KAAK,SAAS,EAAE,EAAE,KAAKK,EAAY,IAAI,EACvDL,EAAM,IAAI,cAAc,EAC1B,OAGF,MAAMO,EAAaD,EAAU;AAAA,GAAM,KAAK,UAAU,YAAY,CAAC,MAAM,KAAK,IAAI,KAAKA,CAAO,GAAK;AAAA,GAAM,KAAK,UAAU,YAAY,CAAC,MAAM,KAAK,IAAI,YAAYD,CAAU,GAChKG,EAAUH,EAAW,SAAS,SAAS,EAAI,QAAU,MAE3D,QAAQG,CAAO,EAAED,CAAU,CAC7B,CAKA,gBAAiB,CACf,KAAK,OAAO,cAAgB,IAAI,KAChC,KAAK,OAASP,EAAM,IAAI,UAAU,EAAE,KAAK,SAAS,EAAE,SACpD,KAAK,OAAO,kBAAoB,KAAK,OAAO,cAAgB,KAAK,OAAO,WAEpE,KAAK,aACP,OAAO,KAAK,YAGd,KAAK,IACHA,EAAM,IAAI,eAAe,KAAK,SAAS,EAAE,EAAE,GAAG,KAAK,UAAU,YAAY,CAAC,WAAW,EACrF,GAAG,KAAK,UAAU,OAAO,CAAC,EAAE,YAAY,EAAI,KAAK,UAAU,MAAM,CAAC,CAAC,KAAK,KAAK,IAAI,aACnF,CACF,CAKA,cAAe,CACb,KAAK,OAAO,cAAgB,IAAI,KAChC,KAAK,OAASA,EAAM,IAAI,UAAU,EAAE,KAAK,SAAS,EAAE,OACpD,KAAK,OAAO,kBAAoB,KAAK,OAAO,cAAgB,KAAK,OAAO,WAExE,KAAK,IACHA,EAAM,IAAI,eAAe,KAAK,SAAS,EAAE,EAAE,GAAG,KAAK,UAAU,YAAY,CAAC,SAAS,EACnF,GAAG,KAAK,UAAU,OAAO,CAAC,EAAE,YAAY,EAAI,KAAK,UAAU,MAAM,CAAC,CAAC,KAAK,KAAK,IAAI,WACnF,CACF,CAKA,eAAgB,CAAE,CAKlB,eAAgB,CAAE,CAKlB,eAAgB,CACd,KAAK,OAAO,WAAa,IAAI,KAC7B,KAAK,OAASA,EAAM,IAAI,UAAU,EAAE,KAAK,SAAS,EAAE,QAEpD,KAAK,IACHA,EAAM,IAAI,eAAe,KAAK,SAAS,EAAE,EAAE,GAAG,KAAK,UAAU,YAAY,CAAC,UAAU,EACpF,GAAG,KAAK,UAAU,OAAO,CAAC,EAAE,YAAY,EAAI,KAAK,UAAU,MAAM,CAAC,CAAC,KAAK,KAAK,IAAI,YACnF,CACF,CAQA,SAASS,EAAM,CACb,OAAOT,EAAM,IAAIS,CAAI,CACvB,CAOA,SAASA,EAAMC,EAAO,CACpBV,EAAM,IAAIS,EAAMC,CAAK,CACvB,CAMA,YAAYD,EAAM,CAChBT,EAAM,OAAOS,CAAI,CACnB,CACF",
|
|
6
|
+
"names": ["uuidv4", "base_types", "State", "Base", "__name", "name", "base_type", "event_name", "message", "logMessage", "logType", "path", "value"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o=Object.defineProperty;var t=(e,s)=>o(e,"name",{value:s,configurable:!0});class c extends BroadcastChannel{static{t(this,"Broadcast")}constructor(s){super(s)}send(s){this.postMessage(s)}onReceive(s){this.onmessage=a=>{s(a.data)}}destroy(){this.close()}}export{c as default};
|
|
2
|
+
//# sourceMappingURL=broadcast.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/classes/events/broadcast.js"],
|
|
4
|
+
"sourcesContent": ["/**\n * Broadcast class provides a simplified wrapper around the BroadcastChannel API\n * for cross-context communication (e.g., between tabs, windows, workers).\n * \n * This class allows you to send and receive messages across different browsing contexts\n * that share the same origin. It encapsulates the creation and management of a BroadcastChannel,\n * providing a simplified API for sending and receiving messages.\n * \n * @class Broadcast\n * @extends BroadcastChannel\n */\nexport default class Broadcast extends BroadcastChannel {\n /**\n * Creates a new Broadcast instance for a named channel.\n * \n * @constructor\n * @param {string} channelName - The name of the broadcast channel to create or connect to.\n * Multiple Broadcast instances with the same channel name can communicate with each other.\n */\n constructor(channelName) {\n super(channelName);\n }\n\n /**\n * Sends data to all other contexts listening on this channel.\n * \n * @param {*} data - The data to broadcast. Can be any structured-cloneable value\n * (primitives, objects, arrays, etc.). Functions and DOM nodes cannot be sent.\n * @returns {void}\n */\n send(data) {\n this.postMessage(data);\n }\n\n /**\n * Registers a callback to handle incoming messages on this channel.\n * \n * @param {Function} callback - Function to call when a message is received.\n * Receives the message data as its only parameter.\n * @returns {void}\n */\n onReceive(callback) {\n this.onmessage = (event) => {\n callback(event.data);\n };\n }\n\n /**\n * Closes the broadcast channel and releases its resources.\n * After calling this method, the Broadcast instance can no longer send or receive messages.\n * \n * @returns {void}\n */\n destroy() {\n this.close();\n }\n}\n"],
|
|
5
|
+
"mappings": "+EAWA,MAAOA,UAAgC,gBAAiB,CAXxD,MAWwD,CAAAC,EAAA,kBAQtD,YAAYC,EAAa,CACvB,MAAMA,CAAW,CACnB,CASA,KAAKC,EAAM,CACT,KAAK,YAAYA,CAAI,CACvB,CASA,UAAUC,EAAU,CAClB,KAAK,UAAaC,GAAU,CAC1BD,EAASC,EAAM,IAAI,CACrB,CACF,CAQA,SAAU,CACR,KAAK,MAAM,CACb,CACF",
|
|
6
|
+
"names": ["Broadcast", "__name", "channelName", "data", "callback", "event"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var l=Object.defineProperty;var i=(h,t)=>l(h,"name",{value:t,configurable:!0});import{warnings as u}from"../../enums/index.js";import c from"./broadcast.js";class o extends EventTarget{static{i(this,"Event")}constructor(){super(),this.events={},this._listener_map=new Map}registerEvents(t){for(const e of Object.values(t))this.events[e]=new o}emit(t,e,s=!1,n=!0){const a=JSON.parse(JSON.stringify(e)),d=new CustomEvent(t,{detail:a,bubbles:s,cancelable:n}),p=this.dispatchEvent(d);try{const r=new c(t);r.send(a),r.destroy()}catch(r){console.warn(u.BROADCAST_FAILED,r)}return p}onBroadcast(t,e){const s=new c(t);return s.onReceive(e),s}onAny(t,e){this.on(t,e);const s=this.onBroadcast(t,e);return{event:this,broadcast:s}}on(t,e){const s=i(n=>{e(n.detail)},"wrapped_listener");return this._listener_map.set(e,s),this.addEventListener(t,s),this}once(t,e){const s=i(n=>{e(n.detail)},"wrapped_listener");return this.addEventListener(t,s,{once:!0}),this}off(t,e){if(this._listener_map&&this._listener_map.has(e)){const s=this._listener_map.get(e);this.removeEventListener(t,s),this._listener_map.delete(e)}return this}removeListener(t,e){return this.off(t,e)}}var w=o;export{w as default};
|
|
2
|
+
//# sourceMappingURL=event.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/classes/events/event.js"],
|
|
4
|
+
"sourcesContent": ["import { errors, warnings } from '../../enums/index.js';\nimport Broadcast from './broadcast.js';\n\n/**\n * Event class for micro-flow\n * Provides a simple event emitter implementation for workflow steps and state changes.\n *\n * This class is used for emitting and listening to events within workflows and steps.\n * For broadcasting events across multiple workflows or listeners, see the Broadcast class.\n */\nclass Event extends EventTarget {\n /**\n * Creates a new Event instance.\n * @constructor\n */\n constructor() {\n super();\n this.events = {};\n this._listener_map = new Map();\n }\n\n /**\n * Registers multiple events by creating Event instances for each event name.\n * @param {Object} event_names - An object containing event name constants.\n * @returns {void}\n */\n registerEvents(event_names) {\n for (const event_name of Object.values(event_names)) {\n this.events[event_name] = new Event();\n }\n }\n\n /**\n * Emits a custom event with optional data payload.\n * This method maintains API compatibility with EventEmitter while using CustomEvent.\n * @param {string} event_name - The name of the event to emit.\n * @param {*} [data] - Optional data to pass with the event in the detail property.\n * @param {boolean} [bubbles=false] - Whether the event should bubble up through the DOM.\n * @param {boolean} [cancelable=true] - Whether the event is cancelable.\n * @returns {boolean} True if the event was not cancelled, false if it was cancelled.\n */\n emit(event_name, data, bubbles = false, cancelable = true) {\n const workingData = JSON.parse(JSON.stringify(data));\n\n const custom_event = new CustomEvent(event_name, {\n detail: workingData,\n bubbles,\n cancelable\n });\n const result = this.dispatchEvent(custom_event);\n\n try {\n const channel = new Broadcast(event_name);\n channel.send(workingData);\n channel.destroy();\n } catch (e) {\n console.warn(warnings.BROADCAST_FAILED, e);\n }\n return result;\n }\n\n /**\n * Listen for broadcasts on a given event name (channel).\n * @param {string} event_name - The event name/channel to listen for.\n * @param {Function} listener - Callback for broadcasted data.\n * @returns {Broadcast} Returns the Broadcast instance for manual control.\n */\n onBroadcast(event_name, listener) {\n const channel = new Broadcast(event_name);\n channel.onReceive(listener);\n return channel;\n }\n\n /**\n * Listen for both local and broadcast events.\n * @param {string} event_name - The event name/channel to listen for.\n * @param {Function} listener - Callback for event data.\n * @returns {Object} Returns { event: this, broadcast: Broadcast instance }\n */\n onAny(event_name, listener) {\n this.on(event_name, listener);\n const broadcast = this.onBroadcast(event_name, listener);\n return { event: this, broadcast };\n }\n\n /**\n * Adds an event listener with EventEmitter-style API.\n * Maintains compatibility with the original API while using addEventListener.\n * @param {string} event_name - The name of the event to listen for.\n * @param {Function} listener - The callback function to execute when the event fires.\n * @returns {Event} Returns this for chaining.\n */\n on(event_name, listener) {\n const wrapped_listener = (event) => {\n // Call the listener with the detail (data) from CustomEvent\n listener(event.detail);\n };\n // Store the original listener reference for removeListener\n this._listener_map.set(listener, wrapped_listener);\n this.addEventListener(event_name, wrapped_listener);\n return this;\n }\n\n /**\n * Adds a one-time event listener with EventEmitter-style API.\n * @param {string} event_name - The name of the event to listen for.\n * @param {Function} listener - The callback function to execute when the event fires.\n * @returns {Event} Returns this for chaining.\n */\n once(event_name, listener) {\n const wrapped_listener = (event) => {\n listener(event.detail);\n };\n this.addEventListener(event_name, wrapped_listener, { once: true });\n return this;\n }\n\n /**\n * Removes an event listener with EventEmitter-style API.\n * @param {string} event_name - The name of the event.\n * @param {Function} listener - The callback function to remove.\n * @returns {Event} Returns this for chaining.\n */\n off(event_name, listener) {\n if (this._listener_map && this._listener_map.has(listener)) {\n const wrapped_listener = this._listener_map.get(listener);\n this.removeEventListener(event_name, wrapped_listener);\n this._listener_map.delete(listener);\n }\n return this;\n }\n\n /**\n * Alias for off() to maintain EventEmitter API compatibility.\n * @param {string} event_name - The name of the event.\n * @param {Function} listener - The callback function to remove.\n * @returns {Event} Returns this for chaining.\n */\n removeListener(event_name, listener) {\n return this.off(event_name, listener);\n }\n}\n\nexport default Event;\n"],
|
|
5
|
+
"mappings": "+EAAA,OAAiB,YAAAA,MAAgB,uBACjC,OAAOC,MAAe,iBAStB,MAAMC,UAAc,WAAY,CAVhC,MAUgC,CAAAC,EAAA,cAK9B,aAAc,CACZ,MAAM,EACN,KAAK,OAAS,CAAC,EACf,KAAK,cAAgB,IAAI,GAC3B,CAOA,eAAeC,EAAa,CAC1B,UAAWC,KAAc,OAAO,OAAOD,CAAW,EAChD,KAAK,OAAOC,CAAU,EAAI,IAAIH,CAElC,CAWA,KAAKG,EAAYC,EAAMC,EAAU,GAAOC,EAAa,GAAM,CACzD,MAAMC,EAAc,KAAK,MAAM,KAAK,UAAUH,CAAI,CAAC,EAE7CI,EAAe,IAAI,YAAYL,EAAY,CAC/C,OAAQI,EACR,QAAAF,EACA,WAAAC,CACF,CAAC,EACKG,EAAS,KAAK,cAAcD,CAAY,EAE9C,GAAI,CACF,MAAME,EAAU,IAAIX,EAAUI,CAAU,EACxCO,EAAQ,KAAKH,CAAW,EACxBG,EAAQ,QAAQ,CAClB,OAASC,EAAG,CACV,QAAQ,KAAKb,EAAS,iBAAkBa,CAAC,CAC3C,CACA,OAAOF,CACT,CAQA,YAAYN,EAAYS,EAAU,CAChC,MAAMF,EAAU,IAAIX,EAAUI,CAAU,EACxC,OAAAO,EAAQ,UAAUE,CAAQ,EACnBF,CACT,CAQA,MAAMP,EAAYS,EAAU,CAC1B,KAAK,GAAGT,EAAYS,CAAQ,EAC5B,MAAMC,EAAY,KAAK,YAAYV,EAAYS,CAAQ,EACvD,MAAO,CAAE,MAAO,KAAM,UAAAC,CAAU,CAClC,CASA,GAAGV,EAAYS,EAAU,CACvB,MAAME,EAAmBb,EAACc,GAAU,CAElCH,EAASG,EAAM,MAAM,CACvB,EAHyB,oBAKzB,YAAK,cAAc,IAAIH,EAAUE,CAAgB,EACjD,KAAK,iBAAiBX,EAAYW,CAAgB,EAC3C,IACT,CAQA,KAAKX,EAAYS,EAAU,CACzB,MAAME,EAAmBb,EAACc,GAAU,CAClCH,EAASG,EAAM,MAAM,CACvB,EAFyB,oBAGzB,YAAK,iBAAiBZ,EAAYW,EAAkB,CAAE,KAAM,EAAK,CAAC,EAC3D,IACT,CAQA,IAAIX,EAAYS,EAAU,CACxB,GAAI,KAAK,eAAiB,KAAK,cAAc,IAAIA,CAAQ,EAAG,CAC1D,MAAME,EAAmB,KAAK,cAAc,IAAIF,CAAQ,EACxD,KAAK,oBAAoBT,EAAYW,CAAgB,EACrD,KAAK,cAAc,OAAOF,CAAQ,CACpC,CACA,OAAO,IACT,CAQA,eAAeT,EAAYS,EAAU,CACnC,OAAO,KAAK,IAAIT,EAAYS,CAAQ,CACtC,CACF,CAEA,IAAOI,EAAQhB",
|
|
6
|
+
"names": ["warnings", "Broadcast", "Event", "__name", "event_names", "event_name", "data", "bubbles", "cancelable", "workingData", "custom_event", "result", "channel", "e", "listener", "broadcast", "wrapped_listener", "event", "event_default"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{default as a}from"./broadcast.js";import{default as r}from"./event.js";import{default as d}from"./state_event.js";import{default as p}from"./step_event.js";import{default as m}from"./workflow_event.js";export{a as Broadcast,r as Event,d as StateEvent,p as StepEvent,m as WorkflowEvent};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/classes/events/index.js"],
|
|
4
|
+
"sourcesContent": ["export { default as Broadcast } from './broadcast.js';\nexport { default as Event } from './event.js';\nexport { default as StateEvent } from './state_event.js';\nexport { default as StepEvent } from './step_event.js';\nexport { default as WorkflowEvent } from './workflow_event.js';\n"],
|
|
5
|
+
"mappings": "AAAA,OAAoB,WAAXA,MAA4B,iBACrC,OAAoB,WAAXA,MAAwB,aACjC,OAAoB,WAAXA,MAA6B,mBACtC,OAAoB,WAAXA,MAA4B,kBACrC,OAAoB,WAAXA,MAAgC",
|
|
6
|
+
"names": ["default"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var r=Object.defineProperty;var t=(e,s)=>r(e,"name",{value:s,configurable:!0});import{Event as n}from"./index.js";import{state_event_names as a}from"../../enums/index.js";class i extends n{static{t(this,"StateEvent")}event_names=a;constructor(){super(),this.registerStateEvents()}registerStateEvents(){this.registerEvents(this.event_names)}}export{i as default};
|
|
2
|
+
//# sourceMappingURL=state_event.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/classes/events/state_event.js"],
|
|
4
|
+
"sourcesContent": ["import { Event } from './index.js';\nimport { state_event_names } from '../../enums/index.js';\n\n/**\n * Manages state-specific events by extending the base Event class.\n * @class StateEvent\n * @extends Event\n */\nexport default class StateEvent extends Event {\n event_names = state_event_names;\n\n /**\n * Creates a new StateEvent instance and registers all state events.\n * @constructor\n */\n constructor() {\n super();\n this.registerStateEvents();\n }\n\n /**\n * Registers all state event names defined in the state_event_names enum.\n * @returns {void}\n */\n registerStateEvents() {\n this.registerEvents(this.event_names);\n }\n}\n"],
|
|
5
|
+
"mappings": "+EAAA,OAAS,SAAAA,MAAa,aACtB,OAAS,qBAAAC,MAAyB,uBAOlC,MAAOC,UAAiCF,CAAM,CAR9C,MAQ8C,CAAAG,EAAA,mBAC5C,YAAcF,EAMd,aAAc,CACZ,MAAM,EACN,KAAK,oBAAoB,CAC3B,CAMA,qBAAsB,CACpB,KAAK,eAAe,KAAK,WAAW,CACtC,CACF",
|
|
6
|
+
"names": ["Event", "state_event_names", "StateEvent", "__name"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var r=Object.defineProperty;var t=(e,s)=>r(e,"name",{value:s,configurable:!0});import{Event as n}from"./index.js";import{step_event_names as i}from"../../enums/index.js";class p extends n{static{t(this,"StepEvent")}event_names=i;constructor(){super(),this.registerStepEvents()}registerStepEvents(){this.registerEvents(this.event_names)}}export{p as default};
|
|
2
|
+
//# sourceMappingURL=step_event.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/classes/events/step_event.js"],
|
|
4
|
+
"sourcesContent": ["import { Event } from './index.js';\nimport { step_event_names } from '../../enums/index.js';\n\n/**\n * Manages step-specific events by extending the base Event class.\n * @class StepEvent\n * @extends Event\n */\nexport default class StepEvent extends Event {\n event_names = step_event_names;\n\n /**\n * Creates a new StepEvent instance and registers all step events.\n * @constructor\n */\n constructor() {\n super();\n this.registerStepEvents();\n }\n \n /**\n * Registers all step event names defined in the step_event_names enum.\n * @returns {void}\n */\n registerStepEvents() {\n this.registerEvents(this.event_names);\n }\n}\n"],
|
|
5
|
+
"mappings": "+EAAA,OAAS,SAAAA,MAAa,aACtB,OAAS,oBAAAC,MAAwB,uBAOjC,MAAOC,UAAgCF,CAAM,CAR7C,MAQ6C,CAAAG,EAAA,kBAC3C,YAAcF,EAMd,aAAc,CACZ,MAAM,EACN,KAAK,mBAAmB,CAC1B,CAMA,oBAAqB,CACnB,KAAK,eAAe,KAAK,WAAW,CACtC,CACF",
|
|
6
|
+
"names": ["Event", "step_event_names", "StepEvent", "__name"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var s=Object.defineProperty;var t=(e,r)=>s(e,"name",{value:r,configurable:!0});import{Event as o}from"./index.js";import{workflow_event_names as n}from"../../enums/index.js";class i extends o{static{t(this,"WorkflowEvent")}event_names=n;constructor(){super(),this.registerWorkflowEvents()}registerWorkflowEvents(){this.registerEvents(this.event_names)}}export{i as default};
|
|
2
|
+
//# sourceMappingURL=workflow_event.js.map
|