text: (function webpackUniversalModuleDefinition(root, factory) {
  	if(typeof exports === 'object' && typeof module === 'object')
  		module.exports = factory(require("@aws-amplify/auth"), require("@aws-amplify/cache"), require("@aws-amplify/core"), require("graphql"));
  	else if(typeof define === 'function' && define.amd)
  		define("aws_amplify_pubsub", ["@aws-amplify/auth", "@aws-amplify/cache", "@aws-amplify/core", "graphql"], factory);
  	else if(typeof exports === 'object')
  		exports["aws_amplify_pubsub"] = factory(require("@aws-amplify/auth"), require("@aws-amplify/cache"), require("@aws-amplify/core"), require("graphql"));
  	else
  		root["aws_amplify_pubsub"] = factory(root["@aws-amplify/auth"], root["@aws-amplify/cache"], root["@aws-amplify/core"], root["graphql"]);
  })(this, function(__WEBPACK_EXTERNAL_MODULE__aws_amplify_auth__, __WEBPACK_EXTERNAL_MODULE__aws_amplify_cache__, __WEBPACK_EXTERNAL_MODULE__aws_amplify_core__, __WEBPACK_EXTERNAL_MODULE_graphql__) {
  return /******/ (function(modules) { // webpackBootstrap
  /******/ 	// The module cache
  /******/ 	var installedModules = {};
  /******/
  /******/ 	// The require function
  /******/ 	function __webpack_require__(moduleId) {
  /******/
  /******/ 		// Check if module is in cache
  /******/ 		if(installedModules[moduleId]) {
  /******/ 			return installedModules[moduleId].exports;
  /******/ 		}
  /******/ 		// Create a new module (and put it into the cache)
  /******/ 		var module = installedModules[moduleId] = {
  /******/ 			i: moduleId,
  /******/ 			l: false,
  /******/ 			exports: {}
  /******/ 		};
  /******/
  /******/ 		// Execute the module function
  /******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  /******/
  /******/ 		// Flag the module as loaded
  /******/ 		module.l = true;
  /******/
  /******/ 		// Return the exports of the module
  /******/ 		return module.exports;
  /******/ 	}
  /******/
  /******/
  /******/ 	// expose the modules object (__webpack_modules__)
  /******/ 	__webpack_require__.m = modules;
  /******/
  /******/ 	// expose the module cache
  /******/ 	__webpack_require__.c = installedModules;
  /******/
  /******/ 	// define getter function for harmony exports
  /******/ 	__webpack_require__.d = function(exports, name, getter) {
  /******/ 		if(!__webpack_require__.o(exports, name)) {
  /******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
  /******/ 		}
  /******/ 	};
  /******/
  /******/ 	// define __esModule on exports
  /******/ 	__webpack_require__.r = function(exports) {
  /******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  /******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
  /******/ 		}
  /******/ 		Object.defineProperty(exports, '__esModule', { value: true });
  /******/ 	};
  /******/
  /******/ 	// create a fake namespace object
  /******/ 	// mode & 1: value is a module id, require it
  /******/ 	// mode & 2: merge all properties of value into the ns
  /******/ 	// mode & 4: return value when already ns object
  /******/ 	// mode & 8|1: behave like require
  /******/ 	__webpack_require__.t = function(value, mode) {
  /******/ 		if(mode & 1) value = __webpack_require__(value);
  /******/ 		if(mode & 8) return value;
  /******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  /******/ 		var ns = Object.create(null);
  /******/ 		__webpack_require__.r(ns);
  /******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
  /******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
  /******/ 		return ns;
  /******/ 	};
  /******/
  /******/ 	// getDefaultExport function for compatibility with non-harmony modules
  /******/ 	__webpack_require__.n = function(module) {
  /******/ 		var getter = module && module.__esModule ?
  /******/ 			function getDefault() { return module['default']; } :
  /******/ 			function getModuleExports() { return module; };
  /******/ 		__webpack_require__.d(getter, 'a', getter);
  /******/ 		return getter;
  /******/ 	};
  /******/
  /******/ 	// Object.prototype.hasOwnProperty.call
  /******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
  /******/
  /******/ 	// __webpack_public_path__
  /******/ 	__webpack_require__.p = "";
  /******/
  /******/
  /******/ 	// Load entry module and return exports
  /******/ 	return __webpack_require__(__webpack_require__.s = "./lib-esm/index.js");
  /******/ })
  /************************************************************************/
  /******/ ({
  
  /***/ "../../node_modules/base64-js/index.js":
  /*!********************************************************!*\
    !*** /root/amplify-js/node_modules/base64-js/index.js ***!
    \********************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.byteLength = byteLength
  exports.toByteArray = toByteArray
  exports.fromByteArray = fromByteArray
  
  var lookup = []
  var revLookup = []
  var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
  
  var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
  for (var i = 0, len = code.length; i < len; ++i) {
    lookup[i] = code[i]
    revLookup[code.charCodeAt(i)] = i
  }
  
  // Support decoding URL-safe base64 strings, as Node.js does.
  // See: https://en.wikipedia.org/wiki/Base64#URL_applications
  revLookup['-'.charCodeAt(0)] = 62
  revLookup['_'.charCodeAt(0)] = 63
  
  function getLens (b64) {
    var len = b64.length
  
    if (len % 4 > 0) {
      throw new Error('Invalid string. Length must be a multiple of 4')
    }
  
    // Trim off extra bytes after placeholder bytes are found
    // See: https://github.com/beatgammit/base64-js/issues/42
    var validLen = b64.indexOf('=')
    if (validLen === -1) validLen = len
  
    var placeHoldersLen = validLen === len
      ? 0
      : 4 - (validLen % 4)
  
    return [validLen, placeHoldersLen]
  }
  
  // base64 is 4/3 + up to two characters of the original data
  function byteLength (b64) {
    var lens = getLens(b64)
    var validLen = lens[0]
    var placeHoldersLen = lens[1]
    return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
  }
  
  function _byteLength (b64, validLen, placeHoldersLen) {
    return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen
  }
  
  function toByteArray (b64) {
    var tmp
    var lens = getLens(b64)
    var validLen = lens[0]
    var placeHoldersLen = lens[1]
  
    var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))
  
    var curByte = 0
  
    // if there are placeholders, only get up to the last complete 4 chars
    var len = placeHoldersLen > 0
      ? validLen - 4
      : validLen
  
    var i
    for (i = 0; i < len; i += 4) {
      tmp =
        (revLookup[b64.charCodeAt(i)] << 18) |
        (revLookup[b64.charCodeAt(i + 1)] << 12) |
        (revLookup[b64.charCodeAt(i + 2)] << 6) |
        revLookup[b64.charCodeAt(i + 3)]
      arr[curByte++] = (tmp >> 16) & 0xFF
      arr[curByte++] = (tmp >> 8) & 0xFF
      arr[curByte++] = tmp & 0xFF
    }
  
    if (placeHoldersLen === 2) {
      tmp =
        (revLookup[b64.charCodeAt(i)] << 2) |
        (revLookup[b64.charCodeAt(i + 1)] >> 4)
      arr[curByte++] = tmp & 0xFF
    }
  
    if (placeHoldersLen === 1) {
      tmp =
        (revLookup[b64.charCodeAt(i)] << 10) |
        (revLookup[b64.charCodeAt(i + 1)] << 4) |
        (revLookup[b64.charCodeAt(i + 2)] >> 2)
      arr[curByte++] = (tmp >> 8) & 0xFF
      arr[curByte++] = tmp & 0xFF
    }
  
    return arr
  }
  
  function tripletToBase64 (num) {
    return lookup[num >> 18 & 0x3F] +
      lookup[num >> 12 & 0x3F] +
      lookup[num >> 6 & 0x3F] +
      lookup[num & 0x3F]
  }
  
  function encodeChunk (uint8, start, end) {
    var tmp
    var output = []
    for (var i = start; i < end; i += 3) {
      tmp =
        ((uint8[i] << 16) & 0xFF0000) +
        ((uint8[i + 1] << 8) & 0xFF00) +
        (uint8[i + 2] & 0xFF)
      output.push(tripletToBase64(tmp))
    }
    return output.join('')
  }
  
  function fromByteArray (uint8) {
    var tmp
    var len = uint8.length
    var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
    var parts = []
    var maxChunkLength = 16383 // must be multiple of 3
  
    // go through the array every three bytes, we'll deal with trailing stuff later
    for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
      parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
    }
  
    // pad the end with zeros, but make sure to not forget the extra bytes
    if (extraBytes === 1) {
      tmp = uint8[len - 1]
      parts.push(
        lookup[tmp >> 2] +
        lookup[(tmp << 4) & 0x3F] +
        '=='
      )
    } else if (extraBytes === 2) {
      tmp = (uint8[len - 2] << 8) + uint8[len - 1]
      parts.push(
        lookup[tmp >> 10] +
        lookup[(tmp >> 4) & 0x3F] +
        lookup[(tmp << 2) & 0x3F] +
        '='
      )
    }
  
    return parts.join('')
  }
  
  
  /***/ }),
  
  /***/ "../../node_modules/buffer/index.js":
  /*!*****************************************************!*\
    !*** /root/amplify-js/node_modules/buffer/index.js ***!
    \*****************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  /* WEBPACK VAR INJECTION */(function(global) {/*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <http://feross.org>
   * @license  MIT
   */
  /* eslint-disable no-proto */
  
  
  
  var base64 = __webpack_require__(/*! base64-js */ "../../node_modules/base64-js/index.js")
  var ieee754 = __webpack_require__(/*! ieee754 */ "../../node_modules/ieee754/index.js")
  var isArray = __webpack_require__(/*! isarray */ "../../node_modules/isarray/index.js")
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Due to various browser bugs, sometimes the Object implementation will be used even
   * when the browser supports typed arrays.
   *
   * Note:
   *
   *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
   *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *     incorrect length in some situations.
  
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
   * get the Object implementation, which is slower but behaves correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
    ? global.TYPED_ARRAY_SUPPORT
    : typedArraySupport()
  
  /*
   * Export kMaxLength after typed array support is determined.
   */
  exports.kMaxLength = kMaxLength()
  
  function typedArraySupport () {
    try {
      var arr = new Uint8Array(1)
      arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}
      return arr.foo() === 42 && // typed array instances can be augmented
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  }
  
  function kMaxLength () {
    return Buffer.TYPED_ARRAY_SUPPORT
      ? 0x7fffffff
      : 0x3fffffff
  }
  
  function createBuffer (that, length) {
    if (kMaxLength() < length) {
      throw new RangeError('Invalid typed array length')
    }
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = new Uint8Array(length)
      that.__proto__ = Buffer.prototype
    } else {
      // Fallback: Return an object instance of the Buffer class
      if (that === null) {
        that = new Buffer(length)
      }
      that.length = length
    }
  
    return that
  }
  
  /**
   * The Buffer constructor returns instances of `Uint8Array` that have their
   * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of
   * `Uint8Array`, so the returned instances will have all the node `Buffer` methods
   * and the `Uint8Array` methods. Square bracket notation works as expected -- it
   * returns a single octet.
   *
   * The `Uint8Array` prototype remains unmodified.
   */
  
  function Buffer (arg, encodingOrOffset, length) {
    if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) {
      return new Buffer(arg, encodingOrOffset, length)
    }
  
    // Common case.
    if (typeof arg === 'number') {
      if (typeof encodingOrOffset === 'string') {
        throw new Error(
          'If encoding is specified then the first argument must be a string'
        )
      }
      return allocUnsafe(this, arg)
    }
    return from(this, arg, encodingOrOffset, length)
  }
  
  Buffer.poolSize = 8192 // not used by this implementation
  
  // TODO: Legacy, not needed anymore. Remove in next major version.
  Buffer._augment = function (arr) {
    arr.__proto__ = Buffer.prototype
    return arr
  }
  
  function from (that, value, encodingOrOffset, length) {
    if (typeof value === 'number') {
      throw new TypeError('"value" argument must not be a number')
    }
  
    if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) {
      return fromArrayBuffer(that, value, encodingOrOffset, length)
    }
  
    if (typeof value === 'string') {
      return fromString(that, value, encodingOrOffset)
    }
  
    return fromObject(that, value)
  }
  
  /**
   * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError
   * if value is a number.
   * Buffer.from(str[, encoding])
   * Buffer.from(array)
   * Buffer.from(buffer)
   * Buffer.from(arrayBuffer[, byteOffset[, length]])
   **/
  Buffer.from = function (value, encodingOrOffset, length) {
    return from(null, value, encodingOrOffset, length)
  }
  
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    Buffer.prototype.__proto__ = Uint8Array.prototype
    Buffer.__proto__ = Uint8Array
    if (typeof Symbol !== 'undefined' && Symbol.species &&
        Buffer[Symbol.species] === Buffer) {
      // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97
      Object.defineProperty(Buffer, Symbol.species, {
        value: null,
        configurable: true
      })
    }
  }
  
  function assertSize (size) {
    if (typeof size !== 'number') {
      throw new TypeError('"size" argument must be a number')
    } else if (size < 0) {
      throw new RangeError('"size" argument must not be negative')
    }
  }
  
  function alloc (that, size, fill, encoding) {
    assertSize(size)
    if (size <= 0) {
      return createBuffer(that, size)
    }
    if (fill !== undefined) {
      // Only pay attention to encoding if it's a string. This
      // prevents accidentally sending in a number that would
      // be interpretted as a start offset.
      return typeof encoding === 'string'
        ? createBuffer(that, size).fill(fill, encoding)
        : createBuffer(that, size).fill(fill)
    }
    return createBuffer(that, size)
  }
  
  /**
   * Creates a new filled Buffer instance.
   * alloc(size[, fill[, encoding]])
   **/
  Buffer.alloc = function (size, fill, encoding) {
    return alloc(null, size, fill, encoding)
  }
  
  function allocUnsafe (that, size) {
    assertSize(size)
    that = createBuffer(that, size < 0 ? 0 : checked(size) | 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < size; ++i) {
        that[i] = 0
      }
    }
    return that
  }
  
  /**
   * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance.
   * */
  Buffer.allocUnsafe = function (size) {
    return allocUnsafe(null, size)
  }
  /**
   * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance.
   */
  Buffer.allocUnsafeSlow = function (size) {
    return allocUnsafe(null, size)
  }
  
  function fromString (that, string, encoding) {
    if (typeof encoding !== 'string' || encoding === '') {
      encoding = 'utf8'
    }
  
    if (!Buffer.isEncoding(encoding)) {
      throw new TypeError('"encoding" must be a valid string encoding')
    }
  
    var length = byteLength(string, encoding) | 0
    that = createBuffer(that, length)
  
    var actual = that.write(string, encoding)
  
    if (actual !== length) {
      // Writing a hex string, for example, that contains invalid characters will
      // cause everything after the first invalid character to be ignored. (e.g.
      // 'abxxcd' will be treated as 'ab')
      that = that.slice(0, actual)
    }
  
    return that
  }
  
  function fromArrayLike (that, array) {
    var length = array.length < 0 ? 0 : checked(array.length) | 0
    that = createBuffer(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  function fromArrayBuffer (that, array, byteOffset, length) {
    array.byteLength // this throws if `array` is not a valid ArrayBuffer
  
    if (byteOffset < 0 || array.byteLength < byteOffset) {
      throw new RangeError('\'offset\' is out of bounds')
    }
  
    if (array.byteLength < byteOffset + (length || 0)) {
      throw new RangeError('\'length\' is out of bounds')
    }
  
    if (byteOffset === undefined && length === undefined) {
      array = new Uint8Array(array)
    } else if (length === undefined) {
      array = new Uint8Array(array, byteOffset)
    } else {
      array = new Uint8Array(array, byteOffset, length)
    }
  
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = array
      that.__proto__ = Buffer.prototype
    } else {
      // Fallback: Return an object instance of the Buffer class
      that = fromArrayLike(that, array)
    }
    return that
  }
  
  function fromObject (that, obj) {
    if (Buffer.isBuffer(obj)) {
      var len = checked(obj.length) | 0
      that = createBuffer(that, len)
  
      if (that.length === 0) {
        return that
      }
  
      obj.copy(that, 0, 0, len)
      return that
    }
  
    if (obj) {
      if ((typeof ArrayBuffer !== 'undefined' &&
          obj.buffer instanceof ArrayBuffer) || 'length' in obj) {
        if (typeof obj.length !== 'number' || isnan(obj.length)) {
          return createBuffer(that, 0)
        }
        return fromArrayLike(that, obj)
      }
  
      if (obj.type === 'Buffer' && isArray(obj.data)) {
        return fromArrayLike(that, obj.data)
      }
    }
  
    throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.')
  }
  
  function checked (length) {
    // Note: cannot use `length < kMaxLength()` here because that fails when
    // length is NaN (which is otherwise coerced to zero.)
    if (length >= kMaxLength()) {
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                           'size: 0x' + kMaxLength().toString(16) + ' bytes')
    }
    return length | 0
  }
  
  function SlowBuffer (length) {
    if (+length != length) { // eslint-disable-line eqeqeq
      length = 0
    }
    return Buffer.alloc(+length)
  }
  
  Buffer.isBuffer = function isBuffer (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function compare (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
      throw new TypeError('Arguments must be Buffers')
    }
  
    if (a === b) return 0
  
    var x = a.length
    var y = b.length
  
    for (var i = 0, len = Math.min(x, y); i < len; ++i) {
      if (a[i] !== b[i]) {
        x = a[i]
        y = b[i]
        break
      }
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function isEncoding (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'latin1':
      case 'binary':
      case 'base64':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function concat (list, length) {
    if (!isArray(list)) {
      throw new TypeError('"list" argument must be an Array of Buffers')
    }
  
    if (list.length === 0) {
      return Buffer.alloc(0)
    }
  
    var i
    if (length === undefined) {
      length = 0
      for (i = 0; i < list.length; ++i) {
        length += list[i].length
      }
    }
  
    var buffer = Buffer.allocUnsafe(length)
    var pos = 0
    for (i = 0; i < list.length; ++i) {
      var buf = list[i]
      if (!Buffer.isBuffer(buf)) {
        throw new TypeError('"list" argument must be an Array of Buffers')
      }
      buf.copy(buffer, pos)
      pos += buf.length
    }
    return buffer
  }
  
  function byteLength (string, encoding) {
    if (Buffer.isBuffer(string)) {
      return string.length
    }
    if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' &&
        (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) {
      return string.byteLength
    }
    if (typeof string !== 'string') {
      string = '' + string
    }
  
    var len = string.length
    if (len === 0) return 0
  
    // Use a for loop to avoid recursion
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'ascii':
        case 'latin1':
        case 'binary':
          return len
        case 'utf8':
        case 'utf-8':
        case undefined:
          return utf8ToBytes(string).length
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return len * 2
        case 'hex':
          return len >>> 1
        case 'base64':
          return base64ToBytes(string).length
        default:
          if (loweredCase) return utf8ToBytes(string).length // assume utf8
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  Buffer.byteLength = byteLength
  
  function slowToString (encoding, start, end) {
    var loweredCase = false
  
    // No need to verify that "this.length <= MAX_UINT32" since it's a read-only
    // property of a typed array.
  
    // This behaves neither like String nor Uint8Array in that we set start/end
    // to their upper/lower bounds if the value passed is out of range.
    // undefined is handled specially as per ECMA-262 6th Edition,
    // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization.
    if (start === undefined || start < 0) {
      start = 0
    }
    // Return early if start > this.length. Done here to prevent potential uint32
    // coercion fail below.
    if (start > this.length) {
      return ''
    }
  
    if (end === undefined || end > this.length) {
      end = this.length
    }
  
    if (end <= 0) {
      return ''
    }
  
    // Force coersion to uint32. This will also coerce falsey/NaN values to 0.
    end >>>= 0
    start >>>= 0
  
    if (end <= start) {
      return ''
    }
  
    if (!encoding) encoding = 'utf8'
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'latin1':
        case 'binary':
          return latin1Slice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  // The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect
  // Buffer instances.
  Buffer.prototype._isBuffer = true
  
  function swap (b, n, m) {
    var i = b[n]
    b[n] = b[m]
    b[m] = i
  }
  
  Buffer.prototype.swap16 = function swap16 () {
    var len = this.length
    if (len % 2 !== 0) {
      throw new RangeError('Buffer size must be a multiple of 16-bits')
    }
    for (var i = 0; i < len; i += 2) {
      swap(this, i, i + 1)
    }
    return this
  }
  
  Buffer.prototype.swap32 = function swap32 () {
    var len = this.length
    if (len % 4 !== 0) {
      throw new RangeError('Buffer size must be a multiple of 32-bits')
    }
    for (var i = 0; i < len; i += 4) {
      swap(this, i, i + 3)
      swap(this, i + 1, i + 2)
    }
    return this
  }
  
  Buffer.prototype.swap64 = function swap64 () {
    var len = this.length
    if (len % 8 !== 0) {
      throw new RangeError('Buffer size must be a multiple of 64-bits')
    }
    for (var i = 0; i < len; i += 8) {
      swap(this, i, i + 7)
      swap(this, i + 1, i + 6)
      swap(this, i + 2, i + 5)
      swap(this, i + 3, i + 4)
    }
    return this
  }
  
  Buffer.prototype.toString = function toString () {
    var length = this.length | 0
    if (length === 0) return ''
    if (arguments.length === 0) return utf8Slice(this, 0, length)
    return slowToString.apply(this, arguments)
  }
  
  Buffer.prototype.equals = function equals (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return true
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function inspect () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max) str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) {
    if (!Buffer.isBuffer(target)) {
      throw new TypeError('Argument must be a Buffer')
    }
  
    if (start === undefined) {
      start = 0
    }
    if (end === undefined) {
      end = target ? target.length : 0
    }
    if (thisStart === undefined) {
      thisStart = 0
    }
    if (thisEnd === undefined) {
      thisEnd = this.length
    }
  
    if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) {
      throw new RangeError('out of range index')
    }
  
    if (thisStart >= thisEnd && start >= end) {
      return 0
    }
    if (thisStart >= thisEnd) {
      return -1
    }
    if (start >= end) {
      return 1
    }
  
    start >>>= 0
    end >>>= 0
    thisStart >>>= 0
    thisEnd >>>= 0
  
    if (this === target) return 0
  
    var x = thisEnd - thisStart
    var y = end - start
    var len = Math.min(x, y)
  
    var thisCopy = this.slice(thisStart, thisEnd)
    var targetCopy = target.slice(start, end)
  
    for (var i = 0; i < len; ++i) {
      if (thisCopy[i] !== targetCopy[i]) {
        x = thisCopy[i]
        y = targetCopy[i]
        break
      }
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`,
  // OR the last index of `val` in `buffer` at offset <= `byteOffset`.
  //
  // Arguments:
  // - buffer - a Buffer to search
  // - val - a string, Buffer, or number
  // - byteOffset - an index into `buffer`; will be clamped to an int32
  // - encoding - an optional encoding, relevant is val is a string
  // - dir - true for indexOf, false for lastIndexOf
  function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) {
    // Empty buffer means no match
    if (buffer.length === 0) return -1
  
    // Normalize byteOffset
    if (typeof byteOffset === 'string') {
      encoding = byteOffset
      byteOffset = 0
    } else if (byteOffset > 0x7fffffff) {
      byteOffset = 0x7fffffff
    } else if (byteOffset < -0x80000000) {
      byteOffset = -0x80000000
    }
    byteOffset = +byteOffset  // Coerce to Number.
    if (isNaN(byteOffset)) {
      // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer
      byteOffset = dir ? 0 : (buffer.length - 1)
    }
  
    // Normalize byteOffset: negative offsets start from the end of the buffer
    if (byteOffset < 0) byteOffset = buffer.length + byteOffset
    if (byteOffset >= buffer.length) {
      if (dir) return -1
      else byteOffset = buffer.length - 1
    } else if (byteOffset < 0) {
      if (dir) byteOffset = 0
      else return -1
    }
  
    // Normalize val
    if (typeof val === 'string') {
      val = Buffer.from(val, encoding)
    }
  
    // Finally, search either indexOf (if dir is true) or lastIndexOf
    if (Buffer.isBuffer(val)) {
      // Special case: looking for empty string/buffer always fails
      if (val.length === 0) {
        return -1
      }
      return arrayIndexOf(buffer, val, byteOffset, encoding, dir)
    } else if (typeof val === 'number') {
      val = val & 0xFF // Search for a byte value [0-255]
      if (Buffer.TYPED_ARRAY_SUPPORT &&
          typeof Uint8Array.prototype.indexOf === 'function') {
        if (dir) {
          return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset)
        } else {
          return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset)
        }
      }
      return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir)
    }
  
    throw new TypeError('val must be string, number or Buffer')
  }
  
  function arrayIndexOf (arr, val, byteOffset, encoding, dir) {
    var indexSize = 1
    var arrLength = arr.length
    var valLength = val.length
  
    if (encoding !== undefined) {
      encoding = String(encoding).toLowerCase()
      if (encoding === 'ucs2' || encoding === 'ucs-2' ||
          encoding === 'utf16le' || encoding === 'utf-16le') {
        if (arr.length < 2 || val.length < 2) {
          return -1
        }
        indexSize = 2
        arrLength /= 2
        valLength /= 2
        byteOffset /= 2
      }
    }
  
    function read (buf, i) {
      if (indexSize === 1) {
        return buf[i]
      } else {
        return buf.readUInt16BE(i * indexSize)
      }
    }
  
    var i
    if (dir) {
      var foundIndex = -1
      for (i = byteOffset; i < arrLength; i++) {
        if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) {
          if (foundIndex === -1) foundIndex = i
          if (i - foundIndex + 1 === valLength) return foundIndex * indexSize
        } else {
          if (foundIndex !== -1) i -= i - foundIndex
          foundIndex = -1
        }
      }
    } else {
      if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength
      for (i = byteOffset; i >= 0; i--) {
        var found = true
        for (var j = 0; j < valLength; j++) {
          if (read(arr, i + j) !== read(val, j)) {
            found = false
            break
          }
        }
        if (found) return i
      }
    }
  
    return -1
  }
  
  Buffer.prototype.includes = function includes (val, byteOffset, encoding) {
    return this.indexOf(val, byteOffset, encoding) !== -1
  }
  
  Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) {
    return bidirectionalIndexOf(this, val, byteOffset, encoding, true)
  }
  
  Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) {
    return bidirectionalIndexOf(this, val, byteOffset, encoding, false)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new TypeError('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; ++i) {
      var parsed = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(parsed)) return i
      buf[offset + i] = parsed
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  function asciiWrite (buf, string, offset, length) {
    return blitBuffer(asciiToBytes(string), buf, offset, length)
  }
  
  function latin1Write (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    return blitBuffer(base64ToBytes(string), buf, offset, length)
  }
  
  function ucs2Write (buf, string, offset, length) {
    return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  Buffer.prototype.write = function write (string, offset, length, encoding) {
    // Buffer#write(string)
    if (offset === undefined) {
      encoding = 'utf8'
      length = this.length
      offset = 0
    // Buffer#write(string, encoding)
    } else if (length === undefined && typeof offset === 'string') {
      encoding = offset
      length = this.length
      offset = 0
    // Buffer#write(string, offset[, length][, encoding])
    } else if (isFinite(offset)) {
      offset = offset | 0
      if (isFinite(length)) {
        length = length | 0
        if (encoding === undefined) encoding = 'utf8'
      } else {
        encoding = length
        length = undefined
      }
    // legacy write(string, encoding, offset, length) - remove in v0.13
    } else {
      throw new Error(
        'Buffer.write(string, encoding, offset[, length]) is no longer supported'
      )
    }
  
    var remaining = this.length - offset
    if (length === undefined || length > remaining) length = remaining
  
    if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
      throw new RangeError('Attempt to write outside buffer bounds')
    }
  
    if (!encoding) encoding = 'utf8'
  
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'hex':
          return hexWrite(this, string, offset, length)
  
        case 'utf8':
        case 'utf-8':
          return utf8Write(this, string, offset, length)
  
        case 'ascii':
          return asciiWrite(this, string, offset, length)
  
        case 'latin1':
        case 'binary':
          return latin1Write(this, string, offset, length)
  
        case 'base64':
          // Warning: maxLength not taken into account in base64Write
          return base64Write(this, string, offset, length)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return ucs2Write(this, string, offset, length)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toJSON = function toJSON () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    end = Math.min(buf.length, end)
    var res = []
  
    var i = start
    while (i < end) {
      var firstByte = buf[i]
      var codePoint = null
      var bytesPerSequence = (firstByte > 0xEF) ? 4
        : (firstByte > 0xDF) ? 3
        : (firstByte > 0xBF) ? 2
        : 1
  
      if (i + bytesPerSequence <= end) {
        var secondByte, thirdByte, fourthByte, tempCodePoint
  
        switch (bytesPerSequence) {
          case 1:
            if (firstByte < 0x80) {
              codePoint = firstByte
            }
            break
          case 2:
            secondByte = buf[i + 1]
            if ((secondByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
              if (tempCodePoint > 0x7F) {
                codePoint = tempCodePoint
              }
            }
            break
          case 3:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
              if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
                codePoint = tempCodePoint
              }
            }
            break
          case 4:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            fourthByte = buf[i + 3]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
              if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
                codePoint = tempCodePoint
              }
            }
        }
      }
  
      if (codePoint === null) {
        // we did not generate a valid codePoint so insert a
        // replacement char (U+FFFD) and advance only 1 byte
        codePoint = 0xFFFD
        bytesPerSequence = 1
      } else if (codePoint > 0xFFFF) {
        // encode to utf16 (surrogate pair dance)
        codePoint -= 0x10000
        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
        codePoint = 0xDC00 | codePoint & 0x3FF
      }
  
      res.push(codePoint)
      i += bytesPerSequence
    }
  
    return decodeCodePointsArray(res)
  }
  
  // Based on http://stackoverflow.com/a/22747272/680742, the browser with
  // the lowest limit is Chrome, with 0x10000 args.
  // We go 1 magnitude less, for safety
  var MAX_ARGUMENTS_LENGTH = 0x1000
  
  function decodeCodePointsArray (codePoints) {
    var len = codePoints.length
    if (len <= MAX_ARGUMENTS_LENGTH) {
      return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
    }
  
    // Decode in chunks to avoid "call stack size exceeded".
    var res = ''
    var i = 0
    while (i < len) {
      res += String.fromCharCode.apply(
        String,
        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
      )
    }
    return res
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; ++i) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function latin1Slice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; ++i) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; ++i) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function slice (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len
      if (start < 0) start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0) end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start) end = start
  
    var newBuf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      newBuf = this.subarray(start, end)
      newBuf.__proto__ = Buffer.prototype
    } else {
      var sliceLen = end - start
      newBuf = new Buffer(sliceLen, undefined)
      for (var i = 0; i < sliceLen; ++i) {
        newBuf[i] = this[i + start]
      }
    }
  
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
    if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      checkOffset(offset, byteLength, this.length)
    }
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100)) {
      val += this[offset + --byteLength] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
      ((this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100)) {
      val += this[offset + --i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80)) return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16) |
      (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
      (this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('"value" argument is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('Index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      var maxBytes = Math.pow(2, 8 * byteLength) - 1
      checkInt(this, value, offset, byteLength, maxBytes, 0)
    }
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      var maxBytes = Math.pow(2, 8 * byteLength) - 1
      checkInt(this, value, offset, byteLength, maxBytes, 0)
    }
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = 0
    var mul = 1
    var sub = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) {
        sub = 1
      }
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) {
        sub = 1
      }
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (offset + ext > buf.length) throw new RangeError('Index out of range')
    if (offset < 0) throw new RangeError('Index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    }
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    }
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function copy (target, targetStart, start, end) {
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (targetStart >= target.length) targetStart = target.length
    if (!targetStart) targetStart = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || this.length === 0) return 0
  
    // Fatal error conditions
    if (targetStart < 0) {
      throw new RangeError('targetStart out of bounds')
    }
    if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length) end = this.length
    if (target.length - targetStart < end - start) {
      end = target.length - targetStart + start
    }
  
    var len = end - start
    var i
  
    if (this === target && start < targetStart && targetStart < end) {
      // descending copy from end
      for (i = len - 1; i >= 0; --i) {
        target[i + targetStart] = this[i + start]
      }
    } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      // ascending copy from start
      for (i = 0; i < len; ++i) {
        target[i + targetStart] = this[i + start]
      }
    } else {
      Uint8Array.prototype.set.call(
        target,
        this.subarray(start, start + len),
        targetStart
      )
    }
  
    return len
  }
  
  // Usage:
  //    buffer.fill(number[, offset[, end]])
  //    buffer.fill(buffer[, offset[, end]])
  //    buffer.fill(string[, offset[, end]][, encoding])
  Buffer.prototype.fill = function fill (val, start, end, encoding) {
    // Handle string cases:
    if (typeof val === 'string') {
      if (typeof start === 'string') {
        encoding = start
        start = 0
        end = this.length
      } else if (typeof end === 'string') {
        encoding = end
        end = this.length
      }
      if (val.length === 1) {
        var code = val.charCodeAt(0)
        if (code < 256) {
          val = code
        }
      }
      if (encoding !== undefined && typeof encoding !== 'string') {
        throw new TypeError('encoding must be a string')
      }
      if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) {
        throw new TypeError('Unknown encoding: ' + encoding)
      }
    } else if (typeof val === 'number') {
      val = val & 255
    }
  
    // Invalid ranges are not set to a default, so can range check early.
    if (start < 0 || this.length < start || this.length < end) {
      throw new RangeError('Out of range index')
    }
  
    if (end <= start) {
      return this
    }
  
    start = start >>> 0
    end = end === undefined ? this.length : end >>> 0
  
    if (!val) val = 0
  
    var i
    if (typeof val === 'number') {
      for (i = start; i < end; ++i) {
        this[i] = val
      }
    } else {
      var bytes = Buffer.isBuffer(val)
        ? val
        : utf8ToBytes(new Buffer(val, encoding).toString())
      var len = bytes.length
      for (i = 0; i < end - start; ++i) {
        this[i + start] = bytes[i % len]
      }
    }
  
    return this
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (string, units) {
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
  
    for (var i = 0; i < length; ++i) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          leadSurrogate = codePoint
  
          continue
        }
  
        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }
  
        // valid surrogate pair
        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }
  
      leadSurrogate = null
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; ++i) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; ++i) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length) {
    for (var i = 0; i < length; ++i) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  function isnan (val) {
    return val !== val // eslint-disable-line no-self-compare
  }
  
  /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ "../../node_modules/webpack/buildin/global.js")))
  
  /***/ }),
  
  /***/ "../../node_modules/ieee754/index.js":
  /*!******************************************************!*\
    !*** /root/amplify-js/node_modules/ieee754/index.js ***!
    \******************************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = (nBytes * 8) - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var s = buffer[offset + i]
  
    i += d
  
    e = s & ((1 << (-nBits)) - 1)
    s >>= (-nBits)
    nBits += eLen
    for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {}
  
    m = e & ((1 << (-nBits)) - 1)
    e >>= (-nBits)
    nBits += mLen
    for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {}
  
    if (e === 0) {
      e = 1 - eBias
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity)
    } else {
      m = m + Math.pow(2, mLen)
      e = e - eBias
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen)
  }
  
  exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = (nBytes * 8) - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0
  
    value = Math.abs(value)
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0
      e = eMax
    } else {
      e = Math.floor(Math.log(value) / Math.LN2)
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--
        c *= 2
      }
      if (e + eBias >= 1) {
        value += rt / c
      } else {
        value += rt * Math.pow(2, 1 - eBias)
      }
      if (value * c >= 2) {
        e++
        c /= 2
      }
  
      if (e + eBias >= eMax) {
        m = 0
        e = eMax
      } else if (e + eBias >= 1) {
        m = ((value * c) - 1) * Math.pow(2, mLen)
        e = e + eBias
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)
        e = 0
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
  
    e = (e << mLen) | m
    eLen += mLen
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
  
    buffer[offset + i - d] |= s * 128
  }
  
  
  /***/ }),
  
  /***/ "../../node_modules/isarray/index.js":
  /*!******************************************************!*\
    !*** /root/amplify-js/node_modules/isarray/index.js ***!
    \******************************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  var toString = {}.toString;
  
  module.exports = Array.isArray || function (arr) {
    return toString.call(arr) == '[object Array]';
  };
  
  
  /***/ }),
  
  /***/ "../../node_modules/node-libs-browser/node_modules/punycode/punycode.js":
  /*!*****************************************************************************************!*\
    !*** /root/amplify-js/node_modules/node-libs-browser/node_modules/punycode/punycode.js ***!
    \*****************************************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */
  ;(function(root) {
  
  	/** Detect free variables */
  	var freeExports =  true && exports &&
  		!exports.nodeType && exports;
  	var freeModule =  true && module &&
  		!module.nodeType && module;
  	var freeGlobal = typeof global == 'object' && global;
  	if (
  		freeGlobal.global === freeGlobal ||
  		freeGlobal.window === freeGlobal ||
  		freeGlobal.self === freeGlobal
  	) {
  		root = freeGlobal;
  	}
  
  	/**
  	 * The `punycode` object.
  	 * @name punycode
  	 * @type Object
  	 */
  	var punycode,
  
  	/** Highest positive signed 32-bit float value */
  	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
  
  	/** Bootstring parameters */
  	base = 36,
  	tMin = 1,
  	tMax = 26,
  	skew = 38,
  	damp = 700,
  	initialBias = 72,
  	initialN = 128, // 0x80
  	delimiter = '-', // '\x2D'
  
  	/** Regular expressions */
  	regexPunycode = /^xn--/,
  	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
  	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
  
  	/** Error messages */
  	errors = {
  		'overflow': 'Overflow: input needs wider integers to process',
  		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
  		'invalid-input': 'Invalid input'
  	},
  
  	/** Convenience shortcuts */
  	baseMinusTMin = base - tMin,
  	floor = Math.floor,
  	stringFromCharCode = String.fromCharCode,
  
  	/** Temporary variable */
  	key;
  
  	/*--------------------------------------------------------------------------*/
  
  	/**
  	 * A generic error utility function.
  	 * @private
  	 * @param {String} type The error type.
  	 * @returns {Error} Throws a `RangeError` with the applicable error message.
  	 */
  	function error(type) {
  		throw new RangeError(errors[type]);
  	}
  
  	/**
  	 * A generic `Array#map` utility function.
  	 * @private
  	 * @param {Array} array The array to iterate over.
  	 * @param {Function} callback The function that gets called for every array
  	 * item.
  	 * @returns {Array} A new array of values returned by the callback function.
  	 */
  	function map(array, fn) {
  		var length = array.length;
  		var result = [];
  		while (length--) {
  			result[length] = fn(array[length]);
  		}
  		return result;
  	}
  
  	/**
  	 * A simple `Array#map`-like wrapper to work with domain name strings or email
  	 * addresses.
  	 * @private
  	 * @param {String} domain The domain name or email address.
  	 * @param {Function} callback The function that gets called for every
  	 * character.
  	 * @returns {Array} A new string of characters returned by the callback
  	 * function.
  	 */
  	function mapDomain(string, fn) {
  		var parts = string.split('@');
  		var result = '';
  		if (parts.length > 1) {
  			// In email addresses, only the domain name should be punycoded. Leave
  			// the local part (i.e. everything up to `@`) intact.
  			result = parts[0] + '@';
  			string = parts[1];
  		}
  		// Avoid `split(regex)` for IE8 compatibility. See #17.
  		string = string.replace(regexSeparators, '\x2E');
  		var labels = string.split('.');
  		var encoded = map(labels, fn).join('.');
  		return result + encoded;
  	}
  
  	/**
  	 * Creates an array containing the numeric code points of each Unicode
  	 * character in the string. While JavaScript uses UCS-2 internally,
  	 * this function will convert a pair of surrogate halves (each of which
  	 * UCS-2 exposes as separate characters) into a single code point,
  	 * matching UTF-16.
  	 * @see `punycode.ucs2.encode`
  	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  	 * @memberOf punycode.ucs2
  	 * @name decode
  	 * @param {String} string The Unicode input string (UCS-2).
  	 * @returns {Array} The new array of code points.
  	 */
  	function ucs2decode(string) {
  		var output = [],
  		    counter = 0,
  		    length = string.length,
  		    value,
  		    extra;
  		while (counter < length) {
  			value = string.charCodeAt(counter++);
  			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  				// high surrogate, and there is a next character
  				extra = string.charCodeAt(counter++);
  				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  				} else {
  					// unmatched surrogate; only append this code unit, in case the next
  					// code unit is the high surrogate of a surrogate pair
  					output.push(value);
  					counter--;
  				}
  			} else {
  				output.push(value);
  			}
  		}
  		return output;
  	}
  
  	/**
  	 * Creates a string based on an array of numeric code points.
  	 * @see `punycode.ucs2.decode`
  	 * @memberOf punycode.ucs2
  	 * @name encode
  	 * @param {Array} codePoints The array of numeric code points.
  	 * @returns {String} The new Unicode string (UCS-2).
  	 */
  	function ucs2encode(array) {
  		return map(array, function(value) {
  			var output = '';
  			if (value > 0xFFFF) {
  				value -= 0x10000;
  				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  				value = 0xDC00 | value & 0x3FF;
  			}
  			output += stringFromCharCode(value);
  			return output;
  		}).join('');
  	}
  
  	/**
  	 * Converts a basic code point into a digit/integer.
  	 * @see `digitToBasic()`
  	 * @private
  	 * @param {Number} codePoint The basic numeric code point value.
  	 * @returns {Number} The numeric value of a basic code point (for use in
  	 * representing integers) in the range `0` to `base - 1`, or `base` if
  	 * the code point does not represent a value.
  	 */
  	function basicToDigit(codePoint) {
  		if (codePoint - 48 < 10) {
  			return codePoint - 22;
  		}
  		if (codePoint - 65 < 26) {
  			return codePoint - 65;
  		}
  		if (codePoint - 97 < 26) {
  			return codePoint - 97;
  		}
  		return base;
  	}
  
  	/**
  	 * Converts a digit/integer into a basic code point.
  	 * @see `basicToDigit()`
  	 * @private
  	 * @param {Number} digit The numeric value of a basic code point.
  	 * @returns {Number} The basic code point whose value (when used for
  	 * representing integers) is `digit`, which needs to be in the range
  	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
  	 * used; else, the lowercase form is used. The behavior is undefined
  	 * if `flag` is non-zero and `digit` has no uppercase form.
  	 */
  	function digitToBasic(digit, flag) {
  		//  0..25 map to ASCII a..z or A..Z
  		// 26..35 map to ASCII 0..9
  		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
  	}
  
  	/**
  	 * Bias adaptation function as per section 3.4 of RFC 3492.
  	 * https://tools.ietf.org/html/rfc3492#section-3.4
  	 * @private
  	 */
  	function adapt(delta, numPoints, firstTime) {
  		var k = 0;
  		delta = firstTime ? floor(delta / damp) : delta >> 1;
  		delta += floor(delta / numPoints);
  		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
  			delta = floor(delta / baseMinusTMin);
  		}
  		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
  	}
  
  	/**
  	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
  	 * symbols.
  	 * @memberOf punycode
  	 * @param {String} input The Punycode string of ASCII-only symbols.
  	 * @returns {String} The resulting string of Unicode symbols.
  	 */
  	function decode(input) {
  		// Don't use UCS-2
  		var output = [],
  		    inputLength = input.length,
  		    out,
  		    i = 0,
  		    n = initialN,
  		    bias = initialBias,
  		    basic,
  		    j,
  		    index,
  		    oldi,
  		    w,
  		    k,
  		    digit,
  		    t,
  		    /** Cached calculation results */
  		    baseMinusT;
  
  		// Handle the basic code points: let `basic` be the number of input code
  		// points before the last delimiter, or `0` if there is none, then copy
  		// the first basic code points to the output.
  
  		basic = input.lastIndexOf(delimiter);
  		if (basic < 0) {
  			basic = 0;
  		}
  
  		for (j = 0; j < basic; ++j) {
  			// if it's not a basic code point
  			if (input.charCodeAt(j) >= 0x80) {
  				error('not-basic');
  			}
  			output.push(input.charCodeAt(j));
  		}
  
  		// Main decoding loop: start just after the last delimiter if any basic code
  		// points were copied; start at the beginning otherwise.
  
  		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
  
  			// `index` is the index of the next character to be consumed.
  			// Decode a generalized variable-length integer into `delta`,
  			// which gets added to `i`. The overflow checking is easier
  			// if we increase `i` as we go, then subtract off its starting
  			// value at the end to obtain `delta`.
  			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
  
  				if (index >= inputLength) {
  					error('invalid-input');
  				}
  
  				digit = basicToDigit(input.charCodeAt(index++));
  
  				if (digit >= base || digit > floor((maxInt - i) / w)) {
  					error('overflow');
  				}
  
  				i += digit * w;
  				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  
  				if (digit < t) {
  					break;
  				}
  
  				baseMinusT = base - t;
  				if (w > floor(maxInt / baseMinusT)) {
  					error('overflow');
  				}
  
  				w *= baseMinusT;
  
  			}
  
  			out = output.length + 1;
  			bias = adapt(i - oldi, out, oldi == 0);
  
  			// `i` was supposed to wrap around from `out` to `0`,
  			// incrementing `n` each time, so we'll fix that now:
  			if (floor(i / out) > maxInt - n) {
  				error('overflow');
  			}
  
  			n += floor(i / out);
  			i %= out;
  
  			// Insert `n` at position `i` of the output
  			output.splice(i++, 0, n);
  
  		}
  
  		return ucs2encode(output);
  	}
  
  	/**
  	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
  	 * Punycode string of ASCII-only symbols.
  	 * @memberOf punycode
  	 * @param {String} input The string of Unicode symbols.
  	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
  	 */
  	function encode(input) {
  		var n,
  		    delta,
  		    handledCPCount,
  		    basicLength,
  		    bias,
  		    j,
  		    m,
  		    q,
  		    k,
  		    t,
  		    currentValue,
  		    output = [],
  		    /** `inputLength` will hold the number of code points in `input`. */
  		    inputLength,
  		    /** Cached calculation results */
  		    handledCPCountPlusOne,
  		    baseMinusT,
  		    qMinusT;
  
  		// Convert the input in UCS-2 to Unicode
  		input = ucs2decode(input);
  
  		// Cache the length
  		inputLength = input.length;
  
  		// Initialize the state
  		n = initialN;
  		delta = 0;
  		bias = initialBias;
  
  		// Handle the basic code points
  		for (j = 0; j < inputLength; ++j) {
  			currentValue = input[j];
  			if (currentValue < 0x80) {
  				output.push(stringFromCharCode(currentValue));
  			}
  		}
  
  		handledCPCount = basicLength = output.length;
  
  		// `handledCPCount` is the number of code points that have been handled;
  		// `basicLength` is the number of basic code points.
  
  		// Finish the basic string - if it is not empty - with a delimiter
  		if (basicLength) {
  			output.push(delimiter);
  		}
  
  		// Main encoding loop:
  		while (handledCPCount < inputLength) {
  
  			// All non-basic code points < n have been handled already. Find the next
  			// larger one:
  			for (m = maxInt, j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  				if (currentValue >= n && currentValue < m) {
  					m = currentValue;
  				}
  			}
  
  			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
  			// but guard against overflow
  			handledCPCountPlusOne = handledCPCount + 1;
  			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
  				error('overflow');
  			}
  
  			delta += (m - n) * handledCPCountPlusOne;
  			n = m;
  
  			for (j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  
  				if (currentValue < n && ++delta > maxInt) {
  					error('overflow');
  				}
  
  				if (currentValue == n) {
  					// Represent delta as a generalized variable-length integer
  					for (q = delta, k = base; /* no condition */; k += base) {
  						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  						if (q < t) {
  							break;
  						}
  						qMinusT = q - t;
  						baseMinusT = base - t;
  						output.push(
  							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
  						);
  						q = floor(qMinusT / baseMinusT);
  					}
  
  					output.push(stringFromCharCode(digitToBasic(q, 0)));
  					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
  					delta = 0;
  					++handledCPCount;
  				}
  			}
  
  			++delta;
  			++n;
  
  		}
  		return output.join('');
  	}
  
  	/**
  	 * Converts a Punycode string representing a domain name or an email address
  	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
  	 * it doesn't matter if you call it on a string that has already been
  	 * converted to Unicode.
  	 * @memberOf punycode
  	 * @param {String} input The Punycoded domain name or email address to
  	 * convert to Unicode.
  	 * @returns {String} The Unicode representation of the given Punycode
  	 * string.
  	 */
  	function toUnicode(input) {
  		return mapDomain(input, function(string) {
  			return regexPunycode.test(string)
  				? decode(string.slice(4).toLowerCase())
  				: string;
  		});
  	}
  
  	/**
  	 * Converts a Unicode string representing a domain name or an email address to
  	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
  	 * i.e. it doesn't matter if you call it with a domain that's already in
  	 * ASCII.
  	 * @memberOf punycode
  	 * @param {String} input The domain name or email address to convert, as a
  	 * Unicode string.
  	 * @returns {String} The Punycode representation of the given domain name or
  	 * email address.
  	 */
  	function toASCII(input) {
  		return mapDomain(input, function(string) {
  			return regexNonASCII.test(string)
  				? 'xn--' + encode(string)
  				: string;
  		});
  	}
  
  	/*--------------------------------------------------------------------------*/
  
  	/** Define the public API */
  	punycode = {
  		/**
  		 * A string representing the current Punycode.js version number.
  		 * @memberOf punycode
  		 * @type String
  		 */
  		'version': '1.4.1',
  		/**
  		 * An object of methods to convert from JavaScript's internal character
  		 * representation (UCS-2) to Unicode code points, and back.
  		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  		 * @memberOf punycode
  		 * @type Object
  		 */
  		'ucs2': {
  			'decode': ucs2decode,
  			'encode': ucs2encode
  		},
  		'decode': decode,
  		'encode': encode,
  		'toASCII': toASCII,
  		'toUnicode': toUnicode
  	};
  
  	/** Expose `punycode` */
  	// Some AMD build optimizers, like r.js, check for specific condition patterns
  	// like the following:
  	if (
  		true
  	) {
  		!(__WEBPACK_AMD_DEFINE_RESULT__ = (function() {
  			return punycode;
  		}).call(exports, __webpack_require__, exports, module),
  				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  	} else {}
  
  }(this));
  
  /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../../webpack/buildin/module.js */ "../../node_modules/webpack/buildin/module.js")(module), __webpack_require__(/*! ./../../../webpack/buildin/global.js */ "../../node_modules/webpack/buildin/global.js")))
  
  /***/ }),
  
  /***/ "../../node_modules/paho-mqtt/paho-mqtt.js":
  /*!************************************************************!*\
    !*** /root/amplify-js/node_modules/paho-mqtt/paho-mqtt.js ***!
    \************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  /* WEBPACK VAR INJECTION */(function(global) {/*******************************************************************************
   * Copyright (c) 2013 IBM Corp.
   *
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * and Eclipse Distribution License v1.0 which accompany this distribution.
   *
   * The Eclipse Public License is available at
   *    http://www.eclipse.org/legal/epl-v10.html
   * and the Eclipse Distribution License is available at
   *   http://www.eclipse.org/org/documents/edl-v10.php.
   *
   * Contributors:
   *    Andrew Banks - initial API and implementation and initial documentation
   *******************************************************************************/
  
  
  // Only expose a single object name in the global namespace.
  // Everything must go through this module. Global Paho module
  // only has a single public function, client, which returns
  // a Paho client object given connection details.
  
  /**
   * Send and receive messages using web browsers.
   * <p>
   * This programming interface lets a JavaScript client application use the MQTT V3.1 or
   * V3.1.1 protocol to connect to an MQTT-supporting messaging server.
   *
   * The function supported includes:
   * <ol>
   * <li>Connecting to and disconnecting from a server. The server is identified by its host name and port number.
   * <li>Specifying options that relate to the communications link with the server,
   * for example the frequency of keep-alive heartbeats, and whether SSL/TLS is required.
   * <li>Subscribing to and receiving messages from MQTT Topics.
   * <li>Publishing messages to MQTT Topics.
   * </ol>
   * <p>
   * The API consists of two main objects:
   * <dl>
   * <dt><b>{@link Paho.Client}</b></dt>
   * <dd>This contains methods that provide the functionality of the API,
   * including provision of callbacks that notify the application when a message
   * arrives from or is delivered to the messaging server,
   * or when the status of its connection to the messaging server changes.</dd>
   * <dt><b>{@link Paho.Message}</b></dt>
   * <dd>This encapsulates the payload of the message along with various attributes
   * associated with its delivery, in particular the destination to which it has
   * been (or is about to be) sent.</dd>
   * </dl>
   * <p>
   * The programming interface validates parameters passed to it, and will throw
   * an Error containing an error message intended for developer use, if it detects
   * an error with any parameter.
   * <p>
   * Example:
   *
   * <code><pre>
  var client = new Paho.MQTT.Client(location.hostname, Number(location.port), "clientId");
  client.onConnectionLost = onConnectionLost;
  client.onMessageArrived = onMessageArrived;
  client.connect({onSuccess:onConnect});
  
  function onConnect() {
    // Once a connection has been made, make a subscription and send a message.
    console.log("onConnect");
    client.subscribe("/World");
    var message = new Paho.MQTT.Message("Hello");
    message.destinationName = "/World";
    client.send(message);
  };
  function onConnectionLost(responseObject) {
    if (responseObject.errorCode !== 0)
  	console.log("onConnectionLost:"+responseObject.errorMessage);
  };
  function onMessageArrived(message) {
    console.log("onMessageArrived:"+message.payloadString);
    client.disconnect();
  };
   * </pre></code>
   * @namespace Paho
   */
  
  /* jshint shadow:true */
  (function ExportLibrary(root, factory) {
  	if(true){
  		module.exports = factory();
  	} else {}
  })(this, function LibraryFactory(){
  
  
  	var PahoMQTT = (function (global) {
  
  	// Private variables below, these are only visible inside the function closure
  	// which is used to define the module.
  	var version = "@VERSION@-@BUILDLEVEL@";
  
  	/**
  	 * @private
  	 */
  	var localStorage = global.localStorage || (function () {
  		var data = {};
  
  		return {
  			setItem: function (key, item) { data[key] = item; },
  			getItem: function (key) { return data[key]; },
  			removeItem: function (key) { delete data[key]; },
  		};
  	})();
  
  		/**
  	 * Unique message type identifiers, with associated
  	 * associated integer values.
  	 * @private
  	 */
  		var MESSAGE_TYPE = {
  			CONNECT: 1,
  			CONNACK: 2,
  			PUBLISH: 3,
  			PUBACK: 4,
  			PUBREC: 5,
  			PUBREL: 6,
  			PUBCOMP: 7,
  			SUBSCRIBE: 8,
  			SUBACK: 9,
  			UNSUBSCRIBE: 10,
  			UNSUBACK: 11,
  			PINGREQ: 12,
  			PINGRESP: 13,
  			DISCONNECT: 14
  		};
  
  		// Collection of utility methods used to simplify module code
  		// and promote the DRY pattern.
  
  		/**
  	 * Validate an object's parameter names to ensure they
  	 * match a list of expected variables name for this option
  	 * type. Used to ensure option object passed into the API don't
  	 * contain erroneous parameters.
  	 * @param {Object} obj - User options object
  	 * @param {Object} keys - valid keys and types that may exist in obj.
  	 * @throws {Error} Invalid option parameter found.
  	 * @private
  	 */
  		var validate = function(obj, keys) {
  			for (var key in obj) {
  				if (obj.hasOwnProperty(key)) {
  					if (keys.hasOwnProperty(key)) {
  						if (typeof obj[key] !== keys[key])
  							throw new Error(format(ERROR.INVALID_TYPE, [typeof obj[key], key]));
  					} else {
  						var errorStr = "Unknown property, " + key + ". Valid properties are:";
  						for (var validKey in keys)
  							if (keys.hasOwnProperty(validKey))
  								errorStr = errorStr+" "+validKey;
  						throw new Error(errorStr);
  					}
  				}
  			}
  		};
  
  		/**
  	 * Return a new function which runs the user function bound
  	 * to a fixed scope.
  	 * @param {function} User function
  	 * @param {object} Function scope
  	 * @return {function} User function bound to another scope
  	 * @private
  	 */
  		var scope = function (f, scope) {
  			return function () {
  				return f.apply(scope, arguments);
  			};
  		};
  
  		/**
  	 * Unique message type identifiers, with associated
  	 * associated integer values.
  	 * @private
  	 */
  		var ERROR = {
  			OK: {code:0, text:"AMQJSC0000I OK."},
  			CONNECT_TIMEOUT: {code:1, text:"AMQJSC0001E Connect timed out."},
  			SUBSCRIBE_TIMEOUT: {code:2, text:"AMQJS0002E Subscribe timed out."},
  			UNSUBSCRIBE_TIMEOUT: {code:3, text:"AMQJS0003E Unsubscribe timed out."},
  			PING_TIMEOUT: {code:4, text:"AMQJS0004E Ping timed out."},
  			INTERNAL_ERROR: {code:5, text:"AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}"},
  			CONNACK_RETURNCODE: {code:6, text:"AMQJS0006E Bad Connack return code:{0} {1}."},
  			SOCKET_ERROR: {code:7, text:"AMQJS0007E Socket error:{0}."},
  			SOCKET_CLOSE: {code:8, text:"AMQJS0008I Socket closed."},
  			MALFORMED_UTF: {code:9, text:"AMQJS0009E Malformed UTF data:{0} {1} {2}."},
  			UNSUPPORTED: {code:10, text:"AMQJS0010E {0} is not supported by this browser."},
  			INVALID_STATE: {code:11, text:"AMQJS0011E Invalid state {0}."},
  			INVALID_TYPE: {code:12, text:"AMQJS0012E Invalid type {0} for {1}."},
  			INVALID_ARGUMENT: {code:13, text:"AMQJS0013E Invalid argument {0} for {1}."},
  			UNSUPPORTED_OPERATION: {code:14, text:"AMQJS0014E Unsupported operation."},
  			INVALID_STORED_DATA: {code:15, text:"AMQJS0015E Invalid data in local storage key={0} value={1}."},
  			INVALID_MQTT_MESSAGE_TYPE: {code:16, text:"AMQJS0016E Invalid MQTT message type {0}."},
  			MALFORMED_UNICODE: {code:17, text:"AMQJS0017E Malformed Unicode string:{0} {1}."},
  			BUFFER_FULL: {code:18, text:"AMQJS0018E Message buffer is full, maximum buffer size: {0}."},
  		};
  
  		/** CONNACK RC Meaning. */
  		var CONNACK_RC = {
  			0:"Connection Accepted",
  			1:"Connection Refused: unacceptable protocol version",
  			2:"Connection Refused: identifier rejected",
  			3:"Connection Refused: server unavailable",
  			4:"Connection Refused: bad user name or password",
  			5:"Connection Refused: not authorized"
  		};
  
  	/**
  	 * Format an error message text.
  	 * @private
  	 * @param {error} ERROR value above.
  	 * @param {substitutions} [array] substituted into the text.
  	 * @return the text with the substitutions made.
  	 */
  		var format = function(error, substitutions) {
  			var text = error.text;
  			if (substitutions) {
  				var field,start;
  				for (var i=0; i<substitutions.length; i++) {
  					field = "{"+i+"}";
  					start = text.indexOf(field);
  					if(start > 0) {
  						var part1 = text.substring(0,start);
  						var part2 = text.substring(start+field.length);
  						text = part1+substitutions[i]+part2;
  					}
  				}
  			}
  			return text;
  		};
  
  		//MQTT protocol and version          6    M    Q    I    s    d    p    3
  		var MqttProtoIdentifierv3 = [0x00,0x06,0x4d,0x51,0x49,0x73,0x64,0x70,0x03];
  		//MQTT proto/version for 311         4    M    Q    T    T    4
  		var MqttProtoIdentifierv4 = [0x00,0x04,0x4d,0x51,0x54,0x54,0x04];
  
  		/**
  	 * Construct an MQTT wire protocol message.
  	 * @param type MQTT packet type.
  	 * @param options optional wire message attributes.
  	 *
  	 * Optional properties
  	 *
  	 * messageIdentifier: message ID in the range [0..65535]
  	 * payloadMessage:	Application Message - PUBLISH only
  	 * connectStrings:	array of 0 or more Strings to be put into the CONNECT payload
  	 * topics:			array of strings (SUBSCRIBE, UNSUBSCRIBE)
  	 * requestQoS:		array of QoS values [0..2]
  	 *
  	 * "Flag" properties
  	 * cleanSession:	true if present / false if absent (CONNECT)
  	 * willMessage:  	true if present / false if absent (CONNECT)
  	 * isRetained:		true if present / false if absent (CONNECT)
  	 * userName:		true if present / false if absent (CONNECT)
  	 * password:		true if present / false if absent (CONNECT)
  	 * keepAliveInterval:	integer [0..65535]  (CONNECT)
  	 *
  	 * @private
  	 * @ignore
  	 */
  		var WireMessage = function (type, options) {
  			this.type = type;
  			for (var name in options) {
  				if (options.hasOwnProperty(name)) {
  					this[name] = options[name];
  				}
  			}
  		};
  
  		WireMessage.prototype.encode = function() {
  		// Compute the first byte of the fixed header
  			var first = ((this.type & 0x0f) << 4);
  
  			/*
  		 * Now calculate the length of the variable header + payload by adding up the lengths
  		 * of all the component parts
  		 */
  
  			var remLength = 0;
  			var topicStrLength = [];
  			var destinationNameLength = 0;
  			var willMessagePayloadBytes;
  
  			// if the message contains a messageIdentifier then we need two bytes for that
  			if (this.messageIdentifier !== undefined)
  				remLength += 2;
  
  			switch(this.type) {
  			// If this a Connect then we need to include 12 bytes for its header
  			case MESSAGE_TYPE.CONNECT:
  				switch(this.mqttVersion) {
  				case 3:
  					remLength += MqttProtoIdentifierv3.length + 3;
  					break;
  				case 4:
  					remLength += MqttProtoIdentifierv4.length + 3;
  					break;
  				}
  
  				remLength += UTF8Length(this.clientId) + 2;
  				if (this.willMessage !== undefined) {
  					remLength += UTF8Length(this.willMessage.destinationName) + 2;
  					// Will message is always a string, sent as UTF-8 characters with a preceding length.
  					willMessagePayloadBytes = this.willMessage.payloadBytes;
  					if (!(willMessagePayloadBytes instanceof Uint8Array))
  						willMessagePayloadBytes = new Uint8Array(payloadBytes);
  					remLength += willMessagePayloadBytes.byteLength +2;
  				}
  				if (this.userName !== undefined)
  					remLength += UTF8Length(this.userName) + 2;
  				if (this.password !== undefined)
  					remLength += UTF8Length(this.password) + 2;
  				break;
  
  			// Subscribe, Unsubscribe can both contain topic strings
  			case MESSAGE_TYPE.SUBSCRIBE:
  				first |= 0x02; // Qos = 1;
  				for ( var i = 0; i < this.topics.length; i++) {
  					topicStrLength[i] = UTF8Length(this.topics[i]);
  					remLength += topicStrLength[i] + 2;
  				}
  				remLength += this.requestedQos.length; // 1 byte for each topic's Qos
  				// QoS on Subscribe only
  				break;
  
  			case MESSAGE_TYPE.UNSUBSCRIBE:
  				first |= 0x02; // Qos = 1;
  				for ( var i = 0; i < this.topics.length; i++) {
  					topicStrLength[i] = UTF8Length(this.topics[i]);
  					remLength += topicStrLength[i] + 2;
  				}
  				break;
  
  			case MESSAGE_TYPE.PUBREL:
  				first |= 0x02; // Qos = 1;
  				break;
  
  			case MESSAGE_TYPE.PUBLISH:
  				if (this.payloadMessage.duplicate) first |= 0x08;
  				first  = first |= (this.payloadMessage.qos << 1);
  				if (this.payloadMessage.retained) first |= 0x01;
  				destinationNameLength = UTF8Length(this.payloadMessage.destinationName);
  				remLength += destinationNameLength + 2;
  				var payloadBytes = this.payloadMessage.payloadBytes;
  				remLength += payloadBytes.byteLength;
  				if (payloadBytes instanceof ArrayBuffer)
  					payloadBytes = new Uint8Array(payloadBytes);
  				else if (!(payloadBytes instanceof Uint8Array))
  					payloadBytes = new Uint8Array(payloadBytes.buffer);
  				break;
  
  			case MESSAGE_TYPE.DISCONNECT:
  				break;
  
  			default:
  				break;
  			}
  
  			// Now we can allocate a buffer for the message
  
  			var mbi = encodeMBI(remLength);  // Convert the length to MQTT MBI format
  			var pos = mbi.length + 1;        // Offset of start of variable header
  			var buffer = new ArrayBuffer(remLength + pos);
  			var byteStream = new Uint8Array(buffer);    // view it as a sequence of bytes
  
  			//Write the fixed header into the buffer
  			byteStream[0] = first;
  			byteStream.set(mbi,1);
  
  			// If this is a PUBLISH then the variable header starts with a topic
  			if (this.type == MESSAGE_TYPE.PUBLISH)
  				pos = writeString(this.payloadMessage.destinationName, destinationNameLength, byteStream, pos);
  			// If this is a CONNECT then the variable header contains the protocol name/version, flags and keepalive time
  
  			else if (this.type == MESSAGE_TYPE.CONNECT) {
  				switch (this.mqttVersion) {
  				case 3:
  					byteStream.set(MqttProtoIdentifierv3, pos);
  					pos += MqttProtoIdentifierv3.length;
  					break;
  				case 4:
  					byteStream.set(MqttProtoIdentifierv4, pos);
  					pos += MqttProtoIdentifierv4.length;
  					break;
  				}
  				var connectFlags = 0;
  				if (this.cleanSession)
  					connectFlags = 0x02;
  				if (this.willMessage !== undefined ) {
  					connectFlags |= 0x04;
  					connectFlags |= (this.willMessage.qos<<3);
  					if (this.willMessage.retained) {
  						connectFlags |= 0x20;
  					}
  				}
  				if (this.userName !== undefined)
  					connectFlags |= 0x80;
  				if (this.password !== undefined)
  					connectFlags |= 0x40;
  				byteStream[pos++] = connectFlags;
  				pos = writeUint16 (this.keepAliveInterval, byteStream, pos);
  			}
  
  			// Output the messageIdentifier - if there is one
  			if (this.messageIdentifier !== undefined)
  				pos = writeUint16 (this.messageIdentifier, byteStream, pos);
  
  			switch(this.type) {
  			case MESSAGE_TYPE.CONNECT:
  				pos = writeString(this.clientId, UTF8Length(this.clientId), byteStream, pos);
  				if (this.willMessage !== undefined) {
  					pos = writeString(this.willMessage.destinationName, UTF8Length(this.willMessage.destinationName), byteStream, pos);
  					pos = writeUint16(willMessagePayloadBytes.byteLength, byteStream, pos);
  					byteStream.set(willMessagePayloadBytes, pos);
  					pos += willMessagePayloadBytes.byteLength;
  
  				}
  				if (this.userName !== undefined)
  					pos = writeString(this.userName, UTF8Length(this.userName), byteStream, pos);
  				if (this.password !== undefined)
  					pos = writeString(this.password, UTF8Length(this.password), byteStream, pos);
  				break;
  
  			case MESSAGE_TYPE.PUBLISH:
  				// PUBLISH has a text or binary payload, if text do not add a 2 byte length field, just the UTF characters.
  				byteStream.set(payloadBytes, pos);
  
  				break;
  
  				//    	    case MESSAGE_TYPE.PUBREC:
  				//    	    case MESSAGE_TYPE.PUBREL:
  				//    	    case MESSAGE_TYPE.PUBCOMP:
  				//    	    	break;
  
  			case MESSAGE_TYPE.SUBSCRIBE:
  				// SUBSCRIBE has a list of topic strings and request QoS
  				for (var i=0; i<this.topics.length; i++) {
  					pos = writeString(this.topics[i], topicStrLength[i], byteStream, pos);
  					byteStream[pos++] = this.requestedQos[i];
  				}
  				break;
  
  			case MESSAGE_TYPE.UNSUBSCRIBE:
  				// UNSUBSCRIBE has a list of topic strings
  				for (var i=0; i<this.topics.length; i++)
  					pos = writeString(this.topics[i], topicStrLength[i], byteStream, pos);
  				break;
  
  			default:
  				// Do nothing.
  			}
  
  			return buffer;
  		};
  
  		function decodeMessage(input,pos) {
  			var startingPos = pos;
  			var first = input[pos];
  			var type = first >> 4;
  			var messageInfo = first &= 0x0f;
  			pos += 1;
  
  
  			// Decode the remaining length (MBI format)
  
  			var digit;
  			var remLength = 0;
  			var multiplier = 1;
  			do {
  				if (pos == input.length) {
  					return [null,startingPos];
  				}
  				digit = input[pos++];
  				remLength += ((digit & 0x7F) * multiplier);
  				multiplier *= 128;
  			} while ((digit & 0x80) !== 0);
  
  			var endPos = pos+remLength;
  			if (endPos > input.length) {
  				return [null,startingPos];
  			}
  
  			var wireMessage = new WireMessage(type);
  			switch(type) {
  			case MESSAGE_TYPE.CONNACK:
  				var connectAcknowledgeFlags = input[pos++];
  				if (connectAcknowledgeFlags & 0x01)
  					wireMessage.sessionPresent = true;
  				wireMessage.returnCode = input[pos++];
  				break;
  
  			case MESSAGE_TYPE.PUBLISH:
  				var qos = (messageInfo >> 1) & 0x03;
  
  				var len = readUint16(input, pos);
  				pos += 2;
  				var topicName = parseUTF8(input, pos, len);
  				pos += len;
  				// If QoS 1 or 2 there will be a messageIdentifier
  				if (qos > 0) {
  					wireMessage.messageIdentifier = readUint16(input, pos);
  					pos += 2;
  				}
  
  				var message = new Message(input.subarray(pos, endPos));
  				if ((messageInfo & 0x01) == 0x01)
  					message.retained = true;
  				if ((messageInfo & 0x08) == 0x08)
  					message.duplicate =  true;
  				message.qos = qos;
  				message.destinationName = topicName;
  				wireMessage.payloadMessage = message;
  				break;
  
  			case  MESSAGE_TYPE.PUBACK:
  			case  MESSAGE_TYPE.PUBREC:
  			case  MESSAGE_TYPE.PUBREL:
  			case  MESSAGE_TYPE.PUBCOMP:
  			case  MESSAGE_TYPE.UNSUBACK:
  				wireMessage.messageIdentifier = readUint16(input, pos);
  				break;
  
  			case  MESSAGE_TYPE.SUBACK:
  				wireMessage.messageIdentifier = readUint16(input, pos);
  				pos += 2;
  				wireMessage.returnCode = input.subarray(pos, endPos);
  				break;
  
  			default:
  				break;
  			}
  
  			return [wireMessage,endPos];
  		}
  
  		function writeUint16(input, buffer, offset) {
  			buffer[offset++] = input >> 8;      //MSB
  			buffer[offset++] = input % 256;     //LSB
  			return offset;
  		}
  
  		function writeString(input, utf8Length, buffer, offset) {
  			offset = writeUint16(utf8Length, buffer, offset);
  			stringToUTF8(input, buffer, offset);
  			return offset + utf8Length;
  		}
  
  		function readUint16(buffer, offset) {
  			return 256*buffer[offset] + buffer[offset+1];
  		}
  
  		/**
  	 * Encodes an MQTT Multi-Byte Integer
  	 * @private
  	 */
  		function encodeMBI(number) {
  			var output = new Array(1);
  			var numBytes = 0;
  
  			do {
  				var digit = number % 128;
  				number = number >> 7;
  				if (number > 0) {
  					digit |= 0x80;
  				}
  				output[numBytes++] = digit;
  			} while ( (number > 0) && (numBytes<4) );
  
  			return output;
  		}
  
  		/**
  	 * Takes a String and calculates its length in bytes when encoded in UTF8.
  	 * @private
  	 */
  		function UTF8Length(input) {
  			var output = 0;
  			for (var i = 0; i<input.length; i++)
  			{
  				var charCode = input.charCodeAt(i);
  				if (charCode > 0x7FF)
  				{
  					// Surrogate pair means its a 4 byte character
  					if (0xD800 <= charCode && charCode <= 0xDBFF)
  					{
  						i++;
  						output++;
  					}
  					output +=3;
  				}
  				else if (charCode > 0x7F)
  					output +=2;
  				else
  					output++;
  			}
  			return output;
  		}
  
  		/**
  	 * Takes a String and writes it into an array as UTF8 encoded bytes.
  	 * @private
  	 */
  		function stringToUTF8(input, output, start) {
  			var pos = start;
  			for (var i = 0; i<input.length; i++) {
  				var charCode = input.charCodeAt(i);
  
  				// Check for a surrogate pair.
  				if (0xD800 <= charCode && charCode <= 0xDBFF) {
  					var lowCharCode = input.charCodeAt(++i);
  					if (isNaN(lowCharCode)) {
  						throw new Error(format(ERROR.MALFORMED_UNICODE, [charCode, lowCharCode]));
  					}
  					charCode = ((charCode - 0xD800)<<10) + (lowCharCode - 0xDC00) + 0x10000;
  
  				}
  
  				if (charCode <= 0x7F) {
  					output[pos++] = charCode;
  				} else if (charCode <= 0x7FF) {
  					output[pos++] = charCode>>6  & 0x1F | 0xC0;
  					output[pos++] = charCode     & 0x3F | 0x80;
  				} else if (charCode <= 0xFFFF) {
  					output[pos++] = charCode>>12 & 0x0F | 0xE0;
  					output[pos++] = charCode>>6  & 0x3F | 0x80;
  					output[pos++] = charCode     & 0x3F | 0x80;
  				} else {
  					output[pos++] = charCode>>18 & 0x07 | 0xF0;
  					output[pos++] = charCode>>12 & 0x3F | 0x80;
  					output[pos++] = charCode>>6  & 0x3F | 0x80;
  					output[pos++] = charCode     & 0x3F | 0x80;
  				}
  			}
  			return output;
  		}
  
  		function parseUTF8(input, offset, length) {
  			var output = "";
  			var utf16;
  			var pos = offset;
  
  			while (pos < offset+length)
  			{
  				var byte1 = input[pos++];
  				if (byte1 < 128)
  					utf16 = byte1;
  				else
  				{
  					var byte2 = input[pos++]-128;
  					if (byte2 < 0)
  						throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16),""]));
  					if (byte1 < 0xE0)             // 2 byte character
  						utf16 = 64*(byte1-0xC0) + byte2;
  					else
  					{
  						var byte3 = input[pos++]-128;
  						if (byte3 < 0)
  							throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16)]));
  						if (byte1 < 0xF0)        // 3 byte character
  							utf16 = 4096*(byte1-0xE0) + 64*byte2 + byte3;
  						else
  						{
  							var byte4 = input[pos++]-128;
  							if (byte4 < 0)
  								throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16), byte4.toString(16)]));
  							if (byte1 < 0xF8)        // 4 byte character
  								utf16 = 262144*(byte1-0xF0) + 4096*byte2 + 64*byte3 + byte4;
  							else                     // longer encodings are not supported
  								throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16), byte4.toString(16)]));
  						}
  					}
  				}
  
  				if (utf16 > 0xFFFF)   // 4 byte character - express as a surrogate pair
  				{
  					utf16 -= 0x10000;
  					output += String.fromCharCode(0xD800 + (utf16 >> 10)); // lead character
  					utf16 = 0xDC00 + (utf16 & 0x3FF);  // trail character
  				}
  				output += String.fromCharCode(utf16);
  			}
  			return output;
  		}
  
  		/**
  	 * Repeat keepalive requests, monitor responses.
  	 * @ignore
  	 */
  		var Pinger = function(client, keepAliveInterval) {
  			this._client = client;
  			this._keepAliveInterval = keepAliveInterval*1000;
  			this.isReset = false;
  
  			var pingReq = new WireMessage(MESSAGE_TYPE.PINGREQ).encode();
  
  			var doTimeout = function (pinger) {
  				return function () {
  					return doPing.apply(pinger);
  				};
  			};
  
  			/** @ignore */
  			var doPing = function() {
  				if (!this.isReset) {
  					this._client._trace("Pinger.doPing", "Timed out");
  					this._client._disconnected( ERROR.PING_TIMEOUT.code , format(ERROR.PING_TIMEOUT));
  				} else {
  					this.isReset = false;
  					this._client._trace("Pinger.doPing", "send PINGREQ");
  					this._client.socket.send(pingReq);
  					this.timeout = setTimeout(doTimeout(this), this._keepAliveInterval);
  				}
  			};
  
  			this.reset = function() {
  				this.isReset = true;
  				clearTimeout(this.timeout);
  				if (this._keepAliveInterval > 0)
  					this.timeout = setTimeout(doTimeout(this), this._keepAliveInterval);
  			};
  
  			this.cancel = function() {
  				clearTimeout(this.timeout);
  			};
  		};
  
  		/**
  	 * Monitor request completion.
  	 * @ignore
  	 */
  		var Timeout = function(client, timeoutSeconds, action, args) {
  			if (!timeoutSeconds)
  				timeoutSeconds = 30;
  
  			var doTimeout = function (action, client, args) {
  				return function () {
  					return action.apply(client, args);
  				};
  			};
  			this.timeout = setTimeout(doTimeout(action, client, args), timeoutSeconds * 1000);
  
  			this.cancel = function() {
  				clearTimeout(this.timeout);
  			};
  		};
  
  	/**
  	 * Internal implementation of the Websockets MQTT V3.1 client.
  	 *
  	 * @name Paho.ClientImpl @constructor
  	 * @param {String} host the DNS nameof the webSocket host.
  	 * @param {Number} port the port number for that host.
  	 * @param {String} clientId the MQ client identifier.
  	 */
  		var ClientImpl = function (uri, host, port, path, clientId) {
  		// Check dependencies are satisfied in this browser.
  			if (!("WebSocket" in global && global.WebSocket !== null)) {
  				throw new Error(format(ERROR.UNSUPPORTED, ["WebSocket"]));
  			}
  			if (!("ArrayBuffer" in global && global.ArrayBuffer !== null)) {
  				throw new Error(format(ERROR.UNSUPPORTED, ["ArrayBuffer"]));
  			}
  			this._trace("Paho.Client", uri, host, port, path, clientId);
  
  			this.host = host;
  			this.port = port;
  			this.path = path;
  			this.uri = uri;
  			this.clientId = clientId;
  			this._wsuri = null;
  
  			// Local storagekeys are qualified with the following string.
  			// The conditional inclusion of path in the key is for backward
  			// compatibility to when the path was not configurable and assumed to
  			// be /mqtt
  			this._localKey=host+":"+port+(path!="/mqtt"?":"+path:"")+":"+clientId+":";
  
  			// Create private instance-only message queue
  			// Internal queue of messages to be sent, in sending order.
  			this._msg_queue = [];
  			this._buffered_msg_queue = [];
  
  			// Messages we have sent and are expecting a response for, indexed by their respective message ids.
  			this._sentMessages = {};
  
  			// Messages we have received and acknowleged and are expecting a confirm message for
  			// indexed by their respective message ids.
  			this._receivedMessages = {};
  
  			// Internal list of callbacks to be executed when messages
  			// have been successfully sent over web socket, e.g. disconnect
  			// when it doesn't have to wait for ACK, just message is dispatched.
  			this._notify_msg_sent = {};
  
  			// Unique identifier for SEND messages, incrementing
  			// counter as messages are sent.
  			this._message_identifier = 1;
  
  			// Used to determine the transmission sequence of stored sent messages.
  			this._sequence = 0;
  
  
  			// Load the local state, if any, from the saved version, only restore state relevant to this client.
  			for (var key in localStorage)
  				if (   key.indexOf("Sent:"+this._localKey) === 0 || key.indexOf("Received:"+this._localKey) === 0)
  					this.restore(key);
  		};
  
  		// Messaging Client public instance members.
  		ClientImpl.prototype.host = null;
  		ClientImpl.prototype.port = null;
  		ClientImpl.prototype.path = null;
  		ClientImpl.prototype.uri = null;
  		ClientImpl.prototype.clientId = null;
  
  		// Messaging Client private instance members.
  		ClientImpl.prototype.socket = null;
  		/* true once we have received an acknowledgement to a CONNECT packet. */
  		ClientImpl.prototype.connected = false;
  		/* The largest message identifier allowed, may not be larger than 2**16 but
  		 * if set smaller reduces the maximum number of outbound messages allowed.
  		 */
  		ClientImpl.prototype.maxMessageIdentifier = 65536;
  		ClientImpl.prototype.connectOptions = null;
  		ClientImpl.prototype.hostIndex = null;
  		ClientImpl.prototype.onConnected = null;
  		ClientImpl.prototype.onConnectionLost = null;
  		ClientImpl.prototype.onMessageDelivered = null;
  		ClientImpl.prototype.onMessageArrived = null;
  		ClientImpl.prototype.traceFunction = null;
  		ClientImpl.prototype._msg_queue = null;
  		ClientImpl.prototype._buffered_msg_queue = null;
  		ClientImpl.prototype._connectTimeout = null;
  		/* The sendPinger monitors how long we allow before we send data to prove to the server that we are alive. */
  		ClientImpl.prototype.sendPinger = null;
  		/* The receivePinger monitors how long we allow before we require evidence that the server is alive. */
  		ClientImpl.prototype.receivePinger = null;
  		ClientImpl.prototype._reconnectInterval = 1; // Reconnect Delay, starts at 1 second
  		ClientImpl.prototype._reconnecting = false;
  		ClientImpl.prototype._reconnectTimeout = null;
  		ClientImpl.prototype.disconnectedPublishing = false;
  		ClientImpl.prototype.disconnectedBufferSize = 5000;
  
  		ClientImpl.prototype.receiveBuffer = null;
  
  		ClientImpl.prototype._traceBuffer = null;
  		ClientImpl.prototype._MAX_TRACE_ENTRIES = 100;
  
  		ClientImpl.prototype.connect = function (connectOptions) {
  			var connectOptionsMasked = this._traceMask(connectOptions, "password");
  			this._trace("Client.connect", connectOptionsMasked, this.socket, this.connected);
  
  			if (this.connected)
  				throw new Error(format(ERROR.INVALID_STATE, ["already connected"]));
  			if (this.socket)
  				throw new Error(format(ERROR.INVALID_STATE, ["already connected"]));
  
  			if (this._reconnecting) {
  			// connect() function is called while reconnect is in progress.
  			// Terminate the auto reconnect process to use new connect options.
  				this._reconnectTimeout.cancel();
  				this._reconnectTimeout = null;
  				this._reconnecting = false;
  			}
  
  			this.connectOptions = connectOptions;
  			this._reconnectInterval = 1;
  			this._reconnecting = false;
  			if (connectOptions.uris) {
  				this.hostIndex = 0;
  				this._doConnect(connectOptions.uris[0]);
  			} else {
  				this._doConnect(this.uri);
  			}
  
  		};
  
  		ClientImpl.prototype.subscribe = function (filter, subscribeOptions) {
  			this._trace("Client.subscribe", filter, subscribeOptions);
  
  			if (!this.connected)
  				throw new Error(format(ERROR.INVALID_STATE, ["not connected"]));
  
              var wireMessage = new WireMessage(MESSAGE_TYPE.SUBSCRIBE);
              wireMessage.topics = filter.constructor === Array ? filter : [filter];
              if (subscribeOptions.qos === undefined)
                  subscribeOptions.qos = 0;
              wireMessage.requestedQos = [];
              for (var i = 0; i < wireMessage.topics.length; i++)
                  wireMessage.requestedQos[i] = subscribeOptions.qos;
  
  			if (subscribeOptions.onSuccess) {
  				wireMessage.onSuccess = function(grantedQos) {subscribeOptions.onSuccess({invocationContext:subscribeOptions.invocationContext,grantedQos:grantedQos});};
  			}
  
  			if (subscribeOptions.onFailure) {
  				wireMessage.onFailure = function(errorCode) {subscribeOptions.onFailure({invocationContext:subscribeOptions.invocationContext,errorCode:errorCode, errorMessage:format(errorCode)});};
  			}
  
  			if (subscribeOptions.timeout) {
  				wireMessage.timeOut = new Timeout(this, subscribeOptions.timeout, subscribeOptions.onFailure,
  					[{invocationContext:subscribeOptions.invocationContext,
  						errorCode:ERROR.SUBSCRIBE_TIMEOUT.code,
  						errorMessage:format(ERROR.SUBSCRIBE_TIMEOUT)}]);
  			}
  
  			// All subscriptions return a SUBACK.
  			this._requires_ack(wireMessage);
  			this._schedule_message(wireMessage);
  		};
  
  		/** @ignore */
  		ClientImpl.prototype.unsubscribe = function(filter, unsubscribeOptions) {
  			this._trace("Client.unsubscribe", filter, unsubscribeOptions);
  
  			if (!this.connected)
  				throw new Error(format(ERROR.INVALID_STATE, ["not connected"]));
  
              var wireMessage = new WireMessage(MESSAGE_TYPE.UNSUBSCRIBE);
              wireMessage.topics = filter.constructor === Array ? filter : [filter];
  
  			if (unsubscribeOptions.onSuccess) {
  				wireMessage.callback = function() {unsubscribeOptions.onSuccess({invocationContext:unsubscribeOptions.invocationContext});};
  			}
  			if (unsubscribeOptions.timeout) {
  				wireMessage.timeOut = new Timeout(this, unsubscribeOptions.timeout, unsubscribeOptions.onFailure,
  					[{invocationContext:unsubscribeOptions.invocationContext,
  						errorCode:ERROR.UNSUBSCRIBE_TIMEOUT.code,
  						errorMessage:format(ERROR.UNSUBSCRIBE_TIMEOUT)}]);
  			}
  
  			// All unsubscribes return a SUBACK.
  			this._requires_ack(wireMessage);
  			this._schedule_message(wireMessage);
  		};
  
  		ClientImpl.prototype.send = function (message) {
  			this._trace("Client.send", message);
  
  			var wireMessage = new WireMessage(MESSAGE_TYPE.PUBLISH);
  			wireMessage.payloadMessage = message;
  
  			if (this.connected) {
  			// Mark qos 1 & 2 message as "ACK required"
  			// For qos 0 message, invoke onMessageDelivered callback if there is one.
  			// Then schedule the message.
  				if (message.qos > 0) {
  					this._requires_ack(wireMessage);
  				} else if (this.onMessageDelivered) {
  					this._notify_msg_sent[wireMessage] = this.onMessageDelivered(wireMessage.payloadMessage);
  				}
  				this._schedule_message(wireMessage);
  			} else {
  			// Currently disconnected, will not schedule this message
  			// Check if reconnecting is in progress and disconnected publish is enabled.
  				if (this._reconnecting && this.disconnectedPublishing) {
  				// Check the limit which include the "required ACK" messages
  					var messageCount = Object.keys(this._sentMessages).length + this._buffered_msg_queue.length;
  					if (messageCount > this.disconnectedBufferSize) {
  						throw new Error(format(ERROR.BUFFER_FULL, [this.disconnectedBufferSize]));
  					} else {
  						if (message.qos > 0) {
  						// Mark this message as "ACK required"
  							this._requires_ack(wireMessage);
  						} else {
  							wireMessage.sequence = ++this._sequence;
  							// Add messages in fifo order to array, by adding to start
  							this._buffered_msg_queue.unshift(wireMessage);
  						}
  					}
  				} else {
  					throw new Error(format(ERROR.INVALID_STATE, ["not connected"]));
  				}
  			}
  		};
  
  		ClientImpl.prototype.disconnect = function () {
  			this._trace("Client.disconnect");
  
  			if (this._reconnecting) {
  			// disconnect() function is called while reconnect is in progress.
  			// Terminate the auto reconnect process.
  				this._reconnectTimeout.cancel();
  				this._reconnectTimeout = null;
  				this._reconnecting = false;
  			}
  
  			if (!this.socket)
  				throw new Error(format(ERROR.INVALID_STATE, ["not connecting or connected"]));
  
  			var wireMessage = new WireMessage(MESSAGE_TYPE.DISCONNECT);
  
  			// Run the disconnected call back as soon as the message has been sent,
  			// in case of a failure later on in the disconnect processing.
  			// as a consequence, the _disconected call back may be run several times.
  			this._notify_msg_sent[wireMessage] = scope(this._disconnected, this);
  
  			this._schedule_message(wireMessage);
  		};
  
  		ClientImpl.prototype.getTraceLog = function () {
  			if ( this._traceBuffer !== null ) {
  				this._trace("Client.getTraceLog", new Date());
  				this._trace("Client.getTraceLog in flight messages", this._sentMessages.length);
  				for (var key in this._sentMessages)
  					this._trace("_sentMessages ",key, this._sentMessages[key]);
  				for (var key in this._receivedMessages)
  					this._trace("_receivedMessages ",key, this._receivedMessages[key]);
  
  				return this._traceBuffer;
  			}
  		};
  
  		ClientImpl.prototype.startTrace = function () {
  			if ( this._traceBuffer === null ) {
  				this._traceBuffer = [];
  			}
  			this._trace("Client.startTrace", new Date(), version);
  		};
  
  		ClientImpl.prototype.stopTrace = function () {
  			delete this._traceBuffer;
  		};
  
  		ClientImpl.prototype._doConnect = function (wsurl) {
  		// When the socket is open, this client will send the CONNECT WireMessage using the saved parameters.
  			if (this.connectOptions.useSSL) {
  				var uriParts = wsurl.split(":");
  				uriParts[0] = "wss";
  				wsurl = uriParts.join(":");
  			}
  			this._wsuri = wsurl;
  			this.connected = false;
  
  
  
  			if (this.connectOptions.mqttVersion < 4) {
  				this.socket = new WebSocket(wsurl, ["mqttv3.1"]);
  			} else {
  				this.socket = new WebSocket(wsurl, ["mqtt"]);
  			}
  			this.socket.binaryType = "arraybuffer";
  			this.socket.onopen = scope(this._on_socket_open, this);
  			this.socket.onmessage = scope(this._on_socket_message, this);
  			this.socket.onerror = scope(this._on_socket_error, this);
  			this.socket.onclose = scope(this._on_socket_close, this);
  
  			this.sendPinger = new Pinger(this, this.connectOptions.keepAliveInterval);
  			this.receivePinger = new Pinger(this, this.connectOptions.keepAliveInterval);
  			if (this._connectTimeout) {
  				this._connectTimeout.cancel();
  				this._connectTimeout = null;
  			}
  			this._connectTimeout = new Timeout(this, this.connectOptions.timeout, this._disconnected,  [ERROR.CONNECT_TIMEOUT.code, format(ERROR.CONNECT_TIMEOUT)]);
  		};
  
  
  		// Schedule a new message to be sent over the WebSockets
  		// connection. CONNECT messages cause WebSocket connection
  		// to be started. All other messages are queued internally
  		// until this has happened. When WS connection starts, process
  		// all outstanding messages.
  		ClientImpl.prototype._schedule_message = function (message) {
  			// Add messages in fifo order to array, by adding to start
  			this._msg_queue.unshift(message);
  			// Process outstanding messages in the queue if we have an  open socket, and have received CONNACK.
  			if (this.connected) {
  				this._process_queue();
  			}
  		};
  
  		ClientImpl.prototype.store = function(prefix, wireMessage) {
  			var storedMessage = {type:wireMessage.type, messageIdentifier:wireMessage.messageIdentifier, version:1};
  
  			switch(wireMessage.type) {
  			case MESSAGE_TYPE.PUBLISH:
  				if(wireMessage.pubRecReceived)
  					storedMessage.pubRecReceived = true;
  
  				// Convert the payload to a hex string.
  				storedMessage.payloadMessage = {};
  				var hex = "";
  				var messageBytes = wireMessage.payloadMessage.payloadBytes;
  				for (var i=0; i<messageBytes.length; i++) {
  					if (messageBytes[i] <= 0xF)
  						hex = hex+"0"+messageBytes[i].toString(16);
  					else
  						hex = hex+messageBytes[i].toString(16);
  				}
  				storedMessage.payloadMessage.payloadHex = hex;
  
  				storedMessage.payloadMessage.qos = wireMessage.payloadMessage.qos;
  				storedMessage.payloadMessage.destinationName = wireMessage.payloadMessage.destinationName;
  				if (wireMessage.payloadMessage.duplicate)
  					storedMessage.payloadMessage.duplicate = true;
  				if (wireMessage.payloadMessage.retained)
  					storedMessage.payloadMessage.retained = true;
  
  				// Add a sequence number to sent messages.
  				if ( prefix.indexOf("Sent:") === 0 ) {
  					if ( wireMessage.sequence === undefined )
  						wireMessage.sequence = ++this._sequence;
  					storedMessage.sequence = wireMessage.sequence;
  				}
  				break;
  
  			default:
  				throw Error(format(ERROR.INVALID_STORED_DATA, [prefix+this._localKey+wireMessage.messageIdentifier, storedMessage]));
  			}
  			localStorage.setItem(prefix+this._localKey+wireMessage.messageIdentifier, JSON.stringify(storedMessage));
  		};
  
  		ClientImpl.prototype.restore = function(key) {
  			var value = localStorage.getItem(key);
  			var storedMessage = JSON.parse(value);
  
  			var wireMessage = new WireMessage(storedMessage.type, storedMessage);
  
  			switch(storedMessage.type) {
  			case MESSAGE_TYPE.PUBLISH:
  				// Replace the payload message with a Message object.
  				var hex = storedMessage.payloadMessage.payloadHex;
  				var buffer = new ArrayBuffer((hex.length)/2);
  				var byteStream = new Uint8Array(buffer);
  				var i = 0;
  				while (hex.length >= 2) {
  					var x = parseInt(hex.substring(0, 2), 16);
  					hex = hex.substring(2, hex.length);
  					byteStream[i++] = x;
  				}
  				var payloadMessage = new Message(byteStream);
  
  				payloadMessage.qos = storedMessage.payloadMessage.qos;
  				payloadMessage.destinationName = storedMessage.payloadMessage.destinationName;
  				if (storedMessage.payloadMessage.duplicate)
  					payloadMessage.duplicate = true;
  				if (storedMessage.payloadMessage.retained)
  					payloadMessage.retained = true;
  				wireMessage.payloadMessage = payloadMessage;
  
  				break;
  
  			default:
  				throw Error(format(ERROR.INVALID_STORED_DATA, [key, value]));
  			}
  
  			if (key.indexOf("Sent:"+this._localKey) === 0) {
  				wireMessage.payloadMessage.duplicate = true;
  				this._sentMessages[wireMessage.messageIdentifier] = wireMessage;
  			} else if (key.indexOf("Received:"+this._localKey) === 0) {
  				this._receivedMessages[wireMessage.messageIdentifier] = wireMessage;
  			}
  		};
  
  		ClientImpl.prototype._process_queue = function () {
  			var message = null;
  
  			// Send all queued messages down socket connection
  			while ((message = this._msg_queue.pop())) {
  				this._socket_send(message);
  				// Notify listeners that message was successfully sent
  				if (this._notify_msg_sent[message]) {
  					this._notify_msg_sent[message]();
  					delete this._notify_msg_sent[message];
  				}
  			}
  		};
  
  		/**
  	 * Expect an ACK response for this message. Add message to the set of in progress
  	 * messages and set an unused identifier in this message.
  	 * @ignore
  	 */
  		ClientImpl.prototype._requires_ack = function (wireMessage) {
  			var messageCount = Object.keys(this._sentMessages).length;
  			if (messageCount > this.maxMessageIdentifier)
  				throw Error ("Too many messages:"+messageCount);
  
  			while(this._sentMessages[this._message_identifier] !== undefined) {
  				this._message_identifier++;
  			}
  			wireMessage.messageIdentifier = this._message_identifier;
  			this._sentMessages[wireMessage.messageIdentifier] = wireMessage;
  			if (wireMessage.type === MESSAGE_TYPE.PUBLISH) {
  				this.store("Sent:", wireMessage);
  			}
  			if (this._message_identifier === this.maxMessageIdentifier) {
  				this._message_identifier = 1;
  			}
  		};
  
  		/**
  	 * Called when the underlying websocket has been opened.
  	 * @ignore
  	 */
  		ClientImpl.prototype._on_socket_open = function () {
  		// Create the CONNECT message object.
  			var wireMessage = new WireMessage(MESSAGE_TYPE.CONNECT, this.connectOptions);
  			wireMessage.clientId = this.clientId;
  			this._socket_send(wireMessage);
  		};
  
  		/**
  	 * Called when the underlying websocket has received a complete packet.
  	 * @ignore
  	 */
  		ClientImpl.prototype._on_socket_message = function (event) {
  			this._trace("Client._on_socket_message", event.data);
  			var messages = this._deframeMessages(event.data);
  			for (var i = 0; i < messages.length; i+=1) {
  				this._handleMessage(messages[i]);
  			}
  		};
  
  		ClientImpl.prototype._deframeMessages = function(data) {
  			var byteArray = new Uint8Array(data);
  			var messages = [];
  			if (this.receiveBuffer) {
  				var newData = new Uint8Array(this.receiveBuffer.length+byteArray.length);
  				newData.set(this.receiveBuffer);
  				newData.set(byteArray,this.receiveBuffer.length);
  				byteArray = newData;
  				delete this.receiveBuffer;
  			}
  			try {
  				var offset = 0;
  				while(offset < byteArray.length) {
  					var result = decodeMessage(byteArray,offset);
  					var wireMessage = result[0];
  					offset = result[1];
  					if (wireMessage !== null) {
  						messages.push(wireMessage);
  					} else {
  						break;
  					}
  				}
  				if (offset < byteArray.length) {
  					this.receiveBuffer = byteArray.subarray(offset);
  				}
  			} catch (error) {
  				var errorStack = ((error.hasOwnProperty("stack") == "undefined") ? error.stack.toString() : "No Error Stack Available");
  				this._disconnected(ERROR.INTERNAL_ERROR.code , format(ERROR.INTERNAL_ERROR, [error.message,errorStack]));
  				return;
  			}
  			return messages;
  		};
  
  		ClientImpl.prototype._handleMessage = function(wireMessage) {
  
  			this._trace("Client._handleMessage", wireMessage);
  
  			try {
  				switch(wireMessage.type) {
  				case MESSAGE_TYPE.CONNACK:
  					this._connectTimeout.cancel();
  					if (this._reconnectTimeout)
  						this._reconnectTimeout.cancel();
  
  					// If we have started using clean session then clear up the local state.
  					if (this.connectOptions.cleanSession) {
  						for (var key in this._sentMessages) {
  							var sentMessage = this._sentMessages[key];
  							localStorage.removeItem("Sent:"+this._localKey+sentMessage.messageIdentifier);
  						}
  						this._sentMessages = {};
  
  						for (var key in this._receivedMessages) {
  							var receivedMessage = this._receivedMessages[key];
  							localStorage.removeItem("Received:"+this._localKey+receivedMessage.messageIdentifier);
  						}
  						this._receivedMessages = {};
  					}
  					// Client connected and ready for business.
  					if (wireMessage.returnCode === 0) {
  
  						this.connected = true;
  						// Jump to the end of the list of uris and stop looking for a good host.
  
  						if (this.connectOptions.uris)
  							this.hostIndex = this.connectOptions.uris.length;
  
  					} else {
  						this._disconnected(ERROR.CONNACK_RETURNCODE.code , format(ERROR.CONNACK_RETURNCODE, [wireMessage.returnCode, CONNACK_RC[wireMessage.returnCode]]));
  						break;
  					}
  
  					// Resend messages.
  					var sequencedMessages = [];
  					for (var msgId in this._sentMessages) {
  						if (this._sentMessages.hasOwnProperty(msgId))
  							sequencedMessages.push(this._sentMessages[msgId]);
  					}
  
  					// Also schedule qos 0 buffered messages if any
  					if (this._buffered_msg_queue.length > 0) {
  						var msg = null;
  						while ((msg = this._buffered_msg_queue.pop())) {
  							sequencedMessages.push(msg);
  							if (this.onMessageDelivered)
  								this._notify_msg_sent[msg] = this.onMessageDelivered(msg.payloadMessage);
  						}
  					}
  
  					// Sort sentMessages into the original sent order.
  					var sequencedMessages = sequencedMessages.sort(function(a,b) {return a.sequence - b.sequence;} );
  					for (var i=0, len=sequencedMessages.length; i<len; i++) {
  						var sentMessage = sequencedMessages[i];
  						if (sentMessage.type == MESSAGE_TYPE.PUBLISH && sentMessage.pubRecReceived) {
  							var pubRelMessage = new WireMessage(MESSAGE_TYPE.PUBREL, {messageIdentifier:sentMessage.messageIdentifier});
  							this._schedule_message(pubRelMessage);
  						} else {
  							this._schedule_message(sentMessage);
  						}
  					}
  
  					// Execute the connectOptions.onSuccess callback if there is one.
  					// Will also now return if this connection was the result of an automatic
  					// reconnect and which URI was successfully connected to.
  					if (this.connectOptions.onSuccess) {
  						this.connectOptions.onSuccess({invocationContext:this.connectOptions.invocationContext});
  					}
  
  					var reconnected = false;
  					if (this._reconnecting) {
  						reconnected = true;
  						this._reconnectInterval = 1;
  						this._reconnecting = false;
  					}
  
  					// Execute the onConnected callback if there is one.
  					this._connected(reconnected, this._wsuri);
  
  					// Process all queued messages now that the connection is established.
  					this._process_queue();
  					break;
  
  				case MESSAGE_TYPE.PUBLISH:
  					this._receivePublish(wireMessage);
  					break;
  
  				case MESSAGE_TYPE.PUBACK:
  					var sentMessage = this._sentMessages[wireMessage.messageIdentifier];
  					// If this is a re flow of a PUBACK after we have restarted receivedMessage will not exist.
  					if (sentMessage) {
  						delete this._sentMessages[wireMessage.messageIdentifier];
  						localStorage.removeItem("Sent:"+this._localKey+wireMessage.messageIdentifier);
  						if (this.onMessageDelivered)
  							this.onMessageDelivered(sentMessage.payloadMessage);
  					}
  					break;
  
  				case MESSAGE_TYPE.PUBREC:
  					var sentMessage = this._sentMessages[wireMessage.messageIdentifier];
  					// If this is a re flow of a PUBREC after we have restarted receivedMessage will not exist.
  					if (sentMessage) {
  						sentMessage.pubRecReceived = true;
  						var pubRelMessage = new WireMessage(MESSAGE_TYPE.PUBREL, {messageIdentifier:wireMessage.messageIdentifier});
  						this.store("Sent:", sentMessage);
  						this._schedule_message(pubRelMessage);
  					}
  					break;
  
  				case MESSAGE_TYPE.PUBREL:
  					var receivedMessage = this._receivedMessages[wireMessage.messageIdentifier];
  					localStorage.removeItem("Received:"+this._localKey+wireMessage.messageIdentifier);
  					// If this is a re flow of a PUBREL after we have restarted receivedMessage will not exist.
  					if (receivedMessage) {
  						this._receiveMessage(receivedMessage);
  						delete this._receivedMessages[wireMessage.messageIdentifier];
  					}
  					// Always flow PubComp, we may have previously flowed PubComp but the server lost it and restarted.
  					var pubCompMessage = new WireMessage(MESSAGE_TYPE.PUBCOMP, {messageIdentifier:wireMessage.messageIdentifier});
  					this._schedule_message(pubCompMessage);
  
  
  					break;
  
  				case MESSAGE_TYPE.PUBCOMP:
  					var sentMessage = this._sentMessages[wireMessage.messageIdentifier];
  					delete this._sentMessages[wireMessage.messageIdentifier];
  					localStorage.removeItem("Sent:"+this._localKey+wireMessage.messageIdentifier);
  					if (this.onMessageDelivered)
  						this.onMessageDelivered(sentMessage.payloadMessage);
  					break;
  
  				case MESSAGE_TYPE.SUBACK:
  					var sentMessage = this._sentMessages[wireMessage.messageIdentifier];
  					if (sentMessage) {
  						if(sentMessage.timeOut)
  							sentMessage.timeOut.cancel();
  						// This will need to be fixed when we add multiple topic support
  						if (wireMessage.returnCode[0] === 0x80) {
  							if (sentMessage.onFailure) {
  								sentMessage.onFailure(wireMessage.returnCode);
  							}
  						} else if (sentMessage.onSuccess) {
  							sentMessage.onSuccess(wireMessage.returnCode);
  						}
  						delete this._sentMessages[wireMessage.messageIdentifier];
  					}
  					break;
  
  				case MESSAGE_TYPE.UNSUBACK:
  					var sentMessage = this._sentMessages[wireMessage.messageIdentifier];
  					if (sentMessage) {
  						if (sentMessage.timeOut)
  							sentMessage.timeOut.cancel();
  						if (sentMessage.callback) {
  							sentMessage.callback();
  						}
  						delete this._sentMessages[wireMessage.messageIdentifier];
  					}
  
  					break;
  
  				case MESSAGE_TYPE.PINGRESP:
  				/* The sendPinger or receivePinger may have sent a ping, the receivePinger has already been reset. */
  					this.sendPinger.reset();
  					break;
  
  				case MESSAGE_TYPE.DISCONNECT:
  				// Clients do not expect to receive disconnect packets.
  					this._disconnected(ERROR.INVALID_MQTT_MESSAGE_TYPE.code , format(ERROR.INVALID_MQTT_MESSAGE_TYPE, [wireMessage.type]));
  					break;
  
  				default:
  					this._disconnected(ERROR.INVALID_MQTT_MESSAGE_TYPE.code , format(ERROR.INVALID_MQTT_MESSAGE_TYPE, [wireMessage.type]));
  				}
  			} catch (error) {
  				var errorStack = ((error.hasOwnProperty("stack") == "undefined") ? error.stack.toString() : "No Error Stack Available");
  				this._disconnected(ERROR.INTERNAL_ERROR.code , format(ERROR.INTERNAL_ERROR, [error.message,errorStack]));
  				return;
  			}
  		};
  
  		/** @ignore */
  		ClientImpl.prototype._on_socket_error = function (error) {
  			if (!this._reconnecting) {
  				this._disconnected(ERROR.SOCKET_ERROR.code , format(ERROR.SOCKET_ERROR, [error.data]));
  			}
  		};
  
  		/** @ignore */
  		ClientImpl.prototype._on_socket_close = function () {
  			if (!this._reconnecting) {
  				this._disconnected(ERROR.SOCKET_CLOSE.code , format(ERROR.SOCKET_CLOSE));
  			}
  		};
  
  		/** @ignore */
  		ClientImpl.prototype._socket_send = function (wireMessage) {
  
  			if (wireMessage.type == 1) {
  				var wireMessageMasked = this._traceMask(wireMessage, "password");
  				this._trace("Client._socket_send", wireMessageMasked);
  			}
  			else this._trace("Client._socket_send", wireMessage);
  
  			this.socket.send(wireMessage.encode());
  			/* We have proved to the server we are alive. */
  			this.sendPinger.reset();
  		};
  
  		/** @ignore */
  		ClientImpl.prototype._receivePublish = function (wireMessage) {
  			switch(wireMessage.payloadMessage.qos) {
  			case "undefined":
  			case 0:
  				this._receiveMessage(wireMessage);
  				break;
  
  			case 1:
  				var pubAckMessage = new WireMessage(MESSAGE_TYPE.PUBACK, {messageIdentifier:wireMessage.messageIdentifier});
  				this._schedule_message(pubAckMessage);
  				this._receiveMessage(wireMessage);
  				break;
  
  			case 2:
  				this._receivedMessages[wireMessage.messageIdentifier] = wireMessage;
  				this.store("Received:", wireMessage);
  				var pubRecMessage = new WireMessage(MESSAGE_TYPE.PUBREC, {messageIdentifier:wireMessage.messageIdentifier});
  				this._schedule_message(pubRecMessage);
  
  				break;
  
  			default:
  				throw Error("Invaild qos=" + wireMessage.payloadMessage.qos);
  			}
  		};
  
  		/** @ignore */
  		ClientImpl.prototype._receiveMessage = function (wireMessage) {
  			if (this.onMessageArrived) {
  				this.onMessageArrived(wireMessage.payloadMessage);
  			}
  		};
  
  		/**
  	 * Client has connected.
  	 * @param {reconnect} [boolean] indicate if this was a result of reconnect operation.
  	 * @param {uri} [string] fully qualified WebSocket URI of the server.
  	 */
  		ClientImpl.prototype._connected = function (reconnect, uri) {
  		// Execute the onConnected callback if there is one.
  			if (this.onConnected)
  				this.onConnected(reconnect, uri);
  		};
  
  		/**
  	 * Attempts to reconnect the client to the server.
     * For each reconnect attempt, will double the reconnect interval
     * up to 128 seconds.
  	 */
  		ClientImpl.prototype._reconnect = function () {
  			this._trace("Client._reconnect");
  			if (!this.connected) {
  				this._reconnecting = true;
  				this.sendPinger.cancel();
  				this.receivePinger.cancel();
  				if (this._reconnectInterval < 128)
  					this._reconnectInterval = this._reconnectInterval * 2;
  				if (this.connectOptions.uris) {
  					this.hostIndex = 0;
  					this._doConnect(this.connectOptions.uris[0]);
  				} else {
  					this._doConnect(this.uri);
  				}
  			}
  		};
  
  		/**
  	 * Client has disconnected either at its own request or because the server
  	 * or network disconnected it. Remove all non-durable state.
  	 * @param {errorCode} [number] the error number.
  	 * @param {errorText} [string] the error text.
  	 * @ignore
  	 */
  		ClientImpl.prototype._disconnected = function (errorCode, errorText) {
  			this._trace("Client._disconnected", errorCode, errorText);
  
  			if (errorCode !== undefined && this._reconnecting) {
  				//Continue automatic reconnect process
  				this._reconnectTimeout = new Timeout(this, this._reconnectInterval, this._reconnect);
  				return;
  			}
  
  			this.sendPinger.cancel();
  			this.receivePinger.cancel();
  			if (this._connectTimeout) {
  				this._connectTimeout.cancel();
  				this._connectTimeout = null;
  			}
  
  			// Clear message buffers.
  			this._msg_queue = [];
  			this._buffered_msg_queue = [];
  			this._notify_msg_sent = {};
  
  			if (this.socket) {
  			// Cancel all socket callbacks so that they cannot be driven again by this socket.
  				this.socket.onopen = null;
  				this.socket.onmessage = null;
  				this.socket.onerror = null;
  				this.socket.onclose = null;
  				if (this.socket.readyState === 1)
  					this.socket.close();
  				delete this.socket;
  			}
  
  			if (this.connectOptions.uris && this.hostIndex < this.connectOptions.uris.length-1) {
  			// Try the next host.
  				this.hostIndex++;
  				this._doConnect(this.connectOptions.uris[this.hostIndex]);
  			} else {
  
  				if (errorCode === undefined) {
  					errorCode = ERROR.OK.code;
  					errorText = format(ERROR.OK);
  				}
  
  				// Run any application callbacks last as they may attempt to reconnect and hence create a new socket.
  				if (this.connected) {
  					this.connected = false;
  					// Execute the connectionLostCallback if there is one, and we were connected.
  					if (this.onConnectionLost) {
  						this.onConnectionLost({errorCode:errorCode, errorMessage:errorText, reconnect:this.connectOptions.reconnect, uri:this._wsuri});
  					}
  					if (errorCode !== ERROR.OK.code && this.connectOptions.reconnect) {
  					// Start automatic reconnect process for the very first time since last successful connect.
  						this._reconnectInterval = 1;
  						this._reconnect();
  						return;
  					}
  				} else {
  				// Otherwise we never had a connection, so indicate that the connect has failed.
  					if (this.connectOptions.mqttVersion === 4 && this.connectOptions.mqttVersionExplicit === false) {
  						this._trace("Failed to connect V4, dropping back to V3");
  						this.connectOptions.mqttVersion = 3;
  						if (this.connectOptions.uris) {
  							this.hostIndex = 0;
  							this._doConnect(this.connectOptions.uris[0]);
  						} else {
  							this._doConnect(this.uri);
  						}
  					} else if(this.connectOptions.onFailure) {
  						this.connectOptions.onFailure({invocationContext:this.connectOptions.invocationContext, errorCode:errorCode, errorMessage:errorText});
  					}
  				}
  			}
  		};
  
  		/** @ignore */
  		ClientImpl.prototype._trace = function () {
  		// Pass trace message back to client's callback function
  			if (this.traceFunction) {
  				var args = Array.prototype.slice.call(arguments);
  				for (var i in args)
  				{
  					if (typeof args[i] !== "undefined")
  						args.splice(i, 1, JSON.stringify(args[i]));
  				}
  				var record = args.join("");
  				this.traceFunction ({severity: "Debug", message: record	});
  			}
  
  			//buffer style trace
  			if ( this._traceBuffer !== null ) {
  				for (var i = 0, max = arguments.length; i < max; i++) {
  					if ( this._traceBuffer.length == this._MAX_TRACE_ENTRIES ) {
  						this._traceBuffer.shift();
  					}
  					if (i === 0) this._traceBuffer.push(arguments[i]);
  					else if (typeof arguments[i] === "undefined" ) this._traceBuffer.push(arguments[i]);
  					else this._traceBuffer.push("  "+JSON.stringify(arguments[i]));
  				}
  			}
  		};
  
  		/** @ignore */
  		ClientImpl.prototype._traceMask = function (traceObject, masked) {
  			var traceObjectMasked = {};
  			for (var attr in traceObject) {
  				if (traceObject.hasOwnProperty(attr)) {
  					if (attr == masked)
  						traceObjectMasked[attr] = "******";
  					else
  						traceObjectMasked[attr] = traceObject[attr];
  				}
  			}
  			return traceObjectMasked;
  		};
  
  		// ------------------------------------------------------------------------
  		// Public Programming interface.
  		// ------------------------------------------------------------------------
  
  		/**
  	 * The JavaScript application communicates to the server using a {@link Paho.Client} object.
  	 * <p>
  	 * Most applications will create just one Client object and then call its connect() method,
  	 * however applications can create more than one Client object if they wish.
  	 * In this case the combination of host, port and clientId attributes must be different for each Client object.
  	 * <p>
  	 * The send, subscribe and unsubscribe methods are implemented as asynchronous JavaScript methods
  	 * (even though the underlying protocol exchange might be synchronous in nature).
  	 * This means they signal their completion by calling back to the application,
  	 * via Success or Failure callback functions provided by the application on the method in question.
  	 * Such callbacks are called at most once per method invocation and do not persist beyond the lifetime
  	 * of the script that made the invocation.
  	 * <p>
  	 * In contrast there are some callback functions, most notably <i>onMessageArrived</i>,
  	 * that are defined on the {@link Paho.Client} object.
  	 * These may get called multiple times, and aren't directly related to specific method invocations made by the client.
  	 *
  	 * @name Paho.Client
  	 *
  	 * @constructor
  	 *
  	 * @param {string} host - the address of the messaging server, as a fully qualified WebSocket URI, as a DNS name or dotted decimal IP address.
  	 * @param {number} port - the port number to connect to - only required if host is not a URI
  	 * @param {string} path - the path on the host to connect to - only used if host is not a URI. Default: '/mqtt'.
  	 * @param {string} clientId - the Messaging client identifier, between 1 and 23 characters in length.
  	 *
  	 * @property {string} host - <i>read only</i> the server's DNS hostname or dotted decimal IP address.
  	 * @property {number} port - <i>read only</i> the server's port.
  	 * @property {string} path - <i>read only</i> the server's path.
  	 * @property {string} clientId - <i>read only</i> used when connecting to the server.
  	 * @property {function} onConnectionLost - called when a connection has been lost.
  	 *                            after a connect() method has succeeded.
  	 *                            Establish the call back used when a connection has been lost. The connection may be
  	 *                            lost because the client initiates a disconnect or because the server or network
  	 *                            cause the client to be disconnected. The disconnect call back may be called without
  	 *                            the connectionComplete call back being invoked if, for example the client fails to
  	 *                            connect.
  	 *                            A single response object parameter is passed to the onConnectionLost callback containing the following fields:
  	 *                            <ol>
  	 *                            <li>errorCode
  	 *                            <li>errorMessage
  	 *                            </ol>
  	 * @property {function} onMessageDelivered - called when a message has been delivered.
  	 *                            All processing that this Client will ever do has been completed. So, for example,
  	 *                            in the case of a Qos=2 message sent by this client, the PubComp flow has been received from the server
  	 *                            and the message has been removed from persistent storage before this callback is invoked.
  	 *                            Parameters passed to the onMessageDelivered callback are:
  	 *                            <ol>
  	 *                            <li>{@link Paho.Message} that was delivered.
  	 *                            </ol>
  	 * @property {function} onMessageArrived - called when a message has arrived in this Paho.client.
  	 *                            Parameters passed to the onMessageArrived callback are:
  	 *                            <ol>
  	 *                            <li>{@link Paho.Message} that has arrived.
  	 *                            </ol>
  	 * @property {function} onConnected - called when a connection is successfully made to the server.
  	 *                                  after a connect() method.
  	 *                                  Parameters passed to the onConnected callback are:
  	 *                                  <ol>
  	 *                                  <li>reconnect (boolean) - If true, the connection was the result of a reconnect.</li>
  	 *                                  <li>URI (string) - The URI used to connect to the server.</li>
  	 *                                  </ol>
  	 * @property {boolean} disconnectedPublishing - if set, will enable disconnected publishing in
  	 *                                            in the event that the connection to the server is lost.
  	 * @property {number} disconnectedBufferSize - Used to set the maximum number of messages that the disconnected
  	 *                                             buffer will hold before rejecting new messages. Default size: 5000 messages
  	 * @property {function} trace - called whenever trace is called. TODO
  	 */
  		var Client = function (host, port, path, clientId) {
  
  			var uri;
  
  			if (typeof host !== "string")
  				throw new Error(format(ERROR.INVALID_TYPE, [typeof host, "host"]));
  
  			if (arguments.length == 2) {
  			// host: must be full ws:// uri
  			// port: clientId
  				clientId = port;
  				uri = host;
  				var match = uri.match(/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/);
  				if (match) {
  					host = match[4]||match[2];
  					port = parseInt(match[7]);
  					path = match[8];
  				} else {
  					throw new Error(format(ERROR.INVALID_ARGUMENT,[host,"host"]));
  				}
  			} else {
  				if (arguments.length == 3) {
  					clientId = path;
  					path = "/mqtt";
  				}
  				if (typeof port !== "number" || port < 0)
  					throw new Error(format(ERROR.INVALID_TYPE, [typeof port, "port"]));
  				if (typeof path !== "string")
  					throw new Error(format(ERROR.INVALID_TYPE, [typeof path, "path"]));
  
  				var ipv6AddSBracket = (host.indexOf(":") !== -1 && host.slice(0,1) !== "[" && host.slice(-1) !== "]");
  				uri = "ws://"+(ipv6AddSBracket?"["+host+"]":host)+":"+port+path;
  			}
  
  			var clientIdLength = 0;
  			for (var i = 0; i<clientId.length; i++) {
  				var charCode = clientId.charCodeAt(i);
  				if (0xD800 <= charCode && charCode <= 0xDBFF)  {
  					i++; // Surrogate pair.
  				}
  				clientIdLength++;
  			}
  			if (typeof clientId !== "string" || clientIdLength > 65535)
  				throw new Error(format(ERROR.INVALID_ARGUMENT, [clientId, "clientId"]));
  
  			var client = new ClientImpl(uri, host, port, path, clientId);
  
  			//Public Properties
  			Object.defineProperties(this,{
  				"host":{
  					get: function() { return host; },
  					set: function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }
  				},
  				"port":{
  					get: function() { return port; },
  					set: function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }
  				},
  				"path":{
  					get: function() { return path; },
  					set: function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }
  				},
  				"uri":{
  					get: function() { return uri; },
  					set: function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }
  				},
  				"clientId":{
  					get: function() { return client.clientId; },
  					set: function() { throw new Error(format(ERROR.UNSUPPORTED_OPERATION)); }
  				},
  				"onConnected":{
  					get: function() { return client.onConnected; },
  					set: function(newOnConnected) {
  						if (typeof newOnConnected === "function")
  							client.onConnected = newOnConnected;
  						else
  							throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnConnected, "onConnected"]));
  					}
  				},
  				"disconnectedPublishing":{
  					get: function() { return client.disconnectedPublishing; },
  					set: function(newDisconnectedPublishing) {
  						client.disconnectedPublishing = newDisconnectedPublishing;
  					}
  				},
  				"disconnectedBufferSize":{
  					get: function() { return client.disconnectedBufferSize; },
  					set: function(newDisconnectedBufferSize) {
  						client.disconnectedBufferSize = newDisconnectedBufferSize;
  					}
  				},
  				"onConnectionLost":{
  					get: function() { return client.onConnectionLost; },
  					set: function(newOnConnectionLost) {
  						if (typeof newOnConnectionLost === "function")
  							client.onConnectionLost = newOnConnectionLost;
  						else
  							throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnConnectionLost, "onConnectionLost"]));
  					}
  				},
  				"onMessageDelivered":{
  					get: function() { return client.onMessageDelivered; },
  					set: function(newOnMessageDelivered) {
  						if (typeof newOnMessageDelivered === "function")
  							client.onMessageDelivered = newOnMessageDelivered;
  						else
  							throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnMessageDelivered, "onMessageDelivered"]));
  					}
  				},
  				"onMessageArrived":{
  					get: function() { return client.onMessageArrived; },
  					set: function(newOnMessageArrived) {
  						if (typeof newOnMessageArrived === "function")
  							client.onMessageArrived = newOnMessageArrived;
  						else
  							throw new Error(format(ERROR.INVALID_TYPE, [typeof newOnMessageArrived, "onMessageArrived"]));
  					}
  				},
  				"trace":{
  					get: function() { return client.traceFunction; },
  					set: function(trace) {
  						if(typeof trace === "function"){
  							client.traceFunction = trace;
  						}else{
  							throw new Error(format(ERROR.INVALID_TYPE, [typeof trace, "onTrace"]));
  						}
  					}
  				},
  			});
  
  			/**
  		 * Connect this Messaging client to its server.
  		 *
  		 * @name Paho.Client#connect
  		 * @function
  		 * @param {object} connectOptions - Attributes used with the connection.
  		 * @param {number} connectOptions.timeout - If the connect has not succeeded within this
  		 *                    number of seconds, it is deemed to have failed.
  		 *                    The default is 30 seconds.
  		 * @param {string} connectOptions.userName - Authentication username for this connection.
  		 * @param {string} connectOptions.password - Authentication password for this connection.
  		 * @param {Paho.Message} connectOptions.willMessage - sent by the server when the client
  		 *                    disconnects abnormally.
  		 * @param {number} connectOptions.keepAliveInterval - the server disconnects this client if
  		 *                    there is no activity for this number of seconds.
  		 *                    The default value of 60 seconds is assumed if not set.
  		 * @param {boolean} connectOptions.cleanSession - if true(default) the client and server
  		 *                    persistent state is deleted on successful connect.
  		 * @param {boolean} connectOptions.useSSL - if present and true, use an SSL Websocket connection.
  		 * @param {object} connectOptions.invocationContext - passed to the onSuccess callback or onFailure callback.
  		 * @param {function} connectOptions.onSuccess - called when the connect acknowledgement
  		 *                    has been received from the server.
  		 * A single response object parameter is passed to the onSuccess callback containing the following fields:
  		 * <ol>
  		 * <li>invocationContext as passed in to the onSuccess method in the connectOptions.
  		 * </ol>
  	 * @param {function} connectOptions.onFailure - called when the connect request has failed or timed out.
  		 * A single response object parameter is passed to the onFailure callback containing the following fields:
  		 * <ol>
  		 * <li>invocationContext as passed in to the onFailure method in the connectOptions.
  		 * <li>errorCode a number indicating the nature of the error.
  		 * <li>errorMessage text describing the error.
  		 * </ol>
  	 * @param {array} connectOptions.hosts - If present this contains either a set of hostnames or fully qualified
  		 * WebSocket URIs (ws://iot.eclipse.org:80/ws), that are tried in order in place
  		 * of the host and port paramater on the construtor. The hosts are tried one at at time in order until
  		 * one of then succeeds.
  	 * @param {array} connectOptions.ports - If present the set of ports matching the hosts. If hosts contains URIs, this property
  		 * is not used.
  	 * @param {boolean} connectOptions.reconnect - Sets whether the client will automatically attempt to reconnect
  	 * to the server if the connection is lost.
  	 *<ul>
  	 *<li>If set to false, the client will not attempt to automatically reconnect to the server in the event that the
  	 * connection is lost.</li>
  	 *<li>If set to true, in the event that the connection is lost, the client will attempt to reconnect to the server.
  	 * It will initially wait 1 second before it attempts to reconnect, for every failed reconnect attempt, the delay
  	 * will double until it is at 2 minutes at which point the delay will stay at 2 minutes.</li>
  	 *</ul>
  	 * @param {number} connectOptions.mqttVersion - The version of MQTT to use to connect to the MQTT Broker.
  	 *<ul>
  	 *<li>3 - MQTT V3.1</li>
  	 *<li>4 - MQTT V3.1.1</li>
  	 *</ul>
  	 * @param {boolean} connectOptions.mqttVersionExplicit - If set to true, will force the connection to use the
  	 * selected MQTT Version or will fail to connect.
  	 * @param {array} connectOptions.uris - If present, should contain a list of fully qualified WebSocket uris
  	 * (e.g. ws://iot.eclipse.org:80/ws), that are tried in order in place of the host and port parameter of the construtor.
  	 * The uris are tried one at a time in order until one of them succeeds. Do not use this in conjunction with hosts as
  	 * the hosts array will be converted to uris and will overwrite this property.
  		 * @throws {InvalidState} If the client is not in disconnected state. The client must have received connectionLost
  		 * or disconnected before calling connect for a second or subsequent time.
  		 */
  			this.connect = function (connectOptions) {
  				connectOptions = connectOptions || {} ;
  				validate(connectOptions,  {timeout:"number",
  					userName:"string",
  					password:"string",
  					willMessage:"object",
  					keepAliveInterval:"number",
  					cleanSession:"boolean",
  					useSSL:"boolean",
  					invocationContext:"object",
  					onSuccess:"function",
  					onFailure:"function",
  					hosts:"object",
  					ports:"object",
  					reconnect:"boolean",
  					mqttVersion:"number",
  					mqttVersionExplicit:"boolean",
  					uris: "object"});
  
  				// If no keep alive interval is set, assume 60 seconds.
  				if (connectOptions.keepAliveInterval === undefined)
  					connectOptions.keepAliveInterval = 60;
  
  				if (connectOptions.mqttVersion > 4 || connectOptions.mqttVersion < 3) {
  					throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.mqttVersion, "connectOptions.mqttVersion"]));
  				}
  
  				if (connectOptions.mqttVersion === undefined) {
  					connectOptions.mqttVersionExplicit = false;
  					connectOptions.mqttVersion = 4;
  				} else {
  					connectOptions.mqttVersionExplicit = true;
  				}
  
  				//Check that if password is set, so is username
  				if (connectOptions.password !== undefined && connectOptions.userName === undefined)
  					throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.password, "connectOptions.password"]));
  
  				if (connectOptions.willMessage) {
  					if (!(connectOptions.willMessage instanceof Message))
  						throw new Error(format(ERROR.INVALID_TYPE, [connectOptions.willMessage, "connectOptions.willMessage"]));
  					// The will message must have a payload that can be represented as a string.
  					// Cause the willMessage to throw an exception if this is not the case.
  					connectOptions.willMessage.stringPayload = null;
  
  					if (typeof connectOptions.willMessage.destinationName === "undefined")
  						throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.willMessage.destinationName, "connectOptions.willMessage.destinationName"]));
  				}
  				if (typeof connectOptions.cleanSession === "undefined")
  					connectOptions.cleanSession = true;
  				if (connectOptions.hosts) {
  
  					if (!(connectOptions.hosts instanceof Array) )
  						throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts, "connectOptions.hosts"]));
  					if (connectOptions.hosts.length <1 )
  						throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts, "connectOptions.hosts"]));
  
  					var usingURIs = false;
  					for (var i = 0; i<connectOptions.hosts.length; i++) {
  						if (typeof connectOptions.hosts[i] !== "string")
  							throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.hosts[i], "connectOptions.hosts["+i+"]"]));
  						if (/^(wss?):\/\/((\[(.+)\])|([^\/]+?))(:(\d+))?(\/.*)$/.test(connectOptions.hosts[i])) {
  							if (i === 0) {
  								usingURIs = true;
  							} else if (!usingURIs) {
  								throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts[i], "connectOptions.hosts["+i+"]"]));
  							}
  						} else if (usingURIs) {
  							throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.hosts[i], "connectOptions.hosts["+i+"]"]));
  						}
  					}
  
  					if (!usingURIs) {
  						if (!connectOptions.ports)
  							throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, "connectOptions.ports"]));
  						if (!(connectOptions.ports instanceof Array) )
  							throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, "connectOptions.ports"]));
  						if (connectOptions.hosts.length !== connectOptions.ports.length)
  							throw new Error(format(ERROR.INVALID_ARGUMENT, [connectOptions.ports, "connectOptions.ports"]));
  
  						connectOptions.uris = [];
  
  						for (var i = 0; i<connectOptions.hosts.length; i++) {
  							if (typeof connectOptions.ports[i] !== "number" || connectOptions.ports[i] < 0)
  								throw new Error(format(ERROR.INVALID_TYPE, [typeof connectOptions.ports[i], "connectOptions.ports["+i+"]"]));
  							var host = connectOptions.hosts[i];
  							var port = connectOptions.ports[i];
  
  							var ipv6 = (host.indexOf(":") !== -1);
  							uri = "ws://"+(ipv6?"["+host+"]":host)+":"+port+path;
  							connectOptions.uris.push(uri);
  						}
  					} else {
  						connectOptions.uris = connectOptions.hosts;
  					}
  				}
  
  				client.connect(connectOptions);
  			};
  
  			/**
  		 * Subscribe for messages, request receipt of a copy of messages sent to the destinations described by the filter.
  		 *
  		 * @name Paho.Client#subscribe
  		 * @function
  		 * @param {string} filter describing the destinations to receive messages from.
  		 * <br>
  		 * @param {object} subscribeOptions - used to control the subscription
  		 *
  		 * @param {number} subscribeOptions.qos - the maximum qos of any publications sent
  		 *                                  as a result of making this subscription.
  		 * @param {object} subscribeOptions.invocationContext - passed to the onSuccess callback
  		 *                                  or onFailure callback.
  		 * @param {function} subscribeOptions.onSuccess - called when the subscribe acknowledgement
  		 *                                  has been received from the server.
  		 *                                  A single response object parameter is passed to the onSuccess callback containing the following fields:
  		 *                                  <ol>
  		 *                                  <li>invocationContext if set in the subscribeOptions.
  		 *                                  </ol>
  		 * @param {function} subscribeOptions.onFailure - called when the subscribe request has failed or timed out.
  		 *                                  A single response object parameter is passed to the onFailure callback containing the following fields:
  		 *                                  <ol>
  		 *                                  <li>invocationContext - if set in the subscribeOptions.
  		 *                                  <li>errorCode - a number indicating the nature of the error.
  		 *                                  <li>errorMessage - text describing the error.
  		 *                                  </ol>
  		 * @param {number} subscribeOptions.timeout - which, if present, determines the number of
  		 *                                  seconds after which the onFailure calback is called.
  		 *                                  The presence of a timeout does not prevent the onSuccess
  		 *                                  callback from being called when the subscribe completes.
  		 * @throws {InvalidState} if the client is not in connected state.
  		 */
  			this.subscribe = function (filter, subscribeOptions) {
  				if (typeof filter !== "string" && filter.constructor !== Array)
  					throw new Error("Invalid argument:"+filter);
  				subscribeOptions = subscribeOptions || {} ;
  				validate(subscribeOptions,  {qos:"number",
  					invocationContext:"object",
  					onSuccess:"function",
  					onFailure:"function",
  					timeout:"number"
  				});
  				if (subscribeOptions.timeout && !subscribeOptions.onFailure)
  					throw new Error("subscribeOptions.timeout specified with no onFailure callback.");
  				if (typeof subscribeOptions.qos !== "undefined" && !(subscribeOptions.qos === 0 || subscribeOptions.qos === 1 || subscribeOptions.qos === 2 ))
  					throw new Error(format(ERROR.INVALID_ARGUMENT, [subscribeOptions.qos, "subscribeOptions.qos"]));
  				client.subscribe(filter, subscribeOptions);
  			};
  
  		/**
  		 * Unsubscribe for messages, stop receiving messages sent to destinations described by the filter.
  		 *
  		 * @name Paho.Client#unsubscribe
  		 * @function
  		 * @param {string} filter - describing the destinations to receive messages from.
  		 * @param {object} unsubscribeOptions - used to control the subscription
  		 * @param {object} unsubscribeOptions.invocationContext - passed to the onSuccess callback
  											  or onFailure callback.
  		 * @param {function} unsubscribeOptions.onSuccess - called when the unsubscribe acknowledgement has been received from the server.
  		 *                                    A single response object parameter is passed to the
  		 *                                    onSuccess callback containing the following fields:
  		 *                                    <ol>
  		 *                                    <li>invocationContext - if set in the unsubscribeOptions.
  		 *                                    </ol>
  		 * @param {function} unsubscribeOptions.onFailure called when the unsubscribe request has failed or timed out.
  		 *                                    A single response object parameter is passed to the onFailure callback containing the following fields:
  		 *                                    <ol>
  		 *                                    <li>invocationContext - if set in the unsubscribeOptions.
  		 *                                    <li>errorCode - a number indicating the nature of the error.
  		 *                                    <li>errorMessage - text describing the error.
  		 *                                    </ol>
  		 * @param {number} unsubscribeOptions.timeout - which, if present, determines the number of seconds
  		 *                                    after which the onFailure callback is called. The presence of
  		 *                                    a timeout does not prevent the onSuccess callback from being
  		 *                                    called when the unsubscribe completes
  		 * @throws {InvalidState} if the client is not in connected state.
  		 */
  			this.unsubscribe = function (filter, unsubscribeOptions) {
  				if (typeof filter !== "string" && filter.constructor !== Array)
  					throw new Error("Invalid argument:"+filter);
  				unsubscribeOptions = unsubscribeOptions || {} ;
  				validate(unsubscribeOptions,  {invocationContext:"object",
  					onSuccess:"function",
  					onFailure:"function",
  					timeout:"number"
  				});
  				if (unsubscribeOptions.timeout && !unsubscribeOptions.onFailure)
  					throw new Error("unsubscribeOptions.timeout specified with no onFailure callback.");
  				client.unsubscribe(filter, unsubscribeOptions);
  			};
  
  			/**
  		 * Send a message to the consumers of the destination in the Message.
  		 *
  		 * @name Paho.Client#send
  		 * @function
  		 * @param {string|Paho.Message} topic - <b>mandatory</b> The name of the destination to which the message is to be sent.
  		 * 					   - If it is the only parameter, used as Paho.Message object.
  		 * @param {String|ArrayBuffer} payload - The message data to be sent.
  		 * @param {number} qos The Quality of Service used to deliver the message.
  		 * 		<dl>
  		 * 			<dt>0 Best effort (default).
  		 *     			<dt>1 At least once.
  		 *     			<dt>2 Exactly once.
  		 * 		</dl>
  		 * @param {Boolean} retained If true, the message is to be retained by the server and delivered
  		 *                     to both current and future subscriptions.
  		 *                     If false the server only delivers the message to current subscribers, this is the default for new Messages.
  		 *                     A received message has the retained boolean set to true if the message was published
  		 *                     with the retained boolean set to true
  		 *                     and the subscrption was made after the message has been published.
  		 * @throws {InvalidState} if the client is not connected.
  		 */
  			this.send = function (topic,payload,qos,retained) {
  				var message ;
  
  				if(arguments.length === 0){
  					throw new Error("Invalid argument."+"length");
  
  				}else if(arguments.length == 1) {
  
  					if (!(topic instanceof Message) && (typeof topic !== "string"))
  						throw new Error("Invalid argument:"+ typeof topic);
  
  					message = topic;
  					if (typeof message.destinationName === "undefined")
  						throw new Error(format(ERROR.INVALID_ARGUMENT,[message.destinationName,"Message.destinationName"]));
  					client.send(message);
  
  				}else {
  				//parameter checking in Message object
  					message = new Message(payload);
  					message.destinationName = topic;
  					if(arguments.length >= 3)
  						message.qos = qos;
  					if(arguments.length >= 4)
  						message.retained = retained;
  					client.send(message);
  				}
  			};
  
  			/**
  		 * Publish a message to the consumers of the destination in the Message.
  		 * Synonym for Paho.Mqtt.Client#send
  		 *
  		 * @name Paho.Client#publish
  		 * @function
  		 * @param {string|Paho.Message} topic - <b>mandatory</b> The name of the topic to which the message is to be published.
  		 * 					   - If it is the only parameter, used as Paho.Message object.
  		 * @param {String|ArrayBuffer} payload - The message data to be published.
  		 * @param {number} qos The Quality of Service used to deliver the message.
  		 * 		<dl>
  		 * 			<dt>0 Best effort (default).
  		 *     			<dt>1 At least once.
  		 *     			<dt>2 Exactly once.
  		 * 		</dl>
  		 * @param {Boolean} retained If true, the message is to be retained by the server and delivered
  		 *                     to both current and future subscriptions.
  		 *                     If false the server only delivers the message to current subscribers, this is the default for new Messages.
  		 *                     A received message has the retained boolean set to true if the message was published
  		 *                     with the retained boolean set to true
  		 *                     and the subscrption was made after the message has been published.
  		 * @throws {InvalidState} if the client is not connected.
  		 */
  			this.publish = function(topic,payload,qos,retained) {
  				var message ;
  
  				if(arguments.length === 0){
  					throw new Error("Invalid argument."+"length");
  
  				}else if(arguments.length == 1) {
  
  					if (!(topic instanceof Message) && (typeof topic !== "string"))
  						throw new Error("Invalid argument:"+ typeof topic);
  
  					message = topic;
  					if (typeof message.destinationName === "undefined")
  						throw new Error(format(ERROR.INVALID_ARGUMENT,[message.destinationName,"Message.destinationName"]));
  					client.send(message);
  
  				}else {
  					//parameter checking in Message object
  					message = new Message(payload);
  					message.destinationName = topic;
  					if(arguments.length >= 3)
  						message.qos = qos;
  					if(arguments.length >= 4)
  						message.retained = retained;
  					client.send(message);
  				}
  			};
  
  			/**
  		 * Normal disconnect of this Messaging client from its server.
  		 *
  		 * @name Paho.Client#disconnect
  		 * @function
  		 * @throws {InvalidState} if the client is already disconnected.
  		 */
  			this.disconnect = function () {
  				client.disconnect();
  			};
  
  			/**
  		 * Get the contents of the trace log.
  		 *
  		 * @name Paho.Client#getTraceLog
  		 * @function
  		 * @return {Object[]} tracebuffer containing the time ordered trace records.
  		 */
  			this.getTraceLog = function () {
  				return client.getTraceLog();
  			};
  
  			/**
  		 * Start tracing.
  		 *
  		 * @name Paho.Client#startTrace
  		 * @function
  		 */
  			this.startTrace = function () {
  				client.startTrace();
  			};
  
  			/**
  		 * Stop tracing.
  		 *
  		 * @name Paho.Client#stopTrace
  		 * @function
  		 */
  			this.stopTrace = function () {
  				client.stopTrace();
  			};
  
  			this.isConnected = function() {
  				return client.connected;
  			};
  		};
  
  		/**
  	 * An application message, sent or received.
  	 * <p>
  	 * All attributes may be null, which implies the default values.
  	 *
  	 * @name Paho.Message
  	 * @constructor
  	 * @param {String|ArrayBuffer} payload The message data to be sent.
  	 * <p>
  	 * @property {string} payloadString <i>read only</i> The payload as a string if the payload consists of valid UTF-8 characters.
  	 * @property {ArrayBuffer} payloadBytes <i>read only</i> The payload as an ArrayBuffer.
  	 * <p>
  	 * @property {string} destinationName <b>mandatory</b> The name of the destination to which the message is to be sent
  	 *                    (for messages about to be sent) or the name of the destination from which the message has been received.
  	 *                    (for messages received by the onMessage function).
  	 * <p>
  	 * @property {number} qos The Quality of Service used to deliver the message.
  	 * <dl>
  	 *     <dt>0 Best effort (default).
  	 *     <dt>1 At least once.
  	 *     <dt>2 Exactly once.
  	 * </dl>
  	 * <p>
  	 * @property {Boolean} retained If true, the message is to be retained by the server and delivered
  	 *                     to both current and future subscriptions.
  	 *                     If false the server only delivers the message to current subscribers, this is the default for new Messages.
  	 *                     A received message has the retained boolean set to true if the message was published
  	 *                     with the retained boolean set to true
  	 *                     and the subscrption was made after the message has been published.
  	 * <p>
  	 * @property {Boolean} duplicate <i>read only</i> If true, this message might be a duplicate of one which has already been received.
  	 *                     This is only set on messages received from the server.
  	 *
  	 */
  		var Message = function (newPayload) {
  			var payload;
  			if (   typeof newPayload === "string" ||
  		newPayload instanceof ArrayBuffer ||
  		(ArrayBuffer.isView(newPayload) && !(newPayload instanceof DataView))
  			) {
  				payload = newPayload;
  			} else {
  				throw (format(ERROR.INVALID_ARGUMENT, [newPayload, "newPayload"]));
  			}
  
  			var destinationName;
  			var qos = 0;
  			var retained = false;
  			var duplicate = false;
  
  			Object.defineProperties(this,{
  				"payloadString":{
  					enumerable : true,
  					get : function () {
  						if (typeof payload === "string")
  							return payload;
  						else
  							return parseUTF8(payload, 0, payload.length);
  					}
  				},
  				"payloadBytes":{
  					enumerable: true,
  					get: function() {
  						if (typeof payload === "string") {
  							var buffer = new ArrayBuffer(UTF8Length(payload));
  							var byteStream = new Uint8Array(buffer);
  							stringToUTF8(payload, byteStream, 0);
  
  							return byteStream;
  						} else {
  							return payload;
  						}
  					}
  				},
  				"destinationName":{
  					enumerable: true,
  					get: function() { return destinationName; },
  					set: function(newDestinationName) {
  						if (typeof newDestinationName === "string")
  							destinationName = newDestinationName;
  						else
  							throw new Error(format(ERROR.INVALID_ARGUMENT, [newDestinationName, "newDestinationName"]));
  					}
  				},
  				"qos":{
  					enumerable: true,
  					get: function() { return qos; },
  					set: function(newQos) {
  						if (newQos === 0 || newQos === 1 || newQos === 2 )
  							qos = newQos;
  						else
  							throw new Error("Invalid argument:"+newQos);
  					}
  				},
  				"retained":{
  					enumerable: true,
  					get: function() { return retained; },
  					set: function(newRetained) {
  						if (typeof newRetained === "boolean")
  							retained = newRetained;
  						else
  							throw new Error(format(ERROR.INVALID_ARGUMENT, [newRetained, "newRetained"]));
  					}
  				},
  				"topic":{
  					enumerable: true,
  					get: function() { return destinationName; },
  					set: function(newTopic) {destinationName=newTopic;}
  				},
  				"duplicate":{
  					enumerable: true,
  					get: function() { return duplicate; },
  					set: function(newDuplicate) {duplicate=newDuplicate;}
  				}
  			});
  		};
  
  		// Module contents.
  		return {
  			Client: Client,
  			Message: Message
  		};
  	// eslint-disable-next-line no-nested-ternary
  	})(typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {});
  	return PahoMQTT;
  });
  
  /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ "../../node_modules/webpack/buildin/global.js")))
  
  /***/ }),
  
  /***/ "../../node_modules/querystring-es3/decode.js":
  /*!***************************************************************!*\
    !*** /root/amplify-js/node_modules/querystring-es3/decode.js ***!
    \***************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  
  // If obj.hasOwnProperty has been overridden, then calling
  // obj.hasOwnProperty(prop) will break.
  // See: https://github.com/joyent/node/issues/1707
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  module.exports = function(qs, sep, eq, options) {
    sep = sep || '&';
    eq = eq || '=';
    var obj = {};
  
    if (typeof qs !== 'string' || qs.length === 0) {
      return obj;
    }
  
    var regexp = /\+/g;
    qs = qs.split(sep);
  
    var maxKeys = 1000;
    if (options && typeof options.maxKeys === 'number') {
      maxKeys = options.maxKeys;
    }
  
    var len = qs.length;
    // maxKeys <= 0 means that we should not limit keys count
    if (maxKeys > 0 && len > maxKeys) {
      len = maxKeys;
    }
  
    for (var i = 0; i < len; ++i) {
      var x = qs[i].replace(regexp, '%20'),
          idx = x.indexOf(eq),
          kstr, vstr, k, v;
  
      if (idx >= 0) {
        kstr = x.substr(0, idx);
        vstr = x.substr(idx + 1);
      } else {
        kstr = x;
        vstr = '';
      }
  
      k = decodeURIComponent(kstr);
      v = decodeURIComponent(vstr);
  
      if (!hasOwnProperty(obj, k)) {
        obj[k] = v;
      } else if (isArray(obj[k])) {
        obj[k].push(v);
      } else {
        obj[k] = [obj[k], v];
      }
    }
  
    return obj;
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  
  /***/ }),
  
  /***/ "../../node_modules/querystring-es3/encode.js":
  /*!***************************************************************!*\
    !*** /root/amplify-js/node_modules/querystring-es3/encode.js ***!
    \***************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  
  var stringifyPrimitive = function(v) {
    switch (typeof v) {
      case 'string':
        return v;
  
      case 'boolean':
        return v ? 'true' : 'false';
  
      case 'number':
        return isFinite(v) ? v : '';
  
      default:
        return '';
    }
  };
  
  module.exports = function(obj, sep, eq, name) {
    sep = sep || '&';
    eq = eq || '=';
    if (obj === null) {
      obj = undefined;
    }
  
    if (typeof obj === 'object') {
      return map(objectKeys(obj), function(k) {
        var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
        if (isArray(obj[k])) {
          return map(obj[k], function(v) {
            return ks + encodeURIComponent(stringifyPrimitive(v));
          }).join(sep);
        } else {
          return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
        }
      }).join(sep);
  
    }
  
    if (!name) return '';
    return encodeURIComponent(stringifyPrimitive(name)) + eq +
           encodeURIComponent(stringifyPrimitive(obj));
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  function map (xs, f) {
    if (xs.map) return xs.map(f);
    var res = [];
    for (var i = 0; i < xs.length; i++) {
      res.push(f(xs[i], i));
    }
    return res;
  }
  
  var objectKeys = Object.keys || function (obj) {
    var res = [];
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
    }
    return res;
  };
  
  
  /***/ }),
  
  /***/ "../../node_modules/querystring-es3/index.js":
  /*!**************************************************************!*\
    !*** /root/amplify-js/node_modules/querystring-es3/index.js ***!
    \**************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  exports.decode = exports.parse = __webpack_require__(/*! ./decode */ "../../node_modules/querystring-es3/decode.js");
  exports.encode = exports.stringify = __webpack_require__(/*! ./encode */ "../../node_modules/querystring-es3/encode.js");
  
  
  /***/ }),
  
  /***/ "../../node_modules/url/url.js":
  /*!************************************************!*\
    !*** /root/amplify-js/node_modules/url/url.js ***!
    \************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  
  
  var punycode = __webpack_require__(/*! punycode */ "../../node_modules/node-libs-browser/node_modules/punycode/punycode.js");
  var util = __webpack_require__(/*! ./util */ "../../node_modules/url/util.js");
  
  exports.parse = urlParse;
  exports.resolve = urlResolve;
  exports.resolveObject = urlResolveObject;
  exports.format = urlFormat;
  
  exports.Url = Url;
  
  function Url() {
    this.protocol = null;
    this.slashes = null;
    this.auth = null;
    this.host = null;
    this.port = null;
    this.hostname = null;
    this.hash = null;
    this.search = null;
    this.query = null;
    this.pathname = null;
    this.path = null;
    this.href = null;
  }
  
  // Reference: RFC 3986, RFC 1808, RFC 2396
  
  // define these here so at least they only have to be
  // compiled once on the first module load.
  var protocolPattern = /^([a-z0-9.+-]+:)/i,
      portPattern = /:[0-9]*$/,
  
      // Special case for a simple path URL
      simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
  
      // RFC 2396: characters reserved for delimiting URLs.
      // We actually just auto-escape these.
      delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
  
      // RFC 2396: characters not allowed for various reasons.
      unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
  
      // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
      autoEscape = ['\''].concat(unwise),
      // Characters that are never ever allowed in a hostname.
      // Note that any invalid chars are also handled, but these
      // are the ones that are *expected* to be seen, so we fast-path
      // them.
      nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
      hostEndingChars = ['/', '?', '#'],
      hostnameMaxLen = 255,
      hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
      hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
      // protocols that can allow "unsafe" and "unwise" chars.
      unsafeProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that never have a hostname.
      hostlessProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that always contain a // bit.
      slashedProtocol = {
        'http': true,
        'https': true,
        'ftp': true,
        'gopher': true,
        'file': true,
        'http:': true,
        'https:': true,
        'ftp:': true,
        'gopher:': true,
        'file:': true
      },
      querystring = __webpack_require__(/*! querystring */ "../../node_modules/querystring-es3/index.js");
  
  function urlParse(url, parseQueryString, slashesDenoteHost) {
    if (url && util.isObject(url) && url instanceof Url) return url;
  
    var u = new Url;
    u.parse(url, parseQueryString, slashesDenoteHost);
    return u;
  }
  
  Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
    if (!util.isString(url)) {
      throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
    }
  
    // Copy chrome, IE, opera backslash-handling behavior.
    // Back slashes before the query string get converted to forward slashes
    // See: https://code.google.com/p/chromium/issues/detail?id=25916
    var queryIndex = url.indexOf('?'),
        splitter =
            (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#',
        uSplit = url.split(splitter),
        slashRegex = /\\/g;
    uSplit[0] = uSplit[0].replace(slashRegex, '/');
    url = uSplit.join(splitter);
  
    var rest = url;
  
    // trim before proceeding.
    // This is to support parse stuff like "  http://foo.com  \n"
    rest = rest.trim();
  
    if (!slashesDenoteHost && url.split('#').length === 1) {
      // Try fast path regexp
      var simplePath = simplePathPattern.exec(rest);
      if (simplePath) {
        this.path = rest;
        this.href = rest;
        this.pathname = simplePath[1];
        if (simplePath[2]) {
          this.search = simplePath[2];
          if (parseQueryString) {
            this.query = querystring.parse(this.search.substr(1));
          } else {
            this.query = this.search.substr(1);
          }
        } else if (parseQueryString) {
          this.search = '';
          this.query = {};
        }
        return this;
      }
    }
  
    var proto = protocolPattern.exec(rest);
    if (proto) {
      proto = proto[0];
      var lowerProto = proto.toLowerCase();
      this.protocol = lowerProto;
      rest = rest.substr(proto.length);
    }
  
    // figure out if it's got a host
    // user@server is *always* interpreted as a hostname, and url
    // resolution will treat //foo/bar as host=foo,path=bar because that's
    // how the browser resolves relative URLs.
    if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
      var slashes = rest.substr(0, 2) === '//';
      if (slashes && !(proto && hostlessProtocol[proto])) {
        rest = rest.substr(2);
        this.slashes = true;
      }
    }
  
    if (!hostlessProtocol[proto] &&
        (slashes || (proto && !slashedProtocol[proto]))) {
  
      // there's a hostname.
      // the first instance of /, ?, ;, or # ends the host.
      //
      // If there is an @ in the hostname, then non-host chars *are* allowed
      // to the left of the last @ sign, unless some host-ending character
      // comes *before* the @-sign.
      // URLs are obnoxious.
      //
      // ex:
      // http://a@b@c/ => user:a@b host:c
      // http://a@b?@c => user:a host:c path:/?@c
  
      // v0.12 TODO(isaacs): This is not quite how Chrome does things.
      // Review our test case against browsers more comprehensively.
  
      // find the first instance of any hostEndingChars
      var hostEnd = -1;
      for (var i = 0; i < hostEndingChars.length; i++) {
        var hec = rest.indexOf(hostEndingChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
  
      // at this point, either we have an explicit point where the
      // auth portion cannot go past, or the last @ char is the decider.
      var auth, atSign;
      if (hostEnd === -1) {
        // atSign can be anywhere.
        atSign = rest.lastIndexOf('@');
      } else {
        // atSign must be in auth portion.
        // http://a@b/c@d => host:b auth:a path:/c@d
        atSign = rest.lastIndexOf('@', hostEnd);
      }
  
      // Now we have a portion which is definitely the auth.
      // Pull that off.
      if (atSign !== -1) {
        auth = rest.slice(0, atSign);
        rest = rest.slice(atSign + 1);
        this.auth = decodeURIComponent(auth);
      }
  
      // the host is the remaining to the left of the first non-host char
      hostEnd = -1;
      for (var i = 0; i < nonHostChars.length; i++) {
        var hec = rest.indexOf(nonHostChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
      // if we still have not hit it, then the entire thing is a host.
      if (hostEnd === -1)
        hostEnd = rest.length;
  
      this.host = rest.slice(0, hostEnd);
      rest = rest.slice(hostEnd);
  
      // pull out port.
      this.parseHost();
  
      // we've indicated that there is a hostname,
      // so even if it's empty, it has to be present.
      this.hostname = this.hostname || '';
  
      // if hostname begins with [ and ends with ]
      // assume that it's an IPv6 address.
      var ipv6Hostname = this.hostname[0] === '[' &&
          this.hostname[this.hostname.length - 1] === ']';
  
      // validate a little.
      if (!ipv6Hostname) {
        var hostparts = this.hostname.split(/\./);
        for (var i = 0, l = hostparts.length; i < l; i++) {
          var part = hostparts[i];
          if (!part) continue;
          if (!part.match(hostnamePartPattern)) {
            var newpart = '';
            for (var j = 0, k = part.length; j < k; j++) {
              if (part.charCodeAt(j) > 127) {
                // we replace non-ASCII char with a temporary placeholder
                // we need this to make sure size of hostname is not
                // broken by replacing non-ASCII by nothing
                newpart += 'x';
              } else {
                newpart += part[j];
              }
            }
            // we test again with ASCII char only
            if (!newpart.match(hostnamePartPattern)) {
              var validParts = hostparts.slice(0, i);
              var notHost = hostparts.slice(i + 1);
              var bit = part.match(hostnamePartStart);
              if (bit) {
                validParts.push(bit[1]);
                notHost.unshift(bit[2]);
              }
              if (notHost.length) {
                rest = '/' + notHost.join('.') + rest;
              }
              this.hostname = validParts.join('.');
              break;
            }
          }
        }
      }
  
      if (this.hostname.length > hostnameMaxLen) {
        this.hostname = '';
      } else {
        // hostnames are always lower case.
        this.hostname = this.hostname.toLowerCase();
      }
  
      if (!ipv6Hostname) {
        // IDNA Support: Returns a punycoded representation of "domain".
        // It only converts parts of the domain name that
        // have non-ASCII characters, i.e. it doesn't matter if
        // you call it with a domain that already is ASCII-only.
        this.hostname = punycode.toASCII(this.hostname);
      }
  
      var p = this.port ? ':' + this.port : '';
      var h = this.hostname || '';
      this.host = h + p;
      this.href += this.host;
  
      // strip [ and ] from the hostname
      // the host field still retains them, though
      if (ipv6Hostname) {
        this.hostname = this.hostname.substr(1, this.hostname.length - 2);
        if (rest[0] !== '/') {
          rest = '/' + rest;
        }
      }
    }
  
    // now rest is set to the post-host stuff.
    // chop off any delim chars.
    if (!unsafeProtocol[lowerProto]) {
  
      // First, make 100% sure that any "autoEscape" chars get
      // escaped, even if encodeURIComponent doesn't think they
      // need to be.
      for (var i = 0, l = autoEscape.length; i < l; i++) {
        var ae = autoEscape[i];
        if (rest.indexOf(ae) === -1)
          continue;
        var esc = encodeURIComponent(ae);
        if (esc === ae) {
          esc = escape(ae);
        }
        rest = rest.split(ae).join(esc);
      }
    }
  
  
    // chop off from the tail first.
    var hash = rest.indexOf('#');
    if (hash !== -1) {
      // got a fragment string.
      this.hash = rest.substr(hash);
      rest = rest.slice(0, hash);
    }
    var qm = rest.indexOf('?');
    if (qm !== -1) {
      this.search = rest.substr(qm);
      this.query = rest.substr(qm + 1);
      if (parseQueryString) {
        this.query = querystring.parse(this.query);
      }
      rest = rest.slice(0, qm);
    } else if (parseQueryString) {
      // no query string, but parseQueryString still requested
      this.search = '';
      this.query = {};
    }
    if (rest) this.pathname = rest;
    if (slashedProtocol[lowerProto] &&
        this.hostname && !this.pathname) {
      this.pathname = '/';
    }
  
    //to support http.request
    if (this.pathname || this.search) {
      var p = this.pathname || '';
      var s = this.search || '';
      this.path = p + s;
    }
  
    // finally, reconstruct the href based on what has been validated.
    this.href = this.format();
    return this;
  };
  
  // format a parsed object into a url string
  function urlFormat(obj) {
    // ensure it's an object, and not a string url.
    // If it's an obj, this is a no-op.
    // this way, you can call url_format() on strings
    // to clean up potentially wonky urls.
    if (util.isString(obj)) obj = urlParse(obj);
    if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
    return obj.format();
  }
  
  Url.prototype.format = function() {
    var auth = this.auth || '';
    if (auth) {
      auth = encodeURIComponent(auth);
      auth = auth.replace(/%3A/i, ':');
      auth += '@';
    }
  
    var protocol = this.protocol || '',
        pathname = this.pathname || '',
        hash = this.hash || '',
        host = false,
        query = '';
  
    if (this.host) {
      host = auth + this.host;
    } else if (this.hostname) {
      host = auth + (this.hostname.indexOf(':') === -1 ?
          this.hostname :
          '[' + this.hostname + ']');
      if (this.port) {
        host += ':' + this.port;
      }
    }
  
    if (this.query &&
        util.isObject(this.query) &&
        Object.keys(this.query).length) {
      query = querystring.stringify(this.query);
    }
  
    var search = this.search || (query && ('?' + query)) || '';
  
    if (protocol && protocol.substr(-1) !== ':') protocol += ':';
  
    // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
    // unless they had them to begin with.
    if (this.slashes ||
        (!protocol || slashedProtocol[protocol]) && host !== false) {
      host = '//' + (host || '');
      if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
    } else if (!host) {
      host = '';
    }
  
    if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
    if (search && search.charAt(0) !== '?') search = '?' + search;
  
    pathname = pathname.replace(/[?#]/g, function(match) {
      return encodeURIComponent(match);
    });
    search = search.replace('#', '%23');
  
    return protocol + host + pathname + search + hash;
  };
  
  function urlResolve(source, relative) {
    return urlParse(source, false, true).resolve(relative);
  }
  
  Url.prototype.resolve = function(relative) {
    return this.resolveObject(urlParse(relative, false, true)).format();
  };
  
  function urlResolveObject(source, relative) {
    if (!source) return relative;
    return urlParse(source, false, true).resolveObject(relative);
  }
  
  Url.prototype.resolveObject = function(relative) {
    if (util.isString(relative)) {
      var rel = new Url();
      rel.parse(relative, false, true);
      relative = rel;
    }
  
    var result = new Url();
    var tkeys = Object.keys(this);
    for (var tk = 0; tk < tkeys.length; tk++) {
      var tkey = tkeys[tk];
      result[tkey] = this[tkey];
    }
  
    // hash is always overridden, no matter what.
    // even href="" will remove it.
    result.hash = relative.hash;
  
    // if the relative url is empty, then there's nothing left to do here.
    if (relative.href === '') {
      result.href = result.format();
      return result;
    }
  
    // hrefs like //foo/bar always cut to the protocol.
    if (relative.slashes && !relative.protocol) {
      // take everything except the protocol from relative
      var rkeys = Object.keys(relative);
      for (var rk = 0; rk < rkeys.length; rk++) {
        var rkey = rkeys[rk];
        if (rkey !== 'protocol')
          result[rkey] = relative[rkey];
      }
  
      //urlParse appends trailing / to urls like http://www.example.com
      if (slashedProtocol[result.protocol] &&
          result.hostname && !result.pathname) {
        result.path = result.pathname = '/';
      }
  
      result.href = result.format();
      return result;
    }
  
    if (relative.protocol && relative.protocol !== result.protocol) {
      // if it's a known url protocol, then changing
      // the protocol does weird things
      // first, if it's not file:, then we MUST have a host,
      // and if there was a path
      // to begin with, then we MUST have a path.
      // if it is file:, then the host is dropped,
      // because that's known to be hostless.
      // anything else is assumed to be absolute.
      if (!slashedProtocol[relative.protocol]) {
        var keys = Object.keys(relative);
        for (var v = 0; v < keys.length; v++) {
          var k = keys[v];
          result[k] = relative[k];
        }
        result.href = result.format();
        return result;
      }
  
      result.protocol = relative.protocol;
      if (!relative.host && !hostlessProtocol[relative.protocol]) {
        var relPath = (relative.pathname || '').split('/');
        while (relPath.length && !(relative.host = relPath.shift()));
        if (!relative.host) relative.host = '';
        if (!relative.hostname) relative.hostname = '';
        if (relPath[0] !== '') relPath.unshift('');
        if (relPath.length < 2) relPath.unshift('');
        result.pathname = relPath.join('/');
      } else {
        result.pathname = relative.pathname;
      }
      result.search = relative.search;
      result.query = relative.query;
      result.host = relative.host || '';
      result.auth = relative.auth;
      result.hostname = relative.hostname || relative.host;
      result.port = relative.port;
      // to support http.request
      if (result.pathname || result.search) {
        var p = result.pathname || '';
        var s = result.search || '';
        result.path = p + s;
      }
      result.slashes = result.slashes || relative.slashes;
      result.href = result.format();
      return result;
    }
  
    var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
        isRelAbs = (
            relative.host ||
            relative.pathname && relative.pathname.charAt(0) === '/'
        ),
        mustEndAbs = (isRelAbs || isSourceAbs ||
                      (result.host && relative.pathname)),
        removeAllDots = mustEndAbs,
        srcPath = result.pathname && result.pathname.split('/') || [],
        relPath = relative.pathname && relative.pathname.split('/') || [],
        psychotic = result.protocol && !slashedProtocol[result.protocol];
  
    // if the url is a non-slashed url, then relative
    // links like ../.. should be able
    // to crawl up to the hostname, as well.  This is strange.
    // result.protocol has already been set by now.
    // Later on, put the first path part into the host field.
    if (psychotic) {
      result.hostname = '';
      result.port = null;
      if (result.host) {
        if (srcPath[0] === '') srcPath[0] = result.host;
        else srcPath.unshift(result.host);
      }
      result.host = '';
      if (relative.protocol) {
        relative.hostname = null;
        relative.port = null;
        if (relative.host) {
          if (relPath[0] === '') relPath[0] = relative.host;
          else relPath.unshift(relative.host);
        }
        relative.host = null;
      }
      mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
    }
  
    if (isRelAbs) {
      // it's absolute.
      result.host = (relative.host || relative.host === '') ?
                    relative.host : result.host;
      result.hostname = (relative.hostname || relative.hostname === '') ?
                        relative.hostname : result.hostname;
      result.search = relative.search;
      result.query = relative.query;
      srcPath = relPath;
      // fall through to the dot-handling below.
    } else if (relPath.length) {
      // it's relative
      // throw away the existing file, and take the new path instead.
      if (!srcPath) srcPath = [];
      srcPath.pop();
      srcPath = srcPath.concat(relPath);
      result.search = relative.search;
      result.query = relative.query;
    } else if (!util.isNullOrUndefined(relative.search)) {
      // just pull out the search.
      // like href='?foo'.
      // Put this after the other two cases because it simplifies the booleans
      if (psychotic) {
        result.hostname = result.host = srcPath.shift();
        //occationaly the auth can get stuck only in host
        //this especially happens in cases like
        //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
        var authInHost = result.host && result.host.indexOf('@') > 0 ?
                         result.host.split('@') : false;
        if (authInHost) {
          result.auth = authInHost.shift();
          result.host = result.hostname = authInHost.shift();
        }
      }
      result.search = relative.search;
      result.query = relative.query;
      //to support http.request
      if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
        result.path = (result.pathname ? result.pathname : '') +
                      (result.search ? result.search : '');
      }
      result.href = result.format();
      return result;
    }
  
    if (!srcPath.length) {
      // no path at all.  easy.
      // we've already handled the other stuff above.
      result.pathname = null;
      //to support http.request
      if (result.search) {
        result.path = '/' + result.search;
      } else {
        result.path = null;
      }
      result.href = result.format();
      return result;
    }
  
    // if a url ENDs in . or .., then it must get a trailing slash.
    // however, if it ends in anything else non-slashy,
    // then it must NOT get a trailing slash.
    var last = srcPath.slice(-1)[0];
    var hasTrailingSlash = (
        (result.host || relative.host || srcPath.length > 1) &&
        (last === '.' || last === '..') || last === '');
  
    // strip single dots, resolve double dots to parent dir
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = srcPath.length; i >= 0; i--) {
      last = srcPath[i];
      if (last === '.') {
        srcPath.splice(i, 1);
      } else if (last === '..') {
        srcPath.splice(i, 1);
        up++;
      } else if (up) {
        srcPath.splice(i, 1);
        up--;
      }
    }
  
    // if the path is allowed to go above the root, restore leading ..s
    if (!mustEndAbs && !removeAllDots) {
      for (; up--; up) {
        srcPath.unshift('..');
      }
    }
  
    if (mustEndAbs && srcPath[0] !== '' &&
        (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
      srcPath.unshift('');
    }
  
    if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
      srcPath.push('');
    }
  
    var isAbsolute = srcPath[0] === '' ||
        (srcPath[0] && srcPath[0].charAt(0) === '/');
  
    // put the host back
    if (psychotic) {
      result.hostname = result.host = isAbsolute ? '' :
                                      srcPath.length ? srcPath.shift() : '';
      //occationaly the auth can get stuck only in host
      //this especially happens in cases like
      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
      var authInHost = result.host && result.host.indexOf('@') > 0 ?
                       result.host.split('@') : false;
      if (authInHost) {
        result.auth = authInHost.shift();
        result.host = result.hostname = authInHost.shift();
      }
    }
  
    mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  
    if (mustEndAbs && !isAbsolute) {
      srcPath.unshift('');
    }
  
    if (!srcPath.length) {
      result.pathname = null;
      result.path = null;
    } else {
      result.pathname = srcPath.join('/');
    }
  
    //to support request.http
    if (!util.isNull(result.pathname) || !util.isNull(result.search)) {
      result.path = (result.pathname ? result.pathname : '') +
                    (result.search ? result.search : '');
    }
    result.auth = relative.auth || result.auth;
    result.slashes = result.slashes || relative.slashes;
    result.href = result.format();
    return result;
  };
  
  Url.prototype.parseHost = function() {
    var host = this.host;
    var port = portPattern.exec(host);
    if (port) {
      port = port[0];
      if (port !== ':') {
        this.port = port.substr(1);
      }
      host = host.substr(0, host.length - port.length);
    }
    if (host) this.hostname = host;
  };
  
  
  /***/ }),
  
  /***/ "../../node_modules/url/util.js":
  /*!*************************************************!*\
    !*** /root/amplify-js/node_modules/url/util.js ***!
    \*************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  module.exports = {
    isString: function(arg) {
      return typeof(arg) === 'string';
    },
    isObject: function(arg) {
      return typeof(arg) === 'object' && arg !== null;
    },
    isNull: function(arg) {
      return arg === null;
    },
    isNullOrUndefined: function(arg) {
      return arg == null;
    }
  };
  
  
  /***/ }),
  
  /***/ "../../node_modules/uuid/index.js":
  /*!***************************************************!*\
    !*** /root/amplify-js/node_modules/uuid/index.js ***!
    \***************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  var v1 = __webpack_require__(/*! ./v1 */ "../../node_modules/uuid/v1.js");
  var v4 = __webpack_require__(/*! ./v4 */ "../../node_modules/uuid/v4.js");
  
  var uuid = v4;
  uuid.v1 = v1;
  uuid.v4 = v4;
  
  module.exports = uuid;
  
  
  /***/ }),
  
  /***/ "../../node_modules/uuid/lib/bytesToUuid.js":
  /*!*************************************************************!*\
    !*** /root/amplify-js/node_modules/uuid/lib/bytesToUuid.js ***!
    \*************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  /**
   * Convert array of 16 byte values to UUID string format of the form:
   * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
   */
  var byteToHex = [];
  for (var i = 0; i < 256; ++i) {
    byteToHex[i] = (i + 0x100).toString(16).substr(1);
  }
  
  function bytesToUuid(buf, offset) {
    var i = offset || 0;
    var bth = byteToHex;
    // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
    return ([
      bth[buf[i++]], bth[buf[i++]],
      bth[buf[i++]], bth[buf[i++]], '-',
      bth[buf[i++]], bth[buf[i++]], '-',
      bth[buf[i++]], bth[buf[i++]], '-',
      bth[buf[i++]], bth[buf[i++]], '-',
      bth[buf[i++]], bth[buf[i++]],
      bth[buf[i++]], bth[buf[i++]],
      bth[buf[i++]], bth[buf[i++]]
    ]).join('');
  }
  
  module.exports = bytesToUuid;
  
  
  /***/ }),
  
  /***/ "../../node_modules/uuid/lib/rng-browser.js":
  /*!*************************************************************!*\
    !*** /root/amplify-js/node_modules/uuid/lib/rng-browser.js ***!
    \*************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  // Unique ID creation requires a high quality random # generator.  In the
  // browser this is a little complicated due to unknown quality of Math.random()
  // and inconsistent support for the `crypto` API.  We do the best we can via
  // feature-detection
  
  // getRandomValues needs to be invoked in a context where "this" is a Crypto
  // implementation. Also, find the complete implementation of crypto on IE11.
  var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
                        (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
  
  if (getRandomValues) {
    // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
    var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
  
    module.exports = function whatwgRNG() {
      getRandomValues(rnds8);
      return rnds8;
    };
  } else {
    // Math.random()-based (RNG)
    //
    // If all else fails, use Math.random().  It's fast, but is of unspecified
    // quality.
    var rnds = new Array(16);
  
    module.exports = function mathRNG() {
      for (var i = 0, r; i < 16; i++) {
        if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
        rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
      }
  
      return rnds;
    };
  }
  
  
  /***/ }),
  
  /***/ "../../node_modules/uuid/v1.js":
  /*!************************************************!*\
    !*** /root/amplify-js/node_modules/uuid/v1.js ***!
    \************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  var rng = __webpack_require__(/*! ./lib/rng */ "../../node_modules/uuid/lib/rng-browser.js");
  var bytesToUuid = __webpack_require__(/*! ./lib/bytesToUuid */ "../../node_modules/uuid/lib/bytesToUuid.js");
  
  // **`v1()` - Generate time-based UUID**
  //
  // Inspired by https://github.com/LiosK/UUID.js
  // and http://docs.python.org/library/uuid.html
  
  var _nodeId;
  var _clockseq;
  
  // Previous uuid creation time
  var _lastMSecs = 0;
  var _lastNSecs = 0;
  
  // See https://github.com/uuidjs/uuid for API details
  function v1(options, buf, offset) {
    var i = buf && offset || 0;
    var b = buf || [];
  
    options = options || {};
    var node = options.node || _nodeId;
    var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
  
    // node and clockseq need to be initialized to random values if they're not
    // specified.  We do this lazily to minimize issues related to insufficient
    // system entropy.  See #189
    if (node == null || clockseq == null) {
      var seedBytes = rng();
      if (node == null) {
        // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)
        node = _nodeId = [
          seedBytes[0] | 0x01,
          seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]
        ];
      }
      if (clockseq == null) {
        // Per 4.2.2, randomize (14 bit) clockseq
        clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;
      }
    }
  
    // UUID timestamps are 100 nano-second units since the Gregorian epoch,
    // (1582-10-15 00:00).  JSNumbers aren't precise enough for this, so
    // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'
    // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.
    var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();
  
    // Per 4.2.1.2, use count of uuid's generated during the current clock
    // cycle to simulate higher resolution clock
    var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;
  
    // Time since last uuid creation (in msecs)
    var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;
  
    // Per 4.2.1.2, Bump clockseq on clock regression
    if (dt < 0 && options.clockseq === undefined) {
      clockseq = clockseq + 1 & 0x3fff;
    }
  
    // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new
    // time interval
    if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {
      nsecs = 0;
    }
  
    // Per 4.2.1.2 Throw error if too many uuids are requested
    if (nsecs >= 10000) {
      throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec');
    }
  
    _lastMSecs = msecs;
    _lastNSecs = nsecs;
    _clockseq = clockseq;
  
    // Per 4.1.4 - Convert from unix epoch to Gregorian epoch
    msecs += 12219292800000;
  
    // `time_low`
    var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;
    b[i++] = tl >>> 24 & 0xff;
    b[i++] = tl >>> 16 & 0xff;
    b[i++] = tl >>> 8 & 0xff;
    b[i++] = tl & 0xff;
  
    // `time_mid`
    var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;
    b[i++] = tmh >>> 8 & 0xff;
    b[i++] = tmh & 0xff;
  
    // `time_high_and_version`
    b[i++] = tmh >>> 24 & 0xf | 0x10; // include version
    b[i++] = tmh >>> 16 & 0xff;
  
    // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)
    b[i++] = clockseq >>> 8 | 0x80;
  
    // `clock_seq_low`
    b[i++] = clockseq & 0xff;
  
    // `node`
    for (var n = 0; n < 6; ++n) {
      b[i + n] = node[n];
    }
  
    return buf ? buf : bytesToUuid(b);
  }
  
  module.exports = v1;
  
  
  /***/ }),
  
  /***/ "../../node_modules/uuid/v4.js":
  /*!************************************************!*\
    !*** /root/amplify-js/node_modules/uuid/v4.js ***!
    \************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  var rng = __webpack_require__(/*! ./lib/rng */ "../../node_modules/uuid/lib/rng-browser.js");
  var bytesToUuid = __webpack_require__(/*! ./lib/bytesToUuid */ "../../node_modules/uuid/lib/bytesToUuid.js");
  
  function v4(options, buf, offset) {
    var i = buf && offset || 0;
  
    if (typeof(options) == 'string') {
      buf = options === 'binary' ? new Array(16) : null;
      options = null;
    }
    options = options || {};
  
    var rnds = options.random || (options.rng || rng)();
  
    // Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
    rnds[6] = (rnds[6] & 0x0f) | 0x40;
    rnds[8] = (rnds[8] & 0x3f) | 0x80;
  
    // Copy bytes to buffer, if provided
    if (buf) {
      for (var ii = 0; ii < 16; ++ii) {
        buf[i + ii] = rnds[ii];
      }
    }
  
    return buf || bytesToUuid(rnds);
  }
  
  module.exports = v4;
  
  
  /***/ }),
  
  /***/ "../../node_modules/webpack/buildin/global.js":
  /*!***********************************!*\
    !*** (webpack)/buildin/global.js ***!
    \***********************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  var g;
  
  // This works in non-strict mode
  g = (function() {
  	return this;
  })();
  
  try {
  	// This works if eval is allowed (see CSP)
  	g = g || new Function("return this")();
  } catch (e) {
  	// This works if the window reference is available
  	if (typeof window === "object") g = window;
  }
  
  // g can still be undefined, but nothing to do about it...
  // We return undefined, instead of nothing here, so it's
  // easier to handle this case. if(!global) { ...}
  
  module.exports = g;
  
  
  /***/ }),
  
  /***/ "../../node_modules/webpack/buildin/module.js":
  /*!***********************************!*\
    !*** (webpack)/buildin/module.js ***!
    \***********************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  module.exports = function(module) {
  	if (!module.webpackPolyfill) {
  		module.deprecate = function() {};
  		module.paths = [];
  		// module.parent = undefined by default
  		if (!module.children) module.children = [];
  		Object.defineProperty(module, "loaded", {
  			enumerable: true,
  			get: function() {
  				return module.l;
  			}
  		});
  		Object.defineProperty(module, "id", {
  			enumerable: true,
  			get: function() {
  				return module.i;
  			}
  		});
  		module.webpackPolyfill = 1;
  	}
  	return module;
  };
  
  
  /***/ }),
  
  /***/ "../../node_modules/zen-observable-ts/lib/bundle.esm.js":
  /*!*************************************************************************!*\
    !*** /root/amplify-js/node_modules/zen-observable-ts/lib/bundle.esm.js ***!
    \*************************************************************************/
  /*! exports provided: default, Observable */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Observable", function() { return Observable; });
  /* harmony import */ var zen_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zen-observable */ "../../node_modules/zen-observable-ts/node_modules/zen-observable/index.js");
  /* harmony import */ var zen_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(zen_observable__WEBPACK_IMPORTED_MODULE_0__);
  
  
  var Observable = zen_observable__WEBPACK_IMPORTED_MODULE_0___default.a;
  
  /* harmony default export */ __webpack_exports__["default"] = (Observable);
  
  //# sourceMappingURL=bundle.esm.js.map
  
  
  /***/ }),
  
  /***/ "../../node_modules/zen-observable-ts/node_modules/zen-observable/index.js":
  /*!********************************************************************************************!*\
    !*** /root/amplify-js/node_modules/zen-observable-ts/node_modules/zen-observable/index.js ***!
    \********************************************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  module.exports = __webpack_require__(/*! ./lib/Observable.js */ "../../node_modules/zen-observable-ts/node_modules/zen-observable/lib/Observable.js").Observable;
  
  
  /***/ }),
  
  /***/ "../../node_modules/zen-observable-ts/node_modules/zen-observable/lib/Observable.js":
  /*!*****************************************************************************************************!*\
    !*** /root/amplify-js/node_modules/zen-observable-ts/node_modules/zen-observable/lib/Observable.js ***!
    \*****************************************************************************************************/
  /*! no static exports found */
  /***/ (function(module, exports, __webpack_require__) {
  
  "use strict";
  
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.Observable = void 0;
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  
  // === Symbol Support ===
  var hasSymbols = function () {
    return typeof Symbol === 'function';
  };
  
  var hasSymbol = function (name) {
    return hasSymbols() && Boolean(Symbol[name]);
  };
  
  var getSymbol = function (name) {
    return hasSymbol(name) ? Symbol[name] : '@@' + name;
  };
  
  if (hasSymbols() && !hasSymbol('observable')) {
    Symbol.observable = Symbol('observable');
  }
  
  var SymbolIterator = getSymbol('iterator');
  var SymbolObservable = getSymbol('observable');
  var SymbolSpecies = getSymbol('species'); // === Abstract Operations ===
  
  function getMethod(obj, key) {
    var value = obj[key];
    if (value == null) return undefined;
    if (typeof value !== 'function') throw new TypeError(value + ' is not a function');
    return value;
  }
  
  function getSpecies(obj) {
    var ctor = obj.constructor;
  
    if (ctor !== undefined) {
      ctor = ctor[SymbolSpecies];
  
      if (ctor === null) {
        ctor = undefined;
      }
    }
  
    return ctor !== undefined ? ctor : Observable;
  }
  
  function isObservable(x) {
    return x instanceof Observable; // SPEC: Brand check
  }
  
  function hostReportError(e) {
    if (hostReportError.log) {
      hostReportError.log(e);
    } else {
      setTimeout(function () {
        throw e;
      });
    }
  }
  
  function enqueue(fn) {
    Promise.resolve().then(function () {
      try {
        fn();
      } catch (e) {
        hostReportError(e);
      }
    });
  }
  
  function cleanupSubscription(subscription) {
    var cleanup = subscription._cleanup;
    if (cleanup === undefined) return;
    subscription._cleanup = undefined;
  
    if (!cleanup) {
      return;
    }
  
    try {
      if (typeof cleanup === 'function') {
        cleanup();
      } else {
        var unsubscribe = getMethod(cleanup, 'unsubscribe');
  
        if (unsubscribe) {
          unsubscribe.call(cleanup);
        }
      }
    } catch (e) {
      hostReportError(e);
    }
  }
  
  function closeSubscription(subscription) {
    subscription._observer = undefined;
    subscription._queue = undefined;
    subscription._state = 'closed';
  }
  
  function flushSubscription(subscription) {
    var queue = subscription._queue;
  
    if (!queue) {
      return;
    }
  
    subscription._queue = undefined;
    subscription._state = 'ready';
  
    for (var i = 0; i < queue.length; ++i) {
      notifySubscription(subscription, queue[i].type, queue[i].value);
      if (subscription._state === 'closed') break;
    }
  }
  
  function notifySubscription(subscription, type, value) {
    subscription._state = 'running';
    var observer = subscription._observer;
  
    try {
      var m = getMethod(observer, type);
  
      switch (type) {
        case 'next':
          if (m) m.call(observer, value);
          break;
  
        case 'error':
          closeSubscription(subscription);
          if (m) m.call(observer, value);else throw value;
          break;
  
        case 'complete':
          closeSubscription(subscription);
          if (m) m.call(observer);
          break;
      }
    } catch (e) {
      hostReportError(e);
    }
  
    if (subscription._state === 'closed') cleanupSubscription(subscription);else if (subscription._state === 'running') subscription._state = 'ready';
  }
  
  function onNotify(subscription, type, value) {
    if (subscription._state === 'closed') return;
  
    if (subscription._state === 'buffering') {
      subscription._queue.push({
        type: type,
        value: value
      });
  
      return;
    }
  
    if (subscription._state !== 'ready') {
      subscription._state = 'buffering';
      subscription._queue = [{
        type: type,
        value: value
      }];
      enqueue(function () {
        return flushSubscription(subscription);
      });
      return;
    }
  
    notifySubscription(subscription, type, value);
  }
  
  var Subscription =
  /*#__PURE__*/
  function () {
    function Subscription(observer, subscriber) {
      _classCallCheck(this, Subscription);
  
      // ASSERT: observer is an object
      // ASSERT: subscriber is callable
      this._cleanup = undefined;
      this._observer = observer;
      this._queue = undefined;
      this._state = 'initializing';
      var subscriptionObserver = new SubscriptionObserver(this);
  
      try {
        this._cleanup = subscriber.call(undefined, subscriptionObserver);
      } catch (e) {
        subscriptionObserver.error(e);
      }
  
      if (this._state === 'initializing') this._state = 'ready';
    }
  
    _createClass(Subscription, [{
      key: "unsubscribe",
      value: function unsubscribe() {
        if (this._state !== 'closed') {
          closeSubscription(this);
          cleanupSubscription(this);
        }
      }
    }, {
      key: "closed",
      get: function () {
        return this._state === 'closed';
      }
    }]);
  
    return Subscription;
  }();
  
  var SubscriptionObserver =
  /*#__PURE__*/
  function () {
    function SubscriptionObserver(subscription) {
      _classCallCheck(this, SubscriptionObserver);
  
      this._subscription = subscription;
    }
  
    _createClass(SubscriptionObserver, [{
      key: "next",
      value: function next(value) {
        onNotify(this._subscription, 'next', value);
      }
    }, {
      key: "error",
      value: function error(value) {
        onNotify(this._subscription, 'error', value);
      }
    }, {
      key: "complete",
      value: function complete() {
        onNotify(this._subscription, 'complete');
      }
    }, {
      key: "closed",
      get: function () {
        return this._subscription._state === 'closed';
      }
    }]);
  
    return SubscriptionObserver;
  }();
  
  var Observable =
  /*#__PURE__*/
  function () {
    function Observable(subscriber) {
      _classCallCheck(this, Observable);
  
      if (!(this instanceof Observable)) throw new TypeError('Observable cannot be called as a function');
      if (typeof subscriber !== 'function') throw new TypeError('Observable initializer must be a function');
      this._subscriber = subscriber;
    }
  
    _createClass(Observable, [{
      key: "subscribe",
      value: function subscribe(observer) {
        if (typeof observer !== 'object' || observer === null) {
          observer = {
            next: observer,
            error: arguments[1],
            complete: arguments[2]
          };
        }
  
        return new Subscription(observer, this._subscriber);
      }
    }, {
      key: "forEach",
      value: function forEach(fn) {
        var _this = this;
  
        return new Promise(function (resolve, reject) {
          if (typeof fn !== 'function') {
            reject(new TypeError(fn + ' is not a function'));
            return;
          }
  
          function done() {
            subscription.unsubscribe();
            resolve();
          }
  
          var subscription = _this.subscribe({
            next: function (value) {
              try {
                fn(value, done);
              } catch (e) {
                reject(e);
                subscription.unsubscribe();
              }
            },
            error: reject,
            complete: resolve
          });
        });
      }
    }, {
      key: "map",
      value: function map(fn) {
        var _this2 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        return new C(function (observer) {
          return _this2.subscribe({
            next: function (value) {
              try {
                value = fn(value);
              } catch (e) {
                return observer.error(e);
              }
  
              observer.next(value);
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              observer.complete();
            }
          });
        });
      }
    }, {
      key: "filter",
      value: function filter(fn) {
        var _this3 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        return new C(function (observer) {
          return _this3.subscribe({
            next: function (value) {
              try {
                if (!fn(value)) return;
              } catch (e) {
                return observer.error(e);
              }
  
              observer.next(value);
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              observer.complete();
            }
          });
        });
      }
    }, {
      key: "reduce",
      value: function reduce(fn) {
        var _this4 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        var hasSeed = arguments.length > 1;
        var hasValue = false;
        var seed = arguments[1];
        var acc = seed;
        return new C(function (observer) {
          return _this4.subscribe({
            next: function (value) {
              var first = !hasValue;
              hasValue = true;
  
              if (!first || hasSeed) {
                try {
                  acc = fn(acc, value);
                } catch (e) {
                  return observer.error(e);
                }
              } else {
                acc = value;
              }
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              if (!hasValue && !hasSeed) return observer.error(new TypeError('Cannot reduce an empty sequence'));
              observer.next(acc);
              observer.complete();
            }
          });
        });
      }
    }, {
      key: "concat",
      value: function concat() {
        var _this5 = this;
  
        for (var _len = arguments.length, sources = new Array(_len), _key = 0; _key < _len; _key++) {
          sources[_key] = arguments[_key];
        }
  
        var C = getSpecies(this);
        return new C(function (observer) {
          var subscription;
          var index = 0;
  
          function startNext(next) {
            subscription = next.subscribe({
              next: function (v) {
                observer.next(v);
              },
              error: function (e) {
                observer.error(e);
              },
              complete: function () {
                if (index === sources.length) {
                  subscription = undefined;
                  observer.complete();
                } else {
                  startNext(C.from(sources[index++]));
                }
              }
            });
          }
  
          startNext(_this5);
          return function () {
            if (subscription) {
              subscription.unsubscribe();
              subscription = undefined;
            }
          };
        });
      }
    }, {
      key: "flatMap",
      value: function flatMap(fn) {
        var _this6 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        return new C(function (observer) {
          var subscriptions = [];
  
          var outer = _this6.subscribe({
            next: function (value) {
              if (fn) {
                try {
                  value = fn(value);
                } catch (e) {
                  return observer.error(e);
                }
              }
  
              var inner = C.from(value).subscribe({
                next: function (value) {
                  observer.next(value);
                },
                error: function (e) {
                  observer.error(e);
                },
                complete: function () {
                  var i = subscriptions.indexOf(inner);
                  if (i >= 0) subscriptions.splice(i, 1);
                  completeIfDone();
                }
              });
              subscriptions.push(inner);
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              completeIfDone();
            }
          });
  
          function completeIfDone() {
            if (outer.closed && subscriptions.length === 0) observer.complete();
          }
  
          return function () {
            subscriptions.forEach(function (s) {
              return s.unsubscribe();
            });
            outer.unsubscribe();
          };
        });
      }
    }, {
      key: SymbolObservable,
      value: function () {
        return this;
      }
    }], [{
      key: "from",
      value: function from(x) {
        var C = typeof this === 'function' ? this : Observable;
        if (x == null) throw new TypeError(x + ' is not an object');
        var method = getMethod(x, SymbolObservable);
  
        if (method) {
          var observable = method.call(x);
          if (Object(observable) !== observable) throw new TypeError(observable + ' is not an object');
          if (isObservable(observable) && observable.constructor === C) return observable;
          return new C(function (observer) {
            return observable.subscribe(observer);
          });
        }
  
        if (hasSymbol('iterator')) {
          method = getMethod(x, SymbolIterator);
  
          if (method) {
            return new C(function (observer) {
              enqueue(function () {
                if (observer.closed) return;
                var _iteratorNormalCompletion = true;
                var _didIteratorError = false;
                var _iteratorError = undefined;
  
                try {
                  for (var _iterator = method.call(x)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                    var _item = _step.value;
                    observer.next(_item);
                    if (observer.closed) return;
                  }
                } catch (err) {
                  _didIteratorError = true;
                  _iteratorError = err;
                } finally {
                  try {
                    if (!_iteratorNormalCompletion && _iterator.return != null) {
                      _iterator.return();
                    }
                  } finally {
                    if (_didIteratorError) {
                      throw _iteratorError;
                    }
                  }
                }
  
                observer.complete();
              });
            });
          }
        }
  
        if (Array.isArray(x)) {
          return new C(function (observer) {
            enqueue(function () {
              if (observer.closed) return;
  
              for (var i = 0; i < x.length; ++i) {
                observer.next(x[i]);
                if (observer.closed) return;
              }
  
              observer.complete();
            });
          });
        }
  
        throw new TypeError(x + ' is not observable');
      }
    }, {
      key: "of",
      value: function of() {
        for (var _len2 = arguments.length, items = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
          items[_key2] = arguments[_key2];
        }
  
        var C = typeof this === 'function' ? this : Observable;
        return new C(function (observer) {
          enqueue(function () {
            if (observer.closed) return;
  
            for (var i = 0; i < items.length; ++i) {
              observer.next(items[i]);
              if (observer.closed) return;
            }
  
            observer.complete();
          });
        });
      }
    }, {
      key: SymbolSpecies,
      get: function () {
        return this;
      }
    }]);
  
    return Observable;
  }();
  
  exports.Observable = Observable;
  
  if (hasSymbols()) {
    Object.defineProperty(Observable, Symbol('extensions'), {
      value: {
        symbol: SymbolObservable,
        hostReportError: hostReportError
      },
      configurable: true
    });
  }
  
  /***/ }),
  
  /***/ "./lib-esm/Providers/AWSAppSyncProvider.js":
  /*!*************************************************!*\
    !*** ./lib-esm/Providers/AWSAppSyncProvider.js ***!
    \*************************************************/
  /*! exports provided: AWSAppSyncProvider */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AWSAppSyncProvider", function() { return AWSAppSyncProvider; });
  /* harmony import */ var zen_observable_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zen-observable-ts */ "../../node_modules/zen-observable-ts/lib/bundle.esm.js");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @aws-amplify/core */ "@aws-amplify/core");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__);
  /* harmony import */ var _MqttOverWSProvider__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./MqttOverWSProvider */ "./lib-esm/Providers/MqttOverWSProvider.js");
  var __extends = undefined && undefined.__extends || function () {
    var _extendStatics = function extendStatics(d, b) {
      _extendStatics = Object.setPrototypeOf || {
        __proto__: []
      } instanceof Array && function (d, b) {
        d.__proto__ = b;
      } || function (d, b) {
        for (var p in b) {
          if (b.hasOwnProperty(p)) d[p] = b[p];
        }
      };
  
      return _extendStatics(d, b);
    };
  
    return function (d, b) {
      _extendStatics(d, b);
  
      function __() {
        this.constructor = d;
      }
  
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
  }();
  
  var __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {
    function adopt(value) {
      return value instanceof P ? value : new P(function (resolve) {
        resolve(value);
      });
    }
  
    return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      }
  
      function rejected(value) {
        try {
          step(generator["throw"](value));
        } catch (e) {
          reject(e);
        }
      }
  
      function step(result) {
        result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
      }
  
      step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
  };
  
  var __generator = undefined && undefined.__generator || function (thisArg, body) {
    var _ = {
      label: 0,
      sent: function sent() {
        if (t[0] & 1) throw t[1];
        return t[1];
      },
      trys: [],
      ops: []
    },
        f,
        y,
        t,
        g;
    return g = {
      next: verb(0),
      "throw": verb(1),
      "return": verb(2)
    }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
      return this;
    }), g;
  
    function verb(n) {
      return function (v) {
        return step([n, v]);
      };
    }
  
    function step(op) {
      if (f) throw new TypeError("Generator is already executing.");
  
      while (_) {
        try {
          if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
          if (y = 0, t) op = [op[0] & 2, t.value];
  
          switch (op[0]) {
            case 0:
            case 1:
              t = op;
              break;
  
            case 4:
              _.label++;
              return {
                value: op[1],
                done: false
              };
  
            case 5:
              _.label++;
              y = op[1];
              op = [0];
              continue;
  
            case 7:
              op = _.ops.pop();
  
              _.trys.pop();
  
              continue;
  
            default:
              if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                _ = 0;
                continue;
              }
  
              if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
                _.label = op[1];
                break;
              }
  
              if (op[0] === 6 && _.label < t[1]) {
                _.label = t[1];
                t = op;
                break;
              }
  
              if (t && _.label < t[2]) {
                _.label = t[2];
  
                _.ops.push(op);
  
                break;
              }
  
              if (t[2]) _.ops.pop();
  
              _.trys.pop();
  
              continue;
          }
  
          op = body.call(thisArg, _);
        } catch (e) {
          op = [6, e];
          y = 0;
        } finally {
          f = t = 0;
        }
      }
  
      if (op[0] & 5) throw op[1];
      return {
        value: op[0] ? op[1] : void 0,
        done: true
      };
    }
  };
  
  var __rest = undefined && undefined.__rest || function (s, e) {
    var t = {};
  
    for (var p in s) {
      if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
    }
  
    if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
      if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
    }
    return t;
  };
  
  var __read = undefined && undefined.__read || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o),
        r,
        ar = [],
        e;
  
    try {
      while ((n === void 0 || n-- > 0) && !(r = i.next()).done) {
        ar.push(r.value);
      }
    } catch (error) {
      e = {
        error: error
      };
    } finally {
      try {
        if (r && !r.done && (m = i["return"])) m.call(i);
      } finally {
        if (e) throw e.error;
      }
    }
  
    return ar;
  };
  
  var __spread = undefined && undefined.__spread || function () {
    for (var ar = [], i = 0; i < arguments.length; i++) {
      ar = ar.concat(__read(arguments[i]));
    }
  
    return ar;
  };
  
  
  
  
  var logger = new _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["ConsoleLogger"]('AWSAppSyncProvider');
  
  var AWSAppSyncProvider =
  /** @class */
  function (_super) {
    __extends(AWSAppSyncProvider, _super);
  
    function AWSAppSyncProvider() {
      var _this = _super !== null && _super.apply(this, arguments) || this;
  
      _this._topicClient = new Map();
      _this._topicAlias = new Map();
      return _this;
    }
  
    Object.defineProperty(AWSAppSyncProvider.prototype, "endpoint", {
      get: function get() {
        throw new Error('Not supported');
      },
      enumerable: true,
      configurable: true
    });
  
    AWSAppSyncProvider.prototype.getProviderName = function () {
      return 'AWSAppSyncProvider';
    };
  
    AWSAppSyncProvider.prototype.publish = function (topics, msg, options) {
      return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
          throw new Error('Operation not supported');
        });
      });
    };
  
    AWSAppSyncProvider.prototype._cleanUp = function (clientId) {
      var _this = this;
  
      var topicsForClient = Array.from(this._topicClient.entries()).filter(function (_a) {
        var _b = __read(_a, 2),
            c = _b[1];
  
        return c.clientId === clientId;
      }).map(function (_a) {
        var _b = __read(_a, 1),
            t = _b[0];
  
        return t;
      });
      topicsForClient.forEach(function (t) {
        return _this._cleanUpForTopic(t);
      });
    };
  
    AWSAppSyncProvider.prototype._cleanUpForTopic = function (topic) {
      this._topicClient["delete"](topic);
  
      this._topicAlias["delete"](topic);
    };
  
    AWSAppSyncProvider.prototype.onDisconnect = function (_a) {
      var _this = this;
  
      var clientId = _a.clientId,
          errorCode = _a.errorCode,
          args = __rest(_a, ["clientId", "errorCode"]);
  
      if (errorCode !== 0) {
        var topicsForClient = Array.from(this._topicClient.entries()).filter(function (_a) {
          var _b = __read(_a, 2),
              c = _b[1];
  
          return c.clientId === clientId;
        }).map(function (_a) {
          var _b = __read(_a, 1),
              t = _b[0];
  
          return t;
        });
        topicsForClient.forEach(function (topic) {
          if (_this._topicObservers.has(topic)) {
            _this._topicObservers.get(topic).forEach(function (obs) {
              if (!obs.closed) {
                obs.error(args);
              }
            });
  
            _this._topicObservers["delete"](topic);
          }
        });
  
        this._cleanUp(clientId);
      }
    };
  
    AWSAppSyncProvider.prototype.disconnect = function (clientId) {
      return __awaiter(this, void 0, void 0, function () {
        var client;
        return __generator(this, function (_a) {
          switch (_a.label) {
            case 0:
              return [4
              /*yield*/
              , this.clientsQueue.get(clientId, function () {
                return null;
              })];
  
            case 1:
              client = _a.sent();
              return [4
              /*yield*/
              , _super.prototype.disconnect.call(this, clientId)];
  
            case 2:
              _a.sent();
  
              this._cleanUp(clientId);
  
              return [2
              /*return*/
              ];
          }
        });
      });
    };
  
    AWSAppSyncProvider.prototype.subscribe = function (topics, options) {
      var _this = this;
  
      if (options === void 0) {
        options = {};
      }
  
      var result = new zen_observable_ts__WEBPACK_IMPORTED_MODULE_0__["default"](function (observer) {
        var targetTopics = [].concat(topics);
        logger.debug('Subscribing to topic(s)', targetTopics.join(','));
  
        (function () {
          return __awaiter(_this, void 0, void 0, function () {
            var _a, mqttConnections, newSubscriptions, newAliases, map;
  
            var _this = this;
  
            return __generator(this, function (_b) {
              switch (_b.label) {
                case 0:
                  // Add these topics to map
                  targetTopics.forEach(function (t) {
                    if (!_this._topicObservers.has(t)) {
                      _this._topicObservers.set(t, new Set());
                    }
  
                    _this._topicObservers.get(t).add(observer);
                  });
                  _a = options.mqttConnections, mqttConnections = _a === void 0 ? [] : _a, newSubscriptions = options.newSubscriptions;
                  newAliases = Object.entries(newSubscriptions).map(function (_a) {
                    var _b = __read(_a, 2),
                        alias = _b[0],
                        v = _b[1];
  
                    return [v.topic, alias];
                  }); // Merge new aliases with old ones
  
                  this._topicAlias = new Map(__spread(Array.from(this._topicAlias.entries()), newAliases));
                  map = Object.entries(targetTopics.reduce(function (acc, elem) {
                    var connectionInfoForTopic = mqttConnections.find(function (c) {
                      return c.topics.indexOf(elem) > -1;
                    });
  
                    if (connectionInfoForTopic) {
                      var clientId = connectionInfoForTopic.client,
                          url = connectionInfoForTopic.url;
  
                      if (!acc[clientId]) {
                        acc[clientId] = {
                          url: url,
                          topics: new Set()
                        };
                      }
  
                      acc[clientId].topics.add(elem);
                    }
  
                    return acc;
                  }, {})); // reconnect everything we have in the map
  
                  return [4
                  /*yield*/
                  , Promise.all(map.map(function (_a) {
                    var _b = __read(_a, 2),
                        clientId = _b[0],
                        _c = _b[1],
                        url = _c.url,
                        topics = _c.topics;
  
                    return __awaiter(_this, void 0, void 0, function () {
                      var client, err_1;
  
                      var _this = this;
  
                      return __generator(this, function (_d) {
                        switch (_d.label) {
                          case 0:
                            client = null;
                            _d.label = 1;
  
                          case 1:
                            _d.trys.push([1, 3,, 4]);
  
                            return [4
                            /*yield*/
                            , this.connect(clientId, {
                              clientId: clientId,
                              url: url
                            })];
  
                          case 2:
                            client = _d.sent();
                            return [3
                            /*break*/
                            , 4];
  
                          case 3:
                            err_1 = _d.sent();
                            observer.error({
                              message: 'Failed to connect',
                              error: err_1
                            });
                            observer.complete();
                            return [2
                            /*return*/
                            , undefined];
  
                          case 4:
                            // subscribe to all topics for this client
                            // store topic-client mapping
                            topics.forEach(function (topic) {
                              if (client.isConnected()) {
                                client.subscribe(topic);
  
                                _this._topicClient.set(topic, client);
                              }
                            });
                            return [2
                            /*return*/
                            , client];
                        }
                      });
                    });
                  }))];
  
                case 1:
                  // reconnect everything we have in the map
                  _b.sent();
  
                  return [2
                  /*return*/
                  ];
              }
            });
          });
        })();
  
        return function () {
          logger.debug('Unsubscribing from topic(s)', targetTopics.join(','));
          targetTopics.forEach(function (t) {
            var client = _this._topicClient.get(t);
  
            if (client && client.isConnected()) {
              client.unsubscribe(t);
  
              _this._topicClient["delete"](t);
  
              if (!Array.from(_this._topicClient.values()).some(function (c) {
                return c === client;
              })) {
                _this.disconnect(client.clientId);
              }
            }
  
            _this._topicObservers["delete"](t);
          });
        };
      });
      return zen_observable_ts__WEBPACK_IMPORTED_MODULE_0__["default"].from(result).map(function (value) {
        var topic = _this.getTopicForValue(value);
  
        var alias = _this._topicAlias.get(topic);
  
        value.data = Object.entries(value.data).reduce(function (obj, _a) {
          var _b = __read(_a, 2),
              origKey = _b[0],
              val = _b[1];
  
          return obj[alias || origKey] = val, obj;
        }, {});
        return value;
      });
    };
  
    return AWSAppSyncProvider;
  }(_MqttOverWSProvider__WEBPACK_IMPORTED_MODULE_2__["MqttOverWSProvider"]);
  
  
  
  /***/ }),
  
  /***/ "./lib-esm/Providers/AWSAppSyncRealTimeProvider.js":
  /*!*********************************************************!*\
    !*** ./lib-esm/Providers/AWSAppSyncRealTimeProvider.js ***!
    \*********************************************************/
  /*! exports provided: AWSAppSyncRealTimeProvider */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AWSAppSyncRealTimeProvider", function() { return AWSAppSyncRealTimeProvider; });
  /* harmony import */ var zen_observable_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zen-observable-ts */ "../../node_modules/zen-observable-ts/lib/bundle.esm.js");
  /* harmony import */ var graphql__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! graphql */ "graphql");
  /* harmony import */ var graphql__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(graphql__WEBPACK_IMPORTED_MODULE_1__);
  /* harmony import */ var url__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! url */ "../../node_modules/url/url.js");
  /* harmony import */ var url__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(url__WEBPACK_IMPORTED_MODULE_2__);
  /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! uuid */ "../../node_modules/uuid/index.js");
  /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(uuid__WEBPACK_IMPORTED_MODULE_3__);
  /* harmony import */ var buffer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! buffer */ "../../node_modules/buffer/index.js");
  /* harmony import */ var buffer__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(buffer__WEBPACK_IMPORTED_MODULE_4__);
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @aws-amplify/core */ "@aws-amplify/core");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__);
  /* harmony import */ var _aws_amplify_cache__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @aws-amplify/cache */ "@aws-amplify/cache");
  /* harmony import */ var _aws_amplify_cache__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_cache__WEBPACK_IMPORTED_MODULE_6__);
  /* harmony import */ var _aws_amplify_auth__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @aws-amplify/auth */ "@aws-amplify/auth");
  /* harmony import */ var _aws_amplify_auth__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_auth__WEBPACK_IMPORTED_MODULE_7__);
  /* harmony import */ var _PubSubProvider__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./PubSubProvider */ "./lib-esm/Providers/PubSubProvider.js");
  /* harmony import */ var _index__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../index */ "./lib-esm/index.js");
  var __extends = undefined && undefined.__extends || function () {
    var _extendStatics = function extendStatics(d, b) {
      _extendStatics = Object.setPrototypeOf || {
        __proto__: []
      } instanceof Array && function (d, b) {
        d.__proto__ = b;
      } || function (d, b) {
        for (var p in b) {
          if (b.hasOwnProperty(p)) d[p] = b[p];
        }
      };
  
      return _extendStatics(d, b);
    };
  
    return function (d, b) {
      _extendStatics(d, b);
  
      function __() {
        this.constructor = d;
      }
  
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
  }();
  
  var __assign = undefined && undefined.__assign || function () {
    __assign = Object.assign || function (t) {
      for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
  
        for (var p in s) {
          if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
      }
  
      return t;
    };
  
    return __assign.apply(this, arguments);
  };
  
  var __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {
    function adopt(value) {
      return value instanceof P ? value : new P(function (resolve) {
        resolve(value);
      });
    }
  
    return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      }
  
      function rejected(value) {
        try {
          step(generator["throw"](value));
        } catch (e) {
          reject(e);
        }
      }
  
      function step(result) {
        result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
      }
  
      step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
  };
  
  var __generator = undefined && undefined.__generator || function (thisArg, body) {
    var _ = {
      label: 0,
      sent: function sent() {
        if (t[0] & 1) throw t[1];
        return t[1];
      },
      trys: [],
      ops: []
    },
        f,
        y,
        t,
        g;
    return g = {
      next: verb(0),
      "throw": verb(1),
      "return": verb(2)
    }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
      return this;
    }), g;
  
    function verb(n) {
      return function (v) {
        return step([n, v]);
      };
    }
  
    function step(op) {
      if (f) throw new TypeError("Generator is already executing.");
  
      while (_) {
        try {
          if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
          if (y = 0, t) op = [op[0] & 2, t.value];
  
          switch (op[0]) {
            case 0:
            case 1:
              t = op;
              break;
  
            case 4:
              _.label++;
              return {
                value: op[1],
                done: false
              };
  
            case 5:
              _.label++;
              y = op[1];
              op = [0];
              continue;
  
            case 7:
              op = _.ops.pop();
  
              _.trys.pop();
  
              continue;
  
            default:
              if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                _ = 0;
                continue;
              }
  
              if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
                _.label = op[1];
                break;
              }
  
              if (op[0] === 6 && _.label < t[1]) {
                _.label = t[1];
                t = op;
                break;
              }
  
              if (t && _.label < t[2]) {
                _.label = t[2];
  
                _.ops.push(op);
  
                break;
              }
  
              if (t[2]) _.ops.pop();
  
              _.trys.pop();
  
              continue;
          }
  
          op = body.call(thisArg, _);
        } catch (e) {
          op = [6, e];
          y = 0;
        } finally {
          f = t = 0;
        }
      }
  
      if (op[0] & 5) throw op[1];
      return {
        value: op[0] ? op[1] : void 0,
        done: true
      };
    }
  };
  
  var __read = undefined && undefined.__read || function (o, n) {
    var m = typeof Symbol === "function" && o[Symbol.iterator];
    if (!m) return o;
    var i = m.call(o),
        r,
        ar = [],
        e;
  
    try {
      while ((n === void 0 || n-- > 0) && !(r = i.next()).done) {
        ar.push(r.value);
      }
    } catch (error) {
      e = {
        error: error
      };
    } finally {
      try {
        if (r && !r.done && (m = i["return"])) m.call(i);
      } finally {
        if (e) throw e.error;
      }
    }
  
    return ar;
  };
  /*
   * Copyright 2017-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
   * the License. A copy of the License is located at
   *
   *     http://aws.amazon.com/apache2.0/
   *
   * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
   * and limitations under the License.
   */
  
  
  
  
  
  
  
  
  
  
  
  
  var logger = new _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["Logger"]('AWSAppSyncRealTimeProvider');
  var AMPLIFY_SYMBOL = typeof Symbol !== 'undefined' && typeof Symbol["for"] === 'function' ? Symbol["for"]('amplify_default') : '@@amplify_default';
  
  var dispatchApiEvent = function dispatchApiEvent(event, data, message) {
    _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["Hub"].dispatch('api', {
      event: event,
      data: data,
      message: message
    }, 'PubSub', AMPLIFY_SYMBOL);
  };
  
  var MAX_DELAY_MS = 5000;
  var NON_RETRYABLE_CODES = [400, 401, 403];
  var MESSAGE_TYPES;
  
  (function (MESSAGE_TYPES) {
    /**
     * Client -> Server message.
     * This message type is the first message after handshake and this will initialize AWS AppSync RealTime communication
     */
    MESSAGE_TYPES["GQL_CONNECTION_INIT"] = "connection_init";
    /**
     * Server -> Client message
     * This message type is in case there is an issue with AWS AppSync RealTime when establishing connection
     */
  
    MESSAGE_TYPES["GQL_CONNECTION_ERROR"] = "connection_error";
    /**
     * Server -> Client message.
     * This message type is for the ack response from AWS AppSync RealTime for GQL_CONNECTION_INIT message
     */
  
    MESSAGE_TYPES["GQL_CONNECTION_ACK"] = "connection_ack";
    /**
     * Client -> Server message.
     * This message type is for register subscriptions with AWS AppSync RealTime
     */
  
    MESSAGE_TYPES["GQL_START"] = "start";
    /**
     * Server -> Client message.
     * This message type is for the ack response from AWS AppSync RealTime for GQL_START message
     */
  
    MESSAGE_TYPES["GQL_START_ACK"] = "start_ack";
    /**
     * Server -> Client message.
     * This message type is for subscription message from AWS AppSync RealTime
     */
  
    MESSAGE_TYPES["GQL_DATA"] = "data";
    /**
     * Server -> Client message.
     * This message type helps the client to know is still receiving messages from AWS AppSync RealTime
     */
  
    MESSAGE_TYPES["GQL_CONNECTION_KEEP_ALIVE"] = "ka";
    /**
     * Client -> Server message.
     * This message type is for unregister subscriptions with AWS AppSync RealTime
     */
  
    MESSAGE_TYPES["GQL_STOP"] = "stop";
    /**
     * Server -> Client message.
     * This message type is for the ack response from AWS AppSync RealTime for GQL_STOP message
     */
  
    MESSAGE_TYPES["GQL_COMPLETE"] = "complete";
    /**
     * Server -> Client message.
     * This message type is for sending error messages from AWS AppSync RealTime to the client
     */
  
    MESSAGE_TYPES["GQL_ERROR"] = "error";
  })(MESSAGE_TYPES || (MESSAGE_TYPES = {}));
  
  var SUBSCRIPTION_STATUS;
  
  (function (SUBSCRIPTION_STATUS) {
    SUBSCRIPTION_STATUS[SUBSCRIPTION_STATUS["PENDING"] = 0] = "PENDING";
    SUBSCRIPTION_STATUS[SUBSCRIPTION_STATUS["CONNECTED"] = 1] = "CONNECTED";
    SUBSCRIPTION_STATUS[SUBSCRIPTION_STATUS["FAILED"] = 2] = "FAILED";
  })(SUBSCRIPTION_STATUS || (SUBSCRIPTION_STATUS = {}));
  
  var SOCKET_STATUS;
  
  (function (SOCKET_STATUS) {
    SOCKET_STATUS[SOCKET_STATUS["CLOSED"] = 0] = "CLOSED";
    SOCKET_STATUS[SOCKET_STATUS["READY"] = 1] = "READY";
    SOCKET_STATUS[SOCKET_STATUS["CONNECTING"] = 2] = "CONNECTING";
  })(SOCKET_STATUS || (SOCKET_STATUS = {}));
  
  var AWS_APPSYNC_REALTIME_HEADERS = {
    accept: 'application/json, text/javascript',
    'content-encoding': 'amz-1.0',
    'content-type': 'application/json; charset=UTF-8'
  };
  /**
   * Time in milleseconds to wait for GQL_CONNECTION_INIT message
   */
  
  var CONNECTION_INIT_TIMEOUT = 15000;
  /**
   * Time in milleseconds to wait for GQL_START_ACK message
   */
  
  var START_ACK_TIMEOUT = 15000;
  /**
   * Default Time in milleseconds to wait for GQL_CONNECTION_KEEP_ALIVE message
   */
  
  var DEFAULT_KEEP_ALIVE_TIMEOUT = 5 * 60 * 1000;
  
  var AWSAppSyncRealTimeProvider =
  /** @class */
  function (_super) {
    __extends(AWSAppSyncRealTimeProvider, _super);
  
    function AWSAppSyncRealTimeProvider() {
      var _this = _super !== null && _super.apply(this, arguments) || this;
  
      _this.socketStatus = SOCKET_STATUS.CLOSED;
      _this.keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
      _this.subscriptionObserverMap = new Map();
      _this.promiseArray = [];
      return _this;
    }
  
    AWSAppSyncRealTimeProvider.prototype.getProviderName = function () {
      return 'AWSAppSyncRealTimeProvider';
    };
  
    AWSAppSyncRealTimeProvider.prototype.newClient = function () {
      throw new Error('Not used here');
    };
  
    AWSAppSyncRealTimeProvider.prototype.publish = function (_topics, _msg, _options) {
      return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
          throw new Error('Operation not supported');
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype.subscribe = function (_topics, options) {
      var _this = this;
  
      var appSyncGraphqlEndpoint = options.appSyncGraphqlEndpoint;
      return new zen_observable_ts__WEBPACK_IMPORTED_MODULE_0__["default"](function (observer) {
        if (!appSyncGraphqlEndpoint) {
          observer.error({
            errors: [__assign({}, new graphql__WEBPACK_IMPORTED_MODULE_1__["GraphQLError"]("Subscribe only available for AWS AppSync endpoint"))]
          });
          observer.complete();
        } else {
          var subscriptionId_1 = Object(uuid__WEBPACK_IMPORTED_MODULE_3__["v4"])();
  
          _this._startSubscriptionWithAWSAppSyncRealTime({
            options: options,
            observer: observer,
            subscriptionId: subscriptionId_1
          })["catch"](function (err) {
            observer.error({
              errors: [__assign({}, new graphql__WEBPACK_IMPORTED_MODULE_1__["GraphQLError"](_index__WEBPACK_IMPORTED_MODULE_9__["CONTROL_MSG"].REALTIME_SUBSCRIPTION_INIT_ERROR + ": " + err))]
            });
            observer.complete();
          });
  
          return function () {
            return __awaiter(_this, void 0, void 0, function () {
              var subscriptionState, err_1;
              return __generator(this, function (_a) {
                switch (_a.label) {
                  case 0:
                    _a.trys.push([0, 2, 3, 4]); // Waiting that subscription has been connected before trying to unsubscribe
  
  
                    return [4
                    /*yield*/
                    , this._waitForSubscriptionToBeConnected(subscriptionId_1)];
  
                  case 1:
                    // Waiting that subscription has been connected before trying to unsubscribe
                    _a.sent();
  
                    subscriptionState = (this.subscriptionObserverMap.get(subscriptionId_1) || {}).subscriptionState;
  
                    if (!subscriptionState) {
                      // subscription already unsubscribed
                      return [2
                      /*return*/
                      ];
                    }
  
                    if (subscriptionState === SUBSCRIPTION_STATUS.CONNECTED) {
                      this._sendUnsubscriptionMessage(subscriptionId_1);
                    } else {
                      throw new Error('Subscription never connected');
                    }
  
                    return [3
                    /*break*/
                    , 4];
  
                  case 2:
                    err_1 = _a.sent();
                    logger.debug("Error while unsubscribing " + err_1);
                    return [3
                    /*break*/
                    , 4];
  
                  case 3:
                    this._removeSubscriptionObserver(subscriptionId_1);
  
                    return [7
                    /*endfinally*/
                    ];
  
                  case 4:
                    return [2
                    /*return*/
                    ];
                }
              });
            });
          };
        }
      });
    };
  
    Object.defineProperty(AWSAppSyncRealTimeProvider.prototype, "isSSLEnabled", {
      get: function get() {
        return !this.options.aws_appsync_dangerously_connect_to_http_endpoint_for_testing;
      },
      enumerable: true,
      configurable: true
    });
  
    AWSAppSyncRealTimeProvider.prototype._startSubscriptionWithAWSAppSyncRealTime = function (_a) {
      var options = _a.options,
          observer = _a.observer,
          subscriptionId = _a.subscriptionId;
      return __awaiter(this, void 0, void 0, function () {
        var appSyncGraphqlEndpoint, authenticationType, query, variables, apiKey, region, _b, graphql_headers, _c, additionalHeaders, subscriptionState, data, dataString, headerObj, _d, _e, subscriptionMessage, stringToAWSRealTime, err_2, _f, message, subscriptionFailedCallback_1, _g, subscriptionFailedCallback, subscriptionReadyCallback;
  
        var _h;
  
        var _this = this;
  
        return __generator(this, function (_j) {
          switch (_j.label) {
            case 0:
              appSyncGraphqlEndpoint = options.appSyncGraphqlEndpoint, authenticationType = options.authenticationType, query = options.query, variables = options.variables, apiKey = options.apiKey, region = options.region, _b = options.graphql_headers, graphql_headers = _b === void 0 ? function () {
                return {};
              } : _b, _c = options.additionalHeaders, additionalHeaders = _c === void 0 ? {} : _c;
              subscriptionState = SUBSCRIPTION_STATUS.PENDING;
              data = {
                query: query,
                variables: variables
              }; // Having a subscription id map will make it simple to forward messages received
  
              this.subscriptionObserverMap.set(subscriptionId, {
                observer: observer,
                query: query,
                variables: variables,
                subscriptionState: subscriptionState,
                startAckTimeoutId: null
              });
              dataString = JSON.stringify(data);
              _d = [{}];
              return [4
              /*yield*/
              , this._awsRealTimeHeaderBasedAuth({
                apiKey: apiKey,
                appSyncGraphqlEndpoint: appSyncGraphqlEndpoint,
                authenticationType: authenticationType,
                payload: dataString,
                canonicalUri: '',
                region: region
              })];
  
            case 1:
              _e = [__assign.apply(void 0, _d.concat([_j.sent()]))];
              return [4
              /*yield*/
              , graphql_headers()];
  
            case 2:
              headerObj = __assign.apply(void 0, [__assign.apply(void 0, [__assign.apply(void 0, _e.concat([_j.sent()])), additionalHeaders]), (_h = {}, _h[_aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["USER_AGENT_HEADER"]] = _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["Constants"].userAgent, _h)]);
              subscriptionMessage = {
                id: subscriptionId,
                payload: {
                  data: dataString,
                  extensions: {
                    authorization: __assign({}, headerObj)
                  }
                },
                type: MESSAGE_TYPES.GQL_START
              };
              stringToAWSRealTime = JSON.stringify(subscriptionMessage);
              _j.label = 3;
  
            case 3:
              _j.trys.push([3, 5,, 6]);
  
              return [4
              /*yield*/
              , this._initializeWebSocketConnection({
                apiKey: apiKey,
                appSyncGraphqlEndpoint: appSyncGraphqlEndpoint,
                authenticationType: authenticationType,
                region: region
              })];
  
            case 4:
              _j.sent();
  
              return [3
              /*break*/
              , 6];
  
            case 5:
              err_2 = _j.sent();
              logger.debug({
                err: err_2
              });
              _f = err_2.message, message = _f === void 0 ? '' : _f;
              observer.error({
                errors: [__assign({}, new graphql__WEBPACK_IMPORTED_MODULE_1__["GraphQLError"](_index__WEBPACK_IMPORTED_MODULE_9__["CONTROL_MSG"].CONNECTION_FAILED + ": " + message))]
              });
              observer.complete();
              subscriptionFailedCallback_1 = (this.subscriptionObserverMap.get(subscriptionId) || {}).subscriptionFailedCallback; // Notify concurrent unsubscription
  
              if (typeof subscriptionFailedCallback_1 === 'function') {
                subscriptionFailedCallback_1();
              }
  
              return [2
              /*return*/
              ];
  
            case 6:
              _g = this.subscriptionObserverMap.get(subscriptionId), subscriptionFailedCallback = _g.subscriptionFailedCallback, subscriptionReadyCallback = _g.subscriptionReadyCallback; // This must be done before sending the message in order to be listening immediately
  
              this.subscriptionObserverMap.set(subscriptionId, {
                observer: observer,
                subscriptionState: subscriptionState,
                variables: variables,
                query: query,
                subscriptionReadyCallback: subscriptionReadyCallback,
                subscriptionFailedCallback: subscriptionFailedCallback,
                startAckTimeoutId: setTimeout(function () {
                  _this._timeoutStartSubscriptionAck.call(_this, subscriptionId);
                }, START_ACK_TIMEOUT)
              });
  
              if (this.awsRealTimeSocket) {
                this.awsRealTimeSocket.send(stringToAWSRealTime);
              }
  
              return [2
              /*return*/
              ];
          }
        });
      });
    }; // Waiting that subscription has been connected before trying to unsubscribe
  
  
    AWSAppSyncRealTimeProvider.prototype._waitForSubscriptionToBeConnected = function (subscriptionId) {
      return __awaiter(this, void 0, void 0, function () {
        var subscriptionState;
  
        var _this = this;
  
        return __generator(this, function (_a) {
          subscriptionState = this.subscriptionObserverMap.get(subscriptionId).subscriptionState; // This in case unsubscribe is invoked before sending start subscription message
  
          if (subscriptionState === SUBSCRIPTION_STATUS.PENDING) {
            return [2
            /*return*/
            , new Promise(function (res, rej) {
              var _a = _this.subscriptionObserverMap.get(subscriptionId),
                  observer = _a.observer,
                  subscriptionState = _a.subscriptionState,
                  variables = _a.variables,
                  query = _a.query;
  
              _this.subscriptionObserverMap.set(subscriptionId, {
                observer: observer,
                subscriptionState: subscriptionState,
                variables: variables,
                query: query,
                subscriptionReadyCallback: res,
                subscriptionFailedCallback: rej
              });
            })];
          }
  
          return [2
          /*return*/
          ];
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._sendUnsubscriptionMessage = function (subscriptionId) {
      try {
        if (this.awsRealTimeSocket && this.awsRealTimeSocket.readyState === WebSocket.OPEN && this.socketStatus === SOCKET_STATUS.READY) {
          // Preparing unsubscribe message to stop receiving messages for that subscription
          var unsubscribeMessage = {
            id: subscriptionId,
            type: MESSAGE_TYPES.GQL_STOP
          };
          var stringToAWSRealTime = JSON.stringify(unsubscribeMessage);
          this.awsRealTimeSocket.send(stringToAWSRealTime);
        }
      } catch (err) {
        // If GQL_STOP is not sent because of disconnection issue, then there is nothing the client can do
        logger.debug({
          err: err
        });
      }
    };
  
    AWSAppSyncRealTimeProvider.prototype._removeSubscriptionObserver = function (subscriptionId) {
      this.subscriptionObserverMap["delete"](subscriptionId); // Verifying 1000ms after removing subscription in case there are new subscription unmount/mount
  
      setTimeout(this._closeSocketIfRequired.bind(this), 1000);
    };
  
    AWSAppSyncRealTimeProvider.prototype._closeSocketIfRequired = function () {
      if (this.subscriptionObserverMap.size > 0) {
        // Active subscriptions on the WebSocket
        return;
      }
  
      if (!this.awsRealTimeSocket) {
        this.socketStatus = SOCKET_STATUS.CLOSED;
        return;
      }
  
      if (this.awsRealTimeSocket.bufferedAmount > 0) {
        // Still data on the WebSocket
        setTimeout(this._closeSocketIfRequired.bind(this), 1000);
      } else {
        logger.debug('closing WebSocket...');
        clearTimeout(this.keepAliveTimeoutId);
        var tempSocket = this.awsRealTimeSocket; // Cleaning callbacks to avoid race condition, socket still exists
  
        tempSocket.onclose = undefined;
        tempSocket.onerror = undefined;
        tempSocket.close(1000);
        this.awsRealTimeSocket = null;
        this.socketStatus = SOCKET_STATUS.CLOSED;
      }
    };
  
    AWSAppSyncRealTimeProvider.prototype._handleIncomingSubscriptionMessage = function (message) {
      logger.debug("subscription message from AWS AppSync RealTime: " + message.data);
  
      var _a = JSON.parse(message.data),
          _b = _a.id,
          id = _b === void 0 ? '' : _b,
          payload = _a.payload,
          type = _a.type;
  
      var _c = this.subscriptionObserverMap.get(id) || {},
          _d = _c.observer,
          observer = _d === void 0 ? null : _d,
          _e = _c.query,
          query = _e === void 0 ? '' : _e,
          _f = _c.variables,
          variables = _f === void 0 ? {} : _f,
          startAckTimeoutId = _c.startAckTimeoutId,
          subscriptionReadyCallback = _c.subscriptionReadyCallback,
          subscriptionFailedCallback = _c.subscriptionFailedCallback;
  
      logger.debug({
        id: id,
        observer: observer,
        query: query,
        variables: variables
      });
  
      if (type === MESSAGE_TYPES.GQL_DATA && payload && payload.data) {
        if (observer) {
          observer.next(payload);
        } else {
          logger.debug("observer not found for id: " + id);
        }
  
        return;
      }
  
      if (type === MESSAGE_TYPES.GQL_START_ACK) {
        logger.debug("subscription ready for " + JSON.stringify({
          query: query,
          variables: variables
        }));
  
        if (typeof subscriptionReadyCallback === 'function') {
          subscriptionReadyCallback();
        }
  
        clearTimeout(startAckTimeoutId);
        dispatchApiEvent(_index__WEBPACK_IMPORTED_MODULE_9__["CONTROL_MSG"].SUBSCRIPTION_ACK, {
          query: query,
          variables: variables
        }, 'Connection established for subscription');
        var subscriptionState = SUBSCRIPTION_STATUS.CONNECTED;
        this.subscriptionObserverMap.set(id, {
          observer: observer,
          query: query,
          variables: variables,
          startAckTimeoutId: null,
          subscriptionState: subscriptionState,
          subscriptionReadyCallback: subscriptionReadyCallback,
          subscriptionFailedCallback: subscriptionFailedCallback
        }); // TODO: emit event on hub but it requires to store the id first
  
        return;
      }
  
      if (type === MESSAGE_TYPES.GQL_CONNECTION_KEEP_ALIVE) {
        clearTimeout(this.keepAliveTimeoutId);
        this.keepAliveTimeoutId = setTimeout(this._errorDisconnect.bind(this, _index__WEBPACK_IMPORTED_MODULE_9__["CONTROL_MSG"].TIMEOUT_DISCONNECT), this.keepAliveTimeout);
        return;
      }
  
      if (type === MESSAGE_TYPES.GQL_ERROR) {
        var subscriptionState = SUBSCRIPTION_STATUS.FAILED;
        this.subscriptionObserverMap.set(id, {
          observer: observer,
          query: query,
          variables: variables,
          startAckTimeoutId: startAckTimeoutId,
          subscriptionReadyCallback: subscriptionReadyCallback,
          subscriptionFailedCallback: subscriptionFailedCallback,
          subscriptionState: subscriptionState
        });
        observer.error({
          errors: [__assign({}, new graphql__WEBPACK_IMPORTED_MODULE_1__["GraphQLError"](_index__WEBPACK_IMPORTED_MODULE_9__["CONTROL_MSG"].CONNECTION_FAILED + ": " + JSON.stringify(payload)))]
        });
        clearTimeout(startAckTimeoutId);
        observer.complete();
  
        if (typeof subscriptionFailedCallback === 'function') {
          subscriptionFailedCallback();
        }
      }
    };
  
    AWSAppSyncRealTimeProvider.prototype._errorDisconnect = function (msg) {
      logger.debug("Disconnect error: " + msg);
      this.subscriptionObserverMap.forEach(function (_a) {
        var observer = _a.observer;
  
        if (observer && !observer.closed) {
          observer.error({
            errors: [__assign({}, new graphql__WEBPACK_IMPORTED_MODULE_1__["GraphQLError"](msg))]
          });
        }
      });
      this.subscriptionObserverMap.clear();
  
      if (this.awsRealTimeSocket) {
        this.awsRealTimeSocket.close();
      }
  
      this.socketStatus = SOCKET_STATUS.CLOSED;
    };
  
    AWSAppSyncRealTimeProvider.prototype._timeoutStartSubscriptionAck = function (subscriptionId) {
      var _a = this.subscriptionObserverMap.get(subscriptionId) || {},
          observer = _a.observer,
          query = _a.query,
          variables = _a.variables;
  
      if (!observer) {
        return;
      }
  
      this.subscriptionObserverMap.set(subscriptionId, {
        observer: observer,
        query: query,
        variables: variables,
        subscriptionState: SUBSCRIPTION_STATUS.FAILED
      });
  
      if (observer && !observer.closed) {
        observer.error({
          errors: [__assign({}, new graphql__WEBPACK_IMPORTED_MODULE_1__["GraphQLError"]("Subscription timeout " + JSON.stringify({
            query: query,
            variables: variables
          })))]
        }); // Cleanup will be automatically executed
  
        observer.complete();
      }
  
      logger.debug('timeoutStartSubscription', JSON.stringify({
        query: query,
        variables: variables
      }));
    };
  
    AWSAppSyncRealTimeProvider.prototype._initializeWebSocketConnection = function (_a) {
      var _this = this;
  
      var appSyncGraphqlEndpoint = _a.appSyncGraphqlEndpoint,
          authenticationType = _a.authenticationType,
          apiKey = _a.apiKey,
          region = _a.region;
  
      if (this.socketStatus === SOCKET_STATUS.READY) {
        return;
      }
  
      return new Promise(function (res, rej) {
        return __awaiter(_this, void 0, void 0, function () {
          var protocol, discoverableEndpoint, payloadString, headerString, _a, _b, headerQs, payloadQs, awsRealTimeUrl, err_3;
  
          return __generator(this, function (_c) {
            switch (_c.label) {
              case 0:
                this.promiseArray.push({
                  res: res,
                  rej: rej
                });
                if (!(this.socketStatus === SOCKET_STATUS.CLOSED)) return [3
                /*break*/
                , 5];
                _c.label = 1;
  
              case 1:
                _c.trys.push([1, 4,, 5]);
  
                this.socketStatus = SOCKET_STATUS.CONNECTING;
                protocol = this.isSSLEnabled ? 'wss://' : 'ws://';
                discoverableEndpoint = appSyncGraphqlEndpoint.replace('https://', protocol).replace('http://', protocol).replace('appsync-api', 'appsync-realtime-api').replace('gogi-beta', 'grt-beta');
                payloadString = '{}';
                _b = (_a = JSON).stringify;
                return [4
                /*yield*/
                , this._awsRealTimeHeaderBasedAuth({
                  authenticationType: authenticationType,
                  payload: payloadString,
                  canonicalUri: '/connect',
                  apiKey: apiKey,
                  appSyncGraphqlEndpoint: appSyncGraphqlEndpoint,
                  region: region
                })];
  
              case 2:
                headerString = _b.apply(_a, [_c.sent()]);
                headerQs = buffer__WEBPACK_IMPORTED_MODULE_4__["Buffer"].from(headerString).toString('base64');
                payloadQs = buffer__WEBPACK_IMPORTED_MODULE_4__["Buffer"].from(payloadString).toString('base64');
                awsRealTimeUrl = discoverableEndpoint + "?header=" + headerQs + "&payload=" + payloadQs;
                return [4
                /*yield*/
                , this._initializeRetryableHandshake({
                  awsRealTimeUrl: awsRealTimeUrl
                })];
  
              case 3:
                _c.sent();
  
                this.promiseArray.forEach(function (_a) {
                  var res = _a.res;
                  logger.debug('Notifying connection successful');
                  res();
                });
                this.socketStatus = SOCKET_STATUS.READY;
                this.promiseArray = [];
                return [3
                /*break*/
                , 5];
  
              case 4:
                err_3 = _c.sent();
                this.promiseArray.forEach(function (_a) {
                  var rej = _a.rej;
                  return rej(err_3);
                });
                this.promiseArray = [];
  
                if (this.awsRealTimeSocket && this.awsRealTimeSocket.readyState === WebSocket.OPEN) {
                  this.awsRealTimeSocket.close(3001);
                }
  
                this.awsRealTimeSocket = null;
                this.socketStatus = SOCKET_STATUS.CLOSED;
                return [3
                /*break*/
                , 5];
  
              case 5:
                return [2
                /*return*/
                ];
            }
          });
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._initializeRetryableHandshake = function (_a) {
      var awsRealTimeUrl = _a.awsRealTimeUrl;
      return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_b) {
          switch (_b.label) {
            case 0:
              logger.debug("Initializaling retryable Handshake");
              return [4
              /*yield*/
              , Object(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["jitteredExponentialRetry"])(this._initializeHandshake.bind(this), [{
                awsRealTimeUrl: awsRealTimeUrl
              }], MAX_DELAY_MS)];
  
            case 1:
              _b.sent();
  
              return [2
              /*return*/
              ];
          }
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._initializeHandshake = function (_a) {
      var awsRealTimeUrl = _a.awsRealTimeUrl;
      return __awaiter(this, void 0, void 0, function () {
        var err_4, errorType, errorCode;
  
        var _this = this;
  
        return __generator(this, function (_b) {
          switch (_b.label) {
            case 0:
              logger.debug("Initializing handshake " + awsRealTimeUrl);
              _b.label = 1;
  
            case 1:
              _b.trys.push([1, 4,, 5]);
  
              return [4
              /*yield*/
              , function () {
                return new Promise(function (res, rej) {
                  var newSocket = new WebSocket(awsRealTimeUrl, 'graphql-ws');
  
                  newSocket.onerror = function () {
                    logger.debug("WebSocket connection error");
                  };
  
                  newSocket.onclose = function () {
                    rej(new Error('Connection handshake error'));
                  };
  
                  newSocket.onopen = function () {
                    _this.awsRealTimeSocket = newSocket;
                    return res();
                  };
                });
              }()];
  
            case 2:
              _b.sent(); // Step 2: wait for ack from AWS AppSyncReaTime after sending init
  
  
              return [4
              /*yield*/
              , function () {
                return new Promise(function (res, rej) {
                  var ackOk = false;
  
                  _this.awsRealTimeSocket.onerror = function (error) {
                    logger.debug("WebSocket error " + JSON.stringify(error));
                  };
  
                  _this.awsRealTimeSocket.onclose = function (event) {
                    logger.debug("WebSocket closed " + event.reason);
                    rej(new Error(JSON.stringify(event)));
                  };
  
                  _this.awsRealTimeSocket.onmessage = function (message) {
                    logger.debug("subscription message from AWS AppSyncRealTime: " + message.data + " ");
                    var data = JSON.parse(message.data);
                    var type = data.type,
                        _a = data.payload,
                        _b = (_a === void 0 ? {} : _a).connectionTimeoutMs,
                        connectionTimeoutMs = _b === void 0 ? DEFAULT_KEEP_ALIVE_TIMEOUT : _b;
  
                    if (type === MESSAGE_TYPES.GQL_CONNECTION_ACK) {
                      ackOk = true;
                      _this.keepAliveTimeout = connectionTimeoutMs;
                      _this.awsRealTimeSocket.onmessage = _this._handleIncomingSubscriptionMessage.bind(_this);
  
                      _this.awsRealTimeSocket.onerror = function (err) {
                        logger.debug(err);
  
                        _this._errorDisconnect(_index__WEBPACK_IMPORTED_MODULE_9__["CONTROL_MSG"].CONNECTION_CLOSED);
                      };
  
                      _this.awsRealTimeSocket.onclose = function (event) {
                        logger.debug("WebSocket closed " + event.reason);
  
                        _this._errorDisconnect(_index__WEBPACK_IMPORTED_MODULE_9__["CONTROL_MSG"].CONNECTION_CLOSED);
                      };
  
                      res('Cool, connected to AWS AppSyncRealTime');
                      return;
                    }
  
                    if (type === MESSAGE_TYPES.GQL_CONNECTION_ERROR) {
                      var _c = data.payload,
                          _d = (_c === void 0 ? {} : _c).errors,
                          _e = __read(_d === void 0 ? [] : _d, 1),
                          _f = _e[0],
                          _g = _f === void 0 ? {} : _f,
                          _h = _g.errorType,
                          errorType = _h === void 0 ? '' : _h,
                          _j = _g.errorCode,
                          errorCode = _j === void 0 ? 0 : _j;
  
                      rej({
                        errorType: errorType,
                        errorCode: errorCode
                      });
                    }
                  };
  
                  var gqlInit = {
                    type: MESSAGE_TYPES.GQL_CONNECTION_INIT
                  };
  
                  _this.awsRealTimeSocket.send(JSON.stringify(gqlInit));
  
                  function checkAckOk() {
                    if (!ackOk) {
                      rej(new Error("Connection timeout: ack from AWSRealTime was not received on " + CONNECTION_INIT_TIMEOUT + " ms"));
                    }
                  }
  
                  setTimeout(checkAckOk.bind(_this), CONNECTION_INIT_TIMEOUT);
                });
              }()];
  
            case 3:
              // Step 2: wait for ack from AWS AppSyncReaTime after sending init
              _b.sent();
  
              return [3
              /*break*/
              , 5];
  
            case 4:
              err_4 = _b.sent();
              errorType = err_4.errorType, errorCode = err_4.errorCode;
  
              if (NON_RETRYABLE_CODES.includes(errorCode)) {
                throw new _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["NonRetryableError"](errorType);
              } else if (errorType) {
                throw new Error(errorType);
              } else {
                throw err_4;
              }
  
              return [3
              /*break*/
              , 5];
  
            case 5:
              return [2
              /*return*/
              ];
          }
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._awsRealTimeHeaderBasedAuth = function (_a) {
      var authenticationType = _a.authenticationType,
          payload = _a.payload,
          canonicalUri = _a.canonicalUri,
          appSyncGraphqlEndpoint = _a.appSyncGraphqlEndpoint,
          apiKey = _a.apiKey,
          region = _a.region;
      return __awaiter(this, void 0, void 0, function () {
        var headerHandler, handler, host, result;
        return __generator(this, function (_b) {
          switch (_b.label) {
            case 0:
              headerHandler = {
                API_KEY: this._awsRealTimeApiKeyHeader.bind(this),
                AWS_IAM: this._awsRealTimeIAMHeader.bind(this),
                OPENID_CONNECT: this._awsRealTimeOPENIDHeader.bind(this),
                AMAZON_COGNITO_USER_POOLS: this._awsRealTimeCUPHeader.bind(this)
              };
              handler = headerHandler[authenticationType];
  
              if (typeof handler !== 'function') {
                logger.debug("Authentication type " + authenticationType + " not supported");
                return [2
                /*return*/
                , ''];
              }
  
              host = url__WEBPACK_IMPORTED_MODULE_2__["parse"](appSyncGraphqlEndpoint).host;
              return [4
              /*yield*/
              , handler({
                payload: payload,
                canonicalUri: canonicalUri,
                appSyncGraphqlEndpoint: appSyncGraphqlEndpoint,
                apiKey: apiKey,
                region: region,
                host: host
              })];
  
            case 1:
              result = _b.sent();
              return [2
              /*return*/
              , result];
          }
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._awsRealTimeCUPHeader = function (_a) {
      var host = _a.host;
      return __awaiter(this, void 0, void 0, function () {
        var session;
        return __generator(this, function (_b) {
          switch (_b.label) {
            case 0:
              return [4
              /*yield*/
              , _aws_amplify_auth__WEBPACK_IMPORTED_MODULE_7___default.a.currentSession()];
  
            case 1:
              session = _b.sent();
              return [2
              /*return*/
              , {
                Authorization: session.getAccessToken().getJwtToken(),
                host: host
              }];
          }
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._awsRealTimeOPENIDHeader = function (_a) {
      var host = _a.host;
      return __awaiter(this, void 0, void 0, function () {
        var token, federatedInfo, currentUser;
        return __generator(this, function (_b) {
          switch (_b.label) {
            case 0:
              return [4
              /*yield*/
              , _aws_amplify_cache__WEBPACK_IMPORTED_MODULE_6___default.a.getItem('federatedInfo')];
  
            case 1:
              federatedInfo = _b.sent();
              if (!federatedInfo) return [3
              /*break*/
              , 2];
              token = federatedInfo.token;
              return [3
              /*break*/
              , 4];
  
            case 2:
              return [4
              /*yield*/
              , _aws_amplify_auth__WEBPACK_IMPORTED_MODULE_7___default.a.currentAuthenticatedUser()];
  
            case 3:
              currentUser = _b.sent();
  
              if (currentUser) {
                token = currentUser.token;
              }
  
              _b.label = 4;
  
            case 4:
              if (!token) {
                throw new Error('No federated jwt');
              }
  
              return [2
              /*return*/
              , {
                Authorization: token,
                host: host
              }];
          }
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._awsRealTimeApiKeyHeader = function (_a) {
      var apiKey = _a.apiKey,
          host = _a.host;
      return __awaiter(this, void 0, void 0, function () {
        var dt, dtStr;
        return __generator(this, function (_b) {
          dt = new Date();
          dtStr = dt.toISOString().replace(/[:\-]|\.\d{3}/g, '');
          return [2
          /*return*/
          , {
            host: host,
            'x-amz-date': dtStr,
            'x-api-key': apiKey
          }];
        });
      });
    };
  
    AWSAppSyncRealTimeProvider.prototype._awsRealTimeIAMHeader = function (_a) {
      var payload = _a.payload,
          canonicalUri = _a.canonicalUri,
          appSyncGraphqlEndpoint = _a.appSyncGraphqlEndpoint,
          region = _a.region;
      return __awaiter(this, void 0, void 0, function () {
        var endpointInfo, credentialsOK, creds, request, signed_params;
        return __generator(this, function (_b) {
          switch (_b.label) {
            case 0:
              endpointInfo = {
                region: region,
                service: 'appsync'
              };
              return [4
              /*yield*/
              , this._ensureCredentials()];
  
            case 1:
              credentialsOK = _b.sent();
  
              if (!credentialsOK) {
                throw new Error('No credentials');
              }
  
              return [4
              /*yield*/
              , _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["Credentials"].get().then(function (credentials) {
                return {
                  secret_key: credentials.secretAccessKey,
                  access_key: credentials.accessKeyId,
                  session_token: credentials.sessionToken
                };
              })];
  
            case 2:
              creds = _b.sent();
              request = {
                url: "" + appSyncGraphqlEndpoint + canonicalUri,
                data: payload,
                method: 'POST',
                headers: __assign({}, AWS_APPSYNC_REALTIME_HEADERS)
              };
              signed_params = _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["Signer"].sign(request, creds, endpointInfo);
              return [2
              /*return*/
              , signed_params.headers];
          }
        });
      });
    };
    /**
     * @private
     */
  
  
    AWSAppSyncRealTimeProvider.prototype._ensureCredentials = function () {
      return _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["Credentials"].get().then(function (credentials) {
        if (!credentials) return false;
        var cred = _aws_amplify_core__WEBPACK_IMPORTED_MODULE_5__["Credentials"].shear(credentials);
        logger.debug('set credentials for AWSAppSyncRealTimeProvider', cred);
        return true;
      })["catch"](function (err) {
        logger.warn('ensure credentials error', err);
        return false;
      });
    };
  
    return AWSAppSyncRealTimeProvider;
  }(_PubSubProvider__WEBPACK_IMPORTED_MODULE_8__["AbstractPubSubProvider"]);
  
  
  
  /***/ }),
  
  /***/ "./lib-esm/Providers/AWSIotProvider.js":
  /*!*********************************************!*\
    !*** ./lib-esm/Providers/AWSIotProvider.js ***!
    \*********************************************/
  /*! exports provided: AWSIoTProvider */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AWSIoTProvider", function() { return AWSIoTProvider; });
  /* harmony import */ var _MqttOverWSProvider__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./MqttOverWSProvider */ "./lib-esm/Providers/MqttOverWSProvider.js");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @aws-amplify/core */ "@aws-amplify/core");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__);
  var __extends = undefined && undefined.__extends || function () {
    var _extendStatics = function extendStatics(d, b) {
      _extendStatics = Object.setPrototypeOf || {
        __proto__: []
      } instanceof Array && function (d, b) {
        d.__proto__ = b;
      } || function (d, b) {
        for (var p in b) {
          if (b.hasOwnProperty(p)) d[p] = b[p];
        }
      };
  
      return _extendStatics(d, b);
    };
  
    return function (d, b) {
      _extendStatics(d, b);
  
      function __() {
        this.constructor = d;
      }
  
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
  }();
  
  var __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {
    function adopt(value) {
      return value instanceof P ? value : new P(function (resolve) {
        resolve(value);
      });
    }
  
    return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      }
  
      function rejected(value) {
        try {
          step(generator["throw"](value));
        } catch (e) {
          reject(e);
        }
      }
  
      function step(result) {
        result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
      }
  
      step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
  };
  
  var __generator = undefined && undefined.__generator || function (thisArg, body) {
    var _ = {
      label: 0,
      sent: function sent() {
        if (t[0] & 1) throw t[1];
        return t[1];
      },
      trys: [],
      ops: []
    },
        f,
        y,
        t,
        g;
    return g = {
      next: verb(0),
      "throw": verb(1),
      "return": verb(2)
    }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
      return this;
    }), g;
  
    function verb(n) {
      return function (v) {
        return step([n, v]);
      };
    }
  
    function step(op) {
      if (f) throw new TypeError("Generator is already executing.");
  
      while (_) {
        try {
          if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
          if (y = 0, t) op = [op[0] & 2, t.value];
  
          switch (op[0]) {
            case 0:
            case 1:
              t = op;
              break;
  
            case 4:
              _.label++;
              return {
                value: op[1],
                done: false
              };
  
            case 5:
              _.label++;
              y = op[1];
              op = [0];
              continue;
  
            case 7:
              op = _.ops.pop();
  
              _.trys.pop();
  
              continue;
  
            default:
              if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                _ = 0;
                continue;
              }
  
              if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
                _.label = op[1];
                break;
              }
  
              if (op[0] === 6 && _.label < t[1]) {
                _.label = t[1];
                t = op;
                break;
              }
  
              if (t && _.label < t[2]) {
                _.label = t[2];
  
                _.ops.push(op);
  
                break;
              }
  
              if (t[2]) _.ops.pop();
  
              _.trys.pop();
  
              continue;
          }
  
          op = body.call(thisArg, _);
        } catch (e) {
          op = [6, e];
          y = 0;
        } finally {
          f = t = 0;
        }
      }
  
      if (op[0] & 5) throw op[1];
      return {
        value: op[0] ? op[1] : void 0,
        done: true
      };
    }
  };
  /*
   * Copyright 2017-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
   * the License. A copy of the License is located at
   *
   *     http://aws.amazon.com/apache2.0/
   *
   * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
   * and limitations under the License.
   */
  
  
  
  
  var SERVICE_NAME = 'iotdevicegateway';
  
  var AWSIoTProvider =
  /** @class */
  function (_super) {
    __extends(AWSIoTProvider, _super);
  
    function AWSIoTProvider() {
      return _super !== null && _super.apply(this, arguments) || this;
    }
  
    Object.defineProperty(AWSIoTProvider.prototype, "region", {
      get: function get() {
        return this.options.aws_pubsub_region;
      },
      enumerable: true,
      configurable: true
    });
  
    AWSIoTProvider.prototype.getProviderName = function () {
      return 'AWSIoTProvider';
    };
  
    Object.defineProperty(AWSIoTProvider.prototype, "endpoint", {
      get: function get() {
        var _this = this;
  
        return function () {
          return __awaiter(_this, void 0, void 0, function () {
            var endpoint, serviceInfo, _a, access_key, secret_key, session_token, result;
  
            return __generator(this, function (_b) {
              switch (_b.label) {
                case 0:
                  endpoint = this.options.aws_pubsub_endpoint;
                  serviceInfo = {
                    service: SERVICE_NAME,
                    region: this.region
                  };
                  return [4
                  /*yield*/
                  , _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["Credentials"].get()];
  
                case 1:
                  _a = _b.sent(), access_key = _a.accessKeyId, secret_key = _a.secretAccessKey, session_token = _a.sessionToken;
                  result = _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["Signer"].signUrl(endpoint, {
                    access_key: access_key,
                    secret_key: secret_key,
                    session_token: session_token
                  }, serviceInfo);
                  return [2
                  /*return*/
                  , result];
              }
            });
          });
        }();
      },
      enumerable: true,
      configurable: true
    });
    return AWSIoTProvider;
  }(_MqttOverWSProvider__WEBPACK_IMPORTED_MODULE_0__["MqttOverWSProvider"]);
  
  
  
  /***/ }),
  
  /***/ "./lib-esm/Providers/MqttOverWSProvider.js":
  /*!*************************************************!*\
    !*** ./lib-esm/Providers/MqttOverWSProvider.js ***!
    \*************************************************/
  /*! exports provided: mqttTopicMatch, MqttOverWSProvider */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "mqttTopicMatch", function() { return mqttTopicMatch; });
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MqttOverWSProvider", function() { return MqttOverWSProvider; });
  /* harmony import */ var paho_mqtt__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! paho-mqtt */ "../../node_modules/paho-mqtt/paho-mqtt.js");
  /* harmony import */ var paho_mqtt__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(paho_mqtt__WEBPACK_IMPORTED_MODULE_0__);
  /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! uuid */ "../../node_modules/uuid/index.js");
  /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(uuid__WEBPACK_IMPORTED_MODULE_1__);
  /* harmony import */ var zen_observable_ts__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! zen-observable-ts */ "../../node_modules/zen-observable-ts/lib/bundle.esm.js");
  /* harmony import */ var _PubSubProvider__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./PubSubProvider */ "./lib-esm/Providers/PubSubProvider.js");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @aws-amplify/core */ "@aws-amplify/core");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_4__);
  function _typeof(obj) {
    "@babel/helpers - typeof";
  
    if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
      _typeof = function _typeof(obj) {
        return typeof obj;
      };
    } else {
      _typeof = function _typeof(obj) {
        return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
      };
    }
  
    return _typeof(obj);
  }
  
  var __extends = undefined && undefined.__extends || function () {
    var _extendStatics = function extendStatics(d, b) {
      _extendStatics = Object.setPrototypeOf || {
        __proto__: []
      } instanceof Array && function (d, b) {
        d.__proto__ = b;
      } || function (d, b) {
        for (var p in b) {
          if (b.hasOwnProperty(p)) d[p] = b[p];
        }
      };
  
      return _extendStatics(d, b);
    };
  
    return function (d, b) {
      _extendStatics(d, b);
  
      function __() {
        this.constructor = d;
      }
  
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
  }();
  
  var __assign = undefined && undefined.__assign || function () {
    __assign = Object.assign || function (t) {
      for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
  
        for (var p in s) {
          if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
      }
  
      return t;
    };
  
    return __assign.apply(this, arguments);
  };
  
  var __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {
    function adopt(value) {
      return value instanceof P ? value : new P(function (resolve) {
        resolve(value);
      });
    }
  
    return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      }
  
      function rejected(value) {
        try {
          step(generator["throw"](value));
        } catch (e) {
          reject(e);
        }
      }
  
      function step(result) {
        result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
      }
  
      step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
  };
  
  var __generator = undefined && undefined.__generator || function (thisArg, body) {
    var _ = {
      label: 0,
      sent: function sent() {
        if (t[0] & 1) throw t[1];
        return t[1];
      },
      trys: [],
      ops: []
    },
        f,
        y,
        t,
        g;
    return g = {
      next: verb(0),
      "throw": verb(1),
      "return": verb(2)
    }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
      return this;
    }), g;
  
    function verb(n) {
      return function (v) {
        return step([n, v]);
      };
    }
  
    function step(op) {
      if (f) throw new TypeError("Generator is already executing.");
  
      while (_) {
        try {
          if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
          if (y = 0, t) op = [op[0] & 2, t.value];
  
          switch (op[0]) {
            case 0:
            case 1:
              t = op;
              break;
  
            case 4:
              _.label++;
              return {
                value: op[1],
                done: false
              };
  
            case 5:
              _.label++;
              y = op[1];
              op = [0];
              continue;
  
            case 7:
              op = _.ops.pop();
  
              _.trys.pop();
  
              continue;
  
            default:
              if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                _ = 0;
                continue;
              }
  
              if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
                _.label = op[1];
                break;
              }
  
              if (op[0] === 6 && _.label < t[1]) {
                _.label = t[1];
                t = op;
                break;
              }
  
              if (t && _.label < t[2]) {
                _.label = t[2];
  
                _.ops.push(op);
  
                break;
              }
  
              if (t[2]) _.ops.pop();
  
              _.trys.pop();
  
              continue;
          }
  
          op = body.call(thisArg, _);
        } catch (e) {
          op = [6, e];
          y = 0;
        } finally {
          f = t = 0;
        }
      }
  
      if (op[0] & 5) throw op[1];
      return {
        value: op[0] ? op[1] : void 0,
        done: true
      };
    }
  };
  
  var __rest = undefined && undefined.__rest || function (s, e) {
    var t = {};
  
    for (var p in s) {
      if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
    }
  
    if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
      if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
    }
    return t;
  };
  /*
   * Copyright 2017-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
   * the License. A copy of the License is located at
   *
   *     http://aws.amazon.com/apache2.0/
   *
   * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
   * and limitations under the License.
   */
  
  
  
  
  
  
  
  var logger = new _aws_amplify_core__WEBPACK_IMPORTED_MODULE_4__["ConsoleLogger"]('MqttOverWSProvider');
  function mqttTopicMatch(filter, topic) {
    var filterArray = filter.split('/');
    var length = filterArray.length;
    var topicArray = topic.split('/');
  
    for (var i = 0; i < length; ++i) {
      var left = filterArray[i];
      var right = topicArray[i];
      if (left === '#') return topicArray.length >= length;
      if (left !== '+' && left !== right) return false;
    }
  
    return length === topicArray.length;
  }
  
  var ClientsQueue =
  /** @class */
  function () {
    function ClientsQueue() {
      this.promises = new Map();
    }
  
    ClientsQueue.prototype.get = function (clientId, clientFactory) {
      return __awaiter(this, void 0, void 0, function () {
        var promise;
        return __generator(this, function (_a) {
          promise = this.promises.get(clientId);
  
          if (promise) {
            return [2
            /*return*/
            , promise];
          }
  
          promise = clientFactory(clientId);
          this.promises.set(clientId, promise);
          return [2
          /*return*/
          , promise];
        });
      });
    };
  
    Object.defineProperty(ClientsQueue.prototype, "allClients", {
      get: function get() {
        return Array.from(this.promises.keys());
      },
      enumerable: true,
      configurable: true
    });
  
    ClientsQueue.prototype.remove = function (clientId) {
      this.promises["delete"](clientId);
    };
  
    return ClientsQueue;
  }();
  
  var topicSymbol = typeof Symbol !== 'undefined' ? Symbol('topic') : '@@topic';
  
  var MqttOverWSProvider =
  /** @class */
  function (_super) {
    __extends(MqttOverWSProvider, _super);
  
    function MqttOverWSProvider(options) {
      if (options === void 0) {
        options = {};
      }
  
      var _this = _super.call(this, __assign(__assign({}, options), {
        clientId: options.clientId || Object(uuid__WEBPACK_IMPORTED_MODULE_1__["v4"])()
      })) || this;
  
      _this._clientsQueue = new ClientsQueue();
      _this._topicObservers = new Map();
      _this._clientIdObservers = new Map();
      return _this;
    }
  
    Object.defineProperty(MqttOverWSProvider.prototype, "clientId", {
      get: function get() {
        return this.options.clientId;
      },
      enumerable: true,
      configurable: true
    });
    Object.defineProperty(MqttOverWSProvider.prototype, "endpoint", {
      get: function get() {
        return this.options.aws_pubsub_endpoint;
      },
      enumerable: true,
      configurable: true
    });
    Object.defineProperty(MqttOverWSProvider.prototype, "clientsQueue", {
      get: function get() {
        return this._clientsQueue;
      },
      enumerable: true,
      configurable: true
    });
    Object.defineProperty(MqttOverWSProvider.prototype, "isSSLEnabled", {
      get: function get() {
        return !this.options.aws_appsync_dangerously_connect_to_http_endpoint_for_testing;
      },
      enumerable: true,
      configurable: true
    });
  
    MqttOverWSProvider.prototype.getTopicForValue = function (value) {
      return _typeof(value) === 'object' && value[topicSymbol];
    };
  
    MqttOverWSProvider.prototype.getProviderName = function () {
      return 'MqttOverWSProvider';
    };
  
    MqttOverWSProvider.prototype.onDisconnect = function (_a) {
      var _this = this;
  
      var clientId = _a.clientId,
          errorCode = _a.errorCode,
          args = __rest(_a, ["clientId", "errorCode"]);
  
      if (errorCode !== 0) {
        logger.warn(clientId, JSON.stringify(__assign({
          errorCode: errorCode
        }, args), null, 2));
        var topicsToDelete_1 = [];
  
        var clientIdObservers = this._clientIdObservers.get(clientId);
  
        if (!clientIdObservers) {
          return;
        }
  
        clientIdObservers.forEach(function (observer) {
          observer.error('Disconnected, error code: ' + errorCode); // removing observers for disconnected clientId
  
          _this._topicObservers.forEach(function (observerForTopic, observerTopic) {
            observerForTopic["delete"](observer);
  
            if (observerForTopic.size === 0) {
              topicsToDelete_1.push(observerTopic);
            }
          });
        }); // forgiving any trace of clientId
  
        this._clientIdObservers["delete"](clientId); // Removing topics that are not listen by an observer
  
  
        topicsToDelete_1.forEach(function (topic) {
          _this._topicObservers["delete"](topic);
        });
      }
    };
  
    MqttOverWSProvider.prototype.newClient = function (_a) {
      var url = _a.url,
          clientId = _a.clientId;
      return __awaiter(this, void 0, void 0, function () {
        var client;
  
        var _this = this;
  
        return __generator(this, function (_b) {
          switch (_b.label) {
            case 0:
              logger.debug('Creating new MQTT client', clientId);
              client = new paho_mqtt__WEBPACK_IMPORTED_MODULE_0__["Client"](url, clientId); // client.trace = (args) => logger.debug(clientId, JSON.stringify(args, null, 2));
  
              client.onMessageArrived = function (_a) {
                var topic = _a.destinationName,
                    msg = _a.payloadString;
  
                _this._onMessage(topic, msg);
              };
  
              client.onConnectionLost = function (_a) {
                var errorCode = _a.errorCode,
                    args = __rest(_a, ["errorCode"]);
  
                _this.onDisconnect(__assign({
                  clientId: clientId,
                  errorCode: errorCode
                }, args));
              };
  
              return [4
              /*yield*/
              , new Promise(function (resolve, reject) {
                client.connect({
                  useSSL: _this.isSSLEnabled,
                  mqttVersion: 3,
                  onSuccess: function onSuccess() {
                    return resolve(client);
                  },
                  onFailure: reject
                });
              })];
  
            case 1:
              _b.sent();
  
              return [2
              /*return*/
              , client];
          }
        });
      });
    };
  
    MqttOverWSProvider.prototype.connect = function (clientId, options) {
      if (options === void 0) {
        options = {};
      }
  
      return __awaiter(this, void 0, void 0, function () {
        var _this = this;
  
        return __generator(this, function (_a) {
          switch (_a.label) {
            case 0:
              return [4
              /*yield*/
              , this.clientsQueue.get(clientId, function (clientId) {
                return _this.newClient(__assign(__assign({}, options), {
                  clientId: clientId
                }));
              })];
  
            case 1:
              return [2
              /*return*/
              , _a.sent()];
          }
        });
      });
    };
  
    MqttOverWSProvider.prototype.disconnect = function (clientId) {
      return __awaiter(this, void 0, void 0, function () {
        var client;
        return __generator(this, function (_a) {
          switch (_a.label) {
            case 0:
              return [4
              /*yield*/
              , this.clientsQueue.get(clientId, function () {
                return null;
              })];
  
            case 1:
              client = _a.sent();
  
              if (client && client.isConnected()) {
                client.disconnect();
              }
  
              this.clientsQueue.remove(clientId);
              return [2
              /*return*/
              ];
          }
        });
      });
    };
  
    MqttOverWSProvider.prototype.publish = function (topics, msg) {
      return __awaiter(this, void 0, void 0, function () {
        var targetTopics, message, url, client;
        return __generator(this, function (_a) {
          switch (_a.label) {
            case 0:
              targetTopics = [].concat(topics);
              message = JSON.stringify(msg);
              return [4
              /*yield*/
              , this.endpoint];
  
            case 1:
              url = _a.sent();
              return [4
              /*yield*/
              , this.connect(this.clientId, {
                url: url
              })];
  
            case 2:
              client = _a.sent();
              logger.debug('Publishing to topic(s)', targetTopics.join(','), message);
              targetTopics.forEach(function (topic) {
                return client.send(topic, message);
              });
              return [2
              /*return*/
              ];
          }
        });
      });
    };
  
    MqttOverWSProvider.prototype._onMessage = function (topic, msg) {
      try {
        var matchedTopicObservers_1 = [];
  
        this._topicObservers.forEach(function (observerForTopic, observerTopic) {
          if (mqttTopicMatch(observerTopic, topic)) {
            matchedTopicObservers_1.push(observerForTopic);
          }
        });
  
        var parsedMessage_1 = JSON.parse(msg);
  
        if (_typeof(parsedMessage_1) === 'object') {
          parsedMessage_1[topicSymbol] = topic;
        }
  
        matchedTopicObservers_1.forEach(function (observersForTopic) {
          observersForTopic.forEach(function (observer) {
            return observer.next(parsedMessage_1);
          });
        });
      } catch (error) {
        logger.warn('Error handling message', error, msg);
      }
    };
  
    MqttOverWSProvider.prototype.subscribe = function (topics, options) {
      var _this = this;
  
      if (options === void 0) {
        options = {};
      }
  
      var targetTopics = [].concat(topics);
      logger.debug('Subscribing to topic(s)', targetTopics.join(','));
      return new zen_observable_ts__WEBPACK_IMPORTED_MODULE_2__["default"](function (observer) {
        targetTopics.forEach(function (topic) {
          // this._topicObservers is used to notify the observers according to the topic received on the message
          var observersForTopic = _this._topicObservers.get(topic);
  
          if (!observersForTopic) {
            observersForTopic = new Set();
  
            _this._topicObservers.set(topic, observersForTopic);
          }
  
          observersForTopic.add(observer);
        }); // @ts-ignore
  
        var client;
        var _a = options.clientId,
            clientId = _a === void 0 ? _this.clientId : _a; // this._clientIdObservers is used to close observers when client gets disconnected
  
        var observersForClientId = _this._clientIdObservers.get(clientId);
  
        if (!observersForClientId) {
          observersForClientId = new Set();
        }
  
        observersForClientId.add(observer);
  
        _this._clientIdObservers.set(clientId, observersForClientId);
  
        (function () {
          return __awaiter(_this, void 0, void 0, function () {
            var _a, url, _b, e_1;
  
            return __generator(this, function (_c) {
              switch (_c.label) {
                case 0:
                  _a = options.url;
                  if (!(_a === void 0)) return [3
                  /*break*/
                  , 2];
                  return [4
                  /*yield*/
                  , this.endpoint];
  
                case 1:
                  _b = _c.sent();
                  return [3
                  /*break*/
                  , 3];
  
                case 2:
                  _b = _a;
                  _c.label = 3;
  
                case 3:
                  url = _b;
                  _c.label = 4;
  
                case 4:
                  _c.trys.push([4, 6,, 7]);
  
                  return [4
                  /*yield*/
                  , this.connect(clientId, {
                    url: url
                  })];
  
                case 5:
                  client = _c.sent();
                  targetTopics.forEach(function (topic) {
                    client.subscribe(topic);
                  });
                  return [3
                  /*break*/
                  , 7];
  
                case 6:
                  e_1 = _c.sent();
                  observer.error(e_1);
                  return [3
                  /*break*/
                  , 7];
  
                case 7:
                  return [2
                  /*return*/
                  ];
              }
            });
          });
        })();
  
        return function () {
          logger.debug('Unsubscribing from topic(s)', targetTopics.join(','));
  
          if (client) {
            _this._clientIdObservers.get(clientId)["delete"](observer); // No more observers per client => client not needed anymore
  
  
            if (_this._clientIdObservers.get(clientId).size === 0) {
              _this.disconnect(clientId);
  
              _this._clientIdObservers["delete"](clientId);
            }
  
            targetTopics.forEach(function (topic) {
              var observersForTopic = _this._topicObservers.get(topic) || new Set();
              observersForTopic["delete"](observer); // if no observers exists for the topic, topic should be removed
  
              if (observersForTopic.size === 0) {
                _this._topicObservers["delete"](topic);
  
                if (client.isConnected()) {
                  client.unsubscribe(topic);
                }
              }
            });
          }
  
          return null;
        };
      });
    };
  
    return MqttOverWSProvider;
  }(_PubSubProvider__WEBPACK_IMPORTED_MODULE_3__["AbstractPubSubProvider"]);
  
  
  
  /***/ }),
  
  /***/ "./lib-esm/Providers/PubSubProvider.js":
  /*!*********************************************!*\
    !*** ./lib-esm/Providers/PubSubProvider.js ***!
    \*********************************************/
  /*! exports provided: AbstractPubSubProvider */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "AbstractPubSubProvider", function() { return AbstractPubSubProvider; });
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @aws-amplify/core */ "@aws-amplify/core");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_0__);
  var __assign = undefined && undefined.__assign || function () {
    __assign = Object.assign || function (t) {
      for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
  
        for (var p in s) {
          if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
        }
      }
  
      return t;
    };
  
    return __assign.apply(this, arguments);
  };
  
  
  var logger = new _aws_amplify_core__WEBPACK_IMPORTED_MODULE_0__["ConsoleLogger"]('AbstractPubSubProvider');
  
  var AbstractPubSubProvider =
  /** @class */
  function () {
    function AbstractPubSubProvider(options) {
      if (options === void 0) {
        options = {};
      }
  
      this._config = options;
    }
  
    AbstractPubSubProvider.prototype.configure = function (config) {
      if (config === void 0) {
        config = {};
      }
  
      this._config = __assign(__assign({}, config), this._config);
      logger.debug("configure " + this.getProviderName(), this._config);
      return this.options;
    };
  
    AbstractPubSubProvider.prototype.getCategory = function () {
      return 'PubSub';
    };
  
    Object.defineProperty(AbstractPubSubProvider.prototype, "options", {
      get: function get() {
        return __assign({}, this._config);
      },
      enumerable: true,
      configurable: true
    });
    return AbstractPubSubProvider;
  }();
  
  
  
  /***/ }),
  
  /***/ "./lib-esm/Providers/index.js":
  /*!************************************!*\
    !*** ./lib-esm/Providers/index.js ***!
    \************************************/
  /*! exports provided: AbstractPubSubProvider, AWSAppSyncProvider, AWSAppSyncRealTimeProvider, AWSIoTProvider, mqttTopicMatch, MqttOverWSProvider */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony import */ var _PubSubProvider__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PubSubProvider */ "./lib-esm/Providers/PubSubProvider.js");
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AbstractPubSubProvider", function() { return _PubSubProvider__WEBPACK_IMPORTED_MODULE_0__["AbstractPubSubProvider"]; });
  
  /* harmony import */ var _AWSAppSyncProvider__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./AWSAppSyncProvider */ "./lib-esm/Providers/AWSAppSyncProvider.js");
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AWSAppSyncProvider", function() { return _AWSAppSyncProvider__WEBPACK_IMPORTED_MODULE_1__["AWSAppSyncProvider"]; });
  
  /* harmony import */ var _AWSAppSyncRealTimeProvider__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./AWSAppSyncRealTimeProvider */ "./lib-esm/Providers/AWSAppSyncRealTimeProvider.js");
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AWSAppSyncRealTimeProvider", function() { return _AWSAppSyncRealTimeProvider__WEBPACK_IMPORTED_MODULE_2__["AWSAppSyncRealTimeProvider"]; });
  
  /* harmony import */ var _AWSIotProvider__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AWSIotProvider */ "./lib-esm/Providers/AWSIotProvider.js");
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AWSIoTProvider", function() { return _AWSIotProvider__WEBPACK_IMPORTED_MODULE_3__["AWSIoTProvider"]; });
  
  /* harmony import */ var _MqttOverWSProvider__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./MqttOverWSProvider */ "./lib-esm/Providers/MqttOverWSProvider.js");
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mqttTopicMatch", function() { return _MqttOverWSProvider__WEBPACK_IMPORTED_MODULE_4__["mqttTopicMatch"]; });
  
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "MqttOverWSProvider", function() { return _MqttOverWSProvider__WEBPACK_IMPORTED_MODULE_4__["MqttOverWSProvider"]; });
  
  /*
   * Copyright 2017-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
   * the License. A copy of the License is located at
   *
   *     http://aws.amazon.com/apache2.0/
   *
   * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
   * and limitations under the License.
   */
  
  
  
  
  
  
  /***/ }),
  
  /***/ "./lib-esm/PubSub.js":
  /*!***************************!*\
    !*** ./lib-esm/PubSub.js ***!
    \***************************/
  /*! exports provided: PubSubClass, PubSub */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PubSubClass", function() { return PubSubClass; });
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "PubSub", function() { return PubSub; });
  /* harmony import */ var zen_observable_ts__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! zen-observable-ts */ "../../node_modules/zen-observable-ts/lib/bundle.esm.js");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @aws-amplify/core */ "@aws-amplify/core");
  /* harmony import */ var _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__);
  /* harmony import */ var _Providers__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Providers */ "./lib-esm/Providers/index.js");
  var __awaiter = undefined && undefined.__awaiter || function (thisArg, _arguments, P, generator) {
    function adopt(value) {
      return value instanceof P ? value : new P(function (resolve) {
        resolve(value);
      });
    }
  
    return new (P || (P = Promise))(function (resolve, reject) {
      function fulfilled(value) {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      }
  
      function rejected(value) {
        try {
          step(generator["throw"](value));
        } catch (e) {
          reject(e);
        }
      }
  
      function step(result) {
        result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
      }
  
      step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
  };
  
  var __generator = undefined && undefined.__generator || function (thisArg, body) {
    var _ = {
      label: 0,
      sent: function sent() {
        if (t[0] & 1) throw t[1];
        return t[1];
      },
      trys: [],
      ops: []
    },
        f,
        y,
        t,
        g;
    return g = {
      next: verb(0),
      "throw": verb(1),
      "return": verb(2)
    }, typeof Symbol === "function" && (g[Symbol.iterator] = function () {
      return this;
    }), g;
  
    function verb(n) {
      return function (v) {
        return step([n, v]);
      };
    }
  
    function step(op) {
      if (f) throw new TypeError("Generator is already executing.");
  
      while (_) {
        try {
          if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
          if (y = 0, t) op = [op[0] & 2, t.value];
  
          switch (op[0]) {
            case 0:
            case 1:
              t = op;
              break;
  
            case 4:
              _.label++;
              return {
                value: op[1],
                done: false
              };
  
            case 5:
              _.label++;
              y = op[1];
              op = [0];
              continue;
  
            case 7:
              op = _.ops.pop();
  
              _.trys.pop();
  
              continue;
  
            default:
              if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
                _ = 0;
                continue;
              }
  
              if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
                _.label = op[1];
                break;
              }
  
              if (op[0] === 6 && _.label < t[1]) {
                _.label = t[1];
                t = op;
                break;
              }
  
              if (t && _.label < t[2]) {
                _.label = t[2];
  
                _.ops.push(op);
  
                break;
              }
  
              if (t[2]) _.ops.pop();
  
              _.trys.pop();
  
              continue;
          }
  
          op = body.call(thisArg, _);
        } catch (e) {
          op = [6, e];
          y = 0;
        } finally {
          f = t = 0;
        }
      }
  
      if (op[0] & 5) throw op[1];
      return {
        value: op[0] ? op[1] : void 0,
        done: true
      };
    }
  };
  /*
   * Copyright 2017-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
   * the License. A copy of the License is located at
   *
   *     http://aws.amazon.com/apache2.0/
   *
   * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
   * and limitations under the License.
   */
  // import '../Common/Polyfills';
  
  
  
  
  
  var isNode = Object(_aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["browserOrNode"])().isNode;
  var logger = new _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["ConsoleLogger"]('PubSub');
  
  var PubSubClass =
  /** @class */
  function () {
    /**
     * Initialize PubSub with AWS configurations
     *
     * @param {PubSubOptions} options - Configuration object for PubSub
     */
    function PubSubClass(options) {
      this._options = options;
      logger.debug('PubSub Options', this._options);
      this._pluggables = [];
      this.subscribe = this.subscribe.bind(this);
    }
  
    Object.defineProperty(PubSubClass.prototype, "awsAppSyncProvider", {
      /**
       * Lazy instantiate AWSAppSyncProvider when it is required by the API category
       */
      get: function get() {
        if (!this._awsAppSyncProvider) {
          this._awsAppSyncProvider = new _Providers__WEBPACK_IMPORTED_MODULE_2__["AWSAppSyncProvider"](this._options);
        }
  
        return this._awsAppSyncProvider;
      },
      enumerable: true,
      configurable: true
    });
    Object.defineProperty(PubSubClass.prototype, "awsAppSyncRealTimeProvider", {
      /**
       * Lazy instantiate AWSAppSyncRealTimeProvider when it is required by the API category
       */
      get: function get() {
        if (!this._awsAppSyncRealTimeProvider) {
          this._awsAppSyncRealTimeProvider = new _Providers__WEBPACK_IMPORTED_MODULE_2__["AWSAppSyncRealTimeProvider"](this._options);
        }
  
        return this._awsAppSyncRealTimeProvider;
      },
      enumerable: true,
      configurable: true
    });
  
    PubSubClass.prototype.getModuleName = function () {
      return 'PubSub';
    };
    /**
     * Configure PubSub part with configurations
     *
     * @param {PubSubOptions} config - Configuration for PubSub
     * @return {Object} - The current configuration
     */
  
  
    PubSubClass.prototype.configure = function (options) {
      var _this = this;
  
      var opt = options ? options.PubSub || options : {};
      logger.debug('configure PubSub', {
        opt: opt
      });
      this._options = Object.assign({}, this._options, opt);
  
      this._pluggables.map(function (pluggable) {
        return pluggable.configure(_this._options);
      });
  
      return this._options;
    };
    /**
     * add plugin into Analytics category
     * @param {Object} pluggable - an instance of the plugin
     */
  
  
    PubSubClass.prototype.addPluggable = function (pluggable) {
      return __awaiter(this, void 0, void 0, function () {
        var config;
        return __generator(this, function (_a) {
          if (pluggable && pluggable.getCategory() === 'PubSub') {
            this._pluggables.push(pluggable);
  
            config = pluggable.configure(this._options);
            return [2
            /*return*/
            , config];
          }
  
          return [2
          /*return*/
          ];
        });
      });
    };
  
    PubSubClass.prototype.getProviderByName = function (providerName) {
      if (providerName === _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["INTERNAL_AWS_APPSYNC_PUBSUB_PROVIDER"]) {
        return this.awsAppSyncProvider;
      }
  
      if (providerName === _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["INTERNAL_AWS_APPSYNC_REALTIME_PUBSUB_PROVIDER"]) {
        return this.awsAppSyncRealTimeProvider;
      }
  
      return this._pluggables.find(function (pluggable) {
        return pluggable.getProviderName() === providerName;
      });
    };
  
    PubSubClass.prototype.getProviders = function (options) {
      if (options === void 0) {
        options = {};
      }
  
      var providerName = options.provider;
  
      if (!providerName) {
        return this._pluggables;
      }
  
      var provider = this.getProviderByName(providerName);
  
      if (!provider) {
        throw new Error("Could not find provider named " + providerName);
      }
  
      return [provider];
    };
  
    PubSubClass.prototype.publish = function (topics, msg, options) {
      return __awaiter(this, void 0, void 0, function () {
        return __generator(this, function (_a) {
          return [2
          /*return*/
          , Promise.all(this.getProviders(options).map(function (provider) {
            return provider.publish(topics, msg, options);
          }))];
        });
      });
    };
  
    PubSubClass.prototype.subscribe = function (topics, options) {
      if (isNode && this._options && this._options.ssr) {
        throw new Error('Subscriptions are not supported for Server-Side Rendering (SSR)');
      }
  
      logger.debug('subscribe options', options);
      var providers = this.getProviders(options);
      return new zen_observable_ts__WEBPACK_IMPORTED_MODULE_0__["default"](function (observer) {
        var observables = providers.map(function (provider) {
          return {
            provider: provider,
            observable: provider.subscribe(topics, options)
          };
        });
        var subscriptions = observables.map(function (_a) {
          var provider = _a.provider,
              observable = _a.observable;
          return observable.subscribe({
            start: console.error,
            next: function next(value) {
              return observer.next({
                provider: provider,
                value: value
              });
            },
            error: function error(_error) {
              return observer.error({
                provider: provider,
                error: _error
              });
            }
          });
        });
        return function () {
          return subscriptions.forEach(function (subscription) {
            return subscription.unsubscribe();
          });
        };
      });
    };
  
    return PubSubClass;
  }();
  
  
  var PubSub = new PubSubClass(null);
  _aws_amplify_core__WEBPACK_IMPORTED_MODULE_1__["Amplify"].register(PubSub);
  
  /***/ }),
  
  /***/ "./lib-esm/index.js":
  /*!**************************!*\
    !*** ./lib-esm/index.js ***!
    \**************************/
  /*! exports provided: AbstractPubSubProvider, AWSAppSyncProvider, AWSAppSyncRealTimeProvider, AWSIoTProvider, mqttTopicMatch, MqttOverWSProvider, PubSub, CONTROL_MSG, default */
  /***/ (function(module, __webpack_exports__, __webpack_require__) {
  
  "use strict";
  __webpack_require__.r(__webpack_exports__);
  /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CONTROL_MSG", function() { return CONTROL_MSG; });
  /* harmony import */ var _PubSub__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./PubSub */ "./lib-esm/PubSub.js");
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "PubSub", function() { return _PubSub__WEBPACK_IMPORTED_MODULE_0__["PubSub"]; });
  
  /* harmony import */ var _Providers__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Providers */ "./lib-esm/Providers/index.js");
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AbstractPubSubProvider", function() { return _Providers__WEBPACK_IMPORTED_MODULE_1__["AbstractPubSubProvider"]; });
  
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AWSAppSyncProvider", function() { return _Providers__WEBPACK_IMPORTED_MODULE_1__["AWSAppSyncProvider"]; });
  
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AWSAppSyncRealTimeProvider", function() { return _Providers__WEBPACK_IMPORTED_MODULE_1__["AWSAppSyncRealTimeProvider"]; });
  
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "AWSIoTProvider", function() { return _Providers__WEBPACK_IMPORTED_MODULE_1__["AWSIoTProvider"]; });
  
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "mqttTopicMatch", function() { return _Providers__WEBPACK_IMPORTED_MODULE_1__["mqttTopicMatch"]; });
  
  /* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "MqttOverWSProvider", function() { return _Providers__WEBPACK_IMPORTED_MODULE_1__["MqttOverWSProvider"]; });
  
  /*
   * Copyright 2017-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   *
   * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
   * the License. A copy of the License is located at
   *
   *     http://aws.amazon.com/apache2.0/
   *
   * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
   * and limitations under the License.
   */
  
  
  var CONTROL_MSG;
  
  (function (CONTROL_MSG) {
    CONTROL_MSG["CONNECTION_CLOSED"] = "Connection closed";
    CONTROL_MSG["CONNECTION_FAILED"] = "Connection failed";
    CONTROL_MSG["REALTIME_SUBSCRIPTION_INIT_ERROR"] = "AppSync Realtime subscription init error";
    CONTROL_MSG["SUBSCRIPTION_ACK"] = "Subscription ack";
    CONTROL_MSG["TIMEOUT_DISCONNECT"] = "Timeout disconnect";
  })(CONTROL_MSG || (CONTROL_MSG = {}));
  
  
  /**
   * @deprecated use named import
   */
  
  /* harmony default export */ __webpack_exports__["default"] = (_PubSub__WEBPACK_IMPORTED_MODULE_0__["PubSub"]);
  
  /***/ }),
  
  /***/ "@aws-amplify/auth":
  /*!************************************!*\
    !*** external "@aws-amplify/auth" ***!
    \************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  module.exports = __WEBPACK_EXTERNAL_MODULE__aws_amplify_auth__;
  
  /***/ }),
  
  /***/ "@aws-amplify/cache":
  /*!*************************************!*\
    !*** external "@aws-amplify/cache" ***!
    \*************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  module.exports = __WEBPACK_EXTERNAL_MODULE__aws_amplify_cache__;
  
  /***/ }),
  
  /***/ "@aws-amplify/core":
  /*!************************************!*\
    !*** external "@aws-amplify/core" ***!
    \************************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  module.exports = __WEBPACK_EXTERNAL_MODULE__aws_amplify_core__;
  
  /***/ }),
  
  /***/ "graphql":
  /*!**************************!*\
    !*** external "graphql" ***!
    \**************************/
  /*! no static exports found */
  /***/ (function(module, exports) {
  
  module.exports = __WEBPACK_EXTERNAL_MODULE_graphql__;
  
  /***/ })
  
  /******/ });
  });
  //# sourceMappingURL=aws-amplify-pubsub.js.map