This commit is contained in:
2025-04-25 02:14:24 +08:00
parent 6827945446
commit 9eb4d06939
38 changed files with 1941 additions and 42 deletions

View File

@@ -0,0 +1,44 @@
import path from 'node:path';
import { checkFileExists, AssistantConfig } from '@/module/assistant/index.ts';
import { chalk } from '@/module/chalk.ts';
export type AssistantInitOptions = {
path?: string;
};
/**
* 助手初始化类
* @class AssistantInit
*/
export class AssistantInit extends AssistantConfig {
constructor(opts?: AssistantInitOptions) {
const configDir = opts?.path || process.cwd();
super({
configDir,
});
}
async init() {
// 1. 检查助手路径是否存在
if (!this.checkConfigPath()) {
console.log(chalk.blue('助手路径不存在,正在创建...'));
super.init();
this.createAssistantConfig();
} else {
super.init();
console.log(chalk.yellow('助手路径已存在'));
return;
}
}
checkConfigPath() {
const assistantPath = path.join(this.configDir, 'assistant-config.json');
return checkFileExists(assistantPath);
}
createAssistantConfig() {
const assistantPath = this.configPath?.configPath;
if (!checkFileExists(assistantPath, true)) {
this.setConfig({
description: '助手配置文件',
});
console.log(chalk.green('助手配置文件创建成功'));
}
}
}

View File

@@ -0,0 +1,84 @@
import fs from 'node:fs';
import { AssistantConfig, checkFileExists } from '@/module/assistant/index.ts';
import path from 'node:path';
export const localProxyProxyList = [
{
user: 'root',
key: 'assistant-base-app',
path: '/root/assistant-base-app',
indexPath: 'root/assistant-base-app/index.html',
},
{
user: 'root',
key: 'talkshow-admin',
path: '/root/talkshow-admin',
indexPath: 'root/talkshow-admin/index.html',
},
{
user: 'root',
key: 'center',
path: '/root/center',
indexPath: 'root/center/index.html',
},
];
type ProxyType = {
user: string;
key: string;
path: string;
indexPath: string;
absolutePath?: string;
};
export type LocalProxyOpts = {
assistantConfig?: AssistantConfig; // 前端应用路径
};
export class LocalProxy {
localProxyProxyList: ProxyType[] = [];
assistantConfig?: AssistantConfig;
constructor(opts?: LocalProxyOpts) {
this.assistantConfig = opts?.assistantConfig;
if (this.assistantConfig) {
this.init();
}
}
init() {
const frontAppDir = this.assistantConfig.configPath?.appDir;
console.log('frontAppDir', frontAppDir);
if (frontAppDir) {
const userList = fs.readdirSync(frontAppDir);
const localProxyProxyList: ProxyType[] = [];
userList.forEach((user) => {
const userPath = path.join(frontAppDir, user);
const stat = fs.statSync(userPath);
if (stat.isDirectory()) {
const appList = fs.readdirSync(userPath);
appList.forEach((app) => {
const appPath = path.join(userPath, app);
const indexPath = path.join(appPath, 'index.html');
if (!checkFileExists(indexPath, true)) {
return;
}
// const appPath = `${appPath}/index.html`;
if (checkFileExists(indexPath, true)) {
localProxyProxyList.push({
user: user,
key: app,
path: `/${user}/${app}`,
indexPath: `${user}/${app}/index.html`,
absolutePath: appPath,
});
}
});
}
});
this.localProxyProxyList = localProxyProxyList;
}
}
getLocalProxyList() {
return this.localProxyProxyList;
}
reload() {
// 重新加载本地代理列表
}
}

View File

@@ -0,0 +1,85 @@
import { fileProxy, apiProxy, createApiProxy } from '@/module/assistant/index.ts';
import http from 'http';
import { LocalProxy } from './local-proxy.ts';
import { assistantConfig } from '@/app.ts';
import { log } from '@/module/logger.ts';
const localProxy = new LocalProxy({
assistantConfig,
});
export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResponse) => {
const _assistantConfig = assistantConfig.getCacheAssistantConfig();
const appDir = assistantConfig.configPath?.appDir;
const url = new URL(req.url, 'http://localhost');
const pathname = url.pathname;
if (pathname.startsWith('/favicon.ico')) {
res.statusCode = 404;
res.end('Not Found Favicon');
return;
}
if (pathname.startsWith('/client')) {
console.log('handle by router');
return;
}
// client, api, v1, serve 开头的拦截
const apiProxyList = _assistantConfig?.apiProxyList || [];
const defaultApiProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn');
const apiBackendProxy = [...apiProxyList, ...defaultApiProxy].find((item) => pathname.startsWith(item.path));
if (apiBackendProxy) {
console.log('apiBackendProxy', apiBackendProxy, req.url);
return apiProxy(req, res, {
path: apiBackendProxy.path,
target: apiBackendProxy.target,
});
}
const urls = pathname.split('/');
const [_, _user, _app] = urls;
if (!_app) {
res.statusCode = 404;
res.end('Not Found Proxy');
return;
}
if (_app && urls.length === 3) {
// 重定向到
res.writeHead(302, { Location: `${req.url}/` });
return res.end();
}
const proxyApiList = _assistantConfig?.proxy || [];
const proxyApi = proxyApiList.find((item) => pathname.startsWith(item.path));
if (proxyApi) {
log.log('proxyApi', { proxyApi, pathname });
const { user, key } = proxyApi;
return fileProxy(req, res, {
path: proxyApi.path, // 代理路径, 比如/root/center
rootPath: appDir, // 根路径
indexPath: `${user}/${key}/index.html`, // 首页路径
});
}
const localProxyProxyList = localProxy.getLocalProxyList();
const localProxyProxy = localProxyProxyList.find((item) => pathname.startsWith(item.path));
if (localProxyProxy) {
log.log('localProxyProxy', { localProxyProxy, url: req.url });
return fileProxy(req, res, {
path: localProxyProxy.path,
rootPath: assistantConfig.configPath?.appDir,
indexPath: localProxyProxy.indexPath,
});
}
console.log('handle by router 404', req.url);
const creatCenterProxy = createApiProxy(_assistantConfig?.pageApi || 'https://kevisual.cn', ['/root']);
const centerProxy = creatCenterProxy.find((item) => pathname.startsWith(item.path));
if (centerProxy) {
console.log('centerProxy', centerProxy, req.url);
return apiProxy(req, res, {
path: centerProxy.path,
target: centerProxy.target,
type: 'static',
});
}
res.statusCode = 404;
res.end('Not Found Proxy');
// console.log('getCacheAssistantConfig().pageApi', getCacheAssistantConfig().pageApi);
// return apiProxy(req, res, {
// path: url.pathname,
// target: getCacheAssistantConfig().pageApi,
// });
};