feat(SW-200): refactored breadcrumbs fetching and added json schema to layout

This commit is contained in:
Erik Tiekstra
2024-11-14 13:18:35 +01:00
parent 28738d7161
commit b22888db5f
13 changed files with 318 additions and 379 deletions
+162 -197
View File
@@ -1,3 +1,7 @@
import { metrics } from "@opentelemetry/api"
import { cache } from "react"
import { Lang } from "@/constants/languages"
import {
GetMyPagesBreadcrumbs,
GetMyPagesBreadcrumbsRefs,
@@ -14,237 +18,198 @@ import {
GetLoyaltyPageBreadcrumbs,
GetLoyaltyPageBreadcrumbsRefs,
} from "@/lib/graphql/Query/Breadcrumbs/LoyaltyPage.graphql"
import { request } from "@/lib/graphql/request"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import {
GetCollectionPageBreadcrumbsData,
GetCollectionPageBreadcrumbsRefsData,
type GetContentPageBreadcrumbsData,
type GetContentPageBreadcrumbsRefsData,
type GetLoyaltyPageBreadcrumbsData,
type GetLoyaltyPageBreadcrumbsRefsData,
type GetMyPagesBreadcrumbsData,
type GetMyPagesBreadcrumbsRefsData,
validateCollectionPageBreadcrumbsContentstackSchema,
validateCollectionPageBreadcrumbsRefsContentstackSchema,
validateContentPageBreadcrumbsContentstackSchema,
validateContentPageBreadcrumbsRefsContentstackSchema,
validateLoyaltyPageBreadcrumbsContentstackSchema,
validateLoyaltyPageBreadcrumbsRefsContentstackSchema,
validateMyPagesBreadcrumbsContentstackSchema,
validateMyPagesBreadcrumbsRefsContentstackSchema,
} from "./output"
import {
getBreadcrumbs,
getRefsResponse,
getResponse,
getTags,
Variables,
} from "./utils"
import { breadcrumbsRefsSchema, breadcrumbsSchema } from "./output"
import { getTags } from "./utils"
import { PageTypeEnum } from "@/types/requests/pageType"
import {
BreadcrumbsRefsSchema,
RawBreadcrumbsSchema,
} from "@/types/trpc/routers/contentstack/breadcrumbs"
async function getLoyaltyPageBreadcrumbs(variables: Variables) {
const refsResponse = await getRefsResponse<GetLoyaltyPageBreadcrumbsRefsData>(
GetLoyaltyPageBreadcrumbsRefs,
variables
)
const meter = metrics.getMeter("trpc.breadcrumbs")
const validatedRefsData =
validateLoyaltyPageBreadcrumbsRefsContentstackSchema.safeParse(
refsResponse.data
)
// OpenTelemetry metrics
const getBreadcrumbsRefsCounter = meter.createCounter(
"trpc.contentstack.breadcrumbs.refs.get"
)
const getBreadcrumbsRefsSuccessCounter = meter.createCounter(
"trpc.contentstack.breadcrumbs.refs.get-success"
)
const getBreadcrumbsRefsFailCounter = meter.createCounter(
"trpc.contentstack.breadcrumbs.refs.get-fail"
)
const getBreadcrumbsCounter = meter.createCounter(
"trpc.contentstack.breadcrumbs.get"
)
const getBreadcrumbsSuccessCounter = meter.createCounter(
"trpc.contentstack.breadcrumbs.get-success"
)
const getBreadcrumbsFailCounter = meter.createCounter(
"trpc.contentstack.breadcrumbs.get-fail"
)
if (!validatedRefsData.success) {
console.error(
`Failed to validate Loyaltypage Breadcrumbs Refs - (uid: ${variables.uid})`
)
console.error(validatedRefsData.error)
return null
}
const tags = getTags(validatedRefsData.data.loyalty_page, variables)
const response = await getResponse<GetLoyaltyPageBreadcrumbsData>(
GetLoyaltyPageBreadcrumbs,
variables,
tags
)
if (!response.data.loyalty_page.web?.breadcrumbs?.title) {
return null
}
const validatedBreadcrumbsData =
validateLoyaltyPageBreadcrumbsContentstackSchema.safeParse(response.data)
if (!validatedBreadcrumbsData.success) {
console.error(
`Failed to validate Loyaltypage Breadcrumbs Data - (uid: ${variables.uid})`
)
console.error(validatedBreadcrumbsData.error)
return null
}
return getBreadcrumbs(
validatedBreadcrumbsData.data.loyalty_page,
variables.locale
)
interface BreadcrumbsPageData<T> {
dataKey: keyof T
refQuery: string
query: string
}
async function getCollectionPageBreadcrumbs(variables: Variables) {
const refsResponse =
await getRefsResponse<GetCollectionPageBreadcrumbsRefsData>(
GetCollectionPageBreadcrumbsRefs,
variables
)
const validatedRefsData =
validateCollectionPageBreadcrumbsRefsContentstackSchema.safeParse(
refsResponse.data
)
const getBreadcrumbs = cache(async function fetchMemoizedBreadcrumbs<T>(
{ dataKey, refQuery, query }: BreadcrumbsPageData<T>,
{ uid, lang }: { uid: string; lang: Lang }
) {
getBreadcrumbsRefsCounter.add(1, { lang, uid })
console.info(
"contentstack.breadcrumbs refs get start",
JSON.stringify({ query: { lang, uid } })
)
const refsResponse = await request<{ [K in keyof T]: BreadcrumbsRefsSchema }>(
refQuery,
{ locale: lang, uid }
)
const validatedRefsData = breadcrumbsRefsSchema.safeParse(
refsResponse.data[dataKey]
)
if (!validatedRefsData.success) {
getBreadcrumbsRefsFailCounter.add(1, {
error_type: "validation_error",
error: JSON.stringify(validatedRefsData.error),
})
console.error(
`Failed to validate CollectionPpage Breadcrumbs Refs - (uid: ${variables.uid})`
"contentstack.breadcrumbs refs validation error",
JSON.stringify({
error: validatedRefsData.error,
})
)
console.error(validatedRefsData.error)
return null
}
const tags = getTags(validatedRefsData.data.collection_page, variables)
const response = await getResponse<GetCollectionPageBreadcrumbsData>(
GetCollectionPageBreadcrumbs,
variables,
tags
)
if (!response.data.collection_page.web?.breadcrumbs?.title) {
return null
}
const validatedBreadcrumbsData =
validateCollectionPageBreadcrumbsContentstackSchema.safeParse(response.data)
if (!validatedBreadcrumbsData.success) {
console.error(
`Failed to validate Collectionpage Breadcrumbs Data - (uid: ${variables.uid})`
)
console.error(validatedBreadcrumbsData.error)
return null
}
return getBreadcrumbs(
validatedBreadcrumbsData.data.collection_page,
variables.locale
)
}
async function getContentPageBreadcrumbs(variables: Variables) {
const refsResponse = await getRefsResponse<GetContentPageBreadcrumbsRefsData>(
GetContentPageBreadcrumbsRefs,
variables
)
const validatedRefsData =
validateContentPageBreadcrumbsRefsContentstackSchema.safeParse(
refsResponse.data
)
if (!validatedRefsData.success) {
console.error(
`Failed to validate Contentpage Breadcrumbs Refs - (uid: ${variables.uid})`
)
console.error(validatedRefsData.error)
return null
}
const tags = getTags(validatedRefsData.data.content_page, variables)
const response = await getResponse<GetContentPageBreadcrumbsData>(
GetContentPageBreadcrumbs,
variables,
tags
)
if (!response.data.content_page.web?.breadcrumbs?.title) {
return null
}
const validatedBreadcrumbsData =
validateContentPageBreadcrumbsContentstackSchema.safeParse(response.data)
if (!validatedBreadcrumbsData.success) {
console.error(
`Failed to validate Contentpage Breadcrumbs Data - (uid: ${variables.uid})`
)
console.error(validatedBreadcrumbsData.error)
return null
}
return getBreadcrumbs(
validatedBreadcrumbsData.data.content_page,
variables.locale
)
}
async function getMyPagesBreadcrumbs(variables: Variables) {
const refsResponse = await getRefsResponse<GetMyPagesBreadcrumbsRefsData>(
GetMyPagesBreadcrumbsRefs,
variables
)
const validatedRefsData =
validateMyPagesBreadcrumbsRefsContentstackSchema.safeParse(
refsResponse.data
)
if (!validatedRefsData.success) {
console.error(
`Failed to validate My Page Breadcrumbs Refs - (uid: ${variables.uid})`
)
console.error(validatedRefsData.error)
return null
}
const tags = getTags(validatedRefsData.data.account_page, variables)
const response = await getResponse<GetMyPagesBreadcrumbsData>(
GetMyPagesBreadcrumbs,
variables,
tags
)
if (!response.data.account_page.web?.breadcrumbs?.title) {
return []
}
const validatedBreadcrumbsData =
validateMyPagesBreadcrumbsContentstackSchema.safeParse(response.data)
getBreadcrumbsRefsSuccessCounter.add(1, { lang, uid })
console.info(
"contentstack.breadcrumbs refs get success",
JSON.stringify({ query: { lang, uid } })
)
if (!validatedBreadcrumbsData.success) {
const tags = getTags(validatedRefsData.data, lang)
getBreadcrumbsCounter.add(1, { lang, uid })
console.info(
"contentstack.breadcrumbs get start",
JSON.stringify({ query: { lang, uid } })
)
const response = await request<T>(
query,
{ locale: lang, uid },
{
cache: "force-cache",
next: { tags },
}
)
if (!response.data) {
const notFoundError = notFound(response)
getBreadcrumbsFailCounter.add(1, {
lang,
uid,
error_type: "not_found",
error: JSON.stringify({ code: notFoundError.code }),
})
console.error(
`Failed to validate My Page Breadcrumbs Data - (uid: ${variables.uid})`
"contentstack.breadcrumbs get not found error",
JSON.stringify({
query: { lang, uid },
error: { code: notFoundError.code },
})
)
console.error(validatedBreadcrumbsData.error)
return null
throw notFoundError
}
return getBreadcrumbs(
validatedBreadcrumbsData.data.account_page,
variables.locale
const validatedBreadcrumbs = breadcrumbsSchema.safeParse(
response.data[dataKey]
)
}
if (!validatedBreadcrumbs.success) {
getBreadcrumbsFailCounter.add(1, {
error_type: "validation_error",
error: JSON.stringify(validatedBreadcrumbs.error),
})
console.error(
"contentstack.breadcrumbs validation error",
JSON.stringify({
error: validatedBreadcrumbs.error,
})
)
return []
}
getBreadcrumbsSuccessCounter.add(1, { lang, uid })
console.info(
"contentstack.breadcrumbs get success",
JSON.stringify({ query: { lang, uid } })
)
return validatedBreadcrumbs.data
})
export const breadcrumbsQueryRouter = router({
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
const variables = {
locale: ctx.lang,
lang: ctx.lang,
uid: ctx.uid,
}
switch (ctx.contentType) {
case PageTypeEnum.accountPage:
return await getMyPagesBreadcrumbs(variables)
return await getBreadcrumbs<{
account_page: RawBreadcrumbsSchema
}>(
{
dataKey: "account_page",
refQuery: GetMyPagesBreadcrumbsRefs,
query: GetMyPagesBreadcrumbs,
},
variables
)
case PageTypeEnum.collectionPage:
return await getCollectionPageBreadcrumbs(variables)
return await getBreadcrumbs<{
collection_page: RawBreadcrumbsSchema
}>(
{
dataKey: "collection_page",
refQuery: GetCollectionPageBreadcrumbsRefs,
query: GetCollectionPageBreadcrumbs,
},
variables
)
case PageTypeEnum.contentPage:
return await getContentPageBreadcrumbs(variables)
return await getBreadcrumbs<{
content_page: RawBreadcrumbsSchema
}>(
{
dataKey: "content_page",
refQuery: GetContentPageBreadcrumbsRefs,
query: GetContentPageBreadcrumbs,
},
variables
)
case PageTypeEnum.loyaltyPage:
return await getLoyaltyPageBreadcrumbs(variables)
return await getBreadcrumbs<{
loyalty_page: RawBreadcrumbsSchema
}>(
{
dataKey: "loyalty_page",
refQuery: GetLoyaltyPageBreadcrumbsRefs,
query: GetLoyaltyPageBreadcrumbs,
},
variables
)
default:
return []
}