NestJS Modular Architecture
Scalable backend development with NestJS.
Instructions
- Module Structure
src/ ├── main.ts ├── app.module.ts ├── common/ │ ├── decorators/ │ ├── filters/ │ ├── guards/ │ └── interceptors/ └── modules/ └── users/ ├── users.module.ts ├── users.controller.ts ├── users.service.ts ├── dto/ │ ├── create-user.dto.ts │ └── update-user.dto.ts └── entities/ └── user.entity.ts
- Module
// users/users.module.ts import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UsersService } from './users.service';
@Module({ controllers: [UsersController], providers: [UsersService], exports: [UsersService], }) export class UsersModule {}
- Controller
// users/users.controller.ts @Controller('users') export class UsersController { constructor(private readonly usersService: UsersService) {}
@Get() findAll(): Promise<User[]> { return this.usersService.findAll(); }
@Get(':id') findOne(@Param('id') id: string): Promise<User> { return this.usersService.findOne(id); }
@Post() create(@Body() createUserDto: CreateUserDto): Promise<User> { return this.usersService.create(createUserDto); }
@Patch(':id') update( @Param('id') id: string, @Body() updateUserDto: UpdateUserDto, ): Promise<User> { return this.usersService.update(id, updateUserDto); }
@Delete(':id') remove(@Param('id') id: string): Promise<void> { return this.usersService.remove(id); } }
- Service
// users/users.service.ts @Injectable() export class UsersService { constructor(private prisma: PrismaService) {}
async findAll(): Promise<User[]> { return this.prisma.user.findMany(); }
async findOne(id: string): Promise<User> { const user = await this.prisma.user.findUnique({ where: { id } }); if (!user) throw new NotFoundException('User not found'); return user; }
async create(dto: CreateUserDto): Promise<User> { return this.prisma.user.create({ data: dto }); }
async update(id: string, dto: UpdateUserDto): Promise<User> { await this.findOne(id); // Check exists return this.prisma.user.update({ where: { id }, data: dto }); }
async remove(id: string): Promise<void> { await this.findOne(id); await this.prisma.user.delete({ where: { id } }); } }
- DTOs with Validation
// users/dto/create-user.dto.ts import { IsEmail, IsString, MinLength } from 'class-validator';
export class CreateUserDto { @IsString() @MinLength(2) name: string;
@IsEmail() email: string;
@IsString() @MinLength(8) password: string; }
// users/dto/update-user.dto.ts import { PartialType } from '@nestjs/mapped-types';
export class UpdateUserDto extends PartialType(CreateUserDto) {}
- Exception Handling
// common/filters/http-exception.filter.ts @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { catch(exception: HttpException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const status = exception.getStatus();
response.status(status).json({
success: false,
statusCode: status,
message: exception.message,
timestamp: new Date().toISOString(),
});
} }
- Guards
// common/guards/auth.guard.ts @Injectable() export class AuthGuard implements CanActivate { constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> { const request = context.switchToHttp().getRequest(); const token = this.extractToken(request);
if (!token) throw new UnauthorizedException();
try {
const payload = await this.jwtService.verify(token);
request.user = payload;
return true;
} catch {
throw new UnauthorizedException();
}
} }
References
-
NestJS Documentation
-
Prisma with NestJS