Postfach/Team-Verwaltung/Supporter-Abo als Node.js/Express-Server portiert
Vollständiger 1:1-Port des cloudflare-worker/ (dogfather-universe-postfach) auf server-internal/: Bewerbungs-Postfach mit Rollen/Rechten, Team- Zugangsverwaltung (verschlüsselte Owner-only-Codes), DogiCrew-Supporter-Abo (PayPal Subscriptions, Google-Login, Resend-E-Mail, 30-Monats-Prämienzyklus) und automatische TikTok-Live-Erkennung. D1 -> better-sqlite3, Cloudflare- Cron -> node-cron. Läuft ohne gesetzte Secrets weiter (PayPal/Google/Resend/ Ticketanizer/Discord bleiben "nicht konfiguriert" statt kaputt), bis die echten Zugangsdaten eingetragen werden.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
/* =====================================================================
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user