All files client.ts

62.75% Statements 32/51
47.5% Branches 19/40
38.46% Functions 5/13
63.27% Lines 31/49

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 1271x   1x   1x 1x   1x 1x 1x 1x   44x 44x 44x                   44x   44x 44x 22x 22x   22x                                                                               56x         56x       56x       56x       14x 14x     14x       14x       14x             2x 2x         12x 12x 12x                      
import { WebSocketServer } from './server';
import { SocketAddress, ServerConfigs } from './index';
import { native, setupNative, noop, DEFAULT_PAYLOAD_LIMIT, OPCODE_PING, OPCODE_BINARY, OPCODE_TEXT } from './shared';
 
const clientGroup: any = native.client.group.create(0, DEFAULT_PAYLOAD_LIMIT);
setupNative(clientGroup, 'client');
 
export class WebSocket {
  public static OPEN: number = 1;
  public static CLOSED: number = 3;
  public static Server: new (options: ServerConfigs, cb?: () => void) => WebSocketServer = WebSocketServer;
 
  public OPEN: number = WebSocket.OPEN;
  public CLOSED: number = WebSocket.OPEN;
  public registeredEvents: any = {
    open: noop,
    ping: noop,
    pong: noop,
    error: noop,
    close: noop,
    message: noop
  };
 
  private external: any;
  private socketType: string = 'client';
 
  constructor(public url: string, private options: any = {}) {
    if (!this.url && (this.options as any).external) {
      this.socketType = 'server';
      this.external = (this.options as any).external;
    } else {
      native.connect(clientGroup, url, this);
    }
  }
 
  public get _socket(): SocketAddress {
    const address: any[] = this.external ? native.getAddress(this.external) : new Array(3);
    return {
      remotePort: address[0],
      remoteAddress: address[1],
      remoteFamily: address[2]
    };
  }
 
  public get readyState(): number {
    return this.external ? this.OPEN : this.CLOSED;
  }
 
  public set onopen(listener: () => void) {
    this.on('open', listener);
  }
 
  public set onclose(listener: (code?: number, reason?: string) => void) {
    this.on('close', listener);
  }
 
  public set onerror(listener: (err: Error) => void) {
    this.on('error', listener);
  }
 
  public set onmessage(listener: (message: string | any) => void) {
    this.on('message', listener);
  }
 
  public on(event: 'open', listener: () => void): void;
  public on(event: 'ping', listener: () => void): void;
  public on(event: 'pong', listener: () => void): void;
  public on(event: 'error', listener: (err: Error) => void): void;
  public on(event: 'message', listener: (message: string | any) => void): void;
  public on(event: 'close', listener: (code?: number, reason?: string) => void): void;
  public on(event: string, listener: (...args: any[]) => void): void {
    Iif (this.registeredEvents[event] === undefined) {
      console.warn(`cWS does not support '${event}' event`);
      return;
    }
 
    Iif (typeof listener !== 'function') {
      throw new Error(`Listener for '${event}' event must be a function`);
    }
 
    Iif (this.registeredEvents[event] !== noop) {
      console.warn(`cWS does not support multiple listeners for the same event. Old listener for '${event}' event will be overwritten`);
    }
 
    this.registeredEvents[event] = listener;
  }
 
  public send(message: string | Buffer, options?: { binary?: boolean, compress?: boolean }, cb?: (err?: Error) => void): void {
    Eif (this.external) {
      let opCode: number = typeof message === 'string' ? OPCODE_TEXT : OPCODE_BINARY;
 
      // provided options should always overwrite default
      Iif (options && options.binary === false) {
        opCode = OPCODE_TEXT;
      }
 
      Iif (options && options.binary === true) {
        opCode = OPCODE_BINARY;
      }
 
      native[this.socketType].send(this.external, message, opCode, cb ? (): void => process.nextTick(cb) : null, options && options.compress);
    } else if (cb) {
      cb(new Error('Socket not connected'));
    }
  }
 
  public ping(message?: string | Buffer): void {
    Eif (this.external) {
      native[this.socketType].send(this.external, message, OPCODE_PING);
    }
  }
 
  public close(code: number = 1000, reason?: string): void {
    Eif (this.external) {
      native[this.socketType].close(this.external, code, reason);
      this.external = null;
    }
  }
 
  public terminate(): void {
    if (this.external) {
      native[this.socketType].terminate(this.external);
      this.external = null;
    }
  }
}