Files
web/packages/trpc/lib/routers/contentstack/base/query.ts
Anton Gunnarsson 4e1cb01b84 Merged in chore/cleanup-after-trpc-migration (pull request #2457)
Chore/cleanup after trpc migration

* Clean up TODOs

* Rename REDEMPTION constant to SEARCH_TYPE_REDEMPTION

* Update dependencies

Remove unused deps from scandic-web
Add missing deps to trpc package

* Update self-referencing imports

* Remove unused variables from scandic-web env

* Fix missing graphql-tag package

* Actually fix

* Remove unused env var


Approved-by: Christian Andolf
Approved-by: Linus Flood
2025-06-30 12:08:19 +00:00

501 lines
13 KiB
TypeScript

import { cache } from "react"
import { createCounter } from "@scandic-hotels/common/telemetry"
import { router } from "../../.."
import { notFound } from "../../../errors"
import { GetContactConfig } from "../../../graphql/Query/ContactConfig.graphql"
import {
GetCurrentFooter,
GetCurrentFooterRef,
} from "../../../graphql/Query/Current/Footer.graphql"
import {
GetCurrentHeader,
GetCurrentHeaderRef,
} from "../../../graphql/Query/Current/Header.graphql"
import { GetFooter, GetFooterRef } from "../../../graphql/Query/Footer.graphql"
import { GetHeader, GetHeaderRef } from "../../../graphql/Query/Header.graphql"
import {
GetSiteConfig,
GetSiteConfigRef,
} from "../../../graphql/Query/SiteConfig.graphql"
// import { router } from "../../.."
import { request } from "../../../graphql/request"
import { contentstackBaseProcedure } from "../../../procedures"
import { langInput } from "../../../utils"
import {
generateRefsResponseTag,
generateTag,
generateTags,
generateTagsFromSystem,
} from "../../../utils/generateTag"
import {
type ContactConfigData,
type CurrentFooterDataRaw,
type CurrentFooterRefDataRaw,
type CurrentHeaderRefDataRaw,
type GetCurrentHeaderData,
headerRefsSchema,
headerSchema,
siteConfigRefSchema,
siteConfigSchema,
validateContactConfigSchema,
validateCurrentFooterConfigSchema,
validateCurrentHeaderConfigSchema,
validateFooterConfigSchema,
validateFooterRefConfigSchema,
} from "./output"
import {
getAlertPhoneContactData,
getConnections,
getFooterConnections,
getSiteConfigConnections,
} from "./utils"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { FooterDataRaw, FooterRefDataRaw } from "../../../types/footer"
import type {
GetHeader as GetHeaderData,
GetHeaderRefs,
} from "../../../types/header"
import type {
GetSiteConfigData,
GetSiteConfigRefData,
} from "../../../types/siteConfig"
const getContactConfig = cache(async (lang: Lang) => {
const getContactConfigCounter = createCounter(
"trpc.contentstack",
"contactConfig.get"
)
const metricsGetContactConfig = getContactConfigCounter.init({ lang })
metricsGetContactConfig.start()
const response = await request<ContactConfigData>(
GetContactConfig,
{
locale: lang,
},
{
key: `${lang}:contact`,
ttl: "max",
}
)
if (!response.data) {
const notFoundError = notFound(response)
metricsGetContactConfig.noDataError()
throw notFoundError
}
const verifiedData = validateContactConfigSchema.safeParse(response.data)
if (!verifiedData.success) {
metricsGetContactConfig.validationError(verifiedData.error)
return null
}
metricsGetContactConfig.success()
return verifiedData.data.all_contact_config.items[0]
})
export const baseQueryRouter = router({
contact: contentstackBaseProcedure.query(async ({ ctx }) => {
return await getContactConfig(ctx.lang)
}),
header: contentstackBaseProcedure.query(async ({ ctx }) => {
const { lang } = ctx
const getHeaderRefsCounter = createCounter(
"trpc.contentstack",
"header.get.refs"
)
const metricsGetHeaderRefs = getHeaderRefsCounter.init({ lang })
metricsGetHeaderRefs.start()
const responseRef = await request<GetHeaderRefs>(
GetHeaderRef,
{
locale: lang,
},
{
key: generateRefsResponseTag(lang, "header"),
ttl: "max",
}
)
if (!responseRef.data) {
const notFoundError = notFound(responseRef)
metricsGetHeaderRefs.noDataError()
throw notFoundError
}
const validatedHeaderRefs = headerRefsSchema.safeParse(responseRef.data)
if (!validatedHeaderRefs.success) {
metricsGetHeaderRefs.validationError(validatedHeaderRefs.error)
return null
}
metricsGetHeaderRefs.success()
const connections = getConnections(validatedHeaderRefs.data)
const getHeaderCounter = createCounter("trpc.contentstack", "header.get")
const metricsGetHeader = getHeaderCounter.init({ lang })
metricsGetHeader.start()
const tags = [
generateTagsFromSystem(lang, connections),
generateTag(lang, validatedHeaderRefs.data.header.system.uid),
].flat()
const response = await request<GetHeaderData>(
GetHeader,
{ locale: lang },
{ key: tags, ttl: "max" }
)
if (!response.data) {
const notFoundError = notFound(response)
metricsGetHeader.noDataError()
throw notFoundError
}
const validatedHeaderConfig = headerSchema.safeParse(response.data)
if (!validatedHeaderConfig.success) {
metricsGetHeader.validationError(validatedHeaderConfig.error)
return null
}
metricsGetHeader.success()
return {
data: validatedHeaderConfig.data.header,
}
}),
currentHeader: contentstackBaseProcedure
.input(langInput)
.query(async ({ input }) => {
const getCurrentHeaderRefsCounter = createCounter(
"trpc.contentstack",
"currentHeader.get.refs"
)
const metricsGetCurrentHeaderRefs = getCurrentHeaderRefsCounter.init({
lang: input.lang,
})
metricsGetCurrentHeaderRefs.start()
const responseRef = await request<CurrentHeaderRefDataRaw>(
GetCurrentHeaderRef,
{
locale: input.lang,
},
{
key: generateRefsResponseTag(input.lang, "current_header"),
ttl: "max",
}
)
const getCurrentHeaderCounter = createCounter(
"trpc.contentstack",
"currentHeader.get"
)
const metricsGetCurrentHeader = getCurrentHeaderCounter.init({
lang: input.lang,
})
metricsGetCurrentHeader.start()
const currentHeaderUID =
responseRef.data.all_current_header.items[0].system.uid
// There's currently no error handling/validation for the responseRef, should it be added?
const response = await request<GetCurrentHeaderData>(
GetCurrentHeader,
{ locale: input.lang },
{
key: generateTag(input.lang, currentHeaderUID),
ttl: "max",
}
)
if (!response.data) {
const notFoundError = notFound(response)
metricsGetCurrentHeader.noDataError()
throw notFoundError
}
const validatedHeaderConfig = validateCurrentHeaderConfigSchema.safeParse(
response.data
)
if (!validatedHeaderConfig.success) {
metricsGetCurrentHeader.validationError(validatedHeaderConfig.error)
return null
}
metricsGetCurrentHeader.success()
return validatedHeaderConfig.data
}),
currentFooter: contentstackBaseProcedure
.input(langInput)
.query(async ({ input }) => {
const getCurrentFooterRefsCounter = createCounter(
"trpc.contentstack",
"currentFooter.get.refs"
)
const metricsGetCurrentFooterRefs = getCurrentFooterRefsCounter.init({
lang: input.lang,
})
metricsGetCurrentFooterRefs.start()
const responseRef = await request<CurrentFooterRefDataRaw>(
GetCurrentFooterRef,
{
locale: input.lang,
},
{
key: generateRefsResponseTag(input.lang, "current_footer"),
ttl: "max",
}
)
const getCurrentFooterCounter = createCounter(
"trpc.contentstack",
"currentFooter.get"
)
const metricsGetCurrentFooter = getCurrentFooterCounter.init({
lang: input.lang,
})
metricsGetCurrentFooter.start()
const currentFooterUID =
responseRef.data.all_current_footer.items[0].system.uid
const response = await request<CurrentFooterDataRaw>(
GetCurrentFooter,
{
locale: input.lang,
},
{
key: generateTag(input.lang, currentFooterUID),
ttl: "max",
}
)
if (!response.data) {
const notFoundError = notFound(response)
metricsGetCurrentFooter.noDataError()
throw notFoundError
}
const validatedCurrentFooterConfig =
validateCurrentFooterConfigSchema.safeParse(response.data)
if (!validatedCurrentFooterConfig.success) {
metricsGetCurrentFooter.validationError(
validatedCurrentFooterConfig.error
)
return null
}
metricsGetCurrentFooter.success()
return validatedCurrentFooterConfig.data.all_current_footer.items[0]
}),
footer: contentstackBaseProcedure.query(async ({ ctx }) => {
const { lang } = ctx
const getFooterRefsCounter = createCounter(
"trpc.contentstack",
"footer.get.refs"
)
const metricsGetFooterRefs = getFooterRefsCounter.init({ lang })
metricsGetFooterRefs.start()
const responseRef = await request<FooterRefDataRaw>(
GetFooterRef,
{
locale: lang,
},
{
key: generateRefsResponseTag(lang, "footer"),
ttl: "max",
}
)
if (!responseRef.data) {
const notFoundError = notFound(responseRef)
metricsGetFooterRefs.noDataError()
throw notFoundError
}
const validatedFooterRefs = validateFooterRefConfigSchema.safeParse(
responseRef.data
)
if (!validatedFooterRefs.success) {
metricsGetFooterRefs.validationError(validatedFooterRefs.error)
return null
}
metricsGetFooterRefs.success()
const connections = getFooterConnections(validatedFooterRefs.data)
const footerUID = responseRef.data.all_footer.items[0].system.uid
const getFooterCounter = createCounter("trpc.contentstack", "footer.get")
const metricsGetFooter = getFooterCounter.init({ lang })
metricsGetFooter.start()
const tags = [
generateTags(lang, connections),
generateTag(lang, footerUID),
].flat()
const response = await request<FooterDataRaw>(
GetFooter,
{
locale: lang,
},
{
key: tags,
ttl: "max",
}
)
if (!response.data) {
const notFoundError = notFound(response)
metricsGetFooter.noDataError()
throw notFoundError
}
const validatedFooterConfig = validateFooterConfigSchema.safeParse(
response.data
)
if (!validatedFooterConfig.success) {
metricsGetFooter.validationError(validatedFooterConfig.error)
return null
}
metricsGetFooter.success()
return validatedFooterConfig.data
}),
siteConfig: contentstackBaseProcedure
.input(langInput)
.query(async ({ input, ctx }) => {
const lang = input.lang ?? ctx.lang
const getSiteConfigRefsCounter = createCounter(
"trpc.contentstack",
"siteConfig.get.refs"
)
const metricsGetSiteConfigRefs = getSiteConfigRefsCounter.init({ lang })
metricsGetSiteConfigRefs.start()
const responseRef = await request<GetSiteConfigRefData>(
GetSiteConfigRef,
{
locale: lang,
},
{
key: generateRefsResponseTag(lang, "site_config"),
ttl: "max",
}
)
if (!responseRef.data) {
const notFoundError = notFound(responseRef)
metricsGetSiteConfigRefs.noDataError()
throw notFoundError
}
const validatedSiteConfigRef = siteConfigRefSchema.safeParse(
responseRef.data
)
if (!validatedSiteConfigRef.success) {
metricsGetSiteConfigRefs.validationError(validatedSiteConfigRef.error)
return null
}
const connections = getSiteConfigConnections(validatedSiteConfigRef.data)
const siteConfigUid = responseRef.data.all_site_config.items[0].system.uid
const tags = [
generateTagsFromSystem(lang, connections),
generateTag(lang, siteConfigUid),
].flat()
metricsGetSiteConfigRefs.success()
const getSiteConfigCounter = createCounter(
"trpc.contentstack",
"siteConfig.get"
)
const metricsGetSiteConfig = getSiteConfigCounter.init({ lang })
metricsGetSiteConfig.start()
const [siteConfigResponse, contactConfig] = await Promise.all([
request<GetSiteConfigData>(
GetSiteConfig,
{
locale: lang,
},
{
key: tags,
ttl: "max",
}
),
getContactConfig(lang),
])
if (!siteConfigResponse.data) {
const notFoundError = notFound(siteConfigResponse)
metricsGetSiteConfig.noDataError()
throw notFoundError
}
const validatedSiteConfig = siteConfigSchema.safeParse(
siteConfigResponse.data
)
if (!validatedSiteConfig.success) {
metricsGetSiteConfig.validationError(validatedSiteConfig.error)
return null
}
metricsGetSiteConfig.success()
const { sitewideAlert } = validatedSiteConfig.data
return {
...validatedSiteConfig.data,
sitewideAlert: sitewideAlert
? {
...sitewideAlert,
phoneContact: contactConfig
? getAlertPhoneContactData(sitewideAlert, contactConfig)
: null,
}
: null,
}
}),
})