import { checkFileExists, AssistantConfig } from '@/module/assistant/index.ts'; import path from 'path'; import fs from 'fs'; import inquirer from 'inquirer'; import { spawnSync } from 'child_process'; export const runCommand = (command: string, args: string[]) => { const result = spawnSync(command, args, { stdio: 'inherit', shell: true, }); if (result.error) { console.error('Error executing command:', result.error); throw result.error; } if (result.status !== 0) { console.error('Command failed with status:', result.status); throw new Error(`Command failed with status: ${result.status}`); } return result; }; export type appType = 'web' | 'app'; type DownloadAppOptions = { /** * 应用名称 * @type {string} * @example user/app * @description 应用名称 */ id: string; type?: appType; registry?: string; /** * 应用名称,默认为 user/app的 app */ appName?: string; force?: boolean; yes?: boolean; }; type DeleteAppOptions = { /** * 应用名称 * @type {string} * @example user/app * @description 应用名称 */ id: string; type?: appType; appName?: string; yes?: boolean; }; export class AppDownload { config: AssistantConfig; constructor(config: AssistantConfig) { this.config = config; } async getRegistry() { return this.config.getRegistry(); } async downloadApp(opts: DownloadAppOptions) { const { id, type = 'web', force, yes } = opts; const configDir = this.config.configDir; this.config?.checkMounted(); const appsDir = this.config.configPath?.appsDir; const pagesDir = this.config.configPath?.pagesDir; if (!id) { throw new Error('应用名称不能为空'); } const command = 'ev'; const args = ['app', 'download']; args.push('-i', id); if (type === 'web') { args.push('-o', pagesDir); } else if (type === 'app') { args.push('-o', path.join(appsDir)); } else { throw new Error('应用类型错误,只能是 web 或 app'); } if (force) { args.push('-f'); if (opts.yes) { args.push('-y'); } } if (opts.registry) { args.push('-r', opts.registry); } return runCommand(command, args); } async confirm(message?: string) { const { confirm } = await inquirer.prompt([ { type: 'confirm', name: 'confirm', message: message || '是否继续删除应用?', default: false, }, ]); return confirm; } async deleteApp(opts: DeleteAppOptions) { const { id, type = 'web', yes = false } = opts; const appName = opts?.appName || id.split('/').pop(); this.config?.checkMounted(); const appsDir = this.config.configPath?.appsDir; const pagesDir = this.config.configPath?.pagesDir; if (!id) { throw new Error('应用名称不能为空'); } let deletePath = ''; let isDelete = false; if (type === 'web') { // 直接删除路径就行 const pagePath = path.join(pagesDir, id); deletePath = pagePath; } else if (type === 'app') { const appPath = path.join(appsDir, id); deletePath = appPath; } if (deletePath && checkFileExists(deletePath)) { if (!yes) { const confirm = await this.confirm(`是否删除 ${deletePath} 应用?`); if (!confirm) { console.log('取消删除应用'); return; } } fs.rmSync(deletePath, { recursive: true }); isDelete = true; console.log(`删除应用成功: ${deletePath}`); } } }