117 lines
3.5 KiB
TypeScript
117 lines
3.5 KiB
TypeScript
import * as fs from "fs";
|
||
import * as path from "path";
|
||
import {
|
||
saveRoutesToDb,
|
||
loadRoutesFromDb,
|
||
loadServerConfig,
|
||
saveServerConfig,
|
||
loadIpRulesFromDb,
|
||
} from "./db";
|
||
import { getActiveRoutes } from "./route-matching";
|
||
import { state } from "./state";
|
||
import type { AppConfig, RouteApiNameMap, RouteEnabledMap } from "./types";
|
||
|
||
// 验证mock文件是否存在
|
||
export function validateMockFiles(): void {
|
||
console.log(`[CONFIG] 验证mock文件...`);
|
||
const missingFiles: Array<{
|
||
route: string;
|
||
filePath: string;
|
||
fullPath: string;
|
||
}> = [];
|
||
|
||
const activeRoutes = getActiveRoutes();
|
||
for (const [route, filePath] of Object.entries(activeRoutes)) {
|
||
const fullPath = path.join(__dirname, "..", filePath);
|
||
if (!fs.existsSync(fullPath)) {
|
||
missingFiles.push({ route, filePath, fullPath });
|
||
console.warn(
|
||
`[CONFIG] 警告: mock文件不存在 - ${filePath} (用于路由: ${route})`,
|
||
);
|
||
}
|
||
}
|
||
|
||
if (missingFiles.length > 0) {
|
||
console.log(
|
||
`[CONFIG] 缺少 ${missingFiles.length} 个mock文件,请创建这些文件`,
|
||
);
|
||
} else {
|
||
console.log(`[CONFIG] 所有mock文件验证通过`);
|
||
}
|
||
}
|
||
|
||
// 从 SQLite 加载全部配置
|
||
export async function loadConfig(): Promise<void> {
|
||
try {
|
||
state.config = await loadServerConfig();
|
||
|
||
const dbMappings = await loadRoutesFromDb();
|
||
state.rawRoutes = dbMappings.routes;
|
||
state.rawRouteStatuses = dbMappings.routeStatuses;
|
||
state.routeEnabledMap = dbMappings.routeEnabledMap;
|
||
state.routeApiNameMap = dbMappings.routeApiNameMap;
|
||
|
||
state.ipRules = await loadIpRulesFromDb();
|
||
|
||
const activeCount = Object.values(state.routeEnabledMap).filter(
|
||
(v) => v !== false,
|
||
).length;
|
||
console.log(
|
||
`[CONFIG] 配置已加载(路由 ${activeCount} 条)${state.config.mockEnabled !== false ? "" : "(mock 已关闭,全部走代理)"}`,
|
||
);
|
||
|
||
validateMockFiles();
|
||
} catch (error) {
|
||
console.error(`[CONFIG] 加载配置失败:`, error);
|
||
state.rawRoutes = {};
|
||
state.rawRouteStatuses = {};
|
||
state.routeEnabledMap = {};
|
||
state.routeApiNameMap = {};
|
||
state.ipRules = [];
|
||
state.config = {
|
||
cacheConfig: true,
|
||
reloadOnChange: true,
|
||
defaultContentType: "application/json",
|
||
proxyPort: 8879,
|
||
targetHost: "localhost",
|
||
targetPort: 80,
|
||
targetHttps: false,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 保存服务器配置到 SQLite
|
||
export async function saveConfig(nextConfig: AppConfig): Promise<void> {
|
||
await saveServerConfig(nextConfig);
|
||
state.config = nextConfig;
|
||
}
|
||
|
||
// 保存路由配置到 SQLite 并刷新内存
|
||
export async function saveRoutes(
|
||
routes: Record<string, string>,
|
||
routeStatuses: Record<string, number>,
|
||
routeEnabledMap: RouteEnabledMap = {},
|
||
routeApiNameMap: RouteApiNameMap = {},
|
||
): Promise<void> {
|
||
await saveRoutesToDb(routes, routeStatuses, routeEnabledMap, routeApiNameMap);
|
||
const dbMappings = await loadRoutesFromDb();
|
||
state.rawRoutes = dbMappings.routes;
|
||
state.rawRouteStatuses = dbMappings.routeStatuses;
|
||
state.routeEnabledMap = dbMappings.routeEnabledMap;
|
||
state.routeApiNameMap = dbMappings.routeApiNameMap;
|
||
}
|
||
|
||
// 重新从 SQLite 加载全部配置
|
||
export async function reloadConfig(): Promise<void> {
|
||
const oldCount = Object.values(state.routeEnabledMap).filter(
|
||
(v) => v !== false,
|
||
).length;
|
||
await loadConfig();
|
||
const newCount = Object.values(state.routeEnabledMap).filter(
|
||
(v) => v !== false,
|
||
).length;
|
||
console.log(
|
||
`[CONFIG] 配置重载完成 (路由数: ${oldCount} -> ${newCount})`,
|
||
);
|
||
}
|