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>
This commit is contained in:
127
utils/app-config.js
Normal file
127
utils/app-config.js
Normal file
@@ -0,0 +1,127 @@
|
||||
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();
|
Reference in New Issue
Block a user