Files
web/server/routers/contentstack/contentPage/query.ts
2024-09-05 16:33:14 +02:00

210 lines
6.8 KiB
TypeScript

import { Lang } from "@/constants/languages"
import { GetContentPage } from "@/lib/graphql/Query/ContentPage.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import { makeImageVaultImage } from "@/utils/imageVault"
import { removeMultipleSlashes } from "@/utils/url"
import { removeEmptyObjects } from "../../utils"
import { validateContentPageSchema } from "./output"
import {
fetchContentPageRefs,
generatePageTags,
getContentPageCounter,
makeButtonObject,
validateContentPageRefs,
} from "./utils"
import {
CardsGridEnum,
ContentBlocksTypenameEnum,
SidebarTypenameEnum,
} from "@/types/components/content/enums"
import {
TrackingChannelEnum,
TrackingSDKPageData,
} from "@/types/components/tracking"
import {
Block,
ContentPage,
ContentPageDataRaw,
Sidebar,
} from "@/types/trpc/routers/contentstack/contentPage"
export const contentPageQueryRouter = router({
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
const { lang, uid } = ctx
const cleanedRefsData = await fetchContentPageRefs(lang, uid)
const validatedRefsData = validateContentPageRefs(
cleanedRefsData,
lang,
uid
)
const tags = generatePageTags(validatedRefsData, lang)
getContentPageCounter.add(1, { lang, uid })
console.info(
"contentstack.contentPage start",
JSON.stringify({
query: { lang, uid },
})
)
const response = await request<ContentPageDataRaw>(
GetContentPage,
{ locale: lang, uid },
{
cache: "force-cache",
next: {
tags,
},
}
)
const { content_page } = removeEmptyObjects(response.data)
if (!content_page) {
throw notFound(response)
}
const processedBlocks = content_page.blocks
? content_page.blocks.map((block: any) => {
switch (block.__typename) {
case ContentBlocksTypenameEnum.ContentPageBlocksContent:
return block
case ContentBlocksTypenameEnum.ContentPageBlocksShortcuts:
return {
...block,
shortcuts: {
...block.shortcuts,
shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({
text: shortcut.text,
openInNewTab: shortcut.open_in_new_tab,
...shortcut.linkConnection.edges[0].node,
url:
shortcut.linkConnection.edges[0].node.web?.original_url ||
removeMultipleSlashes(
`/${shortcut.linkConnection.edges[0].node.system.locale}/${shortcut.linkConnection.edges[0].node.url}`
),
})),
},
}
case ContentBlocksTypenameEnum.ContentPageBlocksCardsGrid:
return {
...block,
cards_grid: {
...block.cards_grid,
cards: block.cards_grid.cardConnection.edges.map(
({ node: card }: { node: any }) => {
switch (card.__typename) {
case CardsGridEnum.Card:
return {
...card,
backgroundImage: makeImageVaultImage(
card.background_image
),
primaryButton: card.has_primary_button
? makeButtonObject(card.primary_button)
: undefined,
secondaryButton: card.has_secondary_button
? makeButtonObject(card.secondary_button)
: undefined,
}
case CardsGridEnum.LoyaltyCard:
return {
...card,
image: makeImageVaultImage(card.image),
link: makeButtonObject(card.link),
}
}
}
),
},
}
case ContentBlocksTypenameEnum.ContentPageBlocksDynamicContent:
return {
...block,
dynamic_content: {
...block.dynamic_content,
link: block.dynamic_content.link.pageConnection.edges.length
? {
text: block.dynamic_content.link.text,
href: removeMultipleSlashes(
`/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}/${block.dynamic_content.link.pageConnection.edges[0].node.url}`
),
title:
block.dynamic_content.link.pageConnection.edges[0]
.node.title,
}
: undefined,
},
}
default:
return block
}
})
: null
const sidebar = response.data.content_page.sidebar
? response.data.content_page.sidebar.map((item: any) => {
switch (item.__typename) {
case SidebarTypenameEnum.ContentPageSidebarJoinLoyaltyContact:
return {
...item,
join_loyalty_contact: {
...item.join_loyalty_contact,
button: makeButtonObject(item.join_loyalty_contact.button),
},
}
default:
return item
}
})
: null
const heroImage = makeImageVaultImage(content_page.hero_image)
const validatedContentPage = validateContentPageSchema.safeParse({
content_page: {
...content_page,
blocks: processedBlocks,
sidebar,
hero_image: heroImage,
},
})
if (!validatedContentPage.success) {
console.error(
`Failed to validate Contentpage Data - (lang: ${lang}, uid: ${uid})`
)
console.error(validatedContentPage.error?.format())
return null
}
const { hero_image, blocks, ...restContentPage } =
validatedContentPage.data.content_page
const contentPage: ContentPage = {
...restContentPage,
heroImage,
blocks: blocks as Block[],
sidebar: sidebar as Sidebar[],
}
const tracking: TrackingSDKPageData = {
pageId: contentPage.system.uid,
lang: contentPage.system.locale as Lang,
publishedDate: contentPage.system.updated_at,
createdDate: contentPage.system.created_at,
channel: TrackingChannelEnum["static-content-page"],
pageType: "staticcontentpage",
}
return {
contentPage,
tracking,
}
}),
})