import {z} from 'zod' export type GetApiRecipesTop25randomArgs = {any_kw?: string | undefined, folder?: string | undefined, coll?: number | undefined, filter?: string | undefined, title_kw?: string | undefined, userId?: number | undefined, username?: string | undefined, token?: string | undefined, photos?: boolean | undefined, boostmine?: boolean | undefined, include_cat?: string | undefined, exclude_cat?: string | undefined, include_primarycat?: string | undefined, exclude_primarycat?: string | undefined, include_ing?: string | undefined, exclude_ing?: string | undefined, cuisine?: string | undefined, db?: string | undefined, userset?: string | undefined, servingsMin?: number | undefined, totalMins?: number | undefined, maxIngredients?: number | undefined, minIngredients?: number | undefined, vtn?: number | undefined, vgn?: number | undefined, chs?: number | undefined, glf?: number | undefined, ntf?: number | undefined, dyf?: number | undefined, sff?: number | undefined, slf?: number | undefined, tnf?: number | undefined, wmf?: number | undefined, rmf?: number | undefined, cps?: number | undefined, champion?: number | undefined, synonyms?: boolean | undefined}; export type GetApiRecipesTop25randomOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const bigOvenModelAPI2UserInfoTinyx = z.object({UserName: z.string().optional(), UserID: z.number().int().optional(), FirstName: z.string().optional(), LastName: z.string().optional(), PhotoUrl: z.string().optional()}); export const bigOvenModelAPI2RecipeInfox = z.object({RecipeID: z.number().int().optional(), Title: z.string().optional(), Cuisine: z.string().optional(), Category: z.string().optional(), Subcategory: z.string().optional(), Microcategory: z.string().optional(), StarRating: z.number().optional(), WebURL: z.string().optional(), ReviewCount: z.number().int().optional(), Poster: bigOvenModelAPI2UserInfoTinyx.optional(), IsPrivate: z.boolean().optional(), Servings: z.number().optional(), CreationDate: z.string().optional(), IsRecipeScan: z.boolean().optional(), IsBookmark: z.boolean().optional(), TotalTries: z.number().int().optional(), PhotoUrl: z.string().optional(), HasVideos: z.boolean().optional()}); export const bigOvenModelAPI2RecipeSearchResult = z.object({ResultCount: z.number().int().optional(), Results: z.array(bigOvenModelAPI2RecipeInfox).optional(), SpellSuggest: 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 }; /** * Search for recipes. There are many parameters that you can apply. Starting with the most common, use title_kw to search within a title. * Use any_kw to search across the entire recipe. * If you'd like to limit by course, set the parameter "include_primarycat" to one of (appetizers,bread,breakfast,dessert,drinks,maindish,salad,sidedish,soup,marinades,other). * If you'd like to exclude a category, set exclude_cat to one or more (comma-separated) list of those categories to exclude. * If you'd like to include a category, set include_cat to one or more (comma-separated) of those categories to include. * To explicitly include an ingredient in your search, set the parameter "include_ing" to a CSV of up to three ingredients, e.g.:include_ing=mustard,chicken,beef%20tips * To explicitly exclude an ingredient in your search, set the parameter "exclude_ing" to a CSV of up to three ingredients. * All searches must contain the paging parameters pg and rpp, which are integers, and represent the page number (1-based) and results per page (rpp). * So, to get the third page of a result set paged with 25 recipes per page, you'd pass pg=3&rpp=25 * If you'd like to target searches to just a single target user's recipes, set userId=the target userId (number). * Or, you can set username=theirusername * vtn;vgn;chs;glf;ntf;dyf;sff;slf;tnf;wmf;rmf;cps * cuisine * photos * filter=added,try,favorites,myrecipes\r\n\r\n * folder=FolderNameCaseSensitive * coll=ID of Collection * * GET /recipes/top25random */ export const getApiRecipesTop25random = async (args: GetApiRecipesTop25randomArgs, options?: GetApiRecipesTop25randomOptions) => { const {baseUrl = "https://api2.bigoven.com", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.any_kw != null) query.append("any_kw", String(args.any_kw)) if (args.folder != null) query.append("folder", String(args.folder)) if (args.coll != null) query.append("coll", String(args.coll)) if (args.filter != null) query.append("filter", String(args.filter)) if (args.title_kw != null) query.append("title_kw", String(args.title_kw)) if (args.userId != null) query.append("userId", String(args.userId)) if (args.username != null) query.append("username", String(args.username)) if (args.token != null) query.append("token", String(args.token)) if (args.photos != null) query.append("photos", String(args.photos)) if (args.boostmine != null) query.append("boostmine", String(args.boostmine)) if (args.include_cat != null) query.append("include_cat", String(args.include_cat)) if (args.exclude_cat != null) query.append("exclude_cat", String(args.exclude_cat)) if (args.include_primarycat != null) query.append("include_primarycat", String(args.include_primarycat)) if (args.exclude_primarycat != null) query.append("exclude_primarycat", String(args.exclude_primarycat)) if (args.include_ing != null) query.append("include_ing", String(args.include_ing)) if (args.exclude_ing != null) query.append("exclude_ing", String(args.exclude_ing)) if (args.cuisine != null) query.append("cuisine", String(args.cuisine)) if (args.db != null) query.append("db", String(args.db)) if (args.userset != null) query.append("userset", String(args.userset)) if (args.servingsMin != null) query.append("servingsMin", String(args.servingsMin)) if (args.totalMins != null) query.append("totalMins", String(args.totalMins)) if (args.maxIngredients != null) query.append("maxIngredients", String(args.maxIngredients)) if (args.minIngredients != null) query.append("minIngredients", String(args.minIngredients)) if (args.vtn != null) query.append("vtn", String(args.vtn)) if (args.vgn != null) query.append("vgn", String(args.vgn)) if (args.chs != null) query.append("chs", String(args.chs)) if (args.glf != null) query.append("glf", String(args.glf)) if (args.ntf != null) query.append("ntf", String(args.ntf)) if (args.dyf != null) query.append("dyf", String(args.dyf)) if (args.sff != null) query.append("sff", String(args.sff)) if (args.slf != null) query.append("slf", String(args.slf)) if (args.tnf != null) query.append("tnf", String(args.tnf)) if (args.wmf != null) query.append("wmf", String(args.wmf)) if (args.rmf != null) query.append("rmf", String(args.rmf)) if (args.cps != null) query.append("cps", String(args.cps)) if (args.champion != null) query.append("champion", String(args.champion)) if (args.synonyms != null) query.append("synonyms", String(args.synonyms)) const url = `${baseUrl.replace(/\/+$/, '')}/recipes/top25random${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(bigOvenModelAPI2RecipeSearchResult, await res.json()) };