No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Integrando Swagger y PartialType con Open API

13/17
Recursos

Una API profesional debe estar documentada. Cuando hablamos de documentación, nos suena a una tarea tediosa que nadie quiere realizar. Afortunadamente, NestJS permite automatizar fácilmente la creación de la misma.

Cómo hacer la documentación API Rest

Swagger es un reconocido set de herramientas para la documentación de API Rest. Instala las dependencias necesarias con el comando npm install --save @nestjs/swagger swagger-ui-express y configura el archivo main.ts con el siguiente código.

// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
    
  // Configuración Swagger en NestJS
  const config = new DocumentBuilder()
    .setTitle('Platzi API')
    .setDescription('Documentación Platzi API')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  
  // URL API
  SwaggerModule.setup('docs', app, document);

  await app.listen(process.env.PORT || 3000);
}
bootstrap();

Setea el título, descripción y versión de tu documentación. Lo más importante es la URL para acceder a la misma.

Levanta el servidor con npm run start:dev y accede a localhost:3000/docs para visualizar la documentación autogenerada que mapea automáticamente todos los endpoints de tu aplicación.

Tipado de la documentación

La documentación autogenerada por Swagger es bastante simple, puedes volverla más completa tipando los datos de entrada y salida de cada endpoint gracias a los DTO.

Busca el archivo nest-cli.json en la raíz de tu proyecto y agrega el siguiente plugin:

{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compileOptions": {
    "plugins": ["@nestjs/swagger"]
  }
}

A continuación, prepara tus DTO de la siguiente manera:

import { IsNotEmpty, IsString, IsNumber } from 'class-validator';
import { ApiProperty, PartialType, OmitType } from '@nestjs/swagger';

export class CreateProductDTO {

  @ApiProperty()
  @IsNotEmpty()
  @IsString()
  readonly name: string;

  @ApiProperty()
  @IsNotEmpty()
  @IsString()
  readonly description: string;

  @ApiProperty()
  @IsNotEmpty()
  @IsNumber()
  readonly price: number;
}

export class UpdateAuthorDto extends PartialType(
  OmitType(CreateProductDTO, ['name']),
) {}

Lo más relevante aquí es importar PartialType y OmitType desde @nestjs/swagger en lugar de importarlo desde @nestjs/mapped-types. Coloca también el decorador @ApiProperty() en cada una de las propiedades que el DTO necesita.

Documentación Swagger.png

De esta manera, observarás en la documentación que indica el tipo de dato que requiere cada uno de tus endpoints.

Cuadro de código para uso de swagger

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

// src/main.ts

import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger';

async function bootstrap() {
  ...
  const config = new DocumentBuilder()
    .setTitle('API')
    .setDescription('PLATZI STORE')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('docs', app, document);
  ...
  await app.listen(3000);
}
bootstrap();
# nest-cli.json
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "plugins": ["@nestjs/swagger/plugin"]
  }
}
// src/products/dtos/brand.dtos.ts
import { PartialType } from '@nestjs/swagger';
// src/products/dtos/category.dtos.ts
import { PartialType } from '@nestjs/swagger';
// src/products/dtos/products.dtos.ts
import { PartialType } from '@nestjs/swagger';
// src/users/dtos/customer.dto.ts
import { PartialType } from '@nestjs/swagger';
// src/users/dtos/user.dto.ts
import { PartialType } from '@nestjs/swagger';

Contribución creada por: Kevin Fiorentino.

Aportes 30

Preguntas 19

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Para que Swagger encuentre tus DTOs y Entities es necesario tener los archivos con extension .dto.ts y .entity.ts repectivamente

Buenas por si a alguien más le pasa hice toda la configuración como el profesor pero los dtos no me reflejaban bien en la documentación solo los entities al mirar en la documentación me di cuenta que ellos le añaden otro decorador más a los dtos. @ApiProperty()

https://docs.nestjs.com/openapi/mapped-types

Aquí dejo un ejemplo de como quedaría un dto:

import { IsString, IsUrl, IsNotEmpty } from 'class-validator';
import { PartialType, ApiProperty } from '@nestjs/swagger';

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

  @ApiProperty()
  @IsUrl()
  @IsNotEmpty()
  readonly image: string;
}

export class UpdateBrandDto extends PartialType(CreateBrandDto) {}

´´´

Para los que no les funciona el swagger, se debe actualizar el repositorio
nest update -f -t latest

Si tienes fallos, intenta con swagger 4.

npm i @nestjs/swagger@4.5.12-next.1

No entiendo por qué tengo errores con la ultima versión ‘Swagger 5’, así que esto es una alternativa.

Si estás usando el repo del profesor con Nest v7, seguramente tendrás que hacer:

npm i --save @nestjs/swagger@4.7.16 swagger-ui-express@4.1.6 --legacy-peer-deps

Si como yo estan usando Fastify, necesitan instalar:

npm install --save @nestjs/swagger fastify-swagger

yarn:

yarn add @nestjs/swagger fastify-swagger

Para que Swagger reconozca las DTOs es necesario borrar la carpeta dist y correr de nuevo el proyecto.
En Git Bash / Linux:

rm -rf dist
si estas desde el 2023 no hacer caso de los casos de abajo funciona automáticamente con los pasos del profesor.

Me funciono fue esta version npm i @nestjs/[email protected] swagger-ui-express

si tratan de hacer el ejercicio al día de hoy, deben actualizar esta dependencia si tiene problemas.

@nestjs/platform-express

Está muy buena la documentación que genera Swagger! muy facil.

Creo que ya me gustó más Nest que Express… Solo por esto

Para los que integren al Nest CLI el plugin de Swagger, les recomiendo no usar caracteres especiales en sus directorios.

Si les aparece el error:

Module Not Found

Lo más probable es que en algún lugar de su directorio tengan alguno. En mi caso fue un acento. Pues bautice mi carpeta raíz como:

programación-modular

No fue hasta que buscando la causa del error, encontré la respuesta en GitHub Issues:


https://github.com/nestjs/swagger/issues/1868

10/07/2022.
Al instalar Swagger tanto con el comando que usa Nico como el comando que aparece en la documentacion oficial de Nestjs, me tiro errores. A continuacion dejo los pasos sobre como resolvi el error por si a algun otro le sucede lo mismo.

Para instalar swagger usamos el comando:

$ npm install --save @nestjs/swagger

Al instalar Swagger tira conflictos de dependencias.
Primero dependencia @nestjs/common deprecada. Cuando lo actualizas, luego aparece @nestjs/core deprecada.
Por lo que al final, procedo a actualizar las dependencias en general de nestjs, por las dudas.

Comando:

$ nest update --force

▹▹▹▹▹ Installation in progress… ☕▹▹▹▹▹ Package install
▹▸▹▹▹ Installation in progress… ☕
Failed to execute command: npm install --save @nestjs/axios@latest @nestjs/common@latest @nestjs/config@latest @nestjs/core@latest @nestjs/mapped-types@latest @nestjs/platform-express@latest
✖ Package installation in progress… ☕
✔ Installation in progress… ☕

Sale error de que no se pudo ejecutar la cadena de comandos para actualizar dependencias (probablemente haya error en alguna de todas las dependencias que se muestra que se esta queriendo actualizar). Por lo que procedo a actualizar manualmente, una a una para verificar cual tira error.

$ npm install --save @nestjs/axios@latest (✔)
$ npm install --save @nestjs/common@latest (✔)
$ npm install --save @nestjs/config@latest (✔)
$ npm install --save @nestjs/core@latest (✖ tira error)
$ npm install --save @nestjs/mapped-types@latest (✔)
$ npm install --save @nestjs/platform-express@latest (✖ tira error)

Una vez identificado las dependencias que generan conflicto vemos que @nestjs/platform-express@latest depende de tener @nestjs/core actualizada y a su vez descubrimos que @nestjs/core@latest depende de tener @nestjs/testing actualizada.

por lo que se procede a instalar en orden esas dependencias:

$ npm install --save @nestjs/testing@latest
$ npm install --save @nestjs/core@latest
$ npm install --save @nestjs/platform-express@latest

y vemos que ahora instalan y actualizan correctamente.

Para asegurarnos de actualizar correctamente todas las dependencias, le damos de vuelta al comando: nest update --force (no debería tener conflictos ahora):

$ nest update --force

Y vemos que finaliza la actualización de manera satisfactoria.

Al final, procedemos a instalar Swagger (de paso instalamos la ultima versión):

$ npm install --save @nestjs/swagger@latest

Y vemos que se instala sin problemas.

Nota: Al final, el problema era que al actualizar nestjs con el comando: nest update --force , faltaba @nestjs/testing@latest antes del @nestjs/core@latest .
La solución era que se debía haber introducido la siguiente secuencia de comandos manual :

$ npm install --save @nestjs/axios@latest @nestjs/common@latest @nestjs/config@latest @nestjs/testing@latest @nestjs/core@latest @nestjs/mapped-types@latest @nestjs/platform-express@latest

  1. Instalamos las dependencias npm install --save @nestjs/swagger swagger-ui-express
  2. Editamos el archivo nest-cli.js
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "plugins": ["@nestjs/swagger"]
  }
}
  1. En el main.ts se agrega la configuracion de swagger antes de listen del server
const config = new DocumentBuilder()
    .setTitle('API')
    .setDescription('Store')
    .setVersion('1.0')
    .build();
  const document = SwaggerModule.createDocument(app, config);
  SwaggerModule.setup('docs', app, document);
  1. En los DTOs tenemos que importar el partialtype de swagger para que tome los cambios
import { PartialType } from '@nestjs/swagger';
  1. Borramos la carpeta dist rm -rf dist o click derecho borrar carpeta

  2. Ejecutamos la aplicacion npm run start:dev

PickType

Hay otra manera de extender las propiedades de un dto y seleccionar las que si son obligatorias. Imaginemos el escenario yo tengo un dto que tiene el modelo de un producto, necesito un dto que contenga el modelo de las unidades de un producto comprado y solo algunos datos del producto (id, nombre).

Defino el DTO de producto (padre)

import { ApiProperty } from '@nestjs/swagger';
export class ProductResponseDto {
  @IsString()
  @IsNotEmpty()
  @ApiProperty({ description: 'Product Id' })
  id: string;

  @IsString()
  @IsNotEmpty()
  @ApiProperty({ description: "Product's Name", example: 'Uniforme marca Titin' })
  @Expose()
  name: string;

  @IsString()
  @IsNotEmpty()
  @ApiProperty({ description: "Product's Sku", example: 'RBLL005' })
  @Expose()
  sku: string;

  @IsString()
  @ApiProperty({
    description: "Product's Description",
    example: 'American Drink',
  })
  @Expose()
  description: string;
}

DTO de producto comprado (hijo)

import { ApiProperty, PickType } from '@nestjs/swagger';

class ProductSaleResponseDto extends PickType(ProductResponseDto , [
  'id',
  'name',
]) {
  @IsNumber()
  @IsPositive()
  @ApiProperty({ description: 'Quantity product buy' })
  quantity: number;
}

Mas clean no puede ser este seccion de cursos de NestJS 👌💚

Yo tuve un problema con el user.entity.ts, me aparecía un error 'Module\_Not\_Found'; luego de probar un rato y ver la documentación, lo solucioné agregando ApiProperty() a las variables en los dto. También eliminé el plugin. Los PartialType si los tomé de swagger.
Hola, cómo puedo documentar mis DTOs si estos se encuentran en una librería de Nodejs aparte? Es decir, el DTO quedaría dentro de la carpeta node-modules del proyecto Nest principal.

Para no estar eliminando la carpeta /dist constantemente con el comando

rm -rf dist 

Podemos activar la eliminación automática de la carpeta cada vez que se invoque al compilador ejecutando npm run start:dev colocando

"deleteOutDir": true

dentro de nuestro nest-cli.json quedando de la siguiente manera:

"compilerOptions": {
    "deleteOutDir": true, // <- Si es true, primero eliminará el directorio de salida de la compilación.
    "plugins": [
        "@nestjs/swagger"
    ]
  }

Más detalles aquí

Excelente Nico gracias por esos paso extra!

genial la documentaion!!!

Ahora la documentacion se genera mediante la ruta /api

si estan en 2022 y actualizaron su node y el swagger les presento problemas
hagan lo siguiente

yarn add @nestjs/platform-express @nestjs/common @nestjs/core  @nestjs/axios

en el archivo app.module.ts

reemplazan

import { Module, HttpModule, HttpService } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { HttpModule, HttpService } from '@nestjs/axios';

ya que en las nuevas versiones de @nestjs/common ya no soporta los modulos de HttpModule y HttpService .
por ende se instala Axios y queda ok.

😄

que buena esta clase

Swagger nest

Una consulta hice todo el proceso para ver los dto en swagger, pero el ultimo paso de rm-rf dist/ me sale rm no se reconoce como un comando interno o externo …Entonces no puedo ver los dto como se podria solucionar ya que voy en la mitad de la clase 14, la que sigue de esta pero sigo sin ver los dto. muchas Gracias

Si eres usuario windows y no lo sabes, para eliminar archivos en lugar de utilizar el comando ‘rm -rf’ utiliza ‘del’. En el ejemplo concreto de esta sesión sería:

del dist

Luego de esto escribe: YES o Y para aceptar.