mihawk
Version:
A tiny & simple mock server tool, support json,js,cjs,ts(typescript).
152 lines (151 loc) • 5.95 kB
JavaScript
;
import { join, basename } from 'path';
import Colors from 'color-cc';
import { cosmiconfig } from 'cosmiconfig';
import { existsSync } from 'fs-extra';
import deepmerge from 'deepmerge';
import { writeFileSafeSync } from '../utils/file';
import { CWD, DEFAULT_OPTIONS, MOCK_DIR_NAME, MOCK_DATA_DIR_NAME, PKG_NAME } from '../consts';
import { Debugger, Printer } from '../utils/print';
import { absifyPath, getLogicFileExt } from '../utils/path';
import { isObjStrict } from '../utils/is';
export async function initRCfile(name, options = { fileType: 'json' }) {
const { fileType = 'json', overwrite = false, initConfig = {}, tsInfo = null } = options;
const rcType = fileType || 'json';
const rcName = `${name}.${rcType}`;
Printer.log(`init ${rcName} file..`);
const rcFilePath = join(CWD, `./${rcName}`);
if (existsSync(rcFilePath)) {
if (overwrite) {
Printer.log(`Force Update file ${rcName}..`);
}
else {
Printer.log(`${rcName} file already exists. Will skip it..`);
return;
}
}
let initContent = JSON.stringify(initConfig || {}, null, 2);
switch (rcType) {
case 'ts': {
const { typeName, typeImportId } = tsInfo || {};
const hasTypeInfo = typeName && typeImportId;
const importTypeCode = hasTypeInfo ? `import type { ${typeName} } from '${typeImportId}';` : '';
initContent = [
'"use strict";',
'/**',
` * ${name}.ts`,
' */',
importTypeCode,
'',
`const config: ${hasTypeInfo ? typeName : 'any'} = ${initContent};`,
'export default config;',
'',
].join('\n');
break;
}
case 'js': {
initContent = [
'"use strict";',
'/**',
` * ${name}.js`,
' */',
'',
`module.exports = ${initContent};`,
'',
].join('\n');
break;
}
case 'json':
default:
initConfig.$schema = `./node_modules/${PKG_NAME}/assets/schema/root-config.json`;
initContent = JSON.stringify(initConfig || {}, null, 2);
break;
}
writeFileSafeSync(rcFilePath, initContent);
}
export async function getRcData(name, options) {
const { initConfig = {} } = options || {};
const defConfig = Object.assign({}, initConfig);
const rcNames = [`${name}.json`, `${name}.js`, `${name}.ts`];
try {
if (rcNames.some(fileName => existsSync(join(CWD, fileName)))) {
const explorer = cosmiconfig(name, {
stopDir: CWD,
searchPlaces: rcNames,
packageProp: name.replace(/^\.+/g, ''),
});
const res = await explorer.search(CWD);
const { config, filepath } = res || {};
Printer.log(Colors.success(`load root-config file: ${Colors.gray(basename(filepath))}`));
Debugger.log('root-config: ', config);
return config || defConfig;
}
else {
Printer.log(Colors.yellow(`Can't found rc-file(.${name}.js|json|ts). Will auto create & init it..`));
await initRCfile(name, { fileType: 'json', initConfig: defConfig, overwrite: false });
return defConfig;
}
}
catch (error) {
Printer.error(Colors.error('Load config file error..'), '\n', error);
return defConfig;
}
}
export function formatOptionsByConfig(config) {
const options = deepmerge({}, {
...DEFAULT_OPTIONS,
...config,
});
['_', '--', 'h', 'H', 'help', 'v', 'V', 'version'].forEach(key => delete options[key]);
if (options.p !== undefined) {
options.port = options.p;
delete options.p;
}
if (options.d !== undefined) {
options.mockDir = options.d || MOCK_DIR_NAME;
delete options.d;
}
if (options.w !== undefined) {
options.watch = options.w;
delete options.w;
}
const { mockDataFileType, mockLogicFileType } = options || {};
options.port = Number(options.port);
options.mockDirPath = absifyPath(options.mockDir || MOCK_DIR_NAME);
options.mockDataDirPath = join(options.mockDirPath, MOCK_DATA_DIR_NAME);
const isTypesctiptMode = mockLogicFileType === 'ts' || mockLogicFileType === 'typescript';
options.isTypesctiptMode = isTypesctiptMode;
if (isTypesctiptMode) {
if (options.tsconfigPath) {
options.tsconfigPath = absifyPath(options.tsconfigPath);
}
else {
options.tsconfigPath = join(options.mockDirPath, 'tsconfig.json');
}
}
const dataFileExt = mockDataFileType;
options.dataFileExt = dataFileExt;
const useLogicFile = mockLogicFileType !== 'none';
options.useLogicFile = useLogicFile;
const logicFileExt = getLogicFileExt(mockLogicFileType);
options.logicFileExt = logicFileExt;
if (useLogicFile) {
options.middlewareFilePath = join(options.mockDirPath, `./middleware.${logicFileExt}`);
}
options.routesFilePath = join(options.mockDirPath, `./routes.${logicFileExt || dataFileExt}`);
options.useHttps = !!options.https || isObjStrict(options.https);
options.useWS = !!options.socketConfig;
if (options.useWS) {
if (typeof options.socketConfig !== 'object') {
options.socketConfig = {
host: options.host,
port: options.port,
secure: options.useHttps,
stomp: false,
};
}
options.socketFilePath = join(options.mockDirPath, `./socket.${logicFileExt}`);
}
options.useRemoteData = typeof options.setJsonByRemote === 'object' && options.setJsonByRemote?.enable;
return options;
}