feat(core): add secure recipe APIs, precise scaling and versioned imports

This commit is contained in:
OpenCode committed 2026-10-24 15:40:44 +02:00
commit 5d71d32e20
31 files changed
+6293

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
import { z } from 'zod';
import { mkdir, writeFile } from 'node:fs/promises';
import { collectionSchema, recipeSchema } from '../src/lib/recipe';
import { exportRecipes } from '../src/lib/import';
import { examples } from '../tests/fixtures';
await mkdir('public/examples', { recursive: true });
await writeFile(
'public/examples/hamham.schema.json',
JSON.stringify(z.toJSONSchema(collectionSchema, { target: 'draft-2020-12' }), null, 2),
);
const r = recipeSchema.parse({
title: 'Serbische Pljeskavica',
subtitle: 'Saftig gegrillt, mit Ajvar und frischen Zwiebeln',
description:
'Ein Klassiker vom Balkan: würzige Faschierte-Laibchen, außen kräftig geröstet und innen saftig. Dazu passen Lepinja, Ajvar und ein knackiger Salat.',
cuisine: 'Serbien',
categories: ['Für Gäste'],
tags: ['Grillen', 'Familienliebling'],
difficulty: 'Einfach',
prepMinutes: 20,
cookMinutes: 12,
restMinutes: 60,
servings: 4,
published: false,
ingredients: [
{ id: 'fleisch', name: 'Rinderfaschiertes', amount: 800, unit: 'g', section: 'Pljeskavica' },
{
id: 'zwiebel',
name: 'Zwiebel',
amount: 1,
unit: 'Stück',
note: 'sehr fein gewürfelt',
section: 'Pljeskavica',
},
{ id: 'paprika', name: 'Paprikapulver edelsüß', amount: 2, unit: 'TL', section: 'Pljeskavica' },
{ id: 'salz', name: 'Salz', amount: 10, unit: 'g', section: 'Pljeskavica' },
{
id: 'pfeffer',
name: 'Schwarzer Pfeffer',
amount: null,
unit: '',
note: 'nach Geschmack',
section: 'Pljeskavica',
},
{ id: 'wasser', name: 'Mineralwasser', amount: 60, unit: 'ml', section: 'Pljeskavica' },
{
id: 'ajvar',
name: 'Ajvar',
amount: 120,
unit: 'g',
section: 'Zum Servieren',
optional: true,
},
{ id: 'brot', name: 'Lepinja', amount: 4, unit: 'Stück', section: 'Zum Servieren' },
],
steps: [
{
id: 'mischen',
title: 'Die Mischung vorbereiten',
text: '{{fleisch}}, {{zwiebel}}, {{paprika}}, {{salz}} und {{wasser}} gründlich verkneten. Mit {{pfeffer}} abschmecken.',
ingredients: ['fleisch', 'zwiebel', 'paprika', 'salz', 'wasser', 'pfeffer'],
},
{
id: 'ruhen',
title: 'Geschmack entwickeln lassen',
text: 'Die Masse zugedeckt mindestens eine Stunde im Kühlschrank ruhen lassen.',
timers: [{ id: 'ruhezeit', label: 'Im Kühlschrank ruhen', seconds: 3600 }],
},
{
id: 'formen',
title: 'Flache Laibchen formen',
text: 'Mit angefeuchteten Händen je Portion ein etwa 1,5 cm dickes Laibchen formen. In die Mitte eine leichte Mulde drücken.',
},
{
id: 'grillen',
title: 'Kräftig grillen',
text: 'Grill oder Grillpfanne vorheizen. Laibchen von beiden Seiten je etwa fünf bis sechs Minuten braten. Faschiertes vollständig durchgaren: im Kern mindestens 70 °C für zwei Minuten erreichen.',
timers: [
{ id: 'erste-seite', label: 'Erste Seite', seconds: 360 },
{ id: 'zweite-seite', label: 'Zweite Seite', seconds: 360 },
],
},
{
id: 'servieren',
title: 'Ab an den Tisch',
text: 'In {{brot}} mit {{ajvar}} servieren. Nach Wunsch frische Zwiebelringe dazu reichen.',
ingredients: ['brot', 'ajvar'],
},
],
tips: 'Nicht während des Bratens flachdrücken – so bleibt die Pljeskavica saftig. Für Schärfe etwas Chiliflocken zur Masse geben.',
storage:
'Reste rasch abkühlen, abgedeckt im Kühlschrank aufbewahren und innerhalb von zwei Tagen verbrauchen. Vor dem Essen gründlich erhitzen.',
});
await writeFile('public/examples/pljeskavica.json', exportRecipes([r], 'json'));
await writeFile('public/examples/pljeskavica.xml', exportRecipes([r], 'xml'));
await writeFile('public/examples/kochbuch.json', exportRecipes(examples, 'json'));
console.log('JSON Schema und vollständige JSON/XML-Beispiele erzeugt.');