cis-api-tool
Version:
根据 swagger/yapi/apifox 的接口定义生成 TypeScript/JavaScript 的接口类型及其请求函数代码。
361 lines (359 loc) • 10.8 kB
JavaScript
const require_chunk = require('./chunk-nOFOJqeH.js');
const dayjs = require_chunk.__toESM(require("dayjs"));
const swagger_client = require_chunk.__toESM(require("swagger-client"));
const lodash = require_chunk.__toESM(require("lodash"));
//#region src/swaggerJsonToYApiData.ts
let SwaggerData, isOAS3;
function handlePath(path) {
if (path === "/") return path;
if (path.charAt(0) !== "/") path = `/${path}`;
if (path.charAt(path.length - 1) === "/") path = path.substr(0, path.length - 1);
return path;
}
function openapi2swagger(data) {
data.swagger = "2.0";
(0, lodash.each)(data.paths, (apis) => {
(0, lodash.each)(apis, (api) => {
(0, lodash.each)(api.responses, (res) => {
if (res.content && res.content["application/json"] && typeof res.content["application/json"] === "object") {
Object.assign(res, res.content["application/json"]);
delete res.content;
}
if (res.content && res.content["application/hal+json"] && typeof res.content["application/hal+json"] === "object") {
Object.assign(res, res.content["application/hal+json"]);
delete res.content;
}
if (res.content && res.content["*/*"] && typeof res.content["*/*"] === "object") {
Object.assign(res, res.content["*/*"]);
delete res.content;
}
});
if (api.requestBody) {
if (!api.parameters) api.parameters = [];
const body = {
type: "object",
name: "body",
in: "body"
};
try {
body.schema = api.requestBody.content["application/json"].schema;
} catch (e) {
body.schema = {};
}
api.parameters.push(body);
}
});
});
return data;
}
async function handleSwaggerData(res) {
return new Promise((resolve) => {
const data = (0, swagger_client.default)({ spec: res });
data.then((res$1) => {
resolve(res$1.spec);
});
});
}
async function run(res) {
const interfaceData = {
apis: [],
cats: [],
basePath: "",
swaggerData: {}
};
if (typeof res === "string" && res) try {
res = JSON.parse(res);
} catch (e) {
console.error("json 解析出错", e.message);
}
isOAS3 = res.openapi && String(res.openapi).startsWith("3.");
if (isOAS3) res = openapi2swagger(res);
res = await handleSwaggerData(res);
SwaggerData = res;
interfaceData.swaggerData = SwaggerData;
interfaceData.basePath = res.basePath || "";
if (res.tags && Array.isArray(res.tags)) res.tags.forEach((tag) => {
interfaceData.cats.push({
name: tag.name,
desc: tag.description
});
});
else res.tags = [];
(0, lodash.each)(res.paths, (apis, path) => {
delete apis.parameters;
(0, lodash.each)(apis, (api, method) => {
api.path = path;
api.method = method;
let data = null;
try {
data = handleSwagger(api, res.tags);
if (data.catname) {
if (!(0, lodash.find)(interfaceData.cats, (item) => item.name === data.catname)) {
if (res.tags.length === 0) interfaceData.cats.push({
name: data.catname,
desc: data.catname
});
}
}
} catch (err) {
data = null;
}
if (data) interfaceData.apis.push(data);
});
});
interfaceData.cats = interfaceData.cats.filter((catData) => {
const catName = catData.name;
return (0, lodash.find)(interfaceData.apis, (apiData) => {
return apiData.catname === catName;
});
});
return interfaceData;
}
function handleSwagger(data, originTags = []) {
const api = {};
api.method = data.method.toUpperCase();
api.title = data.summary || data.path;
api.desc = data.description;
api.catname = null;
if (data.tags && Array.isArray(data.tags)) {
api.tag = data.tags;
for (let i = 0; i < data.tags.length; i++) {
if (/v[0-9.]+/.test(data.tags[i])) continue;
if (originTags.length > 0 && (0, lodash.find)(originTags, (item) => {
return item.name === data.tags[i];
})) {
api.catname = data.tags[i];
break;
}
if (originTags.length === 0) {
api.catname = data.tags[i];
break;
}
}
}
api.path = handlePath(data.path);
api.req_params = [];
api.req_body_form = [];
api.req_headers = [];
api.req_query = [];
api.req_body_type = "raw";
api.res_body_type = "raw";
if (data.produces && data.produces.indexOf("application/json") > -1) {
api.res_body_type = "json";
api.res_body_is_json_schema = true;
}
if (data.consumes && Array.isArray(data.consumes)) {
if (data.consumes.indexOf("application/x-www-form-urlencoded") > -1 || data.consumes.indexOf("multipart/form-data") > -1) api.req_body_type = "form";
else if (data.consumes.indexOf("application/json") > -1) {
api.req_body_type = "json";
api.req_body_is_json_schema = true;
}
}
api.res_body = handleResponse(data.responses);
try {
JSON.parse(api.res_body);
api.res_body_type = "json";
api.res_body_is_json_schema = true;
} catch (e) {
api.res_body_type = "raw";
}
function simpleJsonPathParse(key, json) {
if (!key || typeof key !== "string" || key.indexOf("#/") !== 0 || key.length <= 2) return null;
let keys = key.substr(2).split("/");
keys = keys.filter((item) => {
return item;
});
for (let i = 0, l = keys.length; i < l; i++) try {
json = json[keys[i]];
} catch (e) {
json = "";
break;
}
return json;
}
/**
* 从 schema 中提取类型信息
* @param schema 参数或响应的 schema 对象
* @returns 类型字符串
*/
function extractTypeFromSchema(schema) {
if (!schema || typeof schema !== "object") return "string";
if (schema.type) {
if (schema.type === "array" && schema.items) {
const itemType = extractTypeFromSchema(schema.items);
return `array<${itemType}>`;
}
return schema.type;
}
if (schema.$ref) return "object";
if (schema.properties) return "object";
if (schema.enum) return "string";
if (schema.format) switch (schema.format) {
case "int32":
case "int64": return "integer";
case "float":
case "double": return "number";
case "date":
case "date-time": return "string";
default: return "string";
}
return "string";
}
/**
* 从 schema 中提取类型信息,返回标准类型字符串
* @param schema 参数或响应的 schema 对象
* @returns 标准类型字符串
*/
function getStandardTypeFromSchema(schema) {
if (!schema || typeof schema !== "object") return "string";
if (schema.type) return schema.type;
if (schema.$ref) return "object";
if (schema.properties) return "object";
if (schema.enum) return "string";
if (schema.format) switch (schema.format) {
case "int32":
case "int64": return "integer";
case "float":
case "double": return "number";
case "date":
case "date-time": return "string";
default: return "string";
}
return "string";
}
if (data.parameters && Array.isArray(data.parameters)) data.parameters.forEach((param) => {
if (param && typeof param === "object" && param.$ref) param = simpleJsonPathParse(param.$ref, { parameters: SwaggerData.parameters });
const defaultParam = {
name: param.name,
desc: param.description,
required: param.required ? "1" : "0"
};
if (param.in) switch (param.in) {
case "path":
if (param.schema) {
defaultParam.type = getStandardTypeFromSchema(param.schema);
if (param.schema.type === "array" && param.schema.items) defaultParam.schema = param.schema;
} else defaultParam.type = param.type;
api.req_params.push(defaultParam);
break;
case "query":
if (param.schema) {
defaultParam.type = getStandardTypeFromSchema(param.schema);
if (param.schema.type === "array" && param.schema.items) defaultParam.schema = param.schema;
} else defaultParam.type = param.type;
api.req_query.push(defaultParam);
break;
case "body":
handleBodyPamras(param.schema, api);
break;
case "formData":
if (param.schema) {
const formType = getStandardTypeFromSchema(param.schema);
defaultParam.type = formType === "file" ? "file" : "text";
if (param.schema.type === "array" && param.schema.items) defaultParam.schema = param.schema;
} else defaultParam.type = param.type === "file" ? "file" : "text";
if (param.example) defaultParam.example = param.example;
api.req_body_form.push(defaultParam);
break;
case "header":
if (param.schema) {
defaultParam.type = getStandardTypeFromSchema(param.schema);
if (param.schema.type === "array" && param.schema.items) defaultParam.schema = param.schema;
} else defaultParam.type = param.type;
api.req_headers.push(defaultParam);
break;
default: break;
}
else {
if (param.schema) {
defaultParam.type = getStandardTypeFromSchema(param.schema);
if (param.schema.type === "array" && param.schema.items) defaultParam.schema = param.schema;
} else defaultParam.type = param.type;
api.req_query.push(defaultParam);
}
});
return api;
}
function isJson(json) {
try {
return JSON.parse(json);
} catch (e) {
return false;
}
}
function handleBodyPamras(data, api) {
api.req_body_other = JSON.stringify(data, null, 2);
if (isJson(api.req_body_other)) {
api.req_body_type = "json";
api.req_body_is_json_schema = true;
}
}
function handleResponse(api) {
let res_body = "";
if (!api || typeof api !== "object") return res_body;
const codes = Object.keys(api);
let curCode;
if (codes.length > 0) {
if (codes.indexOf("200") > -1) curCode = "200";
else curCode = codes[0];
const res = api[curCode];
if (res && typeof res === "object") {
if (res.schema) res_body = JSON.stringify(res.schema, null, 2);
else if (res.description) res_body = res.description;
} else if (typeof res === "string") res_body = res;
else res_body = "";
} else res_body = "";
return res_body;
}
async function swaggerJsonToYApiData(data) {
const yapiData = await run(data);
if (!yapiData.cats.length) {
yapiData.cats = [{
name: "default",
desc: "default"
}];
yapiData.apis.forEach((api) => {
api.catname = "default";
});
}
const currentTime = (0, dayjs.default)().unix();
const project = {
_id: 0,
name: yapiData.swaggerData.info.title,
desc: yapiData.swaggerData.info.description || "",
basepath: yapiData.swaggerData.basePath || "",
tag: [],
env: [{
name: "local",
domain: `${yapiData.swaggerData.schemes?.[0] || "http"}://${yapiData.swaggerData.host || "127.0.0.1"}`
}]
};
const cats = yapiData.cats.map((cat, index) => ({
_id: index + 1,
name: cat.name,
desc: cat.desc,
add_time: currentTime,
up_time: currentTime
}));
const interfaces = yapiData.apis.map((api, index) => ({
...api,
_id: index + 1,
project_id: 0,
catid: cats.find((cat) => cat.name === api.catname)?._id || -1,
tag: api.tag || [],
add_time: currentTime,
up_time: currentTime
}));
return {
project,
cats,
interfaces
};
}
//#endregion
Object.defineProperty(exports, 'swaggerJsonToYApiData', {
enumerable: true,
get: function () {
return swaggerJsonToYApiData;
}
});