update: 更新light-code部分的代码模块
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
],
|
],
|
||||||
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
"author": "abearxiong <xiongxiao@xiongxiao.me> (https://www.xiongxiao.me)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"packageManager": "pnpm@10.11.0",
|
"packageManager": "pnpm@10.21.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
@@ -41,32 +41,32 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@kevisual/ai": "^0.0.5",
|
"@kevisual/ai": "^0.0.11",
|
||||||
"@kevisual/load": "^0.0.6",
|
"@kevisual/load": "^0.0.6",
|
||||||
"@kevisual/local-app-manager": "^0.1.21",
|
"@kevisual/local-app-manager": "^0.1.23",
|
||||||
"@kevisual/logger": "^0.0.4",
|
"@kevisual/logger": "^0.0.4",
|
||||||
"@kevisual/query": "0.0.20",
|
"@kevisual/query": "0.0.29",
|
||||||
"@kevisual/query-login": "0.0.6",
|
"@kevisual/query-login": "0.0.6",
|
||||||
"@kevisual/router": "^0.0.21",
|
"@kevisual/router": "^0.0.30",
|
||||||
"@kevisual/task-command": "^0.0.7",
|
"@kevisual/task-command": "^0.0.7",
|
||||||
"@kevisual/types": "^0.0.10",
|
"@kevisual/types": "^0.0.10",
|
||||||
"@kevisual/use-config": "^1.0.17",
|
"@kevisual/use-config": "^1.0.19",
|
||||||
"@types/bun": "^1.2.15",
|
"@types/bun": "^1.3.2",
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^22.15.29",
|
"@types/node": "^24.10.0",
|
||||||
"@types/send": "^0.17.4",
|
"@types/send": "^1.2.1",
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"chalk": "^5.4.1",
|
"chalk": "^5.6.2",
|
||||||
"commander": "^14.0.0",
|
"commander": "^14.0.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^10.1.0",
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.19",
|
||||||
"dotenv": "^16.5.0",
|
"dotenv": "^17.2.3",
|
||||||
"get-port": "^7.1.0",
|
"get-port": "^7.1.0",
|
||||||
"inquirer": "^12.6.3",
|
"inquirer": "^12.11.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.6",
|
||||||
"send": "^1.2.0",
|
"send": "^1.2.0",
|
||||||
"supports-color": "^10.0.0",
|
"supports-color": "^10.2.2",
|
||||||
"ws": "npm:@kevisual/ws"
|
"ws": "npm:@kevisual/ws"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -78,6 +78,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eventemitter3": "^5.0.1",
|
"eventemitter3": "^5.0.1",
|
||||||
"lowdb": "^7.0.1",
|
"lowdb": "^7.0.1",
|
||||||
"pm2": "^6.0.6"
|
"lru-cache": "^11.2.2",
|
||||||
|
"pm2": "^6.0.13",
|
||||||
|
"unstorage": "^1.17.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
52
assistant/pnpm-lock.yaml
generated
52
assistant/pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ importers:
|
|||||||
lowdb:
|
lowdb:
|
||||||
specifier: ^7.0.1
|
specifier: ^7.0.1
|
||||||
version: 7.0.1
|
version: 7.0.1
|
||||||
|
lru-cache:
|
||||||
|
specifier: ^11.2.2
|
||||||
|
version: 11.2.2
|
||||||
pm2:
|
pm2:
|
||||||
specifier: ^6.0.6
|
specifier: ^6.0.6
|
||||||
version: 6.0.6(supports-color@10.0.0)
|
version: 6.0.6(supports-color@10.0.0)
|
||||||
@@ -100,43 +103,6 @@ importers:
|
|||||||
specifier: npm:@kevisual/ws
|
specifier: npm:@kevisual/ws
|
||||||
version: '@kevisual/ws@8.0.0'
|
version: '@kevisual/ws@8.0.0'
|
||||||
|
|
||||||
tasks/silkyai-cli:
|
|
||||||
dependencies:
|
|
||||||
pm2:
|
|
||||||
specifier: ^6.0.5
|
|
||||||
version: 6.0.6(supports-color@10.0.0)
|
|
||||||
devDependencies:
|
|
||||||
'@kevisual/assistant-cli':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../..
|
|
||||||
'@kevisual/task-command':
|
|
||||||
specifier: ^0.0.7
|
|
||||||
version: 0.0.7
|
|
||||||
chalk:
|
|
||||||
specifier: ^5.4.1
|
|
||||||
version: 5.4.1
|
|
||||||
commander:
|
|
||||||
specifier: ^13.1.0
|
|
||||||
version: 13.1.0
|
|
||||||
cross-env:
|
|
||||||
specifier: ^7.0.3
|
|
||||||
version: 7.0.3
|
|
||||||
dayjs:
|
|
||||||
specifier: ^1.11.13
|
|
||||||
version: 1.11.13
|
|
||||||
dotenv:
|
|
||||||
specifier: ^16.5.0
|
|
||||||
version: 16.5.0
|
|
||||||
inquirer:
|
|
||||||
specifier: ^12.6.0
|
|
||||||
version: 12.6.3(@types/node@22.15.29)
|
|
||||||
lodash-es:
|
|
||||||
specifier: ^4.17.21
|
|
||||||
version: 4.17.21
|
|
||||||
nanoid:
|
|
||||||
specifier: ^5.1.5
|
|
||||||
version: 5.1.5
|
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
'@babel/code-frame@7.26.2':
|
'@babel/code-frame@7.26.2':
|
||||||
@@ -630,10 +596,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
|
||||||
commander@13.1.0:
|
|
||||||
resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
|
|
||||||
engines: {node: '>=18'}
|
|
||||||
|
|
||||||
commander@14.0.0:
|
commander@14.0.0:
|
||||||
resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==}
|
resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
@@ -1002,6 +964,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==}
|
resolution: {integrity: sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
lru-cache@11.2.2:
|
||||||
|
resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==}
|
||||||
|
engines: {node: 20 || >=22}
|
||||||
|
|
||||||
lru-cache@6.0.0:
|
lru-cache@6.0.0:
|
||||||
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -1914,8 +1880,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
delayed-stream: 1.0.0
|
delayed-stream: 1.0.0
|
||||||
|
|
||||||
commander@13.1.0: {}
|
|
||||||
|
|
||||||
commander@14.0.0: {}
|
commander@14.0.0: {}
|
||||||
|
|
||||||
commander@2.15.1: {}
|
commander@2.15.1: {}
|
||||||
@@ -2242,6 +2206,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
steno: 4.0.2
|
steno: 4.0.2
|
||||||
|
|
||||||
|
lru-cache@11.2.2: {}
|
||||||
|
|
||||||
lru-cache@6.0.0:
|
lru-cache@6.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
yallist: 4.0.0
|
yallist: 4.0.0
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
packages:
|
|
||||||
- 'tasks/**'
|
|
||||||
- '!assistant-app/**'
|
|
||||||
@@ -70,6 +70,20 @@ appManagerCommand
|
|||||||
console.log('Restart App:', appKey);
|
console.log('Restart App:', appKey);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
appManagerCommand
|
||||||
|
.command('reload')
|
||||||
|
.description('重载配置项,对路径的app的内容变更有效')
|
||||||
|
.argument('<app-key-name>', '应用的 key 名称')
|
||||||
|
.action(async (appKey: string) => {
|
||||||
|
const manager = new AssistantApp(assistantConfig);
|
||||||
|
try {
|
||||||
|
await manager.loadConfig();
|
||||||
|
await manager.reload(appKey);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
console.log('Reload App:', appKey);
|
||||||
|
});
|
||||||
appManagerCommand
|
appManagerCommand
|
||||||
.command('delete')
|
.command('delete')
|
||||||
.alias('del')
|
.alias('del')
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export class HttpsPem {
|
|||||||
assistantConfig: AssistantConfig;
|
assistantConfig: AssistantConfig;
|
||||||
key: string;
|
key: string;
|
||||||
cert: string;
|
cert: string;
|
||||||
|
isHttps = false;
|
||||||
constructor(assistantConfig: AssistantConfig) {
|
constructor(assistantConfig: AssistantConfig) {
|
||||||
this.assistantConfig = assistantConfig;
|
this.assistantConfig = assistantConfig;
|
||||||
this.#initKeyCert();
|
this.#initKeyCert();
|
||||||
@@ -32,6 +33,7 @@ export class HttpsPem {
|
|||||||
console.log(chalk.yellow('当前配置文件 https.type 不是 https, 不使用证书'));
|
console.log(chalk.yellow('当前配置文件 https.type 不是 https, 不使用证书'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.isHttps = true;
|
||||||
if (config.https.keyPath) {
|
if (config.https.keyPath) {
|
||||||
const keyPath = config.https.keyPath;
|
const keyPath = config.https.keyPath;
|
||||||
const certPath = config.https.certPath;
|
const certPath = config.https.certPath;
|
||||||
@@ -45,6 +47,7 @@ export class HttpsPem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!this.isHttps) return;
|
||||||
const { key, cert } = this.getCert();
|
const { key, cert } = this.getCert();
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.cert = cert;
|
this.cert = cert;
|
||||||
|
|||||||
6
assistant/src/module/cache/auth.ts
vendored
Normal file
6
assistant/src/module/cache/auth.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { LRUCache } from 'lru-cache'
|
||||||
|
|
||||||
|
export const authCache = new LRUCache<string, any>({
|
||||||
|
max: 10000, // 最大缓存数量
|
||||||
|
ttl: 1000 * 60 * 60 * 24 * 7, // 缓存过期时间,单位为毫秒,这里设置为7天
|
||||||
|
});
|
||||||
149
assistant/src/module/light-code/run.ts
Normal file
149
assistant/src/module/light-code/run.ts
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
import { fork } from 'child_process'
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
export const fileExists = (path: string): boolean => {
|
||||||
|
try {
|
||||||
|
fs.accessSync(path, fs.constants.F_OK);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RunCodeParams = {
|
||||||
|
path?: string;
|
||||||
|
key?: string;
|
||||||
|
payload?: string;
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
type RunCodeOptions = {
|
||||||
|
timeout?: number; // 超时时间,单位毫秒
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
type RunCode = {
|
||||||
|
// 调用进程的功能
|
||||||
|
success?: boolean
|
||||||
|
data?: {
|
||||||
|
// 调用router的结果
|
||||||
|
code?: number
|
||||||
|
data?: any
|
||||||
|
message?: string
|
||||||
|
[key: string]: any
|
||||||
|
};
|
||||||
|
error?: any
|
||||||
|
timestamp?: string
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
export const runCode = async (tsPath: string, params: RunCodeParams = {}, opts?: RunCodeOptions): Promise<RunCode> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (fileExists(tsPath) === false) {
|
||||||
|
resolve({
|
||||||
|
success: false,
|
||||||
|
error: `文件不存在: ${tsPath}`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeoutMs = opts?.timeout || 30000; // 默认30秒超时
|
||||||
|
|
||||||
|
let child
|
||||||
|
let resolved = false // 防止多次 resolve
|
||||||
|
let isSendParam = false;
|
||||||
|
let timeout: NodeJS.Timeout
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
if (timeout) {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
}
|
||||||
|
if (child && !child.killed) {
|
||||||
|
child.kill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sendParam = () => {
|
||||||
|
if (!resolved && child && !isSendParam) {
|
||||||
|
isSendParam = true
|
||||||
|
child.send(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolveOnce = (result: RunCode) => {
|
||||||
|
if (!resolved) {
|
||||||
|
resolved = true
|
||||||
|
cleanup()
|
||||||
|
resolve(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 使用 Bun 的 fork 模式启动子进程
|
||||||
|
child = fork(tsPath, [], {
|
||||||
|
silent: true // 启用 stdio 重定向
|
||||||
|
})
|
||||||
|
// 监听来自子进程的消息
|
||||||
|
child.on('message', (msg: RunCode) => {
|
||||||
|
resolveOnce(msg)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 捕获 stderr 输出(语法错误等)
|
||||||
|
if (child.stderr) {
|
||||||
|
child.stderr.on('data', (data) => {
|
||||||
|
console.log('子进程错误输出:', data.toString())
|
||||||
|
resolveOnce({
|
||||||
|
success: false,
|
||||||
|
error: `子进程错误输出: ${data.toString()}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听子进程退出事件
|
||||||
|
child.on('exit', (code, signal) => {
|
||||||
|
if (code !== 0) {
|
||||||
|
resolveOnce({
|
||||||
|
success: false,
|
||||||
|
error: `子进程异常退出,退出码: ${code},信号: ${signal}`
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
resolveOnce({
|
||||||
|
success: false,
|
||||||
|
error: '子进程正常退出但未返回消息'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听子进程关闭事件
|
||||||
|
child.on('close', (code, signal) => {
|
||||||
|
resolveOnce({
|
||||||
|
success: false,
|
||||||
|
error: `子进程已关闭,退出码: ${code},信号: ${signal}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听子进程错误事件
|
||||||
|
child.on('error', (error) => {
|
||||||
|
resolveOnce({
|
||||||
|
success: false,
|
||||||
|
error: `子进程错误: ${error?.message}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 添加超时处理
|
||||||
|
timeout = setTimeout(() => {
|
||||||
|
resolveOnce({
|
||||||
|
success: false,
|
||||||
|
error: '子进程执行超时'
|
||||||
|
})
|
||||||
|
}, timeoutMs)
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
sendParam()
|
||||||
|
}, 10); // 35秒响应超时
|
||||||
|
// 向子进程发送消息
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
resolveOnce({
|
||||||
|
success: false,
|
||||||
|
error: `启动子进程失败: ${error instanceof Error ? error.message : '未知错误'}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { app, assistantConfig } from '../app.ts';
|
|||||||
import './config/index.ts';
|
import './config/index.ts';
|
||||||
import './shop-install/index.ts';
|
import './shop-install/index.ts';
|
||||||
import './ai/index.ts';
|
import './ai/index.ts';
|
||||||
|
import './light-code/index.ts';
|
||||||
|
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
|
|
||||||
|
|||||||
30
assistant/src/routes/light-code/call.ts
Normal file
30
assistant/src/routes/light-code/call.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { app, assistantConfig } from '../../app.ts'
|
||||||
|
import path from 'path'
|
||||||
|
import { runCode } from '../../module/light-code/run.ts'
|
||||||
|
|
||||||
|
// http://localhost:4005/api/router?path=call
|
||||||
|
app.route({
|
||||||
|
path: 'call',
|
||||||
|
// middleware: ['auth']
|
||||||
|
}).define(async (ctx) => {
|
||||||
|
const filename = ctx.query?.filename || 'root/light-code-demo/demo-router.ts'
|
||||||
|
const data = ctx.query?.data || {}
|
||||||
|
const appsConfigPath = assistantConfig.configPath?.appsDir || '';
|
||||||
|
const testA = path.join(appsConfigPath, filename)
|
||||||
|
try {
|
||||||
|
const resulst = await runCode(testA, data);
|
||||||
|
if (resulst.success) {
|
||||||
|
const callResult = resulst.data;
|
||||||
|
if (callResult.code === 200) ctx.body = callResult.data
|
||||||
|
else {
|
||||||
|
const callError = `调用程序错误: ${callResult.message}`
|
||||||
|
ctx.throw(callResult.code, callError)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx.body = `执行脚本错误: ${resulst.error}`
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ctx.body = `执行脚本异常: ${error?.message || error}`
|
||||||
|
}
|
||||||
|
|
||||||
|
}).addTo(app)
|
||||||
1
assistant/src/routes/light-code/index.ts
Normal file
1
assistant/src/routes/light-code/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
import './call.ts'
|
||||||
@@ -71,14 +71,11 @@ export class AppDownload {
|
|||||||
const command = 'ev';
|
const command = 'ev';
|
||||||
const args = ['app', 'download'];
|
const args = ['app', 'download'];
|
||||||
args.push('-i', id);
|
args.push('-i', id);
|
||||||
if (type) {
|
|
||||||
args.push('-t', type);
|
|
||||||
}
|
|
||||||
const appName = opts?.appName || id.split('/').pop();
|
|
||||||
if (type === 'web') {
|
if (type === 'web') {
|
||||||
args.push('-o', pagesDir);
|
args.push('-o', pagesDir);
|
||||||
} else if (type === 'app') {
|
} else if (type === 'app') {
|
||||||
args.push('-o', path.join(appsDir, appName));
|
args.push('-o', path.join(appsDir));
|
||||||
} else {
|
} else {
|
||||||
throw new Error('应用类型错误,只能是 web 或 app');
|
throw new Error('应用类型错误,只能是 web 或 app');
|
||||||
}
|
}
|
||||||
@@ -120,7 +117,7 @@ export class AppDownload {
|
|||||||
const pagePath = path.join(pagesDir, id);
|
const pagePath = path.join(pagesDir, id);
|
||||||
deletePath = pagePath;
|
deletePath = pagePath;
|
||||||
} else if (type === 'app') {
|
} else if (type === 'app') {
|
||||||
const appPath = path.join(appsDir, appName);
|
const appPath = path.join(appsDir, id);
|
||||||
deletePath = appPath;
|
deletePath = appPath;
|
||||||
}
|
}
|
||||||
if (deletePath && checkFileExists(deletePath)) {
|
if (deletePath && checkFileExists(deletePath)) {
|
||||||
|
|||||||
@@ -59,9 +59,11 @@ export class AssistantInit extends AssistantConfig {
|
|||||||
}
|
}
|
||||||
// create pem dir //
|
// create pem dir //
|
||||||
const pemDir = path.join(this.configPath?.configDir, 'pem');
|
const pemDir = path.join(this.configPath?.configDir, 'pem');
|
||||||
if (!checkFileExists(pemDir)) {
|
const httpsPem = new HttpsPem(this);
|
||||||
new HttpsPem(this);
|
if (httpsPem.isHttps) {
|
||||||
console.log(chalk.green('助手证书目录创建成功'));
|
if (!checkFileExists(pemDir)) {
|
||||||
|
console.log(chalk.green('助手证书目录创建成功'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
createAssistantConfig() {
|
createAssistantConfig() {
|
||||||
|
|||||||
18
package.json
18
package.json
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@kevisual/cli",
|
"name": "@kevisual/cli",
|
||||||
"version": "0.0.60",
|
"version": "0.0.61",
|
||||||
"description": "envision command tools",
|
"description": "envision command tools",
|
||||||
"main": "dist/app.mjs",
|
"main": "dist/app.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"private": false,
|
"private": false,
|
||||||
"basename": "/root/backend-envision-cli",
|
"basename": "/root/cli",
|
||||||
"app": {
|
"app": {
|
||||||
"key": "envision-cli",
|
"key": "cli",
|
||||||
"entry": "dist/app.mjs",
|
"entry": "dist/app.mjs",
|
||||||
"type": "pm2-system-app",
|
"type": "pm2-system-app",
|
||||||
"runtime": [
|
"runtime": [
|
||||||
@@ -51,22 +51,22 @@
|
|||||||
"@kevisual/logger": "^0.0.4",
|
"@kevisual/logger": "^0.0.4",
|
||||||
"@kevisual/query": "0.0.29",
|
"@kevisual/query": "0.0.29",
|
||||||
"@kevisual/query-login": "0.0.6",
|
"@kevisual/query-login": "0.0.6",
|
||||||
"@types/bun": "^1.3.0",
|
"@types/bun": "^1.3.2",
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/micromatch": "^4.0.9",
|
"@types/micromatch": "^4.0.10",
|
||||||
"@types/node": "^24.7.2",
|
"@types/node": "^24.10.0",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
"commander": "^14.0.1",
|
"commander": "^14.0.2",
|
||||||
"cross-env": "^10.1.0",
|
"cross-env": "^10.1.0",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
"fast-glob": "^3.3.3",
|
"fast-glob": "^3.3.3",
|
||||||
"filesize": "^11.0.13",
|
"filesize": "^11.0.13",
|
||||||
"form-data": "^4.0.4",
|
"form-data": "^4.0.4",
|
||||||
"ignore": "^7.0.5",
|
"ignore": "^7.0.5",
|
||||||
"inquirer": "^12.9.6",
|
"inquirer": "^12.11.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"tar": "^7.5.1",
|
"tar": "^7.5.2",
|
||||||
"zustand": "^5.0.8"
|
"zustand": "^5.0.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
1430
pnpm-lock.yaml
generated
1430
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,6 @@ const downloadAppCommand = new Command('download')
|
|||||||
.description('下载 app serve client的包. \napp download -i root/code-center')
|
.description('下载 app serve client的包. \napp download -i root/code-center')
|
||||||
.option('-i, --id <id>', '下载 app serve client的包, id 或者user/key')
|
.option('-i, --id <id>', '下载 app serve client的包, id 或者user/key')
|
||||||
.option('-o, --output <output>', '下载 app serve client的包, 输出路径, 默认是当前目录')
|
.option('-o, --output <output>', '下载 app serve client的包, 输出路径, 默认是当前目录')
|
||||||
.option('-t, --type <type>', '下载 app serve client的包, 类型, app,或者web, 默认为web')
|
|
||||||
.option('-r, --registry <registry>', '下载 app serve client的包, 使用私有源')
|
.option('-r, --registry <registry>', '下载 app serve client的包, 使用私有源')
|
||||||
.option('-f, --force ', '强制覆盖')
|
.option('-f, --force ', '强制覆盖')
|
||||||
.option('-y, --yes ', '覆盖的时候不提示')
|
.option('-y, --yes ', '覆盖的时候不提示')
|
||||||
@@ -71,16 +70,9 @@ const downloadAppCommand = new Command('download')
|
|||||||
console.log('registry', registry, data, options.type);
|
console.log('registry', registry, data, options.type);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const app = res.data;
|
const app = res.data;
|
||||||
let appType: 'app' | 'web' = 'web';
|
|
||||||
if (options.type === 'app') {
|
|
||||||
appType = 'app';
|
|
||||||
} else if (options.type === 'web') {
|
|
||||||
appType = 'web';
|
|
||||||
}
|
|
||||||
const result = await installApp(app, {
|
const result = await installApp(app, {
|
||||||
appDir: output,
|
appDir: output,
|
||||||
kevisualUrl: registry,
|
kevisualUrl: registry,
|
||||||
appType: appType,
|
|
||||||
force: options.force,
|
force: options.force,
|
||||||
yes: options.yes,
|
yes: options.yes,
|
||||||
});
|
});
|
||||||
@@ -98,7 +90,6 @@ const uninstallAppCommand = new Command('uninstall')
|
|||||||
.alias('remove')
|
.alias('remove')
|
||||||
.description('卸载 app serve client的包。 手动删除更简单。')
|
.description('卸载 app serve client的包。 手动删除更简单。')
|
||||||
.option('-i, --id <id>', 'user/key')
|
.option('-i, --id <id>', 'user/key')
|
||||||
.option('-t, --type <type>', 'app,或者web, 默认为web', 'web')
|
|
||||||
.option('-p, --path <path>', '删除的路径, 如果存在,则优先执行,不会去判断 id 和 type 。')
|
.option('-p, --path <path>', '删除的路径, 如果存在,则优先执行,不会去判断 id 和 type 。')
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
if (options.path) {
|
if (options.path) {
|
||||||
|
|||||||
@@ -121,14 +121,6 @@ export const rewritePkg = (packagePath: string, pkg: Package) => {
|
|||||||
type InstallAppOpts = {
|
type InstallAppOpts = {
|
||||||
appDir?: string;
|
appDir?: string;
|
||||||
kevisualUrl?: string;
|
kevisualUrl?: string;
|
||||||
/**
|
|
||||||
* 是否是客户端, 下载到 assistant-config的下面
|
|
||||||
*/
|
|
||||||
isClient?: boolean;
|
|
||||||
/**
|
|
||||||
* 是否是web, 下载到 web-config的下面
|
|
||||||
*/
|
|
||||||
appType?: 'app' | 'web';
|
|
||||||
/**
|
/**
|
||||||
* 是否强制覆盖, 下载前删除已有的
|
* 是否强制覆盖, 下载前删除已有的
|
||||||
*/
|
*/
|
||||||
@@ -137,16 +129,16 @@ type InstallAppOpts = {
|
|||||||
};
|
};
|
||||||
export const installApp = async (app: Package, opts: InstallAppOpts = {}) => {
|
export const installApp = async (app: Package, opts: InstallAppOpts = {}) => {
|
||||||
// const _app = demoData;
|
// const _app = demoData;
|
||||||
const { appDir = '', kevisualUrl = 'https://kevisual.cn', isClient = false, appType = 'web' } = opts;
|
const { appDir = '', kevisualUrl = 'https://kevisual.cn', } = opts;
|
||||||
const _app = app;
|
const _app = app;
|
||||||
try {
|
try {
|
||||||
let files = _app.data.files || [];
|
let files = _app.data.files || [];
|
||||||
const version = _app.version;
|
const version = _app.version;
|
||||||
const user = _app.user;
|
const user = _app.user;
|
||||||
const key = _app.key;
|
const key = _app.key;
|
||||||
const downloadDirPath = appType === 'web' ? path.join(appDir, user, key) : path.join(appDir);
|
const downloadDirPath = path.join(appDir, user, key);
|
||||||
await checkDelete({ force: opts?.force, yes: opts?.yes, dir: downloadDirPath });
|
await checkDelete({ force: opts?.force, yes: opts?.yes, dir: downloadDirPath });
|
||||||
const packagePath = path.join(appDir, appType === 'app' ? 'package.json' : `${user}/${key}/package.json`);
|
const packagePath = path.join(appDir, `${user}/${key}/package.json`);
|
||||||
const downFiles = files
|
const downFiles = files
|
||||||
.filter((file: any) => file?.path)
|
.filter((file: any) => file?.path)
|
||||||
.map((file: any) => {
|
.map((file: any) => {
|
||||||
@@ -154,9 +146,6 @@ export const installApp = async (app: Package, opts: InstallAppOpts = {}) => {
|
|||||||
const noVersionPath = file.path.replace(`/${version}`, '');
|
const noVersionPath = file.path.replace(`/${version}`, '');
|
||||||
let downloadPath = noVersionPath;
|
let downloadPath = noVersionPath;
|
||||||
let downloadUrl = '';
|
let downloadUrl = '';
|
||||||
if (appType === 'app') {
|
|
||||||
downloadPath = noVersionPath.replace(`${user}/${key}/`, '');
|
|
||||||
}
|
|
||||||
if (file.path.startsWith('http')) {
|
if (file.path.startsWith('http')) {
|
||||||
downloadUrl = file.path;
|
downloadUrl = file.path;
|
||||||
} else {
|
} else {
|
||||||
@@ -178,7 +167,7 @@ export const installApp = async (app: Package, opts: InstallAppOpts = {}) => {
|
|||||||
if (!fs.existsSync(dir)) {
|
if (!fs.existsSync(dir)) {
|
||||||
fs.mkdirSync(dir, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
}
|
}
|
||||||
console.log('downloadUrwl', downloadUrl);
|
console.log('downloadUrl', downloadUrl);
|
||||||
const { blob, type } = await fetchLink(downloadUrl);
|
const { blob, type } = await fetchLink(downloadUrl);
|
||||||
if (type.includes('text/html')) {
|
if (type.includes('text/html')) {
|
||||||
const html = await blob.text();
|
const html = await blob.text();
|
||||||
@@ -222,7 +211,7 @@ export const checkAppDir = (appDir: string) => {
|
|||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
fs.rmSync(appDir, { recursive: true });
|
fs.rmSync(appDir, { recursive: true });
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
};
|
};
|
||||||
export const checkFileExists = (path: string) => {
|
export const checkFileExists = (path: string) => {
|
||||||
try {
|
try {
|
||||||
@@ -237,7 +226,7 @@ type UninstallAppOpts = {
|
|||||||
type?: 'app' | 'web';
|
type?: 'app' | 'web';
|
||||||
};
|
};
|
||||||
export const uninstallApp = async (app: Partial<Package>, opts: UninstallAppOpts = {}) => {
|
export const uninstallApp = async (app: Partial<Package>, opts: UninstallAppOpts = {}) => {
|
||||||
const { appDir = '', type = 'web' } = opts;
|
const { appDir = '' } = opts;
|
||||||
try {
|
try {
|
||||||
const { user, key } = app;
|
const { user, key } = app;
|
||||||
const keyDir = path.join(appDir, user, key);
|
const keyDir = path.join(appDir, user, key);
|
||||||
@@ -254,7 +243,7 @@ export const uninstallApp = async (app: Partial<Package>, opts: UninstallAppOpts
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
type === 'web' && checkAppDir(parentDir);
|
checkAppDir(parentDir);
|
||||||
return {
|
return {
|
||||||
code: 200,
|
code: 200,
|
||||||
message: 'Uninstall app success',
|
message: 'Uninstall app success',
|
||||||
|
|||||||
Reference in New Issue
Block a user