Files
web/packages/trpc/lib/routers/contentstack/destinationCityPage/output.ts
Linus Flood 5fc93472f4 Merged in feat/rework-contentstack (pull request #3493)
Feat(SW-3708): refactor contentstack fetching (removing all refs) and cache invalidation

* Remove all REFS

* Revalidate correct language

* PR fixes

* PR fixes

* Throw when errors from contentstack api


Approved-by: Joakim Jäderberg
2026-01-27 12:38:36 +00:00

220 lines
6.3 KiB
TypeScript

import { z } from "zod"
import { transformedImageVaultAssetSchema } from "@scandic-hotels/common/utils/imageVault"
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
import { DestinationCityPageEnum } from "../../../types/destinationCityPage"
import { isDefined } from "../../../utils"
import { discriminatedUnionArray } from "../../../utils/discriminatedUnion"
import { accordionSchema } from "../schemas/blocks/accordion"
import { contentSchema } from "../schemas/blocks/content"
import { transformedDestinationFiltersSchema } from "../schemas/destinationFilters"
import { mapLocationSchema } from "../schemas/mapLocation"
import { linkUnionSchema, transformPageLink } from "../schemas/pageLinks"
import { systemSchema } from "../schemas/system"
import type { ImageVaultAsset } from "@scandic-hotels/common/utils/imageVault"
export const destinationCityPageDestinationSettingsSchema = z
.object({
city_denmark: z.string().optional().nullable(),
city_finland: z.string().optional().nullable(),
city_germany: z.string().optional().nullable(),
city_poland: z.string().optional().nullable(),
city_norway: z.string().optional().nullable(),
city_sweden: z.string().optional().nullable(),
location: mapLocationSchema,
})
.transform(
({
city_denmark,
city_finland,
city_germany,
city_norway,
city_poland,
city_sweden,
location,
}) => {
return {
city:
city_denmark ||
city_finland ||
city_germany ||
city_poland ||
city_norway ||
city_sweden,
location,
}
}
)
export const destinationCityListDataSchema = z
.object({
all_destination_city_page: z.object({
items: z.array(
z
.object({
heading: z.string(),
destination_settings: destinationCityPageDestinationSettingsSchema,
sort_order: z.number().nullable(),
preamble: z.string(),
experiences: z
.object({
destination_experiences: z.array(z.string()),
})
.transform(
({ destination_experiences }) => destination_experiences
)
.nullish(),
images: z
.array(z.object({ image: transformedImageVaultAssetSchema }))
.transform((images) =>
images
.map((image) => image.image)
.filter((image): image is ImageVaultAsset => !!image)
)
.nullish(),
url: z.string(),
system: systemSchema,
})
.transform((data) => {
return {
...data,
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
}
})
),
}),
})
.transform(
({ all_destination_city_page }) => all_destination_city_page.items?.[0]
)
export const destinationCityPageContent = z
.object({
__typename: z.literal(DestinationCityPageEnum.ContentStack.blocks.Content),
})
.merge(contentSchema)
export const destinationCityPageAccordion = z
.object({
__typename: z.literal(
DestinationCityPageEnum.ContentStack.blocks.Accordion
),
})
.merge(accordionSchema)
export const blocksSchema = z.discriminatedUnion("__typename", [
destinationCityPageAccordion,
destinationCityPageContent,
])
export const destinationCityPageSchema = z.object({
destination_city_page: z.object({
title: z.string(),
destination_settings: destinationCityPageDestinationSettingsSchema,
heading: z.string(),
preamble: z.string(),
experiences: z
.object({
destination_experiences: z.array(z.string()),
})
.nullish()
.transform((experiences) => experiences?.destination_experiences ?? []),
images: z
.array(z.object({ image: transformedImageVaultAssetSchema }))
.transform((images) =>
images
.map((image) => image.image)
.filter((image): image is ImageVaultAsset => !!image)
)
.nullish(),
has_sidepeek: z.boolean().default(false),
sidepeek_button_text: z.string().nullish().default(""),
sidepeek_content: z
.object({
heading: z.string(),
content: z
.object({
json: z.any(),
embedded_itemsConnection: z.object({
edges: z.array(
z.object({
node: linkUnionSchema.transform((data) => {
const link = transformPageLink(data)
if (link) {
return link
}
return data
}),
})
),
}),
})
.nullish(),
})
.nullish(),
blocks: discriminatedUnionArray(blocksSchema.options).nullable(),
seo_filters: transformedDestinationFiltersSchema,
system: systemSchema.merge(
z.object({
created_at: z.string(),
updated_at: z.string(),
})
),
}),
trackingProps: z.object({
url: z.string(),
}),
})
export const cityPageCountSchema = z
.object({
all_destination_city_page: z.object({
total: z.number(),
}),
})
.transform(({ all_destination_city_page }) => all_destination_city_page.total)
export const cityPageUrlsSchema = z
.object({
all_destination_city_page: z.object({
items: z
.array(
z
.object({
url: z.string().nullish(),
destination_settings:
destinationCityPageDestinationSettingsSchema,
system: systemSchema,
})
.transform((data) => {
if (!data.destination_settings.city || !data.url) {
return null
}
return {
city: data.destination_settings.city,
url: removeMultipleSlashes(
`/${data.system.locale}/${data.url}`
),
}
})
)
.transform((data) => {
return data.filter(isDefined)
}),
}),
})
.transform(({ all_destination_city_page }) => all_destination_city_page.items)
export const batchedCityPageUrlsSchema = z
.array(
z.object({
data: cityPageUrlsSchema,
})
)
.transform((allItems) => {
return allItems.flatMap((item) => item.data)
})