export function websocket_api(hub, plugin_options) :: let _ws_on_data = ab => new Uint8Array(ab) let _ws_on_err = err => null return @{} connectWS(ws_or_wss_url, channel_id) :: let websock = ws_or_wss_url.send ? ws_or_wss_url : this.createWS(ws_or_wss_url) if undefined === websock :: throw new TypeError @ `Invalid websocket connection` if null == channel_id :: channel_id = 'websocket' let channel = this.createWSChannel(websock, {channel_id}) return channel.init() createWSChannel(websock, options) :: let channel = this.createStreamChannel @ websock, @{} subscribe: _on_ws_msg_evt ... options Object.defineProperty @ channel, 'websock', {value: websock} return Object.assign @ channel, @{} when_opened: new Promise @ resolve => :: websock.addEventListener @ 'open' @=> resolve() @{} passive: true, once: true when_closed: new Promise @ resolve => :: websock.addEventListener @ 'close' @=> resolve() @{} passive: true, once: true get ready() :: return new Promise @ (resolve, reject) => :: switch (websock.readyState) :: case 0: // connecting state this.when_opened.then @=> resolve(true) this.when_closed.then @=> resolve(false) return case 1: return resolve(true) default: return resolve(false) WebSocket: plugin_options.WebSocket createWS(ws_or_wss_url) :: let _WebSocket = this.WebSocket || WebSocket return new _WebSocket @ ws_or_wss_url+'', plugin_options.protocols function _on_ws_msg_evt(tgt_recv, fn_recv_pkt, fn_accept) :: tgt_recv.addEventListener @ 'message', async evt => :: if true === fn_accept(evt) :: let data = evt.data if data && 'function' === typeof data.arrayBuffer :: // received blob data = await data.arrayBuffer() .then @ _ws_on_data, _ws_on_err if data :: return fn_recv_pkt(data, evt) @{} passive: true