56 lines
5.4 KiB
Markdown
56 lines
5.4 KiB
Markdown
# Architektur und Entwicklung
|
|
|
|
## Stack
|
|
|
|
Next.js App Router, React, TypeScript, PostgreSQL, Drizzle, Zod, decimal.js, Motion, Lucide, Sharp und `@node-rs/argon2`. Konkrete kompatible Versionen sind in `package-lock.json` fixiert. Das UI nutzt bewusst eigenständiges CSS mit Designvariablen statt eines generischen Dashboard-Themes. Lokale DM Sans und Fraunces werden über Fontsource gebündelt.
|
|
|
|
## Verantwortlichkeiten
|
|
|
|
| Pfad | Verantwortung |
|
|
| -------------------------------- | -------------------------------------------------------------- |
|
|
| `src/lib/recipe.ts` | Gemeinsames Datenmodell, Validierung, Referenzintegrität |
|
|
| `src/lib/calculator.ts` | Reine präzise Skalierung, Einheiten, Anzeige und Einkaufsliste |
|
|
| `src/lib/import.ts` | JSON/XML-Dekodierung und verlustfreier Metadatenexport |
|
|
| `src/lib/cooking.ts` | Testbare Zeitstempel-Timer |
|
|
| `src/lib/server.ts` | Sessions, CSRF, Größenlimits, Rate Limit, Fehlerabbildung |
|
|
| `src/lib/repository.ts` | Rezeptpersistenz, Sichtbarkeit, Versionskonflikte |
|
|
| `src/db/` | Drizzle-Mappings und PostgreSQL-Pool |
|
|
| `src/app/api/[...path]/route.ts` | Dünne HTTP-Operationen mit Validierung/Autorisierung |
|
|
| `src/components/` | Bibliothek, Detail, Kochmodus, Editor, Administration |
|
|
| `migrations/` | Versionierte SQL-Migrationen |
|
|
| `scripts/` | Migration, Admin-Bootstrap, Schema/Beispielgenerierung |
|
|
|
|
Die Rezeptstruktur liegt als validiertes JSONB-Dokument vor, ergänzt um relationale ID, Titel, normalisierten eindeutigen Titel, Veröffentlichungsstatus und Zeitstempel. Damit werden Zutaten/Schritte atomar geändert und beim Import nicht auseinandergerissen. Sessions, Administratoren, Limits und Medien sind getrennte relationale Tabellen. Öffentliche Leseoperationen filtern serverseitig auf `published=true`.
|
|
|
|
## API
|
|
|
|
Alle Fehler: `{ "error": "Verständliche Meldung" }`. Statuscodes: 400 Syntax, 401 Anmeldung, 403 Origin, 404 fehlt, 409 Duplikat/Versionskonflikt, 413 Größe, 415 Dateityp, 422 Datenvalidierung, 428 fehlende Bearbeitungsversion, 429 Loginlimit, 500 unerwarteter Serverfehler. Unerwartete Fehler werden serverseitig geloggt, ohne interne Details an Clients auszugeben.
|
|
|
|
- `GET /api/recipes`: veröffentlichte Rezepte; `?admin=1` nur mit gültiger Session erweitert.
|
|
- `GET /api/recipes/:id`: öffentlich nur veröffentlicht, sonst autorisierter Admin.
|
|
- `POST /api/recipes`, `PUT /api/recipes/:id`, `DELETE /api/recipes/:id`: Admin, Origin erforderlich. PUT benötigt den letzten `updatedAt`-Wert.
|
|
- `POST /api/auth/login`, `POST /api/auth/logout`, `GET /api/auth/me`, `POST /api/auth/password`.
|
|
- `POST /api/import`: `{raw, format: "json"|"xml", preview: boolean}`.
|
|
- `GET /api/export?format=json|xml&id=UUID`: ID optional, sonst gesamte Sammlung.
|
|
- `GET/PUT /api/settings`: Kategorien-/Tag-Auswahllisten und Sammlungsname.
|
|
- `GET/POST/DELETE /api/media`: Rohbild-Upload mit Content-Type JPEG/PNG/WebP, Löschung per `{name}`. Bilder werden serverseitig dekodiert und als WebP neu kodiert (max. 40 MP, 10 MB Eingabe, 2400 px Kantenlänge). EXIF wird entfernt.
|
|
- `GET /api/health`: Datenbankverbindung + Anwendung.
|
|
|
|
Alle Admin-Operationen prüfen die Session auf dem Server. Passwörter werden mit Argon2id (64 MiB, 3 Iterationen) gehasht. CSRF-Schutz nutzt den verpflichtenden exakten Origin-Vergleich plus SameSite-Strict-Cookies. Automatisierte API-Clients müssen die konfigurierte Origin explizit setzen. Es gibt keine Token in Local Storage.
|
|
|
|
## Rechner und Referenzen
|
|
|
|
Faktoren bleiben als hochpräzise Dezimalstrings erhalten. Neue Zielmengen werden stets durch die unveränderte Originalmenge geteilt; Originalzutaten werden nie mutiert. Runden erfolgt nur zur Anzeige. Übliche Viertel-/Halbbrüche werden typografisch dargestellt, kleine Mengen mit bis zu sechs Nachkommastellen. Nährwerte sind pro Originalportion, Gesamtzeit wird nicht skaliert.
|
|
|
|
## Editor und lokale Speicherung
|
|
|
|
Änderungen werden lokal im Browser gesichert, ohne das veröffentlichte Rezept zu verändern. „Rezept speichern“ validiert und überträgt ausdrücklich auf den Server. Der Browser warnt beim Verlassen mit noch nicht auf den Server übertragenen Änderungen. Konflikte mit einer zwischenzeitlich geänderten Fassung werden als 409 zurückgegeben. Lokale Entwürfe bleiben dann erhalten.
|
|
|
|
Zutaten und Schritte lassen sich per Drag-Handle sowie per Auf/Ab-Buttons sortieren. So ist die Funktion auch ohne Maus bedienbar. Bilder werden sofort in die lokale Medienablage hochgeladen und können dort später entfernt werden, solange kein Rezept sie verwendet.
|
|
|
|
## Tests
|
|
|
|
Unit: `npm test`. E2E: `npm run build && npm run test:e2e`. Tests verwenden echte PostgreSQL-Persistenz, echte HTTP-Authentifizierung und Chromium ohne gemockte Produktfunktionen. Die E2E-Datenbank muss auf `_test` enden und wird zurückgesetzt. Playwright erzeugt Screenshots für Desktop (1440 px), Smartphone (390 px) und Tablet (768 px).
|
|
|
|
Bei Schemaänderungen `npm run schema:generate` ausführen und generierte Dokumente mitcommitten. Entwicklungsserver und Produktionsbuild teilen dieselbe Datenbankkonfiguration. Next-Telemetrie im Container ist deaktiviert; lokal bei Bedarf `NEXT_TELEMETRY_DISABLED=1` setzen.
|