I feel like a combination of this thread and this thread is what I need to implement, I'm having trouble drawing them together.
I have a DTO that contains an enum
.
Using Postman, I am sending a PurchasableType
of FOO
and expecting to get an error of some sort. Reading through the above links, it seems like the process is quite involved; which makes me thing I'm completely missing the point.
How can I use the validation pipe(s) to make sure only the values in the purchasable-type.enum.ts
are allowed?
Thank you for any suggestions!
// create-order.dto.ts
import { IsEmail, IsNotEmpty, IsEnum } from 'class-validator';
import { PurchasableType } from '../enum/purchaseable-type.enum';
export class CreateOrderDto {
@IsNotEmpty()
readonly userId: string;
@IsNotEmpty()
readonly locationId: string;
@IsNotEmpty()
@IsEnum(PurchasableType)
readonly purchasableType: PurchasableType;
@IsNotEmpty()
@IsEmail()
readonly email: string;
}
// purchasable-type.enum.ts
export enum PurchasableType {
CLINIC = 'CLINIC',
EVENT = 'EVENT',
LESSON = 'LESSON',
RESERVATION = 'RESERVATION',
TEAM = 'TEAM',
}
EDIT
It seems I was also not defining the entity correctly, and that may have been the main issue. I am still curious if my implementation good/bad.
// order.entity.ts
...
import { PurchasableType } from '../enum/purchaseable-type.enum';
@Entity()
export class Order extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({
type: 'enum',
enum: PurchasableType,
})
Now when I send a purchasableType
of foo
I am getting a 500 error. If I send any valid value that is within the enum
I am getting a 200/201.
EDIT 2
Sure - here is a bit wider view of what I've got. Everything seems to be working properly, I'd just like to have a better grasp of what was really happening.
// event.controller.ts
@Post('/:id/orders')
async purchaseEventTickets(@Body() createOrderDto: CreateOrderDto):
Promise<Order> {
return await this.eventService.purchaseEventTickets(createOrderDto);
}
// create-order.dto.ts
export class CreateOrderDto {
@IsNotEmpty()
@IsEnum(PurchasableType)
readonly purchasableType: PurchasableType;
}
// event.service.ts
async purchaseEventTickets(createOrderDto: CreateOrderDto): Promise<Order> {
...
return await this.orderRepository.createOrder(createOrderDto);
}
// order.repository.ts
async createOrder(createOrderDto: CreateOrderDto): Promise<Order> {
const { purchasableType } = createOrderDto;
const order = this.create();
order.purchasableType = purchasableType;
try {
await order.save();
} catch (error) {
this.logger.error(`Failed to create the order: ${error.stack}`);
throw new InternalServerErrorException();
}
return order;
}
Using Postman, if I send an invalid value of "Foo" as a PurchasableType
I get the expected error.
Here is what your create-dto
looks like that contains an enum
.
// create-order.dto.ts
import { IsEmail, IsNotEmpty, IsEnum } from 'class-validator';
import { PurchasableType } from '../enum/purchaseable-type.enum';
export class CreateOrderDto {
...
@IsNotEmpty()
@IsEnum(PurchasableType)
readonly purchasableType: PurchasableType;
}
Here is what that enum file looks like:
// purchasable-type.enum.ts
export enum PurchasableType {
CLINIC = 'CLINIC',
EVENT = 'EVENT',
LESSON = 'LESSON',
RESERVATION = 'RESERVATION',
TEAM = 'TEAM',
}
From there I can confidently expect the value of the enum to be one of the above values. If some other value comes through, nest will throw a validation error.
Additionally, If you are attempting to use a nested object (or something with multiple attributes or an array) you can do something like this in your DTO:
import { PurchasableType } from '../interface/purchasable-type.interface';
...
@ApiProperty()
@IsArray()
@ArrayMinSize(7)
@ArrayMaxSize(7)
@ValidateNested({ each: true })
@Type(() => PurchasableType)
@IsNotEmpty()
readonly PurchasableType: PurchasableType[];
...