Aller au contenu

d

Validation et ESLint

Il y a généralement des contraintes que nous voulons appliquer aux données qui sont stockées dans la base de données de notre application. Notre application ne devrait pas accepter les notes dont la propriété content est manquante ou vide. La validité de la note est vérifiée dans le gestionnaire de route :

app.post('/api/notes', (request, response) => {
  const body = request.body
  if (body.content === undefined) {    return response.status(400).json({ error: 'content missing' })  }
  // ...
})

Si la note ne possède pas la propriété content, nous répondons à la requête avec le code d'état 400 bad request.

Une façon plus intelligente de valider le format des données avant de les stocker dans la base de données, est d'utiliser la fonctionnalité validation disponible dans Mongoose.

Nous pouvons définir des règles de validation spécifiques pour chaque champ du schéma :

const noteSchema = new mongoose.Schema({
  content: {    type: String,    minLength: 5,    required: true  },  date: {     type: Date,    required: true  },  important: Boolean
})

Le champ contenu doit désormais comporter au moins cinq caractères. Le champ date est défini comme obligatoire, ce qui signifie qu'il ne peut pas être manquant. La même contrainte est également appliquée au champ contenu, puisque la contrainte de longueur minimale permet au champ d'être manquant. Nous n'avons pas ajouté de contraintes au champ important, sa définition dans le schéma n'a donc pas changé.

Les validateurs minLength et required sont built-in et fournis par Mongoose. La fonctionnalité Mongoose custom validator nous permet de créer de nouveaux validateurs, si aucun des validateurs intégrés ne couvre nos besoins.

Si nous essayons de stocker dans la base de données un objet qui ne respecte pas l'une des contraintes, l'opération déclenchera une exception. Modifions notre gestionnaire pour la création d'une nouvelle note afin qu'il transmette toute exception potentielle au middleware de gestion des erreurs :

app.post('/api/notes', (request, response, next) => {  const body = request.body

  const note = new Note({
    content: body.content,
    important: body.important || false,
    date: new Date(),
  })

  note.save()
    .then(savedNote => {
      response.json(savedNote)
    })
    .catch(error => next(error))})

Développons le gestionnaire d'erreurs pour traiter ces erreurs de validation :

const errorHandler = (error, request, response, next) => {
  console.error(error.message)

  if (error.name === 'CastError') {
    return response.status(400).send({ error: 'malformatted id' })
  } else if (error.name === 'ValidationError') {    return response.status(400).json({ error: error.message })  }

  next(error)
}

Lorsque la validation d'un objet échoue, nous renvoyons le message d'erreur par défaut suivant de Mongoose :

fullstack content

Nous remarquons que le backend a maintenant un problème : les validations ne sont pas effectuées lors de l'édition d'une note. La documentation explique quel est le problème, les validations ne sont pas exécutées par défaut lorsque findOneAndUpdate est exécuté.

La correction est simple. Reformulons aussi un peu le code de la route :

app.put('/api/notes/:id', (request, response, next) => {
  const { content, important } = request.body
  Note.findByIdAndUpdate(
    request.params.id, 
    { content, important },    { new: true, runValidators: true, context: 'query' }  ) 
    .then(updatedNote => {
      response.json(updatedNote)
    })
    .catch(error => next(error))
})

Déploiement du backend de la base de données en production

L'application devrait fonctionner presque telle quelle dans Heroku. Nous devons générer un nouveau build de production du frontend en raison des modifications que nous avons apportées à notre frontend.

Les variables d'environnement définies dans dotenv ne seront utilisées que lorsque le backend n'est pas en mode production, c'est-à-dire Heroku.

Nous avons défini les variables d'environnement pour le développement dans le fichier .env, mais la variable d'environnement qui définit l'URL de la base de données en production doit être définie sur Heroku avec la commande heroku config:set.

heroku config:set MONGODB_URI=mongodb+srv://fullstack:secretpasswordhere@cluster0-ostce.mongodb.net/note-app?retryWrites=true

NB: si la commande provoque une erreur, donnez la valeur de MONGODB_URI entre apostrophes :

heroku config:set MONGODB_URI='mongodb+srv://fullstack:secretpasswordhere@cluster0-ostce.mongodb.net/note-app?retryWrites=true'

L'application devrait maintenant fonctionner. Parfois, les choses ne se passent pas comme prévu. S'il y a des problèmes, les logsheroku seront là pour vous aider. Ma propre application n'a pas fonctionné après avoir effectué les changements. Les journaux montraient ce qui suit :

fullstack content

Pour une raison quelconque, l'URL de la base de données était indéfinie. La commande heroku config a révélé que j'avais accidentellement défini l'URL dans la variable d'environnement MONGO_URL, alors que le code s'attendait à ce qu'elle soit dans MONGODB_URI.

Vous pouvez trouver le code de notre application actuelle dans son intégralité dans la branche part3-5 de ce dépôt GitHub.

Lint

Avant de passer à la partie suivante, nous allons jeter un coup d'oeil à un outil important appelé lint. Wikipedia dit ce qui suit à propos de lint :

Généralement, lint ou un linter est tout outil qui détecte et signale les erreurs dans les langages de programmation, y compris les erreurs stylistiques. Le terme de comportement de type lint est parfois appliqué au processus de signalisation de l'utilisation suspecte du langage. Les outils de type linter effectuent généralement une analyse statique du code source.

Dans les langages compilés à typage statique comme Java, les IDE comme NetBeans peuvent signaler les erreurs dans le code, même celles qui sont plus que de simples erreurs de compilation. Des outils supplémentaires pour effectuer une analyse statique comme checkstyle, peuvent être utilisés pour étendre les capacités de l'IDE afin de signaler également les problèmes liés au style, comme l'indentation.

Dans l'univers JavaScript, le principal outil d'analyse statique, autrement dit de "linting", est ESlint.

Installons ESlint comme une dépendance de développement au projet principal avec la commande :

npm install eslint --save-dev

Après cela, nous pouvons initialiser une configuration ESlint par défaut avec la commande :

npx eslint --init

Nous allons répondre à toutes les questions :

fullstack content

La configuration sera sauvegardée dans le fichier .eslintrc.js :

module.exports = {
    'env': {
        'commonjs': true,
        'es2021': true,
        'node': true
    },
    'extends': 'eslint:recommended',
    'parserOptions': {
        'ecmaVersion': 'latest'
    },
    'rules': {
        'indent': [
            'error',
            4
        ],
        'linebreak-style': [
            'error',
            'unix'
        ],
        'quotes': [
            'error',
            'single'
        ],
        'semi': [
            'error',
            'never'
        ]
    }
}

Changeons immédiatement la règle concernant l'indentation, de sorte que le niveau d'indentation soit de deux espaces.

"indent": [
    "error",
    2
],

L'inspection et la validation d'un fichier comme index.js peuvent être effectuées avec la commande suivante :

npx eslint index.js

Il est recommandé de créer un script npm séparé pour le linting :

{
  // ...
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    // ...
    "lint": "eslint ."  },
  // ...
}

Maintenant, la commande npm run lint vérifiera chaque fichier du projet.

Les fichiers du répertoire build seront également vérifiés lors de l'exécution de la commande. Nous ne voulons pas que cela se produise, et nous pouvons y parvenir en créant un fichier .eslintignore à la racine du projet avec le contenu suivant :

build

Cela fait en sorte que le répertoire entier build ne soit pas vérifié par ESlint.

Lint a beaucoup de choses à dire sur notre code :

fullstack content

Ne corrigeons pas ces problèmes pour l'instant.

Une meilleure alternative à l'exécution du linter depuis la ligne de commande est de configurer un eslint-plugin à l'éditeur, qui exécute le linter en continu. En utilisant le plugin, vous verrez immédiatement les erreurs dans votre code. Vous pouvez trouver plus d'informations sur le plugin ESLint de Visual Studio ici.

Le plugin VS Code ESlint soulignera les violations de style par une ligne rouge :

fullstack content

Cela permet de repérer facilement les erreurs et de les corriger immédiatement.

ESlint dispose d'une vaste gamme de règles qu'il est facile de mettre en oeuvre en modifiant le fichier .eslintrc.js.

Ajoutons la règle eqeqeq qui nous avertit, si l'égalité est vérifiée avec autre chose que l'opérateur triple égal. La règle est ajoutée sous le champ rules dans le fichier de configuration.

{
  // ...
  'rules': {
    // ...
   'eqeqeq': 'error',
  },
}

Pendant que nous y sommes, apportons quelques autres modifications aux règles.

Empêchons les espaces de fin inutiles en fin de ligne, exigeons qu'il y ait toujours un espace avant et après les accolades, et exigeons également une utilisation cohérente des espaces dans les paramètres des fonctions flèches.

{
  // ...
  'rules': {
    // ...
    'eqeqeq': 'error',
    'no-trailing-spaces': 'error',
    'object-curly-spacing': [
        'error', 'always'
    ],
    'arrow-spacing': [
        'error', { 'before': true, 'after': true }
    ]
  },
}

Notre configuration par défaut utilise un ensemble de règles prédéterminées provenant de eslint:recommended :

'extends': 'eslint:recommended',

Cela inclut une règle qui met en garde contre les commandes console.log. La désactivation d'une règle peut être accomplie en définissant sa "valeur" comme 0 dans le fichier de configuration. Faisons cela pour la règle no-console en attendant.

{
  // ...
  'rules': {
    // ...
    'eqeqeq': 'error',
    'no-trailing-spaces': 'error',
    'object-curly-spacing': [
        'error', 'always'
    ],
    'arrow-spacing': [
        'error', { 'before': true, 'after': true }
    ],
    'no-console': 0  },
}

NB lorsque vous apportez des modifications au fichier .eslintrc.js, il est recommandé d'exécuter le linter depuis la ligne de commande. Cela permettra de vérifier que le fichier de configuration est correctement formaté :

fullstack content

Si quelque chose ne va pas dans votre fichier de configuration, le plugin lint peut se comporter de manière assez erratique.

De nombreuses entreprises définissent des normes de codage qui sont appliquées dans toute l'organisation par le biais du fichier de configuration ESlint. Il n'est pas recommandé de réinventer la roue encore et encore, et cela peut être une bonne idée d'adopter une configuration prête à l'emploi du projet de quelqu'un d'autre dans le vôtre. Récemment, de nombreux projets ont adopté le guide de style Javascript d'Airbnb en utilisant la configuration ESlint d'Airbnb.

Vous pouvez trouver le code de notre application actuelle dans son intégralité dans la branche part3-7 de ce dépôt GitHub.