import WebSocket from 'ws' /* Example config config = { hostname: 'localhost', port: 1338, connectstring: `ws://localhost:1338/ws`, } */ class EvtBus { constructor() { this._on = {} } on(type, callback) { this._on[type] = this._on[type] || [] this._on[type].push(callback) } dispatch(type, ...args) { (this._on[type] || []).forEach(cb => { cb(...args) }) } } class WebSocketServer { constructor(config) { this.config = config this._websocketserver = null this._interval = null this.evt = new EvtBus() } on(type, callback) { this.evt.on(type, callback) } listen() { this._websocketserver = new WebSocket.Server(this.config) this._websocketserver.on('connection', (socket, request, client) => { const pathname = new URL(this.config.connectstring).pathname if (request.url.indexOf(pathname) !== 0) { console.log('bad request url: ', request.url) socket.close() return } socket.isAlive = true socket.on('pong', function () { this.isAlive = true; }) socket.on('message', (data) => { console.log(`ws| `, data) this.evt.dispatch('message', {socket, data}) }) }) this._interval = setInterval(() => { this._websocketserver.clients.forEach((socket) => { if (socket.isAlive === false) { return socket.terminate() } socket.isAlive = false socket.ping(() => { }) }) }, 30000) this._websocketserver.on('close', () => { clearInterval(this._interval) }) } notifyOne(data, socket) { if (socket.isAlive) { socket.send(JSON.stringify(data)) } } notifyAll(data) { this._websocketserver.clients.forEach((socket) => { this.notifyOne(data, socket) }) } } export default WebSocketServer