How to override/re-declare function declared in NPM package?

How to override/re-declare function declared in NPM package?
0

#1

I’m working with an NPM package that provides a wrapper to an API. The API requires a fresh key/token be used after the previous session has been closed. The original author of the NPM package persists this data by writing a file with the newly issued/refresded value to disk, like this:

Questrade.prototype._saveKey = function (cb) {
  cb = cb || function(){};
  var self = this;
  fs.writeFile(self._getKeyFile(), self.refreshToken, 'utf8', function (err) {
    if (err) return cb({ message: 'failed_to_write', details: err });
    cb(null, self.refreshToken);
  });
}

I would like to modifiy _saveKey() so that it writes the value to my database instead of to a file. I would also like to “overwrite” _loadKey() so that when it is called, it gets the key value from the database.

I’ve never before “overrided” a function like this in Node that has been set in an NPM package. How should I do this? Do I just redefine Questrade.prototype._saveKey() somewhere in my code after I have required the package? (Questrade.prototype._saveKey = function() {};)

Thanks in advance for your help and time.


#2

This is called monkey patching (sometimes duck punching) and it’s generally a very bad idea, especially with functions that start with an underscore. There’s a very good chance that you could break something, either now or in a future update. The absolute best thing to do is download the source code, make the modifications you want, submit a pull request, and then bask in the glory of being an open source contributor. You’ve got a good idea, and I don’t think it would take much modification to integrate it into the module. Since you want to write the functionality anyways, I’d strongly suggest going this route.

But, if you need to punch the duck, then you just have to overwrite both of the functions on the prototype, just as you guessed. I would write this in a function that returns the modified questrade object. This makes it clear to anyone reading your code that this object has been modified and they know exactly where to look for details.

const qt_patched = patchDB(require('questrade'));

#3

@PortableStick

Apologies for not responding sooner - life gets way too hectic sometimes!

Thanks very much for your detailed reply! This makes a lot of sense and I like the idea of returning the modified/“patched” object vs the original.

I’m a little scared to submit a real life pull request but, hey, maybe I will(??).

Thank you very much for your answer - it’s really appreciated and helps me a lot!