init
This commit is contained in:
@@ -7,7 +7,7 @@ const external = ['bun'];
|
|||||||
await Bun.build({
|
await Bun.build({
|
||||||
target: 'node',
|
target: 'node',
|
||||||
format: 'esm',
|
format: 'esm',
|
||||||
entrypoints: ['./src/index.ts'],
|
entrypoints: ['./src/oldindex.ts'],
|
||||||
outdir: './dist',
|
outdir: './dist',
|
||||||
naming: {
|
naming: {
|
||||||
entry: 'envision.js',
|
entry: 'envision.js',
|
||||||
12
package.json
12
package.json
@@ -26,12 +26,12 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
"bin",
|
"bin",
|
||||||
"bun.config.mjs"
|
"bun.config.ts"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "bun src/run.ts ",
|
"dev": "bun src/cli.ts ",
|
||||||
"dev:server": "cd assistant && bun --watch src/run-server.ts ",
|
"dev:server": "cd assistant && bun --watch src/run-server.ts ",
|
||||||
"build": "rimraf dist && bun run bun.config.mjs",
|
"build": "rimraf dist && bun run bun.config.ts",
|
||||||
"deploy": "ev pack -u -p -m no",
|
"deploy": "ev pack -u -p -m no",
|
||||||
"postbuild": "cd assistant && pnpm build "
|
"postbuild": "cd assistant && pnpm build "
|
||||||
},
|
},
|
||||||
@@ -58,7 +58,8 @@
|
|||||||
"nanoid": "^5.1.7",
|
"nanoid": "^5.1.7",
|
||||||
"pm2": "latest",
|
"pm2": "latest",
|
||||||
"semver": "^7.7.4",
|
"semver": "^7.7.4",
|
||||||
"unstorage": "^1.17.4"
|
"unstorage": "^1.17.4",
|
||||||
|
"zod": "^4.3.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/api": "^0.0.65",
|
"@kevisual/api": "^0.0.65",
|
||||||
@@ -76,13 +77,14 @@
|
|||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
"commander": "^14.0.3",
|
"commander": "^14.0.3",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
|
"es-toolkit": "^1.45.1",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"filesize": "^11.0.13",
|
"filesize": "^11.0.13",
|
||||||
"form-data": "^4.0.5",
|
"form-data": "^4.0.5",
|
||||||
"ignore": "^7.0.5",
|
"ignore": "^7.0.5",
|
||||||
"jsonwebtoken": "^9.0.3",
|
"jsonwebtoken": "^9.0.3",
|
||||||
"pm2": "^6.0.14",
|
"pm2": "^6.0.14",
|
||||||
"tar": "^7.5.12",
|
"tar": "^7.5.13",
|
||||||
"zustand": "^5.0.12"
|
"zustand": "^5.0.12"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -62,6 +62,9 @@ importers:
|
|||||||
unstorage:
|
unstorage:
|
||||||
specifier: ^1.17.4
|
specifier: ^1.17.4
|
||||||
version: 1.17.4(idb-keyval@6.2.2)
|
version: 1.17.4(idb-keyval@6.2.2)
|
||||||
|
zod:
|
||||||
|
specifier: ^4.3.6
|
||||||
|
version: 4.3.6
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@kevisual/api':
|
'@kevisual/api':
|
||||||
specifier: ^0.0.65
|
specifier: ^0.0.65
|
||||||
@@ -108,6 +111,9 @@ importers:
|
|||||||
crypto-js:
|
crypto-js:
|
||||||
specifier: ^4.2.0
|
specifier: ^4.2.0
|
||||||
version: 4.2.0
|
version: 4.2.0
|
||||||
|
es-toolkit:
|
||||||
|
specifier: ^1.45.1
|
||||||
|
version: 1.45.1
|
||||||
fast-glob:
|
fast-glob:
|
||||||
specifier: ^3.3.3
|
specifier: ^3.3.3
|
||||||
version: 3.3.3
|
version: 3.3.3
|
||||||
@@ -124,8 +130,8 @@ importers:
|
|||||||
specifier: ^9.0.3
|
specifier: ^9.0.3
|
||||||
version: 9.0.3
|
version: 9.0.3
|
||||||
tar:
|
tar:
|
||||||
specifier: ^7.5.12
|
specifier: ^7.5.13
|
||||||
version: 7.5.12
|
version: 7.5.13
|
||||||
zustand:
|
zustand:
|
||||||
specifier: ^5.0.12
|
specifier: ^5.0.12
|
||||||
version: 5.0.12(react@19.2.4)
|
version: 5.0.12(react@19.2.4)
|
||||||
@@ -2257,8 +2263,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
|
resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
|
|
||||||
tar@7.5.12:
|
tar@7.5.13:
|
||||||
resolution: {integrity: sha512-9TsuLcdhOn4XztcQqhNyq1KOwOOED/3k58JAvtULiYqbO8B/0IBAAIE1hj0Svmm58k27TmcigyDI0deMlgG3uw==}
|
resolution: {integrity: sha512-tOG/7GyXpFevhXVh8jOPJrmtRpOTsYqUIkVdVooZYJS/z8WhfQUX8RJILmeuJNinGAMSu1veBr4asSHFt5/hng==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
to-regex-range@5.0.1:
|
to-regex-range@5.0.1:
|
||||||
@@ -4928,7 +4934,7 @@ snapshots:
|
|||||||
string-width: 4.2.3
|
string-width: 4.2.3
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
|
|
||||||
tar@7.5.12:
|
tar@7.5.13:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@isaacs/fs-minipass': 4.0.1
|
'@isaacs/fs-minipass': 4.0.1
|
||||||
chownr: 3.0.0
|
chownr: 3.0.0
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
import { App } from '@kevisual/app/mod.ts';
|
|
||||||
import { storage } from '../module/query.ts';
|
|
||||||
import { sessionStorage } from '../module/cache.ts';
|
|
||||||
export const app = new App({ token: storage.getItem('token') || '', storage: sessionStorage });
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { app } from './ai.ts'
|
|
||||||
import './routes/cmd-run.ts'
|
|
||||||
|
|
||||||
export {
|
|
||||||
app
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import { app } from '../ai.ts';
|
|
||||||
import { execSync } from 'node:child_process'
|
|
||||||
import { logger } from '@/module/logger.ts';
|
|
||||||
const promptTemplate = `# CMD 结果判断器
|
|
||||||
|
|
||||||
分析上一条 CMD 命令的执行结果,判断是否需要执行下一条命令。
|
|
||||||
|
|
||||||
- 若结果中隐含或明确指示需继续执行 → 返回:\`{"cmd": "推断出的下一条命令", "type": "cmd"}\`
|
|
||||||
- 若无后续操作,甚至上一次执行的返回为空或者成功 → 返回:\`{"type": "none"}\`
|
|
||||||
|
|
||||||
1. 仅输出合法 JSON,无任何额外文本。
|
|
||||||
2. \`cmd\` 必须从执行结果中合理推断得出,非预设或猜测。
|
|
||||||
3. 禁止解释、注释、换行或格式错误。`
|
|
||||||
|
|
||||||
app.router.route({
|
|
||||||
path: 'cmd-run',
|
|
||||||
description: '执行 CMD 命令并判断下一步操作, 参数是 cmd 字符串',
|
|
||||||
}).define(async (ctx) => {
|
|
||||||
const cmd = ctx.query.cmd || '';
|
|
||||||
if (!cmd) {
|
|
||||||
ctx.throw(400, 'cmd is required');
|
|
||||||
}
|
|
||||||
let result = '';
|
|
||||||
ctx.state.steps = ctx.state?.steps || [];
|
|
||||||
|
|
||||||
try {
|
|
||||||
logger.info('执行命令:', cmd);
|
|
||||||
result = execSync(cmd, { encoding: 'utf-8' });
|
|
||||||
ctx.state.steps.push({ cmd, result });
|
|
||||||
logger.info(result);
|
|
||||||
} catch (error: any) {
|
|
||||||
result = error.message || '';
|
|
||||||
ctx.state.steps.push({ cmd, result, error: true });
|
|
||||||
ctx.body = {
|
|
||||||
steps: ctx.state.steps,
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await app.loadAI()
|
|
||||||
const prompt = `${promptTemplate}\n上一条命令:\n${cmd}\n执行结果:\n${result}\n`;
|
|
||||||
const response = await app.ai.question(prompt);
|
|
||||||
|
|
||||||
const msg = app.ai.utils.extractJsonFromMarkdown(app.ai.responseText);
|
|
||||||
try {
|
|
||||||
logger.debug('AI Prompt', prompt);
|
|
||||||
logger.debug('AI 分析结果:', msg);
|
|
||||||
const { cmd, type } = msg;
|
|
||||||
if (type === 'cmd' && cmd) {
|
|
||||||
await app.router.call({ path: 'cmd-run', payload: { cmd } }, { state: ctx.state });
|
|
||||||
} else {
|
|
||||||
logger.info('无后续命令,结束执行');
|
|
||||||
ctx.state.steps.push({ type: 'none' });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
result = '执行错误,无法解析返回结果为合法 JSON' + app.ai.responseText
|
|
||||||
logger.error(result);
|
|
||||||
ctx.state.steps.push({ cmd, result, parseError: true });
|
|
||||||
}
|
|
||||||
ctx.body = {
|
|
||||||
steps: ctx.state.steps,
|
|
||||||
}
|
|
||||||
}).addTo(app.router);
|
|
||||||
6
src/app.ts
Normal file
6
src/app.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { App } from '@kevisual/router';
|
||||||
|
import { useContextKey } from '@kevisual/context';
|
||||||
|
|
||||||
|
export const app = useContextKey<App>('app', () => {
|
||||||
|
return new App()
|
||||||
|
});
|
||||||
4
src/cli.ts
Normal file
4
src/cli.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
import { app } from './index.ts';
|
||||||
|
import { parse } from "@kevisual/router/commander"
|
||||||
|
|
||||||
|
parse({ app });
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { program, Command } from '@/program.ts';
|
import { program, Command } from '@/program.ts';
|
||||||
import { getConfig, getEnvToken } from '@/module/get-config.ts';
|
import { getConfig, getEnvToken } from '@/module/get-config.ts';
|
||||||
import { input, password } from '@inquirer/prompts';
|
import { input } from '@inquirer/prompts';
|
||||||
import { loginInCommand } from '@/module/login/login-by-web.ts';
|
import { loginInCommand } from '@/module/login/login-by-web.ts';
|
||||||
import { queryLogin, storage } from '@/module/query.ts';
|
import { queryLogin, storage } from '@/module/query.ts';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|||||||
37
src/index.ts
37
src/index.ts
@@ -1,34 +1,7 @@
|
|||||||
import { program } from '@/program.ts';
|
import { app } from './app.ts'
|
||||||
import './command/login.ts';
|
import './routes/login.ts'
|
||||||
import './command/ls-token.ts';
|
|
||||||
import './command/deploy.ts';
|
|
||||||
import './command/config.ts';
|
|
||||||
import './command/router.ts';
|
|
||||||
import './command/npm.ts';
|
|
||||||
import './command/publish.ts';
|
|
||||||
import './command/proxy.ts';
|
|
||||||
import './command/update.ts';
|
|
||||||
|
|
||||||
import './command/sync/sync.ts';
|
export { app };
|
||||||
|
|
||||||
import './command/app/index.ts';
|
app.createAuth(() => { })
|
||||||
|
app.createRouteList()
|
||||||
import './command/gist/index.ts';
|
|
||||||
import './command/config-remote.ts';
|
|
||||||
import './command/config-secret-remote.ts';
|
|
||||||
// import './command/ai.ts';
|
|
||||||
import './command/coding-plan/cc.ts'
|
|
||||||
import './command/coding-plan/oc.ts'
|
|
||||||
import './command/docker.ts';
|
|
||||||
import './command/jwks.ts';
|
|
||||||
|
|
||||||
import './command/cnb/index.ts';
|
|
||||||
import './command/download.ts';
|
|
||||||
|
|
||||||
// program.parse(process.argv);
|
|
||||||
|
|
||||||
export const runParser = async (argv: string[]) => {
|
|
||||||
// program.parse(process.argv);
|
|
||||||
// console.log('argv', argv);
|
|
||||||
program.parse(argv);
|
|
||||||
};
|
|
||||||
33
src/oldindex.ts
Normal file
33
src/oldindex.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import { program } from '@/program.ts';
|
||||||
|
import './command/login.ts';
|
||||||
|
import './command/ls-token.ts';
|
||||||
|
import './command/deploy.ts';
|
||||||
|
import './command/config.ts';
|
||||||
|
import './command/router.ts';
|
||||||
|
import './command/npm.ts';
|
||||||
|
import './command/publish.ts';
|
||||||
|
import './command/proxy.ts';
|
||||||
|
import './command/update.ts';
|
||||||
|
|
||||||
|
import './command/sync/sync.ts';
|
||||||
|
|
||||||
|
import './command/app/index.ts';
|
||||||
|
|
||||||
|
import './command/gist/index.ts';
|
||||||
|
import './command/config-remote.ts';
|
||||||
|
import './command/config-secret-remote.ts';
|
||||||
|
import './command/coding-plan/cc.ts'
|
||||||
|
import './command/coding-plan/oc.ts'
|
||||||
|
import './command/docker.ts';
|
||||||
|
import './command/jwks.ts';
|
||||||
|
|
||||||
|
import './command/cnb/index.ts';
|
||||||
|
import './command/download.ts';
|
||||||
|
|
||||||
|
// program.parse(process.argv);
|
||||||
|
|
||||||
|
export const runParser = async (argv: string[]) => {
|
||||||
|
// program.parse(process.argv);
|
||||||
|
// console.log('argv', argv);
|
||||||
|
program.parse(argv);
|
||||||
|
};
|
||||||
194
src/routes/login.ts
Normal file
194
src/routes/login.ts
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
import { app } from '../app.ts';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { getConfig, getEnvToken } from '@/module/get-config.ts';
|
||||||
|
import { input, password as inputPassword } from '@inquirer/prompts';
|
||||||
|
import { loginInCommand } from '@/module/login/login-by-web.ts';
|
||||||
|
import { queryLogin, storage } from '@/module/query.ts';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
import util from 'util';
|
||||||
|
import { pick } from 'es-toolkit'
|
||||||
|
|
||||||
|
export const getUsername = async () => {
|
||||||
|
const token = getEnvToken();
|
||||||
|
const localToken = storage.getItem('token');
|
||||||
|
if (!token && !localToken) {
|
||||||
|
console.log('请先登录');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let me = await queryLogin.getMe(localToken || token);
|
||||||
|
if (me?.code === 401) {
|
||||||
|
me = await queryLogin.getMe();
|
||||||
|
}
|
||||||
|
if (me?.code === 200) {
|
||||||
|
return me.data?.username;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const showMe = async (show = true) => {
|
||||||
|
const token = getEnvToken();
|
||||||
|
const localToken = storage.getItem('token');
|
||||||
|
if (!token && !localToken) {
|
||||||
|
console.log('请先登录');
|
||||||
|
return { code: 40400, message: '请先登录' };
|
||||||
|
}
|
||||||
|
let me = await queryLogin.getMe(localToken || token);
|
||||||
|
if (me?.code === 401) {
|
||||||
|
me = await queryLogin.getMe();
|
||||||
|
}
|
||||||
|
if (show) {
|
||||||
|
console.log('Me', me.data);
|
||||||
|
}
|
||||||
|
return me;
|
||||||
|
};
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'user',
|
||||||
|
key: 'login',
|
||||||
|
description: '登录',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
username: z.string().optional().describe('用户名'),
|
||||||
|
password: z.string().optional().describe('密码'),
|
||||||
|
force: z.boolean().optional().describe('强制登录'),
|
||||||
|
web: z.boolean().optional().describe('是否通过web登录'),
|
||||||
|
env: z.boolean().optional().describe('是否通过环境变量KEVISUAL_TOKEN登录'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
let { username, password, force, web, env } = ctx.args;
|
||||||
|
if (web) {
|
||||||
|
await loginInCommand();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 从环境变量登录
|
||||||
|
if (env) {
|
||||||
|
const envToken = getEnvToken();
|
||||||
|
if (!envToken) {
|
||||||
|
console.log('环境变量 KEVISUAL_TOKEN 未设置');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const res = await showMe(false);
|
||||||
|
if (res.code === 200) {
|
||||||
|
console.log('Login success:', res.data?.username || res.data?.email);
|
||||||
|
} else {
|
||||||
|
console.log('Login failed:', res.message || 'Invalid token');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 如果没有传递参数,则通过交互式输入
|
||||||
|
if (!username) {
|
||||||
|
username = await input({
|
||||||
|
message: 'Enter your username:',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!password) {
|
||||||
|
password = await inputPassword({
|
||||||
|
message: 'Enter your password:',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const token = storage.getItem('token');
|
||||||
|
if (token) {
|
||||||
|
const res = await showMe(false);
|
||||||
|
if (res.code === 200) {
|
||||||
|
const data = res.data;
|
||||||
|
if (data.username === username) {
|
||||||
|
console.log('Already Login For', data.username);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await queryLogin.login({
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
}).catch((err) => {
|
||||||
|
return { code: 500, message: err.message || '' };
|
||||||
|
});
|
||||||
|
if (res.code === 200) {
|
||||||
|
console.log('welcome', username);
|
||||||
|
} else {
|
||||||
|
console.log('登录失败', res.message || '');
|
||||||
|
}
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'user',
|
||||||
|
key: 'me',
|
||||||
|
description: '查看当前登录用户信息',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
all: z.boolean().optional().describe('是否显示全部信息,默认为false'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const options = ctx.args;
|
||||||
|
try {
|
||||||
|
let res = await showMe(false);
|
||||||
|
let isRefresh = false;
|
||||||
|
if (res.code === 200 && res.data?.accessToken) {
|
||||||
|
res = await showMe(false);
|
||||||
|
isRefresh = true;
|
||||||
|
}
|
||||||
|
if (res.code === 40400) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (res.code === 200) {
|
||||||
|
if (isRefresh) {
|
||||||
|
console.log(chalk.green('refresh token success'), '\n');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
isRefresh ? chalk.red('refresh token failed, please login again.') : chalk.red('you need login first. \n run `envision login` to login'),
|
||||||
|
'\n',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const baseURL = getConfig().baseURL;
|
||||||
|
const pickData = pick(res?.data, ['username', 'type', 'orgs']);
|
||||||
|
|
||||||
|
console.log(chalk.blue('baseURL', baseURL));
|
||||||
|
if (options.all) {
|
||||||
|
console.log(chalk.blue(util.inspect(res?.data, { colors: true, depth: 4 })));
|
||||||
|
} else {
|
||||||
|
// 打印pickData
|
||||||
|
console.log(chalk.blue(util.inspect(pickData, { colors: true, depth: 4 })));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('me error', error);
|
||||||
|
}
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'user',
|
||||||
|
key: 'switch',
|
||||||
|
description: '切换到其他组织或用户',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
username: z.string().describe('用户名或组织名'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { username } = ctx.args;
|
||||||
|
const res = await queryLogin.switchUser(username);
|
||||||
|
if (res.code === 200) {
|
||||||
|
console.log('success switch to', username);
|
||||||
|
} else {
|
||||||
|
console.log('switch to', username, 'failed', res.message || '');
|
||||||
|
}
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'user',
|
||||||
|
key: 'logout',
|
||||||
|
description: '退出登录',
|
||||||
|
metadata: {}
|
||||||
|
}).define(async () => {
|
||||||
|
try {
|
||||||
|
await queryLogin.logout();
|
||||||
|
storage.removeItem('token');
|
||||||
|
console.log('退出成功');
|
||||||
|
} catch (error) {
|
||||||
|
console.log('退出失败', error);
|
||||||
|
}
|
||||||
|
}).addTo(app)
|
||||||
252
src/routes/token-ls.ts
Normal file
252
src/routes/token-ls.ts
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
import { app } from '../app.ts';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { getConfig, getEnvToken, writeConfig } from '@/module/get-config.ts';
|
||||||
|
import { queryLogin, storage } from '@/module/query.ts';
|
||||||
|
import { Kevisual } from '@/module/kevisual.ts';
|
||||||
|
import { showMore } from '@/uitls/show-more.ts';
|
||||||
|
|
||||||
|
function isNumeric(str: string) {
|
||||||
|
return /^-?\d+\.?\d*$/.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
const showList = (list: string[]) => {
|
||||||
|
if (list.length === 0) {
|
||||||
|
console.log('expand baseURLList is empty');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const config = getConfig();
|
||||||
|
console.log('----current baseURL:' + config.baseURL + '----\n');
|
||||||
|
list.forEach((item, index) => {
|
||||||
|
console.log(`${index + 1}: ${item}`);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'token',
|
||||||
|
key: 'ls',
|
||||||
|
description: '显示 token 列表',
|
||||||
|
metadata: {
|
||||||
|
args: {}
|
||||||
|
}
|
||||||
|
}).define(async () => {
|
||||||
|
console.log('show token list');
|
||||||
|
queryLogin.cacheStore.init();
|
||||||
|
console.log(queryLogin.cacheStore.cacheData);
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'token',
|
||||||
|
key: 'info',
|
||||||
|
description: '显示 token 信息',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
env: z.boolean().optional().describe('显示环境变量中的 token'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { env } = ctx.args;
|
||||||
|
const token = storage.getItem('token');
|
||||||
|
if (env) {
|
||||||
|
console.log('token in env', getEnvToken());
|
||||||
|
} else {
|
||||||
|
console.log('token', token);
|
||||||
|
}
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'token',
|
||||||
|
key: 'create',
|
||||||
|
description: '创建 jwks token',
|
||||||
|
metadata: {
|
||||||
|
args: {}
|
||||||
|
}
|
||||||
|
}).define(async () => {
|
||||||
|
const kevisual = new Kevisual();
|
||||||
|
const res = await kevisual.getAdminToken();
|
||||||
|
if (res.code === 200) {
|
||||||
|
const jwtToken = res.data?.accessToken;
|
||||||
|
console.log('============jwt token============\n\n');
|
||||||
|
console.log(jwtToken);
|
||||||
|
} else {
|
||||||
|
console.log('create token failed', showMore(res));
|
||||||
|
}
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'baseURL',
|
||||||
|
key: 'info',
|
||||||
|
description: '显示 baseURL',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
add: z.string().optional().describe('添加 baseURL'),
|
||||||
|
remove: z.number().optional().describe('按编号移除 baseURL'),
|
||||||
|
set: z.union([z.number(), z.string()]).optional().describe('设置 baseURL'),
|
||||||
|
list: z.boolean().optional().describe('列出 baseURL'),
|
||||||
|
clear: z.boolean().optional().describe('清除 baseURL'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
let { add, remove, set, list, clear } = ctx.args;
|
||||||
|
let config = getConfig();
|
||||||
|
let baseList = (config.baseURLList as Array<string>) || [];
|
||||||
|
if (!config.baseURL) {
|
||||||
|
baseList = ['https://kevisual.cn'];
|
||||||
|
writeConfig({ ...config, baseURL: 'https://kevisual.cn', baseURLList: baseList });
|
||||||
|
config = getConfig();
|
||||||
|
}
|
||||||
|
const quineList = (list: string[]) => {
|
||||||
|
const newList = new Set(list);
|
||||||
|
return Array.from(newList);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (add || set) {
|
||||||
|
let change = false;
|
||||||
|
if (add) {
|
||||||
|
change = true;
|
||||||
|
baseList.push(add);
|
||||||
|
} else if (set) {
|
||||||
|
if (!isNumeric(String(set))) {
|
||||||
|
change = true;
|
||||||
|
baseList.push(String(set));
|
||||||
|
writeConfig({ ...config, baseURL: String(set) });
|
||||||
|
config = getConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (change) {
|
||||||
|
baseList = quineList(baseList);
|
||||||
|
writeConfig({ ...config, baseURLList: baseList });
|
||||||
|
config = getConfig();
|
||||||
|
showList(baseList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remove !== undefined) {
|
||||||
|
const index = remove - 1;
|
||||||
|
if (index < 0 || index >= baseList.length) {
|
||||||
|
console.log('index out of range');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const removeBase = baseList.splice(index, 1);
|
||||||
|
baseList = quineList(baseList);
|
||||||
|
showList(baseList);
|
||||||
|
writeConfig({ ...config, baseURLList: baseList });
|
||||||
|
removeBase[0];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (set !== undefined) {
|
||||||
|
const isNumber = isNumeric(String(set));
|
||||||
|
if (isNumber) {
|
||||||
|
const index = Number(set) - 1;
|
||||||
|
if (index < 0 || index >= baseList.length) {
|
||||||
|
console.log('index out of range');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeConfig({ ...config, baseURL: baseList[index] });
|
||||||
|
showList(baseList);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (list) {
|
||||||
|
showList(baseList);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (clear) {
|
||||||
|
writeConfig({ ...config, baseURLList: [] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!config.baseURL) {
|
||||||
|
config = getConfig();
|
||||||
|
writeConfig({ ...config, baseURL: 'https://kevisual.cn' });
|
||||||
|
config = getConfig();
|
||||||
|
}
|
||||||
|
console.log('current baseURL:', config.baseURL);
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'baseURL',
|
||||||
|
key: 'set',
|
||||||
|
description: '设置 baseURL',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
baseURL: z.string().optional().describe('baseURL 地址'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const config = getConfig();
|
||||||
|
let baseURL = ctx.args.baseURL;
|
||||||
|
if (!baseURL) {
|
||||||
|
console.log('baseURL is required');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeConfig({ ...config, baseURL });
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'registry',
|
||||||
|
key: 'manage',
|
||||||
|
description: 'registry 管理',
|
||||||
|
metadata: {
|
||||||
|
args: {
|
||||||
|
list: z.boolean().optional().describe('列出 registry'),
|
||||||
|
set: z.string().optional().describe('设置 registry'),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const { list, set } = ctx.args;
|
||||||
|
const config = getConfig();
|
||||||
|
const defaultRegistry = ['https://kevisual.cn', 'https://kevisual.silkyai.cn', 'https://kevisual.xiongxiao.me', 'http://localhost:3005'];
|
||||||
|
if (list) {
|
||||||
|
showList(defaultRegistry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (set) {
|
||||||
|
const isNumber = isNumeric(set);
|
||||||
|
if (isNumber) {
|
||||||
|
const index = Number(set) - 1;
|
||||||
|
if (index < 0 || index >= defaultRegistry.length) {
|
||||||
|
console.log('index out of range');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeConfig({ ...config, baseURL: defaultRegistry[index] });
|
||||||
|
console.log('set registry', defaultRegistry[index]);
|
||||||
|
} else {
|
||||||
|
writeConfig({ ...config, baseURL: set });
|
||||||
|
console.log('set registry', set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'baseURL',
|
||||||
|
key: 'kevisual',
|
||||||
|
description: 'kevisual registry',
|
||||||
|
metadata: { args: {} }
|
||||||
|
}).define(async () => {
|
||||||
|
const config = getConfig();
|
||||||
|
const defaultRegistry = ['https://kevisual.cn'];
|
||||||
|
writeConfig({ ...config, baseURL: defaultRegistry[0] });
|
||||||
|
showList(defaultRegistry);
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'baseURL',
|
||||||
|
key: 'silky',
|
||||||
|
description: 'silky registry',
|
||||||
|
metadata: { args: {} }
|
||||||
|
}).define(async () => {
|
||||||
|
const config = getConfig();
|
||||||
|
const defaultRegistry = ['https://kevisual.silkyai.cn'];
|
||||||
|
writeConfig({ ...config, baseURL: defaultRegistry[0] });
|
||||||
|
showList(defaultRegistry);
|
||||||
|
}).addTo(app)
|
||||||
|
|
||||||
|
app.route({
|
||||||
|
path: 'baseURL',
|
||||||
|
key: 'local',
|
||||||
|
description: 'local registry',
|
||||||
|
metadata: { args: {} }
|
||||||
|
}).define(async () => {
|
||||||
|
const config = getConfig();
|
||||||
|
const defaultRegistry = ['http://localhost:3005'];
|
||||||
|
writeConfig({ ...config, baseURL: defaultRegistry[0] });
|
||||||
|
showList(defaultRegistry);
|
||||||
|
}).addTo(app)
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import { runParser } from './index.ts';
|
|
||||||
|
|
||||||
runParser(process.argv);
|
|
||||||
Reference in New Issue
Block a user