import { cache } from "react" import { GetContactConfig } from "@/lib/graphql/Query/ContactConfig.graphql" import { GetCurrentFooter, GetCurrentFooterRef, } from "@/lib/graphql/Query/Current/Footer.graphql" import { GetCurrentHeader, GetCurrentHeaderRef, } from "@/lib/graphql/Query/Current/Header.graphql" import { GetFooter, GetFooterRef } from "@/lib/graphql/Query/Footer.graphql" import { GetHeader, GetHeaderRef } from "@/lib/graphql/Query/Header.graphql" import { GetSiteConfig, GetSiteConfigRef, } from "@/lib/graphql/Query/SiteConfig.graphql" import { request } from "@/lib/graphql/request" import { notFound } from "@/server/errors/trpc" import { contentstackBaseProcedure, router } from "@/server/trpc" import { langInput } from "@/server/utils" import { getCacheClient } from "@/services/dataCache" import { generateRefsResponseTag, generateTag, generateTags, generateTagsFromSystem, } from "@/utils/generateTag" import { type ContactConfigData, type CurrentFooterDataRaw, type CurrentFooterRefDataRaw, type CurrentHeaderRefDataRaw, type GetCurrentHeaderData, headerRefsSchema, headerSchema, siteConfigRefSchema, siteConfigSchema, validateContactConfigSchema, validateCurrentFooterConfigSchema, validateCurrentHeaderConfigSchema, validateFooterConfigSchema, validateFooterRefConfigSchema, } from "./output" import { getContactConfigCounter, getContactConfigFailCounter, getContactConfigSuccessCounter, getCurrentFooterCounter, getCurrentFooterFailCounter, getCurrentFooterRefCounter, getCurrentFooterSuccessCounter, getCurrentHeaderCounter, getCurrentHeaderFailCounter, getCurrentHeaderRefCounter, getCurrentHeaderSuccessCounter, getFooterCounter, getFooterFailCounter, getFooterRefCounter, getFooterRefFailCounter, getFooterRefSuccessCounter, getFooterSuccessCounter, getHeaderCounter, getHeaderFailCounter, getHeaderRefsCounter, getHeaderRefsFailCounter, getHeaderRefsSuccessCounter, getHeaderSuccessCounter, getSiteConfigCounter, getSiteConfigFailCounter, getSiteConfigRefCounter, getSiteConfigRefFailCounter, getSiteConfigRefSuccessCounter, getSiteConfigSuccessCounter, } from "./telemetry" import { getAlertPhoneContactData, getConnections, getFooterConnections, getSiteConfigConnections, } from "./utils" import type { FooterDataRaw, FooterRefDataRaw, } from "@/types/components/footer/footer" import type { GetHeader as GetHeaderData, GetHeaderRefs, } from "@/types/trpc/routers/contentstack/header" import type { GetSiteConfigData, GetSiteConfigRefData, } from "@/types/trpc/routers/contentstack/siteConfig" import type { Lang } from "@/constants/languages" const getContactConfig = cache(async (lang: Lang) => { getContactConfigCounter.add(1, { lang }) console.info( "contentstack.contactConfig start", JSON.stringify({ query: { lang } }) ) const response = await request( GetContactConfig, { locale: lang, }, { key: `${lang}:contact`, ttl: "max", } ) if (!response.data) { const notFoundError = notFound(response) getContactConfigFailCounter.add(1, { lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.config not found error", JSON.stringify({ query: { lang }, error: { code: notFoundError.code } }) ) throw notFoundError } const validatedContactConfigConfig = validateContactConfigSchema.safeParse( response.data ) if (!validatedContactConfigConfig.success) { getContactConfigFailCounter.add(1, { lang, error_type: "validation_error", error: JSON.stringify(validatedContactConfigConfig.error), }) console.error( "contentstack.contactConfig validation error", JSON.stringify({ query: { lang }, error: validatedContactConfigConfig.error, }) ) return null } getContactConfigSuccessCounter.add(1, { lang }) console.info( "contentstack.contactConfig success", JSON.stringify({ query: { lang } }) ) return validatedContactConfigConfig.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 getHeaderRefsCounter.add(1, { lang }) console.info( "contentstack.header.refs start", JSON.stringify({ query: { lang } }) ) const responseRef = await request( GetHeaderRef, { locale: lang, }, { key: generateRefsResponseTag(lang, "header"), ttl: "max", } ) if (!responseRef.data) { const notFoundError = notFound(responseRef) getHeaderRefsFailCounter.add(1, { lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.header.refs not found error", JSON.stringify({ query: { lang, }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedHeaderRefs = headerRefsSchema.safeParse(responseRef.data) if (!validatedHeaderRefs.success) { getHeaderRefsFailCounter.add(1, { lang, error_type: "validation_error", error: JSON.stringify(validatedHeaderRefs.error), }) console.error( "contentstack.header.refs validation error", JSON.stringify({ query: { lang, }, error: validatedHeaderRefs.error, }) ) return null } getHeaderRefsSuccessCounter.add(1, { lang }) console.info( "contentstack.header.refs success", JSON.stringify({ query: { lang } }) ) const connections = getConnections(validatedHeaderRefs.data) getHeaderCounter.add(1, { lang }) console.info( "contentstack.header start", JSON.stringify({ query: { lang } }) ) const tags = [ generateTagsFromSystem(lang, connections), generateTag(lang, validatedHeaderRefs.data.header.system.uid), ].flat() const response = await request( GetHeader, { locale: lang }, { key: tags, ttl: "max" } ) if (!response.data) { const notFoundError = notFound(response) getHeaderFailCounter.add(1, { lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.header not found error", JSON.stringify({ query: { lang }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedHeaderConfig = headerSchema.safeParse(response.data) if (!validatedHeaderConfig.success) { getHeaderFailCounter.add(1, { lang, error_type: "validation_error", error: JSON.stringify(validatedHeaderConfig.error), }) console.error( "contentstack.header validation error", JSON.stringify({ query: { lang }, error: validatedHeaderConfig.error, }) ) return null } getHeaderSuccessCounter.add(1, { lang }) console.info( "contentstack.header success", JSON.stringify({ query: { lang } }) ) return { data: validatedHeaderConfig.data.header, } }), currentHeader: contentstackBaseProcedure .input(langInput) .query(async ({ input }) => { getCurrentHeaderRefCounter.add(1, { lang: input.lang }) console.info( "contentstack.currentHeader.ref start", JSON.stringify({ query: { lang: input.lang } }) ) const responseRef = await request( GetCurrentHeaderRef, { locale: input.lang, }, { key: generateRefsResponseTag(input.lang, "current_header"), ttl: "max", } ) getCurrentHeaderCounter.add(1, { lang: input.lang }) console.info( "contentstack.currentHeader start", JSON.stringify({ query: { lang: input.lang }, }) ) const currentHeaderUID = responseRef.data.all_current_header.items[0].system.uid // There's currently no error handling/validation for the responseRef, should it be added? const response = await request( GetCurrentHeader, { locale: input.lang }, { key: generateTag(input.lang, currentHeaderUID), ttl: "max", } ) if (!response.data) { const notFoundError = notFound(response) getCurrentHeaderFailCounter.add(1, { lang: input.lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.currentHeader not found error", JSON.stringify({ query: { lang: input.lang, }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedHeaderConfig = validateCurrentHeaderConfigSchema.safeParse( response.data ) if (!validatedHeaderConfig.success) { getCurrentHeaderFailCounter.add(1, { lang: input.lang, error_type: "validation_error", error: JSON.stringify(validatedHeaderConfig.error), }) console.error( "contentstack.currentHeader validation error", JSON.stringify({ query: { lang: input.lang, }, error: validatedHeaderConfig.error, }) ) return null } getCurrentHeaderSuccessCounter.add(1, { lang: input.lang }) console.info( "contentstack.currentHeader success", JSON.stringify({ query: { lang: input.lang }, }) ) return validatedHeaderConfig.data }), currentFooter: contentstackBaseProcedure .input(langInput) .query(async ({ input }) => { getCurrentFooterRefCounter.add(1, { lang: input.lang }) console.info( "contentstack.currentFooter.ref start", JSON.stringify({ query: { lang: input.lang } }) ) const responseRef = await request( GetCurrentFooterRef, { locale: input.lang, }, { key: generateRefsResponseTag(input.lang, "current_footer"), ttl: "max", } ) // There's currently no error handling/validation for the responseRef, should it be added? getCurrentFooterCounter.add(1, { lang: input.lang }) console.info( "contentstack.currentFooter start", JSON.stringify({ query: { lang: input.lang, }, }) ) const currentFooterUID = responseRef.data.all_current_footer.items[0].system.uid const response = await request( GetCurrentFooter, { locale: input.lang, }, { key: generateTag(input.lang, currentFooterUID), ttl: "max", } ) if (!response.data) { const notFoundError = notFound(response) getCurrentFooterFailCounter.add(1, { lang: input.lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.currentFooter not found error", JSON.stringify({ query: { lang: input.lang, }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedCurrentFooterConfig = validateCurrentFooterConfigSchema.safeParse(response.data) if (!validatedCurrentFooterConfig.success) { getFooterFailCounter.add(1, { lang: input.lang, error_type: "validation_error", error: JSON.stringify(validatedCurrentFooterConfig.error), }) console.error( "contentstack.currentFooter validation error", JSON.stringify({ query: { lang: input.lang }, error: validatedCurrentFooterConfig.error, }) ) return null } getCurrentFooterSuccessCounter.add(1, { lang: input.lang }) console.info( "contentstack.currentFooter success", JSON.stringify({ query: { lang: input.lang } }) ) return validatedCurrentFooterConfig.data.all_current_footer.items[0] }), footer: contentstackBaseProcedure.query(async ({ ctx }) => { const { lang } = ctx getFooterRefCounter.add(1, { lang }) console.info( "contentstack.footer.ref start", JSON.stringify({ query: { lang } }) ) const responseRef = await request( GetFooterRef, { locale: lang, }, { key: generateRefsResponseTag(lang, "footer"), ttl: "max", } ) if (!responseRef.data) { const notFoundError = notFound(responseRef) getFooterRefFailCounter.add(1, { lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.footer.refs not found error", JSON.stringify({ query: { lang, }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedFooterRefs = validateFooterRefConfigSchema.safeParse( responseRef.data ) if (!validatedFooterRefs.success) { getFooterRefFailCounter.add(1, { lang, error_type: "validation_error", error: JSON.stringify(validatedFooterRefs.error), }) console.error( "contentstack.footer.refs validation error", JSON.stringify({ query: { lang, }, error: validatedFooterRefs.error, }) ) return null } getFooterRefSuccessCounter.add(1, { lang }) console.info( "contentstack.footer.refs success", JSON.stringify({ query: { lang } }) ) const connections = getFooterConnections(validatedFooterRefs.data) const footerUID = responseRef.data.all_footer.items[0].system.uid getFooterCounter.add(1, { lang: lang }) console.info( "contentstack.footer start", JSON.stringify({ query: { lang, }, }) ) const tags = [ generateTags(lang, connections), generateTag(lang, footerUID), ].flat() const response = await request( GetFooter, { locale: lang, }, { key: tags, ttl: "max", } ) if (!response.data) { const notFoundError = notFound(response) getFooterFailCounter.add(1, { lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.footer not found error", JSON.stringify({ query: { lang, }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedFooterConfig = validateFooterConfigSchema.safeParse( response.data ) if (!validatedFooterConfig.success) { getFooterFailCounter.add(1, { lang, error_type: "validation_error", error: JSON.stringify(validatedFooterConfig.error), }) console.error( "contentstack.footer validation error", JSON.stringify({ query: { lang: lang }, error: validatedFooterConfig.error, }) ) return null } getFooterSuccessCounter.add(1, { lang }) console.info( "contentstack.footer success", JSON.stringify({ query: { lang } }) ) return validatedFooterConfig.data }), siteConfig: contentstackBaseProcedure .input(langInput) .query(async ({ input, ctx }) => { const lang = input.lang ?? ctx.lang const cacheClient = await getCacheClient() return await cacheClient.cacheOrGet( generateRefsResponseTag(lang, "site_config", "root"), async () => { getSiteConfigRefCounter.add(1, { lang }) console.info( "contentstack.siteConfig.ref start", JSON.stringify({ query: { lang } }) ) const responseRef = await request( GetSiteConfigRef, { locale: lang, }, { key: generateRefsResponseTag(lang, "site_config"), ttl: "max", } ) if (!responseRef.data) { const notFoundError = notFound(responseRef) getSiteConfigRefFailCounter.add(1, { lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.siteConfig.refs not found error", JSON.stringify({ query: { lang, }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedSiteConfigRef = siteConfigRefSchema.safeParse( responseRef.data ) if (!validatedSiteConfigRef.success) { getSiteConfigRefFailCounter.add(1, { lang, error_type: "validation_error", error: JSON.stringify(validatedSiteConfigRef.error), }) console.error( "contentstack.siteConfig.refs validation error", JSON.stringify({ query: { lang, }, error: validatedSiteConfigRef.error, }) ) return null } const connections = getSiteConfigConnections( validatedSiteConfigRef.data ) const siteConfigUid = responseRef.data.all_site_config.items[0].system.uid const tags = [ generateTagsFromSystem(lang, connections), generateTag(lang, siteConfigUid), ].flat() getSiteConfigRefSuccessCounter.add(1, { lang }) console.info( "contentstack.siteConfig.refs success", JSON.stringify({ query: { lang } }) ) getSiteConfigCounter.add(1, { lang }) console.info( "contentstack.siteConfig start", JSON.stringify({ query: { lang } }) ) const [siteConfigResponse, contactConfig] = await Promise.all([ request( GetSiteConfig, { locale: lang, }, { key: tags, ttl: "max", } ), getContactConfig(lang), ]) if (!siteConfigResponse.data) { const notFoundError = notFound(siteConfigResponse) getSiteConfigFailCounter.add(1, { lang, error_type: "not_found", error: JSON.stringify({ code: notFoundError.code }), }) console.error( "contentstack.siteConfig not found error", JSON.stringify({ query: { lang }, error: { code: notFoundError.code }, }) ) throw notFoundError } const validatedSiteConfig = siteConfigSchema.safeParse( siteConfigResponse.data ) if (!validatedSiteConfig.success) { getSiteConfigFailCounter.add(1, { lang, error_type: "validation_error", error: JSON.stringify(validatedSiteConfig.error), }) console.error( "contentstack.siteConfig validation error", JSON.stringify({ query: { lang }, error: validatedSiteConfig.error, }) ) return null } getSiteConfigSuccessCounter.add(1, { lang }) console.info( "contentstack.siteConfig success", JSON.stringify({ query: { lang } }) ) const { sitewideAlert } = validatedSiteConfig.data return { ...validatedSiteConfig.data, sitewideAlert: sitewideAlert ? { ...sitewideAlert, phoneContact: contactConfig ? getAlertPhoneContactData(sitewideAlert, contactConfig) : null, } : null, } }, "max" ) }), })