Skip to content

Construire un projet NestJS ​

Conventions ​

Conventions de nommage ​

Les noms des modules et fichiers associés de NestJS doivent respecter la convention du framework. Les noms sont au pluriel: CatsModule, CatsService, CatsController etc.

La structure est la suivante :

txt
├── src
│   └── modules
│       └── cats
│           ├── controllers
│           │   ├── cats.controller.ts
│           │   └── cats.controller.spec.ts
│           ├── providers
│           │   ├── cats.service.ts
│           │   └── cats.service.spec.ts
│           ├── entity
│           │   └── cats.entity.ts
│           └── cats.module.ts
└ ...

Log ​

Le logger recommandé pour nestjs est nestjs-pino, qui permet d’avoir des logs en JSON sans aucune configuration.

Installer les deux packages npm nestjs-pino et pino-http.

L’implémentation se fait en 2 étapes :

  1. Dans app.module.ts, ajouter ceci :
diff
+import { LoggerModule } from 'nestjs-pino';

 @Module({
+  imports: [LoggerModule.forRoot()],
 })
 class AppModule {}
  1. Modifier main.ts comme suit :
diff
 import { NestFactory } from '@nestjs/core'
+import { Logger } from 'nestjs-pino';

+import { AppModule } from './app.module'

 async function bootstrap() {
-  const app = await NestFactory.create(AppModule)
+  const app = await NestFactory.create(AppModule, { bufferLogs: true })
+  app.useLogger(app.get(Logger))
   await app.listen(3000)
 }
 bootstrap()

Désormais, toutes les requêtes seront loggées comme dans cet exemple :

{"level":30,"time":1692613948292,"pid":12000,"hostname":"MacBook-Air-de-Foo.local","req":{"id":1,"method":"GET","url":"/","query":{},"params":{"0":""},"headers":{"accept-encoding":"gzip, deflate, br","accept":"*/*","user-agent":"Thunder Client (https://www.thunderclient.com)","host":"localhost:3000","connection":"close"},"remoteAddress":"::ffff:127.0.0.1","remotePort":58635},"res":{"statusCode":200,"headers":{"x-powered-by":"Express","content-type":"text/html; charset=utf-8","content-length":"12","etag":"W/\"c-Lve95gjOVATpfV8EL5X4nxwjKHE\""}},"responseTime":12,"msg":"request completed"}

Un exemple d’utilisation du logger :

typescript
// NestJS standard built-in logger.
// Logs will be produced by pino internally
import { Logger } from '@nestjs/common';

export class MyService {
  private readonly logger = new Logger(MyService.name);
  foo() {
    // All logger methods have args format the same as pino, but pino methods
    // `trace` and `info` are mapped to `verbose` and `log` to satisfy
    // `LoggerService` interface of NestJS:
    this.logger.verbose({ foo: 'bar' }, 'baz %s', 'qux');
    this.logger.debug('foo %s %o', 'bar', { baz: 'qux' });
    this.logger.log('foo');
  }
}

Gestion des erreurs ​

Créer un filter qui interceptera toutes les erreurs et les loggera d'une part, et les renverra sous forme de réponse HTTP structurée d'autre part :

typescript
import { ArgumentsHost, Catch, ExceptionFilter, HttpException, LoggerService } from '@nestjs/common'
import { Response } from 'express'

@Catch(HttpException)
export class HttpExceptionFilter<T extends HttpException> implements ExceptionFilter {
  constructor(private readonly logger: LoggerService) {}

  catch(exception: T, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const response = ctx.getResponse<Response>()
    const status = exception.getStatus()
    const exceptionResponse = exception.getResponse()
    const error: { message: string } = typeof response === 'string' ? { message: response } : (exceptionResponse as Error)

    this.logger.error(new Error(error.message))

    response.status(status).json({
      ...error,
      timestamp: new Date().toISOString(),
    })
  }
}

Docs ​

L’API doit fournir une documentation OpenAPI à jour.

Pour cela, il faut utiliser @nestjs/swagger telle que documenté ici dans la documentation officielle de nestjs.

Voir aussi