Files
web/server/routers/contentstack/metadata/query.ts

147 lines
4.6 KiB
TypeScript

import { metrics } from "@opentelemetry/api"
import { cache } from "react"
import { Lang } from "@/constants/languages"
import { GetAccountPageMetaData } from "@/lib/graphql/Query/AccountPage/MetaData.graphql"
import { GetCollectionPageMetaData } from "@/lib/graphql/Query/CollectionPage/MetaData.graphql"
import { GetContentPageMetaData } from "@/lib/graphql/Query/ContentPage/MetaData.graphql"
import { GetLoyaltyPageMetaData } from "@/lib/graphql/Query/LoyaltyPage/MetaData.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import { generateTag } from "@/utils/generateTag"
import { metaDataSchema } from "./output"
import { affix } from "./utils"
import { PageTypeEnum } from "@/types/requests/pageType"
import { RawMetaDataSchema } from "@/types/trpc/routers/contentstack/metadata"
const meter = metrics.getMeter("trpc.metaData")
// OpenTelemetry metrics
const fetchMetaDataCounter = meter.createCounter(
"trpc.contentstack.metaData.get"
)
const fetchMetaDataSuccessCounter = meter.createCounter(
"trpc.contentstack.metaData.get-success"
)
const fetchMetaDataFailCounter = meter.createCounter(
"trpc.contentstack.metaData.get-fail"
)
const transformMetaDataCounter = meter.createCounter(
"trpc.contentstack.metaData.transform"
)
const transformMetaDataSuccessCounter = meter.createCounter(
"trpc.contentstack.metaData.transform-success"
)
const transformMetaDataFailCounter = meter.createCounter(
"trpc.contentstack.metaData.transform-fail"
)
const fetchMetaData = cache(async function fetchMemoizedMetaData<T>(
query: string,
{ uid, lang }: { uid: string; lang: Lang }
) {
fetchMetaDataCounter.add(1, { lang, uid })
console.info(
"contentstack.metaData fetch start",
JSON.stringify({ query: { lang, uid } })
)
const response = await request<T>(
query,
{ locale: lang, uid },
{
cache: "force-cache",
next: {
tags: [generateTag(lang, uid, affix)],
},
}
)
if (!response.data) {
const notFoundError = notFound(response)
fetchMetaDataFailCounter.add(1, {
lang,
uid,
error_type: "not_found",
error: JSON.stringify({ code: notFoundError.code }),
})
console.error(
"contentstack.metaData fetch not found error",
JSON.stringify({
query: { lang, uid },
error: { code: notFoundError.code },
})
)
throw notFoundError
}
fetchMetaDataSuccessCounter.add(1, { lang, uid })
console.info(
"contentstack.metaData fetch success",
JSON.stringify({ query: { lang, uid } })
)
return response.data
})
function getTransformedMetaData(data: unknown) {
transformMetaDataCounter.add(1)
console.info("contentstack.metaData transform start")
const validatedMetaData = metaDataSchema.safeParse(data)
if (!validatedMetaData.success) {
transformMetaDataFailCounter.add(1, {
error_type: "validation_error",
error: JSON.stringify(validatedMetaData.error),
})
console.error(
"contentstack.metaData validation error",
JSON.stringify({
error: validatedMetaData.error,
})
)
return null
}
transformMetaDataSuccessCounter.add(1)
console.info("contentstack.metaData transform success")
return validatedMetaData.data
}
export const metaDataQueryRouter = router({
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
const variables = {
lang: ctx.lang,
uid: ctx.uid,
}
switch (ctx.contentType) {
case PageTypeEnum.accountPage:
const accountPageResponse = await fetchMetaData<{
account_page: RawMetaDataSchema
}>(GetAccountPageMetaData, variables)
return getTransformedMetaData(accountPageResponse.account_page)
case PageTypeEnum.collectionPage:
const collectionPageResponse = await fetchMetaData<{
collection_page: RawMetaDataSchema
}>(GetCollectionPageMetaData, variables)
return getTransformedMetaData(collectionPageResponse.collection_page)
case PageTypeEnum.contentPage:
const contentPageResponse = await fetchMetaData<{
content_page: RawMetaDataSchema
}>(GetContentPageMetaData, variables)
return getTransformedMetaData(contentPageResponse.content_page)
case PageTypeEnum.loyaltyPage:
const loyaltyPageResponse = await fetchMetaData<{
loyalty_page: RawMetaDataSchema
}>(GetLoyaltyPageMetaData, variables)
return getTransformedMetaData(loyaltyPageResponse.loyalty_page)
default:
return null
}
}),
})