aws-local-stepfunctions
Version:
Execute an AWS Step Function state machine locally
3,117 lines • 106 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/main.ts
var main_exports = {};
__export(main_exports, {
ExecutionAbortedError: () => ExecutionAbortedError,
ExecutionError: () => ExecutionError,
ExecutionTimeoutError: () => ExecutionTimeoutError,
StateMachine: () => StateMachine
});
module.exports = __toCommonJS(main_exports);
// src/error/ExecutionAbortedError.ts
var ExecutionAbortedError = class extends Error {
constructor() {
super("Execution aborted");
this.name = "ExecutionAbortedError";
}
};
// src/error/ExecutionTimeoutError.ts
var ExecutionTimeoutError = class extends Error {
constructor() {
super("Execution timed out");
this.name = "ExecutionTimeoutError";
}
};
// src/error/ExecutionError.ts
var ExecutionError = class extends Error {
constructor(caughtError) {
super(`Execution has failed with the following error: ${caughtError.message}`, { cause: caughtError });
this.name = "ExecutionError";
}
};
// src/util/random.ts
function cyrb128(str) {
let h1 = 1779033703, h2 = 3144134277, h3 = 1013904242, h4 = 2773480762;
for (let i = 0, k; i < str.length; i++) {
k = str.charCodeAt(i);
h1 = h2 ^ Math.imul(h1 ^ k, 597399067);
h2 = h3 ^ Math.imul(h2 ^ k, 2869860233);
h3 = h4 ^ Math.imul(h3 ^ k, 951274213);
h4 = h1 ^ Math.imul(h4 ^ k, 2716044179);
}
h1 = Math.imul(h3 ^ h1 >>> 18, 597399067);
h2 = Math.imul(h4 ^ h2 >>> 22, 2869860233);
h3 = Math.imul(h1 ^ h3 >>> 17, 951274213);
h4 = Math.imul(h2 ^ h4 >>> 19, 2716044179);
return [(h1 ^ h2 ^ h3 ^ h4) >>> 0, (h2 ^ h1) >>> 0, (h3 ^ h1) >>> 0, (h4 ^ h1) >>> 0];
}
function sfc32(a, b, c, d) {
return function() {
a >>>= 0;
b >>>= 0;
c >>>= 0;
d >>>= 0;
let t = a + b | 0;
a = b ^ b >>> 9;
b = c + (c << 3) | 0;
c = c << 21 | c >>> 11;
d = d + 1 | 0;
t = t + d | 0;
c = c + t | 0;
return (t >>> 0) / 4294967296;
};
}
function getRandomNumber(min, max, rng = Math.random) {
return Math.floor(rng() * (max - min + 1)) + min;
}
// src/util/index.ts
var isBrowserEnvironment = typeof window !== "undefined" && typeof window.document !== "undefined";
function isPlainObj(value) {
return !!value && Object.getPrototypeOf(value) === Object.prototype;
}
function sleep(ms, abortSignal) {
if (ms === 0) return;
return new Promise((resolve) => {
if (abortSignal?.aborted) {
return resolve();
}
const onAbort = () => {
clearTimeout(timeout);
resolve();
};
const timeout = setTimeout(() => {
abortSignal?.removeEventListener("abort", onAbort);
resolve();
}, ms);
abortSignal?.addEventListener("abort", onAbort, { once: true });
});
}
function byteToHex(byte) {
return byte.toString(16).padStart(2, "0");
}
function isRFC3339Timestamp(date) {
const regex = /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(\.\d+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/;
return regex.test(date);
}
function stringifyJSONValue(value) {
return JSON.stringify(value);
}
function clamp(value, min, max) {
if (min && value < min) return min;
if (max && value > max) return max;
return value;
}
// src/stateMachine/jsonPath/JsonPath.ts
var import_jsonpath_plus = require("jsonpath-plus");
// src/stateMachine/jsonPath/constraints/BaseJsonPathConstraint.ts
var BaseJSONPathConstraint = class {
pathExpression;
constructor(pathExpression) {
this.pathExpression = pathExpression;
}
};
// src/error/RuntimeError.ts
var RuntimeError = class extends Error {
/**
* Whether this runtime error can be matched in a `Retry` field
*/
retryable;
/**
* Whether this runtime error can be caught in a `Catch` field
*/
catchable;
constructor(message, cause) {
super(message, { cause });
this.name = "RuntimeError";
this.retryable = true;
this.catchable = true;
}
get isRetryable() {
return this.retryable;
}
get isCatchable() {
return this.catchable;
}
};
// src/error/predefined/StatesRuntimeError.ts
var StatesRuntimeError = class extends RuntimeError {
constructor(message = "States.Runtime") {
super(message);
this.name = "States.Runtime";
this.retryable = false;
this.catchable = false;
}
};
// src/stateMachine/jsonPath/constraints/DefinedValueConstraint.ts
var DefinedValueConstraint = class extends BaseJSONPathConstraint {
test(value) {
if (typeof value === "undefined") {
throw new StatesRuntimeError(`Path expression '${this.pathExpression}' does not point to a value`);
}
}
};
// src/stateMachine/jsonPath/JsonPath.ts
function jsonPathQuery(pathExpression, json, context, options) {
const defaultConstraints = [];
if (!options?.ignoreDefinedValueConstraint) {
defaultConstraints.push(DefinedValueConstraint);
}
const constraints = [...defaultConstraints, ...options?.constraints ?? []];
let evaluation;
if (pathExpression.startsWith("$$")) {
evaluation = (0, import_jsonpath_plus.JSONPath)({ path: pathExpression.slice(1), json: context ?? null, wrap: false });
} else {
evaluation = (0, import_jsonpath_plus.JSONPath)({ path: pathExpression, json, wrap: false });
}
for (const Constraint of constraints) {
const constraintObject = new Constraint(pathExpression);
constraintObject.test(evaluation);
}
return evaluation;
}
// src/error/predefined/StatesResultPathMatchFailureError.ts
var StatesResultPathMatchFailureError = class extends RuntimeError {
constructor() {
super("States.ResultPathMatchFailure");
this.name = "States.ResultPathMatchFailure";
}
};
// src/stateMachine/intrinsicFunctions/ArgumentHandling.ts
function validateArgumentType(allowedTypes, argPosition, funcArg, funcName) {
let matchesAllowedType = false;
for (const argType of allowedTypes) {
switch (argType) {
case "string":
case "number":
case "boolean":
matchesAllowedType = typeof funcArg === argType;
break;
case "null":
matchesAllowedType = funcArg === null;
break;
case "array":
matchesAllowedType = Array.isArray(funcArg);
break;
case "object":
matchesAllowedType = isPlainObj(funcArg);
break;
case "any":
matchesAllowedType = true;
break;
}
if (matchesAllowedType) break;
}
const expectedType = allowedTypes.map((type) => `'${type}'`).join(" | ");
if (!matchesAllowedType) {
throw new StatesRuntimeError(
`Intrinsic function ${funcName} expected argument ${argPosition} to be of type ${expectedType}, but received ${typeof funcArg}`
);
}
}
function validateArgumentConstraints(argConstraints, argPosition, funcArg, funcName) {
if (argConstraints) {
let matchesAllConstraints = false;
for (const constraint of argConstraints) {
switch (constraint) {
case "ZERO":
matchesAllConstraints = funcArg === 0;
break;
case "POSITIVE_INTEGER":
matchesAllConstraints = Number.isInteger(funcArg) && funcArg > 0;
break;
case "NEGATIVE_INTEGER":
matchesAllConstraints = Number.isInteger(funcArg) && funcArg < 0;
break;
case "INTEGER":
matchesAllConstraints = Number.isInteger(funcArg);
break;
}
if (matchesAllConstraints) break;
}
const expectedConstraints = argConstraints.map((constraint) => `'${constraint}'`).join(" | ");
if (!matchesAllConstraints) {
throw new StatesRuntimeError(
`Intrinsic function ${funcName} expected argument ${argPosition} to satisfy the following constraints: ${expectedConstraints}`
);
}
}
}
function validateArguments(funcDefinition, ...args) {
if ("exactArgs" in funcDefinition && args.length !== funcDefinition.exactArgs) {
throw new StatesRuntimeError(
`Intrinsic function ${funcDefinition.name} expects exactly ${funcDefinition.exactArgs} arguments, but received ${args.length}`
);
}
if ("minArgs" in funcDefinition && args.length < funcDefinition.minArgs) {
throw new StatesRuntimeError(
`Intrinsic function ${funcDefinition.name} expects at least ${funcDefinition.minArgs} arguments, but received ${args.length}`
);
}
if ("maxArgs" in funcDefinition && args.length > funcDefinition.maxArgs) {
throw new StatesRuntimeError(
`Intrinsic function ${funcDefinition.name} expects at most ${funcDefinition.maxArgs} arguments, but received ${args.length}`
);
}
if ("arguments" in funcDefinition) {
for (let i = 0; i < funcDefinition.arguments.length; i++) {
const argDefinition = funcDefinition.arguments[i];
const funcArg = args[i];
if (funcArg === void 0) break;
validateArgumentType(argDefinition.allowedTypes, i + 1, funcArg, funcDefinition.name);
validateArgumentConstraints(argDefinition.constraints, i + 1, funcArg, funcDefinition.name);
}
}
if ("variadicArguments" in funcDefinition) {
const argDefinition = funcDefinition.variadicArguments;
for (let i = funcDefinition.arguments?.length ?? 0; i < args.length; i++) {
const funcArg = args[i];
validateArgumentType(argDefinition.allowedTypes, i + 1, funcArg, funcDefinition.name);
validateArgumentConstraints(argDefinition.constraints, i + 1, funcArg, funcDefinition.name);
}
}
}
function parseArguments(input, context, ...args) {
return args.map((arg) => {
if (arg[0] === "'") {
const lastSingleQuote = arg.lastIndexOf("'");
return arg.slice(1, lastSingleQuote);
}
if (arg[0] === "$") {
return jsonPathQuery(arg, input, context);
}
return JSON.parse(arg);
});
}
// src/stateMachine/intrinsicFunctions/BaseIntrinsicFunction.ts
var BaseIntrinsicFunction = class {
call(input, context, ...args) {
const parsedArgs = parseArguments(input, context, ...args);
validateArguments(this.funcDefinition, ...parsedArgs);
let result = this.execute(...parsedArgs);
if (typeof result === "string") {
result = result.replaceAll("\\", "");
}
return result;
}
};
// src/stateMachine/intrinsicFunctions/StatesFormat.ts
var StatesFormat = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.Format",
minArgs: 1,
arguments: [
{
allowedTypes: ["string"]
}
],
variadicArguments: {
allowedTypes: ["string", "boolean", "number", "null"]
}
};
}
execute(templateStr, ...placeholderValues) {
const placeholdersNumber = templateStr.match(/\{\}/g)?.length ?? 0;
if (placeholdersNumber !== placeholderValues.length) {
throw new StatesRuntimeError(
`Number of arguments in ${this.funcDefinition.name} do not match the occurrences of {}`
);
}
let i = 0;
return templateStr.replace(/\{\}/g, () => placeholderValues[i++]);
}
};
// src/stateMachine/intrinsicFunctions/StatesStringToJson.ts
var StatesStringToJson = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.StringToJson",
exactArgs: 1,
arguments: [
{
allowedTypes: ["string"]
}
]
};
}
execute(jsonString) {
return JSON.parse(jsonString);
}
};
// src/stateMachine/intrinsicFunctions/StatesJsonToString.ts
var StatesJsonToString = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.JsonToString",
exactArgs: 1,
arguments: [
{
allowedTypes: ["any"]
}
]
};
}
execute(json) {
return JSON.stringify(json);
}
};
// src/stateMachine/intrinsicFunctions/StatesArray.ts
var StatesArray = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.Array",
variadicArguments: {
allowedTypes: ["any"]
}
};
}
execute(...args) {
return args;
}
};
// src/stateMachine/intrinsicFunctions/StatesArrayPartition.ts
var StatesArrayPartition = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.ArrayPartition",
exactArgs: 2,
arguments: [
{
allowedTypes: ["array"]
},
{
allowedTypes: ["number"],
constraints: ["POSITIVE_INTEGER"]
}
]
};
}
execute(array, chunkSize) {
const partitionedArr = [];
for (let i = 0; i < array.length; i += chunkSize) {
const subArray = array.slice(i, i + chunkSize);
partitionedArr.push(subArray);
}
return partitionedArr;
}
};
// src/stateMachine/intrinsicFunctions/StatesArrayContains.ts
var import_isEqual = __toESM(require("lodash/isEqual.js"), 1);
var StatesArrayContains = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.ArrayContains",
exactArgs: 2,
arguments: [
{
allowedTypes: ["array"]
},
{
allowedTypes: ["any"]
}
]
};
}
execute(array, searchVal) {
return array.findIndex((val) => (0, import_isEqual.default)(val, searchVal)) > -1;
}
};
// src/stateMachine/intrinsicFunctions/StatesArrayRange.ts
var StatesArrayRange = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.ArrayRange",
exactArgs: 3,
arguments: [
{
allowedTypes: ["number"],
constraints: ["INTEGER"]
},
{
allowedTypes: ["number"],
constraints: ["INTEGER"]
},
{
allowedTypes: ["number"],
constraints: ["POSITIVE_INTEGER", "NEGATIVE_INTEGER"]
}
]
};
}
execute(start, end, step) {
const slots = (end - start) / step;
if (slots < 0) {
return [];
}
const arrLength = Math.floor(slots) + 1;
if (arrLength > 1e3) {
throw new StatesRuntimeError(
`Result of intrinsic function ${this.funcDefinition.name} cannot contain more than 1000 items`
);
}
const range = Array.from({ length: arrLength }).map((_, i) => start + step * i);
return range;
}
};
// src/stateMachine/intrinsicFunctions/StatesArrayGetItem.ts
var StatesArrayGetItem = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.ArrayGetItem",
exactArgs: 2,
arguments: [
{
allowedTypes: ["array"]
},
{
allowedTypes: ["number"]
}
]
};
}
execute(array, index) {
return array[index] ?? null;
}
};
// src/stateMachine/intrinsicFunctions/StatesArrayLength.ts
var StatesArrayLength = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.ArrayLength",
exactArgs: 1,
arguments: [
{
allowedTypes: ["array"]
}
]
};
}
execute(array) {
return array.length;
}
};
// src/stateMachine/intrinsicFunctions/StatesArrayUnique.ts
var import_isEqual2 = __toESM(require("lodash/isEqual.js"), 1);
var import_uniqWith = __toESM(require("lodash/uniqWith.js"), 1);
var StatesArrayUnique = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.ArrayUnique",
exactArgs: 1,
arguments: [
{
allowedTypes: ["array"]
}
]
};
}
execute(array) {
return (0, import_uniqWith.default)(array, import_isEqual2.default);
}
};
// src/stateMachine/intrinsicFunctions/StatesBase64Encode.ts
var StatesBase64Encode = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.Base64Encode",
exactArgs: 1,
arguments: [
{
allowedTypes: ["string"]
}
]
};
}
execute(str) {
if (str.length > 1e4) {
throw new StatesRuntimeError(
`Intrinsic function ${this.funcDefinition.name} cannot encode a string with more than 10,000 characters`
);
}
return btoa(str);
}
};
// src/stateMachine/intrinsicFunctions/StatesBase64Decode.ts
var StatesBase64Decode = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.Base64Decode",
exactArgs: 1,
arguments: [
{
allowedTypes: ["string"]
}
]
};
}
execute(str) {
if (str.length > 1e4) {
throw new StatesRuntimeError(
`Intrinsic function ${this.funcDefinition.name} cannot decode a Base64 string with more than 10,000 characters`
);
}
return atob(str);
}
};
// src/util/hash/BaseHash.ts
var BaseHashAlgorithm = class {
textEncoder;
constructor() {
this.textEncoder = new TextEncoder();
}
getDigest(input) {
const message = this.textEncoder.encode(input);
const paddedMessage = this.padMessage(message);
const hash = this.computeHash(paddedMessage);
const digest = this.hashToString(hash);
return digest;
}
rotl(n, x) {
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");
}
rotr(n, x) {
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");
}
ch(x, y, z) {
if (typeof x === typeof y && typeof y === typeof z) {
return x & y ^ ~x & z;
}
throw new Error("All arguments must be of the same type");
}
parity(x, y, z) {
if (typeof x === typeof y && typeof y === typeof z) {
return x ^ y ^ z;
}
throw new Error("All arguments must be of the same type");
}
maj(x, y, z) {
if (typeof x === typeof y && typeof y === typeof z) {
return x & y ^ x & z ^ y & z;
}
throw new Error("All arguments must be of the same type");
}
bigSigma0(x) {
if (typeof x === "number") {
return this.rotr(2, x) ^ this.rotr(13, x) ^ this.rotr(22, x);
}
return this.rotr(28n, x) ^ this.rotr(34n, x) ^ this.rotr(39n, x);
}
bigSigma1(x) {
if (typeof x === "number") {
return this.rotr(6, x) ^ this.rotr(11, x) ^ this.rotr(25, x);
}
return this.rotr(14n, x) ^ this.rotr(18n, x) ^ this.rotr(41n, x);
}
smallSigma0(x) {
if (typeof x === "number") {
return this.rotr(7, x) ^ this.rotr(18, x) ^ x >>> 3;
}
return this.rotr(1n, x) ^ this.rotr(8n, x) ^ x >> 7n;
}
smallSigma1(x) {
if (typeof x === "number") {
return this.rotr(17, x) ^ this.rotr(19, x) ^ x >>> 10;
}
return this.rotr(19n, x) ^ this.rotr(61n, x) ^ x >> 6n;
}
};
// src/util/hash/MD5.ts
var MD5 = class extends BaseHashAlgorithm {
padMessage(message) {
const msgLenMod64 = message.length % 64;
let bytesToAdd = 64 - msgLenMod64;
if (msgLenMod64 >= 56) {
bytesToAdd += 64;
}
const padding = new Uint8Array(bytesToAdd);
const paddedMsg = new Uint8Array([...message, ...padding]);
const dataView = new DataView(paddedMsg.buffer);
dataView.setUint8(message.length, 128);
dataView.setBigUint64(paddedMsg.length - 8, BigInt(message.length * 8), true);
return paddedMsg.buffer;
}
computeHash(paddedMessage) {
const b1 = new Uint32Array(4);
const b2 = new Uint32Array([1732584193, 4023233417, 2562383102, 271733878]);
const seq = new Uint32Array(16);
const table = new Uint32Array([
3614090360,
3905402710,
606105819,
3250441966,
4118548399,
1200080426,
2821735955,
4249261313,
1770035416,
2336552879,
4294925233,
2304563134,
1804603682,
4254626195,
2792965006,
1236535329,
4129170786,
3225465664,
643717713,
3921069994,
3593408605,
38016083,
3634488961,
3889429448,
568446438,
3275163606,
4107603335,
1163531501,
2850285829,
4243563512,
1735328473,
2368359562,
4294588738,
2272392833,
1839030562,
4259657740,
2763975236,
1272893353,
4139469664,
3200236656,
681279174,
3936430074,
3572445317,
76029189,
3654602809,
3873151461,
530742520,
3299628645,
4096336452,
1126891415,
2878612391,
4237533241,
1700485571,
2399980690,
4293915773,
2240044497,
1873313359,
4264355552,
2734768916,
1309151649,
4149444226,
3174756917,
718787259,
3951481745
]);
const dataView = new DataView(paddedMessage);
for (let i = 0; i < paddedMessage.byteLength / 4; i += 16) {
for (let t = 0; t < 16; t++) {
seq[t] = dataView.getUint32(i + t * 4, true);
}
b1[0] = b2[0];
b1[1] = b2[1];
b1[2] = b2[2];
b1[3] = b2[3];
b1[0] = b1[1] + this.rotl(7, b1[0] + this.F(b1[1], b1[2], b1[3]) + seq[0] + table[0]);
b1[3] = b1[0] + this.rotl(12, b1[3] + this.F(b1[0], b1[1], b1[2]) + seq[1] + table[1]);
b1[2] = b1[3] + this.rotl(17, b1[2] + this.F(b1[3], b1[0], b1[1]) + seq[2] + table[2]);
b1[1] = b1[2] + this.rotl(22, b1[1] + this.F(b1[2], b1[3], b1[0]) + seq[3] + table[3]);
b1[0] = b1[1] + this.rotl(7, b1[0] + this.F(b1[1], b1[2], b1[3]) + seq[4] + table[4]);
b1[3] = b1[0] + this.rotl(12, b1[3] + this.F(b1[0], b1[1], b1[2]) + seq[5] + table[5]);
b1[2] = b1[3] + this.rotl(17, b1[2] + this.F(b1[3], b1[0], b1[1]) + seq[6] + table[6]);
b1[1] = b1[2] + this.rotl(22, b1[1] + this.F(b1[2], b1[3], b1[0]) + seq[7] + table[7]);
b1[0] = b1[1] + this.rotl(7, b1[0] + this.F(b1[1], b1[2], b1[3]) + seq[8] + table[8]);
b1[3] = b1[0] + this.rotl(12, b1[3] + this.F(b1[0], b1[1], b1[2]) + seq[9] + table[9]);
b1[2] = b1[3] + this.rotl(17, b1[2] + this.F(b1[3], b1[0], b1[1]) + seq[10] + table[10]);
b1[1] = b1[2] + this.rotl(22, b1[1] + this.F(b1[2], b1[3], b1[0]) + seq[11] + table[11]);
b1[0] = b1[1] + this.rotl(7, b1[0] + this.F(b1[1], b1[2], b1[3]) + seq[12] + table[12]);
b1[3] = b1[0] + this.rotl(12, b1[3] + this.F(b1[0], b1[1], b1[2]) + seq[13] + table[13]);
b1[2] = b1[3] + this.rotl(17, b1[2] + this.F(b1[3], b1[0], b1[1]) + seq[14] + table[14]);
b1[1] = b1[2] + this.rotl(22, b1[1] + this.F(b1[2], b1[3], b1[0]) + seq[15] + table[15]);
b1[0] = b1[1] + this.rotl(5, b1[0] + this.G(b1[1], b1[2], b1[3]) + seq[1] + table[16]);
b1[3] = b1[0] + this.rotl(9, b1[3] + this.G(b1[0], b1[1], b1[2]) + seq[6] + table[17]);
b1[2] = b1[3] + this.rotl(14, b1[2] + this.G(b1[3], b1[0], b1[1]) + seq[11] + table[18]);
b1[1] = b1[2] + this.rotl(20, b1[1] + this.G(b1[2], b1[3], b1[0]) + seq[0] + table[19]);
b1[0] = b1[1] + this.rotl(5, b1[0] + this.G(b1[1], b1[2], b1[3]) + seq[5] + table[20]);
b1[3] = b1[0] + this.rotl(9, b1[3] + this.G(b1[0], b1[1], b1[2]) + seq[10] + table[21]);
b1[2] = b1[3] + this.rotl(14, b1[2] + this.G(b1[3], b1[0], b1[1]) + seq[15] + table[22]);
b1[1] = b1[2] + this.rotl(20, b1[1] + this.G(b1[2], b1[3], b1[0]) + seq[4] + table[23]);
b1[0] = b1[1] + this.rotl(5, b1[0] + this.G(b1[1], b1[2], b1[3]) + seq[9] + table[24]);
b1[3] = b1[0] + this.rotl(9, b1[3] + this.G(b1[0], b1[1], b1[2]) + seq[14] + table[25]);
b1[2] = b1[3] + this.rotl(14, b1[2] + this.G(b1[3], b1[0], b1[1]) + seq[3] + table[26]);
b1[1] = b1[2] + this.rotl(20, b1[1] + this.G(b1[2], b1[3], b1[0]) + seq[8] + table[27]);
b1[0] = b1[1] + this.rotl(5, b1[0] + this.G(b1[1], b1[2], b1[3]) + seq[13] + table[28]);
b1[3] = b1[0] + this.rotl(9, b1[3] + this.G(b1[0], b1[1], b1[2]) + seq[2] + table[29]);
b1[2] = b1[3] + this.rotl(14, b1[2] + this.G(b1[3], b1[0], b1[1]) + seq[7] + table[30]);
b1[1] = b1[2] + this.rotl(20, b1[1] + this.G(b1[2], b1[3], b1[0]) + seq[12] + table[31]);
b1[0] = b1[1] + this.rotl(4, b1[0] + this.H(b1[1], b1[2], b1[3]) + seq[5] + table[32]);
b1[3] = b1[0] + this.rotl(11, b1[3] + this.H(b1[0], b1[1], b1[2]) + seq[8] + table[33]);
b1[2] = b1[3] + this.rotl(16, b1[2] + this.H(b1[3], b1[0], b1[1]) + seq[11] + table[34]);
b1[1] = b1[2] + this.rotl(23, b1[1] + this.H(b1[2], b1[3], b1[0]) + seq[14] + table[35]);
b1[0] = b1[1] + this.rotl(4, b1[0] + this.H(b1[1], b1[2], b1[3]) + seq[1] + table[36]);
b1[3] = b1[0] + this.rotl(11, b1[3] + this.H(b1[0], b1[1], b1[2]) + seq[4] + table[37]);
b1[2] = b1[3] + this.rotl(16, b1[2] + this.H(b1[3], b1[0], b1[1]) + seq[7] + table[38]);
b1[1] = b1[2] + this.rotl(23, b1[1] + this.H(b1[2], b1[3], b1[0]) + seq[10] + table[39]);
b1[0] = b1[1] + this.rotl(4, b1[0] + this.H(b1[1], b1[2], b1[3]) + seq[13] + table[40]);
b1[3] = b1[0] + this.rotl(11, b1[3] + this.H(b1[0], b1[1], b1[2]) + seq[0] + table[41]);
b1[2] = b1[3] + this.rotl(16, b1[2] + this.H(b1[3], b1[0], b1[1]) + seq[3] + table[42]);
b1[1] = b1[2] + this.rotl(23, b1[1] + this.H(b1[2], b1[3], b1[0]) + seq[6] + table[43]);
b1[0] = b1[1] + this.rotl(4, b1[0] + this.H(b1[1], b1[2], b1[3]) + seq[9] + table[44]);
b1[3] = b1[0] + this.rotl(11, b1[3] + this.H(b1[0], b1[1], b1[2]) + seq[12] + table[45]);
b1[2] = b1[3] + this.rotl(16, b1[2] + this.H(b1[3], b1[0], b1[1]) + seq[15] + table[46]);
b1[1] = b1[2] + this.rotl(23, b1[1] + this.H(b1[2], b1[3], b1[0]) + seq[2] + table[47]);
b1[0] = b1[1] + this.rotl(6, b1[0] + this.I(b1[1], b1[2], b1[3]) + seq[0] + table[48]);
b1[3] = b1[0] + this.rotl(10, b1[3] + this.I(b1[0], b1[1], b1[2]) + seq[7] + table[49]);
b1[2] = b1[3] + this.rotl(15, b1[2] + this.I(b1[3], b1[0], b1[1]) + seq[14] + table[50]);
b1[1] = b1[2] + this.rotl(21, b1[1] + this.I(b1[2], b1[3], b1[0]) + seq[5] + table[51]);
b1[0] = b1[1] + this.rotl(6, b1[0] + this.I(b1[1], b1[2], b1[3]) + seq[12] + table[52]);
b1[3] = b1[0] + this.rotl(10, b1[3] + this.I(b1[0], b1[1], b1[2]) + seq[3] + table[53]);
b1[2] = b1[3] + this.rotl(15, b1[2] + this.I(b1[3], b1[0], b1[1]) + seq[10] + table[54]);
b1[1] = b1[2] + this.rotl(21, b1[1] + this.I(b1[2], b1[3], b1[0]) + seq[1] + table[55]);
b1[0] = b1[1] + this.rotl(6, b1[0] + this.I(b1[1], b1[2], b1[3]) + seq[8] + table[56]);
b1[3] = b1[0] + this.rotl(10, b1[3] + this.I(b1[0], b1[1], b1[2]) + seq[15] + table[57]);
b1[2] = b1[3] + this.rotl(15, b1[2] + this.I(b1[3], b1[0], b1[1]) + seq[6] + table[58]);
b1[1] = b1[2] + this.rotl(21, b1[1] + this.I(b1[2], b1[3], b1[0]) + seq[13] + table[59]);
b1[0] = b1[1] + this.rotl(6, b1[0] + this.I(b1[1], b1[2], b1[3]) + seq[4] + table[60]);
b1[3] = b1[0] + this.rotl(10, b1[3] + this.I(b1[0], b1[1], b1[2]) + seq[11] + table[61]);
b1[2] = b1[3] + this.rotl(15, b1[2] + this.I(b1[3], b1[0], b1[1]) + seq[2] + table[62]);
b1[1] = b1[2] + this.rotl(21, b1[1] + this.I(b1[2], b1[3], b1[0]) + seq[9] + table[63]);
b2[0] += b1[0];
b2[1] += b1[1];
b2[2] += b1[2];
b2[3] += b1[3];
}
return b2.buffer;
}
hashToString(hash) {
const dataView = new DataView(hash);
dataView.setUint32(0, dataView.getUint32(0), true);
dataView.setUint32(4, dataView.getUint32(4), true);
dataView.setUint32(8, dataView.getUint32(8), true);
dataView.setUint32(12, dataView.getUint32(12), true);
return [...new Uint32Array(hash)].map((w) => w.toString(16).padStart(8, "0")).join("");
}
F(x, y, z) {
return this.ch(x, y, z);
}
G(x, y, z) {
return this.ch(z, x, y);
}
H(x, y, z) {
return this.parity(x, y, z);
}
I(x, y, z) {
return y ^ (x | ~z);
}
};
// src/util/hash/SHA1.ts
var SHA1 = class extends BaseHashAlgorithm {
padMessage(message) {
const msgLenMod64 = message.length % 64;
let bytesToAdd = 64 - msgLenMod64;
if (msgLenMod64 >= 56) {
bytesToAdd += 64;
}
const padding = new Uint8Array(bytesToAdd);
const paddedMsg = new Uint8Array([...message, ...padding]);
const dataView = new DataView(paddedMsg.buffer);
dataView.setUint8(message.length, 128);
dataView.setBigUint64(paddedMsg.length - 8, BigInt(message.length * 8));
return paddedMsg.buffer;
}
computeHash(paddedMessage) {
const b1 = new Uint32Array(5);
const b2 = new Uint32Array([1732584193, 4023233417, 2562383102, 271733878, 3285377520]);
const seq = new Uint32Array(80);
const dataView = new DataView(paddedMessage);
for (let i = 0; i < paddedMessage.byteLength / 4; i += 16) {
for (let t = 0; t < 16; t++) {
seq[t] = dataView.getUint32(i + t * 4);
}
for (let t = 16; t < 80; t++) {
seq[t] = this.rotl(1, seq[t - 3] ^ seq[t - 8] ^ seq[t - 14] ^ seq[t - 16]);
}
b1[0] = b2[0];
b1[1] = b2[1];
b1[2] = b2[2];
b1[3] = b2[3];
b1[4] = b2[4];
for (let t = 0; t < 80; t++) {
const temp = this.rotl(5, b1[0]) + this.lf(t, b1[1], b1[2], b1[3]) + b1[4] + seq[t] + this.cw(t);
b1[4] = b1[3];
b1[3] = b1[2];
b1[2] = this.rotl(30, b1[1]);
b1[1] = b1[0];
b1[0] = temp;
}
b2[0] += b1[0];
b2[1] += b1[1];
b2[2] += b1[2];
b2[3] += b1[3];
b2[4] += b1[4];
}
return b2.buffer;
}
hashToString(hash) {
return [...new Uint32Array(hash)].map((w) => w.toString(16).padStart(8, "0")).join("");
}
// logical function
lf(t, x, y, z) {
if (t < 20) return this.ch(x, y, z);
else if (t < 40) return this.parity(x, y, z);
else if (t < 60) return this.maj(x, y, z);
else return this.parity(x, y, z);
}
// constant words
cw(t) {
if (t < 20) return 1518500249;
else if (t < 40) return 1859775393;
else if (t < 60) return 2400959708;
else return 3395469782;
}
};
// src/util/hash/SHA256.ts
var SHA256 = class _SHA256 extends BaseHashAlgorithm {
// SHA-256 constants
static k = new Uint32Array([
1116352408,
1899447441,
3049323471,
3921009573,
961987163,
1508970993,
2453635748,
2870763221,
3624381080,
310598401,
607225278,
1426881987,
1925078388,
2162078206,
2614888103,
3248222580,
3835390401,
4022224774,
264347078,
604807628,
770255983,
1249150122,
1555081692,
1996064986,
2554220882,
2821834349,
2952996808,
3210313671,
3336571891,
3584528711,
113926993,
338241895,
666307205,
773529912,
1294757372,
1396182291,
1695183700,
1986661051,
2177026350,
2456956037,
2730485921,
2820302411,
3259730800,
3345764771,
3516065817,
3600352804,
4094571909,
275423344,
430227734,
506948616,
659060556,
883997877,
958139571,
1322822218,
1537002063,
1747873779,
1955562222,
2024104815,
2227730452,
2361852424,
2428436474,
2756734187,
3204031479,
3329325298
]);
padMessage(message) {
const msgLenMod64 = message.length % 64;
let bytesToAdd = 64 - msgLenMod64;
if (msgLenMod64 >= 56) {
bytesToAdd += 64;
}
const padding = new Uint8Array(bytesToAdd);
const paddedMsg = new Uint8Array([...message, ...padding]);
const dataView = new DataView(paddedMsg.buffer);
dataView.setUint8(message.length, 128);
dataView.setBigUint64(paddedMsg.length - 8, BigInt(message.length * 8));
return paddedMsg.buffer;
}
computeHash(paddedMessage) {
const b1 = new Uint32Array(8);
const b2 = new Uint32Array([
1779033703,
3144134277,
1013904242,
2773480762,
1359893119,
2600822924,
528734635,
1541459225
]);
const seq = new Uint32Array(64);
const dataView = new DataView(paddedMessage);
for (let i = 0; i < paddedMessage.byteLength / 4; i += 16) {
for (let t = 0; t < 16; t++) {
seq[t] = dataView.getUint32(i + t * 4);
}
for (let t = 16; t < 64; t++) {
seq[t] = this.smallSigma1(seq[t - 2]) + seq[t - 7] + this.smallSigma0(seq[t - 15]) + seq[t - 16];
}
b1[0] = b2[0];
b1[1] = b2[1];
b1[2] = b2[2];
b1[3] = b2[3];
b1[4] = b2[4];
b1[5] = b2[5];
b1[6] = b2[6];
b1[7] = b2[7];
for (let t = 0; t < 64; t++) {
const temp1 = b1[7] + this.bigSigma1(b1[4]) + this.ch(b1[4], b1[5], b1[6]) + _SHA256.k[t] + seq[t];
const temp2 = this.bigSigma0(b1[0]) + this.maj(b1[0], b1[1], b1[2]);
b1[7] = b1[6];
b1[6] = b1[5];
b1[5] = b1[4];
b1[4] = b1[3] + temp1;
b1[3] = b1[2];
b1[2] = b1[1];
b1[1] = b1[0];
b1[0] = temp1 + temp2;
}
b2[0] += b1[0];
b2[1] += b1[1];
b2[2] += b1[2];
b2[3] += b1[3];
b2[4] += b1[4];
b2[5] += b1[5];
b2[6] += b1[6];
b2[7] += b1[7];
}
return b2.buffer;
}
hashToString(hash) {
return [...new Uint32Array(hash)].map((w) => w.toString(16).padStart(8, "0")).join("");
}
};
// src/util/hash/SHA384.ts
var SHA384 = class _SHA384 extends BaseHashAlgorithm {
// SHA-384 constants
static k = new BigUint64Array([
0x428a2f98d728ae22n,
0x7137449123ef65cdn,
0xb5c0fbcfec4d3b2fn,
0xe9b5dba58189dbbcn,
0x3956c25bf348b538n,
0x59f111f1b605d019n,
0x923f82a4af194f9bn,
0xab1c5ed5da6d8118n,
0xd807aa98a3030242n,
0x12835b0145706fben,
0x243185be4ee4b28cn,
0x550c7dc3d5ffb4e2n,
0x72be5d74f27b896fn,
0x80deb1fe3b1696b1n,
0x9bdc06a725c71235n,
0xc19bf174cf692694n,
0xe49b69c19ef14ad2n,
0xefbe4786384f25e3n,
0x0fc19dc68b8cd5b5n,
0x240ca1cc77ac9c65n,
0x2de92c6f592b0275n,
0x4a7484aa6ea6e483n,
0x5cb0a9dcbd41fbd4n,
0x76f988da831153b5n,
0x983e5152ee66dfabn,
0xa831c66d2db43210n,
0xb00327c898fb213fn,
0xbf597fc7beef0ee4n,
0xc6e00bf33da88fc2n,
0xd5a79147930aa725n,
0x06ca6351e003826fn,
0x142929670a0e6e70n,
0x27b70a8546d22ffcn,
0x2e1b21385c26c926n,
0x4d2c6dfc5ac42aedn,
0x53380d139d95b3dfn,
0x650a73548baf63den,
0x766a0abb3c77b2a8n,
0x81c2c92e47edaee6n,
0x92722c851482353bn,
0xa2bfe8a14cf10364n,
0xa81a664bbc423001n,
0xc24b8b70d0f89791n,
0xc76c51a30654be30n,
0xd192e819d6ef5218n,
0xd69906245565a910n,
0xf40e35855771202an,
0x106aa07032bbd1b8n,
0x19a4c116b8d2d0c8n,
0x1e376c085141ab53n,
0x2748774cdf8eeb99n,
0x34b0bcb5e19b48a8n,
0x391c0cb3c5c95a63n,
0x4ed8aa4ae3418acbn,
0x5b9cca4f7763e373n,
0x682e6ff3d6b2b8a3n,
0x748f82ee5defb2fcn,
0x78a5636f43172f60n,
0x84c87814a1f0ab72n,
0x8cc702081a6439ecn,
0x90befffa23631e28n,
0xa4506cebde82bde9n,
0xbef9a3f7b2c67915n,
0xc67178f2e372532bn,
0xca273eceea26619cn,
0xd186b8c721c0c207n,
0xeada7dd6cde0eb1en,
0xf57d4f7fee6ed178n,
0x06f067aa72176fban,
0x0a637dc5a2c898a6n,
0x113f9804bef90daen,
0x1b710b35131c471bn,
0x28db77f523047d84n,
0x32caab7b40c72493n,
0x3c9ebe0a15c9bebcn,
0x431d67c49c100d4cn,
0x4cc5d4becb3e42b6n,
0x597f299cfc657e2an,
0x5fcb6fab3ad6faecn,
0x6c44198c4a475817n
]);
padMessage(message) {
const msgLenMod128 = message.length % 128;
let bytesToAdd = 128 - msgLenMod128;
if (msgLenMod128 >= 112) {
bytesToAdd += 128;
}
const padding = new Uint8Array(bytesToAdd);
const paddedMsg = new Uint8Array([...message, ...padding]);
const dataView = new DataView(paddedMsg.buffer);
dataView.setUint8(message.length, 128);
dataView.setBigUint64(paddedMsg.length - 8, BigInt(message.length * 8));
return paddedMsg.buffer;
}
computeHash(paddedMessage) {
const b1 = new BigUint64Array(8);
const b2 = new BigUint64Array([
0xcbbb9d5dc1059ed8n,
0x629a292a367cd507n,
0x9159015a3070dd17n,
0x152fecd8f70e5939n,
0x67332667ffc00b31n,
0x8eb44a8768581511n,
0xdb0c2e0d64f98fa7n,
0x47b5481dbefa4fa4n
]);
const seq = new BigUint64Array(80);
const dataView = new DataView(paddedMessage);
for (let i = 0; i < paddedMessage.byteLength / 8; i += 16) {
for (let t = 0; t < 16; t++) {
seq[t] = dataView.getBigUint64(i + t * 8);
}
for (let t = 16; t < 80; t++) {
seq[t] = this.smallSigma1(seq[t - 2]) + seq[t - 7] + this.smallSigma0(seq[t - 15]) + seq[t - 16];
}
b1[0] = b2[0];
b1[1] = b2[1];
b1[2] = b2[2];
b1[3] = b2[3];
b1[4] = b2[4];
b1[5] = b2[5];
b1[6] = b2[6];
b1[7] = b2[7];
for (let t = 0; t < 80; t++) {
const temp1 = b1[7] + this.bigSigma1(b1[4]) + this.ch(b1[4], b1[5], b1[6]) + _SHA384.k[t] + seq[t];
const temp2 = this.bigSigma0(b1[0]) + this.maj(b1[0], b1[1], b1[2]);
b1[7] = b1[6];
b1[6] = b1[5];
b1[5] = b1[4];
b1[4] = b1[3] + temp1;
b1[3] = b1[2];
b1[2] = b1[1];
b1[1] = b1[0];
b1[0] = temp1 + temp2;
}
b2[0] += b1[0];
b2[1] += b1[1];
b2[2] += b1[2];
b2[3] += b1[3];
b2[4] += b1[4];
b2[5] += b1[5];
b2[6] += b1[6];
b2[7] += b1[7];
}
return b2.slice(0, 6).buffer;
}
hashToString(hash) {
return [...new BigUint64Array(hash)].map((w) => w.toString(16).padStart(16, "0")).join("");
}
};
// src/util/hash/SHA512.ts
var SHA512 = class _SHA512 extends BaseHashAlgorithm {
// SHA-512 constants
static k = new BigUint64Array([
0x428a2f98d728ae22n,
0x7137449123ef65cdn,
0xb5c0fbcfec4d3b2fn,
0xe9b5dba58189dbbcn,
0x3956c25bf348b538n,
0x59f111f1b605d019n,
0x923f82a4af194f9bn,
0xab1c5ed5da6d8118n,
0xd807aa98a3030242n,
0x12835b0145706fben,
0x243185be4ee4b28cn,
0x550c7dc3d5ffb4e2n,
0x72be5d74f27b896fn,
0x80deb1fe3b1696b1n,
0x9bdc06a725c71235n,
0xc19bf174cf692694n,
0xe49b69c19ef14ad2n,
0xefbe4786384f25e3n,
0x0fc19dc68b8cd5b5n,
0x240ca1cc77ac9c65n,
0x2de92c6f592b0275n,
0x4a7484aa6ea6e483n,
0x5cb0a9dcbd41fbd4n,
0x76f988da831153b5n,
0x983e5152ee66dfabn,
0xa831c66d2db43210n,
0xb00327c898fb213fn,
0xbf597fc7beef0ee4n,
0xc6e00bf33da88fc2n,
0xd5a79147930aa725n,
0x06ca6351e003826fn,
0x142929670a0e6e70n,
0x27b70a8546d22ffcn,
0x2e1b21385c26c926n,
0x4d2c6dfc5ac42aedn,
0x53380d139d95b3dfn,
0x650a73548baf63den,
0x766a0abb3c77b2a8n,
0x81c2c92e47edaee6n,
0x92722c851482353bn,
0xa2bfe8a14cf10364n,
0xa81a664bbc423001n,
0xc24b8b70d0f89791n,
0xc76c51a30654be30n,
0xd192e819d6ef5218n,
0xd69906245565a910n,
0xf40e35855771202an,
0x106aa07032bbd1b8n,
0x19a4c116b8d2d0c8n,
0x1e376c085141ab53n,
0x2748774cdf8eeb99n,
0x34b0bcb5e19b48a8n,
0x391c0cb3c5c95a63n,
0x4ed8aa4ae3418acbn,
0x5b9cca4f7763e373n,
0x682e6ff3d6b2b8a3n,
0x748f82ee5defb2fcn,
0x78a5636f43172f60n,
0x84c87814a1f0ab72n,
0x8cc702081a6439ecn,
0x90befffa23631e28n,
0xa4506cebde82bde9n,
0xbef9a3f7b2c67915n,
0xc67178f2e372532bn,
0xca273eceea26619cn,
0xd186b8c721c0c207n,
0xeada7dd6cde0eb1en,
0xf57d4f7fee6ed178n,
0x06f067aa72176fban,
0x0a637dc5a2c898a6n,
0x113f9804bef90daen,
0x1b710b35131c471bn,
0x28db77f523047d84n,
0x32caab7b40c72493n,
0x3c9ebe0a15c9bebcn,
0x431d67c49c100d4cn,
0x4cc5d4becb3e42b6n,
0x597f299cfc657e2an,
0x5fcb6fab3ad6faecn,
0x6c44198c4a475817n
]);
padMessage(message) {
const msgLenMod128 = message.length % 128;
let bytesToAdd = 128 - msgLenMod128;
if (msgLenMod128 >= 112) {
bytesToAdd += 128;
}
const padding = new Uint8Array(bytesToAdd);
const paddedMsg = new Uint8Array([...message, ...padding]);
const dataView = new DataView(paddedMsg.buffer);
dataView.setUint8(message.length, 128);
dataView.setBigUint64(paddedMsg.length - 8, BigInt(message.length * 8));
return paddedMsg.buffer;
}
computeHash(paddedMessage) {
const b1 = new BigUint64Array(8);
const b2 = new BigUint64Array([
0x6a09e667f3bcc908n,
0xbb67ae8584caa73bn,
0x3c6ef372fe94f82bn,
0xa54ff53a5f1d36f1n,
0x510e527fade682d1n,
0x9b05688c2b3e6c1fn,
0x1f83d9abfb41bd6bn,
0x5be0cd19137e2179n
]);
const seq = new BigUint64Array(80);
const dataView = new DataView(paddedMessage);
for (let i = 0; i < paddedMessage.byteLength / 8; i += 16) {
for (let t = 0; t < 16; t++) {
seq[t] = dataView.getBigUint64(i + t * 8);
}
for (let t = 16; t < 80; t++) {
seq[t] = this.smallSigma1(seq[t - 2]) + seq[t - 7] + this.smallSigma0(seq[t - 15]) + seq[t - 16];
}
b1[0] = b2[0];
b1[1] = b2[1];
b1[2] = b2[2];
b1[3] = b2[3];
b1[4] = b2[4];
b1[5] = b2[5];
b1[6] = b2[6];
b1[7] = b2[7];
for (let t = 0; t < 80; t++) {
const temp1 = b1[7] + this.bigSigma1(b1[4]) + this.ch(b1[4], b1[5], b1[6]) + _SHA512.k[t] + seq[t];
const temp2 = this.bigSigma0(b1[0]) + this.maj(b1[0], b1[1], b1[2]);
b1[7] = b1[6];
b1[6] = b1[5];
b1[5] = b1[4];
b1[4] = b1[3] + temp1;
b1[3] = b1[2];
b1[2] = b1[1];
b1[1] = b1[0];
b1[0] = temp1 + temp2;
}
b2[0] += b1[0];
b2[1] += b1[1];
b2[2] += b1[2];
b2[3] += b1[3];
b2[4] += b1[4];
b2[5] += b1[5];
b2[6] += b1[6];
b2[7] += b1[7];
}
return b2.buffer;
}
hashToString(hash) {
return [...new BigUint64Array(hash)].map((w) => w.toString(16).padStart(16, "0")).join("");
}
};
// src/util/hash.ts
var md5 = new MD5();
var sha1 = new SHA1();
var sha256 = new SHA256();
var sha384 = new SHA384();
var sha512 = new SHA512();
// src/stateMachine/intrinsicFunctions/StatesHash.ts
var StatesHash = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.Hash",
exactArgs: 2,
arguments: [
{
allowedTypes: ["string"]
},
{
allowedTypes: ["string"]
}
]
};
}
execute(str, algorithm) {
if (str.length > 1e4) {
throw new StatesRuntimeError(
`Intrinsic function ${this.funcDefinition.name} cannot hash a string with more than 10,000 characters`
);
}
const algorithms = ["MD5", "SHA-1", "SHA-256", "SHA-384", "SHA-512"];
const supportedAlgorithms = algorithms.join(", ");
if (!algorithms.includes(algorithm)) {
throw new StatesRuntimeError(
`Unsupported hash algorithm '${algorithm}' provided to intrinsic function ${this.funcDefinition.name}. The supported algorithms are: ${supportedAlgorithms}`
);
}
switch (algorithm) {
case "MD5":
return md5.getDigest(str);
case "SHA-1":
return sha1.getDigest(str);
case "SHA-256":
return sha256.getDigest(str);
case "SHA-384":
return sha384.getDigest(str);
case "SHA-512":
return sha512.getDigest(str);
}
}
};
// src/stateMachine/intrinsicFunctions/StatesJsonMerge.ts
var StatesJsonMerge = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.JsonMerge",
exactArgs: 3,
arguments: [
{
allowedTypes: ["object"]
},
{
allowedTypes: ["object"]
},
{
allowedTypes: ["boolean"]
}
]
};
}
execute(obj1, obj2, isDeepMerge) {
if (isDeepMerge) {
throw new StatesRuntimeError(
`Deep merge option is not supported in ${this.funcDefinition.name}. Third argument must be set to false instead of true`
);
}
return Object.assign(obj1, obj2);
}
};
// src/stateMachine/intrinsicFunctions/StatesMathRandom.ts
var StatesMathRandom = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.MathRandom",
minArgs: 2,
arguments: [
{
allowedTypes: ["number"],
constraints: ["INTEGER"]
},
{
allowedTypes: ["number"],
constraints: ["INTEGER"]
},
{
allowedTypes: ["number"]
}
]
};
}
execute(min, max, seed) {
const [s1, s2, s3, s4] = cyrb128((seed ?? Date.now()).toString());
const rng = sfc32(s1, s2, s3, s4);
return getRandomNumber(min, max, rng);
}
};
// src/stateMachine/intrinsicFunctions/StatesMathAdd.ts
var StatesMathAdd = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.MathAdd",
exactArgs: 2,
arguments: [
{
allowedTypes: ["number"]
},
{
allowedTypes: ["number"]
}
]
};
}
execute(num1, num2) {
return num1 + num2;
}
};
// src/stateMachine/intrinsicFunctions/StatesStringSplit.ts
var StatesStringSplit = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.StringSplit",
exactArgs: 2,
arguments: [
{
allowedTypes: ["string"]
},
{
allowedTypes: ["string"]
}
]
};
}
execute(str, separator) {
return str.split(separator);
}
};
// src/stateMachine/intrinsicFunctions/StatesUUID.ts
var StatesUUID = class extends BaseIntrinsicFunction {
funcDefinition;
constructor() {
super();
this.funcDefinition = {
name: "States.UUID"
};
}
execute() {
const octets = new Uint8Array(16);
for (let i = 0; i < octets.length; i++) {
octets[i] = getRandomNumber(0, 255);
}
octets[6] = octets[6] & 127;
octets[6] = octets[6] | 64;
octets[6] = octets[6] & 223;
octets[6] = octets[6] & 239;
octets[8] = octets[8] | 128;
octets[8] = octets[8] & 191;
const b0 = byteToHex(octets[0]);
const b1 = byteToHex(octets[1]);
const b2 = byteToHex(octets[2]);
const b3 = byteToHex(octets[3]);
const b4 = byteToHex(octets[4]);
const b5 = byteToHex(octets[5]);
const b6 = byteToHex(octets[6]);
const b7 = byteToHex(octets[7]);
const b8 = byteToHex(octets[8]);
const b9 = byteToHex(octets[9]);
const b10 = byteToHex(octets[10]);
const b11 = byteToHex(octets[11]);
const b12 = byteToHex(octets[12]);
const b13 = byteToHex(octets[13]);
const b14 = byteToHex(octets[14]);
const b15 = byteToHex(octets[15]);
return `${b0}${b1}${b2}${b3}-${b4}${b5}-${b6}${b7}-${b8}${b9}-${b10}${b11}${b12}${b13}${b14}${b15}`;
}
};
// src/stateMachine/IntrinsicFunctionEvaluation.ts
var functions = {
"States.Format": new StatesFormat(),
"States.StringToJson": new StatesStringToJson(),
"States.JsonToString": new StatesJsonToString(),
"States.Array": new StatesArray(),
"States.ArrayPartition": new StatesArrayPartition(),
"States.ArrayContains": new StatesArrayContains(),
"States.ArrayRange": new StatesArrayRange(),
"States.ArrayGetItem": new StatesArrayGetItem(),
"States.ArrayLength": new StatesArrayLength(),
"States.ArrayUnique": new StatesArrayUnique(),
"States.Base64Encode": new StatesBase64Encode(),
"States.Base64Decode": new StatesBase64Decode(),
"States.Hash": new StatesHash(),
"States.JsonMerge": new StatesJsonMerge(),
"States.MathRandom": new StatesMathRandom(),
"States.MathAdd": new StatesMathAdd(),
"States.StringSplit": new StatesStringSplit(),
"States.UUID": new StatesUUID()
};
function evaluateIntrinsicFunction(intrinsicFunction, input, context) {
const openingParensIdx = intrinsicFunction.indexOf("(");
const funcName = intrinsicFunction.slice(0, openingParensIdx);
const funcArgs = intrinsicFunction.slice(openingParensIdx + 1, intrinsicFunction.length - 1);
const splitArgs = [];
let partialArg = "";
let parensCount = 0;
let apostropheCount = 0;
for (let i = 0; i < funcArgs.length; i++) {
const char = funcArgs[i];
if (char === "(") {
parensCount++;
} else if (char === ")") {
parensCount--;
}
if (char === "'" && partialArg[partialArg.length - 1] !== "\\") {
if (apostropheCount === 1) {
apostropheCount--;
} else {
apostropheCount++;
}
}
if (char === "," && parensCount === 0 && apostropheCount === 0 || i === funcArgs.length - 1) {
if (i === funcArgs.length - 1) partialArg += char;
partialArg = partialArg.trim();
if (partialArg.startsWith("States")) {
const evaluatedNestedFunction = evaluateIntrinsicFunction(partialArg, input, context);
splitArgs.push(JSON.stringify(evaluatedNestedFunction));
} else {
splitArgs.push(partialArg);
}
partialArg = "";
} else {
partialArg += char;
}
}
return functions[funcName].call(input, context, ...splitArgs);
}
// src/stateMachine/InputOutputProcessing.ts
var import_cloneDeep = __toESM(require("lodash/cloneDeep.js"), 1);
var import_set = __toESM(require("lodash/set.js"), 1);
function processInputPath(path, input, context) {
if (path === void 0) {
return input;
}
if (path === null) {
return {};
}
return jsonPathQuery(path, input, context);
}
function processPayloadTemplate(payloadTemplate, json, context) {
if (typeof payloadTemplate !== "object" || payloadTemplate === null) {
return payloadTemplate;
}
if (Array.isArray(payloadTemplate)) {
return payloadTemplate.map((value) => processPayloadTemplate(value, json, context));
}
const resolvedProperties = Object.entries(payloadTemplate).map(([key, value]) => {
let sanitizedKey = key;
let resolvedValue = value;
if (Array.isArray(value)) {
resolvedValue = value.map((innerValue) => processPayloadTemplate(innerValue, json, context));
}
if (isPlainObj(value)) {
resolvedValue = processPayloadTemplate(value, json, context);
}
if (key.endsWith(".$") && typeof value === "string") {
sanitizedKey = key.replace(".$", "");
if (value.startsWith("$")) {
resolvedValue = jsonPathQuery(value, json, context);
} else {
resolvedValue = evaluateIntrinsicFunction(value, json, context);
}
}
return [sanitizedKey, resolvedValue];
});
return Object.fromEntries(resolvedProperties);
}
function processResultPath(path, rawInput, result) {
if (path === void 0) {
return result;
}
if (path === null) {
return rawInput;
}
const sanitizedPath = path.replace("$.", "");
if (isPlainObj(rawInput)) {
const clonedRawInput = (0, import_cloneDeep.default)(rawInput);
return (0, import_set.default)(clonedRawInput, sanitizedPath, result);
}
throw new StatesResultPathMatchFailureError();
}
function processOutputPath(path, result, context) {
if (path === void 0) {
return result;
}
if (path === null) {
return {};
}
return jsonPathQuery(path, result, context);
}
// src/stateMachine/stateActions/BaseStateAction.ts
var BaseStateAction = class {
stateDefinition;
stateName;
constructor(stateDefinition, stateName) {
this.stateDefinition = stateDefinition;
this.stateName = stateName;
}
buildExecutionResult(stateResult) {
const executionResult = { stateResult, nextState: "", isEndState: false };
if ("Next" in this.stateDefinition) {
executionResult.nextState = this.stateDefinition.Next;
}
if ("End" in this.stateDefinition) {
executionResult.isEndState = this.stateDefinition.End;
}
return executionResult;
}
};
// src/error/predefined/StatesNoChoiceMatchedError.ts
var StatesNoChoiceMatchedError = class extends RuntimeError {
constructor() {
super("States.NoChoiceMatched");
this.name = "States.NoChoiceMatched";
}
};
// src/stateMachine/jsonPath/constraints/StringConstraint.ts
var StringConstraint = class extends BaseJSONPathConstraint {
test(value) {
if (typeof value !== "string") {
throw new StatesRuntimeError(
`Path expression '${this.pathExpression}' evaluated to ${stringifyJSONValue(value)}, but expected a string`
);
}
}
};
// src/stateMachine/jsonPath/constraints/NumberConstraint.ts
var NumberConstraint = class extends BaseJSONPathConstraint {
test(value) {
if (typeof value !== "number") {
throw new StatesRuntimeError(
`Path expression '${this.pathExpression}' evaluated to ${stringifyJSONValue(value)}, but expected a number`
);
}
}
};
// src/stateMachine/jsonPath/constraints/BooleanConstraint.ts
var BooleanConstraint = class extends BaseJSONPathConstraint {
test(value) {
if (typeof value !== "boolean") {
throw new StatesRuntimeError(
`Path expression '${this.pathExpression}' evaluated to ${stringifyJSONValue(value)}, but expected a boolean`
);
}
}
};
// src/stateMachine/jsonPath/constraints/RFC3339TimestampConstraint.ts
var RFC3339TimestampConstraint = class extends BaseJSONPathConstraint {
test(value) {
if (typeof value !== "string" || !isRFC3339Timestamp(value)) {
throw new StatesRuntimeError(
`Path expression '${this.pathExpression}' evaluated to ${stringifyJSONValue(
value
)}, but expected a timestamp conforming to the RFC3339 profile`
);
}
}
};
// src/stateMachine/stateActions/ChoiceStateAction.ts
var import_wildcard_match = __toESM(require("wildcard-match"), 1);
var ChoiceStateAction = class extends BaseStateAction {
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
}
testChoiceRule(choiceRule, input, context) {
if ("And" in choiceRule) {
return choiceRule.And.every((rule) => this.testChoiceRule(rule, input, context));
}
if ("Or" in choiceRule) {
return choiceRule.Or.some((rule) => this.testChoiceRule(rule, input, context));
}
if ("Not" in choiceRule) {
return !this.testChoiceRule(choiceRule.Not, input, context);
}
if ("StringEquals" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue === choiceRule.StringEquals;
}
if ("StringEqualsPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const stringValue = jsonPathQuery(choiceRule.StringEqualsPath, input, context, {
constraints: [StringConstraint]
});
return varValue === stringValue;
}
if ("StringLessThan" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue < choiceRule.StringLessThan;
}
if ("StringLessThanPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const stringValue = jsonPathQuery(choiceRule.StringLessThanPath, input, context, {
constraints: [StringConstraint]
});
return varValue < stringValue;
}
if ("StringGreaterThan" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue > choiceRule.StringGreaterThan;
}
if ("StringGreaterThanPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const stringValue = jsonPathQuery(choiceRule.StringGreaterThanPath, input, context, {
constraints: [StringConstraint]
});
return varValue > stringValue;
}
if ("StringLessThanEquals" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue <= choiceRule.StringLessThanEquals;
}
if ("StringLessThanEqualsPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const stringValue = jsonPathQuery(choiceRule.StringLessThanEqualsPath, input, context, {
constraints: [StringConstraint]
});
return varValue <= stringValue;
}
if ("StringGreaterThanEquals" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue >= choiceRule.StringGreaterThanEquals;
}
if ("StringGreaterThanEqualsPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const stringValue = jsonPathQuery(choiceRule.StringGreaterThanEqualsPath, input, context, {
constraints: [StringConstraint]
});
return varValue >= stringValue;
}
if ("StringMatches" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const isMatch = (0, import_wildcard_match.default)(choiceRule.StringMatches, { separator: false });
return isMatch(varValue);
}
if ("NumericEquals" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue === choiceRule.NumericEquals;
}
if ("NumericEqualsPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const numberValue = jsonPathQuery(choiceRule.NumericEqualsPath, input, context, {
constraints: [NumberConstraint]
});
return varValue === numberValue;
}
if ("NumericLessThan" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue < choiceRule.NumericLessThan;
}
if ("NumericLessThanPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const numberValue = jsonPathQuery(choiceRule.NumericLessThanPath, input, context, {
constraints: [NumberConstraint]
});
return varValue < numberValue;
}
if ("NumericGreaterThan" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue > choiceRule.NumericGreaterThan;
}
if ("NumericGreaterThanPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const numberValue = jsonPathQuery(choiceRule.NumericGreaterThanPath, input, context, {
constraints: [NumberConstraint]
});
return varValue > numberValue;
}
if ("NumericLessThanEquals" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue <= choiceRule.NumericLessThanEquals;
}
if ("NumericLessThanEqualsPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const numberValue = jsonPathQuery(choiceRule.NumericLessThanEqualsPath, input, context, {
constraints: [NumberConstraint]
});
return varValue <= numberValue;
}
if ("NumericGreaterThanEquals" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue >= choiceRule.NumericGreaterThanEquals;
}
if ("NumericGreaterThanEqualsPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const numberValue = jsonPathQuery(choiceRule.NumericGreaterThanEqualsPath, input, context, {
constraints: [NumberConstraint]
});
return varValue >= numberValue;
}
if ("BooleanEquals" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
return varValue === choiceRule.BooleanEquals;
}
if ("BooleanEqualsPath" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const booleanValue = jsonPathQuery(choiceRule.BooleanEqualsPath, input, context, {
constraints: [BooleanConstraint]
});
return varValue === booleanValue;
}
if ("TimestampEquals" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(choiceRule.TimestampEquals);
return varValue.getTime() === timestampValue.getTime();
}
if ("TimestampEqualsPath" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(
jsonPathQuery(choiceRule.TimestampEqualsPath, input, context, {
constraints: [RFC3339TimestampConstraint]
})
);
return varValue.getTime() === timestampValue.getTime();
}
if ("TimestampLessThan" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(choiceRule.TimestampLessThan);
return varValue < timestampValue;
}
if ("TimestampLessThanPath" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(
jsonPathQuery(choiceRule.TimestampLessThanPath, input, context, {
constraints: [RFC3339TimestampConstraint]
})
);
return varValue < timestampValue;
}
if ("TimestampGreaterThan" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(choiceRule.TimestampGreaterThan);
return varValue > timestampValue;
}
if ("TimestampGreaterThanPath" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(
jsonPathQuery(choiceRule.TimestampGreaterThanPath, input, context, {
constraints: [RFC3339TimestampConstraint]
})
);
return varValue > timestampValue;
}
if ("TimestampLessThanEquals" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(choiceRule.TimestampLessThanEquals);
return varValue <= timestampValue;
}
if ("TimestampLessThanEqualsPath" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(
jsonPathQuery(choiceRule.TimestampLessThanEqualsPath, input, context, {
constraints: [RFC3339TimestampConstraint]
})
);
return varValue <= timestampValue;
}
if ("TimestampGreaterThanEquals" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(choiceRule.TimestampGreaterThanEquals);
return varValue >= timestampValue;
}
if ("TimestampGreaterThanEqualsPath" in choiceRule) {
const varValue = new Date(jsonPathQuery(choiceRule.Variable, input, context));
const timestampValue = new Date(
jsonPathQuery(choiceRule.TimestampGreaterThanEqualsPath, input, context, {
constraints: [RFC3339TimestampConstraint]
})
);
return varValue >= timestampValue;
}
if ("IsNull" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const isNullTrue = choiceRule.IsNull;
return isNullTrue && varValue === null;
}
if ("IsPresent" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context, { ignoreDefinedValueConstraint: true });
const IsPresentTrue = choiceRule.IsPresent;
return IsPresentTrue && varValue !== void 0;
}
if ("IsNumeric" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const IsNumericTrue = choiceRule.IsNumeric;
return IsNumericTrue && typeof varValue === "number";
}
if ("IsString" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const IsStringTrue = choiceRule.IsString;
return IsStringTrue && typeof varValue === "string";
}
if ("IsBoolean" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const IsBooleanTrue = choiceRule.IsBoolean;
return IsBooleanTrue && typeof varValue === "boolean";
}
if ("IsTimestamp" in choiceRule) {
const varValue = jsonPathQuery(choiceRule.Variable, input, context);
const IsTimestampTrue = choiceRule.IsTimestamp;
return IsTimestampTrue && isRFC3339Timestamp(varValue);
}
return false;
}
async execute(input, context, options) {
const state = this.stateDefinition;
for (const choice of state.Choices) {
const choiceIsMatch = this.testChoiceRule(choice, input, context);
if (choiceIsMatch) {
return { stateResult: input, nextState: choice.Next, isEndState: false };
}
}
if (state.Default) {
return { stateResult: input, nextState: state.Default, isEndState: false };
}
throw new StatesNoChoiceMatchedError();
}
};
// src/error/FailStateError.ts
var FailStateError = class extends RuntimeError {
constructor(name = "FailStateError", message = "Execution failed because of a Fail state") {
super(message);
this.name = name;
}
};
// src/stateMachine/stateActions/FailStateAction.ts
var FailStateAction = class extends BaseStateAction {
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
}
async execute(input, context, options) {
const state = this.stateDefinition;
let error = state.Error;
let cause = state.Cause;
if (state.ErrorPath) {
error = jsonPathQuery(state.ErrorPath, input, context, {
constraints: [StringConstraint]
});
}
if (state.CausePath) {
cause = jsonPathQuery(state.CausePath, input, context, {
constraints: [StringConstraint]
});
}
throw new FailStateError(error, cause);
}
};
// src/stateMachine/jsonPath/constraints/ArrayConstraint.ts
var ArrayConstraint = class extends BaseJSONPathConstraint {
test(value) {
if (!Array.isArray(value)) {
throw new StatesRuntimeError(
`Path expression '${this.pathExpression}' evaluated to ${stringifyJSONValue(value)}, but expected an array`
);
}
}
};
// src/stateMachine/jsonPath/constraints/IntegerConstraint.ts
var IntegerConstraint = class extends BaseJSONPathConstraint {
test(value) {
if (!Number.isInteger(value)) {
throw new StatesRuntimeError(
`Path expression '${this.pathExpression}' evaluated to ${stringifyJSONValue(value)}, but expected an integer`
);
}
}
static greaterThanOrEqual(n) {
return class extends this {
test(value) {
super.test(value);
if (value < n) {
throw new StatesRuntimeError(
`Path expression '${this.pathExpression}' evaluated to ${stringifyJSONValue(
value
)}, but expected an integer >= ${n}`
);
}
}
};
}
};
// src/stateMachine/stateActions/MapStateAction.ts
var import_p_limit = __toESM(require("p-limit"), 1);
var DEFAULT_MAX_CONCURRENCY = 40;
var MapStateAction = class extends BaseStateAction {
executionAbortFuncs;
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
this.executionAbortFuncs = [];
}
async forwardEventsToRootEventLogger(eventLogger, executionEventLogs, index, parentStateRawInput) {
if (!eventLogger) return;
for await (const event of executionEventLogs) {
eventLogger.forwardNestedMapEvent(event, index, this.stateName, parentStateRawInput);
}
}
processItem(stateMachine, item, input, context, index, options) {
const state = this.stateDefinition;
let paramValue;
context["Map"] = {
Item: {
Index: index,
Value: item
}
};
if (state.Parameters || state.ItemSelector) {
const parameters = state.ItemSelector ?? state.Parameters;
paramValue = processPayloadTemplate(parameters, input, context);
}
const execution = stateMachine.run(paramValue ?? item, options.runOptions);
this.executionAbortFuncs.push(execution.abort);
this.forwardEventsToRootEventLogger(options.eventLogger, execution.eventLogs, index, options.rawInput);
return execution.result;
}
async execute(input, context, options) {
const state = this.stateDefinition;
let items = input;
if (state.ItemsPath) {
items = jsonPathQuery(state.ItemsPath, input, context, {
constraints: [ArrayConstraint]
});
}
if (!Array.isArray(items)) {
throw new StatesRuntimeError("Input of Map state must be an array or ItemsPath property must point to an array");
}
const iteratorDefinition = state.ItemProcessor ?? state.Iterator;
const iteratorStateMachine = new StateMachine(iteratorDefinition, {
...options.stateMachineOptions,
validationOptions: { noValidate: true }
});
let maxConcurrency = state.MaxConcurrency;
if (state.MaxConcurrencyPath) {
maxConcurrency = jsonPathQuery(state.MaxConcurrencyPath, input, context, {
constraints: [IntegerConstraint.greaterThanOrEqual(0)],
ignoreDefinedValueConstraint: true
});
}
const limit = (0, import_p_limit.default)(maxConcurrency || DEFAULT_MAX_CONCURRENCY);
const processedItemsPromise = items.map(
(item, i) => limit(() => this.processItem(iteratorStateMachine, item, input, context, i, options))
);
try {
const result = await Promise.all(processedItemsPromise);
return this.buildExecutionResult(result);
} catch (error) {
this.executionAbortFuncs.forEach((abort) => abort());
if (error instanceof ExecutionError) {
throw error.cause;
}
throw error;
} finally {
delete context["Map"];
}
}
};
// src/stateMachine/stateActions/ParallelStateAction.ts
var import_p_limit2 = __toESM(require("p-limit"), 1);
var DEFAULT_CONCURRENCY = 40;
var ParallelStateAction = class extends BaseStateAction {
executionAbortFuncs;
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
this.executionAbortFuncs = [];
}
async forwardEventsToRootEventLogger(eventLogger, executionEventLogs, parentStateRawInput) {
if (!eventLogger) return;
for await (const event of executionEventLogs) {
eventLogger.forwardNestedParallelEvent(event, this.stateName, parentStateRawInput);
}
}
processBranch(branch, input, context, options) {
const stateMachine = new StateMachine(branch, {
...options.stateMachineOptions,
validationOptions: { noValidate: true }
});
const execution = stateMachine.run(input, options.runOptions);
this.executionAbortFuncs.push(execution.abort);
this.forwardEventsToRootEventLogger(options.eventLogger, execution.eventLogs, options.rawInput);
return execution.result;
}
async execute(input, context, options) {
const state = this.stateDefinition;
const limit = (0, import_p_limit2.default)(DEFAULT_CONCURRENCY);
const processedBranchesPromise = state.Branches.map(
(branch) => limit(() => this.processBranch(branch, input, context, options))
);
try {
const result = await Promise.all(processedBranchesPromise);
return this.buildExecutionResult(result);
} catch (error) {
this.executionAbortFuncs.forEach((abort) => abort());
if (error instanceof ExecutionError) {
throw error.cause;
}
throw error;
}
}
};
// src/stateMachine/stateActions/PassStateAction.ts
var PassStateAction = class extends BaseStateAction {
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
}
async execute(input, context, options) {
if (this.stateDefinition.Result) {
return this.buildExecutionResult(this.stateDefinition.Result);
}
return this.buildExecutionResult(input);
}
};
// src/stateMachine/stateActions/SucceedStateAction.ts
var SucceedStateAction = class extends BaseStateAction {
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
}
async execute(input, context, options) {
return { stateResult: input, nextState: "", isEndState: true };
}
};
// src/error/predefined/StatesTimeoutError.ts
var StatesTimeoutError = class extends RuntimeError {
constructor() {
super("States.Timeout");
this.name = "States.Timeout";
}
};
// src/aws/LambdaClient.ts
var import_client_lambda = require("@aws-sdk/client-lambda");
var import_credential_providers = require("@aws-sdk/credential-providers");
// src/error/LambdaInvocationError.ts
var LambdaInvocationError = class extends RuntimeError {
constructor(name, message, cause) {
super(message, cause);
this.name = name;
}
};
// src/aws/LambdaClient.ts
var LambdaClient = class {
client;
constructor(config) {
this.client = new import_client_lambda.LambdaClient({});
if (config) {
if (!config.region) {
throw new StatesRuntimeError(
"'awsConfig' option was specified in state machine constructor, but 'region' property is not set."
);
}
if (!config.credentials) {
throw new StatesRuntimeError(
"'awsConfig' option was specified in state machine constructor, but 'credentials' property is not set."
);
}
if (config.credentials) {
const credentialsTypes = Object.keys(config.credentials);
const credentialsNames = credentialsTypes.map((name) => `'${name}'`).join(", ");
if (credentialsTypes.length > 1) {
throw new StatesRuntimeError(
`More than one type of AWS credentials were specified: ${credentialsNames}. Only one type may be specified`
);
}
}
if (config.credentials?.cognitoIdentityPool) {
this.client = new import_client_lambda.LambdaClient({
region: config.region,
credentials: (0, import_credential_providers.fromCognitoIdentityPool)({
...config.credentials.cognitoIdentityPool,
clientConfig: { region: config.region }
})
});
} else if (config.credentials?.accessKeys) {
this.client = new import_client_lambda.LambdaClient({ region: config.region, credentials: config.credentials.accessKeys });
}
} else {
if (isBrowserEnvironment) {
throw new StatesRuntimeError(
"aws-local-stepfunctions is running in a browser environment and your state machine definition contains a state of type 'Task'. In order to invoke the Lambda function, you must provide an AWS region and credentials in the state machine constructor by passing the 'awsConfig' option."
);
}
}
}
async invokeFunction(funcNameOrArn, payload) {
const payloadBuffer = new TextEncoder().encode(JSON.stringify(payload));
const invokeCommand = new import_client_lambda.InvokeCommand({
FunctionName: funcNameOrArn,
Payload: payloadBuffer
});
const invocationResult = await this.client.send(invokeCommand);
let resultValue = null;
if (invocationResult.Payload) {
resultValue = new TextDecoder().decode(invocationResult.Payload);
resultValue = JSON.parse(resultValue);
}
if (invocationResult.FunctionError) {
const errorResult = resultValue;
throw new LambdaInvocationError(
errorResult.errorType,
`${errorResult.errorType}: ${errorResult.errorMessage}`,
errorResult
);
}
return resultValue;
}
};
// src/stateMachine/stateActions/TaskStateAction.ts
var TaskStateAction = class extends BaseStateAction {
timeoutAbortController;
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
this.timeoutAbortController = new AbortController();
}
createTimeoutPromise(input, context) {
const state = this.stateDefinition;
if (!state.TimeoutSeconds && !state.TimeoutSecondsPath) return;
let timeout;
if (state.TimeoutSeconds) {
timeout = state.TimeoutSeconds;
} else if (state.TimeoutSecondsPath) {
timeout = jsonPathQuery(state.TimeoutSecondsPath, input, context, {
constraints: [IntegerConstraint.greaterThanOrEqual(1)]
});
}
return new Promise((_, reject) => {
const handleTimeoutAbort = () => clearTimeout(timeoutId);
const timeoutId = setTimeout(() => {
this.timeoutAbortController.signal.removeEventListener("abort", handleTimeoutAbort);
reject(new StatesTimeoutError());
}, timeout * 1e3);
this.timeoutAbortController.signal.addEventListener("abort", handleTimeoutAbort, { once: true });
});
}
async execute(input, context, options) {
const state = this.stateDefinition;
const racingPromises = [];
const timeoutPromise = this.createTimeoutPromise(input, context);
if (options.overrideFn) {
const resultPromise = options.overrideFn(input);
racingPromises.push(resultPromise);
} else {
const lambdaClient = new LambdaClient(options.awsConfig);
const resultPromise = lambdaClient.invokeFunction(state.Resource, input);
racingPromises.push(resultPromise);
}
if (timeoutPromise) {
racingPromises.push(timeoutPromise);
}
const result = await Promise.race(racingPromises);
this.timeoutAbortController.abort();
return this.buildExecutionResult(result);
}
};
// src/stateMachine/stateActions/WaitStateAction.ts
var WaitStateAction = class extends BaseStateAction {
constructor(stateDefinition, stateName) {
super(stateDefinition, stateName);
}
async execute(input, context, options) {
const state = this.stateDefinition;
if (options.waitTimeOverrideOption !== void 0) {
await sleep(options.waitTimeOverrideOption, options.abortSignal);
return this.buildExecutionResult(input);
}
if (state.Seconds) {
await sleep(state.Seconds * 1e3, options.abortSignal);
} else if (state.Timestamp) {
const dateTimestamp = new Date(state.Timestamp);
const currentTime = Date.now();
const timeDiff = dateTimestamp.getTime() - currentTime;
await sleep(timeDiff, options.abortSignal);
} else if (state.SecondsPath) {
const seconds = jsonPathQuery(state.SecondsPath, input, context, {
constraints: [IntegerConstraint.greaterThanOrEqual(0)]
});
await sleep(seconds * 1e3, options.abortSignal);
} else if (state.TimestampPath) {
const timestamp = jsonPathQuery(state.TimestampPath, input, context, {
constraints: [RFC3339TimestampConstraint]
});
const dateTimestamp = new Date(timestamp);
const currentTime = Date.now();
const timeDiff = dateTimestamp.getTime() - currentTime;
await sleep(timeDiff, options.abortSignal);
}
return this.buildExecutionResult(input);
}
};
// src/stateMachine/StateExecutor.ts
var import_cloneDeep2 = __toESM(require("lodash/cloneDeep.js"), 1);
var DEFAULT_MAX_ATTEMPTS = 3;
var DEFAULT_INTERVAL_SECONDS = 1;
var DEFAULT_BACKOFF_RATE = 2;
var DEFAULT_JITTER_STRATEGY = "NONE";
var WILDCARD_ERROR = "States.ALL";
var TASK_STATE_WILDCARD_ERROR = "States.TaskFailed";
var StateExecutor = class {
/**
* The name of the state.
*/
stateName;
/**
* The Amazon States Language definition of the state.
*/
stateDefinition;
/**
* An array that stores the number of times each retrier in a Retryable state has been retried.
*/
retrierAttempts;
/**
* A map of functions to execute each type of state.
*/
stateHandlers;
constructor(stateName, stateDefinition) {
this.stateName = stateName;
this.stateDefinition = stateDefinition;
this.retrierAttempts = "Retry" in this.stateDefinition ? new Array(this.stateDefinition.Retry.length).fill(0) : [];
this.stateHandlers = {
Task: this.executeTaskState,
Parallel: this.executeParallelState,
Map: this.executeMapState,
Pass: this.executePassState,
Wait: this.executeWaitState,
Choice: this.executeChoiceState,
Succeed: this.executeSucceedState,
Fail: this.executeFailState
};
}
/**
* Execute the current state.
*/
async execute(input, context, options) {
const rawInput = (0, import_cloneDeep2.default)(input);
try {
const processedInput = this.processInput(input, context);
const {
stateResult: currResult,
nextState,
isEndState
} = await this.stateHandlers[this.stateDefinition.Type](
// @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,
context,
this.stateName,
options
);
const processedResult = this.processResult(currResult, rawInput, context);
return { stateResult: processedResult, nextState, isEndState };
} catch (error) {
options.eventLogger.dispatchStateFailedEvent(
this.stateName,
this.stateDefinition.Type,
input,
error
);
const { shouldRetry, waitTimeBeforeRetry, retrierIndex } = this.shouldRetry(
error,
options.runOptions?.overrides?.retryIntervalOverrides
);
if (shouldRetry) {
const stateDefinition = this.stateDefinition;
await sleep(waitTimeBeforeRetry, options.abortSignal);
options.eventLogger.dispatchStateRetriedEvent(
this.stateName,
stateDefinition.Type,
input,
stateDefinition.Retry[retrierIndex],
this.retrierAttempts[retrierIndex]
);
return this.execute(input, context, options);
}
const { nextState, errorOutput, resultPath, catcherIndex } = this.catchError(error);
if (nextState && errorOutput) {
const stateDefinition = this.stateDefinition;
options.eventLogger.dispatchStateCaughtEvent(
this.stateName,
stateDefinition.Type,
input,
stateDefinition.Catch[catcherIndex]
);
return { stateResult: processResultPath(resultPath, rawInput, errorOutput), nextState, isEndState: false };
}
throw error;
}
}
/**
* Process the current input according to the `InputPath` and `Parameters` fields.
*/
processInput(input, context) {
let processedInput = input;
if ("InputPath" in this.stateDefinition) {
processedInput = processInputPath(this.stateDefinition.InputPath, processedInput, context);
}
if ("Parameters" in this.stateDefinition && this.stateDefinition.Type !== "Map") {
processedInput = processPayloadTemplate(this.stateDefinition.Parameters, processedInput, context);
}
return processedInput;
}
/**
* Process the current result according to the `ResultSelector`, `ResultPath` and `OutputPath` fields.
*/
processResult(result, rawInput, context) {
let processedResult = result;
if ("ResultSelector" in this.stateDefinition) {
processedResult = processPayloadTemplate(this.stateDefinition.ResultSelector, processedResult, context);
}
if ("ResultPath" in this.stateDefinition) {
processedResult = processResultPath(this.stateDefinition.ResultPath, rawInput, processedResult);
}
if ("OutputPath" in this.stateDefinition) {
processedResult = processOutputPath(this.stateDefinition.OutputPath, processedResult, context);
}
return processedResult;
}
/**
* Decide whether this state should be retried, according to the `Retry` field.
*/
shouldRetry(error, retryIntervalOverrides) {
if (!("Retry" in this.stateDefinition)) {
return { shouldRetry: false };
}
for (let i = 0; i < this.stateDefinition.Retry.length; i++) {
const retrier = this.stateDefinition.Retry[i];
let intervalOverride = null;
if (retryIntervalOverrides?.[this.stateName] !== void 0) {
const override = retryIntervalOverrides[this.stateName];
if (typeof override === "number") {
intervalOverride = override / 1e3;
} else if (override[i] !== void 0 && override[i] >= 0) {
intervalOverride = override[i] / 1e3;
}
}
const jitterStrategy = retrier.JitterStrategy ?? DEFAULT_JITTER_STRATEGY;
const maxAttempts = retrier.MaxAttempts ?? DEFAULT_MAX_ATTEMPTS;
const intervalSeconds = retrier.IntervalSeconds ?? DEFAULT_INTERVAL_SECONDS;
const backoffRate = retrier.BackoffRate ?? DEFAULT_BACKOFF_RATE;
const waitInterval = intervalOverride ?? intervalSeconds * Math.pow(backoffRate, this.retrierAttempts[i]);
const retryable = error.isRetryable ?? true;
let waitTimeBeforeRetry = clamp(waitInterval, 0, retrier.MaxDelaySeconds) * 1e3;
if (jitterStrategy === "FULL" && intervalOverride === null) {
waitTimeBeforeRetry = getRandomNumber(0, waitTimeBeforeRetry);
}
for (const retrierError of retrier.ErrorEquals) {
const isErrorMatch = retrierError === error.name;
const isErrorWildcard = retrierError === WILDCARD_ERROR;
const isErrorTaskWildcard = retrierError === TASK_STATE_WILDCARD_ERROR && this.stateDefinition.Type === "Task" && !(error instanceof StatesTimeoutError);
const maybeShouldRetry = retryable && (isErrorMatch || isErrorWildcard || isErrorTaskWildcard);
if (maybeShouldRetry) {
if (this.retrierAttempts[i] >= maxAttempts) return { shouldRetry: false };
this.retrierAttempts[i]++;
return { shouldRetry: true, waitTimeBeforeRetry, retrierIndex: i };
}
}
}
return { shouldRetry: false };
}
/**
* Try to match the current error with a catcher, according to the `Catch` field.
*/
catchError(error) {
if (!("Catch" in this.stateDefinition)) {
return { nextState: "" };
}
for (let i = 0; i < this.stateDefinition.Catch.length; i++) {
const catcher = this.stateDefinition.Catch[i];
const catchable = error.isCatchable ?? true;
for (const catcherError of catcher.ErrorEquals) {
const isErrorMatch = catcherError === error.name;
const isErrorWildcard = catcherError === WILDCARD_ERROR;
const isErrorTaskWildcard = catcherError === TASK_STATE_WILDCARD_ERROR && this.stateDefinition.Type === "Task" && !(error instanceof StatesTimeoutError);
const shouldCatch = catchable && (isErrorMatch || isErrorWildcard || isErrorTaskWildcard);
if (shouldCatch) {
const nextState = catcher.Next;
const errorOutput = {
Error: error.name,
Cause: error.message
};
const resultPath = catcher.ResultPath;
return { nextState, errorOutput, resultPath, catcherIndex: i };
}
}
}
return { nextState: "" };
}
/**
* Handler for task states.
*
* Invokes the Lambda function specified in the `Resource` field
* and sets the current result of the state machine to the value returned by the Lambda.
*/
async executeTaskState(stateDefinition, rawInput, input, context, stateName, options) {
const overrideFn = options.runOptions?.overrides?.taskResourceLocalHandlers?.[stateName];
const awsConfig = options.stateMachineOptions?.awsConfig;
const taskStateAction = new TaskStateAction(stateDefinition, stateName);
const executionResult = await taskStateAction.execute(input, context, { overrideFn, awsConfig });
return executionResult;
}
/**
* Handler for parallel states.
*
* Creates a new state machine for each of the branches specified in the `Branches` field,
* and then executes each branch state machine by passing them the Parallel state input.
*/
async executeParallelState(stateDefinition, rawInput, input, context, stateName, options) {
const parallelStateAction = new ParallelStateAction(stateDefinition, stateName);
const executionResult = await parallelStateAction.execute(input, context, {
stateMachineOptions: options.stateMachineOptions,
runOptions: options.runOptions,
eventLogger: options.eventLogger,
rawInput
});
return executionResult;
}
/**
* Handler for map states.
*
* Iterates over the current input items or the items of an array specified
* by the `ItemsPath` field, and then processes each item by passing it
* as the input to the state machine specified in the `Iterator` field.
*/
async executeMapState(stateDefinition, rawInput, input, context, stateName, options) {
const mapStateAction = new MapStateAction(stateDefinition, stateName);
const executionResult = await mapStateAction.execute(input, context, {
stateMachineOptions: options.stateMachineOptions,
runOptions: options.runOptions,
eventLogger: options.eventLogger,
rawInput
});
return executionResult;
}
/**
* Handler for pass states.
*
* If the `Result` field is specified, copies `Result` into the current result.
* Else, copies the current input into the current result.
*/
async executePassState(stateDefinition, rawInput, input, context, stateName, options) {
const passStateAction = new PassStateAction(stateDefinition, stateName);
const executionResult = await passStateAction.execute(input, context);
return executionResult;
}
/**
* Handler for wait states.
*
* Pauses the state machine execution for a certain amount of time
* based on one of the `Seconds`, `Timestamp`, `SecondsPath` or `TimestampPath` fields.
*/
async executeWaitState(stateDefinition, rawInput, input, context, stateName, options) {
const waitTimeOverrideOption = options.runOptions?.overrides?.waitTimeOverrides?.[stateName];
const waitStateAction = new WaitStateAction(stateDefinition, stateName);
const executionResult = await waitStateAction.execute(input, context, {
waitTimeOverrideOption,
abortSignal: options.abortSignal
});
return executionResult;
}
/**
* Handler for choice states.
*
* Evaluates each choice rule specified in the `Choices` field.
*
* If one of the rules matches, then the state machine transitions to the
* state specified in the `Next` field for that choice rule.
*
* If no rule matches but the `Default` field is specified,
* then the next state will be the state specified in said field.
*
* If no rule matches and the `Default` field is not specified, throws a
* States.NoChoiceMatched error.
*/
async executeChoiceState(stateDefinition, rawInput, input, context, stateName, options) {
const choiceStateAction = new ChoiceStateAction(stateDefinition, stateName);
const executionResult = await choiceStateAction.execute(input, context);
return executionResult;
}
/**
* Handler for succeed states.
*
* Ends the state machine execution successfully.
*/
async executeSucceedState(stateDefinition, rawInput, input, context, stateName, options) {
const succeedStateAction = new SucceedStateAction(stateDefinition, stateName);
const executionResult = await succeedStateAction.execute(input, context);
return executionResult;
}
/**
* Handler for fail states.
*
* Ends the state machine execution and marks it as a failure.
*/
async executeFailState(stateDefinition, rawInput, input, context, stateName, options) {
const failStateAction = new FailStateAction(stateDefinition, stateName);
const executionResult = await failStateAction.execute(input, context);
return executionResult;
}
};
// src/stateMachine/EventLogger.ts
var EventLogger = class {
eventTarget;
eventQueue;
isLoggerClosed;
constructor() {
this.eventTarget = new EventTarget();
this.eventQueue = [];
this.isLoggerClosed = false;
}
async *getEvents() {
while (true) {
if (this.eventQueue.length === 0) {
await this.waitForNewEvent();
}
let event = null;
while (event = this.eventQueue.shift()) {
yield event;
}
if (this.isLoggerClosed) return;
}
}
/**
* Forward nested events created by `Map` states, to the root state machine event logger.
* @param event An event dispatched by the nested state machine spawned by a `Map` state.
* @param index Index of the current iteration being processed.
* @param mapStateName Name of the `Map` state being executed.
* @param mapStateRawInput Raw input passed to the `Map` state being executed.
*/
forwardNestedMapEvent(event, index, mapStateName, mapStateRawInput) {
switch (event.type) {
case "ExecutionStarted":
this.dispatchMapIterationStartedEvent(event, index, mapStateName, mapStateRawInput);
break;
case "ExecutionSucceeded":
this.dispatchMapIterationSucceededEvent(event, index, mapStateName, mapStateRawInput);
break;
case "ExecutionFailed":
this.dispatchMapIterationFailedEvent(event, index, mapStateName, mapStateRawInput);
break;
case "StateEntered":
case "StateExited":
case "StateFailed":
case "StateRetried":
case "StateCaught":
event.index = index;
this.dispatch(event);
break;
case "ExecutionAborted":
case "ExecutionTimeout":
return;
default:
this.dispatch(event);
break;
}
}
/**
* Forward nested events created by `Parallel` states, to the root state machine event logger.
* @param event An event dispatched by the nested state machines spawned by a `Parallel` state.
* @param parallelStateName Name of the `Parallel` state being executed.
* @param parallelStateRawInput Raw input passed to the `Parallel` state being executed.
*/
forwardNestedParallelEvent(event, parallelStateName, parallelStateRawInput) {
switch (event.type) {
case "ExecutionStarted":
this.dispatchParallelBranchStartedEvent(event, parallelStateName, parallelStateRawInput);
break;
case "ExecutionSucceeded":
this.dispatchParallelBranchSucceededEvent(event, parallelStateName, parallelStateRawInput);
break;
case "ExecutionFailed":
this.dispatchParallelBranchFailedEvent(event, parallelStateName, parallelStateRawInput);
break;
case "ExecutionAborted":
case "ExecutionTimeout":
return;
default:
this.dispatch(event);
break;
}
}
dispatchExecutionStartedEvent(input) {
this.dispatch({ type: "ExecutionStarted", timestamp: Date.now(), input });
}
dispatchExecutionSucceededEvent(output) {
this.dispatch({ type: "ExecutionSucceeded", timestamp: Date.now(), output });
this.close();
}
dispatchExecutionFailedEvent(error) {
this.dispatch({
type: "ExecutionFailed",
timestamp: Date.now(),
Error: error.name,
Cause: error.cause ?? error.message
});
this.close();
}
dispatchExecutionAbortedEvent() {
this.dispatch({ type: "ExecutionAborted", timestamp: Date.now() });
this.close();
}
dispatchExecutionTimeoutEvent() {
this.dispatch({ type: "ExecutionTimeout", timestamp: Date.now() });
this.close();
}
dispatchStateEnteredEvent(stateName, stateType, input) {
this.dispatch({
type: "StateEntered",
timestamp: Date.now(),
state: { name: stateName, type: stateType, input }
});
}
dispatchStateExitedEvent(stateName, stateType, input, output) {
this.dispatch({
type: "StateExited",
timestamp: Date.now(),
state: { name: stateName, type: stateType, input, output }
});
}
dispatchStateFailedEvent(stateName, stateType, input, error) {
this.dispatch({
type: "StateFailed",
timestamp: Date.now(),
state: { name: stateName, type: stateType, input },
Error: error.name,
Cause: error.cause ?? error.message
});
}
dispatchStateRetriedEvent(stateName, stateType, input, retrier, retryAttempt) {
this.dispatch({
type: "StateRetried",
timestamp: Date.now(),
state: { name: stateName, type: stateType, input },
retry: { retrier, attempt: retryAttempt }
});
}
dispatchStateCaughtEvent(stateName, stateType, input, catcher) {
this.dispatch({
type: "StateCaught",
timestamp: Date.now(),
state: { name: stateName, type: stateType, input },
catch: { catcher }
});
}
dispatchMapIterationStartedEvent(event, index, mapStateName, mapStateRawInput) {
this.dispatch({
...event,
type: "MapIterationStarted",
index,
parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
});
}
dispatchMapIterationSucceededEvent(event, index, mapStateName, mapStateRawInput) {
this.dispatch({
...event,
type: "MapIterationSucceeded",
index,
parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
});
}
dispatchMapIterationFailedEvent(event, index, mapStateName, mapStateRawInput) {
this.dispatch({
...event,
type: "MapIterationFailed",
index,
parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
});
}
dispatchParallelBranchStartedEvent(event, parallelStateName, parallelStateRawInput) {
this.dispatch({
...event,
type: "ParallelBranchStarted",
parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
});
}
dispatchParallelBranchSucceededEvent(event, parallelStateName, parallelStateRawInput) {
this.dispatch({
...event,
type: "ParallelBranchSucceeded",
parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
});
}
dispatchParallelBranchFailedEvent(event, parallelStateName, parallelStateRawInput) {
this.dispatch({
...event,
type: "ParallelBranchFailed",
parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
});
}
close() {
this.isLoggerClosed = true;
this.eventTarget.dispatchEvent(new Event("newEvent"));
}
dispatch(event) {
if (this.isLoggerClosed) return;
this.eventQueue.push(event);
this.eventTarget.dispatchEvent(new Event("newEvent"));
}
waitForNewEvent() {
if (this.isLoggerClosed) return;
return new Promise((resolve) => {
this.eventTarget.addEventListener("newEvent", resolve, { once: true });
});
}
};
// src/stateMachine/StateMachine.ts
var import_asl_validator = __toESM(require("asl-validator"), 1);
var import_cloneDeep3 = __toESM(require("lodash/cloneDeep.js"), 1);
var StateMachine = class {
/**
* The structure of the State Machine as represented by the Amazon States Language.
*/
definition;
/**
* Options to control certain settings of the state machine.
*/
stateMachineOptions;
/**
* Constructs a new state machine.
* @param definition The state machine definition defined using the Amazon States Language (https://states-language.net/spec.html).
* @param stateMachineOptions Options to control certain settings of the state machine.
* These options also apply to state machines defined in the `Iterator` field of `Map` states and in the `Branches` field of `Parallel` states.
*/
constructor(definition, stateMachineOptions) {
if (!stateMachineOptions?.validationOptions?.noValidate) {
const { isValid, errorsText } = (0, import_asl_validator.default)(definition, {
checkArn: true,
checkPaths: true,
...stateMachineOptions?.validationOptions
});
if (!isValid) {
throw new Error(`State machine definition is invalid, see error(s) below:
${errorsText("\n")}`);
}
}
this.definition = definition;
this.stateMachineOptions = stateMachineOptions;
}
/**
* Executes the state machine, running through the states specified in the definition.
* If the execution fails, the result will throw an `ExecutionError` explaining why the
* execution failed.
*
* If the execution times out because the number of seconds specified in
* the `TimeoutSeconds` top-level field has elapsed, the result will throw an `ExecutionTimeoutError`.
*
* By default, if the execution is aborted, the result will throw an `ExecutionAbortedError`. This behavior can be changed by setting
* the `noThrowOnAbort` option to `true`, in which case the result will be `null`.
*
* @param input The input to pass to this state machine execution.
* @param options Miscellaneous options to control certain behaviors of the execution.
*/
run(input, options) {
const abortController = new AbortController();
const eventLogger = new EventLogger();
let rootSignalAbortHandler;
if (options?._rootAbortSignal) {
rootSignalAbortHandler = () => abortController.abort();
if (options._rootAbortSignal.aborted) {
rootSignalAbortHandler();
} else {
options._rootAbortSignal.addEventListener("abort", rootSignalAbortHandler);
}
}
let onAbortHandler;
const settleOnAbort = new Promise((resolve, reject) => {
if (options?.noThrowOnAbort) {
onAbortHandler = () => {
eventLogger.dispatchExecutionAbortedEvent();
resolve(null);
};
} else {
onAbortHandler = () => {
eventLogger.dispatchExecutionAbortedEvent();
reject(new ExecutionAbortedError());
};
}
abortController.signal.addEventListener("abort", onAbortHandler);
});
let rejectOnTimeout;
let timeoutId;
if (this.definition.TimeoutSeconds !== void 0) {
rejectOnTimeout = new Promise((_, reject) => {
timeoutId = setTimeout(() => {
abortController.signal.removeEventListener("abort", onAbortHandler);
abortController.abort();
eventLogger.dispatchExecutionTimeoutEvent();
reject(new ExecutionTimeoutError());
}, this.definition.TimeoutSeconds * 1e3);
});
}
const executionResult = this.execute(
input,
{
stateMachineOptions: this.stateMachineOptions,
runOptions: { ...options, _rootAbortSignal: options?._rootAbortSignal ?? abortController.signal },
abortSignal: abortController.signal,
eventLogger
},
() => {
abortController.signal.removeEventListener("abort", onAbortHandler);
options?._rootAbortSignal?.removeEventListener("abort", rootSignalAbortHandler);
clearTimeout(timeoutId);
}
);
const racingPromises = [executionResult, settleOnAbort];
if (rejectOnTimeout) {
racingPromises.push(rejectOnTimeout);
}
const result = Promise.race(racingPromises);
return {
abort: () => abortController.abort(),
eventLogs: eventLogger.getEvents(),
result
};
}
/**
* Helper method that handles the execution of the machine states and the transitions between them.
*/
async execute(input, options, cleanupFn) {
options.eventLogger.dispatchExecutionStartedEvent(input);
const context = {
...options.runOptions?.context,
Execution: {
...options.runOptions?.context?.Execution,
Input: input,
StartTime: (/* @__PURE__ */ new Date()).toISOString()
}
};
let currState = this.definition.States[this.definition.StartAt];
let currStateName = this.definition.StartAt;
let currInput = (0, import_cloneDeep3.default)(input);
let currResult = null;
let nextState = "";
let isEndState = false;
try {
do {
options.eventLogger.dispatchStateEnteredEvent(currStateName, currState.Type, currInput);
const stateExecutor = new StateExecutor(currStateName, currState);
({ stateResult: currResult, nextState, isEndState } = await stateExecutor.execute(currInput, context, options));
options.eventLogger.dispatchStateExitedEvent(currStateName, currState.Type, currInput, currResult);
currInput = currResult;
currState = this.definition.States[nextState];
currStateName = nextState;
} while (!isEndState && !options.abortSignal.aborted);
} catch (error) {
options.eventLogger.dispatchExecutionFailedEvent(error);
throw new ExecutionError(error);
} finally {
cleanupFn();
}
options.eventLogger.dispatchExecutionSucceededEvent(currResult);
return currResult;
}
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ExecutionAbortedError,
ExecutionError,
ExecutionTimeoutError,
StateMachine
});