From 44da7721f90a79c9cc5a1b6bd7c9269f7f23a880 Mon Sep 17 00:00:00 2001 From: David Luecke Date: Sun, 5 Jan 2014 10:13:51 -0700 Subject: [PATCH 1/5] Primus provider (#28). --- lib/providers/index.js | 3 +- lib/providers/primus.js | 64 +++++++++++++++++++ package.json | 4 +- test/providers/primus.test.js | 113 ++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 lib/providers/primus.js create mode 100644 test/providers/primus.test.js diff --git a/lib/providers/index.js b/lib/providers/index.js index 278897d473..8b8e267ac7 100644 --- a/lib/providers/index.js +++ b/lib/providers/index.js @@ -2,5 +2,6 @@ module.exports = { rest: require('./rest'), - socketio: require('./socketio') + socketio: require('./socketio'), + primus: require('./primus') }; diff --git a/lib/providers/primus.js b/lib/providers/primus.js new file mode 100644 index 0000000000..1db4ade9e6 --- /dev/null +++ b/lib/providers/primus.js @@ -0,0 +1,64 @@ +'use strict'; + +var _ = require('underscore'); +var Proto = require('uberproto'); +var Primus = require('primus'); +var Emitter = require('primus-emitter'); + +module.exports = function(config, configurer) { + return function() { + var app = this; + var services = {}; + + app.enable('feathers primus'); + + // Monkey patch app.setup(server) + Proto.mixin({ + setup: function(server) { + var self = this; + var result = this._super.apply(this, arguments); + + if (this.disabled('feathers primus')) { + return result; + } + + var primus = this.primus = new Primus(server, config); + 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); + }); + }); + }); + } + }); + + 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)); + } + }); + }); + }); + + if (typeof configurer === 'function') { + configurer.call(this, primus); + } + + return result; + } + }, app); + + app.providers.push(function(path, service) { + services[path] = service; + }); + }; +}; diff --git a/package.json b/package.json index 899c4618b9..afab6a3629 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,9 @@ "express": "~ 3.4.0", "rubberduck": "~1.x", "underscore": "~1.5.0", - "socket.io": "~0.9.0" + "socket.io": "~0.9.0", + "primus-emitter": "~2.0.5", + "primus": "~1.5.1" }, "devDependencies": { "request": "~2.21.0", diff --git a/test/providers/primus.test.js b/test/providers/primus.test.js new file mode 100644 index 0000000000..457656e979 --- /dev/null +++ b/test/providers/primus.test.js @@ -0,0 +1,113 @@ +'use strict'; + +var feathers = require('../../lib/feathers'); +var fixture = require('./service-fixture'); +var todoService = fixture.Service; +var verify = fixture.verify; + +describe('Primus provider', function () { + var server, socket; + + before(function () { + server = feathers() + .configure(feathers.primus({ + transformer: 'socket.io' + }, function(primus) { + socket = new primus.Socket('http://localhost:7888'); + })) + .use('todo', todoService) + .listen(7888); + }); + + after(function (done) { + socket.socket.disconnect(); + server.close(done); + }); + + describe('CRUD', function () { + it('::find', function (done) { + socket.send('todo::find', {}, function (error, data) { + verify.find(data); + + done(error); + }); + }); + + it('::get', function (done) { + socket.send('todo::get', 'laundry', {}, function (error, data) { + verify.get('laundry', data); + + done(error); + }); + }); + + it('::create', function (done) { + var original = { + name: 'creating' + }; + + socket.send('todo::create', original, {}, function (error, data) { + verify.create(original, data); + + done(error); + }); + }); + + it('::update', function (done) { + var original = { + name: 'updating' + }; + + socket.send('todo::update', 23, original, {}, function (error, data) { + verify.update(23, original, data); + + done(error); + }); + }); + + it('::remove', function (done) { + socket.send('todo::remove', 11, {}, function (error, data) { + verify.remove(11, data); + + done(error); + }); + }); + }); + + describe('Events', function () { + it('created', function (done) { + var original = { + name: 'created event' + }; + + socket.on('todo created', function (data) { + verify.create(original, data); + done(); + }); + + socket.send('todo::create', original, {}, function () {}); + }); + + it('updated', function (done) { + var original = { + name: 'updated event' + }; + + socket.on('todo updated', function (data) { + verify.update(10, original, data); + done(); + }); + + socket.send('todo::update', 10, original, {}, function () {}); + }); + + it('removed', function (done) { + socket.on('todo removed', function (data) { + verify.remove(333, data); + done(); + }); + + socket.send('todo::remove', 333, {}, function () {}); + }); + }); +}); From ac8f7084272d7bc03e61745281cf66b6b0fb54fb Mon Sep 17 00:00:00 2001 From: David Luecke Date: Sun, 5 Jan 2014 11:21:05 -0700 Subject: [PATCH 2/5] Adding documentation to use Primus. --- documentation.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/documentation.md b/documentation.md index e628b3d757..9a98698cc9 100644 --- a/documentation.md +++ b/documentation.md @@ -74,6 +74,47 @@ app.configure(feathers.socketio(function(io) { Once the server has been started with `app.listen()` the SocketIO object is available as `app.io`. +### Primus + +[Primus](https://github.com/primus/primus) is a universal wrapper for real-time frameworks and allows you to transparently use Engine.IO, WebSockets, BrowserChannel, SockJS and Socket.IO. Set it up with `feathers.primus(configuration [, fn])` where `configuration` is the [Primus server configuration](https://github.com/primus/primus#getting-started) and `fn` an optional callback with the Primus server instance that can e.g. be used for setting up [authorization](https://github.com/primus/primus#authorization): + +```js +// Set up Primus with SockJS +app.configure(feathers.primus({ + transformer: 'sockjs' +}, function(primus) { + // Set up Primus authorization here + primus.authorize(function (req, done) { + var auth; + + try { auth = authParser(req.headers['authorization']) } + catch (ex) { return done(ex) } + + // Do some async auth check + authCheck(auth, done); + }); +})); +``` + +In the Browser you can connect like this: + +```html + + +``` + ## API ### listen From 7902526209957c8903fe4eef9b4cb169b0c17f4c Mon Sep 17 00:00:00 2001 From: David Luecke Date: Sun, 5 Jan 2014 11:53:34 -0700 Subject: [PATCH 3/5] Adding Node 0.11 to Travis. --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2ca91f2895..83124bc848 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: node_js node_js: - "0.10" - - "0.8" \ No newline at end of file + - "0.8" + - "0.11" \ No newline at end of file From 44b633ffec36b8a9297d7c784f30bcef47696a23 Mon Sep 17 00:00:00 2001 From: David Luecke Date: Sun, 5 Jan 2014 11:55:45 -0700 Subject: [PATCH 4/5] Updating documentation for version 0.3.0 --- documentation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation.md b/documentation.md index 9a98698cc9..c3b728ca43 100644 --- a/documentation.md +++ b/documentation.md @@ -494,6 +494,8 @@ With that being said there are some amazing frameworks already out there and we __0.3.0__ +- Added [Primus](https://github.com/primus/primus) provider ([#34](https://github.com/feathersjs/feathers/pull/34)) +- `app.setup(server)` to support HTTPS (and other functionality that requires a custom server) ([#33](https://github.com/feathersjs/feathers/pull/33)) - Removed bad SocketIO configuration ([#19](https://github.com/feathersjs/feathers/issues/19)) - Add .npmignore to not publish .idea folder ([#30](https://github.com/feathersjs/feathers/issues/30)) - Remove middleware: connect.bodyParser() ([#27](https://github.com/feathersjs/feathers/pull/27)) From 28d32c338ad085766a0f1366fd3fe2c8ec5576bf Mon Sep 17 00:00:00 2001 From: David Luecke Date: Sun, 5 Jan 2014 11:59:45 -0700 Subject: [PATCH 5/5] Removing 0.11. Primus throws an error. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 83124bc848..43be7c3197 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,4 +2,4 @@ language: node_js node_js: - "0.10" - "0.8" - - "0.11" \ No newline at end of file + # - "0.11" \ No newline at end of file