Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/LizandroCanul/back_sdo/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The API uses class-validator and class-transformer to automatically validate incoming requests through DTOs (Data Transfer Objects). Validation is configured globally in main.ts.

Global Validation Configuration

Validation is enabled application-wide with these settings:
import { ValidationPipe } from '@nestjs/common';

app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true,              // Removes unknown properties
    forbidNonWhitelisted: true,   // Throws error for unknown properties
    transform: true,              // Auto-converts types (crucial for nested DTOs)
  }),
);
The transform: true option is critical for nested DTOs and type conversions. It automatically converts plain JSON objects to DTO class instances.

Configuration Options Explained

Automatically strips properties that don’t have validation decorators.Example:
// Request body
{
  "nombre": "Test",
  "hackerField": "malicious" // This will be removed
}
Instead of silently removing unknown properties, it throws a 400 Bad Request error.Response:
{
  "statusCode": 400,
  "message": ["property hackerField should not exist"],
  "error": "Bad Request"
}
Converts incoming data to the expected types and DTO instances.Transformations:
  • "123"123 (string to number)
  • "true"true (string to boolean)
  • Plain objects → DTO class instances

Common Validation Decorators

String Validation

@IsString()
@IsNotEmpty()
@MaxLength(255)
nombre: string;

Number Validation

@IsNumber()
@IsNotEmpty()
municipioId: number;

Optional Fields

@IsString()
@IsOptional()
descripcion?: string;

Enum Validation

export enum TipoGeometria {
  PUNTO = 'PUNTO',
  RUTA = 'RUTA',
  POLIGONO = 'POLIGONO',
}

@IsEnum(TipoGeometria)
@IsOptional()
tipoGeometria?: TipoGeometria;

Boolean Validation

@IsBoolean()
@IsOptional()
activo?: boolean;

Nested DTO Validation

For complex objects with nested DTOs, use @ValidateNested() with @Type():
import { Type } from 'class-transformer';
import { IsArray, ValidateNested, IsOptional } from 'class-validator';
import { CreateObraUbicacionDto } from './create-obra-ubicacion.dto';

export class CreateObraDto {
  @IsString()
  @IsNotEmpty()
  nombre: string;

  // Nested array of location DTOs
  @IsArray()
  @ValidateNested({ each: true }) // Validates each item in array
  @Type(() => CreateObraUbicacionDto) // Transforms to DTO instances
  @IsOptional()
  ubicaciones?: CreateObraUbicacionDto[];
}
Without @Type() decorator, nested DTOs won’t be validated. The transform: true option in ValidationPipe requires this decorator to work with nested objects.

Real-World DTO Examples

CreateUserDto

import { IsEmail, IsString, MinLength, IsOptional, IsIn, IsBoolean } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @MinLength(3)
  nombreCompleto: string;

  @IsString()
  @IsEmail()
  email: string;

  @IsString()
  @MinLength(6, { message: 'La contraseña debe tener al menos 6 caracteres' })
  password: string;

  @IsOptional()
  @IsString()
  @IsIn(['admin', 'user'])
  roles?: string;

  @IsOptional()
  @IsBoolean()
  isActive?: boolean;
}
Location: /home/daytona/workspace/source/src/users/dto/create-user.dto.ts:1

CreateMunicipioDto

import { IsString, IsNotEmpty, IsNumber, Min, Max, IsOptional, IsBoolean } from 'class-validator';
import { Transform } from 'class-transformer';

export class CreateMunicipioDto {
  @IsString()
  @IsNotEmpty()
  @Transform(({ value }) => value?.trim())
  nombre: string;

  @IsNumber()
  @IsNotEmpty()
  @Min(-90)
  @Max(90)
  latitud: number;

  @IsNumber()
  @IsNotEmpty()
  @Min(-180)
  @Max(180)
  longitud: number;

  @IsBoolean()
  @IsOptional()
  activo?: boolean;
}
Location: /home/daytona/workspace/source/src/municipios/dto/create-municipio.dto.ts:1

CreateObraDto (Complex)

import { IsString, IsNotEmpty, IsArray, ValidateNested, IsNumber, IsOptional, IsPositive, Min, MaxLength } from 'class-validator';
import { Type } from 'class-transformer';
import { CreateObraUbicacionDto } from './create-obra-ubicacion.dto';

export class CreateObraDto {
  // Fiscal year
  @IsNumber()
  @IsNotEmpty()
  ejercicioFiscalId: number;

  // Unique key
  @IsString()
  @IsNotEmpty()
  @MaxLength(50)
  claveUnica: string;

  // Name
  @IsString()
  @IsNotEmpty()
  @MaxLength(255)
  nombre: string;

  // Description
  @IsString()
  @IsOptional()
  descripcion?: string;

  // Department
  @IsNumber()
  @IsNotEmpty()
  dependenciaId: number;

  // Budget
  @IsNumber({ maxDecimalPlaces: 2 })
  @IsPositive()
  @Min(0)
  monto: number;

  // Municipality
  @IsNumber()
  @IsNotEmpty()
  municipioId: number;

  // Project type (optional)
  @IsNumber()
  @IsOptional()
  tipoProyectoId?: number;

  // Status
  @IsNumber()
  @IsNotEmpty()
  estatusObraId: number;

  // Nested locations array
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => CreateObraUbicacionDto)
  @IsOptional()
  ubicaciones?: CreateObraUbicacionDto[];
}
Location: /home/daytona/workspace/source/src/obras/dto/create-obra.dto.ts:1

Validation Error Responses

When validation fails, NestJS returns a standardized error response:
{
  "statusCode": 400,
  "message": [
    "email must be an email"
  ],
  "error": "Bad Request"
}

Custom Validation Messages

You can customize error messages using the decorator options:
@MinLength(6, { message: 'La contraseña debe tener al menos 6 caracteres' })
password: string;

Best Practices

Always Use DTOs

Never accept raw request bodies. Create a DTO for every endpoint that accepts data.

Be Explicit

Use @IsNotEmpty() for required fields and @IsOptional() for optional ones.

Type Safety

Combine validation with TypeScript types for compile-time and runtime safety.

Nested Validation

Don’t forget @Type() and @ValidateNested() for nested objects and arrays.
The transform: true configuration (set in main.ts:13) is essential for:
  • Auto-converting query parameters from strings
  • Transforming nested DTOs
  • Type coercion (string to number, etc.)

Common Validation Patterns

Password Validation

@IsString()
@MinLength(6, { message: 'La contraseña debe tener al menos 6 caracteres' })
password: string;

Geographic Coordinates

@IsNumber()
@Min(-90)
@Max(90)
latitud: number;

@IsNumber()
@Min(-180)
@Max(180)
longitud: number;

Money/Currency

@IsNumber({ maxDecimalPlaces: 2 })
@IsPositive()
@Min(0)
monto: number;

Trimmed Strings

@IsString()
@IsNotEmpty()
@Transform(({ value }) => value?.trim())
nombre: string;

Next Steps

Database Schema

Learn about entity relationships

Error Handling

Understand error responses

Build docs developers (and LLMs) love