UNPKG

@pact-foundation/pact

Version:
187 lines 7.71 kB
"use strict"; /** * @module Message */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageProviderPact = exports.providerWithMetadata = exports.setupProxyServer = exports.waitForServerReady = void 0; const node_http_1 = __importDefault(require("node:http")); const pact_core_1 = __importDefault(require("@pact-foundation/pact-core")); const body_parser_1 = __importDefault(require("body-parser")); const express_1 = __importDefault(require("express")); const js_base64_1 = require("js-base64"); const lodash_1 = require("lodash"); const logger_1 = __importStar(require("./common/logger")); // Listens for the server start event // Converts event Emitter to a Promise const waitForServerReady = (server) => new Promise((resolve, reject) => { server.on('listening', () => resolve(server)); server.on('error', () => reject()); }); exports.waitForServerReady = waitForServerReady; // Get the Proxy we'll pass to the CLI for verification const setupProxyServer = (app) => node_http_1.default.createServer(app).listen(); exports.setupProxyServer = setupProxyServer; const hasMetadata = (o) => Boolean(o.__pactMessageMetadata); const providerWithMetadata = (provider, metadata) => (descriptor) => Promise.resolve(provider(descriptor)).then((message) => hasMetadata(message) ? { __pactMessageMetadata: { ...message.__pactMessageMetadata, ...metadata, }, message, } : { __pactMessageMetadata: metadata, message }); exports.providerWithMetadata = providerWithMetadata; /** * A Message Provider is analogous to Consumer in the HTTP Interaction model. * * It is the initiator of an interaction, and expects something on the other end * of the interaction to respond - just in this case, not immediately. */ class MessageProviderPact { config; constructor(config) { this.config = config; if (config.logLevel && !(0, lodash_1.isEmpty)(config.logLevel)) { pact_core_1.default.logLevel(config.logLevel); (0, logger_1.setLogLevel)(config.logLevel); } else { (0, logger_1.setLogLevel)(); } } /** * Verify a Message Provider. */ verify() { logger_1.default.info('Verifying message'); // Start the verification CLI proxy server const app = this.setupProxyApplication(); const server = (0, exports.setupProxyServer)(app); // Run the verification once the proxy server is available return (0, exports.waitForServerReady)(server) .then(this.runProviderVerification()) .then((result) => { server.close(); return result; }, (err) => { server.close(); throw err; }); } // Run the Verification CLI process runProviderVerification() { return (server) => { const opts = { ...(0, lodash_1.omit)(this.config, 'handlers'), ...{ providerBaseUrl: `http://localhost:${server.address().port}`, }, }; return pact_core_1.default.verifyPacts(opts); }; } // Get the API handler for the verification CLI process to invoke on POST /* setupVerificationHandler() { return (req, res) => { const message = req.body; // Invoke the handler, and return the JSON response body // wrapped in a Message this.setupStates(message) .then(() => this.findHandler(message)) .then((handler) => handler(message)) .then((messageFromHandler) => { if (hasMetadata(messageFromHandler)) { const metadata = (0, js_base64_1.encode)(JSON.stringify(messageFromHandler.__pactMessageMetadata)); res.header('Pact-Message-Metadata', metadata); res.header('PACT_MESSAGE_METADATA', metadata); return res.json(messageFromHandler.message); } return res.json(messageFromHandler); }) .catch((e) => res.status(500).send(e)); }; } // Get the Express app that will run on the HTTP Proxy setupProxyApplication() { const app = (0, express_1.default)(); app.use(body_parser_1.default.json()); app.use(body_parser_1.default.urlencoded({ extended: true })); app.use((_req, res, next) => { // TODO: this seems to override the metadata for content-type res.header('Content-Type', 'application/json; charset=utf-8'); next(); }); // Proxy server will respond to Verifier process app.all('/{*splat}', this.setupVerificationHandler()); return app; } // Lookup the handler based on the description, or get the default handler setupStates(message) { const promises = []; if (message.providerStates) { message.providerStates.forEach((state) => { const handler = this.config.stateHandlers ? this.config.stateHandlers[state.name] : null; if (handler) { promises.push(handler(state.name, state.params)); } else { logger_1.default.warn(`no state handler found for "${state.name}", ignoring`); } }); } return Promise.all(promises); } // Lookup the handler based on the description, or get the default handler findHandler(message) { const handler = this.config.messageProviders ? this.config.messageProviders[message.description || ''] : undefined; if (!handler) { logger_1.default.error(`no handler found for message ${message.description}`); return Promise.reject(new Error(`No handler found for message "${message.description}". Check your "handlers" configuration`)); } return Promise.resolve(handler); } } exports.MessageProviderPact = MessageProviderPact; //# sourceMappingURL=messageProviderPact.js.map