8000 Event filtering and params extension for Primus by daffl · Pull Request #51 · feathersjs/feathers · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/providers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module.exports = {
rest: require('./rest'),
socketio: require('./socketio'),
primus: require('./primus')
socketio: require('./socket/socketio'),
primus: require('./socket/primus')
};
50 changes: 50 additions & 0 deletions lib/providers/socket/commons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
var _ = require('lodash');

// The position of the params parameters for a service method so that we can extend them
// default is 1
var paramsPositions = {
find: 0,
update: 2,
patch: 2
};

// Set up the service method handlers for a service and socket.
exports.setupMethodHandler = function setupMethodHandler (emitter, params, service, path, method) {
var name = path + '::' + method;
var position = typeof paramsPositions[method] !== 'undefined' ? paramsPositions[method] : 1;

if (typeof service[method] === 'function') {
emitter.on(name, function () {
var args = _.toArray(arguments);
args[position] = _.extend({}, args[position], params);
service[method].apply(service, args);
}); 10000
}
};

// Set up event handlers for a given service and connected sockets.
// Send it through the service dispatching mechanism (`removed(data, params, callback)`,
// `updated(data, params, callback)` and `created(data, params, callback)`) if it
// exists.
exports.setupEventHandler = function setupEventHandler (info, service, path, ev) {
var defaultDispatcher = function (data, params, callback) {
callback(null, data);
};

service.on(ev, function (data) {
// Check if there is a method on the service with the same name as the event
var dispatcher = typeof service[ev] === 'function' ? service[ev] : defaultDispatcher;
var eventName = path + ' ' + ev;

info.emitters().forEach(function (emitter) {
dispatcher(data, info.params(emitter), function (error, dispatchData) {
if (error) {
emitter[info.method]('error', error);
} else if (dispatchData) {
emitter[info.method](eventName, dispatchData);
}
});
});
});
};

47 changes: 24 additions & 23 deletions lib/providers/primus.js → lib/providers/socket/primus.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ var _ = require('lodash');
var Proto = require('uberproto');
var Primus = require('primus');
var Emitter = require('primus-emitter');
var commons = require('./commons');

module.exports = function(config, configurer) {
return function() {
var app = this;
var services = {};

app.enable('feathers primus');

Expand All @@ -23,30 +23,35 @@ module.exports = function(config, configurer) {
}

var primus = this.primus = new Primus(server, config);
var info = {
emitters: function() {
return primus;
},
params: function(spark) {
return spark.request.feathers;
},
method: 'send'
};

primus.use('emitter', Emitter);

_.each(services, function(service, path) {
// If the service emits events that we want to listen to (Event mixin)
if (typeof service.on === 'function' && service._serviceEvents) {
_.each(service._serviceEvents, function(ev) {
service.on(ev, function(data) {
primus.forEach(function (spark) {
spark.send(path + ' ' + ev, data);
});
});
// For a new connection, set up the service method handlers
primus.on('connection', function (spark) {
_.each(self.services, function (service, path) {
_.each(self.methods, function (method) {
commons.setupMethodHandler(spark, spark.request.feathers, service, path, method);
});
}
});
});

primus.on('connection', function(spark) {
_.each(services, function(service, path) {
_.each(self.methods, function(method) {
var name = path + '::' + method;
if (service[method]) {
spark.on(name, service[method].bind(service));
}
// Set up events and event dispatching
_.each(self.services, function (service, path) {
// If the service emits events that we want to listen to (Event mixin)
if (typeof service.on === 'function' && service._serviceEvents) {
_.each(service._serviceEvents, function (ev) {
commons.setupEventHandler(info, service, path, ev);
});
});
}
});

if (typeof configurer === 'function') {
Expand All @@ -56,9 +61,5 @@ module.exports = function(config, configurer) {
return result;
}
}, app);

app.providers.push(function(path, service) {
services[path] = service;
});
};
};
63 changes: 63 additions & 0 deletions lib/providers/socket/socketio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'use strict';

var _ = require('lodash');
var socketio = require('socket.io');
var Proto = require('uberproto');
var commons = require('./commons');

module.exports = function (config) {
return function () {
var app = this;

app.enable('feathers socketio');

// Monkey patch app.setup(server)
Proto.mixin({
setup: function (server) {
var self = this;
var result = this._super.apply(this, arguments);

if (this.disabled('feathers socketio')) {
return result;
}

var io = this.io = socketio.listen(server);
// The info object we can pass to commons.setupEventHandler
var info = {
emitters: function() {
return io.sockets.clients();
},
params: function(socket) {
return socket.handshake.feathers;
},
method: 'emit'
};

// For a new connection, set up the service method handlers
io.sockets.on('connection', function (socket) {
_.each(self.services, function (service, path) {
_.each(self.methods, function (method) {
commons.setupMethodHandler(socket, socket.handshake.feathers, service, path, method);
});
});
});

// Set up events and event dispatching
_.each(self.services, function (service, path) {
// If the service emits events that we want to listen to (Event mixin)
if (typeof service.on === 'function' && service._serviceEvents) {
_.each(service._serviceEvents, function (ev) {
commons.setupEventHandler(info, service, path, ev);
});
}
});

if (typeof config === 'function') {
config.call(this, io);
}

return result;
}
}, app);
};
};
100 changes: 0 additions & 100 deletions lib/providers/socketio.js

This file was deleted.

17 changes: 17 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,23 @@ In the Browser you can connect like this:
</script>
```

Just like REST and SocketIO, the Primus request object can be extended with a `feathers` parameter during authorization which will extend the `params` for any service request:

```js
app.configure(feathers.primus({
transformer: 'sockjs'
}, function(primus) {
// Set up Primus authorization here
primus.authorize(function (req, done) {
req.feathers = {
user: { name: 'David' }
}

done();
});
}));
```

## API

### listen
Expand Down
Loading
0