import { metrics } from "@opentelemetry/api" import { Lang } from "@/constants/languages" import { GetContentPageRefs } from "@/lib/graphql/Query/ContentPage.graphql" import { request } from "@/lib/graphql/request" import { notFound } from "@/server/errors/trpc" import { generateTag, generateTags } from "@/utils/generateTag" import { removeMultipleSlashes } from "@/utils/url" import { removeEmptyObjects } from "../../utils" import { validateContentPageRefsSchema } from "./output" import { ContentBlocksTypenameEnum } from "@/types/components/content/enums" import { Edges } from "@/types/requests/utils/edges" import { NodeRefs } from "@/types/requests/utils/refs" import { ContentPageRefsDataRaw } from "@/types/trpc/routers/contentstack/contentPage" const meter = metrics.getMeter("trpc.contentPage") // OpenTelemetry metrics: ContentPage export const getContentPageCounter = meter.createCounter( "trpc.contentstack.contentPage.get" ) const getContentPageRefsCounter = meter.createCounter( "trpc.contentstack.contentPage.get" ) const getContentPageRefsFailCounter = meter.createCounter( "trpc.contentstack.contentPage.get-fail" ) const getContentPageRefsSuccessCounter = meter.createCounter( "trpc.contentstack.contentPage.get-success" ) export async function fetchContentPageRefs(lang: Lang, uid: string) { getContentPageRefsCounter.add(1, { lang, uid }) console.info( "contentstack.contentPage.refs start", JSON.stringify({ query: { lang, uid }, }) ) const refsResponse = await request( GetContentPageRefs, { locale: lang, uid }, { cache: "force-cache", next: { tags: [generateTag(lang, uid)] } } ) if (!refsResponse.data) { const notFoundError = notFound(refsResponse) getContentPageRefsFailCounter.add(1, { lang, uid, error_type: "http_error", error: JSON.stringify({ code: notFoundError.code, }), }) console.error( "contentstack.contentPage.refs not found error", JSON.stringify({ query: { lang, uid, }, error: { code: notFoundError.code }, }) ) throw notFoundError } return removeEmptyObjects(refsResponse.data) } export function validateContentPageRefs(data: any, lang: Lang, uid: string) { const validatedData = validateContentPageRefsSchema.safeParse(data) if (!validatedData.success) { getContentPageRefsFailCounter.add(1, { lang, uid, error_type: "validation_error", error: JSON.stringify(validatedData.error), }) console.error( "contentstack.contentPage.refs validation error", JSON.stringify({ query: { lang, uid }, error: validatedData.error, }) ) return null } getContentPageRefsSuccessCounter.add(1, { lang, uid }) console.info( "contentstack.contentPage.refs success", JSON.stringify({ query: { lang, uid }, }) ) return validatedData.data } export function generatePageTags(validatedData: any, lang: Lang): string[] { const connections = getConnections(validatedData) return [ generateTags(lang, connections), generateTag(lang, validatedData.content_page.system.uid), ].flat() } export function getConnections(refs: ContentPageRefsDataRaw) { const connections: Edges[] = [] if (refs.content_page.blocks) { refs.content_page.blocks.forEach((item) => { switch (item.__typename) { case ContentBlocksTypenameEnum.ContentPageBlocksContent: { if (item.content.content.embedded_itemsConnection.edges.length) { connections.push(item.content.content.embedded_itemsConnection) } break } case ContentBlocksTypenameEnum.ContentPageBlocksShortcuts: { item.shortcuts.shortcuts.forEach((shortcut) => { if (shortcut.linkConnection.edges.length) { connections.push(shortcut.linkConnection) } }) break } } }) } return connections } export function makeButtonObject(button: any) { if (!button) return null const isContenstackLink = button?.is_contentstack_link || button.linkConnection?.edges?.length const linkConnnectionNode = isContenstackLink ? button.linkConnection.edges[0]?.node : null return { openInNewTab: button?.open_in_new_tab, title: button.cta_text || (linkConnnectionNode ? linkConnnectionNode.title : button.external_link.title), href: linkConnnectionNode ? linkConnnectionNode.web?.original_url || removeMultipleSlashes( `/${linkConnnectionNode.system.locale}/${linkConnnectionNode.url}` ) : button.external_link.href, isExternal: !isContenstackLink, } }