Skip to content

Commit

Permalink
Реализует валидацию оставшихся методов оффера. Проведет небольшой реф…
Browse files Browse the repository at this point in the history
…акторинг названий
  • Loading branch information
AdonaiJehosua committed Nov 4, 2024
1 parent a8a9212 commit b915d28
Show file tree
Hide file tree
Showing 17 changed files with 266 additions and 74 deletions.
7 changes: 7 additions & 0 deletions src/shared/modules/offer/dto/change-favorite-status.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import {IsBoolean, IsMongoId} from 'class-validator';

import {ChangeFavoriteStatusValidationMessages} from './change-favorite-status.messages.js';

export class ChangeFavoriteStatusDto {
@IsMongoId({message: ChangeFavoriteStatusValidationMessages.offerId.invalidId})
public offerId: string;

@IsBoolean({message: ChangeFavoriteStatusValidationMessages.favoriteStatus.invalidFormat})
public favoriteStatus: boolean;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const ChangeFavoriteStatusValidationMessages = {
offerId: {
invalidId: 'offer id must be a valid id',
},
favoriteStatus: {
invalidFormat: 'favorite status must be boolean'
}
} as const;
25 changes: 25 additions & 0 deletions src/shared/modules/offer/dto/city-and-location.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {IsInt, IsString, ValidateNested} from 'class-validator';
import {Type} from 'class-transformer';

import {City, Location} from '../../../types/index.js';
import {CityAndLocationValidationMessages} from './city-and-location.messages.js';

export class LocationValidate implements Location {
@IsInt({message: CityAndLocationValidationMessages.location.longitude.invalidFormat})
public longitude: number;

@IsInt({message: CityAndLocationValidationMessages.location.latitude.invalidFormat})
public latitude: number;

@IsInt({message: CityAndLocationValidationMessages.location.zoom.invalidFormat})
public zoom: number;
}

export class CityValidate implements City {
@IsString({message: CityAndLocationValidationMessages.city.name.invalidFormat})
public name: string;

@ValidateNested({message: CityAndLocationValidationMessages.location.invalid})
@Type(() => LocationValidate)
public location: Location;
}
20 changes: 20 additions & 0 deletions src/shared/modules/offer/dto/city-and-location.messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
export const CityAndLocationValidationMessages = {
city: {
invalid: 'city must be a City type',
name: {
invalidFormat: 'city name must be a string'
}
},
location: {
invalid: 'location must be a Location type',
longitude: {
invalidFormat: 'longitude must be a number'
},
latitude: {
invalidFormat: 'latitude must be a number'
},
zoom: {
invalidFormat: 'zoom must be a number'
}
}
} as const;
30 changes: 6 additions & 24 deletions src/shared/modules/offer/dto/create-offer.dto.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {Type} from 'class-transformer';
import {
ArrayMaxSize,
ArrayMinSize, ArrayUnique,
Expand All @@ -14,28 +15,9 @@ import {
} from 'class-validator';

import {City, Location, OfferGood, OfferType} from '../../../types/index.js';
import {CityAndLocationValidationMessage, CreateOfferValidationMessage} from './create-offer.messages.js';
import {Type} from 'class-transformer';

class LocationValidate implements Location {
@IsInt({message: CityAndLocationValidationMessage.location.longitude.invalidFormat})
public longitude: number;

@IsInt({message: CityAndLocationValidationMessage.location.latitude.invalidFormat})
public latitude: number;

@IsInt({message: CityAndLocationValidationMessage.location.zoom.invalidFormat})
public zoom: number;
}

class CityValidate implements City {
@IsString({message: CityAndLocationValidationMessage.city.name.invalidFormat})
public name: string;

@ValidateNested({message: CityAndLocationValidationMessage.location.invalid})
@Type(() => LocationValidate)
public location: Location;
}
import {CreateOfferValidationMessage} from './create-offer.messages.js';
import {CityAndLocationValidationMessages} from './city-and-location.messages.js';
import {CityValidate, LocationValidate} from './city-and-location.dto.js';

export class CreateOfferDto {
@IsString({message: CreateOfferValidationMessage.title.minLength})
Expand All @@ -52,11 +34,11 @@ export class CreateOfferDto {
public price: number;

@Type(() => CityValidate)
@ValidateNested({message: CityAndLocationValidationMessage.city.invalid})
@ValidateNested({message: CityAndLocationValidationMessages.city.invalid})
public city: City;

@Type(() => LocationValidate)
@ValidateNested({message: CityAndLocationValidationMessage.location.invalid})
@ValidateNested({message: CityAndLocationValidationMessages.location.invalid})
public location: Location;

@IsBoolean({message: CreateOfferValidationMessage.isFavorite.invalidFormat})
Expand Down
21 changes: 0 additions & 21 deletions src/shared/modules/offer/dto/create-offer.messages.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
export const CityAndLocationValidationMessage = {
city: {
invalid: 'city must be a City type',
name: {
invalidFormat: 'city name must be a string'
}
},
location: {
invalid: 'location must be a Location type',
longitude: {
invalidFormat: 'longitude must be a number'
},
latitude: {
invalidFormat: 'latitude must be a number'
},
zoom: {
invalidFormat: 'zoom must be a number'
}
}
} as const;

export const CreateOfferValidationMessage = {
title: {
invalidFormat: 'title must be a string',
Expand Down
5 changes: 5 additions & 0 deletions src/shared/modules/offer/dto/offers.dto.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {IsInt} from 'class-validator';

import {OffersValidationMessages} from './offers.messages.js';

export class OffersDto {
@IsInt({message: OffersValidationMessages.offersAmount.invalidFormat})
public offersAmount: number;
}
5 changes: 5 additions & 0 deletions src/shared/modules/offer/dto/offers.messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const OffersValidationMessages = {
offersAmount: {
invalidFormat: 'offers amount must be a number'
}
} as const;
5 changes: 5 additions & 0 deletions src/shared/modules/offer/dto/premium-offers.dto.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {IsString} from 'class-validator';

import {PremiumOffersValidationMessages} from './premium-offers.messages.js';

export class PremiumOffersDto {
@IsString({message: PremiumOffersValidationMessages.cityName.invalidFormat})
public cityName: string;
}
5 changes: 5 additions & 0 deletions src/shared/modules/offer/dto/premium-offers.messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const PremiumOffersValidationMessages = {
cityName: {
invalidFormat: 'city name must be a string'
}
} as const;
69 changes: 69 additions & 0 deletions src/shared/modules/offer/dto/update-offer.dto.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,87 @@
import {Type} from 'class-transformer';
import {
ArrayMaxSize,
ArrayMinSize, ArrayUnique,
IsArray,
IsBoolean,
IsEnum,
IsInt, IsMongoId,
IsNumber,
IsString,
Max,
MaxLength,
Min,
MinLength,
ValidateNested
} from 'class-validator';

import {City, Location, OfferGood, OfferType} from '../../../types/index.js';
import {UpdateOfferValidationMessages} from './update-offer.messages.js';
import {CityValidate, LocationValidate} from './city-and-location.dto.js';
import {CityAndLocationValidationMessages} from './city-and-location.messages.js';

export class UpdateOfferDto {
@IsString({message: UpdateOfferValidationMessages.title.minLength})
@MinLength(10, {message: UpdateOfferValidationMessages.title.minLength})
@MaxLength(100, {message: UpdateOfferValidationMessages.title.maxLength})
public title?: string;

@IsEnum(OfferType, {message: UpdateOfferValidationMessages.type.invalid})
public type?: OfferType;

@IsInt({message: UpdateOfferValidationMessages.price.invalidFormat})
@Min(100, {message: UpdateOfferValidationMessages.price.minValue})
@Max(100000, {message: UpdateOfferValidationMessages.price.maxValue})
public price?: number;

@Type(() => CityValidate)
@ValidateNested({message: CityAndLocationValidationMessages.city.invalid})
public city?: City;

@Type(() => LocationValidate)
@ValidateNested({message: CityAndLocationValidationMessages.location.invalid})
public location?: Location;

@IsBoolean({message: UpdateOfferValidationMessages.isFavorite.invalidFormat})
public isFavorite?: boolean;

@IsBoolean({message: UpdateOfferValidationMessages.isPremium.invalidFormat})
public isPremium?: boolean;

@IsNumber({maxDecimalPlaces: 1}, {message: UpdateOfferValidationMessages.rating.invalidFormat})
@Min(1, {message: UpdateOfferValidationMessages.price.minValue})
@Max(5, {message: UpdateOfferValidationMessages.price.maxValue})
public rating?: number;

@IsString({message: UpdateOfferValidationMessages.description.invalidFormat})
@MinLength(20, {message: UpdateOfferValidationMessages.description.minLength})
@MaxLength(1024, {message: UpdateOfferValidationMessages.description.maxLength})
public description?: string;

@IsArray({message: UpdateOfferValidationMessages.images.invalid})
@ArrayMinSize(6, {message: UpdateOfferValidationMessages.images.length})
@ArrayMaxSize(6, {message: UpdateOfferValidationMessages.images.length})
@IsString({each: true, message: UpdateOfferValidationMessages.images.invalidItem})
public images?: string[];

@IsString({message: UpdateOfferValidationMessages.image.invalidFormat})
public previewImage?: string;

@IsArray({message: UpdateOfferValidationMessages.offerGood.invalid})
@IsEnum(OfferGood, {each: true, message: UpdateOfferValidationMessages.offerGood.invalidType})
@ArrayUnique({message: UpdateOfferValidationMessages.offerGood.unique})
public goods?: OfferGood[];

@IsMongoId({message: UpdateOfferValidationMessages.hostId.invalidId})
public hostId?: string;

@IsInt({message: UpdateOfferValidationMessages.bedrooms.invalidFormat})
@Min(1, {message: UpdateOfferValidationMessages.bedrooms.minValue})
@Max(8, {message: UpdateOfferValidationMessages.bedrooms.maxValue})
public bedrooms?: number;

@IsInt({message: UpdateOfferValidationMessages.maxAdults.invalidFormat})
@Min(1, {message: UpdateOfferValidationMessages.maxAdults.minValue})
@Max(10, {message: UpdateOfferValidationMessages.maxAdults.maxValue})
public maxAdults?: number;
}
58 changes: 58 additions & 0 deletions src/shared/modules/offer/dto/update-offer.messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
export const UpdateOfferValidationMessages = {
title: {
invalidFormat: 'title must be a string',
minLength: 'minimum title length must be 10',
maxLength: 'maximum title length must be 100',
},
type: {
invalid: 'type must be 6 cities',
},
price: {
invalidFormat: 'price must be an integer',
minValue: 'minimum price is 100',
maxValue: 'maximum price is 100000',
},
isFavorite: {
invalidFormat: 'isFavorite must be boolean'
},
isPremium: {
invalidFormat: 'isPremium must be boolean'
},
rating: {
invalidFormat: 'rating must be a number with maximum 1 decimal place',
minValue: 'minimum price is 100',
maxValue: 'maximum price is 200000',
},
description: {
invalidFormat: 'description must be a string',
minLength: 'minimum description length must be 20',
maxLength: 'maximum description length must be 1024',
},
images: {
invalid: 'images must be an array of images',
length: 'images array length must be strictly 6',
invalidItem: 'items of images array must be a string type'
},
image: {
invalidFormat: 'image must be a string type',
},
offerGood: {
invalid: 'offerGood must be an array',
invalidType: 'offer goods must be 6 cities',
unique: 'items of offer goods must be unique'
},
hostId: {
invalidId: 'host id field must be a valid id',
},
bedrooms: {
invalidFormat: 'bedrooms must be an integer',
minValue: 'minimum bedrooms count is 1',
maxValue: 'maximum bedrooms count is 8',
},
maxAdults: {
invalidFormat: 'max adults count must be an integer',
minValue: 'minimum max adults count is 1',
maxValue: 'maximum max adults count is 10',
}
} as const;

2 changes: 1 addition & 1 deletion src/shared/modules/offer/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * from './offer.entity.js';
export * from './dto/create-offer.dto.js';
export * from './default-offer.service.js';
export * from './offer.service.js';
export * from './offer.container.js';
export * from './offer-service.interface.js';
export * from './dto/premium-offers.dto.js';
Expand Down
2 changes: 1 addition & 1 deletion src/shared/modules/offer/offer-service.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {OfferEntity} from './offer.entity.js';
import {CreateOfferDto} from './dto/create-offer.dto.js';
import {UpdateOfferDto} from './dto/update-offer.dto.js';

export interface OfferService {
export interface OfferServiceInterface {
create(dto: CreateOfferDto): Promise<DocumentType<OfferEntity>>;
findAll(): Promise<DocumentType<OfferEntity>[]>;
findById(offerId: string): Promise<DocumentType<OfferEntity> | null>;
Expand Down
7 changes: 4 additions & 3 deletions src/shared/modules/offer/offer.container.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import {Container} from 'inversify';
import {types} from '@typegoose/typegoose';
import {OfferService} from './offer-service.interface.js';

import {Component} from '../../types/index.js';
import {DefaultOfferService} from './default-offer.service.js';
import {OfferService} from './offer.service.js';
import {OfferEntity, OfferModel} from './offer.entity.js';
import {OfferController} from './offer.controller.js';
import {Controller} from '../../libs/rest/index.js';
import {OfferServiceInterface} from './offer-service.interface.js';

export function createOfferContainer() {
const offerContainer = new Container();
offerContainer.bind<OfferService>(Component.OfferService).to(DefaultOfferService).inSingletonScope();
offerContainer.bind<OfferServiceInterface>(Component.OfferService).to(OfferService).inSingletonScope();
offerContainer.bind<types.ModelType<OfferEntity>>(Component.OfferModel).toConstantValue(OfferModel);
offerContainer.bind<Controller>(Component.OfferController).to(OfferController).inSingletonScope();

Expand Down
Loading

0 comments on commit b915d28

Please sign in to comment.