Skip to main content
Glama

Swagger MCP Server

by tuskermanshu
template-manager.ts9.98 kB
/** * Template Manager * Responsible for managing and processing various code generation templates */ import fs from 'fs/promises'; import path from 'path'; // 使用Node环境变量__dirname获取当前目录 // 注意:在ESM模块中,需要使用以下技巧模拟__dirname // 这里为了兼容,使用process.cwd()获取当前工作目录 const PROJECT_ROOT = process.cwd(); const TEMPLATES_ROOT = path.join(PROJECT_ROOT, 'src/templates'); // 内置模板目录 const BUILT_IN_TEMPLATES_DIR = path.join(TEMPLATES_ROOT, 'built-in'); // 自定义模板目录 const CUSTOM_TEMPLATES_DIR = path.join(TEMPLATES_ROOT, 'custom'); // 模板配置文件 const BUILT_IN_TEMPLATES_CONFIG = path.join(BUILT_IN_TEMPLATES_DIR, 'templates.json'); const CUSTOM_TEMPLATES_CONFIG = path.join(CUSTOM_TEMPLATES_DIR, 'templates.json'); // Template type enum export enum TemplateType { API_CLIENT = 'api-client', TYPESCRIPT_TYPES = 'typescript-types', CONFIG_FILE = 'config-file' } // Framework type enum export enum FrameworkType { AXIOS = 'axios', FETCH = 'fetch', REACT_QUERY = 'react-query', SWR = 'swr', ANGULAR = 'angular', VUE = 'vue' } // Template interface export interface Template { id: string; name: string; type: TemplateType; framework?: FrameworkType; path?: string; content?: string; isBuiltIn?: boolean; description?: string; } // 模板配置接口 interface TemplatesConfig { templates: Array<Omit<Template, 'content'>>; } /** * 模板管理器选项 */ interface TemplateManagerOptions { builtInTemplatesDir?: string; customTemplatesDir?: string; } /** * 模板管理器类 */ export class TemplateManager { private builtInTemplates: Template[] = []; private customTemplates: Template[] = []; private initialized: boolean = false; /** * 构造函数 */ constructor(options: TemplateManagerOptions = {}) { // 暂时不使用options中的路径,使用常量定义的路径 } /** * 初始化模板管理器 * 加载内置模板和自定义模板 */ async initialize(): Promise<void> { if (this.initialized) { return; } try { // 确保目录存在 await this.ensureDirectoriesExist(); // 加载内置模板 await this.loadBuiltInTemplates(); // 加载自定义模板 await this.loadCustomTemplates(); this.initialized = true; console.log(`🎯 模板管理器初始化完成, 内置模板: ${this.builtInTemplates.length}, 自定义模板: ${this.customTemplates.length}`); } catch (error) { console.error('模板管理器初始化失败:', error); throw error; } } /** * 确保必要的目录存在 */ private async ensureDirectoriesExist(): Promise<void> { try { // 确保自定义模板目录存在 await fs.mkdir(CUSTOM_TEMPLATES_DIR, { recursive: true }); // 如果自定义模板配置文件不存在,创建一个空的配置文件 try { await fs.access(CUSTOM_TEMPLATES_CONFIG); } catch (error) { await fs.writeFile(CUSTOM_TEMPLATES_CONFIG, JSON.stringify({ templates: [] }, null, 2)); } } catch (error) { console.error('确保目录存在失败:', error); throw error; } } /** * 加载内置模板 */ private async loadBuiltInTemplates(): Promise<void> { try { // 读取内置模板配置 const configContent = await fs.readFile(BUILT_IN_TEMPLATES_CONFIG, 'utf-8'); const config: TemplatesConfig = JSON.parse(configContent); // 为每个模板加载内容 for (const template of config.templates) { const templatePath = path.join(BUILT_IN_TEMPLATES_DIR, template.path!); const content = await fs.readFile(templatePath, 'utf-8'); this.builtInTemplates.push({ ...template, content, isBuiltIn: true }); } } catch (error) { console.error('加载内置模板失败:', error); throw error; } } /** * 加载自定义模板 */ private async loadCustomTemplates(): Promise<void> { try { // 读取自定义模板配置 const configContent = await fs.readFile(CUSTOM_TEMPLATES_CONFIG, 'utf-8'); const config: TemplatesConfig = JSON.parse(configContent); // 为每个模板加载内容 for (const template of config.templates) { const templatePath = path.join(CUSTOM_TEMPLATES_DIR, template.path!); try { const content = await fs.readFile(templatePath, 'utf-8'); this.customTemplates.push({ ...template, content, isBuiltIn: false }); } catch (error) { console.warn(`无法加载自定义模板 ${template.id}:`, error); // 跳过无法加载的模板 continue; } } } catch (error) { console.error('加载自定义模板失败:', error); // 如果是文件不存在的错误,则创建一个空的配置文件 if ((error as NodeJS.ErrnoException).code === 'ENOENT') { await fs.writeFile(CUSTOM_TEMPLATES_CONFIG, JSON.stringify({ templates: [] }, null, 2)); } else { throw error; } } } /** * 获取所有模板 */ getAllTemplates(): Template[] { return [...this.builtInTemplates, ...this.customTemplates]; } /** * 根据类型获取模板 */ getTemplatesByType(type: TemplateType): Template[] { return this.getAllTemplates().filter(template => template.type === type); } /** * 根据ID获取模板 */ getTemplate(id: string): Template | undefined { return this.getAllTemplates().find(template => template.id === id); } /** * 根据类型和框架获取模板 */ getTemplateByTypeAndFramework(type: TemplateType, framework?: FrameworkType): Template | undefined { return this.getAllTemplates().find(template => template.type === type && (framework ? template.framework === framework : true) ); } /** * 保存自定义模板 */ async saveCustomTemplate(template: Template): Promise<Template> { // 确保已初始化 if (!this.initialized) { await this.initialize(); } try { // 检查是否是内置模板 const existingTemplate = this.getTemplate(template.id); if (existingTemplate?.isBuiltIn) { throw new Error(`Cannot override built-in template: ${template.id}`); } // 生成保存路径 let relativePath: string; if (template.type === TemplateType.API_CLIENT) { relativePath = `api-client/${template.id}.tpl`; } else if (template.type === TemplateType.TYPESCRIPT_TYPES) { relativePath = `typescript-types/${template.id}.tpl`; } else if (template.type === TemplateType.CONFIG_FILE) { relativePath = `config/${template.id}.tpl`; } else { relativePath = `${template.id}.tpl`; } // 确保子目录存在 const dirPath = path.join(CUSTOM_TEMPLATES_DIR, path.dirname(relativePath)); await fs.mkdir(dirPath, { recursive: true }); // 保存模板内容 const templatePath = path.join(CUSTOM_TEMPLATES_DIR, relativePath); await fs.writeFile(templatePath, template.content || ''); // 更新模板配置 const newTemplate: Template = { id: template.id, name: template.name, type: template.type, framework: template.framework, path: relativePath, description: template.description, isBuiltIn: false }; // 更新内存中的自定义模板 const existingIndex = this.customTemplates.findIndex(t => t.id === template.id); if (existingIndex >= 0) { // 更新现有模板 this.customTemplates[existingIndex] = { ...newTemplate, content: template.content }; } else { // 添加新模板 this.customTemplates.push({ ...newTemplate, content: template.content }); } // 更新配置文件 await this.updateCustomTemplatesConfig(); return { ...newTemplate, content: template.content }; } catch (error) { console.error('保存自定义模板失败:', error); throw error; } } /** * 删除自定义模板 */ async deleteCustomTemplate(id: string): Promise<boolean> { // 确保已初始化 if (!this.initialized) { await this.initialize(); } try { // 获取模板 const template = this.getTemplate(id); // 检查是否是内置模板或不存在 if (!template) { return false; } if (template.isBuiltIn) { throw new Error(`Cannot delete built-in template: ${id}`); } // 删除模板文件 const templatePath = path.join(CUSTOM_TEMPLATES_DIR, template.path!); await fs.unlink(templatePath); // 从内存中移除 this.customTemplates = this.customTemplates.filter(t => t.id !== id); // 更新配置文件 await this.updateCustomTemplatesConfig(); return true; } catch (error) { console.error('删除自定义模板失败:', error); return false; } } /** * 更新自定义模板配置文件 */ private async updateCustomTemplatesConfig(): Promise<void> { try { // 准备配置数据 const configData: TemplatesConfig = { templates: this.customTemplates.map(({ content, ...rest }) => rest) }; // 写入配置文件 await fs.writeFile( CUSTOM_TEMPLATES_CONFIG, JSON.stringify(configData, null, 2) ); } catch (error) { console.error('更新自定义模板配置失败:', error); throw error; } } }

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/tuskermanshu/swagger-mcp-server'

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