import Database from 'better-sqlite3'; import bcrypt from 'bcrypt'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { readFileSync } from 'fs'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const DB_PATH = join(__dirname, 'kenteken.db'); let db; export function initDb() { db = new Database(DB_PATH); db.pragma('journal_mode = WAL'); db.pragma('foreign_keys = ON'); db.exec(` CREATE TABLE IF NOT EXISTS cars ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, width REAL NOT NULL, height REAL NOT NULL, rearWidth REAL, rearHeight REAL ) `); db.exec(` CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY, value TEXT NOT NULL ) `); // Seed the database with default cars if empty const count = db.prepare('SELECT COUNT(*) as cnt FROM cars').get(); if (count.cnt === 0) { seedDefaultCars(); } // Set default admin password if not set const pwd = db.prepare("SELECT value FROM settings WHERE key = 'admin_password'").get(); if (!pwd) { const hash = bcrypt.hashSync('Rotterdam-010', 10); db.prepare("INSERT INTO settings (key, value) VALUES ('admin_password', ?)").run(hash); } } function seedDefaultCars() { const defaultCarsPath = join(__dirname, '..', 'Kenteken-Gen-1-main', 'src', 'frontend', 'carOptions.json'); let defaultCars; try { defaultCars = JSON.parse(readFileSync(defaultCarsPath, 'utf-8')); } catch { // Fallback: try from shared-cars.json try { const sharedPath = join(__dirname, '..', 'Kenteken-Gen-1-main', 'shared-cars.json'); defaultCars = JSON.parse(readFileSync(sharedPath, 'utf-8')); } catch { defaultCars = []; } } const insert = db.prepare( 'INSERT INTO cars (name, width, height, rearWidth, rearHeight) VALUES (?, ?, ?, ?, ?)' ); const insertMany = db.transaction((cars) => { for (const car of cars) { insert.run(car.name, car.width, car.height, car.rearWidth || null, car.rearHeight || null); } }); insertMany(defaultCars); } export function getAllCars() { return db.prepare('SELECT * FROM cars ORDER BY name COLLATE NOCASE').all(); } export function addCar({ name, width, height, rearWidth, rearHeight }) { const result = db.prepare( 'INSERT INTO cars (name, width, height, rearWidth, rearHeight) VALUES (?, ?, ?, ?, ?)' ).run(name, width, height, rearWidth, rearHeight); return db.prepare('SELECT * FROM cars WHERE id = ?').get(result.lastInsertRowid); } export function updateCar(id, { name, width, height, rearWidth, rearHeight }) { const result = db.prepare( 'UPDATE cars SET name = ?, width = ?, height = ?, rearWidth = ?, rearHeight = ? WHERE id = ?' ).run(name, width, height, rearWidth, rearHeight, id); if (result.changes === 0) return null; return db.prepare('SELECT * FROM cars WHERE id = ?').get(id); } export function deleteCar(id) { const result = db.prepare('DELETE FROM cars WHERE id = ?').run(id); return result.changes > 0; } export function replaceAllCars(cars) { const tx = db.transaction(() => { db.prepare('DELETE FROM cars').run(); const insert = db.prepare( 'INSERT INTO cars (name, width, height, rearWidth, rearHeight) VALUES (?, ?, ?, ?, ?)' ); for (const car of cars) { insert.run( String(car.name || '').trim(), Number(car.width) || 0, Number(car.height) || 0, car.rearWidth ? Number(car.rearWidth) : null, car.rearHeight ? Number(car.rearHeight) : null ); } }); tx(); } export function verifyPassword(password) { const row = db.prepare("SELECT value FROM settings WHERE key = 'admin_password'").get(); if (!row) return false; return bcrypt.compareSync(password, row.value); }