UNPKG

typenexus

Version:

TypeNexus is a good tool for API encapsulation and management. It provides a clean and lightweight way to package TypeORM functionality, helping you build applications faster while reducing template code redundancy and type conversion work.

87 lines (83 loc) 3.28 kB
import { MetadataBuilder } from './builder/MetadataBuilder.js'; import { Driver } from './Driver.js'; import { TypeNexusOptions } from './DriverOptions.js'; import { ActionMetadata } from './metadata/ActionMetadata.js'; import { Action } from './Action.js'; import { isPromiseLike } from './utils/isPromiseLike.js'; import { ActionParameterHandler } from './ActionParameterHandler.js'; export class Controllers<T extends Driver> { /** * Used to build metadata objects for controllers and middlewares. */ private metadataBuilder: MetadataBuilder; /** * Used to check and handle controller action parameters. */ private parameterHandler: ActionParameterHandler<T>; constructor(private driver: T, private options: TypeNexusOptions) { this.parameterHandler = new ActionParameterHandler<T>(driver); this.metadataBuilder = new MetadataBuilder(this.options); } registerControllers(classes?: Function[]): this { const controllers = this.metadataBuilder.buildControllerMetadata(classes); controllers.map((controller) => { controller.actions.forEach((actionMetadata) => { this.driver.registerAction(actionMetadata, (action) => { this.executeAction(actionMetadata, action); }); }); }); return this; } /** * Registers middleware that run before controller actions. */ registerMiddlewares(type: 'before' | 'after', classes: Function[], option: TypeNexusOptions): this { this.metadataBuilder .buildMiddlewareMetadata(classes) .filter((middleware) => middleware.global && middleware.type === type) .sort((middleware1, middleware2) => middleware2.priority - middleware1.priority) .forEach((middleware) => this.driver.registerMiddleware(middleware, option)); return this; } /** * Executes given controller action. */ protected executeAction(actionMetadata: ActionMetadata, action: Action) { // compute all parameters const paramsPromises = actionMetadata.params .sort((param1, param2) => param1.index - param2.index) .map((param) => { return this.parameterHandler.handle(action, param); }); // compute all constructor parameters const paramsConstructor = actionMetadata.paramsConstructor .sort((param1, param2) => param1.index - param2.index) .map((param) => this.parameterHandler.handleConstructor(action, param)) .filter(Boolean); return Promise.all(paramsPromises) .then((params) => { const result = actionMetadata.callMethod(params, paramsConstructor, action); return this.handleCallMethodResult(result, actionMetadata, action); }) .catch((error) => { return this.driver.handleError(error, actionMetadata, action); }); } /** * Handles result of the action method execution. */ protected handleCallMethodResult(result: any, action: ActionMetadata, options: Action): any { if (isPromiseLike(result)) { return result .then((data) => { return this.handleCallMethodResult(data, action, options); }) .catch((error) => { return this.driver.handleError(error, action, options); }); } else { return this.driver.handleSuccess(result, action, options); } } }