Agent skill
nestjs-validation-and-pipes
Use this skill whenever the user wants to add, refine, or enforce request/response validation, transformation, and sanitization in a NestJS TypeScript backend using Pipes (e.g., ValidationPipe), DTOs, and custom pipes.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/nestjs-validation-and-pipes-agentivecity-skillfactory
SKILL.md
NestJS Validation & Pipes Skill
Purpose
You are a specialized assistant for data validation, transformation, and sanitization in NestJS applications using Pipes and DTOs.
Use this skill to:
- Set up and configure global validation using
ValidationPipe - Design and maintain DTOs with
class-validatorandclass-transformer - Implement custom pipes for parsing, coercion, normalization, and security
- Enforce strict request payload shapes and reject invalid data
- Normalize query params, route params, and headers
- Safely transform incoming data into typed application models
- Provide consistent error responses for validation failures
Do not use this skill for:
- Auth logic (
nestjs-authentication) - Core app scaffolding (
nestjs-project-scaffold) - DB entity design (
nestjs-typeorm-integration) - Frontend form validation (this is server-side NestJS only)
If CLAUDE.md or existing project conventions describe DTO or validation rules, follow them.
When To Apply This Skill
Trigger this skill when the user asks for:
- “Add validation to my NestJS endpoints.”
- “Make sure bad requests are rejected gracefully.”
- “Create DTOs for these request bodies.”
- “Normalize IDs from params to numbers/UUIDs.”
- “Sanitize input to prevent bad data getting into the system.”
- “Customize validation error messages.”
Avoid when:
- Only internal/domain logic is changing with no external input shape changes.
- Only frontend/Next.js validation is being discussed.
Validation Philosophy
When using this skill, follow these principles:
-
DTOs as API contracts
- All external inputs (body, query, params) should be represented by DTOs.
- DTOs clearly define what is allowed and what is not.
-
Fail fast & clearly
- Reject invalid input before it reaches business logic.
- Provide structured, meaningful error responses.
-
Separation of concerns
- Validation & transformation belong in pipes and DTOs.
- Business logic in services should assume validated, typed data.
-
Type safety ≠ validation
- TypeScript types are compile-time only; runtime validation needs
class-validator+ValidationPipeor similar.
- TypeScript types are compile-time only; runtime validation needs
-
Defense in depth
- Validate at boundaries even if frontend also validates.
Basic Setup: Global Validation Pipe
This skill ensures global validation is enabled in main.ts:
// src/main.ts
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({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
transformOptions: {
enableImplicitConversion: true,
},
}),
);
await app.listen(process.env.PORT ?? 3000);
}
bootstrap();
Key options explained:
whitelist: true- Strips unknown properties from the payload.
forbidNonWhitelisted: true- Instead of stripping, it throws if unknown properties are present.
transform: true- Transforms payloads into DTO class instances.
enableImplicitConversion: true- Allows automatic type conversion based on DTO property types (e.g., strings to numbers).
This skill can adjust these based on project preferences (e.g., allowing extra fields in dev).
DTO Design with class-validator & class-transformer
Example DTO for CreateUser
// src/modules/user/dto/create-user.dto.ts
import { IsEmail, IsString, MinLength } from "class-validator";
export class CreateUserDto {
@IsEmail()
email!: string;
@IsString()
@MinLength(8)
password!: string;
@IsString()
name!: string;
}
Example DTO for Query Params
// src/modules/user/dto/list-users.dto.ts
import { IsBoolean, IsInt, IsOptional, IsString, Min, Max } from "class-validator";
import { Type } from "class-transformer";
export class ListUsersDto {
@IsOptional()
@IsInt()
@Min(1)
@Type(() => Number)
page?: number = 1;
@IsOptional()
@IsInt()
@Min(1)
@Max(100)
@Type(() => Number)
limit?: number = 20;
@IsOptional()
@IsString()
search?: string;
@IsOptional()
@IsBoolean()
@Type(() => Boolean)
includeInactive?: boolean = false;
}
This skill should:
- Use
@Type(() => ...)when implicit conversion is not enough or needs to be explicit. - Define sensible defaults.
- Keep DTOs focused and reusable.
Using DTOs in Controllers
This skill ensures controllers are wired to use DTOs correctly:
// src/modules/user/user.controller.ts
import { Body, Controller, Get, Post, Query } from "@nestjs/common";
import { UserService } from "./user.service";
import { CreateUserDto } from "./dto/create-user.dto";
import { ListUsersDto } from "./dto/list-users.dto";
@Controller("users")
export class UserController {
constructor(private readonly userService: UserService) {}
@Post()
create(@Body() dto: CreateUserDto) {
return this.userService.create(dto);
}
@Get()
findAll(@Query() query: ListUsersDto) {
return this.userService.findAll(query);
}
}
This skill can also adapt to @Param() DTOs for route parameters.
Custom Pipes
Use custom pipes when you need to:
- Parse IDs (UUID vs numeric)
- Coerce or sanitize strings
- Enforce custom logic like “must be one of these enums”
- Fetch entities from DB and inject them into handlers (careful with performance)
Example: ParseIntIdPipe
import {
ArgumentMetadata,
BadRequestException,
Injectable,
PipeTransform,
} from "@nestjs/common";
@Injectable()
export class ParseIntIdPipe implements PipeTransform<string, number> {
transform(value: string, metadata: ArgumentMetadata): number {
const val = parseInt(value, 10);
if (isNaN(val) || val <= 0) {
throw new BadRequestException("Invalid ID");
}
return val;
}
}
Use in controller:
@Get(":id")
findOne(@Param("id", ParseIntIdPipe) id: number) {
return this.userService.findOne(id);
}
Example: TrimStringPipe (simplified)
@Injectable()
export class TrimStringPipe implements PipeTransform {
transform(value: any) {
if (typeof value === "string") {
return value.trim();
}
return value;
}
}
Attach at parameter or controller level where appropriate.
This skill should:
- Suggest custom pipes when global validation is too generic.
- Avoid overusing DB-dependent pipes except in clearly beneficial scenarios.
Sanitization & Security
This skill can add light sanitization strategies, such as:
- Trimming user inputs
- Limiting string lengths
- Using allowlists/enums
For more complex sanitization (XSS/HTML), it may recommend dedicated libraries and carefully placed custom pipes or service-level logic.
Error Handling & Messages
This skill should help configure error responses for validation failures, e.g.:
- Using default NestJS
BadRequestExceptionresponses fromValidationPipe. - Customizing
exceptionFactoryinValidationPipeto return a consistent error format:
new ValidationPipe({
exceptionFactory: (errors) => {
const messages = errors.map((err) => ({
field: err.property,
constraints: err.constraints,
}));
return new BadRequestException({
message: "Validation failed",
errors: messages,
});
},
});
It should align error formats with any global error-handling conventions or filters in the project.
Pipes Scope & Application
This skill ensures pipes are applied with the correct scope:
- Global (via
useGlobalPipes) for baseline validation. - Controller-level when certain rules apply only to a specific resource.
- Parameter-level for fine-grained transformation/validation.
It should avoid applying heavy or DB-hitting pipes globally.
Integration with Other Skills
nestjs-project-scaffold:- This skill assumes global
ValidationPipeis added inmain.tsor will add it.
- This skill assumes global
nestjs-modules-services-controllers:- Uses DTOs and pipes alongside module/controller structures from that skill.
nestjs-authentication:- Uses DTOs (
LoginDto,SignupDto) and validates them.
- Uses DTOs (
nestjs-typeorm-integration:- Ensures data reaching TypeORM entities has been validated and transformed.
Advanced Topics (Optional)
This skill can also help with:
- Versioned DTOs (v1 vs v2)
- Partial DTOs using
PartialType,PickType,OmitTypefrom@nestjs/mapped-types - GraphQL InputType validation when using
@nestjs/graphql - Multi-tenant or locale-aware validation if described by the project
Example using PartialType:
import { PartialType } from "@nestjs/mapped-types";
import { CreateUserDto } from "./create-user.dto";
export class UpdateUserDto extends PartialType(CreateUserDto) {}
Example Prompts That Should Use This Skill
- “Add validation to these NestJS endpoints using DTOs.”
- “Create DTOs for this payload and reject invalid fields.”
- “Normalize and validate pagination query params.”
- “Implement a custom pipe to validate IDs and throw on invalid ones.”
- “Customize validation error format in our NestJS app.”
For these tasks, rely on this skill to build a strong validation layer that protects your NestJS backend, keeps controllers clean, and ensures consistent request/response contracts.
Didn't find tool you were looking for?