Migrate: PocketBase → SvelteKit + better-sqlite3 + JWT
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
This commit is contained in:
parent
61c430f2e6
commit
39981c0d17
58 changed files with 2313 additions and 651 deletions
|
|
@ -1,5 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { pb } from '$lib/pb';
|
||||
import { api } from '$lib/api';
|
||||
import { user } from '$lib/user';
|
||||
import { get } from 'svelte/store';
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import { generatePain008, downloadXml, minEinzugsdatum, type SepaPosition } from '$lib/sepa';
|
||||
|
|
@ -41,11 +43,10 @@
|
|||
};
|
||||
|
||||
onMount(async () => {
|
||||
if (pb.authStore.record?.rolle === 'trainer') { goto('/'); return; }
|
||||
const vid = pb.authStore.record?.verein_id as string;
|
||||
if (get(user)?.rolle === 'trainer') { goto('/'); return; }
|
||||
[beitraege, verein] = await Promise.all([
|
||||
pb.collection('beitraege').getFullList<Beitrag>({ sort: 'name' }),
|
||||
pb.collection('vereine').getOne<Verein>(vid).catch(() => null),
|
||||
api.get<Beitrag[]>('/beitraege', { sort: 'name' }),
|
||||
api.get<Verein>('/vereine').catch(() => null),
|
||||
]);
|
||||
loading = false;
|
||||
});
|
||||
|
|
@ -71,13 +72,12 @@
|
|||
}
|
||||
saving = true;
|
||||
try {
|
||||
const vid = pb.authStore.record?.verein_id as string;
|
||||
const data = { verein_id: vid, name: fName.trim(), betrag, rhythmus: fRhythmus, beschreibung: fBeschr.trim() };
|
||||
const data = { name: fName.trim(), betrag, rhythmus: fRhythmus, beschreibung: fBeschr.trim() };
|
||||
if (editId) {
|
||||
await pb.collection('beitraege').update(editId, data);
|
||||
await api.put('/beitraege/' + editId, data);
|
||||
beitraege = beitraege.map(b => b.id === editId ? { ...b, ...data } as Beitrag : b);
|
||||
} else {
|
||||
const neu = await pb.collection('beitraege').create<Beitrag>(data);
|
||||
const neu = await api.post<Beitrag>('/beitraege', data);
|
||||
beitraege = [...beitraege, neu].sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
showForm = false;
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
|
||||
async function loeschen(b: Beitrag) {
|
||||
if (!confirm(`"${b.name}" wirklich löschen?`)) return;
|
||||
await pb.collection('beitraege').delete(b.id);
|
||||
await api.del('/beitraege/' + b.id);
|
||||
beitraege = beitraege.filter(x => x.id !== b.id);
|
||||
}
|
||||
|
||||
|
|
@ -102,9 +102,7 @@
|
|||
einzugsdatum = minEinzugsdatum();
|
||||
sepaLoading = true;
|
||||
try {
|
||||
const alle = await pb.collection('mitglieder').getFullList<Mitglied>({
|
||||
filter: 'status = "aktiv"', sort: 'nachname,vorname',
|
||||
});
|
||||
const alle = await api.get<Mitglied[]>('/mitglieder', { status: 'aktiv', sort: 'nachname,vorname' });
|
||||
const mit = alle.filter(m => m.iban?.trim());
|
||||
const ohne = alle.length - mit.length;
|
||||
sepaPreview = { mitglieder: mit, ohne };
|
||||
|
|
@ -157,10 +155,9 @@
|
|||
downloadXml(xml, `sepa-einzug-${einzugsdatum}.xml`);
|
||||
|
||||
// Einzüge als "ausstehend" anlegen
|
||||
const vid = pb.authStore.record?.verein_id as string;
|
||||
await Promise.all(
|
||||
sepaPreview.mitglieder.map((m) =>
|
||||
pb.collection('einzuege').create({
|
||||
api.post('/einzuege', {
|
||||
mitglied_id: m.id,
|
||||
beitrag_id: sepaFor!.id,
|
||||
betrag: sepaFor!.betrag,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue