import fs from 'node:fs'; import { AssistantConfig, checkFileExists } from '@/module/assistant/index.ts'; import path from 'node:path'; import { logger } from '@/module/logger.ts'; type ProxyType = { user: string; key: string; path: string; indexPath: string; absolutePath?: string; }; export type LocalProxyOpts = { assistantConfig?: AssistantConfig; // 前端应用路径 // watch?: boolean; // 是否监听文件变化 }; export class LocalProxy { localProxyProxyList: ProxyType[] = []; assistantConfig?: AssistantConfig; watch?: boolean; watching?: boolean; initing?: boolean; constructor(opts?: LocalProxyOpts) { this.assistantConfig = opts?.assistantConfig; if (this.assistantConfig) { this.watch = !!this.assistantConfig.getCacheAssistantConfig()?.watch.enabled; this.init(); console.log('init local proxy', this.assistantConfig.getAppList); if (this.watch) { this.onWatch(); } } } init() { const frontAppDir = this.assistantConfig.configPath?.pagesDir; if (frontAppDir) { if (this.initing) { return; } this.initing = true; 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; this.initing = false; } } onWatch() { // 监听文件变化 const frontAppDir = this.assistantConfig.configPath?.pagesDir; const that = this; if (!this.watch && !frontAppDir) { return; } if (this.watching) { return; } that.watching = true; let timer: NodeJS.Timeout; const debounce = (fn: () => void, delay: number) => { if (timer) { clearTimeout(timer); } timer = setTimeout(() => { fn(); logger.info('reload local proxy'); }, delay); }; fs.watch(frontAppDir, { recursive: true }, (eventType, filename) => { if (eventType === 'rename' || eventType === 'change') { const filePath = path.join(frontAppDir, filename); try { const stat = fs.statSync(filePath); if (stat.isDirectory() || filename.endsWith('.html')) { // 重新加载 debounce(that.init.bind(that), 5 * 1000); } } catch (error) {} } }); } getLocalProxyList() { return this.localProxyProxyList; } reload() { this.init(); } }