2023-01-30 12:39:05 +01:00
|
|
|
import { IncomingMessage, ServerResponse } from 'http'
|
|
|
|
|
import { schedule } from '../../../common/scheduler'
|
|
|
|
|
import { asyncLocalStorage as l } from '../../../common/logger'
|
|
|
|
|
import { Router } from './index'
|
|
|
|
|
import { Reservation } from '../../../common/reservation'
|
|
|
|
|
import { parse } from 'querystring'
|
2023-02-10 12:24:27 +01:00
|
|
|
import dayjs from '../../../common/dayjs'
|
|
|
|
|
import { Dayjs } from 'dayjs'
|
2023-01-30 12:39:05 +01:00
|
|
|
|
|
|
|
|
export class ReservationsRouter extends Router {
|
|
|
|
|
public async handleRequest(
|
|
|
|
|
req: IncomingMessage,
|
2023-02-10 12:24:27 +01:00
|
|
|
res: ServerResponse<IncomingMessage>
|
2023-01-30 12:39:05 +01:00
|
|
|
) {
|
|
|
|
|
const { url = '', method } = req
|
|
|
|
|
const [route] = url.split('?')
|
|
|
|
|
switch (true) {
|
|
|
|
|
case /^\/reservations$/.test(route) && method === 'GET': {
|
|
|
|
|
await this.GET_reservations(req, res)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
case /^\/reservations$/.test(route) && method === 'POST': {
|
|
|
|
|
await this.POST_reservations(req, res)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
case /^\/reservations\/\S+$/.test(route) && method === 'DELETE': {
|
|
|
|
|
await this.DELETE_reservation(req, res)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
default: {
|
|
|
|
|
this.handle404(req, res)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 12:24:27 +01:00
|
|
|
private async GET_reservations(
|
|
|
|
|
req: IncomingMessage,
|
|
|
|
|
res: ServerResponse<IncomingMessage>
|
|
|
|
|
) {
|
2023-01-30 12:39:05 +01:00
|
|
|
const { url = '' } = req
|
|
|
|
|
const [, queryParams] = url.split('?')
|
|
|
|
|
let pageNumber = 0
|
|
|
|
|
let pageSize = 0
|
2023-02-10 12:24:27 +01:00
|
|
|
let date: Dayjs | undefined = undefined
|
|
|
|
|
const {
|
|
|
|
|
pageNumber: rawPageNumber = '0',
|
|
|
|
|
pageSize: rawPageSize = '50',
|
|
|
|
|
date: rawDate,
|
|
|
|
|
} = parse(queryParams)
|
2023-01-30 12:39:05 +01:00
|
|
|
if (typeof rawPageNumber === 'string') {
|
|
|
|
|
pageNumber = Number.parseInt(rawPageNumber)
|
|
|
|
|
} else {
|
|
|
|
|
pageNumber = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (typeof rawPageSize === 'string') {
|
|
|
|
|
pageSize = Math.min(Number.parseInt(rawPageSize), 50)
|
|
|
|
|
} else {
|
|
|
|
|
pageSize = 50
|
|
|
|
|
}
|
2023-02-10 12:24:27 +01:00
|
|
|
|
|
|
|
|
if (typeof rawDate === 'string') {
|
|
|
|
|
date = dayjs(rawDate)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 14:13:12 +01:00
|
|
|
l.getStore()?.debug('Fetching reservations', { pageNumber, pageSize, date })
|
2023-01-30 12:39:05 +01:00
|
|
|
|
|
|
|
|
try {
|
2023-02-10 12:24:27 +01:00
|
|
|
let reservations: Reservation[]
|
|
|
|
|
if (date) {
|
|
|
|
|
reservations = await Reservation.fetchByDate(date, 50)
|
|
|
|
|
} else {
|
|
|
|
|
reservations = await Reservation.fetchByPage(pageNumber, pageSize)
|
|
|
|
|
}
|
2023-01-30 12:39:05 +01:00
|
|
|
res.setHeader('content-type', 'application/json')
|
2023-02-10 12:24:27 +01:00
|
|
|
l.getStore()?.debug('Found reservations', {
|
|
|
|
|
reservations: reservations.map((r) => r.toString(true)),
|
|
|
|
|
})
|
2023-01-30 12:39:05 +01:00
|
|
|
return new Promise<void>((resolve, reject) => {
|
2023-02-10 12:24:27 +01:00
|
|
|
res.write(
|
|
|
|
|
`[${reservations.map((r) => r.toString(true)).join(',')}]`,
|
|
|
|
|
(err) => {
|
|
|
|
|
if (err) {
|
|
|
|
|
reject(err)
|
|
|
|
|
}
|
|
|
|
|
resolve()
|
2023-01-30 12:39:05 +01:00
|
|
|
}
|
2023-02-10 12:24:27 +01:00
|
|
|
)
|
2023-01-30 12:39:05 +01:00
|
|
|
})
|
|
|
|
|
} catch (error) {
|
|
|
|
|
l.getStore()?.error('Failed to get reservations', {
|
|
|
|
|
message: (error as Error).message,
|
|
|
|
|
stack: (error as Error).stack,
|
|
|
|
|
})
|
|
|
|
|
res.writeHead(500)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 12:24:27 +01:00
|
|
|
private async POST_reservations(
|
|
|
|
|
req: IncomingMessage,
|
|
|
|
|
res: ServerResponse<IncomingMessage>
|
|
|
|
|
) {
|
2023-01-30 12:39:05 +01:00
|
|
|
const jsonBody = await this.parseJsonContent(req)
|
|
|
|
|
try {
|
|
|
|
|
await schedule(jsonBody)
|
|
|
|
|
} catch (error: unknown) {
|
|
|
|
|
l.getStore()?.error('Failed to create reservation', {
|
|
|
|
|
message: (error as Error).message,
|
|
|
|
|
stack: (error as Error).stack,
|
|
|
|
|
})
|
|
|
|
|
res.writeHead(400)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 12:24:27 +01:00
|
|
|
private async DELETE_reservation(
|
|
|
|
|
req: IncomingMessage,
|
|
|
|
|
res: ServerResponse<IncomingMessage>
|
|
|
|
|
) {
|
2023-01-30 12:39:05 +01:00
|
|
|
const { url = '' } = req
|
2023-02-10 12:24:27 +01:00
|
|
|
const [, , id] = url.split('/')
|
2023-01-30 12:39:05 +01:00
|
|
|
l.getStore()?.debug('Deleting reservation', { id })
|
|
|
|
|
try {
|
|
|
|
|
await Reservation.deleteById(id)
|
|
|
|
|
res.writeHead(200)
|
|
|
|
|
} catch (error) {
|
|
|
|
|
l.getStore()?.error('Failed to get reservations', {
|
|
|
|
|
message: (error as Error).message,
|
|
|
|
|
stack: (error as Error).stack,
|
|
|
|
|
})
|
|
|
|
|
res.writeHead(500)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|