Include more details when throwing errors for debugging in Sentry * WIP throw errors with more details for debugging in Sentry * Fix throwing response-data * Clearer message when a response fails * Add message to errors * better typings * . * Try to send profileID and membershipNumber to Sentry when we fail to parse the apiResponse * rename notFound -> notFoundError * Merge branch 'master' of bitbucket.org:scandic-swap/web into chore/add-error-details-for-sentry Approved-by: Linus Flood
115 lines
2.7 KiB
TypeScript
115 lines
2.7 KiB
TypeScript
import { createCounter } from "@scandic-hotels/common/telemetry"
|
|
|
|
import * as api from "../../../api"
|
|
import {
|
|
badRequestError,
|
|
extractResponseDetails,
|
|
serverErrorByStatus,
|
|
} from "../../../errors"
|
|
import { toApiLang } from "../../../utils"
|
|
import { hotelsAvailabilitySchema } from "../output"
|
|
|
|
import type { Lang } from "@scandic-hotels/common/constants/language"
|
|
|
|
import type { HotelsAvailabilityInputSchema } from "../availability/hotelsByCity"
|
|
|
|
export async function getHotelsAvailabilityByCity({
|
|
input,
|
|
lang,
|
|
userToken,
|
|
serviceToken,
|
|
userPoints = 0,
|
|
}: {
|
|
input: HotelsAvailabilityInputSchema
|
|
lang: Lang
|
|
userToken: string | null | undefined
|
|
serviceToken: string
|
|
userPoints: number | undefined
|
|
}) {
|
|
const {
|
|
cityId,
|
|
roomStayStartDate,
|
|
roomStayEndDate,
|
|
adults,
|
|
children,
|
|
bookingCode,
|
|
redemption,
|
|
} = input
|
|
|
|
const apiLang = toApiLang(lang)
|
|
|
|
const params = {
|
|
roomStayStartDate,
|
|
roomStayEndDate,
|
|
adults,
|
|
...(children && { children }),
|
|
...(bookingCode && { bookingCode }),
|
|
...(redemption ? { isRedemption: "true" } : {}),
|
|
language: apiLang,
|
|
} satisfies Record<string, string | number>
|
|
|
|
const getHotelsAvailabilityByCityCounter = createCounter(
|
|
"hotel.getHotelsAvailabilityByCity"
|
|
)
|
|
const metricsGetHotelsAvailabilityByCity =
|
|
getHotelsAvailabilityByCityCounter.init({
|
|
apiLang,
|
|
cityId,
|
|
roomStayStartDate,
|
|
roomStayEndDate,
|
|
adults,
|
|
children,
|
|
bookingCode,
|
|
redemption,
|
|
})
|
|
|
|
metricsGetHotelsAvailabilityByCity.start()
|
|
|
|
const apiResponse = await api.get(
|
|
api.endpoints.v1.Availability.city(cityId),
|
|
{
|
|
headers: {
|
|
Authorization: `Bearer ${userToken ?? serviceToken}`,
|
|
},
|
|
},
|
|
params
|
|
)
|
|
|
|
if (!apiResponse.ok) {
|
|
await metricsGetHotelsAvailabilityByCity.httpError(apiResponse)
|
|
|
|
throw serverErrorByStatus(
|
|
apiResponse.status,
|
|
await extractResponseDetails(apiResponse),
|
|
"getHotelsAvailabilityByCity failed"
|
|
)
|
|
}
|
|
|
|
const apiJson = await apiResponse.json()
|
|
const validateAvailabilityData = hotelsAvailabilitySchema.safeParse(apiJson)
|
|
if (!validateAvailabilityData.success) {
|
|
metricsGetHotelsAvailabilityByCity.validationError(
|
|
validateAvailabilityData.error
|
|
)
|
|
throw badRequestError()
|
|
}
|
|
|
|
if (redemption) {
|
|
validateAvailabilityData.data.data.forEach((data) => {
|
|
data.attributes.productType?.redemptions?.forEach((r) => {
|
|
r.hasEnoughPoints = userPoints >= r.localPrice.pointsPerStay
|
|
})
|
|
})
|
|
}
|
|
|
|
const result = {
|
|
availability: validateAvailabilityData.data.data.flatMap(
|
|
(hotels) => hotels.attributes
|
|
),
|
|
}
|
|
|
|
metricsGetHotelsAvailabilityByCity.success()
|
|
|
|
return result
|
|
}
|