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.
 

70 lines
3.0 KiB

// 自动扫描 controllers 目录并注册路由
// 兼容传统 routes 方式和自动注册 controller 方式
import fs from "fs"
import path from "path"
/**
* 自动扫描 controllers 目录,注册所有导出的路由
* 自动检测 routes 目录下已手动注册的 controller,避免重复注册
* @param {Koa} app - Koa 实例
* @param {string} controllersDir - controllers 目录路径
* @param {string} prefix - 路由前缀
* @param {Set<string>} [manualControllers] - 可选,手动传入已注册 controller 文件名集合,优先于自动扫描
*/
export function autoRegisterControllers(app, controllersDir = path.resolve(__dirname, "../controllers")) {
let allRouter = []
async function scan(dir, routePrefix = "") {
for (const file of fs.readdirSync(dir)) {
const fullPath = path.join(dir, file)
const stat = fs.statSync(fullPath)
if (stat.isDirectory()) {
await scan(fullPath, routePrefix + "/" + file)
} else if (file.endsWith("Controller.js")) {
let controller
try {
controller = require(fullPath)
} catch (e) {
controller = (await import(fullPath)).default
}
const routes = controller.createRoutes || controller.default?.createRoutes || controller.default || controller
if (typeof routes === "function") {
allRouter.push(routes())
}
}
}
}
;(async () => {
await scan(controllersDir)
// TODO: 存在问题:每个Controller都是有顺序的,如果其中一个Controller没有next方法,可能会导致后续的Controller无法执行
allRouter.forEach(router => {
app.use(router.middleware())
})
// // 聚合中间件:只分发到匹配的router
// app.use(async (ctx, next) => {
// let matched = false
// for (const router of allRouter) {
// // router._matchRoute 只在 router.js 内部,需暴露或用 middleware 包一层
// if (typeof router._matchRoute === "function") {
// const route = router._matchRoute(ctx.method.toLowerCase(), ctx.path)
// if (route) {
// matched = true
// await router.middleware()(ctx, next)
// break // 命中一个即停止
// }
// } else {
// // fallback: 直接尝试middleware,若未命中会自动next
// const before = ctx.status
// await router.middleware()(ctx, next)
// if (ctx.status !== before) {
// matched = true
// break
// }
// }
// }
// if (!matched) {
// await next()
// }
// })
})()
}