How to node.js require all files in a folder and add a variable to them?

I have all these

const getData = require("../controllers/getData");
const singleEntry = require("../controllers/singleEntry");
const getCategories = require("../controllers/getCategories");
const addEntry = require("../controllers/addEntry");
const removeEntry = require("../controllers/removeEntry");
const addOneCategory = require("../controllers/addOneCategory");
const removeOneCategory = require("../controllers/removeOneCategory");
const passId = require("../controllers/passId");
const editAll = require("../controllers/editAll");

I can do this:

var controllerPath = require("path").join(__dirname, "../controllers");
require("fs")
  .readdirSync(controllerPath)
  .forEach(function (file) {
    require(file);
  });

But then I can’t reference them, like so .get("/aurelbooks", getData(Books)). Is there a way to do this

You could create a modules object and hang all of your functions on that as you dynamically import them.

Given getData.js:

function getData() {
  console.log('Hello from getData');
}

module.exports = getData;

and singleEntry.js

function singleEntry() {
  console.log('Hello from singleEntry');
}

module.exports = singleEntry;

You could do the following in index.js:

const modules = {};
const controllerPath = require('path').join(__dirname, 'controllers');

require('fs')
  .readdirSync(controllerPath)
  .forEach((file) => {
    const name = file.replace(/\.js$/, '');
    modules[name] = require(`../controllers/${file}`);
  });

modules.getData();
modules.singleEntry();

Outputs:

Hello from getData
Hello from singleEntry

If you don’t like prefixing method calls with modules you could also hang everything on global.


TBH, I’m not sure I would recommend doing any of this. I prefer to have a set of explicit imports, as that helps me see what is happening in a file at a glance.

Maybe @m3g4p0p knows of a better way?

1 Like

No I fully concur – such implicit imports would just make your code harder to read as you can’t immediately see where a given export is coming from, plus you won’t get autocomplete and jump-to functionality in your code editor.

But if you just won’t to “bundle” your controller functions, perhaps you could just add an entry file to expose them as a single object?

// controllers/index.js
module.exports = {
  getData: require('./getData'),
  singleEntry: require('./singleEntry'),
  // ...
}
// Then somewhere else...
const { getData, singleEntry } = require('../controllers/index')
1 Like

I understand “you won’t get autocomplete and jump-to functionality”.

I’m new at this, is it recommended to use the loop, do what I originally did, or create the controllers/index.js