176 lines
4.6 KiB
JavaScript
176 lines
4.6 KiB
JavaScript
const sqlite3 = require('sqlite3').verbose();
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const logger = require('../utils/logger');
|
|
|
|
class LocalDatabase {
|
|
constructor() {
|
|
this.db = null;
|
|
this.dbPath = null;
|
|
}
|
|
|
|
async initialize() {
|
|
try {
|
|
// Create data directory if it doesn't exist
|
|
const dataDir = path.join(__dirname, '../../data');
|
|
if (!fs.existsSync(dataDir)) {
|
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
logger.info(`[LOCAL DB] Created data directory: ${dataDir}`);
|
|
}
|
|
|
|
this.dbPath = path.join(dataDir, 'mods.db');
|
|
|
|
logger.info(`[LOCAL DB] Initializing database at: ${this.dbPath}`);
|
|
|
|
// Create database connection
|
|
this.db = new sqlite3.Database(this.dbPath, (err) => {
|
|
if (err) {
|
|
logger.error('[LOCAL DB] Error opening database:', err.message);
|
|
throw err;
|
|
} else {
|
|
logger.info('[LOCAL DB] Database connected successfully');
|
|
}
|
|
});
|
|
|
|
// Enable foreign keys
|
|
await this.run('PRAGMA foreign_keys = ON');
|
|
|
|
// Create tables
|
|
await this.createTables();
|
|
|
|
logger.info('[LOCAL DB] Database initialized successfully');
|
|
return true;
|
|
} catch (error) {
|
|
logger.error('[LOCAL DB] Failed to initialize database:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async createTables() {
|
|
const tables = [
|
|
// Mods table
|
|
`CREATE TABLE IF NOT EXISTS mods (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL UNIQUE,
|
|
version TEXT NOT NULL,
|
|
author TEXT NOT NULL,
|
|
description TEXT,
|
|
enabled INTEGER DEFAULT 1,
|
|
installed_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
file_path TEXT NOT NULL,
|
|
checksum TEXT,
|
|
dependencies TEXT,
|
|
config TEXT
|
|
)`,
|
|
|
|
// Mod assets table
|
|
`CREATE TABLE IF NOT EXISTS mod_assets (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
mod_id INTEGER NOT NULL,
|
|
asset_type TEXT NOT NULL, -- 'ship', 'item', 'quest', etc.
|
|
asset_id TEXT NOT NULL,
|
|
asset_data TEXT NOT NULL, -- JSON data
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (mod_id) REFERENCES mods (id) ON DELETE CASCADE,
|
|
UNIQUE(mod_id, asset_type, asset_id)
|
|
)`,
|
|
|
|
// Server mod preferences table
|
|
`CREATE TABLE IF NOT EXISTS server_mod_preferences (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT NOT NULL,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
)`,
|
|
|
|
// Mod load order table
|
|
`CREATE TABLE IF NOT EXISTS mod_load_order (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
mod_id INTEGER NOT NULL,
|
|
load_order INTEGER NOT NULL,
|
|
FOREIGN KEY (mod_id) REFERENCES mods (id) ON DELETE CASCADE,
|
|
UNIQUE(mod_id)
|
|
)`
|
|
];
|
|
|
|
for (const table of tables) {
|
|
await this.run(table);
|
|
}
|
|
|
|
logger.info('[LOCAL DB] All tables created successfully');
|
|
}
|
|
|
|
// Helper method to run SQL commands
|
|
run(sql, params = []) {
|
|
return new Promise((resolve, reject) => {
|
|
this.db.run(sql, params, function(err) {
|
|
if (err) {
|
|
logger.error('[LOCAL DB] SQL Error:', err.message);
|
|
reject(err);
|
|
} else {
|
|
resolve({ id: this.lastID, changes: this.changes });
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Helper method to get single row
|
|
get(sql, params = []) {
|
|
return new Promise((resolve, reject) => {
|
|
this.db.get(sql, params, (err, row) => {
|
|
if (err) {
|
|
logger.error('[LOCAL DB] SQL Error:', err.message);
|
|
reject(err);
|
|
} else {
|
|
resolve(row);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Helper method to get multiple rows
|
|
all(sql, params = []) {
|
|
return new Promise((resolve, reject) => {
|
|
this.db.all(sql, params, (err, rows) => {
|
|
if (err) {
|
|
logger.error('[LOCAL DB] SQL Error:', err.message);
|
|
reject(err);
|
|
} else {
|
|
resolve(rows);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
// Close database connection
|
|
close() {
|
|
return new Promise((resolve, reject) => {
|
|
if (this.db) {
|
|
this.db.close((err) => {
|
|
if (err) {
|
|
logger.error('[LOCAL DB] Error closing database:', err.message);
|
|
reject(err);
|
|
} else {
|
|
logger.info('[LOCAL DB] Database closed');
|
|
resolve();
|
|
}
|
|
});
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get database instance
|
|
getDatabase() {
|
|
return this.db;
|
|
}
|
|
|
|
// Get database path
|
|
getDatabasePath() {
|
|
return this.dbPath;
|
|
}
|
|
}
|
|
|
|
module.exports = new LocalDatabase();
|