@eggjs/controller-decorator
Version:
tegg controller decorator
144 lines • 16 kB
JavaScript
"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 , , , , , , , , , , or `);
}
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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