diff --git a/CHANGELOG.md b/CHANGELOG.md index 1911b0c..16d12b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ This package is [semantic versioned](http://semver.org/) +## 2.0.8 +- [feature]: custom pass to store logic. Defaults to original passToStore code if no custom logic provided + ## 2.0.7 - [feature]: manual connect/disconnect diff --git a/README.md b/README.md index 82bb8ff..553c71e 100755 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ Vue.use(VueNativeSock, 'ws://localhost:9090', { store: store, format: 'json' }) Enable ws reconnect automatically: ``` js -Vue.use(VueNativeSock, 'ws://localhost:9090', { +Vue.use(VueNativeSock, 'ws://localhost:9090', { reconnection: true, // (Boolean) whether to reconnect automatically (false) reconnectionAttempts: 5, // (Number) number of reconnection attempts before giving up (Infinity), reconnectionDelay: 3000, // (Number) how long to initially wait before attempting a new (1000) @@ -189,6 +189,50 @@ actions: { Use the `.sendObj({some: data})` method on the `$socket` object to send stringified json messages. +##### Custom socket event handling + +Provide you own custom code to handle events received via the `passToStoreHandler` option. The function you provide will be passed the following arguments: + +1. event name +2. event +3. original/default handler code function `function (eventName, event)`. This allows you to optionally do some basic preprocessing before handing the event over to the original handler. + +The original passToStore code is used if no `passToStoreHandler` is configured. + +Here is an example of passing in a custom handler. This has the original passToStore code to give you an example of what you can do: + +``` js +Vue.use(VueNativeSock, 'ws://localhost:9090', { + passToStoreHandler: function (eventName, event) { + if (!eventName.startsWith('SOCKET_')) { return } + let method = 'commit' + let target = eventName.toUpperCase() + let msg = event + if (this.format === 'json' && event.data) { + msg = JSON.parse(event.data) + if (msg.mutation) { + target = [msg.namespace || '', msg.mutation].filter((e) => !!e).join('/') + } else if (msg.action) { + method = 'dispatch' + target = [msg.namespace || '', msg.action].filter((e) => !!e).join('/') + } + } + this.store[method](target, msg) + } +}) +``` + +Here is an example of do some preprocessing, then pass the event onto the original handler code: + +``` js +Vue.use(VueNativeSock, 'ws://localhost:9090', { + passToStoreHandler: function (eventName, event, next) { + event.data = event.should_have_been_named_data + next(eventName, event) + } +}) +``` + ## Examples TODO: post your example here! diff --git a/dist/build.js b/dist/build.js index 32c1e17..e2651b7 100755 --- a/dist/build.js +++ b/dist/build.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.VueNativeSock=t():e.VueNativeSock=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n-1)&&(o.splice(r,1),this.listeners.set(e,o),!0)}},{key:"emit",value:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),o=1;o2&&void 0!==arguments[2]?arguments[2]:{};if(!t)throw new Error("[vue-native-socket] cannot locate connection");var o=null;n.connectManually?(e.prototype.$connect=function(){o=new c.default(t,n),e.prototype.$socket=o.WebSocket},e.prototype.$disconnect=function(){o&&o.reconnection&&(o.reconnection=!1),e.prototype.$socket&&(e.prototype.$socket.close(),delete e.prototype.$socket)}):(o=new c.default(t,n),e.prototype.$socket=o.WebSocket),e.mixin({created:function(){var e=this,t=this,n=this.$options.sockets;this.$options.sockets=new Proxy({},{set:function(e,n,o){return s.default.addListener(n,o,t),e[n]=o,!0},deleteProperty:function(e,n){return s.default.removeListener(n,t.$options.sockets[n],t),delete e.key,!0}}),n&&Object.keys(n).forEach(function(t){e.$options.sockets[t]=n[t]})},beforeDestroy:function(){var e=this,t=this.$options.sockets;t&&Object.keys(t).forEach(function(t){delete e.$options.sockets[t]})}})}}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{};o(this,e),this.format=n.format&&n.format.toLowerCase(),this.connectionUrl=t,this.opts=n,this.reconnection=this.opts.reconnection||!1,this.reconnectionAttempts=this.opts.reconnectionAttempts||1/0,this.reconnectionDelay=this.opts.reconnectionDelay||1e3,this.reconnectTimeoutId=0,this.reconnectionCount=0,this.connect(t,n),n.store&&(this.store=n.store),this.onEvent()}return r(e,[{key:"connect",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=n.protocol||"";return this.WebSocket=n.WebSocket||(""===o?new WebSocket(e):new WebSocket(e,o)),"json"===this.format&&("sendObj"in this.WebSocket||(this.WebSocket.sendObj=function(e){return t.WebSocket.send(JSON.stringify(e))})),this.WebSocket}},{key:"reconnect",value:function(){var e=this;this.reconnectionCount<=this.reconnectionAttempts?(this.reconnectionCount++,clearTimeout(this.reconnectTimeoutId),this.reconnectTimeoutId=setTimeout(function(){e.store&&e.passToStore("SOCKET_RECONNECT",e.reconnectionCount),e.connect(e.connectionUrl,e.opts),e.onEvent()},this.reconnectionDelay)):this.store&&this.passToStore("SOCKET_RECONNECT_ERROR",!0)}},{key:"onEvent",value:function(){var e=this;["onmessage","onclose","onerror","onopen"].forEach(function(t){e.WebSocket[t]=function(n){i.default.emit(t,n),e.store&&e.passToStore("SOCKET_"+t,n),e.reconnection&&"onopen"===t&&(e.reconnectionCount=0),e.reconnection&&"onclose"===t&&e.reconnect()}})}},{key:"passToStore",value:function(e,t){if(e.startsWith("SOCKET_")){var n="commit",o=e.toUpperCase(),r=t;"json"===this.format&&t.data&&(r=JSON.parse(t.data),r.mutation?o=[r.namespace||"",r.mutation].filter(function(e){return!!e}).join("/"):r.action&&(n="dispatch",o=[r.namespace||"",r.action].filter(function(e){return!!e}).join("/"))),this.store[n](o,r)}}}]),e}();t.default=s}])}); \ No newline at end of file +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.VueNativeSock=t():e.VueNativeSock=t()}("undefined"!=typeof self?self:this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,t),r.l=!0,r.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n-1)&&(o.splice(r,1),this.listeners.set(e,o),!0)}},{key:"emit",value:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),o=1;o2&&void 0!==arguments[2]?arguments[2]:{};if(!t)throw new Error("[vue-native-socket] cannot locate connection");var o=null;n.connectManually?(e.prototype.$connect=function(){o=new i.default(t,n),e.prototype.$socket=o.WebSocket},e.prototype.$disconnect=function(){o&&o.reconnection&&(o.reconnection=!1),e.prototype.$socket&&(e.prototype.$socket.close(),delete e.prototype.$socket)}):(o=new i.default(t,n),e.prototype.$socket=o.WebSocket),e.mixin({created:function(){var e=this,t=this,n=this.$options.sockets;this.$options.sockets=new Proxy({},{set:function(e,n,o){return s.default.addListener(n,o,t),e[n]=o,!0},deleteProperty:function(e,n){return s.default.removeListener(n,t.$options.sockets[n],t),delete e.key,!0}}),n&&Object.keys(n).forEach(function(t){e.$options.sockets[t]=n[t]})},beforeDestroy:function(){var e=this,t=this.$options.sockets;t&&Object.keys(t).forEach(function(t){delete e.$options.sockets[t]})}})}}},function(e,t,n){"use strict";function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{};o(this,e),this.format=n.format&&n.format.toLowerCase(),this.connectionUrl=t,this.opts=n,this.reconnection=this.opts.reconnection||!1,this.reconnectionAttempts=this.opts.reconnectionAttempts||1/0,this.reconnectionDelay=this.opts.reconnectionDelay||1e3,this.reconnectTimeoutId=0,this.reconnectionCount=0,this.passToStoreHandler=this.opts.passToStoreHandler||!1,this.connect(t,n),n.store&&(this.store=n.store),this.onEvent()}return r(e,[{key:"connect",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=n.protocol||"";return this.WebSocket=n.WebSocket||(""===o?new WebSocket(e):new WebSocket(e,o)),"json"===this.format&&("sendObj"in this.WebSocket||(this.WebSocket.sendObj=function(e){return t.WebSocket.send(JSON.stringify(e))})),this.WebSocket}},{key:"reconnect",value:function(){var e=this;this.reconnectionCount<=this.reconnectionAttempts?(this.reconnectionCount++,clearTimeout(this.reconnectTimeoutId),this.reconnectTimeoutId=setTimeout(function(){e.store&&e.passToStore("SOCKET_RECONNECT",e.reconnectionCount),e.connect(e.connectionUrl,e.opts),e.onEvent()},this.reconnectionDelay)):this.store&&this.passToStore("SOCKET_RECONNECT_ERROR",!0)}},{key:"onEvent",value:function(){var e=this;["onmessage","onclose","onerror","onopen"].forEach(function(t){e.WebSocket[t]=function(n){c.default.emit(t,n),e.store&&e.passToStore("SOCKET_"+t,n),e.reconnection&&"onopen"===t&&(e.reconnectionCount=0),e.reconnection&&"onclose"===t&&e.reconnect()}})}},{key:"passToStore",value:function(e,t){this.passToStoreHandler?this.passToStoreHandler(e,t,this.defaultPassToStore):this.defaultPassToStore(e,t)}},{key:"defaultPassToStore",value:function(e,t){if(e.startsWith("SOCKET_")){var n="commit",o=e.toUpperCase(),r=t;"json"===this.format&&t.data&&(r=JSON.parse(t.data),r.mutation?o=[r.namespace||"",r.mutation].filter(function(e){return!!e}).join("/"):r.action&&(n="dispatch",o=[r.namespace||"",r.action].filter(function(e){return!!e}).join("/"))),this.store[n](o,r)}}}]),e}();t.default=s}])}); \ No newline at end of file diff --git a/package.json b/package.json index e23a86b..d29e182 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-native-websocket", - "version": "2.0.7", + "version": "2.0.8", "description": "native websocket implemantation for vuejs and vuex", "main": "dist/build.js", "scripts": { diff --git a/src/Observer.js b/src/Observer.js index 17c3c5c..a0dcffb 100755 --- a/src/Observer.js +++ b/src/Observer.js @@ -12,6 +12,8 @@ export default class { this.reconnectTimeoutId = 0 this.reconnectionCount = 0 + this.passToStoreHandler = this.opts.passToStoreHandler || false + this.connect(connectionUrl, opts) if (opts.store) { this.store = opts.store } @@ -61,6 +63,14 @@ export default class { } passToStore (eventName, event) { + if (this.passToStoreHandler) { + this.passToStoreHandler(eventName, event, this.defaultPassToStore) + } else { + this.defaultPassToStore(eventName, event) + } + } + + defaultPassToStore (eventName, event) { if (!eventName.startsWith('SOCKET_')) { return } let method = 'commit' let target = eventName.toUpperCase()