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.
 
 
 
 

100 lines
3.8 KiB

import fs from "fs"
import path from "path"
import { logger } from "@/logger.js"
import compose from "koa-compose"
import { Next, ParameterizedContext } from "koa"
async function scanControllers(rootDir: string) {
const routers = []
const stack: string[] = [rootDir]
while (stack.length) {
const dir = stack.pop()
if (!dir) continue
let files
try {
files = fs.readdirSync(dir)
} catch (error: any) {
logger.error(`[控制器注册] ❌ 读取目录失败 ${dir}: ${error.message}`)
continue
}
for (const file of files) {
if (file.startsWith("_")) continue
const fullPath = path.join(dir, file)
let stat
try {
stat = fs.statSync(fullPath)
} catch (error: any) {
logger.error(`[控制器注册] ❌ 读取文件信息失败 ${fullPath}: ${error.message}`)
continue
}
if (stat.isDirectory()) {
stack.push(fullPath)
continue
}
if (!fullPath.replace(/\\/g, "/").includes("/controller/")) continue
let fileName = fullPath.replace(rootDir + path.sep, "")
try {
const controllerModule = await import(fullPath)
const controller = controllerModule.default || controllerModule
if (!controller) {
logger.warn(`[控制器注册] ${fileName} - 缺少默认导出,跳过注册`)
continue
}
let routesFactory = controller.createRoutes || controller.default?.createRoutes || controller.default || controller
if (typeof routesFactory === "function") {
routesFactory = routesFactory.bind(controller)
}
if (typeof routesFactory !== "function") {
logger.warn(`[控制器注册] ⚠️ ${fileName} - 未找到 createRoutes 方法或导出对象`)
continue
}
let routerResult
try {
routerResult = routesFactory()
} catch (error: any) {
logger.error(`[控制器注册] ❌ ${fileName} - createRoutes() 执行失败: ${error.message}`)
continue
}
const list = Array.isArray(routerResult) ? routerResult : [routerResult]
let added = 0
for (const r of list) {
if (r && typeof r.middleware === "function") {
routers.push(r)
added++
} else {
logger.warn(`[控制器注册] ⚠️ ${fileName} - createRoutes() 返回的部分路由器对象无效`)
}
}
if (added > 0) logger.debug(`[控制器注册] ✅ ${fileName} - 创建成功 (${added})`)
} catch (importError: any) {
logger.error(`[控制器注册] ❌ ${fileName} - 模块导入失败: ${importError.message}`)
logger.error(importError)
}
}
}
return routers
}
export default async function (options: { root: string, handleBeforeEachRequest: Function }) {
const { root, handleBeforeEachRequest } = options
if (!root) {
throw new Error("controller root is required")
}
const routers = await scanControllers(root)
const allRouters: any[] = []
for (let i = 0; i < routers.length; i++) {
const router = routers[i]
allRouters.push(router.middleware((options = {}) => handleBeforeEachRequest(options)))
}
return async function (ctx: ParameterizedContext, next: Next) {
return await compose(allRouters)(ctx, next)
}
}