UNPKG

@alova/wormhole

Version:

More modern openAPI generating solution for alova.js

232 lines (231 loc) 9.12 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generatorHelper = exports.GeneratorHelper = void 0; const node_path_1 = __importDefault(require("node:path")); const lodash_1 = require("lodash"); const zod_validation_error_1 = require("zod-validation-error"); const parser_1 = require("../../core/parser"); const getAlovaVersion_1 = __importDefault(require("../../functions/getAlovaVersion")); const getAutoTemplateType_1 = __importDefault(require("../../functions/getAutoTemplateType")); const helper_1 = require("../../helper"); const utils_1 = require("../../utils"); const zType_1 = require("./zType"); class GeneratorHelper { constructor() { this.defaultConfig = Object.freeze({ input: '', output: '', responseMediaType: 'application/json', bodyMediaType: 'application/json', type: 'auto', global: 'Apis', globalHost: 'globalThis', useImportType: false, defaultRequire: false, }); } static getInstance() { if (!GeneratorHelper.instance) { GeneratorHelper.instance = new GeneratorHelper(); } return GeneratorHelper.instance; } static load(config) { const ins = new GeneratorHelper(); return ins.load(config); } getConfig() { return this.readConfig; } getDefaultConfig() { return this.defaultConfig; } async load(config) { // 合并配置 const mergedConfig = { ...this.defaultConfig, ...config }; // 验证配置 const validatedConfig = await GeneratorHelper.validateConfig(mergedConfig); // 更新配置 this.config = validatedConfig; this.readConfig = Object.freeze(this.config); this.pluginDriver = new helper_1.PluginDriver(this.config.plugins); helper_1.logger.debug('GeneratorConfig loaded successfully', this.config); return this; } getAlovaVersion(projectPath) { return GeneratorHelper.getAlovaVersion(this.config, projectPath); } getTemplateType(projectPath) { return GeneratorHelper.getTemplateType(this.config, projectPath); } getPluginDriver() { return this.pluginDriver; } openApiData(projectPath) { return GeneratorHelper.openApiData(this.config, projectPath); } static async validateConfig(config) { let result = config; try { result = zType_1.zGeneratorConfig.parse(config); } catch (error) { const zError = (0, zod_validation_error_1.fromError)(error); throw helper_1.logger.throwError(zError.message, zError.details); } return result; } static getAlovaVersion(config, projectPath) { const configVersion = Number(config.version); return Number.isNaN(configVersion) ? (0, getAlovaVersion_1.default)(projectPath) : `v${configVersion}`; } static getTemplateType(config, projectPath) { let type; const configType = config.type ?? 'auto'; // Determine the template type based on the type in the configuration file switch (configType) { case 'ts': case 'typescript': type = 'typescript'; break; case 'module': type = 'module'; break; case 'auto': type = (0, getAutoTemplateType_1.default)(projectPath); break; default: type = 'commonjs'; break; } return type; } static openApiData(config, projectPath) { return parser_1.openApiParser.parse(config.input, { projectPath, platformType: config.platform, fetchOptions: config.fetchOptions, }); } static async generate(config, options) { const pluginDriver = new helper_1.PluginDriver(config.plugins); // plugin: handle before parse openapi await pluginDriver.hookParallel('beforeOpenapiParse', [Object.freeze(config)]); let document = await this.openApiData(config, options.projectPath); if (!document) { return false; } // plugin: handle after parse openapi document = await pluginDriver.hookSeq('afterOpenapiParse', [document], (result, args) => { return result ? [result] : args; }) ?? document; const output = node_path_1.default.resolve(options.projectPath, config.output); const version = GeneratorHelper.getAlovaVersion(config, options.projectPath); const templateHelper = helper_1.TemplateHelper.load({ type: this.getTemplateType(config, options.projectPath), version, }); const templateData = await new parser_1.TemplateParser().parse(document, { projectPath: options.projectPath, generatorConfig: config, }); const oldTemplateData = helper_1.TemplateHelper.getData(options.projectPath, config.output); // Transform output filename by config.fileNameCase without changing template filename const toCase = (name) => (0, utils_1.toCase)(name, config.fileNameCase); // Inject computed filenames into template render data for templates to reference Object.assign(templateData, { createApisFileName: toCase('createApis'), apiDefinitionsFileName: toCase('apiDefinitions'), globalsDFileName: toCase('globals.d'), indexFileName: toCase('index'), }); // Do you need to generate api files? if (!options.force && (0, lodash_1.isEqual)(templateData, oldTemplateData)) { return false; } if (oldTemplateData) { await templateHelper.unlink([ // Delete old API creation file oldTemplateData.createApisFileName ?? '', // Delete old API definition file oldTemplateData.apiDefinitionsFileName ?? '', // Delete old global type declaration file (.d.ts) { fileName: oldTemplateData.globalsDFileName ?? '', ext: '.ts', }, ], { output }); } await helper_1.TemplateHelper.setData(templateData, options.projectPath, config.output); const generateFiles = [ { fileName: 'createApis', outFileName: templateData.createApisFileName, data: templateData, output, root: true, hasVersion: false, }, { fileName: 'apiDefinitions', outFileName: templateData.apiDefinitionsFileName, data: templateData, output, root: true, hasVersion: false, }, { fileName: 'globals.d', outFileName: templateData.globalsDFileName, data: templateData, output, ext: '.ts', root: true, hasVersion: false, }, ]; if (!(await (0, utils_1.existsPromise)(node_path_1.default.join(output, `${templateData.indexFileName}${templateHelper.getExt()}`)))) { generateFiles.push({ fileName: 'index', outFileName: templateData.indexFileName, data: templateData, output, root: true, hasVersion: false, }); } // plugin: handle before code generate let codeGenError; try { const unhandledGenerateFiles = []; for (const file of generateFiles) { const fileName = `${file.outFileName ?? file.fileName}${file.ext ?? templateHelper.getExt()}`; const data = await pluginDriver.hookFirst('beforeCodeGenerate', [ file.data, fileName, { renderTemplate: () => templateHelper.readAndRenderTemplate(file.fileName, file.data, file), fileName: file.fileName, }, ]); if (!data) { unhandledGenerateFiles.push(file); continue; } await (0, utils_1.generateFile)(file.output, fileName, data); } await templateHelper.outputFiles(unhandledGenerateFiles); } catch (error) { codeGenError = error; } // plugin: handle after code gen await pluginDriver.hookParallel('afterCodeGenerate', [codeGenError]); return true; } } exports.GeneratorHelper = GeneratorHelper; exports.generatorHelper = GeneratorHelper.getInstance();