Files
2026-04-15 15:21:01 +00:00

131 lines
3.5 KiB
JavaScript
Executable File

const fs = require('fs');
const path = require('path');
class HandlerLoader {
constructor(handlersDir, logPrefix = '📎') {
this.handlersDir = handlersDir;
this.logPrefix = logPrefix;
this.handlers = new Map();
this.fileCache = new Map(); // Cache for file contents and metadata
this.watchedFiles = new Map(); // File watchers for hot reloading
this.preloadHandlers();
}
preloadHandlers() {
const files = fs.readdirSync(this.handlersDir);
const jsFiles = files.filter(file => file.endsWith('.js'));
for (const file of jsFiles) {
const handlerName = path.basename(file, '.js');
this.get(handlerName);
}
}
get(handlerName) {
if (this.handlers.has(handlerName)) {
return this.handlers.get(handlerName);
}
const handlerPath = path.join(this.handlersDir, `${handlerName}.js`);
if (fs.existsSync(handlerPath)) {
delete require.cache[require.resolve(handlerPath)];
const handler = require(handlerPath);
const stats = fs.statSync(handlerPath);
this.handlers.set(handlerName, handler);
this.fileCache.set(handlerName, {
path: handlerPath,
mtime: stats.mtime,
size: stats.size,
loaded: true,
handler: handler
});
return handler;
}
this.logHandlerNotFound(handlerName);
return null;
}
logHandlerNotFound(handlerName) {
console.error(`❌ HANDLER NOT FOUND: ${handlerName}`);
console.error(` Searched in directory: ${this.handlersDir}`);
console.error(` Expected file: ${path.join(this.handlersDir, handlerName + '.js')}`);
}
hasHandler(handlerName) {
return this.handlers.has(handlerName) || fs.existsSync(path.join(this.handlersDir, `${handlerName}.js`));
}
getAvailableHandlers() {
const loadedHandlers = Array.from(this.handlers.keys());
const allFiles = fs.existsSync(this.handlersDir) ?
fs.readdirSync(this.handlersDir)
.filter(file => file.endsWith('.js'))
.map(file => path.basename(file, '.js')) : [];
return [...new Set([...loadedHandlers, ...allFiles])];
}
reloadHandlers() {
this.handlers.clear();
this.fileCache.clear();
this.preloadHandlers();
}
reloadHandler(handlerName) {
const handlerPath = path.join(this.handlersDir, `${handlerName}.js`);
if (!fs.existsSync(handlerPath)) {
console.error(`❌ Handler file not found: ${handlerPath}`);
return false;
}
this.handlers.delete(handlerName);
this.fileCache.delete(handlerName);
const handler = this.get(handlerName);
if (handler) {
console.log(`${this.logPrefix} Reloaded handler: ${handlerName}`);
return true;
} else {
return false;
}
}
getFileInfo(handlerName) {
return this.fileCache.get(handlerName);
}
isFileModified(handlerName) {
const fileInfo = this.fileCache.get(handlerName);
if (!fileInfo) return false;
const stats = fs.statSync(fileInfo.path);
return stats.mtime > fileInfo.mtime;
}
checkForModifications() {
const modified = [];
for (const [handlerName] of this.fileCache) {
if (this.isFileModified(handlerName)) {
modified.push(handlerName);
}
}
if (modified.length > 0) {
console.log(`${this.logPrefix} Detected modifications: ${modified.join(', ')}`);
for (const handlerName of modified) {
this.reloadHandler(handlerName);
}
}
return modified;
}
}
module.exports = { HandlerLoader };