import D from 'debug'; import io from 'socket.io-client'; import {compose} from '@avocado/core'; import {EventEmitter} from '@avocado/mixins'; import {allPackets, idFromPacket} from '../packet'; const debug = D('@avocado:client:socket'); const decorate = compose( EventEmitter, ); import Worker from 'worker-loader!./worker.js'; export class SocketClient extends decorate(class {}) { constructor(address, options = {}) { super(); this.address = address; this.isConnected = false; this.isReconnecting = false; this.options = { path: '/avocado', perMessageDeflate: false, // reconnection: false, ...options, }; this.worker = new Worker(); this.worker.onmessage = (message) => this.onWorkerMessage(message); if (false !== options.autoConnect) { this.connect(this.address, this.options); } } close() { this.worker.postMessage({ type: 'close', }); } connect(address, options) { this.worker.postMessage({ type: 'connect', payload: { address, options, }, }); for (const Packet of allPackets()) { const id = idFromPacket(Packet); this.on(`${id}`, (data) => { this.emit('packet', new Packet(data)); }); } } disconnect() { this.close(); } on(...args) { super.on(...args); this.worker.postMessage({ type: 'on', payload: args[0], }); } onWorkerMessage({data: action}) { switch (action.type) { case 'emit': return this.onWorkerMessageEmit(action.payload); case 'error': return this.onWorkerMessageError(action.payload); } } onWorkerMessageEmit(args) { this.emit(...args); } onWorkerMessageError({message}) { throw new Error(message); } send(packet) { const id = idFromPacket(packet.constructor); this.worker.postMessage({ type: 'emit', payload: [id, packet.data], }); } }