diff --git a/backend/src/app.ts b/backend/src/app.ts index f3c6d5a..7f2fbc1 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -1,76 +1,146 @@ // filepath: /d:/code/CloudDiskDown/backend/src/app.ts import "./types/express"; -import express from "express"; +import express, { Application } from "express"; import cors from "cors"; import cookieParser from "cookie-parser"; +import { QueryTypes } from "sequelize"; + +// 路由和中间件导入 import routes from "./routes/api"; import { errorHandler } from "./middleware/errorHandler"; -import sequelize from "./config/database"; import { authMiddleware } from "./middleware/auth"; + +// 数据库和服务相关 +import sequelize from "./config/database"; import GlobalSetting from "./models/GlobalSetting"; import Searcher from "./services/Searcher"; -const app = express(); +// 常量配置 +const PUBLIC_ROUTES = ["/user/login", "/user/register"]; +const IMAGE_PATH = "tele-images"; +const DEFAULT_PORT = 8009; -app.use( - cors({ - origin: "*", - credentials: true, - methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], - allowedHeaders: ["Content-Type", "Authorization", "Cookie"], - }) -); - -app.use(cookieParser()); -app.use(express.json()); - -// 应用 token 验证中间件,排除登录和注册接口 -app.use((req, res, next) => { - if ( - req.path === "/user/login" || - req.path === "/user/register" || - req.path.includes("tele-images") - ) { - return next(); - } - authMiddleware(req, res, next); -}); - -app.use("/", routes); - -const initializeGlobalSettings = async (): Promise => { - const settings = await GlobalSetting.findOne(); - if (!settings) { - await GlobalSetting.create({ - httpProxyHost: "127.0.0.1", - httpProxyPort: 7890, - isProxyEnabled: true, - CommonUserCode: 9527, - AdminUserCode: 230713, - }); - console.log("Global settings initialized with default values."); - } - await Searcher.updateAxiosInstance(); +// 全局设置默认值 +const DEFAULT_GLOBAL_SETTINGS = { + httpProxyHost: "127.0.0.1", + httpProxyPort: 7890, + isProxyEnabled: false, + CommonUserCode: 9527, + AdminUserCode: 230713, }; -// 错误处理 -app.use(errorHandler); +class App { + private app: Application; -const PORT = process.env.PORT || 8009; + constructor() { + this.app = express(); + this.setupMiddlewares(); + this.setupRoutes(); + this.setupErrorHandling(); + } -// 在同步前禁用外键约束,同步后重新启用 -sequelize - .query("PRAGMA foreign_keys = OFF") // 禁用外键 - .then(() => sequelize.sync({ alter: true })) - .then(() => sequelize.query("PRAGMA foreign_keys = ON")) // 重新启用外键 - .then(() => { - app.listen(PORT, async () => { - await initializeGlobalSettings(); - console.log(`Server is running on port ${PORT}`); + private setupMiddlewares(): void { + // CORS 配置 + this.app.use( + cors({ + origin: "*", + credentials: true, + methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allowedHeaders: ["Content-Type", "Authorization", "Cookie"], + }) + ); + + this.app.use(cookieParser()); + this.app.use(express.json()); + + // 身份验证中间件 + this.app.use((req, res, next) => { + if (PUBLIC_ROUTES.includes(req.path) || req.path.includes(IMAGE_PATH)) { + return next(); + } + authMiddleware(req, res, next); }); - }) - .catch((error) => { - console.error("Database sync failed:", error); - }); + } -export default app; + private setupRoutes(): void { + this.app.use("/", routes); + } + + private setupErrorHandling(): void { + this.app.use(errorHandler); + } + + private async initializeGlobalSettings(): Promise { + try { + const settings = await GlobalSetting.findOne(); + if (!settings) { + await GlobalSetting.create(DEFAULT_GLOBAL_SETTINGS); + console.log("✅ Global settings initialized with default values."); + } + await Searcher.updateAxiosInstance(); + } catch (error) { + console.error("❌ Failed to initialize global settings:", error); + throw error; + } + } + + private async cleanupBackupTables(): Promise { + try { + // 查询所有以 '_backup' 结尾的备份表 + const backupTables = await sequelize.query<{ name: string }>( + "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '%\\_backup%' ESCAPE '\\'", + { type: QueryTypes.SELECT } + ); + + // 逐个删除备份表 + for (const table of backupTables) { + if (table?.name) { + await sequelize.query(`DROP TABLE IF EXISTS ${table.name}`); + console.log(`✅ Cleaned up backup table: ${table.name}`); + } + } + } catch (error) { + console.error("❌ Failed to cleanup backup tables:", error); + throw error; + } + } + + public async start(): Promise { + try { + // 数据库初始化流程 + await sequelize.query("PRAGMA foreign_keys = OFF"); + console.log("📝 Foreign keys disabled for initialization..."); + + await this.cleanupBackupTables(); + console.log("🧹 Backup tables cleaned up"); + + await sequelize.sync({ alter: true }); + console.log("📚 Database schema synchronized"); + + await sequelize.query("PRAGMA foreign_keys = ON"); + console.log("🔐 Foreign keys re-enabled"); + + // 启动服务器 + const port = process.env.PORT || DEFAULT_PORT; + this.app.listen(port, async () => { + await this.initializeGlobalSettings(); + console.log(` +🚀 Server is running on port ${port} +🔧 Environment: ${process.env.NODE_ENV || "development"} + `); + }); + } catch (error) { + console.error("❌ Failed to start server:", error); + process.exit(1); + } + } +} + +// 创建并启动应用 +const application = new App(); +application.start().catch((error) => { + console.error("❌ Application failed to start:", error); + process.exit(1); +}); + +export default application; diff --git a/backend/src/utils/axiosInstance.ts b/backend/src/utils/axiosInstance.ts index 3626a26..09f7bba 100644 --- a/backend/src/utils/axiosInstance.ts +++ b/backend/src/utils/axiosInstance.ts @@ -13,7 +13,6 @@ export function createAxiosInstance( proxyConfig?: ProxyConfig ): AxiosInstance { let agent; - console.log(proxyConfig); if (useProxy && proxyConfig) { agent = tunnel.httpsOverHttp({ proxy: proxyConfig,