aws-local-stepfunctions 0.6.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -25,27 +25,11 @@ var ExecutionAbortedError = class extends Error {
25
25
  }
26
26
  };
27
27
 
28
- // src/error/RuntimeError.ts
29
- var RuntimeError = class extends Error {
30
- constructor(message) {
31
- super(message);
32
- this.name = "RuntimeError";
33
- this.retryable = true;
34
- this.catchable = true;
35
- }
36
- get isRetryable() {
37
- return this.retryable;
38
- }
39
- get isCatchable() {
40
- return this.catchable;
41
- }
42
- };
43
-
44
- // src/error/predefined/StatesTimeoutError.ts
45
- var StatesTimeoutError = class extends RuntimeError {
28
+ // src/error/ExecutionTimeoutError.ts
29
+ var ExecutionTimeoutError = class extends Error {
46
30
  constructor() {
47
- super("States.Timeout");
48
- this.name = "States.Timeout";
31
+ super("Execution timed out");
32
+ this.name = "ExecutionTimeoutError";
49
33
  }
50
34
  };
51
35
 
@@ -96,20 +80,32 @@ function sfc32(a, b, c, d) {
96
80
  return (t >>> 0) / 4294967296;
97
81
  };
98
82
  }
99
- function getRandomNumber(min, max, rngGenerator = Math.random) {
100
- return Math.floor(rngGenerator() * (max - min + 1)) + min;
83
+ function getRandomNumber(min, max, rng = Math.random) {
84
+ return Math.floor(rng() * (max - min + 1)) + min;
101
85
  }
102
86
 
103
87
  // src/util/index.ts
104
88
  function isPlainObj(value) {
105
89
  return !!value && Object.getPrototypeOf(value) === Object.prototype;
106
90
  }
107
- function sleep(ms, abortSignal) {
91
+ function sleep(ms, abortSignal, rootAbortSignal) {
108
92
  return new Promise((resolve) => {
109
- const timeout = setTimeout(resolve, ms);
110
- abortSignal?.addEventListener("abort", () => {
93
+ if (abortSignal?.aborted || rootAbortSignal?.aborted) {
94
+ return resolve();
95
+ }
96
+ const onAbort = () => {
97
+ abortSignal?.removeEventListener("abort", onAbort);
98
+ rootAbortSignal?.removeEventListener("abort", onAbort);
111
99
  clearTimeout(timeout);
112
- });
100
+ resolve();
101
+ };
102
+ const timeout = setTimeout(() => {
103
+ abortSignal?.removeEventListener("abort", onAbort);
104
+ rootAbortSignal?.removeEventListener("abort", onAbort);
105
+ resolve();
106
+ }, ms);
107
+ abortSignal?.addEventListener("abort", onAbort);
108
+ rootAbortSignal?.addEventListener("abort", onAbort);
113
109
  });
114
110
  }
115
111
  function byteToHex(byte) {
@@ -125,6 +121,22 @@ function jsonPathQuery(pathExpression, json, context) {
125
121
  return jp({ path: pathExpression, json, wrap: false });
126
122
  }
127
123
 
124
+ // src/error/RuntimeError.ts
125
+ var RuntimeError = class extends Error {
126
+ constructor(message) {
127
+ super(message);
128
+ this.name = "RuntimeError";
129
+ this.retryable = true;
130
+ this.catchable = true;
131
+ }
132
+ get isRetryable() {
133
+ return this.retryable;
134
+ }
135
+ get isCatchable() {
136
+ return this.catchable;
137
+ }
138
+ };
139
+
128
140
  // src/error/predefined/StatesResultPathMatchFailureError.ts
129
141
  var StatesResultPathMatchFailureError = class extends RuntimeError {
130
142
  constructor() {
@@ -169,7 +181,7 @@ function validateArgumentType(allowedTypes, argPosition, funcArg, funcName) {
169
181
  if (matchesAllowedType)
170
182
  break;
171
183
  }
172
- const expectedType = allowedTypes.map((type) => `"${type}"`).join(" | ");
184
+ const expectedType = allowedTypes.map((type) => `'${type}'`).join(" | ");
173
185
  if (!matchesAllowedType) {
174
186
  throw new StatesRuntimeError(
175
187
  `Intrinsic function ${funcName} expected argument ${argPosition} to be of type ${expectedType}, but received ${typeof funcArg}`
@@ -197,7 +209,7 @@ function validateArgumentConstraints(argConstraints, argPosition, funcArg, funcN
197
209
  if (matchesAllConstraints)
198
210
  break;
199
211
  }
200
- const expectedConstraints = argConstraints.map((constraint) => `"${constraint}"`).join(" | ");
212
+ const expectedConstraints = argConstraints.map((constraint) => `'${constraint}'`).join(" | ");
201
213
  if (!matchesAllConstraints) {
202
214
  throw new StatesRuntimeError(
203
215
  `Intrinsic function ${funcName} expected argument ${argPosition} to satisfy the following constraints: ${expectedConstraints}`
@@ -819,7 +831,7 @@ function processPayloadTemplate(payloadTemplate, json, context) {
819
831
  let sanitizedKey = key;
820
832
  let resolvedValue = value;
821
833
  if (isPlainObj(value)) {
822
- resolvedValue = processPayloadTemplate(value, json);
834
+ resolvedValue = processPayloadTemplate(value, json, context);
823
835
  }
824
836
  if (key.endsWith(".$") && typeof value === "string") {
825
837
  sanitizedKey = key.replace(".$", "");
@@ -859,8 +871,9 @@ function processOutputPath(path, result, context) {
859
871
 
860
872
  // src/stateMachine/stateActions/BaseStateAction.ts
861
873
  var BaseStateAction = class {
862
- constructor(stateDefinition) {
874
+ constructor(stateDefinition, stateName) {
863
875
  this.stateDefinition = stateDefinition;
876
+ this.stateName = stateName;
864
877
  }
865
878
  buildExecutionResult(stateResult) {
866
879
  const executionResult = { stateResult, nextState: "", isEndState: false };
@@ -885,8 +898,8 @@ var StatesNoChoiceMatchedError = class extends RuntimeError {
885
898
  // src/stateMachine/stateActions/ChoiceStateAction.ts
886
899
  import wcmatch from "wildcard-match";
887
900
  var ChoiceStateAction = class extends BaseStateAction {
888
- constructor(stateDefinition) {
889
- super(stateDefinition);
901
+ constructor(stateDefinition, stateName) {
902
+ super(stateDefinition, stateName);
890
903
  }
891
904
  testChoiceRule(choiceRule, input) {
892
905
  if ("And" in choiceRule) {
@@ -1109,8 +1122,8 @@ var FailStateError = class extends RuntimeError {
1109
1122
 
1110
1123
  // src/stateMachine/stateActions/FailStateAction.ts
1111
1124
  var FailStateAction = class extends BaseStateAction {
1112
- constructor(stateDefinition) {
1113
- super(stateDefinition);
1125
+ constructor(stateDefinition, stateName) {
1126
+ super(stateDefinition, stateName);
1114
1127
  }
1115
1128
  async execute(input, context, options) {
1116
1129
  throw new FailStateError(this.stateDefinition.Error, this.stateDefinition.Cause);
@@ -1121,10 +1134,17 @@ var FailStateAction = class extends BaseStateAction {
1121
1134
  import pLimit from "p-limit";
1122
1135
  var DEFAULT_MAX_CONCURRENCY = 40;
1123
1136
  var MapStateAction = class extends BaseStateAction {
1124
- constructor(stateDefinition) {
1125
- super(stateDefinition);
1137
+ constructor(stateDefinition, stateName) {
1138
+ super(stateDefinition, stateName);
1126
1139
  this.executionAbortFuncs = [];
1127
1140
  }
1141
+ async forwardEventsToRootEventLogger(eventLogger, executionEventLogs, index, parentStateRawInput) {
1142
+ if (!eventLogger)
1143
+ return;
1144
+ for await (const event of executionEventLogs) {
1145
+ eventLogger.forwardNestedMapEvent(event, index, this.stateName, parentStateRawInput);
1146
+ }
1147
+ }
1128
1148
  processItem(stateMachine, item, input, context, index, options) {
1129
1149
  const state = this.stateDefinition;
1130
1150
  let paramValue;
@@ -1139,6 +1159,7 @@ var MapStateAction = class extends BaseStateAction {
1139
1159
  }
1140
1160
  const execution = stateMachine.run(paramValue ?? item, options?.runOptions);
1141
1161
  this.executionAbortFuncs.push(execution.abort);
1162
+ this.forwardEventsToRootEventLogger(options?.eventLogger, execution.eventLogs, index, options?.rawInput);
1142
1163
  return execution.result;
1143
1164
  }
1144
1165
  async execute(input, context, options) {
@@ -1150,7 +1171,10 @@ var MapStateAction = class extends BaseStateAction {
1150
1171
  if (!Array.isArray(items)) {
1151
1172
  throw new StatesRuntimeError("Input of Map state must be an array or ItemsPath property must point to an array");
1152
1173
  }
1153
- const iteratorStateMachine = new StateMachine(state.Iterator, options?.stateMachineOptions);
1174
+ const iteratorStateMachine = new StateMachine(state.Iterator, {
1175
+ ...options?.stateMachineOptions,
1176
+ validationOptions: { _noValidate: true }
1177
+ });
1154
1178
  const limit = pLimit(state.MaxConcurrency || DEFAULT_MAX_CONCURRENCY);
1155
1179
  const processedItemsPromise = items.map(
1156
1180
  (item, i) => limit(() => this.processItem(iteratorStateMachine, item, input, context, i, options))
@@ -1174,14 +1198,25 @@ var MapStateAction = class extends BaseStateAction {
1174
1198
  import pLimit2 from "p-limit";
1175
1199
  var DEFAULT_CONCURRENCY = 40;
1176
1200
  var ParallelStateAction = class extends BaseStateAction {
1177
- constructor(stateDefinition) {
1178
- super(stateDefinition);
1201
+ constructor(stateDefinition, stateName) {
1202
+ super(stateDefinition, stateName);
1179
1203
  this.executionAbortFuncs = [];
1180
1204
  }
1205
+ async forwardEventsToRootEventLogger(eventLogger, executionEventLogs, parentStateRawInput) {
1206
+ if (!eventLogger)
1207
+ return;
1208
+ for await (const event of executionEventLogs) {
1209
+ eventLogger.forwardNestedParallelEvent(event, this.stateName, parentStateRawInput);
1210
+ }
1211
+ }
1181
1212
  processBranch(branch, input, context, options) {
1182
- const stateMachine = new StateMachine(branch, options?.stateMachineOptions);
1213
+ const stateMachine = new StateMachine(branch, {
1214
+ ...options?.stateMachineOptions,
1215
+ validationOptions: { _noValidate: true }
1216
+ });
1183
1217
  const execution = stateMachine.run(input, options?.runOptions);
1184
1218
  this.executionAbortFuncs.push(execution.abort);
1219
+ this.forwardEventsToRootEventLogger(options?.eventLogger, execution.eventLogs, options?.rawInput);
1185
1220
  return execution.result;
1186
1221
  }
1187
1222
  async execute(input, context, options) {
@@ -1205,8 +1240,8 @@ var ParallelStateAction = class extends BaseStateAction {
1205
1240
 
1206
1241
  // src/stateMachine/stateActions/PassStateAction.ts
1207
1242
  var PassStateAction = class extends BaseStateAction {
1208
- constructor(stateDefinition) {
1209
- super(stateDefinition);
1243
+ constructor(stateDefinition, stateName) {
1244
+ super(stateDefinition, stateName);
1210
1245
  }
1211
1246
  async execute(input, context, options) {
1212
1247
  if (this.stateDefinition.Result) {
@@ -1218,8 +1253,8 @@ var PassStateAction = class extends BaseStateAction {
1218
1253
 
1219
1254
  // src/stateMachine/stateActions/SucceedStateAction.ts
1220
1255
  var SucceedStateAction = class extends BaseStateAction {
1221
- constructor(stateDefinition) {
1222
- super(stateDefinition);
1256
+ constructor(stateDefinition, stateName) {
1257
+ super(stateDefinition, stateName);
1223
1258
  }
1224
1259
  async execute(input, context, options) {
1225
1260
  return { stateResult: input, nextState: "", isEndState: true };
@@ -1235,12 +1270,12 @@ var LambdaClient = class {
1235
1270
  if (config) {
1236
1271
  if (!config.region) {
1237
1272
  throw new StatesRuntimeError(
1238
- "`awsConfig` option was specified for state machine, but `region` property is not set"
1273
+ "'awsConfig' option was specified for state machine, but 'region' property is not set"
1239
1274
  );
1240
1275
  }
1241
1276
  if (config.credentials) {
1242
1277
  const credentialsTypes = Object.keys(config.credentials);
1243
- const credentialsNames = credentialsTypes.map((name) => `\`${name}\``).join(", ");
1278
+ const credentialsNames = credentialsTypes.map((name) => `'${name}'`).join(", ");
1244
1279
  if (credentialsTypes.length > 1) {
1245
1280
  throw new StatesRuntimeError(
1246
1281
  `More than one type of AWS credentials were specified: ${credentialsNames}. Only one type may be specified`
@@ -1274,7 +1309,7 @@ var LambdaClient = class {
1274
1309
  }
1275
1310
  if (invocationResult.FunctionError) {
1276
1311
  const errorResult = resultValue;
1277
- throw new FailStateError(errorResult.errorType, `Execution of Lambda function "${funcNameOrArn}" failed`);
1312
+ throw new FailStateError(errorResult.errorType, `Execution of Lambda function '${funcNameOrArn}' failed`);
1278
1313
  }
1279
1314
  return resultValue;
1280
1315
  }
@@ -1282,8 +1317,8 @@ var LambdaClient = class {
1282
1317
 
1283
1318
  // src/stateMachine/stateActions/TaskStateAction.ts
1284
1319
  var TaskStateAction = class extends BaseStateAction {
1285
- constructor(stateDefinition) {
1286
- super(stateDefinition);
1320
+ constructor(stateDefinition, stateName) {
1321
+ super(stateDefinition, stateName);
1287
1322
  }
1288
1323
  async execute(input, context, options) {
1289
1324
  const state = this.stateDefinition;
@@ -1299,36 +1334,44 @@ var TaskStateAction = class extends BaseStateAction {
1299
1334
 
1300
1335
  // src/stateMachine/stateActions/WaitStateAction.ts
1301
1336
  var WaitStateAction = class extends BaseStateAction {
1302
- constructor(stateDefinition) {
1303
- super(stateDefinition);
1337
+ constructor(stateDefinition, stateName) {
1338
+ super(stateDefinition, stateName);
1304
1339
  }
1305
1340
  async execute(input, context, options) {
1306
1341
  const state = this.stateDefinition;
1307
1342
  if (options?.waitTimeOverrideOption !== void 0) {
1308
- await sleep(options.waitTimeOverrideOption, options.abortSignal);
1343
+ await sleep(options.waitTimeOverrideOption, options.abortSignal, options.rootAbortSignal);
1309
1344
  return this.buildExecutionResult(input);
1310
1345
  }
1311
1346
  if (state.Seconds) {
1312
- await sleep(state.Seconds * 1e3, options?.abortSignal);
1347
+ await sleep(state.Seconds * 1e3, options?.abortSignal, options?.rootAbortSignal);
1313
1348
  } else if (state.Timestamp) {
1314
1349
  const dateTimestamp = new Date(state.Timestamp);
1315
1350
  const currentTime = Date.now();
1316
1351
  const timeDiff = dateTimestamp.getTime() - currentTime;
1317
- await sleep(timeDiff, options?.abortSignal);
1352
+ await sleep(timeDiff, options?.abortSignal, options?.rootAbortSignal);
1318
1353
  } else if (state.SecondsPath) {
1319
1354
  const seconds = jsonPathQuery(state.SecondsPath, input, context);
1320
- await sleep(seconds * 1e3, options?.abortSignal);
1355
+ await sleep(seconds * 1e3, options?.abortSignal, options?.rootAbortSignal);
1321
1356
  } else if (state.TimestampPath) {
1322
1357
  const timestamp = jsonPathQuery(state.TimestampPath, input, context);
1323
1358
  const dateTimestamp = new Date(timestamp);
1324
1359
  const currentTime = Date.now();
1325
1360
  const timeDiff = dateTimestamp.getTime() - currentTime;
1326
- await sleep(timeDiff, options?.abortSignal);
1361
+ await sleep(timeDiff, options?.abortSignal, options?.rootAbortSignal);
1327
1362
  }
1328
1363
  return this.buildExecutionResult(input);
1329
1364
  }
1330
1365
  };
1331
1366
 
1367
+ // src/error/predefined/StatesTimeoutError.ts
1368
+ var StatesTimeoutError = class extends RuntimeError {
1369
+ constructor() {
1370
+ super("States.Timeout");
1371
+ this.name = "States.Timeout";
1372
+ }
1373
+ };
1374
+
1332
1375
  // src/stateMachine/StateExecutor.ts
1333
1376
  import cloneDeep2 from "lodash/cloneDeep.js";
1334
1377
  var DEFAULT_MAX_ATTEMPTS = 3;
@@ -1366,6 +1409,7 @@ var StateExecutor = class {
1366
1409
  } = await this.stateHandlers[this.stateDefinition.Type](
1367
1410
  // @ts-expect-error Indexing `this.stateActions` by non-literal value produces a `never` type for the `this.stateDefinition` parameter of the handler being called
1368
1411
  this.stateDefinition,
1412
+ rawInput,
1369
1413
  processedInput,
1370
1414
  context,
1371
1415
  this.stateName,
@@ -1376,7 +1420,7 @@ var StateExecutor = class {
1376
1420
  } catch (error) {
1377
1421
  const { shouldRetry, waitTimeBeforeRetry } = this.shouldRetry(error);
1378
1422
  if (shouldRetry && waitTimeBeforeRetry) {
1379
- await sleep(waitTimeBeforeRetry, options.abortSignal);
1423
+ await sleep(waitTimeBeforeRetry, options.abortSignal, options.runOptions?._rootAbortSignal);
1380
1424
  return this.execute(input, context, options);
1381
1425
  }
1382
1426
  const { nextState, errorOutput, resultPath } = this.catchError(error);
@@ -1478,10 +1522,10 @@ var StateExecutor = class {
1478
1522
  * Invokes the Lambda function specified in the `Resource` field
1479
1523
  * and sets the current result of the state machine to the value returned by the Lambda.
1480
1524
  */
1481
- async executeTaskState(stateDefinition, input, context, stateName, options) {
1525
+ async executeTaskState(stateDefinition, rawInput, input, context, stateName, options) {
1482
1526
  const overrideFn = options.runOptions?.overrides?.taskResourceLocalHandlers?.[stateName];
1483
1527
  const awsConfig = options.stateMachineOptions?.awsConfig;
1484
- const taskStateAction = new TaskStateAction(stateDefinition);
1528
+ const taskStateAction = new TaskStateAction(stateDefinition, stateName);
1485
1529
  const executionResult = await taskStateAction.execute(input, context, { overrideFn, awsConfig });
1486
1530
  return executionResult;
1487
1531
  }
@@ -1491,11 +1535,13 @@ var StateExecutor = class {
1491
1535
  * Creates a new state machine for each of the branches specified in the `Branches` field,
1492
1536
  * and then executes each branch state machine by passing them the Parallel state input.
1493
1537
  */
1494
- async executeParallelState(stateDefinition, input, context, stateName, options) {
1495
- const parallelStateAction = new ParallelStateAction(stateDefinition);
1538
+ async executeParallelState(stateDefinition, rawInput, input, context, stateName, options) {
1539
+ const parallelStateAction = new ParallelStateAction(stateDefinition, stateName);
1496
1540
  const executionResult = await parallelStateAction.execute(input, context, {
1497
1541
  stateMachineOptions: options.stateMachineOptions,
1498
- runOptions: options.runOptions
1542
+ runOptions: options.runOptions,
1543
+ eventLogger: options.eventLogger,
1544
+ rawInput
1499
1545
  });
1500
1546
  return executionResult;
1501
1547
  }
@@ -1506,11 +1552,13 @@ var StateExecutor = class {
1506
1552
  * by the `ItemsPath` field, and then processes each item by passing it
1507
1553
  * as the input to the state machine specified in the `Iterator` field.
1508
1554
  */
1509
- async executeMapState(stateDefinition, input, context, stateName, options) {
1510
- const mapStateAction = new MapStateAction(stateDefinition);
1555
+ async executeMapState(stateDefinition, rawInput, input, context, stateName, options) {
1556
+ const mapStateAction = new MapStateAction(stateDefinition, stateName);
1511
1557
  const executionResult = await mapStateAction.execute(input, context, {
1512
1558
  stateMachineOptions: options.stateMachineOptions,
1513
- runOptions: options.runOptions
1559
+ runOptions: options.runOptions,
1560
+ eventLogger: options.eventLogger,
1561
+ rawInput
1514
1562
  });
1515
1563
  return executionResult;
1516
1564
  }
@@ -1520,8 +1568,8 @@ var StateExecutor = class {
1520
1568
  * If the `Result` field is specified, copies `Result` into the current result.
1521
1569
  * Else, copies the current input into the current result.
1522
1570
  */
1523
- async executePassState(stateDefinition, input, context, stateName, options) {
1524
- const passStateAction = new PassStateAction(stateDefinition);
1571
+ async executePassState(stateDefinition, rawInput, input, context, stateName, options) {
1572
+ const passStateAction = new PassStateAction(stateDefinition, stateName);
1525
1573
  const executionResult = await passStateAction.execute(input, context);
1526
1574
  return executionResult;
1527
1575
  }
@@ -1531,13 +1579,13 @@ var StateExecutor = class {
1531
1579
  * Pauses the state machine execution for a certain amount of time
1532
1580
  * based on one of the `Seconds`, `Timestamp`, `SecondsPath` or `TimestampPath` fields.
1533
1581
  */
1534
- async executeWaitState(stateDefinition, input, context, stateName, options) {
1582
+ async executeWaitState(stateDefinition, rawInput, input, context, stateName, options) {
1535
1583
  const waitTimeOverrideOption = options.runOptions?.overrides?.waitTimeOverrides?.[stateName];
1536
- const abortSignal = options.abortSignal;
1537
- const waitStateAction = new WaitStateAction(stateDefinition);
1584
+ const waitStateAction = new WaitStateAction(stateDefinition, stateName);
1538
1585
  const executionResult = await waitStateAction.execute(input, context, {
1539
1586
  waitTimeOverrideOption,
1540
- abortSignal
1587
+ abortSignal: options.abortSignal,
1588
+ rootAbortSignal: options.runOptions?._rootAbortSignal
1541
1589
  });
1542
1590
  return executionResult;
1543
1591
  }
@@ -1555,8 +1603,8 @@ var StateExecutor = class {
1555
1603
  * If no rule matches and the `Default` field is not specified, throws a
1556
1604
  * States.NoChoiceMatched error.
1557
1605
  */
1558
- async executeChoiceState(stateDefinition, input, context, stateName, options) {
1559
- const choiceStateAction = new ChoiceStateAction(stateDefinition);
1606
+ async executeChoiceState(stateDefinition, rawInput, input, context, stateName, options) {
1607
+ const choiceStateAction = new ChoiceStateAction(stateDefinition, stateName);
1560
1608
  const executionResult = await choiceStateAction.execute(input, context);
1561
1609
  return executionResult;
1562
1610
  }
@@ -1565,8 +1613,8 @@ var StateExecutor = class {
1565
1613
  *
1566
1614
  * Ends the state machine execution successfully.
1567
1615
  */
1568
- async executeSucceedState(stateDefinition, input, context, stateName, options) {
1569
- const succeedStateAction = new SucceedStateAction(stateDefinition);
1616
+ async executeSucceedState(stateDefinition, rawInput, input, context, stateName, options) {
1617
+ const succeedStateAction = new SucceedStateAction(stateDefinition, stateName);
1570
1618
  const executionResult = await succeedStateAction.execute(input, context);
1571
1619
  return executionResult;
1572
1620
  }
@@ -1575,13 +1623,186 @@ var StateExecutor = class {
1575
1623
  *
1576
1624
  * Ends the state machine execution and marks it as a failure.
1577
1625
  */
1578
- async executeFailState(stateDefinition, input, context, stateName, options) {
1579
- const failStateAction = new FailStateAction(stateDefinition);
1626
+ async executeFailState(stateDefinition, rawInput, input, context, stateName, options) {
1627
+ const failStateAction = new FailStateAction(stateDefinition, stateName);
1580
1628
  const executionResult = await failStateAction.execute(input, context);
1581
1629
  return executionResult;
1582
1630
  }
1583
1631
  };
1584
1632
 
1633
+ // src/stateMachine/EventLogger.ts
1634
+ var EventLogger = class {
1635
+ constructor() {
1636
+ this.eventTarget = new EventTarget();
1637
+ this.eventQueue = [];
1638
+ this.isLoggerClosed = false;
1639
+ }
1640
+ async *getEvents() {
1641
+ while (true) {
1642
+ if (this.eventQueue.length === 0) {
1643
+ await this.waitForNewEvent();
1644
+ }
1645
+ let event = null;
1646
+ while (event = this.eventQueue.shift()) {
1647
+ yield event;
1648
+ }
1649
+ if (this.isLoggerClosed)
1650
+ return;
1651
+ }
1652
+ }
1653
+ /**
1654
+ * Forward nested events created by `Map` states, to the root state machine event logger.
1655
+ * @param event An event dispatched by the nested state machine spawned by a `Map` state.
1656
+ * @param index Index of the current iteration being processed.
1657
+ * @param mapStateName Name of the `Map` state being executed.
1658
+ * @param mapStateRawInput Raw input passed to the `Map` state being executed.
1659
+ */
1660
+ forwardNestedMapEvent(event, index, mapStateName, mapStateRawInput) {
1661
+ switch (event.type) {
1662
+ case "ExecutionStarted":
1663
+ this.dispatchMapIterationStartedEvent(event, index, mapStateName, mapStateRawInput);
1664
+ break;
1665
+ case "ExecutionSucceeded":
1666
+ this.dispatchMapIterationSucceededEvent(event, index, mapStateName, mapStateRawInput);
1667
+ break;
1668
+ case "ExecutionFailed":
1669
+ this.dispatchMapIterationFailedEvent(event, index, mapStateName, mapStateRawInput);
1670
+ break;
1671
+ case "StateEntered":
1672
+ case "StateExited":
1673
+ event.index = index;
1674
+ this.dispatch(event);
1675
+ break;
1676
+ case "ExecutionAborted":
1677
+ case "ExecutionTimeout":
1678
+ return;
1679
+ default:
1680
+ this.dispatch(event);
1681
+ break;
1682
+ }
1683
+ }
1684
+ /**
1685
+ * Forward nested events created by `Parallel` states, to the root state machine event logger.
1686
+ * @param event An event dispatched by the nested state machines spawned by a `Parallel` state.
1687
+ * @param parallelStateName Name of the `Parallel` state being executed.
1688
+ * @param parallelStateRawInput Raw input passed to the `Parallel` state being executed.
1689
+ */
1690
+ forwardNestedParallelEvent(event, parallelStateName, parallelStateRawInput) {
1691
+ switch (event.type) {
1692
+ case "ExecutionStarted":
1693
+ this.dispatchParallelBranchStartedEvent(event, parallelStateName, parallelStateRawInput);
1694
+ break;
1695
+ case "ExecutionSucceeded":
1696
+ this.dispatchParallelBranchSucceededEvent(event, parallelStateName, parallelStateRawInput);
1697
+ break;
1698
+ case "ExecutionFailed":
1699
+ this.dispatchParallelBranchFailedEvent(event, parallelStateName, parallelStateRawInput);
1700
+ break;
1701
+ case "ExecutionAborted":
1702
+ case "ExecutionTimeout":
1703
+ return;
1704
+ default:
1705
+ this.dispatch(event);
1706
+ break;
1707
+ }
1708
+ }
1709
+ dispatchExecutionStartedEvent(input) {
1710
+ this.dispatch({ type: "ExecutionStarted", timestamp: Date.now(), input });
1711
+ }
1712
+ dispatchExecutionSucceededEvent(output) {
1713
+ this.dispatch({ type: "ExecutionSucceeded", timestamp: Date.now(), output });
1714
+ this.close();
1715
+ }
1716
+ dispatchExecutionFailedEvent(error) {
1717
+ this.dispatch({ type: "ExecutionFailed", timestamp: Date.now(), Error: error.name, Cause: error.message });
1718
+ this.close();
1719
+ }
1720
+ dispatchExecutionAbortedEvent() {
1721
+ this.dispatch({ type: "ExecutionAborted", timestamp: Date.now() });
1722
+ this.close();
1723
+ }
1724
+ dispatchExecutionTimeoutEvent() {
1725
+ this.dispatch({ type: "ExecutionTimeout", timestamp: Date.now() });
1726
+ this.close();
1727
+ }
1728
+ dispatchStateEnteredEvent(stateName, stateType, input) {
1729
+ this.dispatch({
1730
+ type: "StateEntered",
1731
+ timestamp: Date.now(),
1732
+ state: { name: stateName, type: stateType, input }
1733
+ });
1734
+ }
1735
+ dispatchStateExitedEvent(stateName, stateType, input, output) {
1736
+ this.dispatch({
1737
+ type: "StateExited",
1738
+ timestamp: Date.now(),
1739
+ state: { name: stateName, type: stateType, input, output }
1740
+ });
1741
+ }
1742
+ dispatchMapIterationStartedEvent(event, index, mapStateName, mapStateRawInput) {
1743
+ this.dispatch({
1744
+ ...event,
1745
+ type: "MapIterationStarted",
1746
+ index,
1747
+ parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
1748
+ });
1749
+ }
1750
+ dispatchMapIterationSucceededEvent(event, index, mapStateName, mapStateRawInput) {
1751
+ this.dispatch({
1752
+ ...event,
1753
+ type: "MapIterationSucceeded",
1754
+ index,
1755
+ parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
1756
+ });
1757
+ }
1758
+ dispatchMapIterationFailedEvent(event, index, mapStateName, mapStateRawInput) {
1759
+ this.dispatch({
1760
+ ...event,
1761
+ type: "MapIterationFailed",
1762
+ index,
1763
+ parentState: { type: "Map", name: mapStateName, input: mapStateRawInput }
1764
+ });
1765
+ }
1766
+ dispatchParallelBranchStartedEvent(event, parallelStateName, parallelStateRawInput) {
1767
+ this.dispatch({
1768
+ ...event,
1769
+ type: "ParallelBranchStarted",
1770
+ parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
1771
+ });
1772
+ }
1773
+ dispatchParallelBranchSucceededEvent(event, parallelStateName, parallelStateRawInput) {
1774
+ this.dispatch({
1775
+ ...event,
1776
+ type: "ParallelBranchSucceeded",
1777
+ parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
1778
+ });
1779
+ }
1780
+ dispatchParallelBranchFailedEvent(event, parallelStateName, parallelStateRawInput) {
1781
+ this.dispatch({
1782
+ ...event,
1783
+ type: "ParallelBranchFailed",
1784
+ parentState: { type: "Parallel", name: parallelStateName, input: parallelStateRawInput }
1785
+ });
1786
+ }
1787
+ close() {
1788
+ this.isLoggerClosed = true;
1789
+ this.eventTarget.dispatchEvent(new Event("newEvent"));
1790
+ }
1791
+ dispatch(event) {
1792
+ if (this.isLoggerClosed)
1793
+ return;
1794
+ this.eventQueue.push(event);
1795
+ this.eventTarget.dispatchEvent(new Event("newEvent"));
1796
+ }
1797
+ waitForNewEvent() {
1798
+ if (this.isLoggerClosed)
1799
+ return;
1800
+ return new Promise((resolve) => {
1801
+ this.eventTarget.addEventListener("newEvent", resolve, { once: true });
1802
+ });
1803
+ }
1804
+ };
1805
+
1585
1806
  // src/stateMachine/StateMachine.ts
1586
1807
  import aslValidator from "asl-validator";
1587
1808
  import cloneDeep3 from "lodash/cloneDeep.js";
@@ -1593,14 +1814,16 @@ var StateMachine = class {
1593
1814
  * These options also apply to state machines defined in the `Iterator` field of `Map` states and in the `Branches` field of `Parallel` states.
1594
1815
  */
1595
1816
  constructor(definition, stateMachineOptions) {
1596
- const { isValid, errorsText } = aslValidator(definition, {
1597
- checkArn: true,
1598
- checkPaths: true,
1599
- ...stateMachineOptions?.validationOptions
1600
- });
1601
- if (!isValid) {
1602
- throw new Error(`State machine definition is invalid, see error(s) below:
1817
+ if (!stateMachineOptions?.validationOptions?._noValidate) {
1818
+ const { isValid, errorsText } = aslValidator(definition, {
1819
+ checkArn: true,
1820
+ checkPaths: true,
1821
+ ...stateMachineOptions?.validationOptions
1822
+ });
1823
+ if (!isValid) {
1824
+ throw new Error(`State machine definition is invalid, see error(s) below:
1603
1825
  ${errorsText("\n")}`);
1826
+ }
1604
1827
  }
1605
1828
  this.definition = definition;
1606
1829
  this.stateMachineOptions = stateMachineOptions;
@@ -1610,6 +1833,9 @@ var StateMachine = class {
1610
1833
  * If the execution fails, the result will throw an `ExecutionError` explaining why the
1611
1834
  * execution failed.
1612
1835
  *
1836
+ * If the execution times out because the number of seconds specified in
1837
+ * the `TimeoutSeconds` top-level field has elapsed, the result will throw an `ExecutionTimeoutError`.
1838
+ *
1613
1839
  * By default, if the execution is aborted, the result will throw an `ExecutionAbortedError`. This behavior can be changed by setting
1614
1840
  * the `noThrowOnAbort` option to `true`, in which case the result will be `null`.
1615
1841
  *
@@ -1618,30 +1844,47 @@ var StateMachine = class {
1618
1844
  */
1619
1845
  run(input, options) {
1620
1846
  const abortController = new AbortController();
1847
+ const eventLogger = new EventLogger();
1621
1848
  let onAbortHandler;
1622
1849
  const settleOnAbort = new Promise((resolve, reject) => {
1623
1850
  if (options?.noThrowOnAbort) {
1624
- onAbortHandler = () => resolve(null);
1851
+ onAbortHandler = () => {
1852
+ eventLogger.dispatchExecutionAbortedEvent();
1853
+ resolve(null);
1854
+ };
1625
1855
  } else {
1626
- onAbortHandler = () => reject(new ExecutionAbortedError());
1856
+ onAbortHandler = () => {
1857
+ eventLogger.dispatchExecutionAbortedEvent();
1858
+ reject(new ExecutionAbortedError());
1859
+ };
1627
1860
  }
1628
1861
  abortController.signal.addEventListener("abort", onAbortHandler);
1629
1862
  });
1630
- let rejectOnTimeout = null;
1631
- if (this.definition.TimeoutSeconds) {
1863
+ let rejectOnTimeout;
1864
+ let timeoutId;
1865
+ if (this.definition.TimeoutSeconds !== void 0) {
1632
1866
  rejectOnTimeout = new Promise((_, reject) => {
1633
- setTimeout(() => {
1867
+ timeoutId = setTimeout(() => {
1634
1868
  abortController.signal.removeEventListener("abort", onAbortHandler);
1635
1869
  abortController.abort();
1636
- reject(new StatesTimeoutError());
1870
+ eventLogger.dispatchExecutionTimeoutEvent();
1871
+ reject(new ExecutionTimeoutError());
1637
1872
  }, this.definition.TimeoutSeconds * 1e3);
1638
1873
  });
1639
1874
  }
1640
- const executionResult = this.execute(input, {
1641
- stateMachineOptions: this.stateMachineOptions,
1642
- runOptions: options,
1643
- abortSignal: abortController.signal
1644
- });
1875
+ const executionResult = this.execute(
1876
+ input,
1877
+ {
1878
+ stateMachineOptions: this.stateMachineOptions,
1879
+ runOptions: { ...options, _rootAbortSignal: options?._rootAbortSignal ?? abortController.signal },
1880
+ abortSignal: abortController.signal,
1881
+ eventLogger
1882
+ },
1883
+ () => {
1884
+ abortController.signal.removeEventListener("abort", onAbortHandler);
1885
+ clearTimeout(timeoutId);
1886
+ }
1887
+ );
1645
1888
  const racingPromises = [executionResult, settleOnAbort];
1646
1889
  if (rejectOnTimeout) {
1647
1890
  racingPromises.push(rejectOnTimeout);
@@ -1649,37 +1892,45 @@ var StateMachine = class {
1649
1892
  const result = Promise.race(racingPromises);
1650
1893
  return {
1651
1894
  abort: () => abortController.abort(),
1895
+ eventLogs: eventLogger.getEvents(),
1652
1896
  result
1653
1897
  };
1654
1898
  }
1655
1899
  /**
1656
1900
  * Helper method that handles the execution of the machine states and the transitions between them.
1657
1901
  */
1658
- async execute(input, options) {
1902
+ async execute(input, options, cleanupFn) {
1903
+ options.eventLogger.dispatchExecutionStartedEvent(input);
1904
+ const context = options.runOptions?.context ?? {};
1659
1905
  let currState = this.definition.States[this.definition.StartAt];
1660
1906
  let currStateName = this.definition.StartAt;
1661
1907
  let currInput = cloneDeep3(input);
1662
1908
  let currResult = null;
1663
1909
  let nextState = "";
1664
1910
  let isEndState = false;
1665
- let context = {};
1666
1911
  try {
1667
1912
  do {
1913
+ options.eventLogger.dispatchStateEnteredEvent(currStateName, currState.Type, currInput);
1668
1914
  const stateExecutor = new StateExecutor(currStateName, currState);
1669
1915
  ({ stateResult: currResult, nextState, isEndState } = await stateExecutor.execute(currInput, context, options));
1916
+ options.eventLogger.dispatchStateExitedEvent(currStateName, currState.Type, currInput, currResult);
1670
1917
  currInput = currResult;
1671
1918
  currState = this.definition.States[nextState];
1672
1919
  currStateName = nextState;
1673
1920
  } while (!isEndState && !options.abortSignal.aborted);
1674
1921
  } catch (error) {
1922
+ options.eventLogger.dispatchExecutionFailedEvent(error);
1675
1923
  throw new ExecutionError(error);
1924
+ } finally {
1925
+ cleanupFn();
1676
1926
  }
1927
+ options.eventLogger.dispatchExecutionSucceededEvent(currResult);
1677
1928
  return currResult;
1678
1929
  }
1679
1930
  };
1680
1931
  export {
1681
1932
  ExecutionAbortedError,
1682
1933
  ExecutionError,
1683
- StatesTimeoutError as ExecutionTimeoutError,
1934
+ ExecutionTimeoutError,
1684
1935
  StateMachine
1685
1936
  };