Converts typescript code to Amazon State Language. This allows for local development/debugging/testing and deployment as an AWS Step Function.
Not all ASL constructs can be easily represented in Typescript. A Retry block with specified back-off rate is something that does not exists in Typescript natively. The ASL Lib bridges this gap by providing a Typescript library. The Typescript library can be used for local debugging and testing of the program and can be 1:1 converted to AWS ASL.
ASL Lib code:
ASL.Wait({ Seconds: 2 });
ASL.Task({
Resource: "arn:aws:123123123:lambda:function:my-func",
Retry: [{
ErrorEquals: ["States.Timeout"],
IntervalSeconds: 3,
MaxAttempts: 2,
BackoffRate: 1.5
}]
});
ASL Lib code can be mixed with Typescript code:
if (pwd !== "password" ) {
throw new Error("wrong password")
} else {
ASL.Wait({ Seconds: 2 });
performWork();
}
The above will be converted to ASL Lib code prior to being deployed to ASL
ASL.Choice({
Choices: [{
Variable: "$.password",
Not: { StringEquals: "pwd" },
NextInvoke: () => {
ASL.Failed({ Error: 'Error', Cause: 'wrong password' });
}]
DefaultInvoke: () => {
ASL.Wait({ Seconds: 2 });
ASL.Invoke({ Resource: performWork });
}
});
These language constructs translate the ASL Lib code and are implemented as AST transformations. The source code for these transformations can be found in the ./lang-support folder.
The typescript language constructs that are supported are listed below:
let abc = 'hello';
let abc = 43;
let abc = { number: 43; text: 'hello' };
ASL Lib Typescript code
let abc = ASL.Pass({ Result: 'hello' });
let abc = ASL.Pass({ Result: 43 });
let abc = ASL.Pass({ Result: { number: 43, text: 'hello' } });
ASL output
{
"StartAt": "Assign_abc",
"States": {
"Assign_abc": { "Type": "Pass", "ResultPath": "$.abc", "Result": "hello" },
"Assign_abc_1": { "Type": "Pass", "ResultPath": "$.abc", "Result": 43 },
"Assign_abc_2": { "Type": "Pass", "ResultPath": "$.abc",
"Result": {
"number": 43,
"text": "hello"
}
}
}
}
- only literals can be used, e.g. references to other variables are not supported
throw new Error();
throw new Error("bad luck");
throw new SpecialError("bad luck");
ASL Lib Typescript code
ASL.Failed({ Error: 'Error' })
ASL.Failed({ Error: 'Error', Cause: 'bad luck' })
ASL.Failed({ Error: 'SpecialError', Cause: 'bad luck' })
ASL output
{
"StartAt": "Failed",
"States": {
"Failed": { "Type": "Failed", "Error": "Error" },
"Failed_1": { "Type": "Failed", "Error": "Error", "Cause": "bad luck" },
"Failed_2": { "Type": "Failed", "Error": "SpecialError", "Cause": "bad luck" }
}
}
if (password !== 'pwd') throw new Error('wrong password');
if (age < 18) throw new Error('minor') else proceed();
ASL Lib Typescript code
ASL.Choice({
Choices: [{
Variable: "$.password",
Not: { StringEquals: "pwd" },
NextInvoke: () => { ASL.Failed({ Error: 'Error', Cause: 'wrong password' }) }
}]
});
ASL.Choice({
Choices: [{
Variable: "$.age",
NumericLessThan: "18",
NextInvoke: () => { ASL.Failed({ Error: 'Error', Cause: 'minor' }) }
}],
DefaultInvoke: () => {
ASL.Task({ TypescriptInvoke: proceed });
}
});
ASL output
{
"StartAt": "Choice",
"States": {
"Choice": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.password",
"Not": { "StringEquals": "pwd" },
"Next": "Failed"
}
]
},
"Failed": {
"Type": "Failed",
"Error": "Error",
"Cause": "wrong password",
},
"Choice_1": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.age",
"NumericLessThan": "18",
"Next": "Failed_1"
}
],
"Default": "Task",
},
"Failed_1": {
"Type": "Failed",
"Error": "Error",
"Cause": "minor",
},
"Task": {
"Resource": "typescript:proceed",
"Type": "Task",
}
}
}
- else is not supported
- complex boolean expressions are not supported
switch (color) {
case "red":
doRed();
break;
default:
somethingElse();
break;
}
ASL Lib Typescript code
ASL.Choice({
Choices: [{
Variable: "$.color",
StringEquals: "red",
NextInvoke: () => {
ASL.Task({ TypescriptInvoke: doRed });
}
}],
DefaultInvoke: () => {
ASL.Task({ TypescriptInvoke: somethingElse });
}
});
"
ASL output
{
"StartAt": "Choice",
"States": {
"Choice": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.color",
"StringEquals": "red",
"Next": "Task"
}
],
"Default": "Task_1"
},
"Task_1": {
"Type": "Task",
"Resource": "typescript:somethingElse"
},
"Task": {
"Type": "Task",
"Resource": "typescript:doRed"
}
}
}
sayHello(arg);
await sayHello();
const z = await sayHello();
ASL Lib Typescript code
ASL.Task({
TypescriptInvoke: sayHello,
InputPath: \\"$.arg\\"
});
await ASL.Task({
TypescriptInvoke: sayHello
});
const z = await ASL.Task({
TypescriptInvoke: sayHello
});
ASL output
{
"StartAt": "Task",
"States": {
"Task": {
"Type": "Task",
"Resource": "typescript:sayHello",
"InputPath": "$.arg"
},
"Task_1": {
"Type": "Task",
"Resource": "typescript:sayHello"
},
"Assign_z": {
"Type": "Task",
"Resource": "typescript:sayHello",
"ResultPath": "$.z"
}
}
}
await Promise.all([
() => { spinLeft(); },
() => { spinRight(); }
]);
ASL Lib Typescript code
await ASL.Parallel({
Branches: [{
BlockInvoke: () => {
ASL.Task({ TypescriptInvoke: spinLeft }); }
}, {
BlockInvoke: () => {
ASL.Task({ TypescriptInvoke: spinRight }); }
}]
});
ASL output
{
"StartAt": "Parallel",
"States": {
"Parallel": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "Task",
"States": {
"Task": {
"Type": "Task",
"Resource": "typescript:spinLeft"
}
}
},
{
"StartAt": "Task",
"States": {
"Task": {
"Type": "Task",
"Resource": "typescript:spinRight"
}
}
}
]
}
}
}
try { doWork(); } catch { revert(); }
ASL Lib Typescript code
ASL.Parallel({
Branches: [{
BlockInvoke: () => {
ASL.Task({ TypescriptInvoke: doWork });
}
}],
Catch: [{
ErrorEquals: ["States.All"],
NextInvoke: () => { ASL.Task({
TypescriptInvoke: revert
});
}
}]
});
ASL output
{
"StartAt": "Parallel",
"States": {
"Parallel": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "Task",
"States": {
"Task": {
"Type": "Task",
"Resource": "typescript:doWork"
}
}
}
],
"Catch": [
{
"ErrorEquals": ["States.All"],
"Next": "Task"
}
]
},
"Task": {
"Type": "Task",
"Resource": "typescript:revert"
}
}
}
return;
ASL Lib Typescript code
ASL.Succeed();
ASL output
{
"StartAt": "Succeed",
"States": {
"Succeed": {
"Type": "Succeed"
}
}
}