Skip to main content

Operator

A flexible and powerful workflow execution engine for JavaScript that enables you to define and run complex workflows with state management, custom actions, and plugin support.

Overview

Operator is a sophisticated JavaScript library for building complex, extensible workflows with advanced state management, plugin support, and dynamic execution capabilities. It provides a flexible framework for creating multi-step processes with intricate logic and customizable behavior.

Features

  • 🔄 Workflow Orchestration: Define and execute multi-step workflows with complex state management
  • 🧩 Plugin System: Extend functionality through a robust plugin architecture
  • 🎯 Custom Actions: Register and use custom actions with namespaced organization
  • 🔄 Iteration Support: Execute steps sequentially or in parallel over collections
  • 🔀 Conditional Flow: Dynamic workflow paths based on state using JSON Logic
  • 📦 State Management: Sophisticated state handling with dot notation support
  • 🔌 Extensible: Easy to extend with custom plugins and actions

Installation

npm install operator-engine

Quick Start

import Operator from 'operator-engine';

// Define your workflow
const workflow = {
initialState: {
users: ['Alice', 'Bob', 'Charlie']
},
steps: [
{
id: 'greet',
task: {
from: 'greeting',
use: 'sayHello'
},
iterate: {
source: 'users',
itemAs: '$user'
},
output: {
to: 'greetings',
mode: 'push'
}
}
]
};

// Create operator instance
const operator = new Operator();

// Register custom actions
Operator.registerAction('greeting', {
sayHello: async (name) => `Hello, ${name}!`
});

// Execute workflow
const result = await operator.run(workflow);

Core Concepts

Workflow Structure

A workflow is defined by an instructions object with the following structure:

{
initialState: Object, // Initial state data
steps: Array, // Array of step definitions
plugins: Array, // Optional array of plugin names
options: Object // Optional configuration object
}

Steps

Steps are the building blocks of your workflow. Each step represents a single unit of work:

{
id: 'stepId', // Unique step identifier
task: { // Task definition
from: 'namespace', // Action namespace
use: 'actionName' // Action function name
},
input: { // Input configuration
args: [] // Array of argument specifications
},
output: { // Output configuration
to: 'resultPath', // State path for result
mode: 'merge', // Output mode (merge/push/append)
transform: {} // Optional transformation spec
},
iterate: { // Optional iteration configuration
source: 'arrayPath', // Path to source array
itemAs: '$item', // Item variable name
indexAs: '$index', // Index variable name
parallel: false // Parallel execution flag
},
next: 'nextStepId' // Next step specification
}

Custom Actions

Register custom actions to extend functionality:

Operator.registerAction('math', {
add: async (a, b) => a + b,
multiply: async (a, b) => a * b
});

Plugins

Create plugins to add cross-cutting concerns:

class LoggingPlugin {
onBeforeAll(state) {
console.log('Workflow starting', state);
}

onBeforeEach(stepId, state) {
console.log(`Executing step: ${stepId}`);
}

onAfterEach(stepId, state) {
console.log(`Completed step: ${stepId}`);
}

onAfterAll(state) {
console.log('Workflow completed', state);
}
}

Operator.registerPlugin(LoggingPlugin);

Advanced Features

JSON Logic Integration

Use JSON Logic expressions for dynamic values and conditions:

{
id: 'conditional',
next: {
if: [
{ ">": [{ var: "user.age" }, 18] },
"adult-flow",
"minor-flow"
]
}
}

Iteration Modes

Execute iterations sequentially or in parallel:

{
id: 'process-users',
iterate: {
source: 'users',
itemAs: '$user',
parallel: true // Enable parallel execution
}
}

Nested Workflows

Execute workflows within workflows using the built-in runInstructions action:

{
id: 'nested-workflow',
task: {
from: 'operator',
use: 'runInstructions'
},
input: {
args: [{
initialState: { /* ... */ },
steps: [ /* ... */ ]
}]
}
}

Performance Considerations

  • Supports both sequential and parallel execution of iterations
  • Lightweight JSON Logic evaluation
  • Minimal overhead for workflow definition and execution

Error Handling

The Operator engine provides detailed error messages for common issues:

  • Invalid step configurations
  • Missing actions or plugins
  • State path errors
  • Invalid JSON Logic expressions

Best Practices

  1. Organize Actions: Group related actions under meaningful namespaces
  2. State Structure: Plan your state structure carefully and use dot notation paths consistently
  3. Step Isolation: Keep steps focused on single responsibilities
  4. Plugin Hooks: Use plugin hooks for cross-cutting concerns rather than mixing them into steps
  5. Error Handling: Implement proper error handling in your actions and plugins

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

For issues, feature requests, or discussions, please open an issue on our GitHub repository.

License

MIT