🏗️ Architecture

DTO Design Patterns

Data Transfer Object patterns for validation and transformation.

Overview

Every API endpoint uses DTOs (Data Transfer Objects) for:

  • Input validation
  • Data transformation
  • Type safety
  • Documentation (Swagger)

Creating a DTO

import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import {
  IsString,
  IsNotEmpty,
  IsOptional,
  IsEmail,
  IsEnum,
  IsUUID,
} from "class-validator";
import { Transform } from "class-transformer";

export class CreateEmployeeDTO {
  @ApiProperty({ description: "First name" })
  @IsString()
  @IsNotEmpty()
  @Transform(({ value }) => value?.trim())
  firstName: string;

  @ApiProperty({ description: "Last name" })
  @IsString()
  @IsNotEmpty()
  lastName: string;

  @ApiProperty({ description: "Email address" })
  @IsEmail()
  email: string;

  @ApiPropertyOptional({ description: "Phone number" })
  @IsOptional()
  @IsString()
  phone?: string;

  @ApiProperty({ enum: ["ACTIVE", "INACTIVE"] })
  @IsEnum(["ACTIVE", "INACTIVE"])
  status: string;
}

Validation Decorators

DecoratorPurpose
@IsString()Must be string
@IsNotEmpty()Cannot be empty
@IsEmail()Valid email format
@IsUUID()Valid UUID
@IsEnum()Must be in enum values
@IsOptional()Field is optional
@IsDateString()Valid ISO date string
@Min() / @Max()Number range
@Length()String length range
@ValidateNested()Validate nested object

Relation Whitelisting

For security, always whitelist allowed relations:

import { IsOptional, IsEnum } from "class-validator";

export enum AllowedRelations {
  USER = "user",
  ORGANIZATION = "organization",
}

export class FindEmployeeQueryDTO {
  @IsOptional()
  @IsEnum(AllowedRelations, { each: true })
  relations?: AllowedRelations[];
}

DTO Inheritance

// Create
export class CreateTaskDTO { ... }

// Update (all fields optional)
export class UpdateTaskDTO extends PartialType(CreateTaskDTO) {}

// Query (with pagination)
export class FindTaskQueryDTO extends IntersectionType(
  PaginationParams,
  PickType(CreateTaskDTO, ['status'] as const),
) {}

Edit this page

Copyright © 2023-Present Ever Co. LTD.Docs by Sourcey