import {z} from 'zod' export type GetApiFoodsFormattedMpqArgs = {food_names: string}; export type GetApiFoodsFormattedMpqOptions = {baseUrl: string, bearerAuth?: string | undefined, fetch?: typeof fetch | undefined}; export const ccColumnsRequest = z.object({cc_added_sugars: z.boolean().nullable().optional(), cc_additives: z.boolean().nullable().optional(), cc_beverage: z.boolean().nullable().optional(), cc_calcium: z.boolean().nullable().optional(), cc_complexcarbs: z.boolean().nullable().optional(), cc_composite_dish: z.boolean().nullable().optional(), cc_cooked: z.boolean().nullable().optional(), cc_fish: z.boolean().nullable().optional(), cc_fried: z.boolean().nullable().optional(), cc_fruit: z.boolean().nullable().optional(), cc_gluten_free: z.boolean().nullable().optional(), cc_grains: z.boolean().nullable().optional(), cc_healthy_fat: z.boolean().nullable().optional(), cc_high_fiber: z.boolean().nullable().optional(), cc_legume: z.boolean().nullable().optional(), cc_meat: z.boolean().nullable().optional(), cc_non_meat_animal_protein: z.boolean().nullable().optional(), cc_nuts_seeds: z.boolean().nullable().optional(), cc_omega_three: z.boolean().nullable().optional(), cc_plant_based: z.boolean().nullable().optional(), cc_plant_based_whole: z.boolean().nullable().optional(), cc_plant_protein: z.boolean().nullable().optional(), cc_pork: z.boolean().nullable().optional(), cc_poultry: z.boolean().nullable().optional(), cc_processed: z.boolean().nullable().optional(), cc_protein: z.boolean().nullable().optional(), cc_raw: z.boolean().nullable().optional(), cc_redmeat: z.boolean().nullable().optional(), cc_shellfish: z.boolean().nullable().optional(), cc_simplecarbs: z.boolean().nullable().optional(), cc_standalone_food: z.boolean().nullable().optional(), cc_sugar_free: z.boolean().nullable().optional(), cc_sugary_beverage: z.boolean().nullable().optional(), cc_supplement: z.boolean().nullable().optional(), cc_ultraprocessed: z.boolean().nullable().optional(), cc_unhealthy_fat: z.boolean().nullable().optional(), cc_vegetable: z.boolean().nullable().optional(), cc_whole: z.boolean().nullable().optional(), cc_whole_foods: z.boolean().nullable().optional()}); export const createMealItemFoodMatchDetailsRequest = z.object({source_details: z.object({}).optional(), source_name: z.enum(["im_lbl_auto", "nlp_note", "nlp_auto", "mpq_im_lbl", "search", "external", "custom", "patient_history"]), user_type: z.enum(["internal", "system", "patient", "clinician"]).optional()}); export const nutrientEstimatesRequest = z.object({added_sugars_g: z.number().nullable().optional(), alcohol_g: z.number().nullable().optional(), caffeine_mg: z.number().nullable().optional(), calcium_mg: z.number().nullable().optional(), carbohydrate_g: z.number().nullable().optional(), cholesterol_mg: z.number().nullable().optional(), choline_mg: z.number().nullable().optional(), energy_kcal: z.number().nullable().optional(), fat_g: z.number().nullable().optional(), fattyacids_totalmonounsaturated_g: z.number().nullable().optional(), fattyacids_totalpolyunsaturated_g: z.number().nullable().optional(), fattyacids_totalsaturated_g: z.number().nullable().optional(), fattyacids_totaltrans_g: z.number().nullable().optional(), fiber_g: z.number().nullable().optional(), folate_dfe_ug: z.number().nullable().optional(), grams_per_cubic_inch: z.number().nullable().optional(), insoluble_dietary_fiber_g: z.number().nullable().optional(), iron_mg: z.number().nullable().optional(), magnesium_mg: z.number().nullable().optional(), netcarb_g: z.number().nullable().optional(), niacin_mg: z.number().nullable().optional(), omega_three_fatty_acids_g: z.number().nullable().optional(), pantothenic_acid_mg: z.number().nullable().optional(), phosphorus_mg: z.number().nullable().optional(), polyols_g: z.number().nullable().optional(), potassium_mg: z.number().nullable().optional(), protein_g: z.number().nullable().optional(), riboflavin_mg: z.number().nullable().optional(), selenium_mcg: z.number().nullable().optional(), sodium_mg: z.number().nullable().optional(), soluble_dietary_fiber_g: z.number().nullable().optional(), sugars_g: z.number().nullable().optional(), thiamin_mg: z.number().nullable().optional(), vitamin_a_iu: z.number().nullable().optional(), vitamin_a_rae_ug: z.number().nullable().optional(), vitamin_b12_ug: z.number().nullable().optional(), vitamin_b6_mg: z.number().nullable().optional(), vitamin_c_mg: z.number().nullable().optional(), vitamin_d2d3_ug: z.number().nullable().optional(), vitamin_d_iu: z.number().nullable().optional(), vitamin_e_mg: z.number().nullable().optional(), vitamin_k_ug: z.number().nullable().optional(), water_g: z.number().nullable().optional(), zinc_mg: z.number().nullable().optional()}); export const foodOntologyVTO = z.object({adult_serving_size_g: z.number().nullable().optional(), ghg_equivalent_kg: z.number().nullable().optional(), id: z.number().int().nullable().optional(), levels: z.array(z.string())}); export const nutrientOverridesResponse = z.object({cc_columns: ccColumnsRequest.optional(), created_time: z.string(), metadata: z.record(z.string(), z.unknown()).nullable().optional(), nutrients: nutrientEstimatesRequest.optional(), ontology: foodOntologyVTO.optional(), source_id: z.string(), source_name: z.enum(["patient", "reviewer", "external", "estimate", "validation"]), updated_time: z.string()}); export const nutrientOverrideCollection = z.object({aa_patient: nutrientOverridesResponse.optional(), bb_reviewer: nutrientOverridesResponse.optional(), cc_external: nutrientOverridesResponse.optional(), dd_estimate: nutrientOverridesResponse.optional(), ee_validation: nutrientOverridesResponse.optional()}); export const mealItemCustomAddonRequest = z.object({custom_item: z.boolean().nullable().optional(), food_match_details: createMealItemFoodMatchDetailsRequest.optional(), food_name: z.string(), food_name_translations: z.object({}).nullable().optional(), id: z.number().int().nullable().optional(), internal_custom_item_see_docs: z.boolean().nullable().optional(), nutrient_overrides: nutrientOverrideCollection.optional(), rxfood_id: z.string().nullable().optional(), serving_unit_amount: z.number(), serving_unit_label: z.string(), serving_unit_label_translations: z.object({}).nullable().optional(), servings: z.number(), source_meal_id: z.number().int().nullable().optional(), source_meal_item_custom_addon_id: z.number().int().nullable().optional(), source_meal_item_id: z.number().int().nullable().optional()}).nullable(); export const mealPushQuestionFocusRegionImage = z.object({region: z.object({heightPct: z.number().optional(), imageId: z.string().optional(), widthPct: z.number().optional(), xPct: z.number().optional(), yPct: z.number().optional()}).optional(), type: z.literal("image").optional()}); export const mealPushQuestionFocusRegionPatientNote = z.object({region: z.object({endIdx: z.number(), fullText: z.string(), startIdx: z.number(), textSpan: z.string()}).optional(), type: z.literal("patient-note").optional()}); export const mealPushQuestionFocusRegion = z.discriminatedUnion("type", [mealPushQuestionFocusRegionImage, mealPushQuestionFocusRegionPatientNote]); export const userSurveyResponseItem = z.object({form_item_id: z.string(), value: z.union([z.string(), z.number().int(), z.array(z.union([z.string(), z.number().int()]))])}); export const userSurveyResponses = z.object({items: z.array(userSurveyResponseItem).optional()}); export const mealPushQuestionStatusEnum = z.enum(["pending:patient", "pending:system", "resolved", "deleted"]); export const mealPushQuestionTypeEnum = z.enum(["describe_item", "clarify_nft"]); export const updateMealPushQuestionRequest = z.object({id: z.number().int().nullable().optional(), meal_item_id: z.number().int().nullable().optional(), question_focus_region: mealPushQuestionFocusRegion.optional(), question_response: userSurveyResponses.optional(), question_status: mealPushQuestionStatusEnum.optional(), question_type: mealPushQuestionTypeEnum.optional()}); export const preparationMethodEnum = z.enum(["", "homemade", "restaurant", "cpg", "store_bought", "other"]); export const createMealItemFromQueueRequest = z.object({addons: z.array(z.string()), cc_columns: ccColumnsRequest.optional(), custom_addons: z.array(mealItemCustomAddonRequest).nullable().optional(), custom_item: z.boolean().nullable().optional(), custom_item_source: z.string().nullable().optional(), custom_item_source_id: z.string().nullable().optional(), custom_nutrient_estimates: nutrientEstimatesRequest.optional(), custom_usda_id: z.number().int().nullable().optional(), extra_addons: z.array(z.string()), food_match_details: createMealItemFoodMatchDetailsRequest.optional(), food_name: z.string(), food_name_alias: z.string().nullable().optional(), food_name_translations: z.object({}).nullable().optional(), food_replacement_name: z.string().nullable().optional(), meal_push_question: updateMealPushQuestionRequest.optional(), note: z.string().nullable().optional(), nutrient_overrides: nutrientOverrideCollection.optional(), percent_eaten: z.number().nullable().optional(), preparation_method: preparationMethodEnum.optional(), rxfood_id: z.string().nullable().optional(), serving_type_label: z.string().nullable().optional(), serving_type_multiplier: z.number().nullable().optional(), serving_unit_amount: z.number(), serving_unit_label: z.string(), serving_unit_label_translations: z.object({}).nullable().optional(), servings: z.number()}); export const getApiFoodsFormattedMpqResponse = z.array(createMealItemFromQueueRequest); 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 the food data, for a string of foods, from the server in the MPQ format * * GET /foods/formatted_mpq */ export const getApiFoodsFormattedMpq = async (args: GetApiFoodsFormattedMpqArgs, options: GetApiFoodsFormattedMpqOptions) => { const {baseUrl, fetch: fetchFn = fetch, bearerAuth} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.food_names != null) query.append("food_names", String(args.food_names)) if (bearerAuth !== undefined) headers.set('authorization', `Bearer ${bearerAuth}`) const url = `${baseUrl.replace(/\/+$/, '')}/foods/formatted_mpq${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(getApiFoodsFormattedMpqResponse, await res.json()) };