@ronaldroe/micro-flow 0.0.9 → 0.1.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/README.md CHANGED
@@ -1,19 +1,18 @@
1
1
  # Micro-Flow
2
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.
3
+ Micro-Flow is a simple, lightweight, cross platform (browser and runtime) logic orchestration library. Micro-Flow makes async logic flows first-class objects — named, observable, pauseable, and composable so a multi-step process is something you can reason about, monitor, and control, not just a wall of awaits.
4
4
 
5
5
  ## Features
6
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
7
+ - �️ **Observable** - Every step and logic flow emits lifecycle events (`STEP_FAILED`, `WORKFLOW_COMPLETE`, etc.) so you always know what's running, what finished, and what broke — no log-sprinkling required
8
+ - ⏸️ **Pauseable & Resumeable** - Suspend a running logic flow mid-pipeline (e.g. waiting on user input or an external signal) and resume it without losing state
9
+ - 🌿 **First-Class Branching** - `ConditionalStep` and `SwitchStep` keep branching logic out of your callables and in the logic flow structure where it belongs
10
+ - 🎯 **Fine-Grained Flow Control** - Break out of or skip steps in a logic flow dynamically at runtime
11
+ - 💾 **Shared State Singleton** - Steps communicate through a global `State` object with dot/bracket-notation path access — no threading data through function arguments
12
+ - 📢 **Cross-Tab/Worker Communication** - Events broadcast automatically via `BroadcastChannel`, reaching other tabs and workers with no extra wiring
13
+ - 🌐 **Universal** - Works in Node.js (≥18) and all modern browsers
14
+ - 🎨 **Framework Friendly** - Integrates seamlessly with React, Vue, your favorite framework, and vanilla JS
15
+ - ⚡ **Minimal Dependencies** - Lightweight and focused
17
16
 
18
17
  ## Installation
19
18
 
@@ -238,7 +237,7 @@ const step = new Step({
238
237
 
239
238
  Most step types accept a `callable` parameter. Callables are the individual actions a step can take.
240
239
 
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.
240
+ A callable can be any async function, another step, or even a whole workflow. That flexibility allows for everything from very simple logic flows to large, modularized flows broken down into logical units for execution.
242
241
 
243
242
  ### State Management
244
243
 
@@ -306,26 +305,24 @@ stateEvents.on('deleted', (data) => {
306
305
 
307
306
  ### Cross-Tab/Worker Communication
308
307
 
309
- Broadcast messages between browser tabs and windows or across workers in your favorite JS runtime:
308
+ Events broadcast automatically between browser tabs and windows or across workers when emitted, with no extra wiring needed:
310
309
 
311
310
  ```javascript
312
- import { Broadcast } from './micro-flow.js';
311
+ import { State } from './micro-flow.js';
313
312
 
314
- const broadcast = new Broadcast('my-channel');
313
+ // All events broadcast automatically via BroadcastChannel
314
+ const event = State.get('events.workflow');
315
315
 
316
- // Send messages to other tabs
317
- broadcast.send({ type: 'update', data: { userId: 123 } });
316
+ // Send event to other tabs
317
+ event.emit('my-event', { type: 'update', data: { userId: 123 } });
318
318
 
319
- // Receive messages from other tabs
320
- broadcast.onReceive((data) => {
319
+ // Receive events from other tabs
320
+ event.on('my-event', (data) => {
321
321
  console.log('Message from another tab:', data);
322
322
  if (data.type === 'update') {
323
323
  updateUI(data.data);
324
324
  }
325
325
  });
326
-
327
- // Clean up when done
328
- broadcast.destroy();
329
326
  ```
330
327
 
331
328
  ## Use Cases
@@ -475,7 +472,7 @@ Full documentation is available in the [docs](docs/) directory:
475
472
  - [WorkflowEvent API](docs/classes/events/workflow_event.md)
476
473
  - [StepEvent API](docs/classes/events/step_event.md)
477
474
  - [StateEvent API](docs/classes/events/state_event.md)
478
- - [Broadcast API](docs/classes/events/broadcast.md)
475
+
479
476
 
480
477
  **Enumerations:**
481
478
  - [Base Types](docs/enums/base_types.md)
@@ -492,36 +489,3 @@ Full documentation is available in the [docs](docs/) directory:
492
489
  - [Delay Types](docs/enums/delay_types.md)
493
490
  - [Loop Types](docs/enums/loop_types.md)
494
491
  - [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.
@@ -1,2 +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};
1
+ var l=Object.defineProperty;var a=(c,e)=>l(c,"name",{value:e,configurable:!0});import{warnings as p}from"../../enums/index.js";class o extends EventTarget{static{a(this,"Event")}constructor(){super(),this.events={},this._listener_map=new Map}registerEvents(e){for(const t of Object.values(e))this.events[t]=new o}emit(e,t,s=!1,n=!0){const i=JSON.parse(JSON.stringify(t)),h=new CustomEvent(e,{detail:i,bubbles:s,cancelable:n}),d=this.dispatchEvent(h);try{const r=new BroadcastChannel(e);r.postMessage(i),r.close()}catch(r){console.warn(p.BROADCAST_FAILED,r)}return d}onBroadcast(e,t){const s=new BroadcastChannel(e);return s.onmessage=n=>{t(n.data)},s.send=n=>{s.postMessage(n)},s.destroy=()=>{s.close()},s}onAny(e,t){this.on(e,t);const s=this.onBroadcast(e,t);return{event:this,broadcast:s}}on(e,t){const s=a(n=>{t(n.detail)},"wrapped_listener");return this._listener_map.set(t,s),this.addEventListener(e,s),this}once(e,t){const s=a(n=>{t(n.detail)},"wrapped_listener");return this.addEventListener(e,s,{once:!0}),this}off(e,t){if(this._listener_map&&this._listener_map.has(t)){const s=this._listener_map.get(t);this.removeEventListener(e,s),this._listener_map.delete(t)}return this}removeListener(e,t){return this.off(e,t)}}var v=o;export{v as default};
2
2
  //# sourceMappingURL=event.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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"]
4
+ "sourcesContent": ["import { errors, warnings } from '../../enums/index.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, it uses BroadcastChannel.\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 BroadcastChannel(event_name);\n channel.postMessage(workingData);\n channel.close();\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 {BroadcastChannel} Returns the channel with send() and destroy() aliases.\n */\n onBroadcast(event_name, listener) {\n const channel = new BroadcastChannel(event_name);\n channel.onmessage = (event) => {\n listener(event.data);\n };\n channel.send = (data) => {\n channel.postMessage(data);\n };\n channel.destroy = () => {\n channel.close();\n };\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: BroadcastChannel }\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,uBASjC,MAAMC,UAAc,WAAY,CAThC,MASgC,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,IAAI,iBAAiBP,CAAU,EAC/CO,EAAQ,YAAYH,CAAW,EAC/BG,EAAQ,MAAM,CAChB,OAASC,EAAG,CACV,QAAQ,KAAKZ,EAAS,iBAAkBY,CAAC,CAC3C,CACA,OAAOF,CACT,CAQA,YAAYN,EAAYS,EAAU,CAChC,MAAMF,EAAU,IAAI,iBAAiBP,CAAU,EAC/C,OAAAO,EAAQ,UAAaG,GAAU,CAC7BD,EAASC,EAAM,IAAI,CACrB,EACAH,EAAQ,KAAQN,GAAS,CACvBM,EAAQ,YAAYN,CAAI,CAC1B,EACAM,EAAQ,QAAU,IAAM,CACtBA,EAAQ,MAAM,CAChB,EACOA,CACT,CAQA,MAAMP,EAAYS,EAAU,CAC1B,KAAK,GAAGT,EAAYS,CAAQ,EAC5B,MAAME,EAAY,KAAK,YAAYX,EAAYS,CAAQ,EACvD,MAAO,CAAE,MAAO,KAAM,UAAAE,CAAU,CAClC,CASA,GAAGX,EAAYS,EAAU,CACvB,MAAMG,EAAmBd,EAACY,GAAU,CAElCD,EAASC,EAAM,MAAM,CACvB,EAHyB,oBAKzB,YAAK,cAAc,IAAID,EAAUG,CAAgB,EACjD,KAAK,iBAAiBZ,EAAYY,CAAgB,EAC3C,IACT,CAQA,KAAKZ,EAAYS,EAAU,CACzB,MAAMG,EAAmBd,EAACY,GAAU,CAClCD,EAASC,EAAM,MAAM,CACvB,EAFyB,oBAGzB,YAAK,iBAAiBV,EAAYY,EAAkB,CAAE,KAAM,EAAK,CAAC,EAC3D,IACT,CAQA,IAAIZ,EAAYS,EAAU,CACxB,GAAI,KAAK,eAAiB,KAAK,cAAc,IAAIA,CAAQ,EAAG,CAC1D,MAAMG,EAAmB,KAAK,cAAc,IAAIH,CAAQ,EACxD,KAAK,oBAAoBT,EAAYY,CAAgB,EACrD,KAAK,cAAc,OAAOH,CAAQ,CACpC,CACA,OAAO,IACT,CAQA,eAAeT,EAAYS,EAAU,CACnC,OAAO,KAAK,IAAIT,EAAYS,CAAQ,CACtC,CACF,CAEA,IAAOI,EAAQhB",
6
+ "names": ["warnings", "Event", "__name", "event_names", "event_name", "data", "bubbles", "cancelable", "workingData", "custom_event", "result", "channel", "e", "listener", "event", "broadcast", "wrapped_listener", "event_default"]
7
7
  }
@@ -1,2 +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};
1
+ import{default as o}from"./event.js";import{default as f}from"./state_event.js";import{default as l}from"./step_event.js";import{default as d}from"./workflow_event.js";export{o as Event,f as StateEvent,l as StepEvent,d as WorkflowEvent};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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",
4
+ "sourcesContent": ["export { 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,MAAwB,aACjC,OAAoB,WAAXA,MAA6B,mBACtC,OAAoB,WAAXA,MAA4B,kBACrC,OAAoB,WAAXA,MAAgC",
6
6
  "names": ["default"]
7
7
  }
@@ -1,2 +1,2 @@
1
- var T=Object.defineProperty;var m=(w,e)=>T(w,"name",{value:e,configurable:!0});import{errors as f,warnings as _}from"../enums/errors.js";import{StepEvent as y,WorkflowEvent as b,StateEvent as g}from"./events/index.js";import{base_types as h,conditional_step_comparators as O,state_event_names as A,step_event_names as v,step_statuses as k,step_types as j,sub_step_types as d,workflow_event_names as R,workflow_statuses as S}from"../enums/index.js";const E={messages:{errors:f,warnings:_},statuses:{workflow:S,step:k},event_names:{workflow:R,step:v,state:A},events:{workflow:new b,step:new y,state:new g},types:{base_types:h,step_types:j,sub_step_types:d},workflows:{},conditional_step_comparators:O};let s={...E};const n=s.events,c=s.event_names;class i{static{m(this,"State")}static delete(e){if(!e)throw new Error(f.INVALID_STATE_PATH);const a=i.parsePath(e);let r=s;for(let t=0;t<a.length-1;t++){const o=a[t];if(!Object.prototype.hasOwnProperty.call(r,o)||typeof r[o]!="object")return;r=r[o]}delete r[a[a.length-1]],n.state.emit(c.state.DELETED,{state:s})}static async each(e,a){const r=i.get(e);if(Array.isArray(r))for(const[t,o]of r.entries())n.state.emit(c.state.EACH,{state:s}),await a(o,t);else if(typeof r=="object"&&Object.prototype.toString.call(r)==="[object Object]")for(const t of Object.keys(r))n.state.emit(c.state.EACH,{state:s}),await a(r[t],t);else throw new Error(f.VALUE_NOT_ITERABLE)}static freeze(){const e=Object.freeze(s);return n.state.emit(c.state.FROZEN,{state:s}),e}static get(e,a=null,r=null){let t=s;if(!e||["*",""].includes(e))return n.state.emit(c.state.GET,{state:t??a}),t;if(t=i.getFromPropertyPath(e,!1)??a,r)try{switch(r){case"string":t=String(t);break;case"number":t=Number(t);break;case"boolean":t=!!t;break;default:break}}catch(o){console.error("Error converting state value: ",o)}return n.state.emit(c.state.GET,{state:t}),t??a}static getFromPropertyPath(e,a=!0){const r=i.parsePath(e);let t=s;for(const o of r)if(t&&Object.prototype.hasOwnProperty.call(t,o))t=t[o];else return;return a&&n.state.emit(c.state.GET_FROM_PROPERTY_PATH,{state:s}),t}static getState(){return n.state.emit(c.state.GET_STATE,{state:s}),s}static merge(e){return s={...s,...e},n.state.emit(c.state.MERGE,{state:s}),s}static parsePath(e){const a=e.match(/[^.[\]]+|(?<=\[)([^\]]+)(?=\])/g);return a?a.map(r=>r.replace(/^['"]|['"]$/g,"")):[]}static reset(){return s={...E},n.state.emit(c.state.RESET,{state:s}),s}static set(e,a){if(!e)throw new Error(f.INVALID_STATE_PATH);n.state.emit(c.state.SET,{state:s}),i.setToPropertyPath(e,a,!1)}static setToPropertyPath(e,a,r=!0){const t=i.parsePath(e);let o=s;for(let l=0;l<t.length-1;l++){const p=t[l],u=t[l+1];if(!Object.prototype.hasOwnProperty.call(o,p)||typeof o[p]!="object"){const P=/^\d+$/.test(u);o[p]=P?[]:{}}o=o[p]}r&&n.state.emit(c.state.SET_TO_PROPERTY_PATH,{state:s}),o[t[t.length-1]]=a}}var L=i;export{L as default};
1
+ var T=Object.defineProperty;var m=(E,e)=>T(E,"name",{value:e,configurable:!0});import{errors as f,warnings as _}from"../enums/errors.js";import{StepEvent as y,WorkflowEvent as b,StateEvent as g}from"./events/index.js";import{base_types as h,conditional_step_comparators as O,state_event_names as A,step_event_names as v,step_statuses as k,step_types as j,sub_step_types as d,workflow_event_names as R,workflow_statuses as S}from"../enums/index.js";const w={messages:{errors:f,warnings:_},statuses:{workflow:S,step:k},event_names:{workflow:R,step:v,state:A},events:{workflow:new b,step:new y,state:new g},types:{base_types:h,step_types:j,sub_step_types:d},workflows:{},conditional_step_comparators:O};let s={...w};const n=s.events,c=s.event_names;class i{static{m(this,"State")}static delete(e){if(!e)throw new Error(f.INVALID_STATE_PATH);const a=i.parsePath(e);let r=s;for(let t=0;t<a.length-1;t++){const o=a[t];if(!Object.prototype.hasOwnProperty.call(r,o)||typeof r[o]!="object")return;r=r[o]}delete r[a[a.length-1]],n.state.emit(c.state.DELETED,{state:s})}static async each(e,a){const r=i.get(e);if(Array.isArray(r))for(const[t,o]of r.entries())n.state.emit(c.state.EACH,{state:s}),await a(o,t);else if(typeof r=="object"&&Object.prototype.toString.call(r)==="[object Object]")for(const t of Object.keys(r))n.state.emit(c.state.EACH,{state:s}),await a(r[t],t);else throw new Error(f.VALUE_NOT_ITERABLE)}static freeze(){const e=Object.freeze(s);return n.state.emit(c.state.FROZEN,{state:s}),e}static get(e,a=null,r=null){let t=s;if(!e||["*",""].includes(e))return n.state.emit(c.state.GET,{state:t??a}),t;if(t=i.getFromPropertyPath(e,!1)??a,r)try{switch(r){case"string":t=String(t);break;case"number":t=Number(t);break;case"boolean":t=!!t;break;default:break}}catch(o){console.error("Error converting state value: ",o)}return n.state.emit(c.state.GET,{state:t}),t??a}static getFromPropertyPath(e,a=!0){const r=i.parsePath(e);let t=s;for(const o of r)if(t&&Object.prototype.hasOwnProperty.call(t,o))t=t[o];else return;return a&&n.state.emit(c.state.GET_FROM_PROPERTY_PATH,{state:s}),t}static getState(){return n.state.emit(c.state.GET_STATE,{state:s}),s}static merge(e){return s={...s,...e},n.state.emit(c.state.MERGE,{state:s}),s}static parsePath(e){const a=e.match(/[^.[\]]+|(?<=\[)([^\]]+)(?=\])/g);return a?a.map(r=>r.replace(/^['"]|['"]$/g,"")):[]}static reset(){return s={...w,workflows:{}},n.state.emit(c.state.RESET,{state:s}),s}static set(e,a){if(!e)throw new Error(f.INVALID_STATE_PATH);n.state.emit(c.state.SET,{state:s}),i.setToPropertyPath(e,a,!1)}static setToPropertyPath(e,a,r=!0){const t=i.parsePath(e);let o=s;for(let l=0;l<t.length-1;l++){const p=t[l],u=t[l+1];if(!Object.prototype.hasOwnProperty.call(o,p)||typeof o[p]!="object"){const P=/^\d+$/.test(u);o[p]=P?[]:{}}o=o[p]}r&&n.state.emit(c.state.SET_TO_PROPERTY_PATH,{state:s}),o[t[t.length-1]]=a}}var L=i;export{L as default};
2
2
  //# sourceMappingURL=state.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/classes/state.js"],
4
- "sourcesContent": ["import { errors, warnings } from '../enums/errors.js';\nimport { StepEvent, WorkflowEvent, StateEvent } from './events/index.js';\nimport {\n base_types,\n conditional_step_comparators,\n state_event_names,\n step_event_names,\n step_statuses,\n step_types,\n sub_step_types,\n workflow_event_names,\n workflow_statuses,\n} from '../enums/index.js';\n\nconst defaultState = {\n messages: {\n errors,\n warnings,\n },\n statuses: {\n workflow: workflow_statuses,\n step: step_statuses\n },\n event_names: {\n workflow: workflow_event_names,\n step: step_event_names,\n state: state_event_names,\n },\n events: {\n workflow: new WorkflowEvent(),\n step: new StepEvent(),\n state: new StateEvent(),\n },\n types: {\n base_types,\n step_types,\n sub_step_types,\n },\n workflows: {},\n conditional_step_comparators\n};\n\nlet state = { ...defaultState };\n\n// Module-level shortcuts for events and event_names\nconst events = state.events;\nconst event_names = state.event_names;\n\n/**\n * Singleton class representing the global state for workflows, steps, and processes.\n * Provides methods for managing state with getter/setter functionality, nested path access,\n * and immutability options. The state is shared across all workflow and step instances.\n * \n * @class State\n */\nclass State {\n /**\n * Deletes a state property using dot-notation or bracket-notation path access.\n * \n * @param {string} path - The path of the state property to delete (e.g., \"user.profile.email\" or \"users[0].email\").\n * @returns {void}\n * @throws {Error} Throws if path is empty or invalid.\n */\n static delete(path) {\n if (!path) {\n throw new Error(errors.INVALID_STATE_PATH);\n }\n \n const parts = State.parsePath(path);\n let current = state;\n \n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n \n if (!Object.prototype.hasOwnProperty.call(current, part) || typeof current[part] !== 'object') {\n return;\n }\n \n current = current[part];\n }\n \n delete current[parts[parts.length - 1]];\n\n events.state.emit(event_names.state.DELETED, { state });\n }\n\n /**\n * Iterates over a collection (array or object) located at the specified state path,\n * executing a callback function for each item.\n * \n * @param {string} path - The path of the state property to iterate over.\n * @param {Function} callback - The function to execute for each item in the collection.\n * @throws {Error} Throws if the state property at the path is not an array or object.\n */\n static async each(path, callback) {\n const collection = State.get(path);\n \n if (Array.isArray(collection)) {\n for (const [index, item] of collection.entries()) {\n events.state.emit(event_names.state.EACH, { state });\n await callback(item, index);\n }\n } else if (\n typeof collection === 'object' &&\n Object.prototype.toString.call(collection) === '[object Object]'\n ) {\n for (const key of Object.keys(collection)) {\n events.state.emit(event_names.state.EACH, { state });\n await callback(collection[key], key);\n }\n } else {\n throw new Error(errors.VALUE_NOT_ITERABLE);\n }\n }\n\n /**\n * Freezes the entire state object, making it immutable.\n * @returns {void}\n */\n static freeze() {\n const frozenState = Object.freeze(state);\n events.state.emit(event_names.state.FROZEN, { state });\n return frozenState;\n }\n\n /**\n * Gets the value of a state property using dot-notation or bracket-notation path access.\n * \n * @param {string} path - The path of the state property to get. Supports both dot notation\n * (e.g., \"user.profile.name\") and bracket notation (e.g., \"users[0].name\" or \"data['key-name']\").\n * Special values:\n * - Falsy values (null, undefined, false, \"\"): Returns entire state object\n * - \"*\": Returns entire state object\n * @param {*} [defaultValue=null] - Default value to return if the path doesn't exist.\n * @param {string} [type='string'] - The output type to convert the value to.\n * Supported types: \"string\", \"number\", \"boolean\".\n * @returns {*} The value of the state property, or defaultValue if not found. null if not found\n * and no defaultValue provided.\n * @throws {Error} Throws if the value cannot be converted to the specified type.\n */\n static get(path, defaultValue = null, type = null) {\n let gotten = state;\n if (!path || ['*', ''].includes(path)) {\n events.state.emit(event_names.state.GET, { state: gotten ?? defaultValue });\n return gotten;\n }\n\n gotten = State.getFromPropertyPath(path, false) ?? defaultValue;\n\n if (type) {\n try {\n switch (type) {\n case 'string':\n gotten = String(gotten);\n break;\n case 'number':\n gotten = Number(gotten);\n break;\n case 'boolean':\n gotten = Boolean(gotten);\n break;\n default:\n break;\n }\n } catch (error) {\n console.error(\"Error converting state value: \", error);\n }\n }\n\n events.state.emit(event_names.state.GET, { state: gotten });\n\n return gotten ?? defaultValue;\n }\n\n /**\n * Resolves a nested property path within the state object.\n * Supports both dot notation and bracket notation.\n * \n * @param {string} path - The path to the property (e.g., \"user.profile.name\", \"users[0].name\", \"data['key-name']\").\n * @param {boolean} [emit=true] - Whether to emit the GET_FROM_PROPERTY_PATH event.\n * @returns {*} The value at the specified path, or undefined if not found.\n */\n static getFromPropertyPath(path, emit = true) {\n const parts = State.parsePath(path);\n let current = state;\n\n for (const part of parts) {\n if (current && Object.prototype.hasOwnProperty.call(current, part)) {\n current = current[part];\n } else {\n return undefined;\n }\n }\n\n if (emit) {\n events.state.emit(event_names.state.GET_FROM_PROPERTY_PATH, { state });\n }\n\n return current;\n }\n\n /**\n * Gets the entire state object.\n * @returns {Object} The entire state object.\n */\n static getState() {\n events.state.emit(event_names.state.GET_STATE, { state });\n return state;\n }\n\n /**\n * Merges an object into the current State.\n * @param {Object} newState - The object to merge into the current State.\n * @returns {object} The updated state object.\n */\n static merge(newState) {\n state = { ...state, ...newState };\n events.state.emit(event_names.state.MERGE, { state });\n return state;\n }\n\n /**\n * Parses a property path string into an array of keys, supporting both dot notation\n * and bracket notation.\n * \n * @param {string} path - The path to parse (e.g., \"user.profile.name\", \"users[0].name\", \"data['key-name']\").\n * @returns {string[]} Array of property keys.\n */\n static parsePath(path) {\n const matches = path.match(/[^.[\\]]+|(?<=\\[)([^\\]]+)(?=\\])/g);\n \n if (!matches) {\n return [];\n }\n\n return matches.map(part => part.replace(/^['\"]|['\"]$/g, ''));\n }\n\n /**\n * Resets the state to its default values.\n * @returns {object} The reset state object.\n */\n static reset() {\n state = { ...defaultState };\n events.state.emit(event_names.state.RESET, { state });\n return state;\n }\n\n /**\n * Sets the value of a state property using dot-notation or bracket-notation path access.\n * Creates intermediate objects if they don't exist.\n * \n * @param {string} path - The path of the state property to set. Supports both dot notation\n * (e.g., \"user.profile.name\") and bracket notation (e.g., \"users[0].name\" or \"data['key-name']\").\n * @param {*} value - The value to set for the state property.\n * @returns {void}\n * @throws {Error} Throws if path is empty or invalid.\n */\n static set(path, value) {\n if (!path) {\n throw new Error(errors.INVALID_STATE_PATH);\n }\n\n events.state.emit(event_names.state.SET, { state });\n\n State.setToPropertyPath(path, value, false);\n }\n\n /**\n * Sets a nested property value within the state object based on a path.\n * Supports both dot notation and bracket notation. Creates intermediate objects/arrays as needed.\n * \n * @param {string} path - The path to the property (e.g., \"user.profile.name\", \"users[0].name\", \"data['key-name']\").\n * @param {*} value - The value to set at the specified path.\n * @param {boolean} [emit=true] - Whether to emit the SET_TO_PROPERTY_PATH event.\n */\n static setToPropertyPath(path, value, emit = true) {\n const parts = State.parsePath(path);\n let current = state;\n \n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n const nextPart = parts[i + 1];\n \n if (!Object.prototype.hasOwnProperty.call(current, part) || typeof current[part] !== 'object') {\n // Determine if next part is an array index (numeric)\n const isNextPartNumeric = /^\\d+$/.test(nextPart);\n current[part] = isNextPartNumeric ? [] : {};\n }\n current = current[part];\n }\n \n if (emit) {\n events.state.emit(event_names.state.SET_TO_PROPERTY_PATH, { state });\n }\n\n current[parts[parts.length - 1]] = value;\n }\n}\n\nexport default State;\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { errors, warnings } from '../enums/errors.js';\nimport { StepEvent, WorkflowEvent, StateEvent } from './events/index.js';\nimport {\n base_types,\n conditional_step_comparators,\n state_event_names,\n step_event_names,\n step_statuses,\n step_types,\n sub_step_types,\n workflow_event_names,\n workflow_statuses,\n} from '../enums/index.js';\n\nconst defaultState = {\n messages: {\n errors,\n warnings,\n },\n statuses: {\n workflow: workflow_statuses,\n step: step_statuses\n },\n event_names: {\n workflow: workflow_event_names,\n step: step_event_names,\n state: state_event_names,\n },\n events: {\n workflow: new WorkflowEvent(),\n step: new StepEvent(),\n state: new StateEvent(),\n },\n types: {\n base_types,\n step_types,\n sub_step_types,\n },\n workflows: {},\n conditional_step_comparators\n};\n\nlet state = { ...defaultState };\n\n// Module-level shortcuts for events and event_names\nconst events = state.events;\nconst event_names = state.event_names;\n\n/**\n * Singleton class representing the global state for workflows, steps, and processes.\n * Provides methods for managing state with getter/setter functionality, nested path access,\n * and immutability options. The state is shared across all workflow and step instances.\n * \n * @class State\n */\nclass State {\n /**\n * Deletes a state property using dot-notation or bracket-notation path access.\n * \n * @param {string} path - The path of the state property to delete (e.g., \"user.profile.email\" or \"users[0].email\").\n * @returns {void}\n * @throws {Error} Throws if path is empty or invalid.\n */\n static delete(path) {\n if (!path) {\n throw new Error(errors.INVALID_STATE_PATH);\n }\n \n const parts = State.parsePath(path);\n let current = state;\n \n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n \n if (!Object.prototype.hasOwnProperty.call(current, part) || typeof current[part] !== 'object') {\n return;\n }\n \n current = current[part];\n }\n \n delete current[parts[parts.length - 1]];\n\n events.state.emit(event_names.state.DELETED, { state });\n }\n\n /**\n * Iterates over a collection (array or object) located at the specified state path,\n * executing a callback function for each item.\n * \n * @param {string} path - The path of the state property to iterate over.\n * @param {Function} callback - The function to execute for each item in the collection.\n * @throws {Error} Throws if the state property at the path is not an array or object.\n */\n static async each(path, callback) {\n const collection = State.get(path);\n \n if (Array.isArray(collection)) {\n for (const [index, item] of collection.entries()) {\n events.state.emit(event_names.state.EACH, { state });\n await callback(item, index);\n }\n } else if (\n typeof collection === 'object' &&\n Object.prototype.toString.call(collection) === '[object Object]'\n ) {\n for (const key of Object.keys(collection)) {\n events.state.emit(event_names.state.EACH, { state });\n await callback(collection[key], key);\n }\n } else {\n throw new Error(errors.VALUE_NOT_ITERABLE);\n }\n }\n\n /**\n * Freezes the entire state object, making it immutable.\n * @returns {void}\n */\n static freeze() {\n const frozenState = Object.freeze(state);\n events.state.emit(event_names.state.FROZEN, { state });\n return frozenState;\n }\n\n /**\n * Gets the value of a state property using dot-notation or bracket-notation path access.\n * \n * @param {string} path - The path of the state property to get. Supports both dot notation\n * (e.g., \"user.profile.name\") and bracket notation (e.g., \"users[0].name\" or \"data['key-name']\").\n * Special values:\n * - Falsy values (null, undefined, false, \"\"): Returns entire state object\n * - \"*\": Returns entire state object\n * @param {*} [defaultValue=null] - Default value to return if the path doesn't exist.\n * @param {string} [type='string'] - The output type to convert the value to.\n * Supported types: \"string\", \"number\", \"boolean\".\n * @returns {*} The value of the state property, or defaultValue if not found. null if not found\n * and no defaultValue provided.\n * @throws {Error} Throws if the value cannot be converted to the specified type.\n */\n static get(path, defaultValue = null, type = null) {\n let gotten = state;\n if (!path || ['*', ''].includes(path)) {\n events.state.emit(event_names.state.GET, { state: gotten ?? defaultValue });\n return gotten;\n }\n\n gotten = State.getFromPropertyPath(path, false) ?? defaultValue;\n\n if (type) {\n try {\n switch (type) {\n case 'string':\n gotten = String(gotten);\n break;\n case 'number':\n gotten = Number(gotten);\n break;\n case 'boolean':\n gotten = Boolean(gotten);\n break;\n default:\n break;\n }\n } catch (error) {\n console.error(\"Error converting state value: \", error);\n }\n }\n\n events.state.emit(event_names.state.GET, { state: gotten });\n\n return gotten ?? defaultValue;\n }\n\n /**\n * Resolves a nested property path within the state object.\n * Supports both dot notation and bracket notation.\n * \n * @param {string} path - The path to the property (e.g., \"user.profile.name\", \"users[0].name\", \"data['key-name']\").\n * @param {boolean} [emit=true] - Whether to emit the GET_FROM_PROPERTY_PATH event.\n * @returns {*} The value at the specified path, or undefined if not found.\n */\n static getFromPropertyPath(path, emit = true) {\n const parts = State.parsePath(path);\n let current = state;\n\n for (const part of parts) {\n if (current && Object.prototype.hasOwnProperty.call(current, part)) {\n current = current[part];\n } else {\n return undefined;\n }\n }\n\n if (emit) {\n events.state.emit(event_names.state.GET_FROM_PROPERTY_PATH, { state });\n }\n\n return current;\n }\n\n /**\n * Gets the entire state object.\n * @returns {Object} The entire state object.\n */\n static getState() {\n events.state.emit(event_names.state.GET_STATE, { state });\n return state;\n }\n\n /**\n * Merges an object into the current State.\n * @param {Object} newState - The object to merge into the current State.\n * @returns {object} The updated state object.\n */\n static merge(newState) {\n state = { ...state, ...newState };\n events.state.emit(event_names.state.MERGE, { state });\n return state;\n }\n\n /**\n * Parses a property path string into an array of keys, supporting both dot notation\n * and bracket notation.\n * \n * @param {string} path - The path to parse (e.g., \"user.profile.name\", \"users[0].name\", \"data['key-name']\").\n * @returns {string[]} Array of property keys.\n */\n static parsePath(path) {\n const matches = path.match(/[^.[\\]]+|(?<=\\[)([^\\]]+)(?=\\])/g);\n \n if (!matches) {\n return [];\n }\n\n return matches.map(part => part.replace(/^['\"]|['\"]$/g, ''));\n }\n\n /**\n * Resets the state to its default values.\n * @returns {object} The reset state object.\n */\n static reset() {\n state = { \n ...defaultState,\n workflows: {}, // Always create fresh to avoid shared reference mutation\n };\n events.state.emit(event_names.state.RESET, { state });\n return state;\n }\n\n /**\n * Sets the value of a state property using dot-notation or bracket-notation path access.\n * Creates intermediate objects if they don't exist.\n * \n * @param {string} path - The path of the state property to set. Supports both dot notation\n * (e.g., \"user.profile.name\") and bracket notation (e.g., \"users[0].name\" or \"data['key-name']\").\n * @param {*} value - The value to set for the state property.\n * @returns {void}\n * @throws {Error} Throws if path is empty or invalid.\n */\n static set(path, value) {\n if (!path) {\n throw new Error(errors.INVALID_STATE_PATH);\n }\n\n events.state.emit(event_names.state.SET, { state });\n\n State.setToPropertyPath(path, value, false);\n }\n\n /**\n * Sets a nested property value within the state object based on a path.\n * Supports both dot notation and bracket notation. Creates intermediate objects/arrays as needed.\n * \n * @param {string} path - The path to the property (e.g., \"user.profile.name\", \"users[0].name\", \"data['key-name']\").\n * @param {*} value - The value to set at the specified path.\n * @param {boolean} [emit=true] - Whether to emit the SET_TO_PROPERTY_PATH event.\n */\n static setToPropertyPath(path, value, emit = true) {\n const parts = State.parsePath(path);\n let current = state;\n \n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n const nextPart = parts[i + 1];\n \n if (!Object.prototype.hasOwnProperty.call(current, part) || typeof current[part] !== 'object') {\n // Determine if next part is an array index (numeric)\n const isNextPartNumeric = /^\\d+$/.test(nextPart);\n current[part] = isNextPartNumeric ? [] : {};\n }\n current = current[part];\n }\n \n if (emit) {\n events.state.emit(event_names.state.SET_TO_PROPERTY_PATH, { state });\n }\n\n current[parts[parts.length - 1]] = value;\n }\n}\n\nexport default State;\n"],
5
+ "mappings": "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",
6
6
  "names": ["errors", "warnings", "StepEvent", "WorkflowEvent", "StateEvent", "base_types", "conditional_step_comparators", "state_event_names", "step_event_names", "step_statuses", "step_types", "sub_step_types", "workflow_event_names", "workflow_statuses", "defaultState", "state", "events", "event_names", "State", "__name", "path", "parts", "current", "i", "part", "callback", "collection", "index", "item", "key", "frozenState", "defaultValue", "type", "gotten", "error", "emit", "newState", "matches", "value", "nextPart", "isNextPartNumeric", "state_default"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/classes/steps/delay_step.js"],
4
- "sourcesContent": ["import Step from './step.js';\nimport { delay_types, step_types } from '../../enums/index.js';\nimport schedule from 'node-schedule';\nimport { addMilliseconds } from 'date-fns';\n\n/**\n * DelayStep class for introducing delays in workflow execution.\n * Supports both absolute and relative delays.\n * @class DelayStep\n * @extends Step\n */\nexport default class DelayStep extends Step {\n static step_name = 'delay';\n\n /**\n * Creates a new DelayStep instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {Date|string} [options.absolute_timestamp=new Date()] - Absolute timestamp to delay until.\n * @param {number} [options.relative_delay_ms=0] - Relative delay in milliseconds.\n * @param {string} [options.delay_type=delay_types.RELATIVE] - Type of delay ('absolute' or 'relative').\n */\n constructor({\n name,\n absolute_timestamp = new Date(),\n relative_delay_ms = 0,\n delay_type = delay_types.RELATIVE\n }) {\n super({\n name,\n step_type: step_types.DELAY,\n });\n\n this.delay_type = delay_type;\n this.absolute_timestamp = new Date(absolute_timestamp);\n this.relative_delay_ms = relative_delay_ms;\n\n this.callable = this[delay_type].bind(this);\n }\n\n /**\n * Executes an absolute delay until the specified timestamp. If the timestamp is in the past, it continues immediately.\n * @returns {Promise<Object>} Resolves with a message object when delay completes.\n */\n async absolute() {\n const now = new Date();\n\n if (this.absolute_timestamp.getTime() <= now.getTime()) {\n this.log(\n this.getState('events.step.event_names.DELAY_STEP_ABSOLUTE_COMPLETE'),\n `No delay for step: ${this.name}. Continuing.`\n );\n return this;\n }\n\n return this.delay(this.absolute_timestamp);\n }\n\n /** Schedules a delay until the specified date and time.\n * @param {Date} delay_until - The date and time to delay until.\n * @returns {Promise<DelayStep>} Resolves with the DelayStep instance when delay completes.\n */\n async delay(delay_until) {\n return new Promise((resolve) => {\n this.log(\n this.getState(\n `events.step.event_names.DELAY_STEP_${this.delay_type.toUpperCase()}_SCHEDULED`\n ),\n `Delay scheduled for step: ${this.name} until ${delay_until.toISOString()}`\n );\n\n const job = schedule.scheduleJob(delay_until, () => {\n this.log(\n this.getState(\n `events.step.event_names.DELAY_STEP_${this.delay_type.toUpperCase()}_COMPLETE`\n ),\n `Delay complete for step: ${this.name}. Continuing.`\n );\n resolve(this);\n });\n\n this.scheduled_job = job;\n });\n }\n\n /**\n * Executes a relative delay for the specified duration. If the delay duration is zero or negative, it continues immediately.\n * @returns {Promise<Object>} Resolves with a message object when delay completes.\n */\n async relative() {\n if (this.relative_delay_ms <= 0) {\n this.log(\n this.getState('events.step.event_names.DELAY_STEP_RELATIVE_COMPLETE'),\n `No delay for step: ${this.name}. Continuing.`\n );\n return this;\n }\n\n const delay_until = addMilliseconds(new Date(), this.relative_delay_ms);\n\n return this.delay(delay_until);\n }\n}\n"],
4
+ "sourcesContent": ["import Step from './step.js';\nimport { delay_types, step_types } from '../../enums/index.js';\nimport schedule from 'node-schedule';\nimport { addMilliseconds } from 'date-fns';\n\n/**\n * DelayStep class for introducing delays in workflow execution.\n * Supports both absolute and relative delays.\n * @class DelayStep\n * @extends Step\n */\nexport default class DelayStep extends Step {\n static step_name = 'delay';\n\n /**\n * Creates a new DelayStep instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {Date|string} [options.absolute_timestamp=new Date()] - Absolute timestamp to delay until.\n * @param {number} [options.relative_delay_ms=0] - Relative delay in milliseconds.\n * @param {string} [options.delay_type=delay_types.RELATIVE] - Type of delay ('absolute' or 'relative').\n */\n constructor({\n name,\n absolute_timestamp = new Date(),\n relative_delay_ms = 0,\n delay_type = delay_types.RELATIVE\n }) {\n super({\n name,\n step_type: step_types.DELAY,\n });\n\n this.delay_type = delay_type;\n this.absolute_timestamp = new Date(absolute_timestamp);\n this.relative_delay_ms = relative_delay_ms;\n\n this.callable = this[delay_type].bind(this);\n }\n\n /**\n * Executes an absolute delay until the specified timestamp. If the timestamp is in the past, it continues immediately.\n * @returns {Promise<DelayStep>} Resolves with the DelayStep instance when delay completes.\n */\n async absolute() {\n const now = new Date();\n\n if (this.absolute_timestamp.getTime() <= now.getTime()) {\n this.log(\n this.getState('events.step.event_names.DELAY_STEP_ABSOLUTE_COMPLETE'),\n `No delay for step: ${this.name}. Continuing.`\n );\n return this;\n }\n\n return this.delay(this.absolute_timestamp);\n }\n\n /** Schedules a delay until the specified date and time.\n * @param {Date} delay_until - The date and time to delay until.\n * @returns {Promise<DelayStep>} Resolves with the DelayStep instance when delay completes.\n */\n async delay(delay_until) {\n return new Promise((resolve) => {\n this.log(\n this.getState(\n `events.step.event_names.DELAY_STEP_${this.delay_type.toUpperCase()}_SCHEDULED`\n ),\n `Delay scheduled for step: ${this.name} until ${delay_until.toISOString()}`\n );\n\n const job = schedule.scheduleJob(delay_until, () => {\n this.log(\n this.getState(\n `events.step.event_names.DELAY_STEP_${this.delay_type.toUpperCase()}_COMPLETE`\n ),\n `Delay complete for step: ${this.name}. Continuing.`\n );\n resolve(this);\n });\n\n this.scheduled_job = job;\n });\n }\n\n /**\n * Executes a relative delay for the specified duration. If the delay duration is zero or negative, it continues immediately.\n * @returns {Promise<DelayStep>} Resolves with the DelayStep instance when delay completes.\n */\n async relative() {\n if (this.relative_delay_ms <= 0) {\n this.log(\n this.getState('events.step.event_names.DELAY_STEP_RELATIVE_COMPLETE'),\n `No delay for step: ${this.name}. Continuing.`\n );\n return this;\n }\n\n const delay_until = addMilliseconds(new Date(), this.relative_delay_ms);\n\n return this.delay(delay_until);\n }\n}\n"],
5
5
  "mappings": "+EAAA,OAAOA,MAAU,YACjB,OAAS,eAAAC,EAAa,cAAAC,MAAkB,uBACxC,OAAOC,MAAc,gBACrB,OAAS,mBAAAC,MAAuB,WAQhC,MAAOC,UAAgCL,CAAK,CAX5C,MAW4C,CAAAM,EAAA,kBAC1C,OAAO,UAAY,QAUnB,YAAY,CACV,KAAAC,EACA,mBAAAC,EAAqB,IAAI,KACzB,kBAAAC,EAAoB,EACpB,WAAAC,EAAaT,EAAY,QAC3B,EAAG,CACD,MAAM,CACJ,KAAAM,EACA,UAAWL,EAAW,KACxB,CAAC,EAED,KAAK,WAAaQ,EAClB,KAAK,mBAAqB,IAAI,KAAKF,CAAkB,EACrD,KAAK,kBAAoBC,EAEzB,KAAK,SAAW,KAAKC,CAAU,EAAE,KAAK,IAAI,CAC5C,CAMA,MAAM,UAAW,CACf,MAAMC,EAAM,IAAI,KAEhB,OAAI,KAAK,mBAAmB,QAAQ,GAAKA,EAAI,QAAQ,GACnD,KAAK,IACH,KAAK,SAAS,sDAAsD,EACpE,sBAAsB,KAAK,IAAI,eACjC,EACO,MAGF,KAAK,MAAM,KAAK,kBAAkB,CAC3C,CAMA,MAAM,MAAMC,EAAa,CACvB,OAAO,IAAI,QAASC,GAAY,CAC9B,KAAK,IACH,KAAK,SACH,sCAAsC,KAAK,WAAW,YAAY,CAAC,YACrE,EACA,6BAA6B,KAAK,IAAI,UAAUD,EAAY,YAAY,CAAC,EAC3E,EAEA,MAAME,EAAMX,EAAS,YAAYS,EAAa,IAAM,CAClD,KAAK,IACH,KAAK,SACH,sCAAsC,KAAK,WAAW,YAAY,CAAC,WACrE,EACA,4BAA4B,KAAK,IAAI,eACvC,EACAC,EAAQ,IAAI,CACd,CAAC,EAED,KAAK,cAAgBC,CACvB,CAAC,CACH,CAMA,MAAM,UAAW,CACf,GAAI,KAAK,mBAAqB,EAC5B,YAAK,IACH,KAAK,SAAS,sDAAsD,EACpE,sBAAsB,KAAK,IAAI,eACjC,EACO,KAGT,MAAMF,EAAcR,EAAgB,IAAI,KAAQ,KAAK,iBAAiB,EAEtE,OAAO,KAAK,MAAMQ,CAAW,CAC/B,CACF",
6
6
  "names": ["Step", "delay_types", "step_types", "schedule", "addMilliseconds", "DelayStep", "__name", "name", "absolute_timestamp", "relative_delay_ms", "delay_type", "now", "delay_until", "resolve", "job"]
7
7
  }
@@ -1,2 +1,2 @@
1
- var n=Object.defineProperty;var s=(o,t)=>n(o,"name",{value:t,configurable:!0});import{LogicStep as i}from"./index.js";import l from"../../enums/flow_control_types.js";import"../../enums/index.js";class a extends i{static{s(this,"FlowControlStep")}static step_name="flow_control";constructor({conditional:t={subject:null,operator:null,value:null},name:r,flow_control_type:e=l.BREAK}){if(super({name:r,conditional:t}),!Object.values(l).includes(e))throw new Error(`Invalid flow control type: ${e}`);this.flow_control_type=e,this.callable=this.shouldFlowControl.bind(this)}async shouldFlowControl(){return this.checkCondition()?(this.log(this.getState("events.step.event_names.CONDITIONAL_TRUE_BRANCH_EXECUTED"),`Break condition met for step: ${this.name}`),this.setParentWorkflowValue(this.parentWorkflowId,`should_${this.flow_control_type}`,!0),!0):(this.log(this.getState("events.step.event_names.CONDITIONAL_FALSE_BRANCH_EXECUTED"),`Break condition not met for step: ${this.name}`),this.setParentWorkflowValue(this.parentWorkflowId,`should_${this.flow_control_type}`,!1),!1)}}export{a as default};
1
+ var n=Object.defineProperty;var s=(o,t)=>n(o,"name",{value:t,configurable:!0});import i from"./logic_step.js";import l from"../../enums/flow_control_types.js";import"../../enums/index.js";class a extends i{static{s(this,"FlowControlStep")}static step_name="flow_control";constructor({conditional:t={subject:null,operator:null,value:null},name:r,flow_control_type:e=l.BREAK}){if(super({name:r,conditional:t}),!Object.values(l).includes(e))throw new Error(`Invalid flow control type: ${e}`);this.flow_control_type=e,this.callable=this.shouldFlowControl.bind(this)}async shouldFlowControl(){return this.checkCondition()?(this.log(this.getState("events.step.event_names.CONDITIONAL_TRUE_BRANCH_EXECUTED"),`Break condition met for step: ${this.name}`),this.setParentWorkflowValue(this.parentWorkflowId,`should_${this.flow_control_type}`,!0),!0):(this.log(this.getState("events.step.event_names.CONDITIONAL_FALSE_BRANCH_EXECUTED"),`Break condition not met for step: ${this.name}`),this.setParentWorkflowValue(this.parentWorkflowId,`should_${this.flow_control_type}`,!1),!1)}}export{a as default};
2
2
  //# sourceMappingURL=flow_control_step.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/classes/steps/flow_control_step.js"],
4
- "sourcesContent": ["import { LogicStep } from './index.js';\nimport flow_control_types from '../../enums/flow_control_types.js';\nimport { conditional_step_comparators } from '../../enums/index.js';\n\n/**\n * FlowControlStep class for controlling workflow execution flow (break, continue, skip, pause).\n * @class FlowControlStep\n * @extends LogicStep\n */\nexport default class FlowControlStep extends LogicStep {\n static step_name = 'flow_control';\n\n /**\n * Creates a new FlowControlStep instance.\n * @param {Object} options - Configuration options.\n * @param {Object} [options.conditional] - Conditional configuration.\n * @param {*} [options.conditional.subject] - Subject to evaluate.\n * @param {conditional_step_comparators|string} [options.conditional.operator] - Comparison operator.\n * @param {*} [options.conditional.value] - Value to compare against.\n * @param {string} [options.name] - Name of the step.\n * @param {string} [options.flow_control_type=flow_control_types.BREAK] - Type of flow control.\n * @throws {Error} Throws if flow_control_type is invalid.\n */\n constructor({\n conditional = {\n subject: null,\n operator: null,\n value: null,\n },\n name,\n flow_control_type = flow_control_types.BREAK,\n }) {\n super({\n name,\n conditional\n });\n\n if (!Object.values(flow_control_types).includes(flow_control_type)) {\n throw new Error(`Invalid flow control type: ${flow_control_type}`);\n }\n\n this.flow_control_type = flow_control_type;\n this.callable = this.shouldFlowControl.bind(this);\n }\n\n /**\n * Evaluates the condition and sets the appropriate flow control flag.\n * @async\n * @returns {Promise<boolean>} True if the flow control should be activated.\n */\n async shouldFlowControl() {\n if (this.checkCondition()) {\n this.log(\n this.getState('events.step.event_names.CONDITIONAL_TRUE_BRANCH_EXECUTED'),\n `Break condition met for step: ${this.name}`\n );\n this.setParentWorkflowValue(this.parentWorkflowId, `should_${this.flow_control_type}`, true);\n\n return true;\n } else {\n this.log(\n this.getState('events.step.event_names.CONDITIONAL_FALSE_BRANCH_EXECUTED'),\n `Break condition not met for step: ${this.name}`\n );\n this.setParentWorkflowValue(this.parentWorkflowId, `should_${this.flow_control_type}`, false);\n\n return false;\n }\n }\n}\n"],
5
- "mappings": "+EAAA,OAAS,aAAAA,MAAiB,aAC1B,OAAOC,MAAwB,oCAC/B,MAA6C,uBAO7C,MAAOC,UAAsCF,CAAU,CATvD,MASuD,CAAAG,EAAA,wBACrD,OAAO,UAAY,eAanB,YAAY,CACV,YAAAC,EAAc,CACZ,QAAS,KACT,SAAU,KACV,MAAO,IACT,EACA,KAAAC,EACA,kBAAAC,EAAoBL,EAAmB,KACzC,EAAG,CAMD,GALA,MAAM,CACJ,KAAAI,EACA,YAAAD,CACF,CAAC,EAEG,CAAC,OAAO,OAAOH,CAAkB,EAAE,SAASK,CAAiB,EAC/D,MAAM,IAAI,MAAM,8BAA8BA,CAAiB,EAAE,EAGnE,KAAK,kBAAoBA,EACzB,KAAK,SAAW,KAAK,kBAAkB,KAAK,IAAI,CAClD,CAOA,MAAM,mBAAoB,CACxB,OAAI,KAAK,eAAe,GACtB,KAAK,IACH,KAAK,SAAS,0DAA0D,EACxE,iCAAiC,KAAK,IAAI,EAC5C,EACA,KAAK,uBAAuB,KAAK,iBAAkB,UAAU,KAAK,iBAAiB,GAAI,EAAI,EAEpF,KAEP,KAAK,IACH,KAAK,SAAS,2DAA2D,EACzE,qCAAqC,KAAK,IAAI,EAChD,EACA,KAAK,uBAAuB,KAAK,iBAAkB,UAAU,KAAK,iBAAiB,GAAI,EAAK,EAErF,GAEX,CACF",
4
+ "sourcesContent": ["import LogicStep from './logic_step.js';\nimport flow_control_types from '../../enums/flow_control_types.js';\nimport { conditional_step_comparators } from '../../enums/index.js';\n\n/**\n * FlowControlStep class for controlling workflow execution flow (break or skip).\n * @class FlowControlStep\n * @extends LogicStep\n */\nexport default class FlowControlStep extends LogicStep {\n static step_name = 'flow_control';\n\n /**\n * Creates a new FlowControlStep instance.\n * @param {Object} options - Configuration options.\n * @param {Object} [options.conditional] - Conditional configuration.\n * @param {*} [options.conditional.subject] - Subject to evaluate.\n * @param {conditional_step_comparators|string} [options.conditional.operator] - Comparison operator.\n * @param {*} [options.conditional.value] - Value to compare against.\n * @param {string} [options.name] - Name of the step.\n * @param {string} [options.flow_control_type=flow_control_types.BREAK] - Type of flow control.\n * @throws {Error} Throws if flow_control_type is invalid.\n */\n constructor({\n conditional = {\n subject: null,\n operator: null,\n value: null,\n },\n name,\n flow_control_type = flow_control_types.BREAK,\n }) {\n super({\n name,\n conditional\n });\n\n if (!Object.values(flow_control_types).includes(flow_control_type)) {\n throw new Error(`Invalid flow control type: ${flow_control_type}`);\n }\n\n this.flow_control_type = flow_control_type;\n this.callable = this.shouldFlowControl.bind(this);\n }\n\n /**\n * Evaluates the condition and sets the appropriate flow control flag.\n * @async\n * @returns {Promise<boolean>} True if the flow control should be activated.\n */\n async shouldFlowControl() {\n if (this.checkCondition()) {\n this.log(\n this.getState('events.step.event_names.CONDITIONAL_TRUE_BRANCH_EXECUTED'),\n `Break condition met for step: ${this.name}`\n );\n this.setParentWorkflowValue(this.parentWorkflowId, `should_${this.flow_control_type}`, true);\n\n return true;\n } else {\n this.log(\n this.getState('events.step.event_names.CONDITIONAL_FALSE_BRANCH_EXECUTED'),\n `Break condition not met for step: ${this.name}`\n );\n this.setParentWorkflowValue(this.parentWorkflowId, `should_${this.flow_control_type}`, false);\n\n return false;\n }\n }\n}\n"],
5
+ "mappings": "+EAAA,OAAOA,MAAe,kBACtB,OAAOC,MAAwB,oCAC/B,MAA6C,uBAO7C,MAAOC,UAAsCF,CAAU,CATvD,MASuD,CAAAG,EAAA,wBACrD,OAAO,UAAY,eAanB,YAAY,CACV,YAAAC,EAAc,CACZ,QAAS,KACT,SAAU,KACV,MAAO,IACT,EACA,KAAAC,EACA,kBAAAC,EAAoBL,EAAmB,KACzC,EAAG,CAMD,GALA,MAAM,CACJ,KAAAI,EACA,YAAAD,CACF,CAAC,EAEG,CAAC,OAAO,OAAOH,CAAkB,EAAE,SAASK,CAAiB,EAC/D,MAAM,IAAI,MAAM,8BAA8BA,CAAiB,EAAE,EAGnE,KAAK,kBAAoBA,EACzB,KAAK,SAAW,KAAK,kBAAkB,KAAK,IAAI,CAClD,CAOA,MAAM,mBAAoB,CACxB,OAAI,KAAK,eAAe,GACtB,KAAK,IACH,KAAK,SAAS,0DAA0D,EACxE,iCAAiC,KAAK,IAAI,EAC5C,EACA,KAAK,uBAAuB,KAAK,iBAAkB,UAAU,KAAK,iBAAiB,GAAI,EAAI,EAEpF,KAEP,KAAK,IACH,KAAK,SAAS,2DAA2D,EACzE,qCAAqC,KAAK,IAAI,EAChD,EACA,KAAK,uBAAuB,KAAK,iBAAkB,UAAU,KAAK,iBAAiB,GAAI,EAAK,EAErF,GAEX,CACF",
6
6
  "names": ["LogicStep", "flow_control_types", "FlowControlStep", "__name", "conditional", "name", "flow_control_type"]
7
7
  }
@@ -1,2 +1,2 @@
1
- import{default as o}from"./case.js";import{default as r}from"./conditional_step.js";import{default as p}from"./delay_step.js";import{default as d}from"./flow_control_step.js";import{default as m}from"./logic_step.js";import{default as x}from"./loop_step.js";import{default as i}from"./step.js";import{default as C}from"./switch_step.js";export{o as Case,r as ConditionalStep,p as DelayStep,d as FlowControlStep,m as LogicStep,x as LoopStep,i as Step,C as SwitchStep};
1
+ import{default as o}from"./step.js";import{default as r}from"./logic_step.js";import{default as p}from"./case.js";import{default as d}from"./conditional_step.js";import{default as m}from"./delay_step.js";import{default as x}from"./flow_control_step.js";import{default as i}from"./loop_step.js";import{default as C}from"./switch_step.js";export{p as Case,d as ConditionalStep,m as DelayStep,x as FlowControlStep,r as LogicStep,i as LoopStep,o as Step,C as SwitchStep};
2
2
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/classes/steps/index.js"],
4
- "sourcesContent": ["export { default as Case } from './case.js';\nexport { default as ConditionalStep } from './conditional_step.js';\nexport { default as DelayStep } from './delay_step.js';\nexport { default as FlowControlStep } from './flow_control_step.js';\nexport { default as LogicStep } from './logic_step.js';\nexport { default as LoopStep } from './loop_step.js';\nexport { default as Step } from './step.js';\nexport { default as SwitchStep } from './switch_step.js';\n"],
5
- "mappings": "AAAA,OAAoB,WAAXA,MAAuB,YAChC,OAAoB,WAAXA,MAAkC,wBAC3C,OAAoB,WAAXA,MAA4B,kBACrC,OAAoB,WAAXA,MAAkC,yBAC3C,OAAoB,WAAXA,MAA4B,kBACrC,OAAoB,WAAXA,MAA2B,iBACpC,OAAoB,WAAXA,MAAuB,YAChC,OAAoB,WAAXA,MAA6B",
4
+ "sourcesContent": ["export { default as Step } from './step.js';\nexport { default as LogicStep } from './logic_step.js';\nexport { default as Case } from './case.js';\nexport { default as ConditionalStep } from './conditional_step.js';\nexport { default as DelayStep } from './delay_step.js';\nexport { default as FlowControlStep } from './flow_control_step.js';\nexport { default as LoopStep } from './loop_step.js';\nexport { default as SwitchStep } from './switch_step.js';\n"],
5
+ "mappings": "AAAA,OAAoB,WAAXA,MAAuB,YAChC,OAAoB,WAAXA,MAA4B,kBACrC,OAAoB,WAAXA,MAAuB,YAChC,OAAoB,WAAXA,MAAkC,wBAC3C,OAAoB,WAAXA,MAA4B,kBACrC,OAAoB,WAAXA,MAAkC,yBAC3C,OAAoB,WAAXA,MAA2B,iBACpC,OAAoB,WAAXA,MAA6B",
6
6
  "names": ["default"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/classes/steps/logic_step.js"],
4
- "sourcesContent": ["import Step from './step.js';\nimport { conditional_step_comparators, step_types } from '../../enums/index.js';\n\n/**\n * LogicStep class for conditional logic operations.\n * @class LogicStep\n * @extends Step\n */\nexport default class LogicStep extends Step {\n static step_name = 'logic';\n\n /**\n * Creates a new LogicStep instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {Object} [options.conditional] - Conditional configuration.\n * @param {*} [options.conditional.subject] - Subject to evaluate.\n * @param {conditional_step_comparators|string} [options.conditional.operator] - Comparison operator.\n * @param {*} [options.conditional.value] - Value to compare against.\n * @param {Function} [options.callable=async () => {}] - Function to execute.\n */\n constructor({\n name,\n callable = async () => {},\n conditional = {\n operator: null,\n subject: null,\n value: null,\n },\n }) {\n super({\n name,\n base_type: step_types.LOGIC,\n callable\n });\n\n this.setConditional(conditional);\n }\n\n /**\n * Evaluates the conditional expression.\n * @returns {boolean} True if the condition is met.\n * @throws {Error} Throws if operator is unknown.\n */\n checkCondition() {\n const subject = this.conditional.subject;\n const operator = this.conditional.operator;\n const value = this.conditional.value;\n\n switch (operator) {\n case this.getState('conditional_step_comparators.STRICT_EQUALS'):\n case this.getState('conditional_step_comparators.SIGN_STRICT_EQUALS'):\n return subject === value;\n case this.getState('conditional_step_comparators.SIGN_EQUALS'):\n case this.getState('conditional_step_comparators.EQUALS'):\n return subject == value;\n case this.getState('conditional_step_comparators.NOT_EQUALS'):\n case this.getState('conditional_step_comparators.SIGN_NOT_EQUALS'):\n return subject != value;\n case this.getState('conditional_step_comparators.STRICT_NOT_EQUALS'):\n case this.getState('conditional_step_comparators.SIGN_STRICT_NOT_EQUALS'):\n return subject !== value;\n case this.getState('conditional_step_comparators.GREATER_THAN'):\n case this.getState('conditional_step_comparators.SIGN_GREATER_THAN'):\n return subject > value;\n case this.getState('conditional_step_comparators.LESS_THAN'):\n case this.getState('conditional_step_comparators.SIGN_LESS_THAN'):\n return subject < value;\n case this.getState('conditional_step_comparators.GREATER_THAN_OR_EQUAL'):\n case this.getState('conditional_step_comparators.SIGN_GREATER_THAN_OR_EQUAL'):\n return subject >= value;\n case this.getState('conditional_step_comparators.LESS_THAN_OR_EQUAL'):\n case this.getState('conditional_step_comparators.SIGN_LESS_THAN_OR_EQUAL'):\n return subject <= value;\n case this.getState('conditional_step_comparators.STRING_CONTAINS'):\n case this.getState('conditional_step_comparators.STRING_INCLUDES'):\n case this.getState('conditional_step_comparators.ARRAY_CONTAINS'):\n case this.getState('conditional_step_comparators.ARRAY_INCLUDES'):\n case this.getState('conditional_step_comparators.IN'):\n return (Array.isArray(subject) || typeof subject === 'string') && subject.includes(value);\n case this.getState('conditional_step_comparators.STRING_NOT_CONTAINS'):\n case this.getState('conditional_step_comparators.STRING_NOT_INCLUDES'):\n case this.getState('conditional_step_comparators.ARRAY_NOT_CONTAINS'):\n case this.getState('conditional_step_comparators.ARRAY_NOT_INCLUDES'):\n case this.getState('conditional_step_comparators.NOT_IN'):\n return (Array.isArray(subject) || typeof subject === 'string') && !subject.includes(value);\n case this.getState('conditional_step_comparators.EMPTY'):\n return subject === '' || subject === null || subject === undefined || subject.length === 0;\n case this.getState('conditional_step_comparators.NOT_EMPTY'):\n return subject !== '' && subject !== null && subject !== undefined && subject.length > 0;\n case this.getState('conditional_step_comparators.REGEX_MATCH'):\n if (typeof value !== 'string') {\n throw new Error(`Regex input must be a string.`);\n }\n const regex = new RegExp(value);\n return regex.test(subject);\n case this.getState('conditional_step_comparators.REGEX_NOT_MATCH'):\n if (typeof value !== 'string') {\n throw new Error(`Regex input must be a string.`);\n }\n const notMatchRegex = new RegExp(value);\n return !notMatchRegex.test(subject);\n case this.getState('conditional_step_comparators.STRING_STARTS_WITH'):\n return typeof subject === 'string' && typeof value === 'string' && subject.startsWith(value);\n case this.getState('conditional_step_comparators.STRING_ENDS_WITH'):\n return typeof subject === 'string' && typeof value === 'string' && subject.endsWith(value);\n case this.getState('conditional_step_comparators.NULLISH'):\n return subject === null || subject === undefined;\n case this.getState('conditional_step_comparators.NOT_NULLISH'):\n return subject !== null && subject !== undefined;\n case this.getState('conditional_step_comparators.IS_TYPE'):\n return typeof subject === value;\n case this.getState('conditional_step_comparators.IS_NOT_TYPE'):\n return typeof subject !== value;\n case this.getState('conditional_step_comparators.CUSTOM_FUNCTION'):\n if (typeof value !== 'function') {\n throw new Error(`Invalid custom function: ${value}`);\n }\n return value(subject);\n default:\n throw new Error(`Unknown operator: ${operator}`);\n }\n }\n\n /**\n * Checks if the conditional configuration is valid.\n * @returns {boolean} True if conditional is valid.\n */\n conditionalIsValid() {\n return (\n this.conditional.subject !== null &&\n this.conditional.subject !== undefined &&\n this.conditional.operator !== null &&\n this.conditional.operator !== undefined &&\n this.conditional.value !== null &&\n this.conditional.value !== undefined\n );\n }\n\n /**\n * Sets the conditional properties.\n * @param {Object} conditional - Conditional configuration object.\n * @throws {Error} Throws if conditional is invalid.\n */\n setConditional(conditional) {\n this.conditional = { subject: conditional.subject, operator: conditional.operator, value: conditional.value };\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import Step from './step.js';\nimport { conditional_step_comparators, step_types } from '../../enums/index.js';\n\n/**\n * LogicStep class for conditional logic operations.\n * @class LogicStep\n * @extends Step\n */\nexport default class LogicStep extends Step {\n static step_name = 'logic';\n\n /**\n * Creates a new LogicStep instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {Object} [options.conditional] - Conditional configuration.\n * @param {*} [options.conditional.subject] - Subject to evaluate.\n * @param {conditional_step_comparators|string} [options.conditional.operator] - Comparison operator.\n * @param {*} [options.conditional.value] - Value to compare against.\n * @param {Function} [options.callable=async () => {}] - Function to execute.\n */\n constructor({\n name,\n callable = async () => {},\n conditional = {\n operator: null,\n subject: null,\n value: null,\n },\n }) {\n super({\n name,\n base_type: step_types.LOGIC,\n callable\n });\n\n this.setConditional(conditional);\n }\n\n /**\n * Evaluates the conditional expression.\n * @returns {boolean} True if the condition is met.\n * @throws {Error} Throws if operator is unknown.\n */\n checkCondition() {\n const subject = this.conditional.subject;\n const operator = this.conditional.operator;\n const value = this.conditional.value;\n\n switch (operator) {\n case this.getState('conditional_step_comparators.STRICT_EQUALS'):\n case this.getState('conditional_step_comparators.SIGN_STRICT_EQUALS'):\n return subject === value;\n case this.getState('conditional_step_comparators.SIGN_EQUALS'):\n case this.getState('conditional_step_comparators.EQUALS'):\n return subject == value;\n case this.getState('conditional_step_comparators.NOT_EQUALS'):\n case this.getState('conditional_step_comparators.SIGN_NOT_EQUALS'):\n return subject != value;\n case this.getState('conditional_step_comparators.STRICT_NOT_EQUALS'):\n case this.getState('conditional_step_comparators.SIGN_STRICT_NOT_EQUALS'):\n return subject !== value;\n case this.getState('conditional_step_comparators.GREATER_THAN'):\n case this.getState('conditional_step_comparators.SIGN_GREATER_THAN'):\n return subject > value;\n case this.getState('conditional_step_comparators.LESS_THAN'):\n case this.getState('conditional_step_comparators.SIGN_LESS_THAN'):\n return subject < value;\n case this.getState('conditional_step_comparators.GREATER_THAN_OR_EQUAL'):\n case this.getState('conditional_step_comparators.SIGN_GREATER_THAN_OR_EQUAL'):\n return subject >= value;\n case this.getState('conditional_step_comparators.LESS_THAN_OR_EQUAL'):\n case this.getState('conditional_step_comparators.SIGN_LESS_THAN_OR_EQUAL'):\n return subject <= value;\n case this.getState('conditional_step_comparators.STRING_CONTAINS'):\n case this.getState('conditional_step_comparators.STRING_INCLUDES'):\n case this.getState('conditional_step_comparators.ARRAY_CONTAINS'):\n case this.getState('conditional_step_comparators.ARRAY_INCLUDES'):\n case this.getState('conditional_step_comparators.IN'):\n return (Array.isArray(subject) || typeof subject === 'string') && subject.includes(value);\n case this.getState('conditional_step_comparators.STRING_NOT_CONTAINS'):\n case this.getState('conditional_step_comparators.STRING_NOT_INCLUDES'):\n case this.getState('conditional_step_comparators.ARRAY_NOT_CONTAINS'):\n case this.getState('conditional_step_comparators.ARRAY_NOT_INCLUDES'):\n case this.getState('conditional_step_comparators.NOT_IN'):\n return (Array.isArray(subject) || typeof subject === 'string') && !subject.includes(value);\n case this.getState('conditional_step_comparators.EMPTY'):\n return subject === '' || subject === null || subject === undefined || subject.length === 0;\n case this.getState('conditional_step_comparators.NOT_EMPTY'):\n return subject !== '' && subject !== null && subject !== undefined && subject.length > 0;\n case this.getState('conditional_step_comparators.REGEX_MATCH'):\n if (typeof value !== 'string') {\n throw new Error(`Regex input must be a string.`);\n }\n const regex = new RegExp(value);\n return regex.test(subject);\n case this.getState('conditional_step_comparators.REGEX_NOT_MATCH'):\n if (typeof value !== 'string') {\n throw new Error(`Regex input must be a string.`);\n }\n const notMatchRegex = new RegExp(value);\n return !notMatchRegex.test(subject);\n case this.getState('conditional_step_comparators.STRING_STARTS_WITH'):\n return typeof subject === 'string' && typeof value === 'string' && subject.startsWith(value);\n case this.getState('conditional_step_comparators.STRING_ENDS_WITH'):\n return typeof subject === 'string' && typeof value === 'string' && subject.endsWith(value);\n case this.getState('conditional_step_comparators.NULLISH'):\n return subject === null || subject === undefined;\n case this.getState('conditional_step_comparators.NOT_NULLISH'):\n return subject !== null && subject !== undefined;\n case this.getState('conditional_step_comparators.IS_TYPE'):\n return typeof subject === value;\n case this.getState('conditional_step_comparators.IS_NOT_TYPE'):\n return typeof subject !== value;\n case this.getState('conditional_step_comparators.CUSTOM_FUNCTION'):\n if (typeof value !== 'function') {\n throw new Error(`Invalid custom function: ${value}`);\n }\n return value(subject);\n default:\n throw new Error(`Unknown operator: ${operator}`);\n }\n }\n\n /**\n * Checks if the conditional configuration is valid.\n * @returns {boolean} True if conditional is valid.\n */\n conditionalIsValid() {\n return (\n this.conditional.subject !== null &&\n this.conditional.subject !== undefined &&\n this.conditional.operator !== null &&\n this.conditional.operator !== undefined &&\n this.conditional.value !== null &&\n this.conditional.value !== undefined\n );\n }\n\n /**\n * Sets the conditional properties.\n * @param {Object} conditional - Conditional configuration object.\n */\n setConditional(conditional) {\n this.conditional = { subject: conditional.subject, operator: conditional.operator, value: conditional.value };\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["Step", "step_types", "LogicStep", "__name", "name", "callable", "conditional", "subject", "operator", "value"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/classes/steps/loop_step.js"],
4
- "sourcesContent": ["import { loop_types, step_types } from '../../enums/index.js';\nimport LogicStep from './logic_step.js';\nimport { conditional_step_comparators } from '../../enums/index.js';\n\n/**\n * LoopStep class for executing loops within a workflow.\n * @class LoopStep\n * @extends LogicStep\n */\nexport default class LoopStep extends LogicStep {\n static step_name = step_types.LOOP;\n\n /**\n * Creates a new LoopStep instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {Array|Iterable|Function} options.iterable - Iterable to loop over or function returning an iterable. Required for 'for_each' and 'generator' loops.\n * @param {Function} [options.callable=async () => {}] - Function to execute for each iteration.\n * @param {Object} [options.conditional] - Conditional configuration for while loops. Required for 'while' loops.\n * @param {*} [options.conditional.subject] - Subject to evaluate.\n * @param {conditional_step_comparators|string} [options.conditional.operator] - Comparison operator.\n * @param {*} [options.conditional.value] - Value to compare against.\n * @param {string} [options.loop_type=loop_types.FOR_EACH] - Type of loop ('for', 'for_each', 'while', or 'generator').\n * @param {number} [options.max_iterations=1000] - Maximum number of iterations to prevent infinite loops.\n */\n constructor({\n name,\n iterable,\n callable = async () => {},\n conditional = {\n operator: null,\n subject: null,\n value: null,\n },\n loop_type = loop_types.FOR_EACH,\n iterations = 0,\n max_iterations = 1000,\n }) {\n super({ name, conditional });\n this.iterable = iterable;\n this.loop_type = loop_type;\n this.iterations = iterations > max_iterations ? max_iterations : iterations;\n this.max_iterations = max_iterations;\n this.results = [];\n this.current_item = null;\n\n this.callable = this[`${loop_type}_loop`].bind(this);\n\n // When this.callable is set, it binds the callable function to this instance\n // so that it can access instance properties like current_item.\n // Because we're using a local method instead, we bind it here.\n this.callable_type = this.getCallableType(callable);\n this._callable = this.callable_type === 'function'\n ? callable.bind(this)\n : callable.execute.bind(callable);\n }\n\n /**\n * Executes a generator/async generator and appends yielded values to results.\n * @throws {Error} If the callable is not a generator or async generator function.\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async generator() {\n if (!this._callable.constructor.name.includes('Generator')) {\n throw new Error('Iterable must be a generator function for generator loops');\n }\n\n let iterations = 0;\n for (const item of await this._callable()) {\n this.results.push(item);\n\n if (++iterations >= this.max_iterations) {\n break;\n }\n }\n\n return {\n message: `Generator loop ${this.name} completed after ${iterations} iterations`,\n result: this.results\n };\n }\n\n /**\n * Executes a for loop calling the callable for a set number of iterations\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async for_loop() {\n let i = 0;\n for (; i < this.iterations; i++) {\n this.results.push(await this._callable());\n }\n\n return {\n message: `For loop ${this.name} completed after ${i} iterations`,\n result: this.results\n };\n }\n\n /**\n * Executes the callable for each item in the iterable.\n * @throws {Error} If the iterable is not provided.\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async for_each_loop() {\n if (!this.iterable) {\n throw new Error('Iterable is required for for_each loops');\n }\n\n if (typeof this.iterable === 'function') {\n this.iterable = this.iterable();\n }\n\n let iterations = 0;\n for (const item of this.iterable) {\n iterations++;\n this.current_item = item;\n this.results.push(await this._callable());\n }\n\n return {\n message: `For each loop ${this.name} completed after ${iterations} iterations`,\n result: this.results\n };\n }\n\n /**\n * Executes the callable while the condition is true.\n * @throws {Error} If the conditional is not valid.\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async while_loop() {\n if (!this.conditionalIsValid()) {\n throw new Error('Valid conditional is required for while loops');\n }\n\n let iterations = 0;\n while (this.checkCondition() && iterations < this.max_iterations) {\n iterations++;\n this.results.push(await this._callable());\n }\n\n return {\n message: `While loop ${this.name} completed after ${iterations} iterations`,\n result: this.results\n };\n }\n}\n"],
5
- "mappings": "+EAAA,OAAS,cAAAA,EAAY,cAAAC,MAAkB,uBACvC,OAAOC,MAAe,kBACtB,MAA6C,uBAO7C,MAAOC,UAA+BD,CAAU,CAThD,MASgD,CAAAE,EAAA,iBAC9C,OAAO,UAAYH,EAAW,KAe9B,YAAY,CACV,KAAAI,EACA,SAAAC,EACA,SAAAC,EAAWH,EAAA,SAAY,CAAC,EAAb,YACX,YAAAI,EAAc,CACZ,SAAU,KACV,QAAS,KACT,MAAO,IACT,EACA,UAAAC,EAAYT,EAAW,SACvB,WAAAU,EAAa,EACb,eAAAC,EAAiB,GACnB,EAAG,CACD,MAAM,CAAE,KAAAN,EAAM,YAAAG,CAAY,CAAC,EAC3B,KAAK,SAAWF,EAChB,KAAK,UAAYG,EACjB,KAAK,WAAaC,EAAaC,EAAiBA,EAAiBD,EACjE,KAAK,eAAiBC,EACtB,KAAK,QAAU,CAAC,EAChB,KAAK,aAAe,KAEpB,KAAK,SAAW,KAAK,GAAGF,CAAS,OAAO,EAAE,KAAK,IAAI,EAKnD,KAAK,cAAgB,KAAK,gBAAgBF,CAAQ,EAClD,KAAK,UAAY,KAAK,gBAAkB,WACpCA,EAAS,KAAK,IAAI,EAClBA,EAAS,QAAQ,KAAKA,CAAQ,CACpC,CAOA,MAAM,WAAY,CAChB,GAAI,CAAC,KAAK,UAAU,YAAY,KAAK,SAAS,WAAW,EACvD,MAAM,IAAI,MAAM,2DAA2D,EAG7E,IAAIG,EAAa,EACjB,UAAWE,KAAQ,MAAM,KAAK,UAAU,EAGtC,GAFA,KAAK,QAAQ,KAAKA,CAAI,EAElB,EAAEF,GAAc,KAAK,eACvB,MAIJ,MAAO,CACL,QAAS,kBAAkB,KAAK,IAAI,oBAAoBA,CAAU,cAClE,OAAQ,KAAK,OACf,CACF,CAMA,MAAM,UAAW,CACf,IAAIG,EAAI,EACR,KAAOA,EAAI,KAAK,WAAYA,IAC1B,KAAK,QAAQ,KAAK,MAAM,KAAK,UAAU,CAAC,EAG1C,MAAO,CACL,QAAS,YAAY,KAAK,IAAI,oBAAoBA,CAAC,cACnD,OAAQ,KAAK,OACf,CACF,CAOA,MAAM,eAAgB,CACpB,GAAI,CAAC,KAAK,SACR,MAAM,IAAI,MAAM,yCAAyC,EAGvD,OAAO,KAAK,UAAa,aAC3B,KAAK,SAAW,KAAK,SAAS,GAGhC,IAAIH,EAAa,EACjB,UAAWE,KAAQ,KAAK,SACtBF,IACA,KAAK,aAAeE,EACpB,KAAK,QAAQ,KAAK,MAAM,KAAK,UAAU,CAAC,EAG1C,MAAO,CACL,QAAS,iBAAiB,KAAK,IAAI,oBAAoBF,CAAU,cACjE,OAAQ,KAAK,OACf,CACF,CAOA,MAAM,YAAa,CACjB,GAAI,CAAC,KAAK,mBAAmB,EAC3B,MAAM,IAAI,MAAM,+CAA+C,EAGjE,IAAIA,EAAa,EACjB,KAAO,KAAK,eAAe,GAAKA,EAAa,KAAK,gBAChDA,IACA,KAAK,QAAQ,KAAK,MAAM,KAAK,UAAU,CAAC,EAG1C,MAAO,CACL,QAAS,cAAc,KAAK,IAAI,oBAAoBA,CAAU,cAC9D,OAAQ,KAAK,OACf,CACF,CACF",
4
+ "sourcesContent": ["import { loop_types, step_types } from '../../enums/index.js';\nimport LogicStep from './logic_step.js';\nimport { conditional_step_comparators } from '../../enums/index.js';\n\n/**\n * LoopStep class for executing loops within a workflow.\n * @class LoopStep\n * @extends LogicStep\n */\nexport default class LoopStep extends LogicStep {\n static step_name = step_types.LOOP;\n\n /**\n * Creates a new LoopStep instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {Array|Iterable|Function} options.iterable - Iterable to loop over or function returning an iterable. Required for 'for_each' and 'generator' loops.\n * @param {Function} [options.callable=async () => {}] - Function to execute for each iteration.\n * @param {Object} [options.conditional] - Conditional configuration for while loops. Required for 'while' loops.\n * @param {*} [options.conditional.subject] - Subject to evaluate.\n * @param {conditional_step_comparators|string} [options.conditional.operator] - Comparison operator.\n * @param {*} [options.conditional.value] - Value to compare against.\n * @param {string} [options.loop_type=loop_types.FOR_EACH] - Type of loop ('for', 'for_each', 'while', or 'generator').\n * @param {number} [options.iterations=0] - Number of iterations to execute. Only used for 'for' loops.\n * @param {number} [options.max_iterations=1000] - Maximum number of iterations to prevent infinite loops.\n */\n constructor({\n name,\n iterable,\n callable = async () => {},\n conditional = {\n operator: null,\n subject: null,\n value: null,\n },\n loop_type = loop_types.FOR_EACH,\n iterations = 0,\n max_iterations = 1000,\n }) {\n super({ name, conditional });\n this.iterable = iterable;\n this.loop_type = loop_type;\n this.iterations = iterations > max_iterations ? max_iterations : iterations;\n this.max_iterations = max_iterations;\n this.results = [];\n this.current_item = null;\n\n this.callable = this[`${loop_type}_loop`].bind(this);\n\n // When this.callable is set, it binds the callable function to this instance\n // so that it can access instance properties like current_item.\n // Because we're using a local method instead, we bind it here.\n this.callable_type = this.getCallableType(callable);\n this._callable = this.callable_type === 'function'\n ? callable.bind(this)\n : callable.execute.bind(callable);\n }\n\n /**\n * Executes a generator/async generator and appends yielded values to results.\n * @throws {Error} If the callable is not a generator or async generator function.\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async generator() {\n if (!this._callable.constructor.name.includes('Generator')) {\n throw new Error('Iterable must be a generator function for generator loops');\n }\n\n let iterations = 0;\n for (const item of await this._callable()) {\n this.results.push(item);\n\n if (++iterations >= this.max_iterations) {\n break;\n }\n }\n\n return {\n message: `Generator loop ${this.name} completed after ${iterations} iterations`,\n result: this.results\n };\n }\n\n /**\n * Executes a for loop calling the callable for a set number of iterations\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async for_loop() {\n let i = 0;\n for (; i < this.iterations; i++) {\n this.results.push(await this._callable());\n }\n\n return {\n message: `For loop ${this.name} completed after ${i} iterations`,\n result: this.results\n };\n }\n\n /**\n * Executes the callable for each item in the iterable.\n * @throws {Error} If the iterable is not provided.\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async for_each_loop() {\n if (!this.iterable) {\n throw new Error('Iterable is required for for_each loops');\n }\n\n if (typeof this.iterable === 'function') {\n this.iterable = this.iterable();\n }\n\n let iterations = 0;\n for (const item of this.iterable) {\n iterations++;\n this.current_item = item;\n this.results.push(await this._callable());\n }\n\n return {\n message: `For each loop ${this.name} completed after ${iterations} iterations`,\n result: this.results\n };\n }\n\n /**\n * Executes the callable while the condition is true.\n * @throws {Error} If the conditional is not valid.\n * @returns {Object} - An object containing a message and the results of the loop.\n */\n async while_loop() {\n if (!this.conditionalIsValid()) {\n throw new Error('Valid conditional is required for while loops');\n }\n\n let iterations = 0;\n while (this.checkCondition() && iterations < this.max_iterations) {\n iterations++;\n this.results.push(await this._callable());\n }\n\n return {\n message: `While loop ${this.name} completed after ${iterations} iterations`,\n result: this.results\n };\n }\n}\n"],
5
+ "mappings": "+EAAA,OAAS,cAAAA,EAAY,cAAAC,MAAkB,uBACvC,OAAOC,MAAe,kBACtB,MAA6C,uBAO7C,MAAOC,UAA+BD,CAAU,CAThD,MASgD,CAAAE,EAAA,iBAC9C,OAAO,UAAYH,EAAW,KAgB9B,YAAY,CACV,KAAAI,EACA,SAAAC,EACA,SAAAC,EAAWH,EAAA,SAAY,CAAC,EAAb,YACX,YAAAI,EAAc,CACZ,SAAU,KACV,QAAS,KACT,MAAO,IACT,EACA,UAAAC,EAAYT,EAAW,SACvB,WAAAU,EAAa,EACb,eAAAC,EAAiB,GACnB,EAAG,CACD,MAAM,CAAE,KAAAN,EAAM,YAAAG,CAAY,CAAC,EAC3B,KAAK,SAAWF,EAChB,KAAK,UAAYG,EACjB,KAAK,WAAaC,EAAaC,EAAiBA,EAAiBD,EACjE,KAAK,eAAiBC,EACtB,KAAK,QAAU,CAAC,EAChB,KAAK,aAAe,KAEpB,KAAK,SAAW,KAAK,GAAGF,CAAS,OAAO,EAAE,KAAK,IAAI,EAKnD,KAAK,cAAgB,KAAK,gBAAgBF,CAAQ,EAClD,KAAK,UAAY,KAAK,gBAAkB,WACpCA,EAAS,KAAK,IAAI,EAClBA,EAAS,QAAQ,KAAKA,CAAQ,CACpC,CAOA,MAAM,WAAY,CAChB,GAAI,CAAC,KAAK,UAAU,YAAY,KAAK,SAAS,WAAW,EACvD,MAAM,IAAI,MAAM,2DAA2D,EAG7E,IAAIG,EAAa,EACjB,UAAWE,KAAQ,MAAM,KAAK,UAAU,EAGtC,GAFA,KAAK,QAAQ,KAAKA,CAAI,EAElB,EAAEF,GAAc,KAAK,eACvB,MAIJ,MAAO,CACL,QAAS,kBAAkB,KAAK,IAAI,oBAAoBA,CAAU,cAClE,OAAQ,KAAK,OACf,CACF,CAMA,MAAM,UAAW,CACf,IAAIG,EAAI,EACR,KAAOA,EAAI,KAAK,WAAYA,IAC1B,KAAK,QAAQ,KAAK,MAAM,KAAK,UAAU,CAAC,EAG1C,MAAO,CACL,QAAS,YAAY,KAAK,IAAI,oBAAoBA,CAAC,cACnD,OAAQ,KAAK,OACf,CACF,CAOA,MAAM,eAAgB,CACpB,GAAI,CAAC,KAAK,SACR,MAAM,IAAI,MAAM,yCAAyC,EAGvD,OAAO,KAAK,UAAa,aAC3B,KAAK,SAAW,KAAK,SAAS,GAGhC,IAAIH,EAAa,EACjB,UAAWE,KAAQ,KAAK,SACtBF,IACA,KAAK,aAAeE,EACpB,KAAK,QAAQ,KAAK,MAAM,KAAK,UAAU,CAAC,EAG1C,MAAO,CACL,QAAS,iBAAiB,KAAK,IAAI,oBAAoBF,CAAU,cACjE,OAAQ,KAAK,OACf,CACF,CAOA,MAAM,YAAa,CACjB,GAAI,CAAC,KAAK,mBAAmB,EAC3B,MAAM,IAAI,MAAM,+CAA+C,EAGjE,IAAIA,EAAa,EACjB,KAAO,KAAK,eAAe,GAAKA,EAAa,KAAK,gBAChDA,IACA,KAAK,QAAQ,KAAK,MAAM,KAAK,UAAU,CAAC,EAG1C,MAAO,CACL,QAAS,cAAc,KAAK,IAAI,oBAAoBA,CAAU,cAC9D,OAAQ,KAAK,OACf,CACF,CACF",
6
6
  "names": ["loop_types", "step_types", "LogicStep", "LoopStep", "__name", "name", "iterable", "callable", "conditional", "loop_type", "iterations", "max_iterations", "item", "i"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/classes/steps/step.js"],
4
- "sourcesContent": ["import Base from '../base.js';\nimport Workflow from '../workflow.js';\nimport { base_types, step_types } from '../../enums/index.js';\n\n/**\n * Step class representing an executable unit within a workflow.\n * @class Step\n * @extends Base\n */\nexport default class Step extends Base {\n static step_name = 'step';\n #callable_object = null;\n\n /**\n * Creates a new Step instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {string} [options.step_type=step_types.ACTION] - Type of the step.\n * @param {Function|Step|Workflow} [options.callable=async () => {}] - Function, Step, or Workflow to execute.\n * @param {string} [options.sub_step_type=null] - Sub-type of the step.\n */\n constructor({\n name,\n step_type = step_types.ACTION,\n callable = async () => {},\n sub_step_type = null,\n }) {\n super({ name, base_type: base_types.STEP });\n\n this.callable = callable;\n\n // Store off the original callable object, because if it's a Step or Workflow,\n // this.callable is set to the execute method of that object, but we may need to access its properties later.\n this.#callable_object = callable;\n\n this.step_type = step_type;\n this.sub_step_type = sub_step_type;\n\n this.errors = [];\n this.result = null;\n this.retry_results = [];\n }\n\n /**\n * Executes the step's callable function, Step, or Workflow.\n * @async\n * @returns {Promise<Step>} The step instance with execution results.\n */\n async execute() {\n this.markAsRunning();\n\n try {\n this.result = await this._callable();\n } catch (error) {\n this.errors.push(error);\n this.markAsFailed();\n\n this.timing.end_time = new Date();\n this.timing.execution_time_ms = this.timing.end_time - this.timing.start_time;\n\n if (this.getState('exit_on_error')) {\n throw error;\n }\n }\n\n if (this.status !== this.getState('statuses')[this.base_type].FAILED) {\n this.markAsComplete();\n }\n\n if (['step', 'workflow'].includes(this.callable_type)) {\n return this.#callable_object;\n }\n\n return this;\n }\n\n /**\n * Determines the type of the callable (function, step, or workflow).\n * @param {Function|Step|Workflow} callable - The callable to check.\n * @returns {string} The type: 'function', 'step', or 'workflow'.\n * @throws {Error} Throws if callable type is invalid.\n */\n getCallableType(callable) {\n if (callable && callable.base_type === base_types.WORKFLOW) {\n return 'workflow';\n } else if (callable && callable.base_type === base_types.STEP) {\n return 'step';\n } else if (typeof callable === 'function') {\n return 'function';\n } \n\n throw new Error('Invalid callable type. Must be one of function, Step, or Workflow.');\n }\n\n /**\n * Sets a value in the parent workflow's state.\n * @param {string} workflowId - ID of the parent workflow.\n * @param {string} path - Path in the workflow state to set.\n * @param {*} value - Value to set at the specified path.\n * @throws {Error} Throws if parent workflow is not found.\n */\n setParentWorkflowValue(workflowId, path, value) {\n const parentWorkflow = this.getState('workflows')[workflowId];\n\n if (!parentWorkflow) {\n throw new Error(`Parent workflow with ID ${workflowId} not found.`);\n }\n\n parentWorkflow[path] = value;\n }\n\n /**\n * Sets the callable for the step and determines its type.\n * @param {Function|Step|Workflow} callable - The callable to set.\n */\n set callable(callable) {\n this.callable_type = this.getCallableType(callable);\n\n if (['step', 'workflow'].includes(this.callable_type)) {\n if (this.callable_type === 'step') {\n callable.parentWorkflowId = this.parentWorkflowId ?? null;\n }\n\n this._callable = callable.execute.bind(callable);\n } else {\n this._callable = callable.bind(this);\n }\n }\n}\n"],
4
+ "sourcesContent": ["import Base from '../base.js';\nimport Workflow from '../workflow.js';\nimport { base_types, step_types } from '../../enums/index.js';\n\n/**\n * Step class representing an executable unit within a workflow.\n * @class Step\n * @extends Base\n */\nexport default class Step extends Base {\n static step_name = 'step';\n #callable_object = null;\n\n /**\n * Creates a new Step instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the step.\n * @param {string} [options.step_type=step_types.ACTION] - Type of the step.\n * @param {Function|Step|Workflow} [options.callable=async () => {}] - Function, Step, or Workflow to execute.\n * @param {sub_step_types|null} [options.sub_step_type=null] - Sub-type of the step (use values from the sub_step_types enum).\n */\n constructor({\n name,\n step_type = step_types.ACTION,\n callable = async () => {},\n sub_step_type = null,\n }) {\n super({ name, base_type: base_types.STEP });\n\n this.callable = callable;\n\n // Store off the original callable object, because if it's a Step or Workflow,\n // this.callable is set to the execute method of that object, but we may need to access its properties later.\n this.#callable_object = callable;\n\n this.step_type = step_type;\n this.sub_step_type = sub_step_type;\n\n this.errors = [];\n this.result = null;\n this.retry_results = [];\n }\n\n /**\n * Executes the step's callable function, Step, or Workflow.\n * @async\n * @returns {Promise<Step>} The step instance with execution results.\n */\n async execute() {\n this.markAsRunning();\n\n try {\n this.result = await this._callable();\n } catch (error) {\n this.errors.push(error);\n this.markAsFailed();\n\n this.timing.end_time = new Date();\n this.timing.execution_time_ms = this.timing.end_time - this.timing.start_time;\n\n if (this.getState('exit_on_error')) {\n throw error;\n }\n }\n\n if (this.status !== this.getState('statuses')[this.base_type].FAILED) {\n this.markAsComplete();\n }\n\n if (['step', 'workflow'].includes(this.callable_type)) {\n return this.#callable_object;\n }\n\n return this;\n }\n\n /**\n * Determines the type of the callable (function, step, or workflow).\n * @param {Function|Step|Workflow} callable - The callable to check.\n * @returns {string} The type: 'function', 'step', or 'workflow'.\n * @throws {Error} Throws if callable type is invalid.\n */\n getCallableType(callable) {\n if (callable && callable.base_type === base_types.WORKFLOW) {\n return 'workflow';\n } else if (callable && callable.base_type === base_types.STEP) {\n return 'step';\n } else if (typeof callable === 'function') {\n return 'function';\n } \n\n throw new Error('Invalid callable type. Must be one of function, Step, or Workflow.');\n }\n\n /**\n * Sets a value in the parent workflow's state.\n * @param {string} workflowId - ID of the parent workflow.\n * @param {string} path - Path in the workflow state to set.\n * @param {*} value - Value to set at the specified path.\n * @throws {Error} Throws if parent workflow is not found.\n */\n setParentWorkflowValue(workflowId, path, value) {\n const parentWorkflow = this.getState('workflows')[workflowId];\n\n if (!parentWorkflow) {\n throw new Error(`Parent workflow with ID ${workflowId} not found.`);\n }\n\n parentWorkflow[path] = value;\n }\n\n /**\n * Sets the callable for the step and determines its type.\n * @param {Function|Step|Workflow} callable - The callable to set.\n */\n set callable(callable) {\n this.callable_type = this.getCallableType(callable);\n\n if (['step', 'workflow'].includes(this.callable_type)) {\n if (this.callable_type === 'step') {\n callable.parentWorkflowId = this.parentWorkflowId ?? null;\n }\n\n this._callable = callable.execute.bind(callable);\n } else {\n this._callable = callable.bind(this);\n }\n }\n}\n"],
5
5
  "mappings": "+EAAA,OAAOA,MAAU,aACjB,MAAqB,iBACrB,OAAS,cAAAC,EAAY,cAAAC,MAAkB,uBAOvC,MAAOC,UAA2BH,CAAK,CATvC,MASuC,CAAAI,EAAA,aACrC,OAAO,UAAY,OACnBC,GAAmB,KAUnB,YAAY,CACV,KAAAC,EACA,UAAAC,EAAYL,EAAW,OACvB,SAAAM,EAAWJ,EAAA,SAAY,CAAC,EAAb,YACX,cAAAK,EAAgB,IAClB,EAAG,CACD,MAAM,CAAE,KAAAH,EAAM,UAAWL,EAAW,IAAK,CAAC,EAE1C,KAAK,SAAWO,EAIhB,KAAKH,GAAmBG,EAExB,KAAK,UAAYD,EACjB,KAAK,cAAgBE,EAErB,KAAK,OAAS,CAAC,EACf,KAAK,OAAS,KACd,KAAK,cAAgB,CAAC,CACxB,CAOA,MAAM,SAAU,CACd,KAAK,cAAc,EAEnB,GAAI,CACF,KAAK,OAAS,MAAM,KAAK,UAAU,CACrC,OAASC,EAAO,CAOd,GANA,KAAK,OAAO,KAAKA,CAAK,EACtB,KAAK,aAAa,EAElB,KAAK,OAAO,SAAW,IAAI,KAC3B,KAAK,OAAO,kBAAoB,KAAK,OAAO,SAAW,KAAK,OAAO,WAE/D,KAAK,SAAS,eAAe,EAC/B,MAAMA,CAEV,CAMA,OAJI,KAAK,SAAW,KAAK,SAAS,UAAU,EAAE,KAAK,SAAS,EAAE,QAC5D,KAAK,eAAe,EAGlB,CAAC,OAAQ,UAAU,EAAE,SAAS,KAAK,aAAa,EAC3C,KAAKL,GAGP,IACT,CAQA,gBAAgBG,EAAU,CACxB,GAAIA,GAAYA,EAAS,YAAcP,EAAW,SAChD,MAAO,WACF,GAAIO,GAAYA,EAAS,YAAcP,EAAW,KACvD,MAAO,OACF,GAAI,OAAOO,GAAa,WAC7B,MAAO,WAGT,MAAM,IAAI,MAAM,oEAAoE,CACtF,CASA,uBAAuBG,EAAYC,EAAMC,EAAO,CAC9C,MAAMC,EAAiB,KAAK,SAAS,WAAW,EAAEH,CAAU,EAE5D,GAAI,CAACG,EACH,MAAM,IAAI,MAAM,2BAA2BH,CAAU,aAAa,EAGpEG,EAAeF,CAAI,EAAIC,CACzB,CAMA,IAAI,SAASL,EAAU,CACrB,KAAK,cAAgB,KAAK,gBAAgBA,CAAQ,EAE9C,CAAC,OAAQ,UAAU,EAAE,SAAS,KAAK,aAAa,GAC9C,KAAK,gBAAkB,SACzBA,EAAS,iBAAmB,KAAK,kBAAoB,MAGvD,KAAK,UAAYA,EAAS,QAAQ,KAAKA,CAAQ,GAE/C,KAAK,UAAYA,EAAS,KAAK,IAAI,CAEvC,CACF",
6
6
  "names": ["Base", "base_types", "step_types", "Step", "__name", "#callable_object", "name", "step_type", "callable", "sub_step_type", "error", "workflowId", "path", "value", "parentWorkflow"]
7
7
  }
@@ -1,2 +1,2 @@
1
- var a=Object.defineProperty;var h=(i,t)=>a(i,"name",{value:t,configurable:!0});import{Base as o}from"./index.js";import{base_types as n}from"../enums/index.js";class p extends o{static{h(this,"Workflow")}constructor({name:t,exit_on_error:e=!1,steps:s=[],throw_on_empty:r=!1}){super({name:t,base_type:n.WORKFLOW}),this.initializeWorkflowState(),this.addSteps(s),this.exit_on_error=e,this.throw_on_empty=r}async execute(){if(this.isEmpty()){if(this.throw_on_empty)throw new Error("Cannot execute an empty workflow");return this.markAsComplete(),this.prepareResult("Workflow is empty",null),this}this.markAsRunning();for(let t=0;t<this._steps.length;t++){if(this.should_pause)return this.markAsPaused(),this.should_pause=!1,this;if(this.should_break){this.should_break=!1,this.log(this.getState("event_names.workflow").WORKFLOW_BREAK_EXECUTED,`Workflow "${this.name}" execution broken at step ${this._steps[t].name} - ${this._steps[t].id}.`);break}if(this.should_skip){this.log(this.getState("events.workflow.event_names.WORKFLOW_STEP_SKIPPED"),`Workflow "${this.name}" skipping step ${this._steps[t].name} - ${this._steps[t].id}.`),this.should_skip=!1;continue}this.current_step=this._steps[t].id;try{const e=await this.step();this.prepareResult("Success",e)}catch(e){if(this.markAsFailed(),this.prepareResult(`Workflow execution failed at step ${this.steps_by_id[this.current_step].name} - ${this.current_step}`,{error:e}),this.exit_on_error)return this}}return this.markAsComplete(),this}async resume(){return this.should_pause=!1,this.timing.resume_time=new Date,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_RESUMED,this.getState()),this.execute()}async step(){const t=this.steps_by_id[this.current_step];t.parentWorkflowId=this.id;const e=await t.execute();if(t.status===this.getState("statuses.step.FAILED"))throw t.errors[t.errors.length-1]??new Error(`Step "${t.name}" failed`);return e}addStep(t){if(typeof t.getCallableType!="function")throw new Error("Invalid step type. Must be an instance of Step.");Array.isArray(this._steps)||(this._steps=[]),(!this.steps_by_id||typeof this.steps_by_id!="object")&&(this.steps_by_id={}),this.steps_by_id[t.id]=t,t.parentWorkflowId=this.id,this._steps.push(t)}addStepAtIndex(t,e){t.parentWorkflowId=this.id,this._steps.splice(e,0,t)}addSteps(t){t.forEach(e=>this.addStep(e))}clearSteps(){this._steps=[]}deleteStep(t){this._steps=this._steps.filter(e=>e.id!==t)}deleteStepByIndex(t){this._steps.splice(t,1)}initializeWorkflowState(){this.results=[],this.exit_on_error=!1,this.current_step=null,this.should_break=!1,this.should_continue=!1,this.should_pause=!1,this.should_skip=!1,this.status=this.getState("statuses.workflow").CREATED,this._steps=[],this.throw_on_empty=this.throw_on_empty,this.timing={...this.timing,create_time:new Date,pause_time:null,resume_time:null};const t=this.getState("workflows");t[this.id]=this,this.setState("workflows",t),this.log(this.getState("event_names.workflow").WORKFLOW_CREATED,`Workflow "${this.name}" initialized.`)}isEmpty(){return!this._steps||!this._steps.length}markAsCreated(){return this.timing.create_time=new Date,this.log(this.getState("event_names.workflow").WORKFLOW_CREATED,`Workflow "${this.name}" created.`),this.getState("statuses.workflow").CREATED}markAsPaused(){this.timing.pause_time=new Date,this.status=this.getState("statuses.workflow").PAUSED,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_PAUSED,this.getState())}markAsResumed(){this.timing.resume_time=new Date,this.status=this.getState("statuses.workflow").RUNNING,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_RESUMED,this.getState())}moveStep(t,e){const[s]=this._steps.splice(t,1);this._steps.splice(e,0,s),this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_STEP_MOVED,this.getState())}pause(){this.should_pause=!0,this.timing.pause_time=new Date,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_PAUSED,this.getState())}popStep(){return this._steps.pop()}prepareResult(t,e){this.results.push({message:t,data:e})}pushStep(t){this.addStep(t)}pushSteps(t){t.forEach(e=>this.addStep(e))}shiftStep(){return this._steps.shift()}unshiftStep(t){if(typeof t.getCallableType!="function")throw new Error("Invalid step type. Must be an instance of Step.");(!this.steps_by_id||typeof this.steps_by_id!="object")&&(this.steps_by_id={}),this.steps_by_id[t.id]=t,t.parentWorkflowId=this.id,this._steps.unshift(t)}get steps(){return this._steps}set steps(t){t.forEach((e,s)=>{if(typeof e.getCallableType!="function")throw new Error(`Invalid step type. Step at index ${s} is not an instance of Step.`)}),this.addSteps(t)}}export{p as default};
1
+ var o=Object.defineProperty;var r=(i,t)=>o(i,"name",{value:t,configurable:!0});import{v4 as a}from"uuid";import n from"./base.js";import{base_types as p}from"../enums/index.js";class _ extends n{static{r(this,"Workflow")}constructor({name:t,exit_on_error:s=!1,steps:e=[],throw_on_empty:h=!1}){super({name:t,base_type:p.WORKFLOW}),this.initializeWorkflowState(),this.addSteps(e),this.exit_on_error=s,this.throw_on_empty=h,this.sessions={},this.current_session_id=null}async execute(){if(this.current_session_id||(this.current_session_id=a()),this.isEmpty()){if(this.throw_on_empty)throw new Error("Cannot execute an empty workflow");return this.markAsComplete(),this.prepareResult("Workflow is empty",null),this}this.markAsRunning();for(let t=0;t<this._steps.length;t++){if(this.should_break){this.should_break=!1,this.log(this.getState("event_names.workflow").WORKFLOW_BREAK_EXECUTED,`Workflow "${this.name}" execution broken at step ${this._steps[t].name} - ${this._steps[t].id}.`);break}if(this.should_skip){this.log(this.getState("events.workflow.event_names.WORKFLOW_STEP_SKIPPED"),`Workflow "${this.name}" skipping step ${this._steps[t].name} - ${this._steps[t].id}.`),this.should_skip=!1;continue}this.current_step=this._steps[t].id;try{const s=await this.step();this.prepareResult("Success",s)}catch(s){if(this.markAsFailed(),this.prepareResult(`Workflow execution failed at step ${this.steps_by_id[this.current_step].name} - ${this.current_step}`,{error:s}),this.exit_on_error)return this}if(this.should_pause)return this.markAsPaused(),this.should_pause=!1,this}return this.markAsComplete(),this}async resume(){return this.should_pause=!1,this.timing.resume_time=new Date,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_RESUMED,this.getState()),this.execute()}async step(){const t=this.steps_by_id[this.current_step];t.parentWorkflowId=this.id;const s=await t.execute();if(t.status===this.getState("statuses.step.FAILED"))throw t.errors[t.errors.length-1]??new Error(`Step "${t.name}" failed`);return s}addStep(t){if(typeof t.getCallableType!="function")throw new Error("Invalid step type. Must be an instance of Step.");Array.isArray(this._steps)||(this._steps=[]),(!this.steps_by_id||typeof this.steps_by_id!="object")&&(this.steps_by_id={}),this.steps_by_id[t.id]=t,t.parentWorkflowId=this.id,this._steps.push(t)}addStepAtIndex(t,s){(!this.steps_by_id||typeof this.steps_by_id!="object")&&(this.steps_by_id={}),this.steps_by_id[t.id]=t,t.parentWorkflowId=this.id,this._steps.splice(s,0,t)}addSteps(t){t.forEach(s=>this.addStep(s))}clearSteps(){this._steps=[]}closeCurrentSession(){this.current_session_id&&(this.sessions[this.current_session_id]={results:[...this.results],status:this.status,timing:{...this.timing},closed_at:new Date},this.current_session_id=null)}deleteStep(t){this._steps=this._steps.filter(s=>s.id!==t)}deleteStepByIndex(t){this._steps.splice(t,1)}initializeWorkflowState(){this.results=[],this.exit_on_error=!1,this.current_step=null,this.should_break=!1,this.should_continue=!1,this.should_pause=!1,this.should_skip=!1,this.status=this.getState("statuses.workflow").CREATED,this._steps=[],this.throw_on_empty=this.throw_on_empty,this.timing={...this.timing,create_time:new Date,pause_time:null,resume_time:null};const t=this.getState("workflows");t[this.id]=this,this.setState("workflows",t),this.log(this.getState("event_names.workflow").WORKFLOW_CREATED,`Workflow "${this.name}" initialized.`)}isEmpty(){return!this._steps||!this._steps.length}markAsComplete(){super.markAsComplete(),this.closeCurrentSession()}markAsCreated(){return this.timing.create_time=new Date,this.log(this.getState("event_names.workflow").WORKFLOW_CREATED,`Workflow "${this.name}" created.`),this.getState("statuses.workflow").CREATED}markAsFailed(){super.markAsFailed(),this.closeCurrentSession()}markAsPaused(){this.timing.pause_time=new Date,this.status=this.getState("statuses.workflow").PAUSED,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_PAUSED,this.getState())}markAsResumed(){this.timing.resume_time=new Date,this.status=this.getState("statuses.workflow").RUNNING,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_RESUMED,this.getState())}moveStep(t,s){const[e]=this._steps.splice(t,1);this._steps.splice(s,0,e),this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_STEP_MOVED,this.getState())}pause(){this.should_pause=!0,this.timing.pause_time=new Date,this.getState("events.workflow").emit(this.getState("event_names.workflow").WORKFLOW_PAUSED,this.getState())}popStep(){return this._steps.pop()}prepareResult(t,s){this.results.push({message:t,data:s})}pushStep(t){this.addStep(t)}pushSteps(t){t.forEach(s=>this.addStep(s))}shiftStep(){return this._steps.shift()}unshiftStep(t){if(typeof t.getCallableType!="function")throw new Error("Invalid step type. Must be an instance of Step.");(!this.steps_by_id||typeof this.steps_by_id!="object")&&(this.steps_by_id={}),this.steps_by_id[t.id]=t,t.parentWorkflowId=this.id,this._steps.unshift(t)}get steps(){return this._steps}set steps(t){t.forEach((s,e)=>{if(typeof s.getCallableType!="function")throw new Error(`Invalid step type. Step at index ${e} is not an instance of Step.`)}),this.addSteps(t)}}export{_ as default};
2
2
  //# sourceMappingURL=workflow.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/classes/workflow.js"],
4
- "sourcesContent": ["import { Base } from './index.js';\nimport { base_types } from '../enums/index.js';\n\n/**\n * Workflow class for managing and executing a sequence of steps.\n * @class Workflow\n * @extends Base\n */\nexport default class Workflow extends Base {\n /**\n * Creates a new Workflow instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the workflow.\n * @param {boolean} [options.exit_on_error=false] - Whether to exit on error.\n * @param {Array<Step>} [options.steps=[]] - Array of steps to add to the workflow.\n * @param {boolean} [options.throw_on_empty=false] - Whether to throw error if workflow is empty.\n */\n constructor({\n name,\n exit_on_error = false,\n steps = [],\n throw_on_empty = false\n }) {\n super({ name, base_type: base_types.WORKFLOW });\n\n this.initializeWorkflowState();\n\n this.addSteps(steps);\n\n this.exit_on_error = exit_on_error;\n this.throw_on_empty = throw_on_empty;\n }\n\n /**\n * Executes the workflow by running all steps in sequence.\n * @async\n * @returns {Promise<Workflow>} The workflow instance with execution results.\n * @throws {Error} Throws if workflow is empty and throw_on_empty is true.\n */\n async execute() {\n if (this.isEmpty()) {\n if (this.throw_on_empty) {\n throw new Error('Cannot execute an empty workflow');\n }\n\n this.markAsComplete();\n this.prepareResult('Workflow is empty', null);\n return this;\n }\n \n this.markAsRunning();\n\n for (let i = 0; i < this._steps.length; i++) {\n if (this.should_pause) {\n this.markAsPaused();\n this.should_pause = false;\n return this;\n }\n \n if (this.should_break) {\n this.should_break = false;\n this.log(this.getState('event_names.workflow').WORKFLOW_BREAK_EXECUTED, `Workflow \"${this.name}\" execution broken at step ${this._steps[i].name} - ${this._steps[i].id}.`);\n break;\n }\n\n if (this.should_skip) {\n this.log(\n this.getState('events.workflow.event_names.WORKFLOW_STEP_SKIPPED'),\n `Workflow \"${this.name}\" skipping step ${this._steps[i].name} - ${this._steps[i].id}.`\n );\n this.should_skip = false;\n continue;\n }\n\n this.current_step = this._steps[i].id;\n\n try {\n const step_result = await this.step();\n this.prepareResult('Success', step_result);\n } catch (error) {\n this.markAsFailed();\n this.prepareResult(`Workflow execution failed at step ${this.steps_by_id[this.current_step].name} - ${this.current_step}`, { error });\n \n if (this.exit_on_error) {\n return this;\n }\n }\n }\n\n this.markAsComplete();\n return this;\n }\n\n /**\n * Resumes a paused workflow.\n * @async\n * @returns {Promise<Workflow>} The workflow instance.\n */\n async resume() {\n this.should_pause = false;\n this.timing.resume_time = new Date();\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_RESUMED,\n this.getState()\n );\n return this.execute();\n }\n\n /**\n * Executes a single step in the workflow.\n * @async\n * @returns {Promise<*>} The result of the step execution.\n */\n async step() {\n const step = this.steps_by_id[this.current_step];\n\n step.parentWorkflowId = this.id;\n const result = await step.execute();\n\n if (step.status === this.getState('statuses.step.FAILED')) {\n throw step.errors[step.errors.length - 1] ?? new Error(`Step \"${step.name}\" failed`);\n }\n\n return result;\n }\n\n /**\n * Adds a step to the workflow.\n * @param {Step} step - The step to add.\n * @throws {Error} Throws if step is not a valid Step instance.\n */\n addStep(step) {\n if (typeof step.getCallableType !== 'function') {\n throw new Error('Invalid step type. Must be an instance of Step.');\n }\n\n if (!Array.isArray(this._steps)) {\n this._steps = [];\n }\n\n if (!this.steps_by_id || typeof this.steps_by_id !== 'object') {\n this.steps_by_id = {};\n }\n\n this.steps_by_id[step.id] = step;\n\n step.parentWorkflowId = this.id;\n this._steps.push(step);\n }\n\n /**\n * Adds a step at a specific index in the workflow.\n * @param {Step} step - The step to add.\n * @param {number} index - The index at which to insert the step.\n */\n addStepAtIndex(step, index) {\n step.parentWorkflowId = this.id;\n this._steps.splice(index, 0, step);\n }\n\n /**\n * Adds multiple steps to the workflow.\n * @param {Step[]} steps - Array of steps to add.\n */\n addSteps(steps) {\n steps.forEach(step => this.addStep(step));\n }\n\n /**\n * Clears all steps from the workflow.\n */\n clearSteps() {\n this._steps = [];\n }\n\n /**\n * Deletes a step from the workflow by its ID.\n * @param {string} stepId - The ID of the step to delete.\n */\n deleteStep(stepId) {\n this._steps = this._steps.filter(step => step.id !== stepId);\n }\n\n /**\n * Deletes a step from the workflow by its index.\n * @param {number} index - The index of the step to delete.\n */\n deleteStepByIndex(index) {\n this._steps.splice(index, 1);\n }\n\n /**\n * Initializes the workflow state with default values.\n */\n initializeWorkflowState() {\n this.results = [];\n this.exit_on_error = false;\n this.current_step = null;\n this.should_break = false;\n this.should_continue = false;\n this.should_pause = false;\n this.should_skip = false;\n this.status = this.getState('statuses.workflow').CREATED;\n this._steps = [];\n this.throw_on_empty = this.throw_on_empty;\n this.timing = {\n ...this.timing,\n create_time: new Date(),\n pause_time: null,\n resume_time: null,\n }\n\n const workflows = this.getState('workflows');\n workflows[this.id] = this;\n this.setState('workflows', workflows);\n\n this.log(\n this.getState('event_names.workflow').WORKFLOW_CREATED,\n `Workflow \"${this.name}\" initialized.`\n );\n }\n\n /**\n * Checks if the workflow has no steps.\n * @returns {boolean} True if the workflow is empty.\n */\n isEmpty() {\n return !this._steps || !this._steps.length\n }\n \n /**\n * Marks the workflow as created.\n * @returns {string} The CREATED status.\n */\n markAsCreated() {\n this.timing.create_time = new Date();\n \n this.log(\n this.getState('event_names.workflow').WORKFLOW_CREATED,\n `Workflow \"${this.name}\" created.`\n );\n\n return this.getState('statuses.workflow').CREATED;\n }\n \n /**\n * Marks the workflow as paused.\n */\n markAsPaused() {\n this.timing.pause_time = new Date();\n this.status = this.getState('statuses.workflow').PAUSED;\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_PAUSED,\n this.getState()\n );\n }\n \n /**\n * Marks the workflow as resumed.\n */\n markAsResumed() {\n this.timing.resume_time = new Date();\n this.status = this.getState('statuses.workflow').RUNNING;\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_RESUMED,\n this.getState()\n );\n }\n\n /**\n * Moves a step from one index to another.\n * @param {number} fromIndex - The current index of the step.\n * @param {number} toIndex - The target index for the step.\n */\n moveStep(fromIndex, toIndex) {\n const [step] = this._steps.splice(fromIndex, 1);\n this._steps.splice(toIndex, 0, step);\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_STEP_MOVED,\n this.getState()\n );\n }\n\n /**\n * Pauses the workflow execution.\n */\n pause() {\n this.should_pause = true;\n this.timing.pause_time = new Date();\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_PAUSED,\n this.getState()\n );\n }\n\n /**\n * Removes and returns the last step from the workflow.\n * @returns {Step} The last step.\n */\n popStep() {\n return this._steps.pop();\n }\n\n /**\n * Prepares a result object and adds it to the results array.\n * @param {string} message - Result message.\n * @param {*} data - Result data.\n */\n prepareResult(message, data) {\n this.results.push({ message, data });\n }\n\n /**\n * Adds a step to the end of the workflow.\n * @param {Step} step - The step to add.\n */\n pushStep(step) {\n this.addStep(step);\n }\n\n /**\n * Adds multiple steps to the end of the workflow.\n * @param {Step[]} steps - Array of steps to add.\n */\n pushSteps(steps) {\n steps.forEach(step => this.addStep(step));\n }\n\n /**\n * Removes and returns the first step from the workflow.\n * @returns {Step} The first step.\n */\n shiftStep() {\n return this._steps.shift();\n }\n\n /**\n * Adds a step to the beginning of the workflow.\n * @param {Step} step - The step to add.\n * @throws {Error} Throws if step is not a valid Step instance.\n */\n unshiftStep(step) {\n if (typeof step.getCallableType !== 'function') {\n throw new Error('Invalid step type. Must be an instance of Step.');\n }\n\n if (!this.steps_by_id || typeof this.steps_by_id !== 'object') {\n this.steps_by_id = {};\n }\n\n this.steps_by_id[step.id] = step;\n\n step.parentWorkflowId = this.id;\n this._steps.unshift(step);\n }\n\n /**\n * Gets the array of steps in the workflow.\n * @returns {Step[]} Array of steps.\n */\n get steps() {\n return this._steps;\n }\n\n /**\n * Sets the steps array by adding multiple steps.\n * @param {Step[]} steps - Array of steps to add.\n */\n set steps(steps) {\n steps.forEach((step, index) => {\n if (typeof step.getCallableType !== 'function') {\n throw new Error(`Invalid step type. Step at index ${index} is not an instance of Step.`);\n }\n });\n\n this.addSteps(steps);\n }\n}\n"],
5
- "mappings": "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",
6
- "names": ["Base", "base_types", "Workflow", "__name", "name", "exit_on_error", "steps", "throw_on_empty", "i", "step_result", "error", "step", "result", "index", "stepId", "workflows", "fromIndex", "toIndex", "message", "data"]
4
+ "sourcesContent": ["import { v4 as uuidv4 } from 'uuid';\nimport Base from './base.js';\nimport { base_types } from '../enums/index.js';\n\n/**\n * Workflow class for managing and executing a sequence of steps.\n * @class Workflow\n * @extends Base\n */\nexport default class Workflow extends Base {\n /**\n * Creates a new Workflow instance.\n * @param {Object} options - Configuration options.\n * @param {string} [options.name] - Name of the workflow.\n * @param {boolean} [options.exit_on_error=false] - Whether to exit on error.\n * @param {Array<Step>} [options.steps=[]] - Array of steps to add to the workflow.\n * @param {boolean} [options.throw_on_empty=false] - Whether to throw error if workflow is empty.\n */\n constructor({\n name,\n exit_on_error = false,\n steps = [],\n throw_on_empty = false\n }) {\n super({ name, base_type: base_types.WORKFLOW });\n\n this.initializeWorkflowState();\n\n this.addSteps(steps);\n\n this.exit_on_error = exit_on_error;\n this.throw_on_empty = throw_on_empty;\n this.sessions = {};\n this.current_session_id = null;\n }\n\n /**\n * Executes the workflow by running all steps in sequence.\n * @async\n * @returns {Promise<Workflow>} The workflow instance with execution results.\n * @throws {Error} Throws if workflow is empty and throw_on_empty is true.\n */\n async execute() {\n if (!this.current_session_id) {\n this.current_session_id = uuidv4();\n }\n\n if (this.isEmpty()) {\n if (this.throw_on_empty) {\n throw new Error('Cannot execute an empty workflow');\n }\n\n this.markAsComplete();\n this.prepareResult('Workflow is empty', null);\n return this;\n }\n \n this.markAsRunning();\n\n for (let i = 0; i < this._steps.length; i++) {\n if (this.should_break) {\n this.should_break = false;\n this.log(this.getState('event_names.workflow').WORKFLOW_BREAK_EXECUTED, `Workflow \"${this.name}\" execution broken at step ${this._steps[i].name} - ${this._steps[i].id}.`);\n break;\n }\n\n if (this.should_skip) {\n this.log(\n this.getState('events.workflow.event_names.WORKFLOW_STEP_SKIPPED'),\n `Workflow \"${this.name}\" skipping step ${this._steps[i].name} - ${this._steps[i].id}.`\n );\n this.should_skip = false;\n continue;\n }\n\n this.current_step = this._steps[i].id;\n\n try {\n const step_result = await this.step();\n this.prepareResult('Success', step_result);\n } catch (error) {\n this.markAsFailed();\n this.prepareResult(`Workflow execution failed at step ${this.steps_by_id[this.current_step].name} - ${this.current_step}`, { error });\n \n if (this.exit_on_error) {\n return this;\n }\n }\n\n if (this.should_pause) {\n this.markAsPaused();\n this.should_pause = false;\n return this;\n }\n }\n\n this.markAsComplete();\n return this;\n }\n\n /**\n * Resumes a paused workflow.\n * @async\n * @returns {Promise<Workflow>} The workflow instance.\n */\n async resume() {\n this.should_pause = false;\n this.timing.resume_time = new Date();\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_RESUMED,\n this.getState()\n );\n return this.execute();\n }\n\n /**\n * Executes a single step in the workflow.\n * @async\n * @returns {Promise<*>} The result of the step execution.\n */\n async step() {\n const step = this.steps_by_id[this.current_step];\n\n step.parentWorkflowId = this.id;\n const result = await step.execute();\n\n if (step.status === this.getState('statuses.step.FAILED')) {\n throw step.errors[step.errors.length - 1] ?? new Error(`Step \"${step.name}\" failed`);\n }\n\n return result;\n }\n\n /**\n * Adds a step to the workflow.\n * @param {Step} step - The step to add.\n * @throws {Error} Throws if step is not a valid Step instance.\n */\n addStep(step) {\n if (typeof step.getCallableType !== 'function') {\n throw new Error('Invalid step type. Must be an instance of Step.');\n }\n\n if (!Array.isArray(this._steps)) {\n this._steps = [];\n }\n\n if (!this.steps_by_id || typeof this.steps_by_id !== 'object') {\n this.steps_by_id = {};\n }\n\n this.steps_by_id[step.id] = step;\n\n step.parentWorkflowId = this.id;\n this._steps.push(step);\n }\n\n /**\n * Adds a step at a specific index in the workflow.\n * @param {Step} step - The step to add.\n * @param {number} index - The index at which to insert the step.\n */\n addStepAtIndex(step, index) {\n if (!this.steps_by_id || typeof this.steps_by_id !== 'object') {\n this.steps_by_id = {};\n }\n\n this.steps_by_id[step.id] = step;\n step.parentWorkflowId = this.id;\n this._steps.splice(index, 0, step);\n }\n\n /**\n * Adds multiple steps to the workflow.\n * @param {Step[]} steps - Array of steps to add.\n */\n addSteps(steps) {\n steps.forEach(step => this.addStep(step));\n }\n\n /**\n * Clears all steps from the workflow.\n */\n clearSteps() {\n this._steps = [];\n }\n\n /**\n * Closes the current session and stores a snapshot of the workflow state.\n */\n closeCurrentSession() {\n if (!this.current_session_id) {\n return;\n }\n\n this.sessions[this.current_session_id] = {\n results: [...this.results],\n status: this.status,\n timing: { ...this.timing },\n closed_at: new Date()\n };\n this.current_session_id = null;\n }\n\n /**\n * Deletes a step from the workflow by its ID.\n * @param {string} stepId - The ID of the step to delete.\n */\n deleteStep(stepId) {\n this._steps = this._steps.filter(step => step.id !== stepId);\n }\n\n /**\n * Deletes a step from the workflow by its index.\n * @param {number} index - The index of the step to delete.\n */\n deleteStepByIndex(index) {\n this._steps.splice(index, 1);\n }\n\n /**\n * Initializes the workflow state with default values.\n */\n initializeWorkflowState() {\n this.results = [];\n this.exit_on_error = false;\n this.current_step = null;\n this.should_break = false;\n this.should_continue = false;\n this.should_pause = false;\n this.should_skip = false;\n this.status = this.getState('statuses.workflow').CREATED;\n this._steps = [];\n this.throw_on_empty = this.throw_on_empty;\n this.timing = {\n ...this.timing,\n create_time: new Date(),\n pause_time: null,\n resume_time: null,\n }\n\n const workflows = this.getState('workflows');\n workflows[this.id] = this;\n this.setState('workflows', workflows);\n\n this.log(\n this.getState('event_names.workflow').WORKFLOW_CREATED,\n `Workflow \"${this.name}\" initialized.`\n );\n }\n\n /**\n * Checks if the workflow has no steps.\n * @returns {boolean} True if the workflow is empty.\n */\n isEmpty() {\n return !this._steps || !this._steps.length\n }\n\n /**\n * Marks the workflow as complete and closes the current session.\n */\n markAsComplete() {\n super.markAsComplete();\n this.closeCurrentSession();\n }\n\n /**\n * Marks the workflow as created.\n * @returns {string} The CREATED status.\n */\n markAsCreated() {\n this.timing.create_time = new Date();\n \n this.log(\n this.getState('event_names.workflow').WORKFLOW_CREATED,\n `Workflow \"${this.name}\" created.`\n );\n\n return this.getState('statuses.workflow').CREATED;\n }\n\n /**\n * Marks the workflow as failed and closes the current session.\n */\n markAsFailed() {\n super.markAsFailed();\n this.closeCurrentSession();\n }\n\n /**\n * Marks the workflow as paused.\n */\n markAsPaused() {\n this.timing.pause_time = new Date();\n this.status = this.getState('statuses.workflow').PAUSED;\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_PAUSED,\n this.getState()\n );\n }\n \n /**\n * Marks the workflow as resumed.\n */\n markAsResumed() {\n this.timing.resume_time = new Date();\n this.status = this.getState('statuses.workflow').RUNNING;\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_RESUMED,\n this.getState()\n );\n }\n\n /**\n * Moves a step from one index to another.\n * @param {number} fromIndex - The current index of the step.\n * @param {number} toIndex - The target index for the step.\n */\n moveStep(fromIndex, toIndex) {\n const [step] = this._steps.splice(fromIndex, 1);\n this._steps.splice(toIndex, 0, step);\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_STEP_MOVED,\n this.getState()\n );\n }\n\n /**\n * Pauses the workflow execution.\n */\n pause() {\n this.should_pause = true;\n this.timing.pause_time = new Date();\n\n this.getState('events.workflow').emit(\n this.getState('event_names.workflow').WORKFLOW_PAUSED,\n this.getState()\n );\n }\n\n /**\n * Removes and returns the last step from the workflow.\n * @returns {Step} The last step.\n */\n popStep() {\n return this._steps.pop();\n }\n\n /**\n * Prepares a result object and adds it to the results array.\n * @param {string} message - Result message.\n * @param {*} data - Result data.\n */\n prepareResult(message, data) {\n this.results.push({ message, data });\n }\n\n /**\n * Adds a step to the end of the workflow.\n * @param {Step} step - The step to add.\n */\n pushStep(step) {\n this.addStep(step);\n }\n\n /**\n * Adds multiple steps to the end of the workflow.\n * @param {Step[]} steps - Array of steps to add.\n */\n pushSteps(steps) {\n steps.forEach(step => this.addStep(step));\n }\n\n /**\n * Removes and returns the first step from the workflow.\n * @returns {Step} The first step.\n */\n shiftStep() {\n return this._steps.shift();\n }\n\n /**\n * Adds a step to the beginning of the workflow.\n * @param {Step} step - The step to add.\n * @throws {Error} Throws if step is not a valid Step instance.\n */\n unshiftStep(step) {\n if (typeof step.getCallableType !== 'function') {\n throw new Error('Invalid step type. Must be an instance of Step.');\n }\n\n if (!this.steps_by_id || typeof this.steps_by_id !== 'object') {\n this.steps_by_id = {};\n }\n\n this.steps_by_id[step.id] = step;\n\n step.parentWorkflowId = this.id;\n this._steps.unshift(step);\n }\n\n /**\n * Gets the array of steps in the workflow.\n * @returns {Step[]} Array of steps.\n */\n get steps() {\n return this._steps;\n }\n\n /**\n * Sets the steps array by adding multiple steps.\n * @param {Step[]} steps - Array of steps to add.\n */\n set steps(steps) {\n steps.forEach((step, index) => {\n if (typeof step.getCallableType !== 'function') {\n throw new Error(`Invalid step type. Step at index ${index} is not an instance of Step.`);\n }\n });\n\n this.addSteps(steps);\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["uuidv4", "Base", "base_types", "Workflow", "__name", "name", "exit_on_error", "steps", "throw_on_empty", "i", "step_result", "error", "step", "result", "index", "stepId", "workflows", "fromIndex", "toIndex", "message", "data"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ronaldroe/micro-flow",
3
- "version": "0.0.9",
3
+ "version": "0.1.0",
4
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
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -1,12 +1,11 @@
1
1
  import { errors, warnings } from '../../enums/index.js';
2
- import Broadcast from './broadcast.js';
3
2
 
4
3
  /**
5
4
  * Event class for micro-flow
6
5
  * Provides a simple event emitter implementation for workflow steps and state changes.
7
6
  *
8
7
  * This class is used for emitting and listening to events within workflows and steps.
9
- * For broadcasting events across multiple workflows or listeners, see the Broadcast class.
8
+ * For broadcasting events across multiple workflows or listeners, it uses BroadcastChannel.
10
9
  */
11
10
  class Event extends EventTarget {
12
11
  /**
@@ -50,9 +49,9 @@ class Event extends EventTarget {
50
49
  const result = this.dispatchEvent(custom_event);
51
50
 
52
51
  try {
53
- const channel = new Broadcast(event_name);
54
- channel.send(workingData);
55
- channel.destroy();
52
+ const channel = new BroadcastChannel(event_name);
53
+ channel.postMessage(workingData);
54
+ channel.close();
56
55
  } catch (e) {
57
56
  console.warn(warnings.BROADCAST_FAILED, e);
58
57
  }
@@ -63,11 +62,19 @@ class Event extends EventTarget {
63
62
  * Listen for broadcasts on a given event name (channel).
64
63
  * @param {string} event_name - The event name/channel to listen for.
65
64
  * @param {Function} listener - Callback for broadcasted data.
66
- * @returns {Broadcast} Returns the Broadcast instance for manual control.
65
+ * @returns {BroadcastChannel} Returns the channel with send() and destroy() aliases.
67
66
  */
68
67
  onBroadcast(event_name, listener) {
69
- const channel = new Broadcast(event_name);
70
- channel.onReceive(listener);
68
+ const channel = new BroadcastChannel(event_name);
69
+ channel.onmessage = (event) => {
70
+ listener(event.data);
71
+ };
72
+ channel.send = (data) => {
73
+ channel.postMessage(data);
74
+ };
75
+ channel.destroy = () => {
76
+ channel.close();
77
+ };
71
78
  return channel;
72
79
  }
73
80
 
@@ -75,7 +82,7 @@ class Event extends EventTarget {
75
82
  * Listen for both local and broadcast events.
76
83
  * @param {string} event_name - The event name/channel to listen for.
77
84
  * @param {Function} listener - Callback for event data.
78
- * @returns {Object} Returns { event: this, broadcast: Broadcast instance }
85
+ * @returns {Object} Returns { event: this, broadcast: BroadcastChannel }
79
86
  */
80
87
  onAny(event_name, listener) {
81
88
  this.on(event_name, listener);
@@ -1,4 +1,3 @@
1
- export { default as Broadcast } from './broadcast.js';
2
1
  export { default as Event } from './event.js';
3
2
  export { default as StateEvent } from './state_event.js';
4
3
  export { default as StepEvent } from './step_event.js';
@@ -241,7 +241,10 @@ class State {
241
241
  * @returns {object} The reset state object.
242
242
  */
243
243
  static reset() {
244
- state = { ...defaultState };
244
+ state = {
245
+ ...defaultState,
246
+ workflows: {}, // Always create fresh to avoid shared reference mutation
247
+ };
245
248
  events.state.emit(event_names.state.RESET, { state });
246
249
  return state;
247
250
  }
@@ -40,7 +40,7 @@ export default class DelayStep extends Step {
40
40
 
41
41
  /**
42
42
  * Executes an absolute delay until the specified timestamp. If the timestamp is in the past, it continues immediately.
43
- * @returns {Promise<Object>} Resolves with a message object when delay completes.
43
+ * @returns {Promise<DelayStep>} Resolves with the DelayStep instance when delay completes.
44
44
  */
45
45
  async absolute() {
46
46
  const now = new Date();
@@ -85,7 +85,7 @@ export default class DelayStep extends Step {
85
85
 
86
86
  /**
87
87
  * Executes a relative delay for the specified duration. If the delay duration is zero or negative, it continues immediately.
88
- * @returns {Promise<Object>} Resolves with a message object when delay completes.
88
+ * @returns {Promise<DelayStep>} Resolves with the DelayStep instance when delay completes.
89
89
  */
90
90
  async relative() {
91
91
  if (this.relative_delay_ms <= 0) {
@@ -1,9 +1,9 @@
1
- import { LogicStep } from './index.js';
1
+ import LogicStep from './logic_step.js';
2
2
  import flow_control_types from '../../enums/flow_control_types.js';
3
3
  import { conditional_step_comparators } from '../../enums/index.js';
4
4
 
5
5
  /**
6
- * FlowControlStep class for controlling workflow execution flow (break, continue, skip, pause).
6
+ * FlowControlStep class for controlling workflow execution flow (break or skip).
7
7
  * @class FlowControlStep
8
8
  * @extends LogicStep
9
9
  */
@@ -1,8 +1,8 @@
1
+ export { default as Step } from './step.js';
2
+ export { default as LogicStep } from './logic_step.js';
1
3
  export { default as Case } from './case.js';
2
4
  export { default as ConditionalStep } from './conditional_step.js';
3
5
  export { default as DelayStep } from './delay_step.js';
4
6
  export { default as FlowControlStep } from './flow_control_step.js';
5
- export { default as LogicStep } from './logic_step.js';
6
7
  export { default as LoopStep } from './loop_step.js';
7
- export { default as Step } from './step.js';
8
8
  export { default as SwitchStep } from './switch_step.js';
@@ -140,7 +140,6 @@ export default class LogicStep extends Step {
140
140
  /**
141
141
  * Sets the conditional properties.
142
142
  * @param {Object} conditional - Conditional configuration object.
143
- * @throws {Error} Throws if conditional is invalid.
144
143
  */
145
144
  setConditional(conditional) {
146
145
  this.conditional = { subject: conditional.subject, operator: conditional.operator, value: conditional.value };
@@ -21,6 +21,7 @@ export default class LoopStep extends LogicStep {
21
21
  * @param {conditional_step_comparators|string} [options.conditional.operator] - Comparison operator.
22
22
  * @param {*} [options.conditional.value] - Value to compare against.
23
23
  * @param {string} [options.loop_type=loop_types.FOR_EACH] - Type of loop ('for', 'for_each', 'while', or 'generator').
24
+ * @param {number} [options.iterations=0] - Number of iterations to execute. Only used for 'for' loops.
24
25
  * @param {number} [options.max_iterations=1000] - Maximum number of iterations to prevent infinite loops.
25
26
  */
26
27
  constructor({
@@ -17,7 +17,7 @@ export default class Step extends Base {
17
17
  * @param {string} [options.name] - Name of the step.
18
18
  * @param {string} [options.step_type=step_types.ACTION] - Type of the step.
19
19
  * @param {Function|Step|Workflow} [options.callable=async () => {}] - Function, Step, or Workflow to execute.
20
- * @param {string} [options.sub_step_type=null] - Sub-type of the step.
20
+ * @param {sub_step_types|null} [options.sub_step_type=null] - Sub-type of the step (use values from the sub_step_types enum).
21
21
  */
22
22
  constructor({
23
23
  name,
@@ -1,4 +1,5 @@
1
- import { Base } from './index.js';
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import Base from './base.js';
2
3
  import { base_types } from '../enums/index.js';
3
4
 
4
5
  /**
@@ -29,6 +30,8 @@ export default class Workflow extends Base {
29
30
 
30
31
  this.exit_on_error = exit_on_error;
31
32
  this.throw_on_empty = throw_on_empty;
33
+ this.sessions = {};
34
+ this.current_session_id = null;
32
35
  }
33
36
 
34
37
  /**
@@ -38,6 +41,10 @@ export default class Workflow extends Base {
38
41
  * @throws {Error} Throws if workflow is empty and throw_on_empty is true.
39
42
  */
40
43
  async execute() {
44
+ if (!this.current_session_id) {
45
+ this.current_session_id = uuidv4();
46
+ }
47
+
41
48
  if (this.isEmpty()) {
42
49
  if (this.throw_on_empty) {
43
50
  throw new Error('Cannot execute an empty workflow');
@@ -51,12 +58,6 @@ export default class Workflow extends Base {
51
58
  this.markAsRunning();
52
59
 
53
60
  for (let i = 0; i < this._steps.length; i++) {
54
- if (this.should_pause) {
55
- this.markAsPaused();
56
- this.should_pause = false;
57
- return this;
58
- }
59
-
60
61
  if (this.should_break) {
61
62
  this.should_break = false;
62
63
  this.log(this.getState('event_names.workflow').WORKFLOW_BREAK_EXECUTED, `Workflow "${this.name}" execution broken at step ${this._steps[i].name} - ${this._steps[i].id}.`);
@@ -85,6 +86,12 @@ export default class Workflow extends Base {
85
86
  return this;
86
87
  }
87
88
  }
89
+
90
+ if (this.should_pause) {
91
+ this.markAsPaused();
92
+ this.should_pause = false;
93
+ return this;
94
+ }
88
95
  }
89
96
 
90
97
  this.markAsComplete();
@@ -155,6 +162,11 @@ export default class Workflow extends Base {
155
162
  * @param {number} index - The index at which to insert the step.
156
163
  */
157
164
  addStepAtIndex(step, index) {
165
+ if (!this.steps_by_id || typeof this.steps_by_id !== 'object') {
166
+ this.steps_by_id = {};
167
+ }
168
+
169
+ this.steps_by_id[step.id] = step;
158
170
  step.parentWorkflowId = this.id;
159
171
  this._steps.splice(index, 0, step);
160
172
  }
@@ -174,6 +186,23 @@ export default class Workflow extends Base {
174
186
  this._steps = [];
175
187
  }
176
188
 
189
+ /**
190
+ * Closes the current session and stores a snapshot of the workflow state.
191
+ */
192
+ closeCurrentSession() {
193
+ if (!this.current_session_id) {
194
+ return;
195
+ }
196
+
197
+ this.sessions[this.current_session_id] = {
198
+ results: [...this.results],
199
+ status: this.status,
200
+ timing: { ...this.timing },
201
+ closed_at: new Date()
202
+ };
203
+ this.current_session_id = null;
204
+ }
205
+
177
206
  /**
178
207
  * Deletes a step from the workflow by its ID.
179
208
  * @param {string} stepId - The ID of the step to delete.
@@ -228,7 +257,15 @@ export default class Workflow extends Base {
228
257
  isEmpty() {
229
258
  return !this._steps || !this._steps.length
230
259
  }
231
-
260
+
261
+ /**
262
+ * Marks the workflow as complete and closes the current session.
263
+ */
264
+ markAsComplete() {
265
+ super.markAsComplete();
266
+ this.closeCurrentSession();
267
+ }
268
+
232
269
  /**
233
270
  * Marks the workflow as created.
234
271
  * @returns {string} The CREATED status.
@@ -243,7 +280,15 @@ export default class Workflow extends Base {
243
280
 
244
281
  return this.getState('statuses.workflow').CREATED;
245
282
  }
246
-
283
+
284
+ /**
285
+ * Marks the workflow as failed and closes the current session.
286
+ */
287
+ markAsFailed() {
288
+ super.markAsFailed();
289
+ this.closeCurrentSession();
290
+ }
291
+
247
292
  /**
248
293
  * Marks the workflow as paused.
249
294
  */
@@ -1,57 +0,0 @@
1
- /**
2
- * Broadcast class provides a simplified wrapper around the BroadcastChannel API
3
- * for cross-context communication (e.g., between tabs, windows, workers).
4
- *
5
- * This class allows you to send and receive messages across different browsing contexts
6
- * that share the same origin. It encapsulates the creation and management of a BroadcastChannel,
7
- * providing a simplified API for sending and receiving messages.
8
- *
9
- * @class Broadcast
10
- * @extends BroadcastChannel
11
- */
12
- export default class Broadcast extends BroadcastChannel {
13
- /**
14
- * Creates a new Broadcast instance for a named channel.
15
- *
16
- * @constructor
17
- * @param {string} channelName - The name of the broadcast channel to create or connect to.
18
- * Multiple Broadcast instances with the same channel name can communicate with each other.
19
- */
20
- constructor(channelName) {
21
- super(channelName);
22
- }
23
-
24
- /**
25
- * Sends data to all other contexts listening on this channel.
26
- *
27
- * @param {*} data - The data to broadcast. Can be any structured-cloneable value
28
- * (primitives, objects, arrays, etc.). Functions and DOM nodes cannot be sent.
29
- * @returns {void}
30
- */
31
- send(data) {
32
- this.postMessage(data);
33
- }
34
-
35
- /**
36
- * Registers a callback to handle incoming messages on this channel.
37
- *
38
- * @param {Function} callback - Function to call when a message is received.
39
- * Receives the message data as its only parameter.
40
- * @returns {void}
41
- */
42
- onReceive(callback) {
43
- this.onmessage = (event) => {
44
- callback(event.data);
45
- };
46
- }
47
-
48
- /**
49
- * Closes the broadcast channel and releases its resources.
50
- * After calling this method, the Broadcast instance can no longer send or receive messages.
51
- *
52
- * @returns {void}
53
- */
54
- destroy() {
55
- this.close();
56
- }
57
- }