@deliverr/serverless-offline-step-functions
Version:
Serverless Offline Plugin to Support Step Functions for Local Development
136 lines (135 loc) • 6.31 kB
JavaScript
"use strict";
const StepFunctionSimulatorServer_1 = require("./StepFunctionSimulatorServer");
const StateInfoHandler_1 = require("./StateInfoHandler");
const Logger_1 = require("./utils/Logger");
const StateType_1 = require("./stateTasks/StateType");
const EnvVarResolver_1 = require("./utils/EnvVarResolver");
const StateMachines_1 = require("./StateMachine/StateMachines");
class ServerlessOfflineStepFunctionsPlugin {
constructor(serverless, cliOptions) {
var _a, _b;
this.serverless = serverless;
this.cliOptions = cliOptions;
this.logger = Logger_1.Logger.getInstance();
this.commands = {
'@fernthedev/serverless-offline-step-functions': {
options: {
port: {
required: false,
usage: 'Port of the Step Functions API Simulator (Default: 8014)',
},
enabled: {
required: false,
usage: 'Enabled Step Function API Simulator (Default: true)',
},
debug: {
required: false,
usage: 'Enable Debugger Output (Default: false)',
},
},
},
};
this.mergeOptions();
if (((_a = this.options) === null || _a === void 0 ? void 0 : _a.enabled) === false) {
this.logger.warning('Simulator will not execute.');
return;
}
if (((_b = this.options) === null || _b === void 0 ? void 0 : _b.debug) === true) {
this.logger.turnOnDebugger();
}
this.hooks = {
'before:offline:start:init': this.start.bind(this),
'offline:start:init': this.ready.bind(this),
'offline:start:end': this.end.bind(this),
};
}
start() {
var _a, _b, _c, _d, _e;
const envVarResolver = EnvVarResolver_1.EnvVarResolver.getInstance();
envVarResolver.global = (_b = (_a = this.serverless.service.initialServerlessConfig) === null || _a === void 0 ? void 0 : _a.provider) === null || _b === void 0 ? void 0 : _b.environment;
envVarResolver.injectGlobalEnvVars();
const definedStateMachines = (_d = (_c = this.serverless.service.initialServerlessConfig) === null || _c === void 0 ? void 0 : _c.stepFunctions) === null || _d === void 0 ? void 0 : _d.stateMachines;
const stateMachines = StateMachines_1.StateMachines.create(definedStateMachines);
if (!stateMachines) {
throw new Error('No step machines defined');
}
this.resolveHandlers(stateMachines);
this.stepFunctionSimulatorServer = new StepFunctionSimulatorServer_1.StepFunctionSimulatorServer({
port: ((_e = this.options) === null || _e === void 0 ? void 0 : _e.port) || 8014,
stateMachines,
});
}
ready() {
var _a;
return (_a = this.stepFunctionSimulatorServer) === null || _a === void 0 ? void 0 : _a.initServer();
}
async end() {
var _a;
await ((_a = this.stepFunctionSimulatorServer) === null || _a === void 0 ? void 0 : _a.shutdown());
}
mergeOptions() {
const custom = this.serverless.service.custom;
const customOptions = custom['@fernthedev/serverless-offline-step-functions'];
this.options = {
...this.cliOptions,
...customOptions,
};
}
getFunctionName(stateOptions) {
var _a, _b;
let functionName;
const resource = stateOptions.Resource;
if (typeof resource === 'string') {
if (resource.endsWith('.waitForTaskToken')) {
functionName = (_b = (_a = stateOptions.Parameters) === null || _a === void 0 ? void 0 : _a.FunctionName) === null || _b === void 0 ? void 0 : _b['Fn::GetAtt'][0];
}
else {
functionName = resource.split('-').slice(-1)[0];
}
}
else {
for (const [key, value] of Object.entries(resource)) {
if (key === 'Fn::GetAtt') {
functionName = value[0];
}
}
}
if (!functionName) {
throw Error(`Could not find funciton name for resource ${resource}`);
}
return functionName;
}
setStateInfo(states, stateMachineName) {
var _a, _b;
const definedFunctions = this.serverless.service.initialServerlessConfig.functions;
const statesInfoHandler = StateInfoHandler_1.StateInfoHandler.getInstance();
this.logger.debug(`ServerlessOfflineStepFunctionsPlugin - setStateInfo - ${states}`);
for (const [stateName, stateOptions] of states) {
if (stateOptions.Type === StateType_1.StateType.Map) {
const stateDefinition = Object.entries(stateOptions.Iterator.States);
this.setStateInfo(stateDefinition, stateMachineName);
continue;
}
if (stateOptions.Type !== StateType_1.StateType.Task) {
continue;
}
const functionName = this.getFunctionName(stateOptions);
if (functionName === 'arn:aws:states:::states:startExecution') {
continue;
}
const { handler } = definedFunctions[functionName];
const indexOfHandlerNameSeparator = handler.lastIndexOf('.');
const handlerPath = handler.substring(0, indexOfHandlerNameSeparator);
const handlerName = handler.substring(indexOfHandlerNameSeparator + 1);
const environment = (_b = (_a = this.serverless.service.initialServerlessConfig) === null || _a === void 0 ? void 0 : _a.functions[functionName]) === null || _b === void 0 ? void 0 : _b.environment;
statesInfoHandler.setStateInfo(stateMachineName, stateName, handlerPath, handlerName, environment);
}
}
resolveHandlers(definedStateMachines) {
for (const stateMachine of definedStateMachines.stateMachines) {
const states = Object.entries(stateMachine.definition.States);
this.setStateInfo(states, stateMachine.name);
}
}
}
module.exports = ServerlessOfflineStepFunctionsPlugin;