Este tutorial está diseñado para guiar a quienes desean aprender más acerca de NestJS. Es ideal para un nivel medio.
NestJS es un framework progresivo de Node.js para construir aplicaciones backend modernas y escalables, aprovechando TypeScript y principios de arquitectura robustos. Esta guía de nivel intermedio explora la estructura modular (Modules), el rol de Controladores y Proveedores (Servicios, Repositorios), profundiza en la Inyección de Dependencias, y cubre los componentes clave del framework como Decoradores, Pipes (Validación, Transformación), Guards (Autenticación, Autorización) e Interceptors (Lógica extra en peticiones/respuestas). Se introduce la integración con bases de datos y se aborda la importancia de las pruebas automatizadas, permitiendo construir APIs y microservicios eficientes y mantenibles.
El 'Hola, mundo' en NestJS es un controlador básico dentro de un módulo que responde a una petición. A nivel intermedio, se enfatiza la estructura modular.
import { Controller, Get } from '@nestjs/common';
import { Module } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
@Controller()
export class AppController {
@Get()
getHello(): string {
return 'Hola, mundo';
}
}
@Module({
imports: [],
controllers: [AppController],
providers: [],
})
export class AppModule {}
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
console.log('Aplicación escuchando en http://localhost:3000');
}
bootstrap();
Resultado:
Hola, mundo
Familiarizarse con estos comandos es esencial para interactuar eficientemente con NestJS:
npm install -g @nestjs/cli
nest new proyecto-backend --package-manager npm
npm run start:dev
npm run build
npm run start:prod
nest g module nombre-modulo
nest g controller nombre-controlador --no-spec
nest g service nombre-servicio --no-spec
nest g class common/dto/create-item.dto --no-spec
nest g pipe pipes/validation --no-spec
nest g guard guards/auth --no-spec
nest g interceptor interceptors/transform --no-spec
nest g resource items --no-spec
npm install @nestjs/typeorm typeorm pg
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe()); // Aplica Pipe de validación globalmente
await app.listen(3000);
console.log('Aplicación escuchando en http://localhost:3000');
}
bootstrap();
import { Controller, UseGuards, Get } from '@nestjs/common';
import { AuthGuard } from './auth.guard'; // Tu Guard de autenticación
@Controller('admin')
@UseGuards(AuthGuard)
export class AdminController {
@Get('dashboard')
getDashboard() { return 'Panel de administración'; }
}
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { TransformInterceptor } from './transform.interceptor'; // Tu Interceptor de transformación
@Controller('data')
export class DataController {
@Get('items')
@UseInterceptors(TransformInterceptor) // Aplica solo a este método
getItems() { return [{ id: 1, name: 'Item 1' }]; }
}
Comprender estos conceptos fundamentales te ayudará a dominar NestJS de forma más organizada y eficiente:
Arquitectura Basada en Módulos:
NestJS estructura las aplicaciones en módulos (`@Module`) que agrupan controladores, proveedores y otros módulos relacionados. Los módulos definen el alcance de los proveedores y ayudan a organizar la aplicación en funcionalidades cohesivas y reutilizables.
Controladores (`@Controller`):
Responsables de manejar las peticiones HTTP y definir los endpoints de la API. Utilizan decoradores de métodos (`@Get`, `@Post`, `@Put`, `@Delete`, `@Patch`) para manejar diferentes verbos HTTP y decoradores de parámetros (`@Body`, `@Param`, `@Query`, `@Headers`) para extraer datos de la petición.
Proveedores (`@Injectable`):
Clases (servicios, repositorios, fábricas, etc.) que contienen la lógica de negocio de la aplicación y la interacción con fuentes de datos o servicios externos. Son 'inyectables' en otros componentes y se gestionan por el contenedor de Inyección de Dependencias de NestJS.
Inyección de Dependencias (DI):
NestJS utiliza un robusto sistema de DI similar al de Angular. Permite a las clases declarar sus dependencias (otros proveedores) en su constructor, y NestJS se encarga de crear y proporcionar las instancias necesarias. Esto promueve el bajo acoplamiento y facilita las pruebas.
Decoradores:
Características de TypeScript (y una propuesta de estándar para JavaScript) que NestJS utiliza extensivamente para añadir metadatos y definir la estructura de la aplicación. Decoradores como `@Module`, `@Controller`, `@Injectable`, y los decoradores de enrutamiento y parámetros son fundamentales.
Pipes (`@Pipe`):
Clases que se utilizan para dos propósitos principales: Transformación de datos (ej: convertir un string a número, aplicar valores por defecto) y Validación de datos (ej: verificar que un DTO cumpla ciertas reglas). Se pueden aplicar a nivel global, de controlador, ruta o parámetro.
Guards (`@Guard`):
Se utilizan para determinar si una petición debe ser manejada por el controlador o no. Son ideales para implementar lógica de autenticación (verificar credenciales) y autorización (verificar permisos de usuario) antes de que se ejecute el código del handler de ruta.
Interceptors (`@Interceptor`):
Permiten añadir lógica adicional en puntos específicos del ciclo de vida de una petición o respuesta. Son útiles para: transformar el valor de retorno de un handler, interceptar y manejar excepciones, añadir lógica de logging antes/después de la petición, o añadir funcionalidades de caché.
Custom Decorators:
NestJS te permite crear tus propios decoradores personalizados para extraer y procesar información específica del objeto de petición de forma reutilizable (ej: obtener el usuario autenticado del request, extraer headers específicos).
Integración con Bases de Datos (ORMs/ODMs):
NestJS no impone una base de datos o ORM/ODM específico, pero se integra muy bien con opciones populares como TypeORM y Prisma (para bases de datos relacionales) o Mongoose (para MongoDB). La integración se gestiona a través de módulos dedicados.
Fundamentos de Testing:
NestJS está diseñado pensando en la testeabilidad. El sistema de módulos y la DI facilitan escribir pruebas unitarias para servicios y controladores, así como pruebas de integración para módulos o partes de la aplicación. El CLI genera archivos de pruebas (`.spec.ts`) por defecto.
Algunos ejemplos de aplicaciones prácticas donde se utiliza NestJS:
Construcción completa de APIs RESTful con validación y transformación de datos:
Desarrollar APIs robustas implementando lógica CRUD en servicios, utilizando DTOs y ValidationPipe para validar datos de entrada, y Pipes de transformación para ajustar formatos. Todo ello organizado en módulos temáticos.
Implementación de sistemas de autenticación (JWT, OAuth) y autorización basada en roles:
Proteger endpoints utilizando Guards para verificar tokens de acceso o sesiones, y controlar el acceso a funcionalidades específicas basándose en los roles o permisos del usuario autenticado.
Manejo centralizado de errores, logging y transformación de respuestas:
Utilizar Interceptors para implementar una estrategia global de manejo de errores (capturar excepciones, formatear respuestas de error), logging de peticiones/respuestas o transformar el formato de los datos de salida (ej: envolver la respuesta en un objeto `data`).
Integración y gestión de datos con bases de datos SQL y NoSQL:
Conectar tu aplicación a bases de datos utilizando módulos de integración para TypeORM, Prisma o Mongoose, definir tus esquemas/entidades e implementar la lógica de acceso a datos en servicios/repositorios.
Implementación de funcionalidades en tiempo real con WebSockets:
Utilizar el soporte integrado de NestJS para crear gateways de WebSockets (`@WebSocketGateway`) y manejar mensajes entrantes (`@SubscribeMessage`) para construir funcionalidades en tiempo real como chats, notificaciones o dashboards en vivo.
Creación de microservicios basados en NestJS:
Desarrollar múltiples servicios pequeños y enfocados que se comuniquen entre sí utilizando las estrategias de transporte de NestJS (TCP, Redis, gRPC, NATS, etc.), aprovechando la arquitectura modular y la DI para mantenerlos desacoplados.
Aquí tienes algunas recomendaciones para facilitar tus inicios en NestJS:
Entiende la Arquitectura Modular:
NestJS se basa en módulos. Aprende a organizar tu aplicación dividiendo funcionalidades en módulos coherentes. Esto mejora la mantenibilidad, la escalabilidad y la reusabilidad del código.
Domina la Inyección de Dependencias:
Es un concepto central en NestJS. Practica cómo inyectar servicios, repositorios u otros proveedores en tus clases (controladores, servicios) a través del constructor. Entender los proveedores y sus scopes es clave.
Utiliza el CLI de NestJS de Forma Eficiente:
El CLI (`nest g module`, `nest g controller`, `nest g service`, `nest g resource`) te ahorra mucho tiempo generando el boilerplate y asegurando que tus componentes sigan las convenciones del framework. Úsalo siempre que puedas.
Comprende el Propósito de Pipes, Guards e Interceptors:
Estos tres tipos de componentes son pilares de la arquitectura de NestJS para añadir lógica en diferentes fases de la petición. Dedica tiempo a entender cuándo usar cada uno (Validación/Transformación, Autorización, Lógica AOP/Logging/Transformación de respuesta).
Integra una Base de Datos Temprano en tu Aprendizaje:
La mayoría de las aplicaciones backend interactúan con una base de datos. Aprende a integrar NestJS con un ORM (como TypeORM o Prisma) o un ODM (como Mongoose para MongoDB) para manejar la persistencia de datos. El módulo `@nestjs/typeorm` o `@nestjs/mongoose` son buenos puntos de partida.
Empieza a Escribir Pruebas Automatizadas:
NestJS está diseñado para ser testeable. La DI y la arquitectura modular facilitan la escritura de pruebas unitarias para tus servicios y pruebas de integración para controladores o módulos. El CLI genera archivos `.spec.ts` por defecto; aprovéchalos.
Aprovecha TypeScript al Máximo:
NestJS está construido con TypeScript. Utiliza el tipado estático, las interfaces, los decoradores y otras características de TypeScript para escribir código más robusto, legible y fácil de mantener.
Configura Variables de Entorno:
Usa variables de entorno (con paquetes como `@nestjs/config`) para gestionar la configuración de tu aplicación (credenciales de base de datos, puertos, claves API) sin hardcodearlas en tu código. Esto es esencial para desplegar en diferentes entornos.
Si te interesa NestJS, también podrías explorar estas herramientas:
Amplía tus conocimientos con estos enlaces y materiales: