healthy-meals-core 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/bmr.d.ts +3 -0
  2. package/dist/bmr.js +14 -0
  3. package/dist/dailyMealPlanGenerator.d.ts +3 -0
  4. package/dist/dailyMealPlanGenerator.js +211 -0
  5. package/dist/data/detailed-recipes-bs.json +417 -0
  6. package/dist/data/detailed-recipes.json +744 -0
  7. package/dist/foodConversion.d.ts +55 -0
  8. package/dist/foodConversion.js +200 -0
  9. package/dist/index.d.ts +12 -0
  10. package/dist/index.js +27 -0
  11. package/dist/planner.d.ts +2 -0
  12. package/dist/planner.js +24 -0
  13. package/dist/recipeBasedMealPlanGenerator.d.ts +17 -0
  14. package/dist/recipeBasedMealPlanGenerator.js +255 -0
  15. package/dist/recipeService.d.ts +28 -0
  16. package/dist/recipeService.js +136 -0
  17. package/dist/rules/cholesterol.d.ts +2 -0
  18. package/dist/rules/cholesterol.js +7 -0
  19. package/dist/rules/diabetes.d.ts +2 -0
  20. package/dist/rules/diabetes.js +7 -0
  21. package/dist/rules/fattyLiver.d.ts +2 -0
  22. package/dist/rules/fattyLiver.js +7 -0
  23. package/dist/rules/index.d.ts +7 -0
  24. package/dist/rules/index.js +47 -0
  25. package/dist/rules/lowCarb.d.ts +2 -0
  26. package/dist/rules/lowCarb.js +7 -0
  27. package/dist/rules/triglycerides.d.ts +2 -0
  28. package/dist/rules/triglycerides.js +7 -0
  29. package/dist/src/bmr.d.ts +3 -0
  30. package/dist/src/bmr.js +13 -0
  31. package/dist/src/dailyMealPlanGenerator.d.ts +3 -0
  32. package/dist/src/dailyMealPlanGenerator.js +210 -0
  33. package/dist/src/foodConversion.d.ts +55 -0
  34. package/dist/src/foodConversion.js +199 -0
  35. package/dist/src/index.d.ts +12 -0
  36. package/dist/src/index.js +27 -0
  37. package/dist/src/planner.d.ts +2 -0
  38. package/dist/src/planner.js +23 -0
  39. package/dist/src/recipeBasedMealPlanGenerator.d.ts +17 -0
  40. package/dist/src/recipeBasedMealPlanGenerator.js +254 -0
  41. package/dist/src/recipeService.d.ts +28 -0
  42. package/dist/src/recipeService.js +136 -0
  43. package/dist/src/rules/cholesterol.d.ts +2 -0
  44. package/dist/src/rules/cholesterol.js +6 -0
  45. package/dist/src/rules/diabetes.d.ts +2 -0
  46. package/dist/src/rules/diabetes.js +6 -0
  47. package/dist/src/rules/fattyLiver.d.ts +2 -0
  48. package/dist/src/rules/fattyLiver.js +6 -0
  49. package/dist/src/rules/index.d.ts +7 -0
  50. package/dist/src/rules/index.js +46 -0
  51. package/dist/src/rules/lowCarb.d.ts +2 -0
  52. package/dist/src/rules/lowCarb.js +6 -0
  53. package/dist/src/rules/triglycerides.d.ts +2 -0
  54. package/dist/src/rules/triglycerides.js +6 -0
  55. package/dist/src/types/firestore.d.ts +100 -0
  56. package/dist/src/types/firestore.js +2 -0
  57. package/dist/src/types/openfoodfacts.d.ts +113 -0
  58. package/dist/src/types/openfoodfacts.js +3 -0
  59. package/dist/src/types/recipe.d.ts +36 -0
  60. package/dist/src/types/recipe.js +2 -0
  61. package/dist/src/types.d.ts +24 -0
  62. package/dist/src/types.js +2 -0
  63. package/dist/src/variety.d.ts +17 -0
  64. package/dist/src/variety.js +129 -0
  65. package/dist/src/weeklyMealPlanGenerator.d.ts +3 -0
  66. package/dist/src/weeklyMealPlanGenerator.js +468 -0
  67. package/dist/src/weeklyPlanner.d.ts +12 -0
  68. package/dist/src/weeklyPlanner.js +31 -0
  69. package/dist/types/firestore.d.ts +100 -0
  70. package/dist/types/firestore.js +2 -0
  71. package/dist/types/openfoodfacts.d.ts +113 -0
  72. package/dist/types/openfoodfacts.js +3 -0
  73. package/dist/types/recipe.d.ts +36 -0
  74. package/dist/types/recipe.js +2 -0
  75. package/dist/types.d.ts +24 -0
  76. package/dist/types.js +2 -0
  77. package/dist/variety.d.ts +17 -0
  78. package/dist/variety.js +130 -0
  79. package/dist/weeklyMealPlanGenerator.d.ts +3 -0
  80. package/dist/weeklyMealPlanGenerator.js +469 -0
  81. package/dist/weeklyPlanner.d.ts +12 -0
  82. package/dist/weeklyPlanner.js +32 -0
  83. package/package.json +66 -0
@@ -0,0 +1,55 @@
1
+ import { NormalizedFoodItem } from './types/openfoodfacts';
2
+ import { Meal, Ingredient } from './types/firestore';
3
+ export interface ExtendedIngredient extends Ingredient {
4
+ barcode?: string;
5
+ brand?: string;
6
+ nutritionGrade?: string;
7
+ ecoScore?: string;
8
+ allergens?: string[];
9
+ }
10
+ /**
11
+ * Convert Open Food Facts item to Ingredient for meal planning
12
+ */
13
+ export declare function convertFoodItemToIngredient(foodItem: NormalizedFoodItem, amount?: number, unit?: string): Ingredient;
14
+ /**
15
+ * Calculate total nutrition for a list of ingredients
16
+ */
17
+ export declare function calculateTotalNutrition(ingredients: Ingredient[]): {
18
+ calories: number;
19
+ protein: number;
20
+ carbs: number;
21
+ fat: number;
22
+ fiber: number;
23
+ sugar: number;
24
+ sodium: number;
25
+ };
26
+ /**
27
+ * Create a meal from selected food items
28
+ */
29
+ export declare function createMealFromFoodItems(name: string, type: 'breakfast' | 'lunch' | 'dinner' | 'snack', foodItems: Array<{
30
+ food: NormalizedFoodItem;
31
+ amount: number;
32
+ unit: string;
33
+ }>): Meal;
34
+ /**
35
+ * Get nutrition density score (protein per calorie ratio)
36
+ */
37
+ export declare function getNutritionDensityScore(foodItem: NormalizedFoodItem): number;
38
+ /**
39
+ * Check if food item meets dietary restrictions
40
+ */
41
+ export declare function checkDietaryRestrictions(foodItem: NormalizedFoodItem, restrictions: string[]): {
42
+ meets: boolean;
43
+ violations: string[];
44
+ };
45
+ /**
46
+ * Get recommended serving size based on meal type and nutrition goals
47
+ */
48
+ export declare function getRecommendedServingSize(foodItem: NormalizedFoodItem, mealType: 'breakfast' | 'lunch' | 'dinner' | 'snack', targetCalories?: number): {
49
+ amount: number;
50
+ unit: string;
51
+ };
52
+ /**
53
+ * Filter foods by health goals
54
+ */
55
+ export declare function filterFoodsByHealthGoals(foods: NormalizedFoodItem[], healthGoals: string[]): NormalizedFoodItem[];
@@ -0,0 +1,200 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.filterFoodsByHealthGoals = exports.getRecommendedServingSize = exports.checkDietaryRestrictions = exports.getNutritionDensityScore = exports.createMealFromFoodItems = exports.calculateTotalNutrition = exports.convertFoodItemToIngredient = void 0;
4
+ /**
5
+ * Convert Open Food Facts item to Ingredient for meal planning
6
+ */
7
+ function convertFoodItemToIngredient(foodItem, amount = 100, unit = 'g') {
8
+ // Calculate nutrition values based on amount (default is per 100g)
9
+ const multiplier = amount / 100;
10
+ return {
11
+ id: `${foodItem.name.toLowerCase().replace(/\s+/g, '-')}-${Date.now()}`,
12
+ name: foodItem.name,
13
+ quantity: amount,
14
+ unit,
15
+ calories: Math.round((foodItem.nutritionPer100g?.calories || 0) * multiplier) || 0,
16
+ protein: Math.round(((foodItem.nutritionPer100g?.protein || 0) * multiplier * 10)) / 10 || 0,
17
+ carbs: Math.round(((foodItem.nutritionPer100g?.carbs || 0) * multiplier * 10)) / 10 || 0,
18
+ fat: Math.round(((foodItem.nutritionPer100g?.fat || 0) * multiplier * 10)) / 10 || 0,
19
+ fiber: Math.round(((foodItem.nutritionPer100g?.fiber || 0) * multiplier * 10)) / 10 || 0,
20
+ sugar: Math.round(((foodItem.nutritionPer100g?.sugar || 0) * multiplier * 10)) / 10 || 0,
21
+ sodium: Math.round(((foodItem.nutritionPer100g?.sodium || 0) * multiplier * 10)) / 10 || 0,
22
+ };
23
+ }
24
+ exports.convertFoodItemToIngredient = convertFoodItemToIngredient;
25
+ /**
26
+ * Calculate total nutrition for a list of ingredients
27
+ */
28
+ function calculateTotalNutrition(ingredients) {
29
+ return ingredients.reduce((total, ingredient) => ({
30
+ calories: total.calories + (ingredient.calories || 0),
31
+ protein: Math.round((total.protein + (ingredient.protein || 0)) * 10) / 10,
32
+ carbs: Math.round((total.carbs + (ingredient.carbs || 0)) * 10) / 10,
33
+ fat: Math.round((total.fat + (ingredient.fat || 0)) * 10) / 10,
34
+ fiber: Math.round((total.fiber + (ingredient.fiber || 0)) * 10) / 10,
35
+ sugar: Math.round((total.sugar + (ingredient.sugar || 0)) * 10) / 10,
36
+ sodium: Math.round((total.sodium + (ingredient.sodium || 0)) * 10) / 10,
37
+ }), { calories: 0, protein: 0, carbs: 0, fat: 0, fiber: 0, sugar: 0, sodium: 0 });
38
+ }
39
+ exports.calculateTotalNutrition = calculateTotalNutrition;
40
+ /**
41
+ * Create a meal from selected food items
42
+ */
43
+ function createMealFromFoodItems(name, type, foodItems) {
44
+ const ingredients = foodItems.map(({ food, amount, unit }) => convertFoodItemToIngredient(food, amount, unit));
45
+ const nutrition = calculateTotalNutrition(ingredients);
46
+ return {
47
+ id: `${type}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
48
+ name,
49
+ type,
50
+ ingredients,
51
+ nutrition: {
52
+ calories: nutrition.calories,
53
+ protein: nutrition.protein,
54
+ carbs: nutrition.carbs,
55
+ fat: nutrition.fat,
56
+ fiber: nutrition.fiber,
57
+ sugar: nutrition.sugar,
58
+ sodium: nutrition.sodium,
59
+ },
60
+ instructions: [],
61
+ prepTime: 15,
62
+ cookTime: 20,
63
+ servings: 1,
64
+ tags: [type],
65
+ difficulty: 'easy',
66
+ createdAt: new Date(),
67
+ updatedAt: new Date(),
68
+ };
69
+ }
70
+ exports.createMealFromFoodItems = createMealFromFoodItems;
71
+ /**
72
+ * Get nutrition density score (protein per calorie ratio)
73
+ */
74
+ function getNutritionDensityScore(foodItem) {
75
+ if (foodItem.nutritionPer100g.calories === 0)
76
+ return 0;
77
+ return foodItem.nutritionPer100g.protein / foodItem.nutritionPer100g.calories;
78
+ }
79
+ exports.getNutritionDensityScore = getNutritionDensityScore;
80
+ /**
81
+ * Check if food item meets dietary restrictions
82
+ */
83
+ function checkDietaryRestrictions(foodItem, restrictions) {
84
+ const violations = [];
85
+ // Check categories for dietary restrictions
86
+ const categories = foodItem.categories?.map(c => c.toLowerCase()) || [];
87
+ const ingredients = foodItem.ingredients?.toLowerCase() || '';
88
+ const allergens = foodItem.allergens?.map(a => a.toLowerCase()) || [];
89
+ restrictions.forEach(restriction => {
90
+ const restrictionLower = restriction.toLowerCase();
91
+ switch (restrictionLower) {
92
+ case 'vegetarian':
93
+ if (categories.some((cat) => cat.includes('meat') || cat.includes('fish') || cat.includes('poultry'))) {
94
+ violations.push('Contains meat/fish');
95
+ }
96
+ break;
97
+ case 'vegan':
98
+ if (categories.some((cat) => cat.includes('meat') || cat.includes('fish') || cat.includes('dairy') ||
99
+ cat.includes('eggs') || cat.includes('honey')) || ingredients.includes('milk') || ingredients.includes('egg')) {
100
+ violations.push('Contains animal products');
101
+ }
102
+ break;
103
+ case 'gluten-free':
104
+ if (allergens.includes('gluten') || ingredients.includes('wheat') ||
105
+ ingredients.includes('barley') || ingredients.includes('rye')) {
106
+ violations.push('Contains gluten');
107
+ }
108
+ break;
109
+ case 'dairy-free':
110
+ if (allergens.includes('milk') || categories.some((cat) => cat.includes('dairy')) ||
111
+ ingredients.includes('milk') || ingredients.includes('lactose')) {
112
+ violations.push('Contains dairy');
113
+ }
114
+ break;
115
+ case 'nut-free':
116
+ if (allergens.some((a) => a.includes('nut')) || ingredients.includes('nuts')) {
117
+ violations.push('Contains nuts');
118
+ }
119
+ break;
120
+ }
121
+ });
122
+ return {
123
+ meets: violations.length === 0,
124
+ violations
125
+ };
126
+ }
127
+ exports.checkDietaryRestrictions = checkDietaryRestrictions;
128
+ /**
129
+ * Get recommended serving size based on meal type and nutrition goals
130
+ */
131
+ function getRecommendedServingSize(foodItem, mealType, targetCalories) {
132
+ // Default serving size from product data
133
+ if (foodItem.servingSize) {
134
+ const match = foodItem.servingSize.match(/(\d+(?:\.\d+)?)\s*(\w+)/);
135
+ if (match) {
136
+ return {
137
+ amount: parseFloat(match[1]),
138
+ unit: match[2]
139
+ };
140
+ }
141
+ }
142
+ // Calculate based on target calories if provided
143
+ if (targetCalories && foodItem.nutritionPer100g.calories > 0) {
144
+ const amount = Math.round((targetCalories / foodItem.nutritionPer100g.calories) * 100);
145
+ return { amount, unit: 'g' };
146
+ }
147
+ // Default serving sizes by meal type
148
+ const defaultServings = {
149
+ breakfast: 150,
150
+ lunch: 200,
151
+ dinner: 200,
152
+ snack: 50 // g
153
+ };
154
+ return {
155
+ amount: defaultServings[mealType],
156
+ unit: 'g'
157
+ };
158
+ }
159
+ exports.getRecommendedServingSize = getRecommendedServingSize;
160
+ /**
161
+ * Filter foods by health goals
162
+ */
163
+ function filterFoodsByHealthGoals(foods, healthGoals) {
164
+ return foods.filter(food => {
165
+ for (const goal of healthGoals) {
166
+ switch (goal.toLowerCase()) {
167
+ case 'weight_loss':
168
+ // Prefer low-calorie, high-protein foods
169
+ if (food.nutritionPer100g.calories > 300 ||
170
+ getNutritionDensityScore(food) < 0.05) {
171
+ return false;
172
+ }
173
+ break;
174
+ case 'muscle_gain':
175
+ // Prefer high-protein foods
176
+ if (food.nutritionPer100g.protein < 10) {
177
+ return false;
178
+ }
179
+ break;
180
+ case 'heart_health':
181
+ // Prefer foods with good nutrition grades and low sodium
182
+ if (food.nutritionGrade && !['a', 'b'].includes(food.nutritionGrade.toLowerCase())) {
183
+ return false;
184
+ }
185
+ if (food.nutritionPer100g.sodium && food.nutritionPer100g.sodium > 600) {
186
+ return false;
187
+ }
188
+ break;
189
+ case 'diabetes_management':
190
+ // Prefer low-sugar, high-fiber foods
191
+ if (food.nutritionPer100g.sugar && food.nutritionPer100g.sugar > 15) {
192
+ return false;
193
+ }
194
+ break;
195
+ }
196
+ }
197
+ return true;
198
+ });
199
+ }
200
+ exports.filterFoodsByHealthGoals = filterFoodsByHealthGoals;
@@ -0,0 +1,12 @@
1
+ export { UserProfile, HealthCondition, Gender } from './types';
2
+ export * from './bmr';
3
+ export * from './planner';
4
+ export * from './rules';
5
+ export * from './weeklyPlanner';
6
+ export * from './variety';
7
+ export * from './dailyMealPlanGenerator';
8
+ export * from './weeklyMealPlanGenerator';
9
+ export * from './foodConversion';
10
+ export * from './types/recipe';
11
+ export * from './recipeService';
12
+ export * from './recipeBasedMealPlanGenerator';
package/dist/index.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./bmr"), exports);
18
+ __exportStar(require("./planner"), exports);
19
+ __exportStar(require("./rules"), exports);
20
+ __exportStar(require("./weeklyPlanner"), exports);
21
+ __exportStar(require("./variety"), exports);
22
+ __exportStar(require("./dailyMealPlanGenerator"), exports);
23
+ __exportStar(require("./weeklyMealPlanGenerator"), exports);
24
+ __exportStar(require("./foodConversion"), exports);
25
+ __exportStar(require("./types/recipe"), exports);
26
+ __exportStar(require("./recipeService"), exports);
27
+ __exportStar(require("./recipeBasedMealPlanGenerator"), exports);
@@ -0,0 +1,2 @@
1
+ import { Recipe, MealPlan, UserProfile } from './types';
2
+ export declare function generateDailyPlan(profile: UserProfile, recipes: Recipe[]): MealPlan;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateDailyPlan = void 0;
4
+ const bmr_1 = require("./bmr");
5
+ const rules_1 = require("./rules");
6
+ function generateDailyPlan(profile, recipes) {
7
+ const targetCalories = Math.round((0, bmr_1.calculateTDEE)(profile));
8
+ const filtered = (0, rules_1.applyHealthRules)(recipes, profile.conditions);
9
+ let total = 0;
10
+ const meals = [];
11
+ for (const recipe of filtered) {
12
+ if (total + recipe.calories <= targetCalories) {
13
+ meals.push(recipe);
14
+ total += recipe.calories;
15
+ }
16
+ if (total >= targetCalories * 0.95)
17
+ break;
18
+ }
19
+ return {
20
+ dailyCalories: total,
21
+ meals
22
+ };
23
+ }
24
+ exports.generateDailyPlan = generateDailyPlan;
@@ -0,0 +1,17 @@
1
+ import { UserProfile, MealPlan, Meal } from './types/firestore';
2
+ import { Recipe } from './types/recipe';
3
+ /**
4
+ * Generate a daily meal plan using recipes from the recipe database
5
+ * Each meal will have complete ingredients and cooking instructions
6
+ */
7
+ export declare function generateDailyMealPlanWithRecipes(profile: UserProfile, userId: string): MealPlan;
8
+ /**
9
+ * Generate a weekly meal plan using recipes from the recipe database
10
+ * Each day will have 4 meals with complete ingredients and cooking instructions
11
+ */
12
+ export declare function generateWeeklyMealPlanWithRecipes(profile: UserProfile, userId: string): MealPlan;
13
+ /**
14
+ * Get recipe details for a meal in a meal plan
15
+ * This allows you to retrieve the full recipe with instructions for any meal
16
+ */
17
+ export declare function getRecipeForMeal(meal: Meal): Recipe | undefined;
@@ -0,0 +1,255 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRecipeForMeal = exports.generateWeeklyMealPlanWithRecipes = exports.generateDailyMealPlanWithRecipes = void 0;
4
+ const recipeService_1 = require("./recipeService");
5
+ function calculateDailyNeeds(profile) {
6
+ const age = profile.age || 30;
7
+ const height = profile.height || 170;
8
+ const weight = profile.weight || 70;
9
+ const gender = profile.gender || 'male';
10
+ const activityLevel = profile.activityLevel || 'moderately_active';
11
+ const bmr = gender === 'male'
12
+ ? 88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age)
13
+ : 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age);
14
+ const activityMultipliers = {
15
+ sedentary: 1.2,
16
+ lightly_active: 1.375,
17
+ moderately_active: 1.55,
18
+ very_active: 1.725,
19
+ extremely_active: 1.9
20
+ };
21
+ const tdee = bmr * (activityMultipliers[activityLevel] || 1.2);
22
+ let dailyCalories = tdee;
23
+ if (profile.healthGoals?.includes('weight_loss')) {
24
+ dailyCalories -= 500;
25
+ }
26
+ else if (profile.healthGoals?.includes('weight_gain')) {
27
+ dailyCalories += 500;
28
+ }
29
+ return {
30
+ calories: Math.round(Math.max(dailyCalories, 1200)),
31
+ protein: Math.round(Math.max(dailyCalories * 0.3 / 4, 50)),
32
+ carbs: Math.round(Math.max(dailyCalories * 0.4 / 4, 100)),
33
+ fat: Math.round(Math.max(dailyCalories * 0.3 / 9, 30))
34
+ };
35
+ }
36
+ function convertRecipeToMeal(recipe) {
37
+ return {
38
+ id: recipe.id,
39
+ name: recipe.name,
40
+ type: recipe.category,
41
+ ingredients: recipe.ingredients.map(ing => ({
42
+ id: `${recipe.id}-${ing.name}`,
43
+ name: ing.name,
44
+ quantity: ing.quantity,
45
+ unit: ing.unit,
46
+ calories: 0,
47
+ protein: 0,
48
+ carbs: 0,
49
+ fat: 0,
50
+ fiber: 0,
51
+ sugar: 0,
52
+ sodium: 0
53
+ })),
54
+ instructions: recipe.instructions,
55
+ prepTime: recipe.prepTime,
56
+ cookTime: recipe.cookTime,
57
+ servings: recipe.servings,
58
+ nutrition: {
59
+ calories: recipe.nutrition.calories,
60
+ protein: recipe.nutrition.protein,
61
+ carbs: recipe.nutrition.carbs,
62
+ fat: recipe.nutrition.fat,
63
+ fiber: recipe.nutrition.fiber,
64
+ sugar: recipe.nutrition.sugar,
65
+ sodium: recipe.nutrition.sodium
66
+ },
67
+ tags: recipe.tags,
68
+ difficulty: recipe.difficulty,
69
+ createdAt: new Date(),
70
+ updatedAt: new Date()
71
+ };
72
+ }
73
+ /**
74
+ * Generate a daily meal plan using recipes from the recipe database
75
+ * Each meal will have complete ingredients and cooking instructions
76
+ */
77
+ function generateDailyMealPlanWithRecipes(profile, userId) {
78
+ const needs = calculateDailyNeeds(profile);
79
+ // Get recipes filtered by user preferences
80
+ let availableRecipes = recipeService_1.recipeService.getAllRecipes();
81
+ // Filter by dietary restrictions
82
+ if (profile.dietaryRestrictions && profile.dietaryRestrictions.length > 0) {
83
+ availableRecipes = recipeService_1.recipeService.getRecipesForDietaryRestrictions(profile.dietaryRestrictions);
84
+ }
85
+ // Filter by health goals
86
+ if (profile.healthGoals && profile.healthGoals.length > 0) {
87
+ const healthRecipes = recipeService_1.recipeService.getRecipesForHealthGoals(profile.healthGoals);
88
+ availableRecipes = availableRecipes.filter(r => healthRecipes.some(hr => hr.id === r.id));
89
+ }
90
+ // Filter by cooking time preference if available
91
+ if (profile.preferences?.cookingTime) {
92
+ availableRecipes = availableRecipes.filter(r => recipeService_1.recipeService.getTotalTime(r) <= profile.preferences.cookingTime);
93
+ }
94
+ // Select one recipe for each meal type
95
+ const breakfastRecipes = availableRecipes.filter(r => r.category === 'breakfast');
96
+ const lunchRecipes = availableRecipes.filter(r => r.category === 'lunch');
97
+ const dinnerRecipes = availableRecipes.filter(r => r.category === 'dinner');
98
+ const snackRecipes = availableRecipes.filter(r => r.category === 'snack');
99
+ // Pick random recipes or first available
100
+ const selectedRecipes = {
101
+ breakfast: breakfastRecipes.length > 0
102
+ ? breakfastRecipes[Math.floor(Math.random() * breakfastRecipes.length)]
103
+ : recipeService_1.recipeService.getRecipeById('breakfast-1'),
104
+ lunch: lunchRecipes.length > 0
105
+ ? lunchRecipes[Math.floor(Math.random() * lunchRecipes.length)]
106
+ : recipeService_1.recipeService.getRecipeById('lunch-1'),
107
+ dinner: dinnerRecipes.length > 0
108
+ ? dinnerRecipes[Math.floor(Math.random() * dinnerRecipes.length)]
109
+ : recipeService_1.recipeService.getRecipeById('dinner-1'),
110
+ snack: snackRecipes.length > 0
111
+ ? snackRecipes[Math.floor(Math.random() * snackRecipes.length)]
112
+ : recipeService_1.recipeService.getRecipeById('snack-1')
113
+ };
114
+ // Convert recipes to meals
115
+ const meals = [
116
+ convertRecipeToMeal(selectedRecipes.breakfast),
117
+ convertRecipeToMeal(selectedRecipes.lunch),
118
+ convertRecipeToMeal(selectedRecipes.dinner),
119
+ convertRecipeToMeal(selectedRecipes.snack)
120
+ ];
121
+ // Calculate total nutrition
122
+ const totalNutrition = meals.reduce((total, meal) => ({
123
+ calories: total.calories + (meal.nutrition?.calories || 0),
124
+ protein: Math.round((total.protein + (meal.nutrition?.protein || 0)) * 10) / 10,
125
+ carbs: Math.round((total.carbs + (meal.nutrition?.carbs || 0)) * 10) / 10,
126
+ fat: Math.round((total.fat + (meal.nutrition?.fat || 0)) * 10) / 10
127
+ }), { calories: 0, protein: 0, carbs: 0, fat: 0 });
128
+ const today = new Date();
129
+ return {
130
+ id: `daily-recipe-plan-${Date.now()}`,
131
+ userId: userId,
132
+ name: `Daily Meal Plan - ${today.toLocaleDateString()}`,
133
+ description: `Personalized daily meal plan with complete recipes (${Math.round(totalNutrition.calories)} cal)`,
134
+ startDate: today.toISOString().split('T')[0],
135
+ endDate: today.toISOString().split('T')[0],
136
+ dailyPlans: [],
137
+ meals,
138
+ totalCalories: totalNutrition.calories,
139
+ totalProtein: totalNutrition.protein,
140
+ totalCarbs: totalNutrition.carbs,
141
+ totalFat: totalNutrition.fat,
142
+ uid: userId,
143
+ goals: {
144
+ dailyCalories: needs.calories,
145
+ proteinPercentage: 25,
146
+ carbsPercentage: 45,
147
+ fatPercentage: 30,
148
+ },
149
+ createdAt: new Date(),
150
+ updatedAt: new Date()
151
+ };
152
+ }
153
+ exports.generateDailyMealPlanWithRecipes = generateDailyMealPlanWithRecipes;
154
+ /**
155
+ * Generate a weekly meal plan using recipes from the recipe database
156
+ * Each day will have 4 meals with complete ingredients and cooking instructions
157
+ */
158
+ function generateWeeklyMealPlanWithRecipes(profile, userId) {
159
+ const needs = calculateDailyNeeds(profile);
160
+ // Get recipes filtered by user preferences
161
+ let availableRecipes = recipeService_1.recipeService.getAllRecipes();
162
+ // Filter by dietary restrictions
163
+ if (profile.dietaryRestrictions && profile.dietaryRestrictions.length > 0) {
164
+ availableRecipes = recipeService_1.recipeService.getRecipesForDietaryRestrictions(profile.dietaryRestrictions);
165
+ }
166
+ // Filter by health goals
167
+ if (profile.healthGoals && profile.healthGoals.length > 0) {
168
+ const healthRecipes = recipeService_1.recipeService.getRecipesForHealthGoals(profile.healthGoals);
169
+ availableRecipes = availableRecipes.filter(r => healthRecipes.some(hr => hr.id === r.id));
170
+ }
171
+ // Filter by cooking time preference
172
+ if (profile.preferences?.cookingTime) {
173
+ availableRecipes = availableRecipes.filter(r => recipeService_1.recipeService.getTotalTime(r) <= profile.preferences.cookingTime);
174
+ }
175
+ // Separate by category
176
+ const breakfastRecipes = availableRecipes.filter(r => r.category === 'breakfast');
177
+ const lunchRecipes = availableRecipes.filter(r => r.category === 'lunch');
178
+ const dinnerRecipes = availableRecipes.filter(r => r.category === 'dinner');
179
+ const snackRecipes = availableRecipes.filter(r => r.category === 'snack');
180
+ const allMeals = [];
181
+ const daysOfWeek = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
182
+ // Generate meals for each day
183
+ daysOfWeek.forEach((day, dayIndex) => {
184
+ // Select different recipes for variety (cycle through available recipes)
185
+ const breakfast = breakfastRecipes.length > 0
186
+ ? breakfastRecipes[dayIndex % breakfastRecipes.length]
187
+ : recipeService_1.recipeService.getRecipeById('breakfast-1');
188
+ const lunch = lunchRecipes.length > 0
189
+ ? lunchRecipes[dayIndex % lunchRecipes.length]
190
+ : recipeService_1.recipeService.getRecipeById('lunch-1');
191
+ const dinner = dinnerRecipes.length > 0
192
+ ? dinnerRecipes[dayIndex % dinnerRecipes.length]
193
+ : recipeService_1.recipeService.getRecipeById('dinner-1');
194
+ const snack = snackRecipes.length > 0
195
+ ? snackRecipes[dayIndex % snackRecipes.length]
196
+ : recipeService_1.recipeService.getRecipeById('snack-1');
197
+ // Convert to meals and add day prefix
198
+ const dayMeals = [
199
+ { ...convertRecipeToMeal(breakfast), name: `${day} - ${breakfast.name}` },
200
+ { ...convertRecipeToMeal(lunch), name: `${day} - ${lunch.name}` },
201
+ { ...convertRecipeToMeal(dinner), name: `${day} - ${dinner.name}` },
202
+ { ...convertRecipeToMeal(snack), name: `${day} - ${snack.name}` }
203
+ ];
204
+ allMeals.push(...dayMeals);
205
+ });
206
+ // Calculate total nutrition
207
+ const totalNutrition = allMeals.reduce((total, meal) => ({
208
+ calories: total.calories + (meal.nutrition?.calories || 0),
209
+ protein: Math.round((total.protein + (meal.nutrition?.protein || 0)) * 10) / 10,
210
+ carbs: Math.round((total.carbs + (meal.nutrition?.carbs || 0)) * 10) / 10,
211
+ fat: Math.round((total.fat + (meal.nutrition?.fat || 0)) * 10) / 10
212
+ }), { calories: 0, protein: 0, carbs: 0, fat: 0 });
213
+ const startDate = new Date();
214
+ const endDate = new Date();
215
+ endDate.setDate(startDate.getDate() + 6);
216
+ return {
217
+ id: `weekly-recipe-plan-${Date.now()}`,
218
+ userId: userId,
219
+ name: `Weekly Meal Plan - ${startDate.toLocaleDateString()} to ${endDate.toLocaleDateString()}`,
220
+ description: `7-day meal plan with complete recipes and instructions (${Math.round(totalNutrition.calories / 7)} cal/day avg)`,
221
+ startDate: startDate.toISOString().split('T')[0],
222
+ endDate: endDate.toISOString().split('T')[0],
223
+ dailyPlans: [],
224
+ meals: allMeals,
225
+ totalCalories: totalNutrition.calories,
226
+ totalProtein: totalNutrition.protein,
227
+ totalCarbs: totalNutrition.carbs,
228
+ totalFat: totalNutrition.fat,
229
+ uid: userId,
230
+ goals: {
231
+ dailyCalories: needs.calories,
232
+ proteinPercentage: 25,
233
+ carbsPercentage: 45,
234
+ fatPercentage: 30,
235
+ },
236
+ createdAt: new Date(),
237
+ updatedAt: new Date()
238
+ };
239
+ }
240
+ exports.generateWeeklyMealPlanWithRecipes = generateWeeklyMealPlanWithRecipes;
241
+ /**
242
+ * Get recipe details for a meal in a meal plan
243
+ * This allows you to retrieve the full recipe with instructions for any meal
244
+ */
245
+ function getRecipeForMeal(meal) {
246
+ // Try to find the recipe by ID (if meal ID matches recipe ID)
247
+ const recipe = recipeService_1.recipeService.getRecipeById(meal.id);
248
+ if (recipe) {
249
+ return recipe;
250
+ }
251
+ // Try to find by name (remove day prefix if present)
252
+ const cleanName = meal.name.replace(/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday) - /, '');
253
+ return recipeService_1.recipeService.searchRecipes(cleanName)[0];
254
+ }
255
+ exports.getRecipeForMeal = getRecipeForMeal;
@@ -0,0 +1,28 @@
1
+ import { Recipe, RecipeFilter } from './types/recipe';
2
+ export { RecipeFilter };
3
+ export declare class RecipeService {
4
+ private recipes;
5
+ private recipesBS;
6
+ private currentLocale;
7
+ constructor(locale?: string);
8
+ setLocale(locale: string): void;
9
+ private getCurrentRecipes;
10
+ getAllRecipes(): Recipe[];
11
+ getRecipeById(id: string): Recipe | undefined;
12
+ getRecipesByCategory(category: 'breakfast' | 'lunch' | 'dinner' | 'snack'): Recipe[];
13
+ filterRecipes(filter: RecipeFilter): Recipe[];
14
+ getRecipesByTags(tags: string[]): Recipe[];
15
+ getRecipesForHealthGoals(healthGoals: string[]): Recipe[];
16
+ getRecipesForDietaryRestrictions(restrictions: string[]): Recipe[];
17
+ getRandomRecipe(category?: 'breakfast' | 'lunch' | 'dinner' | 'snack'): Recipe;
18
+ getWeeklyRecipeSuggestions(healthGoals: string[], dietaryRestrictions: string[]): {
19
+ breakfast: Recipe[];
20
+ lunch: Recipe[];
21
+ dinner: Recipe[];
22
+ snack: Recipe[];
23
+ };
24
+ searchRecipes(query: string): Recipe[];
25
+ getTotalTime(recipe: Recipe): number;
26
+ getRecipesByTotalTime(maxMinutes: number): Recipe[];
27
+ }
28
+ export declare const recipeService: RecipeService;