@hestjs/core
Version:
HestJS Core Framework - A TypeScript framework built on Hono with dependency injection and decorators
205 lines • 7.38 kB
JavaScript
;
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