diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..cd3bea1 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,25 @@ +# Changelog + +This package is [semantic versioned](http://semver.org/) + +## 2.0.0 + +- [api change]: move `store` and `protocol` options from arguments to the opts` hash + +e.g. for an instantiation in 1.0.0 like: + +``` +Vue.use(VueNativeSock, 'ws://localhost:9090', 'my-protocol', store, { format: 'json' }) +``` + +is now, in 2.0.0: + +``` +Vue.use(VueNativeSock, 'ws://localhost:9090', { protocol: 'my-protocol', store: store, format: 'json' }) +``` + +- [bugfix]: allow json message passing without a namespace + +## 1.0.0 + +First release diff --git a/README.md b/README.md index 6d6e063..5c29afb 100755 --- a/README.md +++ b/README.md @@ -13,31 +13,46 @@ npm install vue-native-websocket --save ``` ## Usage + #### Configuration + Automatic socket connection from an URL string + ``` js import VueNativeSock from 'vue-native-websocket' Vue.use(VueNativeSock, 'ws://localhost:9090') ``` -Set sub-protocol, this is optional option and default is empty string. -``` js -import VueNativeSock from 'vue-native-websocket' -Vue.use(VueNativeSock, 'ws://localhost:9090', 'my-protocol') -``` Enable Vuex integration, where `'./store'` is your local apps store: + ``` js import store from './store' -Vue.use(VueNativeSock, 'ws://localhost:9090', store) +Vue.use(VueNativeSock, 'ws://localhost:9090', { store: store }) ``` +Set sub-protocol, this is optional option and default is empty string. + +``` js +import VueNativeSock from 'vue-native-websocket' +Vue.use(VueNativeSock, 'ws://localhost:9090', { protocol: 'my-protocol' }) +``` + + Optionally enable JSON message passing: + +``` js +Vue.use(VueNativeSock, 'ws://localhost:9090', { format: 'json' }) +``` + +JSON message passing with a store: + ``` js import store from './store' -Vue.use(VueNativeSock, 'ws://localhost:9090', store, {format: 'json'}) +Vue.use(VueNativeSock, 'ws://localhost:9090', { store: store, format: 'json' }) ``` #### On Vuejs instance usage + ``` js var vm = new Vue({ methods: { @@ -52,13 +67,17 @@ var vm = new Vue({ ``` #### Dynamic socket event listeners -Create a new listener + +Create a new listener, for example: + ``` js -this.$options.sockets.event_name = (data) => console.log(data) +this.$options.sockets.onmessage = (data) => console.log(data) ``` + Remove existing listener + ``` js -delete this.$options.sockets.event_name +delete this.$options.sockets.onmessage ``` #### Vuex Store integration diff --git a/dist/build.js b/dist/build.js index da1fe98..3e64e8d 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.i=function(e){return e},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=3)}([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]:"",o=arguments[3],r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};if(!t)throw new Error("[vue-native-socket] cannot locate connection");var s=new i.default(t,o,n,r);e.prototype.$socket=s.WebSocket,e.mixin({created:function(){var e=this,t=this.$options.sockets;this.$options.sockets=new Proxy({},{set:function(e,t,n){return c.default.addListener(t,n,this),e[t]=n,!0},deleteProperty:function(e,t){return c.default.removeListener(t,this.$options.sockets[t],this),delete e.key,!0}}),t&&Object.keys(t).forEach(function(n){e.$options.sockets[n]=t[n]})},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;n3&&void 0!==arguments[3]?arguments[3]:{};o(this,e),this.format=i.format&&i.format.toLowerCase(),this.connect(t,n),r&&(this.store=r),this.onEvent()}return r(e,[{key:"connect",value:function(e,t){var n=this;this.WebSocket=new WebSocket(e,t),"json"===this.format&&("sendObj"in this.WebSocket||(this.WebSocket.sendObj=function(e){return n.WebSocket.send(JSON.stringify(e))}))}},{key:"onEvent",value:function(){var e=this;["onmessage","onclose","onerror","onopen"].forEach(function(t){e.WebSocket[t]=function(n){s.default.emit(t,n),e.store&&e.passToStore("SOCKET_"+t,n)}})}},{key:"passToStore",value:function(e,t){if(e.startsWith("SOCKET_"))if("json"===this.format&&t.data){var n=JSON.parse(t.data),o=n.namespace||"";n.mutation&&this.store.commit([o,n.mutation].join("/"),n),n.action&&this.store.dispatch([o,n.action].join("/"),n)}else this.store.commit(e.toUpperCase(),t)}}]),e}();t.default=c},function(e,t,n){e.exports=n(1)}])}); \ 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()}(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=new i.default(t,n);e.prototype.$socket=o.WebSocket,e.mixin({created:function(){var e=this,t=this.$options.sockets;this.$options.sockets=new Proxy({},{set:function(e,t,n){return c.default.addListener(t,n,this),e[t]=n,!0},deleteProperty:function(e,t){return c.default.removeListener(t,this.$options.sockets[t],this),delete e.key,!0}}),t&&Object.keys(t).forEach(function(n){e.$options.sockets[n]=t[n]})},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.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||"";this.WebSocket=n.WebSocket||new WebSocket(e,o),"json"===this.format&&("sendObj"in this.WebSocket||(this.WebSocket.sendObj=function(e){return t.WebSocket.send(JSON.stringify(e))}))}},{key:"onEvent",value:function(){var e=this;["onmessage","onclose","onerror","onopen"].forEach(function(t){e.WebSocket[t]=function(n){s.default.emit(t,n),e.store&&e.passToStore("SOCKET_"+t,n)}})}},{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),o=[r.namespace||"",r.mutation].filter(function(e){return!!e}).join("/"),r.action&&(n="dispatch")),this.store[n](o,r)}}}]),e}();t.default=c}])}); \ No newline at end of file diff --git a/package.json b/package.json index 5c25dc4..e5d9663 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-native-websocket", - "version": "1.0.0", + "version": "2.0.0", "description": "native websocket implemantation for vuejs and vuex", "main": "dist/build.js", "scripts": { diff --git a/src/Main.js b/src/Main.js index 7ed4b0c..d90cffe 100755 --- a/src/Main.js +++ b/src/Main.js @@ -3,10 +3,10 @@ import Emitter from './Emitter' export default { - install (Vue, connection, protocol = '', store, opts = {}) { + install (Vue, connection, opts = {}) { if (!connection) { throw new Error('[vue-native-socket] cannot locate connection') } - let observer = new Observer(connection, protocol, store, opts) + let observer = new Observer(connection, opts) Vue.prototype.$socket = observer.WebSocket diff --git a/src/Observer.js b/src/Observer.js index 1a428dd..7a530a1 100755 --- a/src/Observer.js +++ b/src/Observer.js @@ -1,14 +1,15 @@ import Emitter from './Emitter' export default class { - constructor (connectionUrl, protocol, store, opts = {}) { + constructor (connectionUrl, opts = {}) { this.format = opts.format && opts.format.toLowerCase() - this.connect(connectionUrl, protocol, opts) - if (store) { this.store = store } + this.connect(connectionUrl, opts) + if (opts.store) { this.store = opts.store } this.onEvent() } - connect (connectionUrl, protocol, opts = {}) { + connect (connectionUrl, opts = {}) { + let protocol = opts.protocol || '' this.WebSocket = opts.WebSocket || new WebSocket(connectionUrl, protocol) if (this.format === 'json') { if (!('sendObj' in this.WebSocket)) { diff --git a/test/unit/specs/Main.spec.js b/test/unit/specs/Main.spec.js index 542b441..2600539 100644 --- a/test/unit/specs/Main.spec.js +++ b/test/unit/specs/Main.spec.js @@ -9,7 +9,7 @@ describe("Main.js", () =>{ it ('can be bound to the onopen event', (done) => { mockServer = new Server('ws://localhost:8080') - Vue.use(VueNativeSock, 'ws://localhost:8080', null) + Vue.use(VueNativeSock, 'ws://localhost:8080') let vm = new Vue() vm.$options.sockets.onopen = (data) => { expect(data.type).to.equal('open') diff --git a/test/unit/specs/Observer.spec.js b/test/unit/specs/Observer.spec.js index ff19f6f..c164d08 100644 --- a/test/unit/specs/Observer.spec.js +++ b/test/unit/specs/Observer.spec.js @@ -37,7 +37,8 @@ describe ("Observer.js", () => { Vue.use(VueNativeSock, wsUrl) let vm = new Vue() - observer = new Observer(wsUrl, null, mockStore.object, { + observer = new Observer(wsUrl, { + store: mockStore.object, format: 'json', websocket: new WebSocket(wsUrl) }) @@ -62,7 +63,8 @@ describe ("Observer.js", () => { Vue.use(VueNativeSock, wsUrl) let vm = new Vue() - observer = new Observer(wsUrl, null, mockStore.object, { + observer = new Observer(wsUrl, { + store: mockStore.object, format: 'json', websocket: new WebSocket(wsUrl) })