Private
Public Access
131 lines
3.5 KiB
JavaScript
Executable File
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 };
|