refactor: infer types from zod validation
This commit is contained in:
208
server/routers/contentstack/loyaltyPage/output.ts
Normal file
208
server/routers/contentstack/loyaltyPage/output.ts
Normal file
@@ -0,0 +1,208 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import { Embeds } from "@/types/requests/embeds"
|
||||
import {
|
||||
JoinLoyaltyContactTypenameEnum,
|
||||
LoyaltyBlocksTypenameEnum,
|
||||
LoyaltyComponentEnum,
|
||||
SidebarTypenameEnum,
|
||||
} from "@/types/requests/loyaltyPage"
|
||||
import { Edges } from "@/types/requests/utils/edges"
|
||||
import { RTEDocument } from "@/types/rte/node"
|
||||
|
||||
const loyaltyPageBlockCardGrid = z.object({
|
||||
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid),
|
||||
card_grid: z.object({
|
||||
title: z.string().optional(),
|
||||
subtitle: z.string().optional(),
|
||||
cards: z.array(
|
||||
z.object({
|
||||
title: z.string().optional(),
|
||||
subtitle: z.string().optional(),
|
||||
referenceConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
system: z.object({
|
||||
uid: z.string(),
|
||||
}),
|
||||
url: z.string(),
|
||||
title: z.string(),
|
||||
__typename: z.string(),
|
||||
}),
|
||||
})
|
||||
),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
open_in_new_tab: z.boolean(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
const loyaltyPageDynamicContent = z.object({
|
||||
__typename: z.literal(
|
||||
LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent
|
||||
),
|
||||
dynamic_content: z.object({
|
||||
title: z.string().optional(),
|
||||
subtitle: z.string().optional(),
|
||||
component: z.nativeEnum(LoyaltyComponentEnum),
|
||||
link: z.object({
|
||||
text: z.string().optional(),
|
||||
pageConnection: z.object({
|
||||
edges: z.array(
|
||||
z.object({
|
||||
node: z.object({
|
||||
system: z.object({
|
||||
uid: z.string(),
|
||||
}),
|
||||
url: z.string(),
|
||||
title: z.string(),
|
||||
}),
|
||||
})
|
||||
),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
const loyaltyPageBlockTextContent = z.object({
|
||||
__typename: z.literal(LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksContent),
|
||||
content: z.object({
|
||||
content: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(z.any()),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
json: z.any(),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
const loyaltyPageBlockItem = z.discriminatedUnion("__typename", [
|
||||
loyaltyPageBlockCardGrid,
|
||||
loyaltyPageDynamicContent,
|
||||
loyaltyPageBlockTextContent,
|
||||
])
|
||||
|
||||
const loyaltyPageSidebarTextContent = z.object({
|
||||
__typename: z.literal(SidebarTypenameEnum.LoyaltyPageSidebarContent),
|
||||
content: z.object({
|
||||
content: z.object({
|
||||
embedded_itemsConnection: z.object({
|
||||
edges: z.array(z.any()),
|
||||
totalCount: z.number(),
|
||||
}),
|
||||
json: z.any(),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
|
||||
const loyaltyPageJoinLoyaltyContact = z.object({
|
||||
__typename: z.literal(
|
||||
SidebarTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContact
|
||||
),
|
||||
join_loyalty_contact: z.object({
|
||||
title: z.string().optional(),
|
||||
preamble: z.string().optional(),
|
||||
contact: z.array(
|
||||
z.object({
|
||||
__typename: z.literal(
|
||||
JoinLoyaltyContactTypenameEnum.LoyaltyPageSidebarJoinLoyaltyContactBlockContactContact
|
||||
),
|
||||
contact: z.object({
|
||||
display_text: z.string().optional(),
|
||||
|
||||
contact_field: z.string(),
|
||||
}),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
const loyaltyPageSidebarItem = z.discriminatedUnion("__typename", [
|
||||
loyaltyPageSidebarTextContent,
|
||||
loyaltyPageJoinLoyaltyContact,
|
||||
])
|
||||
|
||||
export const validateLoyaltyPageSchema = z.object({
|
||||
all_loyalty_page: z.object({
|
||||
items: z.array(
|
||||
z.object({
|
||||
title: z.string(),
|
||||
blocks: z.array(loyaltyPageBlockItem),
|
||||
sidebar: z.array(loyaltyPageSidebarItem),
|
||||
})
|
||||
),
|
||||
}),
|
||||
})
|
||||
|
||||
// Block types
|
||||
type CardGridRaw = z.infer<typeof loyaltyPageBlockCardGrid>
|
||||
|
||||
export type CardGridCard = Omit<
|
||||
CardGridRaw["card_grid"]["cards"][number],
|
||||
"referenceConnection"
|
||||
> & {
|
||||
link:
|
||||
| {
|
||||
href: string
|
||||
title: string
|
||||
}
|
||||
| undefined
|
||||
}
|
||||
|
||||
export type CardGrid = Omit<CardGridRaw, "card_grid"> & {
|
||||
card_grid: Omit<CardGridRaw["card_grid"], "cards"> & {
|
||||
cards: CardGridCard[]
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
type BlockContentRaw = z.infer<typeof loyaltyPageBlockTextContent>
|
||||
|
||||
export interface RteBlockContent extends BlockContentRaw {
|
||||
content: {
|
||||
content: {
|
||||
json: RTEDocument
|
||||
embedded_itemsConnection: Edges<Embeds>
|
||||
}
|
||||
}
|
||||
}
|
||||
export type Block = CardGrid | RteBlockContent | DynamicContent
|
||||
|
||||
// Sidebar block types
|
||||
type SidebarContentRaw = z.infer<typeof loyaltyPageSidebarTextContent>
|
||||
|
||||
export type RteSidebarContent = Omit<SidebarContentRaw, "content"> & {
|
||||
content: {
|
||||
content: {
|
||||
json: RTEDocument
|
||||
embedded_itemsConnection: Edges<Embeds>
|
||||
}
|
||||
}
|
||||
}
|
||||
export type JoinLoyaltyContact = z.infer<typeof loyaltyPageJoinLoyaltyContact>
|
||||
export type Sidebar = JoinLoyaltyContact | RteSidebarContent
|
||||
|
||||
type LoyaltyPageDataRaw = z.infer<typeof validateLoyaltyPageSchema>
|
||||
|
||||
type LoyaltyPageRaw = LoyaltyPageDataRaw["all_loyalty_page"]["items"][0]
|
||||
|
||||
export type LoyaltyPage = Omit<LoyaltyPageRaw, "blocks" | "sidebar"> & {
|
||||
blocks: Block[]
|
||||
sidebar: Sidebar[]
|
||||
}
|
||||
@@ -1,33 +1,132 @@
|
||||
import { z } from "zod"
|
||||
|
||||
import GetLoyaltyPage from "@/lib/graphql/Query/LoyaltyPage.graphql"
|
||||
import { request } from "@/lib/graphql/request"
|
||||
import { badRequestError } from "@/server/errors/trpc"
|
||||
import { publicProcedure, router } from "@/server/trpc"
|
||||
import { request } from "@/lib/graphql/request"
|
||||
import { Lang } from "@/constants/languages"
|
||||
|
||||
import GetLoyaltyPage from "@/lib/graphql/Query/LoyaltyPage.graphql"
|
||||
import { getLoyaltyPageInput } from "./input"
|
||||
import { type LoyaltyPage, validateLoyaltyPageSchema } from "./output"
|
||||
|
||||
import type { GetLoyaltyPageData } from "@/types/requests/loyaltyPage"
|
||||
import { Embeds } from "@/types/requests/embeds"
|
||||
import {
|
||||
LoyaltyBlocksTypenameEnum,
|
||||
SidebarTypenameEnum,
|
||||
} from "@/types/requests/loyaltyPage"
|
||||
import { Edges } from "@/types/requests/utils/edges"
|
||||
import { RTEDocument } from "@/types/rte/node"
|
||||
|
||||
export const loyaltyPageQueryRouter = router({
|
||||
get: publicProcedure
|
||||
.input(z.object({ uri: z.string(), lang: z.nativeEnum(Lang) }))
|
||||
.query(async ({ input }) => {
|
||||
const loyaltyPage = await request<GetLoyaltyPageData>(
|
||||
GetLoyaltyPage,
|
||||
{
|
||||
locale: input.lang,
|
||||
url: input.uri,
|
||||
},
|
||||
{
|
||||
tags: [`${input.uri}-${input.lang}`],
|
||||
}
|
||||
)
|
||||
get: publicProcedure.input(getLoyaltyPageInput).query(async ({ input }) => {
|
||||
try {
|
||||
const loyaltyPageRes = await request<LoyaltyPage>(GetLoyaltyPage, {
|
||||
locale: input.locale,
|
||||
url: input.href,
|
||||
})
|
||||
|
||||
if (loyaltyPage.data && loyaltyPage.data.all_loyalty_page.items.length) {
|
||||
return loyaltyPage.data.all_loyalty_page.items[0]
|
||||
if (!loyaltyPageRes.data) {
|
||||
throw badRequestError()
|
||||
}
|
||||
|
||||
const validatedLoyaltyPage = validateLoyaltyPageSchema.safeParse(
|
||||
loyaltyPageRes.data
|
||||
)
|
||||
|
||||
if (!validatedLoyaltyPage.success) {
|
||||
throw badRequestError()
|
||||
}
|
||||
|
||||
const sidebar =
|
||||
validatedLoyaltyPage.data.all_loyalty_page.items[0].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
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const blocks =
|
||||
validatedLoyaltyPage.data.all_loyalty_page.items[0].blocks.map(
|
||||
(block) => {
|
||||
switch (block.__typename) {
|
||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksCardGrid:
|
||||
return {
|
||||
...block,
|
||||
card_grid: {
|
||||
...block.card_grid,
|
||||
cards: block.card_grid.cards.map((card) => {
|
||||
return {
|
||||
...card,
|
||||
link:
|
||||
card.referenceConnection.totalCount > 0
|
||||
? {
|
||||
href: card.referenceConnection.edges[0].node
|
||||
.url,
|
||||
title:
|
||||
card.referenceConnection.edges[0].node.title,
|
||||
}
|
||||
: undefined,
|
||||
}
|
||||
}),
|
||||
},
|
||||
}
|
||||
case LoyaltyBlocksTypenameEnum.LoyaltyPageBlocksDynamicContent:
|
||||
return {
|
||||
...block,
|
||||
dynamic_content: {
|
||||
...block.dynamic_content,
|
||||
link:
|
||||
block.dynamic_content.link.pageConnection.totalCount > 0
|
||||
? {
|
||||
text: block.dynamic_content.link.text,
|
||||
href: block.dynamic_content.link.pageConnection
|
||||
.edges[0].node.url,
|
||||
title:
|
||||
block.dynamic_content.link.pageConnection.edges[0]
|
||||
.node.title,
|
||||
}
|
||||
: 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>,
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
return block
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const loyaltyPage = {
|
||||
...validatedLoyaltyPage.data.all_loyalty_page.items[0],
|
||||
blocks,
|
||||
sidebar,
|
||||
} as LoyaltyPage
|
||||
|
||||
return loyaltyPage
|
||||
} catch (error) {
|
||||
console.info(`Get Loyalty Page Error`)
|
||||
console.error(error)
|
||||
throw badRequestError()
|
||||
}),
|
||||
}
|
||||
}),
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user