/* ===================================================================== db.js — SQLite-Datenbank (better-sqlite3), Ersatz für Cloudflare D1. Führt beim ersten Start alle vier Migrationen aus ../cloudflare-worker/migrations/ in der ursprünglichen Reihenfolge aus (0001 Basis-Schema, 0002 app_settings, 0003 Supporter-Abo, 0004 TikTok/Discord-Spalten) — anders als bei VanVans Shop ist hier NIE alles in einer konsolidierten schema.sql zusammengefasst worden, deshalb müssen wir hier tatsächlich alle vier 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", ]; 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}`); } }