import WebSocket from "ws" ; import { Client , IClientData , EventListener , IMessagePack , ClientEvent } from "../../internal" ; export interface IWebSocketClientData extends IClientData { ref : WebSocket ; messagePack : IMessagePack ; requestTimeout ? : number ; } interface IResponse { resolve : any ; reject : any ; timer : NodeJS . Timer ; } export class WebSocketClient extends Client { public ws : WebSocket ; public messagePack : IMessagePack ; public pingCount : number = 0 ; public listners : { [ type ] : EventListener [ ] ; } = { } ; public requestTimeout : number ; public lastResponseId : number = 0 ; public responses : { [ id ] : IResponse ; } = { } ; constructor ( clientData ) { super ( clientData ) ; this . ws = clientData . ref ; this . messagePack = clientData . messagePack ; this . requestTimeout = clientData . requestTimeout || 1000 ; this . ws . on ( "message" , ( buf ) => { const event = buf [ 0 ] ; const args = this . messagePack . decode < any [ ] > ( buf . slice ( 1 ) ) ; if ( event === ClientEvent . response ) { const [ id , err , data ] = args ; const response = this . responses [ id ] ; if ( response ) { clearTimeout ( response . timer ) ; if ( err ) { console . debug ( "REJECT: response error" ) ; response . reject ( err ) ; } else { response . resolve ( data ) ; } } } else if ( event ) { const listners = this . listners [ event ] || [ ] ; listners . forEach ( ( ( listener ) => listener ( ... args ) ) ) ; } } ) ; } public async request ( type , data ) { return new Promise ( ( resolve , reject ) => { const id = this . lastResponseId ++ ; const timer = setTimeout ( ( ) => reject ( "Request timeout" ) , 1000 ) ; this . responses [ id ] = { resolve , reject , timer } ; this . emit ( ClientEvent . request , type , data , id ) ; } ) ; } public on ( event , listner ) { if ( ! this . listners [ event ] ) { this . listners [ event ] = [ ] ; } this . listners [ event ] . push ( listner ) ; } public emit ( event , ... args ) { if ( event === ClientEvent . encodedPatch && args [ 0 ] instanceof Buffer ) { this . ws . send ( Buffer . concat ( [ Buffer . from ( [ event ] ) , args [ 0 ] ] ) ) ; } else { const pack = this . messagePack . encode ( args ) ; this . ws . send ( Buffer . concat ( [ Buffer . from ( [ event ] ) , pack ] ) ) ; } } public terminate ( code , reason ) { this . ws . close ( code , reason ) ; } }