mocker-api
Version:
This is dev support mock RESTful API.
244 lines • 11.2 kB
JavaScript
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
;