Files
LuHost/utils/app-config.js
Nathan Schneider 3aed09b60f Initial commit: LuHost - Luanti Server Management Web Interface
A modern web interface for Luanti (Minetest) server management with ContentDB integration.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-23 17:32:37 -06:00

127 lines
3.2 KiB
JavaScript

const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');
const os = require('os');
class AppConfig {
constructor() {
this.configDir = path.join(os.homedir(), '.luhost');
this.configFile = path.join(this.configDir, 'config.json');
this.defaultConfig = {
dataDirectory: this.getDefaultDataDirectory(),
serverPort: 3000,
debugMode: false
};
this.config = null;
}
getDefaultDataDirectory() {
const homeDir = os.homedir();
const possibleDirs = [
path.join(homeDir, '.luanti'),
path.join(homeDir, '.minetest')
];
// Use the first one that exists, or default to .minetest
for (const dir of possibleDirs) {
if (fsSync.existsSync(dir)) {
return dir;
}
}
return path.join(homeDir, '.minetest');
}
async load() {
try {
// Ensure config directory exists
if (!fsSync.existsSync(this.configDir)) {
await fs.mkdir(this.configDir, { recursive: true });
}
// Try to read existing config
try {
const configData = await fs.readFile(this.configFile, 'utf8');
this.config = { ...this.defaultConfig, ...JSON.parse(configData) };
} catch (error) {
if (error.code === 'ENOENT') {
// Config file doesn't exist, create it with defaults
this.config = { ...this.defaultConfig };
await this.save();
} else {
throw error;
}
}
return this.config;
} catch (error) {
console.error('Failed to load app config:', error);
// Fall back to defaults if config loading fails
this.config = { ...this.defaultConfig };
return this.config;
}
}
async save() {
try {
if (!fsSync.existsSync(this.configDir)) {
await fs.mkdir(this.configDir, { recursive: true });
}
await fs.writeFile(this.configFile, JSON.stringify(this.config, null, 2), 'utf8');
} catch (error) {
console.error('Failed to save app config:', error);
throw error;
}
}
get(key) {
return this.config ? this.config[key] : this.defaultConfig[key];
}
set(key, value) {
if (!this.config) {
this.config = { ...this.defaultConfig };
}
this.config[key] = value;
}
async update(updates) {
if (!this.config) {
this.config = { ...this.defaultConfig };
}
Object.assign(this.config, updates);
await this.save();
}
getDataDirectory() {
return this.get('dataDirectory');
}
async setDataDirectory(dataDir) {
const resolvedPath = path.resolve(dataDir);
// Validate that the directory exists or can be created
try {
await fs.access(resolvedPath);
} catch (error) {
if (error.code === 'ENOENT') {
// Try to create the directory
try {
await fs.mkdir(resolvedPath, { recursive: true });
} catch (createError) {
throw new Error(`Cannot create data directory: ${createError.message}`);
}
} else {
throw new Error(`Cannot access data directory: ${error.message}`);
}
}
this.set('dataDirectory', resolvedPath);
await this.save();
return resolvedPath;
}
}
module.exports = new AppConfig();