/**
 * WebSocket connection setup.
 */ import * as proto from './proto' ; const TRACE_MESSAGES = true ; /** Prints a proto-encoded message. */ function printMessage ( prefix , msg ) { if ( 'tag' in msg ) { printMessage ( `${ prefix }tag(${ msg . tag }):` , msg . val ) ; return ; } console . groupCollapsed ( `${ prefix }` ) ; for ( const field in msg ) { const val = msg [ field ] ; if ( typeof val === 'object' && ! Array . isArray ( val ) ) { printMessage ( `${ field }: ` , val ) ; } else { console . info ( `${ field }:` , val ) ; } } console . groupEnd ( ) ; } /** Parses a WebSocket MessageEvent as a server-sent message. */ function parseMessage ( event ) { return new proto . Reader ( new DataView ( event . data ) ) . readServerMsg ( ) ; } /** Promisifies WebSocket connection. */ function connect ( ws ) { return new Promise ( ( res , rej ) => { ws . onopen = ( ) => { res ( ) ; } ; ws . onerror = ( ) => { rej ( `websocket connection failed` ) ; } ; } ) ; } async function read ( ws ) { return new Promise ( ( res , rej ) => { ws . onmessage = ( event ) => { res ( parseMessage ( event ) ) ; } ; ws . onclose = ( event ) => { let msg = 'connection closed' ; if ( event . reason ) msg += `: ${ event . reason }` ; rej ( msg ) ; } ; ws . onerror = ( ) => { rej ( `websocket connection failed` ) ; } ; } ) ; } export class ServerConnection { ws ! : WebSocket ; /**
     * Opens the connection to the server.
     */ async connect ( ) { const url = new URL ( '/ws' , window . location . href ) ; url . protocol = url . protocol . replace ( 'http' , 'ws' ) ; const ws = new WebSocket ( url . href ) ; ws . binaryType = 'arraybuffer' ; await connect ( ws ) ; ws . onopen = ( event ) => { console . error ( `unexpected ws open:` , event ) ; } ; this . ws = ws ; const msg = await read ( ws ) ; if ( msg . tag !== 'Hello' ) { throw new Error ( `expected hello message, got ${ msg }` ) ; } return msg . val ; } async read ( ) { const msg = await read ( this . ws ) ; if ( TRACE_MESSAGES ) printMessage ( 'read: ' , msg ) ; return msg ; } send ( msg ) { if ( TRACE_MESSAGES ) printMessage ( 'send: ' , msg ) ; const writer = new proto . Writer ( ) ; writer . writeClientMessage ( msg ) ; writer . buf = new Uint8Array ( writer . ofs ) ; writer . ofs = 0 ; writer . writeClientMessage ( msg ) ; this . ws . send ( writer . buf ) ; } }