All files / core/router routes-resolver.ts

90.48% Statements 38/42
80% Branches 8/10
80% Functions 8/10
90.48% Lines 38/42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 1111x 1x     1x   1x   1x   1x 1x 1x   1x 6x 6x         6x 6x   6x         6x                   1x 1x 2x     2x 2x                   1x 1x 1x   1x 1x                     1x 1x         1x         1x 1x         1x     1x         1x 1x 1x       2x   1x   1x        
import { BadRequestException, NotFoundException } from '@nestjs/common';
import { MODULE_PATH } from '@nestjs/common/constants';
import { HttpServer } from '@nestjs/common/interfaces';
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
import { Logger } from '@nestjs/common/services/logger.service';
import { ApplicationConfig } from '../application-config';
import { CONTROLLER_MAPPING_MESSAGE } from '../helpers/messages';
import { InstanceWrapper, NestContainer } from '../injector/container';
import { MetadataScanner } from '../metadata-scanner';
import { Resolver } from './interfaces/resolver.interface';
import { RouterExceptionFilters } from './router-exception-filters';
import { RouterExplorer } from './router-explorer';
import { RouterProxy } from './router-proxy';
 
export class RoutesResolver implements Resolver {
  private readonly logger = new Logger(RoutesResolver.name, true);
  private readonly routerProxy = new RouterProxy();
  private readonly routerExceptionsFilter: RouterExceptionFilters;
  private readonly routerBuilder: RouterExplorer;
 
  constructor(
    private readonly container: NestContainer,
    private readonly config: ApplicationConfig,
  ) {
    this.routerExceptionsFilter = new RouterExceptionFilters(
      container,
      config,
      container.getApplicationRef(),
    );
    this.routerBuilder = new RouterExplorer(
      new MetadataScanner(),
      this.container,
      this.routerProxy,
      this.routerExceptionsFilter,
      this.config,
    );
  }
 
  public resolve(appInstance, basePath: string) {
    const modules = this.container.getModules();
    modules.forEach(({ routes, metatype }, moduleName) => {
      let path = metatype
        ? Reflect.getMetadata(MODULE_PATH, metatype)
        : undefined;
      path = path ? path + basePath : basePath;
      this.registerRouters(routes, moduleName, path, appInstance);
    });
  }
 
  public registerRouters(
    routes: Map<string, InstanceWrapper<Controller>>,
    moduleName: string,
    basePath: string,
    appInstance: HttpServer,
  ) {
    routes.forEach(({ instance, metatype }) => {
      const path = this.routerBuilder.extractRouterPath(metatype, basePath);
      const controllerName = metatype.name;
 
      this.logger.log(CONTROLLER_MAPPING_MESSAGE(controllerName, path));
      this.routerBuilder.explore(
        instance,
        metatype,
        moduleName,
        appInstance,
        path,
      );
    });
  }
 
  public registerNotFoundHandler() {
    const applicationRef = this.container.getApplicationRef();
    const callback = (req, res) => {
      const method = applicationRef.getRequestMethod(req);
      const url = applicationRef.getRequestUrl(req);
      throw new NotFoundException(`Cannot ${method} ${url}`);
    };
    const handler = this.routerExceptionsFilter.create(
      {},
      callback,
      undefined,
    );
    const proxy = this.routerProxy.createProxy(callback, handler);
    applicationRef.setNotFoundHandler &&
      applicationRef.setNotFoundHandler(proxy);
  }
 
  public registerExceptionHandler() {
    const callback = (err, req, res, next) => {
      throw this.mapExternalException(err);
    };
    const handler = this.routerExceptionsFilter.create(
      {},
      callback as any,
      undefined,
    );
    const proxy = this.routerProxy.createExceptionLayerProxy(callback, handler);
    const applicationRef = this.container.getApplicationRef();
    applicationRef.setErrorHandler && applicationRef.setErrorHandler(proxy);
  }
 
  public mapExternalException(err: any) {
    switch (true) {
      case err instanceof SyntaxError:
        return new BadRequestException(err.message);
      default:
        return err;
    }
  }
}