简体   繁体   中英

node.js configure submodules

[EDIT]

Thanks to Stafano that formalized my question in a better way: You have a module

-) There are several files in this module

-) All these files depend on a configuration whose path is unknown to the module itself

-) This module does not do much on its own, and is meant to be used by other applications

-) These applications should inject a configuration path into the module before it can be used

So i have this module, used from another application. It's composed of other submodules and i want to configure it using a configuration object. I already tried to inject the configuration in my submodels but i had the same problem exposed in the original question.

For example my module use mongoDB (with mongoose) as a store.

// app.js
// in the config object i have the URI to the mongo instance (in order to create a connection).
var myModule = require('myModule')(config);

// myModule.js
// files
// myModule/index.js expose the module's functionalities
// is the entry point so I create the mongoose connection
var mongoose = require('mongoose');
module.exports = function(config){
  var connection = mongoose.createConnection(config.store.URL);
  // I need to expose this connection to the others submodules.
}

// myModule/storeController.js contains the business logic that use the store (createItem, deleteItem, get...) and requrie mongoose and my Models (store in the models folder)
var mongoose = require('mongoose');
var Item     = require('./models/item.js');

exports.createItem = function(item){
  Item.save(item, function(err, item){
    if (err) throw
    ...
  });
} 

// myModule/models/item.js

// In this module i need to use the connection application in the configuration.
var mongoose = require('mongoose');
var connection = // i don't know how to get it

var ItemSchema = new mongoose.Schema({
  name: String
});

module.exports = mongoose.model('item', ItemSchema);

If I inject the configuration obj to the item.js i can't do the module.exports of my model. I hope that this example can clarify my question, but the problem is the simple, expose an object after get it as a parameter.

[PREVIOUS] I have a node.js application that require a module. This module accept the coniguration file path (a JSON file). I need to load that configuration on require and expose it to the module.

How can I achieve this behavior?

Something like:

// app.js
var myModule = require('myModule')(__dirname + '/config/myModuleCnfig.json');

// myModule.js

module.exports = function(configPath){
  var config = require(configPath);
  module.exports = config;  // This is wrong
}

Is there another way to get the configuration path, configure the module and share the configuration??

With "share the configuration" i mean that i want to give the possibility to other files of my module to use that configuration.

Thanks for any suggestions!

FINAL EDIT:

After many misunderstandings, your problem is finally clear to me. To summarise what's in the comments, here is the situation:

  • You have a module
  • There are several files in this module
  • All these files depend on a configuration whose path is unknown to the module itself
  • This module does not do much on its own, and is meant to be used by other applications
  • These applications should inject a configuration path into the module before it can be used

Since you cannot modify dynamically what a module exports, you should use another approach. As with most situations that you encounter in programming, there is not one way which is always right, as much pedends on your requirements and limitations.

The easiest way to do this (which I don't recommend) is to use a global variable, which you set in your myModule.js file and will be used by the other files in your module. The biggest drawback of this approach is that you wouldn't be able to use multiple instances of the module at the same time with different configurations. Also, any other module could easily modify (deliberately or not) you configuration at any time, by simply changing the value of the global variable, so it's also a security risk.

A much better way, which will probably require more work on your part - depending on how many files you have - is to implement some kind of Inversion of Control (IoC) . In your case, you could turn all your exports into functions that accept a config, and then initialise them by passing the active configuration after you require the module. I don't know the specifics of your implementation, so here is some sample code:

// submodule1.js
module.exports = function(config) {
    // return something that uses the configuration
}

// myModule.js
var fs = require('fs');
var submodule1 = require('./submodule1');
var submodule2 = require('./submodule2');
// ...
module.exports = function(configPath){
    var config = JSON.parse(fs.readFileSync(configPath));
    var sm1 = submodule1(config);
    var sm2 = submodule2(config);
    return /* an object that uses sm1 and sm2 */; 
}

If your module is quite complex, you can use some IoC library that does the binding for you. An good one could be Electrolite .

Hope this helps.

PREVIOUS ANSWER:

You can use a library called jsop :

var jsop = require('jsop');
var config = jsop('./config/myModuleCnfig.json');

If you don't want to add a dependency to this module, the linked GitHub page also has a snippet that you can use to load the json config using only native methods.

EDIT: I just realised that this module is only for node 0.11, which you are probably not using. Since you don't probably need the writing functionality, you can use the following snippet instead:

var fs = require('fs')
var config = JSON.parse(fs.readFileSync('./config/myModuleCnfig.json'))

EDIT 2:

Now I think I understand your problem better. To pass the path to the required configuration, you can do something like this:

// myModule.js

var fs = require('fs')
module.exports = function(configPath){
    var config = JSON.parse(fs.readFileSync(configPath))
    return config;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM