memorium/lib/recipeSchema.ts

59 lines
2.0 KiB
TypeScript

import { z } from "npm:zod";
export const IngredientSchema = z.object({
quantity: z.string().describe(
"e.g., '2', '1/2', or an empty string for 'to taste'",
),
unit: z.string().describe('e.g., "g", "tbsp", "cup"'),
name: z.string().describe('e.g., "sugar", "flour"'), //
note: z.string().describe('optional, e.g., "sifted", "chopped finely"'),
});
export type Ingredient = z.infer<typeof IngredientSchema>;
export const IngredientGroupSchema = z.object({
name: z.string(),
items: z.array(IngredientSchema),
});
export type IngredientGroup = z.infer<typeof IngredientGroupSchema>;
const recipeSchema = z.object({
title: z.string().describe(
"Title of the Recipe, without the name of the website or author",
),
image: z.string().describe("URL of the main image of the recipe"),
author: z.string().describe("author of the Recipe (optional)"),
description: z.string().describe("Optional, short description of the recipe"),
ingredients: z.array(z.union([IngredientSchema, IngredientGroupSchema]))
.describe("List of ingredients"),
instructions: z.array(z.string()).describe("List of instructions"),
servings: z.number().describe("Amount of Portions"),
prepTime: z.number().describe("Preparation time in minutes"),
cookTime: z.number().describe("Cooking time in minutes"),
totalTime: z.number().describe("Total time in minutes"),
tags: z.array(z.string()).describe(
"List of tags (e.g., ['vegan', 'dessert'])",
),
notes: z.array(z.string()).describe("Optional notes about the recipe"),
});
const noRecipeSchema = z.object({
errorMessages: z.array(z.string()).describe(
"List of error messages, if no recipe was found",
),
});
export const recipeResponseSchema = z.union([recipeSchema, noRecipeSchema]);
export function isValidRecipe(
recipe:
| { ingredients?: unknown[]; instructions?: string[]; name?: string }
| null
| undefined,
) {
return recipe?.ingredients?.length && recipe.ingredients.length > 1 &&
recipe?.instructions?.length &&
recipe.name?.length;
}
export default recipeSchema;