UNPKG

@lonu/stc

Version:

A tool for converting OpenApi/Swagger/Apifox into code.

124 lines (123 loc) 4.23 kB
import Logs from "./console.js"; import { PluginManager } from "./plugins/index.js"; import { getApiPath, getDefinition } from "./core.js"; import { createDiffFile, createFile, readFile, removeFile } from "./utils.js"; import { getT } from "./i18n/index.js"; const LOCK_FILE = ".stc.lock"; /** * 初始化插件管理器 */ const initPluginManager = (context) => { const pluginManager = new PluginManager(); // 注册插件 pluginManager.register([ ...(context.options.plugins ?? []), ]); // 启动所有插件 pluginManager.setupAll(context); }; /** * 创建上下文 * @param options */ const createContext = (context) => { // 初始化插件管理器 initPluginManager(context); return context; }; /** * 获取 Swagger 数据 * @param urlOrPath - 远程地址或本地 * @returns */ const getData = async (urlOrPath, _outDir) => { try { // const lockFile = await readFile(`${outDir}/${LOCK_FILE}`); let data; // 从本地文件获取 Swagger 数据 if (!/^http(s?):\/\//.test(urlOrPath)) { const content = await readFile(urlOrPath); data = JSON.parse(content); } else { // 从远程地址获取 Swagger 数据 const res = await fetch(urlOrPath); data = await res.json(); } // 对比 path 和 definitions/schemas 数据是否有变化,有变化则使用新数据 // if (lockFile) { // const oldData = JSON.parse(lockFile) as unknown as ISwaggerResult; // createFile( // `${outDir}/.stc_new.lock`, // JSON.stringify(data, null, 2), // { // banner: false, // }, // ); // const isChange = diff["diffLines"]( // JSON.stringify(oldData, null, 2), // JSON.stringify(data, null, 2), // ); // createFile( // `${outDir}/.stc_diff.lock`, // JSON.stringify(isChange, null, 2), // { // banner: false, // }, // ); // } return data; } catch (error) { throw new Error(getT("$t(app.apiJsonFileError)", { error })); } }; /** * 启动 * @param options - 配置 */ export const start = async (options) => { // 创建上下文 const context = createContext({ options }); const data = await getData(options.url, options.outDir); // 触发插件 onload 事件 context.onLoad?.(data, context.options); // 处理类型定义。v2 版本中,通过 `definitions` 属性获取。而 v3 版本,则通过 `components.schemas` 属性获取。 const defData = getDefinition(data.definitions || data.components?.schemas); // 触发插件 onDefinition 事件 context.onDefinition?.(defData, context.options); const actionData = getApiPath(data.paths, options); // 触发插件 onAction 事件 context.onAction?.(actionData, context.options); if (options.clean) { const exclude = [`${options.outDir}/${LOCK_FILE}`]; if (!options.shared) { exclude.push(`${options.outDir}/shared/**/*`); } await removeFile(`${options.outDir}/**/*.*`, { exclude, }); } // 触发插件 onTransform 事件 const transformData = await context.onTransform?.(defData, actionData, context.options); // 写入类型定义文件 if (transformData?.definition?.content) { const name = `${options.outDir}/${transformData.definition.filename}`; const content = transformData.definition.content; createDiffFile(name, content, options.clean); } // 写入 API 文件 if (transformData?.action) { transformData.action.forEach((content, filename) => { createDiffFile(`${options.outDir}/${filename}`, content, options.clean); }); } // 保存数据 createFile(`${options.outDir}/${LOCK_FILE}`, JSON.stringify(data, null, 2), { banner: false, }); console.log("\n"); Logs.success(`${getT("$t(app.generateFileDone)")}\n\t${options.outDir}\n`); // 触发插件 onEnd 事件 context.onEnd?.(context.options); };