En mi vida cotidiana como developer, he perdido bastante tiempo resolviendo bugs tan tontos de este tipo, este validación debería ser un must to do en todos tus proyectos. Se los recomiendo.
Módulos de NestJS
Programación Modular y Deployment en Nest GS
Encapsulación de Lógica en Módulos con NestJS
Programación Modular en NestJS: Controladores y Entidades
Interacción entre Módulos en NestJS: Servicios y Controladores
Inyección de Dependencias en Arquitectura de Software
Tipos de Providers en NestJS: Use Class y Use Value
useFactory
Uso de Módulos Globales en NestJS para Inyecciones Compartidas
Configuración de entornos
Configuración y uso de variables de entorno en NestJS
Configuración de Ambientes con Archivos .env en Node.js
Tipado seguro en TypeScript para configuración de aplicaciones
Validación de Variables de Entorno con Joi en Node.js
Documentación
Documentación automática de APIs con NestJS y Swagger
Documentación de API con NestJS y Swagger
Deploy
Deployment de Aplicaciones Node.js en Heroku
Deployment de Aplicaciones en Heroku: Configuración y Solución de Errores
Próximos pasos
Inyección de Dependencias en APIs con Heroku
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Las variables de entorno son sensibles, pueden ser requeridas o no, pueden ser un string o un number. Validemos tus variables de entorno para evitar errores u omisiones de las mismas.
Instala la dependencia Joi con el comando npm instal joi --save
. La misma nos dará las herramientas para realizar validaciones de nuestras variables de entorno.
Importa Joi en el módulo de tu aplicación y a través de la propiedad validationSchema
del objeto que recibe el ConfigModule crea el tipado y las validaciones de tus variables de entorno.
import { ConfigModule } from '@nestjs/config';
import * as Joi from 'joi';
import config from './config';
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: '.env',
load: [config],
isGlobal: true,
validationSchema: Joi.object({
API_KEY: Joi.string().required(),
DATABASE_NAME: Joi.string().required(),
DATABASE_PORT: Joi.number().required(),
})
}),
],
],
})
export class AppModule {}
Lo que hace Joi es asegurar que, en el archivo .env
, existan las variables de entorno indicadas dependiendo si son obligatorias o no, además de validar el tipo para no ingresar un string donde debería ir un number.
En equipos de trabajo profesional, quienes suelen desplegar las aplicaciones en los entornos es el equipo DevOpsy ellos no necesariamente saben qué variables de entorno necesita tu aplicación y de qué tipo son. Gracias a esta configuración, tu app emitirá mensajes de error claros por consola cuando alguna variable no sea correcta.
npm install --save joi
// src/app.module.ts
import * as Joi from 'joi'; // 👈
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: enviroments[process.env.NODE_ENV] || '.env',
load: [config],
isGlobal: true,
validationSchema: Joi.object({ // 👈
API_KEY: Joi.number().required(),
DATABASE_NAME: Joi.string().required(),
DATABASE_PORT: Joi.number().required(),
}),
}),
...
],
...
})
export class AppModule {}
Contribución creada por: Kevin Fiorentino.
Aportes 16
Preguntas 2
En mi vida cotidiana como developer, he perdido bastante tiempo resolviendo bugs tan tontos de este tipo, este validación debería ser un must to do en todos tus proyectos. Se los recomiendo.
Genial, este tipo de configuración, esto nos ayuda es a fallar lo antes posible y así evitar problemas mas serios luego cuando el código sea mas grande y también para evitar errores mas costosos los cuales serian directamente en producción 👍
Como dato, si importas joi así import Joi from 'joi';
te da errores de compilación, asi que tienes que ponerlo si o si como el profesor import * as Joi from 'joi';
Me tocó hacer lo mismo pero con class-validator, dejo mi aporte por si a alguien le sirve:
.env.validation.ts
import { IsEnum, IsNumber, IsString, validateSync } from 'class-validator';
import { plainToClass } from 'class-transformer';
import { Environment } from '../src/common/models/environment.model';
class EnvironmentVariables {
// Environment
@IsString()
@IsEnum(Environment)
ENV: Environment;
// Server config
@IsNumber()
PORT: number;
@IsString()
END_POINT: string;
}
export function validate(config: Record<string, unknown>) {
const validatedConfig = plainToClass(EnvironmentVariables, config, {
enableImplicitConversion: true,
});
const errors = validateSync(validatedConfig, {
skipMissingProperties: false,
});
if (errors.length > 0) {
throw new Error(`ENV validation error` + errors.toString());
}
return validatedConfig;
}
}
configuration.ts:
import { registerAs } from '@nestjs/config';
export default registerAs('config', () => {
return {
environment: process.env.ENV,
server: {
port: parseInt(process.env.PORT, 10) || 3000,
endpoint: process.env.END_POINT,
},
};
});
app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import config from '../config/configuration';
import { validate } from 'config/env.validation';
import { LoggerMiddleware } from './common/middleware/appLogger.middleware';
@Module({
imports: [
ConfigModule.forRoot({
load: [config],
validate,
isGlobal: true,
}),
],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer): void {
consumer.apply(LoggerMiddleware).forRoutes('*');
}
}
Yo he sido ese devops al que le a faltado una variable de entorno durante el despliegue de una aplicación, y he pasado mucgas horas buscando el fallo en la aplicación, así que apoyo la validación de las variables de entorno.
El tipado en las variables de ambiente nos ayuda a solucionar errores faciles en tiempos de desarrollo.
En el momento de despliegue cuando un servidor externo nos envia variables de ambiente, tenemos que validar los tipos de datos que recibimos en nuestras variables de entorno.
Instalamos npm install joi
app.module.ts
importamos joi
import * as Joi from 'joi';
...
@Module({
imports: [
ConfigModule.forRoot({
envFilePath: environments[process.env.NODE_ENV] || '.env',
load: [config],
isGlobal: true,
validationSchema: Joi.object({
API_KEY: Joi.number().required(),
DATABASE_NAME: Joi.string().required(),
DATABASE_PORT: Joi.number().required(),
}),
}),
...
})
Corres la aplicacion npm run start:dev
El output de errores en consola daria lo siguiente
Si la variable no se setea:
throw new Error(`Config validation error: ${error.message}`);
^
Error: Config validation error: "DATABASE_PORT" is required
Si la variable se seteo con otro tipo de dato:
throw new Error(`Config validation error: ${error.message}`);
^
Error: Config validation error: "DATABASE_PORT" must be a number
Si estás usando el repo del profesor con nest v7, para instalar joi seguramente tendrás que hacer
npm i joi@17.4.0 --legacy-peer-deps --save
No me estaba funcionando las validaciones al correr el servidor, Tuve que instalar:
npm install --save-dev @types/joi
luego ir al archivo: tsconfig.json y agregar la siguiente configuración:
"esModuleInterop": true
Tambien podemos pasar las siguientes opciones de validación:
allowUnknown: le dice a Nestjs si permitir claves que no se encuentran definidas en nuestro esquema.
abortEarly: lanza una excepción si hace falta una variable de entorno en nuestra configuración.
ConfigModule.forRoot({
envFilePath: envirotments[process.env.NODE_ENV] || '.env',
isGlobal: true,
load: [Configuration],
validationSchema: Joi.object({
NODE_ENV: Joi.string().valid('dev', 'stag', 'prod').required(),
API_KEY: Joi.string().required(),
DB_NAME: Joi.string().required(),
DB_PORT: Joi.number().positive().integer().required(),
}),
validationOptions: {
allowUnknown: false,
abortEarly: true,
},
}),
Me encantó esta sección. Personalmente por el trabajo ya he tenido un poco de contacto con NestJS, pero seguía teniendo muchas fallas precisamente por esto, por no tener validaciones y todo mi entorno. Y esto hacía que mi proceso de desarrollo se vaya entorpeciendo cada vez más. Muchas gracias!
Genial las validaciones para evitar bugs!
Hola, les dejo un recurso para hacer el esquema de validacion y la integracion de Zod en Nest. Enlace
La verdad me pareció muy interesante utilizar joi para evitar malas configuraciones.
Muy útil todo hasta ahora, en las implementaciones muchas veces he tenido problemas de tipado en los archivos de configuración y esto viene de maravilla. Muchas gracias!
Me encanta esta feature, cada tanto siempre estos errores ocurren, me lo llevo también para aplicar en otros lenguajes.
Excelente! Puro poder de NestJS.
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?