index.js
/*!
* compose-emitter <https://github.com/tunnckoCore/compose-emitter>
*
* Copyright (c) 2016 Charlike Mike Reagent <@tunnckoCore> (http://www.tunnckocore.tk)
* Released under the MIT license.
*/
'use strict'
var extend = require('extend-shallow')
var AppBase = require('app-base').AppBase
var isObject = require('is-extendable')
/**
* > Initialize ComposeEmitter with `options`. Pass your EventEmitter
* instance and optionally pass `options.context` to bind to listeners.
*
* **Example**
*
* ```js
* var ComposeEmitter = require('compose-emitter').ComposeEmitter
* var Emitter = require('component-emitter')
*
* var ee = new ComposeEmitter({
* emitter: new Emitter()
* })
*
* ee
* .compose('on')('foo', console.log) // => 1, 2, 3
* .compose('emit')('foo', 1, 2, 3)
* ```
*
* @param {Object} `options` Pass event emitter instance to `options.emitter`.
* @api public
*/
function ComposeEmitter (options) {
if (!(this instanceof ComposeEmitter)) {
return new ComposeEmitter(options)
}
AppBase.call(this)
this.options = isObject(options)
? options
: isObject(this.options) ? this.options : {}
}
/**
* > Extend your application with ComposeEmitter static and prototype methods.
* See [static-extend][] or [tunnckoCore/app-base](https://github.com/tunnckoCore/app-base)
* for more info and what's static and prototype methods are added.
*
* **Example**
*
* ```js
* var ComposeEmitter = require('compose-emitter').ComposeEmitter
* var Emitter = require('eventemitter3')
*
* function App (options) {
* if (!(this instanceof App)) {
* return new App(options)
* }
* ComposeEmitter.call(this, options)
* }
*
* ComposeEmitter.extend(App)
*
* App.prototype.on = function on (name, fn, context) {
* return this.compose('on')(name, fn, context)
* }
*
* App.prototype.once = function once (name, fn, context) {
* return this.compose('once')(name, fn, context)
* }
*
* App.prototype.off = function off (name, fn, context) {
* return this.compose('off')(name, fn, context)
* }
*
* App.prototype.emit = function emit () {
* return this.compose('emit').apply(null, arguments)
* }
*
* var app = new App({
* context: {foo: 'bar'},
* emitter: new Emitter()
* })
*
* app
* .on('foo', function (a) {
* console.log('foo:', a, this) // => 123, {foo: 'bar'}
* })
* .once('bar', function (b) {
* console.log('bar:', b) // => 456
* })
* .emit('foo', 123)
* .emit('bar', 456)
* .emit('bar', 789)
* ```
*
* @name ComposeEmitter.extend
* @param {Function} `Parent` The constructor to extend, using [static-extend][].
* @api public
*/
AppBase.extend(ComposeEmitter)
/**
* > Compose different `type` of emitter methods. You can use this to create
* the usual `.on`, `.emit` and other methods. Pass as `type` name of the method
* that your emitter have and optional `options` to pass context for the listeners.
*
* **Example**
*
* ```js
* var emitter = require('compose-emitter')
* var Emitter = require('eventemitter3')
*
* var on = emitter.compose('on', {
* context: {a: 'b'},
* emitter: new Emitter()
* })
* var emit = emitter.compose('emit')
*
* on('foo', function (a, b) {
* console.log('foo:', a, b, this) // => 1, 2, {a: 'b', c: 'd'}
* }, {c: 'd'})
*
* emit('foo', 1, 2)
* ```
*
* @name .compose
* @param {String} `type` Name of the emitter method that you want to mirror.
* @param {Object} `options` Optionally pass `context` that will be bind to listeners.
* @return {Function} Method that accept as many arguments as you want or emitter method need.
* @api public
*/
AppBase.define(ComposeEmitter.prototype, 'compose', function compose (type, options) {
if (typeof type !== 'string') {
throw new TypeError('.compose: expect `type` be string')
}
// @todo
var opts = this.options
var ctx = options ? extend({}, opts.context, options.context) : opts.context
this.options = options ? extend({}, opts, options) : opts
this.options.context = ctx
if (!isObject(this.options.emitter)) {
throw new TypeError('.compose: expect `options.emitter` be extendable object')
}
this.define('emitter', this.options.emitter)
var self = this
return function onOffEmitOnce (name, fn, context) {
if (type !== 'on' && type !== 'once' && type !== 'off') {
self.emitter[type].apply(self.emitter, arguments)
return self
}
self.options.context = context ? extend({}, self.options.context, context) : self.options.context
self.options.context = isObject(self.options.context) ? self.options.context : self
self.emitter[type](name, fn, self.options.context)
return self
}
})
/**
* Expose `ComposeEmitter` instance
* @type {ComposeEmitter}
* @private
*/
module.exports = new ComposeEmitter()
/**
* Expose `ComposeEmitter` constructor
* @type {ComposeEmitter}
* @private
*/
module.exports.ComposeEmitter = ComposeEmitter