UNPKG

happn-3

Version:

pub/sub api as a service using primus and mongo & redis or nedb, can work as cluster, single process or embedded using nedb

1,898 lines (1,626 loc) 103 kB
(function UMDish(name, context, definition, plugins) { context[name] = definition.call(context); for (var i = 0; i < plugins.length; i++) { plugins[i](context[name]) } if (typeof module !== "undefined" && module.exports) { module.exports = context[name]; } else if (typeof define === "function" && define.amd) { define(function reference() { return context[name]; }); } })("Primus", this || {}, function wrapper() { var define, module, exports , Primus = (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){ 'use strict'; /** * Create a function that will cleanup the instance. * * @param {Array|String} keys Properties on the instance that needs to be cleared. * @param {Object} options Additional configuration. * @returns {Function} Destroy function * @api public */ module.exports = function demolish(keys, options) { var split = /[, ]+/; options = options || {}; keys = keys || []; if ('string' === typeof keys) keys = keys.split(split); /** * Run addition cleanup hooks. * * @param {String} key Name of the clean up hook to run. * @param {Mixed} selfie Reference to the instance we're cleaning up. * @api private */ function run(key, selfie) { if (!options[key]) return; if ('string' === typeof options[key]) options[key] = options[key].split(split); if ('function' === typeof options[key]) return options[key].call(selfie); for (var i = 0, type, what; i < options[key].length; i++) { what = options[key][i]; type = typeof what; if ('function' === type) { what.call(selfie); } else if ('string' === type && 'function' === typeof selfie[what]) { selfie[what](); } } } /** * Destroy the instance completely and clean up all the existing references. * * @returns {Boolean} * @api public */ return function destroy() { var selfie = this , i = 0 , prop; if (selfie[keys[0]] === null) return false; run('before', selfie); for (; i < keys.length; i++) { prop = keys[i]; if (selfie[prop]) { if ('function' === typeof selfie[prop].destroy) selfie[prop].destroy(); selfie[prop] = null; } } if (selfie.emit) selfie.emit('destroy'); run('after', selfie); return true; }; }; },{}],2:[function(_dereq_,module,exports){ 'use strict'; /** * Returns a function that when invoked executes all the listeners of the * given event with the given arguments. * * @returns {Function} The function that emits all the things. * @api public */ module.exports = function emits() { var self = this , parser; for (var i = 0, l = arguments.length, args = new Array(l); i < l; i++) { args[i] = arguments[i]; } // // If the last argument is a function, assume that it's a parser. // if ('function' !== typeof args[args.length - 1]) return function emitter() { for (var i = 0, l = arguments.length, arg = new Array(l); i < l; i++) { arg[i] = arguments[i]; } return self.emit.apply(self, args.concat(arg)); }; parser = args.pop(); /** * The actual function that emits the given event. It returns a boolean * indicating if the event was emitted. * * @returns {Boolean} * @api public */ return function emitter() { for (var i = 0, l = arguments.length, arg = new Array(l + 1); i < l; i++) { arg[i + 1] = arguments[i]; } /** * Async completion method for the parser. * * @param {Error} err Optional error when parsing failed. * @param {Mixed} returned Emit instructions. * @api private */ arg[0] = function next(err, returned) { if (err) return self.emit('error', err); arg = returned === undefined ? arg.slice(1) : returned === null ? [] : returned; self.emit.apply(self, args.concat(arg)); }; parser.apply(self, arg); return true; }; }; },{}],3:[function(_dereq_,module,exports){ 'use strict'; var has = Object.prototype.hasOwnProperty , prefix = '~'; /** * Constructor to create a storage for our `EE` objects. * An `Events` instance is a plain object whose properties are event names. * * @constructor * @private */ function Events() {} // // We try to not inherit from `Object.prototype`. In some engines creating an // instance in this way is faster than calling `Object.create(null)` directly. // If `Object.create(null)` is not supported we prefix the event names with a // character to make sure that the built-in object properties are not // overridden or used as an attack vector. // if (Object.create) { Events.prototype = Object.create(null); // // This hack is needed because the `__proto__` property is still inherited in // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. // if (!new Events().__proto__) prefix = false; } /** * Representation of a single event listener. * * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} [once=false] Specify if the listener is a one-time listener. * @constructor * @private */ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Add a listener for a given event. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} once Specify if the listener is a one-time listener. * @returns {EventEmitter} * @private */ function addListener(emitter, event, fn, context, once) { if (typeof fn !== 'function') { throw new TypeError('The listener must be a function'); } var listener = new EE(fn, context || emitter, once) , evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } /** * Clear event by name. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} evt The Event name. * @private */ function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. * * @constructor * @public */ function EventEmitter() { this._events = new Events(); this._eventsCount = 0; } /** * Return an array listing the events for which the emitter has registered * listeners. * * @returns {Array} * @public */ EventEmitter.prototype.eventNames = function eventNames() { var names = [] , events , name; if (this._eventsCount === 0) return names; for (name in (events = this._events)) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; /** * Return the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Array} The registered listeners. * @public */ EventEmitter.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event , handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { ee[i] = handlers[i].fn; } return ee; }; /** * Return the number of listeners listening to a given event. * * @param {(String|Symbol)} event The event name. * @returns {Number} The number of listeners. * @public */ EventEmitter.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event , listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; /** * Calls each of the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Boolean} `true` if the event had listeners, else `false`. * @public */ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt] , len = arguments.length , args , i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len -1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length , j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Add a listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; /** * Add a one-time listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; /** * Remove the listeners of a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn Only remove the listeners that match this function. * @param {*} context Only remove the listeners that have this context. * @param {Boolean} once Only remove one-time listeners. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if ( listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context) ) { clearEvent(this, evt); } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { if ( listeners[i].fn !== fn || (once && !listeners[i].once) || (context && listeners[i].context !== context) ) { events.push(listeners[i]); } } // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; /** * Remove all listeners, or those of the specified event. * * @param {(String|Symbol)} [event] The event name. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; // // Alias methods names because people roll like that. // EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.addListener = EventEmitter.prototype.on; // // Expose the prefix. // EventEmitter.prefixed = prefix; // // Allow `EventEmitter` to be imported as module namespace. // EventEmitter.EventEmitter = EventEmitter; // // Expose the module. // if ('undefined' !== typeof module) { module.exports = EventEmitter; } },{}],4:[function(_dereq_,module,exports){ if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { if (superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }) } }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { if (superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } } },{}],5:[function(_dereq_,module,exports){ 'use strict'; var regex = new RegExp('^((?:\\d+)?\\.?\\d+) *('+ [ 'milliseconds?', 'msecs?', 'ms', 'seconds?', 'secs?', 's', 'minutes?', 'mins?', 'm', 'hours?', 'hrs?', 'h', 'days?', 'd', 'weeks?', 'wks?', 'w', 'years?', 'yrs?', 'y' ].join('|') +')?$', 'i'); var second = 1000 , minute = second * 60 , hour = minute * 60 , day = hour * 24 , week = day * 7 , year = day * 365; /** * Parse a time string and return the number value of it. * * @param {String} ms Time string. * @returns {Number} * @api private */ module.exports = function millisecond(ms) { var type = typeof ms , amount , match; if ('number' === type) return ms; else if ('string' !== type || '0' === ms || !ms) return 0; else if (+ms) return +ms; // // We are vulnerable to the regular expression denial of service (ReDoS). // In order to mitigate this we don't parse the input string if it is too long. // See https://nodesecurity.io/advisories/46. // if (ms.length > 10000 || !(match = regex.exec(ms))) return 0; amount = parseFloat(match[1]); switch (match[2].toLowerCase()) { case 'years': case 'year': case 'yrs': case 'yr': case 'y': return amount * year; case 'weeks': case 'week': case 'wks': case 'wk': case 'w': return amount * week; case 'days': case 'day': case 'd': return amount * day; case 'hours': case 'hour': case 'hrs': case 'hr': case 'h': return amount * hour; case 'minutes': case 'minute': case 'mins': case 'min': case 'm': return amount * minute; case 'seconds': case 'second': case 'secs': case 'sec': case 's': return amount * second; default: return amount; } }; },{}],6:[function(_dereq_,module,exports){ 'use strict'; /** * Wrap callbacks to prevent double execution. * * @param {Function} fn Function that should only be called once. * @returns {Function} A wrapped callback which prevents execution. * @api public */ module.exports = function one(fn) { var called = 0 , value; /** * The function that prevents double execution. * * @api private */ function onetime() { if (called) return value; called = 1; value = fn.apply(this, arguments); fn = null; return value; } // // To make debugging more easy we want to use the name of the supplied // function. So when you look at the functions that are assigned to event // listeners you don't see a load of `onetime` functions but actually the // names of the functions that this module will call. // onetime.displayName = fn.displayName || fn.name || onetime.displayName || onetime.name; return onetime; }; },{}],7:[function(_dereq_,module,exports){ // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it // don't break things. But we need to wrap it in a try catch in case it is // wrapped in strict mode code which doesn't define any globals. It's inside a // function because try/catches deoptimize in certain engines. var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } } ()) function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.prependListener = noop; process.prependOnceListener = noop; process.listeners = function (name) { return [] } process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; },{}],8:[function(_dereq_,module,exports){ 'use strict'; var has = Object.prototype.hasOwnProperty , undef; /** * Decode a URI encoded string. * * @param {String} input The URI encoded string. * @returns {String|Null} The decoded string. * @api private */ function decode(input) { try { return decodeURIComponent(input.replace(/\+/g, ' ')); } catch (e) { return null; } } /** * Attempts to encode a given input. * * @param {String} input The string that needs to be encoded. * @returns {String|Null} The encoded string. * @api private */ function encode(input) { try { return encodeURIComponent(input); } catch (e) { return null; } } /** * Simple query string parser. * * @param {String} query The query string that needs to be parsed. * @returns {Object} * @api public */ function querystring(query) { var parser = /([^=?#&]+)=?([^&]*)/g , result = {} , part; while (part = parser.exec(query)) { var key = decode(part[1]) , value = decode(part[2]); // // Prevent overriding of existing properties. This ensures that build-in // methods like `toString` or __proto__ are not overriden by malicious // querystrings. // // In the case if failed decoding, we want to omit the key/value pairs // from the result. // if (key === null || value === null || key in result) continue; result[key] = value; } return result; } /** * Transform a query string to an object. * * @param {Object} obj Object that should be transformed. * @param {String} prefix Optional prefix. * @returns {String} * @api public */ function querystringify(obj, prefix) { prefix = prefix || ''; var pairs = [] , value , key; // // Optionally prefix with a '?' if needed // if ('string' !== typeof prefix) prefix = '?'; for (key in obj) { if (has.call(obj, key)) { value = obj[key]; // // Edge cases where we actually want to encode the value to an empty // string instead of the stringified value. // if (!value && (value === null || value === undef || isNaN(value))) { value = ''; } key = encode(key); value = encode(value); // // If we failed to encode the strings, we should bail out as we don't // want to add invalid strings to the query. // if (key === null || value === null) continue; pairs.push(key +'='+ value); } } return pairs.length ? prefix + pairs.join('&') : ''; } // // Expose the module. // exports.stringify = querystringify; exports.parse = querystring; },{}],9:[function(_dereq_,module,exports){ 'use strict'; var EventEmitter = _dereq_('eventemitter3') , millisecond = _dereq_('millisecond') , destroy = _dereq_('demolish') , Tick = _dereq_('tick-tock') , one = _dereq_('one-time'); /** * Returns sane defaults about a given value. * * @param {String} name Name of property we want. * @param {Recovery} selfie Recovery instance that got created. * @param {Object} opts User supplied options we want to check. * @returns {Number} Some default value. * @api private */ function defaults(name, selfie, opts) { return millisecond( name in opts ? opts[name] : (name in selfie ? selfie[name] : Recovery[name]) ); } /** * Attempt to recover your connection with reconnection attempt. * * @constructor * @param {Object} options Configuration * @api public */ function Recovery(options) { var recovery = this; if (!(recovery instanceof Recovery)) return new Recovery(options); options = options || {}; recovery.attempt = null; // Stores the current reconnect attempt. recovery._fn = null; // Stores the callback. recovery['reconnect timeout'] = defaults('reconnect timeout', recovery, options); recovery.retries = defaults('retries', recovery, options); recovery.factor = defaults('factor', recovery, options); recovery.max = defaults('max', recovery, options); recovery.min = defaults('min', recovery, options); recovery.timers = new Tick(recovery); } Recovery.prototype = new EventEmitter(); Recovery.prototype.constructor = Recovery; Recovery['reconnect timeout'] = '30 seconds'; // Maximum time to wait for an answer. Recovery.max = Infinity; // Maximum delay. Recovery.min = '500 ms'; // Minimum delay. Recovery.retries = 10; // Maximum amount of retries. Recovery.factor = 2; // Exponential back off factor. /** * Start a new reconnect procedure. * * @returns {Recovery} * @api public */ Recovery.prototype.reconnect = function reconnect() { var recovery = this; return recovery.backoff(function backedoff(err, opts) { opts.duration = (+new Date()) - opts.start; if (err) return recovery.emit('reconnect failed', err, opts); recovery.emit('reconnected', opts); }, recovery.attempt); }; /** * Exponential back off algorithm for retry operations. It uses a randomized * retry so we don't DDOS our server when it goes down under pressure. * * @param {Function} fn Callback to be called after the timeout. * @param {Object} opts Options for configuring the timeout. * @returns {Recovery} * @api private */ Recovery.prototype.backoff = function backoff(fn, opts) { var recovery = this; opts = opts || recovery.attempt || {}; // // Bailout when we already have a back off process running. We shouldn't call // the callback then. // if (opts.backoff) return recovery; opts['reconnect timeout'] = defaults('reconnect timeout', recovery, opts); opts.retries = defaults('retries', recovery, opts); opts.factor = defaults('factor', recovery, opts); opts.max = defaults('max', recovery, opts); opts.min = defaults('min', recovery, opts); opts.start = +opts.start || +new Date(); opts.duration = +opts.duration || 0; opts.attempt = +opts.attempt || 0; // // Bailout if we are about to make too much attempts. // if (opts.attempt === opts.retries) { fn.call(recovery, new Error('Unable to recover'), opts); return recovery; } // // Prevent duplicate back off attempts using the same options object and // increment our attempt as we're about to have another go at this thing. // opts.backoff = true; opts.attempt++; recovery.attempt = opts; // // Calculate the timeout, but make it randomly so we don't retry connections // at the same interval and defeat the purpose. This exponential back off is // based on the work of: // // http://dthain.blogspot.nl/2009/02/exponential-backoff-in-distributed.html // opts.scheduled = opts.attempt !== 1 ? Math.min(Math.round( (Math.random() + 1) * opts.min * Math.pow(opts.factor, opts.attempt - 1) ), opts.max) : opts.min; recovery.timers.setTimeout('reconnect', function delay() { opts.duration = (+new Date()) - opts.start; opts.backoff = false; recovery.timers.clear('reconnect, timeout'); // // Create a `one` function which can only be called once. So we can use the // same function for different types of invocations to create a much better // and usable API. // var connect = recovery._fn = one(function connect(err) { recovery.reset(); if (err) return recovery.backoff(fn, opts); fn.call(recovery, undefined, opts); }); recovery.emit('reconnect', opts, connect); recovery.timers.setTimeout('timeout', function timeout() { var err = new Error('Failed to reconnect in a timely manner'); opts.duration = (+new Date()) - opts.start; recovery.emit('reconnect timeout', err, opts); connect(err); }, opts['reconnect timeout']); }, opts.scheduled); // // Emit a `reconnecting` event with current reconnect options. This allows // them to update the UI and provide their users with feedback. // recovery.emit('reconnect scheduled', opts); return recovery; }; /** * Check if the reconnection process is currently reconnecting. * * @returns {Boolean} * @api public */ Recovery.prototype.reconnecting = function reconnecting() { return !!this.attempt; }; /** * Tell our reconnection procedure that we're passed. * * @param {Error} err Reconnection failed. * @returns {Recovery} * @api public */ Recovery.prototype.reconnected = function reconnected(err) { if (this._fn) this._fn(err); return this; }; /** * Reset the reconnection attempt so it can be re-used again. * * @returns {Recovery} * @api public */ Recovery.prototype.reset = function reset() { this._fn = this.attempt = null; this.timers.clear('reconnect, timeout'); return this; }; /** * Clean up the instance. * * @type {Function} * @returns {Boolean} * @api public */ Recovery.prototype.destroy = destroy('timers attempt _fn'); // // Expose the module. // module.exports = Recovery; },{"demolish":1,"eventemitter3":10,"millisecond":5,"one-time":6,"tick-tock":12}],10:[function(_dereq_,module,exports){ 'use strict'; // // We store our EE objects in a plain object whose properties are event names. // If `Object.create(null)` is not supported we prefix the event names with a // `~` to make sure that the built-in object properties are not overridden or // used as an attack vector. // We also assume that `Object.create(null)` is available when the event name // is an ES6 Symbol. // var prefix = typeof Object.create !== 'function' ? '~' : false; /** * Representation of a single EventEmitter function. * * @param {Function} fn Event handler to be called. * @param {Mixed} context Context for function execution. * @param {Boolean} once Only emit once * @api private */ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Minimal EventEmitter interface that is molded against the Node.js * EventEmitter interface. * * @constructor * @api public */ function EventEmitter() { /* Nothing to set */ } /** * Holds the assigned EventEmitters by name. * * @type {Object} * @private */ EventEmitter.prototype._events = undefined; /** * Return a list of assigned event listeners. * * @param {String} event The events that should be listed. * @param {Boolean} exists We only need to know if there are listeners. * @returns {Array|Boolean} * @api public */ EventEmitter.prototype.listeners = function listeners(event, exists) { var evt = prefix ? prefix + event : event , available = this._events && this._events[evt]; if (exists) return !!available; if (!available) return []; if (available.fn) return [available.fn]; for (var i = 0, l = available.length, ee = new Array(l); i < l; i++) { ee[i] = available[i].fn; } return ee; }; /** * Emit an event to all registered event listeners. * * @param {String} event The name of the event. * @returns {Boolean} Indication if we've emitted an event. * @api public */ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events || !this._events[evt]) return false; var listeners = this._events[evt] , len = arguments.length , args , i; if ('function' === typeof listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len -1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length , j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; default: if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Register a new EventListener for the given event. * * @param {String} event Name of the event. * @param {Functon} fn Callback function. * @param {Mixed} context The context of the function. * @api public */ EventEmitter.prototype.on = function on(event, fn, context) { var listener = new EE(fn, context || this) , evt = prefix ? prefix + event : event; if (!this._events) this._events = prefix ? {} : Object.create(null); if (!this._events[evt]) this._events[evt] = listener; else { if (!this._events[evt].fn) this._events[evt].push(listener); else this._events[evt] = [ this._events[evt], listener ]; } return this; }; /** * Add an EventListener that's only called once. * * @param {String} event Name of the event. * @param {Function} fn Callback function. * @param {Mixed} context The context of the function. * @api public */ EventEmitter.prototype.once = function once(event, fn, context) { var listener = new EE(fn, context || this, true) , evt = prefix ? prefix + event : event; if (!this._events) this._events = prefix ? {} : Object.create(null); if (!this._events[evt]) this._events[evt] = listener; else { if (!this._events[evt].fn) this._events[evt].push(listener); else this._events[evt] = [ this._events[evt], listener ]; } return this; }; /** * Remove event listeners. * * @param {String} event The event we want to remove. * @param {Function} fn The listener that we need to find. * @param {Mixed} context Only remove listeners matching this context. * @param {Boolean} once Only remove once listeners. * @api public */ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events || !this._events[evt]) return this; var listeners = this._events[evt] , events = []; if (fn) { if (listeners.fn) { if ( listeners.fn !== fn || (once && !listeners.once) || (context && listeners.context !== context) ) { events.push(listeners); } } else { for (var i = 0, length = listeners.length; i < length; i++) { if ( listeners[i].fn !== fn || (once && !listeners[i].once) || (context && listeners[i].context !== context) ) { events.push(listeners[i]); } } } } // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) { this._events[evt] = events.length === 1 ? events[0] : events; } else { delete this._events[evt]; } return this; }; /** * Remove all listeners or only the listeners for the specified event. * * @param {String} event The event want to remove all listeners for. * @api public */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { if (!this._events) return this; if (event) delete this._events[prefix ? prefix + event : event]; else this._events = prefix ? {} : Object.create(null); return this; }; // // Alias methods names because people roll like that. // EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.addListener = EventEmitter.prototype.on; // // This function doesn't apply anymore. // EventEmitter.prototype.setMaxListeners = function setMaxListeners() { return this; }; // // Expose the prefix. // EventEmitter.prefixed = prefix; // // Expose the module. // if ('undefined' !== typeof module) { module.exports = EventEmitter; } },{}],11:[function(_dereq_,module,exports){ 'use strict'; /** * Check if we're required to add a port number. * * @see https://url.spec.whatwg.org/#default-port * @param {Number|String} port Port number we need to check * @param {String} protocol Protocol we need to check against. * @returns {Boolean} Is it a default port for the given protocol * @api private */ module.exports = function required(port, protocol) { protocol = protocol.split(':')[0]; port = +port; if (!port) return false; switch (protocol) { case 'http': case 'ws': return port !== 80; case 'https': case 'wss': return port !== 443; case 'ftp': return port !== 21; case 'gopher': return port !== 70; case 'file': return false; } return port !== 0; }; },{}],12:[function(_dereq_,module,exports){ (function (setImmediate,clearImmediate){(function (){ 'use strict'; var has = Object.prototype.hasOwnProperty , ms = _dereq_('millisecond'); /** * Timer instance. * * @constructor * @param {Object} timer New timer instance. * @param {Function} clear Clears the timer instance. * @param {Function} duration Duration of the timer. * @param {Function} fn The functions that need to be executed. * @api private */ function Timer(timer, clear, duration, fn) { this.start = +(new Date()); this.duration = duration; this.clear = clear; this.timer = timer; this.fns = [fn]; } /** * Calculate the time left for a given timer. * * @returns {Number} Time in milliseconds. * @api public */ Timer.prototype.remaining = function remaining() { return this.duration - this.taken(); }; /** * Calculate the amount of time it has taken since we've set the timer. * * @returns {Number} * @api public */ Timer.prototype.taken = function taken() { return +(new Date()) - this.start; }; /** * Custom wrappers for the various of clear{whatever} functions. We cannot * invoke them directly as this will cause thrown errors in Google Chrome with * an Illegal Invocation Error * * @see #2 * @type {Function} * @api private */ function unsetTimeout(id) { clearTimeout(id); } function unsetInterval(id) { clearInterval(id); } function unsetImmediate(id) { clearImmediate(id); } /** * Simple timer management. * * @constructor * @param {Mixed} context Context of the callbacks that we execute. * @api public */ function Tick(context) { if (!(this instanceof Tick)) return new Tick(context); this.timers = {}; this.context = context || this; } /** * Return a function which will just iterate over all assigned callbacks and * optionally clear the timers from memory if needed. * * @param {String} name Name of the timer we need to execute. * @param {Boolean} clear Also clear from memory. * @returns {Function} * @api private */ Tick.prototype.tock = function ticktock(name, clear) { var tock = this; return function tickedtock() { if (!(name in tock.timers)) return; var timer = tock.timers[name] , fns = timer.fns.slice() , l = fns.length , i = 0; if (clear) tock.clear(name); else tock.start = +new Date(); for (; i < l; i++) { fns[i].call(tock.context); } }; }; /** * Add a new timeout. * * @param {String} name Name of the timer. * @param {Function} fn Completion callback. * @param {Mixed} time Duration of the timer. * @returns {Tick} * @api public */ Tick.prototype.setTimeout = function timeout(name, fn, time) { var tick = this , tock; if (tick.timers[name]) { tick.timers[name].fns.push(fn); return tick; } tock = ms(time); tick.timers[name] = new Timer( setTimeout(tick.tock(name, true), ms(time)), unsetTimeout, tock, fn ); return tick; }; /** * Add a new interval. * * @param {String} name Name of the timer. * @param {Function} fn Completion callback. * @param {Mixed} time Interval of the timer. * @returns {Tick} * @api public */ Tick.prototype.setInterval = function interval(name, fn, time) { var tick = this , tock; if (tick.timers[name]) { tick.timers[name].fns.push(fn); return tick; } tock = ms(time); tick.timers[name] = new Timer( setInterval(tick.tock(name), ms(time)), unsetInterval, tock, fn ); return tick; }; /** * Add a new setImmediate. * * @param {String} name Name of the timer. * @param {Function} fn Completion callback. * @returns {Tick} * @api public */ Tick.prototype.setImmediate = function immediate(name, fn) { var tick = this; if ('function' !== typeof setImmediate) return tick.setTimeout(name, fn, 0); if (tick.timers[name]) { tick.timers[name].fns.push(fn); return tick; } tick.timers[name] = new Timer( setImmediate(tick.tock(name, true)), unsetImmediate, 0, fn ); return tick; }; /** * Check if we have a timer set. * * @param {String} name * @returns {Boolean} * @api public */ Tick.prototype.active = function active(name) { return name in this.timers; }; /** * Properly clean up all timeout references. If no arguments are supplied we * will attempt to clear every single timer that is present. * * @param {Arguments} ..args.. The names of the timeouts we need to clear * @returns {Tick} * @api public */ Tick.prototype.clear = function clear() { var args = arguments.length ? arguments : [] , tick = this , timer, i, l; if (args.length === 1 && 'string' === typeof args[0]) { args = args[0].split(/[, ]+/); } if (!args.length) { for (timer in tick.timers) { if (has.call(tick.timers, timer)) args.push(timer); } } for (i = 0, l = args.length; i < l; i++) { timer = tick.timers[args[i]]; if (!timer) continue; timer.clear(timer.timer); timer.fns = timer.timer = timer.clear = null; delete tick.timers[args[i]]; } return tick; }; /** * Adjust a timeout or interval to a new duration. * * @returns {Tick} * @api public */ Tick.prototype.adjust = function adjust(name, time) { var interval , tick = this , tock = ms(time) , timer = tick.timers[name]; if (!timer) return tick; interval = timer.clear === unsetInterval; timer.clear(timer.timer); timer.start = +(new Date()); timer.duration = tock; timer.timer = (interval ? setInterval : setTimeout)(tick.tock(name, !interval), tock); return tick; }; /** * We will no longer use this module, prepare your self for global cleanups. * * @returns {Boolean} * @api public */ Tick.prototype.end = Tick.prototype.destroy = function end() { if (!this.context) return false; this.clear(); this.context = this.timers = null; return true; }; // // Expose the timer factory. // Tick.Timer = Timer; module.exports = Tick; }).call(this)}).call(this,_dereq_("timers").setImmediate,_dereq_("timers").clearImmediate) },{"millisecond":5,"timers":13}],13:[function(_dereq_,module,exports){ (function (setImmediate,clearImmediate){(function (){ var nextTick = _dereq_('process/browser.js').nextTick; var apply = Function.prototype.apply; var slice = Array.prototype.slice; var immediateIds = {}; var nextImmediateId = 0; // DOM APIs, for completeness exports.setTimeout = function() { return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); }; exports.setInterval = function() { return new Timeout(apply.call(setInterval, window, arguments), clearInterval); }; exports.clearTimeout = exports.clearInterval = function(timeout) { timeout.close(); }; function Timeout(id, clearFn) { this._id = id; this._clearFn = clearFn; } Timeout.prototype.unref = Timeout.prototype.ref = function() {}; Timeout.prototype.close = function() { this._clearFn.call(window, this._id); }; // Does not start the time, just sets up the members needed. exports.enroll = function(item, msecs) { clearTimeout(item._idleTimeoutId); item._idleTimeout = msecs; }; exports.unenroll = function(item) { clearTimeout(item._idleTimeoutId); item._idleTimeout = -1; }; exports._unrefActive = exports.active = function(item) { clearTimeout(item._idleTimeoutId); var msecs = item._idleTimeout; if (msecs >= 0) { item._idleTimeoutId = setTimeout(function onTimeout() { if (item._onTimeout) item._onTimeout(); }, msecs); } }; // That's not how node.js implements it but the exposed api is the same. exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { var id = nextImmediateId++; var args = arguments.length < 2 ? false : slice.call(arguments, 1); immediateIds[id] = true; nextTick(function onNextTick() { if (immediateIds[id]) { // fn.call() is faster so we optimize for the common use-case // @see http://jsperf.com/call-apply-segu if (args) { fn.apply(null, args); } else { fn.call(null); } // Prevent ids from leaking exports.clearImmediate(id); } }); return id; }; exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { delete immediateIds[id]; }; }).call(this)}).call(this,_dereq_("timers").setImmediate,_dereq_("timers").clearImmediate) },{"process/browser.js":7,"timers":13}],14:[function(_dereq_,module,exports){ (function (global){(function (){ 'use strict'; var required = _dereq_('requires-port') , qs = _dereq_('querystringify') , controlOrWhitespace = /^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/ , CRHTLF = /[\n\r\t]/g , slashes = /^[A-Za-z][A-Za-z0-9+-.]*:\/\// , port = /:\d+$/ , protocolre = /^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i , windowsDriveLetter = /^[a-zA-Z]:/; /** * Remove control characters and whitespace from the beginning of a string. * * @param {Object|String} str String to trim. * @returns {String} A new string representing `str` stripped of control * characters and whitespace from its beginning. * @public */ function trimLeft(str) { return (str ? str : '').toString().replace(controlOrWhitespace, ''); } /** * These are the parse rules for the URL parser, it informs the parser * about: * * 0. The char it Needs to parse, if it's a string it should be done using * indexOf, RegExp using exec and NaN means set as current value. * 1. The property we should set when parsing this value. * 2. Indication if it's backwards or forward parsing, when set as number it's * the value of extra chars that should be split off. * 3. Inherit from location if non existing in the parser. * 4. `toLowerCase` the resulting value. */ var rules = [ ['#', 'hash'], // Extract from the back. ['?', 'query'], // Extract from the back. function sanitize(address, url) { // Sanitize what is left of the address return isSpecial(url.protocol) ? address.replace(/\\/g, '/') : address; }, ['/', 'pathname'], // Extract from the back. ['@', 'auth', 1], // Extract from the front. [NaN, 'host', undefined, 1, 1], // Set left over value. [/:(\d*)$/, 'port', undefined, 1], // RegExp the back. [NaN, 'hostname', undefined,