diff --git a/README.md b/README.md index 901cf56..34e9ab2 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,16 @@ const eventsWithoutCtx = EventEmitter.of(); } ``` +### * event type + +`*` is a special event type which denotes all events. This allows you to add a mapper or handler to all events. For example: + +```js +events.map('*', payload => { + // +}); +``` + --- ### API diff --git a/docs/migrations/00009.md b/docs/migrations/00009.md new file mode 100644 index 0000000..dd2ee17 --- /dev/null +++ b/docs/migrations/00009.md @@ -0,0 +1,9 @@ +#### Changes made to event mappers/handlers on '*' event type + +The following examples will run on every event type, where previously they +only ran on events with an explicit type '*'. + +```js +events.on('*', (payload) => {}); +events.map('*', (payload) => {}); +``` diff --git a/src/__tests__/index.js b/src/__tests__/index.js index ff28133..16958c0 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -54,10 +54,92 @@ test('Base EventEmitter mappers', t => { mapCount++; return Object.assign(event, {a: true}); }); - events.emit('test', { - b: true, - }); + events.emit('test', {b: true}); t.equal(eventHandlerCount, 1, 'calls handler one time'); t.equal(mapCount, 1, 'calls mapper one time'); t.end(); }); + +test('Base EventEmitter * mappers', t => { + const events = new EventEmitter(); + events.map('*', payload => { + return {...payload, a: true}; + }); + events.map('test', payload => { + return {...payload, b: true}; + }); + events.on('test', payload => { + t.deepLooseEqual(payload, { + a: true, + b: true, + c: true, + }); + t.end(); + }); + events.emit('test', {c: true}); +}); + +test('Base EventEmitter implicit * mappers', t => { + const events = new EventEmitter(); + events.map(payload => { + return {...payload, a: true}; + }); + events.map('test', payload => { + return {...payload, b: true}; + }); + events.on('test', payload => { + t.deepLooseEqual(payload, { + a: true, + b: true, + c: true, + }); + t.end(); + }); + events.emit('test', {c: true}); +}); + +test('Base EventEmitter * handlers', t => { + const events = new EventEmitter(); + let calledGlobal = false; + let calledNormal = false; + events.on(payload => { + t.deepLooseEqual(payload, { + c: true, + }); + calledGlobal = true; + }); + + events.on('test', payload => { + t.deepLooseEqual(payload, { + c: true, + }); + calledNormal = true; + }); + events.emit('test', {c: true}); + t.ok(calledGlobal); + t.ok(calledNormal); + t.end(); +}); + +test('Base EventEmitter implicit * handlers', t => { + const events = new EventEmitter(); + let calledGlobal = false; + let calledNormal = false; + events.on('*', payload => { + t.deepLooseEqual(payload, { + c: true, + }); + calledGlobal = true; + }); + + events.on('test', payload => { + t.deepLooseEqual(payload, { + c: true, + }); + calledNormal = true; + }); + events.emit('test', {c: true}); + t.ok(calledGlobal); + t.ok(calledNormal); + t.end(); +}); diff --git a/src/emitter.js b/src/emitter.js index f48274c..d792336 100644 --- a/src/emitter.js +++ b/src/emitter.js @@ -20,15 +20,16 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +const globalEventType = '*'; export default class UniversalEmitter { constructor() { this.handlers = {}; this.mappers = {}; } - map(type, mapper) { - validateHandler(mapper); + map(...args) { + const {type, callback} = getArgs(args); if (!this.mappers[type]) this.mappers[type] = []; - this.mappers[type].push(mapper); + this.mappers[type].push(callback); } on(...args) { const {type, callback} = getArgs(args); @@ -41,8 +42,10 @@ export default class UniversalEmitter { if (index > -1) this.handlers[type].splice(index, 1); } emit(type, payload, ctx) { - const mappers = this.mappers[type] || []; - const handlers = this.handlers[type] || []; + const globalMappers = this.mappers[globalEventType] || []; + const globalHandlers = this.handlers[globalEventType] || []; + const mappers = (this.mappers[type] || []).concat(globalMappers); + const handlers = (this.handlers[type] || []).concat(globalHandlers); const event = { type, payload: mappers.reduce((payload, mapper) => {