Skip to content

Commit

Permalink
Make sure event punching happens after method normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
daffl committed Oct 25, 2015
1 parent 3931807 commit 7631197
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 62 deletions.
2 changes: 1 addition & 1 deletion lib/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module.exports = {
});

// If we ran setup already, set this service up explicitly
if (this._isSetup) {
if (this._isSetup && typeof protoService.setup === 'function') {
debug('Setting up service for `' + location + '`');
protoService.setup(this, location);
}
Expand Down
77 changes: 30 additions & 47 deletions lib/mixins/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,60 +11,43 @@ var eventMappings = {
patch: 'patched'
};

/**
* An event mixin that emits events after a service method calls its callback.
*
* @type {{setup: Function}}
*/
var EventMixin = {
setup: function () {
var emitter = this._rubberDuck = rubberduck.emitter(this);
var self = this;

self._serviceEvents = _.isArray(self.events) ? self.events.slice() : [];

// Pass the Rubberduck error event through
// TODO deal with error events properly
emitter.on('error', function (errors) {
self.emit('serviceError', errors[0]);
});

_.each(eventMappings, function (event, method) {
var alreadyEmits = self._serviceEvents.indexOf(event) !== -1;

if (typeof self[method] === 'function' && !alreadyEmits) {
// The Rubberduck event name (e.g. afterCreate, afterUpdate or afterDestroy)
var eventName = 'after' + method.charAt(0).toUpperCase() + method.substring(1);
self._serviceEvents.push(event);
// Punch the given method
emitter.punch(method, -1);
// Pass the event and error event through
emitter.on(eventName, function (results, args) {
if (!results[0]) { // callback without error
var hook = hookObject(method, 'after', args);
self.emit(event, results[1], hook);
} else {
self.emit('serviceError', results[0]);
}
});
}
});

return this._super ? this._super.apply(this, arguments) : this;
}
};

module.exports = function (service) {
var isEmitter = typeof service.on === 'function' &&
typeof service.emit === 'function';
var emitter = service._rubberDuck = rubberduck.emitter(service);

if (typeof service.mixin === 'function') {
if(!isEmitter) {
service.mixin(EventEmitter.prototype);
}

service.mixin(EventMixin);
}
};

module.exports.Mixin = EventMixin;
service._serviceEvents = _.isArray(service.events) ? service.events.slice() : [];

// Pass the Rubberduck error event through
// TODO deal with error events properly
emitter.on('error', function (errors) {
service.emit('serviceError', errors[0]);
});

_.each(eventMappings, function (event, method) {
var alreadyEmits = service._serviceEvents.indexOf(event) !== -1;

if (typeof service[method] === 'function' && !alreadyEmits) {
// The Rubberduck event name (e.g. afterCreate, afterUpdate or afterDestroy)
var eventName = 'after' + method.charAt(0).toUpperCase() + method.substring(1);
service._serviceEvents.push(event);
// Punch the given method
emitter.punch(method, -1);
// Pass the event and error event through
emitter.on(eventName, function (results, args) {
if (!results[0]) { // callback without error
var hook = hookObject(method, 'after', args);
service.emit(event, results[1], hook);
} else {
service.emit('serviceError', results[0]);
}
});
}
});
};
20 changes: 20 additions & 0 deletions test/application.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,4 +302,24 @@ describe('Feathers application', function () {
otherApp.mixins.push(function() {});
assert.equal(otherApp.mixins.length, 4);
});

it('Event punching happens after normalization (#150)', function (done) {
var todoService = {
create: function (data, params, callback) {
callback(null, data);
}
};

var app = feathers()
.configure(feathers.rest())
.use('/todo', todoService);

var server = app.listen(7001).on('listening', function () {
app.service('todo').create({
test: 'item'
});

server.close(done);
});
});
});
24 changes: 10 additions & 14 deletions test/mixins/event.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@ describe('Event mixin', function () {
}
});

mixinEvent(FixtureService);

var instance = create.call(FixtureService);
instance.setup();

mixinEvent(instance);

instance.on('serviceError', function (error) {
assert.ok(error instanceof Error);
Expand All @@ -79,10 +78,9 @@ describe('Event mixin', function () {
}
});

mixinEvent(FixtureService);

var instance = create.call(FixtureService);
instance.setup();

mixinEvent(instance);

instance.on('created', function (data, args) {
assert.equal(data.id, 10);
Expand Down Expand Up @@ -113,10 +111,9 @@ describe('Event mixin', function () {
}
});

mixinEvent(FixtureService);

var instance = create.call(FixtureService);
instance.setup();

mixinEvent(instance);

instance.on('updated', function (data, args) {
assert.equal(data.id, 12);
Expand Down Expand Up @@ -147,10 +144,9 @@ describe('Event mixin', function () {
}
});

mixinEvent(FixtureService);

var instance = create.call(FixtureService);
instance.setup();

mixinEvent(instance);

instance.on('removed', function (data, args) {
assert.equal(data.id, 27);
Expand Down Expand Up @@ -180,10 +176,10 @@ describe('Event mixin', function () {
});

FixtureService.mixin(EventEmitter.prototype);
mixinEvent(FixtureService);

var instance = create.call(FixtureService);
instance.setup();

mixinEvent(instance);

instance.on('created', function (data) {
assert.deepEqual(data, { custom: 'event' });
Expand Down

0 comments on commit 7631197

Please sign in to comment.