feat: loosen up the zod validations and return null instead of throwing

This commit is contained in:
Simon Emanuelsson
2024-06-07 10:36:23 +02:00
parent 5c50ac060d
commit aca9221ea6
89 changed files with 1117 additions and 821 deletions

View File

@@ -3,7 +3,7 @@ import {
GetAccountPageRefs,
} from "@/lib/graphql/Query/AccountPage.graphql"
import { request } from "@/lib/graphql/request"
import { internalServerError, notFound } from "@/server/errors/trpc"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import {
@@ -45,15 +45,14 @@ export const accountPageQueryRouter = router({
throw notFound(refsResponse)
}
// Remove empty objects from a fetched content type. Needed since
// Contentstack returns empty objects for all non queried blocks in modular blocks.
// This is an ongoing support case in Contentstack, ticker number #00031579
const cleanedData = removeEmptyObjects(refsResponse.data)
const validatedAccountPageRefs =
validateAccountPageRefsSchema.safeParse(cleanedData)
if (!validatedAccountPageRefs.success) {
throw internalServerError(validatedAccountPageRefs.error)
console.info(`Failed to validate My Page Refs - (uid: ${uid})`)
console.error(validatedAccountPageRefs.error)
return null
}
const connections = getConnections(validatedAccountPageRefs.data)
@@ -81,7 +80,9 @@ export const accountPageQueryRouter = router({
)
if (!validatedAccountPage.success) {
throw internalServerError(validatedAccountPage.error)
console.info(`Failed to validate Account Page - (uid: ${uid})`)
console.error(validatedAccountPage.error)
return null
}
// TODO: Make returned data nicer

View File

@@ -8,12 +8,8 @@ import {
GetCurrentHeaderRef,
} from "@/lib/graphql/Query/CurrentHeader.graphql"
import { request } from "@/lib/graphql/request"
import { internalServerError, notFound } from "@/server/errors/trpc"
import {
contentstackBaseProcedure,
publicProcedure,
router,
} from "@/server/trpc"
import { notFound } from "@/server/errors/trpc"
import { contentstackBaseProcedure, router } from "@/server/trpc"
import { generateTag } from "@/utils/generateTag"
@@ -47,12 +43,16 @@ export const baseQueryRouter = router({
)
if (!validatedContactConfigConfig.success) {
throw internalServerError(validatedContactConfigConfig.error)
console.info(
`Failed to validate Contact Config Data - (lang: ${ctx.lang})`
)
console.error(validatedContactConfigConfig.error)
return null
}
return validatedContactConfigConfig.data.all_contact_config.items[0]
}),
header: publicProcedure.input(langInput).query(async ({ input }) => {
header: contentstackBaseProcedure.input(langInput).query(async ({ input }) => {
const responseRef = await request<HeaderRefDataRaw>(GetCurrentHeaderRef, {
locale: input.lang,
})
@@ -79,7 +79,9 @@ export const baseQueryRouter = router({
)
if (!validatedHeaderConfig.success) {
throw internalServerError(validatedHeaderConfig.error)
console.info(`Failed to validate Header - (lang: ${input.lang})`)
console.error(validatedHeaderConfig.error)
return null
}
const logo =
@@ -91,7 +93,7 @@ export const baseQueryRouter = router({
logo,
} as HeaderData
}),
footer: publicProcedure.input(langInput).query(async ({ input }) => {
footer: contentstackBaseProcedure.input(langInput).query(async ({ input }) => {
const responseRef = await request<FooterRefDataRaw>(GetCurrentFooterRef, {
locale: input.lang,
})
@@ -116,7 +118,9 @@ export const baseQueryRouter = router({
)
if (!validatedFooterConfig.success) {
throw internalServerError(validatedFooterConfig.error)
console.info(`Failed to validate Footer - (lang: ${input.lang})`)
console.error(validatedFooterConfig.error)
return null
}
return validatedFooterConfig.data.all_current_footer.items[0]

View File

@@ -6,7 +6,6 @@ import {
GetMyPagesBreadcrumbs,
GetMyPagesBreadcrumbsRefs,
} from "@/lib/graphql/Query/BreadcrumbsMyPages.graphql"
import { internalServerError } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import {
@@ -41,7 +40,11 @@ async function getLoyaltyPageBreadcrumbs(variables: Variables) {
)
if (!validatedRefsData.success) {
throw internalServerError(validatedRefsData.error)
console.info(
`Failed to validate Loyaltypage Breadcrumbs Refs - (url: ${variables.url})`
)
console.error(validatedRefsData.error)
return null
}
const tags = getTags(validatedRefsData.data.all_loyalty_page, variables)
@@ -53,14 +56,18 @@ async function getLoyaltyPageBreadcrumbs(variables: Variables) {
)
if (!response.data.all_loyalty_page.items[0].web?.breadcrumbs?.title) {
return []
return null
}
const validatedBreadcrumbsData =
validateLoyaltyPageBreadcrumbsContentstackSchema.safeParse(response.data)
if (!validatedBreadcrumbsData.success) {
throw internalServerError(validatedBreadcrumbsData.error)
console.info(
`Failed to validate Loyaltypage Breadcrumbs Data - (url: ${variables.url})`
)
console.error(validatedBreadcrumbsData.error)
return null
}
return getBreadcrumbs(
@@ -80,7 +87,11 @@ async function getMyPagesBreadcrumbs(variables: Variables) {
refsResponse.data
)
if (!validatedRefsData.success) {
throw internalServerError(validatedRefsData.error)
console.info(
`Failed to validate My Page Breadcrumbs Refs - (url: ${variables.url})`
)
console.error(validatedRefsData.error)
return null
}
const tags = getTags(validatedRefsData.data.all_account_page, variables)
@@ -99,7 +110,11 @@ async function getMyPagesBreadcrumbs(variables: Variables) {
validateMyPagesBreadcrumbsContentstackSchema.safeParse(response.data)
if (!validatedBreadcrumbsData.success) {
throw internalServerError(validatedBreadcrumbsData.error)
console.info(
`Failed to validate My Page Breadcrumbs Data - (url: ${variables.url})`
)
console.error(validatedBreadcrumbsData.error)
return null
}
return getBreadcrumbs(

View File

@@ -119,7 +119,11 @@ export const languageSwitcherQueryRouter = router({
validateLanguageSwitcherData.safeParse(urls)
if (!validatedLanguageSwitcherData.success) {
throw internalServerError(validatedLanguageSwitcherData.error)
console.info(
`Failed to validate Language Switcher Data - (contentType: ${ctx.contentType}, lang: ${ctx.lang}, uid: ${ctx.uid})`
)
console.error(validatedLanguageSwitcherData.error)
return null
}
return {

View File

@@ -3,7 +3,7 @@ import {
GetLoyaltyPageRefs,
} from "@/lib/graphql/Query/LoyaltyPage.graphql"
import { request } from "@/lib/graphql/request"
import { internalServerError, notFound } from "@/server/errors/trpc"
import { notFound } from "@/server/errors/trpc"
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
import {
@@ -35,9 +35,9 @@ function makeButtonObject(button: any) {
href:
button.is_contentstack_link && button.linkConnection.edges.length
? button.linkConnection.edges[0].node.web?.original_url ||
removeMultipleSlashes(
`/${button.linkConnection.edges[0].node.system.locale}/${button.linkConnection.edges[0].node.url}`
)
removeMultipleSlashes(
`/${button.linkConnection.edges[0].node.system.locale}/${button.linkConnection.edges[0].node.url}`
)
: button.external_link.href,
isExternal: !button.is_contentstack_link,
}
@@ -62,17 +62,16 @@ export const loyaltyPageQueryRouter = router({
throw notFound(refsResponse)
}
// Remove empty objects from a fetched content type. Needed since
// Contentstack returns empty objects for all non queried blocks in modular blocks.
// This is an ongoing support case in Contentstack, ticker number #00031579
const cleanedData = removeEmptyObjects(refsResponse.data)
const validatedLoyaltyPageRefs =
validateLoyaltyPageRefsSchema.safeParse(cleanedData)
if (!validatedLoyaltyPageRefs.success) {
console.error("Bad validation for `GetLoyaltyPageRefs`")
console.info(
`Failed to validate Loyaltypage Refs - (lang: ${lang}, uid: ${uid})`
)
console.error(validatedLoyaltyPageRefs.error)
throw internalServerError(validatedLoyaltyPageRefs.error)
return null
}
const connections = getConnections(validatedLoyaltyPageRefs.data)
@@ -97,66 +96,66 @@ export const loyaltyPageQueryRouter = router({
const blocks = response.data.loyalty_page.blocks
? response.data.loyalty_page.blocks.map((block: any) => {
switch (block.__typename) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
return {
...block,
dynamic_content: {
...block.dynamic_content,
link: block.dynamic_content.link.pageConnection.edges.length
? {
text: block.dynamic_content.link.text,
href: removeMultipleSlashes(
`/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}/${block.dynamic_content.link.pageConnection.edges[0].node.url}`
),
title:
block.dynamic_content.link.pageConnection.edges[0]
.node.title,
}
: undefined,
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts:
return {
...block,
shortcuts: {
...block.shortcuts,
shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({
text: shortcut.text,
openInNewTab: shortcut.open_in_new_tab,
...shortcut.linkConnection.edges[0].node,
url:
shortcut.linkConnection.edges[0].node.web?.original_url ||
removeMultipleSlashes(
`/${shortcut.linkConnection.edges[0].node.system.locale}/${shortcut.linkConnection.edges[0].node.url}`
),
})),
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
return {
...block,
cards_grid: {
...block.cards_grid,
cards: block.cards_grid.cardConnection.edges.map(
({ node: card }: { node: any }) => {
return {
...card,
primaryButton: card.has_primary_button
? makeButtonObject(card.primary_button)
: undefined,
secondaryButton: card.has_secondary_button
? makeButtonObject(card.secondary_button)
: undefined,
}
switch (block.__typename) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
return {
...block,
dynamic_content: {
...block.dynamic_content,
link: block.dynamic_content.link.pageConnection.edges.length
? {
text: block.dynamic_content.link.text,
href: removeMultipleSlashes(
`/${block.dynamic_content.link.pageConnection.edges[0].node.system.locale}/${block.dynamic_content.link.pageConnection.edges[0].node.url}`
),
title:
block.dynamic_content.link.pageConnection.edges[0]
.node.title,
}
: undefined,
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts:
return {
...block,
shortcuts: {
...block.shortcuts,
shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({
text: shortcut.text,
openInNewTab: shortcut.open_in_new_tab,
...shortcut.linkConnection.edges[0].node,
url:
shortcut.linkConnection.edges[0].node.web?.original_url ||
removeMultipleSlashes(
`/${shortcut.linkConnection.edges[0].node.system.locale}/${shortcut.linkConnection.edges[0].node.url}`
),
})),
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardsGrid:
return {
...block,
cards_grid: {
...block.cards_grid,
cards: block.cards_grid.cardConnection.edges.map(
({ node: card }: { node: any }) => {
return {
...card,
primaryButton: card.has_primary_button
? makeButtonObject(card.primary_button)
: undefined,
secondaryButton: card.has_secondary_button
? makeButtonObject(card.secondary_button)
: undefined,
}
),
},
}
default:
return block
}
})
}
),
},
}
default:
return block
}
})
: null
const loyaltyPage = {
@@ -170,7 +169,11 @@ export const loyaltyPageQueryRouter = router({
validateLoyaltyPageSchema.safeParse(loyaltyPage)
if (!validatedLoyaltyPage.success) {
throw internalServerError(validatedLoyaltyPage.error)
console.info(
`Failed to validate Loyaltypage Data - (lang: ${lang}, uid: ${uid})`
)
console.error(validatedLoyaltyPage.error)
return null
}
// Assert LoyaltyPage type to get correct typings for RTE fields

View File

@@ -3,7 +3,7 @@ import {
GetNavigationMyPagesRefs,
} from "@/lib/graphql/Query/NavigationMyPages.graphql"
import { request } from "@/lib/graphql/request"
import { internalServerError, notFound } from "@/server/errors/trpc"
import { notFound } from "@/server/errors/trpc"
import { contentstackBaseProcedure, router } from "@/server/trpc"
import {
@@ -71,7 +71,11 @@ export const navigationQueryRouter = router({
const validatedMyPagesNavigationRefs =
navigationRefsPayloadSchema.safeParse(refsResponse.data)
if (!validatedMyPagesNavigationRefs.success) {
throw internalServerError(validatedMyPagesNavigationRefs.error)
console.info(
`Failed to validate My Pages Navigation Refs - (lang: ${lang}`
)
console.error(validatedMyPagesNavigationRefs.error)
return null
}
const connections = getConnections(validatedMyPagesNavigationRefs.data)
@@ -99,7 +103,11 @@ export const navigationQueryRouter = router({
response.data
)
if (!validatedMyPagesNavigation.success) {
throw internalServerError(validatedMyPagesNavigation.error)
console.info(
`Failed to validate My Pages Navigation Data - (lang: ${lang}`
)
console.error(validatedMyPagesNavigation.error)
return null
}
const menuItem =
@@ -112,7 +120,11 @@ export const navigationQueryRouter = router({
const validatedNav = getNavigationSchema.safeParse(nav)
if (!validatedNav.success) {
throw internalServerError(validatedNav.error)
console.info(
`Failed to validate My Pages Navigation Return Data - (lang: ${lang}`
)
console.error(validatedNav.error)
return null
}
return validatedNav.data