Dwex Logo
OpenAPI

DTOs

Document your Data Transfer Objects with property decorators

DTO Documentation

Document your DTOs (Data Transfer Objects) using property decorators to generate detailed schema information.

@ApiProperty

Define required properties with detailed information:

import { ApiProperty } from '@dwex/openapi';

export class CreateUserDto {
  @ApiProperty({
    description: 'Username',
    example: 'john_doe',
    minLength: 3,
    maxLength: 20,
  })
  username: string;

  @ApiProperty({
    description: 'Email address',
    example: 'john@example.com',
    format: 'email',
  })
  email: string;

  @ApiProperty({
    description: 'User age',
    example: 25,
    minimum: 18,
    maximum: 100,
  })
  age: number;
}

@ApiPropertyOptional

Define optional properties:

import { ApiPropertyOptional } from '@dwex/openapi';

export class UpdateUserDto {
  @ApiPropertyOptional({
    description: 'Username',
    example: 'john_doe_updated',
  })
  username?: string;

  @ApiPropertyOptional({
    description: 'Email address',
    example: 'john.updated@example.com',
  })
  email?: string;

  @ApiPropertyOptional({
    description: 'User age',
    example: 26,
  })
  age?: number;
}

Property Options

All available options for @ApiProperty:

@ApiProperty({
  // Basic information
  description: 'Property description',
  example: 'example value',
  default: 'default value',

  // Type information
  type: String,  // or Number, Boolean, Date, etc.
  format: 'email',  // 'email', 'date-time', 'uri', etc.

  // Validation
  required: true,
  minimum: 0,
  maximum: 100,
  minLength: 3,
  maxLength: 20,
  pattern: '^[a-z]+$',

  // Enums
  enum: ['option1', 'option2', 'option3'],

  // Arrays
  isArray: true,
})
propertyName: string;

Enums

Document enum properties:

export class CreateUserDto {
  @ApiProperty({
    description: 'User role',
    enum: ['admin', 'user', 'guest'],
    default: 'user',
    example: 'user',
  })
  role: string;
}

Or with TypeScript enums:

enum UserRole {
  ADMIN = 'admin',
  USER = 'user',
  GUEST = 'guest',
}

export class CreateUserDto {
  @ApiProperty({
    description: 'User role',
    enum: UserRole,
    default: UserRole.USER,
  })
  role: UserRole;
}

Arrays

Document array properties:

export class CreateUserDto {
  @ApiProperty({
    description: 'User tags',
    type: [String],
    example: ['tag1', 'tag2'],
  })
  tags: string[];

  // Or use isArray
  @ApiProperty({
    description: 'User interests',
    type: String,
    isArray: true,
    example: ['coding', 'music'],
  })
  interests: string[];
}

Nested Objects

Document nested DTO properties:

export class AddressDto {
  @ApiProperty({ description: 'Street address' })
  street: string;

  @ApiProperty({ description: 'City' })
  city: string;

  @ApiProperty({ description: 'Postal code' })
  postalCode: string;
}

export class CreateUserDto {
  @ApiProperty({ description: 'Username' })
  username: string;

  @ApiProperty({
    description: 'User address',
    type: AddressDto,
  })
  address: AddressDto;
}

Array of Objects

Document arrays of nested objects:

export class PhoneDto {
  @ApiProperty({ description: 'Phone type', enum: ['mobile', 'home', 'work'] })
  type: string;

  @ApiProperty({ description: 'Phone number' })
  number: string;
}

export class CreateUserDto {
  @ApiProperty({ description: 'Username' })
  username: string;

  @ApiProperty({
    description: 'Phone numbers',
    type: [PhoneDto],
    isArray: true,
  })
  phones: PhoneDto[];
}

Validation Examples

String Validation

@ApiProperty({
  description: 'Username',
  minLength: 3,
  maxLength: 20,
  pattern: '^[a-zA-Z0-9_]+$',
  example: 'john_doe',
})
username: string;

Number Validation

@ApiProperty({
  description: 'User age',
  type: Number,
  minimum: 18,
  maximum: 100,
  example: 25,
})
age: number;

Date Properties

@ApiProperty({
  description: 'Birth date',
  type: Date,
  format: 'date-time',
  example: '1990-01-01T00:00:00Z',
})
birthDate: Date;

Complete DTO Example

import { ApiProperty, ApiPropertyOptional } from '@dwex/openapi';

export enum UserRole {
  ADMIN = 'admin',
  USER = 'user',
  GUEST = 'guest',
}

export class CreateUserDto {
  @ApiProperty({
    description: 'Username (alphanumeric and underscores only)',
    example: 'john_doe',
    minLength: 3,
    maxLength: 20,
    pattern: '^[a-zA-Z0-9_]+$',
  })
  username: string;

  @ApiProperty({
    description: 'Email address',
    example: 'john@example.com',
    format: 'email',
  })
  email: string;

  @ApiProperty({
    description: 'User password (min 8 characters)',
    example: 'SecurePass123',
    minLength: 8,
    format: 'password',
  })
  password: string;

  @ApiProperty({
    description: 'User age (must be 18 or older)',
    example: 25,
    minimum: 18,
    maximum: 100,
  })
  age: number;

  @ApiPropertyOptional({
    description: 'User role',
    enum: UserRole,
    default: UserRole.USER,
    example: UserRole.USER,
  })
  role?: UserRole;

  @ApiPropertyOptional({
    description: 'User interests',
    type: [String],
    example: ['coding', 'music', 'sports'],
  })
  interests?: string[];

  @ApiPropertyOptional({
    description: 'User bio',
    example: 'Software developer from NYC',
    maxLength: 500,
  })
  bio?: string;
}

export class UpdateUserDto {
  @ApiPropertyOptional({
    description: 'Updated username',
    minLength: 3,
    maxLength: 20,
  })
  username?: string;

  @ApiPropertyOptional({
    description: 'Updated email',
    format: 'email',
  })
  email?: string;

  @ApiPropertyOptional({
    description: 'Updated bio',
    maxLength: 500,
  })
  bio?: string;
}

export class UserDto {
  @ApiProperty({
    description: 'User ID',
    example: '123',
  })
  id: string;

  @ApiProperty({
    description: 'Username',
    example: 'john_doe',
  })
  username: string;

  @ApiProperty({
    description: 'Email address',
    example: 'john@example.com',
  })
  email: string;

  @ApiProperty({
    description: 'User age',
    example: 25,
  })
  age: number;

  @ApiProperty({
    description: 'User role',
    enum: UserRole,
    example: UserRole.USER,
  })
  role: UserRole;

  @ApiProperty({
    description: 'Account creation timestamp',
    format: 'date-time',
    example: '2024-01-01T00:00:00Z',
  })
  createdAt: Date;
}

Using DTOs in Controllers

Reference your DTOs in controller decorators:

import { Controller, Post, Body } from '@dwex/core';
import { ApiBody, ApiCreatedResponse, ApiBadRequestResponse } from '@dwex/openapi';
import { CreateUserDto, UserDto } from './user.dto';

@Controller('users')
export class UsersController {
  @Post()
  @ApiBody({
    description: 'User creation data',
    type: CreateUserDto,
  })
  @ApiCreatedResponse({
    description: 'User created successfully',
    type: UserDto,
  })
  @ApiBadRequestResponse({
    description: 'Invalid user data',
  })
  create(@Body() createUserDto: CreateUserDto): UserDto {
    // Implementation
    return {} as UserDto;
  }
}

Next Steps