You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
5.3 KiB
115 lines
5.3 KiB
// 自动扫描 controllers 目录并注册路由
|
|
// 兼容传统 routes 方式和自动注册 controller 方式
|
|
import fs from "fs"
|
|
import path from "path"
|
|
import { logger } from "@/logger.js"
|
|
|
|
// 保证不会被摇树(tree-shaking),即使在生产环境也会被打包
|
|
if (import.meta.env.PROD) {
|
|
// 通过引用返回值,防止被摇树优化
|
|
let controllers = import.meta.glob("../controllers/**/*Controller.js", { eager: true })
|
|
controllers = null
|
|
console.log(controllers);
|
|
}
|
|
|
|
/**
|
|
* 自动扫描 controllers 目录,注册所有导出的路由
|
|
* 自动检测 routes 目录下已手动注册的 controller,避免重复注册
|
|
* @param {Koa} app - Koa 实例
|
|
* @param {string} controllersDir - controllers 目录路径
|
|
* @param {string} prefix - 路由前缀
|
|
* @param {Set<string>} [manualControllers] - 可选,手动传入已注册 controller 文件名集合,优先于自动扫描
|
|
*/
|
|
export function autoRegisterControllers(app, controllersDir) {
|
|
let allRouter = []
|
|
|
|
function scan(dir, routePrefix = "") {
|
|
try {
|
|
for (const file of fs.readdirSync(dir)) {
|
|
const fullPath = path.join(dir, file)
|
|
const stat = fs.statSync(fullPath)
|
|
|
|
if (stat.isDirectory()) {
|
|
scan(fullPath, routePrefix + "/" + file)
|
|
} else if (file.endsWith("Controller.js")) {
|
|
try {
|
|
// 使用同步的import方式,确保ES模块兼容性
|
|
const controllerModule = require(fullPath)
|
|
const controller = controllerModule.default || controllerModule
|
|
|
|
if (!controller) {
|
|
logger.warn(`[控制器注册] ${file} - 缺少默认导出,跳过注册`)
|
|
continue
|
|
}
|
|
|
|
const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller
|
|
|
|
if (typeof routes === "function") {
|
|
try {
|
|
const router = routes()
|
|
if (router && typeof router.middleware === "function") {
|
|
allRouter.push(router)
|
|
logger.info(`[控制器注册] ✅ ${file} - 路由创建成功`)
|
|
} else {
|
|
logger.warn(`[控制器注册] ⚠️ ${file} - createRoutes() 返回的不是有效的路由器对象`)
|
|
}
|
|
} catch (error) {
|
|
logger.error(`[控制器注册] ❌ ${file} - createRoutes() 执行失败: ${error.message}`)
|
|
}
|
|
} else {
|
|
logger.warn(`[控制器注册] ⚠️ ${file} - 未找到 createRoutes 方法或导出对象`)
|
|
}
|
|
} catch (importError) {
|
|
logger.error(`[控制器注册] ❌ ${file} - 模块导入失败: ${importError.message}`)
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
logger.error(`[控制器注册] ❌ 扫描目录失败 ${dir}: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
try {
|
|
scan(controllersDir)
|
|
|
|
if (allRouter.length === 0) {
|
|
logger.warn("[路由注册] ⚠️ 未发现任何可注册的控制器")
|
|
return
|
|
}
|
|
|
|
logger.info(`[路由注册] 📋 发现 ${allRouter.length} 个控制器,开始注册到应用`)
|
|
|
|
// 按顺序注册路由,确保中间件执行顺序
|
|
for (let i = 0; i < allRouter.length; i++) {
|
|
const router = allRouter[i]
|
|
try {
|
|
app.use(router.middleware())
|
|
logger.debug(`[路由注册] 🔗 路由 ${i + 1}/${allRouter.length} 注册成功`)
|
|
|
|
// 枚举并紧凑输出该路由器下的所有路由方法与路径(单行聚合)
|
|
const methodEntries = Object.entries(router.routes || {})
|
|
const items = []
|
|
for (const [method, list] of methodEntries) {
|
|
if (!Array.isArray(list) || list.length === 0) continue
|
|
for (const r of list) {
|
|
if (!r || !r.path) continue
|
|
items.push(`${method.toUpperCase()} ${r.path}`)
|
|
}
|
|
}
|
|
if (items.length > 0) {
|
|
const prefix = router.options && router.options.prefix ? router.options.prefix : ""
|
|
logger.info(`[路由注册] ✅ ${prefix || "/"} 共 ${items.length} 条 -> ${items.join("; ")}`)
|
|
} else {
|
|
logger.warn(`[路由注册] ⚠️ 该控制器未包含任何可用路由`)
|
|
}
|
|
} catch (error) {
|
|
logger.error(`[路由注册] ❌ 路由 ${i + 1}/${allRouter.length} 注册失败: ${error.message}`)
|
|
}
|
|
}
|
|
|
|
logger.info(`[路由注册] ✅ 完成!成功注册 ${allRouter.length} 个控制器路由`)
|
|
|
|
} catch (error) {
|
|
logger.error(`[路由注册] ❌ 自动注册过程中发生严重错误: ${error.message}`)
|
|
}
|
|
}
|
|
|