Merged in feature/SW-3572-hotel-data-endpoint (pull request #3051)
SW-3572 API route for listing hotels per city or country * wip hotel data endpoint * Correct route params type * wip * skip static paths call * timeout when getting destinations take too long * call noStore when we get a timeout * add cache-control headers * . * . * . * wip * wip * wip * wip * add route for getting hotels per country * include city when listing by country * fix distance SI unit * fix sorting * Merge branch 'master' of bitbucket.org:scandic-swap/web into feature/SW-3572-hotel-data-endpoint * packages/tracking passWithNoTests * revalidate must be static value * remove oxc reference * cleanup * cleanup hotel api route * feat(SW-3572): cleanup error handling Approved-by: Anton Gunnarsson
This commit is contained in:
@@ -11,11 +11,9 @@ import { BreakfastPackageEnum } from "../../enums/breakfast"
|
||||
import { badRequestError } from "../../errors"
|
||||
import {
|
||||
contentStackBaseWithServiceProcedure,
|
||||
publicProcedure,
|
||||
safeProtectedServiceProcedure,
|
||||
serviceProcedure,
|
||||
} from "../../procedures"
|
||||
import { getCityPageUrls } from "../../routers/contentstack/destinationCityPage/utils"
|
||||
import { getHotelPageUrls } from "../../routers/contentstack/hotelPage/utils"
|
||||
import {
|
||||
ancillaryPackageInputSchema,
|
||||
@@ -26,8 +24,6 @@ import {
|
||||
getHotelsByCityIdentifierInput,
|
||||
getHotelsByCountryInput,
|
||||
getHotelsByCSFilterInput,
|
||||
getLocationsInput,
|
||||
getLocationsUrlsInput,
|
||||
getMeetingRoomsInputSchema,
|
||||
hotelInputSchema,
|
||||
nearbyHotelIdsInput,
|
||||
@@ -38,22 +34,22 @@ import {
|
||||
breakfastPackagesSchema,
|
||||
getNearbyHotelIdsSchema,
|
||||
} from "../../routers/hotels/output"
|
||||
import { isCityLocation } from "../../types/locations"
|
||||
import { toApiLang } from "../../utils"
|
||||
import { additionalDataSchema } from "./schemas/hotel/include/additionalData"
|
||||
import { meetingRoomsSchema } from "./schemas/meetingRoom"
|
||||
import { getCitiesByCountry } from "./services/getCitiesByCountry"
|
||||
import { getHotelIdsByCityIdentifier } from "./services/getCityByCityIdentifier"
|
||||
import { getCountries } from "./services/getCountries"
|
||||
import { getHotel } from "./services/getHotel"
|
||||
import { getHotelIdsByCityId } from "./services/getHotelIdsByCityId"
|
||||
import { getHotelIdsByCountry } from "./services/getHotelIdsByCountry"
|
||||
import { getHotelsByHotelIds } from "./services/getHotelsByHotelIds"
|
||||
import { getLocationsByCountries } from "./services/getLocationsByCountries"
|
||||
import { getPackages } from "./services/getPackages"
|
||||
import { availability } from "./availability"
|
||||
import { getLocations } from "./utils"
|
||||
import { locationsRouter } from "./locations"
|
||||
|
||||
import type { HotelListingHotelData } from "../../types/hotel"
|
||||
import type { CityLocation } from "../../types/locations"
|
||||
|
||||
const hotelQueryLogger = createLogger("hotelQueryRouter")
|
||||
|
||||
@@ -82,9 +78,11 @@ export const hotelQueryRouter = router({
|
||||
get: contentStackBaseWithServiceProcedure
|
||||
.input(getHotelsByCountryInput)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const { lang, serviceToken } = ctx
|
||||
const { serviceToken } = ctx
|
||||
const { country } = input
|
||||
|
||||
const lang = input.lang ?? ctx.lang
|
||||
|
||||
const hotelIds = await getHotelIdsByCountry({
|
||||
country,
|
||||
serviceToken: ctx.serviceToken,
|
||||
@@ -133,20 +131,18 @@ export const hotelQueryRouter = router({
|
||||
hotelsToFetch = hotelsToInclude
|
||||
shouldSortByDistance = false
|
||||
} else if (locationFilter?.city) {
|
||||
const locations = await getLocations({
|
||||
const locations = await getLocationsByCountries({
|
||||
lang: language,
|
||||
serviceToken: ctx.serviceToken,
|
||||
citiesByCountry: null,
|
||||
})
|
||||
if (!locations || "error" in locations) {
|
||||
|
||||
if (!locations || locations.length === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const cityId = locations
|
||||
.filter(
|
||||
(loc): loc is CityLocation =>
|
||||
"type" in loc && loc.type === "cities"
|
||||
)
|
||||
.filter(isCityLocation)
|
||||
.find((loc) => loc.cityIdentifier === locationFilter.city)?.id
|
||||
|
||||
if (!cityId) {
|
||||
@@ -339,87 +335,7 @@ export const hotelQueryRouter = router({
|
||||
env.CACHE_TIME_HOTELS
|
||||
)
|
||||
}),
|
||||
locations: router({
|
||||
get: serviceProcedure.input(getLocationsInput).query(async function ({
|
||||
ctx,
|
||||
input,
|
||||
}) {
|
||||
const lang = input.lang ?? ctx.lang
|
||||
const cacheClient = await getCacheClient()
|
||||
return await cacheClient.cacheOrGet(
|
||||
`${lang}:getLocations`,
|
||||
async () => {
|
||||
const countries = await getCountries({
|
||||
lang: lang,
|
||||
serviceToken: ctx.serviceToken,
|
||||
})
|
||||
|
||||
if (!countries) {
|
||||
throw new Error("Unable to fetch countries")
|
||||
}
|
||||
const countryNames = countries.data.map((country) => country.name)
|
||||
const citiesByCountry = await getCitiesByCountry({
|
||||
countries: countryNames,
|
||||
serviceToken: ctx.serviceToken,
|
||||
lang,
|
||||
})
|
||||
|
||||
const locations = await getLocations({
|
||||
lang,
|
||||
serviceToken: ctx.serviceToken,
|
||||
citiesByCountry,
|
||||
})
|
||||
|
||||
if (!locations || "error" in locations) {
|
||||
throw new Error("Unable to fetch locations")
|
||||
}
|
||||
|
||||
return locations
|
||||
},
|
||||
"max"
|
||||
)
|
||||
}),
|
||||
urls: publicProcedure
|
||||
.input(getLocationsUrlsInput)
|
||||
.query(async ({ input }) => {
|
||||
const { lang } = input
|
||||
|
||||
const locationsUrlsCounter = createCounter(
|
||||
"trpc.hotel.locations",
|
||||
"urls"
|
||||
)
|
||||
const metricsLocationsUrls = locationsUrlsCounter.init({
|
||||
lang,
|
||||
})
|
||||
|
||||
metricsLocationsUrls.start()
|
||||
|
||||
const [hotelPageUrlsResult, cityPageUrlsResult] =
|
||||
await Promise.allSettled([
|
||||
getHotelPageUrls(lang),
|
||||
getCityPageUrls(lang),
|
||||
])
|
||||
|
||||
if (
|
||||
hotelPageUrlsResult.status === "rejected" ||
|
||||
cityPageUrlsResult.status === "rejected"
|
||||
) {
|
||||
metricsLocationsUrls.dataError(`Failed to get data for page URLs`, {
|
||||
hotelPageUrlsResult,
|
||||
cityPageUrlsResult,
|
||||
})
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
metricsLocationsUrls.success()
|
||||
|
||||
return {
|
||||
hotels: hotelPageUrlsResult.value,
|
||||
cities: cityPageUrlsResult.value,
|
||||
}
|
||||
}),
|
||||
}),
|
||||
locations: locationsRouter,
|
||||
map: router({
|
||||
city: serviceProcedure
|
||||
.input(cityCoordinatesInputSchema)
|
||||
|
||||
Reference in New Issue
Block a user