mockgeneratorcli
Version:
generate mock data by swaggerapi
166 lines (163 loc) • 4.87 kB
JavaScript
const swaggerParserMock = require('swagger-parser-mock');
const fs = require('fs');
const mkdirp = require('mkdirp');
const signale = require('signale');
const mockGenerator = {
async init({ swaggerUrlList, dataLength, fileName, ignoreList, outputFileType }) {
this.swaggerUrlList = swaggerUrlList;
this.dataLength = dataLength;
this.fileName = fileName;
this.ignoreList = ignoreList;
this.outputFileType = outputFileType || 'ts';
signale.start('mock generate start');
signale.wait(`get swaggerData.`);
this.swaggerUrlList.forEach(async data => {
if (!data.generate) {
return
}
let url = data.swaggerUrl,
outputDir = data.outputDir
signale.start(`mock-job:${url} start`)
let swaggerData = await this.parse(url)
if (swaggerData.length === 0) {
signale.error(`swaggerData cannot be empty`)
return
}
let mockData = this.getMockData(swaggerData)
await this.generateMockFile(mockData, outputDir)
signale.start(`mock-job:${url} complete`)
})
},
// 解析swagger-api-doc
async parse(url) {
try {
const { paths } = await swaggerParserMock(url)
if (!paths) {
return []
}
return paths
} catch (error) {
signale.fatal(error)
return []
}
},
// 生成mock数据
getMockData(paths) {
let keys = Object.keys(paths);
let contentObj = {};
keys.forEach(key => {
let method = paths[key].post ? 'post' : 'get';
let apiDetail = paths[key][method];
let module = apiDetail.tags[0] || this.fileName;
if (!contentObj[module]) {
contentObj[module] = '';
}
if (!this.filterIgnoreList(key)) {
let data = this.generateData(paths, key, method);
contentObj[module] += data;
}
});
return contentObj;
},
// 过滤忽略api
filterIgnoreList(path) {
return (
this.ignoreList.findIndex(ignorePath => {
return path.indexOf(ignorePath) != -1;
}) != -1
);
// return (
// path.match(/[a-zA-z0-9]+/g).findIndex(pathModule => {
// return (
// this.blacklist.findIndex(module => {
// return module == pathModule;
// }) != -1
// );
// }) != -1
// );
},
// 生成每个模块的mock数据
generateData(paths, path, method) {
const summary = paths[path][method]['summary'];
const response = paths[path][method]['responses']['200'];
try {
if (!response['example']) {
signale.error(`responseData parse failed; path:${path} \r\n`, 'example response cannot be empty');
return '';
}
const data = formatResToMock(path, response['example'], this.dataLength);
return ` // ${summary.replace(/\r\n/g, '\r\n//')}
'${method.toUpperCase()} /api${path.replace(/\{([^}]*)\}/g, ':$1')}': (req, res) => {
res.send(Mock.mock(${data.replace(/null/g, '') || `true`}));
},
`;
} catch (error) {
signale.error(`responseData parse failed; path:${path} \r\n`, error);
return '';
}
},
// 生成mock文件
async generateMockFile(mockData, outputDir) {
await this.makeDir(outputDir);
for (let key in mockData) {
await this.writeMockFile(mockData[key], key, outputDir);
}
},
async writeMockFile(data, fileName, outputDir) {
// 写入文件
let temp = '';
if (this.outputFileType == 'ts') {
temp = `import Mock from 'mockjs';
export default {
${data}};`;
} else {
temp = `var Mock = require('mockjs');
module.exports = {
${data}};`;
}
fs.writeFile(`${process.cwd()}${outputDir}/${fileName}.${this.outputFileType}`, temp, 'utf-8', err => {
if (err) {
signale.fatal(err);
throw err;
}
});
},
// 生成目录
async makeDir(outputDir) {
let path=process.cwd() + outputDir
return new Promise((resolve, reject) => {
let exists=fs.existsSync(path)
if (!exists) {
// 新建该文件夹
mkdirp(path).then((made) => {
console.log(made)
resolve();
});
} else {
resolve();
}
});
},
};
// 格式化mock
function formatResToMock(path, res, dataLength) {
let data = '';
let praseRes = JSON.parse(res);
if (Array.isArray(praseRes)) {
data = `{
"data|${dataLength}": ${res}
}`;
} else {
Object.keys(praseRes).forEach(key => {
if (Array.isArray(praseRes[key])) {
praseRes[`${[key]}|${dataLength}`] = praseRes[key];
delete praseRes[key];
}
});
data = `{
"data": ${JSON.stringify(praseRes)}
}`;
}
return data;
}
module.exports = mockGenerator;