Skip to content

Release 2.0.0 #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 33 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
fbb1a47
Bump required node engine to at least v18
nibble-4bits Feb 4, 2024
d90fddf
Upgrade TypeScript to v5.3.3
nibble-4bits Feb 4, 2024
1fdd9b2
Upgrade tsconfig to use es2022 features and output es2022 code
nibble-4bits Feb 4, 2024
5889ec3
Upgrade tsup to v8.0.1
nibble-4bits Feb 4, 2024
d16ba48
Upgrade prettier to v3.2.4
nibble-4bits Feb 4, 2024
56a2941
Upgrade eslint packages to latest major versions
nibble-4bits Feb 4, 2024
89867fc
Removed unused dev dependencies
nibble-4bits Feb 4, 2024
2e4f0a3
Tell vscode to use typescript version from node_modules
nibble-4bits Feb 4, 2024
3e546c9
Ignore typescript error from `wildcard-match` import
nibble-4bits Feb 4, 2024
756afbb
Remove custom `ErrorWithCause` in favor of `Error.cause` property
nibble-4bits Feb 4, 2024
ddbbbd7
Remove `build/main.d.cts` file as it's identical to `build/main.d.ts`
nibble-4bits Feb 4, 2024
97c5b72
Upgrade wildcard-match to v5.1.3
nibble-4bits Mar 10, 2024
7d769bc
Merge pull request #92 from nibble-4bits/chore/bump-to-node18
nibble-4bits Mar 10, 2024
6d198fb
Add `build:watch` script
nibble-4bits Feb 4, 2024
d4aef21
Create base class for hash algorithms
nibble-4bits Feb 10, 2024
f16e5a5
Implement MD5 hash algorithm
nibble-4bits Feb 10, 2024
c0c6ca2
Implement SHA1 hash algorithm
nibble-4bits Feb 10, 2024
7c06455
Implement SHA256 hash algorithm
nibble-4bits Feb 10, 2024
0572afa
Implement SHA384 hash algorithm
nibble-4bits Feb 10, 2024
a1b9964
Implement SHA512 hash algorithm
nibble-4bits Feb 10, 2024
132b191
Create instances of hash algorithms and export them
nibble-4bits Feb 10, 2024
0dbc721
Replace `crypto-js` hash algorithms for built-in implementations
nibble-4bits Feb 10, 2024
63524e1
Remove `crypto-js` dependency
nibble-4bits Feb 9, 2024
7b1f232
Replace instances of "hashing" with "hash"
nibble-4bits Feb 10, 2024
a763de9
Make `textEncoder` a private property of BaseHash
nibble-4bits Feb 10, 2024
36c51cc
Rename base hash class to `BaseHashAlgorithm`
nibble-4bits Feb 10, 2024
c446c68
Print provided extraneous algorithm in error message
nibble-4bits Feb 10, 2024
a292b40
Remove `@ts-ignore` comment
nibble-4bits Feb 11, 2024
645117e
Run GitHub workflows with Node18
nibble-4bits Mar 10, 2024
446b59c
Update name of referenced property in comment
nibble-4bits May 28, 2024
5993770
Update dependencies to latest version with `npm update`
nibble-4bits May 28, 2024
6d8317a
Merge pull request #93 from nibble-4bits/refactor-18
nibble-4bits May 28, 2024
cf3b9e0
Bump package version to v2.0.0
nibble-4bits May 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pr-run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'
- name: Install dependencies
run: npm ci
- name: Run tests
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/prepare-for-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
node-version: '18'
registry-url: 'https://registry.npmjs.org'
- name: Install dependencies
run: npm ci
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"editor.formatOnSave": true,
"eslint.validate": ["typescript"],
"eslint.alwaysShowStatus": true,
"files.eol": "auto"
"files.eol": "auto",
"typescript.tsdk": "node_modules/typescript/lib"
}
2 changes: 1 addition & 1 deletion __tests__/intrinsicFunctions/StatesHash.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ describe('States.Hash intrinsic function', () => {
expect(funcCallWrapper).toThrow(StatesRuntimeError);
});

test('should throw error if passed hashing algorithm is not one of the supported algorithms', () => {
test('should throw error if passed hash algorithm is not one of the supported algorithms', () => {
const func = new StatesHash();
const input = {};
const context = {};
Expand Down
3,275 changes: 1,764 additions & 1,511 deletions package-lock.json

Large diffs are not rendered by default.

41 changes: 19 additions & 22 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "aws-local-stepfunctions",
"version": "1.3.1",
"version": "2.0.0",
"description": "Execute an AWS Step Function state machine locally",
"keywords": [
"aws",
Expand Down Expand Up @@ -38,45 +38,42 @@
"default": "./build/main.browser.esm.js"
},
"engines": {
"node": ">=16.0.0"
"node": ">=18.0.0"
},
"bin": {
"local-sfn": "./bin/CLI.cjs"
},
"scripts": {
"test": "jest",
"build": "tsup",
"build": "tsup && rm build/main.d.cts",
"build:watch": "tsup --watch",
"prettier": "prettier --check \"src/**/*.ts\"",
"prettier:fix": "prettier --write \"src/**/*.ts\"",
"lint": "eslint \"src/**/*.ts\"",
"lint:fix": "eslint --fix \"src/**/*.ts\""
},
"devDependencies": {
"@tsconfig/node16-strictest": "^1.0.4",
"@types/crypto-js": "^4.2.1",
"@types/jest": "^29.5.11",
"@types/lodash": "^4.14.202",
"@types/node": "^18.19.3",
"@types/picomatch": "^2.3.3",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-prettier": "^4.2.1",
"prettier": "^2.8.8",
"ts-jest": "^29.1.1",
"tsup": "^6.7.0",
"typescript": "^4.9.5"
"@types/jest": "^29.5.12",
"@types/lodash": "^4.17.4",
"@types/node": "^18.19.33",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"prettier": "^3.2.5",
"ts-jest": "^29.1.3",
"tsup": "^8.0.2",
"typescript": "^5.4.5"
},
"dependencies": {
"@aws-sdk/client-lambda": "^3.481.0",
"@aws-sdk/credential-providers": "^3.481.0",
"@aws-sdk/client-lambda": "^3.583.0",
"@aws-sdk/credential-providers": "^3.583.0",
"asl-validator": "^3.8.2",
"commander": "^11.1.0",
"crypto-js": "^4.2.0",
"jsonpath-plus": "^7.2.0",
"lodash": "^4.17.21",
"p-limit": "^3.1.0",
"wildcard-match": "^5.1.2"
"wildcard-match": "^5.1.3"
}
}
12 changes: 0 additions & 12 deletions src/error/ErrorWithCause.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/error/ExecutionError.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import type { RuntimeError } from './RuntimeError';
import { ErrorWithCause } from './ErrorWithCause';

/**
* Represents the failure of a state machine execution.
*/
export class ExecutionError extends ErrorWithCause {
export class ExecutionError extends Error {
constructor(caughtError: RuntimeError) {
super(`Execution has failed with the following error: ${caughtError.message}`, { cause: caughtError });

Expand Down
4 changes: 1 addition & 3 deletions src/error/RuntimeError.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { ErrorWithCause } from './ErrorWithCause';

/**
* Base class for all internal errors that can be thrown during the state machine execution.
*/
export abstract class RuntimeError extends ErrorWithCause {
export abstract class RuntimeError extends Error {
/**
* Whether this runtime error can be matched in a `Retry` field
*/
Expand Down
2 changes: 1 addition & 1 deletion src/stateMachine/StateExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ export class StateExecutor {
nextState,
isEndState,
} = await this.stateHandlers[this.stateDefinition.Type](
// @ts-expect-error Indexing `this.stateActions` by non-literal value produces a `never` type for the `this.stateDefinition` parameter of the handler being called
// @ts-expect-error Indexing `this.stateHandlers` by non-literal value produces a `never` type for the `this.stateDefinition` parameter of the handler being called
this.stateDefinition,
rawInput,
processedInput,
Expand Down
24 changes: 10 additions & 14 deletions src/stateMachine/intrinsicFunctions/StatesHash.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import type { IntrinsicFunctionDefinition } from '../../typings/IntrinsicFunctionsImplementation';
import type { HashingAlgorithm } from '../../typings/IntrinsicFunctions';
import type { HashAlgorithm } from '../../typings/IntrinsicFunctions';
import type { JSONValue } from '../../typings/JSONValue';
import { StatesRuntimeError } from '../../error/predefined/StatesRuntimeError';
import { BaseIntrinsicFunction } from './BaseIntrinsicFunction';
import md5 from 'crypto-js/md5.js';
import sha1 from 'crypto-js/sha1.js';
import sha256 from 'crypto-js/sha256.js';
import sha384 from 'crypto-js/sha384.js';
import sha512 from 'crypto-js/sha512.js';
import { md5, sha1, sha256, sha384, sha512 } from '../../util/hash';

class StatesHash extends BaseIntrinsicFunction {
protected readonly funcDefinition: IntrinsicFunctionDefinition;
Expand All @@ -29,32 +25,32 @@ class StatesHash extends BaseIntrinsicFunction {
};
}

protected execute(str: string, algorithm: HashingAlgorithm): JSONValue {
protected execute(str: string, algorithm: HashAlgorithm): JSONValue {
if (str.length > 10000) {
throw new StatesRuntimeError(
`Intrinsic function ${this.funcDefinition.name} cannot hash a string with more than 10,000 characters`
);
}

const algorithms: HashingAlgorithm[] = ['MD5', 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'];
const algorithms: HashAlgorithm[] = ['MD5', 'SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'];
const supportedAlgorithms = algorithms.join(', ');
if (!algorithms.includes(algorithm)) {
throw new StatesRuntimeError(
`Unsupported hashing algorithm provided to intrinsic function ${this.funcDefinition.name}. The supported algorithms are: ${supportedAlgorithms}`
`Unsupported hash algorithm '${algorithm}' provided to intrinsic function ${this.funcDefinition.name}. The supported algorithms are: ${supportedAlgorithms}`
);
}

switch (algorithm) {
case 'MD5':
return md5(str).toString();
return md5.getDigest(str);
case 'SHA-1':
return sha1(str).toString();
return sha1.getDigest(str);
case 'SHA-256':
return sha256(str).toString();
return sha256.getDigest(str);
case 'SHA-384':
return sha384(str).toString();
return sha384.getDigest(str);
case 'SHA-512':
return sha512(str).toString();
return sha512.getDigest(str);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/typings/IntrinsicFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ export type IntrinsicFunctionName =
| 'States.StringSplit'
| 'States.UUID';

export type HashingAlgorithm = 'MD5' | 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
export type HashAlgorithm = 'MD5' | 'SHA-1' | 'SHA-256' | 'SHA-384' | 'SHA-512';
11 changes: 11 additions & 0 deletions src/util/hash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { MD5 } from './hash/MD5';
import { SHA1 } from './hash/SHA1';
import { SHA256 } from './hash/SHA256';
import { SHA384 } from './hash/SHA384';
import { SHA512 } from './hash/SHA512';

export const md5 = new MD5();
export const sha1 = new SHA1();
export const sha256 = new SHA256();
export const sha384 = new SHA384();
export const sha512 = new SHA512();
125 changes: 125 additions & 0 deletions src/util/hash/BaseHash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// TypeScript's DOM library has to be referenced for `TextEncoder` to be recognized as a type
/// <reference lib="dom" />

export abstract class BaseHashAlgorithm {
private textEncoder: TextEncoder;

constructor() {
this.textEncoder = new TextEncoder();
}

getDigest(input: string): string {
const message = this.textEncoder.encode(input);

const paddedMessage = this.padMessage(message);
const hash = this.computeHash(paddedMessage);
const digest = this.hashToString(hash);

return digest;
}

protected abstract padMessage(message: Uint8Array): ArrayBuffer;

protected abstract computeHash(paddedMessage: ArrayBuffer): ArrayBuffer;

protected abstract hashToString(hash: ArrayBuffer): string;

protected rotl(n: number, x: number): number;
protected rotl(n: bigint, x: bigint): bigint;
protected rotl(n: number | bigint, x: number | bigint): number | bigint {
if (typeof n === 'number' && typeof x === 'number') return (x << n) | (x >>> (32 - n));
if (typeof n === 'bigint' && typeof x === 'bigint') return (x << n) | (x >> (64n - n));

throw new Error('Both arguments must be of the same type');
}

protected rotr(n: number, x: number): number;
protected rotr(n: bigint, x: bigint): bigint;
protected rotr(n: number | bigint, x: number | bigint): number | bigint {
if (typeof n === 'number' && typeof x === 'number') return (x >>> n) | (x << (32 - n));
if (typeof n === 'bigint' && typeof x === 'bigint') return (x >> n) | (x << (64n - n));

throw new Error('Both arguments must be of the same type');
}

protected ch(x: number, y: number, z: number): number;
protected ch(x: bigint, y: bigint, z: bigint): bigint;
protected ch(x: number | bigint, y: number | bigint, z: number | bigint): number | bigint {
if (typeof x === typeof y && typeof y === typeof z) {
// @ts-expect-error TypeScript can't disambiguate between number and bigint
return (x & y) ^ (~x & z);
}

throw new Error('All arguments must be of the same type');
}

protected parity(x: number, y: number, z: number): number;
protected parity(x: bigint, y: bigint, z: bigint): bigint;
protected parity(x: number | bigint, y: number | bigint, z: number | bigint): number | bigint {
if (typeof x === typeof y && typeof y === typeof z) {
// @ts-expect-error TypeScript can't disambiguate between number and bigint
return x ^ y ^ z;
}

throw new Error('All arguments must be of the same type');
}

protected maj(x: number, y: number, z: number): number;
protected maj(x: bigint, y: bigint, z: bigint): bigint;
protected maj(x: number | bigint, y: number | bigint, z: number | bigint): number | bigint {
if (typeof x === typeof y && typeof y === typeof z) {
// @ts-expect-error TypeScript can't disambiguate between number and bigint
return (x & y) ^ (x & z) ^ (y & z);
}

throw new Error('All arguments must be of the same type');
}

protected bigSigma0(x: number): number;
protected bigSigma0(x: bigint): bigint;
protected bigSigma0(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(2, x) ^ this.rotr(13, x) ^ this.rotr(22, x);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(28n, x) ^ this.rotr(34n, x) ^ this.rotr(39n, x);
}

protected bigSigma1(x: number): number;
protected bigSigma1(x: bigint): bigint;
protected bigSigma1(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(6, x) ^ this.rotr(11, x) ^ this.rotr(25, x);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(14n, x) ^ this.rotr(18n, x) ^ this.rotr(41n, x);
}

protected smallSigma0(x: number): number;
protected smallSigma0(x: bigint): bigint;
protected smallSigma0(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(7, x) ^ this.rotr(18, x) ^ (x >>> 3);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(1n, x) ^ this.rotr(8n, x) ^ (x >> 7n);
}

protected smallSigma1(x: number): number;
protected smallSigma1(x: bigint): bigint;
protected smallSigma1(x: number | bigint): number | bigint {
if (typeof x === 'number') {
// number version used by SHA1 and SHA256
return this.rotr(17, x) ^ this.rotr(19, x) ^ (x >>> 10);
}

// BigInt version used by SHA384 and SHA512
return this.rotr(19n, x) ^ this.rotr(61n, x) ^ (x >> 6n);
}
}
Loading
Loading