Files
Linus Flood 5fc93472f4 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
2026-01-27 12:38:36 +00:00

200 lines
6.3 KiB
TypeScript

import { type DocumentNode } from "graphql"
import { cache } from "react"
import { createCounter } from "@scandic-hotels/common/telemetry"
import { router } from "../../.."
import { PageContentTypeEnum } from "../../../enums/contentType"
import { notFoundError } from "../../../errors"
import { GetMyPagesBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/AccountPage.graphql"
import { GetCampaignOverviewPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/CampaignOverviewPage.graphql"
import { GetCampaignPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/CampaignPage.graphql"
import { GetCollectionPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/CollectionPage.graphql"
import { GetContentPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/ContentPage.graphql"
import { GetDestinationCityPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/DestinationCityPage.graphql"
import { GetDestinationCountryPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/DestinationCountryPage.graphql"
import { GetDestinationOverviewPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/DestinationOverviewPage.graphql"
import { GetHotelPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/HotelPage.graphql"
import { GetLoyaltyPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/LoyaltyPage.graphql"
import { GetPromoCampaignPageBreadcrumbs } from "../../../graphql/Query/Breadcrumbs/PromoCampaignPage.graphql"
import { request } from "../../../graphql/request"
import { contentstackExtendedProcedureUID } from "../../../procedures"
import { generateTag } from "../../../utils/generateTag"
import { breadcrumbsSchema } from "./output"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { RawBreadcrumbsSchema } from "../../../types/breadcrumbs"
interface BreadcrumbsPageData<T> {
dataKey: keyof T
query: string | DocumentNode
}
const getBreadcrumbs = cache(async function fetchMemoizedBreadcrumbs<T>(
{ dataKey, query }: BreadcrumbsPageData<T>,
{ uid, lang }: { uid: string; lang: Lang }
) {
const getBreadcrumbsCounter = createCounter(
"trpc.contentstack.breadcrumbs.get"
)
const metricsGetBreadcrumbs = getBreadcrumbsCounter.init({
lang,
uid,
})
metricsGetBreadcrumbs.start()
const variables = { locale: lang, uid }
const response = await request<T>(query, variables, {
key: generateTag(lang, uid),
ttl: "max",
})
if (!response.data) {
metricsGetBreadcrumbs.noDataError()
throw notFoundError({
message: "Breadcrumbs query returned no data",
errorDetails: variables,
})
}
const validatedBreadcrumbs = breadcrumbsSchema.safeParse(
response.data[dataKey]
)
if (!validatedBreadcrumbs.success) {
metricsGetBreadcrumbs.validationError(validatedBreadcrumbs.error)
return []
}
metricsGetBreadcrumbs.success()
return validatedBreadcrumbs.data
})
export const breadcrumbsQueryRouter = router({
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
const variables = {
lang: ctx.lang,
uid: ctx.uid,
}
switch (ctx.contentType) {
case PageContentTypeEnum.accountPage:
return await getBreadcrumbs<{
account_page: RawBreadcrumbsSchema
}>(
{
dataKey: "account_page",
query: GetMyPagesBreadcrumbs,
},
variables
)
case PageContentTypeEnum.campaignOverviewPage:
return await getBreadcrumbs<{
campaign_overview_page: RawBreadcrumbsSchema
}>(
{
dataKey: "campaign_overview_page",
query: GetCampaignOverviewPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.campaignPage:
return await getBreadcrumbs<{
campaign_page: RawBreadcrumbsSchema
}>(
{
dataKey: "campaign_page",
query: GetCampaignPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.collectionPage:
return await getBreadcrumbs<{
collection_page: RawBreadcrumbsSchema
}>(
{
dataKey: "collection_page",
query: GetCollectionPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.contentPage:
return await getBreadcrumbs<{
content_page: RawBreadcrumbsSchema
}>(
{
dataKey: "content_page",
query: GetContentPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.destinationOverviewPage:
return await getBreadcrumbs<{
destination_overview_page: RawBreadcrumbsSchema
}>(
{
dataKey: "destination_overview_page",
query: GetDestinationOverviewPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.destinationCountryPage:
return await getBreadcrumbs<{
destination_country_page: RawBreadcrumbsSchema
}>(
{
dataKey: "destination_country_page",
query: GetDestinationCountryPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.destinationCityPage:
return await getBreadcrumbs<{
destination_city_page: RawBreadcrumbsSchema
}>(
{
dataKey: "destination_city_page",
query: GetDestinationCityPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.hotelPage:
return await getBreadcrumbs<{
hotel_page: RawBreadcrumbsSchema
}>(
{
dataKey: "hotel_page",
query: GetHotelPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.loyaltyPage:
return await getBreadcrumbs<{
loyalty_page: RawBreadcrumbsSchema
}>(
{
dataKey: "loyalty_page",
query: GetLoyaltyPageBreadcrumbs,
},
variables
)
case PageContentTypeEnum.promoCampaignPage:
return await getBreadcrumbs<{
promo_campaign_page: RawBreadcrumbsSchema
}>(
{
dataKey: "promo_campaign_page",
query: GetPromoCampaignPageBreadcrumbs,
},
variables
)
default:
return []
}
}),
})