docs(review): fix table names, IMAGE_DIR, image endpoints
- ARCHITECTURE.md: ingredient/step (waren faelschlich recipe_*) - OPERATIONS.md: IMAGE_DIR (statt IMAGES_PATH) - session-handoff: /api/recipes/[id]/image POST/DELETE ergaenzt Findings aus REVIEW-2026-04-18.md / docs-vs-code.md
This commit is contained in:
153
docs/superpowers/plans/2026-04-18-review-fixes.md
Normal file
153
docs/superpowers/plans/2026-04-18-review-fixes.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Review-Fixes 2026-04-18 — Implementation Plan
|
||||
|
||||
> **Quelle:** `docs/superpowers/review/REVIEW-2026-04-18.md` + Sub-Reports.
|
||||
> **Branch:** `review-fixes-2026-04-18`
|
||||
> **Goal:** Alle HIGH/MEDIUM Findings aus dem Code-Review adressieren, bewusst verschobene Items dokumentieren.
|
||||
> **Architecture:** Inkrementelle Refactors, jeder atomar committed + gepusht, Tests nach jedem Wave grün.
|
||||
> **Tech-Stack:** SvelteKit, TypeScript-strict, Zod, Vitest, better-sqlite3, Service-Worker.
|
||||
|
||||
---
|
||||
|
||||
## Was wird angegangen (must-do)
|
||||
|
||||
| # | Wave | Zeit | Begründung |
|
||||
|---|------|------|------------|
|
||||
| 1 | Doku-Fixes (ARCHITECTURE/OPERATIONS/handoff) | 5 min | Hoher Wert, trivialer Aufwand |
|
||||
| 2 | constants.ts + Image-Endpoint EN + interne Types | 30 min | Alle "Quick-Wins" aus REVIEW |
|
||||
| 3 | api-helpers.ts (parsePositiveIntParam + validateBody) | 1-2 h | Refactor A — 9+11 Call-Sites |
|
||||
| 4 | requireProfile() + asyncFetch Wrapper | 1 h | Profile-Guard 4× + fetch-Pattern 5× |
|
||||
| 5 | Cleanup (yauzl-Doku, baseRecipe-Fixture, Console-Logs) | 30 min | Restliche LOW-Findings |
|
||||
| 6 | Ingredient-Parser Edge-Cases (Refactor D) | 2-3 h | Locale-Komma, Unicode-Brüche, Bounds |
|
||||
| 7 | Verifikation (test/check/build, Docker-Smoke) | 30 min | Baseline gegen Regressionen |
|
||||
| 8 | Re-Review + OPEN-ISSUES-NEXT.md | 1 h | Beweis + Ausblick |
|
||||
|
||||
## Was bewusst NICHT angegangen wird (Begründung in OPEN-ISSUES-NEXT.md)
|
||||
|
||||
- **Refactor B** (Search-State-Store, halber Tag): Touch von 808-Zeilen-Page + 678-Zeilen-Layout, bricht riskant Frontend ohne UAT. Eigene Phase planen.
|
||||
- **Refactor C** (RecipeEditor zerlegen): Review sagt explizit "keine Eile, solange niemand sonst drin arbeitet".
|
||||
- **SearXNG Rate-Limit Recovery**: Größeres Feature, eigene Phase.
|
||||
- **SW-Zombie-Cleanup Unit-Tests**: Bereits 6 pwa-store-Tests vorhanden, Erweiterung wäre Bonus.
|
||||
- **JSON-LD Parser Edge-Cases** (Locales): Weniger Käse als Ingredient-Parser-Issues, eigene Iteration.
|
||||
|
||||
---
|
||||
|
||||
## Wave 1 — Doku-Fixes
|
||||
|
||||
**Files:** `docs/ARCHITECTURE.md:55`, `docs/OPERATIONS.md:135`, `docs/superpowers/session-handoff-2026-04-17.md:46`
|
||||
|
||||
- [ ] ARCHITECTURE.md: `recipe_ingredient` + `recipe_step` → `ingredient` + `step`
|
||||
- [ ] OPERATIONS.md: `IMAGES_PATH` → `IMAGE_DIR`
|
||||
- [ ] session-handoff: `/api/recipes/[id]/image` (POST/DELETE) ergänzen
|
||||
- [ ] Commit `docs(review): Doku-Mismatches korrigiert`
|
||||
|
||||
## Wave 2 — Konstanten + Cleanup
|
||||
|
||||
**Files:** `src/lib/constants.ts` (neu), `src/routes/+page.svelte`, `src/lib/client/pwa.svelte.ts`, `src/routes/api/recipes/[id]/image/+server.ts`, `src/lib/sw/cache-strategy.ts`, `src/lib/sw/diff-manifest.ts`
|
||||
|
||||
- [ ] `src/lib/constants.ts` mit `SW_VERSION_QUERY_TIMEOUT_MS = 1500`, `SW_UPDATE_POLL_INTERVAL_MS = 30 * 60_000`
|
||||
- [ ] Image-Endpoint: deutsche Fehlermeldungen → englisch (Konsistenz)
|
||||
- [ ] `RequestShape` / `ManifestDiff`: `export` weg wenn rein intern
|
||||
- [ ] Test + check, Commit
|
||||
|
||||
## Wave 3 — api-helpers.ts (TDD)
|
||||
|
||||
**Files:** `src/lib/server/api-helpers.ts` (neu), `tests/unit/api-helpers.test.ts` (neu), `src/lib/types.ts` (ErrorResponse)
|
||||
|
||||
### 3a Helper bauen
|
||||
- [ ] Test: `parsePositiveIntParam("42", "id")` → 42
|
||||
- [ ] Test: `parsePositiveIntParam("0", "id")` wirft 400
|
||||
- [ ] Test: `parsePositiveIntParam("abc", "id")` wirft 400
|
||||
- [ ] Test: `parsePositiveIntParam(null, "id")` wirft 400
|
||||
- [ ] Test: `validateBody(invalid, schema)` wirft 400 mit issues
|
||||
- [ ] Test: `validateBody(valid, schema)` returns parsed
|
||||
- [ ] Implement helpers
|
||||
- [ ] Tests grün, Commit
|
||||
|
||||
### 3b Migration parseId → parsePositiveIntParam (9 Sites)
|
||||
Files (jeder Endpoint):
|
||||
- `src/routes/api/recipes/[id]/+server.ts`
|
||||
- `src/routes/api/recipes/[id]/favorite/+server.ts`
|
||||
- `src/routes/api/recipes/[id]/rating/+server.ts`
|
||||
- `src/routes/api/recipes/[id]/cooked/+server.ts`
|
||||
- `src/routes/api/recipes/[id]/comments/+server.ts`
|
||||
- `src/routes/api/recipes/[id]/image/+server.ts`
|
||||
- `src/routes/api/profiles/[id]/+server.ts`
|
||||
- `src/routes/api/domains/[id]/+server.ts`
|
||||
- `src/routes/api/wishlist/[recipe_id]/+server.ts`
|
||||
|
||||
- [ ] Pro Endpoint: lokales parseId entfernen, Helper importieren
|
||||
- [ ] Tests grün
|
||||
- [ ] Commit
|
||||
|
||||
### 3c Migration safeParse → validateBody
|
||||
Files: alle `+server.ts` mit `safeParse`. ErrorResponse-Shape standardisieren.
|
||||
|
||||
- [ ] Pro Endpoint umstellen
|
||||
- [ ] Tests grün
|
||||
- [ ] Commit
|
||||
|
||||
## Wave 4 — Client-Helpers
|
||||
|
||||
### 4a requireProfile()
|
||||
- [ ] Helper in `src/lib/client/profile.svelte.ts` ergänzen
|
||||
- [ ] 4 Sites in `src/routes/recipes/[id]/+page.svelte` ersetzen
|
||||
- [ ] Test + Commit
|
||||
|
||||
### 4b asyncFetch Wrapper
|
||||
- [ ] `src/lib/client/api-fetch-wrapper.ts` mit `asyncFetch(url, init, actionTitle)`
|
||||
- [ ] 5 Sites umstellen: `recipes/[id]/+page.svelte` (2×), `admin/domains/+page.svelte` (2×), `admin/profiles/+page.svelte`
|
||||
- [ ] Test + Commit
|
||||
|
||||
## Wave 5 — Cleanup
|
||||
|
||||
- [ ] yauzl: Inline-Kommentar in package.json: "Reserved for Phase 5b ZIP-Backup-Import"
|
||||
- [ ] baseRecipe Fixture nach `tests/fixtures/recipe.ts` (wenn dupliziert)
|
||||
- [ ] Console-Logs: per `if (import.meta.env.DEV)` wrappen oder absichtlich-Kommentar
|
||||
- [ ] Commit
|
||||
|
||||
## Wave 6 — Ingredient-Parser Edge-Cases
|
||||
|
||||
**Files:** `src/lib/server/parsers/ingredient.ts`, `tests/unit/ingredient.test.ts`
|
||||
|
||||
### Tests zuerst (red)
|
||||
- [ ] Locale-Komma: `"1,5 kg Mehl"` → qty 1.5
|
||||
- [ ] Unicode-½: `"½ TL Salz"` → qty 0.5
|
||||
- [ ] Unicode-⅓: `"⅓ Tasse Wasser"` → qty 1/3
|
||||
- [ ] Unicode-¼: `"¼ kg Zucker"` → qty 0.25
|
||||
- [ ] Negativ: `"-1 EL Öl"` → wirft / qty=null
|
||||
- [ ] Null: `"0 g Mehl"` → wirft / qty=null
|
||||
- [ ] Führende Null: `"0.5 kg"` → 0.5
|
||||
- [ ] Wissenschaftliche Notation: `"1e3 g"` → wirft / qty=null
|
||||
|
||||
### Parser fixen
|
||||
- [ ] Unicode-Brüche-Map
|
||||
- [ ] Locale-Komma-Handling (sicher: "1,5" wenn nur 1 Komma + Ziffern drumrum)
|
||||
- [ ] Bounds: 0 < qty <= 10000 (Zod refinement oder Pre-Check)
|
||||
- [ ] Tests grün, Commit
|
||||
|
||||
## Wave 7 — Verifikation
|
||||
|
||||
- [ ] `npm test` — 158+ Tests grün
|
||||
- [ ] `npm run check` — 0 Errors
|
||||
- [ ] `npm run build` — erfolgreich
|
||||
- [ ] Optional: Docker-Smoke `docker compose -f docker-compose.prod.yml up --build`
|
||||
- [ ] Push aller Commits
|
||||
|
||||
## Wave 8 — Re-Review + OPEN-ISSUES-NEXT.md
|
||||
|
||||
- [ ] Parallele Explore-Agenten: dead-code, redundancy, structure, docs-vs-code
|
||||
- [ ] Befunde in `docs/superpowers/review/OPEN-ISSUES-NEXT.md`
|
||||
- [ ] Bewusst verschobene Items mit Begründung
|
||||
- [ ] Neue Findings (falls vorhanden)
|
||||
- [ ] Commit + Push
|
||||
|
||||
---
|
||||
|
||||
## Erfolgs-Kriterien
|
||||
|
||||
1. Tests grün (158+)
|
||||
2. svelte-check: 0 Errors, 0 Warnings (oder ≤ Baseline)
|
||||
3. Build erfolgreich
|
||||
4. Alle 8 Quick-Wins + Refactor A + Refactor D umgesetzt
|
||||
5. OPEN-ISSUES-NEXT.md vorhanden mit klarer Trennung "verschoben (warum)" vs "neu entdeckt"
|
||||
6. Branch ready zum Mergen / PR
|
||||
@@ -43,7 +43,7 @@ docker compose -f docker-compose.prod.yml up -d
|
||||
### Server-Seite
|
||||
- **DB:** SQLite mit FTS5, Migrationen (`./migrations/*.sql`) werden von Vite gebündelt und beim ersten DB-Zugriff angewendet. Auto-mkdir für `data/` und `data/images/`.
|
||||
- **Module:** `parsers/` (iso8601, ingredient, json-ld-recipe), `recipes/` (scaler + repository + actions + importer + search-local), `domains/` (repository + whitelist), `profiles/`, `images/image-downloader`, `search/searxng`, `backup/export`, `http`.
|
||||
- **Routes:** `/api/health`, `/api/profiles`, `/api/profiles/[id]`, `/api/domains`, `/api/domains/[id]`, `/api/recipes/search`, `/api/recipes/search/web`, `/api/recipes/preview`, `/api/recipes/import`, `/api/recipes/[id]`, `/api/recipes/[id]/rating`, `/api/recipes/[id]/favorite`, `/api/recipes/[id]/cooked`, `/api/recipes/[id]/comments`, `/api/admin/backup`, `/images/[filename]`.
|
||||
- **Routes:** `/api/health`, `/api/profiles`, `/api/profiles/[id]`, `/api/domains`, `/api/domains/[id]`, `/api/recipes/search`, `/api/recipes/search/web`, `/api/recipes/preview`, `/api/recipes/import`, `/api/recipes/[id]`, `/api/recipes/[id]/rating`, `/api/recipes/[id]/favorite`, `/api/recipes/[id]/cooked`, `/api/recipes/[id]/comments`, `/api/recipes/[id]/image` (POST/DELETE), `/api/admin/backup`, `/images/[filename]`.
|
||||
|
||||
### Client-Seite (Svelte 5 Runes)
|
||||
- **Layout** mit Profil-Chip und Zahnrad zu Admin.
|
||||
|
||||
Reference in New Issue
Block a user