Cours NestJS · Module 11: Swagger et OpenAPI

Documentation des DTO - Sceaux sur le parchemin

3 min de lecture
Dans cette leçon7

Chaque document de la chancellerie impériale devait comporter des champs précisément décrits - le nom du pétitionnaire, le type d'affaire, la date et le sceau. Dans NestJS, l'équivalent de ces documents sont les DTO (Data Transfer Objects), et le décorateur @ApiProperty() décrit chaque champ afin que Swagger UI puisse l'afficher.

@ApiProperty - Les bases

Le décorateur @ApiProperty() décrit un champ unique dans une classe DTO :

1import { ApiProperty } from '@nestjs/swagger';
2
3export class CreateLegionaryDto {
4  @ApiProperty({
5    description: 'Name of the legionary',
6    example: 'Marcus Aurelius',
7  })
8  name: string;
9
10  @ApiProperty({
11    description: 'Rank in the legion',
12    example: 'Centurio',
13  })
14  rank: string;
15
16  @ApiProperty({
17    description: 'Years of experience',
18    example: 5,
19    minimum: 0,
20    maximum: 40,
21  })
22  experience: number;
23}

Options de @ApiProperty

Le décorateur accepte de nombreuses options de configuration :

OptionDescriptionExemple
descriptionDescription du champ'Name of the legionary'
exampleValeur d'exemple'Marcus'
requiredSi le champ est requistrue / false
defaultValeur par défaut'Miles'
enumListe des valeurs autorisées['Centurio', 'Miles']
typeType du champString, Number, Boolean
isArraySi le champ est un tableautrue
minimumValeur minimale (nombre)0
maximumValeur maximale (nombre)100
minLengthLongueur minimale (chaîne)2
maxLengthLongueur maximale (chaîne)50

Champs optionnels avec @ApiPropertyOptional

Pour les champs optionnels, nous utilisons @ApiPropertyOptional() :

1import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
2
3export class UpdateLegionaryDto {
4  @ApiPropertyOptional({
5    description: 'New rank of the legionary',
6    example: 'Optio',
7  })
8  rank?: string;
9
10  @ApiPropertyOptional({
11    description: 'New assigned legion',
12    example: 'Legio III Augusta',
13  })
14  legio?: string;
15
16  @ApiPropertyOptional({
17    description: 'Additional experience',
18    example: 2,
19    minimum: 0,
20  })
21  additionalExperience?: number;
22}

Champs avec enum - Grades de légion

L'enum est particulièrement utile pour les champs avec un ensemble limité de valeurs :

1export enum LegionaryRank {
2  MILES = 'Miles',
3  OPTIO = 'Optio',
4  CENTURIO = 'Centurio',
5  TRIBUNUS = 'Tribunus',
6  LEGATUS = 'Legatus',
7}
8
9export class CreateLegionaryDto {
10  @ApiProperty({
11    description: 'Rank of the legionary',
12    enum: LegionaryRank,
13    example: LegionaryRank.MILES,
14  })
15  rank: LegionaryRank;
16}

Objets imbriqués - Structure de la légion

Pour les DTO imbriqués, nous utilisons l'option type :

1export class AddressDto {
2  @ApiProperty({ description: 'Province name', example: 'Pannonia' })
3  province: string;
4
5  @ApiProperty({ description: 'City name', example: 'Aquincum' })
6  city: string;
7}
8
9export class LegionDto {
10  @ApiProperty({ description: 'Legion name', example: 'Legio X Gemina' })
11  name: string;
12
13  @ApiProperty({
14    description: 'Legion location',
15    type: AddressDto,
16  })
17  location: AddressDto;
18
19  @ApiProperty({
20    description: 'List of centurions',
21    type: [String],
22    example: ['Marcus', 'Julius', 'Gaius'],
23  })
24  centurions: string[];
25}

DTO de réponse

C'est une bonne pratique de créer des DTO distincts pour les réponses de l'API :

1export class LegionaryResponseDto {
2  @ApiProperty({ description: 'Legionary ID', example: '507f1f77bcf86cd799439011' })
3  id: string;
4
5  @ApiProperty({ description: 'Name of the legionary', example: 'Marcus Aurelius' })
6  name: string;
7
8  @ApiProperty({ description: 'Rank', enum: LegionaryRank })
9  rank: LegionaryRank;
10
11  @ApiProperty({ description: 'Recruitment date', example: '2024-01-15T10:30:00Z' })
12  recruitedAt: Date;
13
14  @ApiProperty({ description: 'Is active', example: true })
15  isActive: boolean;
16}

Exercice pratique

Crée la documentation des DTO pour le système de gestion des provinces de l'Empire :

Code de cette leçon : src/province.dto.ts
1// Documentation des DTO - sceaux sur le parchemin
2import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
3
4// TODO: Crée l'enum ProvinceStatus avec les valeurs :
5// ACTIVE = 'Active', CONQUERED = 'Conquered', REBELLING = 'Rebelling'
6export enum ProvinceStatus {
7  // TODO: Complète les valeurs de l'enum
8}
9
10export class CreateProvinceDto {
11  // TODO: Ajoute @ApiProperty avec description et example
12  name: string;
13
14  // TODO: Ajoute @ApiProperty avec description et example
15  governor: string;
16
17  // TODO: Ajoute @ApiProperty avec enum ProvinceStatus
18  status: ProvinceStatus;
19
20  // TODO: Ajoute @ApiPropertyOptional avec description, example, minimum
21  population?: number;
22
23  // TODO: Ajoute @ApiProperty avec description et type [String]
24  legions: string[];
25}
26
27export class ProvinceResponseDto {
28  @ApiProperty({ description: 'ID de la province', example: '64a1b2c3d4e5f6a7b8c9d0e1' })
29  id: string;
30
31  @ApiProperty({ description: 'Province name', example: 'Pannonia' })
32  name: string;
33
34  @ApiProperty({ description: 'Gouverneur', example: 'Lucius Verus' })
35  governor: string;
36
37  @ApiProperty({ description: 'Statut de la province', enum: ProvinceStatus })
38  status: ProvinceStatus;
39
40  @ApiPropertyOptional({ description: 'Population', example: 500000 })
41  population?: number;
42
43  @ApiProperty({ description: "Date d'annexion" })
44  annexedAt: Date;
45}
46
47console.log("@ApiProperty - champs requis");
48console.log("@ApiPropertyOptional - champs optionnels");
49console.log("Options : description, example, enum, type");
50console.log("minimum, maximum, minLength, maxLength");
51

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. Que fait le décorateur @ApiProperty() sur un champ de classe DTO ?

  2. 2. Quel décorateur est utilisé pour marquer les champs optionnels dans un DTO pour Swagger ?

Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.

Tâches pratiques dans le jeu

  • Éditeur de code

    Complète CreateCenturioDto en ajoutant @ApiProperty avec description et example à chaque champ

  • Tri vertical

    Ordonne les éléments de @ApiProperty avec enum dans le bon ordre :

  • Clique dans l'ordre

    Ordonne les options de @ApiProperty, de la description à la validation des valeurs :

  • Éditeur de code

    Complète CreateProvinceDto avec l'enum ProvinceType, le LocationDto imbriqué et un tableau de chaînes