Skip to content

Commit

Permalink
significant update to how sockets are created and joined, addition of…
Browse files Browse the repository at this point in the history
… init to options
  • Loading branch information
mgamini committed Nov 20, 2014
1 parent a65ca0b commit 2c9b4b8
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 76 deletions.
55 changes: 35 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,55 +9,70 @@ $ bower install --save ember-phoenix-socket
Initialize the socket adapter:
```javascript
window.App = Ember.Application.create();
PhoenixSocket({
// Options go here
});

var options: {
endpoint: "wss://Whateverhost.com/ws",
appName: 'App',
storeName: 'DS',
init: {doInit: true, channel: 'data', topic: 'data', params: null}
}

PhoenixSocket(options);
```

By default, Ember-phoenix-socket is configured to join a channel of 'session' and a topic of 'data', which it attaches to your Ember data store.

## Options
PhoenixSocket takes three options:
```javascript
{
endpoint: "wss://Whateverhost.com/ws",
appName: 'App',
storeName: 'DS'
}
```
Defaults are set to:

PhoenixSocket takes four options (shown with their defaults):
```javascript
{
endpoint: location.protocol.match(/^https/) ? "wss://" + location.host + "/ws" : "ws://" + location.host + "/ws",
appName: 'App',
storeName: 'DS'
init: {doInit: true, channel: 'data', topic: 'data', params: null}
}
```

If `init.doInit` is set to `true`, PhoenixSocket will immediately attempt to connect to the socket with the given params. If you don't want any channels immediately, set `init: false`. If you want a default channel but don't want it to be joined immediately, set `{doInit: false}` with the rest of your params in the object.

## Custom Channels
Adding custom channels is pretty easy. Here's an example of a custom channel being initialized:
Adding custom channels is pretty easy. Here's an example of a custom channel being initialized, and extended with a login method:
```javascript
// adding an "events" channel
// adding a "session" channel

App.Phoenix.Session = App.Phoenix.Channel.extend({
isAuthenticated: false,
login: function(params) {
this.get('join')(params)
.then(function(success) {
this.set('isAuthenticated', true)
console.log(success)
}.bind(this), function(failure) {
console.log(failure)
}.bind(this))
}
})


Ember.onLoad('Ember.Application', function(Application) {
Application.initializer({
name: 'events',
name: 'session',
initialize: function(container, application) {

application.register('service:events', App.Phoenix.Channel, {singleton: true})
application.inject('controller', 'service:events', 'service:events');
application.register('service:session', App.Phoenix.Session, {singleton: true})
application.inject('controller', 'service:session', 'service:session');

container.lookup('service:events').setSocket('session','events');
container.lookup('service:session').setSocket('session','session');
}
})
})

```

Custom channels will adhere to the same API that Ember uses when it queries the store, namely requests being made up of `url, type, params`, and returning a promise. Quick example:
```javascript
container.lookup('service:events').ajax('/events', 'GET', {eventName: "stuff"}).then(function(result) { console.log(result) }))
```

## Connecting to Phoenix
For an example of a Phoenix app configured to work with this, check out [Phember](https://github.com/mgamini/phember).
For an example of a Phoenix app configured to work with this, check out [Phember](https://github.com/mgamini/phember) (currently broken)
104 changes: 49 additions & 55 deletions phoenix-socket.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
var PhoenixSocket = function(ENV) {
ENV = ENV || {
endpoint: location.protocol.match(/^https/) ? "wss://" + location.host + "/ws" : "ws://" + location.host + "/ws",
appName: 'App',
storeName: 'DS'
}
var PhoenixSocket = function(params) {
window.ENV = window.ENV || {};
params = params || {};
ENV.Phoenix = {};

ENV.Phoenix.endpoint = params.endpoint || location.protocol.match(/^https/) ? "wss://" + location.host + "/ws" : "ws://" + location.host + "/ws";
ENV.Phoenix.appName = params.appName || 'App';
ENV.Phoenix.storeName = params.storeName || 'DS';
ENV.Phoenix.init = params.init || {doInit: true, channel: 'data', topic: 'data', params: null};


var DS = window[ENV.storeName],
App = window[ENV.appName];
var DS = window[ENV.Phoenix.storeName],
App = window[ENV.Phoenix.appName];

App.Phoenix = {};

Expand All @@ -16,7 +20,7 @@ App.Phoenix.Socket = Ember.Controller.extend({
init: function() {
this.set('topics', Ember.Map.create())

var sock = new Phoenix.Socket(ENV.endpoint);
var sock = new Phoenix.Socket(ENV.Phoenix.endpoint);
sock.onClose = this.get('handleClose').bind(this);
this.set('socket', sock);
},
Expand All @@ -43,43 +47,41 @@ App.Phoenix.Socket = Ember.Controller.extend({
}
})

App.Phoenix.Session = Ember.Controller.extend({
needs: ['phoenix'],
channel: null,
isAuthenticated: false,
init: function() {},
actions: {
join: function(params, success, fail) {
this.get('service:phoenix').addTopic('session', 'user', params, function(chan, res) {
if (chan == "error") {
fail(res)
} else {
this.set('isAuthenticated', true);
this.set('channel', chan);
success(res);
}
}.bind(this))
}
}
})

App.Phoenix.Channel = DS.PhoenixSocketAdapter = DS.RESTAdapter.extend({
needs: ['phoenix', 'session'],
topic: null,
_channel: null,
_topic: null,
_initialized: false,
_transactions: {},
_channel: null,
_socket: null,
setSocket: function(channel, topic) {
this.set('topic', topic);
this.container.lookup('service:phoenix').addTopic(channel, topic, {}, this.get('setSocketResponse').bind(this))
this.set('_channel', channel);
this.set('_topic', topic);
},
setSocketResponse: function(chan, res) {
chan.on(this.get('topic'), this.get('onData').bind(this));
join: function(params) {
var txn = App.Phoenix.Transaction.create({params: params})
this.container.lookup('service:phoenix').addTopic(
this.get('_channel'),
this.get('_topic'),
params,
this.get('onJoin').bind(this, txn)
)
return txn.promise;
},
onJoin: function(promise, chan, res) {
if (res.success) {
chan.on(this.get('_topic'), this.get('onData').bind(this));

this.set('_socket', chan);
this.set('_initialized', true);

this.set('_channel', chan);
this.set('_initialized', true);
this.get('unloadQueue').call(this);

this.get('unloadQueue').call(this);
promise.success(res);
} else {
promise.error(res);
}
promise.destroy();
},
onData: function(data) {
var caller = this.get('_transactions')[data.uuid];
Expand All @@ -97,16 +99,17 @@ App.Phoenix.Channel = DS.PhoenixSocketAdapter = DS.RESTAdapter.extend({
var txns = this.get('_transactions');

for (var uuid in txns) {
this.get('_channel').send(this.get('topic'), txns[uuid].payload());
this.get('_socket').send(this.get('_topic'), txns[uuid].payload());
}
},
ajax: function(url, type, params) {
var uuid = App.Phoenix.Utils.generateUuid();
var txn = this.get('_transactions')[uuid] = App.Phoenix.Transaction.create({uuid: uuid, url: url, type: type, params: params})

if (this.get('_initialized')) {
this.get('_channel').send(this.get('topic'), txn.payload());
}
if (this.get('_initialized'))
this.get('_socket').send(this.get('_topic'), txn.payload());
else
this.get('join').call(this, {})

return txn.promise;
}
Expand Down Expand Up @@ -152,28 +155,19 @@ App.Phoenix.Utils = {
}

Ember.onLoad('Ember.Application', function(Application) {
Application.initializer({
name: 'session',

initialize: function(container, application) {
application.register('service:session', App.Phoenix.Session, {singleton: true})

application.inject('controller', 'service:session', 'service:session');
}
})

Application.initializer({
name: 'phoenix',
initialize: function(container, application) {
application.register('service:phoenix', App.Phoenix.Socket, {singleton: true})

App.ApplicationAdapter = DS.PhoenixSocketAdapter;
container.lookup('adapter:application').setSocket('session', 'data');

application.inject('service:session', 'service:phoenix', 'service:phoenix')
if (ENV.Phoenix.init.doInit) {
container.lookup('adapter:application').setSocket(ENV.Phoenix.init.channel, ENV.Phoenix.init.topic);
container.lookup('adapter:application').join(ENV.Phoenix.init.params)
}
}
})

})

}
2 changes: 1 addition & 1 deletion phoenix-socket.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2c9b4b8

Please sign in to comment.