Files
Linus Flood 5fc93472f4 Merged in feat/rework-contentstack (pull request #3493)
Feat(SW-3708): refactor contentstack fetching (removing all refs) and cache invalidation

* Remove all REFS

* Revalidate correct language

* PR fixes

* PR fixes

* Throw when errors from contentstack api


Approved-by: Joakim Jäderberg
2026-01-27 12:38:36 +00:00

147 lines
4.0 KiB
TypeScript

import { createCounter } from "@scandic-hotels/common/telemetry"
import { GetDestinationCityListData } from "../../../graphql/Query/DestinationCityPage/DestinationCityListData.graphql"
import { GetCountryPageUrls } from "../../../graphql/Query/DestinationCountryPage/DestinationCountryPageUrl.graphql"
import { request } from "../../../graphql/request"
import { ApiCountry } from "../../../types/country"
import { generateTag } from "../../../utils/generateTag"
import { getCitiesByCountry } from "../../hotels/services/getCitiesByCountry"
import { destinationCityListDataSchema } from "../destinationCityPage/output"
import { countryPageUrlsSchema } from "./output"
import type { Country } from "@scandic-hotels/common/constants/country"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { GetDestinationCityListDataResponse } from "../../../types/destinationCityPage"
import type { GetCountryPageUrlsData } from "../../../types/destinationCountryPage"
export async function getCityListDataByCityIdentifier(
lang: Lang,
cityIdentifier: string
) {
const getCityListDataCounter = createCounter(
"trpc.contentstack.cityListData.get"
)
const metricsGetCityListData = getCityListDataCounter.init({
lang,
cityIdentifier,
})
metricsGetCityListData.start()
const response = await request<GetDestinationCityListDataResponse>(
GetDestinationCityListData,
{
locale: lang,
cityIdentifier,
},
{
key: generateTag(lang, `city_list_data:${cityIdentifier}`),
ttl: "max",
}
)
if (!response.data) {
metricsGetCityListData.dataError(
`Failed to get destination city page for cityIdentifier: ${cityIdentifier}`
)
return null
}
const validatedResponse = destinationCityListDataSchema.safeParse(
response.data
)
if (!validatedResponse.success) {
metricsGetCityListData.validationError(validatedResponse.error)
return null
}
metricsGetCityListData.success()
return validatedResponse.data
}
export async function getCityPages(
lang: Lang,
serviceToken: string,
country: Country
) {
const apiCountry = ApiCountry[lang][country]
const cities = await getCitiesByCountry({
countries: [apiCountry],
lang,
serviceToken,
})
const publishedCities = cities[apiCountry].filter((city) => city.isPublished)
// It happens we receive duplicate cities with the same city identifier.
// Remove duplicate cities based on city identifier
const uniquePublishedCities = publishedCities.filter(
(city, index, self) =>
index === self.findIndex((c) => c.cityIdentifier === city.cityIdentifier)
)
const cityPages = await Promise.all(
uniquePublishedCities.map(async (city) => {
if (!city.cityIdentifier) {
return null
}
const data = await getCityListDataByCityIdentifier(
lang,
city.cityIdentifier
)
return data
? { ...data, cityName: city.name, cityIdentifier: city.cityIdentifier }
: null
})
)
return cityPages
.flat()
.filter((city): city is NonNullable<typeof city> => !!city)
}
export async function getCountryPageUrls(lang: Lang) {
const getCountryPageUrlsCounter = createCounter(
"trpc.contentstack.getCountryPageUrls"
)
const metricsGetCountryPageUrls = getCountryPageUrlsCounter.init({ lang })
metricsGetCountryPageUrls.start()
const tag = `${lang}:country_page_urls`
const response = await request<GetCountryPageUrlsData>(
GetCountryPageUrls,
{
locale: lang,
},
{
key: tag,
ttl: "max",
}
)
if (!response.data) {
metricsGetCountryPageUrls.dataError(
`Failed to get country pages for lang: ${lang}`
)
return []
}
const validatedCountryPageUrls = countryPageUrlsSchema.safeParse(
response.data
)
if (!validatedCountryPageUrls.success) {
metricsGetCountryPageUrls.validationError(validatedCountryPageUrls.error)
return []
}
metricsGetCountryPageUrls.success()
return validatedCountryPageUrls.data
}