unmock-core
Version:
[][npmjs] [](https://circleci.com/gh/unmock/unmock-js) [](h
136 lines (133 loc) • 6.03 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = require("debug");
const Mitm = require("mitm");
const console_1 = require("../console");
const fs_service_def_loader_1 = require("../fs-service-def-loader");
const generator_1 = require("../generator");
const filesystem_logger_1 = require("../loggers/filesystem-logger");
const snapshotter_1 = require("../loggers/snapshotter");
const parser_1 = require("../parser");
const serialize_1 = require("../serialize");
const serviceStore_1 = require("../service/serviceStore");
const utils_1 = require("../utils");
const client_request_tracker_1 = require("./client-request-tracker");
const debugLog = debug_1.default("unmock:node");
const respondFromSerializedResponse = (serializedResponse, res) => {
res.writeHead(serializedResponse.statusCode, serializedResponse.headers);
res.end(serializedResponse.body);
};
const errorForMissingTemplate = (sreq) => {
const serverUrl = `${sreq.protocol}://${sreq.host}`;
return `No matching template found for intercepted request. Please ensure that
1. You have defined a service for host ${serverUrl}
2. The service has a path matching "${sreq.method} ${sreq.pathname}"
For example, add the following to your service:
servers:
- url: ${sreq.protocol}://${sreq.host}
paths:
${sreq.pathname}:
${sreq.method.toLowerCase()}:
// OpenAPI operation object
responses:
200:
...
`;
};
function handleRequestAndResponse(createResponse, req, res, clientRequest) {
return __awaiter(this, void 0, void 0, function* () {
try {
const serializedRequest = yield serialize_1.serializeRequest(req);
debugLog("Serialized request", JSON.stringify(serializedRequest));
const serializedResponse = createResponse(serializedRequest);
if (serializedResponse === undefined) {
debugLog("No match found, emitting error");
const errMsg = errorForMissingTemplate(serializedRequest);
const formatted = console_1.CustomConsole.format("instruct", errMsg);
clientRequest.emit("error", Error(formatted));
return;
}
debugLog("Responding with response", JSON.stringify(serializedResponse));
respondFromSerializedResponse(serializedResponse, res);
}
catch (err) {
clientRequest.emit("error", Error(`unmock error: ${err.message}`));
}
});
}
const nodeBackendDefaultOptions = {};
class NodeBackend {
constructor(config) {
this.serviceStore = new serviceStore_1.ServiceStore([]);
this.config = Object.assign(Object.assign({}, nodeBackendDefaultOptions), config);
this.loadServices();
}
loadServices() {
const unmockDirectories = this.config.servicesDirectory
? [this.config.servicesDirectory]
: utils_1.resolveUnmockDirectories();
debugLog(`Found unmock directories: ${JSON.stringify(unmockDirectories)}`);
const serviceDefLoader = new fs_service_def_loader_1.FsServiceDefLoader({
unmockDirectories,
});
const serviceDefs = serviceDefLoader.loadSync();
const coreServices = serviceDefs.map(serviceDef => parser_1.ServiceParser.parse(serviceDef));
this.serviceStore = new serviceStore_1.ServiceStore(coreServices);
}
get services() {
return (this.serviceStore && this.serviceStore.services) || {};
}
initialize(options) {
if (process.env.NODE_ENV === "production" && !options.useInProduction()) {
throw new Error("Are you trying to run unmock in production?");
}
if (this.mitm !== undefined) {
this.reset();
}
this.mitm = Mitm();
client_request_tracker_1.default.start();
this.mitm.on("connect", (socket, opts) => this.mitmOnConnect(options, socket, opts));
const createResponse = generator_1.responseCreatorFactory({
listeners: [
new filesystem_logger_1.default({ directory: this.config.servicesDirectory }),
snapshotter_1.default.getOrUpdateSnapshotter({}),
],
options,
store: this.serviceStore,
});
this.mitm.on("request", (req, res) => this.mitmOnRequest(createResponse, req, res));
}
reset() {
if (this.mitm) {
this.mitm.disable();
this.mitm = undefined;
}
if (this.serviceStore) {
Object.values(this.serviceStore.services).forEach(service => service.reset());
}
client_request_tracker_1.default.stop();
}
mitmOnRequest(createResponse, req, res) {
debugLog("Handling incoming message...");
req.on("error", (e) => debugLog("Error on intercepted request:", e));
req.on("abort", () => debugLog("Intercepted request aborted"));
const clientRequest = client_request_tracker_1.default.pop(req);
setImmediate(() => handleRequestAndResponse(createResponse, req, res, clientRequest));
}
mitmOnConnect({ isWhitelisted }, socket, opts) {
if (isWhitelisted(opts.host || "")) {
socket.bypass();
}
}
}
exports.default = NodeBackend;
//# sourceMappingURL=index.js.map