Refactor client routes and add IP fetching functionality
- Moved client route definitions to separate files for better organization. - Added new route to fetch client IP addresses, supporting both IPv4 and IPv6. - Implemented system information retrieval in the client routes. - Updated package dependencies to their latest versions. - Adjusted call route to prevent overwriting existing routes.
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import { App, QueryRouterServer } from '@kevisual/router';
|
||||
import { AssistantInit } from '../../services/init/index.ts';
|
||||
import path from 'node:path';
|
||||
import fs, { write } from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import fs from 'node:fs';
|
||||
import glob from 'fast-glob';
|
||||
import { runCode } from './run.ts';
|
||||
const codeDemoId = '0e700dc8-90dd-41b7-91dd-336ea51de3d2'
|
||||
@@ -35,44 +34,47 @@ const writeCodeDemo = async (appDir: string) => {
|
||||
}
|
||||
// writeCodeDemo(path.join(os.homedir(), 'kevisual', 'assistant-app', 'apps'));
|
||||
|
||||
type opts = {
|
||||
type Opts = {
|
||||
router: QueryRouterServer | App
|
||||
config: AssistantConfig | AssistantInit
|
||||
sync?: boolean
|
||||
sync?: 'remote' | 'local' | 'both'
|
||||
rootPath?: string
|
||||
}
|
||||
type LightCodeFile = {
|
||||
id?: string, code?: string, hash?: string, filepath: string
|
||||
}
|
||||
export const initLightCode = async (opts: opts) => {
|
||||
export const initLightCode = async (opts: Opts) => {
|
||||
// 注册 light-code 路由
|
||||
console.log('初始化 light-code 路由');
|
||||
const config = opts.config as AssistantInit;
|
||||
const app = opts.router;
|
||||
const token = config.getConfig()?.token || '';
|
||||
const query = config.query;
|
||||
const sync = opts.sync ?? true;
|
||||
const sync = opts.sync ?? 'remote';
|
||||
if (!config || !app) {
|
||||
console.error('initLightCode 缺少必要参数, config 或 app');
|
||||
return;
|
||||
}
|
||||
const appDir = config.configPath.appsDir;
|
||||
const lightcodeDir = path.join(appDir, 'light-code', 'code');
|
||||
const lightcodeDir = opts.rootPath;
|
||||
if (!fs.existsSync(lightcodeDir)) {
|
||||
fs.mkdirSync(lightcodeDir, { recursive: true });
|
||||
}
|
||||
let diffList: LightCodeFile[] = [];
|
||||
|
||||
const codeFiles = glob.sync(['**/*.ts', '**/*.js'], {
|
||||
cwd: lightcodeDir,
|
||||
onlyFiles: true,
|
||||
}).map(file => {
|
||||
return {
|
||||
filepath: path.join(lightcodeDir, file),
|
||||
// hash: getHash(path.join(lightcodeDir, file))
|
||||
}
|
||||
});
|
||||
const findGlob = (opts: { cwd: string }) => {
|
||||
return glob.sync(['**/*.ts', '**/*.js'], {
|
||||
cwd: opts.cwd,
|
||||
onlyFiles: true,
|
||||
}).map(file => {
|
||||
return {
|
||||
filepath: path.join(opts.cwd, file),
|
||||
// hash: getHash(path.join(lightcodeDir, file))
|
||||
}
|
||||
});
|
||||
}
|
||||
const codeFiles = findGlob({ cwd: lightcodeDir });
|
||||
|
||||
if (sync) {
|
||||
if (sync === 'remote' || sync === 'both') {
|
||||
const queryRes = await query.post({
|
||||
path: 'light-code',
|
||||
key: 'list',
|
||||
@@ -100,13 +102,6 @@ export const initLightCode = async (opts: opts) => {
|
||||
fs.writeFileSync(item.filepath, item.code, 'utf-8');
|
||||
// console.log(`新增 light-code 文件: ${item.filepath}`);
|
||||
}
|
||||
|
||||
// 执行删除
|
||||
for (const filepath of toDelete) {
|
||||
fs.unlinkSync(filepath.filepath);
|
||||
// console.log(`删除 light-code 文件: ${filepath.filepath}`);
|
||||
}
|
||||
|
||||
// 执行更新
|
||||
for (const item of toUpdate) {
|
||||
fs.writeFileSync(item.filepath, item.code, 'utf-8');
|
||||
@@ -117,23 +112,38 @@ export const initLightCode = async (opts: opts) => {
|
||||
// filepath: d.filepath,
|
||||
// hash: d.hash
|
||||
// }));
|
||||
|
||||
if (sync === 'remote') {
|
||||
// 执行删除
|
||||
for (const filepath of toDelete) {
|
||||
// console.log(`删除 light-code 文件: ${filepath.filepath}`);
|
||||
const parentDir = path.dirname(filepath.filepath);
|
||||
// console.log('parentDir', parentDir, lightcodeDir);
|
||||
if (parentDir === lightcodeDir) {
|
||||
fs.unlinkSync(filepath.filepath);
|
||||
}
|
||||
}
|
||||
}
|
||||
diffList = findGlob({ cwd: lightcodeDir });
|
||||
} else {
|
||||
console.error('light-code 同步失败', queryRes.message);
|
||||
diffList = codeFiles;
|
||||
}
|
||||
} else {
|
||||
} else if (sync === 'local') {
|
||||
diffList = codeFiles;
|
||||
}
|
||||
|
||||
|
||||
for (const file of diffList) {
|
||||
const tsPath = file.filepath;
|
||||
const runRes = await runCode(tsPath, { path: 'router', key: 'list' }, { timeout: 10000 });
|
||||
const runRes = await runCode(tsPath, { message: { path: 'router', key: 'list' } }, { timeout: 10000 });
|
||||
// console.log('light-code 运行结果', file.filepath, runRes);
|
||||
if (runRes.success) {
|
||||
const res = runRes.data;
|
||||
if (res.code === 200) {
|
||||
const list = res.data?.list || [];
|
||||
for (const routerItem of list) {
|
||||
// console.log('注册 light-code 路由项:', routerItem.id, routerItem.path);
|
||||
if (routerItem.path?.includes('auth') || routerItem.path?.includes('router') || routerItem.path?.includes('call')) {
|
||||
continue;
|
||||
}
|
||||
@@ -144,6 +154,10 @@ export const initLightCode = async (opts: opts) => {
|
||||
} else {
|
||||
metadata.tags = ['light-code'];
|
||||
}
|
||||
metadata.source = 'light-code';
|
||||
metadata['light-code'] = {
|
||||
id: file.id
|
||||
}
|
||||
app.route({
|
||||
id: routerItem.id,
|
||||
path: `${routerItem.id}__${routerItem.path}`,
|
||||
@@ -153,8 +167,13 @@ export const initLightCode = async (opts: opts) => {
|
||||
middleware: ['auth'],
|
||||
}).define(async (ctx) => {
|
||||
const tokenUser = ctx.state?.tokenUser || {};
|
||||
const query = { ...ctx.query, tokenUser }
|
||||
const runRes2 = await runCode(tsPath, query, { timeout: 30000 });
|
||||
const query = { ...ctx.query }
|
||||
const runRes2 = await runCode(tsPath, {
|
||||
message: query,
|
||||
context: {
|
||||
state: { tokenUser, user: tokenUser },
|
||||
}
|
||||
}, { timeout: 30000 });
|
||||
if (runRes2.success) {
|
||||
const res2 = runRes2.data;
|
||||
if (res2.code === 200) {
|
||||
@@ -166,11 +185,9 @@ export const initLightCode = async (opts: opts) => {
|
||||
ctx.throw(runRes2.error || 'Lightcode 路由执行失败');
|
||||
}
|
||||
}).addTo(app, {
|
||||
override: false,
|
||||
// @ts-ignore
|
||||
overwrite: false
|
||||
});// 不允许覆盖已存在的路由
|
||||
|
||||
// console.log(`light-code 路由注册成功: [${routerItem.path}] ${routerItem.id} 来自文件: ${file.filepath}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -178,4 +195,19 @@ export const initLightCode = async (opts: opts) => {
|
||||
}
|
||||
}
|
||||
console.log(`light-code 路由注册成功`, `注册${diffList.length}个路由`);
|
||||
}
|
||||
|
||||
export const clearLightCodeRoutes = (opts: Pick<Opts, 'router'>) => {
|
||||
const app = opts.router;
|
||||
if (!app) {
|
||||
console.error('clearLightCodeRoutes 缺少必要参数, app');
|
||||
return;
|
||||
}
|
||||
const routes = app.getList();
|
||||
for (const route of routes) {
|
||||
if (route.metadata?.source === 'light-code') {
|
||||
// console.log(`删除 light-code 路由: ${route.path} ${route.id}`);
|
||||
app.removeById(route.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user