UNPKG

mocker-api

Version:

This is dev support mock RESTful API.

244 lines 11.2 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; 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 __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = mockerApi; var path_1 = __importDefault(require("path")); var toRegexp = __importStar(require("path-to-regexp")); var clear_module_1 = __importDefault(require("clear-module")); var chokidar_1 = __importDefault(require("chokidar")); var safe_1 = __importDefault(require("colors-cli/safe")); var proxyHandle_1 = require("./proxyHandle"); var mockerHandle_1 = require("./mockerHandle"); __exportStar(require("./delay"), exports); __exportStar(require("./utils"), exports); var pathToRegexp = toRegexp.pathToRegexp; var mocker = {}; module.exports = mockerApi; function mockerApi(app, watchFile, conf) { if (conf === void 0) { conf = {}; } var watchFiles = (Array.isArray(watchFile) ? watchFile : typeof watchFile === 'string' ? [watchFile] : []).map(function (str) { return path_1.default.resolve(str); }); if (watchFiles.some(function (file) { return !file; })) { throw new Error('Mocker file does not exist!.'); } /** * Mybe watch file or pass parameters * https://github.com/jaywcjlove/mocker-api/issues/116 */ var isWatchFilePath = (Array.isArray(watchFile) && watchFile.every(function (val) { return typeof val === 'string'; })) || typeof watchFile === 'string'; mocker = isWatchFilePath ? getConfig() : watchFile; if (!mocker) { return function (req, res, next) { next(); }; } var options = __assign(__assign({}, conf), (mocker._proxy || {})); var defaultOptions = { changeHost: true, pathRewrite: {}, proxy: {}, // proxy: proxyConf: {}, httpProxy: {}, // httpProxy: httpProxyConf: {}, bodyParserConf: {}, bodyParserJSON: {}, bodyParserText: {}, bodyParserRaw: {}, bodyParserUrlencoded: {}, watchOptions: {}, header: {}, priority: 'proxy', withFullUrlPath: false }; options = __assign(__assign({}, defaultOptions), options); // changeHost = true, // pathRewrite = {}, // proxy: proxyConf = {}, // httpProxy: httpProxyConf = {}, // bodyParserConf= {}, // bodyParserJSON = {}, // bodyParserText = {}, // bodyParserRaw = {}, // bodyParserUrlencoded = {}, // watchOptions = {}, // header = {} if (isWatchFilePath) { // 监听配置入口文件所在的目录,一般为认为在配置文件/mock 目录下的所有文件 // 加上require.resolve,保证 `./mock/`能够找到`./mock/index.js`,要不然就要监控到上一级目录了 var watcher = chokidar_1.default.watch(watchFiles.map(function (watchFile) { return path_1.default.dirname(require.resolve(watchFile)); }), options.watchOptions); watcher.on('all', function (event, path) { if (event === 'change' || event === 'add') { try { // 当监听的可能是多个配置文件时,需要清理掉更新文件以及入口文件的缓存,重新获取 cleanCache(path); watchFiles.forEach(function (file) { return cleanCache(file); }); mocker = getConfig(); if (mocker._proxy) { options = __assign(__assign({}, options), mocker._proxy); } console.log("".concat(safe_1.default.green_b.black(' Done: '), " Hot Mocker ").concat(safe_1.default.green(path.replace(process.cwd(), '')), " file replacement success!")); } catch (ex) { console.error("".concat(safe_1.default.red_b.black(' Failed: '), " Hot Mocker ").concat(safe_1.default.red(path.replace(process.cwd(), '')), " file replacement failed!!")); } } }); } // 监听文件修改重新加载代码 // 配置热更新 app.all('/*', function (req, res, next) { var getExecUrlPath = function (req) { return options.withFullUrlPath ? req.url : req.path; }; /** * Get Proxy key */ var proxyKey = Object.keys(options.proxy).find(function (kname) { try { var regexp = pathToRegexp(kname.replace((new RegExp('^' + req.method + ' ')), '')).regexp; return !!regexp.exec(getExecUrlPath(req)); } catch (error) { console.error("".concat(safe_1.default.red_b.black(' Failed: '), " The proxy configuration ").concat(safe_1.default.red(kname), " contains a syntax error!!\n doc: ").concat(safe_1.default.blue("https://www.npmjs.com/package/path-to-regexp/v/8.2.0"))); return false; } }); /** * Get Mocker key * => `GET /api/:owner/:repo/raw/:ref` * => `GET /api/:owner/:repo/raw/:ref/(.*)` */ var mockerKey = Object.keys(mocker).find(function (kname) { try { var regexp = pathToRegexp(kname.replace((new RegExp('^' + req.method + ' ')), '')).regexp; return !!regexp.exec(getExecUrlPath(req)); } catch (error) { console.error("".concat(safe_1.default.red_b.black(' Failed: '), " The mocker configuration ").concat(safe_1.default.red(kname), " contains a syntax error!!\n doc: ").concat(safe_1.default.blue("https://www.npmjs.com/package/path-to-regexp/v/8.2.0"))); return false; } }); /** * Access Control Allow options. * https://github.com/jaywcjlove/mocker-api/issues/61 */ var accessOptions = __assign({ 'Access-Control-Allow-Origin': req.get('Origin') || '*', 'Access-Control-Allow-Methods': 'POST, GET, OPTIONS, PUT, DELETE', 'Access-Control-Allow-Headers': 'Content-Type, X-Requested-With,' + (req.header('access-control-request-headers') || ''), 'Access-Control-Allow-Credentials': 'true' }, options.header); Object.keys(accessOptions).forEach(function (keyName) { res.setHeader(keyName, accessOptions[keyName]); }); var proxyKeyString = Object.keys(mocker).find(function (kname) { try { var regexp = pathToRegexp(kname.replace((new RegExp('^(PUT|POST|GET|DELETE) ')), '')).regexp; return !!regexp.exec(getExecUrlPath(req)); } catch (error) { console.error("".concat(safe_1.default.red_b.black(' Failed: '), " The mocker configuration ").concat(safe_1.default.red(kname), " contains a syntax error!!\n doc: ").concat(safe_1.default.blue("https://www.npmjs.com/package/path-to-regexp/v/8.2.0"))); return false; } }); // fix issue 34 https://github.com/jaywcjlove/mocker-api/issues/34 // In some cross-origin http request, the browser will send the preflighted options request before sending the request methods written in the code. if (!mockerKey && req.method.toLocaleUpperCase() === 'OPTIONS' && proxyKeyString) { return res.sendStatus(200); } /** * priority 'proxy' or 'mocker' [#151](https://github.com/jaywcjlove/mocker-api/issues/151) */ if (options.priority === 'mocker') { if (mocker[mockerKey]) { return (0, mockerHandle_1.mockerHandle)({ req: req, res: res, next: next, mocker: mocker, options: options, mockerKey: mockerKey }); } else if (proxyKey && options.proxy[proxyKey]) { return (0, proxyHandle_1.proxyHandle)(req, res, options, proxyKey); } } else { if (proxyKey && options.proxy[proxyKey]) { return (0, proxyHandle_1.proxyHandle)(req, res, options, proxyKey); } else if (mocker[mockerKey]) { return (0, mockerHandle_1.mockerHandle)({ req: req, res: res, next: next, mocker: mocker, options: options, mockerKey: mockerKey }); } } next(); }); /** * The old module's resources to be released. * @param modulePath */ function cleanCache(modulePath) { // The entry file does not have a .js suffix, // causing the module's resources not to be released. // https://github.com/jaywcjlove/webpack-api-mocker/issues/30 try { modulePath = require.resolve(modulePath); } catch (e) { } var module = require.cache[modulePath]; if (!module) return; // https://github.com/jaywcjlove/mocker-api/issues/42 (0, clear_module_1.default)(modulePath); } /** * Merge multiple Mockers */ function getConfig() { return watchFiles.reduce(function (mocker, file) { var mockerItem = require(file); return Object.assign(mocker, mockerItem.default ? mockerItem.default : mockerItem); }, {}); } return function (req, res, next) { next(); }; } //# sourceMappingURL=index.js.map