137 lines
3.5 KiB
TypeScript
137 lines
3.5 KiB
TypeScript
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}`);
|
|
}
|
|
}
|
|
}
|