mihawk
Version:
A tiny & simple mock server tool, support json,js,cjs,ts(typescript).
251 lines (250 loc) • 11.6 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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initMockLogicFile = exports.initMockMiddlewareFile = exports.initMockRoutesFile = exports.initMockDataDir = void 0;
const path_1 = require("path");
const color_cc_1 = __importDefault(require("color-cc"));
const fs_extra_1 = require("fs-extra");
const file_1 = require("../utils/file");
const print_1 = require("../utils/print");
const path_2 = require("../utils/path");
const consts_1 = require("../consts");
const dataDemo = {
code: 200,
data: {
str: 'test',
},
message: 'success',
};
const routesDemo = {
'GET /test': './GET/test',
'GET /test-*': './GET/test',
};
function initMockDataDir(mockDirName = consts_1.MOCK_DIR_NAME) {
return __awaiter(this, void 0, void 0, function* () {
const mockDataDir = (0, path_1.join)(mockDirName || consts_1.MOCK_DIR_NAME, consts_1.MOCK_DATA_DIR_NAME);
const mockDataDirPath = (0, path_1.join)(consts_1.CWD, mockDataDir);
if (!(0, fs_extra_1.existsSync)(mockDataDirPath)) {
(0, fs_extra_1.ensureDirSync)(mockDataDirPath);
print_1.Printer.log(color_cc_1.default.success(`Create mock data dir ${color_cc_1.default.green(mockDataDir)} success!`));
}
for (const subDir of ['PUT', 'DELETE', 'POST', 'GET']) {
const subDirPath = (0, path_1.join)(mockDataDirPath, subDir);
if (!(0, fs_extra_1.existsSync)(subDirPath)) {
(0, fs_extra_1.ensureFileSync)((0, path_1.join)(subDirPath, '.gitkeep'));
const subDirPathRel = (0, path_1.join)(mockDataDir, subDir);
print_1.Printer.log(color_cc_1.default.success(`Create mock data dir ${color_cc_1.default.green(subDirPathRel)} success!`));
}
}
const demoFilePathRel = (0, path_1.join)(mockDataDir, './GET/test.json');
const demoFilePath = (0, path_1.join)(consts_1.CWD, demoFilePathRel);
if (!(0, fs_extra_1.existsSync)(demoFilePath)) {
(0, file_1.writeJSONSafeSync)(demoFilePath, dataDemo);
print_1.Printer.log(color_cc_1.default.success(`Create mock data file ${color_cc_1.default.green(demoFilePathRel)} success!`));
}
});
}
exports.initMockDataDir = initMockDataDir;
function initMockRoutesFile(fileType = 'none', mockDirName = 'mocks') {
return __awaiter(this, void 0, void 0, function* () {
const fileExt = (0, path_2.getRoutesFileExt)(fileType) || 'json';
const routesFileName = `routes.${fileExt}`;
const routesFilePathRel = (0, path_1.join)(mockDirName, routesFileName);
const routesFilePathAbs = (0, path_1.join)(consts_1.CWD, mockDirName, routesFileName);
if ((0, fs_extra_1.existsSync)(routesFilePathAbs)) {
print_1.Printer.log(`Mock routes file ${color_cc_1.default.yellow(routesFilePathRel)} is already existed, skip init!`);
return;
}
else {
const demoRouteMap = JSON.stringify(routesDemo, null, 2);
let initContent = demoRouteMap;
const comPrefixs = [
'/**',
` * ${consts_1.PKG_NAME}'s routes file:`,
' */',
];
switch (fileType) {
case 'js':
case 'cjs':
case 'javascript': {
initContent = [
...comPrefixs,
`module.exports = ${demoRouteMap};`,
'',
].join('\n');
break;
}
case 'ts':
case 'typescript':
initContent = [
...comPrefixs,
`const routes: Record<string, string> = ${demoRouteMap}`,
'//',
'export default routes;',
'',
].join('\n');
break;
case 'none':
default: {
break;
}
}
(0, fs_extra_1.ensureDirSync)((0, path_1.join)(consts_1.CWD, mockDirName));
(0, file_1.writeFileSafeSync)(routesFilePathAbs, initContent);
print_1.Printer.log(color_cc_1.default.success(`Init mock routes file ${color_cc_1.default.green(routesFilePathRel)} success!`));
}
});
}
exports.initMockRoutesFile = initMockRoutesFile;
function initMockMiddlewareFile(fileType = 'none', mockDirName = 'mocks') {
return __awaiter(this, void 0, void 0, function* () {
const fileExt = (0, path_2.getLogicFileExt)(fileType);
const middlewareFileName = `middleware.${fileExt || 'cjs'}`;
const middlewareFilePathRel = (0, path_1.join)(mockDirName, middlewareFileName);
const middlewareFilePathAbs = (0, path_1.join)(consts_1.CWD, mockDirName, middlewareFileName);
if ((0, fs_extra_1.existsSync)(middlewareFilePathAbs)) {
print_1.Printer.log(`Mock middleware file ${color_cc_1.default.yellow(middlewareFilePathRel)} is already existed, skip init!`);
return;
}
else {
const comPrefixs = [
'/**',
` * ${consts_1.PKG_NAME}'s custom koa2-middleware file:`,
' * - just a Koa Middleware',
' */',
];
const methodCommentCode = [
'/**',
' * Middleware functions, to implement some special data deal logic,',
' * - This function exec before the default-mock-logic. Simply return or don`t call "await next()" could skip default-mock-logic',
' * - This function is a standard Koa2 middleware that follows the KOA-onion-ring-model',
' * - see more:https://koajs.com/#middleware',
' * @param {KoaContext} ctx',
' * @param {KoaNext} next',
' * @returns {Promise<void>}',
' */',
];
const methodBodyCode = [
' // do something here',
' console.log(ctx.url);',
' if (ctx.peth === "/diy") {',
' ctx.body = "it is my diy logic";',
' } else {',
' await next(); // default logic (such like mock json logic)',
' }',
];
let initContent = '';
switch (fileType) {
case 'ts':
case 'typescript':
initContent = [
...comPrefixs,
`// import typs { Context: KoaContext, Next: KoaNext } from 'koa'; // need koa@v2.0.0+ (eg: koa@^2.15.3)`,
`import type { KoaContext, KoaNext } from '${consts_1.PKG_NAME}/com-types';`,
'',
...methodCommentCode,
'export default async function middleware(ctx: KoaContext, next: KoaNext) {',
...methodBodyCode,
'}',
'',
].join('\n');
break;
case 'none':
case 'js':
case 'cjs':
case 'javascript':
default:
initContent = [
...comPrefixs,
'',
...methodCommentCode,
'module.exports = async function middleware(ctx, next) {',
...methodBodyCode,
'}',
'',
].join('\n');
break;
}
(0, fs_extra_1.ensureDirSync)((0, path_1.join)(consts_1.CWD, mockDirName));
(0, file_1.writeFileSafeSync)(middlewareFilePathAbs, initContent);
print_1.Printer.log(color_cc_1.default.success(`Init mock middleware file ${color_cc_1.default.green(middlewareFilePathRel)} success!`));
}
});
}
exports.initMockMiddlewareFile = initMockMiddlewareFile;
function initMockLogicFile(mockLogicFilePath, options) {
mockLogicFilePath = (0, path_2.absifyPath)(mockLogicFilePath);
const { logicFileExt, routePath, jsonPath4log, overwrite } = options;
if (!logicFileExt) {
print_1.Printer.warn('Empty logic file ext, skip init logic file.');
return;
}
if (!overwrite && (0, fs_extra_1.existsSync)(mockLogicFilePath)) {
print_1.Printer.warn('File is already exists, skip init logic file.', color_cc_1.default.gray(mockLogicFilePath));
return;
}
let initContent = '';
const commentCode = [
"'use strict;'",
'/**',
` * ${routePath}`,
' * This file isn‘t mandatory. If it is not needed (such as when there is no need to modify response data), it can be deleted directly',
' */',
];
const methodCommentCode = [
'/**',
' * Mock data resolve function, the original data source is the JSON file with the same name as this file',
` * @param {object} originData (${jsonPath4log})`,
' * @param {MhkCvtrExtra} extra { url,method,path,query,body }',
' * @returns {object} newData',
' */',
];
switch (logicFileExt) {
case 'ts': {
const useTypeDefine = true;
initContent = [
...commentCode,
useTypeDefine ? `import { MhkCvtrExtra } from '${consts_1.PKG_NAME}/com-types';\n` : '',
...methodCommentCode,
useTypeDefine
? 'export default async function convertData(originData: Record<string, any>, extra: MhkCvtrExtra) {'
: 'export default async function convertData(originData: Record<string, any>, extra: Record<string, any>) {',
' // 👇🏻 write your logic here...',
' return originData;',
'}',
].join('\n');
break;
}
case 'js':
case 'cjs':
initContent = [
...commentCode,
'',
...methodCommentCode,
'module.exports = async function convertData(originData, extra) {',
' // 👇🏻 write your logic here...',
' return originData;',
'};',
].join('\n');
break;
default:
break;
}
if (!initContent) {
print_1.Printer.warn('No logic file ext was matched, skip init logic file.', logicFileExt);
return;
}
(0, file_1.writeFileSafeSync)(mockLogicFilePath, initContent);
}
exports.initMockLogicFile = initMockLogicFile;