Compare commits

..

74 commits

Author SHA1 Message Date
Aybüke ÇALIŞKAN
61614c865e
Update README.md (#327) 2022-01-09 23:53:06 +03:00
Metin Seylan
4f00019283
Update README.md 2021-06-08 19:55:18 +03:00
lju
3337d43298
Add basic Vue 3 compatibility (#289) 2021-02-19 21:26:27 +03:00
sambit sahoo
2f63eebb70
add type declarations for optional options (#285)
Add type declarations for optional options as it throws error.
2020-10-10 21:24:46 +03:00
Metin Seylan
c555cc72ef
Update README.md 2020-09-04 12:33:00 +03:00
IFA
0359c5dd59
Update README.md for making things clear (#277) 2020-09-04 11:58:53 +03:00
Даниил Пронин
d7ddfb23ef
Update README.md (#271) 2020-08-06 11:15:40 +03:00
MetinSeylan
35d8f66d44 revert changes & delete issues folder 2020-07-31 22:35:09 +03:00
Metin Seylan
640dfc044c reverse from 3.0.8 2020-05-08 12:29:11 +03:00
Metin Seylan
f770882eb5 Revert "version upgrade"
This reverts commit 3d04f310a3.
2020-05-08 12:28:33 +03:00
Metin Seylan
3d04f310a3 version upgrade 2020-04-30 22:32:03 +03:00
dailing
45860773e4
Update README.md (#241)
It seems that `import SocketIO from "socket.io-client"` is missing from the examples.
2020-03-16 17:19:25 +03:00
Mehmet Yılmaz
4fba4071f7 readme refactor (#232) 2019-12-10 16:15:22 +03:00
Nikita Umnov
caf4f56b10 add types definition (#218)
* add types definition
2019-08-15 13:20:38 +03:00
Leonardo E. Dominguez
8988085bef Handle more than one namespace (#207)
* add: handle more than one namespace

* Revert "[FIX] Adjusting SocketIO client lib import (#202)"

This reverts commit ee1e7ed1ee.

* add: handle more than one namespace

* change: move useConnectionNamespace inside options object

* update: readme

* add: support namespace listeners in components

* update build files

* add: namespace name property to options object

* update build files
2019-05-13 00:59:44 +03:00
Vinícius Feitosa da Silva
ee1e7ed1ee [FIX] Adjusting SocketIO client lib import (#202) 2019-03-23 11:18:36 +03:00
Metin Seylan
f77564b41e version upgrade 2019-03-07 04:40:01 +03:00
Michael Johansen
ad3d21ecb5 fixed typo on VueSocketIOListener (#200) 2019-03-07 04:37:54 +03:00
Arie Miller
5cbf41a399 Update listener.js (#199)
VueSocketIOListenler -> VueSocketIOListener
2019-03-07 04:37:20 +03:00
Metin Seylan
68d4e5570b upgrade version 2019-03-06 20:24:15 +03:00
Evan bechtol
381cb5fdd0 README.MD Example Usage Updates (#198)
* Fix Spelling

- Rename `Listenler` to `Listener`

* Add Options to Connection

- Add options which can be passed to connection string for `SocketIO`

* Build New Version

* Fix spelling in Package.json

- Change `implemantation` to `implementation`
- Change `vuejs` to `Vue.js`
- Change `vuex` to `VueX`

* Updates to index.js

- Add `options` to JSDocs for constructor
- Fix spelling for JSDoc on `install` and `connect` methods

* Update README.MD

- Add example of connecting using socket.io-client instance

* Update README.MD

- Add options example using connection string

* Update README.MD

- Add options example using connection string

* Remove unnecessary white space
2019-03-06 20:20:24 +03:00
Evan bechtol
f1e03525c0 Add options parameter to Constructor (#195)
* Fix Spelling

- Rename `Listenler` to `Listener`

* Add Options to Connection

- Add options which can be passed to connection string for `SocketIO`

* Build New Version

* Fix spelling in Package.json

- Change `implemantation` to `implementation`
- Change `vuejs` to `Vue.js`
- Change `vuex` to `VueX`

* Updates to index.js

- Add `options` to JSDocs for constructor
- Fix spelling for JSDoc on `install` and `connect` methods
2019-03-06 19:40:24 +03:00
Slava
207a0a13bd don't dispatch ping to store (#188) 2019-02-13 12:37:23 +03:00
Slava
6d5c7983d1 move string concatenation out of loop (#189) 2019-02-13 12:37:02 +03:00
Metin Seylan
60d38b78bc build 3.0.5 2019-01-25 09:23:32 +03:00
Nikita Umnov
4322054bfd FIX: receiving staticEvents messages (#181)
* FIX: receiving staticEvents messages
* return space :)
2019-01-25 09:20:17 +03:00
Metin Seylan
fb8e1f96c1
Update README.md 2019-01-03 23:41:01 +03:00
Metin Seylan
6c837e002f Update issue templates 2018-11-27 22:05:38 +03:00
Metin Seylan
176c060356 update mixin for https://github.com/MetinSeylan/Vue-Socket.io/issues/168 2018-11-26 20:19:11 +03:00
Metin Seylan
4b7c282d0c hotfix for socket.io-client instance 2018-11-25 21:34:19 +03:00
Metin Seylan
de3092cceb
Merge pull request #167 from nodegin/patch-1
Fix #166
2018-11-25 21:32:17 +03:00
nodegin
1f33e87192
Fix #166 2018-11-25 07:20:30 +08:00
Metin Seylan
73a0d32d36 hotfix for build 2018-11-23 18:29:29 +03:00
Metin Seylan
513f6d5cb6
Update README.md 2018-11-22 20:16:39 +03:00
Metin Seylan
d275ccdbf6 added old documentation for ^2.0.0 2018-11-22 16:47:27 +03:00
Metin Seylan
723743227f upgrade version 2018-11-20 15:50:14 +03:00
Metin Seylan
0c737b3b5e
Merge pull request #161 from viniciusrebel/fix-vuex-modules
Fix Vuex modules #39
2018-11-20 15:48:46 +03:00
Vinicius Rebel
496e88b196 Fix vuex modules 2018-11-19 14:03:13 -03:00
Metin Seylan
e0b37e30bd
Merge pull request #160 from eyaylagul/master
Typo fixed
2018-11-19 15:01:39 +03:00
Emre Yaylagül
87dc58e685
Merge pull request #1 from eyaylagul/eyaylagul-patch-1
Update README.md
2018-11-19 14:11:54 +03:00
Emre Yaylagül
e2bbc8ef8e
Update README.md 2018-11-19 14:10:32 +03:00
Metin Seylan
e843ab394e
Update README.md 2018-11-18 21:33:42 +03:00
Metin Seylan
f48326e55c
Update README.md 2018-11-18 18:24:03 +03:00
Metin Seylan
b8cea1d589 cat added 2018-11-18 17:55:39 +03:00
Metin Seylan
cb5055d51a added vuex docs 2018-11-18 17:31:51 +03:00
Metin Seylan
c5a6889176 added dynamic listenler docs 2018-11-18 17:15:14 +03:00
Metin Seylan
b59f1a4a60 readme changes 2018-11-18 15:17:16 +03:00
Metin Seylan
63235b346c component level usage added 2018-11-18 15:08:41 +03:00
Metin Seylan
36870b3d31 added required fields table 2018-11-18 15:00:18 +03:00
Metin Seylan
ff2063b3be installation object table 2018-11-18 14:47:25 +03:00
Metin Seylan
b41e878cf8 installation added 2018-11-18 14:35:36 +03:00
Metin Seylan
92ee7c0291 installation added 2018-11-18 14:31:54 +03:00
Metin Seylan
15400d5b52 readme changes 2018-11-18 14:23:49 +03:00
Metin Seylan
bc0e84bdb3 update badges 2018-11-18 14:10:09 +03:00
Metin Seylan
a613d631cf readme title 2018-11-18 14:00:07 +03:00
Metin Seylan
67c5f97bbc small changes and logo 2018-11-18 13:44:07 +03:00
Metin Seylan
7266731212 webpack & package configration 2018-10-28 22:29:13 +03:00
Metin Seylan
6de5990456 added vuex support
added actions & mutations prefix
updated gitignore & added npmignore file
2018-10-28 18:56:16 +03:00
Metin Seylan
991cc956d2 first raw dirty commit 2018-10-27 23:08:29 +03:00
Metin Seylan
9e6a586423
Merge pull request #118 from stalniy/fix/actions
fix(actions): properly transform action to store action
2018-04-04 18:52:37 +03:00
Metin Seylan
4c6625e18b
Merge branch 'master' into fix/actions 2018-04-04 18:52:27 +03:00
Metin Seylan
99810e131a
Merge pull request #125 from lastmirage/master
Support multiple packet data argument
2018-03-23 11:59:54 +03:00
lastmirage
ffbf48ee28 indent 2018-03-19 15:15:41 +09:00
lastmirage
ec192d89b9
Support multiple packet data argument 2018-03-09 00:42:22 +09:00
Sergey Stotskiy
ce541e7da9 fix(actions): properly transform action to store action 2018-01-30 15:56:39 +02:00
Metin Seylan
8951667903 2.1.1-b build 2018-01-15 14:51:11 +03:00
Metin Seylan
1e2702b912
Merge pull request #100 from stalniy/master
fix(observer): lowercased event name before translation
2018-01-12 20:33:02 +03:00
Sergey Stotskiy
34561d8d03 fix(observer): lowercased event name before translation
Fixes #99
2017-11-20 14:12:00 +02:00
Metin Seylan
57887ea0a1 Merge pull request #89 from abdulmueid/socket.io-2.0.0
Updated Socket.io client version to 2.x
2017-10-14 14:51:54 +03:00
Abdul Mueid Akhtar
0cda8cde27 Updated Socket.io version to 2.x branch 2017-10-07 19:30:56 +02:00
Metin Seylan
d3c8d11f9e Merge pull request #67 from ncoden/fix/event-inheritance
Fix: propagate event to Socket
2017-08-15 07:43:47 +03:00
Nicolas Coden
b0993481f7 Fix: propagate event to Socket 2017-06-17 18:44:10 +02:00
Metin Seylan
d44a480584 Merge pull request #52 from jeystaats/patch-1
Multiple arguments added for emitting to store
2017-05-02 11:56:01 +03:00
Jasper Staats
5cb889fd72 Multiple arguments added for emitting to store
This solves issue #51.
2017-05-02 10:53:51 +02:00
20 changed files with 781 additions and 279 deletions

25
.gitignore vendored
View file

@ -1,4 +1,23 @@
.DS_Store .DS_Store
node_modules/ node_modules
npm-debug.log # dist
.idea/
# local env files
.env.local
.env.*.local
*.map
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
# Editor directories and files
.bitmap
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

17
.npmignore Normal file
View file

@ -0,0 +1,17 @@
.DS_Store
src/
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.map
# Editor directories and files
.idea
.vscode
.bitmap
*.suo
*.ntvs*
*.njsproj
*.sln
.github/

7
LICENSE Normal file
View file

@ -0,0 +1,7 @@
Copyright 2018 Metin Seylan
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

222
README.md Executable file → Normal file
View file

@ -1,114 +1,192 @@
# Vue-Socket.io <p align="center">
<a href="https://github.com/MetinSeylan/Vue-Socket.io" target="_blank">
<img width="250" src="https://raw.githubusercontent.com/MetinSeylan/Vue-Socket.io/master/docs/logo.png">
</a>
</p>
[![NPM version](https://img.shields.io/npm/v/vue-socket.io.svg)](https://www.npmjs.com/package/vue-socket.io) <p align="center">
![VueJS v2 compatible](https://img.shields.io/badge/Vuejs%202-compatible-green.svg) <a href="https://www.npmjs.com/package/vue-socket.io"><img src="https://img.shields.io/npm/v/vue-socket.io.svg"/> <img src="https://img.shields.io/npm/dt/vue-socket.io.svg"/></a>
<a href="https://www.npmjs.com/package/vue-socket.io"><img src="https://img.shields.io/npm/dt/vue-socket.io.svg" alt="Downloads"></a> <a href="https://github.com/vuejs/awesome-vue"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg"/></a>
<img id="dependency_badge" src="https://www.versioneye.com/javascript/metinseylan:vue-socket.io/2.0.1/badge.svg" alt="Dependency Badge" rel="nofollow"> <a href="https://vuejs.org/"><img src="https://img.shields.io/badge/vue-2.x-brightgreen.svg"/></a>
<a href="https://www.npmjs.com/package/vue-socket.io"><img src="https://img.shields.io/npm/l/vue-socket.io.svg" alt="License"></a> <a href="http://packagequality.com/#?package=vue-socket.io"><img src="http://npm.packagequality.com/shield/vue-socket.io.svg"/></a>
<a href="https://github.com/MetinSeylan/Vue-Socket.io/"><img src="https://img.shields.io/npm/l/vue-socket.io.svg"/></a>
<a href="https://github.com/MetinSeylan/Vue-Socket.io/"><img src="https://img.shields.io/github/stars/MetinSeylan/Vue-Socket.io.svg"/></a>
</p>
<p align="center">
<a href="https://www.patreon.com/MetinSeylan">
<img alt="Patreon" src="https://c5.patreon.com/external/logo/become_a_patron_button.png" height="50" />
</a>
</p>
<p>Vue-Socket.io is a socket.io integration for Vuejs, easy to use, supporting Vuex and component level socket consumer managements.<p>
socket.io implementation for Vuejs 2 and Vuex ###### Demo
- <a href="http://metinseylan.com/vuesocketio/" target="_blank">Chat Application</a>
## Install - <a href="http://metinseylan.com" target="_blank">Car Tracking Application</a>
<p>You can also check my other npm library <a href="https://github.com/MetinSeylan/Nestjs-OpenTelemetry">Nestjs OpenTelemetry</a></p>
<p>
are you looking for old documentation? <a href="https://github.com/MetinSeylan/Vue-Socket.io/blob/master/docs/OLD_README.md">it's here</a>
</p>
#### 🚀 Installation
``` bash ``` bash
npm install vue-socket.io --save npm install vue-socket.io --save
``` ```
##### Using Connection String
``` javascript
import Vue from 'vue'
import store from './store'
import App from './App.vue'
import VueSocketIO from 'vue-socket.io'
## Usage Vue.use(new VueSocketIO({
#### Configuration debug: true,
Automatic socket connection from an URL string connection: 'http://metinseylan.com:1992',
``` js vuex: {
import VueSocketio from 'vue-socket.io'; store,
Vue.use(VueSocketio, 'http://socketserver.com:1923'); actionPrefix: 'SOCKET_',
mutationPrefix: 'SOCKET_'
},
options: { path: "/my-app/" } //Optional options
}))
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
``` ```
Bind custom socket.io-client instance ##### Using socket.io-client Instance
``` js ``` javascript
Vue.use(VueSocketio, socketio('http://socketserver.com:1923')); import Vue from 'vue'
import store from './store'
import App from './App.vue'
import VueSocketIO from 'vue-socket.io'
import SocketIO from 'socket.io-client'
const options = { path: '/my-app/' }; //Options object to pass into SocketIO
Vue.use(new VueSocketIO({
debug: true,
connection: SocketIO('http://metinseylan.com:1992', options), //options object is Optional
vuex: {
store,
actionPrefix: "SOCKET_",
mutationPrefix: "SOCKET_"
}
})
);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
``` ```
Enable Vuex integration **Parameters**|**Type's**|**Default**|**Required**|**Description**
``` js -----|-----|-----|-----|-----
import store from './yourstore' debug|Boolean|`false`|Optional|Enable logging for debug
Vue.use(VueSocketio, socketio('http://socketserver.com:1923'), store); connection|String/Socket.io-client|`null`|Required|Websocket server url or socket.io-client instance
``` vuex.store|Vuex|`null`|Optional|Vuex store instance
vuex.actionPrefix|String|`null`|Optional|Prefix for emitting server side vuex actions
vuex.mutationPrefix|String |`null`|Optional|Prefix for emitting server side vuex mutations
#### On Vuejs instance usage #### 🌈 Component Level Usage
``` js
var vm = new Vue({ <p>If you want to listen socket events from component side, you need to add `sockets` object in Vue component. After that every function will start to listen events, depends on object key</p>
sockets:{
connect: function(){ ``` javascript
new Vue({
sockets: {
connect: function () {
console.log('socket connected') console.log('socket connected')
}, },
customEmit: function(val){ customEmit: function (data) {
console.log('this method was fired by the socket server. eg: io.emit("customEmit", data)') console.log('this method was fired by the socket server. eg: io.emit("customEmit", data)')
} }
}, },
methods: { methods: {
clickButton: function(val){ clickButton: function (data) {
// $socket is socket.io-client instance // $socket is socket.io-client instance
this.$socket.emit('emit_method', val); this.$socket.emit('emit_method', data)
} }
} }
}) })
``` ```
#### Dynamic socket event listeners ##### Dynamic Listeners
Create a new listener
``` js <p>If you need consuming events dynamically in runtime, you can use `subscribe` and `unsubscribe` methods in Vue component</p>
this.$options.sockets.event_name = (data) => {
console.log(data) ``` javascript
this.sockets.subscribe('EVENT_NAME', (data) => {
this.msg = data.message;
});
this.sockets.unsubscribe('EVENT_NAME');
```
##### Defining handlers for events with special characters
<p>If you want to handle 'kebab-case', or "event with space inside it" events, then you have to define it via the following way</p>
``` javascript
export default {
name: 'Test',
sockets: {
connect: function () {
console.log('socket to notification channel connected')
},
},
data () {
return {
something: [
// ... something here for the data if you need.
]
}
},
mounted () {
this.$socket.subscribe("kebab-case", function(data) {
console.log("This event was fired by eg. sio.emit('kebab-case')", data)
})
}
} }
``` ```
Remove existing listener
``` js
delete this.$options.sockets.event_name;
```
#### Vuex Store integration #### 🏆 Vuex Integration
<p>When you set store parameter in installation, `Vue-Socket.io` will start sending events to Vuex store. If you set both prefix for vuex, you can use `actions` and `mutations` at the same time. But, best way to use is just `actions`</p>
Socket **mutations** always have `SOCKET_` prefix. ``` javascript
Socket **actions** always have `socket_` prefix and the socket event name is `camelCased` (ex. `SOCKET_USER_MESSAGE` => `socket_userMessage`)
You can use either one or another or both in your store. Namespaced modules are supported.
``` js
import Vue from 'vue' import Vue from 'vue'
import Vuex from 'vuex' import Vuex from 'vuex'
Vue.use(Vuex); Vue.use(Vuex)
export default new Vuex.Store({ export default new Vuex.Store({
state: { state: {},
connect: false, mutations: {
message: null "<MUTATION_PREFIX><EVENT_NAME>"() {
}, // do something
mutations:{
SOCKET_CONNECT: (state, status ) => {
state.connect = true;
},
SOCKET_USER_MESSAGE: (state, message) => {
state.message = message;
} }
}, },
actions: { actions: {
otherAction: (context, type) => { "<ACTION_PREFIX><EVENT_NAME>"() {
return true; // do something
},
socket_userMessage: (context, message) => {
context.dispatch('newMessage', message);
context.commit('NEW_MESSAGE_RECEIVED', message);
if (message.is_important) {
context.dispatch('alertImportantMessage', message);
}
...
} }
} }
}) })
``` ```
## Example ## Stargazers over time
[Realtime Car Tracker System](http://metinseylan.com/)
[Simple Chat App](http://metinseylan.com/vuesocketio/) [![Stargazers over time](https://starcharts.herokuapp.com/MetinSeylan/Vue-Socket.io.svg)](https://starcharts.herokuapp.com/MetinSeylan/Vue-Socket.io)
<p align="center">
<a href="https://github.com/MetinSeylan/Vue-Socket.io" target="_blank">
<img src="https://media.giphy.com/media/11jlnltQgUi2mQ/giphy.gif">
</a>
</p>

1
dist/build.js vendored

File diff suppressed because one or more lines are too long

1
dist/build.js.map vendored

File diff suppressed because one or more lines are too long

12
dist/vue-socketio.js vendored Normal file

File diff suppressed because one or more lines are too long

114
docs/OLD_README.md Executable file
View file

@ -0,0 +1,114 @@
# Vue-Socket.io
[![NPM version](https://img.shields.io/npm/v/vue-socket.io.svg)](https://www.npmjs.com/package/vue-socket.io)
![VueJS v2 compatible](https://img.shields.io/badge/Vuejs%202-compatible-green.svg)
<a href="https://www.npmjs.com/package/vue-socket.io"><img src="https://img.shields.io/npm/dt/vue-socket.io.svg" alt="Downloads"></a>
<img id="dependency_badge" src="https://www.versioneye.com/javascript/metinseylan:vue-socket.io/2.0.1/badge.svg" alt="Dependency Badge" rel="nofollow">
<a href="https://www.npmjs.com/package/vue-socket.io"><img src="https://img.shields.io/npm/l/vue-socket.io.svg" alt="License"></a>
socket.io implementation for Vuejs 2 and Vuex
## Install
``` bash
npm install vue-socket.io --save
```
## Usage
#### Configuration
Automatic socket connection from an URL string
``` js
import VueSocketio from 'vue-socket.io';
Vue.use(VueSocketio, 'http://socketserver.com:1923');
```
Bind custom socket.io-client instance
``` js
Vue.use(VueSocketio, socketio('http://socketserver.com:1923'));
```
Enable Vuex integration
``` js
import store from './yourstore'
Vue.use(VueSocketio, socketio('http://socketserver.com:1923'), store);
```
#### On Vuejs instance usage
``` js
var vm = new Vue({
sockets:{
connect: function(){
console.log('socket connected')
},
customEmit: function(val){
console.log('this method was fired by the socket server. eg: io.emit("customEmit", data)')
}
},
methods: {
clickButton: function(val){
// $socket is socket.io-client instance
this.$socket.emit('emit_method', val);
}
}
})
```
#### Dynamic socket event listeners
Create a new listener
``` js
this.$options.sockets.event_name = (data) => {
console.log(data)
}
```
Remove existing listener
``` js
delete this.$options.sockets.event_name;
```
#### Vuex Store integration
Socket **mutations** always have `SOCKET_` prefix.
Socket **actions** always have `socket_` prefix and the socket event name is `camelCased` (ex. `SOCKET_USER_MESSAGE` => `socket_userMessage`)
You can use either one or another or both in your store. Namespaced modules are supported.
``` js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
connect: false,
message: null
},
mutations:{
SOCKET_CONNECT: (state, status ) => {
state.connect = true;
},
SOCKET_USER_MESSAGE: (state, message) => {
state.message = message;
}
},
actions: {
otherAction: (context, type) => {
return true;
},
socket_userMessage: (context, message) => {
context.dispatch('newMessage', message);
context.commit('NEW_MESSAGE_RECEIVED', message);
if (message.is_important) {
context.dispatch('alertImportantMessage', message);
}
...
}
}
})
```
## Example
[Realtime Car Tracker System](http://metinseylan.com/)
[Simple Chat App](http://metinseylan.com/vuesocketio/)

BIN
docs/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

63
index.d.ts vendored Normal file
View file

@ -0,0 +1,63 @@
import SocketIOClient from "socket.io-client";
import {
DefaultComputed,
DefaultData,
DefaultMethods,
DefaultProps,
PropsDefinition,
} from "vue/types/options";
import { Vue } from "vue/types/vue";
import { PluginFunction, PluginObject } from "vue";
import { Store } from "vuex";
interface socketHandler<T> {
(this: T, ...args: any[]): void
}
interface Sockets<V> {
[key: string]: socketHandler<V>
}
declare module 'vue/types/vue' {
interface Vue {
$socket: SocketIOClient.Socket,
sockets: {
subscribe(eventName: string, handler: socketHandler<Vue>): void,
unsubscribe(eventName: string): void,
}
}
}
declare module 'vue/types/options' {
interface ComponentOptions<
V extends Vue,
Data=DefaultData<V>,
Methods=DefaultMethods<V>,
Computed=DefaultComputed,
PropsDef=PropsDefinition<DefaultProps>,
Props=DefaultProps> {
sockets?: Sockets<V>
}
}
export interface VueSocketOptions {
debug?: boolean;
connection: string | SocketIOClient.Socket,
vuex?: {
store?: Store<any>,
actionPrefix?: string,
mutationPrefix?: string,
options?: {
useConnectionNamespace?: boolean
}
},
// type declarations for optional options
options?:{
path?: string;
}
}
export default class VueSocketIO<T> implements PluginObject<T> {
constructor (options: VueSocketOptions);
install: PluginFunction<T>
}

26
package.json Executable file → Normal file
View file

@ -1,10 +1,11 @@
{ {
"name": "vue-socket.io", "name": "vue-socket.io",
"version": "2.1.1-a", "author": "Metin Seylan <metinsyln@gmail.com>",
"description": "socket.io implemantation for vuejs and vuex", "version": "3.0.10",
"main": "dist/build.js", "description": "socket.io implementation for Vue.js and Vuex",
"main": "dist/vue-socketio.js",
"scripts": { "scripts": {
"build": "webpack --progress --hide-modules" "build": "webpack --mode=production --progress --hide-modules"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -22,19 +23,22 @@
"vuex", "vuex",
"redux" "redux"
], ],
"author": "Metin Seylan",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/MetinSeylan/Vue-Socket.io/issues" "url": "https://github.com/MetinSeylan/Vue-Socket.io/issues"
}, },
"homepage": "https://github.com/MetinSeylan/Vue-Socket.io#readme", "homepage": "https://github.com/MetinSeylan/Vue-Socket.io",
"dependencies": { "dependencies": {
"socket.io-client": "^1.4.6" "socket.io-client": "^2.1.1"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.11.4", "@babel/core": "^7.1.2",
"babel-loader": "^6.2.5", "@babel/plugin-proposal-class-properties": "^7.1.0",
"babel-preset-es2015": "^6.3.13", "@babel/plugin-transform-classes": "^7.1.0",
"webpack": "^2.2.0-rc.3" "@babel/preset-env": "^7.1.0",
"babel-loader": "^8.0.4",
"cross-env": "^5.2.0",
"webpack": "^4.23.1",
"webpack-cli": "^3.1.2"
} }
} }

View file

@ -1,49 +0,0 @@
export default new class {
constructor() {
this.listeners = new Map();
}
addListener(label, callback, vm) {
if(typeof callback == 'function'){
this.listeners.has(label) || this.listeners.set(label, []);
this.listeners.get(label).push({callback: callback, vm: vm});
return true
}
return false
}
removeListener(label, callback, vm) {
let listeners = this.listeners.get(label),
index;
if (listeners && listeners.length) {
index = listeners.reduce((i, listener, index) => {
return (typeof listener.callback == 'function' && listener.callback === callback && listener.vm == vm) ?
i = index :
i;
}, -1);
if (index > -1) {
listeners.splice(index, 1);
this.listeners.set(label, listeners);
return true;
}
}
return false;
}
emit(label, ...args) {
let listeners = this.listeners.get(label);
if (listeners && listeners.length) {
listeners.forEach((listener) => {
listener.callback.call(listener.vm,...args)
});
return true;
}
return false;
}
}

View file

@ -1,52 +0,0 @@
import Observer from './Observer'
import Emitter from './Emitter'
export default {
install(Vue, connection, store){
if(!connection) throw new Error("[Vue-Socket.io] cannot locate connection")
let observer = new Observer(connection, store)
Vue.prototype.$socket = observer.Socket;
Vue.mixin({
created(){
let sockets = this.$options['sockets']
this.$options.sockets = new Proxy({}, {
set: (target, key, value) => {
Emitter.addListener(key, value, this)
target[key] = value
return true;
},
deleteProperty: (target, key) => {
Emitter.removeListener(key, this.$options.sockets[key], this)
delete target.key;
return true
}
})
if(sockets){
Object.keys(sockets).forEach((key) => {
this.$options.sockets[key] = sockets[key];
});
}
},
beforeDestroy(){
let sockets = this.$options['sockets']
if(sockets){
Object.keys(sockets).forEach((key) => {
delete this.$options.sockets[key]
});
}
}
})
}
}

View file

@ -1,59 +0,0 @@
import Emitter from './Emitter'
import Socket from 'socket.io-client'
export default class{
constructor(connection, store) {
if(typeof connection == 'string'){
this.Socket = Socket(connection);
}else{
this.Socket = connection
}
if(store) this.store = store;
this.onEvent()
}
onEvent(){
this.Socket.onevent = (packet) => {
Emitter.emit(packet.data[0], packet.data[1]);
if(this.store) this.passToStore('SOCKET_'+packet.data[0], packet.data[1])
};
let _this = this;
["connect", "error", "disconnect", "reconnect", "reconnect_attempt", "reconnecting", "reconnect_error", "reconnect_failed", "connect_error", "connect_timeout", "connecting", "ping", "pong"]
.forEach((value) => {
_this.Socket.on(value, (data) => {
Emitter.emit(value, data);
if(_this.store) _this.passToStore('SOCKET_'+value, data)
})
})
}
passToStore(event, payload){
if(!event.startsWith('SOCKET_')) return
for(let namespaced in this.store._mutations) {
let mutation = namespaced.split('/').pop()
if(mutation === event.toUpperCase()) this.store.commit(namespaced, payload)
}
for(let namespaced in this.store._actions) {
let action = namespaced.split('/').pop()
if(!action.startsWith('socket_')) continue
let camelcased = 'socket_'+event
.replace('SOCKET_', '')
.replace(/^([A-Z])|[\W\s_]+(\w)/g, (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase())
if(action === camelcased) this.store.dispatch(namespaced, payload)
}
}
}

136
src/emitter.js Normal file
View file

@ -0,0 +1,136 @@
import Logger from './logger';
export default class EventEmitter{
constructor(vuex = {}){
Logger.info(vuex ? `Vuex adapter enabled` : `Vuex adapter disabled`);
Logger.info(vuex.mutationPrefix ? `Vuex socket mutations enabled` : `Vuex socket mutations disabled`);
Logger.info(vuex ? `Vuex socket actions enabled` : `Vuex socket actions disabled`);
this.store = vuex.store;
this.actionPrefix = vuex.actionPrefix ? vuex.actionPrefix : 'SOCKET_';
this.mutationPrefix = vuex.mutationPrefix;
this.listeners = new Map();
}
/**
* register new event listener with vuejs component instance
* @param event
* @param callback
* @param component
*/
addListener(event, callback, component){
if(typeof callback === 'function'){
if (!this.listeners.has(event)) this.listeners.set(event, []);
this.listeners.get(event).push({ callback, component });
Logger.info(`#${event} subscribe, component: ${component.$options.name}`);
} else {
throw new Error(`callback must be a function`);
}
}
/**
* remove a listenler
* @param event
* @param component
*/
removeListener(event, component){
if(this.listeners.has(event)){
const listeners = this.listeners.get(event).filter(listener => (
listener.component !== component
));
if (listeners.length > 0) {
this.listeners.set(event, listeners);
} else {
this.listeners.delete(event);
}
Logger.info(`#${event} unsubscribe, component: ${component.$options.name}`);
}
}
/**
* broadcast incoming event to components
* @param event
* @param args
*/
emit(event, args){
if(this.listeners.has(event)){
Logger.info(`Broadcasting: #${event}, Data:`, args);
this.listeners.get(event).forEach((listener) => {
listener.callback.call(listener.component, args);
});
}
if(event !== 'ping' && event !== 'pong') {
this.dispatchStore(event, args);
}
}
/**
* dispatching vuex actions
* @param event
* @param args
*/
dispatchStore(event, args){
if(this.store && this.store._actions){
let prefixed_event = this.actionPrefix + event;
for (let key in this.store._actions) {
let action = key.split('/').pop();
if(action === prefixed_event) {
Logger.info(`Dispatching Action: ${key}, Data:`, args);
this.store.dispatch(key, args);
}
}
if(this.mutationPrefix) {
let prefixed_event = this.mutationPrefix + event;
for (let key in this.store._mutations) {
let mutation = key.split('/').pop();
if(mutation === prefixed_event) {
Logger.info(`Commiting Mutation: ${key}, Data:`, args);
this.store.commit(key, args);
}
}
}
}
}
}

75
src/index.js Normal file
View file

@ -0,0 +1,75 @@
import Mixin from './mixin';
import Logger from './logger';
import Listener from './listener';
import Emitter from './emitter';
import SocketIO from 'socket.io-client';
export default class VueSocketIO {
/**
* lets take all resource
* @param io
* @param vuex
* @param debug
* @param options
*/
constructor({connection, vuex, debug, options}){
Logger.debug = debug;
this.io = this.connect(connection, options);
this.emitter = new Emitter(vuex);
this.listener = new Listener(this.io, this.emitter);
}
/**
* Vue.js entry point
* @param Vue
*/
install(Vue){
const version = Number(Vue.version.split('.')[0])
if (version >= 3) {
Vue.config.globalProperties.$socket = this.io;
Vue.config.globalProperties.$vueSocketIo = this;
} else {
Vue.prototype.$socket = this.io;
Vue.prototype.$vueSocketIo = this;
}
Vue.mixin(Mixin);
Logger.info('Vue-Socket.io plugin enabled');
}
/**
* registering SocketIO instance
* @param connection
* @param options
*/
connect(connection, options){
if(connection && typeof connection === 'object'){
Logger.info('Received socket.io-client instance');
return connection;
} else if(typeof connection === 'string'){
Logger.info('Received connection string');
return this.io = SocketIO(connection, options);
} else {
throw new Error('Unsupported connection type');
}
}
}

51
src/listener.js Normal file
View file

@ -0,0 +1,51 @@
export default class VueSocketIOListener {
/**
* socket.io-client reserved event keywords
* @type {string[]}
*/
static staticEvents = [
'connect',
'error',
'disconnect',
'reconnect',
'reconnect_attempt',
'reconnecting',
'reconnect_error',
'reconnect_failed',
'connect_error',
'connect_timeout',
'connecting',
'ping',
'pong'
];
constructor(io, emitter){
this.io = io;
this.register();
this.emitter = emitter;
}
/**
* Listening all socket.io events
*/
register(){
this.io.onevent = (packet) => {
let [event, ...args] = packet.data;
if(args.length === 1) args = args[0];
this.onEvent(event, args)
};
VueSocketIOListener.staticEvents.forEach(event => this.io.on(event, args => this.onEvent(event, args)))
}
/**
* Broadcast all events to vuejs environment
*/
onEvent(event, args){
this.emitter.emit(event, args);
}
}

35
src/logger.js Normal file
View file

@ -0,0 +1,35 @@
/**
* shitty logger class
*/
export default new class VueSocketIOLogger {
constructor() {
this.debug = false;
this.prefix = '%cVue-Socket.io: ';
}
info(text, data = '') {
if(this.debug) window.console.info(this.prefix+`%c${text}`, 'color: blue; font-weight: 600', 'color: #333333', data);
}
error() {
if(this.debug) window.console.error(this.prefix, ...arguments);
}
warn() {
if(this.debug) window.console.warn(this.prefix, ...arguments);
}
event(text, data = ''){
if(this.debug) window.console.info(this.prefix+`%c${text}`, 'color: blue; font-weight: 600', 'color: #333333', data);
}
}

56
src/mixin.js Normal file
View file

@ -0,0 +1,56 @@
export default {
/**
* Assign runtime callbacks
*/
beforeCreate(){
if(!this.sockets) this.sockets = {};
this.sockets.subscribe = (event, callback) => {
this.$vueSocketIo.emitter.addListener(event, callback, this);
};
this.sockets.unsubscribe = (event) => {
this.$vueSocketIo.emitter.removeListener(event, this);
};
},
/**
* Register all socket events
*/
mounted(){
if(this.$options.sockets){
Object.keys(this.$options.sockets).forEach(event => {
if(event !== 'subscribe' && event !== 'unsubscribe') {
this.$vueSocketIo.emitter.addListener(event, this.$options.sockets[event], this);
}
});
}
},
/**
* unsubscribe when component unmounting
*/
beforeDestroy(){
if(this.$options.sockets){
Object.keys(this.$options.sockets).forEach(event => {
this.$vueSocketIo.emitter.removeListener(event, this);
});
}
}
}

37
webpack.config.js Executable file → Normal file
View file

@ -1,31 +1,28 @@
var path = require('path');
var webpack = require('webpack');
module.exports = { module.exports = {
entry: ['./src/Main.js'], mode: process.env.NODE_ENV,
entry: ["./src/index.js"],
output: { output: {
path: path.resolve(__dirname, './dist'), library: "VueSocketIO",
filename: 'build.js', libraryTarget: "umd",
library: ['VueSocketio'], libraryExport: "default",
libraryTarget: 'umd' filename: "vue-socketio.js",
globalObject: "typeof self !== 'undefined' ? self : this"
}, },
devtool: "source-map",
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
],
module: { module: {
loaders: [ rules: [
{ {
test: /\.js$/, test: /\.js$/,
exclude: /node_modules/, exclude: /node_modules/,
loader: 'babel-loader', use: {
query: { loader: "babel-loader",
presets: ['es2015'] options: {
plugins: [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-classes"
]
}
} }
} }
] ]
} }
} };