@micro.ts/core
Version:
Microservice framework with Typescript
852 lines (851 loc) • 39.1 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseServer = void 0;
const GlobalMetadata_1 = require("../decorators/GlobalMetadata");
const BaseHelpers_1 = require("../helpers/BaseHelpers");
const Logger_1 = require("./Logger");
const types_1 = require("./types");
const SpecBuilder_1 = require("../openapi/SpecBuilder");
const MainAppErrror_1 = require("../errors/MainAppErrror");
const ParamMetadataTypes_1 = require("../decorators/types/ParamMetadataTypes");
const BaseContainer_1 = require("../di/BaseContainer");
class BaseServer {
constructor(options) {
this.options = options;
this._serverInfo = new Map();
}
get logger() {
return BaseContainer_1.Container.get(Logger_1.LoggerKey);
}
static get controllersMetadata() {
return (0, GlobalMetadata_1.getGlobalMetadata)();
}
/**
* Execute a single middleware and return its result
* @param middleware Middleware function or IMiddleware instance to execute
* @param def Route definition on which the middleware is being called from
* @param action The action object, with the state of the action just before this middleware is being executed
* @param controller The controller instance
* @param broker The broker instance
*/
static executeMiddleware(middleware, def, action, controller, broker, requestModule, send) {
return __awaiter(this, void 0, void 0, function* () {
if (middleware.prototype && 'do' in middleware.prototype) {
const casted = requestModule.get(middleware.prototype.constructor);
return casted.do(action, def, controller, broker, send);
}
return middleware(action, def, controller, broker, send);
});
}
/**
* Execute the error handler and return its result as a boolean
* @param handler Error handler function or IErrorHandler instance
* @param error Error object
* @param action Action object up to the state before the error
* @param def Route definition where the error was thrown
* @param controller The controller instance
* @param broker The broker instance
*/
static executeErrorHandler(handler, error, action, def, controller, broker, requestModule) {
return __awaiter(this, void 0, void 0, function* () {
if (handler.prototype && 'do' in handler.prototype) {
const casted = requestModule.get(handler.prototype.constructor);
return casted.do(error, action, def, controller, broker);
}
return handler(error, action, def, controller, broker);
});
}
/**
* If an error was thrown, the error object will go through all the error handlers sequentially until on of the handlers returns true
* @param handlers List of handlers to execute
* @param error Error object
* @param action Action state on the moment the error was thrown
* @param def Route definition where the error was thrown
* @param controllerInstance The controller instance
* @param broker The broker instance
*/
static handleError(handlers, error, action, def, controllerInstance, broker, requestModule) {
return __awaiter(this, void 0, void 0, function* () {
for (let i = 0; i < handlers.length; i++) {
const result = yield BaseServer.executeErrorHandler(handlers[i], error, action, def, controllerInstance, broker, requestModule);
if (result) {
return true;
}
}
return false;
});
}
executeWithTimeout(def, action, broker, controller, methodControllerMetadata, requestModule) {
return __awaiter(this, void 0, void 0, function* () {
/**
* Get configured timeouts
*/
const baseTimeout = this.options.timeout || 0;
const brokerTimeout = broker.getDefaultTimeout() || 0;
const requestTimeout = def.timeout || 0;
/**
* Get non-zero timeouts and get the minimum timeout
*/
const timeout = (0, BaseHelpers_1.minNonZero)(baseTimeout, brokerTimeout, requestTimeout);
const promises = [
this.handleRequest(def, action, broker, controller, methodControllerMetadata, requestModule),
];
if (timeout) {
promises.push((0, BaseHelpers_1.sleep)(timeout).then(() => {
throw new MainAppErrror_1.TimeoutError('Request timed out');
}));
}
return Promise.race(promises);
});
}
/**
* Execute the request (passing through all the middlewares) and handle errors if thrown any
* @param def Route definition
* @param action Action from the broker
* @param broker Broker instance
*/
executeRequest(def, action, broker) {
return __awaiter(this, void 0, void 0, function* () {
const start = new Date().getTime();
const requestModule = BaseContainer_1.Container.newModule();
requestModule.set(types_1.Action, action);
action.container_module = requestModule;
const controllerInstance = requestModule.get(def.controllerCtor);
const methodControllerMetadata = (0, GlobalMetadata_1.getHandlerMetadata)(def.controllerCtor, def.handlerName);
try {
action = yield this.executeWithTimeout(def, action, broker, controllerInstance, methodControllerMetadata, requestModule);
}
catch (err) {
const error = err;
const errorHandlers = this.getErrorHandlers(methodControllerMetadata);
const handled = yield BaseServer.handleError(errorHandlers, err, action, def, controllerInstance, broker, requestModule);
if (!handled) {
action.response = action.response || {};
action.response.statusCode = Number(error.statusCode) || 500;
action.response.is_error = true;
action.response.error = err;
if (this.options.logErrors &&
action.response.statusCode === 500) {
console.log('Error: ', { error: err, route: def });
}
}
}
/*
* Log the request info if enabled
*/
if (this.options.logRequests) {
// let end = process.hrtime(start);
const end = new Date().getTime() - start;
const seconds = Math.floor(end / 1000);
const millis = end % 1000;
const response = action.response || {};
const statusCode = response.statusCode || 200;
console.log(`[${broker.name}]`, `[${def.method.toUpperCase()}]`, `[${def.controller}]`, `[${def.handlerName}]`, `${action.request.path}`, statusCode === 200 ? `[${statusCode}]` : `[${statusCode}]`, `[${seconds}s ${millis}ms]`);
// console.log(
// chalk.greenBright(`[${broker.name}]`),
// chalk.blueBright(`[${def.method.toUpperCase()}]`),
// chalk.green(`[${def.controller}]`),
// chalk.yellow(`[${def.handlerName}]`),
// `${action.request.path}`,
// statusCode === 200
// ? chalk.blue(`[${statusCode}]`)
// : chalk.red(`[${statusCode}]`),
// chalk.greenBright(`[${seconds}s ${millis}ms]`)
// );
}
return action;
});
}
/**
* Checks if the action for the handler handler needs to pass through authorizationChecker function,
* And executes the the authorizationChecker function, with the corresponding arguments
* @param action Action object at the time of invocation
* @param methodMetadata Metadata for the handler to check if the request should get filtered by authorization checker
*/
checkAuthorization(action, methodMetadata) {
return __awaiter(this, void 0, void 0, function* () {
let shouldCheck = false;
if (methodMetadata.controller.authorize) {
shouldCheck = true;
}
if (methodMetadata.method.authorize === false) {
shouldCheck = false;
}
else if (methodMetadata.method.authorize === true) {
shouldCheck = true;
}
if (shouldCheck && this.options.authorizationChecker) {
const options = methodMetadata.method.authorization ||
methodMetadata.controller.authorization ||
{};
const authorized = yield this.options.authorizationChecker(action, options);
if (!authorized) {
if (this.options.getNotAuthorizedError) {
const error = yield this.options.getNotAuthorizedError(action, options);
throw error;
}
throw new MainAppErrror_1.NotAuthorized('You are not authorized to make this request');
}
}
});
}
/**
* Group an array of middleware options , with the before flag, into to groups, before middlewares and after middlewares
* @param middlewares List of middleware options
*/
groupMiddlewares(middlewares) {
const result = {
before: [],
after: [],
};
middlewares.forEach((m) => {
if (m.before) {
result.before.push(m.middleware);
}
else {
result.after.push(m.middleware);
}
});
return result;
}
/**
* Get all middlewares for a specific handler,
* The sorting of middlewares in this method determines the sequence of the middleware executions
* Before the handler is executed middlewares are executed on this order:
* 1. App before middlewares,
* 2. Controller before middlewares,
* 3. Handler before middlewares
* After the handler is executed after middlewares are executed in this order
* 1. Handler after middlewares
* 2. Controller's after middlewares
* 3. App's after middlewares
* @param methodMetadata
*/
getMiddlewares(methodMetadata) {
const middlewares = {
before: [],
after: [],
};
let afterMiddlewares = [];
/**
* App level before middlewares
*/
if (this.options.beforeMiddlewares &&
this.options.beforeMiddlewares.length > 0) {
middlewares.before.push(...this.options.beforeMiddlewares);
}
/**
* App level after middlwares
*/
if (this.options.afterMiddlewares &&
this.options.afterMiddlewares.length > 0) {
afterMiddlewares.push(this.options.afterMiddlewares);
}
/**
* Controller level middlewares
*/
if (methodMetadata.controller.middlewares &&
methodMetadata.controller.middlewares.length > 0) {
const groupedControllerMiddlewares = this.groupMiddlewares(methodMetadata.controller.middlewares);
/**
* Insert each item to the before middlewares
*/
middlewares.before.push(...groupedControllerMiddlewares.before);
/**
* Insert the whole group to to the after middlwares
*/
afterMiddlewares.push(groupedControllerMiddlewares.after);
}
/**
* Handler level middlwares
*/
if (methodMetadata.method.middlewares &&
methodMetadata.method.middlewares.length > 0) {
const groupedMethodMiddleware = this.groupMiddlewares(methodMetadata.method.middlewares);
/**
* Insert each item to the before middlewares
*/
middlewares.before.push(...groupedMethodMiddleware.before);
/**
* Insert the whole group to to the after middlwares
*/
afterMiddlewares.push(groupedMethodMiddleware.after);
}
// Reverse after middlewares so they go in the order of 1. Handler Middlewares, 2. Controller Middlewares, 3. Global Middlewares
afterMiddlewares = afterMiddlewares.reverse();
afterMiddlewares.forEach((a) => {
middlewares.after.push(...a);
});
return middlewares;
}
/**
* Build error handlers for the route, using first the method error handlers, then controller error handlers, and app-level error handlers
* @param methodMetadata Metadata for the handler
*/
getErrorHandlers(methodMetadata) {
const result = [];
/**
* Handler level error handlers
*/
result.push(...(methodMetadata.method.errorHandlers || []));
/**
* Controller level error handlers
*/
result.push(...(methodMetadata.controller.errorHandlers || []));
/**
* App level error handlers
*/
result.push(...(this.options.errorHandlers || []));
return result;
}
/**
* Handle the before middlewares execution, handler execution, and after middlewares execution
* @param def Route definition
* @param action The action object from the broker
* @param broker The broker instance
* @param controllerInstance The controller instance (needs to be passed into the middlewares)
* @param methodControllerMetadata Handler metadata
*/
handleRequest(def, action, broker, controllerInstance, methodControllerMetadata, requestModule) {
return __awaiter(this, void 0, void 0, function* () {
/**
* If route requires authorization, check it with the authorization function
*/
yield this.checkAuthorization(action, methodControllerMetadata);
/**
* Build middlewares
*/
const middlewares = this.getMiddlewares(methodControllerMetadata);
let broken = false;
const send = (result) => {
broken = true;
action.response = action.response || {};
action.response.headers = action.response.headers || {};
action.response.statusCode = 200;
action.response.body = result;
return action;
};
/**
* Execute before middlewares
*/
if (middlewares.before.length) {
for (let i = 0; i < middlewares.before.length; i++) {
action = yield BaseServer.executeMiddleware(middlewares.before[i], def, action, controllerInstance, broker, requestModule, send);
if (broken) {
break;
}
}
}
if (!broken) {
/**
* Build handler parameters
*/
const args = yield this.buildParams(action, methodControllerMetadata.method, broker, requestModule, def);
/**
* Execute the handler
*/
const result = yield controllerInstance[def.handlerName](...args);
/**
* Build response
*/
action.response = action.response || {};
action.response.headers = action.response.headers || {};
action.response.statusCode = 200;
action.response.body = result;
/**
* Execute after middlewares
*/
if (middlewares.after.length) {
for (let i = 0; i < middlewares.after.length; i++) {
action = yield BaseServer.executeMiddleware(middlewares.after[i], def, action, controllerInstance, broker, requestModule, send);
if (broken) {
break;
}
}
}
/**
* If all are successful execute redirect
*/
if (methodControllerMetadata.method.redirect && !broken) {
action.response = action.response || {};
action.response.headers = action.response.headers || {};
action.response.statusCode = 301;
if (typeof action.response.body === 'string') {
action.response.headers.Location = action.response.body;
}
else if (typeof action.response.body === 'object') {
let unparsedUrl = methodControllerMetadata.method.redirect;
const keys = Object.keys(action.response.body);
keys.forEach((key) => {
const match = new RegExp(`:${key}`, 'gi');
unparsedUrl = unparsedUrl.replace(match, action.response.body[key]);
});
action.response.headers.Location = unparsedUrl;
}
else {
action.response.headers.Location =
methodControllerMetadata.method.redirect;
}
}
}
return action;
});
}
/**
* Build the arguments list for the handler
* @param action Action object
* @param metadata
* @param broker
*/
buildParams(action, metadata, broker, requestModule, def) {
return __awaiter(this, void 0, void 0, function* () {
return Promise.all(metadata.params.map((p) => __awaiter(this, void 0, void 0, function* () {
return this.buildSingleParam(action, p, broker, requestModule, def);
})));
});
}
/**
* Execute currentUserChecker function, to get the user from a request, and inject it if required int the handlers arguments
* @param action Action object with the request
* @param broker Broker instance
*/
getUser(action, broker) {
return __awaiter(this, void 0, void 0, function* () {
if (!this.options.currentUserChecker) {
return null;
}
return this.options.currentUserChecker(action, broker);
});
}
transform(value, description, def, action) {
if (value && this.options.transformerFunction && description.type) {
return this.options.transformerFunction(description.type, value, description, def, action);
}
return value;
}
/**
* Validate a single method argument
* @param value Value of the argument
* @param required If true and value is empty value it throws bad request
* @param validate If true, and the validate function throws it throws bad request
* @param name Key of the value in case is a single key option
* @param type Type of parameter to use in validation
* @param isObject if the value is a key-value object
* @param notEmpty if the value should not be empty
*/
validateParam({ value, required, validate, name, type, isObject, notEmpty, }) {
return __awaiter(this, void 0, void 0, function* () {
if (required && !value) {
throw new MainAppErrror_1.BadRequest(`${name} is required`);
}
if (isObject && notEmpty) {
if (!!value && Object.keys(value).length === 0) {
throw new MainAppErrror_1.BadRequest(`${name} must not be empty`);
}
}
if (validate && !!value && this.options.validateFunction) {
try {
const result = yield this.options.validateFunction(value, type);
return result || value;
}
catch (err) {
const error = err;
throw new MainAppErrror_1.BadRequest('One or more errors with your request', error.details || error.message || error);
}
}
return value;
});
}
/**
* Switches through all the cases of param types and maps the correct information
* @param action Action object after all before middlewares executed
* @param metadata Metadata for the handler
* @param broker Broker instance
*/
buildSingleParam(action, metadata, broker, requestModule, def) {
return __awaiter(this, void 0, void 0, function* () {
if (!metadata.options) {
return action.request.body || action.request.qs || {};
}
else {
const options = metadata.options;
switch (options.decoratorType) {
/**
* Inject the request body
*/
case ParamMetadataTypes_1.ParamDecoratorType.Body:
const body = this.transform(action.request.body, metadata, def, action);
return this.validateParam({
value: body,
required: options.bodyOptions.required || false,
validate: options.bodyOptions.validate || false,
isObject: true,
notEmpty: options.bodyOptions.notEmpty || false,
name: 'body',
type: metadata.type,
});
/**
* Inject only a named field of the body
*/
case ParamMetadataTypes_1.ParamDecoratorType.BodyField:
const bodyField = this.transform(action.request.body[options.name], metadata, def, action);
return this.validateParam({
value: bodyField,
isObject: false,
required: options.bodyParamOptions.required || false,
validate: false,
name: options.name,
});
/**
* Inject the request parameters
*/
case ParamMetadataTypes_1.ParamDecoratorType.Params:
const params = this.transform(action.request.params, metadata, def, action);
return this.validateParam({
value: params,
isObject: true,
required: true,
validate: options.paramOptions.validate || false,
name: 'parameters',
type: metadata.type,
});
/**
* Inject only a named parameter
*/
case ParamMetadataTypes_1.ParamDecoratorType.ParamField:
const paramField = this.transform(action.request.params[options.name], metadata, def, action);
return this.validateParam({
value: paramField || '',
isObject: false,
required: false,
validate: false,
name: options.name,
});
/**
* Inject the request method
*/
case ParamMetadataTypes_1.ParamDecoratorType.Method:
return action.request.method;
/**
* Inject the broker connection
*/
case ParamMetadataTypes_1.ParamDecoratorType.Connection:
return action.connection;
/**
* Inject the full action
*/
case ParamMetadataTypes_1.ParamDecoratorType.Request:
return action;
/**
* Inject the broker's raw request
*/
case ParamMetadataTypes_1.ParamDecoratorType.RawRequest:
return action.request.raw;
/**
* Inject a specified instance from the container
*/
case ParamMetadataTypes_1.ParamDecoratorType.ContainerInject:
return requestModule.get(options.name);
/**
* Inject the broker
*/
case ParamMetadataTypes_1.ParamDecoratorType.Broker:
return broker;
/**
* Inject all the request headers
*/
case ParamMetadataTypes_1.ParamDecoratorType.Header:
const headers = this.transform(action.request.headers, metadata, def, action);
return this.validateParam({
value: headers,
isObject: true,
notEmpty: options.headerOptions.notEmpty || false,
required: options.headerOptions.validate || false,
validate: false,
name: 'headers',
type: metadata.type,
});
/**
* Inject only a named header
*/
case ParamMetadataTypes_1.ParamDecoratorType.HeaderField:
const headerParam = this.transform(action.request.headers[options.name], metadata, def, action);
return this.validateParam({
value: headerParam,
isObject: false,
required: options.headerParamOptions.required || false,
validate: false,
name: options.name,
});
/**
* Inject the request query
*/
case ParamMetadataTypes_1.ParamDecoratorType.Query:
const query = this.transform(action.request.qs, metadata, def, action);
return this.validateParam({
value: query,
isObject: true,
notEmpty: options.queryOptions.notEmpty || false,
required: options.queryOptions.required || false,
validate: options.queryOptions.validate || false,
name: 'query',
type: metadata.type,
});
/**
* Inject only a named query field
*/
case ParamMetadataTypes_1.ParamDecoratorType.QueryField:
const queryParam = this.transform(action.request.qs[options.name], metadata, def, action);
return this.validateParam({
value: queryParam,
isObject: false,
required: options.queryParamOptions.required || false,
validate: false,
name: options.name,
});
/**
* Inject the user object
*/
case ParamMetadataTypes_1.ParamDecoratorType.User:
const user = this.transform(yield this.getUser(action, broker), metadata, def, action);
const required = options.currentUserOptions.required || false;
if (required && !user) {
throw new MainAppErrror_1.NotAuthorized('You are not authorized to access this resource');
}
return user;
}
}
});
}
/**
* Adds route to its corresponding brokers
* @param def Route definition
* @param brokers List of brokers enabled for this handler
* @param params List of parameters required for this handler (to be used when generating API specifications)
*/
addRoute(def, brokers, params) {
return __awaiter(this, void 0, void 0, function* () {
if (this.options.onRouteListeners &&
this.options.onRouteListeners.length) {
this.options.onRouteListeners.forEach((listener) => {
try {
listener(def, brokers, params);
}
catch (_e) {
// ignore
}
});
}
const result = {};
if (brokers && brokers.length) {
for (let i = 0; i < brokers.length; i++) {
const broker = brokers[i];
const name = broker.name;
const route = yield broker.addRoute(def, (action) => {
return this.executeRequest(def, action, broker);
});
result[name] = route;
const brokerServerInfo = this._serverInfo.get(broker) || [];
brokerServerInfo.push({ route, def, params });
this._serverInfo.set(broker, brokerServerInfo);
}
if (this.options.generateSwagger) {
try {
const schemaBuilder = BaseContainer_1.Container.get(SpecBuilder_1.SpecBuilder);
schemaBuilder.registerRoute(def, brokers, params);
}
catch (err) {
console.log(`Error registering route schema!`, {
route: def,
error: err,
});
}
}
}
return result;
});
}
/**
* Registers all routes to the brokers
* Initializes all brokers
*/
start() {
return __awaiter(this, void 0, void 0, function* () {
yield this.buildRoutes();
if (this.options.brokers) {
yield Promise.all(this.options.brokers.map((x) => __awaiter(this, void 0, void 0, function* () {
if (this.options.onBrokerConnnectionError) {
x.setConnectionErrorHandler(this.options.onBrokerConnnectionError);
}
try {
yield x.start();
}
catch (brokerConnectionError) {
if (this.options.onBrokerConnnectionError) {
this.options.onBrokerConnnectionError(x, brokerConnectionError);
}
else {
throw brokerConnectionError;
}
}
})));
this.logger.info('Base Server Started');
}
});
}
get serverInfo() {
return this._serverInfo;
}
/**
* Build route for a single handler
* @param methodName Name of the method
* @param desc Method metadata
* @param basePath Base path of the app
* @param controllerPath Path of the controller
* @param ctor Controller constructor function
* @param isJson Is JsonController
* @param brokers List of brokers enabled for the controller
* @param routes Routes to append to the result
* @param controllerName Name of the controller
*/
buildSingleMethodRoute({ methodName, desc, basePath, controllerPath, ctor, isJson, brokers, routes, controllerName, methodDescriptor, timeout, brokerRouteOptions, }) {
return __awaiter(this, void 0, void 0, function* () {
const metadata = desc.metadata || {};
const methodPath = metadata.path;
let path = methodPath || methodName;
if (methodPath === '') {
path = methodPath;
}
const reqMethod = metadata.method;
const handlerBrokersFilter = metadata.brokers;
let methodBrokers = [...brokers];
if (handlerBrokersFilter) {
methodBrokers = methodBrokers.filter(handlerBrokersFilter);
}
const routeDefinition = {
base: basePath,
controller: controllerPath,
controllerCtor: ctor,
handler: path,
handlerName: methodName,
method: reqMethod || 'get',
queueOptions: metadata.queueOptions,
json: isJson,
timeout: timeout,
methodDescription: methodDescriptor,
brokerRouteOptions,
};
const results = yield this.addRoute(routeDefinition, methodBrokers, desc.params || []);
const brokerNames = methodBrokers
.map((x) => {
return x.name;
})
.join(', ');
routes.push(Object.assign({ brokers: brokerNames, method: (reqMethod || 'get').toUpperCase(), handler: `${controllerName}.${methodName}` }, results));
});
}
/**
* Build routes for a single controller
* @param controllerMetadata Controller metadata
* @param basePath Base path of the app
* @param routes All the routes of the controller
* @param brokers All the brokers filtered for this controller
*/
buildSingleControllerRoute(controllerMetadata, basePath, routes, brokers) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
if (this.options.controllers.includes(controllerMetadata.ctor)) {
const name = controllerMetadata.name;
let options = controllerMetadata.options;
options = options || {};
let controllerBrokers = [...brokers];
/**
* Filter brokers for the controller if annotated with broker filter
*/
if (options.brokersFilter) {
controllerBrokers = controllerBrokers.filter(options.brokersFilter);
}
const cPath = options.path;
const isJson = !!options.json;
const controllerPath = cPath || '';
const handlers = controllerMetadata.handlers;
const controllerTimeout = (controllerMetadata.options &&
controllerMetadata.options.timeout) ||
0;
const controllerBrokerRouteOptions = (_a = controllerMetadata.options) === null || _a === void 0 ? void 0 : _a.brokerRouteOptions;
/**
* Build method handlers
*/
yield Promise.all(Object.keys(handlers).map((key) => __awaiter(this, void 0, void 0, function* () {
var _b;
/**
* Get timeout from controller or method
*/
let timeout = controllerTimeout;
const methodDescriptor = (controllerMetadata.handlers ||
{})[key];
/**
* If it has method timeout configured get the minimum nonzero
*/
if (!!methodDescriptor) {
methodDescriptor.metadata =
methodDescriptor.metadata || {};
const methodTimeout = methodDescriptor.metadata.timeout || 0;
timeout = (0, BaseHelpers_1.minNonZero)(controllerTimeout, methodTimeout);
}
yield this.buildSingleMethodRoute({
methodName: key,
timeout,
desc: (controllerMetadata.handlers || {})[key],
basePath,
controllerPath,
ctor: controllerMetadata.ctor,
isJson,
brokers: controllerBrokers,
routes,
controllerName: name,
methodDescriptor,
brokerRouteOptions: ((_b = methodDescriptor.metadata) === null || _b === void 0 ? void 0 : _b.brokerRouteOptions) ||
controllerBrokerRouteOptions,
});
})));
}
});
}
/**
* Build all the routes for all the app's controllers
* @param controllers Metadata for all registered controllers
*/
buildAllControllers(controllers) {
return __awaiter(this, void 0, void 0, function* () {
const routes = [];
const basePath = this.options.basePath || '';
const brokers = this.options.brokers || [];
yield Promise.all(controllers.map((c) => __awaiter(this, void 0, void 0, function* () {
yield this.buildSingleControllerRoute(c, basePath, routes, brokers);
})));
return routes;
});
}
/**
* Gets all the controllers metadata and build all the routes
* Displays route table on the screen
*/
buildRoutes() {
return __awaiter(this, void 0, void 0, function* () {
const controllers = BaseServer.controllersMetadata.controllers;
const routes = yield this.buildAllControllers(Array.from(controllers.values()));
console.table(routes);
});
}
}
exports.BaseServer = BaseServer;