Skip to main content
Glama
config.ts34.6 kB
import { ref, computed } from "vue"; import { defineStore } from "pinia"; import { useAppStore } from "./app"; // 配置导入导出相关类型 export interface ConfigExportOptions { types: string[]; format: "json" | "yaml" | "zip"; sensitiveData: "exclude" | "encrypt" | "include"; password?: string; notes?: string; } export interface ConfigImportResult { success: boolean; message: string; appliedCounts?: Record<string, number>; errors?: string[]; warnings?: string[]; } export interface ConfigValidationResult { valid: boolean; configCounts: Record<string, number>; errors: Array<{ id: string; message: string; details: string }>; warnings: Array<{ id: string; message: string; details: string }>; } export interface ConfigConflict { id: string; type: string; title: string; current: any; incoming: any; resolution: "keep" | "replace" | "merge"; } export interface ConfigMigrationResult { success: boolean; fromVersion: string; toVersion: string; migratedCounts: Record<string, number>; warnings: string[]; errors: string[]; } export interface ConfigVersionInfo { version: string; format?: string; compatibleVersions: string[]; migrationPath?: string[]; deprecated?: boolean; recommended?: boolean; description?: string; features: string[]; newFeatures?: string[]; breakingChanges?: string[]; } export interface ConfigConflictResolution { conflictId: string; resolution: "keep" | "replace" | "merge" | "custom"; customValue?: any; description?: string; } export interface ConfigMigrationStep { id: string; name: string; title?: string; description: string; fromVersion: string; toVersion: string; targetVersion?: string; type?: string; estimatedDuration?: string; required: boolean; executed: boolean; actions?: Array<{ id: string; type: string; description: string; }>; risks?: string[]; result?: { success: boolean; message: string; data?: any; }; } export interface ConfigBackup { id: string; name: string; timestamp: Date; size: number; types: string[]; description?: string; version?: string; } export interface ConfigMigrationOptions { backupStrategy: "full" | "incremental" | "none"; failureHandling: "rollback" | "continue" | "abort"; validationLevel: "strict" | "standard" | "loose"; parallelExecution: boolean; } export const useConfigStore = defineStore("config", () => { const appStore = useAppStore(); // State const loading = ref(false); const error = ref<string | null>(null); const backups = ref<ConfigBackup[]>([]); const exportHistory = ref< Array<{ id: string; timestamp: Date; filename: string; types: string[]; success: boolean; }> >([]); // 迁移和冲突解决状态 const migrationInProgress = ref(false); const currentVersion = ref("1.0.0"); const availableVersions = ref<ConfigVersionInfo[]>([]); const migrationSteps = ref<ConfigMigrationStep[]>([]); const conflictResolutions = ref<ConfigConflictResolution[]>([]); // Actions const setLoading = (value: boolean) => { loading.value = value; }; const setError = (value: string | null) => { error.value = value; if (value) { appStore.addNotification({ type: "error", title: "配置管理错误", message: value, duration: 5000, }); } }; const clearError = () => { error.value = null; }; // 导出配置 const exportConfig = async ( options: ConfigExportOptions, ): Promise<boolean> => { setLoading(true); clearError(); try { // 模拟导出过程 await new Promise((resolve) => setTimeout(resolve, 2000)); // 收集要导出的配置数据 const exportData: Record<string, any> = {}; for (const type of options.types) { exportData[type] = await getConfigData(type); } // 处理敏感信息 if (options.sensitiveData === "exclude") { removeSensitiveData(exportData); } else if (options.sensitiveData === "encrypt" && options.password) { encryptSensitiveData(exportData, options.password); } // 生成文件 const filename = generateFilename(options.format); const content = formatContent(exportData, options.format); // 下载文件 downloadFile(content, filename, getMimeType(options.format)); // 记录导出历史 exportHistory.value.unshift({ id: `export_${Date.now()}`, timestamp: new Date(), filename, types: options.types, success: true, }); appStore.addNotification({ type: "success", title: "配置导出成功", message: `已导出配置文件: ${filename}`, duration: 3000, }); return true; } catch (error) { const errorMessage = error instanceof Error ? error.message : "导出失败"; setError(errorMessage); return false; } finally { setLoading(false); } }; // 验证导入的配置 const validateImportConfig = async ( file: File, ): Promise<ConfigValidationResult> => { setLoading(true); try { const content = await readFileContent(file); const parsedConfig = parseConfigFile(content, file.name); // 验证配置结构 const result = await validateConfigStructure(parsedConfig); return result; } catch (error) { return { valid: false, configCounts: {}, errors: [ { id: "parse_error", message: "配置文件解析失败", details: error instanceof Error ? error.message : "未知错误", }, ], warnings: [], }; } finally { setLoading(false); } }; // 检测配置冲突 const detectConflicts = async ( parsedConfig: any, ): Promise<ConfigConflict[]> => { const conflicts: ConfigConflict[] = []; // 模拟冲突检测逻辑 for (const [type, configs] of Object.entries(parsedConfig)) { if (Array.isArray(configs)) { for (const config of configs) { const existing = await findExistingConfig(type, config); if (existing) { conflicts.push({ id: `${type}_${config.id || config.name}`, type, title: `${getConfigTypeLabel(type)} 配置冲突`, current: existing, incoming: config, resolution: "keep", }); } } } } return conflicts; }; // 应用导入的配置 const applyImportConfig = async ( parsedConfig: any, conflicts: ConfigConflict[], ): Promise<ConfigImportResult> => { setLoading(true); try { // 根据冲突解决方案处理配置 const resolvedConfig = resolveConflicts(parsedConfig, conflicts); // 应用配置 const appliedCounts: Record<string, number> = {}; for (const [type, configs] of Object.entries(resolvedConfig)) { const count = await applyConfigType(type, configs); appliedCounts[type] = count; } appStore.addNotification({ type: "success", title: "配置导入成功", message: `已成功导入配置`, duration: 3000, }); return { success: true, message: "配置导入完成", appliedCounts, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : "导入失败"; setError(errorMessage); return { success: false, message: errorMessage, errors: [errorMessage], }; } finally { setLoading(false); } }; // 创建配置备份 const createBackup = async ( name: string, types: string[], description?: string, ): Promise<string> => { setLoading(true); try { const backupData: Record<string, any> = {}; for (const type of types) { backupData[type] = await getConfigData(type); } const backup: ConfigBackup = { id: `backup_${Date.now()}`, name, timestamp: new Date(), size: JSON.stringify(backupData).length, types, description, }; // 存储备份(实际项目中应存储到服务器或本地存储) backups.value.unshift(backup); appStore.addNotification({ type: "success", title: "备份创建成功", message: `已创建配置备份: ${name}`, duration: 3000, }); return backup.id; } catch (error) { const errorMessage = error instanceof Error ? error.message : "备份失败"; setError(errorMessage); throw error; } finally { setLoading(false); } }; // 恢复配置备份 const restoreBackup = async (backupId: string): Promise<boolean> => { setLoading(true); try { const backup = backups.value.find((b) => b.id === backupId); if (!backup) { throw new Error("备份不存在"); } // 模拟恢复过程 await new Promise((resolve) => setTimeout(resolve, 2000)); appStore.addNotification({ type: "success", title: "备份恢复成功", message: `已恢复配置备份: ${backup.name}`, duration: 3000, }); return true; } catch (error) { const errorMessage = error instanceof Error ? error.message : "恢复失败"; setError(errorMessage); return false; } finally { setLoading(false); } }; // 检测配置版本 const detectConfigVersion = (config: any): ConfigVersionInfo => { // 检测配置结构特征来判断版本 const detectedVersion = detectVersionFromStructure(config); const versionInfo: ConfigVersionInfo = { version: detectedVersion, compatibleVersions: getCompatibleVersions(detectedVersion), features: getVersionFeatures(detectedVersion), deprecated: isVersionDeprecated(detectedVersion), }; if (needsMigration(detectedVersion, currentVersion.value)) { versionInfo.migrationPath = getMigrationPath( detectedVersion, currentVersion.value, ); } return versionInfo; }; // 创建迁移计划 const createMigrationPlan = ( fromVersion: string, toVersion: string, ): ConfigMigrationStep[] => { const steps: ConfigMigrationStep[] = []; const path = getMigrationPath(fromVersion, toVersion); for (let i = 0; i < path.length - 1; i++) { const from = path[i]; const to = path[i + 1]; steps.push({ id: `migrate_${from}_to_${to}`, name: `从 ${from} 迁移到 ${to}`, description: getMigrationDescription(from, to), fromVersion: from, toVersion: to, required: isMigrationRequired(from, to), executed: false, }); } return steps; }; // 执行配置迁移 const migrateConfig = async ( config: any, targetVersion: string, resolutions: ConfigConflictResolution[] = [], ): Promise<ConfigMigrationResult> => { migrationInProgress.value = true; try { const sourceVersion = detectVersionFromStructure(config); const steps = createMigrationPlan(sourceVersion, targetVersion); migrationSteps.value = steps; let migratedConfig = { ...config }; const migratedCounts: Record<string, number> = {}; const warnings: string[] = []; const errors: string[] = []; // 执行每个迁移步骤 for (const step of steps) { try { const result = await executeMigrationStep( migratedConfig, step, resolutions, ); step.executed = true; step.result = result; if (result.success) { migratedConfig = result.data; // 统计迁移的配置项数量 Object.keys(result.data).forEach((key) => { if (Array.isArray(result.data[key])) { migratedCounts[key] = (migratedCounts[key] || 0) + result.data[key].length; } }); } else { errors.push(`步骤 ${step.name} 失败: ${result.message}`); } } catch (error) { step.result = { success: false, message: error instanceof Error ? error.message : "未知错误", }; errors.push(`步骤 ${step.name} 执行异常: ${step.result.message}`); } } // 验证迁移后的配置 const validation = await validateMigratedConfig( migratedConfig, targetVersion, ); if (!validation.valid) { warnings.push(...validation.warnings); errors.push(...validation.errors); } const result: ConfigMigrationResult = { success: errors.length === 0, fromVersion: sourceVersion, toVersion: targetVersion, migratedCounts, warnings, errors, }; if (result.success) { appStore.addNotification({ type: "success", title: "配置迁移成功", message: `已成功从 ${sourceVersion} 迁移到 ${targetVersion}`, duration: 3000, }); } else { appStore.addNotification({ type: "error", title: "配置迁移失败", message: `迁移过程中发生 ${errors.length} 个错误`, duration: 5000, }); } return result; } catch (error) { const errorMessage = error instanceof Error ? error.message : "迁移失败"; setError(errorMessage); return { success: false, fromVersion: detectVersionFromStructure(config), toVersion: targetVersion, migratedCounts: {}, warnings: [], errors: [errorMessage], }; } finally { migrationInProgress.value = false; } }; // 高级冲突解决 const resolveConfigConflicts = async ( conflicts: ConfigConflict[], resolutions: ConfigConflictResolution[], ): Promise<any> => { const resolvedConfig: any = {}; for (const conflict of conflicts) { const resolution = resolutions.find((r) => r.conflictId === conflict.id); if (!resolution) { // 默认保留当前配置 resolvedConfig[conflict.type] = conflict.current; continue; } switch (resolution.resolution) { case "keep": resolvedConfig[conflict.type] = conflict.current; break; case "replace": resolvedConfig[conflict.type] = conflict.incoming; break; case "merge": resolvedConfig[conflict.type] = mergeConfigurations( conflict.current, conflict.incoming, ); break; case "custom": if (resolution.customValue !== undefined) { resolvedConfig[conflict.type] = resolution.customValue; } else { resolvedConfig[conflict.type] = conflict.current; } break; } } return resolvedConfig; }; // 智能配置合并 const mergeConfigurations = (current: any, incoming: any): any => { if (Array.isArray(current) && Array.isArray(incoming)) { // 数组合并:基于id或name去重 const merged = [...current]; for (const item of incoming) { const existingIndex = merged.findIndex( (existing) => existing.id === item.id || existing.name === item.name, ); if (existingIndex >= 0) { // 合并对象属性 merged[existingIndex] = { ...merged[existingIndex], ...item }; } else { merged.push(item); } } return merged; } else if (typeof current === "object" && typeof incoming === "object") { // 对象合并 return { ...current, ...incoming }; } else { // 基本类型:使用传入值 return incoming; } }; // 重启服务 const restartServices = async (): Promise<void> => { setLoading(true); try { // 模拟重启服务的过程 await new Promise((resolve) => setTimeout(resolve, 2000)); appStore.addNotification({ type: "success", title: "服务重启成功", message: "所有服务已成功重启", duration: 3000, }); } catch (error) { const errorMessage = error instanceof Error ? error.message : "服务重启失败"; setError(errorMessage); appStore.addNotification({ type: "error", title: "服务重启失败", message: errorMessage, duration: 5000, }); throw error; } finally { setLoading(false); } }; // Helper functions for migration const detectVersionFromStructure = (config: any): string => { // 根据配置结构特征检测版本 if (config.version) { return config.version; } // 检查特定字段来推断版本 if (config.servers && Array.isArray(config.servers)) { // 检查服务器配置结构 const server = config.servers[0]; if (server && server.mcpVersion) { return server.mcpVersion; } if (server && server.apiVersion) { return "2.0.0"; // 假设有apiVersion的是2.0版本 } } if (config.auth && config.auth.oauth2) { return "2.1.0"; // 有OAuth2支持的是2.1版本 } return "1.0.0"; // 默认版本 }; const getCompatibleVersions = (version: string): string[] => { const compatibilityMap: Record<string, string[]> = { "1.0.0": ["1.0.0", "1.1.0"], "1.1.0": ["1.0.0", "1.1.0", "1.2.0"], "1.2.0": ["1.1.0", "1.2.0", "2.0.0"], "2.0.0": ["1.2.0", "2.0.0", "2.1.0"], "2.1.0": ["2.0.0", "2.1.0"], }; return compatibilityMap[version] || [version]; }; const getVersionFeatures = (version: string): string[] => { const featureMap: Record<string, string[]> = { "1.0.0": ["基础服务器管理", "简单认证"], "1.1.0": ["批量操作", "配置模板"], "1.2.0": ["高级认证", "性能监控"], "2.0.0": ["新API架构", "WebSocket支持"], "2.1.0": ["OAuth2支持", "高级冲突解决"], }; return featureMap[version] || []; }; const isVersionDeprecated = (version: string): boolean => { const deprecatedVersions = ["1.0.0"]; return deprecatedVersions.includes(version); }; const needsMigration = (fromVersion: string, toVersion: string): boolean => { return ( fromVersion !== toVersion && !getCompatibleVersions(fromVersion).includes(toVersion) ); }; const getMigrationPath = ( fromVersion: string, toVersion: string, ): string[] => { // 定义迁移路径 const migrationPaths: Record<string, Record<string, string[]>> = { "1.0.0": { "1.1.0": ["1.0.0", "1.1.0"], "1.2.0": ["1.0.0", "1.1.0", "1.2.0"], "2.0.0": ["1.0.0", "1.1.0", "1.2.0", "2.0.0"], "2.1.0": ["1.0.0", "1.1.0", "1.2.0", "2.0.0", "2.1.0"], }, "1.1.0": { "1.2.0": ["1.1.0", "1.2.0"], "2.0.0": ["1.1.0", "1.2.0", "2.0.0"], "2.1.0": ["1.1.0", "1.2.0", "2.0.0", "2.1.0"], }, // 可以继续添加更多路径 }; return migrationPaths[fromVersion]?.[toVersion] || [fromVersion, toVersion]; }; const getMigrationDescription = ( fromVersion: string, toVersion: string, ): string => { const descriptions: Record<string, string> = { "1.0.0_1.1.0": "添加批量操作支持和配置模板功能", "1.1.0_1.2.0": "升级认证系统,增加性能监控功能", "1.2.0_2.0.0": "重构API架构,添加WebSocket实时通信", "2.0.0_2.1.0": "集成OAuth2认证,增强冲突解决机制", }; const key = `${fromVersion}_${toVersion}`; return descriptions[key] || `从版本 ${fromVersion} 升级到 ${toVersion}`; }; const isMigrationRequired = ( fromVersion: string, toVersion: string, ): boolean => { // 跨大版本的迁移通常是必需的 const fromMajor = parseInt(fromVersion.split(".")[0]); const toMajor = parseInt(toVersion.split(".")[0]); return fromMajor !== toMajor; }; const executeMigrationStep = async ( config: any, step: ConfigMigrationStep, resolutions: ConfigConflictResolution[], ): Promise<{ success: boolean; message: string; data?: any }> => { try { const { fromVersion, toVersion } = step; const migratedConfig = { ...config }; // 根据版本执行具体的迁移逻辑 if (fromVersion === "1.0.0" && toVersion === "1.1.0") { // 1.0.0 -> 1.1.0: 添加批量操作配置 migratedConfig.batchOperations = { enabled: true, maxConcurrent: 5, }; // 更新服务器配置格式 if (migratedConfig.servers) { migratedConfig.servers = migratedConfig.servers.map( (server: any) => ({ ...server, batchSupport: true, }), ); } } else if (fromVersion === "1.1.0" && toVersion === "1.2.0") { // 1.1.0 -> 1.2.0: 升级认证配置 if (migratedConfig.auth) { migratedConfig.auth = { ...migratedConfig.auth, advanced: { tokenRefresh: true, multiProvider: false, }, }; } } else if (fromVersion === "1.2.0" && toVersion === "2.0.0") { // 1.2.0 -> 2.0.0: 重构API配置 migratedConfig.apiVersion = "2.0"; migratedConfig.websocket = { enabled: true, port: 3001, }; // 重构服务器配置 if (migratedConfig.servers) { migratedConfig.servers = migratedConfig.servers.map( (server: any) => ({ id: server.id || `server_${Date.now()}`, name: server.name, config: { host: server.host || "localhost", port: server.port || 3000, protocol: server.protocol || "http", }, status: server.status || "stopped", version: "2.0.0", }), ); } } else if (fromVersion === "2.0.0" && toVersion === "2.1.0") { // 2.0.0 -> 2.1.0: 添加OAuth2支持 if (migratedConfig.auth) { migratedConfig.auth.oauth2 = { enabled: false, providers: [], }; } migratedConfig.conflictResolution = { strategy: "interactive", autoMerge: false, }; } // 更新版本信息 migratedConfig.version = toVersion; migratedConfig.migratedAt = new Date().toISOString(); return { success: true, message: `成功迁移到版本 ${toVersion}`, data: migratedConfig, }; } catch (error) { return { success: false, message: error instanceof Error ? error.message : "迁移步骤执行失败", }; } }; const validateMigratedConfig = async ( config: any, version: string, ): Promise<{ valid: boolean; warnings: string[]; errors: string[] }> => { const warnings: string[] = []; const errors: string[] = []; // 验证基本结构 if (!config.version) { errors.push("配置缺少版本信息"); } if (config.version !== version) { warnings.push(`配置版本 ${config.version} 与目标版本 ${version} 不匹配`); } // 根据版本验证特定字段 if (version >= "2.0.0") { if (!config.apiVersion) { warnings.push("2.0版本建议包含apiVersion字段"); } if (!config.websocket) { warnings.push("2.0版本建议配置WebSocket支持"); } } if (version >= "2.1.0") { if (!config.auth?.oauth2) { warnings.push("2.1版本建议配置OAuth2认证"); } } // 验证服务器配置 if (config.servers && Array.isArray(config.servers)) { config.servers.forEach((server: any, index: number) => { if (!server.id) { errors.push(`服务器配置 ${index} 缺少ID字段`); } if (!server.name) { errors.push(`服务器配置 ${index} 缺少名称字段`); } }); } return { valid: errors.length === 0, warnings, errors, }; }; // 删除配置备份 const deleteBackup = async (backupId: string): Promise<boolean> => { try { const index = backups.value.findIndex((b) => b.id === backupId); if (index === -1) { throw new Error("备份不存在"); } backups.value.splice(index, 1); appStore.addNotification({ type: "success", title: "备份删除成功", message: "配置备份已删除", duration: 3000, }); return true; } catch (error) { const errorMessage = error instanceof Error ? error.message : "删除失败"; setError(errorMessage); return false; } }; const getConfigData = async (type: string): Promise<any> => { // 模拟获取不同类型的配置数据 const mockData: Record<string, any> = { servers: [ { id: "1", name: "API Server", port: 3000, status: "running" }, { id: "2", name: "Test Server", port: 3001, status: "stopped" }, ], auth: [ { id: "1", type: "bearer", name: "API Token" }, { id: "2", type: "basic", name: "Basic Auth" }, ], openapi: [ { id: "1", name: "User API", version: "1.0.0" }, { id: "2", name: "Product API", version: "2.0.0" }, ], testcases: [ { id: "1", name: "Login Test", type: "auth" }, { id: "2", name: "CRUD Test", type: "api" }, ], settings: { theme: "light", language: "zh-CN", notifications: true, }, }; return mockData[type] || []; }; const getConfigTypeLabel = (type: string): string => { const labels: Record<string, string> = { servers: "服务器配置", auth: "认证配置", openapi: "OpenAPI规范", testcases: "测试用例", settings: "系统设置", }; return labels[type] || type; }; const removeSensitiveData = (data: any): void => { const sensitiveKeys = [ "password", "token", "secret", "key", "apiKey", "clientSecret", ]; const removeSensitive = (obj: any): void => { if (typeof obj === "object" && obj !== null) { for (const key in obj) { if ( sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive), ) ) { obj[key] = "[REMOVED]"; } else if (typeof obj[key] === "object") { removeSensitive(obj[key]); } } } }; removeSensitive(data); }; const encryptSensitiveData = (data: any, password: string): void => { const encrypt = (text: string): string => { // 简单的加密实现(实际项目中应使用更安全的加密方法) return btoa(text + password); }; const sensitiveKeys = [ "password", "token", "secret", "key", "apiKey", "clientSecret", ]; const encryptSensitive = (obj: any): void => { if (typeof obj === "object" && obj !== null) { for (const key in obj) { if ( sensitiveKeys.some((sensitive) => key.toLowerCase().includes(sensitive), ) ) { if (typeof obj[key] === "string") { obj[key] = `[ENCRYPTED]${encrypt(obj[key])}`; } } else if (typeof obj[key] === "object") { encryptSensitive(obj[key]); } } } }; encryptSensitive(data); }; const generateFilename = (format: string): string => { const timestamp = new Date().toISOString().replace(/[:.]/g, "-"); const extensions: Record<string, string> = { json: "json", yaml: "yaml", zip: "zip", }; return `mcp-config-${timestamp}.${extensions[format] || "json"}`; }; const formatContent = (data: any, format: string): string => { switch (format) { case "yaml": // 简单的YAML转换(实际项目中应使用专门的库) return JSON.stringify(data, null, 2) .replace(/"/g, "") .replace(/,$/gm, ""); case "zip": // ZIP格式处理(实际项目中应使用JSZip等库) return JSON.stringify(data, null, 2); default: return JSON.stringify(data, null, 2); } }; const getMimeType = (format: string): string => { const mimeTypes: Record<string, string> = { json: "application/json", yaml: "application/x-yaml", zip: "application/zip", }; return mimeTypes[format] || "application/json"; }; const downloadFile = ( content: string, filename: string, mimeType: string, ): void => { const blob = new Blob([content], { type: mimeType }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); }; const readFileContent = (file: File): Promise<string> => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = (e) => resolve(e.target?.result as string); reader.onerror = () => reject(new Error("文件读取失败")); reader.readAsText(file); }); }; const parseConfigFile = (content: string, filename: string): any => { const ext = filename.split(".").pop()?.toLowerCase(); if (ext === "json") { return JSON.parse(content); } else if (ext === "yaml" || ext === "yml") { // 实际项目中应使用yaml解析库 return JSON.parse(content); // 临时实现 } else { throw new Error("不支持的文件格式"); } }; const validateConfigStructure = async ( config: any, ): Promise<ConfigValidationResult> => { const errors: Array<{ id: string; message: string; details: string }> = []; const warnings: Array<{ id: string; message: string; details: string }> = []; const configCounts: Record<string, number> = {}; // 验证配置结构 const validTypes = ["servers", "auth", "openapi", "testcases", "settings"]; for (const [type, data] of Object.entries(config)) { if (!validTypes.includes(type)) { warnings.push({ id: `unknown_type_${type}`, message: `未知的配置类型: ${type}`, details: "此配置类型可能不被支持", }); continue; } if (Array.isArray(data)) { configCounts[type] = data.length; // 验证数组中的每个配置项 for (const item of data) { if (!item.id && !item.name) { errors.push({ id: `missing_identifier_${type}`, message: `${getConfigTypeLabel(type)} 缺少标识符`, details: "配置项必须包含 id 或 name 字段", }); } } } else if (typeof data === "object") { configCounts[type] = 1; } else { errors.push({ id: `invalid_structure_${type}`, message: `${getConfigTypeLabel(type)} 配置结构无效`, details: "配置数据必须是对象或数组", }); } } return { valid: errors.length === 0, configCounts, errors, warnings, }; }; const findExistingConfig = async ( type: string, config: any, ): Promise<any> => { // 模拟查找现有配置 const existing = await getConfigData(type); if (Array.isArray(existing)) { return existing.find( (item) => item.id === config.id || item.name === config.name, ); } return null; }; const resolveConflicts = (config: any, conflicts: ConfigConflict[]): any => { const resolved = { ...config }; for (const conflict of conflicts) { const [type, identifier] = conflict.id.split("_", 2); if (resolved[type] && Array.isArray(resolved[type])) { const index = resolved[type].findIndex( (item: any) => item.id === identifier || item.name === identifier, ); if (index !== -1) { switch (conflict.resolution) { case "keep": // 保留现有配置,删除导入的配置 resolved[type].splice(index, 1); break; case "replace": // 使用导入的配置替换现有配置 resolved[type][index] = conflict.incoming; break; case "merge": // 合并配置 resolved[type][index] = { ...conflict.current, ...conflict.incoming, }; break; } } } } return resolved; }; const applyConfigType = async ( type: string, configs: any, ): Promise<number> => { // 模拟应用配置 await new Promise((resolve) => setTimeout(resolve, 500)); if (Array.isArray(configs)) { return configs.length; } else if (typeof configs === "object") { return 1; } return 0; }; // Computed const backupList = computed(() => { return backups.value.sort( (a, b) => b.timestamp.getTime() - a.timestamp.getTime(), ); }); const exportHistoryList = computed(() => { return exportHistory.value.sort( (a, b) => b.timestamp.getTime() - a.timestamp.getTime(), ); }); return { // State loading, error, backups, exportHistory, migrationInProgress, currentVersion, availableVersions, migrationSteps, conflictResolutions, // Computed backupList, exportHistoryList, // Actions setLoading, setError, clearError, exportConfig, validateImportConfig, detectConflicts, applyImportConfig, createBackup, restoreBackup, deleteBackup, // Migration and conflict resolution detectConfigVersion, createMigrationPlan, migrateConfig, resolveConfigConflicts, mergeConfigurations, restartServices, }; });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/zaizaizhao/mcp-swagger-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server