UNPKG

erest

Version:

Easy to build api server depend on @leizm/web and express.

154 lines (153 loc) 6.29 kB
"use strict"; 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 }; }