Validez les variables d’environnement de Node.js avec Zod et TypeScript
Cessez de lire process.env partout dans le code Node.js. Un fichier env.ts validé avec Zod détecte les secrets manquants au démarrage et fournit à l’application une configuration TypeScript typée.
Imaginez un déploiement un vendredi après-midi. La compilation réussit, le serveur démarre et tout le monde rentre chez soi. Une heure plus tard, les utilisateurs signalent que les connexions échouent. Il s’avère que personne n’a défini JWT_SECRET dans l’environnement de production. L’application a démarré normalement et ne s’est dégradée que lorsque la première requête a atteint le code nécessitant cette valeur manquante.
La consultation répétée de process.env dans toute une base de code rend ce type d’incident probable. Ce qui suit montre comment remplacer cette habitude par un module de configuration validé et typé, en utilisant Zod et TypeScript.
La méthode habituelle
La plupart des codes Node.js récupèrent les paramètres de configuration directement là où ils sont nécessaires : un port dans un fichier, une chaîne de connexion à la base de données dans un autre.
// Some random controller file
const port = process.env.PORT || 3000;
mongoose.connect(process.env.MONGO_URI);
C’est pratique, mais cela présente trois problèmes réels.
- Aucune sécurité de type. En TypeScript,
process.env.PORTest de typestring | undefined. Si l’on souhaite un nombre, chaque point d’appel doit le parser manuellement. - Échecs silencieux. Lorsque
MONGO_URIest absent, le processus ne plante pas au démarrage. Il plante plutôt lorsque cette ligne spécifique est enfin exécutée, éventuellement des heures après un déploiement qui semblait réussi. - Aucune source unique de vérité. Un nouveau venu ne dispose d’aucune liste des variables nécessaires à l’application. Son unique option est de rechercher tout le répertoire pour trouver
process.env.
Un seul fichier de contrôle
La solution consiste à cesser de modifier process.env dans la logique métier. Un seul module, appelons-le env.ts, lit les variables d’environnement une seule fois au démarrage, les valide et exporte un objet fortement typé. Tous les autres modules importent cet objet.
Zod, une bibliothèque de validation de schémas priorisant TypeScript, s’occupe de cette validation.
L’installer
npm install zod
Écrire le schéma
Placer le module dans src/config/env.ts et décrire précisément à quoi doit ressembler l’environnement.
import dotenv from 'dotenv';
import { z } from 'zod';
// Load variables from .env file (if in development)
dotenv.config();
// 1. Define the schema
const envSchema = z.object({
PORT: z.string().transform(Number).default('3000'),
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
MONGO_URI: z.string(),
JWT_SECRET: z.string(),
JWT_EXPIRES_IN: z.string().default('1d'),
});
// 2. Parse the environment against the schema
const _env = envSchema.safeParse(process.env);
// 3. Fail fast if it's invalid
if (!_env.success) {
console.error('Invalid environment variables:', _env.error.format());
process.exit(1); // Crash the app immediately!
}
// 4. Export the typed, validated object
export const env = _env.data;
Que fait le module
- Il définit des attentes.
MONGO_URIest une chaîne de caractères obligatoire.PORTest fourni sous forme de chaîne, et.transform(Number)la convertit, avec une valeur par défaut de 3000.NODE_ENVdoit être l’un des trois valeurs autorisées. - Il génère une erreur rapidement.
safeParses’exécute dès l’import du fichier, il faut donc l’importer en haut de votre point d’entrée, que ce soitapp.tsouserver.ts. Si une variable obligatoire manque ou est mal formatée, le résultat indique une erreur, le message d’erreur précise ce qui ne va pas etprocess.exit(1)arrête le processus avant qu’il ne traite des requêtes. - Il exporte un objet typé. En cas de succès, les données analysées portent les types inférés par Zod, de sorte que
env.PORTest déjà un nombre.
Désormais, tout fichier peut importer env et l’utiliser.
Avantages
- Saut de complétion. En tapant
env.dans votre éditeur, toutes les variables disponibles sont listées. - Aucune solution de secours dispersée. Les modèles
|| "default_value"disparaissent des contrôleurs, car les valeurs par défaut se trouvent dans le schéma. - Dокументation intégrée. Le schéma constitue une liste précise de ce dont l’application a besoin pour fonctionner, répondant ainsi aux questions des nouveaux utilisateurs sur ce qui doit figurer dans
.env.
Une clé secrète manquante empêche désormais un déploiement en quelques secondes, au démarrage, avec un message clair, plutôt que de se manifester sous forme d’un utilisateur mécontent une heure plus tard.