format import EventEmitter from 'eventemitter3' ; import { FlipperServer } from 'flipper-common' ; import { io , Socket } from 'socket.io-client' ; const CONNECTION_TIMEOUT = 30 * 1000 ; const EXEC_TIMOUT = 30 * 1000 ; export function createFlipperServer ( ) { window . flipperShowError ?. ( 'Connecting to server...' ) ; return new Promise < FlipperServer > ( ( resolve , reject ) => { const initialConnectionTimeout = setTimeout ( ( ) => { reject ( new Error ( 'Failed to connect to Flipper server in a timely manner' ) ) ; } , CONNECTION_TIMEOUT ) ; const eventEmitter = new EventEmitter ( ) ; const socket = io ( ) ; const pendingRequests = new Map ( ) ; let requestId = 0 ; let connected = false ; socket . on ( 'connect' , ( ) => { window ?. flipperHideError ?. ( ) ; console . log ( 'Socket to Flipper server connected' ) ; connected = true ; } ) ; socket . once ( 'connect' , ( ) => { resolve ( flipperServer ) ; clearTimeout ( initialConnectionTimeout ) ; } ) ; socket . on ( 'disconnect' , ( ) => { window ?. flipperShowError ?. ( 'WebSocket connection lost' ) ; console . warn ( 'Socket to Flipper server disconnected' ) ; connected = false ; pendingRequests . forEach ( ( r ) => r . reject ( new Error ( 'FLIPPER_SERVER_SOCKET_CONNECT_LOST' ) ) ) ; pendingRequests . clear ( ) ; } ) ; socket . on ( 'exec-response' , ( id , data ) => { console . debug ( 'exec <<<' , id , data ) ; const entry = pendingRequests . get ( id ) ; if ( ! entry ) { console . warn ( `Unknown request id ` , id ) ; } else { pendingRequests . delete ( id ) ; clearTimeout ( entry . timeout ) ; entry . resolve ( data ) ; } } ) ; socket . on ( 'exec-response-error' , ( id , error ) => { console . debug ( 'exec <<< [SERVER ERROR]' , id , error ) ; const entry = pendingRequests . get ( id ) ; if ( ! entry ) { console . warn ( `Unknown request id ` , id ) ; } else { pendingRequests . delete ( id ) ; clearTimeout ( entry . timeout ) ; entry . reject ( error ) ; } } ) ; socket . on ( 'event' , ( eventType , data ) => { eventEmitter . emit ( eventType , data ) ; } ) ; const flipperServer = { async connect ( ) { } , close ( ) { } , exec ( command , ... args ) { if ( connected ) { const id = ++ requestId ; return new Promise < any > ( ( resolve , reject ) => { console . debug ( 'exec >>>' , id , command , args ) ; pendingRequests . set ( id , { resolve , reject , timeout : setInterval ( ( ) => { pendingRequests . delete ( id ) ; reject ( new Error ( `Timeout for command '${ command }'` ) ) ; } , EXEC_TIMOUT ) , } ) ; socket . emit ( 'exec' , id , command , args ) ; } ) ; } else { throw new Error ( 'Not connected to Flipper Server' ) ; } } , on ( event , callback ) { eventEmitter . on ( event , callback ) ; } , off ( event , callback ) { eventEmitter . off ( event , callback ) ; } , } ; } ) ; }