Nest with Swagger

Author : JaNakh Pon , August 17, 2021

Tags

Add OpenAPI Specification to Nest.js

We are going to use the api from the previous article. After cloning the api repo from the previous article, we can add OpenAPI Specification to Nest.js in a few steps:

  1. Installation
  2. Configure Swagger
  3. Define property

Summary

The OpenAPI Specification, previously known as the Swagger Specification, is a specification for machine-readable interface files for describing, producing, consuming, and visualizing RESTful web services.

In this article, we are going to add OpenAPI/Swagger to our Nest.js app. To do that, we need to install dependencies and configure swagger document builder in main.ts.

And finally, we need to define related property to DTO and Controller.


Installation

Firstly, let's install the required dependencies:

  > npm install --save @nestjs/swagger swagger-ui-express

Confguration

And now we need to configure document builder for swagger in main.ts,

main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix('api/v1');
  app.enableCors();

  const options = new DocumentBuilder()
    .setTitle('Nest.js with Swagger')
    .setDescription('Swagger Example with Nest.js')
    .setVersion('1.0')
    .addTag('user')
    // You can add more tags here
    // for example, sine we already have todo routes we can add ".addTag('todo')"
    // and define its swagger properties in todo's DTO, Controllers 
    // I am not adding it here cuz I am too lazy 😴 to do that 😉
    .addBearerAuth()
    .build();
  const document = SwaggerModule.createDocument(app, options);
  // setup the swagger module
  SwaggerModule.setup('api/v1/documentation', app, document);
  await app.listen(3001);
}
bootstrap();

Properties ? 🤔

And now let's add swagger properties in DTO, so it will be able to display a proper Schema definitions in Documentation.

user.dto.ts
import {
    IsNotEmpty,
    IsString,
    IsEmail
} from 'class-validator';
import { ApiProperty } from '@nestjs/swagger'

export class UserSignupDTO {
    @IsNotEmpty()
    @IsString()
    @ApiProperty()
    readonly name: string;

    @IsString()
    @IsNotEmpty()
    @IsEmail()
    @ApiProperty()
    readonly email: string;

    @IsNotEmpty()
    @IsString()
    @ApiProperty()
    readonly password: string;
}

export class UserSigninDTO {
    @IsString()
    @IsNotEmpty()
    @IsEmail()
    @ApiProperty()
    readonly email: string;

    @IsNotEmpty()
    @IsString()
    @ApiProperty()
    readonly password: string;
}

And finally, let's add a few more properties(sample response, private or public ?) for each route in controller:

user.controller.ts
import { Body, Controller, Post, Get, UseGuards, Request } from '@nestjs/common';
import { User, RespToken } from './interfaces/user.interface'
import { UserService } from './user.service'
import { UserSignupDTO, UserSigninDTO } from './dto/user.dto'
import { AuthGuard } from '@nestjs/passport'
import {
    ApiTags,
    ApiOkResponse,
    ApiCreatedResponse,
    ApiForbiddenResponse,
    ApiUnauthorizedResponse,
    ApiBearerAuth,
} from '@nestjs/swagger';

@Controller('user')
@ApiTags('user')
export class UserController {
    constructor(private userService: UserService) { }
    @Post('register')
    @ApiCreatedResponse({ description: 'Your account is registered!' })
    @ApiForbiddenResponse({ description: 'Forbidden' })
    async register(@Body() user: UserSignupDTO): Promise<User> {
        return await this.userService.signup(user);
    }
    @Post('login')
    @ApiOkResponse({ description: 'Signed in successfully' })
    @ApiForbiddenResponse({ description: 'Forbidden' })
    async login(@Body() user: UserSigninDTO): Promise<RespToken> {
        return await this.userService.signin(user);
    }
    @Get('me')
    @UseGuards(AuthGuard('jwt'))
    @ApiBearerAuth() // private route
    @ApiOkResponse({ description: '200' })
    @ApiUnauthorizedResponse({ description: 'UnAuthorized' })
    async profile(@Request() req) {
        return req.user;
    }
}

Now, we should be able to access swagger documentation via /api/v1/documentation and if we check the routes under the title "user" we should be able to see the sample responses and additional properties such as Schema detail and whether the route is public or private.

And, to access the private route with 🔒 icon, we need to create an example account by clicking Try it out button in /v1/user/register and use that credentials to get a token via /v1/user/login.

We can use that token to access private route by clicking Authorize 🔒 in the top right corner of the documentation and paste it in value input box.

Now, we should be able to access our example private route: /api/v1/user/me by clicking Try it out > Execute.


Nestjs Official OpenAPI Documentation !

Source Code.

Go Back.