UNPKG

@yogeliu/mcp-server-yapi

Version:

Enhanced YAPI MCP server with multi-project support and enterprise features

176 lines 5.89 kB
import { z } from "zod"; import { logger } from "mcp-framework"; import { readFileSync, existsSync } from "fs"; import { resolve } from "path"; /** * 全局配置实例 */ let globalConfig = null; /** * 环境变量验证模式 - 支持旧版单项目配置 */ const LegacyConfigSchema = z.object({ YAPI_BASE_URL: z.string().url("YAPI_BASE_URL必须是有效的URL"), YAPI_TOKEN: z.string().min(1, "YAPI_TOKEN不能为空"), }); /** * 环境变量验证模式 - 新版多项目配置 */ const MultiProjectConfigSchema = z.object({ YAPI_PROJECTS: z.string().min(1, "YAPI_PROJECTS不能为空").optional(), YAPI_PROJECTS_FILE: z.string().min(1, "YAPI_PROJECTS_FILE不能为空").optional(), YAPI_DEFAULT_PROJECT: z.string().optional(), }); /** * 加载和验证配置 * @returns {YapiConfig} 验证后的配置对象 * @throws {Error} 当配置验证失败时抛出错误 */ export function loadConfig() { try { // 尝试加载多项目配置 if (process.env.YAPI_PROJECTS || process.env.YAPI_PROJECTS_FILE) { return loadMultiProjectConfig(); } // 回退到单项目配置(向后兼容) return loadLegacyConfig(); } catch (error) { if (error instanceof z.ZodError) { const messages = error.errors.map((err) => `${err.path.join(".")}: ${err.message}`); throw new Error(`配置验证失败:\n${messages.join("\n")}`); } throw error; } } /** * 加载多项目配置 */ function loadMultiProjectConfig() { const env = MultiProjectConfigSchema.parse(process.env); let projectsConfig; // 优先从文件加载 if (env.YAPI_PROJECTS_FILE) { try { const filePath = resolve(env.YAPI_PROJECTS_FILE); if (!existsSync(filePath)) { throw new Error(`配置文件不存在: ${filePath}`); } const fileContent = readFileSync(filePath, 'utf8'); projectsConfig = JSON.parse(fileContent); logger.debug(`🔧 从文件加载项目配置: ${filePath}`); } catch (error) { if (error instanceof SyntaxError) { throw new Error(`配置文件JSON格式错误: ${env.YAPI_PROJECTS_FILE}`); } throw error; } } else if (env.YAPI_PROJECTS) { // 从环境变量加载(向后兼容) try { projectsConfig = JSON.parse(env.YAPI_PROJECTS); logger.debug("🔧 从环境变量加载项目配置"); } catch (error) { throw new Error("YAPI_PROJECTS必须是有效的JSON格式"); } } else { throw new Error("必须设置 YAPI_PROJECTS_FILE 或 YAPI_PROJECTS"); } // 验证项目配置结构 const projects = {}; for (const [projectName, config] of Object.entries(projectsConfig)) { if (!config || typeof config !== 'object') { throw new Error(`项目 ${projectName} 配置无效`); } const projectConfig = config; if (!projectConfig.baseUrl || !projectConfig.token) { throw new Error(`项目 ${projectName} 缺少必需的 baseUrl 或 token`); } projects[projectName] = { baseUrl: projectConfig.baseUrl.replace(/\/$/, ""), token: projectConfig.token, }; } const yapiConfig = { projects, defaultProject: env.YAPI_DEFAULT_PROJECT, }; logger.debug(`🔧 多项目YAPI配置加载成功: ${Object.keys(projects).length}个项目, 默认项目: ${yapiConfig.defaultProject || '未设置'}`); return yapiConfig; } /** * 加载单项目配置(向后兼容) */ function loadLegacyConfig() { const env = LegacyConfigSchema.parse(process.env); const projectConfig = { baseUrl: env.YAPI_BASE_URL.replace(/\/$/, ""), token: env.YAPI_TOKEN, }; const yapiConfig = { projects: { default: projectConfig }, defaultProject: 'default', }; logger.debug(`🔧 单项目YAPI配置加载成功: baseUrl=${projectConfig.baseUrl}, token=${projectConfig.token}`); return yapiConfig; } /** * 初始化配置(在应用启动时调用) * @throws {Error} 当配置验证失败时抛出错误 */ export function initializeConfig() { globalConfig = loadConfig(); } /** * 获取全局配置 * @returns {YapiConfig} 全局配置对象 * @throws {Error} 当配置未初始化时抛出错误 */ export function getConfig() { if (!globalConfig) { throw new Error("配置未初始化,请先调用 initializeConfig()"); } return globalConfig; } /** * 获取指定项目的配置 * @param projectName 项目名,如果不指定则使用默认项目 * @returns {ProjectConfig} 项目配置对象 * @throws {Error} 当项目不存在时抛出错误 */ export function getProjectConfig(projectName) { const config = getConfig(); const targetProject = projectName || config.defaultProject; if (!targetProject) { throw new Error("未指定项目名且没有默认项目"); } const projectConfig = config.projects[targetProject]; if (!projectConfig) { const availableProjects = Object.keys(config.projects).join(', '); throw new Error(`项目 '${targetProject}' 不存在。可用项目: ${availableProjects}`); } return projectConfig; } /** * 获取所有可用项目名列表 * @returns {string[]} 项目名列表 */ export function getAvailableProjects() { const config = getConfig(); return Object.keys(config.projects); } /** * 验证配置有效性 * @param config 配置对象 * @returns true表示配置有效 */ export function validateConfig(config) { return !!(config.projects && Object.keys(config.projects).length > 0); } //# sourceMappingURL=config.js.map