1- import * as io from 'socket.io-client' ;
21import { camelCase } from 'lodash' ;
32import SocketEmitter from './emitter' ;
43import { Store } from "vuex" ;
54
6- const SYSTEM_EVENTS : Array < string > = [
7- 'connect' ,
8- 'error' ,
9- 'disconnect' ,
10- 'reconnect' ,
11- 'reconnect_attempt' ,
12- 'reconnecting' ,
13- 'reconnect_error' ,
14- 'reconnect_failed' ,
15- 'connect_error' ,
16- 'connect_timeout' ,
17- 'connecting' ,
18- 'ping' ,
19- 'pong' ,
20- ] ;
5+ const SOCKET_CONNECT = 'connect' ;
6+ const SOCKET_ERROR = 'error' ;
7+ const SOCKET_DISCONNECT = 'disconnect' ;
8+
9+ // This is defined in the wings daemon code and referenced here so that it is obvious
10+ // where we are pulling these random data objects from.
11+ type WingsWebsocketResponse = {
12+ event : string ,
13+ args : Array < string >
14+ }
2115
2216export default class SocketioConnector {
2317 /**
2418 * The socket instance.
2519 */
26- socket : null | SocketIOClient . Socket ;
20+ socket : null | WebSocket ;
2721
2822 /**
2923 * The vuex store being used to persist data and socket state.
@@ -37,21 +31,33 @@ export default class SocketioConnector {
3731
3832 /**
3933 * Initialize a new Socket connection.
40- *
41- * @param {io } socket
4234 */
43- connect ( socket : SocketIOClient . Socket ) {
44- this . socket = socket ;
35+ connect ( url : string , protocols ?: string | string [ ] ) : void {
36+ this . socket = new WebSocket ( url , protocols ) ;
4537 this . registerEventListeners ( ) ;
4638 }
4739
4840 /**
4941 * Return the socket instance we are working with.
5042 */
51- instance ( ) : SocketIOClient . Socket | null {
43+ instance ( ) : WebSocket | null {
5244 return this . socket ;
5345 }
5446
47+ /**
48+ * Sends an event along to the websocket. If there is no active connection, a void
49+ * result is returned.
50+ */
51+ emit ( event : string , payload ?: string | Array < string > ) : void | false {
52+ if ( ! this . socket ) {
53+ return false
54+ }
55+
56+ this . socket . send ( JSON . stringify ( {
57+ event, args : typeof payload === 'string' ? [ payload ] : payload
58+ } ) ) ;
59+ }
60+
5561 /**
5662 * Register the event listeners for this socket including user-defined ones in the store as
5763 * well as global system events from Socekt.io.
@@ -61,55 +67,66 @@ export default class SocketioConnector {
6167 return ;
6268 }
6369
64- // @ts -ignore
65- this . socket [ 'onevent' ] = ( packet : { data : Array < any > } ) : void => {
66- const [ event , ...args ] = packet . data ;
67- SocketEmitter . emit ( event , ...args ) ;
68-
69- this . passToStore ( event , args ) ;
70+ this . socket . onopen = ( ) => this . emitAndPassToStore ( SOCKET_CONNECT ) ;
71+ this . socket . onclose = ( ) => this . emitAndPassToStore ( SOCKET_DISCONNECT ) ;
72+ this . socket . onerror = ( ) => {
73+ // @todo reconnect?
74+ if ( this . socket && this . socket . readyState !== 1 ) {
75+ this . emitAndPassToStore ( SOCKET_ERROR , [ 'Failed to connect to websocket.' ] ) ;
76+ }
7077 } ;
7178
72- SYSTEM_EVENTS . forEach ( ( event : string ) : void => {
73- if ( ! this . socket ) {
74- return ;
75- }
79+ this . socket . onmessage = ( wse ) : void => {
80+ console . log ( 'Socket message:' , wse . data ) ;
7681
77- this . socket . on ( event , ( payload : any ) => {
78- SocketEmitter . emit ( event , payload ) ;
82+ try {
83+ let { event, args } : WingsWebsocketResponse = JSON . parse ( wse . data ) ;
7984
80- this . passToStore ( event , payload ) ;
81- } ) ;
82- } ) ;
85+ this . emitAndPassToStore ( event , args ) ;
86+ } catch ( ex ) {
87+ // do nothing, bad JSON response
88+ console . error ( ex ) ;
89+ return
90+ }
91+ } ;
92+ }
93+
94+ /**
95+ * Emits the event over the event emitter and also passes it along to the vuex store.
96+ */
97+ emitAndPassToStore ( event : string , payload ?: Array < string > ) {
98+ payload ? SocketEmitter . emit ( event , ...payload ) : SocketEmitter . emit ( event ) ;
99+ this . passToStore ( event , payload ) ;
83100 }
84101
85102 /**
86103 * Pass event calls off to the Vuex store if there is a corresponding function.
87104 */
88- passToStore ( event : string | number , payload : Array < any > ) {
105+ passToStore ( event : string , payload ? : Array < string > ) {
89106 if ( ! this . store ) {
90107 return ;
91108 }
92109
93110 const s : Store < any > = this . store ;
94- const mutation = `SOCKET_${ String ( event ) . toUpperCase ( ) } ` ;
95- const action = `socket_${ camelCase ( String ( event ) ) } ` ;
111+ const mutation = `SOCKET_${ event . toUpperCase ( ) } ` ;
112+ const action = `socket_${ camelCase ( event ) } ` ;
96113
97114 // @ts -ignore
98115 Object . keys ( this . store . _mutations ) . filter ( ( namespaced : string ) : boolean => {
99116 return namespaced . split ( '/' ) . pop ( ) === mutation ;
100117 } ) . forEach ( ( namespaced : string ) : void => {
101- s . commit ( namespaced , this . unwrap ( payload ) ) ;
118+ s . commit ( namespaced , payload ? this . unwrap ( payload ) : null ) ;
102119 } ) ;
103120
104121 // @ts -ignore
105122 Object . keys ( this . store . _actions ) . filter ( ( namespaced : string ) : boolean => {
106123 return namespaced . split ( '/' ) . pop ( ) === action ;
107124 } ) . forEach ( ( namespaced : string ) : void => {
108- s . dispatch ( namespaced , this . unwrap ( payload ) ) . catch ( console . error ) ;
125+ s . dispatch ( namespaced , payload ? this . unwrap ( payload ) : null ) . catch ( console . error ) ;
109126 } ) ;
110127 }
111128
112- unwrap ( args : Array < any > ) {
129+ unwrap ( args : Array < string > ) {
113130 return ( args && args . length <= 1 ) ? args [ 0 ] : args ;
114131 }
115132}
0 commit comments