Documentation
Notre API doit être facilement compréhensible pour ses utilisateurs. On pourrait manuellement écrire une documentation, mais :
il est difficile de le garder à jour, on est souvent faignant, ou en retard
Une petite modification au code pourrait modifier le comportement documenté
Un standard de documentation qui s'appelle swagger
et depuis peu openapi
a créé une norme pour la documentation d'un API. La documentation est en form .json
et peu être lue est interprété par un autre process. Il y a même des process qui transforment automatiquement un fichier swagger
en interface HTML pour notre lecture.
Il y a plusieurs façons de documenter un API :
Définition vers le code : on rédige notre
swagger.yml
ouswagger.json
manuellement, et puis on fait tourner un processus qui va créer des fonctions/classes/endpoints pour notre architecture cible (nodejs, php, ruby... etc). Le fichierswagger.*
est la source de vérité de l'application.Personnellement, je n'aime pas cette approche, car le code généré est très répétitif, et parfois pas assez flexible pour ce que je veux faire
Parfois on oublie que le fichier swagger est la source de vérité. On ajoute des fonctions, qui seront décrochées ou bien supprimées plus tard quand on relance le générateur.
Code ver la définition : on fait une sorte de bien structurer et documenter notre code (avec des commentaires), et un
swagger.*
fichier est crée de notre code. Notre code devient la source de vérité.Manuel : on maintient la doc et l'implémentation indépendamment. Très lourd, et facile à oublier ou de ne pas mettre à jour.
Personnellement je préfère qu'on ait une seule source de vérité : notre code source !
Grâce à Typescript, il y a des projets comme tsoa
qui permet d'utiliser la structure Typescript et les commentaires déjà présents dans le code afin d'assembler automatiquement la documentation.
Par contre, tsoa
est un framework qui est opinionated. On est obligé de structurer notre code à leurs normes pour que la documentation soit cohérente :
Orienté objet : on précise un objet par endpoint avec des fonctions dedans pour les opérations type CRUD - cet objet est un
Controller
dans le pattern MVC.Décorateurs : on utilise les décorateurs de typescript pour apporter de l'information concernant les routes, paramètres etc
Routing est opaque : au lieu de créer des routes nous même (comme dans le dernier exemple), on laisse
tsoa
construire notre API dans express selon les décorateurs. C'est le seul point que je n'aime pas, mais l'avantage d'avoir une documentation cohérente fait équilibrer ce désavantage.
Mince ! On est allé un peu trop loin de la remaniage de notre code - il faudrait repasser un modèle orienté objet.
Vous trouverez le projet fonctionnel de ce chapitre ici
Installer tsoa
tsoa
Installer tsoa
(TypeScript Open Api) :
Dans tsconfig.json
il faut activer l'usage des décorateurs TypeScript :
Un objet et ses décorateurs
On transforme nos routes /user
sur le format précisé par tsoa
(dans le fichier src/routes/UserController.ts
) :
Réutilisation de notre class
Crud.ts
Décorateurs
@Route
,@Query
,@Path
,@Body
,@Middlewares
Configurer tsoa
Ensuite, nous allons créer un fichier de configuration pour tsoa
à ./tsoa.json
:
On précise
spec.outputDirectory
pour le fichier avec notre documentation. On le met dans le dossier public qui sera servi comme fichier staticOn précise
routes.routesDir
pour la destination de notre routeur Express.
tsoa
va construire un set de routes automatiquement, ainsi qu'un fichier swagger contenant toute la documentation de notre API. Pour cela, il faudrait lancer un script :
Essayons :
Consultez les nouveaux fichiers créés. On verra de la trace de routes définies dans notre UserController.ts
Ensuite, il faut inclure ce code dans notre server.ts
:
Essayer de lancer votre API. Vos routes /user
devront fonctionner correctement.
Consulter la documentation
Un fichier swagger.json
et disponible dans le dossier public
. Ce fichier pourrait être servi, bien formaté, comme une page web grâce à des librairies open source :
Dans notre fichier server.ts
, on ajoute des lignes pour servir ce contenu :
En lançant l'api, le fichier swagger.json
est disponible à http://localhost:5050/swagger.json.
Sinon, grâce à swagger-ui-express
on peut le consulter sous la route docs
à http://localhost:5050/docs/
Notez surtout que les commentaires dans notre code apparaissent maintenant comme de la documentation de notre API. Génial !
Authentication avec tsoa
tsoa
Au lieu de créer un middleware ad-hoc comme on a fait avant, tsoa
préconise un emplacement fixe pour la logique de note notre sécurisation. Cet emplacement est défini dans ./tsoa.json
, notamment la ligne authenticationModule
Il faut donc convertir notre ancien middleware d'autorisation vers ce nouveau fichier :
Vous remarquerez que tsoa
permet de définir différentes stratégies d'autorisation, et contient aussi la logique pour les scopes (qu'on n'utilise pas dans notre exemple).
Ensuite, pour protéger nos routes, il suffit d'ajouter le décorateur @Security
devant une classe ou méthode :
Après une recompilation (npm run swagger
), la route est désormais sécurisée par notre authentification pas JWT.
Automatiser la recompilation du swagger
Vous avez sûrement remarqué qu'à chaque modification, on est obligé de recompiler les routes de tsoa
. On peut automatiser tout cela en ajoutant une configuration pour nodemon
dans nodemon.json
:
Ici, on lance systématiquement la recompilation des routes avant de lancer le serveur, tout en ignorant le fichier routes.ts
qui est le fichier généré par tsoa
.
On peut simplifier alors notre package.json
, car nodemon.json
est automatiquement lu par nodemon
lors de son exécution :
Déploiement
Il y a quelques fichiers de plus à ajouter à notre configuration de déploiement, notamment le dossier public
qui contient le swagger.json
.
En bref, il faut copier le dossier public
dans le dossier build
après la compilation. Pour cela, on utilise la librairie copyfiles
:
On modifier notre package.json
ainsi :
Pour compiler une version de déploiement, il faut juste émettre dans le terminal :
Dernière mise à jour