Primeros Pasos con NestJS
NestJS organiza las aplicaciones de backend mediante una estructura modular inspirada en patrones de nivel empresarial. En esta guía práctica aprenderás a instalar el CLI, instanciar un nuevo proyecto, comprender su arquitectura interna y construir tus propios módulos, controladores y servicios.
1. Arquitectura y Fundamentos de Componentes
Antes de escribir código o generar archivos con el CLI, es esencial comprender cómo interactúan los componentes fundamentales dentro de un módulo de NestJS:
Explicación de los Componentes Principales:
- Módulo (
@Module): Es la unidad organizativa fundamental en NestJS. Agrupa los controladores y proveedores (servicios) relacionados, delimitando las dependencias y permitiendo construir una arquitectura modular escalable. - Controlador (
@Controller): Es responsable de escuchar las peticiones HTTP externas en rutas específicas (por ejemplo,/users), desempaquetar parámetros o payloads en el body, y llamar a la lógica del servicio correspondiente. - Servicio (
@Injectable): Contiene la lógica de negocio pura (cálculos, transformaciones, llamadas a bases de datos o servicios de terceros). Los servicios se decoran con@Injectable()para ser inyectados automáticamente mediante la Inyección de Dependencias de NestJS.
2. Guía Práctica de Desarrollo (Paso a Paso)
Instalación global de NestJS CLI
El CLI (Command Line Interface) de NestJS permite automatizar la creación de proyectos y la generación de componentes siguiendo las mejores prácticas de la arquitectura Nest.
npm install -g @nestjs/cli
El CLI evita la configuración manual de TypeScript, Webpack/SWC, ESLint y Jest, además de mantener una estructura limpia y estandarizada entre proyectos.
Creación del proyecto base
Ejecuta el comando nest new para inicializar un nuevo proyecto llamado my-nest-app:
nest new my-nest-app
Durante la ejecución, el CLI preguntará qué gestor de paquetes deseas utilizar. Selecciona npm (o yarn / pnpm según tus preferencias).
Inspección de la estructura de archivos
Navega al directorio recién creado y examina los archivos generados:
cd my-nest-app
La estructura resultante se organiza de la siguiente manera:
my-nest-app/
├── src/
│ ├── app.controller.spec.ts # Pruebas unitarias del controlador principal
│ ├── app.controller.ts # Controlador base con ruta de prueba ('/')
│ ├── app.module.ts # Módulo raíz de la aplicación
│ ├── app.service.ts # Servicio base con métodos sencillos
│ └── main.ts # Punto de entrada (inicia el servidor HTTP)
├── test/
│ └── app.e2e-spec.ts # Pruebas end-to-end
├── nest-cli.json # Configuración interna del CLI de Nest
├── package.json # Dependencias y scripts de ejecución
└── tsconfig.json # Configuración del compilador de TypeScript
Explicación de los archivos principales en src/:
main.ts: UtilizaNestFactory.create(AppModule)para instanciar la aplicación e iniciar el servidor en el puerto 3000 por defecto.app.module.ts: Punto focal de montaje de la aplicación. Aquí se registran los controladores y proveedores raíz.app.controller.ts: Contiene manejadores HTTP básicos (por ejemplo,GET /).app.service.ts: Retorna respuestas simples (como"Hello World!").
Ejecución de la aplicación en modo desarrollo
Inicia el servidor local en modo vigilancia (watch mode) para que detecte cambios automáticamente al guardar:
npm run start:dev
Abre tu navegador en http://localhost:3000 para verificar que la aplicación responda correctamente.
Si el puerto 3000 está ocupado en tu equipo, puedes modificar el archivo src/main.ts:
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
async function bootstrap() {
// Instancia la aplicación Nest utilizando el módulo raíz
const app = await NestFactory.create(AppModule);
// Define el puerto de escucha del servidor HTTP (ej: 3001)
await app.listen(3001);
}
bootstrap();
Generación modular con el CLI
Para construir una funcionalidad aislada (por ejemplo, gestión de usuarios), se recomienda generar sus tres capas base: Módulo, Controlador y Servicio.
Abre una nueva pestaña en tu terminal e ingresa los siguientes comandos:
- Comandos Individuales
- Comando Todo en Uno (CRUD Resource)
# 1. Generar el módulo de usuarios
nest generate module users
# 2. Generar el controlador de usuarios
nest generate controller users
# 3. Generar el servicio de usuarios
nest generate service users
# Genera el recurso completo de usuarios (Módulo, Controlador, Servicio, DTOs y Entidades)
nest generate resource users
Puedes usar alias abreviados en la consola: nest g mo users, nest g co users y nest g s users.
Implementación del código de Usuarios
Examina el código generado en src/users/ e implementa la lógica básica de comunicación entre las capas:
import { Injectable } from "@nestjs/common";
// Decorador que marca la clase como inyectable por el contenedor de IoC de NestJS
@Injectable()
export class UsersService {
// Colección simulada en memoria para representar la fuente de datos
private users = [
{ id: 1, name: "Alice", email: "alice@icesi.edu.co" },
{ id: 2, name: "Bob", email: "bob@icesi.edu.co" },
];
// Método para retornar todos los usuarios registrados
findAll() {
return this.users;
}
// Método para retornar un usuario específico según su ID
findOne(id: number) {
return this.users.find((user) => user.id === id);
}
}
import { Controller, Get, Param } from "@nestjs/common";
import { UsersService } from "./users.service";
// Decorador que define la ruta base HTTP '/users' para todas las peticiones de este controlador
@Controller("users")
export class UsersController {
// Inyección de dependencias: Nest inyecta automáticamente la instancia de UsersService
constructor(private readonly usersService: UsersService) {}
// Maneja peticiones HTTP GET a '/users'
@Get()
getAllUsers() {
return this.usersService.findAll();
}
// Maneja peticiones HTTP GET a '/users/:id'
@Get(":id")
getUserById(@Param("id") id: string) {
// Convierte el parámetro de ruta en número antes de pasarlo al servicio
return this.usersService.findOne(Number(id));
}
}
import { Module } from "@nestjs/common";
import { UsersController } from "./users.controller";
import { UsersService } from "./users.service";
// Decorador que registra los controladores y proveedores del módulo
@Module({
controllers: [UsersController],
providers: [UsersService],
})
export class UsersModule {}