spine-high-templar
Advanced tools
Comparing version 0.3.0 to 0.4.0
@@ -28,2 +28,22 @@ import mitt from 'mitt'; | ||
var _extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
var Subscription = function () { | ||
@@ -37,3 +57,4 @@ function Subscription() { | ||
this.onPublish = null; | ||
this.wrappedHandler = null; | ||
this.onReconnect = null; | ||
this.wrappedPublishHandler = null; | ||
this.messageCached = true; | ||
@@ -43,2 +64,3 @@ | ||
this.onPublish = props.onPublish; | ||
this.onReconnect = props.onReconnect; | ||
this.socket = props.socket; | ||
@@ -53,11 +75,14 @@ this.requestId = uuid(); | ||
if (this.onPublish) { | ||
this._startListening(); | ||
this._startListeningForPublish(); | ||
} | ||
if (this.onReconnect) { | ||
this._startListeningForReconnect(); | ||
} | ||
} | ||
}, { | ||
key: '_startListening', | ||
value: function _startListening() { | ||
key: '_startListeningForPublish', | ||
value: function _startListeningForPublish() { | ||
var _this = this; | ||
var wrappedHandler = function wrappedHandler(msg) { | ||
this.wrappedPublishHandler = function (msg) { | ||
if (msg.requestId !== _this.requestId || msg.type !== 'publish') { | ||
@@ -68,11 +93,26 @@ return false; | ||
}; | ||
this.wrappedHandler = wrappedHandler; | ||
this.socket.on('message', wrappedHandler); | ||
this.socket.on('message', this.wrappedPublishHandler); | ||
} | ||
}, { | ||
key: '_startListeningForReconnect', | ||
value: function _startListeningForReconnect() { | ||
var _this2 = this; | ||
this.wrappedReconnectHandler = function () { | ||
if (_this2.messageCached) { | ||
return; | ||
} | ||
_this2.onReconnect(); | ||
}; | ||
this.socket.on('open', this.wrappedReconnectHandler); | ||
} | ||
}, { | ||
key: 'stopListening', | ||
value: function stopListening() { | ||
if (this.wrappedHandler) { | ||
this.socket.off('message', this.wrappedHandler); | ||
if (this.wrappedPublishHandler) { | ||
this.socket.off('message', this.wrappedPublishHandler); | ||
} | ||
if (this.wrappedReconnectHandler) { | ||
this.socket.off('open', this.wrappedReconnectHandler); | ||
} | ||
} | ||
@@ -184,7 +224,4 @@ }]); | ||
key: 'subscribe', | ||
value: function subscribe(_ref) { | ||
var room = _ref.room, | ||
onPublish = _ref.onPublish; | ||
var sub = new Subscription({ room: room, onPublish: onPublish, socket: this }); | ||
value: function subscribe(options) { | ||
var sub = new Subscription(_extends({ socket: this }, options)); | ||
this.subscriptions.push(sub); | ||
@@ -191,0 +228,0 @@ this.notifySocketOfSubscription(sub).then(function () { |
@@ -34,2 +34,22 @@ (function (global, factory) { | ||
var _extends = Object.assign || function (target) { | ||
for (var i = 1; i < arguments.length; i++) { | ||
var source = arguments[i]; | ||
for (var key in source) { | ||
if (Object.prototype.hasOwnProperty.call(source, key)) { | ||
target[key] = source[key]; | ||
} | ||
} | ||
} | ||
return target; | ||
}; | ||
var Subscription = function () { | ||
@@ -43,3 +63,4 @@ function Subscription() { | ||
this.onPublish = null; | ||
this.wrappedHandler = null; | ||
this.onReconnect = null; | ||
this.wrappedPublishHandler = null; | ||
this.messageCached = true; | ||
@@ -49,2 +70,3 @@ | ||
this.onPublish = props.onPublish; | ||
this.onReconnect = props.onReconnect; | ||
this.socket = props.socket; | ||
@@ -59,11 +81,14 @@ this.requestId = uuid(); | ||
if (this.onPublish) { | ||
this._startListening(); | ||
this._startListeningForPublish(); | ||
} | ||
if (this.onReconnect) { | ||
this._startListeningForReconnect(); | ||
} | ||
} | ||
}, { | ||
key: '_startListening', | ||
value: function _startListening() { | ||
key: '_startListeningForPublish', | ||
value: function _startListeningForPublish() { | ||
var _this = this; | ||
var wrappedHandler = function wrappedHandler(msg) { | ||
this.wrappedPublishHandler = function (msg) { | ||
if (msg.requestId !== _this.requestId || msg.type !== 'publish') { | ||
@@ -74,11 +99,26 @@ return false; | ||
}; | ||
this.wrappedHandler = wrappedHandler; | ||
this.socket.on('message', wrappedHandler); | ||
this.socket.on('message', this.wrappedPublishHandler); | ||
} | ||
}, { | ||
key: '_startListeningForReconnect', | ||
value: function _startListeningForReconnect() { | ||
var _this2 = this; | ||
this.wrappedReconnectHandler = function () { | ||
if (_this2.messageCached) { | ||
return; | ||
} | ||
_this2.onReconnect(); | ||
}; | ||
this.socket.on('open', this.wrappedReconnectHandler); | ||
} | ||
}, { | ||
key: 'stopListening', | ||
value: function stopListening() { | ||
if (this.wrappedHandler) { | ||
this.socket.off('message', this.wrappedHandler); | ||
if (this.wrappedPublishHandler) { | ||
this.socket.off('message', this.wrappedPublishHandler); | ||
} | ||
if (this.wrappedReconnectHandler) { | ||
this.socket.off('open', this.wrappedReconnectHandler); | ||
} | ||
} | ||
@@ -190,7 +230,4 @@ }]); | ||
key: 'subscribe', | ||
value: function subscribe(_ref) { | ||
var room = _ref.room, | ||
onPublish = _ref.onPublish; | ||
var sub = new Subscription({ room: room, onPublish: onPublish, socket: this }); | ||
value: function subscribe(options) { | ||
var sub = new Subscription(_extends({ socket: this }, options)); | ||
this.subscriptions.push(sub); | ||
@@ -197,0 +234,0 @@ this.notifySocketOfSubscription(sub).then(function () { |
{ | ||
"name": "spine-high-templar", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "author": "Jasper Stam <jasper@codeyellow.nl>", |
@@ -8,1 +8,68 @@ # spine-high-templar | ||
A frontend package which adds websocket and pubSub logic from [high-templar](https://github.com/CodeYellowBV/high-templar) to [mobx-spine](https://github.com/CodeYellowBV/mobx-spine). | ||
The functionality of this package includes: | ||
- Websocket creation | ||
- Keepalive | ||
- Automatic reconnection | ||
- Subscriptions | ||
- Handlers for the publishes happening for a subscription | ||
- Subscription refreshing after a socket disconnect => reconnect | ||
## Usage | ||
### Socket opening | ||
spine-high-templar offers a Socket model. It is recommended to create this socket in the viewStore and save it in the api instance. | ||
In the `store/View` constructor: | ||
```js | ||
this.fetchBootstrap().then(() => { | ||
if (this.bootstrapCode === 200) { | ||
api.socket = new Socket({ | ||
url: process.env.CY_FRONTEND_WEBSOCKET_URL, | ||
}); | ||
} | ||
}); | ||
``` | ||
It is important that the bootstrap has actually succeeded, the high-templar instance will use the headers provided in the socket-open-request to authenticate the user against the binder instance. | ||
### Subscribing & unsubscribing | ||
The frontend subscribes to a room (in the form of an object). `onPublish` will be called with every message published in that room. | ||
Don't forget to unsubscribe when a view will unmount. | ||
View example: | ||
```js | ||
componentDidMount() { | ||
this.subscription = this.props.store.api.socket.subscribe({ | ||
onPublish: this.handlePublish.bind(this), | ||
room: { | ||
tenant: 16, | ||
driver: this.props.screenProps.viewStore.currentUser.id, | ||
}, | ||
}); | ||
} | ||
handlePublish(msg) { | ||
this.props.store.add(msg.data); | ||
} | ||
componentWillUnmount() { | ||
this.props.store.api.socket.unsubscribe(this.subscription); | ||
} | ||
``` | ||
## Authorization: Token | ||
If the app doesn't use session auth but an Authorization token, one can pass the token under the `token` key in the Socket constructor options. Due to a limitation of the WebSocket available in browsers, it's not possible to add custom headers to a websocket open request, so we handle this in high-templar. | ||
The high-templar instance will add a header `Authorization: Token ${token}` when authenticating against the binder instance. | ||
```js | ||
api.socket = new Socket({ | ||
url: WEBSOCKET_URL, | ||
token: this.authToken.value, | ||
}); | ||
``` |
27735
620
75