@skylineos/videojs-clsp
Version:
Video JS plugin for Skyline Technology Solutions' CLSP Player - https://github.com/skylineos/clsp-player
1,592 lines (1,394 loc) • 807 kB
JavaScript
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ 478:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
/**
* This file needs to use `require` rather than `import` to be able to be used
* by webpack.
*/
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
var clspPlayerUtils = __webpack_require__(863);
var Logger = __webpack_require__(764);
var _require = __webpack_require__(330),
version = _require.version,
name = _require.name;
module.exports = _objectSpread({}, clspPlayerUtils, {
version: version,
name: name.split('/').pop(),
// The name that will be used to register this plugin with videojs, which in
// practice will be used as `player.clsp()`
pluginName: 'clsp',
Logger: Logger,
// This gives us access to the clsp player version and name (and of course, it
// duplicates the utils)
clspPlayerUtils: clspPlayerUtils
});
/***/ }),
/***/ 764:
/***/ ((module) => {
"use strict";
/* eslint no-console: off */
/**
* This file needs to use `require` rather than `import` to be able to be used
* by webpack.
*
* We use this in the router as well, so keep it light and ES5 only!
*/
module.exports = function (version, logLevel, disableLogging) {
function Logger(prefix, prefixStyle) {
if (logLevel === undefined && typeof window !== 'undefined') {
var storedVersion = window.localStorage.getItem('skylineos.clsp-player.version');
// Always reset the log level when the version changes
if (storedVersion !== version) {
window.localStorage.setItem('skylineos.clsp-player.logLevel', 0);
window.localStorage.setItem('skylineos.clsp-player.version', version);
}
var storedLogLevel = Number(window.localStorage.getItem('skylineos.clsp-player.logLevel'));
// The logLevel may be set in localstorage
// e.g. localStorage.setItem('skylineos.clsp-player.logLevel', 3), then refresh
logLevel = isNaN(storedLogLevel) || storedLogLevel < 0 ? 0 : storedLogLevel;
window.localStorage.setItem('skylineos.clsp-player.logLevel', logLevel);
}
this.logLevel = logLevel;
this.prefix = prefix;
this.prefixStyle = prefixStyle;
}
Logger.logLevels = ['critical', 'error', 'warn', 'info', 'debug', 'silly'];
Logger.factory = function (prefix, prefixStyle) {
return new Logger(prefix || '', prefixStyle);
};
Logger.prototype._constructMessage = function (type, message) {
var logMessage = '(' + type + ')' + ' --> ' + message;
// @see - https://developers.google.com/web/tools/chrome-devtools/console/console-write#string_substitution_and_formatting
if (this.prefix && this.prefixStyle && this.logLevel > 1) {
return ['%c' + this.prefix, this.prefixStyle, logMessage];
}
if (this.prefix) {
return [this.prefix, logMessage];
}
return [logMessage];
};
var sillyIndex = 5;
var debugIndex = 4;
var infoIndex = 3;
var warnIndex = 2;
var errorIndex = 1;
var criticalIndex = 0;
Logger.prototype.silly = function (message) {
if (this.logLevel < sillyIndex || disableLogging) {
return;
}
console.log.apply(console, this._constructMessage(Logger.logLevels[sillyIndex], message));
};
Logger.prototype.debug = function (message) {
if (this.logLevel < debugIndex || disableLogging) {
return;
}
console.log.apply(console, this._constructMessage(Logger.logLevels[debugIndex], message));
};
Logger.prototype.info = function (message) {
if (this.logLevel < infoIndex || disableLogging) {
return;
}
console.log.apply(console, this._constructMessage(Logger.logLevels[infoIndex], message));
};
Logger.prototype.warn = function (message) {
if (this.logLevel < warnIndex || disableLogging) {
return;
}
console.warn.apply(console, this._constructMessage(Logger.logLevels[warnIndex], message));
};
Logger.prototype.error = function (message) {
if (this.logLevel < errorIndex || disableLogging) {
return;
}
console.error.apply(console, this._constructMessage(Logger.logLevels[errorIndex], message));
};
Logger.prototype.critical = function (message) {
if (disableLogging) {
return;
}
console.error.apply(console, this._constructMessage(Logger.logLevels[criticalIndex], message));
};
return Logger;
};
/***/ }),
/***/ 863:
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
"use strict";
/**
* This file needs to use `require` rather than `import` to be able to be used
* by webpack.
*/
var packageJson = __webpack_require__(814);
var Logger = __webpack_require__(764);
var _isPlayerLoggingEnabled = true;
// CLSP default port for SFS >= 5.2.0 is 80
// CLSP default port for SFS < 5.2.0 is 9001
var DEFAULT_CLSP_PORT = 80;
var DEFAULT_CLSPS_PORT = 443;
// Locally-scoped value that maintains the clsp and clsps port states.
//
// @see - getDefaultStreamPort
// @see - setDefaultStreamPort
//
// @todo - state / config could be managed better than this
var streamPorts = {
clsp: DEFAULT_CLSP_PORT,
clsps: DEFAULT_CLSPS_PORT
};
/**
* The name of the CLSP Player library as defined in `package.json` without the
* group name.
*
* @type {String}
*/
var name = packageJson.name.split('/').pop();
/**
* The version of the CLSP Player library. Follows semver.
*
* @type {String}
*/
var version = packageJson.version;
// @todo - remove this side-effect
var logger = Logger(version).factory();
/**
* The oldest Chrome browser version supported by CLSP Player.
*
* @type {Number}
*/
var MINIMUM_CHROME_VERSION = 53;
/**
* The MIME type required for CLSP Player to be able to play the stream.
*
* @todo - this mime type, though used in the videojs plugin, and
* seemingly enforced, is not actually enforced. The only enforcement
* done is requiring the user provide this string on the video element
* in the DOM. The codecs that are supplied by the SFS's vary. Here
* are some "valid", though not enforced mimeCodec values I have come
* across:
* - video/mp4; codecs="avc1.4DE016"
* - video/mp4; codecs="avc1.42E00C"
* - video/mp4; codecs="avc1.42E00D"
*
* @type {String}
*/
var SUPPORTED_MIME_TYPE = "video/mp4; codecs='avc1.42E01E'";
/**
* The amount of time (in seconds) before a stream times out.
*
* Note that this timeout value should be treated as the minimum value to
* support Vero tours and high-quality streams.
*
* @type {Number}
*/
var DEFAULT_STREAM_TIMEOUT = 20;
/**
* Determine whether or not the CLSP Player is supported in the current browser.
*
* @todo - we are currently manually checking useragentstring - we should find a
* library that can check browser type for us
*
* @returns {Boolean}
* `true` if the browser is supported by CLSP Player
* `false` if the browser is not supported by CLSP Player
*/
function isBrowserCompatable() {
// @todo - at one time, this was needed for browsers on MacOS - is this still
// necessary?
window.MediaSource = window.MediaSource || window.WebKitMediaSource;
if (!window.MediaSource) {
console.error('Media Source Extensions not supported in your browser, unable to load CLSP Player');
return false;
}
var isInternetExplorer = navigator.userAgent.toLowerCase().indexOf('trident') > -1;
if (isInternetExplorer) {
logger.debug('Detected Internet Explorer browser, which is not supported.');
return false;
}
var isEdge = navigator.userAgent.toLowerCase().indexOf('edge') > -1;
if (isEdge) {
logger.debug('Detected older Edge browser, which is not supported');
return false;
}
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
if (isFirefox) {
logger.debug('Detected Firefox browser');
return true;
}
// Most browsers have "Chrome" in their user agent. The above filters rule
// out Internet Explorer and Edge, so we are going to assume that if we're at
// this point, we're really dealing with Chrome.
var isChrome = Boolean(window.chrome);
if (!isChrome) {
return false;
}
try {
// Rather than accounting for match returning null, we'll catch the error
var chromeVersion = parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
logger.debug("Detected Chrome version ".concat(chromeVersion));
return chromeVersion >= MINIMUM_CHROME_VERSION;
} catch (error) {
logger.critical('Unable to detect Chrome version');
logger.critical(error);
return false;
}
}
/**
* Check to see if the passed mimeType is supported by CLSP Player.
*
* @param {String} mimeType
* Will check to see if this mimeType is supported
*
* @returns {Boolean}
* `true` if the mimeType is supported by CLSP Player
* `false` if the mimeType is not supported by CLSP Player
*/
function isSupportedMimeType(mimeType) {
return mimeType === SUPPORTED_MIME_TYPE;
}
/**
* @typedef {Object} PageVisibilityApiPropertyNames
* @property {String} hiddenStateName
* The property name used for the `document.hidden` property
* @property {String} visibilityChangeEventName
* The property name used for the `document.visibilityChange` event name
*/
/**
* Get the property names used by this browser for the Page Visibility API.
*
* @returns {PageVisibilityApiPropertyNames}
*/
function getWindowStateNames() {
logger.debug('Determining Page_Visibility_API property names.');
// @todo - this check is needed to support these utils being imported by
// webpack. there is probably a more elegant way to handle this scenario.
if (typeof document === 'undefined') {
return {
hiddenStateName: '',
visibilityChangeEventName: ''
};
}
// @see - https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
if (typeof document.hidden !== 'undefined') {
logger.debug('Using standard Page_Visibility_API property names.');
return {
hiddenStateName: 'hidden',
visibilityChangeEventName: 'visibilitychange'
};
}
// @todo - do we need this since we don't support IE or old Edge?
if (typeof document.msHidden !== 'undefined') {
logger.debug('Using Microsoft Page_Visibility_API property names.');
return {
hiddenStateName: 'msHidden',
visibilityChangeEventName: 'msvisibilitychange'
};
}
if (typeof document.webkitHidden !== 'undefined') {
logger.debug('Using Webkit Page_Visibility_API property names.');
return {
hiddenStateName: 'webkitHidden',
visibilityChangeEventName: 'webkitvisibilitychange'
};
}
logger.critical('Unable to use the page visibility api - switching tabs and minimizing the page may result in slow downs and page crashes.');
return {
hiddenStateName: '',
visibilityChangeEventName: ''
};
}
/**
* Get the default port number for the given protocol.
*
* @param {String} protocol
* The protocol to get the default port for. Must be a known protocol (e.g.
* `clsp` or `clsps`)
*/
function getDefaultStreamPort(protocol) {
return streamPorts[protocol];
}
/**
* Set the default port number for the given protocol.
*
* @param {String} protocol
* The protocol to set the default port for. Must be a known protocol (e.g.
* `clsp` or `clsps`)
*/
function setDefaultStreamPort(protocol, port) {
streamPorts[protocol] = port;
}
function enablePlayerLogging() {
_isPlayerLoggingEnabled = true;
}
function disablePlayerLogging() {
_isPlayerLoggingEnabled = false;
}
function isPlayerLoggingDisabled() {
return !_isPlayerLoggingEnabled;
}
var windowStateNames = getWindowStateNames();
function isDocumentHidden() {
return document[windowStateNames.hiddenStateName];
}
function isOnline() {
return window.navigator.onLine;
}
module.exports = {
name: name,
version: version,
MINIMUM_CHROME_VERSION: MINIMUM_CHROME_VERSION,
SUPPORTED_MIME_TYPE: SUPPORTED_MIME_TYPE,
DEFAULT_STREAM_TIMEOUT: DEFAULT_STREAM_TIMEOUT,
supported: isBrowserCompatable,
isSupportedMimeType: isSupportedMimeType,
windowStateNames: windowStateNames,
isDocumentHidden: isDocumentHidden,
isOnline: isOnline,
getDefaultStreamPort: getDefaultStreamPort,
setDefaultStreamPort: setDefaultStreamPort,
enablePlayerLogging: enablePlayerLogging,
disablePlayerLogging: disablePlayerLogging,
isPlayerLoggingDisabled: isPlayerLoggingDisabled
};
/***/ }),
/***/ 228:
/***/ ((module) => {
"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 (true) {
module.exports = EventEmitter;
}
/***/ }),
/***/ 973:
/***/ ((module) => {
/**
* @param {*} val - value to check
*
* @returns {boolean} true if the value is then-able
*/
function isPromise(val) {
return val != null && typeof val.then === 'function'
}
/**
* @param {function} func - function to execute
* @param {number|function(number):number} intervalLength - length in ms to wait before executing again
* @param {{iterations: Infinity|number, stopOnError: boolean}} [options]
*
* @returns {Promise} Promise object with no result
*/
function interval(func, intervalLength, options = {}) {
validateArgs(func, intervalLength, options)
const defaults = {
iterations: Infinity,
stopOnError: true
}
const settings = Object.assign(defaults, options)
return new Promise((rootPromiseResolve, rootPromiseReject) => {
const callFunction = currentIteration => {
// Set up a way to track if a "stop" was requested by the user function
let stopRequested = false
const stop = () => {
stopRequested = true
}
// Set up a function to call the next iteration. This is abstracted so it can be called by .then(), or in .catch(), if options allow.
const callNext = () => {
// If we've hit the desired number of iterations, or stop was called, resolve the root promise and return
if (currentIteration === settings.iterations || stopRequested) {
rootPromiseResolve()
return
}
// Otherwise, call the next iteration
callFunction(currentIteration + 1)
}
// Calculate our interval length
const calculatedIntervalLength = (typeof intervalLength === 'function') ? intervalLength(currentIteration) : intervalLength
// If the interval length was calculated, validate the result
if (typeof intervalLength === 'function') {
if (!Number.isInteger(calculatedIntervalLength) || calculatedIntervalLength < 0) {
rootPromiseReject(new Error('Function for "intervalLength" argument must return a non-negative integer.'))
return
}
}
// Call the user function after the desired interval length. After, call the next iteration (and/or handle error)
setTimeout(() => {
const returnVal = func(currentIteration, stop)
// Ensure that the value returned is a promise
if (!isPromise(returnVal)) {
rootPromiseReject(new Error('Return value of "func" must be a Promise.'))
return
}
returnVal.then(callNext).catch(err => {
if (!settings.stopOnError) {
callNext()
return
}
rootPromiseReject(err)
})
}, calculatedIntervalLength)
}
callFunction(1)
})
}
/**
* A helper function to validate the arguments passed to interval(...)
*
* @param {*} func
* @param {*} intervalLength
* @param {*} options
*/
function validateArgs(func, intervalLength, options) {
// Validate "func"
if (typeof func !== 'function') {
throw new TypeError('Argument 1, "func", must be a function.')
}
// Validate "intervalLength"
if (typeof intervalLength === 'number') {
if (!Number.isInteger(intervalLength) || intervalLength < 0) {
throw new TypeError('Argument 2, "intervalLength", must be a non-negative integer or a function that returns a non-negative integer.')
}
} else if (typeof intervalLength !== 'function') {
throw new TypeError('Argument 2, "intervalLength", must be a non-negative integer or a function that returns a non-negative integer.')
}
// Validate options...
if (typeof options !== 'object') {
throw new TypeError('Argument 3, "options", must be an object.')
}
// Validate passed keys
const allowedKeys = ['iterations', 'stopOnError']
Object.keys(options).forEach(key => {
if (!allowedKeys.includes(key)) {
throw new TypeError('Option "' + key + '" is not a valid option.')
}
})
// validate "iterations" option (if passed)
if (typeof options.iterations !== 'undefined') {
if (options.iterations !== Infinity && (!Number.isInteger(options.iterations) || options.iterations < 1)) {
throw new TypeError('Option "iterations" must be Infinity or an integer greater than 0.')
}
}
// validate "stopOnError" option (if passed)
if (typeof options.stopOnError !== 'undefined') {
if (typeof options.stopOnError !== 'boolean') {
throw new TypeError('Option "stopOnError" must be a boolean.')
}
}
}
module.exports = interval
/***/ }),
/***/ 843:
/***/ ((module) => {
/**
* Checks if `value` is `null` or `undefined`.
*
* @static
* @memberOf _
* @since 4.0.0
* @category Lang
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is nullish, else `false`.
* @example
*
* _.isNil(null);
* // => true
*
* _.isNil(void 0);
* // => true
*
* _.isNil(NaN);
* // => false
*/
function isNil(value) {
return value == null;
}
module.exports = isNil;
/***/ }),
/***/ 543:
/***/ (function(module) {
/*******************************************************************************
* 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(1