125 lines
3.7 KiB
JavaScript
125 lines
3.7 KiB
JavaScript
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);
|
|
}
|