Babysitter nestjs
NestJS architecture including modules, dependency injection, guards, interceptors, and microservices patterns.
install
source · Clone the upstream repo
git clone https://github.com/a5c-ai/babysitter
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/a5c-ai/babysitter "$T" && mkdir -p ~/.claude/skills && cp -r "$T/library/specializations/web-development/skills/nestjs" ~/.claude/skills/a5c-ai-babysitter-nestjs && rm -rf "$T"
manifest:
library/specializations/web-development/skills/nestjs/SKILL.mdsource content
NestJS Skill
Expert assistance for building enterprise Node.js applications with NestJS.
Capabilities
- Design modular NestJS applications
- Implement dependency injection patterns
- Create guards, pipes, and interceptors
- Build microservices architectures
- Configure Swagger/OpenAPI documentation
- Set up testing with Jest
Usage
Invoke this skill when you need to:
- Build enterprise-grade APIs
- Implement microservices
- Create modular architecture
- Add authentication/authorization
- Generate API documentation
Inputs
| Parameter | Type | Required | Description |
|---|---|---|---|
| moduleName | string | Yes | Module name |
| features | array | No | guards, pipes, interceptors |
| database | string | No | prisma, typeorm, mongoose |
| microservices | boolean | No | Enable microservices |
Architecture Patterns
Module Structure
// src/users/users.module.ts import { Module } from '@nestjs/common'; import { UsersController } from './users.controller'; import { UsersService } from './users.service'; import { PrismaModule } from '../prisma/prisma.module'; @Module({ imports: [PrismaModule], controllers: [UsersController], providers: [UsersService], exports: [UsersService], }) export class UsersModule {}
Controller with DTOs
// src/users/users.controller.ts import { Controller, Get, Post, Put, Delete, Body, Param, Query, UseGuards, HttpCode, HttpStatus, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse } from '@nestjs/swagger'; import { UsersService } from './users.service'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { UserResponseDto } from './dto/user-response.dto'; import { PaginationDto } from '../common/dto/pagination.dto'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { RolesGuard } from '../auth/guards/roles.guard'; import { Roles } from '../auth/decorators/roles.decorator'; import { CurrentUser } from '../auth/decorators/current-user.decorator'; @ApiTags('users') @Controller('users') @UseGuards(JwtAuthGuard, RolesGuard) @ApiBearerAuth() export class UsersController { constructor(private readonly usersService: UsersService) {} @Get() @ApiOperation({ summary: 'Get all users' }) @ApiResponse({ status: 200, type: [UserResponseDto] }) findAll(@Query() pagination: PaginationDto) { return this.usersService.findAll(pagination); } @Get(':id') @ApiOperation({ summary: 'Get user by ID' }) @ApiResponse({ status: 200, type: UserResponseDto }) findOne(@Param('id') id: string) { return this.usersService.findById(id); } @Post() @Roles('admin') @ApiOperation({ summary: 'Create user' }) @ApiResponse({ status: 201, type: UserResponseDto }) create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } @Put(':id') @ApiOperation({ summary: 'Update user' }) update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) { return this.usersService.update(id, updateUserDto); } @Delete(':id') @Roles('admin') @HttpCode(HttpStatus.NO_CONTENT) @ApiOperation({ summary: 'Delete user' }) remove(@Param('id') id: string) { return this.usersService.delete(id); } } // src/users/dto/create-user.dto.ts import { IsEmail, IsString, MinLength, IsOptional, IsEnum } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class CreateUserDto { @ApiProperty({ example: 'John Doe' }) @IsString() name: string; @ApiProperty({ example: 'john@example.com' }) @IsEmail() email: string; @ApiProperty({ minLength: 8 }) @IsString() @MinLength(8) password: string; @ApiProperty({ required: false, enum: ['user', 'admin'] }) @IsOptional() @IsEnum(['user', 'admin']) role?: string; }
Service with Dependency Injection
// src/users/users.service.ts import { Injectable, NotFoundException, ConflictException } from '@nestjs/common'; import { PrismaService } from '../prisma/prisma.service'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { PaginationDto } from '../common/dto/pagination.dto'; import * as bcrypt from 'bcryptjs'; @Injectable() export class UsersService { constructor(private readonly prisma: PrismaService) {} async findAll(pagination: PaginationDto) { const { page = 1, limit = 10, search } = pagination; const skip = (page - 1) * limit; const [users, total] = await Promise.all([ this.prisma.user.findMany({ where: search ? { name: { contains: search, mode: 'insensitive' } } : undefined, skip, take: limit, select: { id: true, name: true, email: true, role: true, createdAt: true, }, }), this.prisma.user.count({ where: search ? { name: { contains: search, mode: 'insensitive' } } : undefined, }), ]); return { data: users, meta: { total, page, limit, totalPages: Math.ceil(total / limit), }, }; } async findById(id: string) { const user = await this.prisma.user.findUnique({ where: { id }, select: { id: true, name: true, email: true, role: true, createdAt: true, }, }); if (!user) { throw new NotFoundException(`User with ID ${id} not found`); } return user; } async create(dto: CreateUserDto) { const existing = await this.prisma.user.findUnique({ where: { email: dto.email }, }); if (existing) { throw new ConflictException('Email already in use'); } const hashedPassword = await bcrypt.hash(dto.password, 10); return this.prisma.user.create({ data: { ...dto, password: hashedPassword, }, select: { id: true, name: true, email: true, role: true, createdAt: true, }, }); } async update(id: string, dto: UpdateUserDto) { await this.findById(id); if (dto.password) { dto.password = await bcrypt.hash(dto.password, 10); } return this.prisma.user.update({ where: { id }, data: dto, select: { id: true, name: true, email: true, role: true, createdAt: true, }, }); } async delete(id: string) { await this.findById(id); await this.prisma.user.delete({ where: { id } }); } }
Guards and Decorators
// src/auth/guards/jwt-auth.guard.ts import { Injectable, ExecutionContext } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { Reflector } from '@nestjs/core'; import { IS_PUBLIC_KEY } from '../decorators/public.decorator'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { constructor(private reflector: Reflector) { super(); } canActivate(context: ExecutionContext) { const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [ context.getHandler(), context.getClass(), ]); if (isPublic) { return true; } return super.canActivate(context); } } // src/auth/guards/roles.guard.ts import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { ROLES_KEY } from '../decorators/roles.decorator'; @Injectable() export class RolesGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const requiredRoles = this.reflector.getAllAndOverride<string[]>(ROLES_KEY, [ context.getHandler(), context.getClass(), ]); if (!requiredRoles) { return true; } const { user } = context.switchToHttp().getRequest(); return requiredRoles.includes(user.role); } } // src/auth/decorators/roles.decorator.ts import { SetMetadata } from '@nestjs/common'; export const ROLES_KEY = 'roles'; export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles); // src/auth/decorators/current-user.decorator.ts import { createParamDecorator, ExecutionContext } from '@nestjs/common'; export const CurrentUser = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.user; }, );
Interceptors
// src/common/interceptors/transform.interceptor.ts import { Injectable, NestInterceptor, ExecutionContext, CallHandler, } from '@nestjs/common'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; export interface Response<T> { data: T; meta?: Record<string, any>; } @Injectable() export class TransformInterceptor<T> implements NestInterceptor<T, Response<T>> { intercept(context: ExecutionContext, next: CallHandler): Observable<Response<T>> { return next.handle().pipe( map((data) => { if (data?.data && data?.meta) { return data; } return { data }; }), ); } }
Best Practices
- Use modules for feature encapsulation
- Leverage dependency injection
- Implement DTOs for validation
- Use guards for authorization
- Generate OpenAPI documentation
Target Processes
- enterprise-api-development
- microservices-architecture
- backend-development
- nestjs-application