Proper way of handling modules

Hello all.  I am using a node express app, that has a directory structure like this:

server\

server\controllers

server\controllers\api

server\controllers\app

server\controllers\handler

...

server\models\

 

Each of those directories have index.js files, and individual js files, one for each function for that purpose.  Say for example: 

 

Controllers.app.strategyGoogle = module.exports = function ()....

 

The controller/index.js and controller/app/index.js,controller/api/index.js etc files read in the directories on the fly (fs.readdirSync), so that I can simply create a new file or directory and keep going.  I'd prefer to continue to use that, but I've had to shove the actual Controllers.app.strategyGoogle definition in front of the module.exports expression in order to get the IDE to pick up the function reference, knowing that when I require() it, the assignment is going to get overridden anyway.  

So I'm wondering if there is a better, more preferred way to structure the thing, rather than simply tossing the idea of reading in the directory.

Thanks..

 

 

 

 

 

 

 

 

 

4 comments

Hi Paul,

Sorry, not sure I understand your problem. Could you please provide more details? A small example with source code would be just great. Thanks.

0

It's the difference between explicitly stating module definition by reading in js files using require directly, or by allowing the use of fs.readdirSync to spin through the directories and files in a tree to grab all of the files and put them in the right place.  While at the same time letting the IDE be able to understand what to do with them, 

 

At some point, my server calls to init two directories: Controllers and Modules.  Each of these work the same, just named differently.  

Controllers.init = function (callback) {

var dirs = [];

fs.readdirSync(__dirname).forEach(function (name) {

var mPath = __dirname + "/" + name;
if (!fs.existsSync(mPath)) return;

var stat = fs.statSync(mPath);

if (stat.isFile()) {
var parsed = path.parse(name);

// skip index file
if (parsed.name == "index") return;
Controllers[name] = require(mPath));
}

else if (stat.isDirectory()) {
// Look for index.js to be in the path.
if (fs.existsSync(mPath + '/index.js')) {
Controllers[name] = require(mPath);
}
else {
Controllers[name] = {};

fs.readdirSync(mPath).forEach(function (subPath) {
var filePath = mPath + '/' + subPath;
var stat = fs.statSync(filePath);
if (stat && stat.isFile()) {
var fnParsed = path.parse(filePath);
Controllers[name][fnParsed.name] = require(filePath));
}
});
}
}
});

callback();
};

 

This in effect builds the structure in the initial post: 

Controllers.app.strategyGoogle

Controllers.app.strategyLocal

Controllers.api ...

Controllers.handler ...

etc...

 

My issue is, node can handle this as I can reference say Controllers.app.strategyLocal using this structure, and things work fine.  In order to use the IDE to quickly jump to the file controllers/app/strategyLocal.js, I have to assign the value like this:

Controllers.app.strategyLocal = modules.exports = function() {}

In the latest update to webStorm, I am getting a warning that the assignment to Controllers.app.strategyLocal will get overwritten, which I knew.  I just had to define it like this in order to get the IDE to be able to Jump to Declaration. 

The alternative would be to have one huge, non-recursive master list of everything that is getting added, in the Controllers.init file, that I have to remember to update whenever adding a file somewhere downstream. 

Controllers.app = {};

Controllers.app.strategyGoogle = require('./app/strategyGoogle.js');

Controllers.app.strategyLocal = require('./app/strategyLocal.js');

var dir = './api';

Controllers.api = {

tokenInfo:  require(dir + 'tokenInfo.js')

};

 

I am just wondering if there is a middle ground solution somehow that I am missing that is a more expected approach for module definition and usage for node servers, that the IDE was programmed to handle, that uses directory scanning to find all files needed to make the app work.   You can see from the two handwritten examples that very quickly, scanning for certain types of files in directories would be the way to go to define and use your modules.  

Does that help clear it up?

 

 

 

 

 

 

 

 

 

0

Hi Paul,

Thanks for the explanation, I see your idea of using `fs.readdirSync` to traverse the directories. However, unfortunately, I can't reproduce the issue you've mentioned - a warning that the assignment to Controllers.app.strategyLocal will get overwritten. Please attach a screenshot of this warning details: position the text caret at this warning and perform "View | Error Description" on the main menu (Ctrl+F1). Also, please Alt+Enter on the warning, press right arrow and click "Edit inspection profile setting". What inspection provides this warning?

0

Well, for some reason, I am not seeing that warning about the assignment being overwritten.   If/when I see it again, I will take a screenshot and see it.  It was there before the last time I rebooted. 

 

 

0

Please sign in to leave a comment.