ts2workflows 0.10.0 → 0.12.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.
Files changed (53) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +36 -9
  3. package/dist/ast/expressions.d.ts +37 -41
  4. package/dist/ast/expressions.d.ts.map +1 -1
  5. package/dist/ast/expressions.js +124 -255
  6. package/dist/ast/statements.d.ts +132 -0
  7. package/dist/ast/statements.d.ts.map +1 -0
  8. package/dist/ast/statements.js +197 -0
  9. package/dist/ast/steps.d.ts +82 -194
  10. package/dist/ast/steps.d.ts.map +1 -1
  11. package/dist/ast/steps.js +862 -521
  12. package/dist/ast/workflows.d.ts +14 -12
  13. package/dist/ast/workflows.d.ts.map +1 -1
  14. package/dist/ast/workflows.js +20 -35
  15. package/dist/cli.js +45 -32
  16. package/dist/errors.d.ts +4 -0
  17. package/dist/errors.d.ts.map +1 -1
  18. package/dist/errors.js +7 -0
  19. package/dist/transpiler/index.d.ts +19 -1
  20. package/dist/transpiler/index.d.ts.map +1 -1
  21. package/dist/transpiler/index.js +158 -31
  22. package/dist/transpiler/linker.d.ts +3 -0
  23. package/dist/transpiler/linker.d.ts.map +1 -0
  24. package/dist/transpiler/linker.js +41 -0
  25. package/dist/transpiler/parseexpressions.d.ts +11 -0
  26. package/dist/transpiler/parseexpressions.d.ts.map +1 -0
  27. package/dist/transpiler/{expressions.js → parseexpressions.js} +90 -103
  28. package/dist/transpiler/parsestatement.d.ts +7 -0
  29. package/dist/transpiler/parsestatement.d.ts.map +1 -0
  30. package/dist/transpiler/parsestatement.js +862 -0
  31. package/dist/transpiler/stepnames.d.ts +3 -0
  32. package/dist/transpiler/stepnames.d.ts.map +1 -0
  33. package/dist/transpiler/stepnames.js +17 -0
  34. package/dist/transpiler/transformations.d.ts +3 -19
  35. package/dist/transpiler/transformations.d.ts.map +1 -1
  36. package/dist/transpiler/transformations.js +267 -322
  37. package/language_reference.md +53 -17
  38. package/package.json +15 -11
  39. package/types/workflowslib.d.ts +58 -74
  40. package/dist/ast/stepnames.d.ts +0 -9
  41. package/dist/ast/stepnames.d.ts.map +0 -1
  42. package/dist/ast/stepnames.js +0 -280
  43. package/dist/ast/validation.d.ts +0 -20
  44. package/dist/ast/validation.d.ts.map +0 -1
  45. package/dist/ast/validation.js +0 -214
  46. package/dist/transpiler/expressions.d.ts +0 -11
  47. package/dist/transpiler/expressions.d.ts.map +0 -1
  48. package/dist/transpiler/statements.d.ts +0 -10
  49. package/dist/transpiler/statements.d.ts.map +0 -1
  50. package/dist/transpiler/statements.js +0 -1100
  51. package/dist/utils.d.ts +0 -9
  52. package/dist/utils.d.ts.map +0 -1
  53. package/dist/utils.js +0 -13
@@ -1,29 +1,39 @@
1
- import * as R from 'ramda';
2
- import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
3
- import { BinaryExpression, FunctionInvocationExpression, MemberExpression, PrimitiveExpression, UnaryExpression, VariableReferenceExpression, asExpression, isFullyQualifiedName, nullEx, } from '../ast/expressions.js';
1
+ import { TSESTree, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
2
+ import { binaryEx, booleanEx, expressionToString, functionInvocationEx, isQualifiedName, listEx, mapEx, memberEx, nullEx, numberEx, stringEx, unaryEx, variableReferenceEx, } from '../ast/expressions.js';
4
3
  import { InternalTranspilingError, WorkflowSyntaxError } from '../errors.js';
5
4
  export function convertExpression(instance) {
6
5
  switch (instance.type) {
7
6
  case AST_NODE_TYPES.ArrayExpression:
8
- return asExpression(convertArrayExpression(instance));
7
+ return convertArrayExpression(instance);
9
8
  case AST_NODE_TYPES.ObjectExpression:
10
- return asExpression(convertObjectExpression(instance));
9
+ return convertObjectExpression(instance);
11
10
  case AST_NODE_TYPES.Literal:
12
11
  if (instance.value instanceof RegExp) {
13
12
  throw new WorkflowSyntaxError('RegExp is not supported', instance.loc);
14
13
  }
15
- if (typeof instance.value === 'bigint') {
14
+ else if (typeof instance.value === 'bigint') {
16
15
  throw new WorkflowSyntaxError('BigInt is not supported', instance.loc);
17
16
  }
18
- return new PrimitiveExpression(instance.value);
17
+ else if (typeof instance.value === 'string') {
18
+ return stringEx(instance.value);
19
+ }
20
+ else if (typeof instance.value === 'number') {
21
+ return numberEx(instance.value);
22
+ }
23
+ else if (typeof instance.value === 'boolean') {
24
+ return booleanEx(instance.value);
25
+ }
26
+ else {
27
+ return nullEx;
28
+ }
19
29
  case AST_NODE_TYPES.TemplateLiteral:
20
30
  return convertTemplateLiteralToExpression(instance);
21
31
  case AST_NODE_TYPES.Identifier:
22
- if (instance.name === 'null' || instance.name === 'undefined') {
32
+ if (instance.name === 'undefined') {
23
33
  return nullEx;
24
34
  }
25
35
  else {
26
- return new VariableReferenceExpression(instance.name);
36
+ return variableReferenceEx(instance.name);
27
37
  }
28
38
  case AST_NODE_TYPES.UnaryExpression:
29
39
  return convertUnaryExpression(instance);
@@ -39,56 +49,38 @@ export function convertExpression(instance) {
39
49
  case AST_NODE_TYPES.ConditionalExpression:
40
50
  return convertConditionalExpression(instance);
41
51
  case AST_NODE_TYPES.TSAsExpression:
42
- return convertExpression(instance.expression);
43
52
  case AST_NODE_TYPES.TSNonNullExpression:
53
+ case AST_NODE_TYPES.TSInstantiationExpression:
54
+ case AST_NODE_TYPES.TSSatisfiesExpression:
44
55
  return convertExpression(instance.expression);
45
56
  case AST_NODE_TYPES.AwaitExpression:
46
57
  return convertExpression(instance.argument);
47
- case AST_NODE_TYPES.TSInstantiationExpression:
48
- return convertExpression(instance.expression);
49
58
  default:
50
59
  throw new WorkflowSyntaxError(`Not implemented expression type: ${instance.type}`, instance.loc);
51
60
  }
52
61
  }
53
- function convertExpressionOrPrimitive(instance) {
54
- const ex = convertExpression(instance);
55
- if (ex.expressionType === 'primitive') {
56
- return ex.value;
57
- }
58
- else {
59
- return ex;
60
- }
61
- }
62
62
  export function convertObjectExpression(node) {
63
- return Object.fromEntries(throwIfSpread(node.properties).map(({ key, value }) => {
63
+ return mapEx(Object.fromEntries(throwIfSpread(node.properties).map(({ key, value }) => {
64
64
  let keyPrimitive;
65
65
  if (key.type === AST_NODE_TYPES.Identifier) {
66
66
  keyPrimitive = key.name;
67
67
  }
68
- else if (key.type === AST_NODE_TYPES.Literal) {
69
- if (typeof key.value === 'string') {
70
- keyPrimitive = key.value;
71
- }
72
- else {
73
- throw new WorkflowSyntaxError(`Map keys must be identifiers or strings, encountered: ${typeof key.value}`, key.loc);
74
- }
68
+ else if (key.type === AST_NODE_TYPES.Literal &&
69
+ typeof key.value === 'string') {
70
+ keyPrimitive = key.value;
75
71
  }
76
72
  else {
77
- throw new WorkflowSyntaxError(`Not implemented object key type: ${key.type}`, key.loc);
73
+ throw new WorkflowSyntaxError(`Map keys must be identifiers or strings, encountered: ${key.type}`, key.loc);
78
74
  }
79
75
  if (value.type === AST_NODE_TYPES.AssignmentPattern ||
80
76
  value.type === AST_NODE_TYPES.TSEmptyBodyFunctionExpression) {
81
77
  throw new WorkflowSyntaxError('Value not supported', value.loc);
82
78
  }
83
- return [keyPrimitive, convertExpressionOrPrimitive(value)];
84
- }));
85
- }
86
- export function convertObjectAsExpressionValues(node) {
87
- // Convert Primitive values to PrimitiveExpressions
88
- return R.map(asExpression, convertObjectExpression(node));
79
+ return [keyPrimitive, convertExpression(value)];
80
+ })));
89
81
  }
90
82
  function convertArrayExpression(instance) {
91
- return throwIfSpread(instance.elements).map((e) => e === null ? nullEx : convertExpressionOrPrimitive(e));
83
+ return listEx(throwIfSpread(instance.elements).map((e) => e === null ? nullEx : convertExpression(e)));
92
84
  }
93
85
  function convertBinaryExpression(instance) {
94
86
  // Special case for nullish coalescing because the result is a function call
@@ -127,19 +119,16 @@ function convertBinaryExpression(instance) {
127
119
  default:
128
120
  throw new WorkflowSyntaxError(`Unsupported binary operator: ${instance.operator}`, instance.loc);
129
121
  }
130
- if (instance.left.type === AST_NODE_TYPES.PrivateIdentifier) {
131
- throw new WorkflowSyntaxError('Private identifier not supported', instance.left.loc);
132
- }
133
- return new BinaryExpression(convertExpression(instance.left), op, convertExpression(instance.right));
122
+ return binaryEx(convertExpression(throwIfPrivateIdentifier(instance.left)), op, convertExpression(instance.right));
134
123
  }
135
124
  function nullishCoalescingExpression(left, right) {
136
- return new FunctionInvocationExpression('default', [
125
+ return functionInvocationEx('default', [
137
126
  convertExpression(left),
138
127
  convertExpression(right),
139
128
  ]);
140
129
  }
141
130
  function convertUnaryExpression(instance) {
142
- if (instance.prefix === false) {
131
+ if (!instance.prefix) {
143
132
  throw new WorkflowSyntaxError('only prefix unary operators are supported', instance.loc);
144
133
  }
145
134
  let op;
@@ -163,9 +152,6 @@ function convertUnaryExpression(instance) {
163
152
  op = undefined;
164
153
  istypeof = true;
165
154
  break;
166
- case undefined:
167
- op = undefined;
168
- break;
169
155
  default:
170
156
  throw new WorkflowSyntaxError(`Unsupported unary operator: ${instance.operator}`, instance.loc);
171
157
  }
@@ -174,7 +160,7 @@ function convertUnaryExpression(instance) {
174
160
  return convertTypeOfExpression(ex);
175
161
  }
176
162
  else if (op) {
177
- return new UnaryExpression(op, ex);
163
+ return unaryEx(op, ex);
178
164
  }
179
165
  else {
180
166
  return ex;
@@ -182,55 +168,54 @@ function convertUnaryExpression(instance) {
182
168
  }
183
169
  function convertTypeOfExpression(value) {
184
170
  // Note for future refactoring: evalute value only once (in case it has side effects)
185
- return new FunctionInvocationExpression('text.replace_all_regex', [
186
- new FunctionInvocationExpression('text.replace_all_regex', [
187
- new FunctionInvocationExpression('get_type', [value]),
188
- new PrimitiveExpression('^(bytes|list|map|null)$'),
189
- new PrimitiveExpression('object'),
171
+ return functionInvocationEx('text.replace_all_regex', [
172
+ functionInvocationEx('text.replace_all_regex', [
173
+ functionInvocationEx('get_type', [value]),
174
+ stringEx('^(bytes|list|map|null)$'),
175
+ stringEx('object'),
190
176
  ]),
191
- new PrimitiveExpression('^(double|integer)$'),
192
- new PrimitiveExpression('number'),
177
+ stringEx('^(double|integer)$'),
178
+ stringEx('number'),
193
179
  ]);
194
180
  }
195
181
  export function convertMemberExpression(node) {
196
- if (node.property.type === AST_NODE_TYPES.PrivateIdentifier) {
197
- throw new WorkflowSyntaxError('Private identifier not supported', node.property.loc);
198
- }
199
182
  const object = convertExpression(node.object);
200
- return new MemberExpression(object, convertExpression(node.property), node.computed);
183
+ return memberEx(object, convertExpression(throwIfPrivateIdentifier(node.property)), node.computed);
201
184
  }
202
185
  function convertChainExpression(node) {
203
186
  const properties = chainExpressionToFlatArray(node.expression);
204
187
  const args = optionalChainToMapGetArguments(properties);
205
- return new FunctionInvocationExpression('map.get', args);
188
+ return functionInvocationEx('map.get', args);
206
189
  }
207
190
  function chainExpressionToFlatArray(node) {
208
- if (node.type === AST_NODE_TYPES.MemberExpression) {
209
- if (node.property.type === AST_NODE_TYPES.PrivateIdentifier) {
210
- throw new WorkflowSyntaxError('Private identifier not supported', node.property.loc);
191
+ switch (node.type) {
192
+ case TSESTree.AST_NODE_TYPES.Identifier:
193
+ case TSESTree.AST_NODE_TYPES.ChainExpression:
194
+ return [
195
+ {
196
+ property: node,
197
+ optional: false,
198
+ computed: false,
199
+ },
200
+ ];
201
+ case TSESTree.AST_NODE_TYPES.MemberExpression: {
202
+ const data = {
203
+ property: throwIfPrivateIdentifier(node.property),
204
+ optional: node.optional,
205
+ computed: node.computed,
206
+ };
207
+ return chainExpressionToFlatArray(node.object).concat([data]);
211
208
  }
212
- const data = {
213
- property: node.property,
214
- optional: node.optional,
215
- computed: node.computed,
216
- };
217
- return chainExpressionToFlatArray(node.object).concat([data]);
218
- }
219
- else {
220
- return [
221
- {
222
- property: node,
223
- optional: false,
224
- computed: false,
225
- },
226
- ];
209
+ case AST_NODE_TYPES.TSAsExpression:
210
+ case AST_NODE_TYPES.TSNonNullExpression:
211
+ case AST_NODE_TYPES.TSInstantiationExpression:
212
+ case AST_NODE_TYPES.TSSatisfiesExpression:
213
+ return chainExpressionToFlatArray(node.expression);
214
+ default:
215
+ throw new WorkflowSyntaxError(`Type ${node.type} is not supported in optional chaining`, node.loc);
227
216
  }
228
217
  }
229
218
  function optionalChainToMapGetArguments(properties) {
230
- if (properties.length <= 0) {
231
- // this shouldn't happen
232
- return [];
233
- }
234
219
  let base;
235
220
  let optionalSliceStart;
236
221
  const firstOptional = properties.findIndex((p) => p.optional);
@@ -253,8 +238,8 @@ function optionalChainToMapGetArguments(properties) {
253
238
  if (opt.computed) {
254
239
  return propertyExp;
255
240
  }
256
- else if (isFullyQualifiedName(propertyExp)) {
257
- return new PrimitiveExpression(propertyExp.toString());
241
+ else if (isQualifiedName(propertyExp)) {
242
+ return stringEx(expressionToString(propertyExp));
258
243
  }
259
244
  else {
260
245
  throw new WorkflowSyntaxError('Unexpected property in an optional chain', opt.property.loc);
@@ -262,7 +247,7 @@ function optionalChainToMapGetArguments(properties) {
262
247
  });
263
248
  const args = [base];
264
249
  if (optionals.length > 1) {
265
- args.push(new PrimitiveExpression(optionals));
250
+ args.push(listEx(optionals));
266
251
  }
267
252
  else if (optionals.length === 1) {
268
253
  args.push(optionals[0]);
@@ -271,10 +256,10 @@ function optionalChainToMapGetArguments(properties) {
271
256
  }
272
257
  function memberExpressionFromList(properties) {
273
258
  if (properties.length >= 2) {
274
- const base = new MemberExpression(convertExpression(properties[0].property), convertExpression(properties[1].property), properties[1].computed);
259
+ const base = memberEx(convertExpression(properties[0].property), convertExpression(properties[1].property), properties[1].computed);
275
260
  return properties
276
261
  .slice(2)
277
- .reduce((exp, current) => new MemberExpression(exp, convertExpression(current.property), current.computed), base);
262
+ .reduce((exp, current) => memberEx(exp, convertExpression(current.property), current.computed), base);
278
263
  }
279
264
  else if (properties.length === 1) {
280
265
  return convertExpression(properties[0].property);
@@ -288,8 +273,8 @@ function convertCallExpression(node) {
288
273
  throw new WorkflowSyntaxError('Optional call expressions are not supported', node.loc);
289
274
  }
290
275
  const calleeExpression = convertExpression(node.callee);
291
- if (isFullyQualifiedName(calleeExpression)) {
292
- const calleeName = calleeExpression.toString();
276
+ if (isQualifiedName(calleeExpression)) {
277
+ const calleeName = expressionToString(calleeExpression);
293
278
  if (isIntrinsic(calleeName)) {
294
279
  let msg;
295
280
  if (calleeName === 'call_step') {
@@ -302,7 +287,7 @@ function convertCallExpression(node) {
302
287
  throw new WorkflowSyntaxError(msg, node.callee.loc);
303
288
  }
304
289
  const argumentExpressions = throwIfSpread(node.arguments).map(convertExpression);
305
- return new FunctionInvocationExpression(calleeName, argumentExpressions);
290
+ return functionInvocationEx(calleeName, argumentExpressions);
306
291
  }
307
292
  else {
308
293
  throw new WorkflowSyntaxError('Callee should be a qualified name', node.loc);
@@ -312,7 +297,7 @@ export function isIntrinsic(calleeName) {
312
297
  const intrinsics = ['parallel', 'retry_policy', 'call_step'];
313
298
  return intrinsics.includes(calleeName);
314
299
  }
315
- export function isIntrinsicStatment(calleeName) {
300
+ export function isIntrinsicStatement(calleeName) {
316
301
  const statementNames = ['parallel', 'retry_policy'];
317
302
  return statementNames.includes(calleeName);
318
303
  }
@@ -320,18 +305,15 @@ function convertConditionalExpression(node) {
320
305
  const test = convertExpression(node.test);
321
306
  const consequent = convertExpression(node.consequent);
322
307
  const alternate = convertExpression(node.alternate);
323
- return new FunctionInvocationExpression('if', [test, consequent, alternate]);
308
+ return functionInvocationEx('if', [test, consequent, alternate]);
324
309
  }
325
310
  function convertTemplateLiteralToExpression(node) {
326
311
  const stringTerms = node.quasis
327
312
  .map((x) => x.value.cooked)
328
- .map((x) => new PrimitiveExpression(x));
313
+ .map((x) => stringEx(x));
329
314
  const templateTerms = node.expressions
330
315
  .map(convertExpression)
331
- .map((ex) => new FunctionInvocationExpression('default', [
332
- ex,
333
- new PrimitiveExpression('null'),
334
- ]));
316
+ .map((ex) => functionInvocationEx('default', [ex, stringEx('null')]));
335
317
  // interleave string parts and the expression parts starting with strings
336
318
  const interleavedTerms = stringTerms
337
319
  .slice(0, stringTerms.length - 1)
@@ -346,10 +328,10 @@ function convertTemplateLiteralToExpression(node) {
346
328
  interleavedTerms.push(stringTerms[stringTerms.length - 1]);
347
329
  }
348
330
  if (interleavedTerms.length === 0) {
349
- return new PrimitiveExpression('');
331
+ return stringEx('');
350
332
  }
351
333
  else {
352
- return interleavedTerms.reduce((previous, current) => new BinaryExpression(previous, '+', current));
334
+ return interleavedTerms.reduce((previous, current) => binaryEx(previous, '+', current));
353
335
  }
354
336
  }
355
337
  export function throwIfSpread(nodes) {
@@ -360,11 +342,16 @@ export function throwIfSpread(nodes) {
360
342
  const argumentExpressions = nodes.filter((x) => x?.type !== AST_NODE_TYPES.SpreadElement);
361
343
  return argumentExpressions;
362
344
  }
363
- export function convertVariableNameExpression(instance) {
364
- const ex = convertExpression(instance);
365
- if (ex.expressionType !== 'variableReference' &&
366
- ex.expressionType !== 'member') {
367
- throw new WorkflowSyntaxError('The left-hand side of an assignment must be a variable or member expression', instance.loc);
345
+ export function throwIfPrivateIdentifier(prop) {
346
+ if (prop.type === AST_NODE_TYPES.PrivateIdentifier) {
347
+ throw new WorkflowSyntaxError('Private identifier not supported', prop.loc);
348
+ }
349
+ return prop;
350
+ }
351
+ export function convertAssignmentTarget(node) {
352
+ const ex = convertExpression(node);
353
+ if (ex.tag !== 'variableReference' && ex.tag !== 'member') {
354
+ throw new WorkflowSyntaxError('An assignment taget must be an identifer or a member expression', node.loc);
368
355
  }
369
356
  return ex;
370
357
  }
@@ -0,0 +1,7 @@
1
+ import { TSESTree } from '@typescript-eslint/typescript-estree';
2
+ import { WorkflowStatement } from '../ast/statements.js';
3
+ export interface ParsingContext {
4
+ readonly parallelNestingLevel?: number;
5
+ }
6
+ export declare function parseStatement(node: TSESTree.Statement, ctx: ParsingContext): WorkflowStatement[];
7
+ //# sourceMappingURL=parsestatement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsestatement.d.ts","sourceRoot":"","sources":["../../src/transpiler/parsestatement.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,QAAQ,EAAE,MAAM,sCAAsC,CAAA;AAoB/E,OAAO,EAiBL,iBAAiB,EAMlB,MAAM,sBAAsB,CAAA;AAa7B,MAAM,WAAW,cAAc;IAG7B,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAA;CACvC;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,CAAC,SAAS,EACxB,GAAG,EAAE,cAAc,GAClB,iBAAiB,EAAE,CAiFrB"}