npm.io
1.0.0-alpha.6 • Published 2d ago

@eleven-labs/nest-profiler-validator

Licence
MIT
Version
1.0.0-alpha.6
Deps
0
Size
56 kB
Vulns
0
Weekly
0
Stars
2

@eleven-labs/nest-profiler-validator

Powered & maintained by Eleven Labs

Powered & maintained by Eleven Labs

CI Quality Coverage Documentation Node >= 22 Built with NestJS TypeScript strict Code style: Prettier

@eleven-labs/nest-profiler-validator captures every DTO validation result (valid or invalid) and displays it in a dedicated Validator panel, inspired by Symfony's Web Profiler validator tab.

It is validator-agnostic: instead of being tied to class-validator, it wraps any validation PipeTransform and normalizes failures through pluggable, duck-typed extractors. Built-in extractors cover class-validator, nestjs-zod, and a generic HttpException fallback.

Validator panel — DTO validation results with per-property constraint violations

Installation

pnpm add @eleven-labs/nest-profiler-validator

Then install the validator you use:

# class-validator (default)
pnpm add class-validator class-transformer

# …or nestjs-zod
pnpm add nestjs-zod zod

class-validator/class-transformer are not peer dependencies — they are only required when you rely on the default class-validator pipe.

Setup

ValidatorCollectorModule.forRoot() registers ProfilerValidationPipe as the global APP_PIPE. It wraps your validation pipe — do not also register a separate global ValidationPipe.

With class-validator (default)

When pipe is omitted, a class-validator ValidationPipe is built from validationPipeOptions:

import { ValidatorCollectorModule } from '@eleven-labs/nest-profiler-validator';

@Module({
  imports: [
    ProfilerModule.forRoot({ isGlobal: true }),
    ValidatorCollectorModule.forRoot({
      validationPipeOptions: {
        whitelist: true, // remove extra properties
        transform: true, // transform payload to DTO class
        // any other ValidationPipe options
      },
    }),
  ],
})
export class AppModule {}
With nestjs-zod

Pass your own pipe via pipe; class-validator is never loaded:

import { ValidatorCollectorModule } from '@eleven-labs/nest-profiler-validator';
import { ZodValidationPipe } from 'nestjs-zod';

@Module({
  imports: [
    ProfilerModule.forRoot({ isGlobal: true }),
    ValidatorCollectorModule.forRoot({ pipe: new ZodValidationPipe() }),
  ],
})
export class AppModule {}

A NestJS app uses a single global validation strategy, so use one validator at a time.

Options

Option Type Description
enabled boolean Default true. When false, no pipe is installed.
pipe PipeTransform The validation pipe to wrap. Defaults to a class-validator pipe built from the option below.
validationPipeOptions ValidationPipeOptions Forwarded to the default class-validator pipe when pipe is omitted.
extractors ValidationViolationExtractor[] Override the extractor chain. Defaults to [classValidator, zod, generic].

Prerequisite: value import for DTO types

For reflect-metadata to emit the DTO class constructor as parameter metadata, use a value import (not import type) on the DTO in your controllers:

// ✓ value import — emits reflect-metadata
import { CreateProductDto } from './dto/create-product.dto';

// ✗ type-only import — metadata is erased, metatype shows as 'Function'
import type { CreateProductDto } from './dto/create-product.dto';

What it captures

For each @Body(), @Query(), or @Param() parameter using a DTO class:

Field Description
source body, query, param, or custom
dtoClass DTO class name (e.g., CreateProductDto)
status valid or invalid
violationCount Total number of constraint violations
violations Per-property breakdown with constraint names and messages

Each violation entry includes:

  • property — the property path that failed (nested properties use dot notation)
  • value — the rejected value (when available)
  • constraints — map of constraint name → message (e.g., { isNotEmpty: "name should not be empty" })

How it works

ProfilerValidationPipe implements PipeTransform and wraps an inner pipe:

  1. On transform(), it delegates to the inner pipe. On success it records a valid entry.
  2. On failure it runs the configured extractors over the thrown error, records an invalid entry with the normalized violations, then re-throws the original exception.

Extractors are tried in order; the first to recognize the error wins:

  • class-validatorcreateClassValidatorPipe() attaches the raw ValidationError[] to the thrown exception (under a private symbol) so the full property/constraint tree is recovered.
  • nestjs-zod / zod — reads ZodError.issues (via getZodError() or a bare ZodError).
  • generic — any HttpException exposing a message string/array (the universal fallback).

Reading the active profile uses CLS, so capture is concurrent-safe across requests.

Custom extractors

To support another validator, implement ValidationViolationExtractor and pass it via extractors:

import type { ValidationViolationExtractor } from '@eleven-labs/nest-profiler-validator';

const myExtractor: ValidationViolationExtractor = {
  extract({ error }) {
    // return ViolationEntry[] if recognized, otherwise null to defer to the next extractor
    return null;
  },
};

ValidatorCollectorModule.forRoot({ pipe: myPipe, extractors: [myExtractor] });

Toolbar badge

  • All valid: number of validated DTOs (e.g., 1)
  • With violations: total violation count (e.g., 3 violations)

Part of the nest-profiler toolkit · Powered & maintained by Eleven Labs