@onlineapps/conn-orch-cookbook 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +281 -0
- package/examples/basicUsage.js +84 -0
- package/examples/cookbook-experimental.json +169 -0
- package/examples/cookbook-generalized-experimental.json +180 -0
- package/package.json +61 -0
- package/src/index.js +230 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ONLINE APPS s.r.o.; info@onlineapps.cz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
# @onlineapps/connector-cookbook
|
|
2
|
+
|
|
3
|
+
> Complete cookbook toolkit for ALL services - unified wrapper including core, executor, transformer, and router functionality
|
|
4
|
+
|
|
5
|
+
## 🚀 Version 2.0 - Major Update
|
|
6
|
+
|
|
7
|
+
The `connector-cookbook` package (v2.0) is now a complete toolkit that combines all cookbook functionality in one unified package. This ensures architectural consistency across ALL services including infrastructure components like workflow_launcher.
|
|
8
|
+
|
|
9
|
+
### What's New in v2.0
|
|
10
|
+
|
|
11
|
+
- **Modular architecture** - Four specialized modules combined
|
|
12
|
+
- **Backward compatibility** - All v1.x APIs still work
|
|
13
|
+
- **Unified approach** - Same package for ALL services (infrastructure and business)
|
|
14
|
+
- **Complete toolkit** - Parsing, execution, transformation, and routing
|
|
15
|
+
|
|
16
|
+
### Why Unified Approach?
|
|
17
|
+
|
|
18
|
+
Per architectural decision, ALL services including workflow_launcher use this single package to ensure:
|
|
19
|
+
- **Consistency** - Same API everywhere
|
|
20
|
+
- **Predictability** - No special cases
|
|
21
|
+
- **Maintainability** - Single source of truth
|
|
22
|
+
- **Simplicity** - One package to learn
|
|
23
|
+
|
|
24
|
+
## 📦 Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install @onlineapps/connector-cookbook
|
|
28
|
+
# or
|
|
29
|
+
yarn add @onlineapps/connector-cookbook
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## 🔧 Quick Start
|
|
33
|
+
|
|
34
|
+
### Backward Compatible (v1.x style)
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
const {
|
|
38
|
+
parseCookbookFromFile,
|
|
39
|
+
validateCookbook
|
|
40
|
+
} = require('@onlineapps/connector-cookbook');
|
|
41
|
+
|
|
42
|
+
// Works exactly as before
|
|
43
|
+
const cookbook = await parseCookbookFromFile('./workflow.json');
|
|
44
|
+
validateCookbook(cookbook);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### New Modular Approach (v2.0)
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
const cookbook = require('@onlineapps/connector-cookbook');
|
|
51
|
+
|
|
52
|
+
// Use specific modules
|
|
53
|
+
const { CookbookExecutor } = cookbook.executor;
|
|
54
|
+
const { CookbookRouter } = cookbook.router;
|
|
55
|
+
const { CookbookGenerator } = cookbook.transformer;
|
|
56
|
+
|
|
57
|
+
// Or use factory functions
|
|
58
|
+
const processor = cookbook.createProcessor({
|
|
59
|
+
cookbook: myCookbook,
|
|
60
|
+
maxRetries: 3
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 📚 Included Modules
|
|
65
|
+
|
|
66
|
+
### 1. Core Module (@onlineapps/cookbook-core)
|
|
67
|
+
- JSON Schema validation
|
|
68
|
+
- Recursive step validation
|
|
69
|
+
- Parsing from file/object
|
|
70
|
+
- Lightweight (~50KB)
|
|
71
|
+
|
|
72
|
+
### 2. Executor Module (@onlineapps/cookbook-executor)
|
|
73
|
+
- Workflow execution engine
|
|
74
|
+
- Context management
|
|
75
|
+
- Variable resolution ($api_input, $steps)
|
|
76
|
+
- Step processing for all types
|
|
77
|
+
|
|
78
|
+
### 3. Transformer Module (@onlineapps/cookbook-transformer)
|
|
79
|
+
- OpenAPI to cookbook generation
|
|
80
|
+
- API spec analysis
|
|
81
|
+
- Response mapping
|
|
82
|
+
- JSONPath transformations
|
|
83
|
+
|
|
84
|
+
### 4. Router Module (@onlineapps/cookbook-router)
|
|
85
|
+
- Service discovery
|
|
86
|
+
- Queue management
|
|
87
|
+
- Retry with exponential backoff
|
|
88
|
+
- Dead letter queue handling
|
|
89
|
+
|
|
90
|
+
## 🎯 Usage Examples
|
|
91
|
+
|
|
92
|
+
### Complete Service Implementation
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const cookbook = require('@onlineapps/connector-cookbook');
|
|
96
|
+
const MQClient = require('@onlineapps/connector-mq-client');
|
|
97
|
+
const RegistryClient = require('@onlineapps/connector-registry-client');
|
|
98
|
+
|
|
99
|
+
class MyService {
|
|
100
|
+
constructor() {
|
|
101
|
+
// Initialize clients
|
|
102
|
+
this.mqClient = new MQClient(mqConfig);
|
|
103
|
+
this.registryClient = new RegistryClient(registryConfig);
|
|
104
|
+
|
|
105
|
+
// Create router for message handling
|
|
106
|
+
this.router = cookbook.createRouter(
|
|
107
|
+
this.mqClient,
|
|
108
|
+
this.registryClient
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async processWorkflow(message) {
|
|
113
|
+
// Parse and validate
|
|
114
|
+
const workflowDef = cookbook.parseCookbookFromObject(message.cookbook);
|
|
115
|
+
|
|
116
|
+
// Create executor
|
|
117
|
+
const executor = new cookbook.CookbookExecutor(workflowDef);
|
|
118
|
+
|
|
119
|
+
// Execute workflow
|
|
120
|
+
const result = await executor.execute(message.context);
|
|
121
|
+
|
|
122
|
+
// Route to next service
|
|
123
|
+
await this.router.routeToNextService(
|
|
124
|
+
workflowDef,
|
|
125
|
+
result,
|
|
126
|
+
message.current_step
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Infrastructure Service (workflow_launcher)
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
// workflow_launcher uses the SAME package
|
|
136
|
+
const cookbook = require('@onlineapps/connector-cookbook');
|
|
137
|
+
|
|
138
|
+
class WorkflowLauncher {
|
|
139
|
+
async handleWorkflowInit(message) {
|
|
140
|
+
// Validate cookbook
|
|
141
|
+
cookbook.validateCookbook(message.cookbook);
|
|
142
|
+
|
|
143
|
+
// Route to first service
|
|
144
|
+
await this.router.routeWorkflow(
|
|
145
|
+
message.cookbook,
|
|
146
|
+
message.context
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### OpenAPI Integration
|
|
153
|
+
|
|
154
|
+
```javascript
|
|
155
|
+
const { CookbookGenerator } = require('@onlineapps/connector-cookbook');
|
|
156
|
+
|
|
157
|
+
const generator = new CookbookGenerator({
|
|
158
|
+
defaultTimeout: 10000,
|
|
159
|
+
defaultRetry: { maxAttempts: 3, delayMs: 2000 }
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
// Generate cookbook from OpenAPI spec
|
|
163
|
+
const openApiSpec = require('./api-spec.json');
|
|
164
|
+
const cookbook = generator.generate(openApiSpec);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## 📖 Cookbook Structure
|
|
168
|
+
|
|
169
|
+
### Basic Example
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"version": "1.0.0",
|
|
173
|
+
"api_input": {
|
|
174
|
+
"customer": "ACME Corp",
|
|
175
|
+
"amount": 1000
|
|
176
|
+
},
|
|
177
|
+
"steps": [
|
|
178
|
+
{
|
|
179
|
+
"id": "invoice_step",
|
|
180
|
+
"type": "task",
|
|
181
|
+
"service": "invoice_service",
|
|
182
|
+
"input": {
|
|
183
|
+
"customer": "$api_input.customer",
|
|
184
|
+
"amount": "$api_input.amount"
|
|
185
|
+
},
|
|
186
|
+
"output": {
|
|
187
|
+
"invoice_id": "$.invoice_id"
|
|
188
|
+
},
|
|
189
|
+
"retry": {
|
|
190
|
+
"maxAttempts": 3,
|
|
191
|
+
"delayMs": 2000
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## 📚 Step Types
|
|
199
|
+
|
|
200
|
+
All 7 step types are fully supported:
|
|
201
|
+
|
|
202
|
+
- **task** - Service operation execution
|
|
203
|
+
- **foreach** - Iteration over arrays
|
|
204
|
+
- **fork_join** - Parallel execution
|
|
205
|
+
- **switch** - Conditional branching
|
|
206
|
+
- **sub_workflow** - Nested workflows
|
|
207
|
+
- **wait** - Time delays
|
|
208
|
+
- **dispatch** - Webhook dispatching
|
|
209
|
+
|
|
210
|
+
## 🔄 Migration from v1.x
|
|
211
|
+
|
|
212
|
+
Version 2.0 maintains full backward compatibility. Existing code continues to work without changes:
|
|
213
|
+
|
|
214
|
+
```javascript
|
|
215
|
+
// This still works exactly as before
|
|
216
|
+
const { parseCookbookFromFile } = require('@onlineapps/connector-cookbook');
|
|
217
|
+
const cookbook = await parseCookbookFromFile('./workflow.json');
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
To access new features, use the modular exports:
|
|
221
|
+
|
|
222
|
+
```javascript
|
|
223
|
+
// New modular approach
|
|
224
|
+
const { executor, router, transformer } = require('@onlineapps/connector-cookbook');
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## 📋 API Reference
|
|
228
|
+
|
|
229
|
+
### Legacy Exports (v1.x compatible)
|
|
230
|
+
- `parseCookbookFromFile(path)` - Parse from file
|
|
231
|
+
- `parseCookbookFromObject(obj)` - Parse from object
|
|
232
|
+
- `validateCookbook(cookbook)` - Validate structure
|
|
233
|
+
- `CookbookValidationError` - Error class
|
|
234
|
+
|
|
235
|
+
### New Modular Exports (v2.0)
|
|
236
|
+
- `core` - Core parsing and validation
|
|
237
|
+
- `executor` - Workflow execution
|
|
238
|
+
- `transformer` - OpenAPI transformation
|
|
239
|
+
- `router` - Message routing
|
|
240
|
+
- `createProcessor(options)` - Factory for complete processor
|
|
241
|
+
- `createRouter(mqClient, registryClient, options)` - Factory for router
|
|
242
|
+
|
|
243
|
+
## 🧪 Testing
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
npm test # Run all tests
|
|
247
|
+
npm run test:unit # Unit tests only
|
|
248
|
+
npm run test:integration # Integration tests
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## ⚠️ Important Notes
|
|
252
|
+
|
|
253
|
+
### Schema Validation Strictness
|
|
254
|
+
The current schema validation is very strict. See [Schema Audit Report](/shared/cookbook/cookbook-core/docs/SCHEMA_AUDIT.md) for detailed analysis and recommendations.
|
|
255
|
+
|
|
256
|
+
**Known Issues:**
|
|
257
|
+
- All step types incorrectly require `service`, `input`, and `output` fields
|
|
258
|
+
- `type` field should be required but isn't
|
|
259
|
+
- Some control flow steps (foreach, switch) have unnecessary field requirements
|
|
260
|
+
|
|
261
|
+
**Workaround:** Until schema is updated, include all required fields even if not used:
|
|
262
|
+
```javascript
|
|
263
|
+
{
|
|
264
|
+
type: 'foreach',
|
|
265
|
+
service: 'dummy-service', // Not actually used
|
|
266
|
+
input: {}, // Not actually used
|
|
267
|
+
output: {}, // Optional but may be required by schema
|
|
268
|
+
// ... actual foreach fields
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## 📄 License
|
|
273
|
+
|
|
274
|
+
PROPRIETARY - All rights reserved
|
|
275
|
+
|
|
276
|
+
## 🤝 Contributing
|
|
277
|
+
|
|
278
|
+
Internal package - contributions via internal GitLab only.
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
*For detailed documentation on individual modules, see their respective README files in the shared/ directory.*
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* basicUsage.js
|
|
3
|
+
*
|
|
4
|
+
* Example demonstrating full lifecycle of ServiceRegistryClient:
|
|
5
|
+
* 1. Load environment variables
|
|
6
|
+
* 2. Instantiate client
|
|
7
|
+
* 3. Initialize (setup queues and start listening for requests)
|
|
8
|
+
* 4. Register event listeners (apiDescriptionRequest, heartbeatSent, apiDescriptionSent, error)
|
|
9
|
+
* 5. Start heartbeat loop
|
|
10
|
+
* 6. Graceful shutdown on process signals
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Load environment variables from .env file
|
|
14
|
+
require('dotenv').config();
|
|
15
|
+
|
|
16
|
+
const { ServiceRegistryClient, EVENTS } = require('agent-registry-client');
|
|
17
|
+
|
|
18
|
+
// Step 1: Create a new ServiceRegistryClient instance
|
|
19
|
+
const registryClient = new ServiceRegistryClient({
|
|
20
|
+
amqpUrl: process.env.AMQP_URL,
|
|
21
|
+
serviceName: process.env.SERVICE_NAME || 'invoicing',
|
|
22
|
+
version: process.env.SERVICE_VERSION || '1.0.0',
|
|
23
|
+
heartbeatInterval: parseInt(process.env.HEARTBEAT_INTERVAL, 10) || 10000,
|
|
24
|
+
apiQueue: process.env.API_QUEUE,
|
|
25
|
+
registryQueue: process.env.REGISTRY_QUEUE
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Step 2: Register event listeners
|
|
29
|
+
registryClient.on(EVENTS.HEARTBEAT_SENT, (msg) => {
|
|
30
|
+
console.log(`[Heartbeat] Sent at ${msg.timestamp} for ${msg.serviceName}@${msg.version}`);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
registryClient.on(EVENTS.API_DESCRIPTION_REQUEST, async (payload) => {
|
|
34
|
+
console.log(`[API Description Request] for ${payload.serviceName}@${payload.version}`);
|
|
35
|
+
// Load local API description (from file or in-memory)
|
|
36
|
+
const apiDesc = await loadLocalApiDescription();
|
|
37
|
+
await registryClient.sendApiDescription(apiDesc);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
registryClient.on(EVENTS.API_DESCRIPTION_SENT, (msg) => {
|
|
41
|
+
console.log(`[API Description Sent] at ${msg.timestamp} for ${msg.serviceName}@${msg.version}`);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
registryClient.on(EVENTS.ERROR, (err) => {
|
|
45
|
+
console.error('[RegistryClient Error]', err);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
(async () => {
|
|
49
|
+
try {
|
|
50
|
+
// Step 3: Initialize client (setup queues and listeners)
|
|
51
|
+
await registryClient.init();
|
|
52
|
+
console.log('RegistryClient initialized: queues are ready.');
|
|
53
|
+
|
|
54
|
+
// Step 4: Start heartbeat loop
|
|
55
|
+
registryClient.startHeartbeat();
|
|
56
|
+
console.log('Heartbeat loop started.');
|
|
57
|
+
|
|
58
|
+
// Step 5: Graceful shutdown on SIGINT/SIGTERM
|
|
59
|
+
const shutdown = async () => {
|
|
60
|
+
console.log('Shutting down RegistryClient...');
|
|
61
|
+
await registryClient.close();
|
|
62
|
+
process.exit(0);
|
|
63
|
+
};
|
|
64
|
+
process.on('SIGINT', shutdown);
|
|
65
|
+
process.on('SIGTERM', shutdown);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error('Failed to initialize RegistryClient', err);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
})();
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Helper: Load local API description
|
|
74
|
+
* In a real application, this could read from a JSON file,
|
|
75
|
+
* introspect OpenAPI spec, or build dynamically.
|
|
76
|
+
*/
|
|
77
|
+
async function loadLocalApiDescription() {
|
|
78
|
+
return {
|
|
79
|
+
endpoints: [
|
|
80
|
+
{ path: '/invoices', method: 'POST', description: 'Create a new invoice' },
|
|
81
|
+
{ path: '/invoices/:id', method: 'GET', description: 'Retrieve invoice by ID' }
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"api_input": {
|
|
4
|
+
"customer": "ACME Corp.",
|
|
5
|
+
"amount": 1000,
|
|
6
|
+
"currency": "USD",
|
|
7
|
+
"requested_formats": ["html", "pdf"],
|
|
8
|
+
"items": [
|
|
9
|
+
{ "sku": "A1", "qty": 2 },
|
|
10
|
+
{ "sku": "B2", "qty": 1 }
|
|
11
|
+
],
|
|
12
|
+
"priority": "high",
|
|
13
|
+
"order_details": {
|
|
14
|
+
"order_id": "ORD-123",
|
|
15
|
+
"date": "2025-06-01"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"workflow_steps": [
|
|
19
|
+
{
|
|
20
|
+
"step": "1",
|
|
21
|
+
"type": "task",
|
|
22
|
+
"service": "invoice_service",
|
|
23
|
+
"queue": "invoice.process",
|
|
24
|
+
"input_mapping": {
|
|
25
|
+
"customer": "api_input.customer",
|
|
26
|
+
"amount": "api_input.amount",
|
|
27
|
+
"currency": "api_input.currency"
|
|
28
|
+
},
|
|
29
|
+
"output_schema": {
|
|
30
|
+
"invoice_id": "invoice_service.invoice_id",
|
|
31
|
+
"total_amount": "invoice_service.total_amount"
|
|
32
|
+
},
|
|
33
|
+
"retry": {
|
|
34
|
+
"max_attempts": 3,
|
|
35
|
+
"delay": 2000
|
|
36
|
+
},
|
|
37
|
+
"timeout": 10000
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"step": "2",
|
|
41
|
+
"type": "foreach",
|
|
42
|
+
"iterator": "api_input.items",
|
|
43
|
+
"steps": [
|
|
44
|
+
{
|
|
45
|
+
"step": "2.1",
|
|
46
|
+
"type": "task",
|
|
47
|
+
"service": "item_processing_service",
|
|
48
|
+
"queue": "item.process",
|
|
49
|
+
"input_mapping": {
|
|
50
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
51
|
+
"item": "foreach.item"
|
|
52
|
+
},
|
|
53
|
+
"output_schema": {
|
|
54
|
+
"processed_item": "item_processing_service.result"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"step": "3",
|
|
61
|
+
"type": "fork_join",
|
|
62
|
+
"fork": [
|
|
63
|
+
{
|
|
64
|
+
"service": "template_service",
|
|
65
|
+
"queue": "template.generate",
|
|
66
|
+
"input_mapping": {
|
|
67
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
68
|
+
"customer": "api_input.customer"
|
|
69
|
+
},
|
|
70
|
+
"output_schema": {
|
|
71
|
+
"generated_html": "template_service.generated_html"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"service": "analytics_service",
|
|
76
|
+
"queue": "analytics.process",
|
|
77
|
+
"input_mapping": {
|
|
78
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
79
|
+
"amount": "workflow_steps[0].result.total_amount"
|
|
80
|
+
},
|
|
81
|
+
"output_schema": {
|
|
82
|
+
"analytics_report": "analytics_service.report"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"join": {
|
|
87
|
+
"strategy": "merge",
|
|
88
|
+
"result_mapping": {
|
|
89
|
+
"combined_html": ["fork[0].generated_html"],
|
|
90
|
+
"analytics": ["fork[1].analytics_report"]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"step": "4",
|
|
96
|
+
"type": "switch",
|
|
97
|
+
"expression": "api_input.priority",
|
|
98
|
+
"cases": {
|
|
99
|
+
"high": {
|
|
100
|
+
"service": "priority_service",
|
|
101
|
+
"queue": "priority.process",
|
|
102
|
+
"input_mapping": {
|
|
103
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
104
|
+
"priority_flag": "api_input.priority"
|
|
105
|
+
},
|
|
106
|
+
"output_schema": {
|
|
107
|
+
"priority_result": "priority_service.result"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"low": {
|
|
111
|
+
"service": "standard_service",
|
|
112
|
+
"queue": "standard.process",
|
|
113
|
+
"input_mapping": {
|
|
114
|
+
"invoice_id": "workflow_steps[0].result.invoice_id"
|
|
115
|
+
},
|
|
116
|
+
"output_schema": {
|
|
117
|
+
"standard_result": "standard_service.result"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"default": {
|
|
122
|
+
"service": "fallback_service",
|
|
123
|
+
"queue": "fallback.process",
|
|
124
|
+
"input_mapping": {
|
|
125
|
+
"invoice_id": "workflow_steps[0].result.invoice_id"
|
|
126
|
+
},
|
|
127
|
+
"output_schema": {
|
|
128
|
+
"fallback_result": "fallback_service.result"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"step": "5",
|
|
134
|
+
"type": "sub_workflow",
|
|
135
|
+
"workflow_id": "generate_invoice_pdf",
|
|
136
|
+
"parameters": {
|
|
137
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
138
|
+
"html_content": "workflow_steps[3].result.combined_html"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"step": "6",
|
|
143
|
+
"type": "wait",
|
|
144
|
+
"duration": 30000,
|
|
145
|
+
"message": "Čekání 30 s než se vygeneruje PDF na úložišti"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"step": "7",
|
|
149
|
+
"type": "task",
|
|
150
|
+
"service": "pdf_service",
|
|
151
|
+
"queue": "pdf.convert",
|
|
152
|
+
"input_mapping": {
|
|
153
|
+
"html": "workflow_steps[3].result.combined_html",
|
|
154
|
+
"invoice_id": "workflow_steps[0].result.invoice_id"
|
|
155
|
+
},
|
|
156
|
+
"output_schema": {
|
|
157
|
+
"pdf_url": "pdf_service.pdf_url"
|
|
158
|
+
},
|
|
159
|
+
"retry": {
|
|
160
|
+
"max_attempts": 2,
|
|
161
|
+
"delay": 1000
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
"final_delivery": {
|
|
166
|
+
"method": "webhook",
|
|
167
|
+
"target": "https://client.example.com/webhook"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0", # Version of the workflow schema X.X.X
|
|
3
|
+
"api_input": { # Input parameters for the API call
|
|
4
|
+
"customer": "ACME Corp.",
|
|
5
|
+
"amount": 1000,
|
|
6
|
+
"currency": "USD",
|
|
7
|
+
"requested_formats": ["html", "pdf"],
|
|
8
|
+
"items": [
|
|
9
|
+
{ "sku": "A1", "qty": 2 },
|
|
10
|
+
{ "sku": "B2", "qty": 1 }
|
|
11
|
+
],
|
|
12
|
+
"priority": "high",
|
|
13
|
+
"order_details": {
|
|
14
|
+
"order_id": "ORD-123",
|
|
15
|
+
"date": "2025-06-01"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"general_workflow": [ # Steps in the workflow
|
|
19
|
+
{ # typical step structure
|
|
20
|
+
"step": "1", # Unique identifier for the step ("1", "A", etc.)
|
|
21
|
+
"type": "task", # Type of the step (task, foreach, fork_join, sub_workflow, switch, wait, dispatch)
|
|
22
|
+
"service": "invoice_service", # Service and its queue to be called
|
|
23
|
+
"input_mapping": { # Mapping of input parameters to the service
|
|
24
|
+
"customer": "api_input.customer",
|
|
25
|
+
"amount": "api_input.amount",
|
|
26
|
+
"currency": "api_input.currency"
|
|
27
|
+
},
|
|
28
|
+
"output_schema": { # Schema of the output from the service
|
|
29
|
+
"invoice_id": "this.invoice_id", # Reference to the output field, "this" refers to the current step's output
|
|
30
|
+
"total_amount": "this.total_amount"
|
|
31
|
+
},
|
|
32
|
+
"retry": { # Retry configuration for the step
|
|
33
|
+
"max_attempts": 3, # Maximum number of retry attempts
|
|
34
|
+
"delay": 2000 # Delay between retries in milliseconds
|
|
35
|
+
},
|
|
36
|
+
"timeout": 10000 # Timeout for the step in milliseconds
|
|
37
|
+
},
|
|
38
|
+
{ # Foreach step to process each item in the input array
|
|
39
|
+
"step": "B",
|
|
40
|
+
"type": "foreach",
|
|
41
|
+
"input_iterator": "api_input.items", # Input for the foreach loop, in case of an array
|
|
42
|
+
"workflow": [
|
|
43
|
+
{
|
|
44
|
+
"step": "2.1",
|
|
45
|
+
"type": "task",
|
|
46
|
+
"service": "item_processing_service",
|
|
47
|
+
"input_mapping": {
|
|
48
|
+
"invoice_id": "parent.previous.result.invoice_id", # Reference to the parent and previous step's output
|
|
49
|
+
"item": "foreach.item" # Reference to the current item in the foreach loop
|
|
50
|
+
},
|
|
51
|
+
"output_schema": {
|
|
52
|
+
"processed_item": "this.result"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
"output_mapping": {
|
|
57
|
+
"items": "foreach.processed_item" # Output schema for the foreach step}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"step": "3X",
|
|
61
|
+
"type": "fork_join",
|
|
62
|
+
"fork": [
|
|
63
|
+
{
|
|
64
|
+
"service": "template_service",
|
|
65
|
+
"queue": "template.generate",
|
|
66
|
+
"input_mapping": {
|
|
67
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
68
|
+
"customer": "api_input.customer"
|
|
69
|
+
},
|
|
70
|
+
"output_schema": {
|
|
71
|
+
"generated_html": "template_service.generated_html"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"service": "analytics_service",
|
|
76
|
+
"queue": "analytics.process",
|
|
77
|
+
"input_mapping": {
|
|
78
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
79
|
+
"amount": "workflow_steps[0].result.total_amount"
|
|
80
|
+
},
|
|
81
|
+
"output_schema": {
|
|
82
|
+
"analytics_report": "analytics_service.report"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"join": {
|
|
87
|
+
"strategy": "merge",
|
|
88
|
+
"result_mapping": {
|
|
89
|
+
"combined_html": ["fork[0].generated_html"],
|
|
90
|
+
"analytics": ["fork[1].analytics_report"]
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"step": "4",
|
|
96
|
+
"type": "switch",
|
|
97
|
+
"expression": "api_input.priority",
|
|
98
|
+
"cases": {
|
|
99
|
+
"high": {
|
|
100
|
+
"service": "priority_service",
|
|
101
|
+
"queue": "priority.process",
|
|
102
|
+
"input_mapping": {
|
|
103
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
104
|
+
"priority_flag": "api_input.priority"
|
|
105
|
+
},
|
|
106
|
+
"output_schema": {
|
|
107
|
+
"priority_result": "priority_service.result"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"low": {
|
|
111
|
+
"service": "standard_service",
|
|
112
|
+
"queue": "standard.process",
|
|
113
|
+
"input_mapping": {
|
|
114
|
+
"invoice_id": "workflow_steps[0].result.invoice_id"
|
|
115
|
+
},
|
|
116
|
+
"output_schema": {
|
|
117
|
+
"standard_result": "standard_service.result"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
"default": {
|
|
122
|
+
"service": "fallback_service",
|
|
123
|
+
"queue": "fallback.process",
|
|
124
|
+
"input_mapping": {
|
|
125
|
+
"invoice_id": "workflow_steps[0].result.invoice_id"
|
|
126
|
+
},
|
|
127
|
+
"output_schema": {
|
|
128
|
+
"fallback_result": "fallback_service.result"
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
"step": "5",
|
|
134
|
+
"type": "sub_workflow",
|
|
135
|
+
"workflow_id": "generate_invoice_pdf",
|
|
136
|
+
"parameters": {
|
|
137
|
+
"invoice_id": "workflow_steps[0].result.invoice_id",
|
|
138
|
+
"html_content": "workflow_steps[3].result.combined_html"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"step": "6",
|
|
143
|
+
"type": "wait",
|
|
144
|
+
"duration": 30000,
|
|
145
|
+
"message": "Čekání 30 s než se vygeneruje PDF na úložišti"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"step": "7",
|
|
149
|
+
"type": "task",
|
|
150
|
+
"service": "pdf_service",
|
|
151
|
+
"queue": "pdf.convert",
|
|
152
|
+
"input_mapping": {
|
|
153
|
+
"html": "workflow_steps[3].result.combined_html",
|
|
154
|
+
"invoice_id": "workflow_steps[0].result.invoice_id"
|
|
155
|
+
},
|
|
156
|
+
"output_schema": {
|
|
157
|
+
"pdf_url": "pdf_service.pdf_url"
|
|
158
|
+
},
|
|
159
|
+
"retry": {
|
|
160
|
+
"max_attempts": 2,
|
|
161
|
+
"delay": 1000
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
"step": "7",
|
|
166
|
+
"type": "dispatch",
|
|
167
|
+
"method": "webhook",
|
|
168
|
+
"target": "https://client.example.com/webhook",
|
|
169
|
+
"input_mapping": {
|
|
170
|
+
"html": "workflow_steps[3].result.combined_html",
|
|
171
|
+
"invoice_id": "workflow_steps[0].result.invoice_id"
|
|
172
|
+
},
|
|
173
|
+
"retry": {
|
|
174
|
+
"max_attempts": 2,
|
|
175
|
+
"delay": 1000
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
]
|
|
179
|
+
}
|
|
180
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@onlineapps/conn-orch-cookbook",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Complete cookbook toolkit for all services - unified wrapper including core, executor, transformer, and router functionality",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/onlineapps/connector-cookbook.git"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src/",
|
|
12
|
+
"docs/",
|
|
13
|
+
"examples/",
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE",
|
|
16
|
+
"CHANGELOG.md"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"test": "jest --coverage",
|
|
20
|
+
"test:unit": "jest --testPathPattern=unit --coverage",
|
|
21
|
+
"test:component": "jest --testPathPattern=component --coverage",
|
|
22
|
+
"test:integration": "jest --testPathPattern=integration --coverage",
|
|
23
|
+
"test:fixtures": "jest test/integration/cookbook-fixtures.test.js",
|
|
24
|
+
"test:smoke": "jest test/smoke.test.js",
|
|
25
|
+
"test:watch": "jest --watch",
|
|
26
|
+
"test:coverage": "jest --coverage --coverageReporters=text-lcov html",
|
|
27
|
+
"lint": "eslint \"src/**/*.js\" \"tests/**/*.js\"",
|
|
28
|
+
"prettier:check": "prettier --check \"src/**/*.js\" \"tests/**/*.js\"",
|
|
29
|
+
"prettier:fix": "prettier --write \"src/**/*.js\" \"tests/**/*.js\"",
|
|
30
|
+
"docs": "jsdoc2md --files src/**/*.js > API.md"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"connector",
|
|
34
|
+
"cookbook",
|
|
35
|
+
"workflow",
|
|
36
|
+
"orchestration",
|
|
37
|
+
"microservice",
|
|
38
|
+
"parser",
|
|
39
|
+
"validator",
|
|
40
|
+
"json-schema"
|
|
41
|
+
],
|
|
42
|
+
"author": "OnlineApps Team <dev@onlineapps.io>",
|
|
43
|
+
"license": "MIT",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/onlineapps/connector-cookbook/issues"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/onlineapps/connector-cookbook#readme",
|
|
48
|
+
"dependencies": {},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"eslint": "^8.30.0",
|
|
51
|
+
"eslint-config-prettier": "^8.5.0",
|
|
52
|
+
"jest": "^29.5.0",
|
|
53
|
+
"prettier": "^2.8.0"
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=12"
|
|
57
|
+
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @module @onlineapps/conn-orch-cookbook
|
|
5
|
+
* @description Unified cookbook connector for service-wrapper integration.
|
|
6
|
+
* This is a THIN WRAPPER around cookbook-* modules, providing a single
|
|
7
|
+
* unified interface for all cookbook functionality.
|
|
8
|
+
*
|
|
9
|
+
* NO DUPLICATION: All implementation is in cookbook-* modules.
|
|
10
|
+
* This connector only re-exports and provides compatibility layer.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link https://github.com/onlineapps/oa-drive/tree/main/shared/connector/conn-orch-cookbook|GitHub Repository}
|
|
13
|
+
* @author OA Drive Team
|
|
14
|
+
* @license MIT
|
|
15
|
+
* @since 2.0.0
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Import from shared cookbook modules - NO LOCAL IMPLEMENTATIONS!
|
|
19
|
+
const cookbookCore = require('../../../cookbook/cookbook-core');
|
|
20
|
+
const cookbookExecutor = require('../../../cookbook/cookbook-executor');
|
|
21
|
+
const cookbookTransformer = require('../../../cookbook/cookbook-transformer');
|
|
22
|
+
const cookbookRouter = require('../../../cookbook/cookbook-router');
|
|
23
|
+
|
|
24
|
+
// Re-export all from cookbook-core (parser and validator)
|
|
25
|
+
const {
|
|
26
|
+
parseCookbookFromFile,
|
|
27
|
+
parseCookbookFromFileSync,
|
|
28
|
+
parseCookbookFromObject,
|
|
29
|
+
validateCookbook,
|
|
30
|
+
validateStep,
|
|
31
|
+
CookbookValidationError,
|
|
32
|
+
validateAllReferences,
|
|
33
|
+
validateDependsOnReferences,
|
|
34
|
+
validateVariableReferences,
|
|
35
|
+
validateErrorHandlerReferences,
|
|
36
|
+
CookbookSchema,
|
|
37
|
+
loadSchema
|
|
38
|
+
} = cookbookCore;
|
|
39
|
+
|
|
40
|
+
// Re-export all from cookbook-executor
|
|
41
|
+
const {
|
|
42
|
+
CookbookExecutor,
|
|
43
|
+
ContextManager,
|
|
44
|
+
StepProcessor,
|
|
45
|
+
VariableResolver
|
|
46
|
+
} = cookbookExecutor;
|
|
47
|
+
|
|
48
|
+
// Re-export all from cookbook-transformer
|
|
49
|
+
const {
|
|
50
|
+
CookbookGenerator,
|
|
51
|
+
ApiSpecAnalyzer,
|
|
52
|
+
StepTranslator,
|
|
53
|
+
ResponseMapper,
|
|
54
|
+
createTransformer
|
|
55
|
+
} = cookbookTransformer;
|
|
56
|
+
|
|
57
|
+
// Re-export all from cookbook-router
|
|
58
|
+
const {
|
|
59
|
+
CookbookRouter,
|
|
60
|
+
ServiceDiscovery,
|
|
61
|
+
QueueManager,
|
|
62
|
+
RetryHandler,
|
|
63
|
+
createRouter
|
|
64
|
+
} = cookbookRouter;
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Create a cookbook processor with all capabilities
|
|
69
|
+
* Factory function that creates a processor with parser, validator, executor, and router
|
|
70
|
+
*
|
|
71
|
+
* @function createProcessor
|
|
72
|
+
* @param {Object} [config={}] - Processor configuration
|
|
73
|
+
* @param {Object} [config.executor] - Executor configuration
|
|
74
|
+
* @param {Object} [config.router] - Router configuration
|
|
75
|
+
* @param {Object} [config.transformer] - Transformer configuration
|
|
76
|
+
* @param {Object} [config.mqClient] - Message queue client for router
|
|
77
|
+
* @param {Object} [config.registryClient] - Registry client for router
|
|
78
|
+
* @returns {Object} Processor instance with process method
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* const processor = createProcessor({
|
|
82
|
+
* executor: { timeout: 30000 },
|
|
83
|
+
* router: { baseUrl: "http://api.example.com" },
|
|
84
|
+
* mqClient: mqConnector,
|
|
85
|
+
* registryClient: registryConnector
|
|
86
|
+
* });
|
|
87
|
+
*
|
|
88
|
+
* const result = await processor.process(cookbook);
|
|
89
|
+
*/
|
|
90
|
+
function createProcessor(config = {}) {
|
|
91
|
+
const executor = new CookbookExecutor(config.executor);
|
|
92
|
+
const router = config.mqClient && config.registryClient
|
|
93
|
+
? createRouter(config.mqClient, config.registryClient, config.router)
|
|
94
|
+
: null;
|
|
95
|
+
const transformer = createTransformer(config.transformer);
|
|
96
|
+
const mapper = new ResponseMapper(config.transformer);
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
/**
|
|
100
|
+
* Process a cookbook through the full pipeline
|
|
101
|
+
* @param {Object|string} cookbook - Cookbook object or file path
|
|
102
|
+
* @param {Object} [context={}] - Execution context
|
|
103
|
+
* @returns {Promise<Object>} Execution result
|
|
104
|
+
*/
|
|
105
|
+
async process(cookbook, context = {}) {
|
|
106
|
+
// Parse if string (file path)
|
|
107
|
+
if (typeof cookbook === 'string') {
|
|
108
|
+
cookbook = await parseCookbookFromFile(cookbook);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Validate
|
|
112
|
+
validateCookbook(cookbook);
|
|
113
|
+
|
|
114
|
+
// Validate all references
|
|
115
|
+
validateAllReferences(cookbook);
|
|
116
|
+
|
|
117
|
+
// Execute with routing and transformation
|
|
118
|
+
const executionContext = {
|
|
119
|
+
...context,
|
|
120
|
+
router,
|
|
121
|
+
transformer,
|
|
122
|
+
mapper
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
return executor.execute(cookbook, executionContext);
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
// Expose components for direct access
|
|
129
|
+
executor,
|
|
130
|
+
router,
|
|
131
|
+
transformer,
|
|
132
|
+
mapper
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Helper function to execute a single step
|
|
138
|
+
* Convenience wrapper around CookbookExecutor
|
|
139
|
+
*
|
|
140
|
+
* @function executeStep
|
|
141
|
+
* @param {Object} step - Step to execute
|
|
142
|
+
* @param {Object} [context={}] - Execution context
|
|
143
|
+
* @returns {Promise<Object>} Step execution result
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* const result = await executeStep({
|
|
147
|
+
* id: "step1",
|
|
148
|
+
* type: "task",
|
|
149
|
+
* service: "api",
|
|
150
|
+
* action: "GET",
|
|
151
|
+
* endpoint: "/users"
|
|
152
|
+
* });
|
|
153
|
+
*/
|
|
154
|
+
async function executeStep(step, context = {}) {
|
|
155
|
+
const executor = new CookbookExecutor();
|
|
156
|
+
return executor.executeStep(step, context);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Helper function to execute a complete workflow
|
|
161
|
+
* Convenience wrapper around CookbookExecutor
|
|
162
|
+
*
|
|
163
|
+
* @function executeWorkflow
|
|
164
|
+
* @param {Object} cookbook - Cookbook to execute
|
|
165
|
+
* @param {Object} [context={}] - Execution context
|
|
166
|
+
* @returns {Promise<Object>} Workflow execution result
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* const result = await executeWorkflow(cookbook, {
|
|
170
|
+
* variables: { userId: 123 }
|
|
171
|
+
* });
|
|
172
|
+
*/
|
|
173
|
+
async function executeWorkflow(cookbook, context = {}) {
|
|
174
|
+
const executor = new CookbookExecutor();
|
|
175
|
+
return executor.execute(cookbook, context);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Export everything as unified interface
|
|
179
|
+
module.exports = {
|
|
180
|
+
// Parser functions (from cookbook-core)
|
|
181
|
+
parseCookbookFromFile,
|
|
182
|
+
parseCookbookFromFileSync,
|
|
183
|
+
parseCookbookFromObject,
|
|
184
|
+
|
|
185
|
+
// Validator functions (from cookbook-core)
|
|
186
|
+
validateCookbook,
|
|
187
|
+
validateStep,
|
|
188
|
+
CookbookValidationError,
|
|
189
|
+
|
|
190
|
+
// Reference validators (from cookbook-core)
|
|
191
|
+
validateAllReferences,
|
|
192
|
+
validateDependsOnReferences,
|
|
193
|
+
validateVariableReferences,
|
|
194
|
+
validateErrorHandlerReferences,
|
|
195
|
+
|
|
196
|
+
// Schema (from cookbook-core)
|
|
197
|
+
CookbookSchema,
|
|
198
|
+
loadSchema,
|
|
199
|
+
|
|
200
|
+
// Executor classes (from cookbook-executor)
|
|
201
|
+
CookbookExecutor,
|
|
202
|
+
ContextManager,
|
|
203
|
+
StepProcessor,
|
|
204
|
+
VariableResolver,
|
|
205
|
+
|
|
206
|
+
// Transformer classes (from cookbook-transformer)
|
|
207
|
+
CookbookGenerator,
|
|
208
|
+
ApiSpecAnalyzer,
|
|
209
|
+
StepTranslator,
|
|
210
|
+
ResponseMapper,
|
|
211
|
+
createTransformer,
|
|
212
|
+
|
|
213
|
+
// Router classes (from cookbook-router)
|
|
214
|
+
CookbookRouter,
|
|
215
|
+
ServiceDiscovery,
|
|
216
|
+
QueueManager,
|
|
217
|
+
RetryHandler,
|
|
218
|
+
createRouter,
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
// Factory and helper functions
|
|
222
|
+
createProcessor,
|
|
223
|
+
executeStep,
|
|
224
|
+
executeWorkflow,
|
|
225
|
+
|
|
226
|
+
// Version info
|
|
227
|
+
VERSION: '2.0.0',
|
|
228
|
+
COMPATIBLE_CORE_VERSION: cookbookCore.VERSION,
|
|
229
|
+
COMPATIBLE_SCHEMA_VERSION: cookbookCore.SCHEMA_VERSION
|
|
230
|
+
};
|