feat: implement database reset and demo population scripts with tests
This commit is contained in:
1 parent
4df14584f2
commit
a2e5184b3e
4 files changed
+214
-1
No files matched your search
@@ -0,0 +1,69 @@
|
||||
import "dotenv/config";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { createRequire } from "node:module";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { db } from "../src/lib/db";
|
||||
|
||||
async function reset() {
|
||||
const [mode, confirmation, ...extra] = process.argv.slice(2);
|
||||
if (!["clear", "demo"].includes(mode) || confirmation !== "--confirm-reset" || extra.length) {
|
||||
throw new Error("Aufruf: npm run db:clear|db:reset -- --confirm-reset. Alle Instanzdaten und Zugaenge werden geloescht!");
|
||||
}
|
||||
if (!process.env.DATABASE_URL) throw new Error("DATABASE_URL fehlt. Zuerst npm run configure ausfuehren.");
|
||||
const target = new URL(process.env.DATABASE_URL);
|
||||
if (!["postgres:", "postgresql:"].includes(target.protocol)
|
||||
|| !["localhost", "127.0.0.1", "[::1]"].includes(target.hostname)
|
||||
|| !target.pathname.slice(1) || ["/postgres", "/template0", "/template1"].includes(target.pathname)) {
|
||||
throw new Error("Reset nur fuer eine ausdruecklich konfigurierte lokale Anwendungsdatenbank erlaubt.");
|
||||
}
|
||||
if (mode === "demo" && process.env.BOOTSTRAP_PASSWORD !== undefined && process.env.BOOTSTRAP_PASSWORD.length < 12) {
|
||||
throw new Error("BOOTSTRAP_PASSWORD muss mindestens 12 Zeichen haben. Es wurde nichts geloescht.");
|
||||
}
|
||||
console.log(`ACHTUNG: Alle Instanzdaten einschliesslich Konten, Sitzungen und Audit-Verlauf in ${target.hostname}:${target.port || "5432"}${target.pathname} werden geloescht.`);
|
||||
const client = await db.connect();
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
await client.query("SET LOCAL lock_timeout = '5s'");
|
||||
await client.query("SELECT pg_advisory_xact_lock(724139002)");
|
||||
await client.query("ALTER TABLE public.audit_log DISABLE TRIGGER audit_immutable");
|
||||
await client.query(`TRUNCATE TABLE
|
||||
public.applications, public.admission_rounds, public.application_limits,
|
||||
public.attendance, public.day_overrides, public.weekly_schedules,
|
||||
public.pickup_contacts, public.alone_rules, public.children, public.audit_log,
|
||||
public.sessions, public.login_attempts, public.staff, public.pickup_slots
|
||||
RESTART IDENTITY`);
|
||||
await client.query("ALTER SEQUENCE public.attendance_revision RESTART WITH 1");
|
||||
await client.query("ALTER TABLE public.audit_log ENABLE TRIGGER audit_immutable");
|
||||
await client.query(`INSERT INTO public.pickup_slots(starts_at, ends_at) VALUES
|
||||
('14:00', '14:15'), ('15:00', '15:15'), ('16:00', '16:15'), ('17:00', '17:15')`);
|
||||
await client.query("COMMIT");
|
||||
console.log("Instanzdaten geloescht. Schema, Migrationen und vier Standardslots sind bereit.");
|
||||
} catch (error) {
|
||||
await client.query("ROLLBACK");
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
if (mode === "clear") {
|
||||
console.log("Keine Konten vorhanden. Neuer Zugang: npm run db:setup. Demodaten: npm run db:seed.");
|
||||
return;
|
||||
}
|
||||
const tsx = createRequire(import.meta.url).resolve("tsx/cli");
|
||||
for (const script of ["setup.ts", "seed-demo.ts"]) {
|
||||
const result = spawnSync(process.execPath, [tsx, fileURLToPath(new URL(script, import.meta.url))], {
|
||||
cwd: fileURLToPath(new URL("../", import.meta.url)),
|
||||
env: process.env,
|
||||
stdio: "inherit",
|
||||
});
|
||||
if (result.error) throw result.error;
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`${script} fehlgeschlagen. Daten wurden bereits geleert; db:setup und db:seed nach Fehlerbehebung erneut ausfuehren.`);
|
||||
}
|
||||
}
|
||||
console.log("Demo-Instanz bereit. Mit dem neu ausgegebenen Zugang anmelden; alte Sitzungen sind ungueltig.");
|
||||
}
|
||||
|
||||
reset().catch((error: unknown) => {
|
||||
console.error("Instanz-Reset fehlgeschlagen:", error);
|
||||
process.exitCode = 1;
|
||||
}).finally(() => db.end());
|
||||
Reference in new issue
Block a user