Files
dogfather-universe/server-internal/db.js
T
DogFatherGitandClaude Opus 5 399260b805 "Stimmen" verwandelt: Fans reichen selbst Testimonials ein
Nutzer-Wunsch 20.08.2026: "eine richtig geile kachel ... wo die leute mit
namen und tiktok namen mir eine nachricht schreiben können die ich in die
verwaltung kriege, und dann kann ich die ausgewählten über die
verwaltungsseite auf die website hinzufügen ... das wird mega persoenlich
zu den fans, bitte wirklich krass geil speziell."

- Neue, augenschonend gestaltete Einreich-Kachel auf stimmen.html: Name,
  TikTok-Name (optional), Nachricht -- landet NIE automatisch oeffentlich,
  sondern immer erst als Entwurf in der Verwaltung.
  Warmer Babyblau/Rosé-Farbverlauf, wandernder Lichtschein, pulsierendes
  Herz -- ersetzt die 3 ewigen "Hier steht bald..."-Platzhalterkarten.
- Neue Verwaltungs-Sektion "💬 Stimmen verwalten": Warteschlange (offene
  zuerst), Freigeben/Ablehnen/Löschen pro Eintrag.
- Freigegebene Stimmen erscheinen automatisch in einer neuen, spezielleren
  Zitat-Kartenoptik (großes Anführungszeichen, Name + TikTok-Chip) --
  Abschnitt bleibt komplett unsichtbar, solange keine einzige freigegeben
  wurde.
- Backend: neue Tabelle `testimonials` (Migration 0006), routes/
  testimonials.js (oeffentliches Einreichen + Lesen freigegebener,
  admin-Warteschlange + Status/Loeschen mit neuer TESTIMONIALS_MANAGE-
  Berechtigung). 18 automatisierte Tests gegen eine Fake-DB bestanden.
- Alles per Playwright visuell durchgespielt: leerer Zustand, Einreichen
  -> Erfolgsmeldung, freigegebene Stimmen-Anzeige, Verwaltungs-Warteschlange
  mit allen Aktionen.

Backend-Teil (server-internal/, cloudflare-worker/migrations/) noch ohne
Deploy-Zugriff -- Dogi muss ihn manuell auf dogiintern ausrollen.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-20 23:37:31 +02:00

55 lines
2.1 KiB
JavaScript

/* =====================================================================
db.js — SQLite-Datenbank (better-sqlite3), Ersatz für Cloudflare D1.
Führt beim ersten Start alle Migrationen aus ../cloudflare-worker/migrations/
in der ursprünglichen Reihenfolge aus (0001 Basis-Schema, 0002 app_settings,
0003 Supporter-Abo, 0004 TikTok/Discord-Spalten, 0005 Supporter-Abstimmungen)
— anders als bei VanVans Shop ist hier NIE alles in einer konsolidierten
schema.sql zusammengefasst worden, deshalb müssen wir hier tatsächlich alle
der Reihe nach anwenden.
===================================================================== */
import Database from "better-sqlite3";
import { readFileSync, existsSync, mkdirSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const DB_PATH = process.env.DB_PATH || "/var/lib/dogfather-internal/dogfather-internal.db";
const MIGRATIONS_DIR = join(__dirname, "..", "cloudflare-worker", "migrations");
mkdirSync(dirname(DB_PATH), { recursive: true });
export const db = new Database(DB_PATH);
db.pragma("journal_mode = WAL");
db.pragma("foreign_keys = ON");
const MIGRATION_FILES = [
"0001_init.sql",
"0002_app_settings.sql",
"0003_supporter_abo.sql",
"0004_supporter_oauth_providers.sql",
"0005_supporter_polls.sql",
"0006_testimonials.sql",
];
function alreadyApplied(name) {
const row = db.prepare(`SELECT 1 FROM _migrations WHERE name = ?`).get(name);
return !!row;
}
export function initDb() {
db.exec(`CREATE TABLE IF NOT EXISTS _migrations (name TEXT PRIMARY KEY, applied_at TEXT NOT NULL)`);
for (const file of MIGRATION_FILES) {
if (alreadyApplied(file)) continue;
const path = join(MIGRATIONS_DIR, file);
if (!existsSync(path)) {
console.warn(`⚠️ Migration ${file} nicht gefunden unter ${path}, übersprungen.`);
continue;
}
const sql = readFileSync(path, "utf-8");
db.exec(sql);
db.prepare(`INSERT INTO _migrations (name, applied_at) VALUES (?, ?)`).run(file, new Date().toISOString());
console.log(`Migration angewendet: ${file}`);
}
}