Tag: nestjs, nodejs, typescript, backend, dependency-injection, architecture
Livello: intermedio
TL;DR: Framework Node.js opinionated su TypeScript con architettura modulare a blocchi ispirata ad Angular, Dependency Injection nativa ed ecosistema robusto per API enterprise.
Architettura basata su moduli, controller e provider collegati tramite decoratori TypeScript.
I controller gestiscono il routing HTTP e mappano le richieste verso i service.
I provider incapsulano la logica di business e vengono iniettati tramite il container IoC.
Dependency Injection basata su costruttore e token di iniezione generati dai tipi o da stringhe/simboli.
Middleware eseguiti prima del route handler, utili per logging, manipolazione header o parsing raw body.
Guards valutano i permessi a runtime prima dei controller restituendo un booleano (autorizzazione e RBAC).
Interceptors implementano la programmazione orientata agli aspetti per trasformare payload o gestire caching e timeout.
Pipes trasformano i tipi e validano i dati in ingresso sfruttando librerie come class-validator.
Exception Filters catturano e standardizzano la risposta di errore HTTP verso il client.
Scopi del ciclo di vita dei provider: Singleton (default), Request (per singola richiesta) e Transient.
Q: Qual e' la differenza pratica tra Middleware, Guard e Interceptor in NestJS?R: Il Middleware intercetta la richiesta a basso livello stile Express. La Guard stabilisce esclusivamente se la richiesta puo' procedere in base ai permessi. L'Interceptor avvolge l'esecuzione del metodo, permettendomi di modificare sia la chiamata in entrata sia la risposta asincrona o il flusso RxJS in uscita.
Q: Come gestisci l'iniezione delle dipendenze per interfacce TypeScript o configurazioni dinamiche?R: TypeScript cancella le interfacce a runtime, quindi uso un token esplicito con @Inject('CUSTOM_TOKEN') associato a un provider con sintassi useClass, useValue o useFactory all'interno del modulo.
Q: Quando e' sconsigliato usare il provider scope Scope.REQUEST?R: Evito Scope.REQUEST nei percorsi critici per le performance, perche' ricrea l'intera catena di dipendenze a ogni richiesta HTTP, aumentando sensibilmente l'allocazione di memoria e la latenza del garbage collector.
Dimenticare di esportare un provider nell'array exports del modulo proprietario prima di usarlo in un modulo importatore.
Dipendenze circolari tra moduli o service non risolte con forwardRef().
Abuso di Scope.REQUEST che degrada il throughput complessivo dell'applicazione.
Configurazione globale di ValidationPipe omessa, che impedisce la validazione automatica dei DTO via class-validator.
Mutazione diretta dello stato condiviso all'interno di provider con scope Singleton durante richieste concorrenti.
# Installazione CLI e avvio progetto
npm i -g @nestjs/cli
nest new my-nest-api
nest g resource users
TypeScript
// DTO con validazione automatica
import { IsEmail, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
@IsEmail()
email: string;
@IsString()
@MinLength(8)
password: string;
}
TypeScript
// Controller con Guard, Pipe e Iniezione
import { Controller, Post, Body, UseGuards, UsePipes, ValidationPipe } from '@nestjs/common';
import { UsersService } from './users.service';
import { CreateUserDto } from './dto/create-user.dto';
import { AuthGuard } from '../auth/auth.guard';
@Controller('users')
@UseGuards(AuthGuard)
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Post()
@UsePipes(new ValidationPipe({ whitelist: true, forbidNonWhitelisted: true }))
async create(@Body() dto: CreateUserDto) {
return this.usersService.create(dto);
}
}
TypeScript
// Custom Provider con Factory Token
export const DATABASE_CONNECTION = Symbol('DATABASE_CONNECTION');
export const databaseProvider = {
provide: DATABASE_CONNECTION,
useFactory: async (configService: ConfigService) => {
return createPool(configService.get('DATABASE_URL'));
},
inject: [ConfigService],
};
[ ] Sequenza di esecuzione della Request Lifecycle (Middleware -> Guards -> Interceptors -> Pipes -> Controller -> Interceptors -> Exception Filters)
[ ] Configurazione dinamica dei moduli asincroni con convenzione registerAsync o forRootAsync
[ ] Integrazione di RxJS per la gestione degli stream all'interno degli Interceptors
[x] Concetti base di Controller, Service e Moduli
[x] Utilizzo standard dei decoratori @Get, @Post, @Body, @Param, @Query
Documentazione ufficiale NestJS (docs.nestjs.com)