Updating controllers to use separate req class for transformation and validation
This commit is contained in:
parent
39bed45814
commit
d8370ee4b8
5 changed files with 121 additions and 31 deletions
|
|
@ -10,7 +10,7 @@ async function bootstrap() {
|
||||||
const config = app.get(ConfigService)
|
const config = app.get(ConfigService)
|
||||||
const port = config.get('PORT', 3000)
|
const port = config.get('PORT', 3000)
|
||||||
app.enableShutdownHooks()
|
app.enableShutdownHooks()
|
||||||
app.useGlobalPipes(new ValidationPipe())
|
app.useGlobalPipes(new ValidationPipe({ transform: true }))
|
||||||
app.useGlobalInterceptors(new CustomResponseTransformInterceptor())
|
app.useGlobalInterceptors(new CustomResponseTransformInterceptor())
|
||||||
await app.listen(port, () => console.log(`Listening on port ${port}`))
|
await app.listen(port, () => console.log(`Listening on port ${port}`))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,37 @@ import {
|
||||||
Post,
|
Post,
|
||||||
Query,
|
Query,
|
||||||
UseInterceptors,
|
UseInterceptors,
|
||||||
UsePipes,
|
|
||||||
ValidationPipe,
|
|
||||||
} from '@nestjs/common'
|
} from '@nestjs/common'
|
||||||
|
import { IsEnum, IsOptional, IsString, Matches } from 'class-validator'
|
||||||
|
|
||||||
import { DayOfWeek, RecurringReservation } from './entity'
|
import { DayOfWeek } from './entity'
|
||||||
import { RecurringReservationsService } from './service'
|
import { RecurringReservationsService } from './service'
|
||||||
|
|
||||||
|
export class CreateRecurringReservationRequest {
|
||||||
|
@IsString()
|
||||||
|
ownerId: string
|
||||||
|
|
||||||
|
@IsEnum(DayOfWeek)
|
||||||
|
dayOfWeek: number
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@Matches(/[012][0-9]:[0-5][0-9]/)
|
||||||
|
timeStart: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@Matches(/[012][0-9]:[0-5][0-9]/)
|
||||||
|
timeEnd?: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
opponentId?: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
opponentName?: string
|
||||||
|
}
|
||||||
|
|
||||||
@Controller('recurring-reservations')
|
@Controller('recurring-reservations')
|
||||||
@UseInterceptors(ClassSerializerInterceptor)
|
@UseInterceptors(ClassSerializerInterceptor)
|
||||||
export class RecurringReservationsController {
|
export class RecurringReservationsController {
|
||||||
|
|
@ -38,15 +62,8 @@ export class RecurringReservationsController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@UsePipes(
|
async createReservation(@Body() req: CreateRecurringReservationRequest) {
|
||||||
new ValidationPipe({
|
await this.recurringReservationsService.create(req)
|
||||||
transform: true,
|
|
||||||
transformOptions: { groups: ['password'] },
|
|
||||||
groups: ['password'],
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
async createReservation(@Body() recurringReservation: RecurringReservation) {
|
|
||||||
await this.recurringReservationsService.create(recurringReservation)
|
|
||||||
return 'Recurring reservation created'
|
return 'Recurring reservation created'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,30 @@ export class RecurringReservationsService {
|
||||||
.getMany()
|
.getMany()
|
||||||
}
|
}
|
||||||
|
|
||||||
create(recurringReservation: RecurringReservation) {
|
async create({
|
||||||
return this.recurringReservationsRepository.save(recurringReservation)
|
ownerId,
|
||||||
|
dayOfWeek,
|
||||||
|
timeStart,
|
||||||
|
timeEnd,
|
||||||
|
opponentId = '-1',
|
||||||
|
opponentName = 'Gast',
|
||||||
|
}: {
|
||||||
|
ownerId: string
|
||||||
|
dayOfWeek: DayOfWeek
|
||||||
|
timeStart: string
|
||||||
|
timeEnd?: string
|
||||||
|
opponentId?: string
|
||||||
|
opponentName?: string
|
||||||
|
}) {
|
||||||
|
const recRes = this.recurringReservationsRepository.create({
|
||||||
|
ownerId,
|
||||||
|
dayOfWeek,
|
||||||
|
timeStart,
|
||||||
|
timeEnd: timeEnd ?? timeStart,
|
||||||
|
opponentId,
|
||||||
|
opponentName,
|
||||||
|
})
|
||||||
|
return await this.recurringReservationsRepository.save(recRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleReservation(recurringReservation: RecurringReservation) {
|
scheduleReservation(recurringReservation: RecurringReservation) {
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,13 @@ import {
|
||||||
Post,
|
Post,
|
||||||
Query,
|
Query,
|
||||||
UseInterceptors,
|
UseInterceptors,
|
||||||
UsePipes,
|
|
||||||
ValidationPipe,
|
|
||||||
} from '@nestjs/common'
|
} from '@nestjs/common'
|
||||||
import { Queue } from 'bull'
|
import { Queue } from 'bull'
|
||||||
import { Transform } from 'class-transformer'
|
import { Transform, TransformationType } from 'class-transformer'
|
||||||
import { IsBoolean, IsOptional } from 'class-validator'
|
import { IsBoolean, IsOptional, IsString } from 'class-validator'
|
||||||
import { Dayjs } from 'dayjs'
|
import { Dayjs } from 'dayjs'
|
||||||
|
|
||||||
|
import dayjs from '../common/dayjs'
|
||||||
import { LoggerService } from '../logger/service.logger'
|
import { LoggerService } from '../logger/service.logger'
|
||||||
import { RESERVATIONS_QUEUE_NAME } from './config'
|
import { RESERVATIONS_QUEUE_NAME } from './config'
|
||||||
import { Reservation } from './entity'
|
import { Reservation } from './entity'
|
||||||
|
|
@ -34,6 +33,44 @@ export class GetReservationsQueryParams {
|
||||||
readonly schedulable?: boolean
|
readonly schedulable?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class CreateReservationRequest {
|
||||||
|
@IsString()
|
||||||
|
ownerId: string
|
||||||
|
|
||||||
|
@Transform(({ value, type }) => {
|
||||||
|
switch (type) {
|
||||||
|
case TransformationType.PLAIN_TO_CLASS:
|
||||||
|
return dayjs(value)
|
||||||
|
case TransformationType.CLASS_TO_PLAIN:
|
||||||
|
return value.format()
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dateRangeStart: Dayjs
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@Transform(({ value, type }) => {
|
||||||
|
switch (type) {
|
||||||
|
case TransformationType.PLAIN_TO_CLASS:
|
||||||
|
return dayjs(value)
|
||||||
|
case TransformationType.CLASS_TO_PLAIN:
|
||||||
|
return value.format()
|
||||||
|
default:
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
dateRangeEnd?: Dayjs
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
opponentId?: string
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
opponentName?: string
|
||||||
|
}
|
||||||
|
|
||||||
@Controller('reservations')
|
@Controller('reservations')
|
||||||
@UseInterceptors(ClassSerializerInterceptor)
|
@UseInterceptors(ClassSerializerInterceptor)
|
||||||
export class ReservationsController {
|
export class ReservationsController {
|
||||||
|
|
@ -66,21 +103,15 @@ export class ReservationsController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Post()
|
@Post()
|
||||||
@UsePipes(
|
async createReservation(@Body() req: CreateReservationRequest) {
|
||||||
new ValidationPipe({
|
console.log(req)
|
||||||
transform: true,
|
const reservation = await this.reservationsService.create(req)
|
||||||
transformOptions: { groups: ['password'] },
|
|
||||||
groups: ['password'],
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
async createReservation(@Body() reservation: Reservation) {
|
|
||||||
await this.reservationsService.create(reservation)
|
|
||||||
if (!reservation.isAvailableForReservation()) {
|
if (!reservation.isAvailableForReservation()) {
|
||||||
this.loggerService.debug('Reservation not available for reservation')
|
this.loggerService.debug('Reservation not available for reservation')
|
||||||
return 'Reservation saved'
|
return 'Reservation saved'
|
||||||
}
|
}
|
||||||
this.loggerService.debug('Reservation is available for reservation')
|
this.loggerService.debug('Reservation is available for reservation')
|
||||||
await this.reservationsQueue.add(reservation)
|
// await this.reservationsQueue.add(reservation)
|
||||||
return 'Reservation queued'
|
return 'Reservation queued'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { Inject, Injectable } from '@nestjs/common'
|
import { Inject, Injectable } from '@nestjs/common'
|
||||||
import { InjectRepository } from '@nestjs/typeorm'
|
import { InjectRepository } from '@nestjs/typeorm'
|
||||||
|
import { Dayjs } from 'dayjs'
|
||||||
import { Repository } from 'typeorm'
|
import { Repository } from 'typeorm'
|
||||||
|
|
||||||
import dayjs from '../common/dayjs'
|
import dayjs from '../common/dayjs'
|
||||||
|
|
@ -68,8 +69,27 @@ export class ReservationsService {
|
||||||
.getMany()
|
.getMany()
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(reservation: Reservation) {
|
async create({
|
||||||
return await this.reservationsRepository.save(reservation)
|
ownerId,
|
||||||
|
dateRangeStart,
|
||||||
|
dateRangeEnd,
|
||||||
|
opponentId = '-1',
|
||||||
|
opponentName = 'Gast',
|
||||||
|
}: {
|
||||||
|
ownerId: string
|
||||||
|
dateRangeStart: Dayjs
|
||||||
|
dateRangeEnd?: Dayjs
|
||||||
|
opponentId?: string
|
||||||
|
opponentName?: string
|
||||||
|
}) {
|
||||||
|
const res = this.reservationsRepository.create({
|
||||||
|
ownerId,
|
||||||
|
dateRangeStart,
|
||||||
|
dateRangeEnd: dateRangeEnd ?? dateRangeStart,
|
||||||
|
opponentId,
|
||||||
|
opponentName,
|
||||||
|
})
|
||||||
|
return await this.reservationsRepository.save(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(reservationId: string, update: Partial<Reservation>) {
|
async update(reservationId: string, update: Partial<Reservation>) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue