Teamdatenbank ohne lowdb, Pfad unabhaengig vom Startverzeichnis

lowdb v7 ist ESM-only, das Projekt ist CommonJS. Der bisherige Umweg ueber
eine async IIFE mit await import() hatte zur Folge, dass db bei einem sehr
fruehen Request noch undefined sein konnte.

Fuer eine Liste von Teamnamen genuegt fs: read/write lesen und schreiben
db.json direkt und synchron, die Race-Condition entfaellt und lowdb kann als
Abhaengigkeit raus. Die exportierte API bleibt unveraendert, score.js und
routes/admin.js brauchen keine Anpassung.

Der Pfad zu db.json wird jetzt ueber __dirname aufgeloest statt relativ zum
Arbeitsverzeichnis, damit die Datei unabhaengig vom Startverzeichnis immer
an derselben Stelle liegt. Fehlt oder bricht die Datei, wird auf eine leere
Teamliste zurueckgefallen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Julian Appel 2026-08-19 20:39:12 +02:00
parent c4325ae8ac
commit 92eb59d2ef
3 changed files with 38 additions and 50 deletions

View file

@ -1,44 +1,59 @@
"use strict";
let db;
// Datenbank-Controller
// Haelt die Liste der bekannten Teamnamen persistent in db.json vor,
// damit sie im Adminpanel als Auswahl-Dropdown angeboten werden koennen.
// Import ESM into CJS file using immediately invoked function expression because of missing top-level await in CJS
(async () => {
const { LowSync } = await import('lowdb');
const { JSONFileSync } = await import('lowdb/node');
db = new LowSync(new JSONFileSync('db.json'), { teams: []})
})();
const fs = require('node:fs');
const path = require('node:path');
// Pfad relativ zum Modul, nicht zum Arbeitsverzeichnis, damit die Datei
// unabhaengig vom Startverzeichnis immer an derselben Stelle liegt
const dbFile = path.join(__dirname, '..', 'db.json');
// Liest db.json ein, faellt bei fehlender oder defekter Datei auf eine leere Liste zurueck
function read() {
try {
const data = JSON.parse(fs.readFileSync(dbFile, 'utf-8'));
if(!Array.isArray(data.teams)) data.teams = []; // Fehlender oder falscher teams-Key
return data;
} catch (err) {
console.error("db.json konnte nicht gelesen werden, verwende leere Teamliste: ", err.message);
return { teams: [] };
}
}
// Schreibt den uebergebenen Datensatz zurueck nach db.json
function write(data) {
fs.writeFileSync(dbFile, JSON.stringify(data, null, 2));
}
// Returns all teams from db
function getTeams() {
db.read();
return db.data.teams
return read().teams;
}
// Adds passed teamName to db if not already existing
function addTeam(teamName) {
console.log(teamName)
db.read();
if(!db.data.teams.includes(teamName) && teamName != "") { // Teamname not in db
db.data.teams.push(teamName);
db.write();
} else { // Teamname already in db
const data = read();
if(!data.teams.includes(teamName) && teamName != "") { // Teamname not in db
data.teams.push(teamName);
write(data);
}
}
// Deletes passed teamName from db if existing
function deleteTeam(teamName) {
db.read();
if(db.data.teams.includes(teamName) && teamName != "") { // Teamname in db
db.data.teams.splice(db.data.teams.indexOf(teamName), 1) // Delete corresponding array entry
db.write();
const data = read();
if(data.teams.includes(teamName) && teamName != "") { // Teamname in db
data.teams.splice(data.teams.indexOf(teamName), 1); // Delete corresponding array entry
write(data);
}
}
// Returns important values from db
function getValues() {
db.read();
console.log(db.data)
return db.data
return read();
}
module.exports = {

View file

@ -14,7 +14,6 @@
"express-ws": "^5.0.2",
"hbs": "~4.0.4",
"http-errors": "~1.6.3",
"lowdb": "^7.0.1",
"moment": "^2.30.1",
"morgan": "~1.9.1",
"socket.io": "^4.7.5",
@ -470,20 +469,6 @@
"node": ">= 0.10"
}
},
"node_modules/lowdb": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/lowdb/-/lowdb-7.0.1.tgz",
"integrity": "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw==",
"dependencies": {
"steno": "^4.0.2"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -858,17 +843,6 @@
"node": ">= 0.6"
}
},
"node_modules/steno": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/steno/-/steno-4.0.2.tgz",
"integrity": "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A==",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",

View file

@ -12,7 +12,6 @@
"express-ws": "^5.0.2",
"hbs": "~4.0.4",
"http-errors": "~1.6.3",
"lowdb": "^7.0.1",
"moment": "^2.30.1",
"morgan": "~1.9.1",
"socket.io": "^4.7.5",