UNPKG

@hestjs/core

Version:

HestJS Core Framework - A TypeScript framework built on Hono with dependency injection and decorators

205 lines 7.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RouterExplorer = void 0; const logger_1 = require("@hestjs/logger"); const metadata_scanner_1 = require("../metadata/metadata-scanner"); const constants_1 = require("../utils/constants"); const logger = (0, logger_1.createLogger)("Router"); /** * 路由资源管理器 */ class RouterExplorer { app; container; constructor(app, container) { this.app = app; this.container = container; } /** * 探索并注册控制器路由 */ explore(controllers) { controllers.forEach((controller) => { this.exploreController(controller); }); } /** * 探索单个控制器 */ exploreController(controllerClass) { const controllerMetadata = metadata_scanner_1.MetadataScanner.scanController(controllerClass); if (!controllerMetadata) { throw new Error(`Controller metadata not found for ${controllerClass.name}`); } const routes = metadata_scanner_1.MetadataScanner.scanRoutes(controllerClass); const controllerInstance = this.container.resolve(controllerClass); routes.forEach((route) => { this.registerRoute(controllerInstance, controllerMetadata.path, route); }); } /** * 注册单个路由 */ registerRoute(controllerInstance, controllerPath, route) { const fullPath = this.combinePaths(controllerPath, route.path); const method = route.method.toLowerCase(); // 获取参数元数据 const paramMetadata = metadata_scanner_1.MetadataScanner.scanParameters(controllerInstance.constructor, route.methodName); // 创建路由处理器 const handler = async (c) => { try { // 解析参数 const resolutionResult = await this.resolveParameters(c, paramMetadata); if (resolutionResult.errors && resolutionResult.errors.length > 0) { // 处理参数解析错误 throw new Error(`Parameter resolution failed: ${resolutionResult.errors.map((e) => e.error).join(", ")}`); } // 执行控制器方法 const result = await controllerInstance[route.methodName](...resolutionResult.args); // 返回结果 if (typeof result === "object" && result !== null) { return c.json(result); } else if (typeof result === "string") { return c.text(result); } else { return c.json({ data: result }); } } catch (error) { // 直接抛出异常,由用户的Hono中间件处理 throw error; } }; // 注册到 Hono switch (method) { case "get": this.app.get(fullPath, handler); break; case "post": this.app.post(fullPath, handler); break; case "put": this.app.put(fullPath, handler); break; case "delete": this.app.delete(fullPath, handler); break; case "patch": this.app.patch(fullPath, handler); break; case "options": this.app.options(fullPath, handler); break; case "head": this.app.on(method.toUpperCase(), fullPath, handler); break; default: throw new Error(`Unsupported HTTP method: ${method}`); } logger.info(`${getRouteEmoji(route.method, fullPath)} Mapped {${fullPath}, ${route.method}}`); } /** * 解析方法参数 */ async resolveParameters(c, paramMetadata) { const args = []; const errors = []; // 按参数索引排序 const sortedParams = paramMetadata.sort((a, b) => a.index - b.index); for (const param of sortedParams) { let value; try { switch (param.type) { case constants_1.ParamType.BODY: try { value = await c.req.json(); } catch { value = await c.req.text(); } break; case constants_1.ParamType.PARAM: value = param.key ? c.req.param(param.key) : c.req.param(); break; case constants_1.ParamType.QUERY: value = param.key ? c.req.query(param.key) : c.req.query(); break; case constants_1.ParamType.HEADER: value = param.key ? c.req.header(param.key) : c.req.header(); break; case constants_1.ParamType.REQUEST: value = c.req; break; case constants_1.ParamType.RESPONSE: value = c; break; case constants_1.ParamType.CONTEXT: value = c; break; default: value = undefined; } } catch (error) { errors.push({ parameterIndex: param.index, parameterType: param.type, error: error instanceof Error ? error.message : "Unknown parameter resolution error", }); value = undefined; } args[param.index] = value; } return { args, errors: errors.length > 0 ? errors : undefined }; } /** * 合并路径 */ combinePaths(basePath, routePath) { const base = basePath.replace(/\/$/, ""); const route = routePath.replace(/^\//, ""); if (!route) { return base || "/"; } return `${base}/${route}`; } } exports.RouterExplorer = RouterExplorer; // 辅助函数:根据 HTTP 方法和路径返回对应的 Emoji function getRouteEmoji(method, path) { // 1. 根据 HTTP 方法选择基础 Emoji let emoji; switch (method.toUpperCase()) { case "GET": emoji = "🔍"; // 查询 break; case "POST": emoji = "📩"; // 创建 break; case "PUT": case "PATCH": emoji = "✏️"; // 更新 break; case "DELETE": emoji = "🗑️"; // 删除 break; default: emoji = "🚄"; // 默认(其他方法) } // 2. 根据路径特征调整 Emoji if (path.includes("/auth") || path.includes("/login")) { emoji = "🔐"; // 认证相关 } else if (path.includes("/error")) { emoji = "⚠️ "; // 错误路由 } else if (path.includes(":id")) { emoji = "🆔"; // 动态 ID 路由 } return emoji; } //# sourceMappingURL=router-explorer.js.map