UNPKG

@deliverr/serverless-offline-step-functions

Version:

Serverless Offline Plugin to Support Step Functions for Local Development

102 lines (101 loc) 4.89 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StepFunctionSimulatorServer = void 0; const http_terminator_1 = require("http-terminator"); const express_1 = __importDefault(require("express")); const StateMachineExecutor_1 = require("./StateMachineExecutor"); const Logger_1 = require("./utils/Logger"); const StateMachineContext_1 = require("./Context/StateMachineContext"); const ExecutionContext_1 = require("./Context/ExecutionContext"); const Context_1 = require("./Context/Context"); const StateContext_1 = require("./Context/StateContext"); class StepFunctionSimulatorServer { constructor(options) { this.pendingStateMachineExecutions = {}; this.options = options; this.stateMachines = this.options.stateMachines; this.logger = Logger_1.Logger.getInstance(); this.express = express_1.default(); this.setupMiddlewares(); } async initServer() { let httpServer; try { httpServer = this.express.listen(this.options.port, () => { this.logger.success(`Server ready on port ${this.options.port} 🚀`); }); } catch (err) { this.logger.error(`Unexpected error while starting serverless-offline server on port ${this.options.port}: ${err.stack}`); process.exit(1); } this.httpTerminator = http_terminator_1.createHttpTerminator({ server: httpServer }); } async shutdown() { var _a; this.logger.warning('Killing Step Functions API Simulator 🔪'); await ((_a = this.httpTerminator) === null || _a === void 0 ? void 0 : _a.terminate()); } setupMiddlewares() { this.express.use(express_1.default.json({ type(req) { const contentType = req.headers['content-type'] || ''; return ['application/x-amz-json-1.0'].includes(contentType); }, limit: '262144b', })); this.express.use(this.resolveStateMachine.bind(this)); } isSendTaskSuccess(body) { return !!body.taskToken && !!body.output; } isSendTaskFailure(body) { return !!body.taskToken && !body.output; } async resolveStateMachine(req, res) { this.logger.log(`Got request for ${req.method} ${req.url}`); if (req.body.taskToken) { if (this.isSendTaskSuccess(req.body)) { if (typeof this.pendingStateMachineExecutions[req.body.taskToken] !== 'function') { this.logger.log(`No step function to resume with taskToken '${req.body.taskToken}.'`); return; } this.logger.log(`Going to resume taskToken "${req.body.taskToken}" with output "${req.body.output}"`); this.pendingStateMachineExecutions[req.body.taskToken](JSON.parse(req.body.output)); return; } if (this.isSendTaskFailure(req.body)) { } } const executionInput = req.body; const stateMachineContext = StateMachineContext_1.StateMachineContext.create(executionInput.stateMachineArn); const stateMachineToExecute = this.stateMachines.getStateMachineBy(stateMachineContext.Name); if (!stateMachineToExecute) { const errorMessage = `No stateMachineToExecute for name "${stateMachineContext.Name}"`; this.logger.error(errorMessage); return res.status(404).send(); } const executionContext = ExecutionContext_1.ExecutionContext.create(stateMachineContext, executionInput.input); const firstStateContext = StateContext_1.StateContext.create(stateMachineToExecute.definition.StartAt); const context = Context_1.Context.create(executionContext, stateMachineContext, firstStateContext); this.logger.debug('State definitions:'); this.logger.debug(JSON.stringify(stateMachineToExecute.definition.States)); const startAtState = stateMachineToExecute.definition.States[firstStateContext.Name]; const sme = new StateMachineExecutor_1.StateMachineExecutor(stateMachineToExecute, context); await new Promise((resolve) => { const output = { startDate: new Date(context.Execution.StartTime), executionArn: context.Execution.Id, }; resolve(res.status(200).json(output)); }); const executionResult = await sme.execute(startAtState, executionContext.Input); if (typeof executionResult === 'function') { this.pendingStateMachineExecutions[context.Task.Token] = executionResult; } } } exports.StepFunctionSimulatorServer = StepFunctionSimulatorServer;