Initial commit
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
! /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;
|
||||
Reference in New Issue
Block a user