Merged in fix/hotel-page-validation (pull request #675)
Fix validation on hotelData Approved-by: Simon.Emanuelsson
This commit is contained in:
@@ -2,12 +2,11 @@ import { z } from "zod"
|
|||||||
|
|
||||||
import { toLang } from "@/server/utils"
|
import { toLang } from "@/server/utils"
|
||||||
|
|
||||||
|
import { imageMetaDataSchema, imageSizesSchema } from "./schemas/image"
|
||||||
|
import { roomSchema } from "./schemas/room"
|
||||||
import { getPoiGroupByCategoryName } from "./utils"
|
import { getPoiGroupByCategoryName } from "./utils"
|
||||||
|
|
||||||
import {
|
import { PointOfInterestCategoryNameEnum } from "@/types/hotel"
|
||||||
PointOfInterestCategoryNameEnum,
|
|
||||||
PointOfInterestGroupEnum,
|
|
||||||
} from "@/types/hotel"
|
|
||||||
|
|
||||||
const ratingsSchema = z
|
const ratingsSchema = z
|
||||||
.object({
|
.object({
|
||||||
@@ -121,20 +120,6 @@ const locationSchema = z.object({
|
|||||||
longitude: z.number(),
|
longitude: z.number(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const imageMetaDataSchema = z.object({
|
|
||||||
title: z.string(),
|
|
||||||
altText: z.string(),
|
|
||||||
altText_En: z.string(),
|
|
||||||
copyRight: z.string(),
|
|
||||||
})
|
|
||||||
|
|
||||||
const imageSizesSchema = z.object({
|
|
||||||
tiny: z.string(),
|
|
||||||
small: z.string(),
|
|
||||||
medium: z.string(),
|
|
||||||
large: z.string(),
|
|
||||||
})
|
|
||||||
|
|
||||||
const hotelContentSchema = z.object({
|
const hotelContentSchema = z.object({
|
||||||
images: z.object({
|
images: z.object({
|
||||||
metaData: imageMetaDataSchema,
|
metaData: imageMetaDataSchema,
|
||||||
@@ -230,7 +215,6 @@ const rewardNightSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const poiGroups = z.nativeEnum(PointOfInterestGroupEnum)
|
|
||||||
const poiCategoryNames = z.nativeEnum(PointOfInterestCategoryNameEnum)
|
const poiCategoryNames = z.nativeEnum(PointOfInterestCategoryNameEnum)
|
||||||
|
|
||||||
export const pointOfInterestSchema = z
|
export const pointOfInterestSchema = z
|
||||||
@@ -369,96 +353,6 @@ const relationshipsSchema = z.object({
|
|||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
|
||||||
const roomContentSchema = z.object({
|
|
||||||
images: z.array(
|
|
||||||
z.object({
|
|
||||||
metaData: imageMetaDataSchema,
|
|
||||||
imageSizes: imageSizesSchema,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
texts: z.object({
|
|
||||||
descriptions: z.object({
|
|
||||||
short: z.string(),
|
|
||||||
medium: z.string(),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
|
|
||||||
const roomTypesSchema = z.object({
|
|
||||||
name: z.string(),
|
|
||||||
description: z.string(),
|
|
||||||
code: z.string(),
|
|
||||||
roomCount: z.number(),
|
|
||||||
mainBed: z.object({
|
|
||||||
type: z.string(),
|
|
||||||
description: z.string(),
|
|
||||||
widthRange: z.object({
|
|
||||||
min: z.number(),
|
|
||||||
max: z.number(),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
fixedExtraBed: z.object({
|
|
||||||
type: z.string(),
|
|
||||||
description: z.string().optional(),
|
|
||||||
widthRange: z.object({
|
|
||||||
min: z.number(),
|
|
||||||
max: z.number(),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
roomSize: z.object({
|
|
||||||
min: z.number(),
|
|
||||||
max: z.number(),
|
|
||||||
}),
|
|
||||||
occupancy: z.object({
|
|
||||||
total: z.number(),
|
|
||||||
adults: z.number(),
|
|
||||||
children: z.number(),
|
|
||||||
}),
|
|
||||||
isLackingCribs: z.boolean(),
|
|
||||||
isLackingExtraBeds: z.boolean(),
|
|
||||||
})
|
|
||||||
|
|
||||||
const roomFacilitiesSchema = z.object({
|
|
||||||
availableInAllRooms: z.boolean(),
|
|
||||||
name: z.string(),
|
|
||||||
isUniqueSellingPoint: z.boolean(),
|
|
||||||
sortOrder: z.number(),
|
|
||||||
})
|
|
||||||
|
|
||||||
export const roomSchema = z
|
|
||||||
.object({
|
|
||||||
attributes: z.object({
|
|
||||||
name: z.string(),
|
|
||||||
sortOrder: z.number(),
|
|
||||||
content: roomContentSchema,
|
|
||||||
roomTypes: z.array(roomTypesSchema),
|
|
||||||
roomFacilities: z.array(roomFacilitiesSchema),
|
|
||||||
occupancy: z.object({
|
|
||||||
total: z.number(),
|
|
||||||
adults: z.number(),
|
|
||||||
children: z.number(),
|
|
||||||
}),
|
|
||||||
roomSize: z.object({
|
|
||||||
min: z.number(),
|
|
||||||
max: z.number(),
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
id: z.string(),
|
|
||||||
type: z.enum(["roomcategories"]),
|
|
||||||
})
|
|
||||||
.transform((data) => {
|
|
||||||
return {
|
|
||||||
descriptions: data.attributes.content.texts.descriptions,
|
|
||||||
id: data.id,
|
|
||||||
images: data.attributes.content.images,
|
|
||||||
name: data.attributes.name,
|
|
||||||
occupancy: data.attributes.occupancy,
|
|
||||||
roomSize: data.attributes.roomSize,
|
|
||||||
sortOrder: data.attributes.sortOrder,
|
|
||||||
type: data.type,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const merchantInformationSchema = z.object({
|
const merchantInformationSchema = z.object({
|
||||||
webMerchantId: z.string(),
|
webMerchantId: z.string(),
|
||||||
cards: z.record(z.string(), z.boolean()).transform((val) => {
|
cards: z.record(z.string(), z.boolean()).transform((val) => {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import {
|
|||||||
getHotelsAvailabilitySchema,
|
getHotelsAvailabilitySchema,
|
||||||
getRatesSchema,
|
getRatesSchema,
|
||||||
getRoomsAvailabilitySchema,
|
getRoomsAvailabilitySchema,
|
||||||
roomSchema,
|
|
||||||
} from "./output"
|
} from "./output"
|
||||||
import tempRatesData from "./tempRatesData.json"
|
import tempRatesData from "./tempRatesData.json"
|
||||||
import {
|
import {
|
||||||
@@ -190,35 +189,7 @@ export const hotelQueryRouter = router({
|
|||||||
const images = extractHotelImages(hotelAttributes)
|
const images = extractHotelImages(hotelAttributes)
|
||||||
|
|
||||||
const roomCategories = included
|
const roomCategories = included
|
||||||
? included
|
? included.filter((item) => item.type === "roomcategories")
|
||||||
.filter((item) => item.type === "roomcategories")
|
|
||||||
.map((roomCategory) => {
|
|
||||||
const validatedRoom = roomSchema.safeParse(roomCategory)
|
|
||||||
if (!validatedRoom.success) {
|
|
||||||
getHotelFailCounter.add(1, {
|
|
||||||
hotelId,
|
|
||||||
lang,
|
|
||||||
include,
|
|
||||||
error_type: "validation_error",
|
|
||||||
error: JSON.stringify(
|
|
||||||
validatedRoom.error.issues.map(({ code, message }) => ({
|
|
||||||
code,
|
|
||||||
message,
|
|
||||||
}))
|
|
||||||
),
|
|
||||||
})
|
|
||||||
console.error(
|
|
||||||
"api.hotels.hotel validation error",
|
|
||||||
JSON.stringify({
|
|
||||||
query: { hotelId, params },
|
|
||||||
error: validatedRoom.error,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
throw badRequestError()
|
|
||||||
}
|
|
||||||
|
|
||||||
return validatedRoom.data
|
|
||||||
})
|
|
||||||
: []
|
: []
|
||||||
|
|
||||||
const activities = contentstackData?.content
|
const activities = contentstackData?.content
|
||||||
|
|||||||
15
server/routers/hotels/schemas/image.ts
Normal file
15
server/routers/hotels/schemas/image.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
export const imageSizesSchema = z.object({
|
||||||
|
tiny: z.string(),
|
||||||
|
small: z.string(),
|
||||||
|
medium: z.string(),
|
||||||
|
large: z.string(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const imageMetaDataSchema = z.object({
|
||||||
|
title: z.string(),
|
||||||
|
altText: z.string(),
|
||||||
|
altText_En: z.string(),
|
||||||
|
copyRight: z.string(),
|
||||||
|
})
|
||||||
93
server/routers/hotels/schemas/room.ts
Normal file
93
server/routers/hotels/schemas/room.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { z } from "zod"
|
||||||
|
|
||||||
|
import { imageMetaDataSchema, imageSizesSchema } from "./image"
|
||||||
|
|
||||||
|
const roomContentSchema = z.object({
|
||||||
|
images: z.array(
|
||||||
|
z.object({
|
||||||
|
metaData: imageMetaDataSchema,
|
||||||
|
imageSizes: imageSizesSchema,
|
||||||
|
})
|
||||||
|
),
|
||||||
|
texts: z.object({
|
||||||
|
descriptions: z.object({
|
||||||
|
short: z.string(),
|
||||||
|
medium: z.string(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
|
||||||
|
const roomTypesSchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
code: z.string(),
|
||||||
|
roomCount: z.number(),
|
||||||
|
mainBed: z.object({
|
||||||
|
type: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
widthRange: z.object({
|
||||||
|
min: z.number(),
|
||||||
|
max: z.number(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
fixedExtraBed: z.object({
|
||||||
|
type: z.string(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
widthRange: z.object({
|
||||||
|
min: z.number(),
|
||||||
|
max: z.number(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
roomSize: z.object({
|
||||||
|
min: z.number(),
|
||||||
|
max: z.number(),
|
||||||
|
}),
|
||||||
|
occupancy: z.object({
|
||||||
|
total: z.number(),
|
||||||
|
adults: z.number(),
|
||||||
|
children: z.number(),
|
||||||
|
}),
|
||||||
|
isLackingCribs: z.boolean(),
|
||||||
|
isLackingExtraBeds: z.boolean(),
|
||||||
|
})
|
||||||
|
|
||||||
|
const roomFacilitiesSchema = z.object({
|
||||||
|
availableInAllRooms: z.boolean(),
|
||||||
|
name: z.string(),
|
||||||
|
isUniqueSellingPoint: z.boolean(),
|
||||||
|
sortOrder: z.number(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const roomSchema = z
|
||||||
|
.object({
|
||||||
|
attributes: z.object({
|
||||||
|
name: z.string(),
|
||||||
|
sortOrder: z.number(),
|
||||||
|
content: roomContentSchema,
|
||||||
|
roomTypes: z.array(roomTypesSchema),
|
||||||
|
roomFacilities: z.array(roomFacilitiesSchema),
|
||||||
|
occupancy: z.object({
|
||||||
|
total: z.number(),
|
||||||
|
adults: z.number(),
|
||||||
|
children: z.number(),
|
||||||
|
}),
|
||||||
|
roomSize: z.object({
|
||||||
|
min: z.number(),
|
||||||
|
max: z.number(),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
id: z.string(),
|
||||||
|
type: z.enum(["roomcategories"]),
|
||||||
|
})
|
||||||
|
.transform((data) => {
|
||||||
|
return {
|
||||||
|
descriptions: data.attributes.content.texts.descriptions,
|
||||||
|
id: data.id,
|
||||||
|
images: data.attributes.content.images,
|
||||||
|
name: data.attributes.name,
|
||||||
|
occupancy: data.attributes.occupancy,
|
||||||
|
roomSize: data.attributes.roomSize,
|
||||||
|
sortOrder: data.attributes.sortOrder,
|
||||||
|
type: data.type,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -5,8 +5,8 @@ import {
|
|||||||
getHotelDataSchema,
|
getHotelDataSchema,
|
||||||
parkingSchema,
|
parkingSchema,
|
||||||
pointOfInterestSchema,
|
pointOfInterestSchema,
|
||||||
roomSchema,
|
|
||||||
} from "@/server/routers/hotels/output"
|
} from "@/server/routers/hotels/output"
|
||||||
|
import { roomSchema } from "@/server/routers/hotels/schemas/room"
|
||||||
|
|
||||||
export type HotelData = z.infer<typeof getHotelDataSchema>
|
export type HotelData = z.infer<typeof getHotelDataSchema>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user