import { GetDestinationCityListData } from "@/lib/graphql/Query/DestinationCityPage/DestinationCityListData.graphql" import { GetCountryPageUrls } from "@/lib/graphql/Query/DestinationCountryPage/DestinationCountryPageUrl.graphql" import { request } from "@/lib/graphql/request" import { createCounter } from "@/server/telemetry" import { generateTag, generateTagsFromSystem } from "@/utils/generateTag" import { getCitiesByCountry } from "../../hotels/utils" import { destinationCityListDataSchema } from "../destinationCityPage/output" import { countryPageUrlsSchema } from "./output" import { ApiCountry, type Country } from "@/types/enums/country" import { DestinationCountryPageEnum } from "@/types/enums/destinationCountryPage" import type { System } from "@/types/requests/system" import type { GetDestinationCityListDataResponse } from "@/types/trpc/routers/contentstack/destinationCityPage" import type { DestinationCountryPageRefs, GetCountryPageUrlsData, } from "@/types/trpc/routers/contentstack/destinationCountryPage" import type { Lang } from "@/constants/languages" export function generatePageTags( validatedData: DestinationCountryPageRefs, lang: Lang ): string[] { const connections = getConnections(validatedData) return [ generateTagsFromSystem(lang, connections), generateTag(lang, validatedData.destination_country_page.system.uid), ].flat() } export function getConnections({ destination_country_page, }: DestinationCountryPageRefs) { const connections: System["system"][] = [destination_country_page.system] if (destination_country_page.blocks) { destination_country_page.blocks.forEach((block) => { switch (block.__typename) { case DestinationCountryPageEnum.ContentStack.blocks.Accordion: { if (block.accordion.length) { connections.push(...block.accordion) } break } case DestinationCountryPageEnum.ContentStack.blocks.Content: { if (block.content.length) { // TS has trouble infering the filtered types // @ts-ignore connections.push(...block.content) } } break } }) } if (destination_country_page.sidepeek_content) { destination_country_page.sidepeek_content.content.embedded_itemsConnection.edges.forEach( ({ node }) => { connections.push(node.system) } ) } return connections } 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( 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) const cityPages = await Promise.all( publishedCities.map(async (city) => { if (!city.cityIdentifier) { return null } const data = await getCityListDataByCityIdentifier( lang, city.cityIdentifier ) return data ? { ...data, cityName: city.name } : null }) ) return cityPages .flat() .filter((city): city is NonNullable => !!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( 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 }