Vollständige Migration weg von PocketBase. Neuer Stack: - better-sqlite3 (WAL-Mode, direkte SQLite-Abfragen) - jose (JWT HS256, 30 Tage Laufzeit) - bcryptjs (Passwort-Hashing, cost 12) Neue Dateien: - src/lib/server/db.ts → SQLite-Singleton + Schema + Helpers - src/lib/server/auth.ts → JWT sign/verify, bcrypt, Bearer-Token - src/lib/user.ts → Svelte-Store (ersetzt pb.authStore) - src/lib/api.ts → fetch()-Wrapper (ersetzt pb.collection()) - src/app.d.ts → App.Locals TypeScript-Deklaration - 30 neue API-Routes unter src/routes/api/ Entfernt: - Abhängigkeit von pocketbase npm-Paket (bleibt im package.json bis alle Referenzen bereinigt sind) - PocketBase-Container aus docker-compose.yml - Migrations und Hooks aus Deploy-Pipeline Docker: Ein einziger Container, SQLite-Volume unter /data/ Makefile: PocketBase-spezifische Targets entfernt seed.js: Komplett neu für neue REST-API
83 lines
2.4 KiB
TypeScript
83 lines
2.4 KiB
TypeScript
import { json, error } from '@sveltejs/kit';
|
|
import { getDb, row, toArr } from '$lib/server/db';
|
|
import { requireAuth } from '$lib/server/auth';
|
|
|
|
export async function GET({ request, params }) {
|
|
const u = await requireAuth(request);
|
|
const db = getDb();
|
|
const termin = db.prepare(
|
|
'SELECT * FROM termine WHERE id = ? AND verein_id = ?'
|
|
).get(params.id, u.verein_id);
|
|
if (!termin) throw error(404, 'Termin nicht gefunden');
|
|
return json(row(termin as Record<string, unknown>));
|
|
}
|
|
|
|
export async function PUT({ request, params }) {
|
|
const u = await requireAuth(request);
|
|
const db = getDb();
|
|
|
|
const existing = db.prepare(
|
|
'SELECT id FROM termine WHERE id = ? AND verein_id = ?'
|
|
).get(params.id, u.verein_id);
|
|
if (!existing) throw error(404, 'Termin nicht gefunden');
|
|
|
|
const body = await request.json();
|
|
|
|
db.prepare(`
|
|
UPDATE termine SET
|
|
titel = ?, beschreibung = ?, beginn = ?, ende = ?,
|
|
ort = ?, ort_id = ?, gruppe_ids = ?, durchfuehrender_id = ?,
|
|
verfuegbarkeit = ?, rrule = ?, serie_id = ?,
|
|
updated = strftime('%Y-%m-%dT%H:%M:%SZ','now')
|
|
WHERE id = ? AND verein_id = ?
|
|
`).run(
|
|
body.titel,
|
|
body.beschreibung ?? null,
|
|
body.beginn,
|
|
body.ende ?? null,
|
|
body.ort ?? null,
|
|
body.ort_id ?? null,
|
|
toArr(body.gruppe_ids),
|
|
body.durchfuehrender_id ?? null,
|
|
body.verfuegbarkeit ?? 'offen',
|
|
body.rrule ?? null,
|
|
body.serie_id ?? null,
|
|
params.id,
|
|
u.verein_id
|
|
);
|
|
|
|
const termin = db.prepare('SELECT * FROM termine WHERE id = ?').get(params.id);
|
|
return json(row(termin as Record<string, unknown>));
|
|
}
|
|
|
|
export async function DELETE({ request, params, url }) {
|
|
const u = await requireAuth(request);
|
|
const db = getDb();
|
|
|
|
const deleteSerie = url.searchParams.get('serie') === 'true';
|
|
|
|
if (deleteSerie) {
|
|
const termin = db.prepare(
|
|
'SELECT serie_id FROM termine WHERE id = ? AND verein_id = ?'
|
|
).get(params.id, u.verein_id) as { serie_id: string | null } | undefined;
|
|
|
|
if (!termin) throw error(404, 'Termin nicht gefunden');
|
|
|
|
if (termin.serie_id) {
|
|
db.prepare(
|
|
'DELETE FROM termine WHERE serie_id = ? AND verein_id = ?'
|
|
).run(termin.serie_id, u.verein_id);
|
|
} else {
|
|
db.prepare(
|
|
'DELETE FROM termine WHERE id = ? AND verein_id = ?'
|
|
).run(params.id, u.verein_id);
|
|
}
|
|
} else {
|
|
const result = db.prepare(
|
|
'DELETE FROM termine WHERE id = ? AND verein_id = ?'
|
|
).run(params.id, u.verein_id);
|
|
if (result.changes === 0) throw error(404, 'Termin nicht gefunden');
|
|
}
|
|
|
|
return new Response(null, { status: 204 });
|
|
}
|