@onlineapps/cookbook-core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -0
- package/package.json +38 -0
- package/schemas/cookbook.relaxed.schema.json +351 -0
- package/schemas/cookbook.schema.json +482 -0
- package/schemas/cookbook.strict.schema.json +441 -0
- package/src/index.js +60 -0
- package/src/parser/cookbookParser.js +108 -0
- package/src/parser/cookbookValidator.js +569 -0
- package/src/parser.js +7 -0
- package/src/referenceValidator.js +317 -0
- package/src/schema.js +46 -0
- package/src/validator.js +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# @onlineapps/cookbook-core
|
|
2
|
+
|
|
3
|
+
Core cookbook parsing and validation library - lightweight foundation for workflow definitions.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This package provides the essential parsing and validation functionality for cookbook workflow definitions. It contains no heavy dependencies and focuses purely on structural validation.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @onlineapps/cookbook-core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- **JSON Schema validation** - Strict schema enforcement
|
|
18
|
+
- **Recursive step validation** - All step types supported
|
|
19
|
+
- **Unique ID validation** - Ensures no duplicate step IDs
|
|
20
|
+
- **Lightweight** - ~50KB with minimal dependencies
|
|
21
|
+
- **Zero external dependencies** - Only uses `ajv` for validation
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### Basic parsing and validation
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
const {
|
|
29
|
+
parseCookbookFromFile,
|
|
30
|
+
parseCookbookFromObject,
|
|
31
|
+
validateCookbook
|
|
32
|
+
} = require('@onlineapps/cookbook-core');
|
|
33
|
+
|
|
34
|
+
// Parse from file
|
|
35
|
+
const cookbook = await parseCookbookFromFile('./workflow.json');
|
|
36
|
+
|
|
37
|
+
// Parse from object
|
|
38
|
+
const cookbookObj = parseCookbookFromObject(rawData);
|
|
39
|
+
|
|
40
|
+
// Validate only
|
|
41
|
+
validateCookbook(cookbookData); // throws CookbookValidationError if invalid
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Error handling
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
const { CookbookValidationError } = require('@onlineapps/cookbook-core');
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
validateCookbook(data);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (error instanceof CookbookValidationError) {
|
|
53
|
+
console.error('Validation failed:', error.message);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Schema access
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const { CookbookSchema } = require('@onlineapps/cookbook-core');
|
|
62
|
+
|
|
63
|
+
// Access the raw JSON schema for custom validation
|
|
64
|
+
console.log(CookbookSchema.properties);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## API Reference
|
|
68
|
+
|
|
69
|
+
### Parser Functions
|
|
70
|
+
|
|
71
|
+
- `parseCookbookFromFile(filePath)` - Async file parsing
|
|
72
|
+
- `parseCookbookFromFileSync(filePath)` - Sync file parsing
|
|
73
|
+
- `parseCookbookFromObject(object)` - Object parsing
|
|
74
|
+
|
|
75
|
+
### Validator Functions
|
|
76
|
+
|
|
77
|
+
- `validateCookbook(cookbook)` - Full cookbook validation
|
|
78
|
+
- `validateStep(step)` - Single step validation
|
|
79
|
+
|
|
80
|
+
### Schema Functions
|
|
81
|
+
|
|
82
|
+
- `loadSchema()` - Load cookbook JSON schema
|
|
83
|
+
- `CookbookSchema` - Pre-loaded schema object
|
|
84
|
+
|
|
85
|
+
### Error Classes
|
|
86
|
+
|
|
87
|
+
- `CookbookValidationError` - Validation error class
|
|
88
|
+
|
|
89
|
+
## Step Types Supported
|
|
90
|
+
|
|
91
|
+
- `task` - Service operation execution
|
|
92
|
+
- `foreach` - Iteration over arrays
|
|
93
|
+
- `fork_join` - Parallel execution branches
|
|
94
|
+
- `switch` - Conditional branching
|
|
95
|
+
- `sub_workflow` - Nested workflow
|
|
96
|
+
- `wait` - Time delay
|
|
97
|
+
- `dispatch` - Webhook dispatch
|
|
98
|
+
|
|
99
|
+
## Documentation
|
|
100
|
+
|
|
101
|
+
- [**Schema Audit Report**](docs/SCHEMA_AUDIT.md) - Critical analysis of validation rules
|
|
102
|
+
- [Test Coverage](test/parser.test.js) - Progressive test scenarios
|
|
103
|
+
|
|
104
|
+
## Related Packages
|
|
105
|
+
|
|
106
|
+
- `@onlineapps/cookbook-executor` - Workflow execution engine
|
|
107
|
+
- `@onlineapps/cookbook-transformer` - OpenAPI mapping
|
|
108
|
+
- `@onlineapps/cookbook-router` - Message routing
|
|
109
|
+
- `@onlineapps/connector-cookbook` - Full-featured wrapper for microservices
|
|
110
|
+
|
|
111
|
+
## Known Issues
|
|
112
|
+
|
|
113
|
+
See [Schema Audit](docs/SCHEMA_AUDIT.md) for current validation limitations and recommendations.
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
PROPRIETARY - All rights reserved
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@onlineapps/cookbook-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Core cookbook parsing and validation - lightweight foundation for workflow definitions",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "jest",
|
|
8
|
+
"test:watch": "jest --watch",
|
|
9
|
+
"test:coverage": "jest --coverage",
|
|
10
|
+
"docs": "jsdoc2md --files src/**/*.js > API.md"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"cookbook",
|
|
14
|
+
"workflow",
|
|
15
|
+
"parser",
|
|
16
|
+
"validator",
|
|
17
|
+
"schema"
|
|
18
|
+
],
|
|
19
|
+
"author": "OnlineApps",
|
|
20
|
+
"license": "PROPRIETARY",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"ajv": "^8.12.0",
|
|
23
|
+
"ajv-formats": "^2.1.1"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"jest": "^29.7.0"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"src",
|
|
33
|
+
"schemas"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://onlineapps.cz/schemas/cookbook-relaxed/v2.0.0",
|
|
4
|
+
"title": "Cookbook Schema - Relaxed Mode",
|
|
5
|
+
"description": "Relaxed validation schema for development and migration with flexible requirements",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["steps"],
|
|
8
|
+
"additionalProperties": true,
|
|
9
|
+
"properties": {
|
|
10
|
+
"name": {
|
|
11
|
+
"type": "string"
|
|
12
|
+
},
|
|
13
|
+
"version": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "Recommended: Use semantic versioning (e.g., 1.0.0)"
|
|
16
|
+
},
|
|
17
|
+
"description": {
|
|
18
|
+
"type": "string"
|
|
19
|
+
},
|
|
20
|
+
"api_input": {
|
|
21
|
+
"type": "object"
|
|
22
|
+
},
|
|
23
|
+
"steps": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"minItems": 1,
|
|
26
|
+
"items": {
|
|
27
|
+
"$ref": "#/definitions/Step"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"definitions": {
|
|
32
|
+
"Step": {
|
|
33
|
+
"type": "object",
|
|
34
|
+
"required": ["id"],
|
|
35
|
+
"additionalProperties": true,
|
|
36
|
+
"properties": {
|
|
37
|
+
"id": {
|
|
38
|
+
"type": "string",
|
|
39
|
+
"minLength": 1
|
|
40
|
+
},
|
|
41
|
+
"type": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"enum": ["task", "foreach", "fork_join", "switch", "sub_workflow", "wait", "dispatch"],
|
|
44
|
+
"description": "Recommended: Explicitly specify step type"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"oneOf": [
|
|
48
|
+
{ "$ref": "#/definitions/TaskStep" },
|
|
49
|
+
{ "$ref": "#/definitions/ForeachStep" },
|
|
50
|
+
{ "$ref": "#/definitions/ForkJoinStep" },
|
|
51
|
+
{ "$ref": "#/definitions/SwitchStep" },
|
|
52
|
+
{ "$ref": "#/definitions/SubWorkflowStep" },
|
|
53
|
+
{ "$ref": "#/definitions/WaitStep" },
|
|
54
|
+
{ "$ref": "#/definitions/DispatchStep" }
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"TaskStep": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"required": ["id"],
|
|
60
|
+
"additionalProperties": true,
|
|
61
|
+
"properties": {
|
|
62
|
+
"id": {
|
|
63
|
+
"type": "string",
|
|
64
|
+
"minLength": 1
|
|
65
|
+
},
|
|
66
|
+
"type": {
|
|
67
|
+
"type": "string",
|
|
68
|
+
"const": "task"
|
|
69
|
+
},
|
|
70
|
+
"name": {
|
|
71
|
+
"type": "string"
|
|
72
|
+
},
|
|
73
|
+
"service": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "Target service name"
|
|
76
|
+
},
|
|
77
|
+
"operation": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"description": "Operation identifier"
|
|
80
|
+
},
|
|
81
|
+
"action": {
|
|
82
|
+
"type": "string"
|
|
83
|
+
},
|
|
84
|
+
"endpoint": {
|
|
85
|
+
"type": "string"
|
|
86
|
+
},
|
|
87
|
+
"input": {
|
|
88
|
+
"type": "object"
|
|
89
|
+
},
|
|
90
|
+
"output": {
|
|
91
|
+
"type": "object"
|
|
92
|
+
},
|
|
93
|
+
"depends_on": {
|
|
94
|
+
"type": "array",
|
|
95
|
+
"items": {
|
|
96
|
+
"type": "string"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"retry": {
|
|
100
|
+
"$ref": "#/definitions/Retry"
|
|
101
|
+
},
|
|
102
|
+
"timeoutMs": {
|
|
103
|
+
"type": "integer",
|
|
104
|
+
"minimum": 1
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"ForeachStep": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"required": ["id", "iterator", "body"],
|
|
111
|
+
"additionalProperties": true,
|
|
112
|
+
"properties": {
|
|
113
|
+
"id": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"minLength": 1
|
|
116
|
+
},
|
|
117
|
+
"type": {
|
|
118
|
+
"type": "string",
|
|
119
|
+
"const": "foreach"
|
|
120
|
+
},
|
|
121
|
+
"name": {
|
|
122
|
+
"type": "string"
|
|
123
|
+
},
|
|
124
|
+
"iterator": {
|
|
125
|
+
"type": "string"
|
|
126
|
+
},
|
|
127
|
+
"body": {
|
|
128
|
+
"type": "array",
|
|
129
|
+
"minItems": 1,
|
|
130
|
+
"items": {
|
|
131
|
+
"$ref": "#/definitions/Step"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"output": {
|
|
135
|
+
"type": "object"
|
|
136
|
+
},
|
|
137
|
+
"service": {
|
|
138
|
+
"deprecated": true,
|
|
139
|
+
"description": "DEPRECATED: This field should not be used in foreach steps"
|
|
140
|
+
},
|
|
141
|
+
"input": {
|
|
142
|
+
"deprecated": true,
|
|
143
|
+
"description": "DEPRECATED: This field should not be used in foreach steps"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
"ForkJoinStep": {
|
|
148
|
+
"type": "object",
|
|
149
|
+
"required": ["id", "branches"],
|
|
150
|
+
"additionalProperties": true,
|
|
151
|
+
"properties": {
|
|
152
|
+
"id": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"minLength": 1
|
|
155
|
+
},
|
|
156
|
+
"type": {
|
|
157
|
+
"type": "string",
|
|
158
|
+
"const": "fork_join"
|
|
159
|
+
},
|
|
160
|
+
"name": {
|
|
161
|
+
"type": "string"
|
|
162
|
+
},
|
|
163
|
+
"branches": {
|
|
164
|
+
"type": "array",
|
|
165
|
+
"minItems": 1,
|
|
166
|
+
"items": {
|
|
167
|
+
"$ref": "#/definitions/Step"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"join": {
|
|
171
|
+
"type": "object",
|
|
172
|
+
"properties": {
|
|
173
|
+
"strategy": {
|
|
174
|
+
"type": "string",
|
|
175
|
+
"enum": ["merge", "first", "last", "all", "custom"],
|
|
176
|
+
"default": "merge"
|
|
177
|
+
},
|
|
178
|
+
"output": {
|
|
179
|
+
"type": "object"
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
"service": {
|
|
184
|
+
"deprecated": true,
|
|
185
|
+
"description": "DEPRECATED: This field should not be used in fork_join steps"
|
|
186
|
+
},
|
|
187
|
+
"input": {
|
|
188
|
+
"deprecated": true,
|
|
189
|
+
"description": "DEPRECATED: This field should not be used in fork_join steps"
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
"SwitchStep": {
|
|
194
|
+
"type": "object",
|
|
195
|
+
"required": ["id", "expression", "cases"],
|
|
196
|
+
"additionalProperties": true,
|
|
197
|
+
"properties": {
|
|
198
|
+
"id": {
|
|
199
|
+
"type": "string",
|
|
200
|
+
"minLength": 1
|
|
201
|
+
},
|
|
202
|
+
"type": {
|
|
203
|
+
"type": "string",
|
|
204
|
+
"const": "switch"
|
|
205
|
+
},
|
|
206
|
+
"name": {
|
|
207
|
+
"type": "string"
|
|
208
|
+
},
|
|
209
|
+
"expression": {
|
|
210
|
+
"type": "string"
|
|
211
|
+
},
|
|
212
|
+
"cases": {
|
|
213
|
+
"type": "object",
|
|
214
|
+
"minProperties": 1,
|
|
215
|
+
"additionalProperties": {
|
|
216
|
+
"$ref": "#/definitions/Step"
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"default": {
|
|
220
|
+
"$ref": "#/definitions/Step",
|
|
221
|
+
"description": "Recommended: Always provide a default case"
|
|
222
|
+
},
|
|
223
|
+
"depends_on": {
|
|
224
|
+
"type": "array",
|
|
225
|
+
"items": {
|
|
226
|
+
"type": "string"
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
"service": {
|
|
230
|
+
"deprecated": true,
|
|
231
|
+
"description": "DEPRECATED: This field should not be used in switch steps"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
"SubWorkflowStep": {
|
|
236
|
+
"type": "object",
|
|
237
|
+
"required": ["id", "steps"],
|
|
238
|
+
"additionalProperties": true,
|
|
239
|
+
"properties": {
|
|
240
|
+
"id": {
|
|
241
|
+
"type": "string",
|
|
242
|
+
"minLength": 1
|
|
243
|
+
},
|
|
244
|
+
"type": {
|
|
245
|
+
"type": "string",
|
|
246
|
+
"const": "sub_workflow"
|
|
247
|
+
},
|
|
248
|
+
"name": {
|
|
249
|
+
"type": "string"
|
|
250
|
+
},
|
|
251
|
+
"input": {
|
|
252
|
+
"type": "object"
|
|
253
|
+
},
|
|
254
|
+
"steps": {
|
|
255
|
+
"type": "array",
|
|
256
|
+
"minItems": 1,
|
|
257
|
+
"items": {
|
|
258
|
+
"$ref": "#/definitions/Step"
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"WaitStep": {
|
|
264
|
+
"type": "object",
|
|
265
|
+
"required": ["id", "durationMs"],
|
|
266
|
+
"additionalProperties": true,
|
|
267
|
+
"properties": {
|
|
268
|
+
"id": {
|
|
269
|
+
"type": "string",
|
|
270
|
+
"minLength": 1
|
|
271
|
+
},
|
|
272
|
+
"type": {
|
|
273
|
+
"type": "string",
|
|
274
|
+
"const": "wait"
|
|
275
|
+
},
|
|
276
|
+
"name": {
|
|
277
|
+
"type": "string"
|
|
278
|
+
},
|
|
279
|
+
"durationMs": {
|
|
280
|
+
"type": "integer",
|
|
281
|
+
"minimum": 0
|
|
282
|
+
},
|
|
283
|
+
"service": {
|
|
284
|
+
"deprecated": true,
|
|
285
|
+
"description": "DEPRECATED: This field should not be used in wait steps"
|
|
286
|
+
},
|
|
287
|
+
"input": {
|
|
288
|
+
"deprecated": true,
|
|
289
|
+
"description": "DEPRECATED: This field should not be used in wait steps"
|
|
290
|
+
},
|
|
291
|
+
"output": {
|
|
292
|
+
"deprecated": true,
|
|
293
|
+
"description": "DEPRECATED: This field should not be used in wait steps"
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
"DispatchStep": {
|
|
298
|
+
"type": "object",
|
|
299
|
+
"required": ["id", "target"],
|
|
300
|
+
"additionalProperties": true,
|
|
301
|
+
"properties": {
|
|
302
|
+
"id": {
|
|
303
|
+
"type": "string",
|
|
304
|
+
"minLength": 1
|
|
305
|
+
},
|
|
306
|
+
"type": {
|
|
307
|
+
"type": "string",
|
|
308
|
+
"const": "dispatch"
|
|
309
|
+
},
|
|
310
|
+
"name": {
|
|
311
|
+
"type": "string"
|
|
312
|
+
},
|
|
313
|
+
"method": {
|
|
314
|
+
"type": "string",
|
|
315
|
+
"enum": ["webhook", "http", "grpc", "kafka", "sqs", "custom"],
|
|
316
|
+
"default": "webhook"
|
|
317
|
+
},
|
|
318
|
+
"target": {
|
|
319
|
+
"type": "string"
|
|
320
|
+
},
|
|
321
|
+
"input": {
|
|
322
|
+
"type": "object"
|
|
323
|
+
},
|
|
324
|
+
"headers": {
|
|
325
|
+
"type": "object"
|
|
326
|
+
},
|
|
327
|
+
"retry": {
|
|
328
|
+
"$ref": "#/definitions/Retry"
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
"Retry": {
|
|
333
|
+
"type": "object",
|
|
334
|
+
"additionalProperties": true,
|
|
335
|
+
"properties": {
|
|
336
|
+
"maxAttempts": {
|
|
337
|
+
"type": "integer",
|
|
338
|
+
"minimum": 1
|
|
339
|
+
},
|
|
340
|
+
"delayMs": {
|
|
341
|
+
"type": "integer",
|
|
342
|
+
"minimum": 0
|
|
343
|
+
},
|
|
344
|
+
"backoffMultiplier": {
|
|
345
|
+
"type": "number",
|
|
346
|
+
"minimum": 1.0
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|