UNPKG

@eggjs/controller-decorator

Version:

tegg controller decorator

144 lines 16 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.WebSocketFetchControllerMethodMetaBuilder = void 0; const node_path_1 = __importDefault(require("node:path")); const tegg_metadata_1 = require("@eggjs/tegg-metadata"); const tegg_types_1 = require("@eggjs/tegg-types"); const model_1 = require("../../model"); const MethodValidator_1 = require("../../util/validator/MethodValidator"); const MethodInfoUtil_1 = __importDefault(require("../../util/MethodInfoUtil")); const HTTPPriorityUtil_1 = require("../../util/HTTPPriorityUtil"); const WebSocketInfoUtil_1 = __importDefault(require("../../util/WebSocketInfoUtil")); class WebSocketFetchControllerMethodMetaBuilder { constructor(clazz, methodName) { this.clazz = clazz; this.methodName = methodName; } checkParamDecorators(methodType) { const method = this.clazz.prototype[this.methodName]; const functionLength = method.length; const paramIndexList = WebSocketInfoUtil_1.default.getCompatibleParamIndexList(this.clazz, this.methodName); const contextIndex = MethodInfoUtil_1.default.getMethodContextIndex(this.clazz, this.methodName); const hasAnnotationParamCount = typeof contextIndex === 'undefined' ? paramIndexList.length : paramIndexList.length + 1; const maxParamCount = Math.max(functionLength, hasAnnotationParamCount); for (let i = 0; i < maxParamCount; ++i) { if (i === contextIndex) { continue; } const paramType = WebSocketInfoUtil_1.default.getCompatibleMethodParamType(i, this.clazz, this.methodName); if (!paramType) { const classDesc = tegg_metadata_1.ClassUtil.classDescription(this.clazz); throw new Error(`${classDesc}:${this.methodName} param ${i} has no websocket fetch param type, Please add @WebSocketData, @WebSocketClose, @WebSocketError, @WebSocketCloseCode, @WebSocketCloseReason, @HTTPParam, @HTTPQuery, @HTTPQueries, @HTTPHeaders, @Request, @WebSocketSocket or @Context`); } if (!this.isAllowedParamType(methodType, paramType)) { const classDesc = tegg_metadata_1.ClassUtil.classDescription(this.clazz); throw new Error(`${classDesc}:${this.methodName} param ${i} type ${paramType} is not allowed in websocket fetch ${methodType} method`); } } } isAllowedParamType(methodType, paramType) { if (paramType === tegg_types_1.WebSocketParamType.STREAM) { return false; } if (this.isCommonParamType(paramType)) { return true; } if (paramType === tegg_types_1.WebSocketParamType.CLOSE) { return methodType !== tegg_types_1.WebSocketFetchMethodType.CLOSE; } switch (methodType) { case tegg_types_1.WebSocketFetchMethodType.DATA: { return paramType === tegg_types_1.WebSocketParamType.DATA; } case tegg_types_1.WebSocketFetchMethodType.ERROR: { return paramType === tegg_types_1.WebSocketParamType.ERROR; } case tegg_types_1.WebSocketFetchMethodType.CLOSE: { return paramType === tegg_types_1.WebSocketParamType.CLOSE_CODE || paramType === tegg_types_1.WebSocketParamType.CLOSE_REASON; } case tegg_types_1.WebSocketFetchMethodType.CONNECTION: case tegg_types_1.WebSocketFetchMethodType.OPEN: { return false; } default: return false; } } isCommonParamType(paramType) { return paramType === tegg_types_1.WebSocketParamType.PARAM || paramType === tegg_types_1.WebSocketParamType.QUERY || paramType === tegg_types_1.WebSocketParamType.QUERIES || paramType === tegg_types_1.WebSocketParamType.HEADERS || paramType === tegg_types_1.WebSocketParamType.REQUEST || paramType === tegg_types_1.WebSocketParamType.SOCKET; } buildParamType(webSocketPath, methodType) { this.checkParamDecorators(methodType); const paramTypeMap = new Map(); const paramIndexList = WebSocketInfoUtil_1.default.getCompatibleParamIndexList(this.clazz, this.methodName); for (const paramIndex of paramIndexList) { const paramType = WebSocketInfoUtil_1.default.getCompatibleMethodParamType(paramIndex, this.clazz, this.methodName); const paramName = WebSocketInfoUtil_1.default.getCompatibleMethodParamName(paramIndex, this.clazz, this.methodName); const paramMeta = model_1.WebSocketParamMetaUtil.createParam(paramType, paramName); if (methodType === tegg_types_1.WebSocketFetchMethodType.DATA) { try { paramMeta.validate(webSocketPath); } catch (e) { const classDesc = tegg_metadata_1.ClassUtil.classDescription(this.clazz); e.message = `build websocket fetch controller ${classDesc} method ${this.methodName} param ${paramName} failed: ${e.message}`; throw e; } } paramTypeMap.set(paramIndex, paramMeta); } return paramTypeMap; } getPriority() { const priority = WebSocketInfoUtil_1.default.getWebSocketMethodPriority(this.clazz, this.methodName); if (priority !== undefined) { return priority; } const controllerPath = WebSocketInfoUtil_1.default.getWebSocketPath(this.clazz); const methodPath = WebSocketInfoUtil_1.default.getWebSocketMethodPath(this.clazz, this.methodName) || ''; const realPath = controllerPath ? node_path_1.default.posix.join(controllerPath, methodPath) : methodPath; const defaultPriority = HTTPPriorityUtil_1.HTTPPriorityUtil.calcPathPriority(realPath); if (defaultPriority > HTTPPriorityUtil_1.HTTPPriorityUtil.DEFAULT_PRIORITY) { throw new Error(`path ${realPath} is too long, should set priority manually`); } return defaultPriority; } build() { MethodValidator_1.MethodValidator.validate(this.clazz, this.methodName); const controllerType = MethodInfoUtil_1.default.getMethodControllerType(this.clazz, this.methodName); if (!controllerType || controllerType !== tegg_types_1.ControllerType.WEBSOCKET_FETCH) { return undefined; } const methodType = WebSocketInfoUtil_1.default.getWebSocketFetchMethodType(this.clazz, this.methodName); if (!methodType) { return undefined; } const parentPath = WebSocketInfoUtil_1.default.getWebSocketPath(this.clazz); const webSocketPath = methodType === tegg_types_1.WebSocketFetchMethodType.DATA ? WebSocketInfoUtil_1.default.getWebSocketMethodPath(this.clazz, this.methodName) || '' : ''; const contextIndex = MethodInfoUtil_1.default.getMethodContextIndex(this.clazz, this.methodName); const middlewares = MethodInfoUtil_1.default.getMethodMiddlewares(this.clazz, this.methodName); const hosts = MethodInfoUtil_1.default.getMethodHosts(this.clazz, this.methodName); const realPath = parentPath ? node_path_1.default.posix.join(parentPath, webSocketPath) : webSocketPath; const paramTypeMap = this.buildParamType(realPath, methodType); const priority = methodType === tegg_types_1.WebSocketFetchMethodType.DATA ? this.getPriority() : HTTPPriorityUtil_1.HTTPPriorityUtil.DEFAULT_PRIORITY; const timeout = MethodInfoUtil_1.default.getMethodTimeout(this.clazz, this.methodName); return new model_1.WebSocketFetchMethodMeta(this.methodName, webSocketPath, middlewares, contextIndex, paramTypeMap, priority, hosts, methodType, timeout); } } exports.WebSocketFetchControllerMethodMetaBuilder = WebSocketFetchControllerMethodMetaBuilder; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiV2ViU29ja2V0RmV0Y2hDb250cm9sbGVyTWV0aG9kTWV0YUJ1aWxkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaW1wbC93ZWJzb2NrZXQtZmV0Y2gvV2ViU29ja2V0RmV0Y2hDb250cm9sbGVyTWV0aG9kTWV0YUJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsMERBQTZCO0FBQzdCLHdEQUFpRDtBQUNqRCxrREFBaUc7QUFFakcsdUNBQW1HO0FBQ25HLDBFQUF1RTtBQUN2RSwrRUFBdUQ7QUFDdkQsa0VBQStEO0FBQy9ELHFGQUE2RDtBQUU3RCxNQUFhLHlDQUF5QztJQUlwRCxZQUFZLEtBQXdCLEVBQUUsVUFBa0I7UUFDdEQsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7UUFDbkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7SUFDL0IsQ0FBQztJQUVPLG9CQUFvQixDQUFDLFVBQW9DO1FBQy9ELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNyRCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQ3JDLE1BQU0sY0FBYyxHQUFHLDJCQUFpQixDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2xHLE1BQU0sWUFBWSxHQUFHLHdCQUFjLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdkYsTUFBTSx1QkFBdUIsR0FBRyxPQUFPLFlBQVksS0FBSyxXQUFXO1lBQ2pFLENBQUMsQ0FBQyxjQUFjLENBQUMsTUFBTTtZQUN2QixDQUFDLENBQUMsY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDOUIsTUFBTSxhQUFhLEdBQUcs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