Skip to content

Commit f409f88

Browse files
authored
Merge pull request #51 from nibble-4bits/refactor-9
Refactor 9
2 parents 4b5e9e3 + 094d067 commit f409f88

9 files changed

+934
-864
lines changed

README.md

+9-11
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22

33
A TypeScript implementation of the [Amazon States Language specification](https://states-language.net/spec.html).
44

5-
This package lets you run AWS Step Functions locally, both in Node.js and in the browser!
5+
This package lets you run AWS Step Functions completely locally, both in Node.js and in the browser!
66

7-
> NOTE: This is a work in progress. Some features defined in the specification might not be supported at all yet or might have limited support.
8-
9-
## Table of Contents
7+
## Table of contents
108

119
- [Features](#features)
1210
- [Installation](#installation)
@@ -23,7 +21,7 @@ This package lets you run AWS Step Functions locally, both in Node.js and in the
2321

2422
## Features
2523

26-
To see a list of features that have full support, partial support, or no support, refer to [this document](/docs/feature-support.md).
24+
To see the list of features defined in the specification that have full support, partial support, or no support, refer to [this document](/docs/feature-support.md).
2725

2826
## Installation
2927

@@ -78,11 +76,11 @@ The constructor takes the following parameters:
7876
- `validationOptions?`: An object that specifies how the definition should be validated.
7977
- `checkPaths`: If set to `false`, won't validate JSONPaths.
8078
- `checkArn`: If set to `false`, won't validate ARN syntax in `Task` states.
81-
- `awsConfig?`: An object that specifies the AWS region and credentials to use when invoking a Lambda function in a `Task` state. If not set, the AWS config will be resolved based on the [credentials provider chain](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html) of the AWS SDK for JavaScript V3. You don't need to use this option if you have a [shared config/credentials file](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html) (for example, if you have the [AWS CLI](https://aws.amazon.com/cli/) installed) or if you use a local override for all of your `Task` states.
79+
- `awsConfig?`: An object that specifies the [AWS region and credentials](/docs/feature-support.md#providing-aws-credentials-and-region-to-execute-lambda-functions-specified-in-task-states) to use when invoking a Lambda function in a `Task` state. If not set, the AWS config will be resolved based on the [credentials provider chain](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html) of the AWS SDK for JavaScript V3. You don't need to use this option if you have a [shared config/credentials file](https://docs.aws.amazon.com/sdkref/latest/guide/file-format.html) (for example, if you have the [AWS CLI](https://aws.amazon.com/cli/) installed) or if you use a local override for all of your `Task` states.
8280
- `region`: The AWS region where the Lambda functions are created.
8381
- `credentials`: An object that specifies which type of credentials to use.
84-
- `cognitoIdentityPool`: An object that specifies the Cognito Identity Pool to use for requesting credentials.
85-
- `accessKeys`: An object that specifies the [Access Key ID and Secret Access Key](https://docs.aws.amazon.com/IAM/latest/UserGuide/security-creds.html#sec-access-keys-and-secret-access-keys) to use as credentials.
82+
- `cognitoIdentityPool`: An object that specifies the Cognito Identity Pool ID to use for requesting credentials.
83+
- `accessKeys`: An object that specifies the Access Key ID and Secret Access Key to use as credentials.
8684

8785
The constructor will attempt to validate the definition by default, unless the `validationOptions` property is specified. If the definition is not valid, an error will be thrown.
8886

@@ -113,7 +111,7 @@ const stateMachine = new StateMachine(machineDefinition, {
113111

114112
Runs the state machine with the given `input` parameter and returns an object with the following properties:
115113

116-
- `abort`: A function that takes no parameters and doesn't return any value. If called, aborts the execution and throws an `ExecutionAbortedError`, unless the `noThrowOnAbort` option is set.
114+
- `abort`: A function that takes no parameters and doesn't return any value. If called, [aborts the execution](/docs/feature-support.md#abort-a-running-execution) and throws an `ExecutionAbortedError`, unless the `noThrowOnAbort` option is set.
117115
- `result`: A `Promise` that resolves with the execution result once it finishes.
118116

119117
Each execution is independent of all others, meaning that you can concurrently call this method as many times as needed, without worrying about race conditions.
@@ -123,8 +121,8 @@ Each execution is independent of all others, meaning that you can concurrently c
123121
- `input`: The initial input to pass to the state machine. This can be any valid JSON value.
124122
- `options?`:
125123
- `overrides?`: An object to override the behavior of certain states:
126-
- `taskResourceLocalHandlers?`: Overrides the resource of the specified `Task` states to run a local function.
127-
- `waitTimeOverrides?`: Overrides the wait duration of the specified `Wait` states. The specifed override duration should be in milliseconds.
124+
- `taskResourceLocalHandlers?`: An [object that overrides](/docs/feature-support.md#task-state-resource-override) the resource of the specified `Task` states to run a local function.
125+
- `waitTimeOverrides?`: An [object that overrides](/docs/feature-support.md#wait-state-duration-override) the wait duration of the specified `Wait` states. The specifed override duration should be in milliseconds.
128126
- `noThrowOnAbort?`: If this option is set to `true`, aborting the execution will simply return `null` as result instead of throwing.
129127

130128
#### Basic example:

docs/feature-support.md

+69-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Feature support
22

3+
## Table of contents
4+
5+
- [Spec features](#spec-features)
6+
- [Fully supported](#fully-supported)
7+
- [Not supported](#not-supported)
8+
- [Non-spec features](#non-spec-features)
9+
- [Task resource override](#task-state-resource-override)
10+
- [Wait duration override](#wait-state-duration-override)
11+
- [Abort a running execution](#abort-a-running-execution)
12+
- [AWS config for Lambda functions](#providing-aws-credentials-and-region-to-execute-lambda-functions-specified-in-task-states)
13+
314
## Spec features
415

516
The following features all come from the [Amazon States Language specification](https://states-language.net/).
@@ -22,6 +33,8 @@ The following features all come from the [Amazon States Language specification](
2233
- [x] `SecondsPath`
2334
- [x] `Timestamp`
2435
- [x] `TimestampPath`
36+
- [x] Task
37+
- [x] `Resource` (only Lambda functions supported)
2538
- [x] Parallel
2639
- [x] `Branches`
2740
- [x] Map
@@ -86,22 +99,71 @@ The following features all come from the [Amazon States Language specification](
8699
- [x] Predefined error codes
87100
- [x] Retry/Catch
88101

89-
### Limited support
102+
### Not supported
90103

91104
- States
92105
- Task
93-
- [x] `Resource` (only Lambda functions supported)
94106
- [ ] `TimeoutSeconds`
95107
- [ ] `HeartbeatSeconds`
96108
- [ ] `TimeoutSecondsPath`
97109
- [ ] `HeartbeatSecondsPath`
98-
99-
### No support
110+
- [ ] `Credentials`
111+
- Map
112+
- [ ] Distributed mode
113+
- [ ] `ItemProcessor`
114+
- [ ] `ItemReader`
115+
- [ ] `ItemSelector`
116+
- [ ] `ItemBatcher`
117+
- [ ] `ResultWriter`
118+
- [ ] `MaxConcurrencyPath`
119+
- [ ] `ToleratedFailurePercentage`
120+
- [ ] `ToleratedFailureCount`
100121

101122
## Non-spec features
102123

103124
The following features are not defined in the specification, but they have been added for convenience.
104125

105-
- [x] Override Task state resource with a local function handler ([example](/examples/task-state-local-override.js))
106-
- [x] Override Wait state duration ([example](/examples/wait-state-local-override.js))
107-
- [x] Abort a running execution ([example](/examples/abort-execution.js))
126+
### `Task` state resource override
127+
128+
`aws-local-stepfunctions` has the ability to invoke Lambda functions specified in the `Resource` field of `Task` states, provided that you have the necessary AWS credentials. No other service integrations are currently available.
129+
130+
However, if you want to be able to run a state machine completely locally (no matter the type of `Resource` specified) you can specify a local function to be called in place of the resource. This is accomplished through the `overrides.taskResourceLocalHandlers` option of the [`StateMachine.run`](/README.md#statemachineruninput-options) method. This option expects an object that maps state names to an overriding local function.
131+
132+
The overriding function will receive the processed input of its `Task` state as the first argument. The return value of said function will be the result of the state (but not its output, which as defined in the spec, depends on further processing done by the `ResultSelector`, `ResultPath` and `OutputPath` fields).
133+
134+
Effectively, task resource overrides allow `aws-local-stepfunctions` to execute state machines without calls to any AWS service, if you override all of the `Task` states in the state machine definition.
135+
136+
An example usage of this feature can be found [here](/examples/task-state-local-override.js).
137+
138+
### `Wait` state duration override
139+
140+
As defined by the spec, `Wait` states in `aws-local-stepfunction` will pause the state machine execution until the specified `Seconds` have elapsed or the specified `Timestamp` has been reached.
141+
142+
Nonetheless, if you want to override the duration of the wait period of a `Wait` state, you can do so by specifying the `overrides.waitTimeOverrides` option of the [`StateMachine.run`](/README.md#statemachineruninput-options) method. This option expects an object that maps state names to numbers, where the number represents the amount of milliseconds that the overridden `Wait` state will pause the execution for. Note that you may pass `0` for the number value, which effectively means that the overridden `Wait` state will not pause the execution at all.
143+
144+
An example usage of this feature can be found [here](/examples/wait-state-local-override.js).
145+
146+
### Abort a running execution
147+
148+
If for some reason you need to abort an execution in progress, you can do so by calling the `abort` method that is part of the value returned by the `StateMachine.run` method.
149+
150+
By default, aborting an execution will throw an error of type `ExecutionAbortedError`, which you can catch and compare against using `instanceof`. A demonstration of this behavior can be found in this [example](/examples/abort-execution.js).
151+
152+
If instead you prefer to abort an execution without throwing an error, you can pass the `noThrowOnAbort` option to the `StateMachine.run` method. When this option is `true`, aborting an execution will simply return `null` as result. Likewise, an example demonstrating this behavior can be found [here](/examples/abort-execution-without-throwing.js).
153+
154+
### Providing AWS credentials and region to execute Lambda functions specified in `Task` states
155+
156+
_NOTE: If you have [overridden](#task-state-resource-override) all `Task` states in your state machine with local functions, you don't need to specify any AWS credentials or region._
157+
158+
When using `aws-local-stepfunctions` on Node, you don't need to specify AWS credentials explicitly, as those will be automatically loaded from the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` [environment variables](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-environment.html) or from the [shared credentials file](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-shared.html), as described in the [AWS JavaScript SDK docs](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-credentials-node.html).
159+
160+
Similarly, you don't need to specify the AWS region, as it will also be automatically loaded, in this case from the `AWS_REGION` environment variable or from the shared config file, as described in the [SDK docs](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/setting-region.html).
161+
162+
However, when using `aws-local-stepfunctions` in the browser you must provide AWS credentials, otherwise the `aws-local-stepfunctions` will not be able to invoke the Lambda functions and the execution will fail.
163+
164+
To provide credentials and region, specify the `stateMachineOptions.awsConfig` option in the `StateMachine` [constructor](/README.md#constructor-new-statemachinedefinition-statemachineoptions). You can set two types of credentials:
165+
166+
1. [Access Keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html): Access Key ID and Secret Access Key ([example](/examples/aws-credentials-access-keys.js)).
167+
2. [Cognito Identity Pool](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html): The ID of a Cognito Identity Pool ([example](/examples/aws-credentials-cognito.js)).
168+
169+
Make sure that the IAM user/role associated with the access keys or Cognito Identity Pool have the necessary policies to be able to invoke the Lambda functions referenced in your state machine definition.

examples/aws-credentials-access-keys.js

+5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ const stateMachine = new StateMachine(machineDefinition, {
2727
accessKeyId: 'AKIAIOSFODNN7EXAMPLE',
2828
secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
2929
},
30+
// WARNING: You shouldn't commit the `accessKeys` option, as that will expose your keys to other people in the repository.
31+
// Ideally, on Node your access keys should be loaded from one of the following two settings:
32+
// - the `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-environment.html
33+
// - the shared `credentials` file: https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/loading-node-credentials-shared.html
34+
// The `accessKeys` option is meant for browser use, where the two settings above are not available as they have no web platform equivalent.
3035
},
3136
},
3237
});

examples/check-for-execution-timeout.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StateMachine, StatesTimeoutError } from 'aws-local-stepfunctions';
1+
import { StateMachine, ExecutionTimeoutError } from 'aws-local-stepfunctions';
22

33
const machineDefinition = {
44
StartAt: 'WaitState',
@@ -21,8 +21,8 @@ try {
2121
const result = await execution.result;
2222
console.log(result);
2323
} catch (error) {
24-
// When execution times out, type of error is `StatesTimeoutError`
25-
if (error instanceof StatesTimeoutError) {
24+
// When execution times out, type of error is `ExecutionTimeoutError`
25+
if (error instanceof ExecutionTimeoutError) {
2626
console.error('The execution has timed out');
2727
}
2828
}

examples/task-state-local-override.js

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const execution = stateMachine.run(myInput, {
2525
// by specifying the Task state name as the key and the local function as value, as in the example below:
2626
taskResourceLocalHandlers: {
2727
// Call the `addNumbersLocal` function instead of invoking the Lambda function specified for the `AddNumbers` state.
28+
// Note that the key is the name of the `Task` state that we want to override.
2829
AddNumbers: addNumbersLocal,
2930
},
3031
},

examples/wait-state-local-override.js

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const execution = stateMachine.run(myInput, {
1818
// Property `waitTimeOverrides` lets you override any number of Wait states,
1919
// by specifying the Wait state name as the key and the duration override as value (represented in milliseconds):
2020
waitTimeOverrides: {
21+
// Note that the key is the name of the `Wait` state that we want to override.
2122
Wait10Seconds: 500, // wait for 500 milliseconds instead of the 10 seconds specified in the `Wait10Seconds` state
2223
},
2324
},

0 commit comments

Comments
 (0)