import {z} from 'zod' export type GetApiRestaurantsBypostcodePostcodeArgs = {Authorization?: string | undefined, 'Accept-Tenant'?: string | undefined, postcode: string, cuisine?: string | undefined, restaurantName?: string | undefined, brandName?: string | undefined}; export type GetApiRestaurantsBypostcodePostcodeOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const localDateTime = z.string(); export const searchRestaurant = z.object({Id: z.number().optional(), Name: z.string().optional(), UniqueName: z.string().optional(), Address: z.object({City: z.string().optional(), FirstLine: z.string().optional(), Postcode: z.string().optional(), Latitude: z.number().optional(), Longitude: z.number().optional()}).optional(), City: z.string().optional(), Postcode: z.string().optional(), Latitude: z.number().optional(), Longitude: z.number().optional(), Rating: z.object({Count: z.number().optional(), Average: z.number().optional(), StarRating: z.number().optional()}).optional(), RatingStars: z.number().optional(), NumberOfRatings: z.number().optional(), RatingAverage: z.number().optional(), Description: z.string().optional(), Url: z.string().optional(), LogoUrl: z.string().optional(), IsTestRestaurant: z.boolean().optional(), IsHalal: z.boolean().optional(), IsNew: z.boolean().optional(), ReasonWhyTemporarilyOffline: z.string().optional(), DriveDistance: z.number().optional(), DriveInfoCalculated: z.boolean().optional(), IsCloseBy: z.boolean().optional(), OfferPercent: z.number().optional(), NewnessDate: localDateTime.optional(), OpeningTime: z.string().optional(), OpeningTimeUtc: z.string().nullable().optional(), OpeningTimeIso: localDateTime.optional(), OpeningTimeLocal: localDateTime.optional(), DeliveryOpeningTimeLocal: localDateTime.optional(), DeliveryOpeningTime: z.string().optional(), DeliveryOpeningTimeUtc: z.string().nullable().optional(), DeliveryStartTime: z.string().optional(), DeliveryTime: z.number().nullable().optional(), DeliveryTimeMinutes: z.number().nullable().optional(), DeliveryWorkingTimeMinutes: z.number().optional(), DeliveryEtaMinutes: z.object({Approximate: z.number().nullable().optional(), RangeLower: z.number().optional(), RangeUpper: z.number().optional()}).optional(), IsCollection: z.boolean().optional(), IsDelivery: z.boolean().optional(), IsFreeDelivery: z.boolean().optional(), IsOpenNowForCollection: z.boolean().optional(), IsOpenNowForDelivery: z.boolean().optional(), IsOpenNowForPreorder: z.boolean().optional(), IsOpenNow: z.boolean().optional(), IsTemporarilyOffline: z.boolean().optional(), DeliveryMenuId: z.number().optional(), CollectionMenuId: z.number().nullable().optional(), DeliveryZipcode: z.string().nullable().optional(), DeliveryCost: z.number().optional(), MinimumDeliveryValue: z.number().optional(), SecondDateRanking: z.number().optional(), DefaultDisplayRank: z.number().optional(), SponsoredPosition: z.number().optional(), SecondDateRank: z.number().optional(), Score: z.number().optional(), IsTemporaryBoost: z.boolean().optional(), IsSponsored: z.boolean().optional(), IsPremier: z.boolean().optional(), HygieneRating: z.number().nullable().optional(), ShowSmiley: z.boolean().optional(), SmileyDate: z.object({}).nullable().optional(), SmileyElite: z.boolean().optional(), SmileyResult: z.object({}).nullable().optional(), SmileyUrl: z.object({}).nullable().optional(), SendsOnItsWayNotifications: z.boolean().optional(), BrandName: z.string().optional(), IsBrand: z.boolean().optional(), LastUpdated: localDateTime.optional(), Deals: z.array(z.object({Description: z.string().optional(), DiscountPercent: z.number().optional(), QualifyingPrice: z.number().optional(), OfferType: z.string().optional()})).optional(), Offers: z.array(z.record(z.string(), z.unknown())).optional(), Logo: z.array(z.object({StandardResolutionURL: z.string().optional()})).optional(), Tags: z.array(z.string()).optional(), DeliveryChargeBands: z.array(z.object({BasketThresholdPrice: z.number().optional(), DeliveryChargeBelowThreshold: z.number().optional()})).optional(), CuisineTypes: z.array(z.object({Id: z.number().optional(), IsTopCuisine: z.boolean().optional()})).optional(), Cuisines: z.array(z.object({Name: z.string().optional(), SeoName: z.string().optional()})).optional(), ScoreMetaData: z.array(z.object({Key: z.string().optional(), Value: z.string().optional()})).optional(), Badges: z.array(z.object({})).optional(), OpeningTimes: z.array(z.object({})).optional(), ServiceableAreas: z.array(z.object({})).optional()}); export const restaurantDeliveryFees = z.object({restaurantId: z.string().optional(), minimumOrderValue: z.number().optional(), bands: z.array(z.object({minimumAmount: z.number().optional(), fee: z.number().optional()})).optional()}); export const restaurantPromotedPlacementInfo = z.object({restaurantId: z.string().optional(), defaultPromoted: z.boolean().optional()}); export const searchResponse = z.object({area: z.string().optional(), MetaData: z.object({CanonicalName: z.string().optional(), District: z.string().optional(), Postcode: z.string().optional(), Area: z.string().optional(), Latitude: z.number().optional(), Longitude: z.number().optional(), CuisineDetails: z.array(z.object({Name: z.string().optional(), SeoName: z.string().optional(), Total: z.number().optional()})).optional(), ResultCount: z.number().optional(), SearchedTerms: z.object({}).nullable().optional(), TagDetails: z.array(z.object({BackgroundColour: z.string().optional(), Colour: z.string().optional(), DisplayName: z.string().optional(), Key: z.string().optional(), Priority: z.number().optional()})).optional()}).optional(), Restaurants: z.array(searchRestaurant).optional(), RestaurantSets: z.array(z.object({Id: z.string().optional(), Name: z.string().optional(), Type: z.string().optional(), Restaurants: z.array(z.object({Id: z.number().optional(), Metadata: z.array(z.object({Key: z.string().optional(), Value: z.string().optional()})).optional()})).optional()})).optional(), CuisineSets: z.array(z.object({Id: z.string().optional(), Name: z.string().optional(), Type: z.string().optional(), Cuisines: z.array(z.object({Name: z.string().optional(), SeoName: z.string().optional()})).optional()})).optional(), Views: z.array(z.object({Target: z.string().optional(), Components: z.object({Type: z.string().optional(), Id: z.string().optional(), TrackingId: z.string().optional(), TemplateName: z.string().optional(), ViewData: z.object({}).optional()}).optional()})).optional(), Dishes: z.array(z.object({RestaurantId: z.number().optional(), Best: z.array(z.object({ProductId: z.number().optional(), StrProductId: z.string().optional(), Price: z.number().optional(), FullName: z.string().optional()})).optional(), Similar: z.array(z.object({ProductId: z.number().optional(), Price: z.number().optional(), FullName: z.string().optional()})).optional()})).optional(), ShortResultText: z.string().optional(), deliveryFees: z.object({restaurants: z.record(z.string(), restaurantDeliveryFees).optional()}).optional(), promotedPlacement: z.object({filteredSearchPromotedLimit: z.number().optional(), restaurants: z.record(z.string(), restaurantPromotedPlacementInfo).optional(), rankedIds: z.array(z.number()).optional()}).optional()}); export const externalSearchResponse = z.object({Restaurants: z.array(z.object({Id: z.number().optional(), Name: z.string().optional(), UniqueName: z.string().optional(), Address: z.object({City: z.string().optional(), FirstLine: z.string().optional(), Postcode: z.string().optional(), Latitude: z.number().optional(), Longitude: z.number().optional()}).optional(), Url: z.string().optional(), DriveDistance: z.number().optional(), DriveInfoCalculated: z.boolean().optional(), IsOpenNowForDelivery: z.boolean().optional(), IsOpenNow: z.boolean().optional(), DeliveryEtaMinutes: z.object({Approximate: z.number().optional(), RangeLower: z.number().optional(), RangeUpper: z.number().optional()}).optional()})).optional()}); export const searchWebResponse = z.object({Open: z.array(searchRestaurant).optional(), Offline: z.array(searchRestaurant).optional(), Closed: z.array(searchRestaurant).optional()}); export const getApiRestaurantsBypostcodePostcodeResponse = z.union([searchResponse, externalSearchResponse, searchWebResponse]); 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 }; /** * Get restaurants by postcode * * GET /restaurants/bypostcode/{postcode} */ export const getApiRestaurantsBypostcodePostcode = async (args: GetApiRestaurantsBypostcodePostcodeArgs, options?: GetApiRestaurantsBypostcodePostcodeOptions) => { const {baseUrl = "https://uk.api.just-eat.io", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.Authorization != null) headers.set("Authorization", String(args.Authorization)) if (args['Accept-Tenant'] != null) headers.set("Accept-Tenant", String(args['Accept-Tenant'])) if (args.cuisine != null) query.append("cuisine", String(args.cuisine)) if (args.restaurantName != null) query.append("restaurantName", String(args.restaurantName)) if (args.brandName != null) query.append("brandName", String(args.brandName)) const url = `${baseUrl.replace(/\/+$/, '')}/restaurants/bypostcode/${encodeURIComponent(String(args.postcode))}${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiRestaurantsBypostcodePostcodeResponse, await res.json()) };