Files
2026-08-30 15:25:31 +02:00

57 lines
2.2 KiB
JavaScript

/*
! /server/actions.js
? Dynamic action loader for Socket.IO events using a recursive file system scan.
*/
// % imports
import fs from 'fs';
import path from 'path';
import { fileURLToPath, pathToFileURL } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// % Target directory where the actual action files reside
const actionsDir = path.join(__dirname, '..', 'actions');
// $ debug-output
console.info('[Paths] Actions:', actionsDir);
/*
$ Recursive function to load action files and build a flat map for direct dot-notation access
= Maps all JavaScript files inside the actions directory into a flat key-value structure (e.g. 'chat.message').
^ Usage in WebSocket (Socket.io) Handlers:
?? import actions from './actions/index.js';
? Example: "socket.on('chat.message', (data) => actions['chat.message'](socket, data));"
? Example: "socket.on('system.ping', () => actions['system.ping'](socket));"
*/
async function loadActions(dir = actionsDir, baseDir = actionsDir, actionsObj = {}) {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
// ~ Pass the main object (actionsObj) further down recursively
await loadActions(fullPath, baseDir, actionsObj);
} else if (entry.isFile() && entry.name !== 'index.js' && !entry.name.startsWith('.') && entry.name.endsWith('.js')) {
// ~ Calculate the relative path from the root directory
const relativePath = path.relative(baseDir, fullPath);
const parts = relativePath.split(path.sep).map(p => p.replace(/\.js$/, ''));
// ~ Import the module
const fileUrl = pathToFileURL(fullPath).href;
const module = await import(fileUrl);
// ~ Map the module directly as a flat string key (e.g. "chat.message") into the main object
const eventName = parts.join('.');
actionsObj[eventName] = module.default || module;
}
}
return actionsObj;
}
// $ Initialize asynchronously and export the loaded actions object
const actions = await loadActions();
export default actions;