erest
Version:
Easy to build api server depend on @leizm/web and express.
154 lines (153 loc) • 6.29 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = apiDocs;
const params_1 = require("../../params");
const utils_1 = require("../../utils");
const utils_2 = require("./utils");
function apiDocs(data) {
const group = {};
const groupTitles = {};
function add(name, content, title) {
if (!Array.isArray(group[name])) {
group[name] = [];
groupTitles[name] = [];
}
group[name].push(content.trim());
groupTitles[name].push(title);
}
function parseType(type) {
return !type || data.typeManager.has(type)
? (0, utils_2.stringOrEmpty)(type)
: `[${type}](/schema#${type.replace("[]", "").toLocaleLowerCase()})`;
}
function paramsTable(item) {
const paramsList = [];
paramsList.push((0, utils_2.tableHeader)(["参数名", "位置", "类型", "格式化", "必填", "说明"]));
// 参数输出
for (const place of ["params", "query", "body", "headers"]) {
for (const name in item[place]) {
const info = item[place][name];
let required = item.required.has(name) ? "是" : "否";
if (required !== "是") {
for (const names of item.requiredOneOf) {
if (names.indexOf(name) !== -1) {
required = "选填";
break;
}
}
}
const comment = info.type === "ENUM" ? `${info.comment} (${info.params.join(",")})` : info.comment;
const type = parseType(info.type);
paramsList.push((0, utils_2.fieldString)([(0, utils_2.stringOrEmpty)(name, true), place, type, (0, utils_2.itemTF)(info.format), required, (0, utils_2.stringOrEmpty)(comment)]));
}
}
// 选填参数输出
if (item.requiredOneOf.length > 0) {
paramsList.push("\n选填参数:\n");
for (const names of item.requiredOneOf) {
paramsList.push(`- \`${names.join("`, `")}\` 其中一个`);
}
}
// 没有参数
if (paramsList.length === 1) {
return;
}
return paramsList.join("\n");
}
function responseTable(response) {
if (!response)
return;
if (typeof response === "string") {
return `[${response}](/schema#${response.replace("[]", "").toLocaleLowerCase()})`;
}
// FIXME: 处理更多返回类型
if ((0, params_1.isZodSchema)(response) || typeof response.type === "string")
return;
const paramsList = [];
paramsList.push((0, utils_2.tableHeader)(["参数名", "类型", "必填", "说明"]));
// 参数输出
for (const name in response) {
const info = response[name];
const comment = info.type === "ENUM" ? `${info.comment} (${info.params.join(",")})` : info.comment;
const type = parseType(info.type);
paramsList.push((0, utils_2.fieldString)([(0, utils_2.stringOrEmpty)(name, true), type, (0, utils_2.itemTF)(info.required), (0, utils_2.stringOrEmpty)(comment)]));
}
// 没有参数
if (paramsList.length === 1)
return;
return paramsList.join("\n");
}
function formatExampleInput(inputData) {
const ret = Object.assign({}, inputData);
for (const name in ret) {
if (name[0] === "$")
delete ret[name];
}
return ret;
}
function formatExample(str, data) {
return str
.split("\n")
.map((s) => {
const r = s.match(/"(.*)":/);
if (r?.[1] && data[r[1]] && data[r[1]].comment) {
return `${s} \t// ${data[r[1]].comment}`;
}
return s;
})
.join("\n");
}
function examples(exampleList, response) {
return exampleList
.map((item) => {
const title = `// ${(0, utils_2.stringOrEmpty)(item.name)} - ${item.path} `;
const header = item.headers ? `\nheaders = ${(0, utils_1.jsonStringify)(item.headers, 2)}\n` : "";
const input = item.input && `input = ${(0, utils_1.jsonStringify)(formatExampleInput(item.input), 2)};`;
let outString = (0, utils_1.jsonStringify)(item.output || {}, 2);
// FIXME: 处理更多返回类型
if (response && typeof response === "object" && "fields" in response) {
outString = formatExample(outString, response.fields);
}
const output = `output = ${outString};`;
return `${title}\n${header}${input}\n${output}`.trim();
})
.join("\n\n");
}
for (const item of Object.values(data.apis)) {
const tested = (0, utils_2.itemTFEmoji)(item.tested);
const tit = (0, utils_2.stringOrEmpty)(item.title);
const method = item.method.toUpperCase();
const line = [`## ${tit} ${tested}`];
line.push(`\n请求地址:**${method}** \`${item.realPath}\``);
if (item.description) {
line.push(item.description
.split("\n")
.map((it) => it.trim())
.join("\n"));
}
const paramsDoc = paramsTable(item);
if (paramsDoc) {
line.push(`\n### 参数:\n\n${paramsDoc}`);
}
else {
line.push("\n参数:无参数");
}
const responseDoc = responseTable(item.response);
if (responseDoc) {
line.push(`\n### 返回结果:\n\n${responseDoc}`);
}
if (item.examples.length > 0) {
line.push("\n### 使用示例:\n");
line.push("```javascript");
line.push(examples(item.examples, item.responseSchema));
line.push("\n```");
}
const title = ` - ${method} \`${item.path}\` - ${tit}`;
add(item.group, line.join("\n"), title);
}
const list = [];
for (const [name, g] of Object.entries(group)) {
list.push({ name, content: g.join("\n\n") });
}
return { list, groupTitles };
}
;