first raw dirty commit

pull/160/head
Metin Seylan 6 years ago
parent 9e6a586423
commit 991cc956d2

@ -1,114 +0,0 @@
# 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/)

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

@ -1,40 +0,0 @@
{
"name": "vue-socket.io",
"version": "2.1.1-b",
"description": "socket.io implemantation for vuejs and vuex",
"main": "dist/build.js",
"scripts": {
"build": "webpack --progress --hide-modules"
},
"repository": {
"type": "git",
"url": "git+https://github.com/MetinSeylan/Vue-Socket.io.git"
},
"keywords": [
"vuejs",
"socket",
"vue",
"socket.io",
"websocket",
"socket.io-client",
"realtime",
"flux",
"vuex",
"redux"
],
"author": "Metin Seylan",
"license": "MIT",
"bugs": {
"url": "https://github.com/MetinSeylan/Vue-Socket.io/issues"
},
"homepage": "https://github.com/MetinSeylan/Vue-Socket.io#readme",
"dependencies": {
"socket.io-client": "^2.0.0"
},
"devDependencies": {
"babel-cli": "^6.11.4",
"babel-loader": "^6.2.5",
"babel-preset-es2015": "^6.3.13",
"webpack": "^2.2.0-rc.3"
}
}

@ -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;
}
}

@ -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]
});
}
}
})
}
}

@ -1,63 +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() {
var super_onevent = this.Socket.onevent;
this.Socket.onevent = (packet) => {
super_onevent.call(this.Socket, packet);
Emitter.emit.apply(Emitter, packet.data);
if (this.store) this.passToStore('SOCKET_' + packet.data[0], [...packet.data.slice(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_', '')
.toLowerCase()
.replace(/[\W\s_]+(\w)/g, (match, p1) => p1.toUpperCase())
if (action === camelcased) this.store.dispatch(namespaced, payload)
}
}
}

@ -0,0 +1,109 @@
import Logger from './logger';
export default class EventEmitter{
constructor(vuex = {}){
Logger.info(vuex ? `Vuex adapter active` : `Vuex adapter disabled`);
this.store = vuex.store;
this.prefix = vuex.prefix ? vuex.prefix : 'SOCKET_';
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)
});
}
this.dispatchStore(event, ...args)
}
/**
* dispatching vuex actions
* @param event
* @param args
*/
dispatchStore(event, ...args){
if(this.store && this.store._actions){
for (let key in this.store._actions) {
let action = key.split('/').pop();
if(action === this.prefix+event) {
Logger.info(`Dispatching Action: ${action}, Data:`, ...args);
this.store.dispatch(action, ...args);
}
}
}
}
}

@ -0,0 +1,65 @@
import Mixin from './mixin';
import Logger from './logger';
import Listenler from './listenler';
import Emitter from './emitter';
import SocketIO from 'socket.io-client';
export default class VueSocketIO {
/**
* lets take all resource
* @param io
* @param vuex
* @param debug
*/
constructor({connection, vuex, debug}){
Logger.debug = debug;
this.io = this.connect(connection);
this.emitter = new Emitter(vuex);
this.listener = new Listenler(this.io, this.emitter);
}
/**
* Vuejs entrypoint
* @param Vue
*/
install(Vue){
Vue.prototype.$socket = this.io;
Vue.prototype.$vueSocketIo = this;
Vue.mixin(Mixin);
Logger.info('Vue-Socket.io plugin enabled');
}
/**
* registering socketio instance
* @param connection
*/
connect(connection){
if(connection && typeof connection === 'object' && connection.constructor.name === 'Socket'){
Logger.info('Received socket.io-client instance');
return connection;
} else if(typeof connection === 'string'){
Logger.info('Received connection string');
return this.io = SocketIO(connection);
} else {
throw new Error('Unsupported connection type');
}
}
}

@ -0,0 +1,45 @@
export default class VueSocketIOListenler {
/**
* 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) => this.onEvent(packet.data[0], packet.data[1]);
VueSocketIOListenler.staticEvents.forEach(event => this.io.on(event, () => this.onEvent(event)))
}
/**
* Broadcast all events to vuejs environment
*/
onEvent(event, data = {}){
this.emitter.emit(event, data);
}
}

@ -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);
}
}

@ -0,0 +1,52 @@
export default {
/**
* lets collect all socket callback functions then register
*/
created(){
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);
}
});
this.sockets = {
subscribe: (event, callback) => {
this.$vueSocketIo.emitter.addListener(event, callback, this);
},
unsubscribe: (event) => {
this.$vueSocketIo.emitter.removeListener(event, this);
}
};
}
},
/**
* unsubscribe when component unmounting
*/
beforeDestroy(){
if(this.$options.sockets){
Object.keys(this.$options.sockets).forEach(event => {
this.$vueSocketIo.emitter.removeListener(event, this);
});
}
}
}

@ -1,31 +0,0 @@
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: ['./src/Main.js'],
output: {
path: path.resolve(__dirname, './dist'),
filename: 'build.js',
library: ['VueSocketio'],
libraryTarget: 'umd'
},
devtool: "source-map",
plugins: [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
})
],
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
}
}
Loading…
Cancel
Save