import {z} from 'zod' export type BaseFilter = {has_transfer?: boolean | undefined, kind?: Array | undefined, meal_type?: Array | undefined, price_from?: number | undefined, price_to?: number | undefined, star_rating?: Array | undefined}; export type BaseGuestsGroup = {adults?: number | undefined, children?: Array | undefined}; export type BaseECLC = {time?: string | undefined}; export type BaseUpsells = {early_checkin?: BaseECLC | undefined, late_checkout?: BaseECLC | undefined, multiple_eclc?: boolean | undefined, only_eclc?: boolean | undefined}; export type B2bHPRequest = {availability_hash?: string | undefined, checkin?: string | undefined, checkout?: string | undefined, currency?: string | undefined, filter?: BaseFilter | undefined, guests?: Array | undefined, hid?: number | undefined, id?: string | undefined, language?: string | undefined, match_hash?: string | undefined, residency?: string | undefined, timeout?: number | undefined, upsells?: BaseUpsells | undefined}; export type CreateApiApiB2bV3SearchHpArgs = {body: B2bHPRequest}; export type CreateApiApiB2bV3SearchHpOptions = {baseUrl: string, BasicAuth?: {username: string, password: string} | undefined, fetch?: typeof fetch | undefined}; export const b2bHotelBarPriceData = z.object({currency: z.string().optional(), price: z.string().optional()}); export const baseRgExt = z.object({balcony: z.number().int().optional(), bathroom: z.number().int().optional(), bedding: z.number().int().optional(), bedrooms: z.number().int().optional(), capacity: z.number().int().optional(), class: z.number().int().optional(), club: z.number().int().optional(), family: z.number().int().optional(), floor: z.number().int().optional(), quality: z.number().int().optional(), sex: z.number().int().optional(), view: z.number().int().optional()}); export const b2bRoomGroupsBarPriceData = z.object({currency: z.string().optional(), price: z.string().optional(), rg_ext: baseRgExt.optional()}); export const b2bBarPriceData = z.object({hotel: b2bHotelBarPriceData.optional(), room_groups: z.array(b2bRoomGroupsBarPriceData).optional()}); export const b2bBarRatePriceData = z.object({amount: z.string().optional(), currency_code: z.string().optional()}); export const baseDeposit = z.object({amount: z.string().optional(), currency_code: z.string().optional(), is_refundable: z.boolean().optional()}); export const baseLegalInfoHotel = z.object({address: z.string().optional(), name: z.string().optional(), state_registration_number: z.string().optional(), taxpayer_number: z.string().optional(), work_time: z.string().optional()}); export const baseLegalInfoProvider = z.object({address: z.string().optional(), name: z.string().optional(), state_registration_number: z.string().optional(), taxpayer_number: z.string().optional()}); export const baseLegalInfo = z.object({hotel: baseLegalInfoHotel.optional(), provider: baseLegalInfoProvider.optional()}); export const baseMealData = z.object({has_breakfast: z.boolean().optional(), no_child_meal: z.boolean().optional(), value: z.string().optional()}); export const baseNoShow = z.object({amount: z.string().optional(), currency_code: z.string().optional(), from_time: z.string().optional()}); export const b2bCommissionInfoItem = z.object({amount_commission: z.string().optional(), amount_gross: z.string().optional(), amount_net: z.string().optional()}); export const b2bCommissionInfo = z.object({charge: b2bCommissionInfoItem.optional(), show: b2bCommissionInfoItem.optional()}); export const b2bCancellationPolicy = z.object({amount_charge: z.string().optional(), amount_show: z.string().optional(), commission_info: b2bCommissionInfo.optional(), end_at: z.string().optional(), start_at: z.string().optional()}); export const b2bCancellationPenalty = z.object({free_cancellation_before: z.string().optional(), policies: z.array(b2bCancellationPolicy).optional()}); export const b2bECLCPerk = z.object({charge_price: z.string().optional(), commission_info: b2bCommissionInfo.optional(), is_requested: z.boolean().optional(), show_price: z.string().optional(), time: z.string().optional()}); export const b2bPerks = z.object({early_checkin: z.array(b2bECLCPerk).optional(), late_checkout: z.array(b2bECLCPerk).optional()}); export const b2bRecommendedPrice = z.object({amount: z.string().optional(), currency_code: z.string().optional(), show_amount: z.string().optional(), show_currency_code: z.string().optional()}); export const baseTax = z.object({amount: z.string().optional(), currency_code: z.string().optional(), included_by_supplier: z.boolean().optional(), name: z.string().optional()}); export const baseTaxData = z.object({taxes: z.array(baseTax).optional()}); export const b2bVATData = z.object({amount: z.string().optional(), applied: z.boolean().optional(), currency_code: z.string().optional(), included: z.boolean().optional(), value: z.string().optional()}); export const b2bPaymentType = z.object({amount: z.string().optional(), by: z.string().optional(), cancellation_penalties: b2bCancellationPenalty.optional(), commission_info: b2bCommissionInfo.optional(), currency_code: z.string().optional(), is_need_credit_card_data: z.boolean().optional(), is_need_cvc: z.boolean().optional(), perks: b2bPerks.optional(), recommended_price: b2bRecommendedPrice.optional(), show_amount: z.string().optional(), show_currency_code: z.string().optional(), tax_data: baseTaxData.optional(), type: z.string().optional(), vat_data: b2bVATData.optional()}); export const b2bPaymentOptions = z.object({payment_types: z.array(b2bPaymentType).optional()}); export const b2bPrepaymentPolicy = z.object({amount: z.string().optional(), currency_code: z.string().optional(), end_at: z.string().optional(), start_at: z.string().optional()}); export const b2bPrepaymentGroup = z.object({policies: z.array(b2bPrepaymentPolicy).optional()}); export const b2bPrepayment = z.object({groups: z.array(b2bPrepaymentGroup).optional(), type: z.string().optional()}); export const baseBedGroup = z.object({bed: z.string().optional(), count: z.number().int().optional()}); export const baseRoomDataTrans = z.object({bathroom: z.string().optional(), bedding_type: z.string().optional(), beds: z.array(baseBedGroup).optional(), main_name: z.string().optional(), main_room_type: z.string().optional(), misc_room_type: z.string().optional()}); export const baseRoomNameInfo = z.object({original_rate_name: z.string().optional()}); export const b2bSellPriceLimits = z.object({max_price: z.string().optional(), min_price: z.string().optional()}); export const b2bRate = z.object({allotment: z.number().int().optional(), amenities_data: z.array(z.string()).optional(), any_residency: z.boolean().optional(), bar_rate_price_data: b2bBarRatePriceData.optional(), book_hash: z.string().optional(), daily_prices: z.array(z.string()).optional(), deposit: baseDeposit.optional(), is_package: z.boolean().optional(), legal_info: baseLegalInfo.optional(), match_hash: z.string().optional(), meal: z.string().optional(), meal_data: baseMealData.optional(), no_show: baseNoShow.optional(), payment_options: b2bPaymentOptions.optional(), prepayment: b2bPrepayment.optional(), rg_ext: baseRgExt.optional(), room_data_trans: baseRoomDataTrans.optional(), room_name: z.string().optional(), room_name_info: baseRoomNameInfo.optional(), search_hash: z.string().optional(), sell_price_limits: b2bSellPriceLimits.optional(), serp_filters: z.array(z.string()).optional()}); export const b2bHotel = z.object({bar_price_data: b2bBarPriceData.optional(), hid: z.number().int().optional(), id: z.string().optional(), rates: z.array(b2bRate).optional()}); export const b2bResult = z.object({hotels: z.array(b2bHotel).optional(), total_hotels: z.number().int().optional()}); export const v3DebugEndpoint = z.object({endpoint: z.string().optional(), is_active: z.boolean().optional(), is_limited: z.boolean().optional(), remaining: z.number().int().optional(), requests_number: z.number().int().optional(), reset: z.string().optional(), seconds_number: z.number().int().optional()}); export const v3Debug = z.object({api_endpoint: v3DebugEndpoint.optional(), api_key_id: z.number().int().optional(), key_id: z.number().int().optional(), method: z.string().optional(), real_ip: z.string().optional(), request: z.array(z.number().int()).optional(), request_id: z.string().optional(), utcnow: z.string().optional(), validation_error: z.string().optional()}); export const createApiApiB2bV3SearchHpResponse = z.object({data: b2bResult.optional(), debug: v3Debug.optional(), error: z.string().optional(), status: z.string().optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Hotelpage (b2b) * * POST /api/b2b/v3/search/hp */ export const createApiApiB2bV3SearchHp = async (args: CreateApiApiB2bV3SearchHpArgs, options: CreateApiApiB2bV3SearchHpOptions) => { const {baseUrl, fetch: fetchFn = fetch, BasicAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (BasicAuth !== undefined) headers.set('authorization', `Basic ${btoa(`${BasicAuth.username}:${BasicAuth.password}`)}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/b2b/v3/search/hp${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(createApiApiB2bV3SearchHpResponse, await res.json()) };