languages.greeting (de/en/sv geseedet), neue pair_categories-Tabelle (abgeleitet aus statement- und objektverknüpften Wörtern via word_categories) inkl. Backfill für bereits veröffentlichte Pairs. derivePairCategories() wird beim Publish (pairs + pipeline) aufgerufen. /auth/me liefert language_target_greeting, /auth/stats liefert categories[] mit Punkten je Kategorie fürs Profil. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.1 KiB
2.1 KiB
CLAUDE.md
REST-API für das snakkimo-Projekt. Node/Express + PostgreSQL (pg, kein ORM), Bild-Assets auf Hetzner Object Storage (S3-kompatibel). Ausführliche API-Doku in README.md.
Befehle
npm run dev— lokaler Server mit nodemon (Hot-Reload)npm start— Produktion (node src/index.js)- Keine Tests / kein Linter konfiguriert.
Architektur
- Einstieg: src/index.js — registriert alle Routen, jede
/api/*-Route ist mit derauth-Middleware geschützt. - Migrationen laufen automatisch beim Boot (src/db-migrate.js), bevor der Server lauscht. Idempotent halten:
CREATE TABLE IF NOT EXISTS, Spalten-Renames mit.catch(() => {}). Es gibt kein separates Migrations-Tool — Schema-Änderungen hier eintragen. src/db.jsexportiertquery(text, params)undpool. Immer parametrisierte Queries ($1, $2 …), nie String-Interpolation von User-Input.src/routes/— eine Datei pro Entität.src/lib/,src/middleware/,src/s3.js,src/voices.jsfür geteilte Logik.
Konventionen
- Code-Kommentare auf Deutsch, Code/Bezeichner auf Englisch (dem Bestand folgen).
- Route-Handler-Muster:
async (req, res, next) => { try { … } catch (err) { next(err); } }. Fehler an den zentralen Error-Handler inindex.jsdurchreichen, nicht selbst 500en. - Listen-Endpoints:
limit/offsetaus Query,limithart begrenzen (z. B.Math.min(parseInt(limit), 500)). - Status-Felder gegen eine
STATUSES-Whitelist prüfen → bei Verstoß400. - Sprachen-Suffixe:
_de,_en,_sv._seist veraltet (falscher ISO-639-1-Code) und wird beim Boot zu_svumbenannt — niemals neue_se-Spalten anlegen.
Auth (zwei Pfade, siehe src/middleware/auth.js)
- Statische Tokens aus
API_TOKENS(komma-separiert) → Server-zu-Server / Admin, keine Rollenprüfung. - JWT aus
/auth/login·/auth/register. Rolleend-userbekommt auf allen/api/*bewusst 403 (App-Gating).
Öffentlich (ohne Auth): GET /health, /auth/*.
Konfig über .env (siehe .env.example). Deployment via Coolify/Docker.