feat: update ev cli
This commit is contained in:
@@ -21,3 +21,4 @@ export const app = new App({
|
||||
httpsKey: httpsPem.key,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ const pageListCommand = new Command('page-list')
|
||||
.action(async (opts) => {
|
||||
const manager = new AssistantApp(assistantConfig);
|
||||
await manager.loadConfig();
|
||||
const showInfos = manager.pageList();
|
||||
const showInfos = await manager.pageList();
|
||||
if (opts.all) {
|
||||
console.log('Installed Pages:', showInfos);
|
||||
} else {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { logger } from '@/module/logger.ts';
|
||||
import { program, Command, assistantConfig } from '@/program.ts';
|
||||
import { AppDownload } from '@/services/app/index.ts';
|
||||
|
||||
@@ -17,9 +18,12 @@ const downloadCommand = new Command('download')
|
||||
const registry = options.registry || assistantConfig.getRegistry();
|
||||
// console.log('registry', registry);
|
||||
const app = new AppDownload(assistantConfig);
|
||||
let info = '';
|
||||
if (id) {
|
||||
await app.downloadApp({ id, type, registry, force, yes });
|
||||
const msg = await app.downloadApp({ id, type, registry, force, yes });
|
||||
info = String(msg);
|
||||
}
|
||||
logger.debug(info);
|
||||
});
|
||||
|
||||
appManagerCommand.addCommand(downloadCommand);
|
||||
@@ -31,8 +35,11 @@ const deleteCommand = new Command('delete')
|
||||
.action(async (options) => {
|
||||
const { id, type } = options;
|
||||
const app = new AppDownload(assistantConfig);
|
||||
let info = '';
|
||||
if (id) {
|
||||
await app.deleteApp({ id, type });
|
||||
const msg = await app.deleteApp({ id, type });
|
||||
info = String(msg);
|
||||
}
|
||||
logger.debug(info);
|
||||
});
|
||||
appManagerCommand.addCommand(deleteCommand);
|
||||
|
||||
@@ -22,8 +22,8 @@ export class AssistantApp extends Manager {
|
||||
this.pagesPath = pagesPath;
|
||||
this.config = config;
|
||||
}
|
||||
pageList() {
|
||||
const pages = glob.sync('*/*/package.json', {
|
||||
async pageList() {
|
||||
const pages = await glob(['*/*/package.json'], {
|
||||
cwd: this.pagesPath,
|
||||
onlyFiles: true,
|
||||
});
|
||||
@@ -35,9 +35,32 @@ export class AssistantApp extends Manager {
|
||||
user,
|
||||
app,
|
||||
version: content?.version,
|
||||
title: content?.title || '',
|
||||
description: content?.description || '',
|
||||
content,
|
||||
};
|
||||
});
|
||||
return pagesParse;
|
||||
}
|
||||
async getPageAndAppList() {
|
||||
const root = this.config.configPath.configDir;
|
||||
const pages = await glob([root + '/apps/*/package.json', root + '/pages/*/*/package.json'], {
|
||||
cwd: root,
|
||||
onlyFiles: true,
|
||||
});
|
||||
const pagesParse = pages.map((page) => {
|
||||
const relativePath = path.relative(root, page);
|
||||
const contentStr = fs.readFileSync(path.join(page), 'utf-8');
|
||||
const content = parseIfJson(contentStr);
|
||||
if (!content.appType) {
|
||||
const isWeb = relativePath.startsWith('pages/');
|
||||
content.appType = isWeb ? 'web' : 'app';
|
||||
}
|
||||
return {
|
||||
...content,
|
||||
filepath: relativePath,
|
||||
};
|
||||
});
|
||||
return pagesParse;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Logger } from '@kevisual/logger';
|
||||
const level = process.env.LOG_LEVEL || 'info';
|
||||
const logger = new Logger({ level: level as any });
|
||||
export const logger = new Logger({ level: level as any });
|
||||
|
||||
export const console = {
|
||||
log: logger.info,
|
||||
|
||||
@@ -11,3 +11,13 @@ app
|
||||
//
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'client',
|
||||
key: 'version',
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
ctx.body = 'v1.0.0';
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
27
assistant/src/routes/shop-install/define.ts
Normal file
27
assistant/src/routes/shop-install/define.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { QueryUtil } from '@kevisual/router/define';
|
||||
|
||||
export const shopDefine = QueryUtil.create({
|
||||
getRegistry: {
|
||||
path: 'shop',
|
||||
key: 'get-registry',
|
||||
description: '获取应用商店注册表信息',
|
||||
},
|
||||
|
||||
listInstalled: {
|
||||
path: 'shop',
|
||||
key: 'list-installed',
|
||||
description: '列出当前已安装的所有应用',
|
||||
},
|
||||
|
||||
install: {
|
||||
path: 'shop',
|
||||
key: 'install',
|
||||
description: '安装指定的应用,可以指定 id、type、force 和 yes 参数',
|
||||
},
|
||||
|
||||
uninstall: {
|
||||
path: 'shop',
|
||||
key: 'uninstall',
|
||||
description: '卸载指定的应用,可以指定 id 和 type 参数',
|
||||
},
|
||||
});
|
||||
@@ -1,64 +1,69 @@
|
||||
import { app } from '@/app.ts';
|
||||
// import { getInstallList, installApp, uninstallApp } from '@/modules/install.ts';
|
||||
const getInstallList = async () => {
|
||||
return [];
|
||||
};
|
||||
const installApp = async (pkg: string) => {
|
||||
return {
|
||||
code: 200,
|
||||
message: 'success',
|
||||
data: {
|
||||
pkg,
|
||||
},
|
||||
};
|
||||
};
|
||||
const uninstallApp = async (pkg: string) => {
|
||||
return {
|
||||
code: 200,
|
||||
message: 'success',
|
||||
};
|
||||
};
|
||||
|
||||
import { app, assistantConfig } from '@/app.ts';
|
||||
import { AppDownload } from '@/services/app/index.ts';
|
||||
import { AssistantApp } from '@/module/assistant/index.ts';
|
||||
import { shopDefine } from './define.ts';
|
||||
app
|
||||
.route({
|
||||
path: 'shop',
|
||||
key: 'list-installed',
|
||||
...shopDefine.get('getRegistry'),
|
||||
middleware: ['auth'],
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
// https://localhost:51015/client/router?path=shop&key=list-installed
|
||||
const list = await getInstallList();
|
||||
ctx.body = list;
|
||||
const registry = assistantConfig.getRegistry();
|
||||
assistantConfig.checkMounted();
|
||||
ctx.body = registry;
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'shop',
|
||||
key: 'install',
|
||||
...shopDefine.get('listInstalled'),
|
||||
middleware: ['auth'],
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
const manager = new AssistantApp(assistantConfig);
|
||||
await manager.loadConfig();
|
||||
const data = await manager.getPageAndAppList();
|
||||
ctx.body = data;
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
...shopDefine.get('install'),
|
||||
middleware: ['auth'],
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
// https://localhost:51015/client/router?path=shop&key=install
|
||||
const { pkg } = ctx.query.data;
|
||||
const res = await installApp(pkg);
|
||||
if (res.code !== 200) {
|
||||
ctx.throw(res.code, res.message);
|
||||
const options = ctx.query?.data || {};
|
||||
const { id, type, force, yes } = options;
|
||||
assistantConfig.checkMounted();
|
||||
const registry = options.registry || assistantConfig.getRegistry();
|
||||
// console.log('registry', registry);
|
||||
const app = new AppDownload(assistantConfig);
|
||||
let info = '';
|
||||
if (id) {
|
||||
const msg = await app.downloadApp({ id, type, registry, force, yes });
|
||||
info = String(msg);
|
||||
}
|
||||
ctx.body = res;
|
||||
ctx.body = { info };
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
app
|
||||
.route({
|
||||
path: 'shop',
|
||||
key: 'uninstall',
|
||||
...shopDefine.get('uninstall'),
|
||||
middleware: ['auth'],
|
||||
})
|
||||
.define(async (ctx) => {
|
||||
// https://localhost:51015/client/router?path=shop&key=uninstall
|
||||
const { pkg } = ctx.query.data;
|
||||
const res = await uninstallApp(pkg);
|
||||
ctx.body = res;
|
||||
const options = ctx.query?.data || {};
|
||||
const { id, type, yes } = options;
|
||||
const app = new AppDownload(assistantConfig);
|
||||
let info = '';
|
||||
if (id) {
|
||||
const msg = await app.deleteApp({ id, type, yes });
|
||||
info = String(msg);
|
||||
}
|
||||
ctx.body = { info };
|
||||
})
|
||||
.addTo(app);
|
||||
|
||||
@@ -48,14 +48,19 @@ type DeleteAppOptions = {
|
||||
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 } = opts;
|
||||
const { id, type = 'web', force, yes } = opts;
|
||||
const configDir = this.config.configDir;
|
||||
this.config?.checkMounted();
|
||||
const appsDir = this.config.configPath?.appsDir;
|
||||
@@ -100,7 +105,7 @@ export class AppDownload {
|
||||
return confirm;
|
||||
}
|
||||
async deleteApp(opts: DeleteAppOptions) {
|
||||
const { id, type = 'web' } = opts;
|
||||
const { id, type = 'web', yes = false } = opts;
|
||||
const appName = opts?.appName || id.split('/').pop();
|
||||
this.config?.checkMounted();
|
||||
const appsDir = this.config.configPath?.appsDir;
|
||||
@@ -119,10 +124,12 @@ export class AppDownload {
|
||||
deletePath = appPath;
|
||||
}
|
||||
if (deletePath && checkFileExists(deletePath)) {
|
||||
const confirm = await this.confirm(`是否删除 ${deletePath} 应用?`);
|
||||
if (!confirm) {
|
||||
console.log('取消删除应用');
|
||||
return;
|
||||
if (!yes) {
|
||||
const confirm = await this.confirm(`是否删除 ${deletePath} 应用?`);
|
||||
if (!confirm) {
|
||||
console.log('取消删除应用');
|
||||
return;
|
||||
}
|
||||
}
|
||||
fs.rmSync(deletePath, { recursive: true });
|
||||
isDelete = true;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { fileProxy, httpProxy, createApiProxy, wsProxy } from '@/module/assistan
|
||||
import http from 'http';
|
||||
import { LocalProxy } from './local-proxy.ts';
|
||||
import { assistantConfig, app } from '@/app.ts';
|
||||
import { log } from '@/module/logger.ts';
|
||||
import { log, logger } from '@/module/logger.ts';
|
||||
const localProxy = new LocalProxy({
|
||||
assistantConfig,
|
||||
});
|
||||
@@ -21,6 +21,7 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
||||
return;
|
||||
}
|
||||
if (pathname.startsWith('/client')) {
|
||||
logger.info('url', { url: req.url });
|
||||
console.debug('handle by router');
|
||||
return;
|
||||
}
|
||||
@@ -74,7 +75,7 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
||||
indexPath: localProxyProxy.indexPath,
|
||||
});
|
||||
}
|
||||
const creatCenterProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn', ['/root']);
|
||||
const creatCenterProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn', ['/root', '/' + _user]);
|
||||
const centerProxy = creatCenterProxy.find((item) => pathname.startsWith(item.path));
|
||||
if (centerProxy) {
|
||||
return httpProxy(req, res, {
|
||||
|
||||
Reference in New Issue
Block a user