@protobase/workflows 0.0.0-stage → 0.68.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 +202 -0
- package/dist/definition/check-definition.d.ts +21 -0
- package/dist/definition/check-definition.js +128 -0
- package/dist/definition/check-reads.js +46 -0
- package/dist/definition/check-schema.js +74 -0
- package/dist/definition/check-trigger.d.ts +7 -0
- package/dist/definition/check-trigger.js +27 -0
- package/dist/definition/expression-fields.js +68 -0
- package/dist/definition/expressions.js +35 -0
- package/dist/definition/graph.js +39 -0
- package/dist/definition/names.js +14 -0
- package/dist/definition/problem.d.ts +13 -0
- package/dist/definition/problem.js +11 -0
- package/dist/definition/reads.js +81 -0
- package/dist/definition/schema.d.ts +259 -0
- package/dist/definition/schema.js +258 -0
- package/dist/definition/types.d.ts +92 -0
- package/dist/definition/visible.js +52 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +16 -0
- package/dist/limits.d.ts +39 -0
- package/dist/limits.js +40 -0
- package/dist/nesting.d.ts +7 -0
- package/dist/nesting.js +19 -0
- package/dist/plugin/connection-error.d.ts +10 -0
- package/dist/plugin/connection-error.js +15 -0
- package/dist/plugin/context.d.ts +99 -0
- package/dist/plugin/define-plugin.d.ts +7 -0
- package/dist/plugin/define-plugin.js +23 -0
- package/dist/plugin/fetch-errors.d.ts +14 -0
- package/dist/plugin/fetch-errors.js +18 -0
- package/dist/plugin/file-value.d.ts +5 -0
- package/dist/plugin/file-value.js +9 -0
- package/dist/plugin/index.d.ts +8 -0
- package/dist/plugin/index.js +6 -0
- package/dist/plugin/load-plugins.d.ts +10 -0
- package/dist/plugin/load-plugins.js +22 -0
- package/dist/plugin/step-handlers.d.ts +12 -0
- package/dist/plugin/step-handlers.js +33 -0
- package/dist/plugin/trigger-checks.d.ts +6 -0
- package/dist/plugin/trigger-checks.js +28 -0
- package/dist/plugin/type-catalog.d.ts +19 -0
- package/dist/plugin/type-catalog.js +26 -0
- package/dist/plugin/type-list.d.ts +26 -0
- package/dist/plugin/type-list.js +26 -0
- package/dist/plugin/types.d.ts +123 -0
- package/dist/run/context.d.ts +18 -0
- package/dist/run/errors.d.ts +20 -0
- package/dist/run/errors.js +39 -0
- package/dist/run/evaluate.js +59 -0
- package/dist/run/fan-out.js +39 -0
- package/dist/run/json-bytes.js +5 -0
- package/dist/run/port.d.ts +105 -0
- package/dist/run/position.js +54 -0
- package/dist/run/recovery.js +76 -0
- package/dist/run/redact.d.ts +16 -0
- package/dist/run/redact.js +39 -0
- package/dist/run/rerun.d.ts +18 -0
- package/dist/run/rerun.js +62 -0
- package/dist/run/result-states.js +115 -0
- package/dist/run/runner.d.ts +29 -0
- package/dist/run/runner.js +60 -0
- package/dist/run/scope.js +127 -0
- package/dist/run/segment.d.ts +35 -0
- package/dist/run/segment.js +58 -0
- package/dist/run/simple-states.js +108 -0
- package/dist/run/step-input.js +22 -0
- package/dist/run/task.js +39 -0
- package/package.json +34 -4
- package/README.md +0 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/definition/names.ts
|
|
2
|
+
/** Variables a definition cannot assign: `$states`, which the runner gives each expression. */
|
|
3
|
+
const reservedVariables = /* @__PURE__ */ new Set(["states"]);
|
|
4
|
+
/**
|
|
5
|
+
* What an expression may read of `$states.context`, as name paths: the run's input and start time, and a secret by its
|
|
6
|
+
* name (`Secrets.<NAME>`, the name required).
|
|
7
|
+
*/
|
|
8
|
+
const contextReads = [
|
|
9
|
+
["Execution", "Input"],
|
|
10
|
+
["Execution", "StartTime"],
|
|
11
|
+
["Secrets"]
|
|
12
|
+
];
|
|
13
|
+
//#endregion
|
|
14
|
+
export { contextReads, reservedVariables };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/definition/problem.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Why a definition cannot be saved. `state` is the state's path: its name, or names joined by `/` inside a Map's item
|
|
4
|
+
* processor or a Parallel's branch (`Each/Fetch`, `Both/1/Mail`); `field` is the field within it, such as `Retry[0].IntervalSeconds`.
|
|
5
|
+
*/
|
|
6
|
+
export type Problem = {
|
|
7
|
+
state?: string;
|
|
8
|
+
field?: string;
|
|
9
|
+
message: string;
|
|
10
|
+
};
|
|
11
|
+
/** A problem as one line: `State "Fetch", field "Arguments.url": ...`. */
|
|
12
|
+
export declare const problemText: ({ state, field, message }: Problem) => string;
|
|
13
|
+
//#endregion
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/definition/problem.ts
|
|
2
|
+
/** A problem as one line: `State "Fetch", field "Arguments.url": ...`. */
|
|
3
|
+
const problemText = ({ state, field, message }) => {
|
|
4
|
+
const where = [state !== void 0 && `state "${state}"`, field !== void 0 && `field "${field}"`].filter(Boolean).join(", ");
|
|
5
|
+
if (!where) return message;
|
|
6
|
+
return `${where.charAt(0).toUpperCase()}${where.slice(1)}: ${message}`;
|
|
7
|
+
};
|
|
8
|
+
/** A field path as `Retry[0].IntervalSeconds`. */
|
|
9
|
+
const fieldPath = (parts) => parts.reduce((path, part) => typeof part === "number" || /^\d+$/.test(part) ? `${path}[${part}]` : path ? `${path}.${part}` : part, "");
|
|
10
|
+
//#endregion
|
|
11
|
+
export { fieldPath, problemText };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
//#region src/definition/reads.ts
|
|
2
|
+
const isNode = (value) => typeof value === "object" && value !== null && typeof value.type === "string";
|
|
3
|
+
const relativeKeys = /* @__PURE__ */ new Set([
|
|
4
|
+
"stages",
|
|
5
|
+
"predicate",
|
|
6
|
+
"group",
|
|
7
|
+
"terms"
|
|
8
|
+
]);
|
|
9
|
+
const inputReads = /* @__PURE__ */ new Set([
|
|
10
|
+
"name",
|
|
11
|
+
"wildcard",
|
|
12
|
+
"descendant",
|
|
13
|
+
"parent"
|
|
14
|
+
]);
|
|
15
|
+
/** JSONata's own functions, which an expression calls as `$sum(...)`: no reads of a variable. */
|
|
16
|
+
const builtInFunctions = new Set("sum count max min average string substring substringBefore substringAfter lowercase uppercase length trim pad match contains replace split join formatNumber formatBase formatInteger parseInteger number floor ceil round abs sqrt power random boolean not map zip filter single reduce sift keys lookup append exists spread merge reverse each error assert type sort shuffle distinct base64encode base64decode encodeUrlComponent encodeUrl decodeUrlComponent decodeUrl eval toMillis fromMillis clone now millis".split(" "));
|
|
17
|
+
const opensScope = (value) => isNode(value) && (value.type === "block" || value.type === "lambda");
|
|
18
|
+
const boundIn = (value, names = /* @__PURE__ */ new Set(), root = true) => {
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
for (const item of value) boundIn(item, names, false);
|
|
21
|
+
return names;
|
|
22
|
+
}
|
|
23
|
+
if (!isNode(value) || !root && opensScope(value)) return names;
|
|
24
|
+
if (value.type === "bind" && isNode(value.lhs) && value.lhs.type === "variable") names.add(String(value.lhs.value));
|
|
25
|
+
for (const [key, child] of Object.entries(value)) if (key !== "position" && key !== "value" && key !== "type") boundIn(child, names, false);
|
|
26
|
+
return names;
|
|
27
|
+
};
|
|
28
|
+
/** The reads of a compiled expression, from its syntax tree, each name read where it is bound counted as no read. */
|
|
29
|
+
const expressionReads = (expression) => {
|
|
30
|
+
const variables = /* @__PURE__ */ new Set();
|
|
31
|
+
const states = [];
|
|
32
|
+
let input = false;
|
|
33
|
+
const inPath = /* @__PURE__ */ new WeakSet();
|
|
34
|
+
const visit = (value, rooted, outer) => {
|
|
35
|
+
if (Array.isArray(value)) return value.forEach((item) => visit(item, rooted, outer));
|
|
36
|
+
if (!isNode(value)) return;
|
|
37
|
+
let bound = outer;
|
|
38
|
+
if (opensScope(value)) {
|
|
39
|
+
const parameters = value.type === "lambda" && Array.isArray(value.arguments) ? value.arguments.map((argument) => String(argument.value)) : [];
|
|
40
|
+
bound = /* @__PURE__ */ new Set([
|
|
41
|
+
...outer,
|
|
42
|
+
...parameters,
|
|
43
|
+
...boundIn(value)
|
|
44
|
+
]);
|
|
45
|
+
}
|
|
46
|
+
if (value.type === "variable") {
|
|
47
|
+
const name = String(value.value);
|
|
48
|
+
if (name === "" || name === "$") input ||= rooted;
|
|
49
|
+
else if (!bound.has(name)) variables.add(name);
|
|
50
|
+
}
|
|
51
|
+
if (inputReads.has(value.type) && rooted) input = true;
|
|
52
|
+
if (value.type === "path" && Array.isArray(value.steps)) {
|
|
53
|
+
const [first] = value.steps;
|
|
54
|
+
if (first?.type === "variable" && first.value === "states") {
|
|
55
|
+
inPath.add(first);
|
|
56
|
+
const rest = value.steps.slice(1);
|
|
57
|
+
const end = rest.findIndex((step) => step.type !== "name" || step.stages !== void 0 || step.predicate !== void 0);
|
|
58
|
+
states.push(rest.slice(0, end === -1 ? rest.length : end + (rest[end]?.type === "name" ? 1 : 0)).map((step) => String(step.value)));
|
|
59
|
+
}
|
|
60
|
+
value.steps.forEach((step, index) => visit(step, index === 0 ? rooted : false, bound));
|
|
61
|
+
} else if (value.type === "variable" && value.value === "states" && !inPath.has(value)) states.push([]);
|
|
62
|
+
for (const [key, child] of Object.entries(value)) {
|
|
63
|
+
if (key === "steps" && value.type === "path") continue;
|
|
64
|
+
if (key === "position" || key === "value" || key === "type") continue;
|
|
65
|
+
visit(child, relativeKeys.has(key) || value.type === "filter" || value.type === "sort" ? false : rooted, bound);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const ast = expression.ast();
|
|
69
|
+
visit(ast, true, boundIn(ast));
|
|
70
|
+
const evaluates = variables.has("eval");
|
|
71
|
+
for (const name of builtInFunctions) variables.delete(name);
|
|
72
|
+
variables.delete("states");
|
|
73
|
+
return {
|
|
74
|
+
variables,
|
|
75
|
+
states,
|
|
76
|
+
input,
|
|
77
|
+
evaluates
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
//#endregion
|
|
81
|
+
export { builtInFunctions, expressionReads };
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
//#region src/definition/schema.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* The JSON Schema of a workflow definition: its trigger, and a state machine in the States Language with JSONata
|
|
4
|
+
* expressions, in the named-reads profile. It checks the shape; `checkDefinition` also checks the edges and what each expression reads.
|
|
5
|
+
*/
|
|
6
|
+
export declare const definitionSchema: {
|
|
7
|
+
readonly $schema: "http://json-schema.org/draft-07/schema#";
|
|
8
|
+
readonly $id: "https://docs.protobase.net/schemas/workflow-definition.json";
|
|
9
|
+
readonly $ref: "#/definitions/definition";
|
|
10
|
+
readonly definitions: {
|
|
11
|
+
readonly machine: {
|
|
12
|
+
readonly type: "object";
|
|
13
|
+
readonly required: readonly ["StartAt", "States"];
|
|
14
|
+
readonly properties: {
|
|
15
|
+
readonly StartAt: {
|
|
16
|
+
type: string;
|
|
17
|
+
minLength: number;
|
|
18
|
+
maxLength: number;
|
|
19
|
+
};
|
|
20
|
+
readonly Comment: {
|
|
21
|
+
readonly type: "string";
|
|
22
|
+
};
|
|
23
|
+
readonly States: {
|
|
24
|
+
readonly type: "object";
|
|
25
|
+
readonly minProperties: 1;
|
|
26
|
+
readonly propertyNames: {
|
|
27
|
+
type: string;
|
|
28
|
+
minLength: number;
|
|
29
|
+
maxLength: number;
|
|
30
|
+
};
|
|
31
|
+
readonly additionalProperties: {
|
|
32
|
+
readonly $ref: "#/definitions/state";
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
readonly definition: {
|
|
38
|
+
readonly type: "object";
|
|
39
|
+
readonly additionalProperties: false;
|
|
40
|
+
readonly required: readonly ["trigger", "stateMachine"];
|
|
41
|
+
readonly properties: {
|
|
42
|
+
readonly trigger: {
|
|
43
|
+
readonly $ref: "#/definitions/trigger";
|
|
44
|
+
};
|
|
45
|
+
readonly stateMachine: {
|
|
46
|
+
readonly $ref: "#/definitions/stateMachine";
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
readonly trigger: {
|
|
51
|
+
readonly type: "object";
|
|
52
|
+
readonly minProperties: 1;
|
|
53
|
+
readonly maxProperties: 1;
|
|
54
|
+
readonly propertyNames: {
|
|
55
|
+
readonly pattern: "^(manual|[a-z][a-z0-9_]*:[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*)$";
|
|
56
|
+
};
|
|
57
|
+
readonly properties: {
|
|
58
|
+
readonly manual: {
|
|
59
|
+
readonly type: "object";
|
|
60
|
+
readonly maxProperties: 0;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
readonly additionalProperties: {
|
|
64
|
+
readonly type: "object";
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
readonly stateMachine: {
|
|
68
|
+
readonly allOf: readonly [{
|
|
69
|
+
readonly $ref: "#/definitions/machine";
|
|
70
|
+
}];
|
|
71
|
+
readonly required: readonly ["QueryLanguage"];
|
|
72
|
+
readonly properties: {
|
|
73
|
+
readonly QueryLanguage: {
|
|
74
|
+
readonly const: "JSONata";
|
|
75
|
+
};
|
|
76
|
+
readonly StartAt: {};
|
|
77
|
+
readonly States: {};
|
|
78
|
+
readonly Comment: {};
|
|
79
|
+
};
|
|
80
|
+
readonly additionalProperties: false;
|
|
81
|
+
};
|
|
82
|
+
readonly processor: {
|
|
83
|
+
readonly allOf: readonly [{
|
|
84
|
+
readonly $ref: "#/definitions/machine";
|
|
85
|
+
}];
|
|
86
|
+
readonly properties: {
|
|
87
|
+
readonly ProcessorConfig: {
|
|
88
|
+
readonly type: "object";
|
|
89
|
+
readonly additionalProperties: false;
|
|
90
|
+
readonly properties: {
|
|
91
|
+
readonly Mode: {
|
|
92
|
+
readonly const: "INLINE";
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
readonly StartAt: {};
|
|
97
|
+
readonly States: {};
|
|
98
|
+
readonly Comment: {};
|
|
99
|
+
};
|
|
100
|
+
readonly additionalProperties: false;
|
|
101
|
+
};
|
|
102
|
+
readonly state: {
|
|
103
|
+
readonly type: "object";
|
|
104
|
+
readonly required: readonly ["Type"];
|
|
105
|
+
readonly discriminator: {
|
|
106
|
+
readonly propertyName: "Type";
|
|
107
|
+
};
|
|
108
|
+
readonly oneOf: readonly [{
|
|
109
|
+
properties: {
|
|
110
|
+
Type: {
|
|
111
|
+
const: string;
|
|
112
|
+
};
|
|
113
|
+
Comment: {
|
|
114
|
+
type: string;
|
|
115
|
+
};
|
|
116
|
+
Output: {};
|
|
117
|
+
Assign: {
|
|
118
|
+
type: string;
|
|
119
|
+
propertyNames: {
|
|
120
|
+
pattern: string;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
QueryLanguage: {
|
|
124
|
+
const: string;
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
type: string;
|
|
128
|
+
additionalProperties: boolean;
|
|
129
|
+
required: string[];
|
|
130
|
+
}, {
|
|
131
|
+
properties: {
|
|
132
|
+
Type: {
|
|
133
|
+
const: string;
|
|
134
|
+
};
|
|
135
|
+
Comment: {
|
|
136
|
+
type: string;
|
|
137
|
+
};
|
|
138
|
+
Output: {};
|
|
139
|
+
Assign: {
|
|
140
|
+
type: string;
|
|
141
|
+
propertyNames: {
|
|
142
|
+
pattern: string;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
QueryLanguage: {
|
|
146
|
+
const: string;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
type: string;
|
|
150
|
+
additionalProperties: boolean;
|
|
151
|
+
required: string[];
|
|
152
|
+
}, {
|
|
153
|
+
properties: {
|
|
154
|
+
Type: {
|
|
155
|
+
const: string;
|
|
156
|
+
};
|
|
157
|
+
Comment: {
|
|
158
|
+
type: string;
|
|
159
|
+
};
|
|
160
|
+
Output: {};
|
|
161
|
+
Assign: {
|
|
162
|
+
type: string;
|
|
163
|
+
propertyNames: {
|
|
164
|
+
pattern: string;
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
QueryLanguage: {
|
|
168
|
+
const: string;
|
|
169
|
+
};
|
|
170
|
+
};
|
|
171
|
+
type: string;
|
|
172
|
+
additionalProperties: boolean;
|
|
173
|
+
required: string[];
|
|
174
|
+
}, {
|
|
175
|
+
properties: {
|
|
176
|
+
Type: {
|
|
177
|
+
const: string;
|
|
178
|
+
};
|
|
179
|
+
Comment: {
|
|
180
|
+
type: string;
|
|
181
|
+
};
|
|
182
|
+
Output: {};
|
|
183
|
+
Assign: {
|
|
184
|
+
type: string;
|
|
185
|
+
propertyNames: {
|
|
186
|
+
pattern: string;
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
QueryLanguage: {
|
|
190
|
+
const: string;
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
type: string;
|
|
194
|
+
additionalProperties: boolean;
|
|
195
|
+
required: string[];
|
|
196
|
+
}, {
|
|
197
|
+
readonly type: "object";
|
|
198
|
+
readonly additionalProperties: false;
|
|
199
|
+
readonly required: readonly ["Type"];
|
|
200
|
+
readonly properties: {
|
|
201
|
+
readonly Type: {
|
|
202
|
+
readonly const: "Succeed";
|
|
203
|
+
};
|
|
204
|
+
readonly Comment: {
|
|
205
|
+
readonly type: "string";
|
|
206
|
+
};
|
|
207
|
+
readonly Output: {};
|
|
208
|
+
readonly QueryLanguage: {
|
|
209
|
+
readonly const: "JSONata";
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
}, {
|
|
213
|
+
readonly type: "object";
|
|
214
|
+
readonly additionalProperties: false;
|
|
215
|
+
readonly required: readonly ["Type"];
|
|
216
|
+
readonly properties: {
|
|
217
|
+
readonly Type: {
|
|
218
|
+
readonly const: "Fail";
|
|
219
|
+
};
|
|
220
|
+
readonly Comment: {
|
|
221
|
+
readonly type: "string";
|
|
222
|
+
};
|
|
223
|
+
readonly QueryLanguage: {
|
|
224
|
+
readonly const: "JSONata";
|
|
225
|
+
};
|
|
226
|
+
readonly Error: {
|
|
227
|
+
readonly type: "string";
|
|
228
|
+
};
|
|
229
|
+
readonly Cause: {
|
|
230
|
+
readonly type: "string";
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
}, {
|
|
234
|
+
properties: {
|
|
235
|
+
Type: {
|
|
236
|
+
const: string;
|
|
237
|
+
};
|
|
238
|
+
Comment: {
|
|
239
|
+
type: string;
|
|
240
|
+
};
|
|
241
|
+
Output: {};
|
|
242
|
+
Assign: {
|
|
243
|
+
type: string;
|
|
244
|
+
propertyNames: {
|
|
245
|
+
pattern: string;
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
QueryLanguage: {
|
|
249
|
+
const: string;
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
type: string;
|
|
253
|
+
additionalProperties: boolean;
|
|
254
|
+
required: string[];
|
|
255
|
+
}];
|
|
256
|
+
};
|
|
257
|
+
};
|
|
258
|
+
};
|
|
259
|
+
//#endregion
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { limits } from "../limits.js";
|
|
2
|
+
//#region src/definition/schema.ts
|
|
3
|
+
const expression = {
|
|
4
|
+
type: "string",
|
|
5
|
+
pattern: "^\\{%[\\s\\S]*%\\}$"
|
|
6
|
+
};
|
|
7
|
+
const name = {
|
|
8
|
+
type: "string",
|
|
9
|
+
minLength: 1,
|
|
10
|
+
maxLength: 80
|
|
11
|
+
};
|
|
12
|
+
const errorNames = {
|
|
13
|
+
type: "array",
|
|
14
|
+
minItems: 1,
|
|
15
|
+
items: {
|
|
16
|
+
type: "string",
|
|
17
|
+
minLength: 1
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const assign = {
|
|
21
|
+
type: "object",
|
|
22
|
+
propertyNames: { pattern: "^[A-Za-z][A-Za-z0-9_]*$" }
|
|
23
|
+
};
|
|
24
|
+
const common = {
|
|
25
|
+
Type: {},
|
|
26
|
+
Comment: { type: "string" },
|
|
27
|
+
Output: {},
|
|
28
|
+
Assign: assign,
|
|
29
|
+
QueryLanguage: { const: "JSONata" }
|
|
30
|
+
};
|
|
31
|
+
const flow = {
|
|
32
|
+
Next: name,
|
|
33
|
+
End: { const: true }
|
|
34
|
+
};
|
|
35
|
+
const nextOrEnd = { oneOf: [{
|
|
36
|
+
required: ["Next"],
|
|
37
|
+
not: { required: ["End"] }
|
|
38
|
+
}, {
|
|
39
|
+
required: ["End"],
|
|
40
|
+
not: { required: ["Next"] }
|
|
41
|
+
}] };
|
|
42
|
+
const recovery = {
|
|
43
|
+
Retry: {
|
|
44
|
+
type: "array",
|
|
45
|
+
items: {
|
|
46
|
+
type: "object",
|
|
47
|
+
additionalProperties: false,
|
|
48
|
+
required: ["ErrorEquals"],
|
|
49
|
+
properties: {
|
|
50
|
+
ErrorEquals: errorNames,
|
|
51
|
+
IntervalSeconds: {
|
|
52
|
+
type: "integer",
|
|
53
|
+
minimum: 1,
|
|
54
|
+
maximum: limits.retryDelaySeconds
|
|
55
|
+
},
|
|
56
|
+
MaxAttempts: {
|
|
57
|
+
type: "integer",
|
|
58
|
+
minimum: 0,
|
|
59
|
+
maximum: limits.retryAttempts
|
|
60
|
+
},
|
|
61
|
+
BackoffRate: {
|
|
62
|
+
type: "number",
|
|
63
|
+
minimum: 1,
|
|
64
|
+
maximum: 10
|
|
65
|
+
},
|
|
66
|
+
MaxDelaySeconds: {
|
|
67
|
+
type: "integer",
|
|
68
|
+
minimum: 1,
|
|
69
|
+
maximum: limits.retryDelaySeconds
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
Catch: {
|
|
75
|
+
type: "array",
|
|
76
|
+
items: {
|
|
77
|
+
type: "object",
|
|
78
|
+
additionalProperties: false,
|
|
79
|
+
required: ["ErrorEquals", "Next"],
|
|
80
|
+
properties: {
|
|
81
|
+
ErrorEquals: errorNames,
|
|
82
|
+
Next: name,
|
|
83
|
+
Output: {},
|
|
84
|
+
Assign: assign
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const state = (type, properties, { required = [], ...extra } = {}) => ({
|
|
90
|
+
type: "object",
|
|
91
|
+
additionalProperties: false,
|
|
92
|
+
required: ["Type", ...required],
|
|
93
|
+
...extra,
|
|
94
|
+
properties: {
|
|
95
|
+
...common,
|
|
96
|
+
Type: { const: type },
|
|
97
|
+
...properties
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
/**
|
|
101
|
+
* The JSON Schema of a workflow definition: its trigger, and a state machine in the States Language with JSONata
|
|
102
|
+
* expressions, in the named-reads profile. It checks the shape; `checkDefinition` also checks the edges and what each expression reads.
|
|
103
|
+
*/
|
|
104
|
+
const definitionSchema = {
|
|
105
|
+
$schema: "http://json-schema.org/draft-07/schema#",
|
|
106
|
+
$id: "https://docs.protobase.net/schemas/workflow-definition.json",
|
|
107
|
+
$ref: "#/definitions/definition",
|
|
108
|
+
definitions: {
|
|
109
|
+
machine: {
|
|
110
|
+
type: "object",
|
|
111
|
+
required: ["StartAt", "States"],
|
|
112
|
+
properties: {
|
|
113
|
+
StartAt: name,
|
|
114
|
+
Comment: { type: "string" },
|
|
115
|
+
States: {
|
|
116
|
+
type: "object",
|
|
117
|
+
minProperties: 1,
|
|
118
|
+
propertyNames: name,
|
|
119
|
+
additionalProperties: { $ref: "#/definitions/state" }
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
definition: {
|
|
124
|
+
type: "object",
|
|
125
|
+
additionalProperties: false,
|
|
126
|
+
required: ["trigger", "stateMachine"],
|
|
127
|
+
properties: {
|
|
128
|
+
trigger: { $ref: "#/definitions/trigger" },
|
|
129
|
+
stateMachine: { $ref: "#/definitions/stateMachine" }
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
trigger: {
|
|
133
|
+
type: "object",
|
|
134
|
+
minProperties: 1,
|
|
135
|
+
maxProperties: 1,
|
|
136
|
+
propertyNames: { pattern: "^(manual|[a-z][a-z0-9_]*:[a-z][a-z0-9_]*(\\.[a-z][a-z0-9_]*)*)$" },
|
|
137
|
+
properties: { manual: {
|
|
138
|
+
type: "object",
|
|
139
|
+
maxProperties: 0
|
|
140
|
+
} },
|
|
141
|
+
additionalProperties: { type: "object" }
|
|
142
|
+
},
|
|
143
|
+
stateMachine: {
|
|
144
|
+
allOf: [{ $ref: "#/definitions/machine" }],
|
|
145
|
+
required: ["QueryLanguage"],
|
|
146
|
+
properties: {
|
|
147
|
+
QueryLanguage: { const: "JSONata" },
|
|
148
|
+
StartAt: {},
|
|
149
|
+
States: {},
|
|
150
|
+
Comment: {}
|
|
151
|
+
},
|
|
152
|
+
additionalProperties: false
|
|
153
|
+
},
|
|
154
|
+
processor: {
|
|
155
|
+
allOf: [{ $ref: "#/definitions/machine" }],
|
|
156
|
+
properties: {
|
|
157
|
+
ProcessorConfig: {
|
|
158
|
+
type: "object",
|
|
159
|
+
additionalProperties: false,
|
|
160
|
+
properties: { Mode: { const: "INLINE" } }
|
|
161
|
+
},
|
|
162
|
+
StartAt: {},
|
|
163
|
+
States: {},
|
|
164
|
+
Comment: {}
|
|
165
|
+
},
|
|
166
|
+
additionalProperties: false
|
|
167
|
+
},
|
|
168
|
+
state: {
|
|
169
|
+
type: "object",
|
|
170
|
+
required: ["Type"],
|
|
171
|
+
discriminator: { propertyName: "Type" },
|
|
172
|
+
oneOf: [
|
|
173
|
+
state("Pass", flow, nextOrEnd),
|
|
174
|
+
state("Task", {
|
|
175
|
+
...flow,
|
|
176
|
+
...recovery,
|
|
177
|
+
Resource: name,
|
|
178
|
+
Arguments: {},
|
|
179
|
+
TimeoutSeconds: {
|
|
180
|
+
type: "integer",
|
|
181
|
+
minimum: 1,
|
|
182
|
+
maximum: limits.taskTimeoutSeconds
|
|
183
|
+
}
|
|
184
|
+
}, {
|
|
185
|
+
required: ["Resource"],
|
|
186
|
+
...nextOrEnd
|
|
187
|
+
}),
|
|
188
|
+
state("Choice", {
|
|
189
|
+
Choices: {
|
|
190
|
+
type: "array",
|
|
191
|
+
minItems: 1,
|
|
192
|
+
items: {
|
|
193
|
+
type: "object",
|
|
194
|
+
additionalProperties: false,
|
|
195
|
+
required: ["Condition", "Next"],
|
|
196
|
+
properties: {
|
|
197
|
+
Condition: expression,
|
|
198
|
+
Next: name,
|
|
199
|
+
Comment: { type: "string" },
|
|
200
|
+
Output: {},
|
|
201
|
+
Assign: assign
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
Default: name
|
|
206
|
+
}, { required: ["Choices"] }),
|
|
207
|
+
state("Wait", {
|
|
208
|
+
...flow,
|
|
209
|
+
Seconds: { anyOf: [{
|
|
210
|
+
type: "integer",
|
|
211
|
+
minimum: 0,
|
|
212
|
+
maximum: limits.waitSeconds
|
|
213
|
+
}, expression] },
|
|
214
|
+
Timestamp: { type: "string" }
|
|
215
|
+
}, { allOf: [nextOrEnd, { oneOf: [{ required: ["Seconds"] }, { required: ["Timestamp"] }] }] }),
|
|
216
|
+
{
|
|
217
|
+
type: "object",
|
|
218
|
+
additionalProperties: false,
|
|
219
|
+
required: ["Type"],
|
|
220
|
+
properties: {
|
|
221
|
+
Type: { const: "Succeed" },
|
|
222
|
+
Comment: { type: "string" },
|
|
223
|
+
Output: {},
|
|
224
|
+
QueryLanguage: { const: "JSONata" }
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
type: "object",
|
|
229
|
+
additionalProperties: false,
|
|
230
|
+
required: ["Type"],
|
|
231
|
+
properties: {
|
|
232
|
+
Type: { const: "Fail" },
|
|
233
|
+
Comment: { type: "string" },
|
|
234
|
+
QueryLanguage: { const: "JSONata" },
|
|
235
|
+
Error: { type: "string" },
|
|
236
|
+
Cause: { type: "string" }
|
|
237
|
+
}
|
|
238
|
+
},
|
|
239
|
+
state("Map", {
|
|
240
|
+
...flow,
|
|
241
|
+
...recovery,
|
|
242
|
+
Items: {},
|
|
243
|
+
ItemProcessor: { $ref: "#/definitions/processor" },
|
|
244
|
+
MaxConcurrency: {
|
|
245
|
+
type: "integer",
|
|
246
|
+
minimum: 0,
|
|
247
|
+
maximum: limits.mapConcurrency
|
|
248
|
+
}
|
|
249
|
+
}, {
|
|
250
|
+
required: ["ItemProcessor", "Items"],
|
|
251
|
+
...nextOrEnd
|
|
252
|
+
})
|
|
253
|
+
]
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
//#endregion
|
|
258
|
+
export { definitionSchema };
|