mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-30 09:43:43 -04:00 
			
		
		
		
	dev: Fix json2ts codegen (#4590)
This commit is contained in:
		| @@ -1,3 +1,4 @@ | |||||||
|  | import re | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
|  |  | ||||||
| from jinja2 import Template | from jinja2 import Template | ||||||
| @@ -64,7 +65,112 @@ def generate_global_components_types() -> None: | |||||||
| # Pydantic To Typescript Generator | # Pydantic To Typescript Generator | ||||||
|  |  | ||||||
|  |  | ||||||
| def generate_typescript_types() -> None: | def generate_typescript_types() -> None:  # noqa: C901 | ||||||
|  |     def contains_number(s: str) -> bool: | ||||||
|  |         return bool(re.search(r"\d", s)) | ||||||
|  |  | ||||||
|  |     def remove_numbers(s: str) -> str: | ||||||
|  |         return re.sub(r"\d", "", s) | ||||||
|  |  | ||||||
|  |     def extract_type_name(line: str) -> str: | ||||||
|  |         # Looking for "export type EnumName = enumVal1 | enumVal2 | ..." | ||||||
|  |         if not (line.startswith("export type") and "=" in line): | ||||||
|  |             return "" | ||||||
|  |  | ||||||
|  |         return line.split(" ")[2] | ||||||
|  |  | ||||||
|  |     def extract_property_type_name(line: str) -> str: | ||||||
|  |         # Looking for " fieldName: FieldType;" or " fieldName: FieldType & string;" | ||||||
|  |         if not (line.startswith("  ") and ":" in line): | ||||||
|  |             return "" | ||||||
|  |  | ||||||
|  |         return line.split(":")[1].strip().split(";")[0] | ||||||
|  |  | ||||||
|  |     def extract_interface_name(line: str) -> str: | ||||||
|  |         # Looking for "export interface InterfaceName {" | ||||||
|  |         if not (line.startswith("export interface") and "{" in line): | ||||||
|  |             return "" | ||||||
|  |  | ||||||
|  |         return line.split(" ")[2] | ||||||
|  |  | ||||||
|  |     def is_comment_line(line: str) -> bool: | ||||||
|  |         s = line.strip() | ||||||
|  |         return s.startswith("/*") or s.startswith("*") | ||||||
|  |  | ||||||
|  |     def clean_output_file(file: Path) -> None: | ||||||
|  |         """ | ||||||
|  |         json2ts generates duplicate types off of our enums and appends a number to the end of the type name. | ||||||
|  |         Our Python code (hopefully) doesn't have any duplicate enum names, or types with numbers in them, | ||||||
|  |         so we can safely remove the numbers. | ||||||
|  |  | ||||||
|  |         To do this, we read the output line-by-line and replace any type names that contain numbers with | ||||||
|  |         the same type name, but without the numbers. | ||||||
|  |  | ||||||
|  |         Note: the issue arrises from the JSON package json2ts, not the Python package pydantic2ts, | ||||||
|  |         otherwise we could just fix pydantic2ts. | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         # First pass: build a map of type names to their numberless counterparts and lines to skip | ||||||
|  |         replacement_map = {} | ||||||
|  |         lines_to_skip = set() | ||||||
|  |         wait_for_semicolon = False | ||||||
|  |         wait_for_close_bracket = False | ||||||
|  |         skip_comments = False | ||||||
|  |         with open(file) as f: | ||||||
|  |             for i, line in enumerate(f.readlines()): | ||||||
|  |                 if wait_for_semicolon: | ||||||
|  |                     if ";" in line: | ||||||
|  |                         wait_for_semicolon = False | ||||||
|  |                     lines_to_skip.add(i) | ||||||
|  |                     continue | ||||||
|  |                 if wait_for_close_bracket: | ||||||
|  |                     if "}" in line: | ||||||
|  |                         wait_for_close_bracket = False | ||||||
|  |                     lines_to_skip.add(i) | ||||||
|  |                     continue | ||||||
|  |  | ||||||
|  |                 if type_name := extract_type_name(line): | ||||||
|  |                     if not contains_number(type_name): | ||||||
|  |                         continue | ||||||
|  |  | ||||||
|  |                     replacement_map[type_name] = remove_numbers(type_name) | ||||||
|  |                     if ";" not in line: | ||||||
|  |                         wait_for_semicolon = True | ||||||
|  |                     lines_to_skip.add(i) | ||||||
|  |  | ||||||
|  |                 elif type_name := extract_interface_name(line): | ||||||
|  |                     if not contains_number(type_name): | ||||||
|  |                         continue | ||||||
|  |  | ||||||
|  |                     replacement_map[type_name] = remove_numbers(type_name) | ||||||
|  |                     if "}" not in line: | ||||||
|  |                         wait_for_close_bracket = True | ||||||
|  |                     lines_to_skip.add(i) | ||||||
|  |  | ||||||
|  |                 elif skip_comments and is_comment_line(line): | ||||||
|  |                     lines_to_skip.add(i) | ||||||
|  |  | ||||||
|  |                 # we've passed the opening comments and empty line at the header | ||||||
|  |                 elif not skip_comments and not line.strip(): | ||||||
|  |                     skip_comments = True | ||||||
|  |  | ||||||
|  |         # Second pass: rewrite or remove lines as needed. | ||||||
|  |         # We have to do two passes here because definitions don't always appear in the same order as their usage. | ||||||
|  |         lines = [] | ||||||
|  |         with open(file) as f: | ||||||
|  |             for i, line in enumerate(f.readlines()): | ||||||
|  |                 if i in lines_to_skip: | ||||||
|  |                     continue | ||||||
|  |  | ||||||
|  |                 if type_name := extract_property_type_name(line): | ||||||
|  |                     if type_name in replacement_map: | ||||||
|  |                         line = line.replace(type_name, replacement_map[type_name]) | ||||||
|  |  | ||||||
|  |                 lines.append(line) | ||||||
|  |  | ||||||
|  |         with open(file, "w") as f: | ||||||
|  |             f.writelines(lines) | ||||||
|  |  | ||||||
|     def path_to_module(path: Path): |     def path_to_module(path: Path): | ||||||
|         str_path: str = str(path) |         str_path: str = str(path) | ||||||
|  |  | ||||||
| @@ -98,9 +204,10 @@ def generate_typescript_types() -> None: | |||||||
|         try: |         try: | ||||||
|             path_as_module = path_to_module(module) |             path_as_module = path_to_module(module) | ||||||
|             generate_typescript_defs(path_as_module, str(out_path), exclude=("MealieModel"))  # type: ignore |             generate_typescript_defs(path_as_module, str(out_path), exclude=("MealieModel"))  # type: ignore | ||||||
|         except Exception as e: |             clean_output_file(out_path) | ||||||
|  |         except Exception: | ||||||
|             failed_modules.append(module) |             failed_modules.append(module) | ||||||
|             log.error(f"Module Error: {e}") |             log.exception(f"Module Error: {module}") | ||||||
|  |  | ||||||
|     log.debug("\n📁 Skipped Directories:") |     log.debug("\n📁 Skipped Directories:") | ||||||
|     for skipped_dir in skipped_dirs: |     for skipped_dir in skipped_dirs: | ||||||
|   | |||||||
| @@ -162,6 +162,7 @@ export interface RecipeTool { | |||||||
|   name: string; |   name: string; | ||||||
|   slug: string; |   slug: string; | ||||||
|   onHand?: boolean; |   onHand?: boolean; | ||||||
|  |   [k: string]: unknown; | ||||||
| } | } | ||||||
| export interface CustomPageImport { | export interface CustomPageImport { | ||||||
|   name: string; |   name: string; | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ export interface CreateCookBook { | |||||||
|   slug?: string | null; |   slug?: string | null; | ||||||
|   position?: number; |   position?: number; | ||||||
|   public?: boolean; |   public?: boolean; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
| } | } | ||||||
| export interface ReadCookBook { | export interface ReadCookBook { | ||||||
|   name: string; |   name: string; | ||||||
| @@ -23,11 +23,11 @@ export interface ReadCookBook { | |||||||
|   slug?: string | null; |   slug?: string | null; | ||||||
|   position?: number; |   position?: number; | ||||||
|   public?: boolean; |   public?: boolean; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
|   id: string; |   id: string; | ||||||
|   queryFilter: QueryFilterJSON; |   queryFilter?: QueryFilterJSON; | ||||||
| } | } | ||||||
| export interface QueryFilterJSON { | export interface QueryFilterJSON { | ||||||
|   parts?: QueryFilterJSONPart[]; |   parts?: QueryFilterJSONPart[]; | ||||||
| @@ -47,11 +47,11 @@ export interface RecipeCookBook { | |||||||
|   slug?: string | null; |   slug?: string | null; | ||||||
|   position?: number; |   position?: number; | ||||||
|   public?: boolean; |   public?: boolean; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
|   id: string; |   id: string; | ||||||
|   queryFilter: QueryFilterJSON; |   queryFilter?: QueryFilterJSON; | ||||||
|   recipes: RecipeSummary[]; |   recipes: RecipeSummary[]; | ||||||
| } | } | ||||||
| export interface RecipeSummary { | export interface RecipeSummary { | ||||||
| @@ -106,7 +106,7 @@ export interface SaveCookBook { | |||||||
|   slug?: string | null; |   slug?: string | null; | ||||||
|   position?: number; |   position?: number; | ||||||
|   public?: boolean; |   public?: boolean; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
| } | } | ||||||
| @@ -116,7 +116,7 @@ export interface UpdateCookBook { | |||||||
|   slug?: string | null; |   slug?: string | null; | ||||||
|   position?: number; |   position?: number; | ||||||
|   public?: boolean; |   public?: boolean; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
|   id: string; |   id: string; | ||||||
|   | |||||||
| @@ -26,12 +26,14 @@ export interface CreateHouseholdPreferences { | |||||||
| } | } | ||||||
| export interface CreateInviteToken { | export interface CreateInviteToken { | ||||||
|   uses: number; |   uses: number; | ||||||
|  |   groupId?: string | null; | ||||||
|  |   householdId?: string | null; | ||||||
| } | } | ||||||
| export interface CreateWebhook { | export interface CreateWebhook { | ||||||
|   enabled?: boolean; |   enabled?: boolean; | ||||||
|   name?: string; |   name?: string; | ||||||
|   url?: string; |   url?: string; | ||||||
|   webhookType?: WebhookType & string; |   webhookType?: WebhookType; | ||||||
|   scheduledTime: string; |   scheduledTime: string; | ||||||
| } | } | ||||||
| export interface EmailInitationResponse { | export interface EmailInitationResponse { | ||||||
| @@ -46,10 +48,6 @@ export interface GroupEventNotifierCreate { | |||||||
|   name: string; |   name: string; | ||||||
|   appriseUrl?: string | null; |   appriseUrl?: string | null; | ||||||
| } | } | ||||||
| /** |  | ||||||
|  * These events are in-sync with the EventTypes found in the EventBusService. |  | ||||||
|  * If you modify this, make sure to update the EventBusService as well. |  | ||||||
|  */ |  | ||||||
| export interface GroupEventNotifierOptions { | export interface GroupEventNotifierOptions { | ||||||
|   testMessage?: boolean; |   testMessage?: boolean; | ||||||
|   webhookTask?: boolean; |   webhookTask?: boolean; | ||||||
| @@ -204,7 +202,7 @@ export interface ReadWebhook { | |||||||
|   enabled?: boolean; |   enabled?: boolean; | ||||||
|   name?: string; |   name?: string; | ||||||
|   url?: string; |   url?: string; | ||||||
|   webhookType?: WebhookType & string; |   webhookType?: WebhookType; | ||||||
|   scheduledTime: string; |   scheduledTime: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
| @@ -263,7 +261,7 @@ export interface SaveWebhook { | |||||||
|   enabled?: boolean; |   enabled?: boolean; | ||||||
|   name?: string; |   name?: string; | ||||||
|   url?: string; |   url?: string; | ||||||
|   webhookType?: WebhookType & string; |   webhookType?: WebhookType; | ||||||
|   scheduledTime: string; |   scheduledTime: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
| @@ -486,9 +484,6 @@ export interface ShoppingListItemUpdate { | |||||||
|   } | null; |   } | null; | ||||||
|   recipeReferences?: (ShoppingListItemRecipeRefCreate | ShoppingListItemRecipeRefUpdate)[]; |   recipeReferences?: (ShoppingListItemRecipeRefCreate | ShoppingListItemRecipeRefUpdate)[]; | ||||||
| } | } | ||||||
| /** |  | ||||||
|  * Only used for bulk update operations where the shopping list item id isn't already supplied |  | ||||||
|  */ |  | ||||||
| export interface ShoppingListItemUpdateBulk { | export interface ShoppingListItemUpdateBulk { | ||||||
|   quantity?: number; |   quantity?: number; | ||||||
|   unit?: IngredientUnit | CreateIngredientUnit | null; |   unit?: IngredientUnit | CreateIngredientUnit | null; | ||||||
| @@ -509,9 +504,6 @@ export interface ShoppingListItemUpdateBulk { | |||||||
|   recipeReferences?: (ShoppingListItemRecipeRefCreate | ShoppingListItemRecipeRefUpdate)[]; |   recipeReferences?: (ShoppingListItemRecipeRefCreate | ShoppingListItemRecipeRefUpdate)[]; | ||||||
|   id: string; |   id: string; | ||||||
| } | } | ||||||
| /** |  | ||||||
|  * Container for bulk shopping list item changes |  | ||||||
|  */ |  | ||||||
| export interface ShoppingListItemsCollectionOut { | export interface ShoppingListItemsCollectionOut { | ||||||
|   createdItems?: ShoppingListItemOut[]; |   createdItems?: ShoppingListItemOut[]; | ||||||
|   updatedItems?: ShoppingListItemOut[]; |   updatedItems?: ShoppingListItemOut[]; | ||||||
| @@ -565,6 +557,8 @@ export interface RecipeSummary { | |||||||
|   name?: string | null; |   name?: string | null; | ||||||
|   slug?: string; |   slug?: string; | ||||||
|   image?: unknown; |   image?: unknown; | ||||||
|  |   recipeServings?: number; | ||||||
|  |   recipeYieldQuantity?: number; | ||||||
|   recipeYield?: string | null; |   recipeYield?: string | null; | ||||||
|   totalTime?: string | null; |   totalTime?: string | null; | ||||||
|   prepTime?: string | null; |   prepTime?: string | null; | ||||||
| @@ -599,6 +593,7 @@ export interface RecipeTool { | |||||||
|   name: string; |   name: string; | ||||||
|   slug: string; |   slug: string; | ||||||
|   onHand?: boolean; |   onHand?: boolean; | ||||||
|  |   [k: string]: unknown; | ||||||
| } | } | ||||||
| export interface ShoppingListRemoveRecipeParams { | export interface ShoppingListRemoveRecipeParams { | ||||||
|   recipeDecrementQuantity?: number; |   recipeDecrementQuantity?: number; | ||||||
|   | |||||||
| @@ -12,21 +12,16 @@ export type LogicalOperator = "AND" | "OR"; | |||||||
| export type RelationalKeyword = "IS" | "IS NOT" | "IN" | "NOT IN" | "CONTAINS ALL" | "LIKE" | "NOT LIKE"; | export type RelationalKeyword = "IS" | "IS NOT" | "IN" | "NOT IN" | "CONTAINS ALL" | "LIKE" | "NOT LIKE"; | ||||||
| export type RelationalOperator = "=" | "<>" | ">" | "<" | ">=" | "<="; | export type RelationalOperator = "=" | "<>" | ">" | "<" | ">=" | "<="; | ||||||
|  |  | ||||||
| export interface Category { |  | ||||||
|   id: string; |  | ||||||
|   name: string; |  | ||||||
|   slug: string; |  | ||||||
| } |  | ||||||
| export interface CreatePlanEntry { | export interface CreatePlanEntry { | ||||||
|   date: string; |   date: string; | ||||||
|   entryType?: PlanEntryType & string; |   entryType?: PlanEntryType; | ||||||
|   title?: string; |   title?: string; | ||||||
|   text?: string; |   text?: string; | ||||||
|   recipeId?: string | null; |   recipeId?: string | null; | ||||||
| } | } | ||||||
| export interface CreateRandomEntry { | export interface CreateRandomEntry { | ||||||
|   date: string; |   date: string; | ||||||
|   entryType?: PlanEntryType & string; |   entryType?: PlanEntryType; | ||||||
| } | } | ||||||
| export interface ListItem { | export interface ListItem { | ||||||
|   title?: string | null; |   title?: string | null; | ||||||
| @@ -35,18 +30,18 @@ export interface ListItem { | |||||||
|   checked?: boolean; |   checked?: boolean; | ||||||
| } | } | ||||||
| export interface PlanRulesCreate { | export interface PlanRulesCreate { | ||||||
|   day?: PlanRulesDay & string; |   day?: PlanRulesDay; | ||||||
|   entryType?: PlanRulesType & string; |   entryType?: PlanRulesType; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
| } | } | ||||||
| export interface PlanRulesOut { | export interface PlanRulesOut { | ||||||
|   day?: PlanRulesDay & string; |   day?: PlanRulesDay; | ||||||
|   entryType?: PlanRulesType & string; |   entryType?: PlanRulesType; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
|   id: string; |   id: string; | ||||||
|   queryFilter: QueryFilterJSON; |   queryFilter?: QueryFilterJSON; | ||||||
| } | } | ||||||
| export interface QueryFilterJSON { | export interface QueryFilterJSON { | ||||||
|   parts?: QueryFilterJSONPart[]; |   parts?: QueryFilterJSONPart[]; | ||||||
| @@ -61,21 +56,21 @@ export interface QueryFilterJSONPart { | |||||||
|   [k: string]: unknown; |   [k: string]: unknown; | ||||||
| } | } | ||||||
| export interface PlanRulesSave { | export interface PlanRulesSave { | ||||||
|   day?: PlanRulesDay & string; |   day?: PlanRulesDay; | ||||||
|   entryType?: PlanRulesType & string; |   entryType?: PlanRulesType; | ||||||
|   queryFilterString: string; |   queryFilterString?: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
| } | } | ||||||
| export interface ReadPlanEntry { | export interface ReadPlanEntry { | ||||||
|   date: string; |   date: string; | ||||||
|   entryType?: PlanEntryType & string; |   entryType?: PlanEntryType; | ||||||
|   title?: string; |   title?: string; | ||||||
|   text?: string; |   text?: string; | ||||||
|   recipeId?: string | null; |   recipeId?: string | null; | ||||||
|   id: number; |   id: number; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   userId?: string | null; |   userId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
|   recipe?: RecipeSummary | null; |   recipe?: RecipeSummary | null; | ||||||
| } | } | ||||||
| @@ -127,12 +122,12 @@ export interface RecipeTool { | |||||||
| } | } | ||||||
| export interface SavePlanEntry { | export interface SavePlanEntry { | ||||||
|   date: string; |   date: string; | ||||||
|   entryType?: PlanEntryType & string; |   entryType?: PlanEntryType; | ||||||
|   title?: string; |   title?: string; | ||||||
|   text?: string; |   text?: string; | ||||||
|   recipeId?: string | null; |   recipeId?: string | null; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   userId?: string | null; |   userId: string; | ||||||
| } | } | ||||||
| export interface ShoppingListIn { | export interface ShoppingListIn { | ||||||
|   name: string; |   name: string; | ||||||
| @@ -147,11 +142,11 @@ export interface ShoppingListOut { | |||||||
| } | } | ||||||
| export interface UpdatePlanEntry { | export interface UpdatePlanEntry { | ||||||
|   date: string; |   date: string; | ||||||
|   entryType?: PlanEntryType & string; |   entryType?: PlanEntryType; | ||||||
|   title?: string; |   title?: string; | ||||||
|   text?: string; |   text?: string; | ||||||
|   recipeId?: string | null; |   recipeId?: string | null; | ||||||
|   id: number; |   id: number; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   userId?: string | null; |   userId: string; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,215 +6,37 @@ | |||||||
| */ | */ | ||||||
|  |  | ||||||
| export interface OpenAIIngredient { | export interface OpenAIIngredient { | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The input is simply the ingredient string you are processing as-is. It is forbidden to |  | ||||||
|    * modify this at all, you must provide the input exactly as you received it. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   input: string; |   input: string; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * This value is a float between 0 - 100, where 100 is full confidence that the result is correct, |  | ||||||
|    * and 0 is no confidence that the result is correct. If you're unable to parse anything, |  | ||||||
|    * and you put the entire string in the notes, you should return 0 confidence. If you can easily |  | ||||||
|    * parse the string into each component, then you should return a confidence of 100. If you have to |  | ||||||
|    * guess which part is the unit and which part is the food, your confidence should be lower, such as 60. |  | ||||||
|    * Even if there is no unit or note, if you're able to determine the food, you may use a higher confidence. |  | ||||||
|    * If the entire ingredient consists of only a food, you can use a confidence of 100. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   confidence?: number | null; |   confidence?: number | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The numerical representation of how much of this ingredient. For instance, if you receive |  | ||||||
|    * "3 1/2 grams of minced garlic", the quantity is "3 1/2". Quantity may be represented as a whole number |  | ||||||
|    * (integer), a float or decimal, or a fraction. You should output quantity in only whole numbers or |  | ||||||
|    * floats, converting fractions into floats. Floats longer than 10 decimal places should be |  | ||||||
|    * rounded to 10 decimal places. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   quantity?: number | null; |   quantity?: number | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The unit of measurement for this ingredient. For instance, if you receive |  | ||||||
|    * "2 lbs chicken breast", the unit is "lbs" (short for "pounds"). |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   unit?: string | null; |   unit?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The actual physical ingredient used in the recipe. For instance, if you receive |  | ||||||
|    * "3 cups of onions, chopped", the food is "onions". |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   food?: string | null; |   food?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The rest of the text that represents more detail on how to prepare the ingredient. |  | ||||||
|    * Anything that is not one of the above should be the note. For instance, if you receive |  | ||||||
|    * "one can of butter beans, drained" the note would be "drained". If you receive |  | ||||||
|    * "3 cloves of garlic peeled and finely chopped", the note would be "peeled and finely chopped". |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   note?: string | null; |   note?: string | null; | ||||||
| } | } | ||||||
| export interface OpenAIIngredients { | export interface OpenAIIngredients { | ||||||
|   ingredients?: OpenAIIngredient[]; |   ingredients?: OpenAIIngredient[]; | ||||||
| } | } | ||||||
| export interface OpenAIRecipe { | export interface OpenAIRecipe { | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The name or title of the recipe. If you're unable to determine the name of the recipe, you should |  | ||||||
|    * make your best guess based upon the ingredients and instructions provided. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   name: string; |   name: string; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * A long description of the recipe. This should be a string that describes the recipe in a few words |  | ||||||
|    * or sentences. If the recipe doesn't have a description, you should return None. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   description: string | null; |   description: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The yield of the recipe. For instance, if the recipe makes 12 cookies, the yield is "12 cookies". |  | ||||||
|    * If the recipe makes 2 servings, the yield is "2 servings". Typically yield consists of a number followed |  | ||||||
|    * by the word "serving" or "servings", but it can be any string that describes the yield. If the yield |  | ||||||
|    * isn't specified, you should return None. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   recipe_yield?: string | null; |   recipe_yield?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The total time it takes to make the recipe. This should be a string that describes a duration of time, |  | ||||||
|    * such as "1 hour and 30 minutes", "90 minutes", or "1.5 hours". If the recipe has multiple times, choose |  | ||||||
|    * the longest time. If the recipe doesn't specify a total time or duration, or it specifies a prep time or |  | ||||||
|    * perform time but not a total time, you should return None. Do not duplicate times between total time, prep |  | ||||||
|    * time and perform time. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   total_time?: string | null; |   total_time?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The time it takes to prepare the recipe. This should be a string that describes a duration of time, |  | ||||||
|    * such as "30 minutes", "1 hour", or "1.5 hours". If the recipe has a total time, the prep time should be |  | ||||||
|    * less than the total time. If the recipe doesn't specify a prep time, you should return None. If the recipe |  | ||||||
|    * supplies only one time, it should be the total time. Do not duplicate times between total time, prep |  | ||||||
|    * time and coperformok time. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   prep_time?: string | null; |   prep_time?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The time it takes to cook the recipe. This should be a string that describes a duration of time, |  | ||||||
|    * such as "30 minutes", "1 hour", or "1.5 hours". If the recipe has a total time, the perform time should be |  | ||||||
|    * less than the total time. If the recipe doesn't specify a perform time, you should return None. If the |  | ||||||
|    * recipe specifies a cook time, active time, or other time besides total or prep, you should use that |  | ||||||
|    * time as the perform time. If the recipe supplies only one time, it should be the total time, and not the |  | ||||||
|    * perform time. Do not duplicate times between total time, prep time and perform time. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   perform_time?: string | null; |   perform_time?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * A list of ingredients used in the recipe. Ingredients should be inserted in the order they appear in the |  | ||||||
|    * recipe. If the recipe has no ingredients, you should return an empty list. |  | ||||||
|    * |  | ||||||
|    * Often times, but not always, ingredients are separated by line breaks. Use these as a guide to |  | ||||||
|    * separate ingredients. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   ingredients?: OpenAIRecipeIngredient[]; |   ingredients?: OpenAIRecipeIngredient[]; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * A list of ingredients used in the recipe. Ingredients should be inserted in the order they appear in the |  | ||||||
|    * recipe. If the recipe has no ingredients, you should return an empty list. |  | ||||||
|    * |  | ||||||
|    * Often times, but not always, instructions are separated by line breaks and/or separated by paragraphs. |  | ||||||
|    * Use these as a guide to separate instructions. They also may be separated by numbers or words, such as |  | ||||||
|    * "1.", "2.", "Step 1", "Step 2", "First", "Second", etc. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   instructions?: OpenAIRecipeInstruction[]; |   instructions?: OpenAIRecipeInstruction[]; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * A list of notes found in the recipe. Notes should be inserted in the order they appear in the recipe. |  | ||||||
|    * They may appear anywhere on the recipe, though they are typically found under the instructions. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   notes?: OpenAIRecipeNotes[]; |   notes?: OpenAIRecipeNotes[]; | ||||||
| } | } | ||||||
| export interface OpenAIRecipeIngredient { | export interface OpenAIRecipeIngredient { | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The title of the section of the recipe that the ingredient is found in. Recipes may not specify |  | ||||||
|    * ingredient sections, in which case this should be left blank. |  | ||||||
|    * Only the first item in the section should have this set, |  | ||||||
|    * whereas subsuquent items should have their titles left blank (unless they start a new section). |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   title?: string | null; |   title?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The text of the ingredient. This should represent the entire ingredient, such as "1 cup of flour" or |  | ||||||
|    * "2 cups of onions, chopped". If the ingredient is completely blank, skip it and do not add the ingredient, |  | ||||||
|    * since this field is required. |  | ||||||
|    * |  | ||||||
|    * If the ingredient has no text, but has a title, include the title on the |  | ||||||
|    * next ingredient instead. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   text: string; |   text: string; | ||||||
| } | } | ||||||
| export interface OpenAIRecipeInstruction { | export interface OpenAIRecipeInstruction { | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The title of the section of the recipe that the instruction is found in. Recipes may not specify |  | ||||||
|    * instruction sections, in which case this should be left blank. |  | ||||||
|    * Only the first instruction in the section should have this set, |  | ||||||
|    * whereas subsuquent instructions should have their titles left blank (unless they start a new section). |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   title?: string | null; |   title?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The text of the instruction. This represents one step in the recipe, such as "Preheat the oven to 350", |  | ||||||
|    * or "Sauté the onions for 20 minutes". Sometimes steps can be longer, such as "Bring a large pot of lightly |  | ||||||
|    * salted water to a boil. Add ditalini pasta and cook for 8 minutes or until al dente; drain.". |  | ||||||
|    * |  | ||||||
|    * Sometimes, but not always, recipes will include their number in front of the text, such as |  | ||||||
|    * "1.", "2.", or "Step 1", "Step 2", or "First", "Second". In the case where they are directly numbered |  | ||||||
|    * ("1.", "2.", "Step one", "Step 1", "Step two", "Step 2", etc.), you should not include the number in |  | ||||||
|    * the text. However, if they use words ("First", "Second", etc.), then those should be included. |  | ||||||
|    * |  | ||||||
|    * If the instruction is completely blank, skip it and do not add the instruction, since this field is |  | ||||||
|    * required. If the ingredient has no text, but has a title, include the title on the next |  | ||||||
|    * instruction instead. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   text: string; |   text: string; | ||||||
| } | } | ||||||
| export interface OpenAIRecipeNotes { | export interface OpenAIRecipeNotes { | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The title of the note. Notes may not specify a title, and just have a body of text. In this case, |  | ||||||
|    * title should be left blank, and all content should go in the note text. If the note title is just |  | ||||||
|    * "note" or "info", you should ignore it and leave the title blank. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   title?: string | null; |   title?: string | null; | ||||||
|   /** |  | ||||||
|    * |  | ||||||
|    * The text of the note. This should represent the entire note, such as "This recipe is great for |  | ||||||
|    * a summer picnic" or "This recipe is a family favorite". They may also include additional prep |  | ||||||
|    * instructions such as "to make this recipe gluten free, use gluten free flour", or "you may prepare |  | ||||||
|    * the dough the night before and refrigerate it until ready to bake". |  | ||||||
|    * |  | ||||||
|    * If the note is completely blank, skip it and do not add the note, since this field is required. |  | ||||||
|    * |  | ||||||
|    */ |  | ||||||
|   text: string; |   text: string; | ||||||
| } | } | ||||||
| export interface OpenAIBase {} | export interface OpenAIBase {} | ||||||
|   | |||||||
| @@ -116,7 +116,7 @@ export interface ExportBase { | |||||||
| } | } | ||||||
| export interface ExportRecipes { | export interface ExportRecipes { | ||||||
|   recipes: string[]; |   recipes: string[]; | ||||||
|   exportType?: ExportTypes & string; |   exportType?: ExportTypes; | ||||||
| } | } | ||||||
| export interface IngredientConfidence { | export interface IngredientConfidence { | ||||||
|   average?: number | null; |   average?: number | null; | ||||||
| @@ -150,14 +150,11 @@ export interface MultiPurposeLabelSummary { | |||||||
|   groupId: string; |   groupId: string; | ||||||
|   id: string; |   id: string; | ||||||
| } | } | ||||||
| /** |  | ||||||
|  * A list of ingredient references. |  | ||||||
|  */ |  | ||||||
| export interface IngredientReferences { | export interface IngredientReferences { | ||||||
|   referenceId?: string | null; |   referenceId?: string | null; | ||||||
| } | } | ||||||
| export interface IngredientRequest { | export interface IngredientRequest { | ||||||
|   parser?: RegisteredParser & string; |   parser?: RegisteredParser; | ||||||
|   ingredient: string; |   ingredient: string; | ||||||
| } | } | ||||||
| export interface IngredientUnit { | export interface IngredientUnit { | ||||||
| @@ -181,7 +178,7 @@ export interface IngredientUnitAlias { | |||||||
|   name: string; |   name: string; | ||||||
| } | } | ||||||
| export interface IngredientsRequest { | export interface IngredientsRequest { | ||||||
|   parser?: RegisteredParser & string; |   parser?: RegisteredParser; | ||||||
|   ingredients: string[]; |   ingredients: string[]; | ||||||
| } | } | ||||||
| export interface MergeFood { | export interface MergeFood { | ||||||
| @@ -268,9 +265,9 @@ export interface RecipeTool { | |||||||
| export interface RecipeStep { | export interface RecipeStep { | ||||||
|   id?: string | null; |   id?: string | null; | ||||||
|   title?: string | null; |   title?: string | null; | ||||||
|  |   summary?: string | null; | ||||||
|   text: string; |   text: string; | ||||||
|   ingredientReferences?: IngredientReferences[]; |   ingredientReferences?: IngredientReferences[]; | ||||||
|   summary?: string | null; |  | ||||||
| } | } | ||||||
| export interface RecipeAsset { | export interface RecipeAsset { | ||||||
|   name: string; |   name: string; | ||||||
| @@ -495,7 +492,7 @@ export interface ScrapeRecipeTest { | |||||||
|   url: string; |   url: string; | ||||||
|   useOpenAI?: boolean; |   useOpenAI?: boolean; | ||||||
| } | } | ||||||
| export interface SlugResponse { } | export interface SlugResponse {} | ||||||
| export interface TagIn { | export interface TagIn { | ||||||
|   name: string; |   name: string; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ export interface ReportCreate { | |||||||
|   category: ReportCategory; |   category: ReportCategory; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   name: string; |   name: string; | ||||||
|   status?: ReportSummaryStatus & string; |   status?: ReportSummaryStatus; | ||||||
| } | } | ||||||
| export interface ReportEntryCreate { | export interface ReportEntryCreate { | ||||||
|   reportId: string; |   reportId: string; | ||||||
| @@ -35,7 +35,7 @@ export interface ReportOut { | |||||||
|   category: ReportCategory; |   category: ReportCategory; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   name: string; |   name: string; | ||||||
|   status?: ReportSummaryStatus & string; |   status?: ReportSummaryStatus; | ||||||
|   id: string; |   id: string; | ||||||
|   entries?: ReportEntryOut[]; |   entries?: ReportEntryOut[]; | ||||||
| } | } | ||||||
| @@ -44,6 +44,6 @@ export interface ReportSummary { | |||||||
|   category: ReportCategory; |   category: ReportCategory; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   name: string; |   name: string; | ||||||
|   status?: ReportSummaryStatus & string; |   status?: ReportSummaryStatus; | ||||||
|   id: string; |   id: string; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ export interface PaginationQuery { | |||||||
|   perPage?: number; |   perPage?: number; | ||||||
|   orderBy?: string | null; |   orderBy?: string | null; | ||||||
|   orderByNullPosition?: OrderByNullPosition | null; |   orderByNullPosition?: OrderByNullPosition | null; | ||||||
|   orderDirection?: OrderDirection & string; |   orderDirection?: OrderDirection; | ||||||
|   queryFilter?: string | null; |   queryFilter?: string | null; | ||||||
|   paginationSeed?: string | null; |   paginationSeed?: string | null; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -69,7 +69,7 @@ export interface ReadWebhook { | |||||||
|   enabled?: boolean; |   enabled?: boolean; | ||||||
|   name?: string; |   name?: string; | ||||||
|   url?: string; |   url?: string; | ||||||
|   webhookType?: WebhookType & string; |   webhookType?: WebhookType; | ||||||
|   scheduledTime: string; |   scheduledTime: string; | ||||||
|   groupId: string; |   groupId: string; | ||||||
|   householdId: string; |   householdId: string; | ||||||
| @@ -110,7 +110,7 @@ export interface PrivateUser { | |||||||
|   username?: string | null; |   username?: string | null; | ||||||
|   fullName?: string | null; |   fullName?: string | null; | ||||||
|   email: string; |   email: string; | ||||||
|   authMethod?: AuthMethod & string; |   authMethod?: AuthMethod; | ||||||
|   admin?: boolean; |   admin?: boolean; | ||||||
|   group: string; |   group: string; | ||||||
|   household: string; |   household: string; | ||||||
| @@ -175,7 +175,7 @@ export interface CreateWebhook { | |||||||
|   enabled?: boolean; |   enabled?: boolean; | ||||||
|   name?: string; |   name?: string; | ||||||
|   url?: string; |   url?: string; | ||||||
|   webhookType?: WebhookType & string; |   webhookType?: WebhookType; | ||||||
|   scheduledTime: string; |   scheduledTime: string; | ||||||
| } | } | ||||||
| export interface UserBase { | export interface UserBase { | ||||||
| @@ -183,7 +183,7 @@ export interface UserBase { | |||||||
|   username?: string | null; |   username?: string | null; | ||||||
|   fullName?: string | null; |   fullName?: string | null; | ||||||
|   email: string; |   email: string; | ||||||
|   authMethod?: AuthMethod & string; |   authMethod?: AuthMethod; | ||||||
|   admin?: boolean; |   admin?: boolean; | ||||||
|   group?: string | null; |   group?: string | null; | ||||||
|   household?: string | null; |   household?: string | null; | ||||||
| @@ -195,10 +195,10 @@ export interface UserBase { | |||||||
| } | } | ||||||
| export interface UserIn { | export interface UserIn { | ||||||
|   id?: string | null; |   id?: string | null; | ||||||
|   username?: string | null; |   username: string; | ||||||
|   fullName?: string | null; |   fullName: string; | ||||||
|   email: string; |   email: string; | ||||||
|   authMethod?: AuthMethod & string; |   authMethod?: AuthMethod; | ||||||
|   admin?: boolean; |   admin?: boolean; | ||||||
|   group?: string | null; |   group?: string | null; | ||||||
|   household?: string | null; |   household?: string | null; | ||||||
| @@ -214,7 +214,7 @@ export interface UserOut { | |||||||
|   username?: string | null; |   username?: string | null; | ||||||
|   fullName?: string | null; |   fullName?: string | null; | ||||||
|   email: string; |   email: string; | ||||||
|   authMethod?: AuthMethod & string; |   authMethod?: AuthMethod; | ||||||
|   admin?: boolean; |   admin?: boolean; | ||||||
|   group: string; |   group: string; | ||||||
|   household: string; |   household: string; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user