The "Remote Validation" Struggle
Hey everyone! π
If you work with NestJS, you probably love class-validator. Putting an @IsEmail() decorator on a property and sleeping soundly knowing bad data won't reach your Service is a great feeling.
But that peace of mind usually vanishes when we need Remote Validation.
You know the scenario:
- The frontend sends a
userId,couponCode, ortransactionId. - You need to hit an external Microservice or API to check if it's valid.
- If it's valid, you often need to fetch extra data (like the user's name) to save it locally.
The "Dirty" Way (We've all done this):
// β The common anti-pattern
@Post()
async create(@Body() dto: CreateOrderDto) {
// Validation logic leaking into the Controller/Service
const response = await this.http.get(`https://external-api.com/users/${dto.userId}`);
if (response.status !== 200) {
throw new BadRequestException('Invalid User ID');
}
// Business logic finally starts here...
}
This breaks the NestJS patterns. Your Controller should handle requests, and your Service should handle business logic. Validation should stay at the gate: in the DTO.
The Solution: nestjs-remote-validate
I got tired of writing this boilerplate code, so I built a library to solve exactly this: HTTP validation inside DTO decorators.
It's called nestjs-remote-validate.
It turns that manual validation into this:
// β
The clean way
export class CreateOrderDto {
@ValidateApi({
host: 'https://external-api.com/users/:userId', // Dynamic injection!
method: 'GET',
validate: ({ status }) => status === 200
})
userId: string;
}
The Killer Feature: DTO Enrichment π±
This is my favorite part. Often, you don't just want to validate; you want to use the data returned by the API.
The library allows you to extract data from the response and automatically inject it into another field of your DTO.
Check this out:
export class CreateTransactionDto {
// 1. Validates if the ID exists remotely
@ValidateApi({
host: 'https://bank-api.com/accounts/:accountId',
method: 'GET',
validate: ({ status }) => status === 200,
// 2. Extracts the owner name from the response body
extractValue: (body) => body.ownerName,
// 3. Injects it into the field below
targetField: 'accountOwnerName'
})
accountId: string;
// This field gets populated "magically" after validation!
@Allow()
accountOwnerName: string;
}
By the time the DTO reaches your Controller, accountOwnerName is already filled. Zero HTTP calls in your Service code. π€―
Quick Start
It's lightweight and easy to setup.
1. Install
npm install nestjs-remote-validate
2. Setup (Important!)
Since the validator needs to perform async operations and injection, we need to register the provider and tell class-validator to use the NestJS container.
app.module.ts
import { ApiValidatorConstraint } from 'nestjs-remote-validate';
@Module({
providers: [ApiValidatorConstraint], // Register the provider
})
export class AppModule {}
main.ts
import { useContainer } from 'class-validator';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Allow dependency injection inside validators
useContainer(app.select(AppModule), { fallbackOnErrors: true });
app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true }));
await app.listen(3000);
}
bootstrap();
π§ Current Limitations & Roadmap (Let's build this!)
This project was born from a specific need, and while it works great for many cases, there is plenty of room to grow. I want to be transparent about where we are and where we can go:
- Http Client: Currently, it uses native
fetchunder the hood. In the future, I'd love to support Axios injection so you can reuse your global interceptors (for logging, auth, etc.). - Caching: Right now, every validation triggers a request. Implementing a Caching Strategy (Memory/Redis) would be a huge performance boost for repeated validations.
- Batching: Validating arrays of IDs in a single call.
This is where you come in! Since this is Open Source, these are great opportunities for "Good First Issues" or robust PRs.
Contribute! π€
If you think this library solves a pain point for you, give it a try!
If you have ideas on how to implement the Axios support or Caching, drop by the repository. Every Star, Issue, or PR helps the ecosystem grow.
π GitHub: gsmatheus/nestjs-remote-validate
π¦ NPM: npmjs.com/package/nestjs-remote-validate
Happy coding! π
Top comments (0)