Merged in feat/rework-contentstack (pull request #3493)

Feat(SW-3708): refactor contentstack fetching (removing all refs) and cache invalidation

* Remove all REFS

* Revalidate correct language

* PR fixes

* PR fixes

* Throw when errors from contentstack api


Approved-by: Joakim Jäderberg
This commit is contained in:
Linus Flood
2026-01-27 12:38:36 +00:00
parent a5e214f783
commit 5fc93472f4
193 changed files with 489 additions and 9018 deletions

View File

@@ -10,19 +10,10 @@ import {
includedHotelsSchema,
} from "../campaignPage/output"
import { promoHeroSchema } from "../promoCampaignPage/output"
import {
allCampaignsRefsSchema,
allCampaignsSchema,
} from "../schemas/blocks/allCampaigns"
import {
carouselCardsRefsSchema,
carouselCardsSchema,
} from "../schemas/blocks/carouselCards"
import { allCampaignsSchema } from "../schemas/blocks/allCampaigns"
import { carouselCardsSchema } from "../schemas/blocks/carouselCards"
import { campaignOverviewPageHotelListingSchema } from "../schemas/blocks/hotelListing"
import {
linkAndTitleSchema,
linkConnectionRefs,
} from "../schemas/linkConnection"
import { linkAndTitleSchema } from "../schemas/linkConnection"
import { systemSchema } from "../schemas/system"
const navigationLinksSchema = z
@@ -196,49 +187,3 @@ export const campaignOverviewPageSchema = z.object({
url: z.string(),
}),
})
/** REFS */
const campaignOverviewPageHeaderRefs = z.object({
navigation_links: z.array(linkConnectionRefs),
})
const campaignOverviewPageCarouselCardsRef = z
.object({
__typename: z.literal(
CampaignOverviewPageEnum.ContentStack.blocks.CarouselCards
),
})
.merge(carouselCardsRefsSchema)
const campaignOverviewPageAllCampaignsRef = z
.object({
__typename: z.literal(
CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns
),
})
.merge(allCampaignsRefsSchema)
const blockRefsSchema = z.discriminatedUnion("__typename", [
campaignOverviewPageAllCampaignsRef,
campaignOverviewPageCarouselCardsRef,
])
export const campaignOverviewPageRefsSchema = z.object({
campaign_overview_page: z.object({
header: campaignOverviewPageHeaderRefs,
top_campaign_block: z.object({
campaignConnection: z.object({
edges: z.array(
z.object({
node: z.object({
system: systemSchema,
}),
})
),
}),
}),
blocks: discriminatedUnionArray(blockRefsSchema.options).nullable(),
system: systemSchema,
}),
})

View File

@@ -2,72 +2,20 @@ import { createCounter } from "@scandic-hotels/common/telemetry"
import { router } from "../../.."
import { notFoundError } from "../../../errors"
import {
GetCampaignOverviewPage,
GetCampaignOverviewPageRefs,
} from "../../../graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql"
import { GetCampaignOverviewPage } from "../../../graphql/Query/CampaignOverviewPage/CampaignOverviewPage.graphql"
import { request } from "../../../graphql/request"
import { contentStackUidWithServiceProcedure } from "../../../procedures"
import { generateRefsResponseTag } from "../../../utils/generateTag"
import {
campaignOverviewPageRefsSchema,
campaignOverviewPageSchema,
} from "./output"
import { generatePageTags } from "./utils"
import { generateTag } from "../../../utils/generateTag"
import { campaignOverviewPageSchema } from "./output"
import type {
GetCampaignOverviewPageData,
GetCampaignOverviewPageRefsData,
} from "../../../types/campaignOverviewPage"
import type { GetCampaignOverviewPageData } from "../../../types/campaignOverviewPage"
import type { TrackingPageData } from "../../types"
export const campaignOverviewPageQueryRouter = router({
get: contentStackUidWithServiceProcedure.query(async ({ ctx }) => {
const { lang, uid } = ctx
const getCampaignOverviewPageRefsCounter = createCounter(
"trpc.contentstack.campaignOverviewPage.get.refs"
)
const metricsGetCampaignOverviewPageRefs =
getCampaignOverviewPageRefsCounter.init({
lang,
uid,
})
metricsGetCampaignOverviewPageRefs.start()
const refVariables = { locale: lang, uid }
const refsResponse = await request<GetCampaignOverviewPageRefsData>(
GetCampaignOverviewPageRefs,
refVariables,
{
key: generateRefsResponseTag(lang, uid),
ttl: "max",
}
)
if (!refsResponse.data) {
metricsGetCampaignOverviewPageRefs.noDataError()
throw notFoundError({
message: "GetCampaignOverviewPageRefs returned no data",
errorDetails: refVariables,
})
}
const validatedRefsData = campaignOverviewPageRefsSchema.safeParse(
refsResponse.data
)
if (!validatedRefsData.success) {
metricsGetCampaignOverviewPageRefs.validationError(
validatedRefsData.error
)
return null
}
metricsGetCampaignOverviewPageRefs.success()
const tags = generatePageTags(validatedRefsData.data, lang)
const cacheKey = generateTag(lang, uid)
const getCampaignOverviewPageCounter = createCounter(
"trpc.contentstack.campaignOverviewPage.get"
@@ -84,7 +32,7 @@ export const campaignOverviewPageQueryRouter = router({
GetCampaignOverviewPage,
variables,
{
key: tags,
key: `${cacheKey}:campaignOverviewPage`,
ttl: "max",
}
)

View File

@@ -1,63 +0,0 @@
import { CampaignOverviewPageEnum } from "../../../types/campaignOverviewPageEnum"
import { generateTag, generateTagsFromSystem } from "../../../utils/generateTag"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { System } from "../../../routers/contentstack/schemas/system"
import type { CampaignOverviewPageRefs } from "../../../types/campaignOverviewPage"
export function generatePageTags(
validatedData: CampaignOverviewPageRefs,
lang: Lang
): string[] {
const connections = getConnections(validatedData)
return [
generateTagsFromSystem(lang, connections),
generateTag(lang, validatedData.campaign_overview_page.system.uid),
].flat()
}
export function getConnections({
campaign_overview_page,
}: CampaignOverviewPageRefs) {
const connections: System["system"][] = [campaign_overview_page.system]
if (campaign_overview_page.header.navigation_links) {
campaign_overview_page.header.navigation_links.forEach((link) => {
if (link.link) {
connections.push(link.link)
}
})
}
if (campaign_overview_page.top_campaign_block.campaignConnection) {
campaign_overview_page.top_campaign_block.campaignConnection.edges.forEach(
({ node }) => {
connections.push(node.system)
}
)
}
if (campaign_overview_page.blocks) {
campaign_overview_page.blocks.forEach((block) => {
switch (block.__typename) {
case CampaignOverviewPageEnum.ContentStack.blocks.CarouselCards: {
block.carousel_cards.card_groups.forEach((group) => {
group.cardConnection.edges.forEach(({ node }) => {
connections.push(node.system)
})
})
break
}
case CampaignOverviewPageEnum.ContentStack.blocks.AllCampaigns: {
block.all_campaigns.campaignsConnection.edges.forEach(({ node }) => {
if (node.system) {
connections.push(node.system)
}
})
break
}
}
})
}
return connections
}