fix(BOOK-453): avoid linkConnection invalid * fix(BOOK-453): avoid linkConnection invalid * test * test * test * Merge master
318 lines
9.3 KiB
TypeScript
318 lines
9.3 KiB
TypeScript
import { z } from "zod"
|
|
|
|
import { removeMultipleSlashes } from "@scandic-hotels/common/utils/url"
|
|
import { nullableStringValidator } from "@scandic-hotels/common/utils/zod/stringValidator"
|
|
|
|
import { ContentEnum } from "../../../types/content"
|
|
import { safeUnion } from "../base/utils"
|
|
import { systemSchema } from "./system"
|
|
|
|
export const pageLinkSchema = z.object({
|
|
system: systemSchema,
|
|
title: z.string().optional().default(""),
|
|
url: z.string().optional().default(""),
|
|
})
|
|
|
|
export const accountPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.AccountPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const accountPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.AccountPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const extendedPageLinkSchema = pageLinkSchema.merge(
|
|
z.object({
|
|
web: z
|
|
.object({
|
|
original_url: z.string().optional().default(""),
|
|
})
|
|
.default({ original_url: "" }),
|
|
})
|
|
)
|
|
|
|
export const campaignOverviewPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.CampaignOverviewPage),
|
|
})
|
|
.merge(extendedPageLinkSchema)
|
|
|
|
export const campaignOverviewPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.CampaignOverviewPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const collectionPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.CollectionPage),
|
|
})
|
|
.merge(extendedPageLinkSchema)
|
|
|
|
export const collectionPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.CollectionPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const contentPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.ContentPage),
|
|
})
|
|
.merge(extendedPageLinkSchema)
|
|
|
|
export const contentPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.ContentPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const destinationCityPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.DestinationCityPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const destinationCityPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.DestinationCityPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const campaignPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.CampaignPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const campaignPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.CampaignPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const destinationCountryPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.DestinationCountryPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const destinationCountryPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.DestinationCountryPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const destinationOverviewPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.DestinationOverviewPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const destinationOverviewPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.DestinationOverviewPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const hotelPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.HotelPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const hotelPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.HotelPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const loyaltyPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.LoyaltyPage),
|
|
})
|
|
.merge(extendedPageLinkSchema)
|
|
|
|
export const loyaltyPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.LoyaltyPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const startPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.StartPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const startPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.StartPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const promoCampaignPageSchema = z
|
|
.object({
|
|
__typename: z.literal(ContentEnum.blocks.PromoCampaignPage),
|
|
})
|
|
.merge(pageLinkSchema)
|
|
|
|
export const promoCampaignPageRefSchema = z.object({
|
|
__typename: z.literal(ContentEnum.blocks.PromoCampaignPage),
|
|
system: systemSchema.nullable(),
|
|
})
|
|
|
|
export const rawLinkUnionSchema = z.discriminatedUnion("__typename", [
|
|
accountPageSchema,
|
|
campaignOverviewPageSchema,
|
|
campaignPageSchema,
|
|
collectionPageSchema,
|
|
contentPageSchema,
|
|
destinationCityPageSchema,
|
|
destinationCountryPageSchema,
|
|
destinationOverviewPageSchema,
|
|
hotelPageSchema,
|
|
loyaltyPageSchema,
|
|
startPageSchema,
|
|
promoCampaignPageSchema,
|
|
])
|
|
|
|
export const linkUnionSchema = safeUnion(rawLinkUnionSchema)
|
|
type Data =
|
|
| z.output<typeof accountPageSchema>
|
|
| z.output<typeof campaignOverviewPageSchema>
|
|
| z.output<typeof campaignPageSchema>
|
|
| z.output<typeof collectionPageSchema>
|
|
| z.output<typeof contentPageSchema>
|
|
| z.output<typeof destinationCityPageSchema>
|
|
| z.output<typeof destinationCountryPageSchema>
|
|
| z.output<typeof destinationOverviewPageSchema>
|
|
| z.output<typeof hotelPageSchema>
|
|
| z.output<typeof loyaltyPageSchema>
|
|
| z.output<typeof startPageSchema>
|
|
| z.output<typeof promoCampaignPageSchema>
|
|
| Object
|
|
|
|
export function transformPageLink(data: Data) {
|
|
if (data && "__typename" in data) {
|
|
switch (data.__typename) {
|
|
case ContentEnum.blocks.AccountPage:
|
|
case ContentEnum.blocks.CampaignOverviewPage:
|
|
case ContentEnum.blocks.CampaignPage:
|
|
case ContentEnum.blocks.DestinationCityPage:
|
|
case ContentEnum.blocks.DestinationCountryPage:
|
|
case ContentEnum.blocks.DestinationOverviewPage:
|
|
case ContentEnum.blocks.HotelPage:
|
|
case ContentEnum.blocks.StartPage:
|
|
case ContentEnum.blocks.PromoCampaignPage:
|
|
return {
|
|
__typename: data.__typename,
|
|
system: data.system,
|
|
title: data.title,
|
|
url: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
|
}
|
|
case ContentEnum.blocks.CollectionPage:
|
|
case ContentEnum.blocks.ContentPage:
|
|
case ContentEnum.blocks.LoyaltyPage:
|
|
// TODO: Once all links use this transform
|
|
// `web` can be removed and not to be worried
|
|
// about throughout the application
|
|
return {
|
|
__typename: data.__typename,
|
|
system: data.system,
|
|
title: data.title,
|
|
url: data.web?.original_url
|
|
? data.web.original_url
|
|
: removeMultipleSlashes(`/${data.system.locale}/${data.url}`),
|
|
web: data.web,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export const internalOrExternalLinkSchema = z
|
|
.object({
|
|
is_contentstack_link: z.boolean().nullish(),
|
|
external_link: z
|
|
.object({
|
|
href: nullableStringValidator,
|
|
title: z.string().nullish(),
|
|
})
|
|
.nullish(),
|
|
title: nullableStringValidator,
|
|
linkConnection: z.object({
|
|
edges: z.array(
|
|
z.object({
|
|
node: linkUnionSchema.transform((data) => {
|
|
const link = transformPageLink(data)
|
|
if (link) {
|
|
return link
|
|
}
|
|
return data
|
|
}),
|
|
})
|
|
),
|
|
}),
|
|
})
|
|
.transform(
|
|
({ is_contentstack_link, external_link, linkConnection, title }) => {
|
|
if (is_contentstack_link !== false && linkConnection.edges.length) {
|
|
const linkRef = linkConnection.edges[0].node
|
|
return {
|
|
title: title || linkRef.title,
|
|
url: linkRef.url,
|
|
}
|
|
} else if (is_contentstack_link === false && external_link?.href) {
|
|
return {
|
|
title: title || external_link.title || "",
|
|
url: external_link.href,
|
|
}
|
|
}
|
|
}
|
|
)
|
|
|
|
export const rawLinkRefsUnionSchema = z.discriminatedUnion("__typename", [
|
|
accountPageRefSchema,
|
|
campaignOverviewPageRefSchema,
|
|
campaignPageRefSchema,
|
|
collectionPageRefSchema,
|
|
contentPageRefSchema,
|
|
destinationCityPageRefSchema,
|
|
destinationCountryPageRefSchema,
|
|
destinationOverviewPageRefSchema,
|
|
hotelPageRefSchema,
|
|
loyaltyPageRefSchema,
|
|
startPageRefSchema,
|
|
promoCampaignPageRefSchema,
|
|
])
|
|
|
|
export const linkRefsUnionSchema = safeUnion(rawLinkRefsUnionSchema)
|
|
|
|
type RefData =
|
|
| z.output<typeof accountPageRefSchema>
|
|
| z.output<typeof campaignOverviewPageRefSchema>
|
|
| z.output<typeof campaignPageRefSchema>
|
|
| z.output<typeof collectionPageRefSchema>
|
|
| z.output<typeof contentPageRefSchema>
|
|
| z.output<typeof destinationCityPageRefSchema>
|
|
| z.output<typeof destinationCountryPageRefSchema>
|
|
| z.output<typeof destinationOverviewPageRefSchema>
|
|
| z.output<typeof hotelPageRefSchema>
|
|
| z.output<typeof loyaltyPageRefSchema>
|
|
| z.output<typeof startPageRefSchema>
|
|
| z.output<typeof promoCampaignPageRefSchema>
|
|
| Object
|
|
|
|
export function transformPageLinkRef(data: RefData) {
|
|
if (data && "__typename" in data) {
|
|
switch (data.__typename) {
|
|
case ContentEnum.blocks.AccountPage:
|
|
case ContentEnum.blocks.CampaignOverviewPage:
|
|
case ContentEnum.blocks.CampaignPage:
|
|
case ContentEnum.blocks.CollectionPage:
|
|
case ContentEnum.blocks.ContentPage:
|
|
case ContentEnum.blocks.DestinationCityPage:
|
|
case ContentEnum.blocks.DestinationCountryPage:
|
|
case ContentEnum.blocks.DestinationOverviewPage:
|
|
case ContentEnum.blocks.HotelPage:
|
|
case ContentEnum.blocks.LoyaltyPage:
|
|
case ContentEnum.blocks.StartPage:
|
|
case ContentEnum.blocks.PromoCampaignPage:
|
|
return data.system
|
|
}
|
|
}
|
|
}
|