Nest.js Study Notes I

· 2 min read
Nest.js Study Notes I

Project structure

src
├───app.controller.spec.ts
├───app.controller.ts
├───app.module.ts
├───app.service.ts
└───main.ts

Controller

https://docs.nestjs.com/controllers

Controllers are responsible for handling incoming requests and returning responses to the client.

Decotator: @Controller

CLS: nest g controller cats

Routing: namespace as the @Controller decorator parameter.

Providers

https://docs.nestjs.com/providers

Providers are a fundamental concept in Nest. Many of the basic Nest classes may be treated as a provider – services, repositories, factories, helpers, and so on. The main idea of a provider is that it can be injected as dependency; this means objects can create various relationships with each other, and the function of "wiring up" instances of objects can largely be delegated to the Nest runtime system.

Decotator: @Injectable

CLI: nest g service cats

Injection:

@Controller('cats')
export class CatsController {
  constructor(private catsService: CatsService) {}

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}

This design is paying honor to Angular: https://angular.io/guide/dependency-injection

Custom providers

Optional providers

Scopes

https://docs.nestjs.com/fundamentals/injection-scopes

Types: DEFAULT(global shared), REQUEST(single request), TRANSIENT(single user).

Usage:

import { Injectable, Scope } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
@Controller({ path: 'cats', scope: Scope.REQUEST })

Module

The module provides metadata that Nest makes use of to organize the application structure.

Decorator: @Module

Middleware

Middleware is a function which is called before the route handler. Middleware functions have access to the request and response objects, and the next() middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next.

Sample:

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log('Request...');
    next();
  }
}

export function logger(req: Request, res: Response, next: NextFunction) {
  console.log(`Request...`);
  next();
};

Inject to providers or controllers directlly.

Applying middleware in module:

There is no place for middleware in the @Module() decorator. Instead, we set them up using the configure() method of the module class. Modules that include middleware have to implement the NestModule interface.

import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { CatsModule } from './cats/cats.module';

@Module({
  imports: [CatsModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .exclude(
        { path: 'cats', method: RequestMethod.GET },
        { path: 'cats', method: RequestMethod.POST },
        'cats/(.*)',
      )
      .forRoutes({ path: 'cats', method: RequestMethod.GET });
      // .forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });
      // .forRoutes('cats');
  }
}

path-to-regexp supported.

Multiple: consumer.apply(cors(), helmet(), logger).forRoutes(CatsController);

Global middleware: app.use(logger);

Serialization

Serialization is a process that happens before objects are returned in a network response. This is an appropriate place to provide rules for transforming and sanitizing the data to be returned to the client. For example, sensitive data like passwords should always be excluded from the response. Or, certain properties might require additional transformation, such as sending only a subset of properties of an entity. Performing these transformations manually can be tedious and error prone, and can leave you uncertain that all cases have been covered.

Modules

In Angular, the providers are registered in the global scope. Once defined, they're available everywhere. On the other hand, Nest encapsulates providers inside the module scope. You aren't able to use the module providers elsewhere without importing them. But sometimes, you may just want to provide a set of things which should be available always - out-of-the-box, for example: helpers, database connection, whatever. That's why you're able to make the module a global one.

@Global()
@Module({  
  providers: [
    {
      provide: 'MY-TOKEN',
      useValue: 'my-injected-value',
    }
  ],
  exports: ['MY-TOKEN'],
})
export class GlobalModule {}