import * as path from 'path'; import * as fs from 'fs-extra'; import { TemplateNotFoundError, FileSystemError, ConfigurationError } from '../errors'; /** * 模板信息接口 */ export interface TemplateInfo { name: string; path: string; description: string; } /** * 模板配置接口 */ interface TemplateConfig { templates: { [key: string]: { name: string; description: string; folder: string; }; }; } /** * 默认模板配置 */ const defaultTemplates: TemplateConfig = { templates: { uniapp: { name: 'uniapp', description: 'UniApp 跨平台应用工程模板', folder: 'uniapp' }, uniappx: { name: 'uniappx', description: 'UniApp X 扩展版工程模板', folder: 'uniappx' } } }; /** * 获取模板根目录路径 */ function getTemplateRootPath(): string { return path.resolve(__dirname, '../../template'); } /** * 获取可用模板列表 * @returns 可用模板信息数组 */ export function getAvailableTemplates(): TemplateInfo[] { const templateRoot = getTemplateRootPath(); const templates: TemplateInfo[] = []; for (const [key, config] of Object.entries(defaultTemplates.templates)) { const templatePath = path.join(templateRoot, config.folder); templates.push({ name: config.name, path: templatePath, description: config.description }); } return templates; } /** * 检查模板是否存在 * @param templateName 模板名称 * @returns 模板是否存在 */ export function templateExists(templateName: string): boolean { const templateConfig = defaultTemplates.templates[templateName]; if (!templateConfig) { return false; } const templatePath = path.join(getTemplateRootPath(), templateConfig.folder); return fs.existsSync(templatePath); } /** * 复制模板到目标目录 * @param templateName 模板名称 * @param targetDir 目标目录 * @throws TemplateNotFoundError 如果模板配置不存在 * @throws ConfigurationError 如果模板文件夹不存在 * @throws FileSystemError 如果文件系统操作失败 */ export async function copyTemplate(templateName: string, targetDir: string): Promise { const templateConfig = defaultTemplates.templates[templateName]; if (!templateConfig) { throw new TemplateNotFoundError(templateName); } const templatePath = path.join(getTemplateRootPath(), templateConfig.folder); if (!fs.existsSync(templatePath)) { throw new ConfigurationError('模板文件夹不存在,请重新安装 CLI 工具'); } // 检查目标目录是否可写 try { await fs.access(targetDir, fs.constants.W_OK); } catch { throw new FileSystemError('无法写入目标目录,请检查权限'); } try { await fs.copy(templatePath, targetDir, { overwrite: false, errorOnExist: false }); } catch (error) { if (error instanceof Error) { throw new FileSystemError(`复制模板失败: ${error.message}`, error); } throw new FileSystemError('复制模板时发生未知错误'); } }