29-3 Documenter l'API selon le standard OpenAPI
Bien que nous puissions voir les différents points d'entrée de l'API et tester des requêtes, l'information est plutôt limitée.
Par exemple, pour l'action de création d'un projet, nous ne savons pas vraiment ce que nous devons envoyer à l'API. Quels sont les attributs d'un projet, par exemple? Quel est le type de retour?

Définir les propriétés des DTO via @ApiProperty
Via le décorateur @ApiProperty, il est possible de définir pour chaque propriété des DTO un exemple et une description:
export class CreateProjetDto {
@ApiProperty({
description: 'Le nom du projet',
example: 'LAN Party',
})
nom: string;
@ApiProperty({
description: 'la description du projet',
example: "Tout ce qui à trait à l'organisation du LAN Party",
})
description: string;
@ApiProperty({
description: "L'URL de l'image du projet",
example: 'https://i.imgur.com/Y5nZ4Qe.jpg',
})
image_url?: string;
}
Par défaut, la documentation Swagger de votre DTO de création ne sera pas reconduite dans votre DTO de mise à jour (update). En effet, le PartialType importé de @nestjs/mapped-types ne transfert pas la documentation:
import { PartialType } from '@nestjs/mapped-types';
import { CreateProjetDto } from './create-projet.dto';
export class UpdateProjetDto extends PartialType(CreateProjetDto) {}
Pour que la doc soit transférée, vous devez plutôt utiliser PartialType en provenance de la librairie @nestjs/swagger:
import { PartialType } from '@nestjs/swagger';
import { CreateProjetDto } from './create-projet.dto';
export class UpdateProjetDto extends PartialType(CreateProjetDto) {}
Il est possible de sélectionner le bon import de PartialType à l'aide de WebStorm de cette façon:

Il est possible de spécifier simplement @ApiProperty, sans la description ou l'exemple, mais le tout donne plus de contexte à la documentation.
Cela ajoute automatiquement un exemple de Request Body, ainsi que la définition du schéma de données attendu:


Définir le type de la réponse via @ApiResponse
Afin de spécifier adéquatement le type de retour associé à une réponse d'API, on peut utiliser le décorateur @ApiResponse sur une fonction de contrôleur.
@ApiResponse({
type: Projet,
})
@Get(':id')
findOne(@Param('id') id: string) {
const projet = this.projetsService.obtenir(+id);
if (!projet) throw new NotFoundException();
return projet;
}
Ainsi, maintenant pour la fonction en question, le type de retour sera défini dans la section "schema" du bloc Responses.

Le tout manque de détail cependant, pusiqu'au-delà de savoir qu'un Projet sera retourné, on ne sait pas vraiment ce que constitue un projet. Nous verrons dans la prochaine section comment ajouter plus de détails.
Il est aussi possible de donner plus de détails sur le statut de la réponse, en utilisant un décorateur plus précis, comme @ApiOkResponse plutôt que simplement ApiResponse:
@ApiOkResponse({
type: Projet,
})
@Get(':id')
findOne(@Param('id') id: string) {
const projet = this.projetsService.obtenir(+id);
if (!projet) throw new NotFoundException();
return projet;
}
Le code de retour 200 sera ainsi défini comme code de réponse possible.
Définir les attributs du modèle via @ApiProperty()
Le décorateur @ApiProperty() peut aussi être utilisé dans le modèle/entité pour définir les propriétés.
import { ApiProperty } from '@nestjs/swagger';
export class Projet {
@ApiProperty()
id: number;
@ApiProperty()
nom: string;
@ApiProperty()
description: string;
@ApiProperty()
image_url?: string;
@ApiProperty()
date_creation: string;
@ApiProperty()
date_modification: string;
}
Cela nous permettant d'avoir un exemple de valeur et un schéma dans la section Responses:


De plus, il est possible, comme dans les DTO, de spécifier un exemple et une description pour chacun des attributs.
import { ApiProperty } from '@nestjs/swagger';
export class Projet {
@ApiProperty({
description: "L'identifiant du projet",
example: 1,
})
id: number;
@ApiProperty({
description: 'Le nom du projet',
example: 'LAN Party',
})
nom: string;
@ApiProperty({
description: 'la description du projet',
example: "Tout ce qui à trait à l'organisation du LAN Party",
})
description: string;
@ApiProperty({
description: "L'URL de l'image du projet",
example: 'https://i.imgur.com/Y5nZ4Qe.jpg',
})
image_url?: string;
@ApiProperty()
date_creation: string;
@ApiProperty()
date_modification: string;
}
Ce qui viendra améliorer la section Responses de la page de documentation pour la requête en question.

Définir un retour de type Array
Afin de spécifier que le retour attendu est un tableau, comme dans findAll() par exemple, on peut utiliser la formule suivante:
@ApiOkResponse({
type: [Projet],
})
@Get()
findAll() {
return this.projetsService.obtenirTous();
}
Statut Created (201)
Dans le cas de la fonction liée à l'action HTTP POST, le statut sera 201 (created). Il existe un décorateur, tout comme pour @ApiOkResponse, mais pour un statut 201, soit @ApiCreatedResponse.
@ApiCreatedResponse({
type: Projet,
})
@Post()
create(@Body() createProjetDto: CreateProjetDto) {
return this.projetsService.creer(createProjetDto);
}
Statuts pour @Patch et @Delete
En tant normal, @Patch et @Delete retournerons 200 (OK) si l'action a été un succès.
@ApiOkResponse({
type: Projet,
})
@Patch(':id')
update(@Param('id') id: string, @Body() updateProjetDto: UpdateProjetDto) {
const projetModif = this.projetsService.modifier(+id, updateProjetDto);
if (!projetModif) throw new NotFoundException();
return projetModif;
}
@ApiOkResponse()
@Delete(':id')
remove(@Param('id') id: string) {
const projet = this.projetsService.obtenir(+id);
if (!projet) throw new NotFoundException();
return this.projetsService.supprimer(+id);
}
Préciser que plus d'un statut de réponse est possible
Pour certaines actions, on peut retourner plusieurs statuts différents. Par exemple, pour GET /projets/:id, il se pourrait que le statut soit 404 (Not Found). Dans ce cas, plus d'un décorateur peut être ajouté à la fonction.
@ApiOkResponse({
type: Projet,
})
@ApiNotFoundResponse()
@Get(':id')
findOne(@Param('id') id: string) {
const projet = this.projetsService.obtenir(+id);
if (!projet) throw new NotFoundException();
return projet;
}
Cela ajoutera un code de retour à la section Responses.

Il aussi est possible d'ajouter une description pour clarifier la réponse.
@ApiNotFoundResponse({
description: "Le projet demandé n'existe pas",
})

