A Domain Driven Design Approach
So principles of DDD (Domain Driven Design) will encourage keeping things that belong together, together (in this case in Domain specific folders). However, I agree with @Fattie in that keeping all the routes together is better. For example, your NodeJS project may be an API and you can easily see all the endpoints served. This isn't breaking DDD. But here's how you can keep it lean:
# routes.js
const express = require('express');
const bodyParser = require('body-parser');
const { feature } = require('./router-utils');
const router = express.Router();
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
// Easy to see the route and what feature controls it.
router.get('/api/foo/bar/:something', feature('foo/bar'));
router.get('/api/foo/baz/:something', feature('foo/baz'));
router.get('/api/blah/blaaaah/:something', feature('blah/whatever'));
module.exports = router;
# router-utils.js
const cookie = require('cookie');
const auth = require('../auth/authorization');
const feature = (name, data = {}) => async (request, response, next) => {
// Do middleware stuff with cookies
const cookies = cookie.parse(request.headers.cookie || '');
// Do middleware stuff with payloads
if (request.url.includes('/some/path/here') && request.body?.payload) {
request.body = JSON.parse(request.body?.payload);
}
const { something } = request.body || '';
// Exit and continue to next routes if something is wrong.
if (something_wrong_here) {
next();
return null;
}
const Feature = require(`../features/${name}/${name.split('/').pop()}`);
// Pass all data to the feature.
return new Feature({ request, response, next, data }).handle();
};
module.exports = { feature };
# /features/foo/bar.js
const Query = require('../../common/query');
class Bar extends Query {
constructor(props) {
// Attach the request object to "this.request"
super(props);
}
async handle() {
let response = {};
const something = this.request.query.something;
// make some REST call to an upstream service and return the response.
// or make some database call and return the response.
}
module.exports = Bar;