Skip to content

Commit

Permalink
Support functions as modules (#517)
Browse files Browse the repository at this point in the history
* Support functions as modules

* Update docs
  • Loading branch information
Marsup authored and arb committed Oct 13, 2016
1 parent b8f923e commit ae1778b
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 5 deletions.
4 changes: 3 additions & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ as general events are a process-wide facility and will result in duplicated log
- `[extensions]` - an array of [hapi event names](https://github.com/hapijs/hapi/blob/master/API.md#server-events) to listen for and report via the good reporting mechanism. Can not be any of ['log', 'request-error', 'ops', 'request', 'response', 'tail']. **Disclaimer** This option should be used with caution. This option will allow users to listen to internal events that are not meant for public consumption. The list of available events can change with any changes to the hapi event system. Also, *none* of the official hapijs reporters have been tested against these custom events. The schema for these events can not be guaranteed because they vary from version to version of hapi.
- `[reporters]` - Defaults to `{}`. `reporters` is a `key`, `value` pair where the `key` is a reporter name and the `value` is an array of mixed value types. Valid values for the array items are:
- streams specifications object with the following keys
- `module` - a string that will be used to import a module from node_modules or a local file. Should export a single constructor function that can be invoked with `new`.
- `module` - can be :
- a string that will be used to import a module from node_modules or a local file. Should export a single constructor function that can be invoked with `new`.
- a function that is the constructor of your stream. It's a safer alternative to the string version when you risk having module conflicts.
- `[name]` - if the imported module exports more than one constructor function, use `name` to specify which one to use.
- `[args]` - an array of arguments to pass to the constructor when this stream object is created via `new`.
- instantiated stream objects
Expand Down
8 changes: 5 additions & 3 deletions lib/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,16 +109,18 @@ class Monitor {
continue;
}

let Ctor = require(spec.module);
const isFn = typeof spec.module === 'function';
const moduleName = isFn ? spec.module.name || `The unnamed module at position ${i}` : spec.module;
let Ctor = isFn ? spec.module : require(spec.module);
Ctor = spec.name ? Ctor[spec.name] : Ctor;
Hoek.assert(typeof Ctor === 'function', `Error in ${reporterName}. ${spec.module} must be a constructor function.`);
Hoek.assert(typeof Ctor === 'function', `Error in ${reporterName}. ${moduleName} must be a constructor function.`);

const ctorArgs = spec.args ? spec.args.slice() : [];
ctorArgs.unshift(null);

Ctor = Ctor.bind.apply(Ctor, ctorArgs);
const stream = new Ctor();
Hoek.assert(typeof stream.pipe === 'function', `Error in ${reporterName}. ${spec.module} must create a stream that has a pipe function.`);
Hoek.assert(typeof stream.pipe === 'function', `Error in ${reporterName}. ${moduleName} must create a stream that has a pipe function.`);

streamObjs.push(stream);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ exports.monitor = Joi.object().keys({
}).unknown(),
Joi.string().valid('stdout', 'stderr'),
Joi.object().keys({
module: Joi.string().required(),
module: Joi.alternatives().try(Joi.string(), Joi.func()).required(),
name: Joi.string(),
args: Joi.array().default([])
})
Expand Down
14 changes: 14 additions & 0 deletions test/fixtures/unnamed-reporter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use strict';

const Stream = require('stream');

module.exports = class extends Stream.Transform {
constructor() {

super({ objectMode: true });
}
_transform(value, enc, callback) {

callback(null, JSON.stringify(value));
}
};
36 changes: 36 additions & 0 deletions test/monitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,42 @@ describe('Monitor', () => {
});
});

it('accepts a function as module', { plan: 2 }, (done) => {

const monitor = internals.monitorFactory(new Hapi.Server(), {
reporters: {
foo: [{
module: require('./fixtures/reporter')
}]
}
});

monitor.start((error) => {

expect(error).to.not.exist();
expect(monitor._reporters).to.have.length(1);
monitor.stop(done);
});
});

it('accepts an unnamed function as module', { plan: 2 }, (done) => {

const monitor = internals.monitorFactory(new Hapi.Server(), {
reporters: {
foo: [{
module: require('./fixtures/unnamed-reporter')
}]
}
});

monitor.start((error) => {

expect(error).to.not.exist();
expect(monitor._reporters).to.have.length(1);
monitor.stop(done);
});
});

it('attaches events for "ops", "tail", "log", and "request-error"', { plan: 5 }, (done) => {

const monitor = internals.monitorFactory(new Hapi.Server(), {
Expand Down

0 comments on commit ae1778b

Please sign in to comment.