123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116import ddl from"./schema.js";
import manifest from"./manifest.json";
import { database } from"../../shared/database.js";
import { isDuration } from"../../shared/format.js";
exportfunctioncreateRecipes(L) {
const db = database(L, ddl, manifest);
constnormalize = (data) => {
db.check("save-recipe", data);
if (!data.name.trim()) throwError("Enter a recipe name.");
const ingredients = JSON.parse(data.recipe_ingredient ?? "[]");
if (
!Array.isArray(ingredients) ||
!ingredients.every((v) =>typeof v === "string")
)
throwError("Ingredients must be a JSON array of strings.");
for (const field of ["prep_time", "cook_time", "total_time"])
if (!isDuration(data[field]))
throwError(`${field} must be an ISO 8601 duration, such as PT30M.`);
return { ...data, recipe_ingredient: data.recipe_ingredient ?? "[]" };
};
return {
...db,
list: () =>
db.ready.then(() =>
db.query("SELECT * FROM recipes ORDER BY name COLLATE NOCASE, id"),
),
save: (data, id) =>
db.run(async () => {
const value = normalize(data);
if (id !== undefined && !(await db.get("recipes", id)))
throwError("Recipe no longer exists.");
const row =
id === undefined
? await db.insert("recipes", value)
: await db.update("recipes", id, value);
await db.emit(
id === undefined ? "recipe-saved" : "recipe-updated",
row,
);
return row;
}),
remove: (id) =>
db.run(async () => {
const row = await db.get("recipes", id);
if (!row) return;
await db.exec("DELETE FROM recipes WHERE id = ?", [id]);
await db.emit("recipe-removed", row);
}),
};
}
exportconst samples = [
{
name: "Lemon & chickpea orzo",
description: "A one-pan dinner with spinach, lemon, and a little Parmesan.",
author: "Home kitchen",
prep_time: "PT10M",
cook_time: "PT20M",
total_time: "PT30M",
recipe_yield: "4 servings",
recipe_category: "Dinner",
recipe_cuisine: "Mediterranean",
recipe_ingredient: JSON.stringify([
"2 tbsp olive oil",
"1 onion, finely chopped",
"2 cloves garlic, sliced",
"250 g orzo",
"400 g canned chickpeas, drained",
"750 ml vegetable stock",
"100 g baby spinach",
"1 lemon, zest and juice",
"Parmesan, to serve",
]),
recipe_instructions:
"1. Warm the oil in a deep pan. Soften the onion for 5 minutes, then add the garlic.\n\n2. Stir in the orzo and chickpeas. Add the stock and simmer for 12–15 minutes, stirring occasionally.\n\n3. Fold in the spinach and lemon. Season to taste and serve with Parmesan.",
},
{
name: "Overnight oats",
description:
"Rolled oats with yogurt and berries. Prepare the evening before.",
prep_time: "PT5M",
total_time: "PT8H5M",
recipe_yield: "2 jars",
recipe_category: "Breakfast",
recipe_ingredient: JSON.stringify([
"100 g rolled oats",
"200 ml milk",
"100 g plain yogurt",
"1 tbsp chia seeds",
"1 tsp honey",
"A handful of berries",
]),
recipe_instructions:
"Mix the oats, milk, yogurt, chia seeds, and honey. Divide between two jars. Cover and chill overnight. Add berries before serving.",
},
{
name: "Rosemary focaccia",
description: "Olive oil bread with a crisp base and a soft centre.",
prep_time: "PT25M",
cook_time: "PT25M",
total_time: "PT3H",
recipe_yield: "1 tray",
recipe_category: "Baking",
recipe_cuisine: "Italian",
recipe_ingredient: JSON.stringify([
"500 g bread flour",
"7 g instant yeast",
"10 g salt",
"400 ml warm water",
"4 tbsp olive oil",
"2 sprigs rosemary",
"Flaky sea salt",
]),
recipe_instructions:
"Mix flour, yeast, salt, and water into a sticky dough. Rest, covered, for 90 minutes.\n\nOil a baking tray, stretch the dough into it, and rest for 30 minutes. Heat the oven to 220°C.\n\nDimple the dough with oiled fingers. Add rosemary, olive oil, and flaky salt. Bake for 25 minutes until golden.",
},
];