9. Documentation & Swagger
La documentation est essentielle pour maintenir un code de qualité et faciliter le travail d'équipe. Dans ce chapitre, nous allons voir deux approches complémentaires :
- JSDoc : Pour documenter le code TypeScript/JavaScript (fonctions, classes, types)
- OpenAPI : Pour documenter l'API REST (endpoints, paramètres, réponses)
JSDoc
- Améliore la lisibilité : Les développeurs comprennent immédiatement ce que fait une fonction
- Autocomplete améliorée : Les IDE peuvent afficher la documentation en temps réel
- Génération automatique : Possibilité de générer une documentation HTML
- Typage pour JavaScript : Permet d'ajouter des types dans des fichiers
.js(même si TypeScript est préférable) - Maintenance facilitée : Les changements dans le code sont documentés au même endroit
Syntaxe de base
JSDoc utilise des commentaires spéciaux qui commencent par /** et se terminent par */.
/**
* Description de la fonction
* @param parametre1 - Description du paramètre
* @param parametre2 - Description du paramètre
* @returns Description de la valeur retournée
*/
function maFonction(parametre1: string, parametre2: number): boolean {
return true
}
Tags JSDoc courants
Voici les tags les plus utilisés :
| Tag | Description | Exemple |
|---|---|---|
@param | Décrit un paramètre | @param {string} name - Nom de l'utilisateur |
@returns | Décrit la valeur retournée | @returns {Promise<User>} L'utilisateur créé |
@throws | Décrit les erreurs possibles | @throws {Error} Si l'email est invalide |
@example | Fournit un exemple d'utilisation | @example const user = await getUser(1); |
@deprecated | Marque comme obsolète | @deprecated Utiliser getUser() à la place |
@see | Référence à une autre fonction | @see {@link createUser} |
@async | Indique une fonction asynchrone | @async |
@typedef | Définit un type personnalisé | @typedef {Object} User |
@property | Propriété d'un objet | @property {number} id |
Bonnes pratiques JSDoc
- Documentez les fonctions publiques : Toutes les fonctions exportées doivent avoir une documentation
- Soyez concis mais précis : Décrivez clairement ce que fait la fonction sans être verbeux
- Ajoutez des exemples : Pour les fonctions complexes, un exemple vaut mieux qu'une longue explication
- Documentez les erreurs : Utilisez
@throwspour décrire les erreurs possibles - Gardez la documentation à jour : Mettez à jour les commentaires quand vous modifiez le code
- Évitez les évidences : Ne documentez pas
@param id - The ID→ préférez expliquer ce que représente l'ID
OpenAPI avec Swagger
Pourquoi documenter une API ?
- Faciliter la compréhension : Les développeurs savent exactement comment interagir avec l'API (endpoints, paramètres, types de données)
- Réduire les erreurs : Les spécifications claires minimisent le risque d'erreurs lors de l'intégration de l'API
- Améliorer la maintenabilité : La documentation facilite l'évolution et l'extension de l'API
- Interface de test intégrée : Swagger UI permet de tester directement les endpoints depuis le navigateur
OpenAPI est une spécification standardisée pour décrire les API REST. Swagger est l'ensemble d'outils qui exploite cette spécification.
Composants principaux
- Spécification OpenAPI : Format de fichier (YAML ou JSON) décrivant toutes les routes, paramètres et réponses de l'API
- Swagger UI : Interface web interactive pour visualiser et tester la documentation
- Version actuelle : OpenAPI 3.1.0 (compatible JSON Schema)
Les schémas
Les schémas permettent de définir la structure des données utilisées dans votre API (objets, types). Au lieu de
décrire la structure d'un objet User à chaque endpoint qui l'utilise, vous le définissez une seule fois dans
components/schemas et vous le réutilisez partout avec $ref.
Exemple de schéma :
components:
schemas:
User:
type: object
required:
- name
- email
properties:
id:
type: integer
example: 1
name:
type: string
example: "Alice"
email:
type: string
format: email
example: "alice@example.com"
Réutilisation dans un endpoint :
paths:
/users/{id}:
get:
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/User' # Réutilise le schéma User
Avantages des schémas : Évite la duplication, garantit la cohérence des données dans toute l'API, et facilite la maintenance (une modification du schéma se propage partout).
Approche par modules YAML
Cette approche consiste à créer un fichier YAML par module (users, auth, etc.) pour documenter les endpoints de chaque scope. C'est une méthode simple et claire qui sépare bien les préoccupations.
Avantages
Organisation modulaire : Un fichier par module facilite la maintenance
Documentation explicite : Chaque endpoint est documenté manuellement, ce qui force à réfléchir à la documentation
Flexibilité : Fonctionne avec n'importe quelle structure Express
Pas de magie : Tout est explicite et facile à comprendre
Installation
npm install swagger-ui-express yamljs
npm install -D @types/swagger-ui-express @types/yamljs
Structure du projet
Créez un dossier docs/ à la racine avec un fichier par module :
src/
├── routes/
│ ├── auth.routes.ts
│ └── user.routes.ts
├── docs/
│ ├── swagger.config.yml # Configuration principale
│ ├── auth.doc.yml # Documentation des routes auth
│ └── user.doc.yml # Documentation des routes user
└── index.ts
Création des fichiers YAML
Créez src/docs/swagger.config.yml :
openapi: 3.0.0
info:
title: API Documentation
version: 1.0.0
description: Documentation de l'API avec authentification JWT
contact:
name: Votre nom
email: votre@email.com
servers:
- url: http://localhost:3000
description: Serveur de développement
- url: https://api.production.com
description: Serveur de production
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: "Token JWT à obtenir via /auth/login"
schemas:
User:
type: object
properties:
id:
type: integer
example: 1
name:
type: string
example: "Alice"
email:
type: string
format: email
example: "alice@example.com"
Error:
type: object
properties:
message:
type: string
example: "Message d'erreur"
tags:
- name: Authentication
description: Gestion de l'authentification
- name: Users
description: Gestion des utilisateurs
Documentation du module Auth
Créez src/docs/auth.doc.yml :
paths:
/auth/login:
post:
tags:
- Authentication
summary: Connexion utilisateur
description: Authentifie un utilisateur et retourne un token JWT
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- email
- password
properties:
email:
type: string
format: email
example: "alice@example.com"
password:
type: string
format: password
example: "password123"
responses:
'200':
description: Connexion réussie
content:
application/json:
schema:
type: object
properties:
message:
type: string
example: "Connexion réussie"
token:
type: string
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
user:
$ref: '#/components/schemas/User'
'401':
description: Email ou mot de passe incorrect
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Documentation du module User
Créez src/docs/user.doc.yml :
paths:
/users:
get:
tags:
- Users
summary: Liste tous les utilisateurs
description: Récupère la liste complète des utilisateurs
responses:
'200':
description: Liste des utilisateurs
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
example:
- id: 1
name: "Alice"
email: "alice@example.com"
- id: 2
name: "Bob"
email: "bob@example.com"
- id: 3
name: "John Doe"
email: "john@example.com"
post:
tags:
- Users
summary: Créer un utilisateur
description: Crée un nouvel utilisateur (nécessite authentification)
security:
- bearerAuth: [ ]
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- name
- email
- password
properties:
name:
type: string
example: "Charlie"
email:
type: string
format: email
example: "charlie@example.com"
password:
type: string
format: password
example: "password123"
responses:
'201':
description: Utilisateur créé
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'401':
description: Non authentifié
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/users/{id}:
get:
tags:
- Users
summary: Récupérer un utilisateur
description: Récupère les détails d'un utilisateur par son ID
parameters:
- in: path
name: id
required: true
schema:
type: integer
description: ID de l'utilisateur
example: 1
responses:
'200':
description: Détails de l'utilisateur
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: Utilisateur non trouvé
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Fusion des fichiers YAML
Créez src/docs/index.ts pour fusionner tous les fichiers :
import YAML from 'yamljs'
import path from 'path'
import {fileURLToPath} from 'url'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
// Charger la configuration principale
const swaggerConfig = YAML.load(path.join(__dirname, 'swagger.config.yml'))
// Charger les documentations des modules
const authDoc = YAML.load(path.join(__dirname, 'auth.doc.yml'))
const userDoc = YAML.load(path.join(__dirname, 'user.doc.yml'))
// Fusionner tous les paths
export const swaggerDocument = {
...swaggerConfig,
paths: {
...authDoc.paths,
...userDoc.paths
}
}
Intégration dans Express
Modifiez src/index.ts :
import 'dotenv/config'
import express from 'express'
import {userRouter} from "@/routes/user.route";
import {authRouter} from "@/routes/auth.route";
import swaggerUi from 'swagger-ui-express'
import {swaggerDocument} from './docs'
export const app = express()
const port = 3000
// Middleware pour parser le JSON
app.use(express.json())
// Documentation Swagger UI
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument, {
customCss: '.swagger-ui .topbar { display: none }',
customSiteTitle: "API Documentation"
}))
// Route d'accueil
app.get('/', (_req, res) => {
res.status(200).send('Bienvenue sur le serveur HTTP')
})
// Utilisation du router utilisateur
// Toutes les routes définies dans userRouter seront préfixées par /users
app.use('/users', userRouter)
app.use('/auth', authRouter)
// Démarrage du serveur
app.listen(port, () => {
console.log(`Mon serveur démarre sur le port ${port}`)
})
Tester la documentation
Lancez votre serveur :
npm run dev
Accédez à http://localhost:3000/api-docs pour voir :
- Documentation interactive organisée par modules
- Interface Swagger UI pour tester les endpoints
- Authentification JWT via le bouton "Authorize" (cliquez, puis entrez votre token)
- Schémas réutilisables pour les types de données communs