Initial commit
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
! /server/routers.js
|
||||
? Dynamic Express router loader matching the action loader pattern.
|
||||
*/
|
||||
|
||||
// % imports
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath, pathToFileURL } from 'url';
|
||||
import express from 'express';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// % Target directory where the actual route files reside
|
||||
const routersDir = path.join(__dirname, '..', 'routers');
|
||||
|
||||
// $ debug-output
|
||||
console.info('[Paths] Routers:', routersDir);
|
||||
export const registeredEndpoints = [];
|
||||
|
||||
// $ recursive function to load routers and extract clean endpoints
|
||||
async function loadRouters(dir = routersDir, baseDir = routersDir, currentPrefix = '') {
|
||||
let mainRouter = express.Router();
|
||||
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
// ~ handle subdirectory and extend prefix
|
||||
const subPrefix = `${currentPrefix}/${entry.name}`;
|
||||
const subRouter = await loadRouters(fullPath, baseDir, subPrefix);
|
||||
mainRouter.use(`/${entry.name}`, subRouter);
|
||||
} else if (entry.isFile() && entry.name !== 'index.js' && !entry.name.startsWith('.') && entry.name.endsWith('.js')) {
|
||||
const fileUrl = pathToFileURL(fullPath).href;
|
||||
const module = await import(fileUrl);
|
||||
const routeHandler = module.default || module;
|
||||
|
||||
const routeName = entry.name.replace(/\.js$/, '');
|
||||
const subRouter = express.Router();
|
||||
|
||||
// ~ pass subrouter into the handler function
|
||||
if (typeof routeHandler === 'function') {
|
||||
await routeHandler(subRouter);
|
||||
}
|
||||
|
||||
const finalFolderPrefix = currentPrefix === '' ? '' : currentPrefix;
|
||||
const endpointPath = routeName === 'root' ? finalFolderPrefix || '/' : `${finalFolderPrefix}/${routeName}`;
|
||||
|
||||
// ~ extract methods and paths directly from the sub-router stack
|
||||
subRouter.stack.forEach(layer => {
|
||||
if (layer.route) {
|
||||
const methods = Object.keys(layer.route.methods).join(', ').toUpperCase();
|
||||
const subRoutePath = layer.route.path === '/' ? '' : layer.route.path;
|
||||
registeredEndpoints.push(`${methods} ${endpointPath}${subRoutePath}`.replace(/\/+/g, '/'));
|
||||
}
|
||||
});
|
||||
|
||||
if (routeName === 'root') {
|
||||
mainRouter.use('/', subRouter);
|
||||
} else {
|
||||
mainRouter.use(`/${routeName}`, subRouter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return mainRouter;
|
||||
}
|
||||
|
||||
// $ Initialize asynchronously and export the loaded routers object
|
||||
const routers = await loadRouters();
|
||||
|
||||
// $ export
|
||||
export default routers;
|
||||
Reference in New Issue
Block a user