更新依赖并增强应用管理命令功能

This commit is contained in:
2025-12-29 03:33:11 +08:00
parent 9647fcf48f
commit a90f98ef3f
7 changed files with 356 additions and 92 deletions

View File

@@ -1,6 +1,7 @@
import { AssistantApp } from '@/module/assistant/index.ts';
import { program, Command, assistantConfig } from '@/program.ts';
import { AppDownload } from '@/services/app/index.ts';
import { table } from 'table';
const appManagerCommand = new Command('app-manager').alias('am').description('Manage Assistant Apps 管理本地的应用模块');
program.addCommand(appManagerCommand);
@@ -8,11 +9,43 @@ program.addCommand(appManagerCommand);
appManagerCommand
.command('list')
.description('List all installed apps')
.action(async () => {
.option('-s, --status <status>', '列出状态信息, 可选值: running, stopped, inactive')
.option('-w, --wide', '显示更多信息')
.action(async (opts) => {
const manager = new AssistantApp(assistantConfig);
await manager.loadConfig();
const showInfos = manager.getAllAppShowInfo();
console.log('Installed Apps:', showInfos);
let showInfos = manager.getAllAppShowInfo();
const isWide = opts.wide ?? false;
let header = [];
if (!isWide) {
showInfos = showInfos.map((item) => {
return { key: item.key, status: item.status };
});
header = ['Key', 'Status'];
}
if (opts.status) {
const showList = showInfos.filter(info => info.status === opts.status);
if (showList.length === 0) {
console.log(`No apps with status: ${opts.status}`);
return;
}
const teables = showList.map(item => Object.values(item));
teables.unshift(header);
console.log('App Start Info:\n')
console.log(table(teables));
return
}
if (showInfos.length === 0) {
console.log('No installed apps found.');
return;
}
header = Object.keys(showInfos[0]);;
const teables = showInfos.map(item => Object.values(item));
teables.unshift(header);
console.log('Installed Apps:\n')
console.log(table(teables));
});
appManagerCommand

View File

@@ -1,15 +1,69 @@
import { program, Command, assistantConfig } from '@/program.ts';
import { spawnSync } from 'node:child_process';
import path from 'node:path';
import fs from 'node:fs';
import { AssistantApp, checkFileExists } from '@/lib.ts';
import { logger } from '@/module/logger.ts';
import { LoadApp, StopApp } from '@/module/local-apps/src/modules/manager.ts';
const runScriptsCommand = new Command('run-scripts')
.alias('run')
.arguments('<cmd> [env]')
.option('-l --local', '使用当前文件夹的package.json中的scripts', false)
.description('运行脚本在assistant.config.json中配置的脚本')
.action(async (cmd, env) => {
.action(async (cmd, env, opts) => {
const useLocal = opts.local;
const showScripts = cmd === 'show';
const showScriptFunc = (scripts: any) => {
console.log('可用的本地脚本:');
let has = false;
Object.keys(scripts).forEach((key) => {
console.log(`- ${key}: ${scripts[key]}`);
has = true;
});
if (!has) {
console.log('当前未定义任何脚本。');
}
}
if (useLocal) {
const pkgPath = path.join(process.cwd(), 'package.json');
if (checkFileExists(pkgPath) === false) {
console.error('当前目录下未找到 package.json 文件。');
return;
}
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
const scripts = pkg.scripts || {};
if (showScripts) {
showScriptFunc(scripts);
return;
}
const script = scripts[cmd];
if (!script) {
console.error(`Script "${cmd}" not found in local package.json.`);
return;
}
const command = [script, ...(env ? [env] : [])].join(' ');
const res = spawnSync(command, { shell: true, stdio: 'inherit', cwd: assistantConfig.configDir });
console.log(`执行 "[${command}]"...`);
if (res.error) {
console.error(`执行失败 "${cmd}":`, res.error);
return;
}
if (res.status !== 0) {
console.error(`本地脚本 "${cmd}" 以代码 ${res.status} 退出`);
return;
}
return;
}
assistantConfig.checkMounted();
const configs = assistantConfig.getCacheAssistantConfig();
const scripts = configs?.scripts || {};
try {
const script = scripts[cmd];
if (showScripts) {
showScriptFunc(scripts);
return;
}
if (!script) {
console.error(`Script "${cmd}" not found.`);
return;
@@ -32,3 +86,93 @@ const runScriptsCommand = new Command('run-scripts')
}
});
program.addCommand(runScriptsCommand);
const createRandomApp = (opts: { app: any, package: any, pwd: string, status?: string }) => {
const { app, package: packageJson, pwd } = opts;
if (!app.status) {
app.status = opts.status || 'running'
}
if (!app.key) {
const randomSuffix = Math.random().toString(36).substring(2, 8);
app.key = packageJson.basename || `${'unknown-app'}-${randomSuffix}`;
}
app.path = pwd;
if (app.type === 'pm2-system-app' && !app.pm2Options) {
app.pm2Options = {
cwd: pwd,
}
}
return app;
}
const start = new Command('start')
.description('获取package.json中app参数并启动对应的app')
.option('-s --save', '保存应用信息到assistant配置中', false)
.action(async (opts) => {
// assistantConfig.checkMounted();
const pwd = process.cwd();
const packageJsonPath = path.join(pwd, 'package.json');
if (checkFileExists(packageJsonPath) === false) {
logger.error('package.json 在当前目录未找到,请在包含 package.json 的目录下运行此命令。');
return
}
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
const appKey = packageJson.app;
if (!appKey) {
logger.error('package.json 中未找到 app 字段,请确保在 package.json 中正确配置 app 字段。');
return
}
const app = createRandomApp({ app: packageJson.app, package: packageJson, pwd });
if (app.type !== 'system-app') {
const load = await LoadApp(app, {});
if (!load) {
logger.error(`未能加载应用, 请确保应用名称正确且已安装。`, app.type);
return
}
} else {
LoadApp(app, {}).then(() => {
logger.info(`系统应用已启动: ${app.key}`);
}).catch((err) => {
logger.error(`启动系统应用失败: ${app.key}`, err);
});
}
if (opts.save) {
assistantConfig.checkMounted();
const manager = new AssistantApp(assistantConfig, app);
await manager.loadConfig();
await manager.saveAppInfo(app);
}
});
program.addCommand(start);
const stop = new Command('stop')
.description('获取package.json中app参数并停止对应的app')
.option('-t --todo <todo>', '停止应用,在pm2中如果为stop则停止,如果为remove则删除默认为stop', 'stop')
.option('-s --save', '保存应用信息到assistant配置中', false)
.action(async (opts) => {
// assistantConfig.checkMounted();
const pwd = process.cwd();
const packageJsonPath = path.join(pwd, 'package.json');
if (checkFileExists(packageJsonPath) === false) {
logger.error('package.json 在当前目录未找到,请在包含 package.json 的目录下运行此命令。');
return
}
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
const appKey = packageJson.app;
if (!appKey) {
logger.error('package.json 中未找到 app 字段,请确保在 package.json 中正确配置 app 字段。');
return
}
const app = createRandomApp({ app: packageJson.app, package: packageJson, pwd, status: 'stopped' });
await StopApp(app, { todo: opts.todo });
if (opts.save) {
assistantConfig.checkMounted();
const manager = new AssistantApp(assistantConfig, app);
await manager.loadConfig();
await manager.removeApp(app.key, { deleteFile: false });
}
});
program.addCommand(stop);