refactor: simplify codebase and replace external dependencies with Bun built-ins

Backend changes:
- Merge duplicate award logic (calculatePointsAwardProgress + getPointsAwardEntityBreakdown)
- Simplify LoTW service (merge syncQSOs functions, simplify polling)
- Remove job queue abstraction (hardcode LoTW sync, remove processor registry)
- Consolidate config files (database.js, logger.js, jwt.js → single config.js)
- Replace bcrypt with Bun.password.hash/verify
- Replace Pino logger with console-based logger
- Fix: export syncQSOs and getLastLoTWQSLDate for job queue imports
- Fix: correct database path resolution using new URL()

Frontend changes:
- Simplify auth store (remove localStorage wrappers, reduce from 222→109 lines)
- Consolidate API layer (remove verbose JSDoc, 180→80 lines)
- Add shared UI components (Loading, ErrorDisplay, BackButton)

Dependencies:
- Remove bcrypt (replaced with Bun.password)
- Remove pino and pino-pretty (replaced with console logger)

Total: ~445 lines removed (net), 3 dependencies removed
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-16 18:27:10 +01:00
parent 41ccb5c185
commit 0db6b68f48
13 changed files with 520 additions and 813 deletions

62
src/backend/config.js Normal file
View File

@@ -0,0 +1,62 @@
import Database from 'bun:sqlite';
import { drizzle } from 'drizzle-orm/bun-sqlite';
import * as schema from './db/schema/index.js';
import { join } from 'path';
// ===================================================================
// Configuration
// ===================================================================
const isDevelopment = process.env.NODE_ENV !== 'production';
export const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
export const LOG_LEVEL = process.env.LOG_LEVEL || (isDevelopment ? 'debug' : 'info');
// ===================================================================
// Logger
// ===================================================================
const logLevels = { debug: 0, info: 1, warn: 2, error: 3 };
const currentLogLevel = logLevels[LOG_LEVEL] || 1;
function log(level, message, data) {
if (logLevels[level] < currentLogLevel) return;
const timestamp = new Date().toISOString();
const logMessage = `[${timestamp}] ${level.toUpperCase()}: ${message}`;
if (data && Object.keys(data).length > 0) {
console.log(logMessage, JSON.stringify(data, null, 2));
} else {
console.log(logMessage);
}
}
export const logger = {
debug: (message, data) => log('debug', message, data),
info: (message, data) => log('info', message, data),
warn: (message, data) => log('warn', message, data),
error: (message, data) => log('error', message, data),
};
export default logger;
// ===================================================================
// Database
// ===================================================================
// Get the directory containing this config file, then go to parent for db location
const __dirname = new URL('.', import.meta.url).pathname;
const dbPath = join(__dirname, 'award.db');
const sqlite = new Database(dbPath);
sqlite.exec('PRAGMA foreign_keys = ON');
export const db = drizzle({
client: sqlite,
schema,
});
export async function closeDatabase() {
sqlite.close();
}