Structurer le projet
Let us Commençons par créer un peu de structure dans notre serveur. creating a bit of structure in our server.
Créons quelques repertoires dans src :
src/
- routes/
# Contient nos endpoints
- controllers/
# Contient nos controlleurs MVC
- model/
# Contient les definitions des données
- utility/
- error/
# Contient les outils pour la bonne gestion d'erreur
- ORM/
# Contient les outils pour accéder à la base de données
- server.ts
# Le point d'entrée de notre API Raccourcis Typescript
Notre code va souvent importer des classes et des fonctions des dossiers utility et model. Nous pouvons demander à Typescript de fournir un raccourci que nous pouvons utiliser lors de l'importation à partir de ces dossiers. Modifions tsconfig.json :
Pour utiliser ces chemins avec TypeScript, nous devons installer un paquetage capable de les interpréter :
... et modifiez notre script npm pour utiliser ce module (package.json) :
Gestion d'erreurs
Essayez de rentrer des mauvaises informations via Postman :
Créer un utilisateur doublon
Essayer de passer un champ qui n'est pas une colonne dans la base
Passer du texte dans le query param de la requête index (pour limit et offset)
Afficher, mettre à jour, ou supprimer un utilisateur qui n'existe pas
Pour l'instant, on reçoit un message moche (pas en json) et pas très parlant dans Postman.
Idéalement, pour notre api JSON, nous voulons que les erreurs soient renvoyées en JSON également, et avec des informations qui nous sont utiles !
Renvoyer plutôt du json
Meilleure gestion des codes HTTP :
400: la requête est mauvaise (erreur dans les données entrantes)401: non autorisé403: ressource interdit404: élément pas trouvé500: erreur interne (dernier recours)
Imposer une deuxiume couche de code qui explique en plus de détail ce qui ne va pas :
params-invalidconnection-errorauth/unknown-email
D'abord, on crée une classe qui dérive de la classe générique d'erreur de Javascript, dans src/utility/error/ApiError.ts :
Cette classe contient notamment une fonction permettant d'exporter l'erreur en format JSON selon l'interface IApiError (dans src/utility/error/IApiError.ts) :
Le code est une énumération des différentes possibilités, dans src/utility/error/ErrorCode.ts :
Ensuite, nous allons rédiger un middleware qui prend 4 paramètres pour qu'Express l'utilise pour gérer des erreurs (dans src/utility/error/error-handler.middleware.ts) :
Notez les paramètres de notre DefaultErrorHandler. On accepte comme premier paramètre une erreur inconnue. Ensuite, on construit l'erreur formatée à l'aide de notre classe ApiError. Enfin, on renvoie une réponse avec le code HTTP et le json représentant l'erreur.
Utilisez le DefaultErrorHandler comme middleware sur votre serveur. Ajoutez la ligne suivante dans server.ts :
Un ORM basique
Pour cette démonstration, l'accès à la base de données se fera manuellement afin d'exposer spécifiquement les communications qui ont lieu, et sans abstraire les données derrière des interfaces spécifiques.
Si vous souhaitez utiliser un ORM standard, de nombreuses options existent, telles que TypeORM, Prisma, Sequelize, ...
Le schema
Pour notre ORM simple, nous allons spécifier le schéma de la base de données et tous les types associés dans src/model :
Nous centralisons les schemas SQL de notre base de données. En premier, un SQL qui permet de créer une base de données et donner accès à un utilisateur (src/model/schema/init.sql):
Ensuite, le DDL (Data Definition Language) qui implémente notre schema dans MariaDB (src/model/schema/ddl.sql)::
Au fur et à mesure que vous ajouterez des tables à votre base de données, vous retournerez ce fichier et le mettrez à jour.
Pour jouer avec Typescript, nous allons également créer des définitions de type pour chaque table de la base de données, par exemple, pour la table user (dans src/model/types/IUser.ts) :
Cela signifie qu'une fois que les données sont extraites de la base de données, elles seront correctement typées et que Typescript validera au moment de la compilation les fautes de frappe que nous aurions pu commettre.
Enfin, nous voulons créer une énumération des tables disponibles dans la base de données (dans src/model/DbTable.ts) :
Chaque fois que nous ajouterons une table, nous ajouterons son nom ici. Cela nous permet d'éviter les fautes de frappe.
Le ORM
Nous allons mettre en œuvre un ensemble d'opérations CRUD simples qui sont sans danger pour les types. Voici un ensemble d'interfaces Typescript définissant les différentes requêtes et réponses de notre ORM (src/utility/ORM/interfaces/IORM.ts) :
Nous fournissons l'implémentation simple suivante dans src/utility/ORM/ORM.ts :
Mis à jour