I am seeing difficulty to find a good tutorial about writing plugins for nodejs app(not for nodejs itself!).
What I want to do is, for some nodejs app, I want to extend its functionalities with few js files I wrote.
For example, I am using karma runner to run JS unit tests, but the existing reporters don't meet our logging requirement very well. So I wrote my own reporter and put that in a separate js file, e.g. myreporter.js. To use it now, I have to add the myreporter.js into the folder of karma code and add some line like this into reporter.js of karma:
exports.myreporter = require('./reporters/myreporter');
That works nicely on my machine, however, it could be an issue for the CI server. I don't want to include all karma code in our own project. I want to install the karma from the public repo on the server and only include myreporter.js in our project, so that we don't have to install the modified karma for every build. And I only want to install the myreporter.js as a plugin for karma for the builds.
I am not sure whether that is clear enough. So what I need is to write a plugin for karma, or for any existing nodejs app. I should still be able to use the app in the same way as before, while I could use the new functionalities brought by the plugin.
I have see this page about peerdependency. Does that mean if I add peerdependency or karma into the package.json file for myreporter.js, once I installed the myreporter package and run karma, karma will pick up the new reporter?
Thanks for any help regarding this long question.
Updates:
Tried peerdependency, it seems karma 0.8.6 doesn't pick my plugin up. Looks like starts from 0.9 karma is using di, I guess that is when it starts to support plugins. However, 0.9.3 is still not a stable version.
Found the answer by myself. There is PROBABLY no way to write a plugin for a general nodejs app if the app itself doesn't explicitly support plugins.
However, it is extremely easy to change an app to support plugins. The only thing to do is using the powerful "require" to obtain the plugin module with its name. For example, in Karma 0.9.4 (latest version by now), it has plugin.js which loads all plugin modules:
...
var requirePlugin = function(name) {
log.debug('Loading plugin %s.', name);
try {
modules.push(require(name)); // Call require here!
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND' && e.message.indexOf(name) !== -1) {
log.warn('Cannot find plugin "%s".\n Did you forget to install it ?\n' +
' npm install %s --save-dev', name, name);
} else {
log.warn('Error during loading "%s" plugin:\n %s', name, e.message);
}
}
};
And all the custom plugins could be set in the conf.js file like this:
...
plugins: ['you-own-plugin'],
...
To write your own plugins, have a look at the Karma github, there are lots of examples of plugins for Karma.
Unfortunately, the latest stable version of Karma (0.8.6) doesn't support external plugins. I had to modify the preprocessor.js and reporter.js myself to support custom preprocessors and reporters. I provide the change below, it is simple change but not really recommended.
//preprocessor.js line 26
processor = exports[processorName] || require(processorName.toLowerCase())
//reporter.js line 48
var Reporter = exports[helper.ucFirst(name) + (config.colors ? 'Color' : '')] || require(name.toLowerCase());