Files
yapi/exts/yapi-plugin-export-markdown-template/controller.js

265 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const baseController = require('controllers/base.js');
const interfaceModel = require('models/interface.js');
const projectModel = require('models/project.js');
const interfaceCatModel = require('models/interfaceCat.js');
const userModel = require("models/user.js");
const groupModel = require("models/group.js");
const yapi = require('yapi.js');
const uuid = require('uuid');
const configModel = require("./configModel");
const Safeify = require('safeify').default;
const JSZip = require("jszip");
class exportMarkdownController extends baseController {
constructor(ctx) {
super(ctx);
this.catModel = yapi.getInst(interfaceCatModel);
this.interModel = yapi.getInst(interfaceModel);
this.projectModel = yapi.getInst(projectModel);
this.configModel = yapi.getInst(configModel);
this.userModel = yapi.getInst(userModel);
this.groupModel = yapi.getInst(groupModel);
}
/*
handleListClass,handleExistId is same as the exportController(yapi-plugin-export-data).
No DRY,but i have no idea to optimize it.
*/
async handleListClass(pid, status) {
let result = await this.catModel.list(pid),
newResult = [];
for (let i = 0, item, list; i < result.length; i++) {
item = result[i].toObject();
list = await this.interModel.listByInterStatus(item._id, status);
list = list.sort((a, b) => {
return a.index - b.index;
});
if (list.length > 0) {
item.list = list;
newResult.push(item);
}
}
return newResult;
}
handleExistId(data) {
function delArrId(arr, fn) {
if (!Array.isArray(arr)) return;
arr.forEach(item => {
delete item._id;
delete item.__v;
delete item.uid;
delete item.edit_uid;
delete item.catid;
delete item.project_id;
if (typeof fn === 'function') fn(item);
});
}
delArrId(data, function (item) {
delArrId(item.list, function (api) {
delArrId(api.req_body_form);
delArrId(api.req_params);
delArrId(api.req_query);
delArrId(api.req_headers);
if (api.query_path && typeof api.query_path === 'object') {
delArrId(api.query_path.params);
}
});
});
return data;
}
async exportData(ctx) {
let pid = ctx.request.query.pid;
let status = ctx.request.query.status;
if (!pid) {
ctx.body = yapi.commons.resReturn(null, 200, 'pid 不为空');
}
let templateData = await this.configModel.getByProjectId(pid);
let curProject = await this.projectModel.get(pid);
if (!templateData){
templateData = await this.configModel.getByGroupId(curProject.group_id);
}
// console.log(result);
if (!templateData || !templateData.is_export_by_interface) {
console.log("重定向")
ctx.status = 302;
ctx.redirect(`/api/plugin/export?type=markdown&pid=${pid}`);
return;
}
try {
// ctx.set('Content-Type', 'application/json');
// ctx.set('Content-Type', 'application/octet-stream');
const list = await this.handleListClass(pid, status);
let data = this.handleExistId(list);
let userData = await this.userModel.findById(this.getUid());
// console.log("curProject", curProject)
// console.log("list", list)
let model;
// const tmpPath = fs.mkdtempSync(path.join(os.tmpdir(),uuid.v4()));
// console.log("tmpPath=", tmpPath)
const zip = JSZip();
let allErrMsg = [];
for (let item of data) {
for (let interfaceItem of item.list) {
let {result, errMsg} = await this.executeJsRender(templateData.template_data, curProject, interfaceItem, item, userData)
zip.file(`${item.name}/${interfaceItem.title}.md`, result.toString())
if (errMsg){
allErrMsg.push(errMsg)
}
}
}
if (allErrMsg.length) {
ctx.body = yapi.commons.resReturn(allErrMsg, 502, '下载出错');
return;
}
ctx.set('Content-Disposition', `attachment; filename=${encodeURIComponent(curProject.name)}.zip`);
let dataaa = await zip.generateAsync({
type: "nodebuffer",
// 压缩算法
compression: "DEFLATE",
streamFiles: true,
compressionOptions: {
level: 9
}
});
ctx.body = dataaa
// ctx.set('Content-Length', dataaa.length);
// dataaa.copy(ctx.body)
// fs.unlinkSync(tmpPath)
} catch (error) {
yapi.commons.log(error, 'error');
ctx.body = yapi.commons.resReturn(null, 502, '下载出错');
}
}
/**
* 保存配置信息
* @param {*} ctx
*/
async upConfig(ctx) {
let requestBody = ctx.request.body;
let projectId = requestBody.project_id;
let groupId = requestBody.group_id;
if (!projectId && !groupId) {
return (ctx.body = yapi.commons.resReturn(null, 408, '缺少项目Id/组id'));
}
if ((await this.checkAuth(projectId, 'project', 'edit')) !== true) {
return (ctx.body = yapi.commons.resReturn(null, 405, '没有权限'));
}
let result;
if (requestBody.id) {
result = await this.configModel.up(requestBody);
} else {
result = await this.configModel.save(requestBody);
}
return (ctx.body = yapi.commons.resReturn(result));
}
/**
* 查询配置信息
* @param {*} ctx
*/
async getConfig(ctx) {
let projectId = ctx.query.project_id || ctx.query.projectId;
let groupId = ctx.query.group_id || ctx.query.groupId;
if (!projectId && !groupId) {
return (ctx.body = yapi.commons.resReturn(null, 408, '缺少项目Id/组id'));
}
let result = null;
if (projectId){
result = await this.configModel.getByProjectId(projectId);
}else {
result= await this.configModel.getByGroupId(groupId);
}
return (ctx.body = yapi.commons.resReturn(result));
}
/**
* 查询配置信息
* @param {*} ctx
*/
async mdGen(ctx) {
let interfaceId = ctx.query.interfaceId;
let userData = await this.userModel.findById(this.getUid());
let interfaceData = await this.interModel.get(interfaceId);
if (!interfaceData) {
return (ctx.body = yapi.commons.resReturn(null, 200, ''));
}
let project = await this.projectModel.get(interfaceData.project_id);
let templateData = await this.configModel.getByProjectId(interfaceData.project_id);
if (!templateData || !templateData.template_data) {
templateData = await this.configModel.getByGroupId(project.group_id);
}
if (!templateData || !templateData.template_data) {
return (ctx.body = yapi.commons.resReturn(null, 200, ''));
}
let interfaceCat = await this.catModel.get(interfaceData.catid);
let {result, errMsg} = await this.executeJsRender(templateData.template_data, project, interfaceData, interfaceCat, userData);
if (errMsg){
ctx.body = yapi.commons.resReturn(errMsg, 502, '渲染出错');
return;
}
return (ctx.body = yapi.commons.resReturn(result));
}
async executeJsRender(template_data, curProject, interfaceItem, categoryItem, useItem) {
let errMsg;
let result;
const safeVm = new Safeify({
timeout: 3000, //超时时间
asyncTimeout: 10000, //包含异步操作的超时时间
unrestricted: true,
quantity: 4, //沙箱进程数量,默认同 CPU 核数
memoryQuota: 500, //沙箱最大能使用的内存(单位 m默认 500m
cpuQuota: 0.5 //沙箱的 cpu 资源配额(百分比),默认 50%
});
// console.log("curProject", curProject)
const vmContext = {
project: JSON.stringify(curProject),
interface: JSON.stringify(interfaceItem),
category: JSON.stringify(categoryItem),
user: JSON.stringify(useItem)
};
try {
safeVm.preset("project = JSON.parse(project);interface = JSON.parse(interface);category=JSON.parse(category);user=JSON.parse(user)")
result = await safeVm.run(template_data, vmContext);
// fs.writeFileSync(`${tmpPath}/${interfaceItem.title}.md`, model.toString())
safeVm.destroy();
} catch (e) {
errMsg = {
error: e.toString(),
context: vmContext
};
}
return {result: result, errMsg}
}
}
module.exports = exportMarkdownController;