import { cache } from "react" import { createCounter } from "@scandic-hotels/common/telemetry" import { router } from "../../.." import { notFoundError } from "../../../errors" import { GetContactConfig } from "../../../graphql/Query/ContactConfig.graphql" import { GetFooter } from "../../../graphql/Query/Footer.graphql" import { GetHeader } from "../../../graphql/Query/Header.graphql" import { GetSiteConfig } from "../../../graphql/Query/SiteConfig.graphql" import { GetSitewideCampaignBanner } from "../../../graphql/Query/SitewideCampaignBanner.graphql" import { request } from "../../../graphql/request" import { contentstackBaseProcedure } from "../../../procedures" import { langInput } from "../../../utils" import { generateTag } from "../../../utils/generateTag" import { type ContactConfigData, headerSchema, siteConfigSchema, sitewideCampaignBannerSchema, validateContactConfigSchema, validateFooterConfigSchema, } from "./output" import { getAlertPhoneContactData } from "./utils" import type { Lang } from "@scandic-hotels/common/constants/language" import type { FooterDataRaw } from "../../../types/footer" import type { GetHeader as GetHeaderData } from "../../../types/header" import type { GetSiteConfigData, GetSitewideCampaignBannerData, } from "../../../types/siteConfig" const getContactConfig = cache(async (lang: Lang) => { const getContactConfigCounter = createCounter( "trpc.contentstack.contactConfig.get" ) const metricsGetContactConfig = getContactConfigCounter.init({ lang }) metricsGetContactConfig.start() const variables = { locale: lang, } const response = await request( GetContactConfig, variables, { key: `${lang}:contact_config`, ttl: "max", } ) if (!response.data) { metricsGetContactConfig.noDataError() throw notFoundError({ message: "GetContactConfig returned no data", errorDetails: variables, }) } const verifiedData = validateContactConfigSchema.safeParse(response.data) if (!verifiedData.success) { metricsGetContactConfig.validationError(verifiedData.error) return null } metricsGetContactConfig.success() return verifiedData.data.all_contact_config.items[0] }) export const baseQueryRouter = router({ contact: contentstackBaseProcedure.query(async ({ ctx }) => { return await getContactConfig(ctx.lang) }), header: contentstackBaseProcedure.query(async ({ ctx }) => { const { lang } = ctx const getHeaderCounter = createCounter("trpc.contentstack.header.get") const metricsGetHeader = getHeaderCounter.init({ lang }) metricsGetHeader.start() const variables = { locale: lang } const response = await request(GetHeader, variables, { key: generateTag(lang, "header"), ttl: "max", }) if (!response.data) { metricsGetHeader.noDataError() throw notFoundError({ message: "GetHeader returned no data", errorDetails: variables, }) } const validatedHeaderConfig = headerSchema.safeParse(response.data) if (!validatedHeaderConfig.success) { metricsGetHeader.validationError(validatedHeaderConfig.error) return null } metricsGetHeader.success() return { data: validatedHeaderConfig.data.header } }), footer: contentstackBaseProcedure.query(async ({ ctx }) => { const { lang } = ctx const getFooterCounter = createCounter("trpc.contentstack.footer.get") const metricsGetFooter = getFooterCounter.init({ lang }) metricsGetFooter.start() const variables = { locale: lang } const response = await request(GetFooter, variables, { key: generateTag(lang, "footer"), ttl: "max", }) if (!response.data) { metricsGetFooter.noDataError() throw notFoundError({ message: "GetFooter returned no data", errorDetails: variables, }) } const validatedFooterConfig = validateFooterConfigSchema.safeParse( response.data ) if (!validatedFooterConfig.success) { metricsGetFooter.validationError(validatedFooterConfig.error) return null } metricsGetFooter.success() return validatedFooterConfig.data }), sitewideCampaignBanner: router({ get: contentstackBaseProcedure .input(langInput) .query(async ({ input, ctx }) => { const lang = input.lang ?? ctx.lang const getSitewideCampaignBannerCounter = createCounter( "trpc.contentstack.sitewideCampaignBanner.get" ) const metricsGetSitewideCampaignBanner = getSitewideCampaignBannerCounter.init({ lang, }) metricsGetSitewideCampaignBanner.start() const variables = { locale: lang } const sitewideCampaignBannerResponse = await request( GetSitewideCampaignBanner, variables, { key: generateTag(lang, "sitewide_campaign_banner"), ttl: "max" } ) if (!sitewideCampaignBannerResponse.data) { metricsGetSitewideCampaignBanner.noDataError() throw notFoundError({ message: "GetSitewideCampaignBanner returned no data", errorDetails: variables, }) } const validatedSitewideCampaignBanner = sitewideCampaignBannerSchema.safeParse( sitewideCampaignBannerResponse.data ) if (!validatedSitewideCampaignBanner.success) { metricsGetSitewideCampaignBanner.validationError( validatedSitewideCampaignBanner.error ) return null } metricsGetSitewideCampaignBanner.success() return validatedSitewideCampaignBanner.data }), }), siteConfig: contentstackBaseProcedure .input(langInput) .query(async ({ input, ctx }) => { const lang = input.lang ?? ctx.lang const getSiteConfigCounter = createCounter( "trpc.contentstack.siteConfig.get" ) const metricsGetSiteConfig = getSiteConfigCounter.init({ lang }) metricsGetSiteConfig.start() const variables = { locale: lang } const [siteConfigResponse, contactConfig] = await Promise.all([ request(GetSiteConfig, variables, { key: generateTag(lang, "site_config"), ttl: "max", }), getContactConfig(lang), ]) if (!siteConfigResponse.data) { metricsGetSiteConfig.noDataError() throw notFoundError({ message: "SiteConfig returned no data", errorDetails: variables, }) } const validatedSiteConfig = siteConfigSchema.safeParse( siteConfigResponse.data ) if (!validatedSiteConfig.success) { metricsGetSiteConfig.validationError(validatedSiteConfig.error) return null } metricsGetSiteConfig.success() const { sitewideAlert } = validatedSiteConfig.data return { ...validatedSiteConfig.data, sitewideAlert: sitewideAlert ? { ...sitewideAlert, phoneContact: contactConfig ? getAlertPhoneContactData(sitewideAlert, contactConfig) : null, } : null, } }), })