ts2workflows 0.10.0 → 0.11.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 +1 -1
- package/README.md +22 -5
- package/dist/ast/stepnames.js +3 -3
- package/dist/ast/steps.d.ts +5 -5
- package/dist/ast/steps.d.ts.map +1 -1
- package/dist/ast/steps.js +11 -9
- package/dist/ast/workflows.d.ts +0 -5
- package/dist/ast/workflows.d.ts.map +1 -1
- package/dist/ast/workflows.js +1 -25
- package/dist/transpiler/index.d.ts +5 -0
- package/dist/transpiler/index.d.ts.map +1 -1
- package/dist/transpiler/index.js +9 -1
- package/dist/transpiler/statements.d.ts.map +1 -1
- package/dist/transpiler/statements.js +35 -37
- package/dist/utils.d.ts +0 -7
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +0 -10
- package/language_reference.md +45 -15
- package/package.json +11 -9
- package/types/workflowslib.d.ts +58 -74
- package/dist/ast/validation.d.ts +0 -20
- package/dist/ast/validation.d.ts.map +0 -1
- package/dist/ast/validation.js +0 -214
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright © 2024 Antti Ajanki, <antti.ajanki@iki.fi>
|
|
3
|
+
Copyright © 2024-2025 Antti Ajanki, <antti.ajanki@iki.fi>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
6
|
a copy of this software and associated documentation files (the
|
package/README.md
CHANGED
|
@@ -2,13 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
ts2workflows converts Typescript code to a [GCP Workflows](https://cloud.google.com/workflows/docs/apis) program.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
5
8
|
Only a subset of Typescript features are supported. The [language reference](language_reference.md) describes the supported Typescript features.
|
|
6
9
|
|
|
7
10
|
See the [samples](samples) directory for code examples.
|
|
8
11
|
|
|
9
12
|
Project status: It's possible to write Workflows programs, but the transpiler has not been extensively tested. Expect some rough edges!
|
|
10
13
|
|
|
11
|
-
##
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
npm install ts2workflows
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
12
21
|
|
|
13
22
|
Converting Typescript code in a file samples/sample1.ts into GCP Workflows YAML syntax on stdout:
|
|
14
23
|
|
|
@@ -28,7 +37,7 @@ When developing ts2workflows, you can run the transpiler directly from the sourc
|
|
|
28
37
|
npx tsx src/cli.ts samples/sample1.ts
|
|
29
38
|
```
|
|
30
39
|
|
|
31
|
-
## Type checking
|
|
40
|
+
## Type checking workflow sources
|
|
32
41
|
|
|
33
42
|
One benefit of writing the workflow programs in Typescript is that the sources can be type checked.
|
|
34
43
|
|
|
@@ -48,20 +57,28 @@ import { http, retry_policy } from 'ts2workflows/types/workflowslib'
|
|
|
48
57
|
|
|
49
58
|
Type checking step is completely separate from the transpiling. The ts2workflows command ignores type annotations.
|
|
50
59
|
|
|
51
|
-
##
|
|
60
|
+
## Development
|
|
61
|
+
|
|
62
|
+
### Build
|
|
52
63
|
|
|
53
64
|
```
|
|
54
65
|
npm install
|
|
55
66
|
npm run build
|
|
56
67
|
```
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
### Run unit tests
|
|
59
70
|
|
|
60
71
|
```
|
|
61
72
|
npm run test
|
|
62
73
|
```
|
|
63
74
|
|
|
64
|
-
|
|
75
|
+
Run tests and print the test coverage:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
npm run test-coverage
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Architecture
|
|
65
82
|
|
|
66
83
|
A transpilation using ts2workflows consists of five phases:
|
|
67
84
|
|
package/dist/ast/stepnames.js
CHANGED
|
@@ -12,9 +12,9 @@ export class StepNameGenerator {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
export function generateStepNames(ast) {
|
|
15
|
-
const stepNameGenerator = new StepNameGenerator();
|
|
16
15
|
const subworkflows = ast.subworkflows
|
|
17
16
|
.map((subworkflow) => {
|
|
17
|
+
const stepNameGenerator = new StepNameGenerator();
|
|
18
18
|
return subworkflow.withStepNames((x) => stepNameGenerator.generate(x));
|
|
19
19
|
})
|
|
20
20
|
.map(fixJumpLabels);
|
|
@@ -150,7 +150,7 @@ function removeJumpTargetsParallel(step) {
|
|
|
150
150
|
return new ParallelStepASTNamed(transformedSteps, step.shared, step.concurrenceLimit, step.exceptionPolicy);
|
|
151
151
|
}
|
|
152
152
|
function removeJumpTargetsSwitch(step) {
|
|
153
|
-
const transformedConditions = step.
|
|
153
|
+
const transformedConditions = step.branches.map((cond) => {
|
|
154
154
|
return {
|
|
155
155
|
condition: cond.condition,
|
|
156
156
|
steps: removeJumpTargetSteps(cond.steps),
|
|
@@ -250,7 +250,7 @@ function renameJumpTargetsSwitch(step, replaceLabels) {
|
|
|
250
250
|
if (step.next) {
|
|
251
251
|
updatedNext = replaceLabels.get(step.next) ?? step.next;
|
|
252
252
|
}
|
|
253
|
-
const updatedConditions = step.
|
|
253
|
+
const updatedConditions = step.branches.map((cond) => {
|
|
254
254
|
let updatedCondNext = undefined;
|
|
255
255
|
if (cond.next) {
|
|
256
256
|
updatedCondNext = replaceLabels.get(cond.next) ?? cond.next;
|
package/dist/ast/steps.d.ts
CHANGED
|
@@ -157,9 +157,9 @@ export declare class SwitchStepAST {
|
|
|
157
157
|
}
|
|
158
158
|
export declare class SwitchStepASTNamed {
|
|
159
159
|
readonly tag = "switch";
|
|
160
|
-
readonly
|
|
160
|
+
readonly branches: SwitchConditionAST<NamedWorkflowStep>[];
|
|
161
161
|
readonly next?: StepName;
|
|
162
|
-
constructor(
|
|
162
|
+
constructor(branches: SwitchConditionAST<NamedWorkflowStep>[], next?: StepName);
|
|
163
163
|
}
|
|
164
164
|
export interface SwitchConditionAST<T extends WorkflowStepAST | NamedWorkflowStep> {
|
|
165
165
|
readonly condition: Expression;
|
|
@@ -179,11 +179,11 @@ export declare class TryStepAST {
|
|
|
179
179
|
}
|
|
180
180
|
export declare class TryStepASTNamed {
|
|
181
181
|
readonly tag = "try";
|
|
182
|
-
readonly retryPolicy?: string | CustomRetryPolicy;
|
|
183
|
-
readonly errorMap?: VariableName;
|
|
184
182
|
readonly trySteps: NamedWorkflowStep[];
|
|
185
183
|
readonly exceptSteps?: NamedWorkflowStep[];
|
|
186
|
-
|
|
184
|
+
readonly retryPolicy?: string | CustomRetryPolicy;
|
|
185
|
+
readonly errorMap?: VariableName;
|
|
186
|
+
constructor(trySteps: NamedWorkflowStep[], exceptSteps?: NamedWorkflowStep[], retryPolicy?: string | CustomRetryPolicy, errorMap?: VariableName);
|
|
187
187
|
}
|
|
188
188
|
export declare class JumpTargetAST {
|
|
189
189
|
readonly tag = "jumptarget";
|
package/dist/ast/steps.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../../src/ast/steps.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../../src/ast/steps.ts"],"names":[],"mappings":"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"}
|
package/dist/ast/steps.js
CHANGED
|
@@ -267,17 +267,19 @@ export class SwitchStepAST {
|
|
|
267
267
|
}
|
|
268
268
|
export class SwitchStepASTNamed {
|
|
269
269
|
tag = 'switch';
|
|
270
|
-
|
|
270
|
+
branches;
|
|
271
271
|
next;
|
|
272
|
-
constructor(
|
|
273
|
-
this.
|
|
272
|
+
constructor(branches, next) {
|
|
273
|
+
this.branches = branches;
|
|
274
274
|
this.next = next;
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
// https://cloud.google.com/workflows/docs/reference/syntax/catching-errors
|
|
278
278
|
export class TryStepAST {
|
|
279
279
|
tag = 'try';
|
|
280
|
+
// Steps in the try block
|
|
280
281
|
trySteps;
|
|
282
|
+
// Steps in the except block
|
|
281
283
|
exceptSteps;
|
|
282
284
|
retryPolicy;
|
|
283
285
|
errorMap;
|
|
@@ -298,14 +300,14 @@ export class TryStepAST {
|
|
|
298
300
|
}
|
|
299
301
|
export class TryStepASTNamed {
|
|
300
302
|
tag = 'try';
|
|
301
|
-
retryPolicy;
|
|
302
|
-
errorMap;
|
|
303
303
|
// Steps in the try block
|
|
304
304
|
trySteps;
|
|
305
305
|
// Steps in the except block
|
|
306
306
|
exceptSteps;
|
|
307
|
-
|
|
308
|
-
|
|
307
|
+
retryPolicy;
|
|
308
|
+
errorMap;
|
|
309
|
+
constructor(trySteps, exceptSteps, retryPolicy, errorMap) {
|
|
310
|
+
this.trySteps = trySteps;
|
|
309
311
|
this.retryPolicy = retryPolicy;
|
|
310
312
|
this.errorMap = errorMap;
|
|
311
313
|
this.exceptSteps = exceptSteps;
|
|
@@ -443,7 +445,7 @@ export function nestedSteps(step) {
|
|
|
443
445
|
case 'parallel':
|
|
444
446
|
return nestedStepsParallel(step);
|
|
445
447
|
case 'switch':
|
|
446
|
-
return step.
|
|
448
|
+
return step.branches.map((x) => x.steps);
|
|
447
449
|
case 'try':
|
|
448
450
|
return nestedStepsTry(step);
|
|
449
451
|
}
|
|
@@ -519,7 +521,7 @@ export function renderStep(step) {
|
|
|
519
521
|
};
|
|
520
522
|
case 'switch':
|
|
521
523
|
return {
|
|
522
|
-
switch: step.
|
|
524
|
+
switch: step.branches.map(renderSwitchCondition),
|
|
523
525
|
...(step.next && { next: step.next }),
|
|
524
526
|
};
|
|
525
527
|
case 'try':
|
package/dist/ast/workflows.d.ts
CHANGED
|
@@ -19,10 +19,5 @@ export declare class Subworkflow {
|
|
|
19
19
|
constructor(name: string, steps: NamedWorkflowStep[], params?: WorkflowParameter[]);
|
|
20
20
|
render(): Record<string, unknown>;
|
|
21
21
|
renderBody(): Record<string, unknown>;
|
|
22
|
-
iterateStepsDepthFirst(): IterableIterator<NamedWorkflowStep>;
|
|
23
22
|
}
|
|
24
|
-
/**
|
|
25
|
-
* Print the workflow as a YAML string.
|
|
26
|
-
*/
|
|
27
|
-
export declare function toYAMLString(workflow: WorkflowApp): string;
|
|
28
23
|
//# sourceMappingURL=workflows.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/ast/workflows.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/ast/workflows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,+BAA+B,EAAE,MAAM,kBAAkB,CAAA;AAChF,OAAO,EAAE,iBAAiB,EAAc,MAAM,YAAY,CAAA;AAE1D,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,YAAY,CAAA;IAClB,OAAO,CAAC,EAAE,+BAA+B,CAAA;CAC1C;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,YAAY,EAAE,WAAW,EAAE,CAAA;gBAExB,YAAY,GAAE,WAAW,EAAO;IAI5C,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAKlC;AAGD,qBAAa,WAAW;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,EAAE,CAAA;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAA;gBAGnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,iBAAiB,EAAE,EAC1B,MAAM,CAAC,EAAE,iBAAiB,EAAE;IAO9B,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAMjC,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAsBtC"}
|
package/dist/ast/workflows.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { nestedSteps, renderStep } from './steps.js';
|
|
1
|
+
import { renderStep } from './steps.js';
|
|
3
2
|
/**
|
|
4
3
|
* This is the main container class that brings together all subworkflows in a program
|
|
5
4
|
*/
|
|
@@ -48,27 +47,4 @@ export class Subworkflow {
|
|
|
48
47
|
});
|
|
49
48
|
return body;
|
|
50
49
|
}
|
|
51
|
-
*iterateStepsDepthFirst() {
|
|
52
|
-
const visited = new Set();
|
|
53
|
-
function* visitPreOrder(step) {
|
|
54
|
-
if (!visited.has(step)) {
|
|
55
|
-
visited.add(step);
|
|
56
|
-
yield step;
|
|
57
|
-
for (const x of nestedSteps(step.step).flat()) {
|
|
58
|
-
yield* visitPreOrder(x);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
for (const step of this.steps) {
|
|
63
|
-
yield* visitPreOrder(step);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Print the workflow as a YAML string.
|
|
69
|
-
*/
|
|
70
|
-
export function toYAMLString(workflow) {
|
|
71
|
-
return YAML.stringify(workflow.render(), {
|
|
72
|
-
lineWidth: 100,
|
|
73
|
-
});
|
|
74
50
|
}
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
+
import { WorkflowApp } from '../ast/workflows.js';
|
|
1
2
|
export declare function transpile(code: string, inputFile?: string, tsconfigPath?: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Print the workflow as a YAML string.
|
|
5
|
+
*/
|
|
6
|
+
export declare function toYAMLString(workflow: WorkflowApp): string;
|
|
2
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transpiler/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transpiler/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAqB,MAAM,qBAAqB,CAAA;AAKpE,wBAAgB,SAAS,CACvB,IAAI,EAAE,MAAM,EACZ,SAAS,CAAC,EAAE,MAAM,EAClB,YAAY,CAAC,EAAE,MAAM,GACpB,MAAM,CAkBR;AAuID;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,CAI1D"}
|
package/dist/transpiler/index.js
CHANGED
|
@@ -20,7 +20,7 @@ export function transpile(code, inputFile, tsconfigPath) {
|
|
|
20
20
|
const { ast } = parseAndGenerateServices(code, parserOptions);
|
|
21
21
|
const workflowAst = { subworkflows: ast.body.flatMap(parseTopLevelStatement) };
|
|
22
22
|
const workflow = generateStepNames(workflowAst);
|
|
23
|
-
return
|
|
23
|
+
return toYAMLString(workflow);
|
|
24
24
|
}
|
|
25
25
|
function parseTopLevelStatement(node) {
|
|
26
26
|
switch (node.type) {
|
|
@@ -104,3 +104,11 @@ function parseSubworkflowDefaultArgument(param) {
|
|
|
104
104
|
default: defaultValue,
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Print the workflow as a YAML string.
|
|
109
|
+
*/
|
|
110
|
+
export function toYAMLString(workflow) {
|
|
111
|
+
return YAML.stringify(workflow.render(), {
|
|
112
|
+
lineWidth: 100,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statements.d.ts","sourceRoot":"","sources":["../../src/transpiler/statements.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,QAAQ,EAAE,MAAM,sCAAsC,CAAA;AAC/E,OAAO,EAWL,QAAQ,EAOR,eAAe,EAChB,MAAM,iBAAiB,CAAA;AAkCxB,MAAM,WAAW,cAAc;IAE7B,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAA;IAE/B,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAA;IAGlC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAKtC,gBAAgB,CAAC,EAAE,QAAQ,EAAE,CAAA;CAC9B;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,CAAC,SAAS,EACxB,GAAG,EAAE,cAAc,GAClB,eAAe,EAAE,
|
|
1
|
+
{"version":3,"file":"statements.d.ts","sourceRoot":"","sources":["../../src/transpiler/statements.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,QAAQ,EAAE,MAAM,sCAAsC,CAAA;AAC/E,OAAO,EAWL,QAAQ,EAOR,eAAe,EAChB,MAAM,iBAAiB,CAAA;AAkCxB,MAAM,WAAW,cAAc;IAE7B,QAAQ,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAA;IAE/B,QAAQ,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAA;IAGlC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAKtC,gBAAgB,CAAC,EAAE,QAAQ,EAAE,CAAA;CAC9B;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,CAAC,SAAS,EACxB,GAAG,EAAE,cAAc,GAClB,eAAe,EAAE,CA6EnB"}
|
|
@@ -3,18 +3,15 @@ import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
|
|
|
3
3
|
import { AssignStepAST, CallStepAST, ForRangeStepAST, ForStepAST, JumpTargetAST, NextStepAST, ParallelStepAST, RaiseStepAST, ReturnStepAST, StepsStepAST, SwitchStepAST, TryStepAST, } from '../ast/steps.js';
|
|
4
4
|
import { BinaryExpression, FunctionInvocationExpression, MemberExpression, PrimitiveExpression, VariableReferenceExpression, asExpression, isExpression, isFullyQualifiedName, isLiteral, isPure, nullEx, safeAsExpression, trueEx, } from '../ast/expressions.js';
|
|
5
5
|
import { InternalTranspilingError, WorkflowSyntaxError } from '../errors.js';
|
|
6
|
-
import {
|
|
6
|
+
import { isRecord } from '../utils.js';
|
|
7
7
|
import { convertExpression, convertMemberExpression, convertObjectExpression, convertObjectAsExpressionValues, isIntrinsic, throwIfSpread, isIntrinsicStatment as isIntrinsicStatement, convertVariableNameExpression, } from './expressions.js';
|
|
8
8
|
import { blockingFunctions } from './generated/functionMetadata.js';
|
|
9
9
|
export function parseStatement(node, ctx) {
|
|
10
|
-
return parseStatementRecursively(node, undefined, ctx);
|
|
11
|
-
}
|
|
12
|
-
function parseStatementRecursively(node, nextNode, ctx) {
|
|
13
10
|
switch (node.type) {
|
|
14
11
|
case AST_NODE_TYPES.BlockStatement:
|
|
15
|
-
return
|
|
12
|
+
return node.body.flatMap((node) => parseStatement(node, ctx));
|
|
16
13
|
case AST_NODE_TYPES.VariableDeclaration:
|
|
17
|
-
return convertVariableDeclarations(node
|
|
14
|
+
return convertVariableDeclarations(node, ctx);
|
|
18
15
|
case AST_NODE_TYPES.ExpressionStatement:
|
|
19
16
|
if (node.expression.type === AST_NODE_TYPES.AssignmentExpression) {
|
|
20
17
|
return assignmentExpressionToSteps(node.expression, ctx);
|
|
@@ -45,14 +42,8 @@ function parseStatementRecursively(node, nextNode, ctx) {
|
|
|
45
42
|
return [breakStatementToNextStep(node, ctx)];
|
|
46
43
|
case AST_NODE_TYPES.ContinueStatement:
|
|
47
44
|
return [continueStatementToNextStep(node, ctx)];
|
|
48
|
-
case AST_NODE_TYPES.TryStatement:
|
|
49
|
-
|
|
50
|
-
if (nextNode?.type === AST_NODE_TYPES.ExpressionStatement &&
|
|
51
|
-
nextNode.expression.type === AST_NODE_TYPES.CallExpression) {
|
|
52
|
-
retryPolicy = parseRetryPolicy(nextNode.expression);
|
|
53
|
-
}
|
|
54
|
-
return tryStatementToTrySteps(node, retryPolicy, ctx);
|
|
55
|
-
}
|
|
45
|
+
case AST_NODE_TYPES.TryStatement:
|
|
46
|
+
return tryStatementToTrySteps(node, ctx);
|
|
56
47
|
case AST_NODE_TYPES.LabeledStatement:
|
|
57
48
|
return labeledStep(node, ctx);
|
|
58
49
|
case AST_NODE_TYPES.EmptyStatement:
|
|
@@ -68,8 +59,11 @@ function parseStatementRecursively(node, nextNode, ctx) {
|
|
|
68
59
|
throw new WorkflowSyntaxError(`TODO: encountered unsupported type: ${node.type}`, node.loc);
|
|
69
60
|
}
|
|
70
61
|
}
|
|
71
|
-
function convertVariableDeclarations(
|
|
72
|
-
|
|
62
|
+
function convertVariableDeclarations(node, ctx) {
|
|
63
|
+
if (node.kind !== 'const' && node.kind !== 'let') {
|
|
64
|
+
throw new WorkflowSyntaxError('Only const and let variable declarations are supported', node.loc);
|
|
65
|
+
}
|
|
66
|
+
return node.declarations.flatMap((decl) => {
|
|
73
67
|
if (decl.id.type === AST_NODE_TYPES.Identifier) {
|
|
74
68
|
return convertInitializer(decl.id.name, decl.init, ctx);
|
|
75
69
|
}
|
|
@@ -885,7 +879,8 @@ function continueStatementToNextStep(node, ctx) {
|
|
|
885
879
|
}
|
|
886
880
|
return new NextStepAST(target);
|
|
887
881
|
}
|
|
888
|
-
function tryStatementToTrySteps(node,
|
|
882
|
+
function tryStatementToTrySteps(node, ctx) {
|
|
883
|
+
const retryPolicy = extractRetryPolicy(node.block);
|
|
889
884
|
if (!node.finalizer) {
|
|
890
885
|
// Basic try-catch without a finally block
|
|
891
886
|
const baseTryStep = parseTryCatchRetry(node, ctx, retryPolicy);
|
|
@@ -1033,27 +1028,30 @@ function labeledStep(node, ctx) {
|
|
|
1033
1028
|
}
|
|
1034
1029
|
return steps;
|
|
1035
1030
|
}
|
|
1036
|
-
function
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1031
|
+
function extractRetryPolicy(tryBlock) {
|
|
1032
|
+
// Find and parse the first retry_policy() in tryBlock
|
|
1033
|
+
for (const statement of tryBlock.body) {
|
|
1034
|
+
if (statement.type === AST_NODE_TYPES.ExpressionStatement &&
|
|
1035
|
+
statement.expression.type === AST_NODE_TYPES.CallExpression &&
|
|
1036
|
+
statement.expression.callee.type === AST_NODE_TYPES.Identifier &&
|
|
1037
|
+
statement.expression.callee.name === 'retry_policy') {
|
|
1038
|
+
if (statement.expression.arguments.length < 1) {
|
|
1039
|
+
throw new WorkflowSyntaxError('Required argument missing', statement.expression.loc);
|
|
1040
|
+
}
|
|
1041
|
+
const arg0 = throwIfSpread(statement.expression.arguments).map(convertExpression)[0];
|
|
1042
|
+
const argsLoc = statement.expression.arguments[0].loc;
|
|
1043
|
+
if (isFullyQualifiedName(arg0)) {
|
|
1044
|
+
return arg0.toString();
|
|
1045
|
+
}
|
|
1046
|
+
else if (arg0.expressionType === 'primitive' && isRecord(arg0.value)) {
|
|
1047
|
+
return retryPolicyFromParams(arg0.value, argsLoc);
|
|
1048
|
+
}
|
|
1049
|
+
else {
|
|
1050
|
+
throw new WorkflowSyntaxError('Unexpected type', argsLoc);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1056
1053
|
}
|
|
1054
|
+
return undefined;
|
|
1057
1055
|
}
|
|
1058
1056
|
function retryPolicyFromParams(paramsObject, argsLoc) {
|
|
1059
1057
|
const params = R.map(asExpression, paramsObject);
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
1
|
export declare function isRecord(object: unknown): object is Record<keyof never, unknown>;
|
|
2
|
-
/**
|
|
3
|
-
* Like arr.flatMap() but the callback takes two consecutive array elements.
|
|
4
|
-
*
|
|
5
|
-
* During the last execution of the callback, the second argument (which would
|
|
6
|
-
* be element after the last array element) will be undefined.
|
|
7
|
-
*/
|
|
8
|
-
export declare function chainPairs<T, U>(callback: (val: T, next: T | undefined) => U[], arr: readonly T[]): U[];
|
|
9
2
|
//# sourceMappingURL=utils.d.ts.map
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,QAAQ,CACtB,MAAM,EAAE,OAAO,GACd,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,EAAE,OAAO,CAAC,CAExC"}
|
package/dist/utils.js
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
import * as R from 'ramda';
|
|
2
1
|
export function isRecord(object) {
|
|
3
2
|
return object instanceof Object && object.constructor === Object;
|
|
4
3
|
}
|
|
5
|
-
/**
|
|
6
|
-
* Like arr.flatMap() but the callback takes two consecutive array elements.
|
|
7
|
-
*
|
|
8
|
-
* During the last execution of the callback, the second argument (which would
|
|
9
|
-
* be element after the last array element) will be undefined.
|
|
10
|
-
*/
|
|
11
|
-
export function chainPairs(callback, arr) {
|
|
12
|
-
return R.chain(R.apply(callback), R.zip(arr, R.append(undefined, R.tail(arr))));
|
|
13
|
-
}
|
package/language_reference.md
CHANGED
|
@@ -20,6 +20,14 @@ Semicolon can be used as optional statement delimitter.
|
|
|
20
20
|
- Array: `[1, 2, 3]`
|
|
21
21
|
- Map: `{temperature: -12, unit: "Celsius"}`
|
|
22
22
|
|
|
23
|
+
The Typescript type alias `WorkflowsValue` (provided by `ts2workflows/types/workflowslib`) represents any valid Workflows value. Sample usage:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { WorkflowsValue } from 'ts2workflows/types/workflowslib'
|
|
27
|
+
|
|
28
|
+
const x: WorkflowsValue = [1, 2]
|
|
29
|
+
```
|
|
30
|
+
|
|
23
31
|
### Array type
|
|
24
32
|
|
|
25
33
|
⚠️ Arrays are not objects in GCP Workflows. In particular, methods like `[].map()` and `[].concat()` are not available.
|
|
@@ -46,7 +54,7 @@ Note that `null` and `undefined` still are distinct types on the type checking s
|
|
|
46
54
|
|
|
47
55
|
Expressions that combine variables with operators such as `+`, `>`, `==` perform implict type conversions according to the [rules listed on GCP Workflows documentation](https://cloud.google.com/workflows/docs/reference/syntax/datatypes#implicit-conversions). For example, applying `+` to a string and a number concatenates the values into a string.
|
|
48
56
|
|
|
49
|
-
⚠️ Checking if a variable is null or not must be done by an explicit comparison: `if (
|
|
57
|
+
⚠️ Checking if a variable is null or not must be done by an explicit comparison: `if (myVar != null) {...}`. Relying on an implicit conversion (`if (myVvar) {...}` where `myVar` is not a boolean) results in a TypeError at runtime.
|
|
50
58
|
|
|
51
59
|
## Expressions
|
|
52
60
|
|
|
@@ -156,6 +164,25 @@ String literals can include interpolated variables. The syntax is same as in Typ
|
|
|
156
164
|
|
|
157
165
|
⚠️ Interpolated values can (only) be numbers, strings, booleans or nulls. Other types will throw a TypeError at runtime.
|
|
158
166
|
|
|
167
|
+
## Variable scopes
|
|
168
|
+
|
|
169
|
+
Variable scopes are determined by the [GCP Workflows scoping rules](https://cloud.google.com/workflows/docs/reference/syntax/variables#variable-scope).
|
|
170
|
+
|
|
171
|
+
Variables have function scope, that is they are available in the function where they are defined. Variables defined in `for` and `except` blocks are exceptions; they belong to a local scope of the block in which they are declared.
|
|
172
|
+
|
|
173
|
+
⚠️ TypeScript has more strict scoping rules. In Typescript, variables declared with `let` or `const` are accessible only on the block in which they are declared (i.e. variable declared inside an if branch cannot be accessed after the if block ends). Programs written according to TypeScript scoping rules always produce valid GCP Workflows programs, too.
|
|
174
|
+
|
|
175
|
+
Trying to read a variable before it is assigned causes a runtime error.
|
|
176
|
+
|
|
177
|
+
⚠️ If variable is not initialized at declaration, its value is implicitly set to `null`. For example, the following program will return `null`. (Note that the sample is not valid as a TypeScript program. TypeScript compiler consideres variable `x` to be used before it is assigned.)
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
function main(): void {
|
|
181
|
+
let x: number | null
|
|
182
|
+
return x
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
159
186
|
## Subworkflow definitions
|
|
160
187
|
|
|
161
188
|
ts2workflows converts Typescript `function`s to subworkflow definitions.
|
|
@@ -694,24 +721,25 @@ If an exception gets thrown inside a try block, the stack trace in Workflows log
|
|
|
694
721
|
|
|
695
722
|
## Retrying on errors
|
|
696
723
|
|
|
697
|
-
It is possible to set a retry policy for a try-catch statement. Because Typescript does not have `retry` keyword, the retry is implemented by a
|
|
724
|
+
It is possible to set a retry policy for a try-catch statement. Because Typescript does not have `retry` keyword, the retry is implemented by a `retry_policy` intrinsic function. It must be called inside a try block. `retry_policy` is ignored elsewhere. Only the first `retry_policy` in a try block has any effect.
|
|
698
725
|
|
|
699
726
|
The arguments of `retry_policy` specify which errors are retried and how many times. The arguments can be either a policy provided by GCP Workflows or a custom retry policy as explained in the next sections.
|
|
700
727
|
|
|
701
|
-
If an exception gets thrown in a try block and the retry policy covers the exception, the try block is executed again. Finally and catch blocks are run after
|
|
728
|
+
If an exception gets thrown in a try block and the retry policy covers the exception, the try block is executed again. Finally and catch blocks are run if the try block keeps failing after all retry attempts have been used up. The following sample retries `http.get()` if it throws an HTTP error covered by `http.default_retry`. It logs `sys.log('Error!')` if the number of retry attempts exceed retry policy's maximum retry attempt count. `closeConnection()` is run always regardless of whether the HTTP request succeeded or failed.
|
|
702
729
|
|
|
703
730
|
```javascript
|
|
704
731
|
import { http, retry_policy, sys } from 'ts2workflows/types/workflowslib'
|
|
705
732
|
|
|
706
733
|
function main() {
|
|
707
734
|
try {
|
|
735
|
+
retry_policy(http.default_retry)
|
|
736
|
+
|
|
708
737
|
http.get('https://visit.dreamland.test/')
|
|
709
738
|
} catch (err) {
|
|
710
739
|
sys.log('Error!')
|
|
711
740
|
} finally {
|
|
712
741
|
closeConnection()
|
|
713
742
|
}
|
|
714
|
-
retry_policy(http.default_retry)
|
|
715
743
|
}
|
|
716
744
|
```
|
|
717
745
|
|
|
@@ -724,11 +752,12 @@ import { http, retry_policy } from 'ts2workflows/types/workflowslib'
|
|
|
724
752
|
|
|
725
753
|
function main() {
|
|
726
754
|
try {
|
|
755
|
+
retry_policy(http.default_retry)
|
|
756
|
+
|
|
727
757
|
http.get('https://visit.dreamland.test/')
|
|
728
758
|
} catch (err) {
|
|
729
759
|
return 'Error!'
|
|
730
760
|
}
|
|
731
|
-
retry_policy(http.default_retry)
|
|
732
761
|
}
|
|
733
762
|
```
|
|
734
763
|
|
|
@@ -743,19 +772,20 @@ import { http, retry_policy } from 'ts2workflows/types/workflowslib'
|
|
|
743
772
|
|
|
744
773
|
function main() {
|
|
745
774
|
try {
|
|
775
|
+
retry_policy({
|
|
776
|
+
predicate: http.default_retry_predicate,
|
|
777
|
+
max_retries: 3,
|
|
778
|
+
backoff: {
|
|
779
|
+
initial_delay: 0.5,
|
|
780
|
+
max_delay: 60,
|
|
781
|
+
multiplier: 2,
|
|
782
|
+
},
|
|
783
|
+
})
|
|
784
|
+
|
|
746
785
|
http.get('https://visit.dreamland.test/')
|
|
747
786
|
} catch (err) {
|
|
748
787
|
return 'Error!'
|
|
749
788
|
}
|
|
750
|
-
retry_policy({
|
|
751
|
-
predicate: http.default_retry_predicate,
|
|
752
|
-
max_retries: 3,
|
|
753
|
-
backoff: {
|
|
754
|
-
initial_delay: 0.5,
|
|
755
|
-
max_delay: 60,
|
|
756
|
-
multiplier: 2,
|
|
757
|
-
},
|
|
758
|
-
})
|
|
759
789
|
}
|
|
760
790
|
```
|
|
761
791
|
|
|
@@ -904,7 +934,7 @@ function retry_policy(
|
|
|
904
934
|
): void
|
|
905
935
|
```
|
|
906
936
|
|
|
907
|
-
A retry policy can be attached to a `try`-`catch` block
|
|
937
|
+
A retry policy can be attached to a `try`-`catch` block by calling `retry_policy` inside the `try` block. ts2workflows ignores `retry_policy` everywhere else.
|
|
908
938
|
|
|
909
939
|
See the section on [retrying errors](#retrying-on-errors).
|
|
910
940
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts2workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Transpile Typescript code to GCP Workflows programs",
|
|
5
5
|
"homepage": "https://github.com/aajanki/ts2workflows",
|
|
6
6
|
"repository": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"types": "dist/index.d.ts",
|
|
13
13
|
"type": "module",
|
|
14
14
|
"engines": {
|
|
15
|
-
"node": ">=
|
|
15
|
+
"node": ">=20"
|
|
16
16
|
},
|
|
17
17
|
"scripts": {
|
|
18
18
|
"build": "rimraf dist && npm run build:functionmetadata && tsc",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"lint": "eslint src test scripts",
|
|
21
21
|
"format": "prettier . --write",
|
|
22
22
|
"test": "mocha",
|
|
23
|
+
"test-coverage": "nyc mocha",
|
|
23
24
|
"prepare": "husky && npm run build"
|
|
24
25
|
},
|
|
25
26
|
"lint-staged": {
|
|
@@ -61,25 +62,26 @@
|
|
|
61
62
|
"@eslint/js": "^9.10.0",
|
|
62
63
|
"@types/chai": "^5.0.1",
|
|
63
64
|
"@types/mocha": "^10.0.6",
|
|
64
|
-
"@types/node": "^
|
|
65
|
+
"@types/node": "^20",
|
|
65
66
|
"@types/ramda": "^0.30.2",
|
|
66
67
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
67
68
|
"@typescript-eslint/parser": "^8.0.0",
|
|
68
69
|
"chai": "^5.1.1",
|
|
69
70
|
"eslint": "^9.10.0",
|
|
70
71
|
"husky": "^9.1.6",
|
|
71
|
-
"lint-staged": "^
|
|
72
|
+
"lint-staged": "^16.1.2",
|
|
72
73
|
"mocha": "^11.1.0",
|
|
74
|
+
"nyc": "^17.1.0",
|
|
73
75
|
"prettier": "^3.2.5",
|
|
74
|
-
"rimraf": "^
|
|
75
|
-
"tsx": "
|
|
76
|
+
"rimraf": "^6.0.1",
|
|
77
|
+
"tsx": "~4.19.4",
|
|
76
78
|
"typescript-eslint": "^8.0.0"
|
|
77
79
|
},
|
|
78
80
|
"dependencies": {
|
|
79
81
|
"@typescript-eslint/typescript-estree": "^8.0.0",
|
|
80
|
-
"commander": "^
|
|
81
|
-
"ramda": "^0.
|
|
82
|
-
"typescript": "^5.
|
|
82
|
+
"commander": "^14.0.0",
|
|
83
|
+
"ramda": "^0.31.3",
|
|
84
|
+
"typescript": "^5.4.0",
|
|
83
85
|
"yaml": "^2.4.2"
|
|
84
86
|
}
|
|
85
87
|
}
|
package/types/workflowslib.d.ts
CHANGED
|
@@ -10,6 +10,28 @@ export interface bytes {
|
|
|
10
10
|
readonly [__bytes_tag]: 'bytes'
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
// GCP Workflows data types
|
|
14
|
+
export type WorkflowsValue =
|
|
15
|
+
| boolean
|
|
16
|
+
| number
|
|
17
|
+
| string
|
|
18
|
+
| bytes
|
|
19
|
+
| WorkflowsValue[]
|
|
20
|
+
| { [key: string]: WorkflowsValue }
|
|
21
|
+
| null
|
|
22
|
+
|
|
23
|
+
type BooleanNumberStringListOrDict =
|
|
24
|
+
| boolean
|
|
25
|
+
| number
|
|
26
|
+
| string
|
|
27
|
+
| BooleanNumberStringListOrDict[]
|
|
28
|
+
| { [key: string]: BooleanNumberStringListOrDict }
|
|
29
|
+
|
|
30
|
+
type HTTPQuery = Record<
|
|
31
|
+
string,
|
|
32
|
+
string | number | boolean | (string | number | boolean)[]
|
|
33
|
+
>
|
|
34
|
+
|
|
13
35
|
// GCP Workflows expression helpers
|
|
14
36
|
|
|
15
37
|
export declare function double(x: string | number): number
|
|
@@ -19,19 +41,10 @@ export declare function keys(map: Record<string, unknown>): string[]
|
|
|
19
41
|
export declare function len(
|
|
20
42
|
value: unknown[] | Record<string, unknown> | string,
|
|
21
43
|
): number
|
|
22
|
-
export declare function get_type(
|
|
23
|
-
value:
|
|
24
|
-
| boolean
|
|
25
|
-
| number
|
|
26
|
-
| string
|
|
27
|
-
| unknown[]
|
|
28
|
-
| Record<string, unknown>
|
|
29
|
-
| null
|
|
30
|
-
| bytes
|
|
31
|
-
| undefined,
|
|
32
|
-
): string
|
|
44
|
+
export declare function get_type(value: unknown): string
|
|
33
45
|
|
|
34
46
|
// GCP Workflows standard library functions
|
|
47
|
+
// https://cloud.google.com/workflows/docs/reference/stdlib/overview
|
|
35
48
|
|
|
36
49
|
export declare namespace base64 {
|
|
37
50
|
function decode(data: bytes, padding?: boolean): string
|
|
@@ -39,7 +52,7 @@ export declare namespace base64 {
|
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
export declare namespace events {
|
|
42
|
-
function await_callback<ResponseType =
|
|
55
|
+
function await_callback<ResponseType = WorkflowsValue>(
|
|
43
56
|
callback: {
|
|
44
57
|
url: string
|
|
45
58
|
},
|
|
@@ -80,15 +93,12 @@ export declare namespace http {
|
|
|
80
93
|
export function default_retry_predicate_non_idempotent(
|
|
81
94
|
errormap: Record<string, any>,
|
|
82
95
|
): boolean
|
|
83
|
-
function _delete<ResponseType =
|
|
96
|
+
function _delete<ResponseType = WorkflowsValue>(
|
|
84
97
|
url: string,
|
|
85
98
|
timeout?: number,
|
|
86
|
-
body?:
|
|
99
|
+
body?: any,
|
|
87
100
|
headers?: Record<string, string>,
|
|
88
|
-
query?:
|
|
89
|
-
string,
|
|
90
|
-
string | number | boolean | (string | number | boolean)[]
|
|
91
|
-
>,
|
|
101
|
+
query?: HTTPQuery,
|
|
92
102
|
auth?: Record<string, string>,
|
|
93
103
|
private_service_name?: string,
|
|
94
104
|
ca_certificate?: string,
|
|
@@ -97,14 +107,11 @@ export declare namespace http {
|
|
|
97
107
|
code: number
|
|
98
108
|
headers: Record<string, string>
|
|
99
109
|
}
|
|
100
|
-
export function get<ResponseType =
|
|
110
|
+
export function get<ResponseType = WorkflowsValue>(
|
|
101
111
|
url: string,
|
|
102
112
|
timeout?: number,
|
|
103
113
|
headers?: Record<string, string>,
|
|
104
|
-
query?:
|
|
105
|
-
string,
|
|
106
|
-
string | number | boolean | (string | number | boolean)[]
|
|
107
|
-
>,
|
|
114
|
+
query?: HTTPQuery,
|
|
108
115
|
auth?: Record<string, string>,
|
|
109
116
|
private_service_name?: string,
|
|
110
117
|
ca_certificate?: string,
|
|
@@ -113,10 +120,10 @@ export declare namespace http {
|
|
|
113
120
|
code: number
|
|
114
121
|
headers: Record<string, string>
|
|
115
122
|
}
|
|
116
|
-
export function patch<ResponseType =
|
|
123
|
+
export function patch<ResponseType = WorkflowsValue>(
|
|
117
124
|
url: string,
|
|
118
125
|
timeout?: number,
|
|
119
|
-
body?:
|
|
126
|
+
body?: any,
|
|
120
127
|
headers?: Record<string, string>,
|
|
121
128
|
query?: Record<
|
|
122
129
|
string,
|
|
@@ -130,15 +137,12 @@ export declare namespace http {
|
|
|
130
137
|
code: number
|
|
131
138
|
headers: Record<string, string>
|
|
132
139
|
}
|
|
133
|
-
export function post<ResponseType =
|
|
140
|
+
export function post<ResponseType = WorkflowsValue>(
|
|
134
141
|
url: string,
|
|
135
142
|
timeout?: number,
|
|
136
|
-
body?:
|
|
143
|
+
body?: any,
|
|
137
144
|
headers?: Record<string, string>,
|
|
138
|
-
query?:
|
|
139
|
-
string,
|
|
140
|
-
string | number | boolean | (string | number | boolean)[]
|
|
141
|
-
>,
|
|
145
|
+
query?: HTTPQuery,
|
|
142
146
|
auth?: Record<string, string>,
|
|
143
147
|
private_service_name?: string,
|
|
144
148
|
ca_certificate?: string,
|
|
@@ -147,15 +151,12 @@ export declare namespace http {
|
|
|
147
151
|
code: number
|
|
148
152
|
headers: Record<string, string>
|
|
149
153
|
}
|
|
150
|
-
export function put<ResponseType =
|
|
154
|
+
export function put<ResponseType = WorkflowsValue>(
|
|
151
155
|
url: string,
|
|
152
156
|
timeout?: number,
|
|
153
|
-
body?:
|
|
157
|
+
body?: any,
|
|
154
158
|
headers?: Record<string, string>,
|
|
155
|
-
query?:
|
|
156
|
-
string,
|
|
157
|
-
string | number | boolean | (string | number | boolean)[]
|
|
158
|
-
>,
|
|
159
|
+
query?: HTTPQuery,
|
|
159
160
|
auth?: Record<string, string>,
|
|
160
161
|
private_service_name?: string,
|
|
161
162
|
ca_certificate?: string,
|
|
@@ -164,16 +165,13 @@ export declare namespace http {
|
|
|
164
165
|
code: number
|
|
165
166
|
headers: Record<string, string>
|
|
166
167
|
}
|
|
167
|
-
export function request<ResponseType =
|
|
168
|
+
export function request<ResponseType = WorkflowsValue>(
|
|
168
169
|
method: string,
|
|
169
170
|
url: string,
|
|
170
171
|
timeout?: number,
|
|
171
|
-
body?:
|
|
172
|
+
body?: any,
|
|
172
173
|
headers?: Record<string, string>,
|
|
173
|
-
query?:
|
|
174
|
-
string,
|
|
175
|
-
string | number | boolean | (string | number | boolean)[]
|
|
176
|
-
>,
|
|
174
|
+
query?: HTTPQuery,
|
|
177
175
|
auth?: Record<string, string>,
|
|
178
176
|
private_service_name?: string,
|
|
179
177
|
ca_certificate?: string,
|
|
@@ -186,16 +184,9 @@ export declare namespace http {
|
|
|
186
184
|
}
|
|
187
185
|
|
|
188
186
|
export declare namespace json {
|
|
189
|
-
function decode(data: bytes | string):
|
|
187
|
+
function decode(data: bytes | string): WorkflowsValue
|
|
190
188
|
function encode(
|
|
191
|
-
data:
|
|
192
|
-
| string
|
|
193
|
-
| number
|
|
194
|
-
| boolean
|
|
195
|
-
| unknown[]
|
|
196
|
-
| Record<string, unknown>
|
|
197
|
-
| null
|
|
198
|
-
| undefined,
|
|
189
|
+
data: unknown,
|
|
199
190
|
indent?:
|
|
200
191
|
| boolean
|
|
201
192
|
| {
|
|
@@ -204,14 +195,7 @@ export declare namespace json {
|
|
|
204
195
|
},
|
|
205
196
|
): bytes
|
|
206
197
|
function encode_to_string(
|
|
207
|
-
data:
|
|
208
|
-
| string
|
|
209
|
-
| number
|
|
210
|
-
| boolean
|
|
211
|
-
| unknown[]
|
|
212
|
-
| Record<string, unknown>
|
|
213
|
-
| null
|
|
214
|
-
| undefined,
|
|
198
|
+
data: unknown,
|
|
215
199
|
indent?:
|
|
216
200
|
| boolean
|
|
217
201
|
| {
|
|
@@ -228,10 +212,10 @@ export declare namespace list {
|
|
|
228
212
|
|
|
229
213
|
export declare namespace map {
|
|
230
214
|
function _delete<T>(map: Record<string, T>, key: string): Record<string, T>
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
215
|
+
// map.get() with a string key, returns a property value or null
|
|
216
|
+
export function get<T>(map: Record<string, T>, keys: string): T | null
|
|
217
|
+
// map.get() with string[] key or non-object lookup, the return type is unknown
|
|
218
|
+
export function get(map: any, keys: string | string[]): WorkflowsValue
|
|
235
219
|
export function merge<T, U>(
|
|
236
220
|
first: Record<string, T>,
|
|
237
221
|
second: Record<string, U>,
|
|
@@ -250,23 +234,23 @@ export declare namespace math {
|
|
|
250
234
|
}
|
|
251
235
|
|
|
252
236
|
export declare namespace retry {
|
|
253
|
-
function always(exception:
|
|
237
|
+
function always(exception: any): void
|
|
254
238
|
const default_backoff: {
|
|
255
239
|
initial_delay: number
|
|
256
240
|
max_delay: number
|
|
257
241
|
multiplier: number
|
|
258
242
|
}
|
|
259
|
-
function never(exception:
|
|
243
|
+
function never(exception: any): void
|
|
260
244
|
}
|
|
261
245
|
|
|
262
246
|
export declare namespace sys {
|
|
263
247
|
function get_env(name: string): string | null
|
|
264
248
|
function get_env(name: string, default_value: string): string
|
|
265
249
|
function log(
|
|
266
|
-
data?:
|
|
250
|
+
data?: BooleanNumberStringListOrDict,
|
|
267
251
|
severity?: string,
|
|
268
|
-
text?:
|
|
269
|
-
json?:
|
|
252
|
+
text?: BooleanNumberStringListOrDict,
|
|
253
|
+
json?: Record<string, any>,
|
|
270
254
|
timeout?: number,
|
|
271
255
|
): void
|
|
272
256
|
function now(): number
|
|
@@ -456,9 +440,9 @@ export declare namespace googleapis {
|
|
|
456
440
|
interface GoogleLongrunningOperation {
|
|
457
441
|
done: boolean
|
|
458
442
|
error?: Status
|
|
459
|
-
metadata?: Record<string,
|
|
443
|
+
metadata?: Record<string, any>
|
|
460
444
|
name: string
|
|
461
|
-
response: Record<string,
|
|
445
|
+
response: Record<string, any>
|
|
462
446
|
}
|
|
463
447
|
interface GoogleLongrunningListOperationsResponse {
|
|
464
448
|
nextPageToken?: string
|
|
@@ -476,7 +460,7 @@ export declare namespace googleapis {
|
|
|
476
460
|
displayName: string
|
|
477
461
|
labels: Record<string, string>
|
|
478
462
|
locationId: string
|
|
479
|
-
metadata?: Record<string,
|
|
463
|
+
metadata?: Record<string, any>
|
|
480
464
|
name: string
|
|
481
465
|
}
|
|
482
466
|
interface ListCollectionIdsRequest {
|
|
@@ -538,7 +522,7 @@ export declare namespace googleapis {
|
|
|
538
522
|
}
|
|
539
523
|
interface Status {
|
|
540
524
|
code: number
|
|
541
|
-
details: Record<string,
|
|
525
|
+
details: Record<string, any>[]
|
|
542
526
|
message: string
|
|
543
527
|
}
|
|
544
528
|
interface StructuredQuery {
|
|
@@ -751,5 +735,5 @@ export declare function retry_policy(
|
|
|
751
735
|
|
|
752
736
|
export declare function call_step<T, A extends any[]>(
|
|
753
737
|
func: (...args: A) => T,
|
|
754
|
-
arguments: Record<string,
|
|
738
|
+
arguments: Record<string, any>,
|
|
755
739
|
): T
|
package/dist/ast/validation.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { WorkflowApp } from './workflows.js';
|
|
2
|
-
export declare class WorkflowValidationError extends Error {
|
|
3
|
-
issues: WorkflowIssue[];
|
|
4
|
-
constructor(issues: WorkflowIssue[]);
|
|
5
|
-
}
|
|
6
|
-
export interface WorkflowIssue {
|
|
7
|
-
type: string;
|
|
8
|
-
message: string;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* Execute all syntax validators on a WorkflowApp app.
|
|
12
|
-
*
|
|
13
|
-
* Throws a WorkflowValidationError if there are errors.
|
|
14
|
-
*/
|
|
15
|
-
export declare function validate(app: WorkflowApp, disabled?: string[]): void;
|
|
16
|
-
/**
|
|
17
|
-
* Returns all validator names.
|
|
18
|
-
*/
|
|
19
|
-
export declare function validatorNames(): string[];
|
|
20
|
-
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/ast/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAEzD,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,MAAM,EAAE,aAAa,EAAE,CAAA;gBAEX,MAAM,EAAE,aAAa,EAAE;CAMpC;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAWD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,GAAE,MAAM,EAAO,GAAG,IAAI,CAexE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAEzC"}
|
package/dist/ast/validation.js
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
export class WorkflowValidationError extends Error {
|
|
2
|
-
issues;
|
|
3
|
-
constructor(issues) {
|
|
4
|
-
const issueTypes = Array.from(new Set(issues.map((x) => x.type))).join(', ');
|
|
5
|
-
super(`Workflow validation error: ${issueTypes}`);
|
|
6
|
-
this.name = this.constructor.name;
|
|
7
|
-
this.issues = issues;
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
const validators = new Map([
|
|
11
|
-
['invalidWorkflowName', validateWorkflowNames],
|
|
12
|
-
['duplicatedStepName', validateNoDuplicateStepNames],
|
|
13
|
-
['duplicatedSubworkflowName', validateNoDuplicateSubworkflowNames],
|
|
14
|
-
['missingJumpTarget', validateJumpTargets],
|
|
15
|
-
['wrongNumberOfCallArguments', validateSubworkflowArguments],
|
|
16
|
-
]);
|
|
17
|
-
/**
|
|
18
|
-
* Execute all syntax validators on a WorkflowApp app.
|
|
19
|
-
*
|
|
20
|
-
* Throws a WorkflowValidationError if there are errors.
|
|
21
|
-
*/
|
|
22
|
-
export function validate(app, disabled = []) {
|
|
23
|
-
const selectedValidators = Array.from(validators.entries()).filter(([name]) => {
|
|
24
|
-
return !disabled.includes(name);
|
|
25
|
-
});
|
|
26
|
-
const issues = [];
|
|
27
|
-
for (const [, validator] of selectedValidators) {
|
|
28
|
-
issues.push(...validator(app));
|
|
29
|
-
}
|
|
30
|
-
if (issues.length > 0) {
|
|
31
|
-
throw new WorkflowValidationError(issues);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Returns all validator names.
|
|
36
|
-
*/
|
|
37
|
-
export function validatorNames() {
|
|
38
|
-
return Array.from(validators.keys());
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Check that workflow does not contain duplicated step names.
|
|
42
|
-
*/
|
|
43
|
-
function validateNoDuplicateStepNames(app) {
|
|
44
|
-
function collectDuplicateStepName(wf) {
|
|
45
|
-
const seen = new Set();
|
|
46
|
-
const duplicates = new Set();
|
|
47
|
-
for (const { name } of wf.iterateStepsDepthFirst()) {
|
|
48
|
-
if (seen.has(name)) {
|
|
49
|
-
duplicates.add(name);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
seen.add(name);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return Array.from(duplicates.values());
|
|
56
|
-
}
|
|
57
|
-
const issues = [];
|
|
58
|
-
for (const subworkflow of app.subworkflows) {
|
|
59
|
-
const duplicatesInSub = collectDuplicateStepName(subworkflow);
|
|
60
|
-
if (duplicatesInSub.length > 0) {
|
|
61
|
-
const message = `Duplicated step names in the subworkflow ${subworkflow.name}: ${duplicatesInSub.join(', ')}`;
|
|
62
|
-
issues.push({ type: 'duplicatedStepName', message: message });
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return issues;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Check that there are no two subworkflows sharing a name.
|
|
69
|
-
*/
|
|
70
|
-
function validateNoDuplicateSubworkflowNames(app) {
|
|
71
|
-
const seen = new Set();
|
|
72
|
-
const duplicates = new Set();
|
|
73
|
-
const names = app.subworkflows.map((w) => w.name);
|
|
74
|
-
for (const name of names) {
|
|
75
|
-
if (seen.has(name)) {
|
|
76
|
-
duplicates.add(name);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
seen.add(name);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
if (duplicates.size > 0) {
|
|
83
|
-
const dup = Array.from(duplicates);
|
|
84
|
-
return [
|
|
85
|
-
{
|
|
86
|
-
type: 'duplicatedSubworkflowName',
|
|
87
|
-
message: `Duplicated subworkflow names: ${dup.join(', ')}`,
|
|
88
|
-
},
|
|
89
|
-
];
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
return [];
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Check that the subworkflow names are valid.
|
|
97
|
-
*/
|
|
98
|
-
function validateWorkflowNames(app) {
|
|
99
|
-
const issues = [];
|
|
100
|
-
const names = app.subworkflows.map((w) => w.name);
|
|
101
|
-
if (names.some((x) => x === '')) {
|
|
102
|
-
issues.push({
|
|
103
|
-
type: 'invalidWorkflowName',
|
|
104
|
-
message: 'Subworkflow must have a non-empty name',
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
return issues;
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Check that there are no jumps (calls, nexts) to non-existing steps or subworkflows
|
|
111
|
-
*/
|
|
112
|
-
function validateJumpTargets(app) {
|
|
113
|
-
const subworkflowNames = app.subworkflows.map((w) => w.name);
|
|
114
|
-
return app.subworkflows.flatMap((subworkflow) => {
|
|
115
|
-
return validateJumpTargetsInWorkflow(subworkflow, subworkflowNames);
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
function validateJumpTargetsInWorkflow(workflow, subworkflowNames) {
|
|
119
|
-
const issues = [];
|
|
120
|
-
const stepNames = [];
|
|
121
|
-
for (const { name } of workflow.iterateStepsDepthFirst()) {
|
|
122
|
-
stepNames.push(name);
|
|
123
|
-
}
|
|
124
|
-
function validCallTarget(name) {
|
|
125
|
-
return (isRuntimeFunction(name) ||
|
|
126
|
-
stepNames.includes(name) ||
|
|
127
|
-
subworkflowNames.includes(name));
|
|
128
|
-
}
|
|
129
|
-
function validNextTarget(name) {
|
|
130
|
-
return stepNames.includes(name) || name === 'end'; // accepts "next: end"
|
|
131
|
-
}
|
|
132
|
-
for (const { name, step } of workflow.iterateStepsDepthFirst()) {
|
|
133
|
-
if (step.tag === 'call') {
|
|
134
|
-
if (!validCallTarget(step.call))
|
|
135
|
-
issues.push({
|
|
136
|
-
type: 'missingJumpTarget',
|
|
137
|
-
message: `Call target "${step.call}" in step "${name}" not found`,
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
else if (step.tag === 'switch') {
|
|
141
|
-
if (step.next && !validNextTarget(step.next)) {
|
|
142
|
-
issues.push({
|
|
143
|
-
type: 'missingJumpTarget',
|
|
144
|
-
message: `Next target "${step.next}" in step "${name}" not found`,
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
step.conditions.forEach((cond) => {
|
|
148
|
-
if (cond.next && !validNextTarget(cond.next)) {
|
|
149
|
-
issues.push({
|
|
150
|
-
type: 'missingJumpTarget',
|
|
151
|
-
message: `Next target "${cond.next}" in step "${name}" not found`,
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return issues;
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Check that call steps provide a correct number of argument in subworkflow calls
|
|
161
|
-
*/
|
|
162
|
-
function validateSubworkflowArguments(app) {
|
|
163
|
-
const issues = [];
|
|
164
|
-
const paramsBySubworkflow = new Map(app.subworkflows.map((x) => [
|
|
165
|
-
x.name,
|
|
166
|
-
{
|
|
167
|
-
required: x.params
|
|
168
|
-
?.filter((x) => typeof x.default === 'undefined')
|
|
169
|
-
.map((x) => x.name) ?? [],
|
|
170
|
-
optional: x.params
|
|
171
|
-
?.filter((x) => typeof x.default !== 'undefined')
|
|
172
|
-
.map((x) => x.name) ?? [],
|
|
173
|
-
},
|
|
174
|
-
]));
|
|
175
|
-
app.subworkflows.forEach((subw) => {
|
|
176
|
-
issues.push(...findIssuesInCallArguments(subw, paramsBySubworkflow));
|
|
177
|
-
});
|
|
178
|
-
return issues;
|
|
179
|
-
}
|
|
180
|
-
function findIssuesInCallArguments(wf, argumentBySubworkflowName) {
|
|
181
|
-
const issues = [];
|
|
182
|
-
for (const { name, step } of wf.iterateStepsDepthFirst()) {
|
|
183
|
-
if (step.tag === 'call' && argumentBySubworkflowName.has(step.call)) {
|
|
184
|
-
const requiredArgs = argumentBySubworkflowName.get(step.call)?.required ?? [];
|
|
185
|
-
const optionalArgs = argumentBySubworkflowName.get(step.call)?.optional ?? [];
|
|
186
|
-
const requiredAndOptionalArgs = requiredArgs.concat(optionalArgs);
|
|
187
|
-
const providedArgs = Object.keys(step.args ?? {});
|
|
188
|
-
const requiredButNotProvided = requiredArgs.filter((x) => !providedArgs.includes(x));
|
|
189
|
-
const providedButNotRequired = providedArgs.filter((x) => !requiredAndOptionalArgs.includes(x));
|
|
190
|
-
if (requiredButNotProvided.length > 0) {
|
|
191
|
-
issues.push({
|
|
192
|
-
type: 'wrongNumberOfCallArguments',
|
|
193
|
-
message: `Required parameters not provided on call step "${name}": ${JSON.stringify(requiredButNotProvided)}`,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
if (providedButNotRequired.length > 0) {
|
|
197
|
-
issues.push({
|
|
198
|
-
type: 'wrongNumberOfCallArguments',
|
|
199
|
-
message: `Extra arguments provided on call step "${name}": ${JSON.stringify(providedButNotRequired)}`,
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
return issues;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Returns true if functionName is a standard library or connector function.
|
|
208
|
-
*
|
|
209
|
-
* Current version does a minimalistic checking and assumes that a name is a
|
|
210
|
-
* standard library function if it contains a dot.
|
|
211
|
-
*/
|
|
212
|
-
function isRuntimeFunction(functionName) {
|
|
213
|
-
return functionName.includes('.');
|
|
214
|
-
}
|