Files
web/server/routers/contentstack/languageSwitcher/query.ts
Linus Flood 7c0f9084b6 Merged in feat/refactor-header-footer-sitewidealert (pull request #1374)
Refactor: removed parallel routes for header, footer and sidewidealert. Langswitcher and sidewidealert now client components

* feat - removed parallel routes and made sidepeek and sitewidealerts as client components

* Langswitcher as client component

* Fixed lang switcher for current header

* Passing lang when fetching siteconfig

* Merge branch 'master' into feat/refactor-header-footer-sitewidealert

* Refactor

* Removed dead code

* Show only languages that has translation

* Refetch sitewidealert every 60 seconds

* Merge branch 'master' into feat/refactor-header-footer-sitewidealert

* Removed sidepeek parallel route from my-stay

* Added missing env.var to env.test

* Removed console.log


Approved-by: Joakim Jäderberg
2025-02-19 08:59:24 +00:00

268 lines
8.1 KiB
TypeScript

import { metrics } from "@opentelemetry/api"
import { Lang } from "@/constants/languages"
import { baseUrls } from "@/constants/routes/baseUrls"
import { batchRequest } from "@/lib/graphql/batchRequest"
import {
GetDaDeEnUrlsAccountPage,
GetFiNoSvUrlsAccountPage,
} from "@/lib/graphql/Query/AccountPage/AccountPage.graphql"
import {
GetDaDeEnUrlsCollectionPage,
GetFiNoSvUrlsCollectionPage,
} from "@/lib/graphql/Query/CollectionPage/CollectionPage.graphql"
import {
GetDaDeEnUrlsContentPage,
GetFiNoSvUrlsContentPage,
} from "@/lib/graphql/Query/ContentPage/ContentPage.graphql"
import {
GetDaDeEnUrlsCurrentBlocksPage,
GetFiNoSvUrlsCurrentBlocksPage,
} from "@/lib/graphql/Query/Current/LanguageSwitcher.graphql"
import {
GetDaDeEnUrlsDestinationCityPage,
GetFiNoSvUrlsDestinationCityPage,
} from "@/lib/graphql/Query/DestinationCityPage/DestinationCityPage.graphql"
import {
GetDaDeEnUrlsDestinationCountryPage,
GetFiNoSvUrlsDestinationCountryPage,
} from "@/lib/graphql/Query/DestinationCountryPage/DestinationCountryPage.graphql"
import {
GetDaDeEnUrlsDestinationOverviewPage,
GetFiNoSvUrlsDestinationOverviewPage,
} from "@/lib/graphql/Query/DestinationOverviewPage/DestinationOverviewPage.graphql"
import {
GetDaDeEnUrlsHotelPage,
GetFiNoSvUrlsHotelPage,
} from "@/lib/graphql/Query/HotelPage/HotelPage.graphql"
import {
GetDaDeEnUrlsLoyaltyPage,
GetFiNoSvUrlsLoyaltyPage,
} from "@/lib/graphql/Query/LoyaltyPage/LoyaltyPage.graphql"
import {
GetDaDeEnUrlsStartPage,
GetFiNoSvUrlsStartPage,
} from "@/lib/graphql/Query/StartPage/StartPage.graphql"
import { internalServerError } from "@/server/errors/trpc"
import { publicProcedure, router } from "@/server/trpc"
import { getUidAndContentTypeByPath } from "@/services/cms/getUidAndContentTypeByPath"
import { generateTag } from "@/utils/generateTag"
import { getLanguageSwitcherInput } from "./input"
import { validateLanguageSwitcherData } from "./output"
import { languageSwitcherAffix } from "./utils"
import { PageContentTypeEnum } from "@/types/requests/contentType"
import type {
LanguageSwitcherData,
LanguageSwitcherQueryDataRaw,
} from "@/types/requests/languageSwitcher"
interface LanguageSwitcherVariables {
contentType: string
uid: string
}
const meter = metrics.getMeter("trpc.contentstack.languageSwitcher")
const getLanguageSwitcherCounter = meter.createCounter(
"trpc.contentstack.languageSwitcher.get"
)
const getLanguageSwitcherSuccessCounter = meter.createCounter(
"trpc.contentstack.languageSwitcher.get-success"
)
const getLanguageSwitcherFailCounter = meter.createCounter(
"trpc.contentstack.languageSwitcher.get-fail"
)
async function getLanguageSwitcher(options: LanguageSwitcherVariables) {
const variables = { uid: options.uid }
const tagsDaDeEn = [
generateTag(Lang.da, options.uid, languageSwitcherAffix),
generateTag(Lang.de, options.uid, languageSwitcherAffix),
generateTag(Lang.en, options.uid, languageSwitcherAffix),
]
const tagsFiNoSv = [
generateTag(Lang.fi, options.uid, languageSwitcherAffix),
generateTag(Lang.no, options.uid, languageSwitcherAffix),
generateTag(Lang.sv, options.uid, languageSwitcherAffix),
]
let daDeEnDocument = null
let fiNoSvDocument = null
switch (options.contentType) {
case PageContentTypeEnum.accountPage:
daDeEnDocument = GetDaDeEnUrlsAccountPage
fiNoSvDocument = GetFiNoSvUrlsAccountPage
break
case PageContentTypeEnum.currentBlocksPage:
daDeEnDocument = GetDaDeEnUrlsCurrentBlocksPage
fiNoSvDocument = GetFiNoSvUrlsCurrentBlocksPage
break
case PageContentTypeEnum.loyaltyPage:
daDeEnDocument = GetDaDeEnUrlsLoyaltyPage
fiNoSvDocument = GetFiNoSvUrlsLoyaltyPage
break
case PageContentTypeEnum.hotelPage:
daDeEnDocument = GetDaDeEnUrlsHotelPage
fiNoSvDocument = GetFiNoSvUrlsHotelPage
break
case PageContentTypeEnum.contentPage:
daDeEnDocument = GetDaDeEnUrlsContentPage
fiNoSvDocument = GetFiNoSvUrlsContentPage
break
case PageContentTypeEnum.collectionPage:
daDeEnDocument = GetDaDeEnUrlsCollectionPage
fiNoSvDocument = GetFiNoSvUrlsCollectionPage
break
case PageContentTypeEnum.destinationOverviewPage:
daDeEnDocument = GetDaDeEnUrlsDestinationOverviewPage
fiNoSvDocument = GetFiNoSvUrlsDestinationOverviewPage
break
case PageContentTypeEnum.destinationCountryPage:
daDeEnDocument = GetDaDeEnUrlsDestinationCountryPage
fiNoSvDocument = GetFiNoSvUrlsDestinationCountryPage
break
case PageContentTypeEnum.destinationCityPage:
daDeEnDocument = GetDaDeEnUrlsDestinationCityPage
fiNoSvDocument = GetFiNoSvUrlsDestinationCityPage
break
case PageContentTypeEnum.startPage:
daDeEnDocument = GetDaDeEnUrlsStartPage
fiNoSvDocument = GetFiNoSvUrlsStartPage
break
default:
console.error(`type: [${options.contentType}]`)
console.error(`Trying to get a content type that is not supported`)
throw internalServerError()
}
if (daDeEnDocument && fiNoSvDocument) {
return await batchRequest<LanguageSwitcherQueryDataRaw>([
{
document: daDeEnDocument,
variables,
options: {
cache: "force-cache",
next: {
tags: tagsDaDeEn,
},
},
},
{
document: fiNoSvDocument,
variables,
options: {
cache: "force-cache",
next: {
tags: tagsFiNoSv,
},
},
},
])
}
throw internalServerError()
}
export const languageSwitcherQueryRouter = router({
get: publicProcedure
.input(getLanguageSwitcherInput)
.query(async ({ input, ctx }) => {
let uid = ctx.uid
let contentType = ctx.contentType
let lang = ctx.lang ?? input?.lang
if (input) {
const data = await getUidAndContentTypeByPath(input.pathName)
uid = data.uid
contentType = data.contentType ?? ctx.contentType
}
if (!uid || !lang) {
return { lang: lang, urls: baseUrls }
}
getLanguageSwitcherCounter.add(1, {
uid: uid,
lang: lang,
contentType: contentType,
})
console.info(
"contentstack.languageSwitcher start",
JSON.stringify({
query: {
uid: uid,
lang: lang,
contentType: contentType,
},
})
)
const res = await getLanguageSwitcher({
contentType: contentType!,
uid: uid,
})
const urls = Object.keys(res.data).reduce<LanguageSwitcherData>(
(acc, key) => {
const item = res.data[key as Lang]
if (!item?.url) return acc // Skip languages without a URL
const url = item
? item.web?.original_url || `/${key}${item.url}`
: undefined
return {
...acc,
[key]: { url, isExternal: !!item?.web?.original_url },
}
},
{} as LanguageSwitcherData
)
const validatedLanguageSwitcherData =
validateLanguageSwitcherData.safeParse(urls)
if (!validatedLanguageSwitcherData.success) {
getLanguageSwitcherFailCounter.add(1, {
uid: uid,
lang: lang,
contentType: contentType,
error_type: "validation_error",
error: JSON.stringify(validatedLanguageSwitcherData.error),
})
console.error(
"contentstack.languageSwitcher validation error",
JSON.stringify({
query: {
uid: uid,
lang: lang,
contentType: contentType,
},
error: validatedLanguageSwitcherData.error,
})
)
return null
}
getLanguageSwitcherSuccessCounter.add(1, {
uid: uid,
lang: lang,
contentType: contentType,
})
console.info(
"contentstack.languageSwitcher success",
JSON.stringify({
query: {
uid: uid,
lang: lang,
contentType: contentType,
},
})
)
return {
lang: lang,
urls,
}
}),
})