aws-local-stepfunctions 2.0.1 → 3.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.
- package/bin/CLI.cjs +1 -1
- package/build/main.browser.esm.js +27940 -20366
- package/build/main.node.cjs +106 -57
- package/build/main.node.esm.js +106 -57
- package/package.json +18 -19
package/build/main.node.cjs
CHANGED
|
@@ -134,6 +134,81 @@ function clamp(value, min, max) {
|
|
|
134
134
|
if (max && value > max) return max;
|
|
135
135
|
return value;
|
|
136
136
|
}
|
|
137
|
+
function cloneJSON(value) {
|
|
138
|
+
if (value === null || typeof value !== "object") return value;
|
|
139
|
+
if (Array.isArray(value)) return value.map(cloneJSON);
|
|
140
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, cloneJSON(v)]));
|
|
141
|
+
}
|
|
142
|
+
function isEqualJSON(a, b) {
|
|
143
|
+
if (a === b) return true;
|
|
144
|
+
if (a === null || b === null) return false;
|
|
145
|
+
if (typeof a !== "object" || typeof b !== "object") return false;
|
|
146
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
147
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
148
|
+
if (a.length !== b.length) return false;
|
|
149
|
+
return a.every((v, i) => isEqualJSON(v, b[i]));
|
|
150
|
+
}
|
|
151
|
+
const aObj = a;
|
|
152
|
+
const bObj = b;
|
|
153
|
+
const aKeys = Object.keys(aObj);
|
|
154
|
+
const bKeys = Object.keys(bObj);
|
|
155
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
156
|
+
return aKeys.every((k) => Object.prototype.hasOwnProperty.call(bObj, k) && isEqualJSON(aObj[k], bObj[k]));
|
|
157
|
+
}
|
|
158
|
+
function setJSONPath(obj, path, value) {
|
|
159
|
+
function parseSegments(p) {
|
|
160
|
+
const segments = [];
|
|
161
|
+
let current = "";
|
|
162
|
+
let i = 0;
|
|
163
|
+
while (i < p.length) {
|
|
164
|
+
const ch = p[i];
|
|
165
|
+
if (ch === ".") {
|
|
166
|
+
if (current.length > 0) {
|
|
167
|
+
segments.push(current);
|
|
168
|
+
current = "";
|
|
169
|
+
}
|
|
170
|
+
i++;
|
|
171
|
+
} else if (ch === "[") {
|
|
172
|
+
if (current.length > 0) {
|
|
173
|
+
segments.push(current);
|
|
174
|
+
current = "";
|
|
175
|
+
}
|
|
176
|
+
i++;
|
|
177
|
+
const quote = p[i];
|
|
178
|
+
if (quote === '"' || quote === "'") {
|
|
179
|
+
i++;
|
|
180
|
+
while (i < p.length && p[i] !== quote) current += p[i++];
|
|
181
|
+
i++;
|
|
182
|
+
segments.push(current);
|
|
183
|
+
} else {
|
|
184
|
+
while (i < p.length && p[i] !== "]") current += p[i++];
|
|
185
|
+
segments.push(parseInt(current, 10));
|
|
186
|
+
}
|
|
187
|
+
current = "";
|
|
188
|
+
i++;
|
|
189
|
+
} else {
|
|
190
|
+
current += ch;
|
|
191
|
+
i++;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (current.length > 0) segments.push(current);
|
|
195
|
+
return segments;
|
|
196
|
+
}
|
|
197
|
+
function setAtSegments(target, segments) {
|
|
198
|
+
if (segments.length === 0) return value;
|
|
199
|
+
const [head, ...tail] = segments;
|
|
200
|
+
if (typeof head === "number") {
|
|
201
|
+
const arr = Array.isArray(target) ? [...target] : [];
|
|
202
|
+
arr[head] = setAtSegments(arr[head] !== void 0 ? arr[head] : null, tail);
|
|
203
|
+
return arr;
|
|
204
|
+
}
|
|
205
|
+
const o = typeof target === "object" && target !== null && !Array.isArray(target) ? { ...target } : {};
|
|
206
|
+
const existing = o[head];
|
|
207
|
+
o[head] = setAtSegments(existing !== void 0 ? existing : null, tail);
|
|
208
|
+
return o;
|
|
209
|
+
}
|
|
210
|
+
return setAtSegments(obj, parseSegments(path));
|
|
211
|
+
}
|
|
137
212
|
|
|
138
213
|
// src/stateMachine/jsonPath/JsonPath.ts
|
|
139
214
|
var import_jsonpath_plus = require("jsonpath-plus");
|
|
@@ -454,7 +529,6 @@ var StatesArrayPartition = class extends BaseIntrinsicFunction {
|
|
|
454
529
|
};
|
|
455
530
|
|
|
456
531
|
// src/stateMachine/intrinsicFunctions/StatesArrayContains.ts
|
|
457
|
-
var import_isEqual = __toESM(require("lodash/isEqual.js"), 1);
|
|
458
532
|
var StatesArrayContains = class extends BaseIntrinsicFunction {
|
|
459
533
|
funcDefinition;
|
|
460
534
|
constructor() {
|
|
@@ -473,7 +547,7 @@ var StatesArrayContains = class extends BaseIntrinsicFunction {
|
|
|
473
547
|
};
|
|
474
548
|
}
|
|
475
549
|
execute(array, searchVal) {
|
|
476
|
-
return array.
|
|
550
|
+
return array.some((val) => isEqualJSON(val, searchVal));
|
|
477
551
|
}
|
|
478
552
|
};
|
|
479
553
|
|
|
@@ -561,8 +635,6 @@ var StatesArrayLength = class extends BaseIntrinsicFunction {
|
|
|
561
635
|
};
|
|
562
636
|
|
|
563
637
|
// src/stateMachine/intrinsicFunctions/StatesArrayUnique.ts
|
|
564
|
-
var import_isEqual2 = __toESM(require("lodash/isEqual.js"), 1);
|
|
565
|
-
var import_uniqWith = __toESM(require("lodash/uniqWith.js"), 1);
|
|
566
638
|
var StatesArrayUnique = class extends BaseIntrinsicFunction {
|
|
567
639
|
funcDefinition;
|
|
568
640
|
constructor() {
|
|
@@ -578,7 +650,7 @@ var StatesArrayUnique = class extends BaseIntrinsicFunction {
|
|
|
578
650
|
};
|
|
579
651
|
}
|
|
580
652
|
execute(array) {
|
|
581
|
-
return (
|
|
653
|
+
return array.filter((val, i) => array.findIndex((other) => isEqualJSON(val, other)) === i);
|
|
582
654
|
}
|
|
583
655
|
};
|
|
584
656
|
|
|
@@ -1663,8 +1735,6 @@ function evaluateIntrinsicFunction(intrinsicFunction, input, context) {
|
|
|
1663
1735
|
}
|
|
1664
1736
|
|
|
1665
1737
|
// src/stateMachine/InputOutputProcessing.ts
|
|
1666
|
-
var import_cloneDeep = __toESM(require("lodash/cloneDeep.js"), 1);
|
|
1667
|
-
var import_set = __toESM(require("lodash/set.js"), 1);
|
|
1668
1738
|
function processInputPath(path, input, context) {
|
|
1669
1739
|
if (path === void 0) {
|
|
1670
1740
|
return input;
|
|
@@ -1711,8 +1781,7 @@ function processResultPath(path, rawInput, result) {
|
|
|
1711
1781
|
}
|
|
1712
1782
|
const sanitizedPath = path.replace("$.", "");
|
|
1713
1783
|
if (isPlainObj(rawInput)) {
|
|
1714
|
-
|
|
1715
|
-
return (0, import_set.default)(clonedRawInput, sanitizedPath, result);
|
|
1784
|
+
return setJSONPath(rawInput, sanitizedPath, result);
|
|
1716
1785
|
}
|
|
1717
1786
|
throw new StatesResultPathMatchFailureError();
|
|
1718
1787
|
}
|
|
@@ -2357,16 +2426,14 @@ var LambdaClient = class {
|
|
|
2357
2426
|
};
|
|
2358
2427
|
|
|
2359
2428
|
// src/stateMachine/stateActions/TaskStateAction.ts
|
|
2429
|
+
var DEFAULT_TIMEOUT_SECONDS = 60;
|
|
2360
2430
|
var TaskStateAction = class extends BaseStateAction {
|
|
2361
|
-
timeoutAbortController;
|
|
2362
2431
|
constructor(stateDefinition, stateName) {
|
|
2363
2432
|
super(stateDefinition, stateName);
|
|
2364
|
-
this.timeoutAbortController = new AbortController();
|
|
2365
2433
|
}
|
|
2366
|
-
|
|
2434
|
+
getTimeoutMs(input, context) {
|
|
2367
2435
|
const state = this.stateDefinition;
|
|
2368
|
-
|
|
2369
|
-
let timeout;
|
|
2436
|
+
let timeout = DEFAULT_TIMEOUT_SECONDS;
|
|
2370
2437
|
if (state.TimeoutSeconds) {
|
|
2371
2438
|
timeout = state.TimeoutSeconds;
|
|
2372
2439
|
} else if (state.TimeoutSecondsPath) {
|
|
@@ -2374,33 +2441,26 @@ var TaskStateAction = class extends BaseStateAction {
|
|
|
2374
2441
|
constraints: [IntegerConstraint.greaterThanOrEqual(1)]
|
|
2375
2442
|
});
|
|
2376
2443
|
}
|
|
2377
|
-
return
|
|
2378
|
-
const handleTimeoutAbort = () => clearTimeout(timeoutId);
|
|
2379
|
-
const timeoutId = setTimeout(() => {
|
|
2380
|
-
this.timeoutAbortController.signal.removeEventListener("abort", handleTimeoutAbort);
|
|
2381
|
-
reject(new StatesTimeoutError());
|
|
2382
|
-
}, timeout * 1e3);
|
|
2383
|
-
this.timeoutAbortController.signal.addEventListener("abort", handleTimeoutAbort, { once: true });
|
|
2384
|
-
});
|
|
2444
|
+
return timeout * 1e3;
|
|
2385
2445
|
}
|
|
2386
2446
|
async execute(input, context, options) {
|
|
2387
2447
|
const state = this.stateDefinition;
|
|
2388
|
-
const
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2448
|
+
const taskPromise = options.overrideFn ? (
|
|
2449
|
+
// If local override for task resource is defined, use that
|
|
2450
|
+
options.overrideFn(input)
|
|
2451
|
+
) : (
|
|
2452
|
+
// Else, call Lambda in AWS using SDK
|
|
2453
|
+
new LambdaClient(options.awsConfig).invokeFunction(state.Resource, input)
|
|
2454
|
+
);
|
|
2455
|
+
const timeoutMs = this.getTimeoutMs(input, context);
|
|
2456
|
+
const { promise: timeoutPromise, reject: rejectTimeout } = Promise.withResolvers();
|
|
2457
|
+
const timeoutId = setTimeout(() => rejectTimeout(new StatesTimeoutError()), timeoutMs);
|
|
2458
|
+
try {
|
|
2459
|
+
const result = await Promise.race([taskPromise, timeoutPromise]);
|
|
2460
|
+
return this.buildExecutionResult(result);
|
|
2461
|
+
} finally {
|
|
2462
|
+
clearTimeout(timeoutId);
|
|
2400
2463
|
}
|
|
2401
|
-
const result = await Promise.race(racingPromises);
|
|
2402
|
-
this.timeoutAbortController.abort();
|
|
2403
|
-
return this.buildExecutionResult(result);
|
|
2404
2464
|
}
|
|
2405
2465
|
};
|
|
2406
2466
|
|
|
@@ -2441,7 +2501,6 @@ var WaitStateAction = class extends BaseStateAction {
|
|
|
2441
2501
|
};
|
|
2442
2502
|
|
|
2443
2503
|
// src/stateMachine/StateExecutor.ts
|
|
2444
|
-
var import_cloneDeep2 = __toESM(require("lodash/cloneDeep.js"), 1);
|
|
2445
2504
|
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
2446
2505
|
var DEFAULT_INTERVAL_SECONDS = 1;
|
|
2447
2506
|
var DEFAULT_BACKOFF_RATE = 2;
|
|
@@ -2484,7 +2543,7 @@ var StateExecutor = class {
|
|
|
2484
2543
|
* Execute the current state.
|
|
2485
2544
|
*/
|
|
2486
2545
|
async execute(input, context, options) {
|
|
2487
|
-
const rawInput = (
|
|
2546
|
+
const rawInput = cloneJSON(input);
|
|
2488
2547
|
try {
|
|
2489
2548
|
const processedInput = this.processInput(input, context);
|
|
2490
2549
|
const {
|
|
@@ -2766,7 +2825,7 @@ var EventLogger = class {
|
|
|
2766
2825
|
if (this.eventQueue.length === 0) {
|
|
2767
2826
|
await this.waitForNewEvent();
|
|
2768
2827
|
}
|
|
2769
|
-
let event
|
|
2828
|
+
let event;
|
|
2770
2829
|
while (event = this.eventQueue.shift()) {
|
|
2771
2830
|
yield event;
|
|
2772
2831
|
}
|
|
@@ -2959,7 +3018,6 @@ var EventLogger = class {
|
|
|
2959
3018
|
|
|
2960
3019
|
// src/stateMachine/StateMachine.ts
|
|
2961
3020
|
var import_asl_validator = __toESM(require("asl-validator"), 1);
|
|
2962
|
-
var import_cloneDeep3 = __toESM(require("lodash/cloneDeep.js"), 1);
|
|
2963
3021
|
var StateMachine = class {
|
|
2964
3022
|
/**
|
|
2965
3023
|
* The structure of the State Machine as represented by the Amazon States Language.
|
|
@@ -3007,15 +3065,7 @@ var StateMachine = class {
|
|
|
3007
3065
|
run(input, options) {
|
|
3008
3066
|
const abortController = new AbortController();
|
|
3009
3067
|
const eventLogger = new EventLogger();
|
|
3010
|
-
|
|
3011
|
-
if (options?._rootAbortSignal) {
|
|
3012
|
-
rootSignalAbortHandler = () => abortController.abort();
|
|
3013
|
-
if (options._rootAbortSignal.aborted) {
|
|
3014
|
-
rootSignalAbortHandler();
|
|
3015
|
-
} else {
|
|
3016
|
-
options._rootAbortSignal.addEventListener("abort", rootSignalAbortHandler);
|
|
3017
|
-
}
|
|
3018
|
-
}
|
|
3068
|
+
const abortSignal = options?._rootAbortSignal ? AbortSignal.any([abortController.signal, options._rootAbortSignal]) : abortController.signal;
|
|
3019
3069
|
let onAbortHandler;
|
|
3020
3070
|
const settleOnAbort = new Promise((resolve, reject) => {
|
|
3021
3071
|
if (options?.noThrowOnAbort) {
|
|
@@ -3029,14 +3079,14 @@ var StateMachine = class {
|
|
|
3029
3079
|
reject(new ExecutionAbortedError());
|
|
3030
3080
|
};
|
|
3031
3081
|
}
|
|
3032
|
-
|
|
3082
|
+
abortSignal.addEventListener("abort", onAbortHandler);
|
|
3033
3083
|
});
|
|
3034
3084
|
let rejectOnTimeout;
|
|
3035
3085
|
let timeoutId;
|
|
3036
3086
|
if (this.definition.TimeoutSeconds !== void 0) {
|
|
3037
3087
|
rejectOnTimeout = new Promise((_, reject) => {
|
|
3038
3088
|
timeoutId = setTimeout(() => {
|
|
3039
|
-
|
|
3089
|
+
abortSignal.removeEventListener("abort", onAbortHandler);
|
|
3040
3090
|
abortController.abort();
|
|
3041
3091
|
eventLogger.dispatchExecutionTimeoutEvent();
|
|
3042
3092
|
reject(new ExecutionTimeoutError());
|
|
@@ -3047,13 +3097,12 @@ var StateMachine = class {
|
|
|
3047
3097
|
input,
|
|
3048
3098
|
{
|
|
3049
3099
|
stateMachineOptions: this.stateMachineOptions,
|
|
3050
|
-
runOptions: { ...options, _rootAbortSignal:
|
|
3051
|
-
abortSignal
|
|
3100
|
+
runOptions: { ...options, _rootAbortSignal: abortSignal },
|
|
3101
|
+
abortSignal,
|
|
3052
3102
|
eventLogger
|
|
3053
3103
|
},
|
|
3054
3104
|
() => {
|
|
3055
|
-
|
|
3056
|
-
options?._rootAbortSignal?.removeEventListener("abort", rootSignalAbortHandler);
|
|
3105
|
+
abortSignal.removeEventListener("abort", onAbortHandler);
|
|
3057
3106
|
clearTimeout(timeoutId);
|
|
3058
3107
|
}
|
|
3059
3108
|
);
|
|
@@ -3083,7 +3132,7 @@ var StateMachine = class {
|
|
|
3083
3132
|
};
|
|
3084
3133
|
let currState = this.definition.States[this.definition.StartAt];
|
|
3085
3134
|
let currStateName = this.definition.StartAt;
|
|
3086
|
-
let currInput = (
|
|
3135
|
+
let currInput = cloneJSON(input);
|
|
3087
3136
|
let currResult = null;
|
|
3088
3137
|
let nextState = "";
|
|
3089
3138
|
let isEndState = false;
|
package/build/main.node.esm.js
CHANGED
|
@@ -95,6 +95,81 @@ function clamp(value, min, max) {
|
|
|
95
95
|
if (max && value > max) return max;
|
|
96
96
|
return value;
|
|
97
97
|
}
|
|
98
|
+
function cloneJSON(value) {
|
|
99
|
+
if (value === null || typeof value !== "object") return value;
|
|
100
|
+
if (Array.isArray(value)) return value.map(cloneJSON);
|
|
101
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, cloneJSON(v)]));
|
|
102
|
+
}
|
|
103
|
+
function isEqualJSON(a, b) {
|
|
104
|
+
if (a === b) return true;
|
|
105
|
+
if (a === null || b === null) return false;
|
|
106
|
+
if (typeof a !== "object" || typeof b !== "object") return false;
|
|
107
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
108
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
109
|
+
if (a.length !== b.length) return false;
|
|
110
|
+
return a.every((v, i) => isEqualJSON(v, b[i]));
|
|
111
|
+
}
|
|
112
|
+
const aObj = a;
|
|
113
|
+
const bObj = b;
|
|
114
|
+
const aKeys = Object.keys(aObj);
|
|
115
|
+
const bKeys = Object.keys(bObj);
|
|
116
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
117
|
+
return aKeys.every((k) => Object.prototype.hasOwnProperty.call(bObj, k) && isEqualJSON(aObj[k], bObj[k]));
|
|
118
|
+
}
|
|
119
|
+
function setJSONPath(obj, path, value) {
|
|
120
|
+
function parseSegments(p) {
|
|
121
|
+
const segments = [];
|
|
122
|
+
let current = "";
|
|
123
|
+
let i = 0;
|
|
124
|
+
while (i < p.length) {
|
|
125
|
+
const ch = p[i];
|
|
126
|
+
if (ch === ".") {
|
|
127
|
+
if (current.length > 0) {
|
|
128
|
+
segments.push(current);
|
|
129
|
+
current = "";
|
|
130
|
+
}
|
|
131
|
+
i++;
|
|
132
|
+
} else if (ch === "[") {
|
|
133
|
+
if (current.length > 0) {
|
|
134
|
+
segments.push(current);
|
|
135
|
+
current = "";
|
|
136
|
+
}
|
|
137
|
+
i++;
|
|
138
|
+
const quote = p[i];
|
|
139
|
+
if (quote === '"' || quote === "'") {
|
|
140
|
+
i++;
|
|
141
|
+
while (i < p.length && p[i] !== quote) current += p[i++];
|
|
142
|
+
i++;
|
|
143
|
+
segments.push(current);
|
|
144
|
+
} else {
|
|
145
|
+
while (i < p.length && p[i] !== "]") current += p[i++];
|
|
146
|
+
segments.push(parseInt(current, 10));
|
|
147
|
+
}
|
|
148
|
+
current = "";
|
|
149
|
+
i++;
|
|
150
|
+
} else {
|
|
151
|
+
current += ch;
|
|
152
|
+
i++;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (current.length > 0) segments.push(current);
|
|
156
|
+
return segments;
|
|
157
|
+
}
|
|
158
|
+
function setAtSegments(target, segments) {
|
|
159
|
+
if (segments.length === 0) return value;
|
|
160
|
+
const [head, ...tail] = segments;
|
|
161
|
+
if (typeof head === "number") {
|
|
162
|
+
const arr = Array.isArray(target) ? [...target] : [];
|
|
163
|
+
arr[head] = setAtSegments(arr[head] !== void 0 ? arr[head] : null, tail);
|
|
164
|
+
return arr;
|
|
165
|
+
}
|
|
166
|
+
const o = typeof target === "object" && target !== null && !Array.isArray(target) ? { ...target } : {};
|
|
167
|
+
const existing = o[head];
|
|
168
|
+
o[head] = setAtSegments(existing !== void 0 ? existing : null, tail);
|
|
169
|
+
return o;
|
|
170
|
+
}
|
|
171
|
+
return setAtSegments(obj, parseSegments(path));
|
|
172
|
+
}
|
|
98
173
|
|
|
99
174
|
// src/stateMachine/jsonPath/JsonPath.ts
|
|
100
175
|
import { JSONPath as jp } from "jsonpath-plus";
|
|
@@ -415,7 +490,6 @@ var StatesArrayPartition = class extends BaseIntrinsicFunction {
|
|
|
415
490
|
};
|
|
416
491
|
|
|
417
492
|
// src/stateMachine/intrinsicFunctions/StatesArrayContains.ts
|
|
418
|
-
import isEqual from "lodash/isEqual.js";
|
|
419
493
|
var StatesArrayContains = class extends BaseIntrinsicFunction {
|
|
420
494
|
funcDefinition;
|
|
421
495
|
constructor() {
|
|
@@ -434,7 +508,7 @@ var StatesArrayContains = class extends BaseIntrinsicFunction {
|
|
|
434
508
|
};
|
|
435
509
|
}
|
|
436
510
|
execute(array, searchVal) {
|
|
437
|
-
return array.
|
|
511
|
+
return array.some((val) => isEqualJSON(val, searchVal));
|
|
438
512
|
}
|
|
439
513
|
};
|
|
440
514
|
|
|
@@ -522,8 +596,6 @@ var StatesArrayLength = class extends BaseIntrinsicFunction {
|
|
|
522
596
|
};
|
|
523
597
|
|
|
524
598
|
// src/stateMachine/intrinsicFunctions/StatesArrayUnique.ts
|
|
525
|
-
import isEqual2 from "lodash/isEqual.js";
|
|
526
|
-
import uniqWith from "lodash/uniqWith.js";
|
|
527
599
|
var StatesArrayUnique = class extends BaseIntrinsicFunction {
|
|
528
600
|
funcDefinition;
|
|
529
601
|
constructor() {
|
|
@@ -539,7 +611,7 @@ var StatesArrayUnique = class extends BaseIntrinsicFunction {
|
|
|
539
611
|
};
|
|
540
612
|
}
|
|
541
613
|
execute(array) {
|
|
542
|
-
return
|
|
614
|
+
return array.filter((val, i) => array.findIndex((other) => isEqualJSON(val, other)) === i);
|
|
543
615
|
}
|
|
544
616
|
};
|
|
545
617
|
|
|
@@ -1624,8 +1696,6 @@ function evaluateIntrinsicFunction(intrinsicFunction, input, context) {
|
|
|
1624
1696
|
}
|
|
1625
1697
|
|
|
1626
1698
|
// src/stateMachine/InputOutputProcessing.ts
|
|
1627
|
-
import cloneDeep from "lodash/cloneDeep.js";
|
|
1628
|
-
import set from "lodash/set.js";
|
|
1629
1699
|
function processInputPath(path, input, context) {
|
|
1630
1700
|
if (path === void 0) {
|
|
1631
1701
|
return input;
|
|
@@ -1672,8 +1742,7 @@ function processResultPath(path, rawInput, result) {
|
|
|
1672
1742
|
}
|
|
1673
1743
|
const sanitizedPath = path.replace("$.", "");
|
|
1674
1744
|
if (isPlainObj(rawInput)) {
|
|
1675
|
-
|
|
1676
|
-
return set(clonedRawInput, sanitizedPath, result);
|
|
1745
|
+
return setJSONPath(rawInput, sanitizedPath, result);
|
|
1677
1746
|
}
|
|
1678
1747
|
throw new StatesResultPathMatchFailureError();
|
|
1679
1748
|
}
|
|
@@ -2318,16 +2387,14 @@ var LambdaClient = class {
|
|
|
2318
2387
|
};
|
|
2319
2388
|
|
|
2320
2389
|
// src/stateMachine/stateActions/TaskStateAction.ts
|
|
2390
|
+
var DEFAULT_TIMEOUT_SECONDS = 60;
|
|
2321
2391
|
var TaskStateAction = class extends BaseStateAction {
|
|
2322
|
-
timeoutAbortController;
|
|
2323
2392
|
constructor(stateDefinition, stateName) {
|
|
2324
2393
|
super(stateDefinition, stateName);
|
|
2325
|
-
this.timeoutAbortController = new AbortController();
|
|
2326
2394
|
}
|
|
2327
|
-
|
|
2395
|
+
getTimeoutMs(input, context) {
|
|
2328
2396
|
const state = this.stateDefinition;
|
|
2329
|
-
|
|
2330
|
-
let timeout;
|
|
2397
|
+
let timeout = DEFAULT_TIMEOUT_SECONDS;
|
|
2331
2398
|
if (state.TimeoutSeconds) {
|
|
2332
2399
|
timeout = state.TimeoutSeconds;
|
|
2333
2400
|
} else if (state.TimeoutSecondsPath) {
|
|
@@ -2335,33 +2402,26 @@ var TaskStateAction = class extends BaseStateAction {
|
|
|
2335
2402
|
constraints: [IntegerConstraint.greaterThanOrEqual(1)]
|
|
2336
2403
|
});
|
|
2337
2404
|
}
|
|
2338
|
-
return
|
|
2339
|
-
const handleTimeoutAbort = () => clearTimeout(timeoutId);
|
|
2340
|
-
const timeoutId = setTimeout(() => {
|
|
2341
|
-
this.timeoutAbortController.signal.removeEventListener("abort", handleTimeoutAbort);
|
|
2342
|
-
reject(new StatesTimeoutError());
|
|
2343
|
-
}, timeout * 1e3);
|
|
2344
|
-
this.timeoutAbortController.signal.addEventListener("abort", handleTimeoutAbort, { once: true });
|
|
2345
|
-
});
|
|
2405
|
+
return timeout * 1e3;
|
|
2346
2406
|
}
|
|
2347
2407
|
async execute(input, context, options) {
|
|
2348
2408
|
const state = this.stateDefinition;
|
|
2349
|
-
const
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2409
|
+
const taskPromise = options.overrideFn ? (
|
|
2410
|
+
// If local override for task resource is defined, use that
|
|
2411
|
+
options.overrideFn(input)
|
|
2412
|
+
) : (
|
|
2413
|
+
// Else, call Lambda in AWS using SDK
|
|
2414
|
+
new LambdaClient(options.awsConfig).invokeFunction(state.Resource, input)
|
|
2415
|
+
);
|
|
2416
|
+
const timeoutMs = this.getTimeoutMs(input, context);
|
|
2417
|
+
const { promise: timeoutPromise, reject: rejectTimeout } = Promise.withResolvers();
|
|
2418
|
+
const timeoutId = setTimeout(() => rejectTimeout(new StatesTimeoutError()), timeoutMs);
|
|
2419
|
+
try {
|
|
2420
|
+
const result = await Promise.race([taskPromise, timeoutPromise]);
|
|
2421
|
+
return this.buildExecutionResult(result);
|
|
2422
|
+
} finally {
|
|
2423
|
+
clearTimeout(timeoutId);
|
|
2361
2424
|
}
|
|
2362
|
-
const result = await Promise.race(racingPromises);
|
|
2363
|
-
this.timeoutAbortController.abort();
|
|
2364
|
-
return this.buildExecutionResult(result);
|
|
2365
2425
|
}
|
|
2366
2426
|
};
|
|
2367
2427
|
|
|
@@ -2402,7 +2462,6 @@ var WaitStateAction = class extends BaseStateAction {
|
|
|
2402
2462
|
};
|
|
2403
2463
|
|
|
2404
2464
|
// src/stateMachine/StateExecutor.ts
|
|
2405
|
-
import cloneDeep2 from "lodash/cloneDeep.js";
|
|
2406
2465
|
var DEFAULT_MAX_ATTEMPTS = 3;
|
|
2407
2466
|
var DEFAULT_INTERVAL_SECONDS = 1;
|
|
2408
2467
|
var DEFAULT_BACKOFF_RATE = 2;
|
|
@@ -2445,7 +2504,7 @@ var StateExecutor = class {
|
|
|
2445
2504
|
* Execute the current state.
|
|
2446
2505
|
*/
|
|
2447
2506
|
async execute(input, context, options) {
|
|
2448
|
-
const rawInput =
|
|
2507
|
+
const rawInput = cloneJSON(input);
|
|
2449
2508
|
try {
|
|
2450
2509
|
const processedInput = this.processInput(input, context);
|
|
2451
2510
|
const {
|
|
@@ -2727,7 +2786,7 @@ var EventLogger = class {
|
|
|
2727
2786
|
if (this.eventQueue.length === 0) {
|
|
2728
2787
|
await this.waitForNewEvent();
|
|
2729
2788
|
}
|
|
2730
|
-
let event
|
|
2789
|
+
let event;
|
|
2731
2790
|
while (event = this.eventQueue.shift()) {
|
|
2732
2791
|
yield event;
|
|
2733
2792
|
}
|
|
@@ -2920,7 +2979,6 @@ var EventLogger = class {
|
|
|
2920
2979
|
|
|
2921
2980
|
// src/stateMachine/StateMachine.ts
|
|
2922
2981
|
import aslValidator from "asl-validator";
|
|
2923
|
-
import cloneDeep3 from "lodash/cloneDeep.js";
|
|
2924
2982
|
var StateMachine = class {
|
|
2925
2983
|
/**
|
|
2926
2984
|
* The structure of the State Machine as represented by the Amazon States Language.
|
|
@@ -2968,15 +3026,7 @@ var StateMachine = class {
|
|
|
2968
3026
|
run(input, options) {
|
|
2969
3027
|
const abortController = new AbortController();
|
|
2970
3028
|
const eventLogger = new EventLogger();
|
|
2971
|
-
|
|
2972
|
-
if (options?._rootAbortSignal) {
|
|
2973
|
-
rootSignalAbortHandler = () => abortController.abort();
|
|
2974
|
-
if (options._rootAbortSignal.aborted) {
|
|
2975
|
-
rootSignalAbortHandler();
|
|
2976
|
-
} else {
|
|
2977
|
-
options._rootAbortSignal.addEventListener("abort", rootSignalAbortHandler);
|
|
2978
|
-
}
|
|
2979
|
-
}
|
|
3029
|
+
const abortSignal = options?._rootAbortSignal ? AbortSignal.any([abortController.signal, options._rootAbortSignal]) : abortController.signal;
|
|
2980
3030
|
let onAbortHandler;
|
|
2981
3031
|
const settleOnAbort = new Promise((resolve, reject) => {
|
|
2982
3032
|
if (options?.noThrowOnAbort) {
|
|
@@ -2990,14 +3040,14 @@ var StateMachine = class {
|
|
|
2990
3040
|
reject(new ExecutionAbortedError());
|
|
2991
3041
|
};
|
|
2992
3042
|
}
|
|
2993
|
-
|
|
3043
|
+
abortSignal.addEventListener("abort", onAbortHandler);
|
|
2994
3044
|
});
|
|
2995
3045
|
let rejectOnTimeout;
|
|
2996
3046
|
let timeoutId;
|
|
2997
3047
|
if (this.definition.TimeoutSeconds !== void 0) {
|
|
2998
3048
|
rejectOnTimeout = new Promise((_, reject) => {
|
|
2999
3049
|
timeoutId = setTimeout(() => {
|
|
3000
|
-
|
|
3050
|
+
abortSignal.removeEventListener("abort", onAbortHandler);
|
|
3001
3051
|
abortController.abort();
|
|
3002
3052
|
eventLogger.dispatchExecutionTimeoutEvent();
|
|
3003
3053
|
reject(new ExecutionTimeoutError());
|
|
@@ -3008,13 +3058,12 @@ var StateMachine = class {
|
|
|
3008
3058
|
input,
|
|
3009
3059
|
{
|
|
3010
3060
|
stateMachineOptions: this.stateMachineOptions,
|
|
3011
|
-
runOptions: { ...options, _rootAbortSignal:
|
|
3012
|
-
abortSignal
|
|
3061
|
+
runOptions: { ...options, _rootAbortSignal: abortSignal },
|
|
3062
|
+
abortSignal,
|
|
3013
3063
|
eventLogger
|
|
3014
3064
|
},
|
|
3015
3065
|
() => {
|
|
3016
|
-
|
|
3017
|
-
options?._rootAbortSignal?.removeEventListener("abort", rootSignalAbortHandler);
|
|
3066
|
+
abortSignal.removeEventListener("abort", onAbortHandler);
|
|
3018
3067
|
clearTimeout(timeoutId);
|
|
3019
3068
|
}
|
|
3020
3069
|
);
|
|
@@ -3044,7 +3093,7 @@ var StateMachine = class {
|
|
|
3044
3093
|
};
|
|
3045
3094
|
let currState = this.definition.States[this.definition.StartAt];
|
|
3046
3095
|
let currStateName = this.definition.StartAt;
|
|
3047
|
-
let currInput =
|
|
3096
|
+
let currInput = cloneJSON(input);
|
|
3048
3097
|
let currResult = null;
|
|
3049
3098
|
let nextState = "";
|
|
3050
3099
|
let isEndState = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aws-local-stepfunctions",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Execute an AWS Step Function state machine locally",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"aws",
|
|
@@ -32,13 +32,13 @@
|
|
|
32
32
|
"browser": "build/main.browser.esm.js",
|
|
33
33
|
"exports": {
|
|
34
34
|
"types": "./build/main.d.ts",
|
|
35
|
+
"browser": "./build/main.browser.esm.js",
|
|
35
36
|
"import": "./build/main.node.esm.js",
|
|
36
37
|
"require": "./build/main.node.cjs",
|
|
37
|
-
"browser": "./build/main.browser.esm.js",
|
|
38
38
|
"default": "./build/main.browser.esm.js"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
|
-
"node": ">=
|
|
41
|
+
"node": ">=22.0.0"
|
|
42
42
|
},
|
|
43
43
|
"bin": {
|
|
44
44
|
"local-sfn": "./bin/CLI.cjs"
|
|
@@ -53,27 +53,26 @@
|
|
|
53
53
|
"lint:fix": "eslint --fix \"src/**/*.ts\""
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
+
"@eslint/js": "^8.57.1",
|
|
56
57
|
"@types/jest": "^29.5.14",
|
|
57
|
-
"@types/
|
|
58
|
-
"@types/node": "^18.19.64",
|
|
59
|
-
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
60
|
-
"@typescript-eslint/parser": "^6.21.0",
|
|
58
|
+
"@types/node": "^22.19.17",
|
|
61
59
|
"eslint": "^8.57.1",
|
|
62
|
-
"eslint-config-prettier": "^9.1.
|
|
63
|
-
"eslint-plugin-prettier": "^5.
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
60
|
+
"eslint-config-prettier": "^9.1.2",
|
|
61
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
62
|
+
"globals": "^17.4.0",
|
|
63
|
+
"prettier": "^3.8.2",
|
|
64
|
+
"ts-jest": "^29.4.9",
|
|
65
|
+
"tsup": "^8.5.1",
|
|
66
|
+
"typescript": "^5.9.3",
|
|
67
|
+
"typescript-eslint": "^8.58.1"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@aws-sdk/client-lambda": "^3.
|
|
71
|
-
"@aws-sdk/credential-providers": "^3.
|
|
72
|
-
"asl-validator": "^3.
|
|
70
|
+
"@aws-sdk/client-lambda": "^3.1029.0",
|
|
71
|
+
"@aws-sdk/credential-providers": "^3.1029.0",
|
|
72
|
+
"asl-validator": "^3.15.1",
|
|
73
73
|
"commander": "^11.1.0",
|
|
74
|
-
"jsonpath-plus": "^10.
|
|
75
|
-
"lodash": "^4.17.21",
|
|
74
|
+
"jsonpath-plus": "^10.4.0",
|
|
76
75
|
"p-limit": "^3.1.0",
|
|
77
|
-
"wildcard-match": "^5.1.
|
|
76
|
+
"wildcard-match": "^5.1.4"
|
|
78
77
|
}
|
|
79
78
|
}
|