import {z} from 'zod' export type BookingFeesVariantCondition = {operator?: string | undefined, property?: string | undefined, value: unknown}; export type BookingFeesVariantModification = {modification_type?: string | undefined, target?: string | undefined, value?: number | undefined}; export type BookingFeesVariant = {block_discount_code?: boolean | undefined, conditions?: Array | undefined, description?: string | undefined, modifications?: Array | undefined, name?: string | undefined, priority?: number | undefined}; export type DeliveryLocation = {city?: string | undefined, country?: string | undefined, full_search_name_location?: string | undefined, lat?: number | undefined, lng?: number | undefined, search_name_location?: string | undefined, state?: string | undefined, street?: string | undefined, street_etc?: string | undefined, zip?: string | undefined}; export type Delivery = {comment?: string | undefined, estimated_distance?: number | undefined, location?: DeliveryLocation | undefined, stationary?: boolean | undefined}; export type ItemRequest = {count?: number | undefined, id?: number | undefined, name?: string | undefined, original_tax_rate_id?: number | undefined, price?: number | undefined}; export type Occupancy = {adults?: number | undefined, children?: number | undefined, infants?: number | undefined}; export type DBInterfaceMap = unknown; export type RVProfile = {length?: number | undefined, slideouts?: Array | undefined, type?: string | undefined}; export type Request = {booking_fees_variant?: BookingFeesVariant | undefined, bundle_id?: string | undefined, delivery?: Delivery | undefined, delivery_campground_id?: number | undefined, discount_code?: string | undefined, estimated_generator_hours?: number | undefined, estimated_miles?: number | undefined, external_campsite_id?: string | undefined, festival_friendly?: boolean | undefined, from?: string | undefined, from_time?: number | undefined, id?: string | undefined, imported?: boolean | undefined, include_coachnet?: boolean | undefined, include_linen_fee?: boolean | undefined, include_pet_fee?: boolean | undefined, insurance?: string | undefined, items?: Array | undefined, locale?: string | undefined, loyalty_rewards_eligible?: boolean | undefined, make?: string | undefined, model?: Array | undefined, occupancy?: Occupancy | undefined, omit_taxes?: boolean | undefined, only_price_breakdown?: boolean | undefined, pet_friendly?: boolean | undefined, pets?: number | undefined, prefer_cheapest_bundle?: boolean | undefined, presentment_currency?: string | undefined, rental_id?: number | undefined, renter_anon_id?: string | undefined, renter_id?: number | undefined, reserve?: boolean | undefined, roamly_weather_quote?: DBInterfaceMap | undefined, rv_profile?: RVProfile | undefined, services?: Array | undefined, sibling_quote_group_id?: number | undefined, smoking_allowed?: boolean | undefined, source?: string | undefined, tailgate_friendly?: boolean | undefined, to?: string | undefined, to_time?: number | undefined, towing_capacity?: number | undefined, towing_vehicle_make?: string | undefined, towing_vehicle_model?: string | undefined, towing_vehicle_year?: number | undefined, travelers?: number | undefined, trip_credits_disabled?: boolean | undefined, year_max?: number | undefined, year_min?: number | undefined}; export type CreateApiQuotesArgs = {body: Request}; export type CreateApiQuotesOptions = {baseUrl: string, Bearer?: string | undefined, fetch?: typeof fetch | undefined}; export const nullTime = z.object({Time: z.string().optional(), Valid: z.boolean().optional()}); export const bookingTaxRate = z.object({booking_id: z.number().int().optional(), created: z.string().optional(), deleted: z.boolean().optional(), id: z.number().int().optional(), object_id: z.number().int().optional(), object_type: z.string().optional(), payable_to: z.string().optional(), source: z.string().optional(), state: z.string().optional(), tax_amount: z.number().int().optional(), tax_description: z.string().optional(), tax_name: z.string().optional(), tax_rate: z.number().optional(), tax_rate_id: z.number().int().optional(), updated: z.string().optional(), zip_code: z.string().optional()}); export const bookingItem = z.object({_deleted: z.boolean().optional(), booking_id: z.number().int().optional(), coachnet_item: z.boolean().optional(), consigned_pay_amount: z.number().int().optional(), count: z.number().int().optional(), created: nullTime.optional(), daily: z.boolean().optional(), deferred: z.boolean().optional(), deferred_total: z.number().int().nullable().optional(), deleted_at: nullTime.optional(), delivery: z.boolean().optional(), description: z.string().optional(), discount_amount: z.number().int().optional(), generator: z.boolean().optional(), id: z.number().int().optional(), image_url: z.string().optional(), maximum_price: z.number().int().nullable().optional(), mileage: z.boolean().optional(), minimum_price: z.number().int().nullable().optional(), name: z.string().optional(), original_consigned_pay_pct: z.number().optional(), original_tax_rate_id: z.number().int().optional(), other_claim: z.boolean().optional(), outdoorsy_item: z.boolean().optional(), parent_item_id: z.number().int().optional(), parent_item_type: z.string().optional(), percent: z.number().optional(), percent_type: z.string().optional(), position: z.number().int().optional(), premium_amount: z.number().int().optional(), premium_total: z.number().int().optional(), price: z.number().int().optional(), rental_amount: z.boolean().optional(), required: z.boolean().optional(), tax_amount: z.number().int().optional(), tax_description: z.string().optional(), tax_name: z.string().optional(), tax_rate: z.number().optional(), tax_rates: z.array(bookingTaxRate).optional(), total: z.number().int().optional(), updated: nullTime.optional()}); export const campgroundActivityFeature = z.object({feature: z.string().optional(), name: z.string().optional()}); export const campgroundAmenitiesCategory = z.object({id: z.string().optional(), name: z.string().optional()}); export const processedCampgroundAmenity = z.object({available: z.boolean().optional(), category: z.string().optional(), id: z.string().optional(), name: z.string().optional()}); export const campgroundSceneryFeature = z.object({feature: z.string().optional(), name: z.string().optional()}); export const campgroundCatalog = z.object({activity_features: z.array(campgroundActivityFeature).optional(), amenities_categories: z.array(campgroundAmenitiesCategory).optional(), processed_amenities: z.record(z.string(), z.array(processedCampgroundAmenity)).optional(), scenery_features: z.array(campgroundSceneryFeature).optional()}); export const category = z.object({name: z.string().optional(), slug: z.string().optional()}); export const image = z.object({best: z.boolean().optional(), category: category.optional(), description: z.string().optional(), id: z.number().int().optional(), position: z.number().int().optional(), primary: z.boolean().optional(), rental_id: z.number().int().optional(), skip_enhance: z.boolean().optional(), status: z.string().optional(), tags: z.string().optional(), url: z.string().optional(), video: z.boolean().optional()}); export const images = z.array(image); export const locale = z.object({base_currency: z.string().optional(), date_format: z.string().optional(), distance_unit: z.string().optional(), language: z.string().optional(), length_unit: z.string().optional(), liquid_unit: z.string().optional(), time_format: z.string().optional(), timezone: z.string().optional(), weight_unit: z.string().optional()}); export const externalCampground = z.object({available_for_dates: z.boolean().optional(), calculated_day_price: z.number().int().optional(), campground_catalog: campgroundCatalog.optional(), campsite_category_ids: z.array(z.number().int()).optional(), check_in_time: z.string().optional(), check_out_time: z.string().optional(), description: z.string().optional(), email: z.string().optional(), id: z.number().int().optional(), images: images.optional(), is_odn: z.boolean().optional(), is_site_available: z.boolean().optional(), locale: locale.optional(), location: z.number().int().optional(), lowest_price: z.number().int().optional(), name: z.string().optional(), odn_id: z.string().optional(), phone: z.string().optional(), presentment_currency: z.string().optional(), primary_image_url: z.string().optional(), reviews_num: z.number().int().optional(), score: z.number().optional(), settlement_currency: z.string().optional(), site_map_image_url: z.string().optional(), slug: z.string().optional(), unavailable: z.boolean().optional(), vacation_package_slug: z.string().optional(), website_url: z.string().optional()}); export const deliveryLocation = z.object({city: z.string().optional(), country: z.string().optional(), full_search_name_location: z.string().optional(), lat: z.number().optional(), lng: z.number().optional(), search_name_location: z.string().optional(), state: z.string().optional(), street: z.string().optional(), street_etc: z.string().optional(), zip: z.string().optional()}); export const delivery = z.object({comment: z.string().optional(), estimated_distance: z.number().optional(), location: deliveryLocation.optional(), stationary: z.boolean().optional()}); export const warning = z.object({message: z.string().optional()}); export const bundleFeatureItem = z.object({details: z.string().optional(), name: z.string().optional(), position: z.number().int().optional(), service_id: z.number().int().optional(), type: z.string().optional()}); export const bundleFeatureTransfer = z.object({category: z.string().optional(), items: z.array(bundleFeatureItem).optional()}); export const iMap = z.unknown(); export const bookingBundle = z.object({base_price_per_day: z.number().int().optional(), bundle_features: z.array(bundleFeatureTransfer).optional(), dealer_owned_renter: z.boolean().optional(), deductible: z.number().int().optional(), default_selection: z.boolean().optional(), delivery: z.boolean().optional(), description: z.string().optional(), featured_description: z.string().optional(), featured_title: z.string().optional(), id: z.string().optional(), insurance_protection: z.string().optional(), is_rental_shield: z.boolean().optional(), meta: iMap.optional(), name: z.string().optional(), note: z.string().optional(), offer_individual_service_types: z.array(z.string()).optional(), owner_id: z.number().int().optional(), per_mile_price: z.number().int().optional(), per_mile_price_fsd: z.number().int().optional(), percent_uptake: z.number().optional(), premium: z.number().int().optional(), premium_base_rate: z.number().int().optional(), price_per_day: z.number().int().optional(), property_damage: z.string().optional(), qualifies_per_mile_pricing: z.boolean().optional(), recommended: z.boolean().optional(), subtext: z.string().optional(), supported_types: z.array(z.string()).optional(), tier: z.number().int().optional(), total_price: z.number().int().optional(), use_day_pricing: z.boolean().optional()}); export const occupancy = z.object({adults: z.number().int().optional(), children: z.number().int().optional(), infants: z.number().int().optional()}); export const campsiteSummary = z.object({beds: z.number().int().optional(), campground_id: z.number().int().optional(), campground_name: z.string().optional(), campground_sitemap_url: z.string().optional(), display_campsite_type: z.string().optional(), display_max_vehicle_length: z.string().optional(), display_site_type: z.string().optional(), is_odn: z.boolean().optional(), rental_id: z.number().int().optional(), site_type: z.string().optional(), sleeps: z.number().int().optional(), type: z.string().optional()}); export const staySummary = z.object({baths: z.number().int().optional(), bedrooms: z.number().int().optional(), beds: z.number().int().optional(), check_in_type: z.string().optional(), display_stay_type: z.string().optional(), location_description: z.string().optional(), max_parking_spaces: z.number().int().optional(), parking_onsite: z.boolean().optional(), rental_id: z.number().int().optional(), sleeps: z.number().int().optional(), type: z.string().optional()}); export const rentalSummary = z.object({campsite_summary: campsiteSummary.optional(), disallow_movement: z.boolean().optional(), display_type: z.string().optional(), formatted_length: z.string().optional(), id: z.number().int().optional(), interior_primary_image_url: z.string().optional(), internal_id: z.string().optional(), location: z.string().optional(), name: z.string().optional(), primary_image_url: z.string().optional(), rental_category: z.string().optional(), sleeps: z.number().int().optional(), slug: z.string().optional(), stay_summary: staySummary.optional(), style: z.string().optional(), type: z.string().optional()}); export const dBInterfaceMap = z.unknown(); export const bookingService = z.object({booking_id: z.number().int().optional(), bundle_id: z.string().nullable().optional(), category: z.string().optional(), charge_to: z.string().optional(), created: z.string().optional(), daily: z.boolean().optional(), dealer_flat_split: z.number().int().optional(), dealer_percent_split: z.number().optional(), dealer_split_type: z.string().optional(), deleted_at: nullTime.optional(), description: z.string().optional(), discount_amount: z.number().int().optional(), external_reference_id: z.string().optional(), fee_locked: z.boolean().optional(), id: z.number().int().optional(), is_taxable: z.boolean().optional(), last_service_log: z.unknown(), lock_on_booking_status: z.string().optional(), minimum_price: z.number().int().optional(), missing_fields: z.record(z.string(), z.array(z.string())).optional(), name: z.string().optional(), payable_to: z.string().optional(), percent: z.number().optional(), percent_type: z.string().optional(), policy_start_date: z.string().optional(), premium_amount: z.number().int().optional(), premium_total: z.number().int().optional(), prevent_delete: z.boolean().optional(), price: z.number().int().optional(), quantity: z.number().int().optional(), required: z.boolean().optional(), revision: z.number().int().optional(), roamly_weather_quote: dBInterfaceMap.optional(), service_data: dBInterfaceMap.optional(), service_id: z.number().int().optional(), tax_amount: z.number().int().optional(), tax_rates: z.array(bookingTaxRate).optional(), total: z.number().int().optional(), updated: z.string().optional(), variant_price: z.number().int().optional()}); export const siblingTotals = z.object({addons: z.number().int().optional(), damage_protection: z.number().int().optional(), delivery_fee: z.number().int().optional(), discounts: z.number().int().optional(), external_campground_fee: z.number().int().optional(), generator: z.number().int().optional(), insurance_coverage: z.number().int().optional(), mileage: z.number().int().optional(), owner_fees: z.number().int().optional(), pet_fees: z.number().int().optional(), roadside_assistance: z.number().int().optional(), roamly_weather_protection: z.number().int().optional(), security_deposit_waiver: z.number().int().optional(), service_fees: z.number().int().optional(), taxes: z.number().int().optional(), total: z.number().int().optional(), trip_protection: z.number().int().optional()}); export const siblingQuotes = z.object({rental_campsite: z.lazy(() => response.optional()), rental_rv: z.lazy(() => response.optional())}); export const taxRateItem = z.object({description: z.string().optional(), original_tax_rate_id: z.number().int().optional(), tax_amount: z.number().int().optional(), tax_name: z.string().optional(), tax_rate: z.number().optional()}); export const taxRateItems = z.array(taxRateItem); export const taxRateTotalItem = z.object({amount: z.number().int().optional(), name: z.string().optional(), rates: taxRateItems.optional()}); export const noticeResponse = z.object({guest_acknowledgement_text: z.string().optional(), guest_need_to_acknowledge: z.boolean().optional(), guest_user_text: z.string().optional(), host_acknowledgement_text: z.string().optional(), host_help_url: z.string().optional(), host_need_to_acknowledge: z.boolean().optional(), host_user_text: z.string().optional(), id: z.number().int().optional(), name: z.string().optional()}); export const waiverSummary = z.object({description: z.string().optional(), owner_completed: z.boolean().optional(), owner_terms: z.string().optional(), renter_completed: z.boolean().optional(), renter_confirmation_description: z.string().optional(), renter_confirmation_title: z.string().optional(), renter_terms: z.string().optional()}); export const response: z.ZodType = z.object({addons: z.array(bookingItem).optional(), block_discount_code: z.boolean().optional(), bundle_id: z.string().optional(), calculated_day_price: z.number().int().optional(), can_apply_credits: z.boolean().optional(), can_generate_weather_quote: z.boolean().optional(), dealer_minimum_days: z.number().int().optional(), deliverable_campgrounds: z.array(externalCampground).optional(), delivery: delivery.optional(), delivery_campground_id: z.number().int().optional(), delivery_item: bookingItem.optional(), discount_code: z.string().optional(), discount_code_amount: z.number().int().optional(), discount_code_applied_to: z.string().optional(), discount_code_message: z.string().optional(), discount_message: warning.optional(), duration: z.number().int().optional(), estimated_generator_cost: z.number().int().optional(), estimated_mileage_cost: z.number().int().optional(), fees_total: z.number().int().optional(), festival_friendly: z.boolean().optional(), final_payment_amount: z.number().int().optional(), final_payment_due_date: z.string().optional(), from: z.string().optional(), from_time: z.number().int().optional(), generator_item: bookingItem.optional(), generator_total_included: z.number().optional(), id: z.string().optional(), instant_book: z.boolean().optional(), insurance_bundle: bookingBundle.optional(), is_request_less_than_minimum_days: z.boolean().optional(), items: z.array(bookingItem).optional(), locale_base_currency: z.string().optional(), make: z.string().optional(), mileage_item: bookingItem.optional(), mileage_total_included: z.number().optional(), model: z.array(z.string()).optional(), occupancy: occupancy.optional(), offer_affirm: z.boolean().optional(), offer_paypal_pay_later: z.boolean().optional(), original_day_override_price: z.number().int().optional(), original_day_price: z.number().int().optional(), original_month_price: z.number().int().optional(), original_service_fee: z.number().int().optional(), original_week_price: z.number().int().optional(), outdoorsy_fee: z.number().int().optional(), owner_fee: z.number().int().optional(), owner_fees: z.array(bookingItem).optional(), owner_integrations_fee: z.number().int().optional(), pet_friendly: z.boolean().optional(), pets: z.number().int().optional(), presentment_currency: z.string().optional(), remainder_amount: z.number().int().optional(), remainder_due_date: z.string().optional(), rental_amount: z.number().int().optional(), rental_amount_item: bookingItem.optional(), rental_summary: rentalSummary.optional(), renter_credits_applied: z.number().int().optional(), renter_reserve_amount: z.number().int().optional(), requested_duration: z.number().int().optional(), reserve_amount: z.number().int().optional(), security_deposit: z.number().int().optional(), service_fee: z.number().int().optional(), services: z.array(bookingService).optional(), settlement_currency: z.string().optional(), sibling_quote_group_id: z.number().int().optional(), sibling_quotes_totals: siblingTotals.optional(), siblings: siblingQuotes.optional(), smoking_allowed: z.boolean().optional(), subtotal: z.number().int().optional(), tailgate_friendly: z.boolean().optional(), tax: z.number().int().optional(), tax_rates: z.array(taxRateTotalItem).optional(), to: z.string().optional(), to_time: z.number().int().optional(), total: z.number().int().optional(), total_after_credits: z.number().int().optional(), total_after_deductions: z.number().int().optional(), towing_capacity: z.number().int().optional(), towing_vehicle_make: z.string().optional(), towing_vehicle_model: z.string().optional(), towing_vehicle_year: z.number().int().optional(), travelers: z.number().int().optional(), use_day_price: z.boolean().optional(), use_day_pricing: z.boolean().optional(), use_system_tax_rates: z.boolean().optional(), use_tax_inclusive_pricing: z.boolean().optional(), user_notice_events: z.array(noticeResponse).optional(), waiver_summary: waiverSummary.optional(), warning: warning.optional(), year_max: z.number().int().optional(), year_min: z.number().int().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 }; /** * Generates a quote for a given rental based on start and stop dates. * * POST /quotes * * Also accepts auth: API-Key */ export const createApiQuotes = async (args: CreateApiQuotesArgs, options: CreateApiQuotesOptions) => { const {baseUrl, fetch: fetchFn = fetch, Bearer} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (Bearer !== undefined) headers.set("Authorization", Bearer) const url = `${baseUrl.replace(/\/+$/, '')}/quotes${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(response, await res.json()) };