DTOs
Data Transfer Objects (DTOs) in NestJS CRUD Automator are automatically generated based on entity metadata. The library creates appropriate DTOs for request bodies, query parameters, and responses with built-in validation and transformation.
Automatic DTO Generation
DTOs are generated automatically from entity properties decorated with @ApiPropertyDescribe
:
@Entity("users")
export class UserEntity {
@PrimaryGeneratedColumn("uuid")
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.UUID,
description: "User ID",
})
id: string;
@Column()
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.STRING,
description: "Username",
format: EApiPropertyStringType.STRING,
minLength: 3,
maxLength: 20,
})
username: string;
}
This automatically generates:
- CreateUserDto - For POST requests
- UpdateUserDto - For PATCH requests
- UserResponseDto - For responses
- GetListQueryDto - For GET /users query parameters
DTO Types
Body DTOs
Used for request bodies in CREATE and UPDATE operations.
Create DTO includes:
- All properties marked as
isExposedInCreateDto: true
(default: true) - Validation rules from property configuration
- Required fields based on
isRequired
Update DTO includes:
- All properties marked as
isExposedInUpdateDto: true
(default: true) - All fields are optional by default
- Validation rules still apply when provided
Query DTOs
Used for filtering and pagination in GET_LIST operations:
// Generated GetListQueryDto structure
interface GetListQueryDto {
limit?: number;
page?: number;
orderBy?: string;
orderDirection?: "ASC" | "DESC";
[propertyName]?: {
operator: EFilterOperation;
value?: any;
values?: any[];
};
}
Example usage:
GET /users?limit=10&page=1&username[operator]=cont&username[value]=john&orderBy=createdAt&orderDirection=DESC
Response DTOs
Control which properties are included in responses:
@Column()
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.STRING,
description: "Password hash",
format: EApiPropertyStringType.PASSWORD,
dto: {
response: {
isExposed: false, // Never return in responses
},
},
})
password: string;
Controlling DTO Generation
Exclude from DTOs
Prevent a property from appearing in specific DTOs:
@Column()
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.STRING,
description: "Internal notes",
format: EApiPropertyStringType.STRING,
dto: {
body: {
isExposedInCreateDto: false,
isExposedInUpdateDto: false,
},
response: {
isExposed: true, // Show in responses only
},
},
})
internalNotes: string;
Required vs Optional
Control field requirements:
@Column()
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.STRING,
description: "Email",
format: EApiPropertyStringType.EMAIL,
isRequired: true, // Required in create
dto: {
body: {
isRequiredInCreateDto: true,
isRequiredInUpdateDto: false, // Optional in update
},
},
})
email: string;
Default Values
Specify default values for DTO properties:
@Column({ default: false })
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.BOOLEAN,
description: "Is active",
defaultValue: false,
})
isActive: boolean;
Custom DTOs
Replace auto-generated DTOs with custom ones:
import { IsString, IsEmail, MinLength, MaxLength } from "class-validator";
import { ApiProperty } from "@nestjs/swagger";
export class CreateUserDto {
@ApiProperty()
@IsString()
@MinLength(3)
@MaxLength(20)
username: string;
@ApiProperty()
@IsEmail()
email: string;
@ApiProperty()
@IsString()
@MinLength(8)
password: string;
}
Use in controller:
@ApiController<UserEntity>({
entity: UserEntity,
routes: {
[EApiRouteType.CREATE]: {
dto: {
body: CreateUserDto,
response: UserResponseDto,
},
},
},
})
DTO Validation
Built-in Validators
Validation rules are automatically applied based on property configuration:
@Column()
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.STRING,
description: "Username",
format: EApiPropertyStringType.STRING,
minLength: 3, // Adds @MinLength(3)
maxLength: 20, // Adds @MaxLength(20)
pattern: "/^[a-zA-Z0-9_-]+$/", // Adds @Matches(/^[a-zA-Z0-9_-]+$/)
})
username: string;
Custom Validators
Add custom validators to auto-generated DTOs:
import {
AllOrNoneOfListedPropertiesValidator
} from "@elsikora/nestjs-crud-automator";
@ApiController<UserEntity>({
entity: UserEntity,
routes: {
[EApiRouteType.CREATE]: {
autoDto: {
[EApiDtoType.BODY]: {
validators: [
{
constraintClass: AllOrNoneOfListedPropertiesValidator,
options: ["firstName", "lastName"],
},
],
},
},
},
},
})
Available built-in validators:
AllOrNoneOfListedPropertiesValidator
- All or none must be providedOnlyOneOfListedPropertiesValidator
- Exactly one must be providedHasAtLeastOneOfListedPropertiesValidator
- At least one requiredHasAtLeastOneAndOnlyOneOfListedPropertiesValidator
- Only one requiredMustMatchOneOfSchemasValidator
- Must match a schemaHasPairedCustomSuffixesFieldsValidator
- Paired fields validation
Polymorphic DTOs
Support for discriminated unions:
// Base interface
interface Payment {
type: string;
}
// Specific implementations
interface CardPayment extends Payment {
type: "card";
cardNumber: string;
cvv: string;
}
interface PayPalPayment extends Payment {
type: "paypal";
email: string;
}
@Column({ type: "jsonb" })
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.OBJECT,
description: "Payment method",
discriminator: {
propertyName: "type",
mapping: {
card: CardPaymentDto,
paypal: PayPalPaymentDto,
},
},
})
paymentMethod: CardPayment | PayPalPayment;
DTO Transformation
Transform DTO values during processing:
import { Transform } from "class-transformer";
@Column()
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.STRING,
description: "Email",
format: EApiPropertyStringType.EMAIL,
})
@Transform(({ value }) => value.toLowerCase())
email: string;
Guard-Based DTO Properties
Show or hide DTO properties based on guards:
@Column()
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.STRING,
description: "Admin notes",
format: EApiPropertyStringType.STRING,
dto: {
guard: {
responseGuards: [AdminGuard],
},
},
})
adminNotes: string;
Only users passing AdminGuard
will see this property in responses.
Relation DTOs
Control how relations appear in DTOs:
@ManyToOne(() => UserEntity)
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.RELATION,
description: "Post author",
relationMetadata: {
relationType: "many-to-one",
entity: UserEntity,
isEager: false,
},
dto: {
response: {
isExposed: true, // Include in responses
relations: ["author"], // Load author relation
},
},
})
author: UserEntity;
Nested DTOs
For complex nested objects:
@Column({ type: "jsonb" })
@ApiPropertyDescribe({
type: EApiPropertyDescribeType.OBJECT,
description: "User profile",
properties: {
bio: { type: "string", maxLength: 500 },
avatar: { type: "string", format: "url" },
socialLinks: {
type: "object",
properties: {
twitter: { type: "string" },
linkedin: { type: "string" },
},
},
},
})
profile: UserProfile;
Next Steps
- Validation - Advanced validation patterns
- Transformers - Request/response transformation
- Custom DTOs - Working with custom DTOs
- API Reference - Validators - All available validators