Pass data to custom npm package module - javascript

I'm new to building custom npm packages and I'm getting lost configuring it with data coming from the application it is using it.
EDIT: This is just an example but the app will have more methods and those fake a and b will be used from many of those methods.
Basically on App I'm requiring my package in this way:
var a = 'a';
var b = 'b';
var module = require('module')(a, b);
module.test();
My module in his index file has:
var a;
var b;
function test() {
return {
a: a,
b: b
};
}
module.exports = function(_a, _b) {
a = _a;
b = _b;
return {
test: test
}
};
As you can guess it is not working as I was expecting... How can I pass my custom data to my npm package and be able using that data along my methods?

shouldnt you use it something like this
var a = 'a';
var b = 'b';
var module = require('module');
module.init(a,b);
// do some other code....
module.test();
and in your module like this:
var _a = null;
var _b = null;
var test = function() {
return {
a: _a,
b: _b
}
}
var init = function(a, b) {
_a = a;
_b = b;
}
module.exports = {
init,
test
};

Your definition of a module is absolutely fine but it depends on how you plan on using it!
If you would like to use it as though it were published on the npm-registry then you need to use the process described here: Installing a local module using npm?
I know that this is an example but for other readers - you shouldn't use the name module as this is already in use by Node.
If you are simply using a modular approach to producing a larger app and you want to use the exports of your file, then you require the file by pointing to it. For example, if this file was called module.js and is in the same directory as the script which is requiring it then use:
var myModule = require('./module.js')(a, b);
If you have it in another directory then use the normal relative path navigation syntax like ../module.js if it is up one directory or ./lib/module.js if it is in a sub-directory called lib

Related

Passing a parameter to a called module

My app.js contains:
var m1 = require("./m1");
m1.f1(...);
My m1.js contains:
var m1 = module.exports = {};
m1.f1 = function(...) { };
I would like to pass somevariable when loading m1 from app.js:
var m1 = require("./m1")(somevariable);
How can I write m1.js so that the function definition of m1.f1 can access somevariable?
If you want to be able to do this:
var m1 = require("./m1")(somevariable); // it is equivalent to var m = require("./m1"); and then m(someVariable); so m (the exports of the module m1.js) should be a function
then module.exports in m1.js should be a function:
// m1.js:
module.exports = function(theVariable) {
// use variable then return the following object:
return {
f1: function() { /* ... */ }
};
}
So now you can use the module in app.js like this:
// app.js:
var m1 = require("./m1")(someVariable);
m1.f1(/* ... */);
module.exports is the value that will be returned by the call to require when loading the module.
// app.js
require("./m1")(somevar);
// m1.js
module.exports = function(param) {
return "something";
}
The answer above by Ibrahim makes sense if you want to call m1 as a function. What it seems to me, though, is that your use case would be better served by using a JS class.
That way, you can import 'm1' the regular way with require('m1') and then create an instance of M1 with new m1(<whatever you want to pass in>);
Now when you want to call M1, just use m1.f1()
To support classes, your M1 should look something like:
export default class m1 {
constructor(param1, param2) {
this.param1 = param1;
this.param2 = param2;
}
f1() {
do whatever with params here
}
}
The biggest benefit of this is readability. Now when someone (or you) looks at your code, they will see where this input is coming from. Otherwise, it can be hard to track down where the params are coming from. Especially as your code gets more complex.

extending a module when module is using "module.exports"

I've read a few pages on extending a module.They revolve around using a functional form of a module and I get how to do it (from https://toddmotto.com/mastering-the-module-pattern/)
var Module = (function () {
return {
publicMethod: function () {
// code
}
};
})();
but what I have is two modules like this
util.js
module.exports = {
thing1: function() {// do thing1 stuff }
}
extend.js a package I can't change (from npm)
module.exports = {
thing2: function() {// do thing2 one stuff}
}
now pretending I am going to use my util.js module
const _ = require('util.js);
let catin = _.thing1; // that's easy
let thehat = _.thing2;. // this was util.js extended.
I could in util.js just do this.
const ex = require('extend.js')
module.exports = {
thing1: function() {// do thing1 stuff }
thing2: ex.thing2
}
and that's ok since extend.js only has one function/method to extend, but I would like to extend this into my util library https://github.com/dodekeract/bitwise/blob/master/index.js but it has 22! items to extend.
There must be a better slicker way yes?
I'm open to refactoring my util.js file (but not hand coding each extension like I showed) so it extends automatically but obviously can't refactor that package I'm not maintaining, short of a fork...ugh. Also not interested in adding a sub deal like
ex: ex
_.ex.thing2
Ideas?
So given Molda's hint I'll share what I put together to make this question more useful for others. I put together a simple way of building a (utility) module from a folder of (utility) modules plus other one off packages (e.g. bitwise)
Make a utils.js module in say lib/ with this (you'll need require-all or some such package)
let utils = require('require-all')(__dirname + '/util');
let bw = require('bitwise');
let self = module.exports = (function(){
let util={};
for (var key in utils) {
util = utils.object.merge_keys(util,utils[key])
}
util = utils.object.merge_keys(util,bw)
return util;
}());
now make a subdirectory lib/util/ and fill it with your utility modules. Have one of those modules contain this key/function
merge_keys: function (obj1,obj2){
var obj3 = {};
for (var attrname in obj1) { obj3[attrname] = obj1[attrname]; }
for (var attrname in obj2) { obj3[attrname] = obj2[attrname]; }
return obj3;
}
and be sure that module name matches the key used in this line util = utils.object.merge_keys(util,utils[key]). In my case I have a module object.js in lib/util/ containing merge_keys
Then just require the utils.js module and all will be as one including access to the merge_keys function for other merging :-).
let _ = require('./lib/utils');
// see if it worked
console.log(_);
beware: there is no checking for duplicate key names between modules
notes:
let self= allows one to refer to any other key within the merged object itself like self.myfunctionkeyname( )

Using SinonJS stub (with rewire)

I have a function:
var publish = function(a, b, c) {
main = a + getWriterName(b,c);
}
and getWriterName is another function:
var getWriterName = function(b,c) {
return 'Hello World';
}
I want to test the "publish" function but I do not want to run the "getWriterName" function while I am testing "publish". I feel like I stub getWriterName function because I don't want to run it everytime I test "publish", but how do I do that? I did something like:
var sandbox = sinon.sandbox.create();
sandbox.stub(getWriterName).returns('done');
But this gives me an error of
TypeError: Attempted to wrap undefined property undefined as function
What is wrong with my stubbing if I am in the write path?
Edit:
I am using rewire so would like solutions using rewire
This is how Sinon can be used with Rewire to stub a function. Rewire in this case is particularly useful if the stubbed function is private.
it('getWriteName always returns "Hello World"', function() {
var stub = sandbox.stub();
stub.returns('Hello World');
var unset = log.__set__('getWriterName', stub);
// your test and expectations here
unset();
// it's always good to restore the previous state
});
This solved my problem:
If my functions are in a file called main.js then firstly I'd rewire the file as:
var main = rewire('main');
Then to stub any other function being called in one function, in my case, when I had to stub getWriterName I'd do:
main.__set__('getWriterName', function(b, c) {
return 'Something Else'
}
and Finally after finishing using it, do
main.restore();
From sinon docs: "The sinon.sandbox.create(config) method is mostly an integration feature, and as an end-user of Sinon.JS you will probably not need it."
Normally you create a sinon stub with the syntax:
sinon.stub(obj, 'property, function(){
//do something
}
Let's say that somewhere in your file you are exporting these two functions
//somefile.js
var publish = function(a, b, c) {
main = a + getWriterName(b,c);
}
var getWriterName = function(b,c) {
return 'Hello World';
}
exports.getWriterName = getWriterName;
exports.publish = publish;
Importing them in your tests:
var someFile = require('./somefile.js');
And trying to stub out the method you'd like to:
sinon.stub(someFile, 'getWriterName', function(b, c) {
return 'done'
});
You'll find that this too won't work. This is because sinon can't actually stub out a method that has been required unless it can access it as a property of the file you required. In order for this to work, you'd need to be doing this:
//somefile.js
var getWriterName = function(b,c) {
return 'Hello World';
}
exports.getWriterName = getWriterName;
var publish = function(a, b, c) {
main = a + exports.getWriterName(b,c);
}
exports.publish = publish;
Now the getWriterName is accessible for stubbing out once you import the file with the functions into your tests. You'd do it just like the above example:
sinon.stub(someFile, 'getWriterName', function(b, c) {
return 'done'
});
And can undo it with:
someFile.getWriterName.restore();

Declaring libraries as constants

In NodeJS world we require modules using require function:
var foo = require ("foo");
In JavaScript (also in NodeJS) we have const keyword that creates a constant:
const
Creates a constant that can be global or local to the function in which it is declared. Constants follow the same scope rules as variables.
Example:
$ node
> const a = 10
undefined
> a
10
> a = 7
7
> a
10
My question is: would it be good to require libraries as constans?
Example:
const foo = require ("foo")
, http = require ("http")
;
/* do something with foo and http */
Are there any bad/good effects using const instead of var when requiring libraries?
It turns out that it became a common practice to use const over var for dependencies. At least in the Node.js source code this is happening:
http.js
So, I guess it's a good practice. I started to use it as well in my modules.
NodeJS hasn't any optimisations for library that requires as const - require is a simple non native function, which nothing is known about the type of the variable to which is assigned. There is source code of require:
Module.prototype.require = function(path) {
assert(util.isString(path), 'path must be a string');
assert(path, 'missing path');
return Module._load(path, this);
};
Module._load = function(request, parent, isMain) {
if (parent) {
debug('Module._load REQUEST ' + (request) + ' parent: ' + parent.id);
}
var filename = Module._resolveFilename(request, parent);
var cachedModule = Module._cache[filename];
if (cachedModule) {
return cachedModule.exports;
}
if (NativeModule.exists(filename)) {
// REPL is a special case, because it needs the real require.
if (filename == 'repl') {
var replModule = new Module('repl');
replModule._compile(NativeModule.getSource('repl'), 'repl.js');
NativeModule._cache.repl = replModule;
return replModule.exports;
}
debug('load native module ' + request);
return NativeModule.require(filename);
}
var module = new Module(filename, parent);
if (isMain) {
process.mainModule = module;
module.id = '.';
}
Module._cache[filename] = module;
var hadException = true;
try {
module.load(filename);
hadException = false;
} finally {
if (hadException) {
delete Module._cache[filename];
}
}
return module.exports;
};
For more time library is an object (I think you don't have library like this module.exports = 10).
You can change all fields of object also if it is declared as const (If you want to get realy const object use Object.freeze(someObject)).
For conclusion: the effect is the same as for a common variable.
Link to V8 Variable Declaration Function used in NodeJS

Node.js double call to require()

//lib.js
var opt = 0
exports.set = function(arg) {
opt = arg
}
exports.prn = function() {
console.log(opt)
}
///prog.js
var lib = require('./lib')
var lib2 = require('./lib')
lib.set(222)
lib2.set(333)
lib.prn()
lib2.prn()
prog.js will output:
333
333
but I need it to output:
222
333
In ohter words, opt must be unique to variable lib and to variable lib2. How to achieve that?
That's because normally nodejs caches its modules which are got via require. You may use the following helper:
// RequireUncached.js
module.exports = function(module) {
delete require.cache[require.resolve(module)]
return require(module);
}
and the usage of the helper:
var requireUncached = require('RequireUncached.js');
requireUncached("./lib");
Have in mind that this approach is considered as bad practice and should not be used. I'll suggest to wrap your logic into a function, require the module and call the function. So, every time you get a new instance.
require will not load scripts multiple times, but always yield the same instance.
If you need different environments, make your module a constructor function that allows to be instantiated multiple times. Store opt on each object for that instead of in the (global) module scope.
// lib.js
module.exports = function constr() {
var opt = 0
this.set = function(arg) {
opt = arg
};
this.print = function() {
console.log(opt)
};
};
// prog.js
var lib = require('./lib'),
inst1 = new lib(),
inst2 = new lib();
/* or short:
var inst1 = new require('./lib')(),
inst2 = new require('./lib')(); */
inst1.set(222)
inst2.set(333)
inst1.print()
inst2.print()
The way the NodeJS module system works, the output is correct and your expectations contradict the design principle here.
Each module is loaded once and only once, and subsequent calls to require simply return the reference to the pre-existing module.
Maybe what you need to do is create a class you can create one or more instances of instead of using module-level globals.
Adding to Bergi's answer, You may also try it like
// prog.js
var lib = require('./lib')(),
lib2 = require('./lib')();
lib.set(222)
lib2.set(333)
lib.print()
lib2.print()
// lib.js
module.exports = function constr() {
var opt = 0
return { set : function(arg) {
opt = arg
},
print : function() {
console.log(opt)
}
}
};
Add this line as first line of your lib.js
delete require.cache[__filename]
now your module becomes in a separate namespace each time you require it.

Categories

Resources