Merged in fix/nullable-boolean (pull request #197)

fix: only zod validate output from trpc

Approved-by: Michael Zetterberg
This commit is contained in:
Christel Westerberg
2024-05-23 12:30:39 +00:00
committed by Michael Zetterberg
3 changed files with 64 additions and 184 deletions

View File

@@ -4,6 +4,7 @@ fragment CardBlock on Card {
background_image
scripted_top_title
title
has_secondary_button
secondary_button {
is_contentstack_link
cta_text
@@ -23,6 +24,7 @@ fragment CardBlock on Card {
}
}
}
has_primary_button
primary_button {
is_contentstack_link
cta_text

View File

@@ -13,28 +13,6 @@ import { PageLinkEnum } from "@/types/requests/pageLinks"
import { EdgesWithTotalCount } from "@/types/requests/utils/edges"
import { RTEDocument } from "@/types/rte/node"
const pageLink = z.object({
edges: z.array(
z.object({
node: z.object({
system: z.object({
uid: z.string(),
locale: z.nativeEnum(Lang),
}),
web: z
.object({
original_url: z.string().nullable(),
})
.nullable()
.optional(),
url: z.string(),
title: z.string(),
__typename: z.string().optional(),
}),
})
),
})
const loyaltyPageDynamicContent = z.object({
__typename: z.literal(
LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
@@ -43,10 +21,13 @@ const loyaltyPageDynamicContent = z.object({
title: z.string().nullable(),
subtitle: z.string().nullable(),
component: z.nativeEnum(LoyaltyComponentEnum),
link: z.object({
text: z.string().nullable(),
pageConnection: pageLink,
}),
link: z
.object({
text: z.string().nullable(),
href: z.string(),
title: z.string(),
})
.optional(),
}),
})
@@ -57,9 +38,10 @@ const loyaltyPageShortcuts = z.object({
preamble: z.string().nullable(),
shortcuts: z.array(
z.object({
linkConnection: pageLink,
text: z.string().nullable(),
open_in_new_tab: z.boolean(),
text: z.string().optional(),
openInNewTab: z.boolean(),
url: z.string(),
title: z.string(),
})
),
}),
@@ -70,31 +52,22 @@ const cardBlock = z.object({
body_text: z.string().nullable(),
background_image: z.any(),
scripted_top_title: z.string().nullable(),
primary_button: z
primaryButton: z
.object({
is_contentstack_link: z.boolean(),
cta_text: z.string().nullable(),
open_in_new_tab: z.boolean(),
external_link: z.object({
title: z.string().nullable(),
href: z.string().nullable(),
}),
linkConnection: pageLink,
openInNewTab: z.boolean(),
title: z.string(),
href: z.string(),
isExternal: z.boolean(),
})
.nullable(),
secondary_button: z
.optional(),
secondaryButton: z
.object({
is_contentstack_link: z.boolean(),
cta_text: z.string().nullable(),
open_in_new_tab: z.boolean().nullable(),
external_link: z.object({
title: z.string().nullable(),
href: z.string().nullable(),
}),
linkConnection: pageLink,
openInNewTab: z.boolean(),
title: z.string(),
href: z.string(),
isExternal: z.boolean(),
})
.nullable(),
.optional(),
system: z.object({
locale: z.nativeEnum(Lang),
uid: z.string(),
@@ -108,13 +81,7 @@ const loyaltyPageCards = z.object({
preamble: z.string().nullable(),
layout: z.enum(["twoColumnGrid", "threeColumnGrid", "twoPlusOne"]),
theme: z.enum(["one", "two", "three"]).nullable(),
cardConnection: z.object({
edges: z.array(
z.object({
node: cardBlock,
})
),
}),
cards: z.array(cardBlock),
}),
})
@@ -178,31 +145,17 @@ const loyaltyPageSidebarItem = z.discriminatedUnion("__typename", [
])
export const validateLoyaltyPageSchema = z.object({
loyalty_page: z.object({
title: z.string(),
heading: z.string().nullable(),
blocks: z.array(loyaltyPageBlockItem).nullable(),
sidebar: z.array(loyaltyPageSidebarItem).nullable(),
system: z.object({ uid: z.string() }),
}),
heading: z.string().nullable(),
blocks: z.array(loyaltyPageBlockItem).nullable(),
sidebar: z.array(loyaltyPageSidebarItem).nullable(),
system: z.object({ uid: z.string() }),
})
// Block types
type DynamicContentRaw = z.infer<typeof loyaltyPageDynamicContent>
export type DynamicContent = Omit<DynamicContentRaw, "dynamic_content"> & {
dynamic_content: Omit<DynamicContentRaw["dynamic_content"], "link"> & {
link:
| {
href: string
title: string
text?: string
}
| undefined
}
}
export type DynamicContent = z.infer<typeof loyaltyPageDynamicContent>
type BlockContentRaw = z.infer<typeof loyaltyPageBlockTextContent>
export interface RteBlockContent extends BlockContentRaw {
content: {
content: {
@@ -214,44 +167,11 @@ export interface RteBlockContent extends BlockContentRaw {
type CardsGridRaw = z.infer<typeof loyaltyPageCards>
export type CardsRaw =
CardsGridRaw["cards_grid"]["cardConnection"]["edges"][number]["node"]
export type CardsRaw = CardsGridRaw["cards_grid"]["cards"][number]
export type CardsGrid = Omit<CardsGridRaw, "cards_grid"> & {
cards_grid: Omit<CardsGridRaw["cards_grid"], "cardConnection"> & {
cards: (Omit<CardsRaw, "primaryButton" | "secondaryButton"> & {
primaryButton:
| {
openInNewTab: boolean
title: string
href: string
isExternal: boolean
}
| undefined
secondaryButton:
| {
openInNewTab: boolean
title: string
href: string
isExternal: boolean
}
| undefined
})[]
}
}
export type CardsGrid = z.infer<typeof loyaltyPageCards>
type ShortcutsRaw = z.infer<typeof loyaltyPageShortcuts>
export type Shortcuts = Omit<ShortcutsRaw, "shortcuts"> & {
shortcuts: Omit<ShortcutsRaw["shortcuts"], "shortcuts"> & {
shortcuts: {
text?: string
openInNewTab: boolean
url: string
title: string
}[]
}
}
export type Shortcuts = z.infer<typeof loyaltyPageShortcuts>
export type Block = RteBlockContent | DynamicContent | Shortcuts | CardsGrid
@@ -268,12 +188,9 @@ export type RteSidebarContent = Omit<SidebarContentRaw, "content"> & {
}
export type JoinLoyaltyContact = z.infer<typeof loyaltyPageJoinLoyaltyContact>
export type Sidebar = JoinLoyaltyContact | RteSidebarContent
type LoyaltyPageDataRaw = z.infer<typeof validateLoyaltyPageSchema>
export type LoyaltyPageDataRaw = z.infer<typeof validateLoyaltyPageSchema>
type LoyaltyPageRaw = LoyaltyPageDataRaw["loyalty_page"]
export type LoyaltyPage = Omit<LoyaltyPageRaw, "blocks" | "sidebar"> & {
export type LoyaltyPage = Omit<LoyaltyPageDataRaw, "blocks" | "sidebar"> & {
blocks: Block[]
sidebar: Sidebar[]
}

View File

@@ -15,27 +15,16 @@ import {
import { removeEmptyObjects } from "../../utils"
import {
CardsRaw,
type LoyaltyPage,
type LoyaltyPageDataRaw,
LoyaltyPage,
type LoyaltyPageRefsDataRaw,
validateLoyaltyPageRefsSchema,
validateLoyaltyPageSchema,
} from "./output"
import { getConnections } from "./utils"
import {
LoyaltyBlocksTypenameEnum,
SidebarTypenameEnum,
} from "@/types/components/loyalty/enums"
import { Embeds } from "@/types/requests/embeds"
import { Edges } from "@/types/requests/utils/edges"
import { RTEDocument } from "@/types/rte/node"
import { LoyaltyBlocksTypenameEnum } from "@/types/components/loyalty/enums"
function makeButtonObject(
button: CardsRaw["primary_button" | "secondary_button"]
) {
if (!button) return undefined
function makeButtonObject(button: any) {
return {
openInNewTab: button.open_in_new_tab,
title:
@@ -93,7 +82,7 @@ export const loyaltyPageQueryRouter = router({
generateTag(lang, validatedLoyaltyPageRefs.data.loyalty_page.system.uid),
].flat()
const response = await request<LoyaltyPageDataRaw>(
const response = await request<any>(
GetLoyaltyPage,
{
locale: lang,
@@ -106,36 +95,8 @@ export const loyaltyPageQueryRouter = router({
throw notFound(response)
}
const validatedLoyaltyPage = validateLoyaltyPageSchema.safeParse(
response.data
)
if (!validatedLoyaltyPage.success) {
throw internalServerError(validatedLoyaltyPage.error)
}
const sidebar = validatedLoyaltyPage.data.loyalty_page.sidebar
? validatedLoyaltyPage.data.loyalty_page.sidebar.map((block) => {
if (
block.__typename == SidebarTypenameEnum.LoyaltyPageSidebarContent
) {
return {
...block,
content: {
content: {
json: block.content.content.json as RTEDocument,
embedded_itemsConnection: block.content.content
.embedded_itemsConnection as Edges<Embeds>,
},
},
}
} else {
return block
}
})
: null
const blocks = validatedLoyaltyPage.data.loyalty_page.blocks
? validatedLoyaltyPage.data.loyalty_page.blocks.map((block) => {
const blocks = response.data.loyalty_page.blocks
? response.data.loyalty_page.blocks.map((block: any) => {
switch (block.__typename) {
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
return {
@@ -153,23 +114,12 @@ export const loyaltyPageQueryRouter = router({
: undefined,
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent:
return {
...block,
content: {
content: {
json: block.content.content.json as RTEDocument,
embedded_itemsConnection: block.content.content
.embedded_itemsConnection as Edges<Embeds>,
},
},
}
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksShortcuts:
return {
...block,
shortcuts: {
...block.shortcuts,
shortcuts: block.shortcuts.shortcuts.map((shortcut) => ({
shortcuts: block.shortcuts.shortcuts.map((shortcut: any) => ({
text: shortcut.text,
openInNewTab: shortcut.open_in_new_tab,
...shortcut.linkConnection.edges[0].node,
@@ -185,13 +135,15 @@ export const loyaltyPageQueryRouter = router({
cards_grid: {
...block.cards_grid,
cards: block.cards_grid.cardConnection.edges.map(
({ node: card }) => {
({ node: card }: { node: any }) => {
return {
...card,
primaryButton: makeButtonObject(card.primary_button),
secondaryButton: makeButtonObject(
card.secondary_button
),
primaryButton: card.has_primary_button
? makeButtonObject(card.primary_button)
: undefined,
secondaryButton: card.has_secondary_button
? makeButtonObject(card.secondary_button)
: undefined,
}
}
),
@@ -204,11 +156,20 @@ export const loyaltyPageQueryRouter = router({
: null
const loyaltyPage = {
...validatedLoyaltyPage.data.loyalty_page,
heading: response.data.loyalty_page.heading,
system: response.data.loyalty_page.system,
blocks,
sidebar,
} as LoyaltyPage
sidebar: response.data.loyalty_page.sidebar,
}
return loyaltyPage
const validatedLoyaltyPage =
validateLoyaltyPageSchema.safeParse(loyaltyPage)
if (!validatedLoyaltyPage.success) {
throw internalServerError(validatedLoyaltyPage.error)
}
// Assert LoyaltyPage type to get correct typings for RTE fields
return validatedLoyaltyPage.data as LoyaltyPage
}),
})