Cours NestJS · Module 11: Swagger et OpenAPI
Documentation des DTO - Sceaux sur le parchemin
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 :
| Option | Description | Exemple |
|---|---|---|
description | Description du champ | 'Name of the legionary' |
example | Valeur d'exemple | 'Marcus' |
required | Si le champ est requis | true / false |
default | Valeur par défaut | 'Miles' |
enum | Liste des valeurs autorisées | ['Centurio', 'Miles'] |
type | Type du champ | String, Number, Boolean |
isArray | Si le champ est un tableau | true |
minimum | Valeur minimale (nombre) | 0 |
maximum | Valeur maximale (nombre) | 100 |
minLength | Longueur minimale (chaîne) | 2 |
maxLength | Longueur 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");
51Tu 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. Que fait le décorateur @ApiProperty() sur un champ de classe DTO ?
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