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
驴Ya tomaste el Curso de Backend con NestJS?
Overview del proyecto: PlatziStore
Encapsular l贸gica en m贸dulos
Interacci贸n entre m贸dulos
Entendiendo la inyecci贸n de dependencias
useValue y useClass
useFactory
Global Module
Configuraci贸n de entornos
M贸dulo de configuraci贸n
Configuraci贸n por ambientes
Tipado en config
Validaci贸n de esquemas en .envs con Joi
Documentaci贸n
Integrando Swagger y PartialType con Open API
Extendiendo la documentaci贸n
Deploy
Configuraci贸n de Heroku
Deploy de NestJS en Heroku
Pr贸ximos pasos
Contin煤a con los cursos de persistencia de datos en NestJS
A煤n no tienes acceso a esta clase
Crea una cuenta y contin煤a viendo este curso
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 {}
Aportes 11
Preguntas 1
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';
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
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('*');
}
}
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!
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.
Genial las validaciones para evitar bugs!
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 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? Crea una cuenta o inicia sesi贸n.