From 8b9eee1e6a733bc9f44e2c5e01e44b402a5faea8 Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Mon, 30 Mar 2020 09:48:34 -0700 Subject: [PATCH 1/3] WIP: fix fsevents error --- .../optimizely-sdk/optimizely.browser.umd.js | 8133 +++++++++++++++++ .../optimizely.browser.umd.min.js | 1 + packages/optimizely-sdk/package-lock.json | 3754 ++++---- packages/optimizely-sdk/package.json | 10 +- 4 files changed, 9782 insertions(+), 2116 deletions(-) create mode 100644 packages/optimizely-sdk/optimizely.browser.umd.js create mode 100644 packages/optimizely-sdk/optimizely.browser.umd.min.js diff --git a/packages/optimizely-sdk/optimizely.browser.umd.js b/packages/optimizely-sdk/optimizely.browser.umd.js new file mode 100644 index 000000000..2ddeb37fc --- /dev/null +++ b/packages/optimizely-sdk/optimizely.browser.umd.js @@ -0,0 +1,8133 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["optimizelySdk"] = factory(); + else + root["optimizelySdk"] = factory(); +})(window, function() { +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 = 0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016-2017, 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 logging = __webpack_require__(1); +var fns = __webpack_require__(11); +var configValidator = __webpack_require__(13); +var defaultErrorHandler = __webpack_require__(15); +var defaultEventDispatcher = __webpack_require__(16); +var enums = __webpack_require__(14); +var eventProcessor = __webpack_require__(17); +var loggerPlugin = __webpack_require__(26); +var Optimizely = __webpack_require__(27); +var eventProcessorConfigValidator = __webpack_require__(55); + +var logger = logging.getLogger(); +logging.setLogHandler(loggerPlugin.createLogger()); +logging.setLogLevel(logging.LogLevel.INFO); + +var MODULE_NAME = 'INDEX_BROWSER'; + +var DEFAULT_EVENT_BATCH_SIZE = 10; +var DEFAULT_EVENT_FLUSH_INTERVAL = 1000; // Unit is ms, default is 1s + +var hasRetriedEvents = false; +/** + * Entry point into the Optimizely Browser SDK + */ +module.exports = { + logging: loggerPlugin, + errorHandler: defaultErrorHandler, + eventDispatcher: defaultEventDispatcher, + enums: enums, + + setLogger: logging.setLogHandler, + setLogLevel: logging.setLogLevel, + + /** + * Creates an instance of the Optimizely class + * @param {Object} config + * @param {Object} config.datafile + * @param {Object} config.errorHandler + * @param {Object} config.eventDispatcher + * @param {Object} config.logger + * @param {Object} config.logLevel + * @param {Object} config.userProfileService + * @param {Object} config.eventBatchSize + * @param {Object} config.eventFlushInterval + * @return {Object} the Optimizely object + */ + createInstance: function(config) { + try { + config = config || {}; + + // TODO warn about setting per instance errorHandler / logger / logLevel + if (config.errorHandler) { + logging.setErrorHandler(config.errorHandler); + } + if (config.logger) { + logging.setLogHandler(config.logger); + // respect the logger's shouldLog functionality + logging.setLogLevel(logging.LogLevel.NOTSET); + } + if (config.logLevel !== undefined) { + logging.setLogLevel(config.logLevel); + } + + try { + configValidator.validate(config); + config.isValidInstance = true; + } catch (ex) { + logger.error(ex); + config.isValidInstance = false; + } + + // Explicitly check for null or undefined + // prettier-ignore + if (config.skipJSONValidation == null) { // eslint-disable-line eqeqeq + config.skipJSONValidation = true; + } + + var eventDispatcher; + // prettier-ignore + if (config.eventDispatcher == null) { // eslint-disable-line eqeqeq + // only wrap the event dispatcher with pending events retry if the user didnt override + eventDispatcher = new eventProcessor.LocalStoragePendingEventsDispatcher({ + eventDispatcher: defaultEventDispatcher, + }); + + if (!hasRetriedEvents) { + eventDispatcher.sendPendingEvents(); + hasRetriedEvents = true; + } + } else { + eventDispatcher = config.eventDispatcher; + } + + config = fns.assign( + { + clientEngine: enums.JAVASCRIPT_CLIENT_ENGINE, + eventBatchSize: DEFAULT_EVENT_BATCH_SIZE, + eventFlushInterval: DEFAULT_EVENT_FLUSH_INTERVAL, + }, + config, + { + eventDispatcher: eventDispatcher, + // always get the OptimizelyLogger facade from logging + logger: logger, + errorHandler: logging.getErrorHandler(), + } + ); + + if (!eventProcessorConfigValidator.validateEventBatchSize(config.eventBatchSize)) { + logger.warn('Invalid eventBatchSize %s, defaulting to %s', config.eventBatchSize, DEFAULT_EVENT_BATCH_SIZE); + config.eventBatchSize = DEFAULT_EVENT_BATCH_SIZE; + } + if (!eventProcessorConfigValidator.validateEventFlushInterval(config.eventFlushInterval)) { + logger.warn( + 'Invalid eventFlushInterval %s, defaulting to %s', + config.eventFlushInterval, + DEFAULT_EVENT_FLUSH_INTERVAL + ); + config.eventFlushInterval = DEFAULT_EVENT_FLUSH_INTERVAL; + } + + var optimizely = new Optimizely(config); + + try { + if (typeof window.addEventListener === 'function') { + var unloadEvent = 'onpagehide' in window ? 'pagehide' : 'unload'; + window.addEventListener( + unloadEvent, + function() { + optimizely.close(); + }, + false + ); + } + } catch (e) { + logger.error(enums.LOG_MESSAGES.UNABLE_TO_ATTACH_UNLOAD, MODULE_NAME, e.message); + } + + return optimizely; + } catch (e) { + logger.error(e); + return null; + } + }, + + __internalResetRetryState: function() { + hasRetriedEvents = false; + }, +}; + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +__export(__webpack_require__(2)); +__export(__webpack_require__(3)); +__export(__webpack_require__(4)); + + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * @export + * @class NoopErrorHandler + * @implements {ErrorHandler} + */ +var NoopErrorHandler = /** @class */ (function () { + function NoopErrorHandler() { + } + /** + * @param {Error} exception + * @memberof NoopErrorHandler + */ + NoopErrorHandler.prototype.handleError = function (exception) { + // no-op + return; + }; + return NoopErrorHandler; +}()); +exports.NoopErrorHandler = NoopErrorHandler; +var globalErrorHandler = new NoopErrorHandler(); +/** + * @export + * @param {ErrorHandler} handler + */ +function setErrorHandler(handler) { + globalErrorHandler = handler; +} +exports.setErrorHandler = setErrorHandler; +/** + * @export + * @returns {ErrorHandler} + */ +function getErrorHandler() { + return globalErrorHandler; +} +exports.getErrorHandler = getErrorHandler; +/** + * @export + */ +function resetErrorHandler() { + globalErrorHandler = new NoopErrorHandler(); +} +exports.resetErrorHandler = resetErrorHandler; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 LogLevel; +(function (LogLevel) { + LogLevel[LogLevel["NOTSET"] = 0] = "NOTSET"; + LogLevel[LogLevel["DEBUG"] = 1] = "DEBUG"; + LogLevel[LogLevel["INFO"] = 2] = "INFO"; + LogLevel[LogLevel["WARNING"] = 3] = "WARNING"; + LogLevel[LogLevel["ERROR"] = 4] = "ERROR"; +})(LogLevel = exports.LogLevel || (exports.LogLevel = {})); + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 errorHandler_1 = __webpack_require__(2); +var js_sdk_utils_1 = __webpack_require__(5); +var models_1 = __webpack_require__(3); +var stringToLogLevel = { + NOTSET: 0, + DEBUG: 1, + INFO: 2, + WARNING: 3, + ERROR: 4, +}; +function coerceLogLevel(level) { + if (typeof level !== 'string') { + return level; + } + level = level.toUpperCase(); + if (level === 'WARN') { + level = 'WARNING'; + } + if (!stringToLogLevel[level]) { + return level; + } + return stringToLogLevel[level]; +} +var DefaultLogManager = /** @class */ (function () { + function DefaultLogManager() { + this.defaultLoggerFacade = new OptimizelyLogger(); + this.loggers = {}; + } + DefaultLogManager.prototype.getLogger = function (name) { + if (!name) { + return this.defaultLoggerFacade; + } + if (!this.loggers[name]) { + this.loggers[name] = new OptimizelyLogger({ messagePrefix: name }); + } + return this.loggers[name]; + }; + return DefaultLogManager; +}()); +var ConsoleLogHandler = /** @class */ (function () { + /** + * Creates an instance of ConsoleLogger. + * @param {ConsoleLogHandlerConfig} config + * @memberof ConsoleLogger + */ + function ConsoleLogHandler(config) { + if (config === void 0) { config = {}; } + this.logLevel = models_1.LogLevel.NOTSET; + if (config.logLevel !== undefined && js_sdk_utils_1.isValidEnum(models_1.LogLevel, config.logLevel)) { + this.setLogLevel(config.logLevel); + } + this.logToConsole = config.logToConsole !== undefined ? !!config.logToConsole : true; + this.prefix = config.prefix !== undefined ? config.prefix : '[OPTIMIZELY]'; + } + /** + * @param {LogLevel} level + * @param {string} message + * @memberof ConsoleLogger + */ + ConsoleLogHandler.prototype.log = function (level, message) { + if (!this.shouldLog(level) || !this.logToConsole) { + return; + } + var logMessage = this.prefix + " - " + this.getLogLevelName(level) + " " + this.getTime() + " " + message; + this.consoleLog(level, [logMessage]); + }; + /** + * @param {LogLevel} level + * @memberof ConsoleLogger + */ + ConsoleLogHandler.prototype.setLogLevel = function (level) { + level = coerceLogLevel(level); + if (!js_sdk_utils_1.isValidEnum(models_1.LogLevel, level) || level === undefined) { + this.logLevel = models_1.LogLevel.ERROR; + } + else { + this.logLevel = level; + } + }; + /** + * @returns {string} + * @memberof ConsoleLogger + */ + ConsoleLogHandler.prototype.getTime = function () { + return new Date().toISOString(); + }; + /** + * @private + * @param {LogLevel} targetLogLevel + * @returns {boolean} + * @memberof ConsoleLogger + */ + ConsoleLogHandler.prototype.shouldLog = function (targetLogLevel) { + return targetLogLevel >= this.logLevel; + }; + /** + * @private + * @param {LogLevel} logLevel + * @returns {string} + * @memberof ConsoleLogger + */ + ConsoleLogHandler.prototype.getLogLevelName = function (logLevel) { + switch (logLevel) { + case models_1.LogLevel.DEBUG: + return 'DEBUG'; + case models_1.LogLevel.INFO: + return 'INFO '; + case models_1.LogLevel.WARNING: + return 'WARN '; + case models_1.LogLevel.ERROR: + return 'ERROR'; + default: + return 'NOTSET'; + } + }; + /** + * @private + * @param {LogLevel} logLevel + * @param {string[]} logArguments + * @memberof ConsoleLogger + */ + ConsoleLogHandler.prototype.consoleLog = function (logLevel, logArguments) { + switch (logLevel) { + case models_1.LogLevel.DEBUG: + console.log.apply(console, logArguments); + break; + case models_1.LogLevel.INFO: + console.info.apply(console, logArguments); + break; + case models_1.LogLevel.WARNING: + console.warn.apply(console, logArguments); + break; + case models_1.LogLevel.ERROR: + console.error.apply(console, logArguments); + break; + default: + console.log.apply(console, logArguments); + } + }; + return ConsoleLogHandler; +}()); +exports.ConsoleLogHandler = ConsoleLogHandler; +var globalLogLevel = models_1.LogLevel.NOTSET; +var globalLogHandler = null; +var OptimizelyLogger = /** @class */ (function () { + function OptimizelyLogger(opts) { + if (opts === void 0) { opts = {}; } + this.messagePrefix = ''; + if (opts.messagePrefix) { + this.messagePrefix = opts.messagePrefix; + } + } + /** + * @param {(LogLevel | LogInputObject)} levelOrObj + * @param {string} [message] + * @memberof OptimizelyLogger + */ + OptimizelyLogger.prototype.log = function (level, message) { + this.internalLog(coerceLogLevel(level), { + message: message, + splat: [], + }); + }; + OptimizelyLogger.prototype.info = function (message) { + var splat = []; + for (var _i = 1; _i < arguments.length; _i++) { + splat[_i - 1] = arguments[_i]; + } + this.namedLog(models_1.LogLevel.INFO, message, splat); + }; + OptimizelyLogger.prototype.debug = function (message) { + var splat = []; + for (var _i = 1; _i < arguments.length; _i++) { + splat[_i - 1] = arguments[_i]; + } + this.namedLog(models_1.LogLevel.DEBUG, message, splat); + }; + OptimizelyLogger.prototype.warn = function (message) { + var splat = []; + for (var _i = 1; _i < arguments.length; _i++) { + splat[_i - 1] = arguments[_i]; + } + this.namedLog(models_1.LogLevel.WARNING, message, splat); + }; + OptimizelyLogger.prototype.error = function (message) { + var splat = []; + for (var _i = 1; _i < arguments.length; _i++) { + splat[_i - 1] = arguments[_i]; + } + this.namedLog(models_1.LogLevel.ERROR, message, splat); + }; + OptimizelyLogger.prototype.format = function (data) { + return "" + (this.messagePrefix ? this.messagePrefix + ': ' : '') + js_sdk_utils_1.sprintf.apply(void 0, [data.message].concat(data.splat)); + }; + OptimizelyLogger.prototype.internalLog = function (level, data) { + if (!globalLogHandler) { + return; + } + if (level < globalLogLevel) { + return; + } + globalLogHandler.log(level, this.format(data)); + if (data.error && data.error instanceof Error) { + errorHandler_1.getErrorHandler().handleError(data.error); + } + }; + OptimizelyLogger.prototype.namedLog = function (level, message, splat) { + var error; + if (message instanceof Error) { + error = message; + message = error.message; + this.internalLog(level, { + error: error, + message: message, + splat: splat, + }); + return; + } + if (splat.length === 0) { + this.internalLog(level, { + message: message, + splat: splat, + }); + return; + } + var last = splat[splat.length - 1]; + if (last instanceof Error) { + error = last; + splat.splice(-1); + } + this.internalLog(level, { message: message, error: error, splat: splat }); + }; + return OptimizelyLogger; +}()); +var globalLogManager = new DefaultLogManager(); +function getLogger(name) { + return globalLogManager.getLogger(name); +} +exports.getLogger = getLogger; +function setLogHandler(logger) { + globalLogHandler = logger; +} +exports.setLogHandler = setLogHandler; +function setLogLevel(level) { + level = coerceLogLevel(level); + if (!js_sdk_utils_1.isValidEnum(models_1.LogLevel, level) || level === undefined) { + globalLogLevel = models_1.LogLevel.ERROR; + } + else { + globalLogLevel = level; + } +} +exports.setLogLevel = setLogLevel; +function getLogLevel() { + return globalLogLevel; +} +exports.getLogLevel = getLogLevel; +/** + * Resets all global logger state to it's original + */ +function resetLogger() { + globalLogManager = new DefaultLogManager(); + globalLogLevel = models_1.LogLevel.NOTSET; +} +exports.resetLogger = resetLogger; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 uuid_1 = __webpack_require__(6); +function getTimestamp() { + return new Date().getTime(); +} +exports.getTimestamp = getTimestamp; +function generateUUID() { + return uuid_1.v4(); +} +exports.generateUUID = generateUUID; +/** + * Validates a value is a valid TypeScript enum + * + * @export + * @param {object} enumToCheck + * @param {*} value + * @returns {boolean} + */ +function isValidEnum(enumToCheck, value) { + var found = false; + var keys = Object.keys(enumToCheck); + for (var index = 0; index < keys.length; index++) { + if (value === enumToCheck[keys[index]]) { + found = true; + break; + } + } + return found; +} +exports.isValidEnum = isValidEnum; +function groupBy(arr, grouperFn) { + var grouper = {}; + arr.forEach(function (item) { + var key = grouperFn(item); + grouper[key] = grouper[key] || []; + grouper[key].push(item); + }); + return objectValues(grouper); +} +exports.groupBy = groupBy; +function objectValues(obj) { + return Object.keys(obj).map(function (key) { return obj[key]; }); +} +exports.objectValues = objectValues; +function find(arr, cond) { + var found; + for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { + var item = arr_1[_i]; + if (cond(item)) { + found = item; + break; + } + } + return found; +} +exports.find = find; +function keyBy(arr, keyByFn) { + var map = {}; + arr.forEach(function (item) { + var key = keyByFn(item); + map[key] = item; + }); + return map; +} +exports.keyBy = keyBy; +function sprintf(format) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var i = 0; + return format.replace(/%s/g, function () { + var arg = args[i++]; + var type = typeof arg; + if (type === 'function') { + return arg(); + } + else if (type === 'string') { + return arg; + } + else { + return String(arg); + } + }); +} +exports.sprintf = sprintf; + + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + +var v1 = __webpack_require__(7); +var v4 = __webpack_require__(10); + +var uuid = v4; +uuid.v1 = v1; +uuid.v4 = v4; + +module.exports = uuid; + + +/***/ }), +/* 7 */ +/***/ (function(module, exports, __webpack_require__) { + +var rng = __webpack_require__(8); +var bytesToUuid = __webpack_require__(9); + +// **`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/broofa/node-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; + + +/***/ }), +/* 8 */ +/***/ (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; + }; +} + + +/***/ }), +/* 9 */ +/***/ (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; + + +/***/ }), +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +var rng = __webpack_require__(8); +var bytesToUuid = __webpack_require__(9); + +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; + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2017, 2019-2020, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 uuid = __webpack_require__(6); +var MAX_SAFE_INTEGER_LIMIT = Math.pow(2, 53); +var keyBy = __webpack_require__(12).keyBy; +module.exports = { + assign: function(target) { + if (!target) { + return {}; + } + if (typeof Object.assign === 'function') { + return Object.assign.apply(Object, arguments); + } else { + var to = Object(target); + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + if (nextSource !== null && nextSource !== undefined) { + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + } + }, + currentTimestamp: function() { + return Math.round(new Date().getTime()); + }, + isSafeInteger: function(number) { + return typeof number == 'number' && Math.abs(number) <= MAX_SAFE_INTEGER_LIMIT; + }, + keyBy: function(arr, key) { + if (!arr) return {}; + return keyBy(arr, function(item) { + return item[key]; + }); + }, + uuid: function() { + return uuid.v4(); + }, + isNumber: function(value) { + return typeof value === 'number'; + }, +}; + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 uuid_1 = __webpack_require__(6); +function getTimestamp() { + return new Date().getTime(); +} +exports.getTimestamp = getTimestamp; +function generateUUID() { + return uuid_1.v4(); +} +exports.generateUUID = generateUUID; +/** + * Validates a value is a valid TypeScript enum + * + * @export + * @param {object} enumToCheck + * @param {*} value + * @returns {boolean} + */ +function isValidEnum(enumToCheck, value) { + var found = false; + var keys = Object.keys(enumToCheck); + for (var index = 0; index < keys.length; index++) { + if (value === enumToCheck[keys[index]]) { + found = true; + break; + } + } + return found; +} +exports.isValidEnum = isValidEnum; +function groupBy(arr, grouperFn) { + var grouper = {}; + arr.forEach(function (item) { + var key = grouperFn(item); + grouper[key] = grouper[key] || []; + grouper[key].push(item); + }); + return objectValues(grouper); +} +exports.groupBy = groupBy; +function objectValues(obj) { + return Object.keys(obj).map(function (key) { return obj[key]; }); +} +exports.objectValues = objectValues; +function objectEntries(obj) { + return Object.keys(obj).map(function (key) { return [key, obj[key]]; }); +} +exports.objectEntries = objectEntries; +function find(arr, cond) { + var found; + for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { + var item = arr_1[_i]; + if (cond(item)) { + found = item; + break; + } + } + return found; +} +exports.find = find; +function keyBy(arr, keyByFn) { + var map = {}; + arr.forEach(function (item) { + var key = keyByFn(item); + map[key] = item; + }); + return map; +} +exports.keyBy = keyBy; +function sprintf(format) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var i = 0; + return format.replace(/%s/g, function () { + var arg = args[i++]; + var type = typeof arg; + if (type === 'function') { + return arg(); + } + else if (type === 'string') { + return arg; + } + else { + return String(arg); + } + }); +} +exports.sprintf = sprintf; +/* + * Notification types for use with NotificationCenter + * Format is EVENT: + * + * SDK consumers can use these to register callbacks with the notification center. + * + * @deprecated since 3.1.0 + * ACTIVATE: An impression event will be sent to Optimizely + * Callbacks will receive an object argument with the following properties: + * - experiment {Object} + * - userId {string} + * - attributes {Object|undefined} + * - variation {Object} + * - logEvent {Object} + * + * DECISION: A decision is made in the system. i.e. user activation, + * feature access or feature-variable value retrieval + * Callbacks will receive an object argument with the following properties: + * - type {string} + * - userId {string} + * - attributes {Object|undefined} + * - decisionInfo {Object|undefined} + * + * LOG_EVENT: A batch of events, which could contain impressions and/or conversions, + * will be sent to Optimizely + * Callbacks will receive an object argument with the following properties: + * - url {string} + * - httpVerb {string} + * - params {Object} + * + * OPTIMIZELY_CONFIG_UPDATE: This Optimizely instance has been updated with a new + * config + * + * TRACK: A conversion event will be sent to Optimizely + * Callbacks will receive the an object argument with the following properties: + * - eventKey {string} + * - userId {string} + * - attributes {Object|undefined} + * - eventTags {Object|undefined} + * - logEvent {Object} + * + */ +var NOTIFICATION_TYPES; +(function (NOTIFICATION_TYPES) { + NOTIFICATION_TYPES["ACTIVATE"] = "ACTIVATE:experiment, user_id,attributes, variation, event"; + NOTIFICATION_TYPES["DECISION"] = "DECISION:type, userId, attributes, decisionInfo"; + NOTIFICATION_TYPES["LOG_EVENT"] = "LOG_EVENT:logEvent"; + NOTIFICATION_TYPES["OPTIMIZELY_CONFIG_UPDATE"] = "OPTIMIZELY_CONFIG_UPDATE"; + NOTIFICATION_TYPES["TRACK"] = "TRACK:event_key, user_id, attributes, event_tags, event"; +})(NOTIFICATION_TYPES = exports.NOTIFICATION_TYPES || (exports.NOTIFICATION_TYPES = {})); + + +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016, 2018, 2019 Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 sprintf = __webpack_require__(12).sprintf; + +var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; +var MODULE_NAME = 'CONFIG_VALIDATOR'; +var DATAFILE_VERSIONS = __webpack_require__(14).DATAFILE_VERSIONS; + +var SUPPORTED_VERSIONS = [DATAFILE_VERSIONS.V2, DATAFILE_VERSIONS.V3, DATAFILE_VERSIONS.V4]; + +/** + * Provides utility methods for validating that the configuration options are valid + */ +module.exports = { + /** + * Validates the given config options + * @param {Object} config + * @param {Object} config.errorHandler + * @param {Object} config.eventDispatcher + * @param {Object} config.logger + * @return {Boolean} True if the config options are valid + * @throws If any of the config options are not valid + */ + validate: function(config) { + if (config.errorHandler && typeof config.errorHandler.handleError !== 'function') { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_ERROR_HANDLER, MODULE_NAME)); + } + + if (config.eventDispatcher && typeof config.eventDispatcher.dispatchEvent !== 'function') { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_EVENT_DISPATCHER, MODULE_NAME)); + } + + if (config.logger && typeof config.logger.log !== 'function') { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_LOGGER, MODULE_NAME)); + } + + return true; + }, + + /** + * Validates the datafile + * @param {string} datafile + * @return {Boolean} True if the datafile is valid + * @throws If the datafile is not valid for any of the following reasons: + - The datafile string is undefined + - The datafile string cannot be parsed as a JSON object + - The datafile version is not supported + */ + validateDatafile: function(datafile) { + if (!datafile) { + throw new Error(sprintf(ERROR_MESSAGES.NO_DATAFILE_SPECIFIED, MODULE_NAME)); + } + + if (typeof datafile === 'string' || datafile instanceof String) { + // Attempt to parse the datafile string + try { + datafile = JSON.parse(datafile); + } catch (ex) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_MALFORMED, MODULE_NAME)); + } + } + + if (SUPPORTED_VERSIONS.indexOf(datafile.version) === -1) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_VERSION, MODULE_NAME, datafile.version)); + } + + return true; + }, +}; + + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +/**************************************************************************** + * Copyright 2016-2019, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License 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 jsSdkUtils = __webpack_require__(12); + +/** + * Contains global enums used throughout the library + */ +exports.LOG_LEVEL = { + NOTSET: 0, + DEBUG: 1, + INFO: 2, + WARNING: 3, + ERROR: 4, +}; + +exports.ERROR_MESSAGES = { + CONDITION_EVALUATOR_ERROR: '%s: Error evaluating audience condition of type %s: %s', + DATAFILE_AND_SDK_KEY_MISSING: '%s: You must provide at least one of sdkKey or datafile. Cannot start Optimizely', + EXPERIMENT_KEY_NOT_IN_DATAFILE: '%s: Experiment key %s is not in datafile.', + FEATURE_NOT_IN_DATAFILE: '%s: Feature key %s is not in datafile.', + IMPROPERLY_FORMATTED_EXPERIMENT: '%s: Experiment key %s is improperly formatted.', + INVALID_ATTRIBUTES: '%s: Provided attributes are in an invalid format.', + INVALID_BUCKETING_ID: '%s: Unable to generate hash for bucketing ID %s: %s', + INVALID_DATAFILE: '%s: Datafile is invalid - property %s: %s', + INVALID_DATAFILE_MALFORMED: '%s: Datafile is invalid because it is malformed.', + INVALID_JSON: '%s: JSON object is not valid.', + INVALID_ERROR_HANDLER: '%s: Provided "errorHandler" is in an invalid format.', + INVALID_EVENT_DISPATCHER: '%s: Provided "eventDispatcher" is in an invalid format.', + INVALID_EVENT_TAGS: '%s: Provided event tags are in an invalid format.', + INVALID_EXPERIMENT_KEY: '%s: Experiment key %s is not in datafile. It is either invalid, paused, or archived.', + INVALID_EXPERIMENT_ID: '%s: Experiment ID %s is not in datafile.', + INVALID_GROUP_ID: '%s: Group ID %s is not in datafile.', + INVALID_LOGGER: '%s: Provided "logger" is in an invalid format.', + INVALID_ROLLOUT_ID: '%s: Invalid rollout ID %s attached to feature %s', + INVALID_USER_ID: '%s: Provided user ID is in an invalid format.', + INVALID_USER_PROFILE_SERVICE: '%s: Provided user profile service instance is in an invalid format: %s.', + JSON_SCHEMA_EXPECTED: '%s: JSON schema expected.', + NO_DATAFILE_SPECIFIED: '%s: No datafile specified. Cannot start optimizely.', + NO_JSON_PROVIDED: '%s: No JSON object to validate against schema.', + NO_VARIATION_FOR_EXPERIMENT_KEY: '%s: No variation key %s defined in datafile for experiment %s.', + UNDEFINED_ATTRIBUTE: '%s: Provided attribute: %s has an undefined value.', + UNRECOGNIZED_ATTRIBUTE: '%s: Unrecognized attribute %s provided. Pruning before sending event to Optimizely.', + UNABLE_TO_CAST_VALUE: '%s: Unable to cast value %s to type %s, returning null.', + USER_NOT_IN_FORCED_VARIATION: '%s: User %s is not in the forced variation map. Cannot remove their forced variation.', + USER_PROFILE_LOOKUP_ERROR: '%s: Error while looking up user profile for user ID "%s": %s.', + USER_PROFILE_SAVE_ERROR: '%s: Error while saving user profile for user ID "%s": %s.', + VARIABLE_KEY_NOT_IN_DATAFILE: '%s: Variable with key "%s" associated with feature with key "%s" is not in datafile.', + VARIATION_ID_NOT_IN_DATAFILE: '%s: No variation ID %s defined in datafile for experiment %s.', + VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT: '%s: Variation ID %s is not in the datafile.', + INVALID_INPUT_FORMAT: '%s: Provided %s is in an invalid format.', + INVALID_DATAFILE_VERSION: '%s: This version of the JavaScript SDK does not support the given datafile version: %s', + INVALID_VARIATION_KEY: '%s: Provided variation key is in an invalid format.', +}; + +exports.LOG_MESSAGES = { + ACTIVATE_USER: '%s: Activating user %s in experiment %s.', + DISPATCH_CONVERSION_EVENT: '%s: Dispatching conversion event to URL %s with params %s.', + DISPATCH_IMPRESSION_EVENT: '%s: Dispatching impression event to URL %s with params %s.', + DEPRECATED_EVENT_VALUE: '%s: Event value is deprecated in %s call.', + EVENT_KEY_NOT_FOUND: '%s: Event key %s is not in datafile.', + EXPERIMENT_NOT_RUNNING: '%s: Experiment %s is not running.', + FEATURE_ENABLED_FOR_USER: '%s: Feature %s is enabled for user %s.', + FEATURE_NOT_ENABLED_FOR_USER: '%s: Feature %s is not enabled for user %s.', + FEATURE_HAS_NO_EXPERIMENTS: '%s: Feature %s is not attached to any experiments.', + FAILED_TO_PARSE_VALUE: '%s: Failed to parse event value "%s" from event tags.', + FAILED_TO_PARSE_REVENUE: '%s: Failed to parse revenue value "%s" from event tags.', + FORCED_BUCKETING_FAILED: '%s: Variation key %s is not in datafile. Not activating user %s.', + INVALID_OBJECT: '%s: Optimizely object is not valid. Failing %s.', + INVALID_CLIENT_ENGINE: '%s: Invalid client engine passed: %s. Defaulting to node-sdk.', + INVALID_VARIATION_ID: '%s: Bucketed into an invalid variation ID. Returning null.', + NOTIFICATION_LISTENER_EXCEPTION: '%s: Notification listener for (%s) threw exception: %s', + NO_ROLLOUT_EXISTS: '%s: There is no rollout of feature %s.', + NOT_ACTIVATING_USER: '%s: Not activating user %s for experiment %s.', + NOT_TRACKING_USER: '%s: Not tracking user %s.', + PARSED_REVENUE_VALUE: '%s: Parsed revenue value "%s" from event tags.', + PARSED_NUMERIC_VALUE: '%s: Parsed event value "%s" from event tags.', + RETURNING_STORED_VARIATION: + '%s: Returning previously activated variation "%s" of experiment "%s" for user "%s" from user profile.', + ROLLOUT_HAS_NO_EXPERIMENTS: '%s: Rollout of feature %s has no experiments', + SAVED_VARIATION: '%s: Saved variation "%s" of experiment "%s" for user "%s".', + SAVED_VARIATION_NOT_FOUND: + '%s: User %s was previously bucketed into variation with ID %s for experiment %s, but no matching variation was found.', + SHOULD_NOT_DISPATCH_ACTIVATE: '%s: Experiment %s is not in "Running" state. Not activating user.', + SKIPPING_JSON_VALIDATION: '%s: Skipping JSON schema validation.', + TRACK_EVENT: '%s: Tracking event %s for user %s.', + USER_ASSIGNED_TO_VARIATION_BUCKET: '%s: Assigned variation bucket %s to user %s.', + USER_ASSIGNED_TO_EXPERIMENT_BUCKET: '%s: Assigned experiment bucket %s to user %s.', + USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP: '%s: User %s is in experiment %s of group %s.', + USER_BUCKETED_INTO_TARGETING_RULE: '%s: User %s bucketed into targeting rule %s.', + USER_IN_FEATURE_EXPERIMENT: '%s: User %s is in variation %s of experiment %s on the feature %s.', + USER_IN_ROLLOUT: '%s: User %s is in rollout of feature %s.', + USER_BUCKETED_INTO_EVERYONE_TARGETING_RULE: '%s: User %s bucketed into everyone targeting rule.', + USER_NOT_BUCKETED_INTO_EVERYONE_TARGETING_RULE: + '%s: User %s not bucketed into everyone targeting rule due to traffic allocation.', + USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP: '%s: User %s is not in experiment %s of group %s.', + USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP: '%s: User %s is not in any experiment of group %s.', + USER_NOT_BUCKETED_INTO_TARGETING_RULE: + '%s User %s not bucketed into targeting rule %s due to traffic allocation. Trying everyone rule.', + USER_NOT_IN_FEATURE_EXPERIMENT: '%s: User %s is not in any experiment on the feature %s.', + USER_NOT_IN_ROLLOUT: '%s: User %s is not in rollout of feature %s.', + USER_FORCED_IN_VARIATION: '%s: User %s is forced in variation %s.', + USER_MAPPED_TO_FORCED_VARIATION: '%s: Set variation %s for experiment %s and user %s in the forced variation map.', + USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE: '%s: User %s does not meet conditions for targeting rule %s.', + USER_MEETS_CONDITIONS_FOR_TARGETING_RULE: '%s: User %s meets conditions for targeting rule %s.', + USER_HAS_VARIATION: '%s: User %s is in variation %s of experiment %s.', + USER_HAS_FORCED_VARIATION: '%s: Variation %s is mapped to experiment %s and user %s in the forced variation map.', + USER_HAS_NO_VARIATION: '%s: User %s is in no variation of experiment %s.', + USER_HAS_NO_FORCED_VARIATION: '%s: User %s is not in the forced variation map.', + USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT: '%s: No experiment %s mapped to user %s in the forced variation map.', + USER_NOT_IN_ANY_EXPERIMENT: '%s: User %s is not in any experiment of group %s.', + USER_NOT_IN_EXPERIMENT: '%s: User %s does not meet conditions to be in experiment %s.', + USER_RECEIVED_DEFAULT_VARIABLE_VALUE: + '%s: User "%s" is not in any variation or rollout rule. Returning default value for variable "%s" of feature flag "%s".', + FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE: + '%s: Feature "%s" is not enabled for user %s. Returning default value for variable "%s".', + VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE: + '%s: Variable "%s" is not used in variation "%s". Returning default value.', + USER_RECEIVED_VARIABLE_VALUE: '%s: Value for variable "%s" of feature flag "%s" is %s for user "%s"', + VALID_DATAFILE: '%s: Datafile is valid.', + VALID_USER_PROFILE_SERVICE: '%s: Valid user profile service provided.', + VARIATION_REMOVED_FOR_USER: '%s: Variation mapped to experiment %s has been removed for user %s.', + VARIABLE_REQUESTED_WITH_WRONG_TYPE: + '%s: Requested variable type "%s", but variable is of type "%s". Use correct API to retrieve value. Returning None.', + VALID_BUCKETING_ID: '%s: BucketingId is valid: "%s"', + BUCKETING_ID_NOT_STRING: '%s: BucketingID attribute is not a string. Defaulted to userId', + EVALUATING_AUDIENCE: '%s: Starting to evaluate audience "%s" with conditions: %s.', + EVALUATING_AUDIENCES_COMBINED: '%s: Evaluating audiences for experiment "%s": %s.', + AUDIENCE_EVALUATION_RESULT: '%s: Audience "%s" evaluated to %s.', + AUDIENCE_EVALUATION_RESULT_COMBINED: '%s: Audiences for experiment %s collectively evaluated to %s.', + MISSING_ATTRIBUTE_VALUE: + '%s: Audience condition %s evaluated to UNKNOWN because no value was passed for user attribute "%s".', + UNEXPECTED_CONDITION_VALUE: + '%s: Audience condition %s evaluated to UNKNOWN because the condition value is not supported.', + UNEXPECTED_TYPE: + '%s: Audience condition %s evaluated to UNKNOWN because a value of type "%s" was passed for user attribute "%s".', + UNEXPECTED_TYPE_NULL: + '%s: Audience condition %s evaluated to UNKNOWN because a null value was passed for user attribute "%s".', + UNKNOWN_CONDITION_TYPE: + '%s: Audience condition %s has an unknown condition type. You may need to upgrade to a newer release of the Optimizely SDK.', + UNKNOWN_MATCH_TYPE: + '%s: Audience condition %s uses an unknown match type. You may need to upgrade to a newer release of the Optimizely SDK.', + UPDATED_OPTIMIZELY_CONFIG: '%s: Updated Optimizely config to revision %s (project id %s)', + OUT_OF_BOUNDS: + '%s: Audience condition %s evaluated to UNKNOWN because the number value for user attribute "%s" is not in the range [-2^53, +2^53].', + UNABLE_TO_ATTACH_UNLOAD: '%s: unable to bind optimizely.close() to page unload event: "%s"', +}; + +exports.RESERVED_EVENT_KEYWORDS = { + REVENUE: 'revenue', + VALUE: 'value', +}; + +exports.CONTROL_ATTRIBUTES = { + BOT_FILTERING: '$opt_bot_filtering', + BUCKETING_ID: '$opt_bucketing_id', + STICKY_BUCKETING_KEY: '$opt_experiment_bucket_map', + USER_AGENT: '$opt_user_agent', +}; + +exports.JAVASCRIPT_CLIENT_ENGINE = 'javascript-sdk'; +exports.NODE_CLIENT_ENGINE = 'node-sdk'; +exports.REACT_CLIENT_ENGINE = 'react-sdk'; +exports.NODE_CLIENT_VERSION = '3.6.0-alpha.1'; + +exports.VALID_CLIENT_ENGINES = [ + exports.NODE_CLIENT_ENGINE, + exports.REACT_CLIENT_ENGINE, + exports.JAVASCRIPT_CLIENT_ENGINE, +]; + +exports.NOTIFICATION_TYPES = jsSdkUtils.NOTIFICATION_TYPES; + +exports.DECISION_NOTIFICATION_TYPES = { + AB_TEST: 'ab-test', + FEATURE: 'feature', + FEATURE_TEST: 'feature-test', + FEATURE_VARIABLE: 'feature-variable', +}; + +/* + * Represents the source of a decision for feature management. When a feature + * is accessed through isFeatureEnabled or getVariableValue APIs, the decision + * source is used to decide whether to dispatch an impression event to + * Optimizely. + */ +exports.DECISION_SOURCES = { + FEATURE_TEST: 'feature-test', + ROLLOUT: 'rollout', +}; + +/* + * Possible types of variables attached to features + */ +exports.FEATURE_VARIABLE_TYPES = { + BOOLEAN: 'boolean', + DOUBLE: 'double', + INTEGER: 'integer', + STRING: 'string', +}; + +/* + * Supported datafile versions + */ +exports.DATAFILE_VERSIONS = { + V2: '2', + V3: '3', + V4: '4', +}; + + +/***/ }), +/* 15 */ +/***/ (function(module, exports) { + +/** + * Copyright 2016, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ + +/** + * Default error handler implementation + */ +module.exports = { + /** + * Handle given exception + * @param {Object} exception An exception object + */ + handleError: function() { + // no-op + }, +}; + + +/***/ }), +/* 16 */ +/***/ (function(module, exports) { + +/** + * Copyright 2016-2017, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 POST_METHOD = 'POST'; +var GET_METHOD = 'GET'; +var READYSTATE_COMPLETE = 4; + +module.exports = { + /** + * Sample event dispatcher implementation for tracking impression and conversions + * Users of the SDK can provide their own implementation + * @param {Object} eventObj + * @param {Function} callback + */ + dispatchEvent: function(eventObj, callback) { + var url = eventObj.url; + var params = eventObj.params; + var req; + if (eventObj.httpVerb === POST_METHOD) { + req = new XMLHttpRequest(); + req.open(POST_METHOD, url, true); + req.setRequestHeader('Content-Type', 'application/json'); + req.onreadystatechange = function() { + if (req.readyState === READYSTATE_COMPLETE && callback && typeof callback === 'function') { + try { + callback(params); + } catch (e) { + // TODO: Log this somehow (consider adding a logger to the EventDispatcher interface) + } + } + }; + req.send(JSON.stringify(params)); + } else { + // add param for cors headers to be sent by the log endpoint + url += '?wxhr=true'; + if (params) { + url += '&' + toQueryString(params); + } + + req = new XMLHttpRequest(); + req.open(GET_METHOD, url, true); + req.onreadystatechange = function() { + if (req.readyState === READYSTATE_COMPLETE && callback && typeof callback === 'function') { + try { + callback(); + } catch (e) { + // TODO: Log this somehow (consider adding a logger to the EventDispatcher interface) + } + } + }; + req.send(); + } + }, +}; + +var toQueryString = function(obj) { + return Object.keys(obj) + .map(function(k) { + return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]); + }) + .join('&'); +}; + + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +function __export(m) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +__export(__webpack_require__(18)); +__export(__webpack_require__(19)); +__export(__webpack_require__(22)); +__export(__webpack_require__(24)); +__export(__webpack_require__(25)); + + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +function areEventContextsEqual(eventA, eventB) { + var contextA = eventA.context; + var contextB = eventB.context; + return (contextA.accountId === contextB.accountId && + contextA.projectId === contextB.projectId && + contextA.clientName === contextB.clientName && + contextA.clientVersion === contextB.clientVersion && + contextA.revision === contextB.revision && + contextA.anonymizeIP === contextB.anonymizeIP && + contextA.botFiltering === contextB.botFiltering); +} +exports.areEventContextsEqual = areEventContextsEqual; + + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var events_1 = __webpack_require__(18); +var eventQueue_1 = __webpack_require__(20); +var js_sdk_logging_1 = __webpack_require__(1); +var js_sdk_utils_1 = __webpack_require__(12); +var requestTracker_1 = __importDefault(__webpack_require__(21)); +var logger = js_sdk_logging_1.getLogger('EventProcessor'); +var DEFAULT_FLUSH_INTERVAL = 30000; // Unit is ms - default flush interval is 30s +var DEFAULT_MAX_QUEUE_SIZE = 10; +var AbstractEventProcessor = /** @class */ (function () { + function AbstractEventProcessor(_a) { + var dispatcher = _a.dispatcher, _b = _a.flushInterval, flushInterval = _b === void 0 ? 30000 : _b, _c = _a.maxQueueSize, maxQueueSize = _c === void 0 ? 3000 : _c, notificationCenter = _a.notificationCenter; + var _this = this; + this.dispatcher = dispatcher; + if (flushInterval <= 0) { + logger.warn("Invalid flushInterval " + flushInterval + ", defaulting to " + DEFAULT_FLUSH_INTERVAL); + flushInterval = DEFAULT_FLUSH_INTERVAL; + } + maxQueueSize = Math.floor(maxQueueSize); + if (maxQueueSize < 1) { + logger.warn("Invalid maxQueueSize " + maxQueueSize + ", defaulting to " + DEFAULT_MAX_QUEUE_SIZE); + maxQueueSize = DEFAULT_MAX_QUEUE_SIZE; + } + maxQueueSize = Math.max(1, maxQueueSize); + if (maxQueueSize > 1) { + this.queue = new eventQueue_1.DefaultEventQueue({ + flushInterval: flushInterval, + maxQueueSize: maxQueueSize, + sink: function (buffer) { return _this.drainQueue(buffer); }, + batchComparator: events_1.areEventContextsEqual, + }); + } + else { + this.queue = new eventQueue_1.SingleEventQueue({ + sink: function (buffer) { return _this.drainQueue(buffer); }, + }); + } + this.notificationCenter = notificationCenter; + this.requestTracker = new requestTracker_1.default(); + } + AbstractEventProcessor.prototype.drainQueue = function (buffer) { + var _this = this; + var reqPromise = new Promise(function (resolve) { + logger.debug('draining queue with %s events', buffer.length); + if (buffer.length === 0) { + resolve(); + return; + } + var formattedEvent = _this.formatEvents(buffer); + _this.dispatcher.dispatchEvent(formattedEvent, function () { + resolve(); + }); + if (_this.notificationCenter) { + _this.notificationCenter.sendNotifications(js_sdk_utils_1.NOTIFICATION_TYPES.LOG_EVENT, formattedEvent); + } + }); + this.requestTracker.trackRequest(reqPromise); + return reqPromise; + }; + AbstractEventProcessor.prototype.process = function (event) { + this.queue.enqueue(event); + }; + AbstractEventProcessor.prototype.stop = function () { + // swallow - an error stopping this queue shouldn't prevent this from stopping + try { + this.queue.stop(); + return this.requestTracker.onRequestsComplete(); + } + catch (e) { + logger.error('Error stopping EventProcessor: "%s"', e.message, e); + } + return Promise.resolve(); + }; + AbstractEventProcessor.prototype.start = function () { + this.queue.start(); + }; + return AbstractEventProcessor; +}()); +exports.AbstractEventProcessor = AbstractEventProcessor; + + +/***/ }), +/* 20 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var js_sdk_logging_1 = __webpack_require__(1); +var logger = js_sdk_logging_1.getLogger('EventProcessor'); +var Timer = /** @class */ (function () { + function Timer(_a) { + var timeout = _a.timeout, callback = _a.callback; + this.timeout = Math.max(timeout, 0); + this.callback = callback; + } + Timer.prototype.start = function () { + this.timeoutId = setTimeout(this.callback, this.timeout); + }; + Timer.prototype.refresh = function () { + this.stop(); + this.start(); + }; + Timer.prototype.stop = function () { + if (this.timeoutId) { + clearTimeout(this.timeoutId); + } + }; + return Timer; +}()); +var SingleEventQueue = /** @class */ (function () { + function SingleEventQueue(_a) { + var sink = _a.sink; + this.sink = sink; + } + SingleEventQueue.prototype.start = function () { + // no-op + }; + SingleEventQueue.prototype.stop = function () { + // no-op + return Promise.resolve(); + }; + SingleEventQueue.prototype.enqueue = function (event) { + this.sink([event]); + }; + return SingleEventQueue; +}()); +exports.SingleEventQueue = SingleEventQueue; +var DefaultEventQueue = /** @class */ (function () { + function DefaultEventQueue(_a) { + var flushInterval = _a.flushInterval, maxQueueSize = _a.maxQueueSize, sink = _a.sink, batchComparator = _a.batchComparator; + this.buffer = []; + this.maxQueueSize = Math.max(maxQueueSize, 1); + this.sink = sink; + this.batchComparator = batchComparator; + this.timer = new Timer({ + callback: this.flush.bind(this), + timeout: flushInterval, + }); + this.started = false; + } + DefaultEventQueue.prototype.start = function () { + this.started = true; + // dont start the timer until the first event is enqueued + }; + DefaultEventQueue.prototype.stop = function () { + this.started = false; + var result = this.sink(this.buffer); + this.buffer = []; + this.timer.stop(); + return result; + }; + DefaultEventQueue.prototype.enqueue = function (event) { + if (!this.started) { + logger.warn('Queue is stopped, not accepting event'); + return; + } + // If new event cannot be included into the current batch, flush so it can + // be in its own new batch. + var bufferedEvent = this.buffer[0]; + if (bufferedEvent && !this.batchComparator(bufferedEvent, event)) { + this.flush(); + } + // start the timer when the first event is put in + if (this.buffer.length === 0) { + this.timer.refresh(); + } + this.buffer.push(event); + if (this.buffer.length >= this.maxQueueSize) { + this.flush(); + } + }; + DefaultEventQueue.prototype.flush = function () { + this.sink(this.buffer); + this.buffer = []; + this.timer.stop(); + }; + return DefaultEventQueue; +}()); +exports.DefaultEventQueue = DefaultEventQueue; + + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2020, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * RequestTracker keeps track of in-flight requests for EventProcessor using + * an internal counter. It exposes methods for adding a new request to be + * tracked, and getting a Promise representing the completion of currently + * tracked requests. + */ +var RequestTracker = /** @class */ (function () { + function RequestTracker() { + this.reqsInFlightCount = 0; + this.reqsCompleteResolvers = []; + } + /** + * Track the argument request (represented by a Promise). reqPromise will feed + * into the state of Promises returned by onRequestsComplete. + * @param {Promise} reqPromise + */ + RequestTracker.prototype.trackRequest = function (reqPromise) { + var _this = this; + this.reqsInFlightCount++; + var onReqComplete = function () { + _this.reqsInFlightCount--; + if (_this.reqsInFlightCount === 0) { + _this.reqsCompleteResolvers.forEach(function (resolver) { return resolver(); }); + _this.reqsCompleteResolvers = []; + } + }; + reqPromise.then(onReqComplete, onReqComplete); + }; + /** + * Return a Promise that fulfills after all currently-tracked request promises + * are resolved. + * @return {Promise} + */ + RequestTracker.prototype.onRequestsComplete = function () { + var _this = this; + return new Promise(function (resolve) { + if (_this.reqsInFlightCount === 0) { + resolve(); + } + else { + _this.reqsCompleteResolvers.push(resolve); + } + }); + }; + return RequestTracker; +}()); +exports.default = RequestTracker; + + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (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 __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 js_sdk_logging_1 = __webpack_require__(1); +var pendingEventsStore_1 = __webpack_require__(23); +var js_sdk_utils_1 = __webpack_require__(12); +var logger = js_sdk_logging_1.getLogger('EventProcessor'); +var PendingEventsDispatcher = /** @class */ (function () { + function PendingEventsDispatcher(_a) { + var eventDispatcher = _a.eventDispatcher, store = _a.store; + this.dispatcher = eventDispatcher; + this.store = store; + } + PendingEventsDispatcher.prototype.dispatchEvent = function (request, callback) { + this.send({ + uuid: js_sdk_utils_1.generateUUID(), + timestamp: js_sdk_utils_1.getTimestamp(), + request: request, + }, callback); + }; + PendingEventsDispatcher.prototype.sendPendingEvents = function () { + var _this = this; + var pendingEvents = this.store.values(); + logger.debug('Sending %s pending events from previous page', pendingEvents.length); + pendingEvents.forEach(function (item) { + try { + _this.send(item, function () { }); + } + catch (e) { } + }); + }; + PendingEventsDispatcher.prototype.send = function (entry, callback) { + var _this = this; + this.store.set(entry.uuid, entry); + this.dispatcher.dispatchEvent(entry.request, function (response) { + _this.store.remove(entry.uuid); + callback(response); + }); + }; + return PendingEventsDispatcher; +}()); +exports.PendingEventsDispatcher = PendingEventsDispatcher; +var LocalStoragePendingEventsDispatcher = /** @class */ (function (_super) { + __extends(LocalStoragePendingEventsDispatcher, _super); + function LocalStoragePendingEventsDispatcher(_a) { + var eventDispatcher = _a.eventDispatcher; + return _super.call(this, { + eventDispatcher: eventDispatcher, + store: new pendingEventsStore_1.LocalStorageStore({ + // TODO make this configurable + maxValues: 100, + key: 'fs_optly_pending_events', + }), + }) || this; + } + return LocalStoragePendingEventsDispatcher; +}(PendingEventsDispatcher)); +exports.LocalStoragePendingEventsDispatcher = LocalStoragePendingEventsDispatcher; + + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 js_sdk_utils_1 = __webpack_require__(12); +var js_sdk_logging_1 = __webpack_require__(1); +var logger = js_sdk_logging_1.getLogger('EventProcessor'); +var LocalStorageStore = /** @class */ (function () { + function LocalStorageStore(_a) { + var key = _a.key, _b = _a.maxValues, maxValues = _b === void 0 ? 1000 : _b; + this.LS_KEY = key; + this.maxValues = maxValues; + } + LocalStorageStore.prototype.get = function (key) { + return this.getMap()[key] || null; + }; + LocalStorageStore.prototype.set = function (key, value) { + var map = this.getMap(); + map[key] = value; + this.replace(map); + }; + LocalStorageStore.prototype.remove = function (key) { + var map = this.getMap(); + delete map[key]; + this.replace(map); + }; + LocalStorageStore.prototype.values = function () { + return js_sdk_utils_1.objectValues(this.getMap()); + }; + LocalStorageStore.prototype.clear = function () { + this.replace({}); + }; + LocalStorageStore.prototype.replace = function (map) { + try { + // This is a temporary fix to support React Native which does not have localStorage. + window.localStorage && localStorage.setItem(this.LS_KEY, JSON.stringify(map)); + this.clean(); + } + catch (e) { + logger.error(e); + } + }; + LocalStorageStore.prototype.clean = function () { + var map = this.getMap(); + var keys = Object.keys(map); + var toRemove = keys.length - this.maxValues; + if (toRemove < 1) { + return; + } + var entries = keys.map(function (key) { return ({ + key: key, + value: map[key] + }); }); + entries.sort(function (a, b) { return a.value.timestamp - b.value.timestamp; }); + for (var i = 0; i < toRemove; i++) { + delete map[entries[i].key]; + } + this.replace(map); + }; + LocalStorageStore.prototype.getMap = function () { + try { + // This is a temporary fix to support React Native which does not have localStorage. + var data = window.localStorage && localStorage.getItem(this.LS_KEY); + if (data) { + return JSON.parse(data) || {}; + } + } + catch (e) { + logger.error(e); + } + return {}; + }; + return LocalStorageStore; +}()); +exports.LocalStorageStore = LocalStorageStore; + + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +var __assign = (this && this.__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); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var ACTIVATE_EVENT_KEY = 'campaign_activated'; +var CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom'; +var BOT_FILTERING_KEY = '$opt_bot_filtering'; +/** + * Given an array of batchable Decision or ConversionEvent events it returns + * a single EventV1 with proper batching + * + * @param {ProcessableEvents[]} events + * @returns {EventV1} + */ +function makeBatchedEventV1(events) { + var visitors = []; + var data = events[0]; + events.forEach(function (event) { + if (event.type === 'conversion' || event.type === 'impression') { + var visitor = makeVisitor(event); + if (event.type === 'impression') { + visitor.snapshots.push(makeDecisionSnapshot(event)); + } + else if (event.type === 'conversion') { + visitor.snapshots.push(makeConversionSnapshot(event)); + } + visitors.push(visitor); + } + }); + return { + client_name: data.context.clientName, + client_version: data.context.clientVersion, + account_id: data.context.accountId, + project_id: data.context.projectId, + revision: data.context.revision, + anonymize_ip: data.context.anonymizeIP, + enrich_decisions: true, + visitors: visitors, + }; +} +exports.makeBatchedEventV1 = makeBatchedEventV1; +function makeConversionSnapshot(conversion) { + var tags = __assign({}, conversion.tags); + delete tags['revenue']; + delete tags['value']; + var event = { + entity_id: conversion.event.id, + key: conversion.event.key, + timestamp: conversion.timestamp, + uuid: conversion.uuid, + }; + if (conversion.tags) { + event.tags = conversion.tags; + } + if (conversion.value != null) { + event.value = conversion.value; + } + if (conversion.revenue != null) { + event.revenue = conversion.revenue; + } + return { + events: [event], + }; +} +function makeDecisionSnapshot(event) { + var layer = event.layer, experiment = event.experiment, variation = event.variation; + var layerId = layer ? layer.id : null; + var experimentId = experiment ? experiment.id : null; + var variationId = variation ? variation.id : null; + return { + decisions: [ + { + campaign_id: layerId, + experiment_id: experimentId, + variation_id: variationId, + }, + ], + events: [ + { + entity_id: layerId, + timestamp: event.timestamp, + key: ACTIVATE_EVENT_KEY, + uuid: event.uuid, + }, + ], + }; +} +function makeVisitor(data) { + var visitor = { + snapshots: [], + visitor_id: data.user.id, + attributes: [], + }; + data.user.attributes.forEach(function (attr) { + visitor.attributes.push({ + entity_id: attr.entityId, + key: attr.key, + type: 'custom', + value: attr.value, + }); + }); + if (typeof data.context.botFiltering === 'boolean') { + visitor.attributes.push({ + entity_id: BOT_FILTERING_KEY, + key: BOT_FILTERING_KEY, + type: CUSTOM_ATTRIBUTE_FEATURE_TYPE, + value: data.context.botFiltering, + }); + } + return visitor; +} +/** + * Event for usage with v1 logtier + * + * @export + * @interface EventBuilderV1 + */ +function buildImpressionEventV1(data) { + var visitor = makeVisitor(data); + visitor.snapshots.push(makeDecisionSnapshot(data)); + return { + client_name: data.context.clientName, + client_version: data.context.clientVersion, + account_id: data.context.accountId, + project_id: data.context.projectId, + revision: data.context.revision, + anonymize_ip: data.context.anonymizeIP, + enrich_decisions: true, + visitors: [visitor], + }; +} +exports.buildImpressionEventV1 = buildImpressionEventV1; +function buildConversionEventV1(data) { + var visitor = makeVisitor(data); + visitor.snapshots.push(makeConversionSnapshot(data)); + return { + client_name: data.context.clientName, + client_version: data.context.clientVersion, + account_id: data.context.accountId, + project_id: data.context.projectId, + revision: data.context.revision, + anonymize_ip: data.context.anonymizeIP, + enrich_decisions: true, + visitors: [visitor], + }; +} +exports.buildConversionEventV1 = buildConversionEventV1; + + +/***/ }), +/* 25 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 __extends = (this && this.__extends) || (function () { + var extendStatics = function (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 __()); + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +var eventProcessor_1 = __webpack_require__(19); +var buildEventV1_1 = __webpack_require__(24); +var LogTierV1EventProcessor = /** @class */ (function (_super) { + __extends(LogTierV1EventProcessor, _super); + function LogTierV1EventProcessor() { + return _super !== null && _super.apply(this, arguments) || this; + } + LogTierV1EventProcessor.prototype.formatEvents = function (events) { + return { + url: 'https://logx.optimizely.com/v1/events', + httpVerb: 'POST', + params: buildEventV1_1.makeBatchedEventV1(events), + }; + }; + return LogTierV1EventProcessor; +}(eventProcessor_1.AbstractEventProcessor)); +exports.LogTierV1EventProcessor = LogTierV1EventProcessor; + + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016-2017, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 logging = __webpack_require__(1); + +function NoOpLogger() {} + +NoOpLogger.prototype.log = function() {}; + +module.exports = { + createLogger: function(opts) { + return new logging.ConsoleLogHandler(opts); + }, + + createNoOpLogger: function() { + return new NoOpLogger(); + }, +}; + + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + +/**************************************************************************** + * Copyright 2016-2019, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License 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 fns = __webpack_require__(11); +var attributesValidator = __webpack_require__(28); +var decisionService = __webpack_require__(29); +var enums = __webpack_require__(14); +var eventBuilder = __webpack_require__(38); +var eventHelpers = __webpack_require__(40); +var eventProcessor = __webpack_require__(17); +var eventTagsValidator = __webpack_require__(41); +var notificationCenter = __webpack_require__(42); +var projectConfig = __webpack_require__(35); +var jsSdkUtils = __webpack_require__(12); +var userProfileServiceValidator = __webpack_require__(43); +var stringValidator = __webpack_require__(37); +var projectConfigManager = __webpack_require__(44); + +var ERROR_MESSAGES = enums.ERROR_MESSAGES; +var LOG_LEVEL = enums.LOG_LEVEL; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var MODULE_NAME = 'OPTIMIZELY'; +var DECISION_SOURCES = enums.DECISION_SOURCES; +var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES; +var DECISION_NOTIFICATION_TYPES = enums.DECISION_NOTIFICATION_TYPES; +var NOTIFICATION_TYPES = enums.NOTIFICATION_TYPES; + +var DEFAULT_ONREADY_TIMEOUT = 30000; + +/** + * The Optimizely class + * @param {Object} config + * @param {string} config.clientEngine + * @param {string} config.clientVersion + * @param {Object} config.datafile + * @param {Object} config.errorHandler + * @param {Object} config.eventDispatcher + * @param {Object} config.logger + * @param {Object} config.skipJSONValidation + * @param {Object} config.userProfileService + * @param {Object} config.eventBatchSize + * @param {Object} config.eventFlushInterval + */ +function Optimizely(config) { + var clientEngine = config.clientEngine; + if (enums.VALID_CLIENT_ENGINES.indexOf(clientEngine) === -1) { + config.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_CLIENT_ENGINE, MODULE_NAME, clientEngine) + ); + clientEngine = enums.NODE_CLIENT_ENGINE; + } + + this.clientEngine = clientEngine; + this.clientVersion = config.clientVersion || enums.NODE_CLIENT_VERSION; + this.errorHandler = config.errorHandler; + this.eventDispatcher = config.eventDispatcher; + this.__isOptimizelyConfigValid = config.isValidInstance; + this.logger = config.logger; + + this.projectConfigManager = new projectConfigManager.ProjectConfigManager({ + datafile: config.datafile, + datafileOptions: config.datafileOptions, + jsonSchemaValidator: config.jsonSchemaValidator, + sdkKey: config.sdkKey, + skipJSONValidation: config.skipJSONValidation, + }); + + this.__disposeOnUpdate = this.projectConfigManager.onUpdate( + function(configObj) { + this.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf(LOG_MESSAGES.UPDATED_OPTIMIZELY_CONFIG, MODULE_NAME, configObj.revision, configObj.projectId) + ); + this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.OPTIMIZELY_CONFIG_UPDATE); + }.bind(this) + ); + + this.__readyPromise = this.projectConfigManager.onReady(); + + var userProfileService = null; + if (config.userProfileService) { + try { + if (userProfileServiceValidator.validate(config.userProfileService)) { + userProfileService = config.userProfileService; + this.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.VALID_USER_PROFILE_SERVICE, MODULE_NAME)); + } + } catch (ex) { + this.logger.log(LOG_LEVEL.WARNING, ex.message); + } + } + + this.decisionService = decisionService.createDecisionService({ + userProfileService: userProfileService, + logger: this.logger, + UNSTABLE_conditionEvaluators: config.UNSTABLE_conditionEvaluators, + }); + + this.notificationCenter = notificationCenter.createNotificationCenter({ + logger: this.logger, + errorHandler: this.errorHandler, + }); + + this.eventProcessor = new eventProcessor.LogTierV1EventProcessor({ + dispatcher: this.eventDispatcher, + flushInterval: config.eventFlushInterval, + maxQueueSize: config.eventBatchSize, + notificationCenter: this.notificationCenter, + }); + this.eventProcessor.start(); + + this.__readyTimeouts = {}; + this.__nextReadyTimeoutId = 0; +} + +/** + * Returns a truthy value if this instance currently has a valid project config + * object, and the initial configuration object that was passed into the + * constructor was also valid. + * @return {*} + */ +Optimizely.prototype.__isValidInstance = function() { + return this.__isOptimizelyConfigValid && this.projectConfigManager.getConfig(); +}; + +/** + * Buckets visitor and sends impression event to Optimizely. + * @param {string} experimentKey + * @param {string} userId + * @param {Object} attributes + * @return {string|null} variation key + */ +Optimizely.prototype.activate = function(experimentKey, userId, attributes) { + try { + if (!this.__isValidInstance()) { + this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'activate')); + return null; + } + + if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId }, attributes)) { + return this.__notActivatingExperiment(experimentKey, userId); + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return null; + } + + try { + var variationKey = this.getVariation(experimentKey, userId, attributes); + if (variationKey === null) { + return this.__notActivatingExperiment(experimentKey, userId); + } + + // If experiment is not set to 'Running' status, log accordingly and return variation key + if (!projectConfig.isRunning(configObj, experimentKey)) { + var shouldNotDispatchActivateLogMessage = jsSdkUtils.sprintf( + LOG_MESSAGES.SHOULD_NOT_DISPATCH_ACTIVATE, + MODULE_NAME, + experimentKey + ); + this.logger.log(LOG_LEVEL.DEBUG, shouldNotDispatchActivateLogMessage); + return variationKey; + } + + this._sendImpressionEvent(experimentKey, variationKey, userId, attributes); + + return variationKey; + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + var failedActivationLogMessage = jsSdkUtils.sprintf( + LOG_MESSAGES.NOT_ACTIVATING_USER, + MODULE_NAME, + userId, + experimentKey + ); + this.logger.log(LOG_LEVEL.INFO, failedActivationLogMessage); + this.errorHandler.handleError(ex); + return null; + } + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Create an impression event and call the event dispatcher's dispatch method to + * send this event to Optimizely. Then use the notification center to trigger + * any notification listeners for the ACTIVATE notification type. + * @param {string} experimentKey Key of experiment that was activated + * @param {string} variationKey Key of variation shown in experiment that was activated + * @param {string} userId ID of user to whom the variation was shown + * @param {Object} attributes Optional user attributes + */ +Optimizely.prototype._sendImpressionEvent = function(experimentKey, variationKey, userId, attributes) { + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return; + } + + var impressionEvent = eventHelpers.buildImpressionEvent({ + experimentKey: experimentKey, + variationKey: variationKey, + userId: userId, + userAttributes: attributes, + clientEngine: this.clientEngine, + clientVersion: this.clientVersion, + configObj: configObj, + }); + // TODO is it okay to not pass a projectConfig as second argument + this.eventProcessor.process(impressionEvent); + this.__emitNotificationCenterActivate(experimentKey, variationKey, userId, attributes); +}; + +/** + * Emit the ACTIVATE notification on the notificationCenter + * @param {string} experimentKey Key of experiment that was activated + * @param {string} variationKey Key of variation shown in experiment that was activated + * @param {string} userId ID of user to whom the variation was shown + * @param {Object} attributes Optional user attributes + */ +Optimizely.prototype.__emitNotificationCenterActivate = function(experimentKey, variationKey, userId, attributes) { + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return; + } + + var variationId = projectConfig.getVariationIdFromExperimentAndVariationKey(configObj, experimentKey, variationKey); + var experimentId = projectConfig.getExperimentId(configObj, experimentKey); + var impressionEventOptions = { + attributes: attributes, + clientEngine: this.clientEngine, + clientVersion: this.clientVersion, + configObj: configObj, + experimentId: experimentId, + userId: userId, + variationId: variationId, + logger: this.logger, + }; + var impressionEvent = eventBuilder.getImpressionEvent(impressionEventOptions); + var experiment = configObj.experimentKeyMap[experimentKey]; + var variation; + if (experiment && experiment.variationKeyMap) { + variation = experiment.variationKeyMap[variationKey]; + } + this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.ACTIVATE, { + experiment: experiment, + userId: userId, + attributes: attributes, + variation: variation, + logEvent: impressionEvent, + }); +}; + +/** + * Sends conversion event to Optimizely. + * @param {string} eventKey + * @param {string} userId + * @param {string} attributes + * @param {Object} eventTags Values associated with the event. + */ +Optimizely.prototype.track = function(eventKey, userId, attributes, eventTags) { + try { + if (!this.__isValidInstance()) { + this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'track')); + return; + } + + if (!this.__validateInputs({ user_id: userId, event_key: eventKey }, attributes, eventTags)) { + return; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return; + } + + if (!projectConfig.eventWithKeyExists(configObj, eventKey)) { + this.logger.log( + LOG_LEVEL.WARNING, + jsSdkUtils.sprintf(enums.LOG_MESSAGES.EVENT_KEY_NOT_FOUND, MODULE_NAME, eventKey) + ); + this.logger.log(LOG_LEVEL.WARNING, jsSdkUtils.sprintf(LOG_MESSAGES.NOT_TRACKING_USER, MODULE_NAME, userId)); + return; + } + + // remove null values from eventTags + eventTags = this.__filterEmptyValues(eventTags); + var conversionEvent = eventHelpers.buildConversionEvent({ + eventKey: eventKey, + eventTags: eventTags, + userId: userId, + userAttributes: attributes, + clientEngine: this.clientEngine, + clientVersion: this.clientVersion, + configObj: configObj, + }); + this.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(enums.LOG_MESSAGES.TRACK_EVENT, MODULE_NAME, eventKey, userId)); + // TODO is it okay to not pass a projectConfig as second argument + this.eventProcessor.process(conversionEvent); + this.__emitNotificationCenterTrack(eventKey, userId, attributes, eventTags); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + var failedTrackLogMessage = jsSdkUtils.sprintf(LOG_MESSAGES.NOT_TRACKING_USER, MODULE_NAME, userId); + this.logger.log(LOG_LEVEL.ERROR, failedTrackLogMessage); + } +}; + +/** + * Send TRACK event to notificationCenter + * @param {string} eventKey + * @param {string} userId + * @param {string} attributes + * @param {Object} eventTags Values associated with the event. + */ +Optimizely.prototype.__emitNotificationCenterTrack = function(eventKey, userId, attributes, eventTags) { + try { + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return; + } + + var conversionEventOptions = { + attributes: attributes, + clientEngine: this.clientEngine, + clientVersion: this.clientVersion, + configObj: configObj, + eventKey: eventKey, + eventTags: eventTags, + logger: this.logger, + userId: userId, + }; + var conversionEvent = eventBuilder.getConversionEvent(conversionEventOptions); + + this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.TRACK, { + eventKey: eventKey, + userId: userId, + attributes: attributes, + eventTags: eventTags, + logEvent: conversionEvent, + }); + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + this.errorHandler.handleError(ex); + } +}; + +/** + * Gets variation where visitor will be bucketed. + * @param {string} experimentKey + * @param {string} userId + * @param {Object} attributes + * @return {string|null} variation key + */ +Optimizely.prototype.getVariation = function(experimentKey, userId, attributes) { + try { + if (!this.__isValidInstance()) { + this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getVariation')); + return null; + } + + try { + if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId }, attributes)) { + return null; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return null; + } + + var experiment = configObj.experimentKeyMap[experimentKey]; + if (!experiment) { + this.logger.log( + LOG_LEVEL.DEBUG, + jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey) + ); + return null; + } + + var variationKey = this.decisionService.getVariation(configObj, experimentKey, userId, attributes); + var decisionNotificationType = projectConfig.isFeatureExperiment(configObj, experiment.id) + ? DECISION_NOTIFICATION_TYPES.FEATURE_TEST + : DECISION_NOTIFICATION_TYPES.AB_TEST; + + this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.DECISION, { + type: decisionNotificationType, + userId: userId, + attributes: attributes || {}, + decisionInfo: { + experimentKey: experimentKey, + variationKey: variationKey, + }, + }); + + return variationKey; + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + this.errorHandler.handleError(ex); + return null; + } + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Force a user into a variation for a given experiment. + * @param {string} experimentKey + * @param {string} userId + * @param {string|null} variationKey user will be forced into. If null, then clear the existing experiment-to-variation mapping. + * @return boolean A boolean value that indicates if the set completed successfully. + */ +Optimizely.prototype.setForcedVariation = function(experimentKey, userId, variationKey) { + if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId })) { + return false; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return false; + } + + try { + return this.decisionService.setForcedVariation(configObj, experimentKey, userId, variationKey); + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + this.errorHandler.handleError(ex); + return false; + } +}; + +/** + * Gets the forced variation for a given user and experiment. + * @param {string} experimentKey + * @param {string} userId + * @return {string|null} The forced variation key. + */ +Optimizely.prototype.getForcedVariation = function(experimentKey, userId) { + if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId })) { + return null; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return null; + } + + try { + return this.decisionService.getForcedVariation(configObj, experimentKey, userId); + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + this.errorHandler.handleError(ex); + return null; + } +}; + +/** + * Validate string inputs, user attributes and event tags. + * @param {string} stringInputs Map of string keys and associated values + * @param {Object} userAttributes Optional parameter for user's attributes + * @param {Object} eventTags Optional parameter for event tags + * @return {boolean} True if inputs are valid + * + */ +Optimizely.prototype.__validateInputs = function(stringInputs, userAttributes, eventTags) { + try { + // Null, undefined or non-string user Id is invalid. + if (stringInputs.hasOwnProperty('user_id')) { + var userId = stringInputs.user_id; + if (typeof userId !== 'string' || userId === null || userId === 'undefined') { + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, MODULE_NAME, 'user_id')); + } + + delete stringInputs.user_id; + } + + var inputKeys = Object.keys(stringInputs); + for (var index = 0; index < inputKeys.length; index++) { + var key = inputKeys[index]; + if (!stringValidator.validate(stringInputs[key])) { + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, MODULE_NAME, key)); + } + } + if (userAttributes) { + attributesValidator.validate(userAttributes); + } + if (eventTags) { + eventTagsValidator.validate(eventTags); + } + return true; + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + this.errorHandler.handleError(ex); + return false; + } +}; + +/** + * Shows failed activation log message and returns null when user is not activated in experiment + * @param experimentKey + * @param userId + * @return {null} + */ +Optimizely.prototype.__notActivatingExperiment = function(experimentKey, userId) { + var failedActivationLogMessage = jsSdkUtils.sprintf( + LOG_MESSAGES.NOT_ACTIVATING_USER, + MODULE_NAME, + userId, + experimentKey + ); + this.logger.log(LOG_LEVEL.INFO, failedActivationLogMessage); + return null; +}; + +/** + * Filters out attributes/eventTags with null or undefined values + * @param map + * @returns {Object} map + */ +Optimizely.prototype.__filterEmptyValues = function(map) { + for (var key in map) { + if (map.hasOwnProperty(key) && (map[key] === null || map[key] === undefined)) { + delete map[key]; + } + } + return map; +}; + +/** + * Returns true if the feature is enabled for the given user. + * @param {string} featureKey Key of feature which will be checked + * @param {string} userId ID of user which will be checked + * @param {Object} attributes Optional user attributes + * @return {boolean} True if the feature is enabled for the user, false otherwise + */ +Optimizely.prototype.isFeatureEnabled = function(featureKey, userId, attributes) { + try { + if (!this.__isValidInstance()) { + this.logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'isFeatureEnabled') + ); + return false; + } + + if (!this.__validateInputs({ feature_key: featureKey, user_id: userId }, attributes)) { + return false; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return false; + } + + var feature = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); + if (!feature) { + return false; + } + + var featureEnabled = false; + var decision = this.decisionService.getVariationForFeature(configObj, feature, userId, attributes); + var variation = decision.variation; + var sourceInfo = {}; + + if (variation) { + featureEnabled = variation.featureEnabled; + if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { + sourceInfo = { + experimentKey: decision.experiment.key, + variationKey: decision.variation.key, + }; + // got a variation from the exp, so we track the impression + this._sendImpressionEvent(decision.experiment.key, decision.variation.key, userId, attributes); + } + } + + if (featureEnabled === true) { + this.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf(LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId) + ); + } else { + this.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId) + ); + featureEnabled = false; + } + + var featureInfo = { + featureKey: featureKey, + featureEnabled: featureEnabled, + source: decision.decisionSource, + sourceInfo: sourceInfo, + }; + + this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.DECISION, { + type: DECISION_NOTIFICATION_TYPES.FEATURE, + userId: userId, + attributes: attributes || {}, + decisionInfo: featureInfo, + }); + + return featureEnabled; + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return false; + } +}; + +/** + * Returns an Array containing the keys of all features in the project that are + * enabled for the given user. + * @param {string} userId + * @param {Object} attributes + * @return {Array} Array of feature keys (strings) + */ +Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { + try { + var enabledFeatures = []; + if (!this.__isValidInstance()) { + this.logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getEnabledFeatures') + ); + return enabledFeatures; + } + + if (!this.__validateInputs({ user_id: userId })) { + return enabledFeatures; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return enabledFeatures; + } + + jsSdkUtils.objectValues(configObj.featureKeyMap).forEach( + function(feature) { + if (this.isFeatureEnabled(feature.key, userId, attributes)) { + enabledFeatures.push(feature.key); + } + }.bind(this) + ); + + return enabledFeatures; + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return []; + } +}; + +/** + * Returns dynamically-typed value of the variable attached to the given + * feature flag. Returns null if the feature key or variable key is invalid. + * + * @param {string} featureKey Key of the feature whose variable's + * value is being accessed + * @param {string} variableKey Key of the variable whose value is + * being accessed + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {string|boolean|number|null} Value of the variable cast to the appropriate + * type, or null if the feature key is invalid or + * the variable key is invalid + */ + +Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { + try { + return this._getFeatureVariableForType(featureKey, variableKey, null, userId, attributes); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Helper method to get the value for a variable of a certain type attached to a + * feature flag. Returns null if the feature key is invalid, the variable key is + * invalid, the given variable type does not match the variable's actual type, + * or the variable value cannot be cast to the required type. If the given variable + * type is null, the value of the variable cast to the appropriate type is returned. + * + * @param {string} featureKey Key of the feature whose variable's value is + * being accessed + * @param {string} variableKey Key of the variable whose value is being + * accessed + * @param {string|null} variableType Type of the variable whose value is being + * accessed (must be one of FEATURE_VARIABLE_TYPES + * in lib/utils/enums/index.js), or null to return the + * value of the variable cast to the appropriate type + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {string|boolean|number|null} Value of the variable cast to the appropriate + * type, or null if the feature key is invalid, the + * variable key is invalid, or there is a mismatch + * with the type of the variable + */ +Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { + if (!this.__isValidInstance()) { + var apiName = variableType + ? 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1) + : 'getFeatureVariable'; + this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); + return null; + } + + if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { + return null; + } + + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return null; + } + + var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); + if (!featureFlag) { + return null; + } + + var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); + if (!variable) { + return null; + } + + if (!variableType) { + variableType = variable.type; + } else if (variable.type !== variableType) { + this.logger.log( + LOG_LEVEL.WARNING, + jsSdkUtils.sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) + ); + return null; + } + + var featureEnabled = false; + var variableValue = variable.defaultValue; + var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); + + if (decision.variation !== null) { + featureEnabled = decision.variation.featureEnabled; + var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); + if (value !== null) { + if (featureEnabled === true) { + variableValue = value; + this.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf( + LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, + MODULE_NAME, + variableKey, + featureFlag.key, + variableValue, + userId + ) + ); + } else { + this.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf( + LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, + MODULE_NAME, + featureFlag.key, + userId, + variableKey + ) + ); + } + } else { + this.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf( + LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, + MODULE_NAME, + variableKey, + decision.variation.key + ) + ); + } + } else { + this.logger.log( + LOG_LEVEL.INFO, + jsSdkUtils.sprintf( + LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, + MODULE_NAME, + userId, + variableKey, + featureFlag.key + ) + ); + } + + var sourceInfo = {}; + if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { + sourceInfo = { + experimentKey: decision.experiment.key, + variationKey: decision.variation.key, + }; + } + + var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); + this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.DECISION, { + type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, + userId: userId, + attributes: attributes || {}, + decisionInfo: { + featureKey: featureKey, + featureEnabled: featureEnabled, + source: decision.decisionSource, + variableKey: variableKey, + variableValue: typeCastedValue, + variableType: variableType, + sourceInfo: sourceInfo, + }, + }); + return typeCastedValue; +}; + +/** + * Returns value for the given boolean variable attached to the given feature + * flag. + * @param {string} featureKey Key of the feature whose variable's value is + * being accessed + * @param {string} variableKey Key of the variable whose value is being + * accessed + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {boolean|null} Boolean value of the variable, or null if the + * feature key is invalid, the variable key is + * invalid, or there is a mismatch with the type + * of the variable + */ +Optimizely.prototype.getFeatureVariableBoolean = function(featureKey, variableKey, userId, attributes) { + try { + return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.BOOLEAN, userId, attributes); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Returns value for the given double variable attached to the given feature + * flag. + * @param {string} featureKey Key of the feature whose variable's value is + * being accessed + * @param {string} variableKey Key of the variable whose value is being + * accessed + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {number|null} Number value of the variable, or null if the + * feature key is invalid, the variable key is + * invalid, or there is a mismatch with the type + * of the variable + */ +Optimizely.prototype.getFeatureVariableDouble = function(featureKey, variableKey, userId, attributes) { + try { + return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.DOUBLE, userId, attributes); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Returns value for the given integer variable attached to the given feature + * flag. + * @param {string} featureKey Key of the feature whose variable's value is + * being accessed + * @param {string} variableKey Key of the variable whose value is being + * accessed + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {number|null} Number value of the variable, or null if the + * feature key is invalid, the variable key is + * invalid, or there is a mismatch with the type + * of the variable + */ +Optimizely.prototype.getFeatureVariableInteger = function(featureKey, variableKey, userId, attributes) { + try { + return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.INTEGER, userId, attributes); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Returns value for the given string variable attached to the given feature + * flag. + * @param {string} featureKey Key of the feature whose variable's value is + * being accessed + * @param {string} variableKey Key of the variable whose value is being + * accessed + * @param {string} userId ID for the user + * @param {Object} attributes Optional user attributes + * @return {string|null} String value of the variable, or null if the + * feature key is invalid, the variable key is + * invalid, or there is a mismatch with the type + * of the variable + */ +Optimizely.prototype.getFeatureVariableString = function(featureKey, variableKey, userId, attributes) { + try { + return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.STRING, userId, attributes); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Returns OptimizelyConfig object containing experiments and features data + * @return {Object} + * + * OptimizelyConfig Object Schema + * { + * 'experimentsMap': { + * 'my-fist-experiment': { + * 'id': '111111', + * 'key': 'my-fist-experiment' + * 'variationsMap': { + * 'variation_1': { + * 'id': '121212', + * 'key': 'variation_1', + * 'variablesMap': { + * 'age': { + * 'id': '222222', + * 'key': 'age', + * 'type': 'integer', + * 'value': '0', + * } + * } + * } + * } + * } + * }, + * 'featuresMap': { + * 'awesome-feature': { + * 'id': '333333', + * 'key': 'awesome-feature', + * 'experimentsMap': Object, + * 'variationsMap': Object, + * } + * } + * } + */ +Optimizely.prototype.getOptimizelyConfig = function() { + try { + var configObj = this.projectConfigManager.getConfig(); + if (!configObj) { + return null; + } + return this.projectConfigManager.getOptimizelyConfig(); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return null; + } +}; + +/** + * Stop background processes belonging to this instance, including: + * + * - Active datafile requests + * - Pending datafile requests + * - Pending event queue flushes + * + * In-flight datafile requests will be aborted. Any events waiting to be sent + * as part of a batched event request will be immediately flushed to the event + * dispatcher. + * + * Returns a Promise that fulfills after all in-flight event dispatcher requests + * (including any final request resulting from flushing the queue as described + * above) are complete. If there are no in-flight event dispatcher requests and + * no queued events waiting to be sent, returns an immediately-fulfilled Promise. + * + * Returned Promises are fulfilled with result objects containing these + * properties: + * - success (boolean): true if the event dispatcher signaled completion of + * all in-flight and final requests, or if there were no + * queued events and no in-flight requests. false if an + * unexpected error was encountered during the close + * process. + * - reason (string=): If success is false, this is a string property with + * an explanatory message. + * + * NOTE: After close is called, this instance is no longer usable - any events + * generated will no longer be sent to the event dispatcher. + * + * @return {Promise} + */ +Optimizely.prototype.close = function() { + try { + var eventProcessorStoppedPromise = this.eventProcessor.stop(); + if (this.__disposeOnUpdate) { + this.__disposeOnUpdate(); + this.__disposeOnUpdate = null; + } + if (this.projectConfigManager) { + this.projectConfigManager.stop(); + } + Object.keys(this.__readyTimeouts).forEach( + function(readyTimeoutId) { + var readyTimeoutRecord = this.__readyTimeouts[readyTimeoutId]; + clearTimeout(readyTimeoutRecord.readyTimeout); + readyTimeoutRecord.onClose(); + }.bind(this) + ); + this.__readyTimeouts = {}; + return eventProcessorStoppedPromise.then( + function() { + return { + success: true, + }; + }, + function(err) { + return { + success: false, + reason: String(err), + }; + } + ); + } catch (err) { + this.logger.log(LOG_LEVEL.ERROR, err.message); + this.errorHandler.handleError(err); + return Promise.resolve({ + success: false, + reason: String(err), + }); + } +}; + +/** + * Returns a Promise that fulfills when this instance is ready to use (meaning + * it has a valid datafile), or has failed to become ready within a period of + * time (configurable by the timeout property of the options argument), or when + * this instance is closed via the close method. + * + * If a valid datafile was provided in the constructor, the returned Promise is + * immediately fulfilled. If an sdkKey was provided, a manager will be used to + * fetch a datafile, and the returned promise will fulfill if that fetch + * succeeds or fails before the timeout. The default timeout is 30 seconds, + * which will be used if no timeout is provided in the argument options object. + * + * The returned Promise is fulfilled with a result object containing these + * properties: + * - success (boolean): True if this instance is ready to use with a valid + * datafile, or false if this instance failed to become + * ready or was closed prior to becoming ready. + * - reason (string=): If success is false, this is a string property with + * an explanatory message. Failure could be due to + * expiration of the timeout, network errors, + * unsuccessful responses, datafile parse errors, + * datafile validation errors, or the instance being + * closed + * @param {Object=} options + * @param {number|undefined} options.timeout + * @return {Promise} + */ +Optimizely.prototype.onReady = function(options) { + var timeout; + if (typeof options === 'object' && options !== null) { + timeout = options.timeout; + } + if (!fns.isSafeInteger(timeout)) { + timeout = DEFAULT_ONREADY_TIMEOUT; + } + + var resolveTimeoutPromise; + var timeoutPromise = new Promise(function(resolve) { + resolveTimeoutPromise = resolve; + }); + + var timeoutId = this.__nextReadyTimeoutId; + this.__nextReadyTimeoutId++; + + var onReadyTimeout = function() { + delete this.__readyTimeouts[timeoutId]; + resolveTimeoutPromise({ + success: false, + reason: jsSdkUtils.sprintf('onReady timeout expired after %s ms', timeout), + }); + }.bind(this); + var readyTimeout = setTimeout(onReadyTimeout, timeout); + var onClose = function() { + resolveTimeoutPromise({ + success: false, + reason: 'Instance closed', + }); + }; + + this.__readyTimeouts[timeoutId] = { + readyTimeout: readyTimeout, + onClose: onClose, + }; + + this.__readyPromise.then( + function() { + clearTimeout(readyTimeout); + delete this.__readyTimeouts[timeoutId]; + resolveTimeoutPromise({ + success: true, + }); + }.bind(this) + ); + + return Promise.race([this.__readyPromise, timeoutPromise]); +}; + +module.exports = Optimizely; + + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016, 2018-2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ + +/** + * Provides utility method for validating that the attributes user has provided are valid + */ + +var sprintf = __webpack_require__(12).sprintf; +var fns = __webpack_require__(11); + +var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; +var MODULE_NAME = 'ATTRIBUTES_VALIDATOR'; + +module.exports = { + /** + * Validates user's provided attributes + * @param {Object} attributes + * @return {boolean} True if the attributes are valid + * @throws If the attributes are not valid + */ + validate: function(attributes) { + if (typeof attributes === 'object' && !Array.isArray(attributes) && attributes !== null) { + Object.keys(attributes).forEach(function(key) { + if (typeof attributes[key] === 'undefined') { + throw new Error(sprintf(ERROR_MESSAGES.UNDEFINED_ATTRIBUTE, MODULE_NAME, key)); + } + }); + return true; + } else { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, MODULE_NAME)); + } + }, + + isAttributeValid: function(attributeKey, attributeValue) { + return ( + typeof attributeKey === 'string' && + (typeof attributeValue === 'string' || + typeof attributeValue === 'boolean' || + (fns.isNumber(attributeValue) && fns.isSafeInteger(attributeValue))) + ); + }, +}; + + +/***/ }), +/* 29 */ +/***/ (function(module, exports, __webpack_require__) { + +/**************************************************************************** + * Copyright 2017-2019, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License 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 AudienceEvaluator = __webpack_require__(30); +var bucketer = __webpack_require__(33); +var enums = __webpack_require__(14); +var fns = __webpack_require__(11); +var projectConfig = __webpack_require__(35); +var stringValidator = __webpack_require__(37); + +var sprintf = __webpack_require__(12).sprintf; + +var MODULE_NAME = 'DECISION_SERVICE'; +var ERROR_MESSAGES = enums.ERROR_MESSAGES; +var LOG_LEVEL = enums.LOG_LEVEL; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var DECISION_SOURCES = enums.DECISION_SOURCES; + +/** + * Optimizely's decision service that determines which variation of an experiment the user will be allocated to. + * + * The decision service contains all logic around how a user decision is made. This includes all of the following (in order): + * 1. Checking experiment status + * 2. Checking forced bucketing + * 3. Checking whitelisting + * 4. Checking user profile service for past bucketing decisions (sticky bucketing) + * 5. Checking audience targeting + * 6. Using Murmurhash3 to bucket the user. + * + * @constructor + * @param {Object} options + * @param {Object} options.userProfileService An instance of the user profile service for sticky bucketing. + * @param {Object} options.logger An instance of a logger to log messages. + * @returns {Object} + */ +function DecisionService(options) { + this.audienceEvaluator = new AudienceEvaluator(options.UNSTABLE_conditionEvaluators); + this.forcedVariationMap = {}; + this.logger = options.logger; + this.userProfileService = options.userProfileService || null; +} + +/** + * Gets variation where visitor will be bucketed. + * @param {Object} configObj The parsed project configuration object + * @param {string} experimentKey + * @param {string} userId + * @param {Object} attributes + * @return {string|null} the variation the user is bucketed into. + */ +DecisionService.prototype.getVariation = function(configObj, experimentKey, userId, attributes) { + // by default, the bucketing ID should be the user ID + var bucketingId = this._getBucketingId(userId, attributes); + + if (!this.__checkIfExperimentIsActive(configObj, experimentKey)) { + return null; + } + var experiment = configObj.experimentKeyMap[experimentKey]; + var forcedVariationKey = this.getForcedVariation(configObj, experimentKey, userId); + if (forcedVariationKey) { + return forcedVariationKey; + } + + var variation = this.__getWhitelistedVariation(experiment, userId); + if (variation) { + return variation.key; + } + + // check for sticky bucketing + var experimentBucketMap = this.__resolveExperimentBucketMap(userId, attributes); + variation = this.__getStoredVariation(configObj, experiment, userId, experimentBucketMap); + if (variation) { + this.logger.log( + LOG_LEVEL.INFO, + sprintf(LOG_MESSAGES.RETURNING_STORED_VARIATION, MODULE_NAME, variation.key, experimentKey, userId) + ); + return variation.key; + } + + // Perform regular targeting and bucketing + if (!this.__checkIfUserIsInAudience(configObj, experimentKey, userId, attributes)) { + return null; + } + + var bucketerParams = this.__buildBucketerParams(configObj, experimentKey, bucketingId, userId); + var variationId = bucketer.bucket(bucketerParams); + variation = configObj.variationIdMap[variationId]; + if (!variation) { + return null; + } + + // persist bucketing + this.__saveUserProfile(experiment, variation, userId, experimentBucketMap); + + return variation.key; +}; + +/** + * Merges attributes from attributes[STICKY_BUCKETING_KEY] and userProfileService + * @param {Object} attributes + * @return {Object} finalized copy of experiment_bucket_map + */ +DecisionService.prototype.__resolveExperimentBucketMap = function(userId, attributes) { + attributes = attributes || {}; + var userProfile = this.__getUserProfile(userId) || {}; + var attributeExperimentBucketMap = attributes[enums.CONTROL_ATTRIBUTES.STICKY_BUCKETING_KEY]; + return fns.assign({}, userProfile.experiment_bucket_map, attributeExperimentBucketMap); +}; + +/** + * Checks whether the experiment is running + * @param {Object} configObj The parsed project configuration object + * @param {string} experimentKey Key of experiment being validated + * @param {string} userId ID of user + * @return {boolean} True if experiment is running + */ +DecisionService.prototype.__checkIfExperimentIsActive = function(configObj, experimentKey) { + if (!projectConfig.isActive(configObj, experimentKey)) { + var experimentNotRunningLogMessage = sprintf(LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, MODULE_NAME, experimentKey); + this.logger.log(LOG_LEVEL.INFO, experimentNotRunningLogMessage); + return false; + } + + return true; +}; + +/** + * Checks if user is whitelisted into any variation and return that variation if so + * @param {Object} experiment + * @param {string} userId + * @return {string|null} Forced variation if it exists for user ID, otherwise null + */ +DecisionService.prototype.__getWhitelistedVariation = function(experiment, userId) { + if (experiment.forcedVariations && experiment.forcedVariations.hasOwnProperty(userId)) { + var forcedVariationKey = experiment.forcedVariations[userId]; + if (experiment.variationKeyMap.hasOwnProperty(forcedVariationKey)) { + var forcedBucketingSucceededMessageLog = sprintf( + LOG_MESSAGES.USER_FORCED_IN_VARIATION, + MODULE_NAME, + userId, + forcedVariationKey + ); + this.logger.log(LOG_LEVEL.INFO, forcedBucketingSucceededMessageLog); + return experiment.variationKeyMap[forcedVariationKey]; + } else { + var forcedBucketingFailedMessageLog = sprintf( + LOG_MESSAGES.FORCED_BUCKETING_FAILED, + MODULE_NAME, + forcedVariationKey, + userId + ); + this.logger.log(LOG_LEVEL.ERROR, forcedBucketingFailedMessageLog); + return null; + } + } + + return null; +}; + +/** + * Checks whether the user is included in experiment audience + * @param {Object} configObj The parsed project configuration object + * @param {string} experimentKey Key of experiment being validated + * @param {string} userId ID of user + * @param {Object} attributes Optional parameter for user's attributes + * @return {boolean} True if user meets audience conditions + */ +DecisionService.prototype.__checkIfUserIsInAudience = function(configObj, experimentKey, userId, attributes) { + var experimentAudienceConditions = projectConfig.getExperimentAudienceConditions(configObj, experimentKey); + var audiencesById = projectConfig.getAudiencesById(configObj); + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf( + LOG_MESSAGES.EVALUATING_AUDIENCES_COMBINED, + MODULE_NAME, + experimentKey, + JSON.stringify(experimentAudienceConditions) + ) + ); + var result = this.audienceEvaluator.evaluate(experimentAudienceConditions, audiencesById, attributes); + this.logger.log( + LOG_LEVEL.INFO, + sprintf( + LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, + MODULE_NAME, + experimentKey, + result.toString().toUpperCase() + ) + ); + + if (!result) { + var userDoesNotMeetConditionsLogMessage = sprintf( + LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, + MODULE_NAME, + userId, + experimentKey + ); + this.logger.log(LOG_LEVEL.INFO, userDoesNotMeetConditionsLogMessage); + return false; + } + + return true; +}; + +/** + * Given an experiment key and user ID, returns params used in bucketer call + * @param configObj The parsed project configuration object + * @param experimentKey Experiment key used for bucketer + * @param bucketingId ID to bucket user into + * @param userId ID of user to be bucketed + * @return {Object} + */ +DecisionService.prototype.__buildBucketerParams = function(configObj, experimentKey, bucketingId, userId) { + var bucketerParams = {}; + bucketerParams.experimentKey = experimentKey; + bucketerParams.experimentId = projectConfig.getExperimentId(configObj, experimentKey); + bucketerParams.userId = userId; + bucketerParams.trafficAllocationConfig = projectConfig.getTrafficAllocation(configObj, experimentKey); + bucketerParams.experimentKeyMap = configObj.experimentKeyMap; + bucketerParams.groupIdMap = configObj.groupIdMap; + bucketerParams.variationIdMap = configObj.variationIdMap; + bucketerParams.logger = this.logger; + bucketerParams.bucketingId = bucketingId; + return bucketerParams; +}; + +/** + * Pull the stored variation out of the experimentBucketMap for an experiment/userId + * @param {Object} configObj The parsed project configuration object + * @param {Object} experiment + * @param {String} userId + * @param {Object} experimentBucketMap mapping experiment => { variation_id: } + * @return {Object} the stored variation or null if the user profile does not have one for the given experiment + */ +DecisionService.prototype.__getStoredVariation = function(configObj, experiment, userId, experimentBucketMap) { + if (experimentBucketMap.hasOwnProperty(experiment.id)) { + var decision = experimentBucketMap[experiment.id]; + var variationId = decision.variation_id; + if (configObj.variationIdMap.hasOwnProperty(variationId)) { + return configObj.variationIdMap[decision.variation_id]; + } else { + this.logger.log( + LOG_LEVEL.INFO, + sprintf(LOG_MESSAGES.SAVED_VARIATION_NOT_FOUND, MODULE_NAME, userId, variationId, experiment.key) + ); + } + } + + return null; +}; + +/** + * Get the user profile with the given user ID + * @param {string} userId + * @return {Object|undefined} the stored user profile or undefined if one isn't found + */ +DecisionService.prototype.__getUserProfile = function(userId) { + var userProfile = { + user_id: userId, + experiment_bucket_map: {}, + }; + + if (!this.userProfileService) { + return userProfile; + } + + try { + return this.userProfileService.lookup(userId); + } catch (ex) { + this.logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.USER_PROFILE_LOOKUP_ERROR, MODULE_NAME, userId, ex.message) + ); + } +}; + +/** + * Saves the bucketing decision to the user profile + * @param {Object} userProfile + * @param {Object} experiment + * @param {Object} variation + * @param {Object} experimentBucketMap + */ +DecisionService.prototype.__saveUserProfile = function(experiment, variation, userId, experimentBucketMap) { + if (!this.userProfileService) { + return; + } + + try { + experimentBucketMap[experiment.id] = { + variation_id: variation.id + }; + + this.userProfileService.save({ + user_id: userId, + experiment_bucket_map: experimentBucketMap, + }); + + this.logger.log( + LOG_LEVEL.INFO, + sprintf(LOG_MESSAGES.SAVED_VARIATION, MODULE_NAME, variation.key, experiment.key, userId) + ); + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, sprintf(ERROR_MESSAGES.USER_PROFILE_SAVE_ERROR, MODULE_NAME, userId, ex.message)); + } +}; + +/** + * Given a feature, user ID, and attributes, returns an object representing a + * decision. If the user was bucketed into a variation for the given feature + * and attributes, the returned decision object will have variation and + * experiment properties (both objects), as well as a decisionSource property. + * decisionSource indicates whether the decision was due to a rollout or an + * experiment. + * @param {Object} configObj The parsed project configuration object + * @param {Object} feature A feature flag object from project configuration + * @param {String} userId A string identifying the user, for bucketing + * @param {Object} attributes Optional user attributes + * @return {Object} An object with experiment, variation, and decisionSource + * properties. If the user was not bucketed into a variation, the variation + * property is null. + */ +DecisionService.prototype.getVariationForFeature = function(configObj, feature, userId, attributes) { + var experimentDecision = this._getVariationForFeatureExperiment(configObj, feature, userId, attributes); + if (experimentDecision.variation !== null) { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf( + LOG_MESSAGES.USER_IN_FEATURE_EXPERIMENT, + MODULE_NAME, + userId, + experimentDecision.variation.key, + experimentDecision.experiment.key, + feature.key + ) + ); + return experimentDecision; + } + + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_NOT_IN_FEATURE_EXPERIMENT, MODULE_NAME, userId, feature.key) + ); + + var rolloutDecision = this._getVariationForRollout(configObj, feature, userId, attributes); + if (rolloutDecision.variation !== null) { + this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.USER_IN_ROLLOUT, MODULE_NAME, userId, feature.key)); + return rolloutDecision; + } + + this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.USER_NOT_IN_ROLLOUT, MODULE_NAME, userId, feature.key)); + return rolloutDecision; +}; + +DecisionService.prototype._getVariationForFeatureExperiment = function(configObj, feature, userId, attributes) { + var experiment = null; + var variationKey = null; + + if (feature.hasOwnProperty('groupId')) { + var group = configObj.groupIdMap[feature.groupId]; + if (group) { + experiment = this._getExperimentInGroup(configObj, group, userId); + if (experiment && feature.experimentIds.indexOf(experiment.id) !== -1) { + variationKey = this.getVariation(configObj, experiment.key, userId, attributes); + } + } + } else if (feature.experimentIds.length > 0) { + // If the feature does not have a group ID, then it can only be associated + // with one experiment, so we look at the first experiment ID only + experiment = projectConfig.getExperimentFromId(configObj, feature.experimentIds[0], this.logger); + if (experiment) { + variationKey = this.getVariation(configObj, experiment.key, userId, attributes); + } + } else { + this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.FEATURE_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.key)); + } + + var variation = null; + if (variationKey !== null && experiment !== null) { + variation = experiment.variationKeyMap[variationKey]; + } + return { + experiment: experiment, + variation: variation, + decisionSource: DECISION_SOURCES.FEATURE_TEST, + }; +}; + +DecisionService.prototype._getExperimentInGroup = function(configObj, group, userId) { + var experimentId = bucketer.bucketUserIntoExperiment(group, userId, userId, this.logger); + if (experimentId) { + this.logger.log( + LOG_LEVEL.INFO, + sprintf(LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, MODULE_NAME, userId, experimentId, group.id) + ); + var experiment = projectConfig.getExperimentFromId(configObj, experimentId, this.logger); + if (experiment) { + return experiment; + } + } + + this.logger.log( + LOG_LEVEL.INFO, + sprintf(LOG_MESSAGES.USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP, MODULE_NAME, userId, group.id) + ); + return null; +}; + +DecisionService.prototype._getVariationForRollout = function(configObj, feature, userId, attributes) { + if (!feature.rolloutId) { + this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.NO_ROLLOUT_EXISTS, MODULE_NAME, feature.key)); + return { + experiment: null, + variation: null, + decisionSource: DECISION_SOURCES.ROLLOUT, + }; + } + + var rollout = configObj.rolloutIdMap[feature.rolloutId]; + if (!rollout) { + this.logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.INVALID_ROLLOUT_ID, MODULE_NAME, feature.rolloutId, feature.key) + ); + return { + experiment: null, + variation: null, + decisionSource: DECISION_SOURCES.ROLLOUT, + }; + } + + if (rollout.experiments.length === 0) { + this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.ROLLOUT_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.rolloutId)); + return { + experiment: null, + variation: null, + decisionSource: DECISION_SOURCES.ROLLOUT, + }; + } + + var bucketingId = this._getBucketingId(userId, attributes); + + // The end index is length - 1 because the last experiment is assumed to be + // "everyone else", which will be evaluated separately outside this loop + var endIndex = rollout.experiments.length - 1; + var index; + var experiment; + var bucketerParams; + var variationId; + var variation; + for (index = 0; index < endIndex; index++) { + experiment = configObj.experimentKeyMap[rollout.experiments[index].key]; + + if (!this.__checkIfUserIsInAudience(configObj, experiment.key, userId, attributes)) { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, index + 1) + ); + continue; + } + + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, index + 1) + ); + bucketerParams = this.__buildBucketerParams(configObj, experiment.key, bucketingId, userId); + variationId = bucketer.bucket(bucketerParams); + variation = configObj.variationIdMap[variationId]; + if (variation) { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, index + 1) + ); + return { + experiment: experiment, + variation: variation, + decisionSource: DECISION_SOURCES.ROLLOUT, + }; + } else { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_NOT_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, index + 1) + ); + break; + } + } + + var everyoneElseExperiment = configObj.experimentKeyMap[rollout.experiments[endIndex].key]; + if (this.__checkIfUserIsInAudience(configObj, everyoneElseExperiment.key, userId, attributes)) { + bucketerParams = this.__buildBucketerParams(configObj, everyoneElseExperiment.key, bucketingId, userId); + variationId = bucketer.bucket(bucketerParams); + variation = configObj.variationIdMap[variationId]; + if (variation) { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_BUCKETED_INTO_EVERYONE_TARGETING_RULE, MODULE_NAME, userId) + ); + return { + experiment: everyoneElseExperiment, + variation: variation, + decisionSource: DECISION_SOURCES.ROLLOUT, + }; + } else { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_NOT_BUCKETED_INTO_EVERYONE_TARGETING_RULE, MODULE_NAME, userId) + ); + } + } + + return { + experiment: null, + variation: null, + decisionSource: DECISION_SOURCES.ROLLOUT, + }; +}; + +/** + * Get bucketing Id from user attributes. + * @param {String} userId + * @param {Object} attributes + * @returns {String} Bucketing Id if it is a string type in attributes, user Id otherwise. + */ +DecisionService.prototype._getBucketingId = function(userId, attributes) { + var bucketingId = userId; + + // If the bucketing ID key is defined in attributes, than use that in place of the userID for the murmur hash key + if ( + attributes != null && + typeof attributes === 'object' && + attributes.hasOwnProperty(enums.CONTROL_ATTRIBUTES.BUCKETING_ID) + ) { + if (typeof attributes[enums.CONTROL_ATTRIBUTES.BUCKETING_ID] === 'string') { + bucketingId = attributes[enums.CONTROL_ATTRIBUTES.BUCKETING_ID]; + this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.VALID_BUCKETING_ID, MODULE_NAME, bucketingId)); + } else { + this.logger.log(LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.BUCKETING_ID_NOT_STRING, MODULE_NAME)); + } + } + + return bucketingId; +}; + +/** + * Removes forced variation for given userId and experimentKey + * @param {string} userId String representing the user id + * @param {number} experimentId Number representing the experiment id + * @param {string} experimentKey Key representing the experiment id + * @throws If the user id is not valid or not in the forced variation map + */ +DecisionService.prototype.removeForcedVariation = function(userId, experimentId, experimentKey) { + if (!userId) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_ID, MODULE_NAME)); + } + + if (this.forcedVariationMap.hasOwnProperty(userId)) { + delete this.forcedVariationMap[userId][experimentId]; + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.VARIATION_REMOVED_FOR_USER, MODULE_NAME, experimentKey, userId) + ); + } else { + throw new Error(sprintf(ERROR_MESSAGES.USER_NOT_IN_FORCED_VARIATION, MODULE_NAME, userId)); + } +}; + +/** + * Sets forced variation for given userId and experimentKey + * @param {string} userId String representing the user id + * @param {number} experimentId Number representing the experiment id + * @param {number} variationId Number representing the variation id + * @throws If the user id is not valid + */ +DecisionService.prototype.__setInForcedVariationMap = function(userId, experimentId, variationId) { + if (this.forcedVariationMap.hasOwnProperty(userId)) { + this.forcedVariationMap[userId][experimentId] = variationId; + } else { + this.forcedVariationMap[userId] = {}; + this.forcedVariationMap[userId][experimentId] = variationId; + } + + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_MAPPED_TO_FORCED_VARIATION, MODULE_NAME, variationId, experimentId, userId) + ); +}; + +/** + * Gets the forced variation key for the given user and experiment. + * @param {Object} configObj Object representing project configuration + * @param {string} experimentKey Key for experiment. + * @param {string} userId The user Id. + * @return {string|null} Variation The variation which the given user and experiment should be forced into. + */ +DecisionService.prototype.getForcedVariation = function(configObj, experimentKey, userId) { + var experimentToVariationMap = this.forcedVariationMap[userId]; + if (!experimentToVariationMap) { + this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, MODULE_NAME, userId)); + return null; + } + + var experimentId; + try { + var experiment = projectConfig.getExperimentFromKey(configObj, experimentKey); + if (experiment.hasOwnProperty('id')) { + experimentId = experiment['id']; + } else { + // catching improperly formatted experiments + this.logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.IMPROPERLY_FORMATTED_EXPERIMENT, MODULE_NAME, experimentKey) + ); + return null; + } + } catch (ex) { + // catching experiment not in datafile + this.logger.log(LOG_LEVEL.ERROR, ex.message); + return null; + } + + var variationId = experimentToVariationMap[experimentId]; + if (!variationId) { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, MODULE_NAME, experimentKey, userId) + ); + return null; + } + + var variationKey = projectConfig.getVariationKeyFromId(configObj, variationId); + if (variationKey) { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_HAS_FORCED_VARIATION, MODULE_NAME, variationKey, experimentKey, userId) + ); + } else { + this.logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, MODULE_NAME, experimentKey, userId) + ); + } + + return variationKey; +}; + +/** + * Sets the forced variation for a user in a given experiment + * @param {Object} configObj Object representing project configuration + * @param {string} experimentKey Key for experiment. + * @param {string} userId The user Id. + * @param {string} variationKey Key for variation. If null, then clear the existing experiment-to-variation mapping + * @return {boolean} A boolean value that indicates if the set completed successfully. + */ +DecisionService.prototype.setForcedVariation = function(configObj, experimentKey, userId, variationKey) { + if (variationKey != null && !stringValidator.validate(variationKey)) { + this.logger.log(LOG_LEVEL.ERROR, sprintf(ERROR_MESSAGES.INVALID_VARIATION_KEY, MODULE_NAME)); + return false; + } + + var experimentId; + try { + var experiment = projectConfig.getExperimentFromKey(configObj, experimentKey); + if (experiment.hasOwnProperty('id')) { + experimentId = experiment['id']; + } else { + // catching improperly formatted experiments + this.logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.IMPROPERLY_FORMATTED_EXPERIMENT, MODULE_NAME, experimentKey) + ); + return false; + } + } catch (ex) { + // catching experiment not in datafile + this.logger.log(LOG_LEVEL.ERROR, ex.message); + return false; + } + + if (variationKey == null) { + try { + this.removeForcedVariation(userId, experimentId, experimentKey, this.logger); + return true; + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + return false; + } + } + + var variationId = projectConfig.getVariationIdFromExperimentAndVariationKey(configObj, experimentKey, variationKey); + + if (!variationId) { + this.logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.NO_VARIATION_FOR_EXPERIMENT_KEY, MODULE_NAME, variationKey, experimentKey) + ); + return false; + } + + try { + this.__setInForcedVariationMap(userId, experimentId, variationId); + return true; + } catch (ex) { + this.logger.log(LOG_LEVEL.ERROR, ex.message); + return false; + } +}; + +module.exports = { + /** + * Creates an instance of the DecisionService. + * @param {Object} options Configuration options + * @param {Object} options.userProfileService + * @param {Object} options.logger + * @return {Object} An instance of the DecisionService + */ + createDecisionService: function(options) { + return new DecisionService(options); + }, +}; + + +/***/ }), +/* 30 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016, 2018-2019 Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 conditionTreeEvaluator = __webpack_require__(31); +var customAttributeConditionEvaluator = __webpack_require__(32); +var enums = __webpack_require__(14); +var fns = __webpack_require__(11); +var sprintf = __webpack_require__(12).sprintf; +var logging = __webpack_require__(1); +var logger = logging.getLogger(); + +var ERROR_MESSAGES = enums.ERROR_MESSAGES; +var LOG_LEVEL = enums.LOG_LEVEL; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var MODULE_NAME = 'AUDIENCE_EVALUATOR'; + +/** + * Construct an instance of AudienceEvaluator with given options + * @param {Object=} UNSTABLE_conditionEvaluators A map of condition evaluators provided by the consumer. This enables matching + * condition types which are not supported natively by the SDK. Note that built in + * Optimizely evaluators cannot be overridden. + * @constructor + */ +function AudienceEvaluator(UNSTABLE_conditionEvaluators) { + this.typeToEvaluatorMap = fns.assign({}, UNSTABLE_conditionEvaluators, { + custom_attribute: customAttributeConditionEvaluator, + }); +} + +/** + * Determine if the given user attributes satisfy the given audience conditions + * @param {Array|String|null|undefined} audienceConditions Audience conditions to match the user attributes against - can be an array + * of audience IDs, a nested array of conditions, or a single leaf condition. + * Examples: ["5", "6"], ["and", ["or", "1", "2"], "3"], "1" + * @param {Object} audiencesById Object providing access to full audience objects for audience IDs + * contained in audienceConditions. Keys should be audience IDs, values + * should be full audience objects with conditions properties + * @param {Object} [userAttributes] User attributes which will be used in determining if audience conditions + * are met. If not provided, defaults to an empty object + * @return {Boolean} true if the user attributes match the given audience conditions, false + * otherwise + */ +AudienceEvaluator.prototype.evaluate = function(audienceConditions, audiencesById, userAttributes) { + // if there are no audiences, return true because that means ALL users are included in the experiment + if (!audienceConditions || audienceConditions.length === 0) { + return true; + } + + if (!userAttributes) { + userAttributes = {}; + } + + var evaluateAudience = function(audienceId) { + var audience = audiencesById[audienceId]; + if (audience) { + logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.EVALUATING_AUDIENCE, MODULE_NAME, audienceId, JSON.stringify(audience.conditions)) + ); + var result = conditionTreeEvaluator.evaluate( + audience.conditions, + this.evaluateConditionWithUserAttributes.bind(this, userAttributes) + ); + var resultText = result === null ? 'UNKNOWN' : result.toString().toUpperCase(); + logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT, MODULE_NAME, audienceId, resultText)); + return result; + } + + return null; + }.bind(this); + + return conditionTreeEvaluator.evaluate(audienceConditions, evaluateAudience) || false; +}; + +/** + * Wrapper around evaluator.evaluate that is passed to the conditionTreeEvaluator. + * Evaluates the condition provided given the user attributes if an evaluator has been defined for the condition type. + * @param {Object} userAttributes A map of user attributes. + * @param {Object} condition A single condition object to evaluate. + * @return {Boolean|null} true if the condition is satisfied, null if a matcher is not found. + */ +AudienceEvaluator.prototype.evaluateConditionWithUserAttributes = function(userAttributes, condition) { + var evaluator = this.typeToEvaluatorMap[condition.type]; + if (!evaluator) { + logger.log(LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.UNKNOWN_CONDITION_TYPE, MODULE_NAME, JSON.stringify(condition))); + return null; + } + try { + return evaluator.evaluate(condition, userAttributes, logger); + } catch (err) { + logger.log( + LOG_LEVEL.ERROR, + sprintf(ERROR_MESSAGES.CONDITION_EVALUATOR_ERROR, MODULE_NAME, condition.type, err.message) + ); + } + return null; +}; + +module.exports = AudienceEvaluator; + + +/***/ }), +/* 31 */ +/***/ (function(module, exports) { + +/**************************************************************************** + * Copyright 2018, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License 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 AND_CONDITION = 'and'; +var OR_CONDITION = 'or'; +var NOT_CONDITION = 'not'; + +var DEFAULT_OPERATOR_TYPES = [AND_CONDITION, OR_CONDITION, NOT_CONDITION]; + +/** + * Top level method to evaluate conditions + * @param {Array|*} conditions Nested array of and/or conditions, or a single leaf + * condition value of any type + * Example: ['and', '0', ['or', '1', '2']] + * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition + * values + * @return {?Boolean} Result of evaluating the conditions using the operator + * rules and the leaf evaluator. A return value of null + * indicates that the conditions are invalid or unable to be + * evaluated + */ +function evaluate(conditions, leafEvaluator) { + if (Array.isArray(conditions)) { + var firstOperator = conditions[0]; + var restOfConditions = conditions.slice(1); + + if (DEFAULT_OPERATOR_TYPES.indexOf(firstOperator) === -1) { + // Operator to apply is not explicit - assume 'or' + firstOperator = OR_CONDITION; + restOfConditions = conditions; + } + + switch (firstOperator) { + case AND_CONDITION: + return andEvaluator(restOfConditions, leafEvaluator); + case NOT_CONDITION: + return notEvaluator(restOfConditions, leafEvaluator); + default: + // firstOperator is OR_CONDITION + return orEvaluator(restOfConditions, leafEvaluator); + } + } + + var leafCondition = conditions; + return leafEvaluator(leafCondition); +} + +/** + * Evaluates an array of conditions as if the evaluator had been applied + * to each entry and the results AND-ed together. + * @param {Array} conditions Array of conditions ex: [operand_1, operand_2] + * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition values + * @return {?Boolean} Result of evaluating the conditions. A return value of null + * indicates that the conditions are invalid or unable to be + * evaluated. + */ +function andEvaluator(conditions, leafEvaluator) { + var sawNullResult = false; + for (var i = 0; i < conditions.length; i++) { + var conditionResult = evaluate(conditions[i], leafEvaluator); + if (conditionResult === false) { + return false; + } + if (conditionResult === null) { + sawNullResult = true; + } + } + return sawNullResult ? null : true; +} + +/** + * Evaluates an array of conditions as if the evaluator had been applied + * to a single entry and NOT was applied to the result. + * @param {Array} conditions Array of conditions ex: [operand_1] + * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition values + * @return {?Boolean} Result of evaluating the conditions. A return value of null + * indicates that the conditions are invalid or unable to be + * evaluated. + */ +function notEvaluator(conditions, leafEvaluator) { + if (conditions.length > 0) { + var result = evaluate(conditions[0], leafEvaluator); + return result === null ? null : !result; + } + return null; +} + +/** + * Evaluates an array of conditions as if the evaluator had been applied + * to each entry and the results OR-ed together. + * @param {Array} conditions Array of conditions ex: [operand_1, operand_2] + * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition values + * @return {?Boolean} Result of evaluating the conditions. A return value of null + * indicates that the conditions are invalid or unable to be + * evaluated. + */ +function orEvaluator(conditions, leafEvaluator) { + var sawNullResult = false; + for (var i = 0; i < conditions.length; i++) { + var conditionResult = evaluate(conditions[i], leafEvaluator); + if (conditionResult === true) { + return true; + } + if (conditionResult === null) { + sawNullResult = true; + } + } + return sawNullResult ? null : false; +} + +module.exports = { + evaluate: evaluate, +}; + + +/***/ }), +/* 32 */ +/***/ (function(module, exports, __webpack_require__) { + +/**************************************************************************** + * Copyright 2018-2019, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License 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 fns = __webpack_require__(11); +var enums = __webpack_require__(14); +var sprintf = __webpack_require__(12).sprintf; + +var LOG_LEVEL = enums.LOG_LEVEL; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var MODULE_NAME = 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR'; + +var EXACT_MATCH_TYPE = 'exact'; +var EXISTS_MATCH_TYPE = 'exists'; +var GREATER_THAN_MATCH_TYPE = 'gt'; +var LESS_THAN_MATCH_TYPE = 'lt'; +var SUBSTRING_MATCH_TYPE = 'substring'; + +var MATCH_TYPES = [ + EXACT_MATCH_TYPE, + EXISTS_MATCH_TYPE, + GREATER_THAN_MATCH_TYPE, + LESS_THAN_MATCH_TYPE, + SUBSTRING_MATCH_TYPE, +]; + +var EVALUATORS_BY_MATCH_TYPE = {}; +EVALUATORS_BY_MATCH_TYPE[EXACT_MATCH_TYPE] = exactEvaluator; +EVALUATORS_BY_MATCH_TYPE[EXISTS_MATCH_TYPE] = existsEvaluator; +EVALUATORS_BY_MATCH_TYPE[GREATER_THAN_MATCH_TYPE] = greaterThanEvaluator; +EVALUATORS_BY_MATCH_TYPE[LESS_THAN_MATCH_TYPE] = lessThanEvaluator; +EVALUATORS_BY_MATCH_TYPE[SUBSTRING_MATCH_TYPE] = substringEvaluator; + +/** + * Given a custom attribute audience condition and user attributes, evaluate the + * condition against the attributes. + * @param {Object} condition + * @param {Object} userAttributes + * @param {Object} logger + * @return {?Boolean} true/false if the given user attributes match/don't match the given condition, + * null if the given user attributes and condition can't be evaluated + * TODO: Change to accept and object with named properties + */ +function evaluate(condition, userAttributes, logger) { + var conditionMatch = condition.match; + if (typeof conditionMatch !== 'undefined' && MATCH_TYPES.indexOf(conditionMatch) === -1) { + logger.log(LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, JSON.stringify(condition))); + return null; + } + + var attributeKey = condition.name; + if (!userAttributes.hasOwnProperty(attributeKey) && conditionMatch != EXISTS_MATCH_TYPE) { + logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.MISSING_ATTRIBUTE_VALUE, MODULE_NAME, JSON.stringify(condition), attributeKey) + ); + return null; + } + + var evaluatorForMatch = EVALUATORS_BY_MATCH_TYPE[conditionMatch] || exactEvaluator; + return evaluatorForMatch(condition, userAttributes, logger); +} + +/** + * Returns true if the value is valid for exact conditions. Valid values include + * strings, booleans, and numbers that aren't NaN, -Infinity, or Infinity. + * @param value + * @returns {Boolean} + */ +function isValueTypeValidForExactConditions(value) { + return typeof value === 'string' || typeof value === 'boolean' || fns.isNumber(value); +} + +/** + * Evaluate the given exact match condition for the given user attributes + * @param {Object} condition + * @param {Object} userAttributes + * @param {Object} logger + * @return {?Boolean} true if the user attribute value is equal (===) to the condition value, + * false if the user attribute value is not equal (!==) to the condition value, + * null if the condition value or user attribute value has an invalid type, or + * if there is a mismatch between the user attribute type and the condition value + * type + */ +function exactEvaluator(condition, userAttributes, logger) { + var conditionValue = condition.value; + var conditionValueType = typeof conditionValue; + var conditionName = condition.name; + var userValue = userAttributes[conditionName]; + var userValueType = typeof userValue; + + if ( + !isValueTypeValidForExactConditions(conditionValue) || + (fns.isNumber(conditionValue) && !fns.isSafeInteger(conditionValue)) + ) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) + ); + return null; + } + + if (userValue === null) { + logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) + ); + return null; + } + + if (!isValueTypeValidForExactConditions(userValue) || conditionValueType !== userValueType) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) + ); + return null; + } + + if (fns.isNumber(userValue) && !fns.isSafeInteger(userValue)) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName) + ); + return null; + } + + return conditionValue === userValue; +} + +/** + * Evaluate the given exists match condition for the given user attributes + * @param {Object} condition + * @param {Object} userAttributes + * @returns {Boolean} true if both: + * 1) the user attributes have a value for the given condition, and + * 2) the user attribute value is neither null nor undefined + * Returns false otherwise + */ +function existsEvaluator(condition, userAttributes) { + var userValue = userAttributes[condition.name]; + return typeof userValue !== 'undefined' && userValue !== null; +} + +/** + * Evaluate the given greater than match condition for the given user attributes + * @param {Object} condition + * @param {Object} userAttributes + * @param {Object} logger + * @returns {?Boolean} true if the user attribute value is greater than the condition value, + * false if the user attribute value is less than or equal to the condition value, + * null if the condition value isn't a number or the user attribute value + * isn't a number + */ +function greaterThanEvaluator(condition, userAttributes, logger) { + var conditionName = condition.name; + var userValue = userAttributes[conditionName]; + var userValueType = typeof userValue; + var conditionValue = condition.value; + + if (!fns.isSafeInteger(conditionValue)) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) + ); + return null; + } + + if (userValue === null) { + logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) + ); + return null; + } + + if (!fns.isNumber(userValue)) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) + ); + return null; + } + + if (!fns.isSafeInteger(userValue)) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName) + ); + return null; + } + + return userValue > conditionValue; +} + +/** + * Evaluate the given less than match condition for the given user attributes + * @param {Object} condition + * @param {Object} userAttributes + * @param {Object} logger + * @returns {?Boolean} true if the user attribute value is less than the condition value, + * false if the user attribute value is greater than or equal to the condition value, + * null if the condition value isn't a number or the user attribute value isn't a + * number + */ +function lessThanEvaluator(condition, userAttributes, logger) { + var conditionName = condition.name; + var userValue = userAttributes[condition.name]; + var userValueType = typeof userValue; + var conditionValue = condition.value; + + if (!fns.isSafeInteger(conditionValue)) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) + ); + return null; + } + + if (userValue === null) { + logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) + ); + return null; + } + + if (!fns.isNumber(userValue)) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) + ); + return null; + } + + if (!fns.isSafeInteger(userValue)) { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName) + ); + return null; + } + + return userValue < conditionValue; +} + +/** + * Evaluate the given substring match condition for the given user attributes + * @param {Object} condition + * @param {Object} userAttributes + * @param {Object} logger + * @returns {?Boolean} true if the condition value is a substring of the user attribute value, + * false if the condition value is not a substring of the user attribute value, + * null if the condition value isn't a string or the user attribute value + * isn't a string + */ +function substringEvaluator(condition, userAttributes, logger) { + var conditionName = condition.name; + var userValue = userAttributes[condition.name]; + var userValueType = typeof userValue; + var conditionValue = condition.value; + + if (typeof conditionValue !== 'string') { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) + ); + return null; + } + + if (userValue === null) { + logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) + ); + return null; + } + + if (typeof userValue !== 'string') { + logger.log( + LOG_LEVEL.WARNING, + sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) + ); + return null; + } + + return userValue.indexOf(conditionValue) !== -1; +} + +module.exports = { + evaluate: evaluate, +}; + + +/***/ }), +/* 33 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016, 2019 Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ + +/** + * Bucketer API for determining the variation id from the specified parameters + */ +var enums = __webpack_require__(14); +var murmurhash = __webpack_require__(34); +var sprintf = __webpack_require__(12).sprintf; + +var ERROR_MESSAGES = enums.ERROR_MESSAGES; +var HASH_SEED = 1; +var LOG_LEVEL = enums.LOG_LEVEL; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var MAX_HASH_VALUE = Math.pow(2, 32); +var MAX_TRAFFIC_VALUE = 10000; +var MODULE_NAME = 'BUCKETER'; +var RANDOM_POLICY = 'random'; + +module.exports = { + /** + * Determines ID of variation to be shown for the given input params + * @param {Object} bucketerParams + * @param {string} bucketerParams.experimentId + * @param {string} bucketerParams.experimentKey + * @param {string} bucketerParams.userId + * @param {Object[]} bucketerParams.trafficAllocationConfig + * @param {Array} bucketerParams.experimentKeyMap + * @param {Object} bucketerParams.groupIdMap + * @param {Object} bucketerParams.variationIdMap + * @param {string} bucketerParams.varationIdMap[].key + * @param {Object} bucketerParams.logger + * @param {string} bucketerParams.bucketingId + * @return Variation ID that user has been bucketed into, null if user is not bucketed into any experiment + */ + bucket: function(bucketerParams) { + // Check if user is in a random group; if so, check if user is bucketed into a specific experiment + var experiment = bucketerParams.experimentKeyMap[bucketerParams.experimentKey]; + var groupId = experiment['groupId']; + if (groupId) { + var group = bucketerParams.groupIdMap[groupId]; + if (!group) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_GROUP_ID, MODULE_NAME, groupId)); + } + if (group.policy === RANDOM_POLICY) { + var bucketedExperimentId = module.exports.bucketUserIntoExperiment( + group, + bucketerParams.bucketingId, + bucketerParams.userId, + bucketerParams.logger + ); + + // Return if user is not bucketed into any experiment + if (bucketedExperimentId === null) { + var notbucketedInAnyExperimentLogMessage = sprintf( + LOG_MESSAGES.USER_NOT_IN_ANY_EXPERIMENT, + MODULE_NAME, + bucketerParams.userId, + groupId + ); + bucketerParams.logger.log(LOG_LEVEL.INFO, notbucketedInAnyExperimentLogMessage); + return null; + } + + // Return if user is bucketed into a different experiment than the one specified + if (bucketedExperimentId !== bucketerParams.experimentId) { + var notBucketedIntoExperimentOfGroupLogMessage = sprintf( + LOG_MESSAGES.USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + MODULE_NAME, + bucketerParams.userId, + bucketerParams.experimentKey, + groupId + ); + bucketerParams.logger.log(LOG_LEVEL.INFO, notBucketedIntoExperimentOfGroupLogMessage); + return null; + } + + // Continue bucketing if user is bucketed into specified experiment + var bucketedIntoExperimentOfGroupLogMessage = sprintf( + LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, + MODULE_NAME, + bucketerParams.userId, + bucketerParams.experimentKey, + groupId + ); + bucketerParams.logger.log(LOG_LEVEL.INFO, bucketedIntoExperimentOfGroupLogMessage); + } + } + var bucketingId = sprintf('%s%s', bucketerParams.bucketingId, bucketerParams.experimentId); + var bucketValue = module.exports._generateBucketValue(bucketingId); + + var bucketedUserLogMessage = sprintf( + LOG_MESSAGES.USER_ASSIGNED_TO_VARIATION_BUCKET, + MODULE_NAME, + bucketValue, + bucketerParams.userId + ); + bucketerParams.logger.log(LOG_LEVEL.DEBUG, bucketedUserLogMessage); + + var entityId = module.exports._findBucket(bucketValue, bucketerParams.trafficAllocationConfig); + if (!entityId) { + var userHasNoVariationLogMessage = sprintf( + LOG_MESSAGES.USER_HAS_NO_VARIATION, + MODULE_NAME, + bucketerParams.userId, + bucketerParams.experimentKey + ); + bucketerParams.logger.log(LOG_LEVEL.DEBUG, userHasNoVariationLogMessage); + } else if (!bucketerParams.variationIdMap.hasOwnProperty(entityId)) { + var invalidVariationIdLogMessage = sprintf(LOG_MESSAGES.INVALID_VARIATION_ID, MODULE_NAME); + bucketerParams.logger.log(LOG_LEVEL.WARNING, invalidVariationIdLogMessage); + return null; + } else { + var variationKey = bucketerParams.variationIdMap[entityId].key; + var userInVariationLogMessage = sprintf( + LOG_MESSAGES.USER_HAS_VARIATION, + MODULE_NAME, + bucketerParams.userId, + variationKey, + bucketerParams.experimentKey + ); + bucketerParams.logger.log(LOG_LEVEL.INFO, userInVariationLogMessage); + } + + return entityId; + }, + + /** + * Returns bucketed experiment ID to compare against experiment user is being called into + * @param {Object} group Group that experiment is in + * @param {string} bucketingId Bucketing ID + * @param {string} userId ID of user to be bucketed into experiment + * @param {Object} logger Logger implementation + * @return {string} ID of experiment if user is bucketed into experiment within the group, null otherwise + */ + bucketUserIntoExperiment: function(group, bucketingId, userId, logger) { + var bucketingKey = sprintf('%s%s', bucketingId, group.id); + var bucketValue = module.exports._generateBucketValue(bucketingKey); + logger.log( + LOG_LEVEL.DEBUG, + sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, MODULE_NAME, bucketValue, userId) + ); + var trafficAllocationConfig = group.trafficAllocation; + var bucketedExperimentId = module.exports._findBucket(bucketValue, trafficAllocationConfig); + return bucketedExperimentId; + }, + + /** + * Returns entity ID associated with bucket value + * @param {string} bucketValue + * @param {Object[]} trafficAllocationConfig + * @param {number} trafficAllocationConfig[].endOfRange + * @param {number} trafficAllocationConfig[].entityId + * @return {string} Entity ID for bucketing if bucket value is within traffic allocation boundaries, null otherwise + */ + _findBucket: function(bucketValue, trafficAllocationConfig) { + for (var i = 0; i < trafficAllocationConfig.length; i++) { + if (bucketValue < trafficAllocationConfig[i].endOfRange) { + return trafficAllocationConfig[i].entityId; + } + } + return null; + }, + + /** + * Helper function to generate bucket value in half-closed interval [0, MAX_TRAFFIC_VALUE) + * @param {string} bucketingKey String value for bucketing + * @return {string} the generated bucket value + * @throws If bucketing value is not a valid string + */ + _generateBucketValue: function(bucketingKey) { + try { + // NOTE: the mmh library already does cast the hash value as an unsigned 32bit int + // https://github.com/perezd/node-murmurhash/blob/master/murmurhash.js#L115 + var hashValue = murmurhash.v3(bucketingKey, HASH_SEED); + var ratio = hashValue / MAX_HASH_VALUE; + return parseInt(ratio * MAX_TRAFFIC_VALUE, 10); + } catch (ex) { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_BUCKETING_ID, MODULE_NAME, bucketingKey, ex.message)); + } + }, +}; + + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __webpack_require__) { + +(function(){ + var _global = this; + + /** + * JS Implementation of MurmurHash2 + * + * @author Gary Court + * @see http://github.com/garycourt/murmurhash-js + * @author Austin Appleby + * @see http://sites.google.com/site/murmurhash/ + * + * @param {string} str ASCII only + * @param {number} seed Positive integer only + * @return {number} 32-bit positive integer hash + */ + function MurmurHashV2(str, seed) { + var + l = str.length, + h = seed ^ l, + i = 0, + k; + + while (l >= 4) { + k = + ((str.charCodeAt(i) & 0xff)) | + ((str.charCodeAt(++i) & 0xff) << 8) | + ((str.charCodeAt(++i) & 0xff) << 16) | + ((str.charCodeAt(++i) & 0xff) << 24); + + k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + k ^= k >>> 24; + k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + + h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k; + + l -= 4; + ++i; + } + + switch (l) { + case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16; + case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8; + case 1: h ^= (str.charCodeAt(i) & 0xff); + h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + } + + h ^= h >>> 13; + h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); + h ^= h >>> 15; + + return h >>> 0; + }; + + /** + * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011) + * + * @author Gary Court + * @see http://github.com/garycourt/murmurhash-js + * @author Austin Appleby + * @see http://sites.google.com/site/murmurhash/ + * + * @param {string} key ASCII only + * @param {number} seed Positive integer only + * @return {number} 32-bit positive integer hash + */ + function MurmurHashV3(key, seed) { + var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i; + + remainder = key.length & 3; // key.length % 4 + bytes = key.length - remainder; + h1 = seed; + c1 = 0xcc9e2d51; + c2 = 0x1b873593; + i = 0; + + while (i < bytes) { + k1 = + ((key.charCodeAt(i) & 0xff)) | + ((key.charCodeAt(++i) & 0xff) << 8) | + ((key.charCodeAt(++i) & 0xff) << 16) | + ((key.charCodeAt(++i) & 0xff) << 24); + ++i; + + k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); + h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; + h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); + } + + k1 = 0; + + switch (remainder) { + case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; + case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; + case 1: k1 ^= (key.charCodeAt(i) & 0xff); + + k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; + h1 ^= k1; + } + + h1 ^= key.length; + + h1 ^= h1 >>> 16; + h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; + h1 ^= h1 >>> 13; + h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; + h1 ^= h1 >>> 16; + + return h1 >>> 0; + } + + var murmur = MurmurHashV3; + murmur.v2 = MurmurHashV2; + murmur.v3 = MurmurHashV3; + + if (true) { + module.exports = murmur; + } else { var _previousRoot; } +}()); + + +/***/ }), +/* 35 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016-2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 fns = __webpack_require__(11); +var enums = __webpack_require__(14); +var jsSdkUtils = __webpack_require__(12); +var configValidator = __webpack_require__(13); +var projectConfigSchema = __webpack_require__(36); + +var EXPERIMENT_RUNNING_STATUS = 'Running'; +var RESERVED_ATTRIBUTE_PREFIX = '$opt_'; +var MODULE_NAME = 'PROJECT_CONFIG'; + +var ERROR_MESSAGES = enums.ERROR_MESSAGES; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var LOG_LEVEL = enums.LOG_LEVEL; +var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES; + +module.exports = { + /** + * Creates projectConfig object to be used for quick project property lookup + * @param {Object} datafile JSON datafile representing the project + * @return {Object} Object representing project configuration + */ + createProjectConfig: function(datafile) { + var projectConfig = fns.assign({}, datafile); + + /* + * Conditions of audiences in projectConfig.typedAudiences are not + * expected to be string-encoded as they are here in projectConfig.audiences. + */ + (projectConfig.audiences || []).forEach(function(audience) { + audience.conditions = JSON.parse(audience.conditions); + }); + projectConfig.audiencesById = fns.keyBy(projectConfig.audiences, 'id'); + fns.assign(projectConfig.audiencesById, fns.keyBy(projectConfig.typedAudiences, 'id')); + + projectConfig.attributeKeyMap = fns.keyBy(projectConfig.attributes, 'key'); + projectConfig.eventKeyMap = fns.keyBy(projectConfig.events, 'key'); + projectConfig.groupIdMap = fns.keyBy(projectConfig.groups, 'id'); + + var experiments; + Object.keys(projectConfig.groupIdMap || {}).forEach(function(Id) { + experiments = projectConfig.groupIdMap[Id].experiments; + (experiments || []).forEach(function(experiment) { + projectConfig.experiments.push(fns.assign(experiment, { groupId: Id })); + }); + }); + + projectConfig.rolloutIdMap = fns.keyBy(projectConfig.rollouts || [], 'id'); + jsSdkUtils.objectValues(projectConfig.rolloutIdMap || {}).forEach(function (rollout) { + (rollout.experiments || []).forEach(function(experiment) { + projectConfig.experiments.push(experiment); + // Creates { : } map inside of the experiment + experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); + }); + }); + + projectConfig.experimentKeyMap = fns.keyBy(projectConfig.experiments, 'key'); + projectConfig.experimentIdMap = fns.keyBy(projectConfig.experiments, 'id'); + + projectConfig.variationIdMap = {}; + projectConfig.variationVariableUsageMap = {}; + (projectConfig.experiments || []).forEach(function(experiment) { + // Creates { : } map inside of the experiment + experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); + + // Creates { : { key: , id: } } mapping for quick lookup + fns.assign(projectConfig.variationIdMap, fns.keyBy(experiment.variations, 'id')); + jsSdkUtils.objectValues(experiment.variationKeyMap || {}).forEach(function(variation) { + if (variation.variables) { + projectConfig.variationVariableUsageMap[variation.id] = fns.keyBy(variation.variables, 'id'); + } + }); + }); + + // Object containing experiment Ids that exist in any feature + // for checking that experiment is a feature experiment or not. + projectConfig.experimentFeatureMap = {}; + + projectConfig.featureKeyMap = fns.keyBy(projectConfig.featureFlags || [], 'key'); + jsSdkUtils.objectValues(projectConfig.featureKeyMap || {}).forEach(function(feature) { + feature.variableKeyMap = fns.keyBy(feature.variables, 'key'); + (feature.experimentIds || []).forEach(function(experimentId) { + // Add this experiment in experiment-feature map. + if (projectConfig.experimentFeatureMap[experimentId]) { + projectConfig.experimentFeatureMap[experimentId].push(feature.id); + } else { + projectConfig.experimentFeatureMap[experimentId] = [feature.id]; + } + + var experimentInFeature = projectConfig.experimentIdMap[experimentId]; + // Experiments in feature can only belong to one mutex group. + if (experimentInFeature.groupId && !feature.groupId) { + feature.groupId = experimentInFeature.groupId; + } + }); + }); + + return projectConfig; + }, + + /** + * Get experiment ID for the provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which ID is to be determined + * @return {string} Experiment ID corresponding to the provided experiment key + * @throws If experiment key is not in datafile + */ + getExperimentId: function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + return experiment.id; + }, + + /** + * Get layer ID for the provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentId Experiment ID for which layer ID is to be determined + * @return {string} Layer ID corresponding to the provided experiment key + * @throws If experiment key is not in datafile + */ + getLayerId: function(projectConfig, experimentId) { + var experiment = projectConfig.experimentIdMap[experimentId]; + if (!experiment) { + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); + } + return experiment.layerId; + }, + + /** + * Get attribute ID for the provided attribute key + * @param {Object} projectConfig Object representing project configuration + * @param {string} attributeKey Attribute key for which ID is to be determined + * @param {Object} logger + * @return {string|null} Attribute ID corresponding to the provided attribute key. Attribute key if it is a reserved attribute. + */ + getAttributeId: function(projectConfig, attributeKey, logger) { + var attribute = projectConfig.attributeKeyMap[attributeKey]; + var hasReservedPrefix = attributeKey.indexOf(RESERVED_ATTRIBUTE_PREFIX) === 0; + if (attribute) { + if (hasReservedPrefix) { + logger.log( + LOG_LEVEL.WARN, + jsSdkUtils.sprintf( + 'Attribute %s unexpectedly has reserved prefix %s; using attribute ID instead of reserved attribute name.', + attributeKey, + RESERVED_ATTRIBUTE_PREFIX + ) + ); + } + return attribute.id; + } else if (hasReservedPrefix) { + return attributeKey; + } + + logger.log(LOG_LEVEL.DEBUG, jsSdkUtils.sprintf(ERROR_MESSAGES.UNRECOGNIZED_ATTRIBUTE, MODULE_NAME, attributeKey)); + return null; + }, + + /** + * Get event ID for the provided + * @param {Object} projectConfig Object representing project configuration + * @param {string} eventKey Event key for which ID is to be determined + * @return {string|null} Event ID corresponding to the provided event key + */ + getEventId: function(projectConfig, eventKey) { + var event = projectConfig.eventKeyMap[eventKey]; + if (event) { + return event.id; + } + return null; + }, + + /** + * Get experiment status for the provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which status is to be determined + * @return {string} Experiment status corresponding to the provided experiment key + * @throws If experiment key is not in datafile + */ + getExperimentStatus: function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + return experiment.status; + }, + + /** + * Returns whether experiment has a status of 'Running' + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which status is to be compared with 'Running' + * @return {Boolean} true if experiment status is set to 'Running', false otherwise + */ + isActive: function(projectConfig, experimentKey) { + return module.exports.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; + }, + + /** + * Determine for given experiment if event is running, which determines whether should be dispatched or not + */ + isRunning: function(projectConfig, experimentKey) { + return module.exports.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; + }, + + /** + * Get audience conditions for the experiment + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Experiment key for which audience conditions are to be determined + * @return {Array} Audience conditions for the experiment - can be an array of audience IDs, or a + * nested array of conditions + * Examples: ["5", "6"], ["and", ["or", "1", "2"], "3"] + * @throws If experiment key is not in datafile + */ + getExperimentAudienceConditions: function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + + return experiment.audienceConditions || experiment.audienceIds; + }, + + /** + * Get variation key given experiment key and variation ID + * @param {Object} projectConfig Object representing project configuration + * @param {string} variationId ID of the variation + * @return {string} Variation key or null if the variation ID is not found + */ + getVariationKeyFromId: function(projectConfig, variationId) { + if (projectConfig.variationIdMap.hasOwnProperty(variationId)) { + return projectConfig.variationIdMap[variationId].key; + } + return null; + }, + + /** + * Get the variation ID given the experiment key and variation key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Key of the experiment the variation belongs to + * @param {string} variationKey The variation key + * @return {string} the variation ID + */ + getVariationIdFromExperimentAndVariationKey: function(projectConfig, experimentKey, variationKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (experiment.variationKeyMap.hasOwnProperty(variationKey)) { + return experiment.variationKeyMap[variationKey].id; + } + return null; + }, + + /** + * Get experiment from provided experiment key + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Event key for which experiment IDs are to be retrieved + * @return {Object} experiment + * @throws If experiment key is not in datafile + */ + getExperimentFromKey: function(projectConfig, experimentKey) { + if (projectConfig.experimentKeyMap.hasOwnProperty(experimentKey)) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (experiment) { + return experiment; + } + } + + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.EXPERIMENT_KEY_NOT_IN_DATAFILE, MODULE_NAME, experimentKey)); + }, + + /** + * Given an experiment key, returns the traffic allocation within that experiment + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentKey Key representing the experiment + * @return {Array} Traffic allocation for the experiment + * @throws If experiment key is not in datafile + */ + getTrafficAllocation: function(projectConfig, experimentKey) { + var experiment = projectConfig.experimentKeyMap[experimentKey]; + if (!experiment) { + throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); + } + return experiment.trafficAllocation; + }, + + /** + * Get experiment from provided experiment id. Log an error if no experiment + * exists in the project config with the given ID. + * @param {Object} projectConfig Object representing project configuration + * @param {string} experimentId ID of desired experiment object + * @return {Object} Experiment object + */ + getExperimentFromId: function(projectConfig, experimentId, logger) { + if (projectConfig.experimentIdMap.hasOwnProperty(experimentId)) { + var experiment = projectConfig.experimentIdMap[experimentId]; + if (experiment) { + return experiment; + } + } + + logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); + return null; + }, + + /** + * Get feature from provided feature key. Log an error if no feature exists in + * the project config with the given key. + * @param {Object} projectConfig + * @param {string} featureKey + * @param {Object} logger + * @return {Object|null} Feature object, or null if no feature with the given + * key exists + */ + getFeatureFromKey: function(projectConfig, featureKey, logger) { + if (projectConfig.featureKeyMap.hasOwnProperty(featureKey)) { + var feature = projectConfig.featureKeyMap[featureKey]; + if (feature) { + return feature; + } + } + + logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); + return null; + }, + + /** + * Get the variable with the given key associated with the feature with the + * given key. If the feature key or the variable key are invalid, log an error + * message. + * @param {Object} projectConfig + * @param {string} featureKey + * @param {string} variableKey + * @param {Object} logger + * @return {Object|null} Variable object, or null one or both of the given + * feature and variable keys are invalid + */ + getVariableForFeature: function(projectConfig, featureKey, variableKey, logger) { + var feature = projectConfig.featureKeyMap[featureKey]; + if (!feature) { + logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); + return null; + } + + var variable = feature.variableKeyMap[variableKey]; + if (!variable) { + logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(ERROR_MESSAGES.VARIABLE_KEY_NOT_IN_DATAFILE, MODULE_NAME, variableKey, featureKey) + ); + return null; + } + + return variable; + }, + + /** + * Get the value of the given variable for the given variation. If the given + * variable has no value for the given variation, return null. Log an error message if the variation is invalid. If the + * variable or variation are invalid, return null. + * @param {Object} projectConfig + * @param {Object} variable + * @param {Object} variation + * @param {Object} logger + * @return {string|null} The value of the given variable for the given + * variation, or null if the given variable has no value + * for the given variation or if the variation or variable are invalid + */ + getVariableValueForVariation: function(projectConfig, variable, variation, logger) { + if (!variable || !variation) { + return null; + } + + if (!projectConfig.variationVariableUsageMap.hasOwnProperty(variation.id)) { + logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(ERROR_MESSAGES.VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT, MODULE_NAME, variation.id) + ); + return null; + } + + var variableUsages = projectConfig.variationVariableUsageMap[variation.id]; + var variableUsage = variableUsages[variable.id]; + + return variableUsage ? variableUsage.value : null; + }, + + /** + * Given a variable value in string form, try to cast it to the argument type. + * If the type cast succeeds, return the type casted value, otherwise log an + * error and return null. + * @param {string} variableValue Variable value in string form + * @param {string} variableType Type of the variable whose value was passed + * in the first argument. Must be one of + * FEATURE_VARIABLE_TYPES in + * lib/utils/enums/index.js. The return value's + * type is determined by this argument (boolean + * for BOOLEAN, number for INTEGER or DOUBLE, + * and string for STRING). + * @param {Object} logger Logger instance + * @returns {*} Variable value of the appropriate type, or + * null if the type cast failed + */ + getTypeCastValue: function(variableValue, variableType, logger) { + var castValue; + + switch (variableType) { + case FEATURE_VARIABLE_TYPES.BOOLEAN: + if (variableValue !== 'true' && variableValue !== 'false') { + logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) + ); + castValue = null; + } else { + castValue = variableValue === 'true'; + } + break; + + case FEATURE_VARIABLE_TYPES.INTEGER: + castValue = parseInt(variableValue, 10); + if (isNaN(castValue)) { + logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) + ); + castValue = null; + } + break; + + case FEATURE_VARIABLE_TYPES.DOUBLE: + castValue = parseFloat(variableValue); + if (isNaN(castValue)) { + logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) + ); + castValue = null; + } + break; + + default: + // type is STRING + castValue = variableValue; + break; + } + + return castValue; + }, + + /** + * Returns an object containing all audiences in the project config. Keys are audience IDs + * and values are audience objects. + * @param projectConfig + * @returns {Object} + */ + getAudiencesById: function(projectConfig) { + return projectConfig.audiencesById; + }, + + /** + * Returns true if an event with the given key exists in the datafile, and false otherwise + * @param {Object} projectConfig + * @param {string} eventKey + * @returns {boolean} + */ + eventWithKeyExists: function(projectConfig, eventKey) { + return projectConfig.eventKeyMap.hasOwnProperty(eventKey); + }, + + /** + * + * @param {Object} projectConfig + * @param {string} experimentId + * @returns {boolean} Returns true if experiment belongs to + * any feature, false otherwise. + */ + isFeatureExperiment: function(projectConfig, experimentId) { + return projectConfig.experimentFeatureMap.hasOwnProperty(experimentId); + }, + + /** + * Try to create a project config object from the given datafile and + * configuration properties. + * If successful, return the project config object, otherwise throws an error + * @param {Object} config + * @param {Object} config.datafile + * @param {Object} config.jsonSchemaValidator + * @param {Object} config.logger + * @param {Object} config.skipJSONValidation + * @return {Object} Project config object + */ + tryCreatingProjectConfig: function(config) { + configValidator.validateDatafile(config.datafile); + if (config.skipJSONValidation === true) { + config.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.SKIPPING_JSON_VALIDATION, MODULE_NAME)); + } else if (config.jsonSchemaValidator) { + config.jsonSchemaValidator.validate(projectConfigSchema, config.datafile); + config.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.VALID_DATAFILE, MODULE_NAME)); + } + return module.exports.createProjectConfig(config.datafile); + }, +}; + + +/***/ }), +/* 36 */ +/***/ (function(module, exports) { + +/** + * Copyright 2016-2017, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ + +/*eslint-disable */ +/** + * Project Config JSON Schema file used to validate the project json datafile + */ +module.exports = { + $schema: 'http://json-schema.org/draft-04/schema#', + type: 'object', + properties: { + projectId: { + type: 'string', + required: true, + }, + accountId: { + type: 'string', + required: true, + }, + groups: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + required: true, + }, + policy: { + type: 'string', + required: true, + }, + trafficAllocation: { + type: 'array', + items: { + type: 'object', + properties: { + entityId: { + type: 'string', + required: true, + }, + endOfRange: { + type: 'integer', + required: true, + }, + }, + }, + required: true, + }, + experiments: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + required: true, + }, + key: { + type: 'string', + required: true, + }, + status: { + type: 'string', + required: true, + }, + layerId: { + type: 'string', + required: true, + }, + variations: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + required: true, + }, + key: { + type: 'string', + required: true, + }, + }, + }, + required: true, + }, + trafficAllocation: { + type: 'array', + items: { + type: 'object', + properties: { + entityId: { + type: 'string', + required: true, + }, + endOfRange: { + type: 'integer', + required: true, + }, + }, + }, + required: true, + }, + audienceIds: { + type: 'array', + items: { + type: 'string', + }, + required: true, + }, + forcedVariations: { + type: 'object', + required: true, + }, + }, + }, + required: true, + }, + }, + }, + required: true, + }, + experiments: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + required: true, + }, + key: { + type: 'string', + required: true, + }, + status: { + type: 'string', + required: true, + }, + layerId: { + type: 'string', + required: true, + }, + variations: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + required: true, + }, + key: { + type: 'string', + required: true, + }, + }, + }, + required: true, + }, + trafficAllocation: { + type: 'array', + items: { + type: 'object', + properties: { + entityId: { + type: 'string', + required: true, + }, + endOfRange: { + type: 'integer', + required: true, + }, + }, + }, + required: true, + }, + audienceIds: { + type: 'array', + items: { + type: 'string', + }, + required: true, + }, + forcedVariations: { + type: 'object', + required: true, + }, + }, + }, + required: true, + }, + events: { + type: 'array', + items: { + type: 'object', + properties: { + key: { + type: 'string', + required: true, + }, + experimentIds: { + type: 'array', + items: { + type: 'string', + required: true, + }, + }, + id: { + type: 'string', + required: true, + }, + }, + }, + required: true, + }, + audiences: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + required: true, + }, + name: { + type: 'string', + required: true, + }, + conditions: { + type: 'string', + required: true, + }, + }, + }, + required: true, + }, + attributes: { + type: 'array', + items: { + type: 'object', + properties: { + id: { + type: 'string', + required: true, + }, + key: { + type: 'string', + required: true, + }, + }, + }, + required: true, + }, + version: { + type: 'string', + required: true, + }, + revision: { + type: 'string', + required: true, + }, + }, +}; + + +/***/ }), +/* 37 */ +/***/ (function(module, exports) { + +/** + * Copyright 2018, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ + +module.exports = { + /** + * Validates provided value is a non-empty string + * @param {string} input + * @return {boolean} True for non-empty string, false otherwise + */ + validate: function(input) { + return typeof input === 'string' && input !== ''; + }, +}; + + +/***/ }), +/* 38 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2016-2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 enums = __webpack_require__(14); +var fns = __webpack_require__(11); +var eventTagUtils = __webpack_require__(39); +var projectConfig = __webpack_require__(35); +var attributeValidator = __webpack_require__(28); + +var ACTIVATE_EVENT_KEY = 'campaign_activated'; +var CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom'; +var ENDPOINT = 'https://logx.optimizely.com/v1/events'; +var HTTP_VERB = 'POST'; + +/** + * Get params which are used same in both conversion and impression events + * @param {Object} options.attributes Object representing user attributes and values which need to be recorded + * @param {string} options.clientEngine The client we are using: node or javascript + * @param {string} options.clientVersion The version of the client + * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup + * @param {string} options.userId ID for user + * @param {Object} options.Logger logger + * @return {Object} Common params with properties that are used in both conversion and impression events + */ +function getCommonEventParams(options) { + var attributes = options.attributes; + var configObj = options.configObj; + var anonymize_ip = configObj.anonymizeIP; + var botFiltering = configObj.botFiltering; + if (anonymize_ip === null || anonymize_ip === undefined) { + anonymize_ip = false; + } + + var visitor = { + snapshots: [], + visitor_id: options.userId, + attributes: [], + }; + + var commonParams = { + account_id: configObj.accountId, + project_id: configObj.projectId, + visitors: [visitor], + revision: configObj.revision, + client_name: options.clientEngine, + client_version: options.clientVersion, + anonymize_ip: anonymize_ip, + enrich_decisions: true, + }; + + // Omit attribute values that are not supported by the log endpoint. + Object.keys(attributes || {}).forEach(function(attributeKey) { + var attributeValue = attributes[attributeKey]; + if (attributeValidator.isAttributeValid(attributeKey, attributeValue)) { + var attributeId = projectConfig.getAttributeId(options.configObj, attributeKey, options.logger); + if (attributeId) { + commonParams.visitors[0].attributes.push({ + entity_id: attributeId, + key: attributeKey, + type: CUSTOM_ATTRIBUTE_FEATURE_TYPE, + value: attributes[attributeKey], + }); + } + } + }); + + if (typeof botFiltering === 'boolean') { + commonParams.visitors[0].attributes.push({ + entity_id: enums.CONTROL_ATTRIBUTES.BOT_FILTERING, + key: enums.CONTROL_ATTRIBUTES.BOT_FILTERING, + type: CUSTOM_ATTRIBUTE_FEATURE_TYPE, + value: botFiltering, + }); + } + return commonParams; +} + +/** + * Creates object of params specific to impression events + * @param {Object} configObj Object representing project configuration + * @param {string} experimentId ID of experiment for which impression needs to be recorded + * @param {string} variationId ID for variation which would be presented to user + * @return {Object} Impression event params + */ +function getImpressionEventParams(configObj, experimentId, variationId) { + var impressionEventParams = { + decisions: [ + { + campaign_id: projectConfig.getLayerId(configObj, experimentId), + experiment_id: experimentId, + variation_id: variationId, + }, + ], + events: [ + { + entity_id: projectConfig.getLayerId(configObj, experimentId), + timestamp: fns.currentTimestamp(), + key: ACTIVATE_EVENT_KEY, + uuid: fns.uuid(), + }, + ], + }; + return impressionEventParams; +} + +/** + * Creates object of params specific to conversion events + * @param {Object} configObj Object representing project configuration + * @param {string} eventKey Event key representing the event which needs to be recorded + * @param {Object} eventTags Values associated with the event. + * @param {Object} logger Logger object + * @return {Object} Conversion event params + */ +function getVisitorSnapshot(configObj, eventKey, eventTags, logger) { + var snapshot = { + events: [], + }; + + var eventDict = { + entity_id: projectConfig.getEventId(configObj, eventKey), + timestamp: fns.currentTimestamp(), + uuid: fns.uuid(), + key: eventKey, + }; + + if (eventTags) { + var revenue = eventTagUtils.getRevenueValue(eventTags, logger); + if (revenue !== null) { + eventDict[enums.RESERVED_EVENT_KEYWORDS.REVENUE] = revenue; + } + + var eventValue = eventTagUtils.getEventValue(eventTags, logger); + if (eventValue !== null) { + eventDict[enums.RESERVED_EVENT_KEYWORDS.VALUE] = eventValue; + } + + eventDict['tags'] = eventTags; + } + snapshot.events.push(eventDict); + + return snapshot; +} + +module.exports = { + /** + * Create impression event params to be sent to the logging endpoint + * @param {Object} options Object containing values needed to build impression event + * @param {Object} options.attributes Object representing user attributes and values which need to be recorded + * @param {string} options.clientEngine The client we are using: node or javascript + * @param {string} options.clientVersion The version of the client + * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup + * @param {string} options.experimentId Experiment for which impression needs to be recorded + * @param {string} options.userId ID for user + * @param {string} options.variationId ID for variation which would be presented to user + * @return {Object} Params to be used in impression event logging endpoint call + */ + getImpressionEvent: function(options) { + var impressionEvent = { + httpVerb: HTTP_VERB, + }; + + var commonParams = getCommonEventParams(options); + impressionEvent.url = ENDPOINT; + + var impressionEventParams = getImpressionEventParams(options.configObj, options.experimentId, options.variationId); + // combine Event params into visitor obj + commonParams.visitors[0].snapshots.push(impressionEventParams); + + impressionEvent.params = commonParams; + + return impressionEvent; + }, + + /** + * Create conversion event params to be sent to the logging endpoint + * @param {Object} options Object containing values needed to build conversion event + * @param {Object} options.attributes Object representing user attributes and values which need to be recorded + * @param {string} options.clientEngine The client we are using: node or javascript + * @param {string} options.clientVersion The version of the client + * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup + * @param {string} options.eventKey Event key representing the event which needs to be recorded + * @param {Object} options.eventTags Object with event-specific tags + * @param {Object} options.logger Logger object + * @param {string} options.userId ID for user + * @return {Object} Params to be used in conversion event logging endpoint call + */ + getConversionEvent: function(options) { + var conversionEvent = { + httpVerb: HTTP_VERB, + }; + + var commonParams = getCommonEventParams(options); + conversionEvent.url = ENDPOINT; + + var snapshot = getVisitorSnapshot(options.configObj, options.eventKey, options.eventTags, options.logger); + + commonParams.visitors[0].snapshots = [snapshot]; + conversionEvent.params = commonParams; + + return conversionEvent; + }, +}; + + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2017, 2019 Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ + +/** + * Provides utility method for parsing event tag values + */ +var enums = __webpack_require__(14); +var sprintf = __webpack_require__(12).sprintf; + +var LOG_LEVEL = enums.LOG_LEVEL; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var MODULE_NAME = 'EVENT_TAG_UTILS'; +var REVENUE_EVENT_METRIC_NAME = enums.RESERVED_EVENT_KEYWORDS.REVENUE; +var VALUE_EVENT_METRIC_NAME = enums.RESERVED_EVENT_KEYWORDS.VALUE; + +module.exports = { + /** + * Grab the revenue value from the event tags. "revenue" is a reserved keyword. + * @param {Object} eventTags + * @param {Object} logger + * @return {Integer|null} + */ + getRevenueValue: function(eventTags, logger) { + if (eventTags && eventTags.hasOwnProperty(REVENUE_EVENT_METRIC_NAME)) { + var rawValue = eventTags[REVENUE_EVENT_METRIC_NAME]; + var parsedRevenueValue = parseInt(rawValue, 10); + if (isNaN(parsedRevenueValue)) { + logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FAILED_TO_PARSE_REVENUE, MODULE_NAME, rawValue)); + return null; + } + logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.PARSED_REVENUE_VALUE, MODULE_NAME, parsedRevenueValue)); + return parsedRevenueValue; + } + return null; + }, + + /** + * Grab the event value from the event tags. "value" is a reserved keyword. + * @param {Object} eventTags + * @param {Object} logger + * @return {Number|null} + */ + getEventValue: function(eventTags, logger) { + if (eventTags && eventTags.hasOwnProperty(VALUE_EVENT_METRIC_NAME)) { + var rawValue = eventTags[VALUE_EVENT_METRIC_NAME]; + var parsedEventValue = parseFloat(rawValue); + if (isNaN(parsedEventValue)) { + logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FAILED_TO_PARSE_VALUE, MODULE_NAME, rawValue)); + return null; + } + logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.PARSED_NUMERIC_VALUE, MODULE_NAME, parsedEventValue)); + return parsedEventValue; + } + return null; + }, +}; + + +/***/ }), +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 logging = __webpack_require__(1); + +var attributesValidator = __webpack_require__(28); +var fns = __webpack_require__(11); +var eventTagUtils = __webpack_require__(39); +var projectConfig = __webpack_require__(35); + +var logger = logging.getLogger('EVENT_BUILDER'); + +/** + * Creates an ImpressionEvent object from decision data + * @param {Object} config + * @param {Object} config.configObj + * @param {String} config.experimentKey + * @param {String} config.variationKey + * @param {String} config.userId + * @param {Object} config.userAttributes + * @param {String} config.clientEngine + * @param {String} config.clientVersion + * @return {Object} an ImpressionEvent object + */ +exports.buildImpressionEvent = function buildImpressionEvent(config) { + var configObj = config.configObj; + var experimentKey = config.experimentKey; + var variationKey = config.variationKey; + var userId = config.userId; + var userAttributes = config.userAttributes; + var clientEngine = config.clientEngine; + var clientVersion = config.clientVersion; + + var variationId = projectConfig.getVariationIdFromExperimentAndVariationKey(configObj, experimentKey, variationKey); + var experimentId = projectConfig.getExperimentId(configObj, experimentKey); + var layerId = projectConfig.getLayerId(configObj, experimentId); + + return { + type: 'impression', + timestamp: fns.currentTimestamp(), + uuid: fns.uuid(), + + user: { + id: userId, + attributes: buildVisitorAttributes(configObj, userAttributes), + }, + + context: { + accountId: configObj.accountId, + projectId: configObj.projectId, + revision: configObj.revision, + clientName: clientEngine, + clientVersion: clientVersion, + anonymizeIP: configObj.anonymizeIP || false, + botFiltering: configObj.botFiltering, + }, + + layer: { + id: layerId, + }, + + experiment: { + id: experimentId, + key: experimentKey, + }, + + variation: { + id: variationId, + key: variationKey, + }, + }; +}; + +/** + * Creates a ConversionEvent object from track + * @param {Object} config + * @param {Object} config.configObj + * @param {String} config.eventKey + * @param {Object|undefined} config.eventTags + * @param {String} config.userId + * @param {Object} config.userAttributes + * @param {String} config.clientEngine + * @param {String} config.clientVersion + * @return {Object} a ConversionEvent object + */ +exports.buildConversionEvent = function buildConversionEvent(config) { + var configObj = config.configObj; + var userId = config.userId; + var userAttributes = config.userAttributes; + var clientEngine = config.clientEngine; + var clientVersion = config.clientVersion; + + var eventKey = config.eventKey; + var eventTags = config.eventTags; + var eventId = projectConfig.getEventId(configObj, eventKey); + + return { + type: 'conversion', + timestamp: fns.currentTimestamp(), + uuid: fns.uuid(), + + user: { + id: userId, + attributes: buildVisitorAttributes(configObj, userAttributes), + }, + + context: { + accountId: configObj.accountId, + projectId: configObj.projectId, + revision: configObj.revision, + clientName: clientEngine, + clientVersion: clientVersion, + anonymizeIP: configObj.anonymizeIP || false, + botFiltering: configObj.botFiltering, + }, + + event: { + id: eventId, + key: eventKey, + }, + + revenue: eventTagUtils.getRevenueValue(eventTags, logger), + value: eventTagUtils.getEventValue(eventTags, logger), + tags: eventTags, + }; +}; + +function buildVisitorAttributes(configObj, attributes) { + var builtAttributes = []; + // Omit attribute values that are not supported by the log endpoint. + Object.keys(attributes || {}).forEach(function(attributeKey) { + var attributeValue = attributes[attributeKey]; + if (attributesValidator.isAttributeValid(attributeKey, attributeValue)) { + var attributeId = projectConfig.getAttributeId(configObj, attributeKey, logger); + if (attributeId) { + builtAttributes.push({ + entityId: attributeId, + key: attributeKey, + value: attributes[attributeKey], + }); + } + } + }); + + return builtAttributes; +} + + +/***/ }), +/* 41 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2017, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ + +/** + * Provides utility method for validating that event tags user has provided are valid + */ + +var sprintf = __webpack_require__(12).sprintf; + +var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; +var MODULE_NAME = 'EVENT_TAGS_VALIDATOR'; + +module.exports = { + /** + * Validates user's provided event tags + * @param {Object} event tags + * @return {boolean} True if event tags are valid + * @throws If event tags are not valid + */ + validate: function(eventTags) { + if (typeof eventTags === 'object' && !Array.isArray(eventTags) && eventTags !== null) { + return true; + } else { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_EVENT_TAGS, MODULE_NAME)); + } + }, +}; + + +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2017, 2019 Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 enums = __webpack_require__(14); +var jsSdkUtils = __webpack_require__(12); + +var LOG_LEVEL = enums.LOG_LEVEL; +var LOG_MESSAGES = enums.LOG_MESSAGES; +var MODULE_NAME = 'NOTIFICATION_CENTER'; + +/** + * NotificationCenter allows registration and triggering of callback functions using + * notification event types defined in NOTIFICATION_TYPES of utils/enums/index.js: + * - ACTIVATE: An impression event will be sent to Optimizely. + * - TRACK a conversion event will be sent to Optimizely + * @constructor + * @param {Object} options + * @param {Object} options.logger An instance of a logger to log messages with + * @param {object} options.errorHandler An instance of errorHandler to handle any unexpected error + * @returns {Object} + */ +function NotificationCenter(options) { + this.logger = options.logger; + this.errorHandler = options.errorHandler; + this.__notificationListeners = {}; + + jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).forEach( + function(notificationTypeEnum) { + this.__notificationListeners[notificationTypeEnum] = []; + }.bind(this) + ); + this.__listenerId = 1; +} + +/** + * Add a notification callback to the notification center + * @param {string} notificationType One of the values from NOTIFICATION_TYPES in utils/enums/index.js + * @param {Function} callback Function that will be called when the event is triggered + * @returns {number} If the callback was successfully added, returns a listener ID which can be used + * to remove the callback by calling removeNotificationListener. The ID is a number greater than 0. + * If there was an error and the listener was not added, addNotificationListener returns -1. This + * can happen if the first argument is not a valid notification type, or if the same callback + * function was already added as a listener by a prior call to this function. + */ +NotificationCenter.prototype.addNotificationListener = function(notificationType, callback) { + try { + var isNotificationTypeValid = jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).indexOf(notificationType) > -1; + if (!isNotificationTypeValid) { + return -1; + } + + if (!this.__notificationListeners[notificationType]) { + this.__notificationListeners[notificationType] = []; + } + + var callbackAlreadyAdded = false; + (this.__notificationListeners[notificationType] || []).forEach(function(listenerEntry) { + if (listenerEntry.callback === callback) { + callbackAlreadyAdded = true; + return false; + } + }); + if (callbackAlreadyAdded) { + return -1; + } + + this.__notificationListeners[notificationType].push({ + id: this.__listenerId, + callback: callback, + }); + + var returnId = this.__listenerId; + this.__listenerId += 1; + return returnId; + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + return -1; + } +}; + +/** + * Remove a previously added notification callback + * @param {number} listenerId ID of listener to be removed + * @returns {boolean} Returns true if the listener was found and removed, and false + * otherwise. + */ +NotificationCenter.prototype.removeNotificationListener = function(listenerId) { + try { + var indexToRemove; + var typeToRemove; + + Object.keys(this.__notificationListeners).some( + function(notificationType) { + var listenersForType = this.__notificationListeners[notificationType]; + (listenersForType || []).every(function(listenerEntry, i) { + if (listenerEntry.id === listenerId) { + indexToRemove = i; + typeToRemove = notificationType; + return false; + } + return true; + }); + if (indexToRemove !== undefined && typeToRemove !== undefined) { + return true; + } + }.bind(this) + ); + + if (indexToRemove !== undefined && typeToRemove !== undefined) { + this.__notificationListeners[typeToRemove].splice(indexToRemove, 1); + return true; + } + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + } + return false; +}; + +/** + * Removes all previously added notification listeners, for all notification types + */ +NotificationCenter.prototype.clearAllNotificationListeners = function() { + try { + jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).forEach( + function(notificationTypeEnum) { + this.__notificationListeners[notificationTypeEnum] = []; + }.bind(this) + ); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + } +}; + +/** + * Remove all previously added notification listeners for the argument type + * @param {string} notificationType One of enums.NOTIFICATION_TYPES + */ +NotificationCenter.prototype.clearNotificationListeners = function(notificationType) { + try { + this.__notificationListeners[notificationType] = []; + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + } +}; + +/** + * Fires notifications for the argument type. All registered callbacks for this type will be + * called. The notificationData object will be passed on to callbacks called. + * @param {string} notificationType One of enums.NOTIFICATION_TYPES + * @param {Object} notificationData Will be passed to callbacks called + */ +NotificationCenter.prototype.sendNotifications = function(notificationType, notificationData) { + try { + (this.__notificationListeners[notificationType] || []).forEach( + function(listenerEntry) { + var callback = listenerEntry.callback; + try { + callback(notificationData); + } catch (ex) { + this.logger.log( + LOG_LEVEL.ERROR, + jsSdkUtils.sprintf(LOG_MESSAGES.NOTIFICATION_LISTENER_EXCEPTION, MODULE_NAME, notificationType, ex.message) + ); + } + }.bind(this) + ); + } catch (e) { + this.logger.log(LOG_LEVEL.ERROR, e.message); + this.errorHandler.handleError(e); + } +}; + +module.exports = { + /** + * Create an instance of NotificationCenter + * @param {Object} options + * @param {Object} options.logger An instance of a logger to log messages with + * @returns {Object} An instance of NotificationCenter + */ + createNotificationCenter: function(options) { + return new NotificationCenter(options); + }, +}; + + +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { + +/**************************************************************************** + * Copyright 2017, Optimizely, Inc. and contributors * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); * + * you may not use this file except in compliance with the License. * + * You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License 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. * + ***************************************************************************/ + +/** + * Provides utility method for validating that the given user profile service implementation is valid. + */ + +var sprintf = __webpack_require__(12).sprintf; + +var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; +var MODULE_NAME = 'USER_PROFILE_SERVICE_VALIDATOR'; + +module.exports = { + /** + * Validates user's provided user profile service instance + * @param {Object} userProfileServiceInstance + * @return {boolean} True if the instance is valid + * @throws If the instance is not valid + */ + validate: function(userProfileServiceInstance) { + if (typeof userProfileServiceInstance.lookup !== 'function') { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'lookup'")); + } else if (typeof userProfileServiceInstance.save !== 'function') { + throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'save'")); + } + return true; + }, +}; + + +/***/ }), +/* 44 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 fns = __webpack_require__(11); +var sprintf = __webpack_require__(12).sprintf; +var logging = __webpack_require__(1); +var configValidator = __webpack_require__(13); +var datafileManager = __webpack_require__(45); +var enums = __webpack_require__(14); +var projectConfig = __webpack_require__(35); +var optimizelyConfig = __webpack_require__(54); + +var logger = logging.getLogger(); + +var ERROR_MESSAGES = enums.ERROR_MESSAGES; + +var MODULE_NAME = 'PROJECT_CONFIG_MANAGER'; + +/** + * Return an error message derived from a thrown value. If the thrown value is + * an error, return the error's message property. Otherwise, return a default + * provided by the second argument. + * @param {*} maybeError + * @param {String=} defaultMessage + * @return {String} + */ +function getErrorMessage(maybeError, defaultMessage) { + if (maybeError instanceof Error) { + return maybeError.message; + } + return defaultMessage || 'Unknown error'; +} + +/** + * ProjectConfigManager provides project config objects via its methods + * getConfig and onUpdate. It uses a DatafileManager to fetch datafiles. It is + * responsible for parsing and validating datafiles, and converting datafile + * JSON objects into project config objects. + * @param {Object} config + * @param {Object|string=} config.datafile + * @param {Object=} config.datafileOptions + * @param {Object=} config.jsonSchemaValidator + * @param {string=} config.sdkKey + * @param {boolean=} config.skipJSONValidation + */ +function ProjectConfigManager(config) { + try { + this.__initialize(config); + } catch (ex) { + logger.error(ex); + this.__updateListeners = []; + this.__configObj = null; + this.__optimizelyConfigObj = null; + this.__readyPromise = Promise.resolve({ + success: false, + reason: getErrorMessage(ex, 'Error in initialize'), + }); + } +} + +/** + * Initialize internal properties including __updateListeners, __configObj, and + * __readyPromise, using the argument config. Create and subscribe to a datafile + * manager if appropriate. + * @param {Object} config + * @param {Object|string=} config.datafile + * @param {Object=} config.datafileOptions + * @param {Object=} config.jsonSchemaValidator + * @param {string=} config.sdkKey + * @param {boolean=} config.skipJSONValidation + */ +ProjectConfigManager.prototype.__initialize = function(config) { + this.__updateListeners = []; + this.jsonSchemaValidator = config.jsonSchemaValidator; + this.skipJSONValidation = config.skipJSONValidation; + + if (!config.datafile && !config.sdkKey) { + this.__configObj = null; + var datafileAndSdkKeyMissingError = new Error(sprintf(ERROR_MESSAGES.DATAFILE_AND_SDK_KEY_MISSING, MODULE_NAME)); + this.__readyPromise = Promise.resolve({ + success: false, + reason: getErrorMessage(datafileAndSdkKeyMissingError), + }); + logger.error(datafileAndSdkKeyMissingError); + return; + } + + var initialDatafile = this.__getDatafileFromConfig(config); + var projectConfigCreationEx; + if (initialDatafile) { + try { + this.__configObj = projectConfig.tryCreatingProjectConfig({ + datafile: initialDatafile, + jsonSchemaValidator: this.jsonSchemaValidator, + logger: logger, + skipJSONValidation: this.skipJSONValidation, + }); + this.__optimizelyConfigObj = optimizelyConfig.getOptimizelyConfig(this.__configObj); + } catch (ex) { + logger.error(ex); + projectConfigCreationEx = ex; + this.__configObj = null; + } + } else { + this.__configObj = null; + } + + if (config.sdkKey) { + var datafileManagerConfig = { + sdkKey: config.sdkKey, + }; + if (this.__validateDatafileOptions(config.datafileOptions)) { + fns.assign(datafileManagerConfig, config.datafileOptions); + } + if (initialDatafile && this.__configObj) { + datafileManagerConfig.datafile = initialDatafile; + } + this.datafileManager = new datafileManager.HttpPollingDatafileManager(datafileManagerConfig); + this.datafileManager.start(); + this.__readyPromise = this.datafileManager + .onReady() + .then(this.__onDatafileManagerReadyFulfill.bind(this), this.__onDatafileManagerReadyReject.bind(this)); + this.datafileManager.on('update', this.__onDatafileManagerUpdate.bind(this)); + } else if (this.__configObj) { + this.__readyPromise = Promise.resolve({ + success: true, + }); + } else { + this.__readyPromise = Promise.resolve({ + success: false, + reason: getErrorMessage(projectConfigCreationEx, 'Invalid datafile'), + }); + } +}; + +/** + * Respond to datafile manager's onReady promise becoming fulfilled. + * If there are validation or parse failures using the datafile provided by + * DatafileManager, ProjectConfigManager's ready promise is resolved with an + * unsuccessful result. Otherwise, ProjectConfigManager updates its own project + * config object from the new datafile, and its ready promise is resolved with a + * successful result. + */ +ProjectConfigManager.prototype.__onDatafileManagerReadyFulfill = function() { + var newDatafile = this.datafileManager.get(); + var newConfigObj; + try { + newConfigObj = projectConfig.tryCreatingProjectConfig({ + datafile: newDatafile, + jsonSchemaValidator: this.jsonSchemaValidator, + logger: logger, + skipJSONValidation: this.skipJSONValidation, + }); + } catch (ex) { + logger.error(ex); + return { + success: false, + reason: getErrorMessage(ex), + }; + } + this.__handleNewConfigObj(newConfigObj); + return { + success: true, + }; +}; + +/** + * Respond to datafile manager's onReady promise becoming rejected. + * When DatafileManager's onReady promise is rejected, there is no possibility + * of obtaining a datafile. In this case, ProjectConfigManager's ready promise + * is fulfilled with an unsuccessful result. + * @param {Error} err + */ +ProjectConfigManager.prototype.__onDatafileManagerReadyReject = function(err) { + return { + success: false, + reason: getErrorMessage(err, 'Failed to become ready'), + }; +}; + +/** + * Respond to datafile manager's update event. Attempt to update own config + * object using latest datafile from datafile manager. Call own registered + * update listeners if successful + */ +ProjectConfigManager.prototype.__onDatafileManagerUpdate = function() { + var newDatafile = this.datafileManager.get(); + var newConfigObj; + try { + newConfigObj = projectConfig.tryCreatingProjectConfig({ + datafile: newDatafile, + jsonSchemaValidator: this.jsonSchemaValidator, + logger: logger, + skipJSONValidation: this.skipJSONValidation, + }); + } catch (ex) { + logger.error(ex); + } + if (newConfigObj) { + this.__handleNewConfigObj(newConfigObj); + } +}; + +/** + * If the argument config contains a valid datafile object or string, + * return a datafile object based on that provided datafile, otherwise + * return null. + * @param {Object} config + * @param {Object|string=} config.datafile + * @return {Object|null} + */ +ProjectConfigManager.prototype.__getDatafileFromConfig = function(config) { + var initialDatafile = null; + try { + if (config.datafile) { + configValidator.validateDatafile(config.datafile); + if (typeof config.datafile === 'string' || config.datafile instanceof String) { + initialDatafile = JSON.parse(config.datafile); + } else { + initialDatafile = config.datafile; + } + } + } catch (ex) { + logger.error(ex); + } + return initialDatafile; +}; + +/** + * Validate user-provided datafileOptions. It should be an object or undefined. + * @param {*} datafileOptions + * @returns {boolean} + */ +ProjectConfigManager.prototype.__validateDatafileOptions = function(datafileOptions) { + if (typeof datafileOptions === 'undefined') { + return true; + } + + if (typeof datafileOptions === 'object') { + return datafileOptions !== null; + } + + return false; +}; + +/** + * Update internal project config object to be argument object when the argument + * object has a different revision than the current internal project config + * object. If the internal object is updated, call update listeners. + * @param {Object} newConfigObj + */ +ProjectConfigManager.prototype.__handleNewConfigObj = function(newConfigObj) { + var oldConfigObj = this.__configObj; + + var oldRevision = oldConfigObj ? oldConfigObj.revision : 'null'; + if (oldRevision === newConfigObj.revision) { + return; + } + + this.__configObj = newConfigObj; + this.__optimizelyConfigObj = optimizelyConfig.getOptimizelyConfig(newConfigObj); + + this.__updateListeners.forEach(function(listener) { + listener(newConfigObj); + }); +}; + +/** + * Returns the current project config object, or null if no project config object + * is available + * @return {Object|null} + */ +ProjectConfigManager.prototype.getConfig = function() { + return this.__configObj; +}; + +/** + * Returns the optimizely config object + * @return {Object} + */ +ProjectConfigManager.prototype.getOptimizelyConfig = function() { + return this.__optimizelyConfigObj; +}; + +/** + * Returns a Promise that fulfills when this ProjectConfigManager is ready to + * use (meaning it has a valid project config object), or has failed to become + * ready. + * + * Failure can be caused by the following: + * - At least one of sdkKey or datafile is not provided in the constructor argument + * - The provided datafile was invalid + * - The datafile provided by the datafile manager was invalid + * - The datafile manager failed to fetch a datafile + * + * The returned Promise is fulfilled with a result object containing these + * properties: + * - success (boolean): True if this instance is ready to use with a valid + * project config object, or false if it failed to + * become ready + * - reason (string=): If success is false, this is a string property with + * an explanatory message. + * @return {Promise} + */ +ProjectConfigManager.prototype.onReady = function() { + return this.__readyPromise; +}; + +/** + * Add a listener for project config updates. The listener will be called + * whenever this instance has a new project config object available. + * Returns a dispose function that removes the subscription + * @param {Function} listener + * @return {Function} + */ +ProjectConfigManager.prototype.onUpdate = function(listener) { + this.__updateListeners.push(listener); + return function() { + var index = this.__updateListeners.indexOf(listener); + if (index > -1) { + this.__updateListeners.splice(index, 1); + } + }.bind(this); +}; + +/** + * Stop the internal datafile manager and remove all update listeners + */ +ProjectConfigManager.prototype.stop = function() { + if (this.datafileManager) { + this.datafileManager.stop(); + } + this.__updateListeners = []; +}; + +module.exports = { + ProjectConfigManager: ProjectConfigManager, +}; + + +/***/ }), +/* 45 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var browserDatafileManager_1 = __webpack_require__(46); +exports.HttpPollingDatafileManager = browserDatafileManager_1.default; +var staticDatafileManager_1 = __webpack_require__(53); +exports.StaticDatafileManager = staticDatafileManager_1.default; + + +/***/ }), +/* 46 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 __extends = (this && this.__extends) || (function () { + var extendStatics = function (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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var browserRequest_1 = __webpack_require__(47); +var httpPollingDatafileManager_1 = __importDefault(__webpack_require__(49)); +var BrowserDatafileManager = /** @class */ (function (_super) { + __extends(BrowserDatafileManager, _super); + function BrowserDatafileManager() { + return _super !== null && _super.apply(this, arguments) || this; + } + BrowserDatafileManager.prototype.makeGetRequest = function (reqUrl, headers) { + return browserRequest_1.makeGetRequest(reqUrl, headers); + }; + BrowserDatafileManager.prototype.getConfigDefaults = function () { + return { + autoUpdate: false, + }; + }; + return BrowserDatafileManager; +}(httpPollingDatafileManager_1.default)); +exports.default = BrowserDatafileManager; + + +/***/ }), +/* 47 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var config_1 = __webpack_require__(48); +var js_sdk_logging_1 = __webpack_require__(1); +var logger = js_sdk_logging_1.getLogger('DatafileManager'); +var GET_METHOD = 'GET'; +var READY_STATE_DONE = 4; +function parseHeadersFromXhr(req) { + var allHeadersString = req.getAllResponseHeaders(); + if (allHeadersString === null) { + return {}; + } + var headerLines = allHeadersString.split('\r\n'); + var headers = {}; + headerLines.forEach(function (headerLine) { + var separatorIndex = headerLine.indexOf(': '); + if (separatorIndex > -1) { + var headerName = headerLine.slice(0, separatorIndex); + var headerValue = headerLine.slice(separatorIndex + 2); + if (headerValue.length > 0) { + headers[headerName] = headerValue; + } + } + }); + return headers; +} +function setHeadersInXhr(headers, req) { + Object.keys(headers).forEach(function (headerName) { + var header = headers[headerName]; + req.setRequestHeader(headerName, header); + }); +} +function makeGetRequest(reqUrl, headers) { + var req = new XMLHttpRequest(); + var responsePromise = new Promise(function (resolve, reject) { + req.open(GET_METHOD, reqUrl, true); + setHeadersInXhr(headers, req); + req.onreadystatechange = function () { + if (req.readyState === READY_STATE_DONE) { + var statusCode = req.status; + if (statusCode === 0) { + reject(new Error('Request error')); + return; + } + var headers_1 = parseHeadersFromXhr(req); + var resp = { + statusCode: req.status, + body: req.responseText, + headers: headers_1, + }; + resolve(resp); + } + }; + req.timeout = config_1.REQUEST_TIMEOUT_MS; + req.ontimeout = function () { + logger.error('Request timed out'); + }; + req.send(); + }); + return { + responsePromise: responsePromise, + abort: function () { + req.abort(); + }, + }; +} +exports.makeGetRequest = makeGetRequest; + + +/***/ }), +/* 48 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DEFAULT_UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes +exports.MIN_UPDATE_INTERVAL = 1000; +exports.DEFAULT_URL_TEMPLATE = "https://cdn.optimizely.com/datafiles/%s.json"; +exports.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT = [0, 8, 16, 32, 64, 128, 256, 512]; +exports.REQUEST_TIMEOUT_MS = 60 * 1000; // 1 minute + + +/***/ }), +/* 49 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 __assign = (this && this.__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 __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +var js_sdk_logging_1 = __webpack_require__(1); +var js_sdk_utils_1 = __webpack_require__(50); +var eventEmitter_1 = __importDefault(__webpack_require__(51)); +var config_1 = __webpack_require__(48); +var backoffController_1 = __importDefault(__webpack_require__(52)); +var logger = js_sdk_logging_1.getLogger('DatafileManager'); +var UPDATE_EVT = 'update'; +function isValidUpdateInterval(updateInterval) { + return updateInterval >= config_1.MIN_UPDATE_INTERVAL; +} +function isSuccessStatusCode(statusCode) { + return statusCode >= 200 && statusCode < 400; +} +var HttpPollingDatafileManager = /** @class */ (function () { + function HttpPollingDatafileManager(config) { + var _this = this; + var configWithDefaultsApplied = __assign({}, this.getConfigDefaults(), config); + var datafile = configWithDefaultsApplied.datafile, _a = configWithDefaultsApplied.autoUpdate, autoUpdate = _a === void 0 ? false : _a, sdkKey = configWithDefaultsApplied.sdkKey, _b = configWithDefaultsApplied.updateInterval, updateInterval = _b === void 0 ? config_1.DEFAULT_UPDATE_INTERVAL : _b, _c = configWithDefaultsApplied.urlTemplate, urlTemplate = _c === void 0 ? config_1.DEFAULT_URL_TEMPLATE : _c; + this.isReadyPromiseSettled = false; + this.readyPromiseResolver = function () { }; + this.readyPromiseRejecter = function () { }; + this.readyPromise = new Promise(function (resolve, reject) { + _this.readyPromiseResolver = resolve; + _this.readyPromiseRejecter = reject; + }); + if (datafile) { + this.currentDatafile = datafile; + this.resolveReadyPromise(); + } + else { + this.currentDatafile = null; + } + this.isStarted = false; + this.datafileUrl = js_sdk_utils_1.sprintf(urlTemplate, sdkKey); + this.emitter = new eventEmitter_1.default(); + this.autoUpdate = autoUpdate; + if (isValidUpdateInterval(updateInterval)) { + this.updateInterval = updateInterval; + } + else { + logger.warn('Invalid updateInterval %s, defaulting to %s', updateInterval, config_1.DEFAULT_UPDATE_INTERVAL); + this.updateInterval = config_1.DEFAULT_UPDATE_INTERVAL; + } + this.currentTimeout = null; + this.currentRequest = null; + this.backoffController = new backoffController_1.default(); + this.syncOnCurrentRequestComplete = false; + } + HttpPollingDatafileManager.prototype.get = function () { + return this.currentDatafile; + }; + HttpPollingDatafileManager.prototype.start = function () { + if (!this.isStarted) { + logger.debug('Datafile manager started'); + this.isStarted = true; + this.backoffController.reset(); + this.syncDatafile(); + } + }; + HttpPollingDatafileManager.prototype.stop = function () { + logger.debug('Datafile manager stopped'); + this.isStarted = false; + if (this.currentTimeout) { + clearTimeout(this.currentTimeout); + this.currentTimeout = null; + } + this.emitter.removeAllListeners(); + if (this.currentRequest) { + this.currentRequest.abort(); + this.currentRequest = null; + } + return Promise.resolve(); + }; + HttpPollingDatafileManager.prototype.onReady = function () { + return this.readyPromise; + }; + HttpPollingDatafileManager.prototype.on = function (eventName, listener) { + return this.emitter.on(eventName, listener); + }; + HttpPollingDatafileManager.prototype.onRequestRejected = function (err) { + if (!this.isStarted) { + return; + } + this.backoffController.countError(); + if (err instanceof Error) { + logger.error('Error fetching datafile: %s', err.message, err); + } + else if (typeof err === 'string') { + logger.error('Error fetching datafile: %s', err); + } + else { + logger.error('Error fetching datafile'); + } + }; + HttpPollingDatafileManager.prototype.onRequestResolved = function (response) { + if (!this.isStarted) { + return; + } + if (typeof response.statusCode !== 'undefined' && + isSuccessStatusCode(response.statusCode)) { + this.backoffController.reset(); + } + else { + this.backoffController.countError(); + } + this.trySavingLastModified(response.headers); + var datafile = this.getNextDatafileFromResponse(response); + if (datafile !== null) { + logger.info('Updating datafile from response'); + this.currentDatafile = datafile; + if (!this.isReadyPromiseSettled) { + this.resolveReadyPromise(); + } + else { + var datafileUpdate = { + datafile: datafile, + }; + this.emitter.emit(UPDATE_EVT, datafileUpdate); + } + } + }; + HttpPollingDatafileManager.prototype.onRequestComplete = function () { + if (!this.isStarted) { + return; + } + this.currentRequest = null; + if (!this.isReadyPromiseSettled && !this.autoUpdate) { + // We will never resolve ready, so reject it + this.rejectReadyPromise(new Error('Failed to become ready')); + } + if (this.autoUpdate && this.syncOnCurrentRequestComplete) { + this.syncDatafile(); + } + this.syncOnCurrentRequestComplete = false; + }; + HttpPollingDatafileManager.prototype.syncDatafile = function () { + var _this = this; + var headers = {}; + if (this.lastResponseLastModified) { + headers['if-modified-since'] = this.lastResponseLastModified; + } + logger.debug('Making datafile request to url %s with headers: %s', this.datafileUrl, function () { return JSON.stringify(headers); }); + this.currentRequest = this.makeGetRequest(this.datafileUrl, headers); + var onRequestComplete = function () { + _this.onRequestComplete(); + }; + var onRequestResolved = function (response) { + _this.onRequestResolved(response); + }; + var onRequestRejected = function (err) { + _this.onRequestRejected(err); + }; + this.currentRequest.responsePromise + .then(onRequestResolved, onRequestRejected) + .then(onRequestComplete, onRequestComplete); + if (this.autoUpdate) { + this.scheduleNextUpdate(); + } + }; + HttpPollingDatafileManager.prototype.resolveReadyPromise = function () { + this.readyPromiseResolver(); + this.isReadyPromiseSettled = true; + }; + HttpPollingDatafileManager.prototype.rejectReadyPromise = function (err) { + this.readyPromiseRejecter(err); + this.isReadyPromiseSettled = true; + }; + HttpPollingDatafileManager.prototype.scheduleNextUpdate = function () { + var _this = this; + var currentBackoffDelay = this.backoffController.getDelay(); + var nextUpdateDelay = Math.max(currentBackoffDelay, this.updateInterval); + logger.debug('Scheduling sync in %s ms', nextUpdateDelay); + this.currentTimeout = setTimeout(function () { + if (_this.currentRequest) { + _this.syncOnCurrentRequestComplete = true; + } + else { + _this.syncDatafile(); + } + }, nextUpdateDelay); + }; + HttpPollingDatafileManager.prototype.getNextDatafileFromResponse = function (response) { + logger.debug('Response status code: %s', response.statusCode); + if (typeof response.statusCode === 'undefined') { + return null; + } + if (response.statusCode === 304) { + return null; + } + if (isSuccessStatusCode(response.statusCode)) { + return this.tryParsingBodyAsJSON(response.body); + } + return null; + }; + HttpPollingDatafileManager.prototype.tryParsingBodyAsJSON = function (body) { + var parseResult; + try { + parseResult = JSON.parse(body); + } + catch (err) { + logger.error('Error parsing response body: %s', err.message, err); + return null; + } + var datafileObj = null; + if (typeof parseResult === 'object' && parseResult !== null) { + datafileObj = parseResult; + } + else { + logger.error('Error parsing response body: was not an object'); + } + return datafileObj; + }; + HttpPollingDatafileManager.prototype.trySavingLastModified = function (headers) { + var lastModifiedHeader = headers['last-modified'] || headers['Last-Modified']; + if (typeof lastModifiedHeader !== 'undefined') { + this.lastResponseLastModified = lastModifiedHeader; + logger.debug('Saved last modified header value from response: %s', this.lastResponseLastModified); + } + }; + return HttpPollingDatafileManager; +}()); +exports.default = HttpPollingDatafileManager; + + +/***/ }), +/* 50 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 uuid_1 = __webpack_require__(6); +function getTimestamp() { + return new Date().getTime(); +} +exports.getTimestamp = getTimestamp; +function generateUUID() { + return uuid_1.v4(); +} +exports.generateUUID = generateUUID; +/** + * Validates a value is a valid TypeScript enum + * + * @export + * @param {object} enumToCheck + * @param {*} value + * @returns {boolean} + */ +function isValidEnum(enumToCheck, value) { + var found = false; + var keys = Object.keys(enumToCheck); + for (var index = 0; index < keys.length; index++) { + if (value === enumToCheck[keys[index]]) { + found = true; + break; + } + } + return found; +} +exports.isValidEnum = isValidEnum; +function groupBy(arr, grouperFn) { + var grouper = {}; + arr.forEach(function (item) { + var key = grouperFn(item); + grouper[key] = grouper[key] || []; + grouper[key].push(item); + }); + return objectValues(grouper); +} +exports.groupBy = groupBy; +function objectValues(obj) { + return Object.keys(obj).map(function (key) { return obj[key]; }); +} +exports.objectValues = objectValues; +function find(arr, cond) { + var found; + for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { + var item = arr_1[_i]; + if (cond(item)) { + found = item; + break; + } + } + return found; +} +exports.find = find; +function keyBy(arr, keyByFn) { + var map = {}; + arr.forEach(function (item) { + var key = keyByFn(item); + map[key] = item; + }); + return map; +} +exports.keyBy = keyBy; +function sprintf(format) { + var args = []; + for (var _i = 1; _i < arguments.length; _i++) { + args[_i - 1] = arguments[_i]; + } + var i = 0; + return format.replace(/%s/g, function () { + var arg = args[i++]; + var type = typeof arg; + if (type === 'function') { + return arg(); + } + else if (type === 'string') { + return arg; + } + else { + return String(arg); + } + }); +} +exports.sprintf = sprintf; + + +/***/ }), +/* 51 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var EventEmitter = /** @class */ (function () { + function EventEmitter() { + this.listeners = {}; + this.listenerId = 1; + } + EventEmitter.prototype.on = function (eventName, listener) { + var _this = this; + if (!this.listeners[eventName]) { + this.listeners[eventName] = {}; + } + var currentListenerId = String(this.listenerId); + this.listenerId++; + this.listeners[eventName][currentListenerId] = listener; + return function () { + if (_this.listeners[eventName]) { + delete _this.listeners[eventName][currentListenerId]; + } + }; + }; + EventEmitter.prototype.emit = function (eventName, arg) { + var listeners = this.listeners[eventName]; + if (listeners) { + Object.keys(listeners).forEach(function (listenerId) { + var listener = listeners[listenerId]; + listener(arg); + }); + } + }; + EventEmitter.prototype.removeAllListeners = function () { + this.listeners = {}; + }; + return EventEmitter; +}()); +exports.default = EventEmitter; +// TODO: Create a typed event emitter for use in TS only (not JS) + + +/***/ }), +/* 52 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var config_1 = __webpack_require__(48); +function randomMilliseconds() { + return Math.round(Math.random() * 1000); +} +var BackoffController = /** @class */ (function () { + function BackoffController() { + this.errorCount = 0; + } + BackoffController.prototype.getDelay = function () { + if (this.errorCount === 0) { + return 0; + } + var baseWaitSeconds = config_1.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT[Math.min(config_1.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT.length - 1, this.errorCount)]; + return baseWaitSeconds * 1000 + randomMilliseconds(); + }; + BackoffController.prototype.countError = function () { + if (this.errorCount < config_1.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT.length - 1) { + this.errorCount++; + } + }; + BackoffController.prototype.reset = function () { + this.errorCount = 0; + }; + return BackoffController; +}()); +exports.default = BackoffController; + + +/***/ }), +/* 53 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +var doNothing = function () { }; +var StaticDatafileManager = /** @class */ (function () { + function StaticDatafileManager(datafile) { + this.datafile = datafile; + this.readyPromise = Promise.resolve(); + } + StaticDatafileManager.prototype.get = function () { + return this.datafile; + }; + StaticDatafileManager.prototype.onReady = function () { + return this.readyPromise; + }; + StaticDatafileManager.prototype.start = function () { + }; + StaticDatafileManager.prototype.stop = function () { + return Promise.resolve(); + }; + StaticDatafileManager.prototype.on = function (eventName, listener) { + return doNothing; + }; + return StaticDatafileManager; +}()); +exports.default = StaticDatafileManager; + + +/***/ }), +/* 54 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 projectConfig = __webpack_require__(35); + +// Get Experiment Ids which are part of rollouts +function getRolloutExperimentIds(rollouts) { + return (rollouts || []).reduce(function(experimentIds, rollout) { + rollout.experiments.forEach(function(e) { + experimentIds[e.id] = true; + }); + return experimentIds; + }, {}); +} + +// Gets Map of all experiments except rollouts +function getExperimentsMap(configObj) { + var rolloutExperimentIds = getRolloutExperimentIds(configObj.rollouts); + var featureVariablesMap = (configObj.featureFlags || []).reduce(function(resultMap, feature) { + resultMap[feature.id] = feature.variables; + return resultMap; + }, {}); + return (configObj.experiments || []).reduce(function(experiments, experiment) { + // skip experiments that are part of a rollout + if (!rolloutExperimentIds[experiment.id]) { + experiments[experiment.key] = { + id: experiment.id, + key: experiment.key, + variationsMap: (experiment.variations || []).reduce(function(variations, variation) { + variations[variation.key] = { + id: variation.id, + key: variation.key, + variablesMap: getMergedVariablesMap(configObj, variation, experiment.id, featureVariablesMap), + }; + if (projectConfig.isFeatureExperiment(configObj, experiment.id)) { + variations[variation.key].featureEnabled = variation.featureEnabled; + } + return variations; + }, {}), + }; + } + return experiments; + }, {}); +} + +// Merges feature key and type from feature variables to variation variables. +function getMergedVariablesMap(configObj, variation, experimentId, featureVariablesMap) { + var featureId = configObj.experimentFeatureMap[experimentId]; + var variablesObject = {}; + if (featureId) { + var experimentFeatureVariables = featureVariablesMap[featureId]; + // Temporary variation variables map to get values to merge. + var tempVariablesIdMap = (variation.variables || []).reduce(function(variablesMap, variable) { + variablesMap[variable.id] = { + id: variable.id, + value: variable.value, + }; + return variablesMap; + }, {}); + variablesObject = (experimentFeatureVariables || []).reduce(function(variablesMap, featureVariable) { + var variationVariable = tempVariablesIdMap[featureVariable.id]; + var variableValue = + variation.featureEnabled && variationVariable ? variationVariable.value : featureVariable.defaultValue; + variablesMap[featureVariable.key] = { + id: featureVariable.id, + key: featureVariable.key, + type: featureVariable.type, + value: variableValue, + }; + return variablesMap; + }, {}); + } + return variablesObject; +} + +// Gets map of all experiments +function getFeaturesMap(configObj, allExperiments) { + return (configObj.featureFlags || []).reduce(function(features, feature) { + features[feature.key] = { + id: feature.id, + key: feature.key, + experimentsMap: (feature.experimentIds || []).reduce(function(experiments, experimentId) { + var experimentKey = configObj.experimentIdMap[experimentId].key; + experiments[experimentKey] = allExperiments[experimentKey]; + return experiments; + }, {}), + variablesMap: (feature.variables || []).reduce(function(variables, variable) { + variables[variable.key] = { + id: variable.id, + key: variable.key, + type: variable.type, + value: variable.defaultValue, + }; + return variables; + }, {}), + }; + return features; + }, {}); +} + +module.exports = { + getOptimizelyConfig: function(configObj) { + // Fetch all feature variables from feature flags to merge them with variation variables + var experimentsMap = getExperimentsMap(configObj); + return { + experimentsMap: experimentsMap, + featuresMap: getFeaturesMap(configObj, experimentsMap), + revision: configObj.revision, + }; + }, +}; + + +/***/ }), +/* 55 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright 2019, Optimizely + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License 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 fns = __webpack_require__(11); + +/** + * Return true if the argument is a valid event batch size, false otherwise + * @param {*} eventBatchSize + * @returns boolean + */ +function validateEventBatchSize(eventBatchSize) { + return fns.isSafeInteger(eventBatchSize) && eventBatchSize >= 1; +} + +/** + * Return true if the argument is a valid event flush interval, false otherwise + * @param {*} eventFlushInterval + * @returns boolean + */ +function validateEventFlushInterval(eventFlushInterval) { + return fns.isSafeInteger(eventFlushInterval) && eventFlushInterval > 0; +} + +module.exports = { + validateEventBatchSize: validateEventBatchSize, + validateEventFlushInterval: validateEventFlushInterval, +}; + + +/***/ }) +/******/ ]); +}); \ No newline at end of file diff --git a/packages/optimizely-sdk/optimizely.browser.umd.min.js b/packages/optimizely-sdk/optimizely.browser.umd.min.js new file mode 100644 index 000000000..2d9a18f2c --- /dev/null +++ b/packages/optimizely-sdk/optimizely.browser.umd.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.optimizelySdk=t():e.optimizelySdk=t()}(window,(function(){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(i,n,function(t){return e[t]}.bind(null,n));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=19)}([function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(5);function n(e){return Object.keys(e).map((function(t){return e[t]}))}t.getTimestamp=function(){return(new Date).getTime()},t.generateUUID=function(){return i.v4()},t.isValidEnum=function(e,t){for(var r=!1,i=Object.keys(e),n=0;n>>((3&t)<<3)&255;return n}}},function(e,t){for(var r=[],i=0;i<256;++i)r[i]=(i+256).toString(16).substr(1);e.exports=function(e,t){var i=t||0,n=r;return[n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]]].join("")}},function(e,t,r){"use strict";function i(e){for(var r in e)t.hasOwnProperty(r)||(t[r]=e[r])}Object.defineProperty(t,"__esModule",{value:!0}),i(r(14)),i(r(15)),i(r(28)),i(r(16)),i(r(30))},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.areEventContextsEqual=function(e,t){var r=e.context,i=t.context;return r.accountId===i.accountId&&r.projectId===i.projectId&&r.clientName===i.clientName&&r.clientVersion===i.clientVersion&&r.revision===i.revision&&r.anonymizeIP===i.anonymizeIP&&r.botFiltering===i.botFiltering}},function(e,t,r){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var n=r(14),o=r(26),a=r(2),s=r(0),u=i(r(27)),l=a.getLogger("EventProcessor"),c=function(){function e(e){var t=e.dispatcher,r=e.flushInterval,i=void 0===r?3e4:r,a=e.maxQueueSize,s=void 0===a?3e3:a,c=e.notificationCenter,E=this;this.dispatcher=t,i<=0&&(l.warn("Invalid flushInterval "+i+", defaulting to 30000"),i=3e4),(s=Math.floor(s))<1&&(l.warn("Invalid maxQueueSize "+s+", defaulting to 10"),s=10),s=Math.max(1,s),this.queue=s>1?new o.DefaultEventQueue({flushInterval:i,maxQueueSize:s,sink:function(e){return E.drainQueue(e)},batchComparator:n.areEventContextsEqual}):new o.SingleEventQueue({sink:function(e){return E.drainQueue(e)}}),this.notificationCenter=c,this.requestTracker=new u.default}return e.prototype.drainQueue=function(e){var t=this,r=new Promise((function(r){if(l.debug("draining queue with %s events",e.length),0!==e.length){var i=t.formatEvents(e);t.dispatcher.dispatchEvent(i,(function(){r()})),t.notificationCenter&&t.notificationCenter.sendNotifications(s.NOTIFICATION_TYPES.LOG_EVENT,i)}else r()}));return this.requestTracker.trackRequest(r),r},e.prototype.process=function(e){this.queue.enqueue(e)},e.prototype.stop=function(){try{return this.queue.stop(),this.requestTracker.onRequestsComplete()}catch(e){l.error('Error stopping EventProcessor: "%s"',e.message,e)}return Promise.resolve()},e.prototype.start=function(){this.queue.start()},e}();t.AbstractEventProcessor=c},function(e,t,r){"use strict";var i=this&&this.__assign||function(){return(i=Object.assign||function(e){for(var t,r=1,i=arguments.length;r=this.logLevel},e.prototype.getLogLevelName=function(e){switch(e){case o.LogLevel.DEBUG:return"DEBUG";case o.LogLevel.INFO:return"INFO ";case o.LogLevel.WARNING:return"WARN ";case o.LogLevel.ERROR:return"ERROR";default:return"NOTSET"}},e.prototype.consoleLog=function(e,t){switch(e){case o.LogLevel.DEBUG:console.log.apply(console,t);break;case o.LogLevel.INFO:console.info.apply(console,t);break;case o.LogLevel.WARNING:console.warn.apply(console,t);break;case o.LogLevel.ERROR:console.error.apply(console,t);break;default:console.log.apply(console,t)}},e}();t.ConsoleLogHandler=l;var c=o.LogLevel.NOTSET,E=null,f=function(){function e(e){void 0===e&&(e={}),this.messagePrefix="",e.messagePrefix&&(this.messagePrefix=e.messagePrefix)}return e.prototype.log=function(e,t){this.internalLog(s(e),{message:t,splat:[]})},e.prototype.info=function(e){for(var t=[],r=1;rs)&&void 0===e.nsecs&&(d=0),d>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");s=_,u=d,n=f;var I=(1e4*(268435455&(_+=122192928e5))+d)%4294967296;c[l++]=I>>>24&255,c[l++]=I>>>16&255,c[l++]=I>>>8&255,c[l++]=255&I;var h=_/4294967296*1e4&268435455;c[l++]=h>>>8&255,c[l++]=255&h,c[l++]=h>>>24&15|16,c[l++]=h>>>16&255,c[l++]=f>>>8|128,c[l++]=255&f;for(var v=0;v<6;++v)c[l+v]=E[v];return t||a(c)}},function(e,t,r){var i=r(11),n=r(12);e.exports=function(e,t,r){var o=t&&r||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null);var a=(e=e||{}).random||(e.rng||i)();if(a[6]=15&a[6]|64,a[8]=63&a[8]|128,t)for(var s=0;s<16;++s)t[o+s]=a[s];return t||n(a)}},function(e,t){e.exports={handleError:function(){}}},function(e,t){e.exports={dispatchEvent:function(e,t){var i,n=e.url,o=e.params;"POST"===e.httpVerb?((i=new XMLHttpRequest).open("POST",n,!0),i.setRequestHeader("Content-Type","application/json"),i.onreadystatechange=function(){if(4===i.readyState&&t&&"function"==typeof t)try{t(o)}catch(e){}},i.send(JSON.stringify(o))):(n+="?wxhr=true",o&&(n+="&"+r(o)),(i=new XMLHttpRequest).open("GET",n,!0),i.onreadystatechange=function(){if(4===i.readyState&&t&&"function"==typeof t)try{t()}catch(e){}},i.send())}};var r=function(e){return Object.keys(e).map((function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])})).join("&")}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(2).getLogger("EventProcessor"),n=function(){function e(e){var t=e.timeout,r=e.callback;this.timeout=Math.max(t,0),this.callback=r}return e.prototype.start=function(){this.timeoutId=setTimeout(this.callback,this.timeout)},e.prototype.refresh=function(){this.stop(),this.start()},e.prototype.stop=function(){this.timeoutId&&clearTimeout(this.timeoutId)},e}(),o=function(){function e(e){var t=e.sink;this.sink=t}return e.prototype.start=function(){},e.prototype.stop=function(){return Promise.resolve()},e.prototype.enqueue=function(e){this.sink([e])},e}();t.SingleEventQueue=o;var a=function(){function e(e){var t=e.flushInterval,r=e.maxQueueSize,i=e.sink,o=e.batchComparator;this.buffer=[],this.maxQueueSize=Math.max(r,1),this.sink=i,this.batchComparator=o,this.timer=new n({callback:this.flush.bind(this),timeout:t}),this.started=!1}return e.prototype.start=function(){this.started=!0},e.prototype.stop=function(){this.started=!1;var e=this.sink(this.buffer);return this.buffer=[],this.timer.stop(),e},e.prototype.enqueue=function(e){if(this.started){var t=this.buffer[0];t&&!this.batchComparator(t,e)&&this.flush(),0===this.buffer.length&&this.timer.refresh(),this.buffer.push(e),this.buffer.length>=this.maxQueueSize&&this.flush()}else i.warn("Queue is stopped, not accepting event")},e.prototype.flush=function(){this.sink(this.buffer),this.buffer=[],this.timer.stop()},e}();t.DefaultEventQueue=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.reqsInFlightCount=0,this.reqsCompleteResolvers=[]}return e.prototype.trackRequest=function(e){var t=this;this.reqsInFlightCount++;var r=function(){t.reqsInFlightCount--,0===t.reqsInFlightCount&&(t.reqsCompleteResolvers.forEach((function(e){return e()})),t.reqsCompleteResolvers=[])};e.then(r,r)},e.prototype.onRequestsComplete=function(){var e=this;return new Promise((function(t){0===e.reqsInFlightCount?t():e.reqsCompleteResolvers.push(t)}))},e}();t.default=i},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(2),a=r(29),s=r(0),u=o.getLogger("EventProcessor"),l=function(){function e(e){var t=e.eventDispatcher,r=e.store;this.dispatcher=t,this.store=r}return e.prototype.dispatchEvent=function(e,t){this.send({uuid:s.generateUUID(),timestamp:s.getTimestamp(),request:e},t)},e.prototype.sendPendingEvents=function(){var e=this,t=this.store.values();u.debug("Sending %s pending events from previous page",t.length),t.forEach((function(t){try{e.send(t,(function(){}))}catch(e){}}))},e.prototype.send=function(e,t){var r=this;this.store.set(e.uuid,e),this.dispatcher.dispatchEvent(e.request,(function(i){r.store.remove(e.uuid),t(i)}))},e}();t.PendingEventsDispatcher=l;var c=function(e){function t(t){var r=t.eventDispatcher;return e.call(this,{eventDispatcher:r,store:new a.LocalStorageStore({maxValues:100,key:"fs_optly_pending_events"})})||this}return n(t,e),t}(l);t.LocalStoragePendingEventsDispatcher=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(0),n=r(2).getLogger("EventProcessor"),o=function(){function e(e){var t=e.key,r=e.maxValues,i=void 0===r?1e3:r;this.LS_KEY=t,this.maxValues=i}return e.prototype.get=function(e){return this.getMap()[e]||null},e.prototype.set=function(e,t){var r=this.getMap();r[e]=t,this.replace(r)},e.prototype.remove=function(e){var t=this.getMap();delete t[e],this.replace(t)},e.prototype.values=function(){return i.objectValues(this.getMap())},e.prototype.clear=function(){this.replace({})},e.prototype.replace=function(e){try{window.localStorage&&localStorage.setItem(this.LS_KEY,JSON.stringify(e)),this.clean()}catch(e){n.error(e)}},e.prototype.clean=function(){var e=this.getMap(),t=Object.keys(e),r=t.length-this.maxValues;if(!(r<1)){var i=t.map((function(t){return{key:t,value:e[t]}}));i.sort((function(e,t){return e.value.timestamp-t.value.timestamp}));for(var n=0;n0?(n=s.getExperimentFromId(e,t.experimentIds[0],this.logger))&&(o=this.getVariation(e,n.key,r,i)):this.logger.log(f.DEBUG,l(p.FEATURE_HAS_NO_EXPERIMENTS,c,t.key));var u=null;return null!==o&&null!==n&&(u=n.variationKeyMap[o]),{experiment:n,variation:u,decisionSource:_.FEATURE_TEST}},d.prototype._getExperimentInGroup=function(e,t,r){var i=n.bucketUserIntoExperiment(t,r,r,this.logger);if(i){this.logger.log(f.INFO,l(p.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP,c,r,i,t.id));var o=s.getExperimentFromId(e,i,this.logger);if(o)return o}return this.logger.log(f.INFO,l(p.USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP,c,r,t.id)),null},d.prototype._getVariationForRollout=function(e,t,r,i){if(!t.rolloutId)return this.logger.log(f.DEBUG,l(p.NO_ROLLOUT_EXISTS,c,t.key)),{experiment:null,variation:null,decisionSource:_.ROLLOUT};var o=e.rolloutIdMap[t.rolloutId];if(!o)return this.logger.log(f.ERROR,l(E.INVALID_ROLLOUT_ID,c,t.rolloutId,t.key)),{experiment:null,variation:null,decisionSource:_.ROLLOUT};if(0===o.experiments.length)return this.logger.log(f.ERROR,l(p.ROLLOUT_HAS_NO_EXPERIMENTS,c,t.rolloutId)),{experiment:null,variation:null,decisionSource:_.ROLLOUT};var a,s,u,d,g,I=this._getBucketingId(r,i),h=o.experiments.length-1;for(a=0;a0){var r=i(e[0],t);return null===r?null:!r}return null}(o,t);default:return function(e,t){for(var r=!1,n=0;nE},c.lt=function(e,t,r){var n=e.name,l=t[e.name],c=typeof l,E=e.value;if(!i.isSafeInteger(E))return r.log(a.WARNING,o(s.UNEXPECTED_CONDITION_VALUE,u,JSON.stringify(e))),null;if(null===l)return r.log(a.DEBUG,o(s.UNEXPECTED_TYPE_NULL,u,JSON.stringify(e),n)),null;if(!i.isNumber(l))return r.log(a.WARNING,o(s.UNEXPECTED_TYPE,u,JSON.stringify(e),c,n)),null;if(!i.isSafeInteger(l))return r.log(a.WARNING,o(s.OUT_OF_BOUNDS,u,JSON.stringify(e),n)),null;return l>>16)*a&65535)<<16)&4294967295)<<15|u>>>17))*s+(((u>>>16)*s&65535)<<16)&4294967295)<<13|n>>>19))+((5*(n>>>16)&65535)<<16)&4294967295))+((58964+(o>>>16)&65535)<<16);switch(u=0,r){case 3:u^=(255&e.charCodeAt(l+2))<<16;case 2:u^=(255&e.charCodeAt(l+1))<<8;case 1:n^=u=(65535&(u=(u=(65535&(u^=255&e.charCodeAt(l)))*a+(((u>>>16)*a&65535)<<16)&4294967295)<<15|u>>>17))*s+(((u>>>16)*s&65535)<<16)&4294967295}return n^=e.length,n=2246822507*(65535&(n^=n>>>16))+((2246822507*(n>>>16)&65535)<<16)&4294967295,n=3266489909*(65535&(n^=n>>>13))+((3266489909*(n>>>16)&65535)<<16)&4294967295,(n^=n>>>16)>>>0}var r=t;r.v2=function(e,t){for(var r,i=e.length,n=t^i,o=0;i>=4;)r=1540483477*(65535&(r=255&e.charCodeAt(o)|(255&e.charCodeAt(++o))<<8|(255&e.charCodeAt(++o))<<16|(255&e.charCodeAt(++o))<<24))+((1540483477*(r>>>16)&65535)<<16),n=1540483477*(65535&n)+((1540483477*(n>>>16)&65535)<<16)^(r=1540483477*(65535&(r^=r>>>24))+((1540483477*(r>>>16)&65535)<<16)),i-=4,++o;switch(i){case 3:n^=(255&e.charCodeAt(o+2))<<16;case 2:n^=(255&e.charCodeAt(o+1))<<8;case 1:n=1540483477*(65535&(n^=255&e.charCodeAt(o)))+((1540483477*(n>>>16)&65535)<<16)}return n=1540483477*(65535&(n^=n>>>13))+((1540483477*(n>>>16)&65535)<<16),(n^=n>>>15)>>>0},r.v3=t,e.exports=r}()},function(e,t){e.exports={$schema:"http://json-schema.org/draft-04/schema#",type:"object",properties:{projectId:{type:"string",required:!0},accountId:{type:"string",required:!0},groups:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},policy:{type:"string",required:!0},trafficAllocation:{type:"array",items:{type:"object",properties:{entityId:{type:"string",required:!0},endOfRange:{type:"integer",required:!0}}},required:!0},experiments:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0},status:{type:"string",required:!0},layerId:{type:"string",required:!0},variations:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0}}},required:!0},trafficAllocation:{type:"array",items:{type:"object",properties:{entityId:{type:"string",required:!0},endOfRange:{type:"integer",required:!0}}},required:!0},audienceIds:{type:"array",items:{type:"string"},required:!0},forcedVariations:{type:"object",required:!0}}},required:!0}}},required:!0},experiments:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0},status:{type:"string",required:!0},layerId:{type:"string",required:!0},variations:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0}}},required:!0},trafficAllocation:{type:"array",items:{type:"object",properties:{entityId:{type:"string",required:!0},endOfRange:{type:"integer",required:!0}}},required:!0},audienceIds:{type:"array",items:{type:"string"},required:!0},forcedVariations:{type:"object",required:!0}}},required:!0},events:{type:"array",items:{type:"object",properties:{key:{type:"string",required:!0},experimentIds:{type:"array",items:{type:"string",required:!0}},id:{type:"string",required:!0}}},required:!0},audiences:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},name:{type:"string",required:!0},conditions:{type:"string",required:!0}}},required:!0},attributes:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0}}},required:!0},version:{type:"string",required:!0},revision:{type:"string",required:!0}}}},function(e,t,r){var i=r(1),n=r(3),o=r(18),a=r(4),s=r(7),u="https://logx.optimizely.com/v1/events";function l(e){var t=e.attributes,r=e.configObj,n=r.anonymizeIP,o=r.botFiltering;null==n&&(n=!1);var u={snapshots:[],visitor_id:e.userId,attributes:[]},l={account_id:r.accountId,project_id:r.projectId,visitors:[u],revision:r.revision,client_name:e.clientEngine,client_version:e.clientVersion,anonymize_ip:n,enrich_decisions:!0};return Object.keys(t||{}).forEach((function(r){var i=t[r];if(s.isAttributeValid(r,i)){var n=a.getAttributeId(e.configObj,r,e.logger);n&&l.visitors[0].attributes.push({entity_id:n,key:r,type:"custom",value:t[r]})}})),"boolean"==typeof o&&l.visitors[0].attributes.push({entity_id:i.CONTROL_ATTRIBUTES.BOT_FILTERING,key:i.CONTROL_ATTRIBUTES.BOT_FILTERING,type:"custom",value:o}),l}e.exports={getImpressionEvent:function(e){var t={httpVerb:"POST"},r=l(e);t.url=u;var i,o,s,c=(i=e.configObj,o=e.experimentId,s=e.variationId,{decisions:[{campaign_id:a.getLayerId(i,o),experiment_id:o,variation_id:s}],events:[{entity_id:a.getLayerId(i,o),timestamp:n.currentTimestamp(),key:"campaign_activated",uuid:n.uuid()}]});return r.visitors[0].snapshots.push(c),t.params=r,t},getConversionEvent:function(e){var t={httpVerb:"POST"},r=l(e);t.url=u;var s=function(e,t,r,s){var u={events:[]},l={entity_id:a.getEventId(e,t),timestamp:n.currentTimestamp(),uuid:n.uuid(),key:t};if(r){var c=o.getRevenueValue(r,s);null!==c&&(l[i.RESERVED_EVENT_KEYWORDS.REVENUE]=c);var E=o.getEventValue(r,s);null!==E&&(l[i.RESERVED_EVENT_KEYWORDS.VALUE]=E),l.tags=r}return u.events.push(l),u}(e.configObj,e.eventKey,e.eventTags,e.logger);return r.visitors[0].snapshots=[s],t.params=r,t}}},function(e,t,r){var i=r(2),n=r(7),o=r(3),a=r(18),s=r(4),u=i.getLogger("EVENT_BUILDER");function l(e,t){var r=[];return Object.keys(t||{}).forEach((function(i){var o=t[i];if(n.isAttributeValid(i,o)){var a=s.getAttributeId(e,i,u);a&&r.push({entityId:a,key:i,value:t[i]})}})),r}t.buildImpressionEvent=function(e){var t=e.configObj,r=e.experimentKey,i=e.variationKey,n=e.userId,a=e.userAttributes,u=e.clientEngine,c=e.clientVersion,E=s.getVariationIdFromExperimentAndVariationKey(t,r,i),f=s.getExperimentId(t,r),p=s.getLayerId(t,f);return{type:"impression",timestamp:o.currentTimestamp(),uuid:o.uuid(),user:{id:n,attributes:l(t,a)},context:{accountId:t.accountId,projectId:t.projectId,revision:t.revision,clientName:u,clientVersion:c,anonymizeIP:t.anonymizeIP||!1,botFiltering:t.botFiltering},layer:{id:p},experiment:{id:f,key:r},variation:{id:E,key:i}}},t.buildConversionEvent=function(e){var t=e.configObj,r=e.userId,i=e.userAttributes,n=e.clientEngine,c=e.clientVersion,E=e.eventKey,f=e.eventTags,p=s.getEventId(t,E);return{type:"conversion",timestamp:o.currentTimestamp(),uuid:o.uuid(),user:{id:r,attributes:l(t,i)},context:{accountId:t.accountId,projectId:t.projectId,revision:t.revision,clientName:n,clientVersion:c,anonymizeIP:t.anonymizeIP||!1,botFiltering:t.botFiltering},event:{id:p,key:E},revenue:a.getRevenueValue(f,u),value:a.getEventValue(f,u),tags:f}}},function(e,t,r){var i=r(0).sprintf,n=r(1).ERROR_MESSAGES;e.exports={validate:function(e){if("object"!=typeof e||Array.isArray(e)||null===e)throw new Error(i(n.INVALID_EVENT_TAGS,"EVENT_TAGS_VALIDATOR"));return!0}}},function(e,t,r){var i=r(1),n=r(0),o=i.LOG_LEVEL,a=i.LOG_MESSAGES;function s(e){this.logger=e.logger,this.errorHandler=e.errorHandler,this.__notificationListeners={},n.objectValues(i.NOTIFICATION_TYPES).forEach(function(e){this.__notificationListeners[e]=[]}.bind(this)),this.__listenerId=1}s.prototype.addNotificationListener=function(e,t){try{if(!(n.objectValues(i.NOTIFICATION_TYPES).indexOf(e)>-1))return-1;this.__notificationListeners[e]||(this.__notificationListeners[e]=[]);var r=!1;if((this.__notificationListeners[e]||[]).forEach((function(e){if(e.callback===t)return r=!0,!1})),r)return-1;this.__notificationListeners[e].push({id:this.__listenerId,callback:t});var a=this.__listenerId;return this.__listenerId+=1,a}catch(e){return this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e),-1}},s.prototype.removeNotificationListener=function(e){try{var t,r;if(Object.keys(this.__notificationListeners).some(function(i){if((this.__notificationListeners[i]||[]).every((function(n,o){return n.id!==e||(t=o,r=i,!1)})),void 0!==t&&void 0!==r)return!0}.bind(this)),void 0!==t&&void 0!==r)return this.__notificationListeners[r].splice(t,1),!0}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}return!1},s.prototype.clearAllNotificationListeners=function(){try{n.objectValues(i.NOTIFICATION_TYPES).forEach(function(e){this.__notificationListeners[e]=[]}.bind(this))}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}},s.prototype.clearNotificationListeners=function(e){try{this.__notificationListeners[e]=[]}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}},s.prototype.sendNotifications=function(e,t){try{(this.__notificationListeners[e]||[]).forEach(function(r){var i=r.callback;try{i(t)}catch(t){this.logger.log(o.ERROR,n.sprintf(a.NOTIFICATION_LISTENER_EXCEPTION,"NOTIFICATION_CENTER",e,t.message))}}.bind(this))}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}},e.exports={createNotificationCenter:function(e){return new s(e)}}},function(e,t,r){var i=r(0).sprintf,n=r(1).ERROR_MESSAGES;e.exports={validate:function(e){if("function"!=typeof e.lookup)throw new Error(i(n.INVALID_USER_PROFILE_SERVICE,"USER_PROFILE_SERVICE_VALIDATOR","Missing function 'lookup'"));if("function"!=typeof e.save)throw new Error(i(n.INVALID_USER_PROFILE_SERVICE,"USER_PROFILE_SERVICE_VALIDATOR","Missing function 'save'"));return!0}}},function(e,t,r){var i=r(3),n=r(0).sprintf,o=r(2),a=r(6),s=r(46),u=r(1),l=r(4),c=r(54),E=o.getLogger(),f=u.ERROR_MESSAGES;function p(e,t){return e instanceof Error?e.message:t||"Unknown error"}function _(e){try{this.__initialize(e)}catch(e){E.error(e),this.__updateListeners=[],this.__configObj=null,this.__optimizelyConfigObj=null,this.__readyPromise=Promise.resolve({success:!1,reason:p(e,"Error in initialize")})}}_.prototype.__initialize=function(e){if(this.__updateListeners=[],this.jsonSchemaValidator=e.jsonSchemaValidator,this.skipJSONValidation=e.skipJSONValidation,!e.datafile&&!e.sdkKey){this.__configObj=null;var t=new Error(n(f.DATAFILE_AND_SDK_KEY_MISSING,"PROJECT_CONFIG_MANAGER"));return this.__readyPromise=Promise.resolve({success:!1,reason:p(t)}),void E.error(t)}var r,o=this.__getDatafileFromConfig(e);if(o)try{this.__configObj=l.tryCreatingProjectConfig({datafile:o,jsonSchemaValidator:this.jsonSchemaValidator,logger:E,skipJSONValidation:this.skipJSONValidation}),this.__optimizelyConfigObj=c.getOptimizelyConfig(this.__configObj)}catch(e){E.error(e),r=e,this.__configObj=null}else this.__configObj=null;if(e.sdkKey){var a={sdkKey:e.sdkKey};this.__validateDatafileOptions(e.datafileOptions)&&i.assign(a,e.datafileOptions),o&&this.__configObj&&(a.datafile=o),this.datafileManager=new s.HttpPollingDatafileManager(a),this.datafileManager.start(),this.__readyPromise=this.datafileManager.onReady().then(this.__onDatafileManagerReadyFulfill.bind(this),this.__onDatafileManagerReadyReject.bind(this)),this.datafileManager.on("update",this.__onDatafileManagerUpdate.bind(this))}else this.__configObj?this.__readyPromise=Promise.resolve({success:!0}):this.__readyPromise=Promise.resolve({success:!1,reason:p(r,"Invalid datafile")})},_.prototype.__onDatafileManagerReadyFulfill=function(){var e,t=this.datafileManager.get();try{e=l.tryCreatingProjectConfig({datafile:t,jsonSchemaValidator:this.jsonSchemaValidator,logger:E,skipJSONValidation:this.skipJSONValidation})}catch(e){return E.error(e),{success:!1,reason:p(e)}}return this.__handleNewConfigObj(e),{success:!0}},_.prototype.__onDatafileManagerReadyReject=function(e){return{success:!1,reason:p(e,"Failed to become ready")}},_.prototype.__onDatafileManagerUpdate=function(){var e,t=this.datafileManager.get();try{e=l.tryCreatingProjectConfig({datafile:t,jsonSchemaValidator:this.jsonSchemaValidator,logger:E,skipJSONValidation:this.skipJSONValidation})}catch(e){E.error(e)}e&&this.__handleNewConfigObj(e)},_.prototype.__getDatafileFromConfig=function(e){var t=null;try{e.datafile&&(a.validateDatafile(e.datafile),t="string"==typeof e.datafile||e.datafile instanceof String?JSON.parse(e.datafile):e.datafile)}catch(e){E.error(e)}return t},_.prototype.__validateDatafileOptions=function(e){return void 0===e||"object"==typeof e&&null!==e},_.prototype.__handleNewConfigObj=function(e){var t=this.__configObj;(t?t.revision:"null")!==e.revision&&(this.__configObj=e,this.__optimizelyConfigObj=c.getOptimizelyConfig(e),this.__updateListeners.forEach((function(t){t(e)})))},_.prototype.getConfig=function(){return this.__configObj},_.prototype.getOptimizelyConfig=function(){return this.__optimizelyConfigObj},_.prototype.onReady=function(){return this.__readyPromise},_.prototype.onUpdate=function(e){return this.__updateListeners.push(e),function(){var t=this.__updateListeners.indexOf(e);t>-1&&this.__updateListeners.splice(t,1)}.bind(this)},_.prototype.stop=function(){this.datafileManager&&this.datafileManager.stop(),this.__updateListeners=[]},e.exports={ProjectConfigManager:_}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(47);t.HttpPollingDatafileManager=i.default;var n=r(53);t.StaticDatafileManager=n.default},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(48),s=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return n(t,e),t.prototype.makeGetRequest=function(e,t){return a.makeGetRequest(e,t)},t.prototype.getConfigDefaults=function(){return{autoUpdate:!1}},t}(o(r(49)).default);t.default=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(8),n=r(2).getLogger("DatafileManager");t.makeGetRequest=function(e,t){var r=new XMLHttpRequest;return{responsePromise:new Promise((function(o,a){r.open("GET",e,!0),function(e,t){Object.keys(e).forEach((function(r){var i=e[r];t.setRequestHeader(r,i)}))}(t,r),r.onreadystatechange=function(){if(4===r.readyState){if(0===r.status)return void a(new Error("Request error"));var e=function(e){var t=e.getAllResponseHeaders();if(null===t)return{};var r=t.split("\r\n"),i={};return r.forEach((function(e){var t=e.indexOf(": ");if(t>-1){var r=e.slice(0,t),n=e.slice(t+2);n.length>0&&(i[r]=n)}})),i}(r),t={statusCode:r.status,body:r.responseText,headers:e};o(t)}},r.timeout=i.REQUEST_TIMEOUT_MS,r.ontimeout=function(){n.error("Request timed out")},r.send()})),abort:function(){r.abort()}}}},function(e,t,r){"use strict";var i=this&&this.__assign||function(){return(i=Object.assign||function(e){for(var t,r=1,i=arguments.length;r=200&&e<400}var f=function(){function e(e){var t=this,r=i({},this.getConfigDefaults(),e),n=r.datafile,o=r.autoUpdate,E=void 0!==o&&o,f=r.sdkKey,p=r.updateInterval,_=void 0===p?u.DEFAULT_UPDATE_INTERVAL:p,d=r.urlTemplate,g=void 0===d?u.DEFAULT_URL_TEMPLATE:d;this.isReadyPromiseSettled=!1,this.readyPromiseResolver=function(){},this.readyPromiseRejecter=function(){},this.readyPromise=new Promise((function(e,r){t.readyPromiseResolver=e,t.readyPromiseRejecter=r})),n?(this.currentDatafile=n,this.resolveReadyPromise()):this.currentDatafile=null,this.isStarted=!1,this.datafileUrl=a.sprintf(g,f),this.emitter=new s.default,this.autoUpdate=E,!function(e){return e>=u.MIN_UPDATE_INTERVAL}(_)?(c.warn("Invalid updateInterval %s, defaulting to %s",_,u.DEFAULT_UPDATE_INTERVAL),this.updateInterval=u.DEFAULT_UPDATE_INTERVAL):this.updateInterval=_,this.currentTimeout=null,this.currentRequest=null,this.backoffController=new l.default,this.syncOnCurrentRequestComplete=!1}return e.prototype.get=function(){return this.currentDatafile},e.prototype.start=function(){this.isStarted||(c.debug("Datafile manager started"),this.isStarted=!0,this.backoffController.reset(),this.syncDatafile())},e.prototype.stop=function(){return c.debug("Datafile manager stopped"),this.isStarted=!1,this.currentTimeout&&(clearTimeout(this.currentTimeout),this.currentTimeout=null),this.emitter.removeAllListeners(),this.currentRequest&&(this.currentRequest.abort(),this.currentRequest=null),Promise.resolve()},e.prototype.onReady=function(){return this.readyPromise},e.prototype.on=function(e,t){return this.emitter.on(e,t)},e.prototype.onRequestRejected=function(e){this.isStarted&&(this.backoffController.countError(),e instanceof Error?c.error("Error fetching datafile: %s",e.message,e):"string"==typeof e?c.error("Error fetching datafile: %s",e):c.error("Error fetching datafile"))},e.prototype.onRequestResolved=function(e){if(this.isStarted){void 0!==e.statusCode&&E(e.statusCode)?this.backoffController.reset():this.backoffController.countError(),this.trySavingLastModified(e.headers);var t=this.getNextDatafileFromResponse(e);if(null!==t)if(c.info("Updating datafile from response"),this.currentDatafile=t,this.isReadyPromiseSettled){var r={datafile:t};this.emitter.emit("update",r)}else this.resolveReadyPromise()}},e.prototype.onRequestComplete=function(){this.isStarted&&(this.currentRequest=null,this.isReadyPromiseSettled||this.autoUpdate||this.rejectReadyPromise(new Error("Failed to become ready")),this.autoUpdate&&this.syncOnCurrentRequestComplete&&this.syncDatafile(),this.syncOnCurrentRequestComplete=!1)},e.prototype.syncDatafile=function(){var e=this,t={};this.lastResponseLastModified&&(t["if-modified-since"]=this.lastResponseLastModified),c.debug("Making datafile request to url %s with headers: %s",this.datafileUrl,(function(){return JSON.stringify(t)})),this.currentRequest=this.makeGetRequest(this.datafileUrl,t);var r=function(){e.onRequestComplete()};this.currentRequest.responsePromise.then((function(t){e.onRequestResolved(t)}),(function(t){e.onRequestRejected(t)})).then(r,r),this.autoUpdate&&this.scheduleNextUpdate()},e.prototype.resolveReadyPromise=function(){this.readyPromiseResolver(),this.isReadyPromiseSettled=!0},e.prototype.rejectReadyPromise=function(e){this.readyPromiseRejecter(e),this.isReadyPromiseSettled=!0},e.prototype.scheduleNextUpdate=function(){var e=this,t=this.backoffController.getDelay(),r=Math.max(t,this.updateInterval);c.debug("Scheduling sync in %s ms",r),this.currentTimeout=setTimeout((function(){e.currentRequest?e.syncOnCurrentRequestComplete=!0:e.syncDatafile()}),r)},e.prototype.getNextDatafileFromResponse=function(e){return c.debug("Response status code: %s",e.statusCode),void 0===e.statusCode||304===e.statusCode?null:E(e.statusCode)?this.tryParsingBodyAsJSON(e.body):null},e.prototype.tryParsingBodyAsJSON=function(e){var t;try{t=JSON.parse(e)}catch(e){return c.error("Error parsing response body: %s",e.message,e),null}var r=null;return"object"==typeof t&&null!==t?r=t:c.error("Error parsing response body: was not an object"),r},e.prototype.trySavingLastModified=function(e){var t=e["last-modified"]||e["Last-Modified"];void 0!==t&&(this.lastResponseLastModified=t,c.debug("Saved last modified header value from response: %s",this.lastResponseLastModified))},e}();t.default=f},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(5);function n(e){return Object.keys(e).map((function(t){return e[t]}))}t.getTimestamp=function(){return(new Date).getTime()},t.generateUUID=function(){return i.v4()},t.isValidEnum=function(e,t){for(var r=!1,i=Object.keys(e),n=0;n=1},validateEventFlushInterval:function(e){return i.isSafeInteger(e)&&e>0}}}])})); \ No newline at end of file diff --git a/packages/optimizely-sdk/package-lock.json b/packages/optimizely-sdk/package-lock.json index 77390c0ab..bc94fa731 100644 --- a/packages/optimizely-sdk/package-lock.json +++ b/packages/optimizely-sdk/package-lock.json @@ -79,175 +79,178 @@ } }, "@webassemblyjs/ast": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.7.11.tgz", - "integrity": "sha512-ZEzy4vjvTzScC+SH8RBssQUawpaInUdMTYwYYLh54/s8TuT0gBLuyUnppKsVyZEi876VmmStKsUs28UxPgdvrA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", "dev": true, "requires": { - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11" + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.7.11.tgz", - "integrity": "sha512-zY8dSNyYcgzNRNT666/zOoAyImshm3ycKdoLsyDw/Bwo6+/uktb7p4xyApuef1dwEBo/U/SYQzbGBvV+nru2Xg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.7.11.tgz", - "integrity": "sha512-7r1qXLmiglC+wPNkGuXCvkmalyEstKVwcueZRP2GNC2PAvxbLYwLLPr14rcdJaE4UtHxQKfFkuDFuv91ipqvXg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.7.11.tgz", - "integrity": "sha512-MynuervdylPPh3ix+mKZloTcL06P8tenNH3sx6s0qE8SLR6DdwnfgA7Hc9NSYeob2jrW5Vql6GVlsQzKQCa13w==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", "dev": true }, "@webassemblyjs/helper-code-frame": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.7.11.tgz", - "integrity": "sha512-T8ESC9KMXFTXA5urJcyor5cn6qWeZ4/zLPyWeEXZ03hj/x9weSokGNkVCdnhSabKGYWxElSdgJ+sFa9G/RdHNw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", "dev": true, "requires": { - "@webassemblyjs/wast-printer": "1.7.11" + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/helper-fsm": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.7.11.tgz", - "integrity": "sha512-nsAQWNP1+8Z6tkzdYlXT0kxfa2Z1tRTARd8wYnc/e3Zv3VydVVnaeePgqUzFrpkGUyhUUxOl5ML7f1NuT+gC0A==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", "dev": true }, "@webassemblyjs/helper-module-context": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.7.11.tgz", - "integrity": "sha512-JxfD5DX8Ygq4PvXDucq0M+sbUFA7BJAv/GGl9ITovqE+idGX+J3QSzJYz+LwQmL7fC3Rs+utvWoJxDb6pmC0qg==", - "dev": true + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.7.11.tgz", - "integrity": "sha512-cMXeVS9rhoXsI9LLL4tJxBgVD/KMOKXuFqYb5oCJ/opScWpkCMEz9EJtkonaNcnLv2R3K5jIeS4TRj/drde1JQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.7.11.tgz", - "integrity": "sha512-8ZRY5iZbZdtNFE5UFunB8mmBEAbSI3guwbrsCl4fWdfRiAcvqQpeqd5KHhSWLL5wuxo53zcaGZDBU64qgn4I4Q==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" } }, "@webassemblyjs/ieee754": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.7.11.tgz", - "integrity": "sha512-Mmqx/cS68K1tSrvRLtaV/Lp3NZWzXtOHUW2IvDvl2sihAwJh4ACE0eL6A8FvMyDG9abes3saB6dMimLOs+HMoQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.7.11.tgz", - "integrity": "sha512-vuGmgZjjp3zjcerQg+JA+tGOncOnJLWVkt8Aze5eWQLwTQGNgVLcyOTqgSCxWTR4J42ijHbBxnuRaL1Rv7XMdw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", "dev": true, "requires": { - "@xtuc/long": "4.2.1" + "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.7.11.tgz", - "integrity": "sha512-C6GFkc7aErQIAH+BMrIdVSmW+6HSe20wg57HEC1uqJP8E/xpMjXqQUxkQw07MhNDSDcGpxI9G5JSNOQCqJk4sA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.7.11.tgz", - "integrity": "sha512-FUd97guNGsCZQgeTPKdgxJhBXkUbMTY6hFPf2Y4OedXd48H97J+sOY2Ltaq6WGVpIH8o/TGOVNiVz/SbpEMJGg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/helper-wasm-section": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-opt": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "@webassemblyjs/wast-printer": "1.7.11" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" } }, "@webassemblyjs/wasm-gen": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.7.11.tgz", - "integrity": "sha512-U/KDYp7fgAZX5KPfq4NOupK/BmhDc5Kjy2GIqstMhvvdJRcER/kUsMThpWeRP8BMn4LXaKhSTggIJPOeYHwISA==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wasm-opt": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.7.11.tgz", - "integrity": "sha512-XynkOwQyiRidh0GLua7SkeHvAPXQV/RxsUeERILmAInZegApOUAIJfRuPYe2F7RcjOC9tW3Cb9juPvAC/sCqvg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-buffer": "1.7.11", - "@webassemblyjs/wasm-gen": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" } }, "@webassemblyjs/wasm-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.7.11.tgz", - "integrity": "sha512-6lmXRTrrZjYD8Ng8xRyvyXQJYUQKYSXhJqXOBLw24rdiXsHAOlvw5PhesjdcaMadU/pyPQOJ5dHreMjBxwnQKg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-wasm-bytecode": "1.7.11", - "@webassemblyjs/ieee754": "1.7.11", - "@webassemblyjs/leb128": "1.7.11", - "@webassemblyjs/utf8": "1.7.11" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" } }, "@webassemblyjs/wast-parser": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.7.11.tgz", - "integrity": "sha512-lEyVCg2np15tS+dm7+JJTNhNWq9yTZvi3qEhAIIOaofcYlUp0UR5/tVqOwa/gXYr3gjwSZqw+/lS9dscyLelbQ==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/floating-point-hex-parser": "1.7.11", - "@webassemblyjs/helper-api-error": "1.7.11", - "@webassemblyjs/helper-code-frame": "1.7.11", - "@webassemblyjs/helper-fsm": "1.7.11", - "@xtuc/long": "4.2.1" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" } }, "@webassemblyjs/wast-printer": { - "version": "1.7.11", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.7.11.tgz", - "integrity": "sha512-m5vkAsuJ32QpkdkDOUPGSltrg8Cuk3KBx4YrmAGQwCZPRdUHXxG4phIOuuycLemHFr74sWL9Wthqss4fzdzSwg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/wast-parser": "1.7.11", - "@xtuc/long": "4.2.1" + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" } }, "@xtuc/ieee754": { @@ -257,9 +260,9 @@ "dev": true }, "@xtuc/long": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.1.tgz", - "integrity": "sha512-FZdkNBDqBRHKQ2MEbSC17xnPFOhZxeJ2YGSfr2BKf3sujG49Qe3bB+rGCwQfIaA7WHnGeGkSijX4FuBCdrzW/g==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, "abbrev": { @@ -269,30 +272,38 @@ "dev": true }, "accepts": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", "dev": true, "requires": { - "mime-types": "~2.1.18", - "negotiator": "0.6.1" + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "dependencies": { + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "dev": true, + "requires": { + "mime-db": "1.43.0" + } + } } }, "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true }, - "acorn-dynamic-import": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz", - "integrity": "sha512-zVWV8Z8lislJoOKKqdNMOB+s6+XV5WERty8MnKBeFgwA+19XJjJHs2RP5dzM57FftIs+jQnRToLiWazKr6sSWg==", - "dev": true, - "requires": { - "acorn": "^5.0.0" - } - }, "acorn-jsx": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", @@ -326,6 +337,18 @@ "json-schema-traverse": "^0.3.0" } }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", + "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "dev": true + }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -357,6 +380,24 @@ "color-convert": "^1.9.0" } }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -380,6 +421,12 @@ } } }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", @@ -398,16 +445,10 @@ "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", "dev": true }, - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - }, "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, "arraybuffer.slice": { @@ -434,11 +475,12 @@ } }, "assert": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", - "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", "dev": true, "requires": { + "object-assign": "^4.1.1", "util": "0.10.3" }, "dependencies": { @@ -490,15 +532,15 @@ "dev": true }, "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", "dev": true }, "async-limiter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", - "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", "dev": true }, "asynckit": { @@ -593,18 +635,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -615,9 +645,9 @@ "dev": true }, "base64-js": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", - "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", "dev": true }, "base64id": { @@ -652,15 +682,25 @@ "dev": true }, "binary-extensions": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", - "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "blob": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", - "integrity": "sha1-vPEwUspURj8w+fx+lbmkdjCpSSE=", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", + "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", "dev": true }, "bluebird": { @@ -676,21 +716,29 @@ "dev": true }, "body-parser": { - "version": "1.18.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", - "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", "dev": true, "requires": { - "bytes": "3.0.0", + "bytes": "3.1.0", "content-type": "~1.0.4", "debug": "2.6.9", "depd": "~1.1.2", - "http-errors": "~1.6.3", - "iconv-lite": "0.4.23", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "on-finished": "~2.3.0", - "qs": "6.5.2", - "raw-body": "2.3.3", - "type-is": "~1.6.16" + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } } }, "brace-expansion": { @@ -703,6 +751,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", @@ -808,9 +865,9 @@ } }, "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -818,6 +875,28 @@ "isarray": "^1.0.0" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -837,30 +916,84 @@ "dev": true }, "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true }, "cacache": { - "version": "10.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.4.tgz", - "integrity": "sha512-Dph0MzuH+rTQzGPNT9fAnrPmMmjKfST6trxJeK7NQuHRaVw24VzPRWTmg9MpcwOVQZO0E1FBICUlFeNaKPIfHA==", - "dev": true, - "requires": { - "bluebird": "^3.5.1", - "chownr": "^1.0.1", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "lru-cache": "^4.1.1", - "mississippi": "^2.0.0", + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.2", - "ssri": "^5.2.4", - "unique-filename": "^1.1.0", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", "y18n": "^4.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } } }, "cache-base": { @@ -878,14 +1011,6 @@ "to-object-path": "^0.3.0", "union-value": "^1.0.0", "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "callsite": { @@ -949,16 +1074,71 @@ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, + "chokidar": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", + "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.3.0" + }, + "dependencies": { + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "readdirp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", + "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.7" + } + } + } + }, "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "chrome-trace-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz", - "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -994,12 +1174,6 @@ "requires": { "is-descriptor": "^0.1.0" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true } } }, @@ -1056,20 +1230,11 @@ "dev": true }, "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true }, - "combine-lists": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/combine-lists/-/combine-lists-1.0.1.tgz", - "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", - "dev": true, - "requires": { - "lodash": "^4.5.0" - } - }, "combined-stream": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", @@ -1128,25 +1293,22 @@ } }, "connect": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.6.6.tgz", - "integrity": "sha1-Ce/2xVr3I24TcTWnJXSFi2eG9SQ=", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", "dev": true, "requires": { "debug": "2.6.9", - "finalhandler": "1.1.0", - "parseurl": "~1.3.2", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true }, "constants-browserify": { "version": "1.0.0", @@ -1385,9 +1547,9 @@ "dev": true }, "cyclist": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, "d": { @@ -1409,15 +1571,9 @@ } }, "date-format": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/date-format/-/date-format-1.2.0.tgz", - "integrity": "sha1-YV6CjiM90aubua4JUODOzPpuytg=", - "dev": true - }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz", + "integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA==", "dev": true }, "debug": { @@ -1503,18 +1659,6 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true } } }, @@ -1531,9 +1675,9 @@ "dev": true }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -1597,9 +1741,9 @@ "dev": true }, "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", "dev": true, "requires": { "end-of-stream": "^1.0.0", @@ -1625,9 +1769,9 @@ "dev": true }, "elliptic": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", - "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -1658,24 +1802,79 @@ "dev": true }, "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "dev": true, "requires": { "once": "^1.4.0" } }, + "engine.io": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", + "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "engine.io-client": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", + "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~3.3.1", + "xmlhttprequest-ssl": "~1.5.4", + "yeast": "0.1.2" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "engine.io-parser": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.2.tgz", - "integrity": "sha512-dInLFzr80RijZ1rGpx1+56/uFoH7/7InhH3kZt+Ms6hT8tNx3NGW/WNSA/f8As1WkOfkuyb3tnRyuXGxusclMw==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", + "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", "dev": true, "requires": { "after": "0.8.2", "arraybuffer.slice": "~0.0.7", "base64-arraybuffer": "0.1.5", - "blob": "0.0.4", + "blob": "0.0.5", "has-binary2": "~1.0.2" } }, @@ -2008,15 +2207,15 @@ } }, "eventemitter3": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", - "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", + "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", "dev": true }, "events": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", "dev": true }, "evp_bytestokey": { @@ -2044,54 +2243,45 @@ "strip-eof": "^1.0.0" } }, - "expand-braces": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", - "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { - "braces": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-0.1.5.tgz", - "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "expand-range": "^0.1.0" + "is-descriptor": "^0.1.0" } }, - "expand-range": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-0.1.1.tgz", - "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" + "is-extendable": "^0.1.0" } - }, - "is-number": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-0.1.1.tgz", - "integrity": "sha1-aaevEWlj1HIG7JvZtIoUIW8eOAY=", - "dev": true - }, - "repeat-string": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-0.2.2.tgz", - "integrity": "sha1-x6jTI2BoNiBZp+RlH8aITosftK4=", - "dev": true } } }, "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "dev": true }, "extend-shallow": { @@ -2137,6 +2327,71 @@ } } }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + } + } + }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", @@ -2161,6 +2416,12 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, "figures": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", @@ -2179,47 +2440,66 @@ "flat-cache": "^2.0.1" } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + }, + "dependencies": { + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.1", + "encodeurl": "~1.0.2", "escape-html": "~1.0.3", "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", "unpipe": "~1.0.0" - }, - "dependencies": { - "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", - "dev": true - } } }, "find-cache-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", - "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { "commondir": "^1.0.1", - "make-dir": "^1.0.0", - "pkg-dir": "^2.0.0" + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" } }, "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "^3.0.0" } }, "flat-cache": { @@ -2265,32 +2545,38 @@ "dev": true }, "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", "dev": true, "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" } }, "follow-redirects": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", - "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz", + "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==", "dev": true, "requires": { - "debug": "^3.1.0" + "debug": "^3.0.0" }, "dependencies": { "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -2360,6 +2646,17 @@ "null-check": "^1.0.0" } }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -2379,41 +2676,38 @@ "dev": true }, "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.12.tgz", + "integrity": "sha512-Ggd/Ktt7E7I8pxZRbGIs7vwqAPscSESMrCSkx2FtWeqmheJgCo2R74fTsZFCifr0VTPwqRpPv17+6b8Zp7th0Q==", "dev": true, "optional": true, "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" + "bindings": "^1.5.0", + "nan": "^2.12.1", + "node-pre-gyp": "*" }, "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "bundled": true, "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "bundled": true, "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "bundled": true, "dev": true, "optional": true }, "are-we-there-yet": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "version": "1.1.5", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2423,15 +2717,13 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "bundled": true, "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2440,92 +2732,80 @@ } }, "chownr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", - "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "version": "1.1.4", + "bundled": true, "dev": true, "optional": true }, "code-point-at": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "bundled": true, "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "bundled": true, "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "bundled": true, "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "bundled": true, "dev": true, "optional": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "3.2.6", + "bundled": true, "dev": true, "optional": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "deep-extend": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==", + "version": "0.6.0", + "bundled": true, "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "bundled": true, "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "bundled": true, "dev": true, "optional": true }, "fs-minipass": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "version": "1.2.7", + "bundled": true, "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "^2.6.0" } }, "fs.realpath": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "bundled": true, "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2540,9 +2820,8 @@ } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.6", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2556,25 +2835,22 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "bundled": true, "dev": true, "optional": true }, "iconv-lite": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", - "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "version": "0.4.24", + "bundled": true, "dev": true, "optional": true, "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": ">= 2.1.2 < 3" } }, "ignore-walk": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", - "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "version": "3.0.3", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2583,8 +2859,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2593,23 +2868,20 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "bundled": true, "dev": true, "optional": true }, "ini": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "bundled": true, "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2618,15 +2890,13 @@ }, "isarray": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "bundled": true, "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2634,85 +2904,77 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "version": "1.2.5", + "bundled": true, "dev": true, "optional": true }, "minipass": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.4.tgz", - "integrity": "sha512-hzXIWWet/BzWhYs2b+u7dRHlruXhwdgvlTMDKC6Cb1U7ps6Ac6yQlR39xsbjWJE377YTCtKwIXIpJ5oP+j5y8g==", + "version": "2.9.0", + "bundled": true, "dev": true, "optional": true, "requires": { - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.0" } }, "minizlib": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.0.tgz", - "integrity": "sha512-4T6Ur/GctZ27nHfpt9THOdRZNgyJ9FZchYO1ceg5S8Q3DNLCKYy44nCZzgCJgcvx2UM8czmqak5BCxJMrq37lA==", + "version": "1.3.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "minipass": "^2.2.1" + "minipass": "^2.9.0" } }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.2", + "bundled": true, "dev": true, "optional": true }, "needle": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.0.tgz", - "integrity": "sha512-eFagy6c+TYayorXw/qtAdSvaUpEbBsDwDyxYFgLZ0lTojfH7K+OdBqAF7TAFwDokJaGpubpSGG0wO3iC0XPi8w==", + "version": "2.3.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "debug": "^2.1.2", + "debug": "^3.2.6", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, "node-pre-gyp": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.0.tgz", - "integrity": "sha512-G7kEonQLRbcA/mOoFoxvlMrw6Q6dPf92+t/l0DFSMuSlDoWaI9JWIyPwK0jyE1bph//CUEL65/Fz1m2vJbmjQQ==", + "version": "0.14.0", + "bundled": true, "dev": true, "optional": true, "requires": { "detect-libc": "^1.0.2", "mkdirp": "^0.5.1", - "needle": "^2.2.0", + "needle": "^2.2.1", "nopt": "^4.0.1", "npm-packlist": "^1.1.6", "npmlog": "^4.0.2", - "rc": "^1.1.7", + "rc": "^1.2.7", "rimraf": "^2.6.1", "semver": "^5.3.0", - "tar": "^4" + "tar": "^4.4.2" } }, "nopt": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "version": "4.0.3", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2721,27 +2983,34 @@ } }, "npm-bundled": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.3.tgz", - "integrity": "sha512-ByQ3oJ/5ETLyglU2+8dBObvhfWXX8dtPZDMePCahptliFX2iIuhyEszyFk401PZUNQH20vvdW5MLjJxkwU80Ow==", + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, "dev": true, "optional": true }, "npm-packlist": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.10.tgz", - "integrity": "sha512-AQC0Dyhzn4EiYEfIUjCdMl0JJ61I2ER9ukf/sLxJUcZHfo+VyEfz2rMJgLZSS1v30OxPQe1cN0LZA1xbcaVfWA==", + "version": "1.4.8", + "bundled": true, "dev": true, "optional": true, "requires": { "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "npmlog": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2753,22 +3022,19 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "bundled": true, "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "bundled": true, "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2777,22 +3043,19 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "bundled": true, "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "bundled": true, "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2802,44 +3065,31 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "bundled": true, "dev": true, "optional": true }, "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "version": "2.0.1", + "bundled": true, "dev": true, "optional": true }, "rc": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "version": "1.2.8", + "bundled": true, "dev": true, "optional": true, "requires": { - "deep-extend": "^0.5.1", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "optional": true - } } }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2853,61 +3103,53 @@ } }, "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "version": "2.7.1", + "bundled": true, "dev": true, "optional": true, "requires": { - "glob": "^7.0.5" + "glob": "^7.1.3" } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "version": "5.1.2", + "bundled": true, "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "bundled": true, "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "bundled": true, "dev": true, "optional": true }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.7.1", + "bundled": true, "dev": true, "optional": true }, "set-blocking": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "bundled": true, "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "bundled": true, "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2918,8 +3160,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2928,8 +3169,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "dev": true, "optional": true, "requires": { @@ -2938,55 +3178,49 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "bundled": true, "dev": true, "optional": true }, "tar": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "version": "4.4.13", + "bundled": true, "dev": true, "optional": true, "requires": { - "chownr": "^1.0.1", + "chownr": "^1.1.1", "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" } }, "util-deprecate": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "bundled": true, "dev": true, "optional": true }, "wide-align": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "version": "1.1.3", + "bundled": true, "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2" + "string-width": "^1.0.2 || 2" } }, "wrappy": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "bundled": true, "dev": true, "optional": true }, "yallist": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", - "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=", + "version": "3.1.1", + "bundled": true, "dev": true, "optional": true } @@ -3175,14 +3409,6 @@ "get-value": "^2.0.6", "has-values": "^1.0.0", "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "has-values": { @@ -3237,9 +3463,9 @@ } }, "hash.js": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.5.tgz", - "integrity": "sha512-eWI5HG9Np+eHV1KQhisXWwM+4EPPYe5dFX1UZZH7k/E3JzDEazVH+VGlZi6R94ZqImq+A3D1mCEtrFIfg/E7sA==", + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -3264,24 +3490,25 @@ } }, "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", "dev": true, "requires": { "depd": "~1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" } }, "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", + "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", "dev": true, "requires": { - "eventemitter3": "^3.0.0", + "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } @@ -3331,18 +3558,18 @@ } }, "iconv-lite": { - "version": "0.4.23", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, "ieee754": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz", - "integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", "dev": true }, "iferr": { @@ -3451,6 +3678,12 @@ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", "dev": true }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -3560,6 +3793,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-binary-path": { @@ -3584,6 +3828,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "is-descriptor": { @@ -3632,6 +3887,12 @@ "is-extglob": "^2.1.1" } }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -3639,14 +3900,6 @@ "dev": true, "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "is-promise": { @@ -3679,6 +3932,12 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -3686,10 +3945,13 @@ "dev": true }, "isbinaryfile": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", - "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", - "dev": true + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } }, "isexe": { "version": "2.0.0", @@ -3697,6 +3959,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -3827,6 +4095,15 @@ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", "dev": true }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -3840,28 +4117,26 @@ } }, "karma": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/karma/-/karma-3.1.4.tgz", - "integrity": "sha512-31Vo8Qr5glN+dZEVIpnPCxEGleqE0EY6CtC2X9TagRV3rRQ3SNrvfhddICkJgUK3AgqpeKSZau03QumTGhGoSw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-4.4.1.tgz", + "integrity": "sha512-L5SIaXEYqzrh6b1wqYC42tNsFMx2PWuxky84pK9coK09MvmL7mxii3G3bZBh/0rvD27lqDd0le9jyhzvwif73A==", "dev": true, "requires": { "bluebird": "^3.3.0", "body-parser": "^1.16.1", - "chokidar": "^2.0.3", + "braces": "^3.0.2", + "chokidar": "^3.0.0", "colors": "^1.1.0", - "combine-lists": "^1.0.0", "connect": "^3.6.0", - "core-js": "^2.2.0", "di": "^0.0.1", "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", "flatted": "^2.0.0", "glob": "^7.1.1", "graceful-fs": "^4.1.2", "http-proxy": "^1.13.0", "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", + "lodash": "^4.17.14", + "log4js": "^4.0.0", "mime": "^2.3.1", "minimatch": "^3.0.2", "optimist": "^0.6.1", @@ -3875,575 +4150,11 @@ "useragent": "2.3.0" }, "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "circular-json": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.5.9.tgz", - "integrity": "sha512-4ivwqHpIFJZBuhN3g/pEcdbnGUywkBblloGbkglyloVjjR3uT6tieI89MVOfbP2tHX5sgb01FuLgAOzebNlJNQ==", - "dev": true - }, - "engine.io": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz", - "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "engine.io-client": { - "version": "3.2.1", - "resolved": "http://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz", - "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "log4js": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/log4js/-/log4js-3.0.6.tgz", - "integrity": "sha512-ezXZk6oPJCWL483zj64pNkMuY/NcRX5MPiB0zE6tjZM137aeusrOnW1ecxgF9cmwMWkBMhjteQxBPoZBh9FDxQ==", - "dev": true, - "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", - "dev": true - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "socket.io": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", - "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", - "dev": true, - "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "socket.io-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", - "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "socket.io-parser": { - "version": "3.2.0", - "resolved": "http://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", - "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "useragent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", - "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", - "dev": true, - "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" - } } } }, @@ -4542,13 +4253,10 @@ } }, "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true }, "lcid": { "version": "2.0.0", @@ -4576,9 +4284,9 @@ } }, "loader-runner": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.1.tgz", - "integrity": "sha512-By6ZFY7ETWOc9RFaAIb23IjJVcM4dvJC/N57nmdz9RSkMXvAXGI7SyVlAw3v8vjtDRlqThgVDVmTnr9fqMlxkw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", "dev": true }, "loader-utils": { @@ -4593,12 +4301,12 @@ } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", "dev": true, "requires": { - "p-locate": "^2.0.0", + "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, @@ -4608,12 +4316,6 @@ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", "dev": true }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -4666,6 +4368,36 @@ } } }, + "log4js": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", + "integrity": "sha512-EEEgFcE9bLgaYUKuozyFfytQM2wDHtXn4tAN41pkaxpNjAykv11GVdeI4tHtmPWW4Xrgh9R/2d7XYghDVjbKKw==", + "dev": true, + "requires": { + "date-format": "^2.0.0", + "debug": "^4.1.1", + "flatted": "^2.0.0", + "rfdc": "^1.1.4", + "streamroller": "^1.0.6" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "loglevelnext": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", @@ -4703,90 +4435,186 @@ } }, "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true } } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", - "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^1.0.0", - "p-is-promise": "^1.1.0" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.0.0.tgz", + "integrity": "sha512-WQxG/5xYc3tMbYLXoXPm81ET2WDULiU5FxbuIoNbJqLOOI8zehXFdZuiUEgfdrU2mVB1pxBZUGlYORSrpuJreA==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^1.0.0", + "p-is-promise": "^1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + } + } + }, "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", @@ -4797,6 +4625,12 @@ "brorand": "^1.0.1" } }, + "mime": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", + "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "dev": true + }, "mime-db": { "version": "1.33.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", @@ -4846,9 +4680,9 @@ "dev": true }, "mississippi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-2.0.0.tgz", - "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { "concat-stream": "^1.5.0", @@ -4857,16 +4691,16 @@ "flush-write-stream": "^1.0.0", "from2": "^2.1.0", "parallel-transform": "^1.1.0", - "pump": "^2.0.1", + "pump": "^3.0.0", "pumpify": "^1.3.3", "stream-each": "^1.1.0", "through2": "^2.0.0" } }, "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { "for-in": "^1.0.2", @@ -4984,9 +4818,9 @@ "dev": true }, "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", + "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "dev": true, "optional": true }, @@ -5007,26 +4841,6 @@ "regex-not": "^1.0.0", "snapdragon": "^0.8.1", "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } } }, "native-promise-only": { @@ -5042,9 +4856,9 @@ "dev": true }, "negotiator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", - "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", "dev": true }, "neo-async": { @@ -5124,9 +4938,9 @@ } }, "node-libs-browser": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", - "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", "dev": true, "requires": { "assert": "^1.1.1", @@ -5136,10 +4950,10 @@ "constants-browserify": "^1.0.0", "crypto-browserify": "^3.11.0", "domain-browser": "^1.1.1", - "events": "^1.0.0", + "events": "^3.0.0", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", - "path-browserify": "0.0.0", + "path-browserify": "0.0.1", "process": "^0.11.10", "punycode": "^1.2.4", "querystring-es3": "^0.2.0", @@ -5150,8 +4964,8 @@ "timers-browserify": "^2.0.4", "tty-browserify": "0.0.0", "url": "^0.11.0", - "util": "^0.10.3", - "vm-browserify": "0.0.4" + "util": "^0.11.0", + "vm-browserify": "^1.0.1" } }, "nopt": { @@ -5164,13 +4978,10 @@ } }, "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true }, "npm-run-path": { "version": "2.0.2", @@ -5193,6 +5004,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, "object-component": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", @@ -5218,6 +5035,15 @@ "requires": { "is-descriptor": "^0.1.0" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, @@ -5234,14 +5060,6 @@ "dev": true, "requires": { "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "object.assign": { @@ -5263,14 +5081,6 @@ "dev": true, "requires": { "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } } }, "on-finished": { @@ -5388,42 +5198,42 @@ "dev": true }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", + "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", "dev": true, "requires": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "^2.0.0" } }, "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, "parallel-transform": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", "dev": true, "requires": { - "cyclist": "~0.2.2", + "cyclist": "^1.0.1", "inherits": "^2.0.3", "readable-stream": "^2.1.5" } @@ -5438,16 +5248,17 @@ } }, "parse-asn1": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", - "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", "dev": true, "requires": { "asn1.js": "^4.0.0", "browserify-aes": "^1.0.0", "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, "parseqs": { @@ -5469,9 +5280,9 @@ } }, "parseurl": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", - "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", "dev": true }, "pascalcase": { @@ -5481,9 +5292,9 @@ "dev": true }, "path-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", - "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", "dev": true }, "path-dirname": { @@ -5561,13 +5372,25 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, "pkg-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", - "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "find-up": "^2.1.0" + "find-up": "^3.0.0" } }, "posix-character-classes": { @@ -5609,7 +5432,8 @@ "promise-polyfill": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.0.tgz", - "integrity": "sha512-OzSf6gcCUQ01byV4BgwyUCswlaQQ6gzXc23aLQWhicvfX9kfsUiUhgt3CCQej8jDnl8/PhGF31JdHX2/MzF3WA==" + "integrity": "sha512-OzSf6gcCUQ01byV4BgwyUCswlaQQ6gzXc23aLQWhicvfX9kfsUiUhgt3CCQej8jDnl8/PhGF31JdHX2/MzF3WA==", + "dev": true }, "propagate": { "version": "0.3.1", @@ -5659,9 +5483,9 @@ } }, "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { "end-of-stream": "^1.1.0", @@ -5677,6 +5501,18 @@ "duplexify": "^3.6.0", "inherits": "^2.0.3", "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, "punycode": { @@ -5716,9 +5552,9 @@ "dev": true }, "randombytes": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", - "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "requires": { "safe-buffer": "^5.1.0" @@ -5741,14 +5577,14 @@ "dev": true }, "raw-body": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", - "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, "requires": { - "bytes": "3.0.0", - "http-errors": "1.6.3", - "iconv-lite": "0.4.23", + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", "unpipe": "1.0.0" } }, @@ -5768,15 +5604,14 @@ } }, "readdirp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", - "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" } }, "regenerator-runtime": { @@ -5808,9 +5643,9 @@ "dev": true }, "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", "dev": true }, "repeat-string": { @@ -5881,9 +5716,9 @@ "dev": true }, "rfdc": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.2.tgz", - "integrity": "sha512-92ktAgvZhBzYTIK0Mja9uen5q5J3NRVMoDkJL2VMwq6SXjVCgqvQeVP2XAaUY6HT+XpQYeLSjb3UoitBryKmdA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", + "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", "dev": true }, "rimraf": { @@ -5960,37 +5795,32 @@ "dev": true }, "schema-utils": { - "version": "0.4.7", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz", - "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", "ajv-keywords": "^3.1.0" }, "dependencies": { "ajv": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", - "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", "dev": true }, "json-schema-traverse": { @@ -6008,9 +5838,9 @@ "dev": true }, "serialize-javascript": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.5.0.tgz", - "integrity": "sha512-Ga8c8NjAAp46Br4+0oZ2WxJCwIzwP60Gq1YPgU+39PiTVxyed/iKE/zyZI6+UlVYH5Q4PaQdHhcegIFPZTUfoQ==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, "set-blocking": { @@ -6019,16 +5849,10 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "set-immediate-shim": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", - "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", - "dev": true - }, "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", "dev": true, "requires": { "extend-shallow": "^2.0.1", @@ -6055,9 +5879,9 @@ "dev": true }, "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", "dev": true }, "sha.js": { @@ -6208,36 +6032,121 @@ "is-data-descriptor": "^1.0.0", "kind-of": "^6.0.2" } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "socket.io": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.1.1.tgz", + "integrity": "sha512-rORqq9c+7W0DAK3cleWNSyfv/qKXV99hV4tZe+gGLfBECw3XEhBy7x85F3wypA9688LKjtwO9pX9L33/xQI8yA==", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==", + "dev": true + }, + "socket.io-client": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.1.1.tgz", + "integrity": "sha512-jxnFyhAuFxYfjqIgduQlhzqTcOEQSn+OHKVfAxWaNWa7ecP7xSNk2Dx/3UEsDcY7NcFafxvNvKPmmO7HTwTxGQ==", + "dev": true, + "requires": { + "backo2": "1.0.2", + "base64-arraybuffer": "0.1.5", + "component-bind": "1.0.0", + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "engine.io-client": "~3.2.0", + "has-binary2": "~1.0.2", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "object-component": "0.0.3", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "socket.io-parser": "~3.2.0", + "to-array": "0.1.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "socket.io-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.2.0.tgz", + "integrity": "sha512-FYiBx7rc/KORMJlgsXysflWx/RIvtqZbyGLlHZvjfmPTPeuD/I8MaW7cfFrj5tRltICJdgwflhfZ3NVVbVLFQA==", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "isarray": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", + "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", "dev": true } } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", - "dev": true - }, "source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -6255,18 +6164,36 @@ } }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", "urix": "^0.1.0" } }, + "source-map-support": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", @@ -6308,12 +6235,12 @@ } }, "ssri": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.3.0.tgz", - "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "safe-buffer": "^5.1.1" + "figgy-pudding": "^3.5.1" } }, "static-extend": { @@ -6344,9 +6271,9 @@ "dev": true }, "stream-browserify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", - "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "dev": true, "requires": { "inherits": "~2.0.1", @@ -6386,31 +6313,47 @@ } }, "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, "streamroller": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-0.7.0.tgz", - "integrity": "sha512-WREzfy0r0zUqp3lGO096wRuUp7ho1X6uo/7DJfTlEi0Iv/4gT7YHqXDjKC2ioVGBZtE8QzsQD9nx1nIuoZ57jQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-1.0.6.tgz", + "integrity": "sha512-3QC47Mhv3/aZNFpDDVO44qQb9gwB9QggMEE0sQmkTAwBVYdBRWISdsywlkfm5II1Q5y/pmrHflti/IgmIzdDBg==", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "async": "^2.6.2", + "date-format": "^2.0.0", + "debug": "^3.2.6", + "fs-extra": "^7.0.1", + "lodash": "^4.17.14" }, "dependencies": { + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, @@ -6584,6 +6527,56 @@ } } }, + "terser": { + "version": "4.6.7", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.7.tgz", + "integrity": "sha512-fmr7M1f7DBly5cX2+rFDvmGBAaaZyPrHYK4mMdHEDAdNTqXSZgSOfqsfGq2HqPGT/1V0foZZuCZFx8CHKgAk3g==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz", + "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "text-encoding": { "version": "0.6.4", "resolved": "http://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", @@ -6613,9 +6606,9 @@ } }, "timers-browserify": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", - "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", + "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", "dev": true, "requires": { "setimmediate": "^1.0.4" @@ -6649,6 +6642,17 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, "to-regex": { @@ -6681,9 +6685,24 @@ "requires": { "kind-of": "^3.0.2" } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } } } }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, "tslib": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", @@ -6734,61 +6753,38 @@ "dev": true }, "type-is": { - "version": "1.6.16", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", - "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglifyjs-webpack-plugin": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.3.0.tgz", - "integrity": "sha512-ovHIch0AMlxjD/97j9AYovZxG5wnHOPkL7T1GKochBADp/Zwc44pEWNqpKl1Loupp1WhFg7SlYmHZRUfdAacgw==", - "dev": true, - "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "schema-utils": "^0.4.5", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "uglify-es": "^3.3.4", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" + "mime-types": "~2.1.24" }, "dependencies": { - "commander": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", - "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", "dev": true }, - "uglify-es": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", - "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "dev": true, "requires": { - "commander": "~2.13.0", - "source-map": "~0.6.1" + "mime-db": "1.43.0" } } } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, "ultron": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", @@ -6796,38 +6792,15 @@ "dev": true }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "unique-filename": { @@ -6840,14 +6813,20 @@ } }, "unique-slug": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz", - "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "dev": true, "requires": { "imurmurhash": "^0.1.4" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -6891,19 +6870,13 @@ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true } } }, "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, "uri-js": { @@ -6959,10 +6932,20 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + } + }, "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "dev": true, "requires": { "inherits": "2.0.3" @@ -7003,13 +6986,10 @@ } }, "vm-browserify": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", - "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", - "dev": true, - "requires": { - "indexof": "0.0.1" - } + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true }, "void-elements": { "version": "2.0.1", @@ -7018,12 +6998,12 @@ "dev": true }, "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.1.tgz", + "integrity": "sha512-+IF9hfUFOrYOOaKyfaI7h7dquUIOgyEMoQMLA7OP5FxegKA2+XdXThAZ9TU2kucfhDH7rfMHs1oPYziVGWRnZA==", "dev": true, "requires": { - "chokidar": "^2.0.2", + "chokidar": "^2.1.8", "graceful-fs": "^4.1.2", "neo-async": "^2.5.0" }, @@ -7036,20 +7016,19 @@ "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", @@ -7066,166 +7045,35 @@ "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, "requires": { "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", "glob-parent": "^3.1.0", - "inherits": "^2.0.1", + "inherits": "^2.0.3", "is-binary-path": "^1.0.0", "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", + "normalize-path": "^3.0.0", "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "readdirp": "^2.2.1", + "upath": "^1.1.1" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" } }, "fill-range": { @@ -7238,17 +7086,6 @@ "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } } }, "glob-parent": { @@ -7272,50 +7109,6 @@ } } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -7323,405 +7116,144 @@ "dev": true, "requires": { "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "is-buffer": "^1.1.5" } } } }, "webpack": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.25.1.tgz", - "integrity": "sha512-T0GU/3NRtO4tMfNzsvpdhUr8HnzA4LTdP2zd+e5zd6CdOH5vNKHnAlO+DvzccfhPdzqRrALOFcjYxx7K5DWmvA==", + "version": "4.42.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.1.tgz", + "integrity": "sha512-SGfYMigqEfdGchGhFFJ9KyRpQKnipvEvjc1TwrXEPCM6H5Wywu10ka8o3KGrMzSMxMQKt8aCHUFh5DaQ9UmyRg==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.7.11", - "@webassemblyjs/helper-module-context": "1.7.11", - "@webassemblyjs/wasm-edit": "1.7.11", - "@webassemblyjs/wasm-parser": "1.7.11", - "acorn": "^5.6.2", - "acorn-dynamic-import": "^3.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^1.0.0", + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.2.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^4.1.0", - "eslint-scope": "^4.0.0", + "eslint-scope": "^4.0.3", "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", - "tapable": "^1.1.0", - "uglifyjs-webpack-plugin": "^1.2.4", - "watchpack": "^1.5.0", - "webpack-sources": "^1.3.0" + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.6.0", + "webpack-sources": "^1.4.1" }, "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, "ajv": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.5.tgz", - "integrity": "sha512-7q7gtRQDJSyuEHjuVgHoUa2VuemFiCMrfQc9Tc08XTAc4Zj/5U1buQJ0HU6i7fKjXU09SVgSmxa4sLvuvS8Iyg==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", + "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, - "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "eslint-scope": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", - "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", "dev": true }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "minimist": "^1.2.0" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "mkdirp": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz", + "integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==", "dev": true, "requires": { - "kind-of": "^3.0.2" + "minimist": "^1.2.5" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true } } }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } } } }, @@ -7934,9 +7466,9 @@ } }, "webpack-sources": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.3.0.tgz", - "integrity": "sha512-OiVgSrbGu7NEnEvQJJgdSFPl2qWKkWq5lHMhgiToIiN9w34EBnjYzSYs+VbL5KoYiLNtFFa7BZIKxRED3I32pA==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, "requires": { "source-list-map": "^2.0.0", @@ -7979,9 +7511,9 @@ "dev": true }, "worker-farm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz", - "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", "dev": true, "requires": { "errno": "~0.1.7" @@ -8052,9 +7584,9 @@ "dev": true }, "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, "y18n": { diff --git a/packages/optimizely-sdk/package.json b/packages/optimizely-sdk/package.json index c06dfae45..aaecf7e12 100644 --- a/packages/optimizely-sdk/package.json +++ b/packages/optimizely-sdk/package.json @@ -48,21 +48,21 @@ "eslint": "^6.7.2", "istanbul": "^0.4.5", "json-loader": "^0.5.4", - "karma": "^3.1.4", + "karma": "^4.4.1", "karma-browserstack-launcher": "^1.5.1", "karma-chai": "^0.1.0", "karma-chrome-launcher": "^2.1.1", "karma-mocha": "^1.3.0", "karma-sinon": "^1.0.5", "karma-webpack": "^3.0.5", + "lodash": "^4.17.11", "mocha": "^5.2.0", "mocha-lcov-reporter": "^1.3.0", "nock": "^7.7.2", - "sinon": "^2.3.1", - "webpack": "^4.25.1", - "webpack-cli": "^3.1.2", "promise-polyfill": "8.1.0", - "lodash": "^4.17.11" + "sinon": "^2.3.1", + "webpack": "^4.42.1", + "webpack-cli": "^3.1.2" }, "publishConfig": { "access": "public" From d70262792fd73a4b596655bcdc6d150e6ef3a83c Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Mon, 30 Mar 2020 09:59:51 -0700 Subject: [PATCH 2/3] Update version of karma-webpack --- packages/optimizely-sdk/package-lock.json | 339 ++++------------------ packages/optimizely-sdk/package.json | 2 +- 2 files changed, 65 insertions(+), 276 deletions(-) diff --git a/packages/optimizely-sdk/package-lock.json b/packages/optimizely-sdk/package-lock.json index bc94fa731..477f8631c 100644 --- a/packages/optimizely-sdk/package-lock.json +++ b/packages/optimizely-sdk/package-lock.json @@ -356,6 +356,12 @@ "dev": true, "optional": true }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, "ansi-escapes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", @@ -439,12 +445,6 @@ "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, "array-unique": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", @@ -561,16 +561,6 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -1192,6 +1182,17 @@ "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", "dev": true }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1348,12 +1349,6 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "core-js": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.6.tgz", - "integrity": "sha512-lQUVfQi0aLix2xpyjrrJEvfuYCqPc/HwmTKsC/VNf8q0zsjX7SQZtp4+oRONN5Tsur9GDETPjj+Ub2iDiGZfSQ==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1531,15 +1526,6 @@ "randomfill": "^1.0.3" } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, "custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", @@ -1552,15 +1538,6 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, - "d": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1612,15 +1589,6 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, "define-property": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", @@ -1904,28 +1872,6 @@ "prr": "~1.0.1" } }, - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, "es6-promise": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", @@ -1941,16 +1887,6 @@ "es6-promise": "^4.0.3" } }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3226,12 +3162,6 @@ } } }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", @@ -3394,12 +3324,6 @@ "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", "dev": true }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -4201,54 +4125,30 @@ "dev": true }, "karma-webpack": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-3.0.5.tgz", - "integrity": "sha512-nRudGJWstvVuA6Tbju9tyGUfXTtI1UXMXoRHVmM2/78D0q6s/Ye2IC157PKNDC15PWFGR0mVIRtWLAdcfsRJoA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/karma-webpack/-/karma-webpack-4.0.2.tgz", + "integrity": "sha512-970/okAsdUOmiMOCY8sb17A2I8neS25Ad9uhyK3GHgmRSIFJbDcNEFE8dqqUhNe9OHiCC9k3DMrSmtd/0ymP1A==", "dev": true, "requires": { - "async": "^2.0.0", - "babel-runtime": "^6.0.0", - "loader-utils": "^1.0.0", - "lodash": "^4.0.0", - "source-map": "^0.5.6", - "webpack-dev-middleware": "^2.0.6" + "clone-deep": "^4.0.1", + "loader-utils": "^1.1.0", + "neo-async": "^2.6.1", + "schema-utils": "^1.0.0", + "source-map": "^0.7.3", + "webpack-dev-middleware": "^3.7.0" }, "dependencies": { - "async": { + "neo-async": { "version": "2.6.1", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", - "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", - "dev": true, - "requires": { - "lodash": "^4.17.10" - } - }, - "mime": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.0.tgz", - "integrity": "sha512-ikBcWwyqXQSHKtciCcctu9YfPbFYZ4+gbHEmE0Q8jzcTYQg5dHCr3g2wwAZjPoJfQVXZq6KXAjpXOTf5/cjT7w==", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", "dev": true }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", "dev": true - }, - "webpack-dev-middleware": { - "version": "2.0.6", - "resolved": "http://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-2.0.6.tgz", - "integrity": "sha512-tj5LLD9r4tDuRIDa5Mu9lnY2qBBehAITv6A9irqXhw/HQquZgTx3BCd57zYbU2gMDnncA49ufK2qVQSbaKJwOw==", - "dev": true, - "requires": { - "loud-rejection": "^1.6.0", - "memory-fs": "~0.4.1", - "mime": "^2.1.0", - "path-is-absolute": "^1.0.0", - "range-parser": "^1.0.3", - "url-join": "^2.0.2", - "webpack-log": "^1.0.1" - } } } }, @@ -4322,52 +4222,6 @@ "integrity": "sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==", "dev": true }, - "log-symbols": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", - "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", - "dev": true, - "requires": { - "chalk": "^2.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "log4js": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", @@ -4398,32 +4252,12 @@ } } }, - "loglevelnext": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", - "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", - "dev": true, - "requires": { - "es6-symbol": "^3.1.1", - "object.assign": "^4.1.0" - } - }, "lolex": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", "dev": true }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, "lru-cache": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", @@ -4867,12 +4701,6 @@ "integrity": "sha512-MFh0d/Wa7vkKO3Y3LlacqAEeHK0mckVqzDieUKTT+KGxi+zIpeVsFxymkIiRpbpDziHc290Xr9A1O4Om7otoRA==", "dev": true }, - "next-tick": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -5047,12 +4875,6 @@ } } }, - "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", - "dev": true - }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", @@ -5062,18 +4884,6 @@ "isobject": "^3.0.0" } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -5614,12 +5424,6 @@ "readable-stream": "^2.0.2" } }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -5894,6 +5698,15 @@ "safe-buffer": "^5.0.1" } }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -6920,12 +6733,6 @@ } } }, - "url-join": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", - "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=", - "dev": true - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -7416,55 +7223,37 @@ } } }, - "webpack-log": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", - "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "webpack-dev-middleware": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", "dev": true, "requires": { - "chalk": "^2.1.0", - "log-symbols": "^2.1.0", - "loglevelnext": "^1.0.1", - "uuid": "^3.1.0" + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + } + }, "webpack-sources": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", diff --git a/packages/optimizely-sdk/package.json b/packages/optimizely-sdk/package.json index aaecf7e12..3c72b9ae3 100644 --- a/packages/optimizely-sdk/package.json +++ b/packages/optimizely-sdk/package.json @@ -54,7 +54,7 @@ "karma-chrome-launcher": "^2.1.1", "karma-mocha": "^1.3.0", "karma-sinon": "^1.0.5", - "karma-webpack": "^3.0.5", + "karma-webpack": "^4.0.2", "lodash": "^4.17.11", "mocha": "^5.2.0", "mocha-lcov-reporter": "^1.3.0", From a13a9efb42d028d9106386a80ddc3f36c057c56e Mon Sep 17 00:00:00 2001 From: Matt Carroll Date: Mon, 30 Mar 2020 12:54:58 -0700 Subject: [PATCH 3/3] Remove build files --- .../optimizely-sdk/optimizely.browser.umd.js | 8133 ----------------- .../optimizely.browser.umd.min.js | 1 - 2 files changed, 8134 deletions(-) delete mode 100644 packages/optimizely-sdk/optimizely.browser.umd.js delete mode 100644 packages/optimizely-sdk/optimizely.browser.umd.min.js diff --git a/packages/optimizely-sdk/optimizely.browser.umd.js b/packages/optimizely-sdk/optimizely.browser.umd.js deleted file mode 100644 index 2ddeb37fc..000000000 --- a/packages/optimizely-sdk/optimizely.browser.umd.js +++ /dev/null @@ -1,8133 +0,0 @@ -(function webpackUniversalModuleDefinition(root, factory) { - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); - else if(typeof exports === 'object') - exports["optimizelySdk"] = factory(); - else - root["optimizelySdk"] = factory(); -})(window, function() { -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 = 0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016-2017, 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 logging = __webpack_require__(1); -var fns = __webpack_require__(11); -var configValidator = __webpack_require__(13); -var defaultErrorHandler = __webpack_require__(15); -var defaultEventDispatcher = __webpack_require__(16); -var enums = __webpack_require__(14); -var eventProcessor = __webpack_require__(17); -var loggerPlugin = __webpack_require__(26); -var Optimizely = __webpack_require__(27); -var eventProcessorConfigValidator = __webpack_require__(55); - -var logger = logging.getLogger(); -logging.setLogHandler(loggerPlugin.createLogger()); -logging.setLogLevel(logging.LogLevel.INFO); - -var MODULE_NAME = 'INDEX_BROWSER'; - -var DEFAULT_EVENT_BATCH_SIZE = 10; -var DEFAULT_EVENT_FLUSH_INTERVAL = 1000; // Unit is ms, default is 1s - -var hasRetriedEvents = false; -/** - * Entry point into the Optimizely Browser SDK - */ -module.exports = { - logging: loggerPlugin, - errorHandler: defaultErrorHandler, - eventDispatcher: defaultEventDispatcher, - enums: enums, - - setLogger: logging.setLogHandler, - setLogLevel: logging.setLogLevel, - - /** - * Creates an instance of the Optimizely class - * @param {Object} config - * @param {Object} config.datafile - * @param {Object} config.errorHandler - * @param {Object} config.eventDispatcher - * @param {Object} config.logger - * @param {Object} config.logLevel - * @param {Object} config.userProfileService - * @param {Object} config.eventBatchSize - * @param {Object} config.eventFlushInterval - * @return {Object} the Optimizely object - */ - createInstance: function(config) { - try { - config = config || {}; - - // TODO warn about setting per instance errorHandler / logger / logLevel - if (config.errorHandler) { - logging.setErrorHandler(config.errorHandler); - } - if (config.logger) { - logging.setLogHandler(config.logger); - // respect the logger's shouldLog functionality - logging.setLogLevel(logging.LogLevel.NOTSET); - } - if (config.logLevel !== undefined) { - logging.setLogLevel(config.logLevel); - } - - try { - configValidator.validate(config); - config.isValidInstance = true; - } catch (ex) { - logger.error(ex); - config.isValidInstance = false; - } - - // Explicitly check for null or undefined - // prettier-ignore - if (config.skipJSONValidation == null) { // eslint-disable-line eqeqeq - config.skipJSONValidation = true; - } - - var eventDispatcher; - // prettier-ignore - if (config.eventDispatcher == null) { // eslint-disable-line eqeqeq - // only wrap the event dispatcher with pending events retry if the user didnt override - eventDispatcher = new eventProcessor.LocalStoragePendingEventsDispatcher({ - eventDispatcher: defaultEventDispatcher, - }); - - if (!hasRetriedEvents) { - eventDispatcher.sendPendingEvents(); - hasRetriedEvents = true; - } - } else { - eventDispatcher = config.eventDispatcher; - } - - config = fns.assign( - { - clientEngine: enums.JAVASCRIPT_CLIENT_ENGINE, - eventBatchSize: DEFAULT_EVENT_BATCH_SIZE, - eventFlushInterval: DEFAULT_EVENT_FLUSH_INTERVAL, - }, - config, - { - eventDispatcher: eventDispatcher, - // always get the OptimizelyLogger facade from logging - logger: logger, - errorHandler: logging.getErrorHandler(), - } - ); - - if (!eventProcessorConfigValidator.validateEventBatchSize(config.eventBatchSize)) { - logger.warn('Invalid eventBatchSize %s, defaulting to %s', config.eventBatchSize, DEFAULT_EVENT_BATCH_SIZE); - config.eventBatchSize = DEFAULT_EVENT_BATCH_SIZE; - } - if (!eventProcessorConfigValidator.validateEventFlushInterval(config.eventFlushInterval)) { - logger.warn( - 'Invalid eventFlushInterval %s, defaulting to %s', - config.eventFlushInterval, - DEFAULT_EVENT_FLUSH_INTERVAL - ); - config.eventFlushInterval = DEFAULT_EVENT_FLUSH_INTERVAL; - } - - var optimizely = new Optimizely(config); - - try { - if (typeof window.addEventListener === 'function') { - var unloadEvent = 'onpagehide' in window ? 'pagehide' : 'unload'; - window.addEventListener( - unloadEvent, - function() { - optimizely.close(); - }, - false - ); - } - } catch (e) { - logger.error(enums.LOG_MESSAGES.UNABLE_TO_ATTACH_UNLOAD, MODULE_NAME, e.message); - } - - return optimizely; - } catch (e) { - logger.error(e); - return null; - } - }, - - __internalResetRetryState: function() { - hasRetriedEvents = false; - }, -}; - - -/***/ }), -/* 1 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -__export(__webpack_require__(2)); -__export(__webpack_require__(3)); -__export(__webpack_require__(4)); - - -/***/ }), -/* 2 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * @export - * @class NoopErrorHandler - * @implements {ErrorHandler} - */ -var NoopErrorHandler = /** @class */ (function () { - function NoopErrorHandler() { - } - /** - * @param {Error} exception - * @memberof NoopErrorHandler - */ - NoopErrorHandler.prototype.handleError = function (exception) { - // no-op - return; - }; - return NoopErrorHandler; -}()); -exports.NoopErrorHandler = NoopErrorHandler; -var globalErrorHandler = new NoopErrorHandler(); -/** - * @export - * @param {ErrorHandler} handler - */ -function setErrorHandler(handler) { - globalErrorHandler = handler; -} -exports.setErrorHandler = setErrorHandler; -/** - * @export - * @returns {ErrorHandler} - */ -function getErrorHandler() { - return globalErrorHandler; -} -exports.getErrorHandler = getErrorHandler; -/** - * @export - */ -function resetErrorHandler() { - globalErrorHandler = new NoopErrorHandler(); -} -exports.resetErrorHandler = resetErrorHandler; - - -/***/ }), -/* 3 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 LogLevel; -(function (LogLevel) { - LogLevel[LogLevel["NOTSET"] = 0] = "NOTSET"; - LogLevel[LogLevel["DEBUG"] = 1] = "DEBUG"; - LogLevel[LogLevel["INFO"] = 2] = "INFO"; - LogLevel[LogLevel["WARNING"] = 3] = "WARNING"; - LogLevel[LogLevel["ERROR"] = 4] = "ERROR"; -})(LogLevel = exports.LogLevel || (exports.LogLevel = {})); - - -/***/ }), -/* 4 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 errorHandler_1 = __webpack_require__(2); -var js_sdk_utils_1 = __webpack_require__(5); -var models_1 = __webpack_require__(3); -var stringToLogLevel = { - NOTSET: 0, - DEBUG: 1, - INFO: 2, - WARNING: 3, - ERROR: 4, -}; -function coerceLogLevel(level) { - if (typeof level !== 'string') { - return level; - } - level = level.toUpperCase(); - if (level === 'WARN') { - level = 'WARNING'; - } - if (!stringToLogLevel[level]) { - return level; - } - return stringToLogLevel[level]; -} -var DefaultLogManager = /** @class */ (function () { - function DefaultLogManager() { - this.defaultLoggerFacade = new OptimizelyLogger(); - this.loggers = {}; - } - DefaultLogManager.prototype.getLogger = function (name) { - if (!name) { - return this.defaultLoggerFacade; - } - if (!this.loggers[name]) { - this.loggers[name] = new OptimizelyLogger({ messagePrefix: name }); - } - return this.loggers[name]; - }; - return DefaultLogManager; -}()); -var ConsoleLogHandler = /** @class */ (function () { - /** - * Creates an instance of ConsoleLogger. - * @param {ConsoleLogHandlerConfig} config - * @memberof ConsoleLogger - */ - function ConsoleLogHandler(config) { - if (config === void 0) { config = {}; } - this.logLevel = models_1.LogLevel.NOTSET; - if (config.logLevel !== undefined && js_sdk_utils_1.isValidEnum(models_1.LogLevel, config.logLevel)) { - this.setLogLevel(config.logLevel); - } - this.logToConsole = config.logToConsole !== undefined ? !!config.logToConsole : true; - this.prefix = config.prefix !== undefined ? config.prefix : '[OPTIMIZELY]'; - } - /** - * @param {LogLevel} level - * @param {string} message - * @memberof ConsoleLogger - */ - ConsoleLogHandler.prototype.log = function (level, message) { - if (!this.shouldLog(level) || !this.logToConsole) { - return; - } - var logMessage = this.prefix + " - " + this.getLogLevelName(level) + " " + this.getTime() + " " + message; - this.consoleLog(level, [logMessage]); - }; - /** - * @param {LogLevel} level - * @memberof ConsoleLogger - */ - ConsoleLogHandler.prototype.setLogLevel = function (level) { - level = coerceLogLevel(level); - if (!js_sdk_utils_1.isValidEnum(models_1.LogLevel, level) || level === undefined) { - this.logLevel = models_1.LogLevel.ERROR; - } - else { - this.logLevel = level; - } - }; - /** - * @returns {string} - * @memberof ConsoleLogger - */ - ConsoleLogHandler.prototype.getTime = function () { - return new Date().toISOString(); - }; - /** - * @private - * @param {LogLevel} targetLogLevel - * @returns {boolean} - * @memberof ConsoleLogger - */ - ConsoleLogHandler.prototype.shouldLog = function (targetLogLevel) { - return targetLogLevel >= this.logLevel; - }; - /** - * @private - * @param {LogLevel} logLevel - * @returns {string} - * @memberof ConsoleLogger - */ - ConsoleLogHandler.prototype.getLogLevelName = function (logLevel) { - switch (logLevel) { - case models_1.LogLevel.DEBUG: - return 'DEBUG'; - case models_1.LogLevel.INFO: - return 'INFO '; - case models_1.LogLevel.WARNING: - return 'WARN '; - case models_1.LogLevel.ERROR: - return 'ERROR'; - default: - return 'NOTSET'; - } - }; - /** - * @private - * @param {LogLevel} logLevel - * @param {string[]} logArguments - * @memberof ConsoleLogger - */ - ConsoleLogHandler.prototype.consoleLog = function (logLevel, logArguments) { - switch (logLevel) { - case models_1.LogLevel.DEBUG: - console.log.apply(console, logArguments); - break; - case models_1.LogLevel.INFO: - console.info.apply(console, logArguments); - break; - case models_1.LogLevel.WARNING: - console.warn.apply(console, logArguments); - break; - case models_1.LogLevel.ERROR: - console.error.apply(console, logArguments); - break; - default: - console.log.apply(console, logArguments); - } - }; - return ConsoleLogHandler; -}()); -exports.ConsoleLogHandler = ConsoleLogHandler; -var globalLogLevel = models_1.LogLevel.NOTSET; -var globalLogHandler = null; -var OptimizelyLogger = /** @class */ (function () { - function OptimizelyLogger(opts) { - if (opts === void 0) { opts = {}; } - this.messagePrefix = ''; - if (opts.messagePrefix) { - this.messagePrefix = opts.messagePrefix; - } - } - /** - * @param {(LogLevel | LogInputObject)} levelOrObj - * @param {string} [message] - * @memberof OptimizelyLogger - */ - OptimizelyLogger.prototype.log = function (level, message) { - this.internalLog(coerceLogLevel(level), { - message: message, - splat: [], - }); - }; - OptimizelyLogger.prototype.info = function (message) { - var splat = []; - for (var _i = 1; _i < arguments.length; _i++) { - splat[_i - 1] = arguments[_i]; - } - this.namedLog(models_1.LogLevel.INFO, message, splat); - }; - OptimizelyLogger.prototype.debug = function (message) { - var splat = []; - for (var _i = 1; _i < arguments.length; _i++) { - splat[_i - 1] = arguments[_i]; - } - this.namedLog(models_1.LogLevel.DEBUG, message, splat); - }; - OptimizelyLogger.prototype.warn = function (message) { - var splat = []; - for (var _i = 1; _i < arguments.length; _i++) { - splat[_i - 1] = arguments[_i]; - } - this.namedLog(models_1.LogLevel.WARNING, message, splat); - }; - OptimizelyLogger.prototype.error = function (message) { - var splat = []; - for (var _i = 1; _i < arguments.length; _i++) { - splat[_i - 1] = arguments[_i]; - } - this.namedLog(models_1.LogLevel.ERROR, message, splat); - }; - OptimizelyLogger.prototype.format = function (data) { - return "" + (this.messagePrefix ? this.messagePrefix + ': ' : '') + js_sdk_utils_1.sprintf.apply(void 0, [data.message].concat(data.splat)); - }; - OptimizelyLogger.prototype.internalLog = function (level, data) { - if (!globalLogHandler) { - return; - } - if (level < globalLogLevel) { - return; - } - globalLogHandler.log(level, this.format(data)); - if (data.error && data.error instanceof Error) { - errorHandler_1.getErrorHandler().handleError(data.error); - } - }; - OptimizelyLogger.prototype.namedLog = function (level, message, splat) { - var error; - if (message instanceof Error) { - error = message; - message = error.message; - this.internalLog(level, { - error: error, - message: message, - splat: splat, - }); - return; - } - if (splat.length === 0) { - this.internalLog(level, { - message: message, - splat: splat, - }); - return; - } - var last = splat[splat.length - 1]; - if (last instanceof Error) { - error = last; - splat.splice(-1); - } - this.internalLog(level, { message: message, error: error, splat: splat }); - }; - return OptimizelyLogger; -}()); -var globalLogManager = new DefaultLogManager(); -function getLogger(name) { - return globalLogManager.getLogger(name); -} -exports.getLogger = getLogger; -function setLogHandler(logger) { - globalLogHandler = logger; -} -exports.setLogHandler = setLogHandler; -function setLogLevel(level) { - level = coerceLogLevel(level); - if (!js_sdk_utils_1.isValidEnum(models_1.LogLevel, level) || level === undefined) { - globalLogLevel = models_1.LogLevel.ERROR; - } - else { - globalLogLevel = level; - } -} -exports.setLogLevel = setLogLevel; -function getLogLevel() { - return globalLogLevel; -} -exports.getLogLevel = getLogLevel; -/** - * Resets all global logger state to it's original - */ -function resetLogger() { - globalLogManager = new DefaultLogManager(); - globalLogLevel = models_1.LogLevel.NOTSET; -} -exports.resetLogger = resetLogger; - - -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 uuid_1 = __webpack_require__(6); -function getTimestamp() { - return new Date().getTime(); -} -exports.getTimestamp = getTimestamp; -function generateUUID() { - return uuid_1.v4(); -} -exports.generateUUID = generateUUID; -/** - * Validates a value is a valid TypeScript enum - * - * @export - * @param {object} enumToCheck - * @param {*} value - * @returns {boolean} - */ -function isValidEnum(enumToCheck, value) { - var found = false; - var keys = Object.keys(enumToCheck); - for (var index = 0; index < keys.length; index++) { - if (value === enumToCheck[keys[index]]) { - found = true; - break; - } - } - return found; -} -exports.isValidEnum = isValidEnum; -function groupBy(arr, grouperFn) { - var grouper = {}; - arr.forEach(function (item) { - var key = grouperFn(item); - grouper[key] = grouper[key] || []; - grouper[key].push(item); - }); - return objectValues(grouper); -} -exports.groupBy = groupBy; -function objectValues(obj) { - return Object.keys(obj).map(function (key) { return obj[key]; }); -} -exports.objectValues = objectValues; -function find(arr, cond) { - var found; - for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { - var item = arr_1[_i]; - if (cond(item)) { - found = item; - break; - } - } - return found; -} -exports.find = find; -function keyBy(arr, keyByFn) { - var map = {}; - arr.forEach(function (item) { - var key = keyByFn(item); - map[key] = item; - }); - return map; -} -exports.keyBy = keyBy; -function sprintf(format) { - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - var i = 0; - return format.replace(/%s/g, function () { - var arg = args[i++]; - var type = typeof arg; - if (type === 'function') { - return arg(); - } - else if (type === 'string') { - return arg; - } - else { - return String(arg); - } - }); -} -exports.sprintf = sprintf; - - -/***/ }), -/* 6 */ -/***/ (function(module, exports, __webpack_require__) { - -var v1 = __webpack_require__(7); -var v4 = __webpack_require__(10); - -var uuid = v4; -uuid.v1 = v1; -uuid.v4 = v4; - -module.exports = uuid; - - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -var rng = __webpack_require__(8); -var bytesToUuid = __webpack_require__(9); - -// **`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/broofa/node-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; - - -/***/ }), -/* 8 */ -/***/ (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; - }; -} - - -/***/ }), -/* 9 */ -/***/ (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; - - -/***/ }), -/* 10 */ -/***/ (function(module, exports, __webpack_require__) { - -var rng = __webpack_require__(8); -var bytesToUuid = __webpack_require__(9); - -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; - - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2017, 2019-2020, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 uuid = __webpack_require__(6); -var MAX_SAFE_INTEGER_LIMIT = Math.pow(2, 53); -var keyBy = __webpack_require__(12).keyBy; -module.exports = { - assign: function(target) { - if (!target) { - return {}; - } - if (typeof Object.assign === 'function') { - return Object.assign.apply(Object, arguments); - } else { - var to = Object(target); - for (var index = 1; index < arguments.length; index++) { - var nextSource = arguments[index]; - if (nextSource !== null && nextSource !== undefined) { - for (var nextKey in nextSource) { - // Avoid bugs when hasOwnProperty is shadowed - if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { - to[nextKey] = nextSource[nextKey]; - } - } - } - } - return to; - } - }, - currentTimestamp: function() { - return Math.round(new Date().getTime()); - }, - isSafeInteger: function(number) { - return typeof number == 'number' && Math.abs(number) <= MAX_SAFE_INTEGER_LIMIT; - }, - keyBy: function(arr, key) { - if (!arr) return {}; - return keyBy(arr, function(item) { - return item[key]; - }); - }, - uuid: function() { - return uuid.v4(); - }, - isNumber: function(value) { - return typeof value === 'number'; - }, -}; - - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 uuid_1 = __webpack_require__(6); -function getTimestamp() { - return new Date().getTime(); -} -exports.getTimestamp = getTimestamp; -function generateUUID() { - return uuid_1.v4(); -} -exports.generateUUID = generateUUID; -/** - * Validates a value is a valid TypeScript enum - * - * @export - * @param {object} enumToCheck - * @param {*} value - * @returns {boolean} - */ -function isValidEnum(enumToCheck, value) { - var found = false; - var keys = Object.keys(enumToCheck); - for (var index = 0; index < keys.length; index++) { - if (value === enumToCheck[keys[index]]) { - found = true; - break; - } - } - return found; -} -exports.isValidEnum = isValidEnum; -function groupBy(arr, grouperFn) { - var grouper = {}; - arr.forEach(function (item) { - var key = grouperFn(item); - grouper[key] = grouper[key] || []; - grouper[key].push(item); - }); - return objectValues(grouper); -} -exports.groupBy = groupBy; -function objectValues(obj) { - return Object.keys(obj).map(function (key) { return obj[key]; }); -} -exports.objectValues = objectValues; -function objectEntries(obj) { - return Object.keys(obj).map(function (key) { return [key, obj[key]]; }); -} -exports.objectEntries = objectEntries; -function find(arr, cond) { - var found; - for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { - var item = arr_1[_i]; - if (cond(item)) { - found = item; - break; - } - } - return found; -} -exports.find = find; -function keyBy(arr, keyByFn) { - var map = {}; - arr.forEach(function (item) { - var key = keyByFn(item); - map[key] = item; - }); - return map; -} -exports.keyBy = keyBy; -function sprintf(format) { - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - var i = 0; - return format.replace(/%s/g, function () { - var arg = args[i++]; - var type = typeof arg; - if (type === 'function') { - return arg(); - } - else if (type === 'string') { - return arg; - } - else { - return String(arg); - } - }); -} -exports.sprintf = sprintf; -/* - * Notification types for use with NotificationCenter - * Format is EVENT: - * - * SDK consumers can use these to register callbacks with the notification center. - * - * @deprecated since 3.1.0 - * ACTIVATE: An impression event will be sent to Optimizely - * Callbacks will receive an object argument with the following properties: - * - experiment {Object} - * - userId {string} - * - attributes {Object|undefined} - * - variation {Object} - * - logEvent {Object} - * - * DECISION: A decision is made in the system. i.e. user activation, - * feature access or feature-variable value retrieval - * Callbacks will receive an object argument with the following properties: - * - type {string} - * - userId {string} - * - attributes {Object|undefined} - * - decisionInfo {Object|undefined} - * - * LOG_EVENT: A batch of events, which could contain impressions and/or conversions, - * will be sent to Optimizely - * Callbacks will receive an object argument with the following properties: - * - url {string} - * - httpVerb {string} - * - params {Object} - * - * OPTIMIZELY_CONFIG_UPDATE: This Optimizely instance has been updated with a new - * config - * - * TRACK: A conversion event will be sent to Optimizely - * Callbacks will receive the an object argument with the following properties: - * - eventKey {string} - * - userId {string} - * - attributes {Object|undefined} - * - eventTags {Object|undefined} - * - logEvent {Object} - * - */ -var NOTIFICATION_TYPES; -(function (NOTIFICATION_TYPES) { - NOTIFICATION_TYPES["ACTIVATE"] = "ACTIVATE:experiment, user_id,attributes, variation, event"; - NOTIFICATION_TYPES["DECISION"] = "DECISION:type, userId, attributes, decisionInfo"; - NOTIFICATION_TYPES["LOG_EVENT"] = "LOG_EVENT:logEvent"; - NOTIFICATION_TYPES["OPTIMIZELY_CONFIG_UPDATE"] = "OPTIMIZELY_CONFIG_UPDATE"; - NOTIFICATION_TYPES["TRACK"] = "TRACK:event_key, user_id, attributes, event_tags, event"; -})(NOTIFICATION_TYPES = exports.NOTIFICATION_TYPES || (exports.NOTIFICATION_TYPES = {})); - - -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016, 2018, 2019 Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 sprintf = __webpack_require__(12).sprintf; - -var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; -var MODULE_NAME = 'CONFIG_VALIDATOR'; -var DATAFILE_VERSIONS = __webpack_require__(14).DATAFILE_VERSIONS; - -var SUPPORTED_VERSIONS = [DATAFILE_VERSIONS.V2, DATAFILE_VERSIONS.V3, DATAFILE_VERSIONS.V4]; - -/** - * Provides utility methods for validating that the configuration options are valid - */ -module.exports = { - /** - * Validates the given config options - * @param {Object} config - * @param {Object} config.errorHandler - * @param {Object} config.eventDispatcher - * @param {Object} config.logger - * @return {Boolean} True if the config options are valid - * @throws If any of the config options are not valid - */ - validate: function(config) { - if (config.errorHandler && typeof config.errorHandler.handleError !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_ERROR_HANDLER, MODULE_NAME)); - } - - if (config.eventDispatcher && typeof config.eventDispatcher.dispatchEvent !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EVENT_DISPATCHER, MODULE_NAME)); - } - - if (config.logger && typeof config.logger.log !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_LOGGER, MODULE_NAME)); - } - - return true; - }, - - /** - * Validates the datafile - * @param {string} datafile - * @return {Boolean} True if the datafile is valid - * @throws If the datafile is not valid for any of the following reasons: - - The datafile string is undefined - - The datafile string cannot be parsed as a JSON object - - The datafile version is not supported - */ - validateDatafile: function(datafile) { - if (!datafile) { - throw new Error(sprintf(ERROR_MESSAGES.NO_DATAFILE_SPECIFIED, MODULE_NAME)); - } - - if (typeof datafile === 'string' || datafile instanceof String) { - // Attempt to parse the datafile string - try { - datafile = JSON.parse(datafile); - } catch (ex) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_MALFORMED, MODULE_NAME)); - } - } - - if (SUPPORTED_VERSIONS.indexOf(datafile.version) === -1) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_DATAFILE_VERSION, MODULE_NAME, datafile.version)); - } - - return true; - }, -}; - - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - -/**************************************************************************** - * Copyright 2016-2019, Optimizely, Inc. and contributors * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License 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 jsSdkUtils = __webpack_require__(12); - -/** - * Contains global enums used throughout the library - */ -exports.LOG_LEVEL = { - NOTSET: 0, - DEBUG: 1, - INFO: 2, - WARNING: 3, - ERROR: 4, -}; - -exports.ERROR_MESSAGES = { - CONDITION_EVALUATOR_ERROR: '%s: Error evaluating audience condition of type %s: %s', - DATAFILE_AND_SDK_KEY_MISSING: '%s: You must provide at least one of sdkKey or datafile. Cannot start Optimizely', - EXPERIMENT_KEY_NOT_IN_DATAFILE: '%s: Experiment key %s is not in datafile.', - FEATURE_NOT_IN_DATAFILE: '%s: Feature key %s is not in datafile.', - IMPROPERLY_FORMATTED_EXPERIMENT: '%s: Experiment key %s is improperly formatted.', - INVALID_ATTRIBUTES: '%s: Provided attributes are in an invalid format.', - INVALID_BUCKETING_ID: '%s: Unable to generate hash for bucketing ID %s: %s', - INVALID_DATAFILE: '%s: Datafile is invalid - property %s: %s', - INVALID_DATAFILE_MALFORMED: '%s: Datafile is invalid because it is malformed.', - INVALID_JSON: '%s: JSON object is not valid.', - INVALID_ERROR_HANDLER: '%s: Provided "errorHandler" is in an invalid format.', - INVALID_EVENT_DISPATCHER: '%s: Provided "eventDispatcher" is in an invalid format.', - INVALID_EVENT_TAGS: '%s: Provided event tags are in an invalid format.', - INVALID_EXPERIMENT_KEY: '%s: Experiment key %s is not in datafile. It is either invalid, paused, or archived.', - INVALID_EXPERIMENT_ID: '%s: Experiment ID %s is not in datafile.', - INVALID_GROUP_ID: '%s: Group ID %s is not in datafile.', - INVALID_LOGGER: '%s: Provided "logger" is in an invalid format.', - INVALID_ROLLOUT_ID: '%s: Invalid rollout ID %s attached to feature %s', - INVALID_USER_ID: '%s: Provided user ID is in an invalid format.', - INVALID_USER_PROFILE_SERVICE: '%s: Provided user profile service instance is in an invalid format: %s.', - JSON_SCHEMA_EXPECTED: '%s: JSON schema expected.', - NO_DATAFILE_SPECIFIED: '%s: No datafile specified. Cannot start optimizely.', - NO_JSON_PROVIDED: '%s: No JSON object to validate against schema.', - NO_VARIATION_FOR_EXPERIMENT_KEY: '%s: No variation key %s defined in datafile for experiment %s.', - UNDEFINED_ATTRIBUTE: '%s: Provided attribute: %s has an undefined value.', - UNRECOGNIZED_ATTRIBUTE: '%s: Unrecognized attribute %s provided. Pruning before sending event to Optimizely.', - UNABLE_TO_CAST_VALUE: '%s: Unable to cast value %s to type %s, returning null.', - USER_NOT_IN_FORCED_VARIATION: '%s: User %s is not in the forced variation map. Cannot remove their forced variation.', - USER_PROFILE_LOOKUP_ERROR: '%s: Error while looking up user profile for user ID "%s": %s.', - USER_PROFILE_SAVE_ERROR: '%s: Error while saving user profile for user ID "%s": %s.', - VARIABLE_KEY_NOT_IN_DATAFILE: '%s: Variable with key "%s" associated with feature with key "%s" is not in datafile.', - VARIATION_ID_NOT_IN_DATAFILE: '%s: No variation ID %s defined in datafile for experiment %s.', - VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT: '%s: Variation ID %s is not in the datafile.', - INVALID_INPUT_FORMAT: '%s: Provided %s is in an invalid format.', - INVALID_DATAFILE_VERSION: '%s: This version of the JavaScript SDK does not support the given datafile version: %s', - INVALID_VARIATION_KEY: '%s: Provided variation key is in an invalid format.', -}; - -exports.LOG_MESSAGES = { - ACTIVATE_USER: '%s: Activating user %s in experiment %s.', - DISPATCH_CONVERSION_EVENT: '%s: Dispatching conversion event to URL %s with params %s.', - DISPATCH_IMPRESSION_EVENT: '%s: Dispatching impression event to URL %s with params %s.', - DEPRECATED_EVENT_VALUE: '%s: Event value is deprecated in %s call.', - EVENT_KEY_NOT_FOUND: '%s: Event key %s is not in datafile.', - EXPERIMENT_NOT_RUNNING: '%s: Experiment %s is not running.', - FEATURE_ENABLED_FOR_USER: '%s: Feature %s is enabled for user %s.', - FEATURE_NOT_ENABLED_FOR_USER: '%s: Feature %s is not enabled for user %s.', - FEATURE_HAS_NO_EXPERIMENTS: '%s: Feature %s is not attached to any experiments.', - FAILED_TO_PARSE_VALUE: '%s: Failed to parse event value "%s" from event tags.', - FAILED_TO_PARSE_REVENUE: '%s: Failed to parse revenue value "%s" from event tags.', - FORCED_BUCKETING_FAILED: '%s: Variation key %s is not in datafile. Not activating user %s.', - INVALID_OBJECT: '%s: Optimizely object is not valid. Failing %s.', - INVALID_CLIENT_ENGINE: '%s: Invalid client engine passed: %s. Defaulting to node-sdk.', - INVALID_VARIATION_ID: '%s: Bucketed into an invalid variation ID. Returning null.', - NOTIFICATION_LISTENER_EXCEPTION: '%s: Notification listener for (%s) threw exception: %s', - NO_ROLLOUT_EXISTS: '%s: There is no rollout of feature %s.', - NOT_ACTIVATING_USER: '%s: Not activating user %s for experiment %s.', - NOT_TRACKING_USER: '%s: Not tracking user %s.', - PARSED_REVENUE_VALUE: '%s: Parsed revenue value "%s" from event tags.', - PARSED_NUMERIC_VALUE: '%s: Parsed event value "%s" from event tags.', - RETURNING_STORED_VARIATION: - '%s: Returning previously activated variation "%s" of experiment "%s" for user "%s" from user profile.', - ROLLOUT_HAS_NO_EXPERIMENTS: '%s: Rollout of feature %s has no experiments', - SAVED_VARIATION: '%s: Saved variation "%s" of experiment "%s" for user "%s".', - SAVED_VARIATION_NOT_FOUND: - '%s: User %s was previously bucketed into variation with ID %s for experiment %s, but no matching variation was found.', - SHOULD_NOT_DISPATCH_ACTIVATE: '%s: Experiment %s is not in "Running" state. Not activating user.', - SKIPPING_JSON_VALIDATION: '%s: Skipping JSON schema validation.', - TRACK_EVENT: '%s: Tracking event %s for user %s.', - USER_ASSIGNED_TO_VARIATION_BUCKET: '%s: Assigned variation bucket %s to user %s.', - USER_ASSIGNED_TO_EXPERIMENT_BUCKET: '%s: Assigned experiment bucket %s to user %s.', - USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP: '%s: User %s is in experiment %s of group %s.', - USER_BUCKETED_INTO_TARGETING_RULE: '%s: User %s bucketed into targeting rule %s.', - USER_IN_FEATURE_EXPERIMENT: '%s: User %s is in variation %s of experiment %s on the feature %s.', - USER_IN_ROLLOUT: '%s: User %s is in rollout of feature %s.', - USER_BUCKETED_INTO_EVERYONE_TARGETING_RULE: '%s: User %s bucketed into everyone targeting rule.', - USER_NOT_BUCKETED_INTO_EVERYONE_TARGETING_RULE: - '%s: User %s not bucketed into everyone targeting rule due to traffic allocation.', - USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP: '%s: User %s is not in experiment %s of group %s.', - USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP: '%s: User %s is not in any experiment of group %s.', - USER_NOT_BUCKETED_INTO_TARGETING_RULE: - '%s User %s not bucketed into targeting rule %s due to traffic allocation. Trying everyone rule.', - USER_NOT_IN_FEATURE_EXPERIMENT: '%s: User %s is not in any experiment on the feature %s.', - USER_NOT_IN_ROLLOUT: '%s: User %s is not in rollout of feature %s.', - USER_FORCED_IN_VARIATION: '%s: User %s is forced in variation %s.', - USER_MAPPED_TO_FORCED_VARIATION: '%s: Set variation %s for experiment %s and user %s in the forced variation map.', - USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE: '%s: User %s does not meet conditions for targeting rule %s.', - USER_MEETS_CONDITIONS_FOR_TARGETING_RULE: '%s: User %s meets conditions for targeting rule %s.', - USER_HAS_VARIATION: '%s: User %s is in variation %s of experiment %s.', - USER_HAS_FORCED_VARIATION: '%s: Variation %s is mapped to experiment %s and user %s in the forced variation map.', - USER_HAS_NO_VARIATION: '%s: User %s is in no variation of experiment %s.', - USER_HAS_NO_FORCED_VARIATION: '%s: User %s is not in the forced variation map.', - USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT: '%s: No experiment %s mapped to user %s in the forced variation map.', - USER_NOT_IN_ANY_EXPERIMENT: '%s: User %s is not in any experiment of group %s.', - USER_NOT_IN_EXPERIMENT: '%s: User %s does not meet conditions to be in experiment %s.', - USER_RECEIVED_DEFAULT_VARIABLE_VALUE: - '%s: User "%s" is not in any variation or rollout rule. Returning default value for variable "%s" of feature flag "%s".', - FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE: - '%s: Feature "%s" is not enabled for user %s. Returning default value for variable "%s".', - VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE: - '%s: Variable "%s" is not used in variation "%s". Returning default value.', - USER_RECEIVED_VARIABLE_VALUE: '%s: Value for variable "%s" of feature flag "%s" is %s for user "%s"', - VALID_DATAFILE: '%s: Datafile is valid.', - VALID_USER_PROFILE_SERVICE: '%s: Valid user profile service provided.', - VARIATION_REMOVED_FOR_USER: '%s: Variation mapped to experiment %s has been removed for user %s.', - VARIABLE_REQUESTED_WITH_WRONG_TYPE: - '%s: Requested variable type "%s", but variable is of type "%s". Use correct API to retrieve value. Returning None.', - VALID_BUCKETING_ID: '%s: BucketingId is valid: "%s"', - BUCKETING_ID_NOT_STRING: '%s: BucketingID attribute is not a string. Defaulted to userId', - EVALUATING_AUDIENCE: '%s: Starting to evaluate audience "%s" with conditions: %s.', - EVALUATING_AUDIENCES_COMBINED: '%s: Evaluating audiences for experiment "%s": %s.', - AUDIENCE_EVALUATION_RESULT: '%s: Audience "%s" evaluated to %s.', - AUDIENCE_EVALUATION_RESULT_COMBINED: '%s: Audiences for experiment %s collectively evaluated to %s.', - MISSING_ATTRIBUTE_VALUE: - '%s: Audience condition %s evaluated to UNKNOWN because no value was passed for user attribute "%s".', - UNEXPECTED_CONDITION_VALUE: - '%s: Audience condition %s evaluated to UNKNOWN because the condition value is not supported.', - UNEXPECTED_TYPE: - '%s: Audience condition %s evaluated to UNKNOWN because a value of type "%s" was passed for user attribute "%s".', - UNEXPECTED_TYPE_NULL: - '%s: Audience condition %s evaluated to UNKNOWN because a null value was passed for user attribute "%s".', - UNKNOWN_CONDITION_TYPE: - '%s: Audience condition %s has an unknown condition type. You may need to upgrade to a newer release of the Optimizely SDK.', - UNKNOWN_MATCH_TYPE: - '%s: Audience condition %s uses an unknown match type. You may need to upgrade to a newer release of the Optimizely SDK.', - UPDATED_OPTIMIZELY_CONFIG: '%s: Updated Optimizely config to revision %s (project id %s)', - OUT_OF_BOUNDS: - '%s: Audience condition %s evaluated to UNKNOWN because the number value for user attribute "%s" is not in the range [-2^53, +2^53].', - UNABLE_TO_ATTACH_UNLOAD: '%s: unable to bind optimizely.close() to page unload event: "%s"', -}; - -exports.RESERVED_EVENT_KEYWORDS = { - REVENUE: 'revenue', - VALUE: 'value', -}; - -exports.CONTROL_ATTRIBUTES = { - BOT_FILTERING: '$opt_bot_filtering', - BUCKETING_ID: '$opt_bucketing_id', - STICKY_BUCKETING_KEY: '$opt_experiment_bucket_map', - USER_AGENT: '$opt_user_agent', -}; - -exports.JAVASCRIPT_CLIENT_ENGINE = 'javascript-sdk'; -exports.NODE_CLIENT_ENGINE = 'node-sdk'; -exports.REACT_CLIENT_ENGINE = 'react-sdk'; -exports.NODE_CLIENT_VERSION = '3.6.0-alpha.1'; - -exports.VALID_CLIENT_ENGINES = [ - exports.NODE_CLIENT_ENGINE, - exports.REACT_CLIENT_ENGINE, - exports.JAVASCRIPT_CLIENT_ENGINE, -]; - -exports.NOTIFICATION_TYPES = jsSdkUtils.NOTIFICATION_TYPES; - -exports.DECISION_NOTIFICATION_TYPES = { - AB_TEST: 'ab-test', - FEATURE: 'feature', - FEATURE_TEST: 'feature-test', - FEATURE_VARIABLE: 'feature-variable', -}; - -/* - * Represents the source of a decision for feature management. When a feature - * is accessed through isFeatureEnabled or getVariableValue APIs, the decision - * source is used to decide whether to dispatch an impression event to - * Optimizely. - */ -exports.DECISION_SOURCES = { - FEATURE_TEST: 'feature-test', - ROLLOUT: 'rollout', -}; - -/* - * Possible types of variables attached to features - */ -exports.FEATURE_VARIABLE_TYPES = { - BOOLEAN: 'boolean', - DOUBLE: 'double', - INTEGER: 'integer', - STRING: 'string', -}; - -/* - * Supported datafile versions - */ -exports.DATAFILE_VERSIONS = { - V2: '2', - V3: '3', - V4: '4', -}; - - -/***/ }), -/* 15 */ -/***/ (function(module, exports) { - -/** - * Copyright 2016, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ - -/** - * Default error handler implementation - */ -module.exports = { - /** - * Handle given exception - * @param {Object} exception An exception object - */ - handleError: function() { - // no-op - }, -}; - - -/***/ }), -/* 16 */ -/***/ (function(module, exports) { - -/** - * Copyright 2016-2017, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 POST_METHOD = 'POST'; -var GET_METHOD = 'GET'; -var READYSTATE_COMPLETE = 4; - -module.exports = { - /** - * Sample event dispatcher implementation for tracking impression and conversions - * Users of the SDK can provide their own implementation - * @param {Object} eventObj - * @param {Function} callback - */ - dispatchEvent: function(eventObj, callback) { - var url = eventObj.url; - var params = eventObj.params; - var req; - if (eventObj.httpVerb === POST_METHOD) { - req = new XMLHttpRequest(); - req.open(POST_METHOD, url, true); - req.setRequestHeader('Content-Type', 'application/json'); - req.onreadystatechange = function() { - if (req.readyState === READYSTATE_COMPLETE && callback && typeof callback === 'function') { - try { - callback(params); - } catch (e) { - // TODO: Log this somehow (consider adding a logger to the EventDispatcher interface) - } - } - }; - req.send(JSON.stringify(params)); - } else { - // add param for cors headers to be sent by the log endpoint - url += '?wxhr=true'; - if (params) { - url += '&' + toQueryString(params); - } - - req = new XMLHttpRequest(); - req.open(GET_METHOD, url, true); - req.onreadystatechange = function() { - if (req.readyState === READYSTATE_COMPLETE && callback && typeof callback === 'function') { - try { - callback(); - } catch (e) { - // TODO: Log this somehow (consider adding a logger to the EventDispatcher interface) - } - } - }; - req.send(); - } - }, -}; - -var toQueryString = function(obj) { - return Object.keys(obj) - .map(function(k) { - return encodeURIComponent(k) + '=' + encodeURIComponent(obj[k]); - }) - .join('&'); -}; - - -/***/ }), -/* 17 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -function __export(m) { - for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; -} -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -__export(__webpack_require__(18)); -__export(__webpack_require__(19)); -__export(__webpack_require__(22)); -__export(__webpack_require__(24)); -__export(__webpack_require__(25)); - - -/***/ }), -/* 18 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -function areEventContextsEqual(eventA, eventB) { - var contextA = eventA.context; - var contextB = eventB.context; - return (contextA.accountId === contextB.accountId && - contextA.projectId === contextB.projectId && - contextA.clientName === contextB.clientName && - contextA.clientVersion === contextB.clientVersion && - contextA.revision === contextB.revision && - contextA.anonymizeIP === contextB.anonymizeIP && - contextA.botFiltering === contextB.botFiltering); -} -exports.areEventContextsEqual = areEventContextsEqual; - - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var events_1 = __webpack_require__(18); -var eventQueue_1 = __webpack_require__(20); -var js_sdk_logging_1 = __webpack_require__(1); -var js_sdk_utils_1 = __webpack_require__(12); -var requestTracker_1 = __importDefault(__webpack_require__(21)); -var logger = js_sdk_logging_1.getLogger('EventProcessor'); -var DEFAULT_FLUSH_INTERVAL = 30000; // Unit is ms - default flush interval is 30s -var DEFAULT_MAX_QUEUE_SIZE = 10; -var AbstractEventProcessor = /** @class */ (function () { - function AbstractEventProcessor(_a) { - var dispatcher = _a.dispatcher, _b = _a.flushInterval, flushInterval = _b === void 0 ? 30000 : _b, _c = _a.maxQueueSize, maxQueueSize = _c === void 0 ? 3000 : _c, notificationCenter = _a.notificationCenter; - var _this = this; - this.dispatcher = dispatcher; - if (flushInterval <= 0) { - logger.warn("Invalid flushInterval " + flushInterval + ", defaulting to " + DEFAULT_FLUSH_INTERVAL); - flushInterval = DEFAULT_FLUSH_INTERVAL; - } - maxQueueSize = Math.floor(maxQueueSize); - if (maxQueueSize < 1) { - logger.warn("Invalid maxQueueSize " + maxQueueSize + ", defaulting to " + DEFAULT_MAX_QUEUE_SIZE); - maxQueueSize = DEFAULT_MAX_QUEUE_SIZE; - } - maxQueueSize = Math.max(1, maxQueueSize); - if (maxQueueSize > 1) { - this.queue = new eventQueue_1.DefaultEventQueue({ - flushInterval: flushInterval, - maxQueueSize: maxQueueSize, - sink: function (buffer) { return _this.drainQueue(buffer); }, - batchComparator: events_1.areEventContextsEqual, - }); - } - else { - this.queue = new eventQueue_1.SingleEventQueue({ - sink: function (buffer) { return _this.drainQueue(buffer); }, - }); - } - this.notificationCenter = notificationCenter; - this.requestTracker = new requestTracker_1.default(); - } - AbstractEventProcessor.prototype.drainQueue = function (buffer) { - var _this = this; - var reqPromise = new Promise(function (resolve) { - logger.debug('draining queue with %s events', buffer.length); - if (buffer.length === 0) { - resolve(); - return; - } - var formattedEvent = _this.formatEvents(buffer); - _this.dispatcher.dispatchEvent(formattedEvent, function () { - resolve(); - }); - if (_this.notificationCenter) { - _this.notificationCenter.sendNotifications(js_sdk_utils_1.NOTIFICATION_TYPES.LOG_EVENT, formattedEvent); - } - }); - this.requestTracker.trackRequest(reqPromise); - return reqPromise; - }; - AbstractEventProcessor.prototype.process = function (event) { - this.queue.enqueue(event); - }; - AbstractEventProcessor.prototype.stop = function () { - // swallow - an error stopping this queue shouldn't prevent this from stopping - try { - this.queue.stop(); - return this.requestTracker.onRequestsComplete(); - } - catch (e) { - logger.error('Error stopping EventProcessor: "%s"', e.message, e); - } - return Promise.resolve(); - }; - AbstractEventProcessor.prototype.start = function () { - this.queue.start(); - }; - return AbstractEventProcessor; -}()); -exports.AbstractEventProcessor = AbstractEventProcessor; - - -/***/ }), -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -var js_sdk_logging_1 = __webpack_require__(1); -var logger = js_sdk_logging_1.getLogger('EventProcessor'); -var Timer = /** @class */ (function () { - function Timer(_a) { - var timeout = _a.timeout, callback = _a.callback; - this.timeout = Math.max(timeout, 0); - this.callback = callback; - } - Timer.prototype.start = function () { - this.timeoutId = setTimeout(this.callback, this.timeout); - }; - Timer.prototype.refresh = function () { - this.stop(); - this.start(); - }; - Timer.prototype.stop = function () { - if (this.timeoutId) { - clearTimeout(this.timeoutId); - } - }; - return Timer; -}()); -var SingleEventQueue = /** @class */ (function () { - function SingleEventQueue(_a) { - var sink = _a.sink; - this.sink = sink; - } - SingleEventQueue.prototype.start = function () { - // no-op - }; - SingleEventQueue.prototype.stop = function () { - // no-op - return Promise.resolve(); - }; - SingleEventQueue.prototype.enqueue = function (event) { - this.sink([event]); - }; - return SingleEventQueue; -}()); -exports.SingleEventQueue = SingleEventQueue; -var DefaultEventQueue = /** @class */ (function () { - function DefaultEventQueue(_a) { - var flushInterval = _a.flushInterval, maxQueueSize = _a.maxQueueSize, sink = _a.sink, batchComparator = _a.batchComparator; - this.buffer = []; - this.maxQueueSize = Math.max(maxQueueSize, 1); - this.sink = sink; - this.batchComparator = batchComparator; - this.timer = new Timer({ - callback: this.flush.bind(this), - timeout: flushInterval, - }); - this.started = false; - } - DefaultEventQueue.prototype.start = function () { - this.started = true; - // dont start the timer until the first event is enqueued - }; - DefaultEventQueue.prototype.stop = function () { - this.started = false; - var result = this.sink(this.buffer); - this.buffer = []; - this.timer.stop(); - return result; - }; - DefaultEventQueue.prototype.enqueue = function (event) { - if (!this.started) { - logger.warn('Queue is stopped, not accepting event'); - return; - } - // If new event cannot be included into the current batch, flush so it can - // be in its own new batch. - var bufferedEvent = this.buffer[0]; - if (bufferedEvent && !this.batchComparator(bufferedEvent, event)) { - this.flush(); - } - // start the timer when the first event is put in - if (this.buffer.length === 0) { - this.timer.refresh(); - } - this.buffer.push(event); - if (this.buffer.length >= this.maxQueueSize) { - this.flush(); - } - }; - DefaultEventQueue.prototype.flush = function () { - this.sink(this.buffer); - this.buffer = []; - this.timer.stop(); - }; - return DefaultEventQueue; -}()); -exports.DefaultEventQueue = DefaultEventQueue; - - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2020, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * RequestTracker keeps track of in-flight requests for EventProcessor using - * an internal counter. It exposes methods for adding a new request to be - * tracked, and getting a Promise representing the completion of currently - * tracked requests. - */ -var RequestTracker = /** @class */ (function () { - function RequestTracker() { - this.reqsInFlightCount = 0; - this.reqsCompleteResolvers = []; - } - /** - * Track the argument request (represented by a Promise). reqPromise will feed - * into the state of Promises returned by onRequestsComplete. - * @param {Promise} reqPromise - */ - RequestTracker.prototype.trackRequest = function (reqPromise) { - var _this = this; - this.reqsInFlightCount++; - var onReqComplete = function () { - _this.reqsInFlightCount--; - if (_this.reqsInFlightCount === 0) { - _this.reqsCompleteResolvers.forEach(function (resolver) { return resolver(); }); - _this.reqsCompleteResolvers = []; - } - }; - reqPromise.then(onReqComplete, onReqComplete); - }; - /** - * Return a Promise that fulfills after all currently-tracked request promises - * are resolved. - * @return {Promise} - */ - RequestTracker.prototype.onRequestsComplete = function () { - var _this = this; - return new Promise(function (resolve) { - if (_this.reqsInFlightCount === 0) { - resolve(); - } - else { - _this.reqsCompleteResolvers.push(resolve); - } - }); - }; - return RequestTracker; -}()); -exports.default = RequestTracker; - - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (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 __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 js_sdk_logging_1 = __webpack_require__(1); -var pendingEventsStore_1 = __webpack_require__(23); -var js_sdk_utils_1 = __webpack_require__(12); -var logger = js_sdk_logging_1.getLogger('EventProcessor'); -var PendingEventsDispatcher = /** @class */ (function () { - function PendingEventsDispatcher(_a) { - var eventDispatcher = _a.eventDispatcher, store = _a.store; - this.dispatcher = eventDispatcher; - this.store = store; - } - PendingEventsDispatcher.prototype.dispatchEvent = function (request, callback) { - this.send({ - uuid: js_sdk_utils_1.generateUUID(), - timestamp: js_sdk_utils_1.getTimestamp(), - request: request, - }, callback); - }; - PendingEventsDispatcher.prototype.sendPendingEvents = function () { - var _this = this; - var pendingEvents = this.store.values(); - logger.debug('Sending %s pending events from previous page', pendingEvents.length); - pendingEvents.forEach(function (item) { - try { - _this.send(item, function () { }); - } - catch (e) { } - }); - }; - PendingEventsDispatcher.prototype.send = function (entry, callback) { - var _this = this; - this.store.set(entry.uuid, entry); - this.dispatcher.dispatchEvent(entry.request, function (response) { - _this.store.remove(entry.uuid); - callback(response); - }); - }; - return PendingEventsDispatcher; -}()); -exports.PendingEventsDispatcher = PendingEventsDispatcher; -var LocalStoragePendingEventsDispatcher = /** @class */ (function (_super) { - __extends(LocalStoragePendingEventsDispatcher, _super); - function LocalStoragePendingEventsDispatcher(_a) { - var eventDispatcher = _a.eventDispatcher; - return _super.call(this, { - eventDispatcher: eventDispatcher, - store: new pendingEventsStore_1.LocalStorageStore({ - // TODO make this configurable - maxValues: 100, - key: 'fs_optly_pending_events', - }), - }) || this; - } - return LocalStoragePendingEventsDispatcher; -}(PendingEventsDispatcher)); -exports.LocalStoragePendingEventsDispatcher = LocalStoragePendingEventsDispatcher; - - -/***/ }), -/* 23 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 js_sdk_utils_1 = __webpack_require__(12); -var js_sdk_logging_1 = __webpack_require__(1); -var logger = js_sdk_logging_1.getLogger('EventProcessor'); -var LocalStorageStore = /** @class */ (function () { - function LocalStorageStore(_a) { - var key = _a.key, _b = _a.maxValues, maxValues = _b === void 0 ? 1000 : _b; - this.LS_KEY = key; - this.maxValues = maxValues; - } - LocalStorageStore.prototype.get = function (key) { - return this.getMap()[key] || null; - }; - LocalStorageStore.prototype.set = function (key, value) { - var map = this.getMap(); - map[key] = value; - this.replace(map); - }; - LocalStorageStore.prototype.remove = function (key) { - var map = this.getMap(); - delete map[key]; - this.replace(map); - }; - LocalStorageStore.prototype.values = function () { - return js_sdk_utils_1.objectValues(this.getMap()); - }; - LocalStorageStore.prototype.clear = function () { - this.replace({}); - }; - LocalStorageStore.prototype.replace = function (map) { - try { - // This is a temporary fix to support React Native which does not have localStorage. - window.localStorage && localStorage.setItem(this.LS_KEY, JSON.stringify(map)); - this.clean(); - } - catch (e) { - logger.error(e); - } - }; - LocalStorageStore.prototype.clean = function () { - var map = this.getMap(); - var keys = Object.keys(map); - var toRemove = keys.length - this.maxValues; - if (toRemove < 1) { - return; - } - var entries = keys.map(function (key) { return ({ - key: key, - value: map[key] - }); }); - entries.sort(function (a, b) { return a.value.timestamp - b.value.timestamp; }); - for (var i = 0; i < toRemove; i++) { - delete map[entries[i].key]; - } - this.replace(map); - }; - LocalStorageStore.prototype.getMap = function () { - try { - // This is a temporary fix to support React Native which does not have localStorage. - var data = window.localStorage && localStorage.getItem(this.LS_KEY); - if (data) { - return JSON.parse(data) || {}; - } - } - catch (e) { - logger.error(e); - } - return {}; - }; - return LocalStorageStore; -}()); -exports.LocalStorageStore = LocalStorageStore; - - -/***/ }), -/* 24 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -var __assign = (this && this.__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); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var ACTIVATE_EVENT_KEY = 'campaign_activated'; -var CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom'; -var BOT_FILTERING_KEY = '$opt_bot_filtering'; -/** - * Given an array of batchable Decision or ConversionEvent events it returns - * a single EventV1 with proper batching - * - * @param {ProcessableEvents[]} events - * @returns {EventV1} - */ -function makeBatchedEventV1(events) { - var visitors = []; - var data = events[0]; - events.forEach(function (event) { - if (event.type === 'conversion' || event.type === 'impression') { - var visitor = makeVisitor(event); - if (event.type === 'impression') { - visitor.snapshots.push(makeDecisionSnapshot(event)); - } - else if (event.type === 'conversion') { - visitor.snapshots.push(makeConversionSnapshot(event)); - } - visitors.push(visitor); - } - }); - return { - client_name: data.context.clientName, - client_version: data.context.clientVersion, - account_id: data.context.accountId, - project_id: data.context.projectId, - revision: data.context.revision, - anonymize_ip: data.context.anonymizeIP, - enrich_decisions: true, - visitors: visitors, - }; -} -exports.makeBatchedEventV1 = makeBatchedEventV1; -function makeConversionSnapshot(conversion) { - var tags = __assign({}, conversion.tags); - delete tags['revenue']; - delete tags['value']; - var event = { - entity_id: conversion.event.id, - key: conversion.event.key, - timestamp: conversion.timestamp, - uuid: conversion.uuid, - }; - if (conversion.tags) { - event.tags = conversion.tags; - } - if (conversion.value != null) { - event.value = conversion.value; - } - if (conversion.revenue != null) { - event.revenue = conversion.revenue; - } - return { - events: [event], - }; -} -function makeDecisionSnapshot(event) { - var layer = event.layer, experiment = event.experiment, variation = event.variation; - var layerId = layer ? layer.id : null; - var experimentId = experiment ? experiment.id : null; - var variationId = variation ? variation.id : null; - return { - decisions: [ - { - campaign_id: layerId, - experiment_id: experimentId, - variation_id: variationId, - }, - ], - events: [ - { - entity_id: layerId, - timestamp: event.timestamp, - key: ACTIVATE_EVENT_KEY, - uuid: event.uuid, - }, - ], - }; -} -function makeVisitor(data) { - var visitor = { - snapshots: [], - visitor_id: data.user.id, - attributes: [], - }; - data.user.attributes.forEach(function (attr) { - visitor.attributes.push({ - entity_id: attr.entityId, - key: attr.key, - type: 'custom', - value: attr.value, - }); - }); - if (typeof data.context.botFiltering === 'boolean') { - visitor.attributes.push({ - entity_id: BOT_FILTERING_KEY, - key: BOT_FILTERING_KEY, - type: CUSTOM_ATTRIBUTE_FEATURE_TYPE, - value: data.context.botFiltering, - }); - } - return visitor; -} -/** - * Event for usage with v1 logtier - * - * @export - * @interface EventBuilderV1 - */ -function buildImpressionEventV1(data) { - var visitor = makeVisitor(data); - visitor.snapshots.push(makeDecisionSnapshot(data)); - return { - client_name: data.context.clientName, - client_version: data.context.clientVersion, - account_id: data.context.accountId, - project_id: data.context.projectId, - revision: data.context.revision, - anonymize_ip: data.context.anonymizeIP, - enrich_decisions: true, - visitors: [visitor], - }; -} -exports.buildImpressionEventV1 = buildImpressionEventV1; -function buildConversionEventV1(data) { - var visitor = makeVisitor(data); - visitor.snapshots.push(makeConversionSnapshot(data)); - return { - client_name: data.context.clientName, - client_version: data.context.clientVersion, - account_id: data.context.accountId, - project_id: data.context.projectId, - revision: data.context.revision, - anonymize_ip: data.context.anonymizeIP, - enrich_decisions: true, - visitors: [visitor], - }; -} -exports.buildConversionEventV1 = buildConversionEventV1; - - -/***/ }), -/* 25 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 __extends = (this && this.__extends) || (function () { - var extendStatics = function (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 __()); - }; -})(); -Object.defineProperty(exports, "__esModule", { value: true }); -var eventProcessor_1 = __webpack_require__(19); -var buildEventV1_1 = __webpack_require__(24); -var LogTierV1EventProcessor = /** @class */ (function (_super) { - __extends(LogTierV1EventProcessor, _super); - function LogTierV1EventProcessor() { - return _super !== null && _super.apply(this, arguments) || this; - } - LogTierV1EventProcessor.prototype.formatEvents = function (events) { - return { - url: 'https://logx.optimizely.com/v1/events', - httpVerb: 'POST', - params: buildEventV1_1.makeBatchedEventV1(events), - }; - }; - return LogTierV1EventProcessor; -}(eventProcessor_1.AbstractEventProcessor)); -exports.LogTierV1EventProcessor = LogTierV1EventProcessor; - - -/***/ }), -/* 26 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016-2017, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 logging = __webpack_require__(1); - -function NoOpLogger() {} - -NoOpLogger.prototype.log = function() {}; - -module.exports = { - createLogger: function(opts) { - return new logging.ConsoleLogHandler(opts); - }, - - createNoOpLogger: function() { - return new NoOpLogger(); - }, -}; - - -/***/ }), -/* 27 */ -/***/ (function(module, exports, __webpack_require__) { - -/**************************************************************************** - * Copyright 2016-2019, Optimizely, Inc. and contributors * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License 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 fns = __webpack_require__(11); -var attributesValidator = __webpack_require__(28); -var decisionService = __webpack_require__(29); -var enums = __webpack_require__(14); -var eventBuilder = __webpack_require__(38); -var eventHelpers = __webpack_require__(40); -var eventProcessor = __webpack_require__(17); -var eventTagsValidator = __webpack_require__(41); -var notificationCenter = __webpack_require__(42); -var projectConfig = __webpack_require__(35); -var jsSdkUtils = __webpack_require__(12); -var userProfileServiceValidator = __webpack_require__(43); -var stringValidator = __webpack_require__(37); -var projectConfigManager = __webpack_require__(44); - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var MODULE_NAME = 'OPTIMIZELY'; -var DECISION_SOURCES = enums.DECISION_SOURCES; -var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES; -var DECISION_NOTIFICATION_TYPES = enums.DECISION_NOTIFICATION_TYPES; -var NOTIFICATION_TYPES = enums.NOTIFICATION_TYPES; - -var DEFAULT_ONREADY_TIMEOUT = 30000; - -/** - * The Optimizely class - * @param {Object} config - * @param {string} config.clientEngine - * @param {string} config.clientVersion - * @param {Object} config.datafile - * @param {Object} config.errorHandler - * @param {Object} config.eventDispatcher - * @param {Object} config.logger - * @param {Object} config.skipJSONValidation - * @param {Object} config.userProfileService - * @param {Object} config.eventBatchSize - * @param {Object} config.eventFlushInterval - */ -function Optimizely(config) { - var clientEngine = config.clientEngine; - if (enums.VALID_CLIENT_ENGINES.indexOf(clientEngine) === -1) { - config.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_CLIENT_ENGINE, MODULE_NAME, clientEngine) - ); - clientEngine = enums.NODE_CLIENT_ENGINE; - } - - this.clientEngine = clientEngine; - this.clientVersion = config.clientVersion || enums.NODE_CLIENT_VERSION; - this.errorHandler = config.errorHandler; - this.eventDispatcher = config.eventDispatcher; - this.__isOptimizelyConfigValid = config.isValidInstance; - this.logger = config.logger; - - this.projectConfigManager = new projectConfigManager.ProjectConfigManager({ - datafile: config.datafile, - datafileOptions: config.datafileOptions, - jsonSchemaValidator: config.jsonSchemaValidator, - sdkKey: config.sdkKey, - skipJSONValidation: config.skipJSONValidation, - }); - - this.__disposeOnUpdate = this.projectConfigManager.onUpdate( - function(configObj) { - this.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf(LOG_MESSAGES.UPDATED_OPTIMIZELY_CONFIG, MODULE_NAME, configObj.revision, configObj.projectId) - ); - this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.OPTIMIZELY_CONFIG_UPDATE); - }.bind(this) - ); - - this.__readyPromise = this.projectConfigManager.onReady(); - - var userProfileService = null; - if (config.userProfileService) { - try { - if (userProfileServiceValidator.validate(config.userProfileService)) { - userProfileService = config.userProfileService; - this.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.VALID_USER_PROFILE_SERVICE, MODULE_NAME)); - } - } catch (ex) { - this.logger.log(LOG_LEVEL.WARNING, ex.message); - } - } - - this.decisionService = decisionService.createDecisionService({ - userProfileService: userProfileService, - logger: this.logger, - UNSTABLE_conditionEvaluators: config.UNSTABLE_conditionEvaluators, - }); - - this.notificationCenter = notificationCenter.createNotificationCenter({ - logger: this.logger, - errorHandler: this.errorHandler, - }); - - this.eventProcessor = new eventProcessor.LogTierV1EventProcessor({ - dispatcher: this.eventDispatcher, - flushInterval: config.eventFlushInterval, - maxQueueSize: config.eventBatchSize, - notificationCenter: this.notificationCenter, - }); - this.eventProcessor.start(); - - this.__readyTimeouts = {}; - this.__nextReadyTimeoutId = 0; -} - -/** - * Returns a truthy value if this instance currently has a valid project config - * object, and the initial configuration object that was passed into the - * constructor was also valid. - * @return {*} - */ -Optimizely.prototype.__isValidInstance = function() { - return this.__isOptimizelyConfigValid && this.projectConfigManager.getConfig(); -}; - -/** - * Buckets visitor and sends impression event to Optimizely. - * @param {string} experimentKey - * @param {string} userId - * @param {Object} attributes - * @return {string|null} variation key - */ -Optimizely.prototype.activate = function(experimentKey, userId, attributes) { - try { - if (!this.__isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'activate')); - return null; - } - - if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId }, attributes)) { - return this.__notActivatingExperiment(experimentKey, userId); - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return null; - } - - try { - var variationKey = this.getVariation(experimentKey, userId, attributes); - if (variationKey === null) { - return this.__notActivatingExperiment(experimentKey, userId); - } - - // If experiment is not set to 'Running' status, log accordingly and return variation key - if (!projectConfig.isRunning(configObj, experimentKey)) { - var shouldNotDispatchActivateLogMessage = jsSdkUtils.sprintf( - LOG_MESSAGES.SHOULD_NOT_DISPATCH_ACTIVATE, - MODULE_NAME, - experimentKey - ); - this.logger.log(LOG_LEVEL.DEBUG, shouldNotDispatchActivateLogMessage); - return variationKey; - } - - this._sendImpressionEvent(experimentKey, variationKey, userId, attributes); - - return variationKey; - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - var failedActivationLogMessage = jsSdkUtils.sprintf( - LOG_MESSAGES.NOT_ACTIVATING_USER, - MODULE_NAME, - userId, - experimentKey - ); - this.logger.log(LOG_LEVEL.INFO, failedActivationLogMessage); - this.errorHandler.handleError(ex); - return null; - } - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Create an impression event and call the event dispatcher's dispatch method to - * send this event to Optimizely. Then use the notification center to trigger - * any notification listeners for the ACTIVATE notification type. - * @param {string} experimentKey Key of experiment that was activated - * @param {string} variationKey Key of variation shown in experiment that was activated - * @param {string} userId ID of user to whom the variation was shown - * @param {Object} attributes Optional user attributes - */ -Optimizely.prototype._sendImpressionEvent = function(experimentKey, variationKey, userId, attributes) { - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return; - } - - var impressionEvent = eventHelpers.buildImpressionEvent({ - experimentKey: experimentKey, - variationKey: variationKey, - userId: userId, - userAttributes: attributes, - clientEngine: this.clientEngine, - clientVersion: this.clientVersion, - configObj: configObj, - }); - // TODO is it okay to not pass a projectConfig as second argument - this.eventProcessor.process(impressionEvent); - this.__emitNotificationCenterActivate(experimentKey, variationKey, userId, attributes); -}; - -/** - * Emit the ACTIVATE notification on the notificationCenter - * @param {string} experimentKey Key of experiment that was activated - * @param {string} variationKey Key of variation shown in experiment that was activated - * @param {string} userId ID of user to whom the variation was shown - * @param {Object} attributes Optional user attributes - */ -Optimizely.prototype.__emitNotificationCenterActivate = function(experimentKey, variationKey, userId, attributes) { - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return; - } - - var variationId = projectConfig.getVariationIdFromExperimentAndVariationKey(configObj, experimentKey, variationKey); - var experimentId = projectConfig.getExperimentId(configObj, experimentKey); - var impressionEventOptions = { - attributes: attributes, - clientEngine: this.clientEngine, - clientVersion: this.clientVersion, - configObj: configObj, - experimentId: experimentId, - userId: userId, - variationId: variationId, - logger: this.logger, - }; - var impressionEvent = eventBuilder.getImpressionEvent(impressionEventOptions); - var experiment = configObj.experimentKeyMap[experimentKey]; - var variation; - if (experiment && experiment.variationKeyMap) { - variation = experiment.variationKeyMap[variationKey]; - } - this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.ACTIVATE, { - experiment: experiment, - userId: userId, - attributes: attributes, - variation: variation, - logEvent: impressionEvent, - }); -}; - -/** - * Sends conversion event to Optimizely. - * @param {string} eventKey - * @param {string} userId - * @param {string} attributes - * @param {Object} eventTags Values associated with the event. - */ -Optimizely.prototype.track = function(eventKey, userId, attributes, eventTags) { - try { - if (!this.__isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'track')); - return; - } - - if (!this.__validateInputs({ user_id: userId, event_key: eventKey }, attributes, eventTags)) { - return; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return; - } - - if (!projectConfig.eventWithKeyExists(configObj, eventKey)) { - this.logger.log( - LOG_LEVEL.WARNING, - jsSdkUtils.sprintf(enums.LOG_MESSAGES.EVENT_KEY_NOT_FOUND, MODULE_NAME, eventKey) - ); - this.logger.log(LOG_LEVEL.WARNING, jsSdkUtils.sprintf(LOG_MESSAGES.NOT_TRACKING_USER, MODULE_NAME, userId)); - return; - } - - // remove null values from eventTags - eventTags = this.__filterEmptyValues(eventTags); - var conversionEvent = eventHelpers.buildConversionEvent({ - eventKey: eventKey, - eventTags: eventTags, - userId: userId, - userAttributes: attributes, - clientEngine: this.clientEngine, - clientVersion: this.clientVersion, - configObj: configObj, - }); - this.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(enums.LOG_MESSAGES.TRACK_EVENT, MODULE_NAME, eventKey, userId)); - // TODO is it okay to not pass a projectConfig as second argument - this.eventProcessor.process(conversionEvent); - this.__emitNotificationCenterTrack(eventKey, userId, attributes, eventTags); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - var failedTrackLogMessage = jsSdkUtils.sprintf(LOG_MESSAGES.NOT_TRACKING_USER, MODULE_NAME, userId); - this.logger.log(LOG_LEVEL.ERROR, failedTrackLogMessage); - } -}; - -/** - * Send TRACK event to notificationCenter - * @param {string} eventKey - * @param {string} userId - * @param {string} attributes - * @param {Object} eventTags Values associated with the event. - */ -Optimizely.prototype.__emitNotificationCenterTrack = function(eventKey, userId, attributes, eventTags) { - try { - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return; - } - - var conversionEventOptions = { - attributes: attributes, - clientEngine: this.clientEngine, - clientVersion: this.clientVersion, - configObj: configObj, - eventKey: eventKey, - eventTags: eventTags, - logger: this.logger, - userId: userId, - }; - var conversionEvent = eventBuilder.getConversionEvent(conversionEventOptions); - - this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.TRACK, { - eventKey: eventKey, - userId: userId, - attributes: attributes, - eventTags: eventTags, - logEvent: conversionEvent, - }); - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - this.errorHandler.handleError(ex); - } -}; - -/** - * Gets variation where visitor will be bucketed. - * @param {string} experimentKey - * @param {string} userId - * @param {Object} attributes - * @return {string|null} variation key - */ -Optimizely.prototype.getVariation = function(experimentKey, userId, attributes) { - try { - if (!this.__isValidInstance()) { - this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getVariation')); - return null; - } - - try { - if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId }, attributes)) { - return null; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return null; - } - - var experiment = configObj.experimentKeyMap[experimentKey]; - if (!experiment) { - this.logger.log( - LOG_LEVEL.DEBUG, - jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey) - ); - return null; - } - - var variationKey = this.decisionService.getVariation(configObj, experimentKey, userId, attributes); - var decisionNotificationType = projectConfig.isFeatureExperiment(configObj, experiment.id) - ? DECISION_NOTIFICATION_TYPES.FEATURE_TEST - : DECISION_NOTIFICATION_TYPES.AB_TEST; - - this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.DECISION, { - type: decisionNotificationType, - userId: userId, - attributes: attributes || {}, - decisionInfo: { - experimentKey: experimentKey, - variationKey: variationKey, - }, - }); - - return variationKey; - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - this.errorHandler.handleError(ex); - return null; - } - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Force a user into a variation for a given experiment. - * @param {string} experimentKey - * @param {string} userId - * @param {string|null} variationKey user will be forced into. If null, then clear the existing experiment-to-variation mapping. - * @return boolean A boolean value that indicates if the set completed successfully. - */ -Optimizely.prototype.setForcedVariation = function(experimentKey, userId, variationKey) { - if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId })) { - return false; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return false; - } - - try { - return this.decisionService.setForcedVariation(configObj, experimentKey, userId, variationKey); - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - this.errorHandler.handleError(ex); - return false; - } -}; - -/** - * Gets the forced variation for a given user and experiment. - * @param {string} experimentKey - * @param {string} userId - * @return {string|null} The forced variation key. - */ -Optimizely.prototype.getForcedVariation = function(experimentKey, userId) { - if (!this.__validateInputs({ experiment_key: experimentKey, user_id: userId })) { - return null; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return null; - } - - try { - return this.decisionService.getForcedVariation(configObj, experimentKey, userId); - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - this.errorHandler.handleError(ex); - return null; - } -}; - -/** - * Validate string inputs, user attributes and event tags. - * @param {string} stringInputs Map of string keys and associated values - * @param {Object} userAttributes Optional parameter for user's attributes - * @param {Object} eventTags Optional parameter for event tags - * @return {boolean} True if inputs are valid - * - */ -Optimizely.prototype.__validateInputs = function(stringInputs, userAttributes, eventTags) { - try { - // Null, undefined or non-string user Id is invalid. - if (stringInputs.hasOwnProperty('user_id')) { - var userId = stringInputs.user_id; - if (typeof userId !== 'string' || userId === null || userId === 'undefined') { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, MODULE_NAME, 'user_id')); - } - - delete stringInputs.user_id; - } - - var inputKeys = Object.keys(stringInputs); - for (var index = 0; index < inputKeys.length; index++) { - var key = inputKeys[index]; - if (!stringValidator.validate(stringInputs[key])) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_INPUT_FORMAT, MODULE_NAME, key)); - } - } - if (userAttributes) { - attributesValidator.validate(userAttributes); - } - if (eventTags) { - eventTagsValidator.validate(eventTags); - } - return true; - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - this.errorHandler.handleError(ex); - return false; - } -}; - -/** - * Shows failed activation log message and returns null when user is not activated in experiment - * @param experimentKey - * @param userId - * @return {null} - */ -Optimizely.prototype.__notActivatingExperiment = function(experimentKey, userId) { - var failedActivationLogMessage = jsSdkUtils.sprintf( - LOG_MESSAGES.NOT_ACTIVATING_USER, - MODULE_NAME, - userId, - experimentKey - ); - this.logger.log(LOG_LEVEL.INFO, failedActivationLogMessage); - return null; -}; - -/** - * Filters out attributes/eventTags with null or undefined values - * @param map - * @returns {Object} map - */ -Optimizely.prototype.__filterEmptyValues = function(map) { - for (var key in map) { - if (map.hasOwnProperty(key) && (map[key] === null || map[key] === undefined)) { - delete map[key]; - } - } - return map; -}; - -/** - * Returns true if the feature is enabled for the given user. - * @param {string} featureKey Key of feature which will be checked - * @param {string} userId ID of user which will be checked - * @param {Object} attributes Optional user attributes - * @return {boolean} True if the feature is enabled for the user, false otherwise - */ -Optimizely.prototype.isFeatureEnabled = function(featureKey, userId, attributes) { - try { - if (!this.__isValidInstance()) { - this.logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'isFeatureEnabled') - ); - return false; - } - - if (!this.__validateInputs({ feature_key: featureKey, user_id: userId }, attributes)) { - return false; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return false; - } - - var feature = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); - if (!feature) { - return false; - } - - var featureEnabled = false; - var decision = this.decisionService.getVariationForFeature(configObj, feature, userId, attributes); - var variation = decision.variation; - var sourceInfo = {}; - - if (variation) { - featureEnabled = variation.featureEnabled; - if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { - sourceInfo = { - experimentKey: decision.experiment.key, - variationKey: decision.variation.key, - }; - // got a variation from the exp, so we track the impression - this._sendImpressionEvent(decision.experiment.key, decision.variation.key, userId, attributes); - } - } - - if (featureEnabled === true) { - this.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf(LOG_MESSAGES.FEATURE_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId) - ); - } else { - this.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf(LOG_MESSAGES.FEATURE_NOT_ENABLED_FOR_USER, MODULE_NAME, featureKey, userId) - ); - featureEnabled = false; - } - - var featureInfo = { - featureKey: featureKey, - featureEnabled: featureEnabled, - source: decision.decisionSource, - sourceInfo: sourceInfo, - }; - - this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.DECISION, { - type: DECISION_NOTIFICATION_TYPES.FEATURE, - userId: userId, - attributes: attributes || {}, - decisionInfo: featureInfo, - }); - - return featureEnabled; - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return false; - } -}; - -/** - * Returns an Array containing the keys of all features in the project that are - * enabled for the given user. - * @param {string} userId - * @param {Object} attributes - * @return {Array} Array of feature keys (strings) - */ -Optimizely.prototype.getEnabledFeatures = function(userId, attributes) { - try { - var enabledFeatures = []; - if (!this.__isValidInstance()) { - this.logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, 'getEnabledFeatures') - ); - return enabledFeatures; - } - - if (!this.__validateInputs({ user_id: userId })) { - return enabledFeatures; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return enabledFeatures; - } - - jsSdkUtils.objectValues(configObj.featureKeyMap).forEach( - function(feature) { - if (this.isFeatureEnabled(feature.key, userId, attributes)) { - enabledFeatures.push(feature.key); - } - }.bind(this) - ); - - return enabledFeatures; - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return []; - } -}; - -/** - * Returns dynamically-typed value of the variable attached to the given - * feature flag. Returns null if the feature key or variable key is invalid. - * - * @param {string} featureKey Key of the feature whose variable's - * value is being accessed - * @param {string} variableKey Key of the variable whose value is - * being accessed - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {string|boolean|number|null} Value of the variable cast to the appropriate - * type, or null if the feature key is invalid or - * the variable key is invalid - */ - -Optimizely.prototype.getFeatureVariable = function(featureKey, variableKey, userId, attributes) { - try { - return this._getFeatureVariableForType(featureKey, variableKey, null, userId, attributes); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Helper method to get the value for a variable of a certain type attached to a - * feature flag. Returns null if the feature key is invalid, the variable key is - * invalid, the given variable type does not match the variable's actual type, - * or the variable value cannot be cast to the required type. If the given variable - * type is null, the value of the variable cast to the appropriate type is returned. - * - * @param {string} featureKey Key of the feature whose variable's value is - * being accessed - * @param {string} variableKey Key of the variable whose value is being - * accessed - * @param {string|null} variableType Type of the variable whose value is being - * accessed (must be one of FEATURE_VARIABLE_TYPES - * in lib/utils/enums/index.js), or null to return the - * value of the variable cast to the appropriate type - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {string|boolean|number|null} Value of the variable cast to the appropriate - * type, or null if the feature key is invalid, the - * variable key is invalid, or there is a mismatch - * with the type of the variable - */ -Optimizely.prototype._getFeatureVariableForType = function(featureKey, variableKey, variableType, userId, attributes) { - if (!this.__isValidInstance()) { - var apiName = variableType - ? 'getFeatureVariable' + variableType.charAt(0).toUpperCase() + variableType.slice(1) - : 'getFeatureVariable'; - this.logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(LOG_MESSAGES.INVALID_OBJECT, MODULE_NAME, apiName)); - return null; - } - - if (!this.__validateInputs({ feature_key: featureKey, variable_key: variableKey, user_id: userId }, attributes)) { - return null; - } - - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return null; - } - - var featureFlag = projectConfig.getFeatureFromKey(configObj, featureKey, this.logger); - if (!featureFlag) { - return null; - } - - var variable = projectConfig.getVariableForFeature(configObj, featureKey, variableKey, this.logger); - if (!variable) { - return null; - } - - if (!variableType) { - variableType = variable.type; - } else if (variable.type !== variableType) { - this.logger.log( - LOG_LEVEL.WARNING, - jsSdkUtils.sprintf(LOG_MESSAGES.VARIABLE_REQUESTED_WITH_WRONG_TYPE, MODULE_NAME, variableType, variable.type) - ); - return null; - } - - var featureEnabled = false; - var variableValue = variable.defaultValue; - var decision = this.decisionService.getVariationForFeature(configObj, featureFlag, userId, attributes); - - if (decision.variation !== null) { - featureEnabled = decision.variation.featureEnabled; - var value = projectConfig.getVariableValueForVariation(configObj, variable, decision.variation, this.logger); - if (value !== null) { - if (featureEnabled === true) { - variableValue = value; - this.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf( - LOG_MESSAGES.USER_RECEIVED_VARIABLE_VALUE, - MODULE_NAME, - variableKey, - featureFlag.key, - variableValue, - userId - ) - ); - } else { - this.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf( - LOG_MESSAGES.FEATURE_NOT_ENABLED_RETURN_DEFAULT_VARIABLE_VALUE, - MODULE_NAME, - featureFlag.key, - userId, - variableKey - ) - ); - } - } else { - this.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf( - LOG_MESSAGES.VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE, - MODULE_NAME, - variableKey, - decision.variation.key - ) - ); - } - } else { - this.logger.log( - LOG_LEVEL.INFO, - jsSdkUtils.sprintf( - LOG_MESSAGES.USER_RECEIVED_DEFAULT_VARIABLE_VALUE, - MODULE_NAME, - userId, - variableKey, - featureFlag.key - ) - ); - } - - var sourceInfo = {}; - if (decision.decisionSource === DECISION_SOURCES.FEATURE_TEST) { - sourceInfo = { - experimentKey: decision.experiment.key, - variationKey: decision.variation.key, - }; - } - - var typeCastedValue = projectConfig.getTypeCastValue(variableValue, variableType, this.logger); - this.notificationCenter.sendNotifications(NOTIFICATION_TYPES.DECISION, { - type: DECISION_NOTIFICATION_TYPES.FEATURE_VARIABLE, - userId: userId, - attributes: attributes || {}, - decisionInfo: { - featureKey: featureKey, - featureEnabled: featureEnabled, - source: decision.decisionSource, - variableKey: variableKey, - variableValue: typeCastedValue, - variableType: variableType, - sourceInfo: sourceInfo, - }, - }); - return typeCastedValue; -}; - -/** - * Returns value for the given boolean variable attached to the given feature - * flag. - * @param {string} featureKey Key of the feature whose variable's value is - * being accessed - * @param {string} variableKey Key of the variable whose value is being - * accessed - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {boolean|null} Boolean value of the variable, or null if the - * feature key is invalid, the variable key is - * invalid, or there is a mismatch with the type - * of the variable - */ -Optimizely.prototype.getFeatureVariableBoolean = function(featureKey, variableKey, userId, attributes) { - try { - return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.BOOLEAN, userId, attributes); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Returns value for the given double variable attached to the given feature - * flag. - * @param {string} featureKey Key of the feature whose variable's value is - * being accessed - * @param {string} variableKey Key of the variable whose value is being - * accessed - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {number|null} Number value of the variable, or null if the - * feature key is invalid, the variable key is - * invalid, or there is a mismatch with the type - * of the variable - */ -Optimizely.prototype.getFeatureVariableDouble = function(featureKey, variableKey, userId, attributes) { - try { - return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.DOUBLE, userId, attributes); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Returns value for the given integer variable attached to the given feature - * flag. - * @param {string} featureKey Key of the feature whose variable's value is - * being accessed - * @param {string} variableKey Key of the variable whose value is being - * accessed - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {number|null} Number value of the variable, or null if the - * feature key is invalid, the variable key is - * invalid, or there is a mismatch with the type - * of the variable - */ -Optimizely.prototype.getFeatureVariableInteger = function(featureKey, variableKey, userId, attributes) { - try { - return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.INTEGER, userId, attributes); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Returns value for the given string variable attached to the given feature - * flag. - * @param {string} featureKey Key of the feature whose variable's value is - * being accessed - * @param {string} variableKey Key of the variable whose value is being - * accessed - * @param {string} userId ID for the user - * @param {Object} attributes Optional user attributes - * @return {string|null} String value of the variable, or null if the - * feature key is invalid, the variable key is - * invalid, or there is a mismatch with the type - * of the variable - */ -Optimizely.prototype.getFeatureVariableString = function(featureKey, variableKey, userId, attributes) { - try { - return this._getFeatureVariableForType(featureKey, variableKey, FEATURE_VARIABLE_TYPES.STRING, userId, attributes); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Returns OptimizelyConfig object containing experiments and features data - * @return {Object} - * - * OptimizelyConfig Object Schema - * { - * 'experimentsMap': { - * 'my-fist-experiment': { - * 'id': '111111', - * 'key': 'my-fist-experiment' - * 'variationsMap': { - * 'variation_1': { - * 'id': '121212', - * 'key': 'variation_1', - * 'variablesMap': { - * 'age': { - * 'id': '222222', - * 'key': 'age', - * 'type': 'integer', - * 'value': '0', - * } - * } - * } - * } - * } - * }, - * 'featuresMap': { - * 'awesome-feature': { - * 'id': '333333', - * 'key': 'awesome-feature', - * 'experimentsMap': Object, - * 'variationsMap': Object, - * } - * } - * } - */ -Optimizely.prototype.getOptimizelyConfig = function() { - try { - var configObj = this.projectConfigManager.getConfig(); - if (!configObj) { - return null; - } - return this.projectConfigManager.getOptimizelyConfig(); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return null; - } -}; - -/** - * Stop background processes belonging to this instance, including: - * - * - Active datafile requests - * - Pending datafile requests - * - Pending event queue flushes - * - * In-flight datafile requests will be aborted. Any events waiting to be sent - * as part of a batched event request will be immediately flushed to the event - * dispatcher. - * - * Returns a Promise that fulfills after all in-flight event dispatcher requests - * (including any final request resulting from flushing the queue as described - * above) are complete. If there are no in-flight event dispatcher requests and - * no queued events waiting to be sent, returns an immediately-fulfilled Promise. - * - * Returned Promises are fulfilled with result objects containing these - * properties: - * - success (boolean): true if the event dispatcher signaled completion of - * all in-flight and final requests, or if there were no - * queued events and no in-flight requests. false if an - * unexpected error was encountered during the close - * process. - * - reason (string=): If success is false, this is a string property with - * an explanatory message. - * - * NOTE: After close is called, this instance is no longer usable - any events - * generated will no longer be sent to the event dispatcher. - * - * @return {Promise} - */ -Optimizely.prototype.close = function() { - try { - var eventProcessorStoppedPromise = this.eventProcessor.stop(); - if (this.__disposeOnUpdate) { - this.__disposeOnUpdate(); - this.__disposeOnUpdate = null; - } - if (this.projectConfigManager) { - this.projectConfigManager.stop(); - } - Object.keys(this.__readyTimeouts).forEach( - function(readyTimeoutId) { - var readyTimeoutRecord = this.__readyTimeouts[readyTimeoutId]; - clearTimeout(readyTimeoutRecord.readyTimeout); - readyTimeoutRecord.onClose(); - }.bind(this) - ); - this.__readyTimeouts = {}; - return eventProcessorStoppedPromise.then( - function() { - return { - success: true, - }; - }, - function(err) { - return { - success: false, - reason: String(err), - }; - } - ); - } catch (err) { - this.logger.log(LOG_LEVEL.ERROR, err.message); - this.errorHandler.handleError(err); - return Promise.resolve({ - success: false, - reason: String(err), - }); - } -}; - -/** - * Returns a Promise that fulfills when this instance is ready to use (meaning - * it has a valid datafile), or has failed to become ready within a period of - * time (configurable by the timeout property of the options argument), or when - * this instance is closed via the close method. - * - * If a valid datafile was provided in the constructor, the returned Promise is - * immediately fulfilled. If an sdkKey was provided, a manager will be used to - * fetch a datafile, and the returned promise will fulfill if that fetch - * succeeds or fails before the timeout. The default timeout is 30 seconds, - * which will be used if no timeout is provided in the argument options object. - * - * The returned Promise is fulfilled with a result object containing these - * properties: - * - success (boolean): True if this instance is ready to use with a valid - * datafile, or false if this instance failed to become - * ready or was closed prior to becoming ready. - * - reason (string=): If success is false, this is a string property with - * an explanatory message. Failure could be due to - * expiration of the timeout, network errors, - * unsuccessful responses, datafile parse errors, - * datafile validation errors, or the instance being - * closed - * @param {Object=} options - * @param {number|undefined} options.timeout - * @return {Promise} - */ -Optimizely.prototype.onReady = function(options) { - var timeout; - if (typeof options === 'object' && options !== null) { - timeout = options.timeout; - } - if (!fns.isSafeInteger(timeout)) { - timeout = DEFAULT_ONREADY_TIMEOUT; - } - - var resolveTimeoutPromise; - var timeoutPromise = new Promise(function(resolve) { - resolveTimeoutPromise = resolve; - }); - - var timeoutId = this.__nextReadyTimeoutId; - this.__nextReadyTimeoutId++; - - var onReadyTimeout = function() { - delete this.__readyTimeouts[timeoutId]; - resolveTimeoutPromise({ - success: false, - reason: jsSdkUtils.sprintf('onReady timeout expired after %s ms', timeout), - }); - }.bind(this); - var readyTimeout = setTimeout(onReadyTimeout, timeout); - var onClose = function() { - resolveTimeoutPromise({ - success: false, - reason: 'Instance closed', - }); - }; - - this.__readyTimeouts[timeoutId] = { - readyTimeout: readyTimeout, - onClose: onClose, - }; - - this.__readyPromise.then( - function() { - clearTimeout(readyTimeout); - delete this.__readyTimeouts[timeoutId]; - resolveTimeoutPromise({ - success: true, - }); - }.bind(this) - ); - - return Promise.race([this.__readyPromise, timeoutPromise]); -}; - -module.exports = Optimizely; - - -/***/ }), -/* 28 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016, 2018-2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ - -/** - * Provides utility method for validating that the attributes user has provided are valid - */ - -var sprintf = __webpack_require__(12).sprintf; -var fns = __webpack_require__(11); - -var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; -var MODULE_NAME = 'ATTRIBUTES_VALIDATOR'; - -module.exports = { - /** - * Validates user's provided attributes - * @param {Object} attributes - * @return {boolean} True if the attributes are valid - * @throws If the attributes are not valid - */ - validate: function(attributes) { - if (typeof attributes === 'object' && !Array.isArray(attributes) && attributes !== null) { - Object.keys(attributes).forEach(function(key) { - if (typeof attributes[key] === 'undefined') { - throw new Error(sprintf(ERROR_MESSAGES.UNDEFINED_ATTRIBUTE, MODULE_NAME, key)); - } - }); - return true; - } else { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_ATTRIBUTES, MODULE_NAME)); - } - }, - - isAttributeValid: function(attributeKey, attributeValue) { - return ( - typeof attributeKey === 'string' && - (typeof attributeValue === 'string' || - typeof attributeValue === 'boolean' || - (fns.isNumber(attributeValue) && fns.isSafeInteger(attributeValue))) - ); - }, -}; - - -/***/ }), -/* 29 */ -/***/ (function(module, exports, __webpack_require__) { - -/**************************************************************************** - * Copyright 2017-2019, Optimizely, Inc. and contributors * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License 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 AudienceEvaluator = __webpack_require__(30); -var bucketer = __webpack_require__(33); -var enums = __webpack_require__(14); -var fns = __webpack_require__(11); -var projectConfig = __webpack_require__(35); -var stringValidator = __webpack_require__(37); - -var sprintf = __webpack_require__(12).sprintf; - -var MODULE_NAME = 'DECISION_SERVICE'; -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var DECISION_SOURCES = enums.DECISION_SOURCES; - -/** - * Optimizely's decision service that determines which variation of an experiment the user will be allocated to. - * - * The decision service contains all logic around how a user decision is made. This includes all of the following (in order): - * 1. Checking experiment status - * 2. Checking forced bucketing - * 3. Checking whitelisting - * 4. Checking user profile service for past bucketing decisions (sticky bucketing) - * 5. Checking audience targeting - * 6. Using Murmurhash3 to bucket the user. - * - * @constructor - * @param {Object} options - * @param {Object} options.userProfileService An instance of the user profile service for sticky bucketing. - * @param {Object} options.logger An instance of a logger to log messages. - * @returns {Object} - */ -function DecisionService(options) { - this.audienceEvaluator = new AudienceEvaluator(options.UNSTABLE_conditionEvaluators); - this.forcedVariationMap = {}; - this.logger = options.logger; - this.userProfileService = options.userProfileService || null; -} - -/** - * Gets variation where visitor will be bucketed. - * @param {Object} configObj The parsed project configuration object - * @param {string} experimentKey - * @param {string} userId - * @param {Object} attributes - * @return {string|null} the variation the user is bucketed into. - */ -DecisionService.prototype.getVariation = function(configObj, experimentKey, userId, attributes) { - // by default, the bucketing ID should be the user ID - var bucketingId = this._getBucketingId(userId, attributes); - - if (!this.__checkIfExperimentIsActive(configObj, experimentKey)) { - return null; - } - var experiment = configObj.experimentKeyMap[experimentKey]; - var forcedVariationKey = this.getForcedVariation(configObj, experimentKey, userId); - if (forcedVariationKey) { - return forcedVariationKey; - } - - var variation = this.__getWhitelistedVariation(experiment, userId); - if (variation) { - return variation.key; - } - - // check for sticky bucketing - var experimentBucketMap = this.__resolveExperimentBucketMap(userId, attributes); - variation = this.__getStoredVariation(configObj, experiment, userId, experimentBucketMap); - if (variation) { - this.logger.log( - LOG_LEVEL.INFO, - sprintf(LOG_MESSAGES.RETURNING_STORED_VARIATION, MODULE_NAME, variation.key, experimentKey, userId) - ); - return variation.key; - } - - // Perform regular targeting and bucketing - if (!this.__checkIfUserIsInAudience(configObj, experimentKey, userId, attributes)) { - return null; - } - - var bucketerParams = this.__buildBucketerParams(configObj, experimentKey, bucketingId, userId); - var variationId = bucketer.bucket(bucketerParams); - variation = configObj.variationIdMap[variationId]; - if (!variation) { - return null; - } - - // persist bucketing - this.__saveUserProfile(experiment, variation, userId, experimentBucketMap); - - return variation.key; -}; - -/** - * Merges attributes from attributes[STICKY_BUCKETING_KEY] and userProfileService - * @param {Object} attributes - * @return {Object} finalized copy of experiment_bucket_map - */ -DecisionService.prototype.__resolveExperimentBucketMap = function(userId, attributes) { - attributes = attributes || {}; - var userProfile = this.__getUserProfile(userId) || {}; - var attributeExperimentBucketMap = attributes[enums.CONTROL_ATTRIBUTES.STICKY_BUCKETING_KEY]; - return fns.assign({}, userProfile.experiment_bucket_map, attributeExperimentBucketMap); -}; - -/** - * Checks whether the experiment is running - * @param {Object} configObj The parsed project configuration object - * @param {string} experimentKey Key of experiment being validated - * @param {string} userId ID of user - * @return {boolean} True if experiment is running - */ -DecisionService.prototype.__checkIfExperimentIsActive = function(configObj, experimentKey) { - if (!projectConfig.isActive(configObj, experimentKey)) { - var experimentNotRunningLogMessage = sprintf(LOG_MESSAGES.EXPERIMENT_NOT_RUNNING, MODULE_NAME, experimentKey); - this.logger.log(LOG_LEVEL.INFO, experimentNotRunningLogMessage); - return false; - } - - return true; -}; - -/** - * Checks if user is whitelisted into any variation and return that variation if so - * @param {Object} experiment - * @param {string} userId - * @return {string|null} Forced variation if it exists for user ID, otherwise null - */ -DecisionService.prototype.__getWhitelistedVariation = function(experiment, userId) { - if (experiment.forcedVariations && experiment.forcedVariations.hasOwnProperty(userId)) { - var forcedVariationKey = experiment.forcedVariations[userId]; - if (experiment.variationKeyMap.hasOwnProperty(forcedVariationKey)) { - var forcedBucketingSucceededMessageLog = sprintf( - LOG_MESSAGES.USER_FORCED_IN_VARIATION, - MODULE_NAME, - userId, - forcedVariationKey - ); - this.logger.log(LOG_LEVEL.INFO, forcedBucketingSucceededMessageLog); - return experiment.variationKeyMap[forcedVariationKey]; - } else { - var forcedBucketingFailedMessageLog = sprintf( - LOG_MESSAGES.FORCED_BUCKETING_FAILED, - MODULE_NAME, - forcedVariationKey, - userId - ); - this.logger.log(LOG_LEVEL.ERROR, forcedBucketingFailedMessageLog); - return null; - } - } - - return null; -}; - -/** - * Checks whether the user is included in experiment audience - * @param {Object} configObj The parsed project configuration object - * @param {string} experimentKey Key of experiment being validated - * @param {string} userId ID of user - * @param {Object} attributes Optional parameter for user's attributes - * @return {boolean} True if user meets audience conditions - */ -DecisionService.prototype.__checkIfUserIsInAudience = function(configObj, experimentKey, userId, attributes) { - var experimentAudienceConditions = projectConfig.getExperimentAudienceConditions(configObj, experimentKey); - var audiencesById = projectConfig.getAudiencesById(configObj); - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf( - LOG_MESSAGES.EVALUATING_AUDIENCES_COMBINED, - MODULE_NAME, - experimentKey, - JSON.stringify(experimentAudienceConditions) - ) - ); - var result = this.audienceEvaluator.evaluate(experimentAudienceConditions, audiencesById, attributes); - this.logger.log( - LOG_LEVEL.INFO, - sprintf( - LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT_COMBINED, - MODULE_NAME, - experimentKey, - result.toString().toUpperCase() - ) - ); - - if (!result) { - var userDoesNotMeetConditionsLogMessage = sprintf( - LOG_MESSAGES.USER_NOT_IN_EXPERIMENT, - MODULE_NAME, - userId, - experimentKey - ); - this.logger.log(LOG_LEVEL.INFO, userDoesNotMeetConditionsLogMessage); - return false; - } - - return true; -}; - -/** - * Given an experiment key and user ID, returns params used in bucketer call - * @param configObj The parsed project configuration object - * @param experimentKey Experiment key used for bucketer - * @param bucketingId ID to bucket user into - * @param userId ID of user to be bucketed - * @return {Object} - */ -DecisionService.prototype.__buildBucketerParams = function(configObj, experimentKey, bucketingId, userId) { - var bucketerParams = {}; - bucketerParams.experimentKey = experimentKey; - bucketerParams.experimentId = projectConfig.getExperimentId(configObj, experimentKey); - bucketerParams.userId = userId; - bucketerParams.trafficAllocationConfig = projectConfig.getTrafficAllocation(configObj, experimentKey); - bucketerParams.experimentKeyMap = configObj.experimentKeyMap; - bucketerParams.groupIdMap = configObj.groupIdMap; - bucketerParams.variationIdMap = configObj.variationIdMap; - bucketerParams.logger = this.logger; - bucketerParams.bucketingId = bucketingId; - return bucketerParams; -}; - -/** - * Pull the stored variation out of the experimentBucketMap for an experiment/userId - * @param {Object} configObj The parsed project configuration object - * @param {Object} experiment - * @param {String} userId - * @param {Object} experimentBucketMap mapping experiment => { variation_id: } - * @return {Object} the stored variation or null if the user profile does not have one for the given experiment - */ -DecisionService.prototype.__getStoredVariation = function(configObj, experiment, userId, experimentBucketMap) { - if (experimentBucketMap.hasOwnProperty(experiment.id)) { - var decision = experimentBucketMap[experiment.id]; - var variationId = decision.variation_id; - if (configObj.variationIdMap.hasOwnProperty(variationId)) { - return configObj.variationIdMap[decision.variation_id]; - } else { - this.logger.log( - LOG_LEVEL.INFO, - sprintf(LOG_MESSAGES.SAVED_VARIATION_NOT_FOUND, MODULE_NAME, userId, variationId, experiment.key) - ); - } - } - - return null; -}; - -/** - * Get the user profile with the given user ID - * @param {string} userId - * @return {Object|undefined} the stored user profile or undefined if one isn't found - */ -DecisionService.prototype.__getUserProfile = function(userId) { - var userProfile = { - user_id: userId, - experiment_bucket_map: {}, - }; - - if (!this.userProfileService) { - return userProfile; - } - - try { - return this.userProfileService.lookup(userId); - } catch (ex) { - this.logger.log( - LOG_LEVEL.ERROR, - sprintf(ERROR_MESSAGES.USER_PROFILE_LOOKUP_ERROR, MODULE_NAME, userId, ex.message) - ); - } -}; - -/** - * Saves the bucketing decision to the user profile - * @param {Object} userProfile - * @param {Object} experiment - * @param {Object} variation - * @param {Object} experimentBucketMap - */ -DecisionService.prototype.__saveUserProfile = function(experiment, variation, userId, experimentBucketMap) { - if (!this.userProfileService) { - return; - } - - try { - experimentBucketMap[experiment.id] = { - variation_id: variation.id - }; - - this.userProfileService.save({ - user_id: userId, - experiment_bucket_map: experimentBucketMap, - }); - - this.logger.log( - LOG_LEVEL.INFO, - sprintf(LOG_MESSAGES.SAVED_VARIATION, MODULE_NAME, variation.key, experiment.key, userId) - ); - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, sprintf(ERROR_MESSAGES.USER_PROFILE_SAVE_ERROR, MODULE_NAME, userId, ex.message)); - } -}; - -/** - * Given a feature, user ID, and attributes, returns an object representing a - * decision. If the user was bucketed into a variation for the given feature - * and attributes, the returned decision object will have variation and - * experiment properties (both objects), as well as a decisionSource property. - * decisionSource indicates whether the decision was due to a rollout or an - * experiment. - * @param {Object} configObj The parsed project configuration object - * @param {Object} feature A feature flag object from project configuration - * @param {String} userId A string identifying the user, for bucketing - * @param {Object} attributes Optional user attributes - * @return {Object} An object with experiment, variation, and decisionSource - * properties. If the user was not bucketed into a variation, the variation - * property is null. - */ -DecisionService.prototype.getVariationForFeature = function(configObj, feature, userId, attributes) { - var experimentDecision = this._getVariationForFeatureExperiment(configObj, feature, userId, attributes); - if (experimentDecision.variation !== null) { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf( - LOG_MESSAGES.USER_IN_FEATURE_EXPERIMENT, - MODULE_NAME, - userId, - experimentDecision.variation.key, - experimentDecision.experiment.key, - feature.key - ) - ); - return experimentDecision; - } - - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_NOT_IN_FEATURE_EXPERIMENT, MODULE_NAME, userId, feature.key) - ); - - var rolloutDecision = this._getVariationForRollout(configObj, feature, userId, attributes); - if (rolloutDecision.variation !== null) { - this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.USER_IN_ROLLOUT, MODULE_NAME, userId, feature.key)); - return rolloutDecision; - } - - this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.USER_NOT_IN_ROLLOUT, MODULE_NAME, userId, feature.key)); - return rolloutDecision; -}; - -DecisionService.prototype._getVariationForFeatureExperiment = function(configObj, feature, userId, attributes) { - var experiment = null; - var variationKey = null; - - if (feature.hasOwnProperty('groupId')) { - var group = configObj.groupIdMap[feature.groupId]; - if (group) { - experiment = this._getExperimentInGroup(configObj, group, userId); - if (experiment && feature.experimentIds.indexOf(experiment.id) !== -1) { - variationKey = this.getVariation(configObj, experiment.key, userId, attributes); - } - } - } else if (feature.experimentIds.length > 0) { - // If the feature does not have a group ID, then it can only be associated - // with one experiment, so we look at the first experiment ID only - experiment = projectConfig.getExperimentFromId(configObj, feature.experimentIds[0], this.logger); - if (experiment) { - variationKey = this.getVariation(configObj, experiment.key, userId, attributes); - } - } else { - this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.FEATURE_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.key)); - } - - var variation = null; - if (variationKey !== null && experiment !== null) { - variation = experiment.variationKeyMap[variationKey]; - } - return { - experiment: experiment, - variation: variation, - decisionSource: DECISION_SOURCES.FEATURE_TEST, - }; -}; - -DecisionService.prototype._getExperimentInGroup = function(configObj, group, userId) { - var experimentId = bucketer.bucketUserIntoExperiment(group, userId, userId, this.logger); - if (experimentId) { - this.logger.log( - LOG_LEVEL.INFO, - sprintf(LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, MODULE_NAME, userId, experimentId, group.id) - ); - var experiment = projectConfig.getExperimentFromId(configObj, experimentId, this.logger); - if (experiment) { - return experiment; - } - } - - this.logger.log( - LOG_LEVEL.INFO, - sprintf(LOG_MESSAGES.USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP, MODULE_NAME, userId, group.id) - ); - return null; -}; - -DecisionService.prototype._getVariationForRollout = function(configObj, feature, userId, attributes) { - if (!feature.rolloutId) { - this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.NO_ROLLOUT_EXISTS, MODULE_NAME, feature.key)); - return { - experiment: null, - variation: null, - decisionSource: DECISION_SOURCES.ROLLOUT, - }; - } - - var rollout = configObj.rolloutIdMap[feature.rolloutId]; - if (!rollout) { - this.logger.log( - LOG_LEVEL.ERROR, - sprintf(ERROR_MESSAGES.INVALID_ROLLOUT_ID, MODULE_NAME, feature.rolloutId, feature.key) - ); - return { - experiment: null, - variation: null, - decisionSource: DECISION_SOURCES.ROLLOUT, - }; - } - - if (rollout.experiments.length === 0) { - this.logger.log(LOG_LEVEL.ERROR, sprintf(LOG_MESSAGES.ROLLOUT_HAS_NO_EXPERIMENTS, MODULE_NAME, feature.rolloutId)); - return { - experiment: null, - variation: null, - decisionSource: DECISION_SOURCES.ROLLOUT, - }; - } - - var bucketingId = this._getBucketingId(userId, attributes); - - // The end index is length - 1 because the last experiment is assumed to be - // "everyone else", which will be evaluated separately outside this loop - var endIndex = rollout.experiments.length - 1; - var index; - var experiment; - var bucketerParams; - var variationId; - var variation; - for (index = 0; index < endIndex; index++) { - experiment = configObj.experimentKeyMap[rollout.experiments[index].key]; - - if (!this.__checkIfUserIsInAudience(configObj, experiment.key, userId, attributes)) { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_DOESNT_MEET_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, index + 1) - ); - continue; - } - - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_MEETS_CONDITIONS_FOR_TARGETING_RULE, MODULE_NAME, userId, index + 1) - ); - bucketerParams = this.__buildBucketerParams(configObj, experiment.key, bucketingId, userId); - variationId = bucketer.bucket(bucketerParams); - variation = configObj.variationIdMap[variationId]; - if (variation) { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, index + 1) - ); - return { - experiment: experiment, - variation: variation, - decisionSource: DECISION_SOURCES.ROLLOUT, - }; - } else { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_NOT_BUCKETED_INTO_TARGETING_RULE, MODULE_NAME, userId, index + 1) - ); - break; - } - } - - var everyoneElseExperiment = configObj.experimentKeyMap[rollout.experiments[endIndex].key]; - if (this.__checkIfUserIsInAudience(configObj, everyoneElseExperiment.key, userId, attributes)) { - bucketerParams = this.__buildBucketerParams(configObj, everyoneElseExperiment.key, bucketingId, userId); - variationId = bucketer.bucket(bucketerParams); - variation = configObj.variationIdMap[variationId]; - if (variation) { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_BUCKETED_INTO_EVERYONE_TARGETING_RULE, MODULE_NAME, userId) - ); - return { - experiment: everyoneElseExperiment, - variation: variation, - decisionSource: DECISION_SOURCES.ROLLOUT, - }; - } else { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_NOT_BUCKETED_INTO_EVERYONE_TARGETING_RULE, MODULE_NAME, userId) - ); - } - } - - return { - experiment: null, - variation: null, - decisionSource: DECISION_SOURCES.ROLLOUT, - }; -}; - -/** - * Get bucketing Id from user attributes. - * @param {String} userId - * @param {Object} attributes - * @returns {String} Bucketing Id if it is a string type in attributes, user Id otherwise. - */ -DecisionService.prototype._getBucketingId = function(userId, attributes) { - var bucketingId = userId; - - // If the bucketing ID key is defined in attributes, than use that in place of the userID for the murmur hash key - if ( - attributes != null && - typeof attributes === 'object' && - attributes.hasOwnProperty(enums.CONTROL_ATTRIBUTES.BUCKETING_ID) - ) { - if (typeof attributes[enums.CONTROL_ATTRIBUTES.BUCKETING_ID] === 'string') { - bucketingId = attributes[enums.CONTROL_ATTRIBUTES.BUCKETING_ID]; - this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.VALID_BUCKETING_ID, MODULE_NAME, bucketingId)); - } else { - this.logger.log(LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.BUCKETING_ID_NOT_STRING, MODULE_NAME)); - } - } - - return bucketingId; -}; - -/** - * Removes forced variation for given userId and experimentKey - * @param {string} userId String representing the user id - * @param {number} experimentId Number representing the experiment id - * @param {string} experimentKey Key representing the experiment id - * @throws If the user id is not valid or not in the forced variation map - */ -DecisionService.prototype.removeForcedVariation = function(userId, experimentId, experimentKey) { - if (!userId) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_ID, MODULE_NAME)); - } - - if (this.forcedVariationMap.hasOwnProperty(userId)) { - delete this.forcedVariationMap[userId][experimentId]; - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.VARIATION_REMOVED_FOR_USER, MODULE_NAME, experimentKey, userId) - ); - } else { - throw new Error(sprintf(ERROR_MESSAGES.USER_NOT_IN_FORCED_VARIATION, MODULE_NAME, userId)); - } -}; - -/** - * Sets forced variation for given userId and experimentKey - * @param {string} userId String representing the user id - * @param {number} experimentId Number representing the experiment id - * @param {number} variationId Number representing the variation id - * @throws If the user id is not valid - */ -DecisionService.prototype.__setInForcedVariationMap = function(userId, experimentId, variationId) { - if (this.forcedVariationMap.hasOwnProperty(userId)) { - this.forcedVariationMap[userId][experimentId] = variationId; - } else { - this.forcedVariationMap[userId] = {}; - this.forcedVariationMap[userId][experimentId] = variationId; - } - - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_MAPPED_TO_FORCED_VARIATION, MODULE_NAME, variationId, experimentId, userId) - ); -}; - -/** - * Gets the forced variation key for the given user and experiment. - * @param {Object} configObj Object representing project configuration - * @param {string} experimentKey Key for experiment. - * @param {string} userId The user Id. - * @return {string|null} Variation The variation which the given user and experiment should be forced into. - */ -DecisionService.prototype.getForcedVariation = function(configObj, experimentKey, userId) { - var experimentToVariationMap = this.forcedVariationMap[userId]; - if (!experimentToVariationMap) { - this.logger.log(LOG_LEVEL.DEBUG, sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION, MODULE_NAME, userId)); - return null; - } - - var experimentId; - try { - var experiment = projectConfig.getExperimentFromKey(configObj, experimentKey); - if (experiment.hasOwnProperty('id')) { - experimentId = experiment['id']; - } else { - // catching improperly formatted experiments - this.logger.log( - LOG_LEVEL.ERROR, - sprintf(ERROR_MESSAGES.IMPROPERLY_FORMATTED_EXPERIMENT, MODULE_NAME, experimentKey) - ); - return null; - } - } catch (ex) { - // catching experiment not in datafile - this.logger.log(LOG_LEVEL.ERROR, ex.message); - return null; - } - - var variationId = experimentToVariationMap[experimentId]; - if (!variationId) { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, MODULE_NAME, experimentKey, userId) - ); - return null; - } - - var variationKey = projectConfig.getVariationKeyFromId(configObj, variationId); - if (variationKey) { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_HAS_FORCED_VARIATION, MODULE_NAME, variationKey, experimentKey, userId) - ); - } else { - this.logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_HAS_NO_FORCED_VARIATION_FOR_EXPERIMENT, MODULE_NAME, experimentKey, userId) - ); - } - - return variationKey; -}; - -/** - * Sets the forced variation for a user in a given experiment - * @param {Object} configObj Object representing project configuration - * @param {string} experimentKey Key for experiment. - * @param {string} userId The user Id. - * @param {string} variationKey Key for variation. If null, then clear the existing experiment-to-variation mapping - * @return {boolean} A boolean value that indicates if the set completed successfully. - */ -DecisionService.prototype.setForcedVariation = function(configObj, experimentKey, userId, variationKey) { - if (variationKey != null && !stringValidator.validate(variationKey)) { - this.logger.log(LOG_LEVEL.ERROR, sprintf(ERROR_MESSAGES.INVALID_VARIATION_KEY, MODULE_NAME)); - return false; - } - - var experimentId; - try { - var experiment = projectConfig.getExperimentFromKey(configObj, experimentKey); - if (experiment.hasOwnProperty('id')) { - experimentId = experiment['id']; - } else { - // catching improperly formatted experiments - this.logger.log( - LOG_LEVEL.ERROR, - sprintf(ERROR_MESSAGES.IMPROPERLY_FORMATTED_EXPERIMENT, MODULE_NAME, experimentKey) - ); - return false; - } - } catch (ex) { - // catching experiment not in datafile - this.logger.log(LOG_LEVEL.ERROR, ex.message); - return false; - } - - if (variationKey == null) { - try { - this.removeForcedVariation(userId, experimentId, experimentKey, this.logger); - return true; - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - return false; - } - } - - var variationId = projectConfig.getVariationIdFromExperimentAndVariationKey(configObj, experimentKey, variationKey); - - if (!variationId) { - this.logger.log( - LOG_LEVEL.ERROR, - sprintf(ERROR_MESSAGES.NO_VARIATION_FOR_EXPERIMENT_KEY, MODULE_NAME, variationKey, experimentKey) - ); - return false; - } - - try { - this.__setInForcedVariationMap(userId, experimentId, variationId); - return true; - } catch (ex) { - this.logger.log(LOG_LEVEL.ERROR, ex.message); - return false; - } -}; - -module.exports = { - /** - * Creates an instance of the DecisionService. - * @param {Object} options Configuration options - * @param {Object} options.userProfileService - * @param {Object} options.logger - * @return {Object} An instance of the DecisionService - */ - createDecisionService: function(options) { - return new DecisionService(options); - }, -}; - - -/***/ }), -/* 30 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016, 2018-2019 Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 conditionTreeEvaluator = __webpack_require__(31); -var customAttributeConditionEvaluator = __webpack_require__(32); -var enums = __webpack_require__(14); -var fns = __webpack_require__(11); -var sprintf = __webpack_require__(12).sprintf; -var logging = __webpack_require__(1); -var logger = logging.getLogger(); - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var MODULE_NAME = 'AUDIENCE_EVALUATOR'; - -/** - * Construct an instance of AudienceEvaluator with given options - * @param {Object=} UNSTABLE_conditionEvaluators A map of condition evaluators provided by the consumer. This enables matching - * condition types which are not supported natively by the SDK. Note that built in - * Optimizely evaluators cannot be overridden. - * @constructor - */ -function AudienceEvaluator(UNSTABLE_conditionEvaluators) { - this.typeToEvaluatorMap = fns.assign({}, UNSTABLE_conditionEvaluators, { - custom_attribute: customAttributeConditionEvaluator, - }); -} - -/** - * Determine if the given user attributes satisfy the given audience conditions - * @param {Array|String|null|undefined} audienceConditions Audience conditions to match the user attributes against - can be an array - * of audience IDs, a nested array of conditions, or a single leaf condition. - * Examples: ["5", "6"], ["and", ["or", "1", "2"], "3"], "1" - * @param {Object} audiencesById Object providing access to full audience objects for audience IDs - * contained in audienceConditions. Keys should be audience IDs, values - * should be full audience objects with conditions properties - * @param {Object} [userAttributes] User attributes which will be used in determining if audience conditions - * are met. If not provided, defaults to an empty object - * @return {Boolean} true if the user attributes match the given audience conditions, false - * otherwise - */ -AudienceEvaluator.prototype.evaluate = function(audienceConditions, audiencesById, userAttributes) { - // if there are no audiences, return true because that means ALL users are included in the experiment - if (!audienceConditions || audienceConditions.length === 0) { - return true; - } - - if (!userAttributes) { - userAttributes = {}; - } - - var evaluateAudience = function(audienceId) { - var audience = audiencesById[audienceId]; - if (audience) { - logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.EVALUATING_AUDIENCE, MODULE_NAME, audienceId, JSON.stringify(audience.conditions)) - ); - var result = conditionTreeEvaluator.evaluate( - audience.conditions, - this.evaluateConditionWithUserAttributes.bind(this, userAttributes) - ); - var resultText = result === null ? 'UNKNOWN' : result.toString().toUpperCase(); - logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.AUDIENCE_EVALUATION_RESULT, MODULE_NAME, audienceId, resultText)); - return result; - } - - return null; - }.bind(this); - - return conditionTreeEvaluator.evaluate(audienceConditions, evaluateAudience) || false; -}; - -/** - * Wrapper around evaluator.evaluate that is passed to the conditionTreeEvaluator. - * Evaluates the condition provided given the user attributes if an evaluator has been defined for the condition type. - * @param {Object} userAttributes A map of user attributes. - * @param {Object} condition A single condition object to evaluate. - * @return {Boolean|null} true if the condition is satisfied, null if a matcher is not found. - */ -AudienceEvaluator.prototype.evaluateConditionWithUserAttributes = function(userAttributes, condition) { - var evaluator = this.typeToEvaluatorMap[condition.type]; - if (!evaluator) { - logger.log(LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.UNKNOWN_CONDITION_TYPE, MODULE_NAME, JSON.stringify(condition))); - return null; - } - try { - return evaluator.evaluate(condition, userAttributes, logger); - } catch (err) { - logger.log( - LOG_LEVEL.ERROR, - sprintf(ERROR_MESSAGES.CONDITION_EVALUATOR_ERROR, MODULE_NAME, condition.type, err.message) - ); - } - return null; -}; - -module.exports = AudienceEvaluator; - - -/***/ }), -/* 31 */ -/***/ (function(module, exports) { - -/**************************************************************************** - * Copyright 2018, Optimizely, Inc. and contributors * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License 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 AND_CONDITION = 'and'; -var OR_CONDITION = 'or'; -var NOT_CONDITION = 'not'; - -var DEFAULT_OPERATOR_TYPES = [AND_CONDITION, OR_CONDITION, NOT_CONDITION]; - -/** - * Top level method to evaluate conditions - * @param {Array|*} conditions Nested array of and/or conditions, or a single leaf - * condition value of any type - * Example: ['and', '0', ['or', '1', '2']] - * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition - * values - * @return {?Boolean} Result of evaluating the conditions using the operator - * rules and the leaf evaluator. A return value of null - * indicates that the conditions are invalid or unable to be - * evaluated - */ -function evaluate(conditions, leafEvaluator) { - if (Array.isArray(conditions)) { - var firstOperator = conditions[0]; - var restOfConditions = conditions.slice(1); - - if (DEFAULT_OPERATOR_TYPES.indexOf(firstOperator) === -1) { - // Operator to apply is not explicit - assume 'or' - firstOperator = OR_CONDITION; - restOfConditions = conditions; - } - - switch (firstOperator) { - case AND_CONDITION: - return andEvaluator(restOfConditions, leafEvaluator); - case NOT_CONDITION: - return notEvaluator(restOfConditions, leafEvaluator); - default: - // firstOperator is OR_CONDITION - return orEvaluator(restOfConditions, leafEvaluator); - } - } - - var leafCondition = conditions; - return leafEvaluator(leafCondition); -} - -/** - * Evaluates an array of conditions as if the evaluator had been applied - * to each entry and the results AND-ed together. - * @param {Array} conditions Array of conditions ex: [operand_1, operand_2] - * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition values - * @return {?Boolean} Result of evaluating the conditions. A return value of null - * indicates that the conditions are invalid or unable to be - * evaluated. - */ -function andEvaluator(conditions, leafEvaluator) { - var sawNullResult = false; - for (var i = 0; i < conditions.length; i++) { - var conditionResult = evaluate(conditions[i], leafEvaluator); - if (conditionResult === false) { - return false; - } - if (conditionResult === null) { - sawNullResult = true; - } - } - return sawNullResult ? null : true; -} - -/** - * Evaluates an array of conditions as if the evaluator had been applied - * to a single entry and NOT was applied to the result. - * @param {Array} conditions Array of conditions ex: [operand_1] - * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition values - * @return {?Boolean} Result of evaluating the conditions. A return value of null - * indicates that the conditions are invalid or unable to be - * evaluated. - */ -function notEvaluator(conditions, leafEvaluator) { - if (conditions.length > 0) { - var result = evaluate(conditions[0], leafEvaluator); - return result === null ? null : !result; - } - return null; -} - -/** - * Evaluates an array of conditions as if the evaluator had been applied - * to each entry and the results OR-ed together. - * @param {Array} conditions Array of conditions ex: [operand_1, operand_2] - * @param {Function} leafEvaluator Function which will be called to evaluate leaf condition values - * @return {?Boolean} Result of evaluating the conditions. A return value of null - * indicates that the conditions are invalid or unable to be - * evaluated. - */ -function orEvaluator(conditions, leafEvaluator) { - var sawNullResult = false; - for (var i = 0; i < conditions.length; i++) { - var conditionResult = evaluate(conditions[i], leafEvaluator); - if (conditionResult === true) { - return true; - } - if (conditionResult === null) { - sawNullResult = true; - } - } - return sawNullResult ? null : false; -} - -module.exports = { - evaluate: evaluate, -}; - - -/***/ }), -/* 32 */ -/***/ (function(module, exports, __webpack_require__) { - -/**************************************************************************** - * Copyright 2018-2019, Optimizely, Inc. and contributors * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License 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 fns = __webpack_require__(11); -var enums = __webpack_require__(14); -var sprintf = __webpack_require__(12).sprintf; - -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var MODULE_NAME = 'CUSTOM_ATTRIBUTE_CONDITION_EVALUATOR'; - -var EXACT_MATCH_TYPE = 'exact'; -var EXISTS_MATCH_TYPE = 'exists'; -var GREATER_THAN_MATCH_TYPE = 'gt'; -var LESS_THAN_MATCH_TYPE = 'lt'; -var SUBSTRING_MATCH_TYPE = 'substring'; - -var MATCH_TYPES = [ - EXACT_MATCH_TYPE, - EXISTS_MATCH_TYPE, - GREATER_THAN_MATCH_TYPE, - LESS_THAN_MATCH_TYPE, - SUBSTRING_MATCH_TYPE, -]; - -var EVALUATORS_BY_MATCH_TYPE = {}; -EVALUATORS_BY_MATCH_TYPE[EXACT_MATCH_TYPE] = exactEvaluator; -EVALUATORS_BY_MATCH_TYPE[EXISTS_MATCH_TYPE] = existsEvaluator; -EVALUATORS_BY_MATCH_TYPE[GREATER_THAN_MATCH_TYPE] = greaterThanEvaluator; -EVALUATORS_BY_MATCH_TYPE[LESS_THAN_MATCH_TYPE] = lessThanEvaluator; -EVALUATORS_BY_MATCH_TYPE[SUBSTRING_MATCH_TYPE] = substringEvaluator; - -/** - * Given a custom attribute audience condition and user attributes, evaluate the - * condition against the attributes. - * @param {Object} condition - * @param {Object} userAttributes - * @param {Object} logger - * @return {?Boolean} true/false if the given user attributes match/don't match the given condition, - * null if the given user attributes and condition can't be evaluated - * TODO: Change to accept and object with named properties - */ -function evaluate(condition, userAttributes, logger) { - var conditionMatch = condition.match; - if (typeof conditionMatch !== 'undefined' && MATCH_TYPES.indexOf(conditionMatch) === -1) { - logger.log(LOG_LEVEL.WARNING, sprintf(LOG_MESSAGES.UNKNOWN_MATCH_TYPE, MODULE_NAME, JSON.stringify(condition))); - return null; - } - - var attributeKey = condition.name; - if (!userAttributes.hasOwnProperty(attributeKey) && conditionMatch != EXISTS_MATCH_TYPE) { - logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.MISSING_ATTRIBUTE_VALUE, MODULE_NAME, JSON.stringify(condition), attributeKey) - ); - return null; - } - - var evaluatorForMatch = EVALUATORS_BY_MATCH_TYPE[conditionMatch] || exactEvaluator; - return evaluatorForMatch(condition, userAttributes, logger); -} - -/** - * Returns true if the value is valid for exact conditions. Valid values include - * strings, booleans, and numbers that aren't NaN, -Infinity, or Infinity. - * @param value - * @returns {Boolean} - */ -function isValueTypeValidForExactConditions(value) { - return typeof value === 'string' || typeof value === 'boolean' || fns.isNumber(value); -} - -/** - * Evaluate the given exact match condition for the given user attributes - * @param {Object} condition - * @param {Object} userAttributes - * @param {Object} logger - * @return {?Boolean} true if the user attribute value is equal (===) to the condition value, - * false if the user attribute value is not equal (!==) to the condition value, - * null if the condition value or user attribute value has an invalid type, or - * if there is a mismatch between the user attribute type and the condition value - * type - */ -function exactEvaluator(condition, userAttributes, logger) { - var conditionValue = condition.value; - var conditionValueType = typeof conditionValue; - var conditionName = condition.name; - var userValue = userAttributes[conditionName]; - var userValueType = typeof userValue; - - if ( - !isValueTypeValidForExactConditions(conditionValue) || - (fns.isNumber(conditionValue) && !fns.isSafeInteger(conditionValue)) - ) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) - ); - return null; - } - - if (userValue === null) { - logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) - ); - return null; - } - - if (!isValueTypeValidForExactConditions(userValue) || conditionValueType !== userValueType) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) - ); - return null; - } - - if (fns.isNumber(userValue) && !fns.isSafeInteger(userValue)) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName) - ); - return null; - } - - return conditionValue === userValue; -} - -/** - * Evaluate the given exists match condition for the given user attributes - * @param {Object} condition - * @param {Object} userAttributes - * @returns {Boolean} true if both: - * 1) the user attributes have a value for the given condition, and - * 2) the user attribute value is neither null nor undefined - * Returns false otherwise - */ -function existsEvaluator(condition, userAttributes) { - var userValue = userAttributes[condition.name]; - return typeof userValue !== 'undefined' && userValue !== null; -} - -/** - * Evaluate the given greater than match condition for the given user attributes - * @param {Object} condition - * @param {Object} userAttributes - * @param {Object} logger - * @returns {?Boolean} true if the user attribute value is greater than the condition value, - * false if the user attribute value is less than or equal to the condition value, - * null if the condition value isn't a number or the user attribute value - * isn't a number - */ -function greaterThanEvaluator(condition, userAttributes, logger) { - var conditionName = condition.name; - var userValue = userAttributes[conditionName]; - var userValueType = typeof userValue; - var conditionValue = condition.value; - - if (!fns.isSafeInteger(conditionValue)) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) - ); - return null; - } - - if (userValue === null) { - logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) - ); - return null; - } - - if (!fns.isNumber(userValue)) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) - ); - return null; - } - - if (!fns.isSafeInteger(userValue)) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName) - ); - return null; - } - - return userValue > conditionValue; -} - -/** - * Evaluate the given less than match condition for the given user attributes - * @param {Object} condition - * @param {Object} userAttributes - * @param {Object} logger - * @returns {?Boolean} true if the user attribute value is less than the condition value, - * false if the user attribute value is greater than or equal to the condition value, - * null if the condition value isn't a number or the user attribute value isn't a - * number - */ -function lessThanEvaluator(condition, userAttributes, logger) { - var conditionName = condition.name; - var userValue = userAttributes[condition.name]; - var userValueType = typeof userValue; - var conditionValue = condition.value; - - if (!fns.isSafeInteger(conditionValue)) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) - ); - return null; - } - - if (userValue === null) { - logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) - ); - return null; - } - - if (!fns.isNumber(userValue)) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) - ); - return null; - } - - if (!fns.isSafeInteger(userValue)) { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.OUT_OF_BOUNDS, MODULE_NAME, JSON.stringify(condition), conditionName) - ); - return null; - } - - return userValue < conditionValue; -} - -/** - * Evaluate the given substring match condition for the given user attributes - * @param {Object} condition - * @param {Object} userAttributes - * @param {Object} logger - * @returns {?Boolean} true if the condition value is a substring of the user attribute value, - * false if the condition value is not a substring of the user attribute value, - * null if the condition value isn't a string or the user attribute value - * isn't a string - */ -function substringEvaluator(condition, userAttributes, logger) { - var conditionName = condition.name; - var userValue = userAttributes[condition.name]; - var userValueType = typeof userValue; - var conditionValue = condition.value; - - if (typeof conditionValue !== 'string') { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_CONDITION_VALUE, MODULE_NAME, JSON.stringify(condition)) - ); - return null; - } - - if (userValue === null) { - logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE_NULL, MODULE_NAME, JSON.stringify(condition), conditionName) - ); - return null; - } - - if (typeof userValue !== 'string') { - logger.log( - LOG_LEVEL.WARNING, - sprintf(LOG_MESSAGES.UNEXPECTED_TYPE, MODULE_NAME, JSON.stringify(condition), userValueType, conditionName) - ); - return null; - } - - return userValue.indexOf(conditionValue) !== -1; -} - -module.exports = { - evaluate: evaluate, -}; - - -/***/ }), -/* 33 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016, 2019 Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ - -/** - * Bucketer API for determining the variation id from the specified parameters - */ -var enums = __webpack_require__(14); -var murmurhash = __webpack_require__(34); -var sprintf = __webpack_require__(12).sprintf; - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var HASH_SEED = 1; -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var MAX_HASH_VALUE = Math.pow(2, 32); -var MAX_TRAFFIC_VALUE = 10000; -var MODULE_NAME = 'BUCKETER'; -var RANDOM_POLICY = 'random'; - -module.exports = { - /** - * Determines ID of variation to be shown for the given input params - * @param {Object} bucketerParams - * @param {string} bucketerParams.experimentId - * @param {string} bucketerParams.experimentKey - * @param {string} bucketerParams.userId - * @param {Object[]} bucketerParams.trafficAllocationConfig - * @param {Array} bucketerParams.experimentKeyMap - * @param {Object} bucketerParams.groupIdMap - * @param {Object} bucketerParams.variationIdMap - * @param {string} bucketerParams.varationIdMap[].key - * @param {Object} bucketerParams.logger - * @param {string} bucketerParams.bucketingId - * @return Variation ID that user has been bucketed into, null if user is not bucketed into any experiment - */ - bucket: function(bucketerParams) { - // Check if user is in a random group; if so, check if user is bucketed into a specific experiment - var experiment = bucketerParams.experimentKeyMap[bucketerParams.experimentKey]; - var groupId = experiment['groupId']; - if (groupId) { - var group = bucketerParams.groupIdMap[groupId]; - if (!group) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_GROUP_ID, MODULE_NAME, groupId)); - } - if (group.policy === RANDOM_POLICY) { - var bucketedExperimentId = module.exports.bucketUserIntoExperiment( - group, - bucketerParams.bucketingId, - bucketerParams.userId, - bucketerParams.logger - ); - - // Return if user is not bucketed into any experiment - if (bucketedExperimentId === null) { - var notbucketedInAnyExperimentLogMessage = sprintf( - LOG_MESSAGES.USER_NOT_IN_ANY_EXPERIMENT, - MODULE_NAME, - bucketerParams.userId, - groupId - ); - bucketerParams.logger.log(LOG_LEVEL.INFO, notbucketedInAnyExperimentLogMessage); - return null; - } - - // Return if user is bucketed into a different experiment than the one specified - if (bucketedExperimentId !== bucketerParams.experimentId) { - var notBucketedIntoExperimentOfGroupLogMessage = sprintf( - LOG_MESSAGES.USER_NOT_BUCKETED_INTO_EXPERIMENT_IN_GROUP, - MODULE_NAME, - bucketerParams.userId, - bucketerParams.experimentKey, - groupId - ); - bucketerParams.logger.log(LOG_LEVEL.INFO, notBucketedIntoExperimentOfGroupLogMessage); - return null; - } - - // Continue bucketing if user is bucketed into specified experiment - var bucketedIntoExperimentOfGroupLogMessage = sprintf( - LOG_MESSAGES.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP, - MODULE_NAME, - bucketerParams.userId, - bucketerParams.experimentKey, - groupId - ); - bucketerParams.logger.log(LOG_LEVEL.INFO, bucketedIntoExperimentOfGroupLogMessage); - } - } - var bucketingId = sprintf('%s%s', bucketerParams.bucketingId, bucketerParams.experimentId); - var bucketValue = module.exports._generateBucketValue(bucketingId); - - var bucketedUserLogMessage = sprintf( - LOG_MESSAGES.USER_ASSIGNED_TO_VARIATION_BUCKET, - MODULE_NAME, - bucketValue, - bucketerParams.userId - ); - bucketerParams.logger.log(LOG_LEVEL.DEBUG, bucketedUserLogMessage); - - var entityId = module.exports._findBucket(bucketValue, bucketerParams.trafficAllocationConfig); - if (!entityId) { - var userHasNoVariationLogMessage = sprintf( - LOG_MESSAGES.USER_HAS_NO_VARIATION, - MODULE_NAME, - bucketerParams.userId, - bucketerParams.experimentKey - ); - bucketerParams.logger.log(LOG_LEVEL.DEBUG, userHasNoVariationLogMessage); - } else if (!bucketerParams.variationIdMap.hasOwnProperty(entityId)) { - var invalidVariationIdLogMessage = sprintf(LOG_MESSAGES.INVALID_VARIATION_ID, MODULE_NAME); - bucketerParams.logger.log(LOG_LEVEL.WARNING, invalidVariationIdLogMessage); - return null; - } else { - var variationKey = bucketerParams.variationIdMap[entityId].key; - var userInVariationLogMessage = sprintf( - LOG_MESSAGES.USER_HAS_VARIATION, - MODULE_NAME, - bucketerParams.userId, - variationKey, - bucketerParams.experimentKey - ); - bucketerParams.logger.log(LOG_LEVEL.INFO, userInVariationLogMessage); - } - - return entityId; - }, - - /** - * Returns bucketed experiment ID to compare against experiment user is being called into - * @param {Object} group Group that experiment is in - * @param {string} bucketingId Bucketing ID - * @param {string} userId ID of user to be bucketed into experiment - * @param {Object} logger Logger implementation - * @return {string} ID of experiment if user is bucketed into experiment within the group, null otherwise - */ - bucketUserIntoExperiment: function(group, bucketingId, userId, logger) { - var bucketingKey = sprintf('%s%s', bucketingId, group.id); - var bucketValue = module.exports._generateBucketValue(bucketingKey); - logger.log( - LOG_LEVEL.DEBUG, - sprintf(LOG_MESSAGES.USER_ASSIGNED_TO_EXPERIMENT_BUCKET, MODULE_NAME, bucketValue, userId) - ); - var trafficAllocationConfig = group.trafficAllocation; - var bucketedExperimentId = module.exports._findBucket(bucketValue, trafficAllocationConfig); - return bucketedExperimentId; - }, - - /** - * Returns entity ID associated with bucket value - * @param {string} bucketValue - * @param {Object[]} trafficAllocationConfig - * @param {number} trafficAllocationConfig[].endOfRange - * @param {number} trafficAllocationConfig[].entityId - * @return {string} Entity ID for bucketing if bucket value is within traffic allocation boundaries, null otherwise - */ - _findBucket: function(bucketValue, trafficAllocationConfig) { - for (var i = 0; i < trafficAllocationConfig.length; i++) { - if (bucketValue < trafficAllocationConfig[i].endOfRange) { - return trafficAllocationConfig[i].entityId; - } - } - return null; - }, - - /** - * Helper function to generate bucket value in half-closed interval [0, MAX_TRAFFIC_VALUE) - * @param {string} bucketingKey String value for bucketing - * @return {string} the generated bucket value - * @throws If bucketing value is not a valid string - */ - _generateBucketValue: function(bucketingKey) { - try { - // NOTE: the mmh library already does cast the hash value as an unsigned 32bit int - // https://github.com/perezd/node-murmurhash/blob/master/murmurhash.js#L115 - var hashValue = murmurhash.v3(bucketingKey, HASH_SEED); - var ratio = hashValue / MAX_HASH_VALUE; - return parseInt(ratio * MAX_TRAFFIC_VALUE, 10); - } catch (ex) { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_BUCKETING_ID, MODULE_NAME, bucketingKey, ex.message)); - } - }, -}; - - -/***/ }), -/* 34 */ -/***/ (function(module, exports, __webpack_require__) { - -(function(){ - var _global = this; - - /** - * JS Implementation of MurmurHash2 - * - * @author Gary Court - * @see http://github.com/garycourt/murmurhash-js - * @author Austin Appleby - * @see http://sites.google.com/site/murmurhash/ - * - * @param {string} str ASCII only - * @param {number} seed Positive integer only - * @return {number} 32-bit positive integer hash - */ - function MurmurHashV2(str, seed) { - var - l = str.length, - h = seed ^ l, - i = 0, - k; - - while (l >= 4) { - k = - ((str.charCodeAt(i) & 0xff)) | - ((str.charCodeAt(++i) & 0xff) << 8) | - ((str.charCodeAt(++i) & 0xff) << 16) | - ((str.charCodeAt(++i) & 0xff) << 24); - - k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - k ^= k >>> 24; - k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k; - - l -= 4; - ++i; - } - - switch (l) { - case 3: h ^= (str.charCodeAt(i + 2) & 0xff) << 16; - case 2: h ^= (str.charCodeAt(i + 1) & 0xff) << 8; - case 1: h ^= (str.charCodeAt(i) & 0xff); - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - } - - h ^= h >>> 13; - h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); - h ^= h >>> 15; - - return h >>> 0; - }; - - /** - * JS Implementation of MurmurHash3 (r136) (as of May 20, 2011) - * - * @author Gary Court - * @see http://github.com/garycourt/murmurhash-js - * @author Austin Appleby - * @see http://sites.google.com/site/murmurhash/ - * - * @param {string} key ASCII only - * @param {number} seed Positive integer only - * @return {number} 32-bit positive integer hash - */ - function MurmurHashV3(key, seed) { - var remainder, bytes, h1, h1b, c1, c1b, c2, c2b, k1, i; - - remainder = key.length & 3; // key.length % 4 - bytes = key.length - remainder; - h1 = seed; - c1 = 0xcc9e2d51; - c2 = 0x1b873593; - i = 0; - - while (i < bytes) { - k1 = - ((key.charCodeAt(i) & 0xff)) | - ((key.charCodeAt(++i) & 0xff) << 8) | - ((key.charCodeAt(++i) & 0xff) << 16) | - ((key.charCodeAt(++i) & 0xff) << 24); - ++i; - - k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; - k1 = (k1 << 15) | (k1 >>> 17); - k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; - - h1 ^= k1; - h1 = (h1 << 13) | (h1 >>> 19); - h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; - h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); - } - - k1 = 0; - - switch (remainder) { - case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; - case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; - case 1: k1 ^= (key.charCodeAt(i) & 0xff); - - k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; - k1 = (k1 << 15) | (k1 >>> 17); - k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; - h1 ^= k1; - } - - h1 ^= key.length; - - h1 ^= h1 >>> 16; - h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; - h1 ^= h1 >>> 13; - h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; - h1 ^= h1 >>> 16; - - return h1 >>> 0; - } - - var murmur = MurmurHashV3; - murmur.v2 = MurmurHashV2; - murmur.v3 = MurmurHashV3; - - if (true) { - module.exports = murmur; - } else { var _previousRoot; } -}()); - - -/***/ }), -/* 35 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016-2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 fns = __webpack_require__(11); -var enums = __webpack_require__(14); -var jsSdkUtils = __webpack_require__(12); -var configValidator = __webpack_require__(13); -var projectConfigSchema = __webpack_require__(36); - -var EXPERIMENT_RUNNING_STATUS = 'Running'; -var RESERVED_ATTRIBUTE_PREFIX = '$opt_'; -var MODULE_NAME = 'PROJECT_CONFIG'; - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var LOG_LEVEL = enums.LOG_LEVEL; -var FEATURE_VARIABLE_TYPES = enums.FEATURE_VARIABLE_TYPES; - -module.exports = { - /** - * Creates projectConfig object to be used for quick project property lookup - * @param {Object} datafile JSON datafile representing the project - * @return {Object} Object representing project configuration - */ - createProjectConfig: function(datafile) { - var projectConfig = fns.assign({}, datafile); - - /* - * Conditions of audiences in projectConfig.typedAudiences are not - * expected to be string-encoded as they are here in projectConfig.audiences. - */ - (projectConfig.audiences || []).forEach(function(audience) { - audience.conditions = JSON.parse(audience.conditions); - }); - projectConfig.audiencesById = fns.keyBy(projectConfig.audiences, 'id'); - fns.assign(projectConfig.audiencesById, fns.keyBy(projectConfig.typedAudiences, 'id')); - - projectConfig.attributeKeyMap = fns.keyBy(projectConfig.attributes, 'key'); - projectConfig.eventKeyMap = fns.keyBy(projectConfig.events, 'key'); - projectConfig.groupIdMap = fns.keyBy(projectConfig.groups, 'id'); - - var experiments; - Object.keys(projectConfig.groupIdMap || {}).forEach(function(Id) { - experiments = projectConfig.groupIdMap[Id].experiments; - (experiments || []).forEach(function(experiment) { - projectConfig.experiments.push(fns.assign(experiment, { groupId: Id })); - }); - }); - - projectConfig.rolloutIdMap = fns.keyBy(projectConfig.rollouts || [], 'id'); - jsSdkUtils.objectValues(projectConfig.rolloutIdMap || {}).forEach(function (rollout) { - (rollout.experiments || []).forEach(function(experiment) { - projectConfig.experiments.push(experiment); - // Creates { : } map inside of the experiment - experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); - }); - }); - - projectConfig.experimentKeyMap = fns.keyBy(projectConfig.experiments, 'key'); - projectConfig.experimentIdMap = fns.keyBy(projectConfig.experiments, 'id'); - - projectConfig.variationIdMap = {}; - projectConfig.variationVariableUsageMap = {}; - (projectConfig.experiments || []).forEach(function(experiment) { - // Creates { : } map inside of the experiment - experiment.variationKeyMap = fns.keyBy(experiment.variations, 'key'); - - // Creates { : { key: , id: } } mapping for quick lookup - fns.assign(projectConfig.variationIdMap, fns.keyBy(experiment.variations, 'id')); - jsSdkUtils.objectValues(experiment.variationKeyMap || {}).forEach(function(variation) { - if (variation.variables) { - projectConfig.variationVariableUsageMap[variation.id] = fns.keyBy(variation.variables, 'id'); - } - }); - }); - - // Object containing experiment Ids that exist in any feature - // for checking that experiment is a feature experiment or not. - projectConfig.experimentFeatureMap = {}; - - projectConfig.featureKeyMap = fns.keyBy(projectConfig.featureFlags || [], 'key'); - jsSdkUtils.objectValues(projectConfig.featureKeyMap || {}).forEach(function(feature) { - feature.variableKeyMap = fns.keyBy(feature.variables, 'key'); - (feature.experimentIds || []).forEach(function(experimentId) { - // Add this experiment in experiment-feature map. - if (projectConfig.experimentFeatureMap[experimentId]) { - projectConfig.experimentFeatureMap[experimentId].push(feature.id); - } else { - projectConfig.experimentFeatureMap[experimentId] = [feature.id]; - } - - var experimentInFeature = projectConfig.experimentIdMap[experimentId]; - // Experiments in feature can only belong to one mutex group. - if (experimentInFeature.groupId && !feature.groupId) { - feature.groupId = experimentInFeature.groupId; - } - }); - }); - - return projectConfig; - }, - - /** - * Get experiment ID for the provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which ID is to be determined - * @return {string} Experiment ID corresponding to the provided experiment key - * @throws If experiment key is not in datafile - */ - getExperimentId: function(projectConfig, experimentKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); - } - return experiment.id; - }, - - /** - * Get layer ID for the provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentId Experiment ID for which layer ID is to be determined - * @return {string} Layer ID corresponding to the provided experiment key - * @throws If experiment key is not in datafile - */ - getLayerId: function(projectConfig, experimentId) { - var experiment = projectConfig.experimentIdMap[experimentId]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); - } - return experiment.layerId; - }, - - /** - * Get attribute ID for the provided attribute key - * @param {Object} projectConfig Object representing project configuration - * @param {string} attributeKey Attribute key for which ID is to be determined - * @param {Object} logger - * @return {string|null} Attribute ID corresponding to the provided attribute key. Attribute key if it is a reserved attribute. - */ - getAttributeId: function(projectConfig, attributeKey, logger) { - var attribute = projectConfig.attributeKeyMap[attributeKey]; - var hasReservedPrefix = attributeKey.indexOf(RESERVED_ATTRIBUTE_PREFIX) === 0; - if (attribute) { - if (hasReservedPrefix) { - logger.log( - LOG_LEVEL.WARN, - jsSdkUtils.sprintf( - 'Attribute %s unexpectedly has reserved prefix %s; using attribute ID instead of reserved attribute name.', - attributeKey, - RESERVED_ATTRIBUTE_PREFIX - ) - ); - } - return attribute.id; - } else if (hasReservedPrefix) { - return attributeKey; - } - - logger.log(LOG_LEVEL.DEBUG, jsSdkUtils.sprintf(ERROR_MESSAGES.UNRECOGNIZED_ATTRIBUTE, MODULE_NAME, attributeKey)); - return null; - }, - - /** - * Get event ID for the provided - * @param {Object} projectConfig Object representing project configuration - * @param {string} eventKey Event key for which ID is to be determined - * @return {string|null} Event ID corresponding to the provided event key - */ - getEventId: function(projectConfig, eventKey) { - var event = projectConfig.eventKeyMap[eventKey]; - if (event) { - return event.id; - } - return null; - }, - - /** - * Get experiment status for the provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which status is to be determined - * @return {string} Experiment status corresponding to the provided experiment key - * @throws If experiment key is not in datafile - */ - getExperimentStatus: function(projectConfig, experimentKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); - } - return experiment.status; - }, - - /** - * Returns whether experiment has a status of 'Running' - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which status is to be compared with 'Running' - * @return {Boolean} true if experiment status is set to 'Running', false otherwise - */ - isActive: function(projectConfig, experimentKey) { - return module.exports.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; - }, - - /** - * Determine for given experiment if event is running, which determines whether should be dispatched or not - */ - isRunning: function(projectConfig, experimentKey) { - return module.exports.getExperimentStatus(projectConfig, experimentKey) === EXPERIMENT_RUNNING_STATUS; - }, - - /** - * Get audience conditions for the experiment - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Experiment key for which audience conditions are to be determined - * @return {Array} Audience conditions for the experiment - can be an array of audience IDs, or a - * nested array of conditions - * Examples: ["5", "6"], ["and", ["or", "1", "2"], "3"] - * @throws If experiment key is not in datafile - */ - getExperimentAudienceConditions: function(projectConfig, experimentKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); - } - - return experiment.audienceConditions || experiment.audienceIds; - }, - - /** - * Get variation key given experiment key and variation ID - * @param {Object} projectConfig Object representing project configuration - * @param {string} variationId ID of the variation - * @return {string} Variation key or null if the variation ID is not found - */ - getVariationKeyFromId: function(projectConfig, variationId) { - if (projectConfig.variationIdMap.hasOwnProperty(variationId)) { - return projectConfig.variationIdMap[variationId].key; - } - return null; - }, - - /** - * Get the variation ID given the experiment key and variation key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Key of the experiment the variation belongs to - * @param {string} variationKey The variation key - * @return {string} the variation ID - */ - getVariationIdFromExperimentAndVariationKey: function(projectConfig, experimentKey, variationKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (experiment.variationKeyMap.hasOwnProperty(variationKey)) { - return experiment.variationKeyMap[variationKey].id; - } - return null; - }, - - /** - * Get experiment from provided experiment key - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Event key for which experiment IDs are to be retrieved - * @return {Object} experiment - * @throws If experiment key is not in datafile - */ - getExperimentFromKey: function(projectConfig, experimentKey) { - if (projectConfig.experimentKeyMap.hasOwnProperty(experimentKey)) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (experiment) { - return experiment; - } - } - - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.EXPERIMENT_KEY_NOT_IN_DATAFILE, MODULE_NAME, experimentKey)); - }, - - /** - * Given an experiment key, returns the traffic allocation within that experiment - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentKey Key representing the experiment - * @return {Array} Traffic allocation for the experiment - * @throws If experiment key is not in datafile - */ - getTrafficAllocation: function(projectConfig, experimentKey) { - var experiment = projectConfig.experimentKeyMap[experimentKey]; - if (!experiment) { - throw new Error(jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_KEY, MODULE_NAME, experimentKey)); - } - return experiment.trafficAllocation; - }, - - /** - * Get experiment from provided experiment id. Log an error if no experiment - * exists in the project config with the given ID. - * @param {Object} projectConfig Object representing project configuration - * @param {string} experimentId ID of desired experiment object - * @return {Object} Experiment object - */ - getExperimentFromId: function(projectConfig, experimentId, logger) { - if (projectConfig.experimentIdMap.hasOwnProperty(experimentId)) { - var experiment = projectConfig.experimentIdMap[experimentId]; - if (experiment) { - return experiment; - } - } - - logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.INVALID_EXPERIMENT_ID, MODULE_NAME, experimentId)); - return null; - }, - - /** - * Get feature from provided feature key. Log an error if no feature exists in - * the project config with the given key. - * @param {Object} projectConfig - * @param {string} featureKey - * @param {Object} logger - * @return {Object|null} Feature object, or null if no feature with the given - * key exists - */ - getFeatureFromKey: function(projectConfig, featureKey, logger) { - if (projectConfig.featureKeyMap.hasOwnProperty(featureKey)) { - var feature = projectConfig.featureKeyMap[featureKey]; - if (feature) { - return feature; - } - } - - logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); - return null; - }, - - /** - * Get the variable with the given key associated with the feature with the - * given key. If the feature key or the variable key are invalid, log an error - * message. - * @param {Object} projectConfig - * @param {string} featureKey - * @param {string} variableKey - * @param {Object} logger - * @return {Object|null} Variable object, or null one or both of the given - * feature and variable keys are invalid - */ - getVariableForFeature: function(projectConfig, featureKey, variableKey, logger) { - var feature = projectConfig.featureKeyMap[featureKey]; - if (!feature) { - logger.log(LOG_LEVEL.ERROR, jsSdkUtils.sprintf(ERROR_MESSAGES.FEATURE_NOT_IN_DATAFILE, MODULE_NAME, featureKey)); - return null; - } - - var variable = feature.variableKeyMap[variableKey]; - if (!variable) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.VARIABLE_KEY_NOT_IN_DATAFILE, MODULE_NAME, variableKey, featureKey) - ); - return null; - } - - return variable; - }, - - /** - * Get the value of the given variable for the given variation. If the given - * variable has no value for the given variation, return null. Log an error message if the variation is invalid. If the - * variable or variation are invalid, return null. - * @param {Object} projectConfig - * @param {Object} variable - * @param {Object} variation - * @param {Object} logger - * @return {string|null} The value of the given variable for the given - * variation, or null if the given variable has no value - * for the given variation or if the variation or variable are invalid - */ - getVariableValueForVariation: function(projectConfig, variable, variation, logger) { - if (!variable || !variation) { - return null; - } - - if (!projectConfig.variationVariableUsageMap.hasOwnProperty(variation.id)) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.VARIATION_ID_NOT_IN_DATAFILE_NO_EXPERIMENT, MODULE_NAME, variation.id) - ); - return null; - } - - var variableUsages = projectConfig.variationVariableUsageMap[variation.id]; - var variableUsage = variableUsages[variable.id]; - - return variableUsage ? variableUsage.value : null; - }, - - /** - * Given a variable value in string form, try to cast it to the argument type. - * If the type cast succeeds, return the type casted value, otherwise log an - * error and return null. - * @param {string} variableValue Variable value in string form - * @param {string} variableType Type of the variable whose value was passed - * in the first argument. Must be one of - * FEATURE_VARIABLE_TYPES in - * lib/utils/enums/index.js. The return value's - * type is determined by this argument (boolean - * for BOOLEAN, number for INTEGER or DOUBLE, - * and string for STRING). - * @param {Object} logger Logger instance - * @returns {*} Variable value of the appropriate type, or - * null if the type cast failed - */ - getTypeCastValue: function(variableValue, variableType, logger) { - var castValue; - - switch (variableType) { - case FEATURE_VARIABLE_TYPES.BOOLEAN: - if (variableValue !== 'true' && variableValue !== 'false') { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) - ); - castValue = null; - } else { - castValue = variableValue === 'true'; - } - break; - - case FEATURE_VARIABLE_TYPES.INTEGER: - castValue = parseInt(variableValue, 10); - if (isNaN(castValue)) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) - ); - castValue = null; - } - break; - - case FEATURE_VARIABLE_TYPES.DOUBLE: - castValue = parseFloat(variableValue); - if (isNaN(castValue)) { - logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(ERROR_MESSAGES.UNABLE_TO_CAST_VALUE, MODULE_NAME, variableValue, variableType) - ); - castValue = null; - } - break; - - default: - // type is STRING - castValue = variableValue; - break; - } - - return castValue; - }, - - /** - * Returns an object containing all audiences in the project config. Keys are audience IDs - * and values are audience objects. - * @param projectConfig - * @returns {Object} - */ - getAudiencesById: function(projectConfig) { - return projectConfig.audiencesById; - }, - - /** - * Returns true if an event with the given key exists in the datafile, and false otherwise - * @param {Object} projectConfig - * @param {string} eventKey - * @returns {boolean} - */ - eventWithKeyExists: function(projectConfig, eventKey) { - return projectConfig.eventKeyMap.hasOwnProperty(eventKey); - }, - - /** - * - * @param {Object} projectConfig - * @param {string} experimentId - * @returns {boolean} Returns true if experiment belongs to - * any feature, false otherwise. - */ - isFeatureExperiment: function(projectConfig, experimentId) { - return projectConfig.experimentFeatureMap.hasOwnProperty(experimentId); - }, - - /** - * Try to create a project config object from the given datafile and - * configuration properties. - * If successful, return the project config object, otherwise throws an error - * @param {Object} config - * @param {Object} config.datafile - * @param {Object} config.jsonSchemaValidator - * @param {Object} config.logger - * @param {Object} config.skipJSONValidation - * @return {Object} Project config object - */ - tryCreatingProjectConfig: function(config) { - configValidator.validateDatafile(config.datafile); - if (config.skipJSONValidation === true) { - config.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.SKIPPING_JSON_VALIDATION, MODULE_NAME)); - } else if (config.jsonSchemaValidator) { - config.jsonSchemaValidator.validate(projectConfigSchema, config.datafile); - config.logger.log(LOG_LEVEL.INFO, jsSdkUtils.sprintf(LOG_MESSAGES.VALID_DATAFILE, MODULE_NAME)); - } - return module.exports.createProjectConfig(config.datafile); - }, -}; - - -/***/ }), -/* 36 */ -/***/ (function(module, exports) { - -/** - * Copyright 2016-2017, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ - -/*eslint-disable */ -/** - * Project Config JSON Schema file used to validate the project json datafile - */ -module.exports = { - $schema: 'http://json-schema.org/draft-04/schema#', - type: 'object', - properties: { - projectId: { - type: 'string', - required: true, - }, - accountId: { - type: 'string', - required: true, - }, - groups: { - type: 'array', - items: { - type: 'object', - properties: { - id: { - type: 'string', - required: true, - }, - policy: { - type: 'string', - required: true, - }, - trafficAllocation: { - type: 'array', - items: { - type: 'object', - properties: { - entityId: { - type: 'string', - required: true, - }, - endOfRange: { - type: 'integer', - required: true, - }, - }, - }, - required: true, - }, - experiments: { - type: 'array', - items: { - type: 'object', - properties: { - id: { - type: 'string', - required: true, - }, - key: { - type: 'string', - required: true, - }, - status: { - type: 'string', - required: true, - }, - layerId: { - type: 'string', - required: true, - }, - variations: { - type: 'array', - items: { - type: 'object', - properties: { - id: { - type: 'string', - required: true, - }, - key: { - type: 'string', - required: true, - }, - }, - }, - required: true, - }, - trafficAllocation: { - type: 'array', - items: { - type: 'object', - properties: { - entityId: { - type: 'string', - required: true, - }, - endOfRange: { - type: 'integer', - required: true, - }, - }, - }, - required: true, - }, - audienceIds: { - type: 'array', - items: { - type: 'string', - }, - required: true, - }, - forcedVariations: { - type: 'object', - required: true, - }, - }, - }, - required: true, - }, - }, - }, - required: true, - }, - experiments: { - type: 'array', - items: { - type: 'object', - properties: { - id: { - type: 'string', - required: true, - }, - key: { - type: 'string', - required: true, - }, - status: { - type: 'string', - required: true, - }, - layerId: { - type: 'string', - required: true, - }, - variations: { - type: 'array', - items: { - type: 'object', - properties: { - id: { - type: 'string', - required: true, - }, - key: { - type: 'string', - required: true, - }, - }, - }, - required: true, - }, - trafficAllocation: { - type: 'array', - items: { - type: 'object', - properties: { - entityId: { - type: 'string', - required: true, - }, - endOfRange: { - type: 'integer', - required: true, - }, - }, - }, - required: true, - }, - audienceIds: { - type: 'array', - items: { - type: 'string', - }, - required: true, - }, - forcedVariations: { - type: 'object', - required: true, - }, - }, - }, - required: true, - }, - events: { - type: 'array', - items: { - type: 'object', - properties: { - key: { - type: 'string', - required: true, - }, - experimentIds: { - type: 'array', - items: { - type: 'string', - required: true, - }, - }, - id: { - type: 'string', - required: true, - }, - }, - }, - required: true, - }, - audiences: { - type: 'array', - items: { - type: 'object', - properties: { - id: { - type: 'string', - required: true, - }, - name: { - type: 'string', - required: true, - }, - conditions: { - type: 'string', - required: true, - }, - }, - }, - required: true, - }, - attributes: { - type: 'array', - items: { - type: 'object', - properties: { - id: { - type: 'string', - required: true, - }, - key: { - type: 'string', - required: true, - }, - }, - }, - required: true, - }, - version: { - type: 'string', - required: true, - }, - revision: { - type: 'string', - required: true, - }, - }, -}; - - -/***/ }), -/* 37 */ -/***/ (function(module, exports) { - -/** - * Copyright 2018, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ - -module.exports = { - /** - * Validates provided value is a non-empty string - * @param {string} input - * @return {boolean} True for non-empty string, false otherwise - */ - validate: function(input) { - return typeof input === 'string' && input !== ''; - }, -}; - - -/***/ }), -/* 38 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2016-2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 enums = __webpack_require__(14); -var fns = __webpack_require__(11); -var eventTagUtils = __webpack_require__(39); -var projectConfig = __webpack_require__(35); -var attributeValidator = __webpack_require__(28); - -var ACTIVATE_EVENT_KEY = 'campaign_activated'; -var CUSTOM_ATTRIBUTE_FEATURE_TYPE = 'custom'; -var ENDPOINT = 'https://logx.optimizely.com/v1/events'; -var HTTP_VERB = 'POST'; - -/** - * Get params which are used same in both conversion and impression events - * @param {Object} options.attributes Object representing user attributes and values which need to be recorded - * @param {string} options.clientEngine The client we are using: node or javascript - * @param {string} options.clientVersion The version of the client - * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup - * @param {string} options.userId ID for user - * @param {Object} options.Logger logger - * @return {Object} Common params with properties that are used in both conversion and impression events - */ -function getCommonEventParams(options) { - var attributes = options.attributes; - var configObj = options.configObj; - var anonymize_ip = configObj.anonymizeIP; - var botFiltering = configObj.botFiltering; - if (anonymize_ip === null || anonymize_ip === undefined) { - anonymize_ip = false; - } - - var visitor = { - snapshots: [], - visitor_id: options.userId, - attributes: [], - }; - - var commonParams = { - account_id: configObj.accountId, - project_id: configObj.projectId, - visitors: [visitor], - revision: configObj.revision, - client_name: options.clientEngine, - client_version: options.clientVersion, - anonymize_ip: anonymize_ip, - enrich_decisions: true, - }; - - // Omit attribute values that are not supported by the log endpoint. - Object.keys(attributes || {}).forEach(function(attributeKey) { - var attributeValue = attributes[attributeKey]; - if (attributeValidator.isAttributeValid(attributeKey, attributeValue)) { - var attributeId = projectConfig.getAttributeId(options.configObj, attributeKey, options.logger); - if (attributeId) { - commonParams.visitors[0].attributes.push({ - entity_id: attributeId, - key: attributeKey, - type: CUSTOM_ATTRIBUTE_FEATURE_TYPE, - value: attributes[attributeKey], - }); - } - } - }); - - if (typeof botFiltering === 'boolean') { - commonParams.visitors[0].attributes.push({ - entity_id: enums.CONTROL_ATTRIBUTES.BOT_FILTERING, - key: enums.CONTROL_ATTRIBUTES.BOT_FILTERING, - type: CUSTOM_ATTRIBUTE_FEATURE_TYPE, - value: botFiltering, - }); - } - return commonParams; -} - -/** - * Creates object of params specific to impression events - * @param {Object} configObj Object representing project configuration - * @param {string} experimentId ID of experiment for which impression needs to be recorded - * @param {string} variationId ID for variation which would be presented to user - * @return {Object} Impression event params - */ -function getImpressionEventParams(configObj, experimentId, variationId) { - var impressionEventParams = { - decisions: [ - { - campaign_id: projectConfig.getLayerId(configObj, experimentId), - experiment_id: experimentId, - variation_id: variationId, - }, - ], - events: [ - { - entity_id: projectConfig.getLayerId(configObj, experimentId), - timestamp: fns.currentTimestamp(), - key: ACTIVATE_EVENT_KEY, - uuid: fns.uuid(), - }, - ], - }; - return impressionEventParams; -} - -/** - * Creates object of params specific to conversion events - * @param {Object} configObj Object representing project configuration - * @param {string} eventKey Event key representing the event which needs to be recorded - * @param {Object} eventTags Values associated with the event. - * @param {Object} logger Logger object - * @return {Object} Conversion event params - */ -function getVisitorSnapshot(configObj, eventKey, eventTags, logger) { - var snapshot = { - events: [], - }; - - var eventDict = { - entity_id: projectConfig.getEventId(configObj, eventKey), - timestamp: fns.currentTimestamp(), - uuid: fns.uuid(), - key: eventKey, - }; - - if (eventTags) { - var revenue = eventTagUtils.getRevenueValue(eventTags, logger); - if (revenue !== null) { - eventDict[enums.RESERVED_EVENT_KEYWORDS.REVENUE] = revenue; - } - - var eventValue = eventTagUtils.getEventValue(eventTags, logger); - if (eventValue !== null) { - eventDict[enums.RESERVED_EVENT_KEYWORDS.VALUE] = eventValue; - } - - eventDict['tags'] = eventTags; - } - snapshot.events.push(eventDict); - - return snapshot; -} - -module.exports = { - /** - * Create impression event params to be sent to the logging endpoint - * @param {Object} options Object containing values needed to build impression event - * @param {Object} options.attributes Object representing user attributes and values which need to be recorded - * @param {string} options.clientEngine The client we are using: node or javascript - * @param {string} options.clientVersion The version of the client - * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup - * @param {string} options.experimentId Experiment for which impression needs to be recorded - * @param {string} options.userId ID for user - * @param {string} options.variationId ID for variation which would be presented to user - * @return {Object} Params to be used in impression event logging endpoint call - */ - getImpressionEvent: function(options) { - var impressionEvent = { - httpVerb: HTTP_VERB, - }; - - var commonParams = getCommonEventParams(options); - impressionEvent.url = ENDPOINT; - - var impressionEventParams = getImpressionEventParams(options.configObj, options.experimentId, options.variationId); - // combine Event params into visitor obj - commonParams.visitors[0].snapshots.push(impressionEventParams); - - impressionEvent.params = commonParams; - - return impressionEvent; - }, - - /** - * Create conversion event params to be sent to the logging endpoint - * @param {Object} options Object containing values needed to build conversion event - * @param {Object} options.attributes Object representing user attributes and values which need to be recorded - * @param {string} options.clientEngine The client we are using: node or javascript - * @param {string} options.clientVersion The version of the client - * @param {Object} options.configObj Object representing project configuration, including datafile information and mappings for quick lookup - * @param {string} options.eventKey Event key representing the event which needs to be recorded - * @param {Object} options.eventTags Object with event-specific tags - * @param {Object} options.logger Logger object - * @param {string} options.userId ID for user - * @return {Object} Params to be used in conversion event logging endpoint call - */ - getConversionEvent: function(options) { - var conversionEvent = { - httpVerb: HTTP_VERB, - }; - - var commonParams = getCommonEventParams(options); - conversionEvent.url = ENDPOINT; - - var snapshot = getVisitorSnapshot(options.configObj, options.eventKey, options.eventTags, options.logger); - - commonParams.visitors[0].snapshots = [snapshot]; - conversionEvent.params = commonParams; - - return conversionEvent; - }, -}; - - -/***/ }), -/* 39 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2017, 2019 Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ - -/** - * Provides utility method for parsing event tag values - */ -var enums = __webpack_require__(14); -var sprintf = __webpack_require__(12).sprintf; - -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var MODULE_NAME = 'EVENT_TAG_UTILS'; -var REVENUE_EVENT_METRIC_NAME = enums.RESERVED_EVENT_KEYWORDS.REVENUE; -var VALUE_EVENT_METRIC_NAME = enums.RESERVED_EVENT_KEYWORDS.VALUE; - -module.exports = { - /** - * Grab the revenue value from the event tags. "revenue" is a reserved keyword. - * @param {Object} eventTags - * @param {Object} logger - * @return {Integer|null} - */ - getRevenueValue: function(eventTags, logger) { - if (eventTags && eventTags.hasOwnProperty(REVENUE_EVENT_METRIC_NAME)) { - var rawValue = eventTags[REVENUE_EVENT_METRIC_NAME]; - var parsedRevenueValue = parseInt(rawValue, 10); - if (isNaN(parsedRevenueValue)) { - logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FAILED_TO_PARSE_REVENUE, MODULE_NAME, rawValue)); - return null; - } - logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.PARSED_REVENUE_VALUE, MODULE_NAME, parsedRevenueValue)); - return parsedRevenueValue; - } - return null; - }, - - /** - * Grab the event value from the event tags. "value" is a reserved keyword. - * @param {Object} eventTags - * @param {Object} logger - * @return {Number|null} - */ - getEventValue: function(eventTags, logger) { - if (eventTags && eventTags.hasOwnProperty(VALUE_EVENT_METRIC_NAME)) { - var rawValue = eventTags[VALUE_EVENT_METRIC_NAME]; - var parsedEventValue = parseFloat(rawValue); - if (isNaN(parsedEventValue)) { - logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.FAILED_TO_PARSE_VALUE, MODULE_NAME, rawValue)); - return null; - } - logger.log(LOG_LEVEL.INFO, sprintf(LOG_MESSAGES.PARSED_NUMERIC_VALUE, MODULE_NAME, parsedEventValue)); - return parsedEventValue; - } - return null; - }, -}; - - -/***/ }), -/* 40 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 logging = __webpack_require__(1); - -var attributesValidator = __webpack_require__(28); -var fns = __webpack_require__(11); -var eventTagUtils = __webpack_require__(39); -var projectConfig = __webpack_require__(35); - -var logger = logging.getLogger('EVENT_BUILDER'); - -/** - * Creates an ImpressionEvent object from decision data - * @param {Object} config - * @param {Object} config.configObj - * @param {String} config.experimentKey - * @param {String} config.variationKey - * @param {String} config.userId - * @param {Object} config.userAttributes - * @param {String} config.clientEngine - * @param {String} config.clientVersion - * @return {Object} an ImpressionEvent object - */ -exports.buildImpressionEvent = function buildImpressionEvent(config) { - var configObj = config.configObj; - var experimentKey = config.experimentKey; - var variationKey = config.variationKey; - var userId = config.userId; - var userAttributes = config.userAttributes; - var clientEngine = config.clientEngine; - var clientVersion = config.clientVersion; - - var variationId = projectConfig.getVariationIdFromExperimentAndVariationKey(configObj, experimentKey, variationKey); - var experimentId = projectConfig.getExperimentId(configObj, experimentKey); - var layerId = projectConfig.getLayerId(configObj, experimentId); - - return { - type: 'impression', - timestamp: fns.currentTimestamp(), - uuid: fns.uuid(), - - user: { - id: userId, - attributes: buildVisitorAttributes(configObj, userAttributes), - }, - - context: { - accountId: configObj.accountId, - projectId: configObj.projectId, - revision: configObj.revision, - clientName: clientEngine, - clientVersion: clientVersion, - anonymizeIP: configObj.anonymizeIP || false, - botFiltering: configObj.botFiltering, - }, - - layer: { - id: layerId, - }, - - experiment: { - id: experimentId, - key: experimentKey, - }, - - variation: { - id: variationId, - key: variationKey, - }, - }; -}; - -/** - * Creates a ConversionEvent object from track - * @param {Object} config - * @param {Object} config.configObj - * @param {String} config.eventKey - * @param {Object|undefined} config.eventTags - * @param {String} config.userId - * @param {Object} config.userAttributes - * @param {String} config.clientEngine - * @param {String} config.clientVersion - * @return {Object} a ConversionEvent object - */ -exports.buildConversionEvent = function buildConversionEvent(config) { - var configObj = config.configObj; - var userId = config.userId; - var userAttributes = config.userAttributes; - var clientEngine = config.clientEngine; - var clientVersion = config.clientVersion; - - var eventKey = config.eventKey; - var eventTags = config.eventTags; - var eventId = projectConfig.getEventId(configObj, eventKey); - - return { - type: 'conversion', - timestamp: fns.currentTimestamp(), - uuid: fns.uuid(), - - user: { - id: userId, - attributes: buildVisitorAttributes(configObj, userAttributes), - }, - - context: { - accountId: configObj.accountId, - projectId: configObj.projectId, - revision: configObj.revision, - clientName: clientEngine, - clientVersion: clientVersion, - anonymizeIP: configObj.anonymizeIP || false, - botFiltering: configObj.botFiltering, - }, - - event: { - id: eventId, - key: eventKey, - }, - - revenue: eventTagUtils.getRevenueValue(eventTags, logger), - value: eventTagUtils.getEventValue(eventTags, logger), - tags: eventTags, - }; -}; - -function buildVisitorAttributes(configObj, attributes) { - var builtAttributes = []; - // Omit attribute values that are not supported by the log endpoint. - Object.keys(attributes || {}).forEach(function(attributeKey) { - var attributeValue = attributes[attributeKey]; - if (attributesValidator.isAttributeValid(attributeKey, attributeValue)) { - var attributeId = projectConfig.getAttributeId(configObj, attributeKey, logger); - if (attributeId) { - builtAttributes.push({ - entityId: attributeId, - key: attributeKey, - value: attributes[attributeKey], - }); - } - } - }); - - return builtAttributes; -} - - -/***/ }), -/* 41 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2017, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ - -/** - * Provides utility method for validating that event tags user has provided are valid - */ - -var sprintf = __webpack_require__(12).sprintf; - -var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; -var MODULE_NAME = 'EVENT_TAGS_VALIDATOR'; - -module.exports = { - /** - * Validates user's provided event tags - * @param {Object} event tags - * @return {boolean} True if event tags are valid - * @throws If event tags are not valid - */ - validate: function(eventTags) { - if (typeof eventTags === 'object' && !Array.isArray(eventTags) && eventTags !== null) { - return true; - } else { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_EVENT_TAGS, MODULE_NAME)); - } - }, -}; - - -/***/ }), -/* 42 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2017, 2019 Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 enums = __webpack_require__(14); -var jsSdkUtils = __webpack_require__(12); - -var LOG_LEVEL = enums.LOG_LEVEL; -var LOG_MESSAGES = enums.LOG_MESSAGES; -var MODULE_NAME = 'NOTIFICATION_CENTER'; - -/** - * NotificationCenter allows registration and triggering of callback functions using - * notification event types defined in NOTIFICATION_TYPES of utils/enums/index.js: - * - ACTIVATE: An impression event will be sent to Optimizely. - * - TRACK a conversion event will be sent to Optimizely - * @constructor - * @param {Object} options - * @param {Object} options.logger An instance of a logger to log messages with - * @param {object} options.errorHandler An instance of errorHandler to handle any unexpected error - * @returns {Object} - */ -function NotificationCenter(options) { - this.logger = options.logger; - this.errorHandler = options.errorHandler; - this.__notificationListeners = {}; - - jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).forEach( - function(notificationTypeEnum) { - this.__notificationListeners[notificationTypeEnum] = []; - }.bind(this) - ); - this.__listenerId = 1; -} - -/** - * Add a notification callback to the notification center - * @param {string} notificationType One of the values from NOTIFICATION_TYPES in utils/enums/index.js - * @param {Function} callback Function that will be called when the event is triggered - * @returns {number} If the callback was successfully added, returns a listener ID which can be used - * to remove the callback by calling removeNotificationListener. The ID is a number greater than 0. - * If there was an error and the listener was not added, addNotificationListener returns -1. This - * can happen if the first argument is not a valid notification type, or if the same callback - * function was already added as a listener by a prior call to this function. - */ -NotificationCenter.prototype.addNotificationListener = function(notificationType, callback) { - try { - var isNotificationTypeValid = jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).indexOf(notificationType) > -1; - if (!isNotificationTypeValid) { - return -1; - } - - if (!this.__notificationListeners[notificationType]) { - this.__notificationListeners[notificationType] = []; - } - - var callbackAlreadyAdded = false; - (this.__notificationListeners[notificationType] || []).forEach(function(listenerEntry) { - if (listenerEntry.callback === callback) { - callbackAlreadyAdded = true; - return false; - } - }); - if (callbackAlreadyAdded) { - return -1; - } - - this.__notificationListeners[notificationType].push({ - id: this.__listenerId, - callback: callback, - }); - - var returnId = this.__listenerId; - this.__listenerId += 1; - return returnId; - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - return -1; - } -}; - -/** - * Remove a previously added notification callback - * @param {number} listenerId ID of listener to be removed - * @returns {boolean} Returns true if the listener was found and removed, and false - * otherwise. - */ -NotificationCenter.prototype.removeNotificationListener = function(listenerId) { - try { - var indexToRemove; - var typeToRemove; - - Object.keys(this.__notificationListeners).some( - function(notificationType) { - var listenersForType = this.__notificationListeners[notificationType]; - (listenersForType || []).every(function(listenerEntry, i) { - if (listenerEntry.id === listenerId) { - indexToRemove = i; - typeToRemove = notificationType; - return false; - } - return true; - }); - if (indexToRemove !== undefined && typeToRemove !== undefined) { - return true; - } - }.bind(this) - ); - - if (indexToRemove !== undefined && typeToRemove !== undefined) { - this.__notificationListeners[typeToRemove].splice(indexToRemove, 1); - return true; - } - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - } - return false; -}; - -/** - * Removes all previously added notification listeners, for all notification types - */ -NotificationCenter.prototype.clearAllNotificationListeners = function() { - try { - jsSdkUtils.objectValues(enums.NOTIFICATION_TYPES).forEach( - function(notificationTypeEnum) { - this.__notificationListeners[notificationTypeEnum] = []; - }.bind(this) - ); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - } -}; - -/** - * Remove all previously added notification listeners for the argument type - * @param {string} notificationType One of enums.NOTIFICATION_TYPES - */ -NotificationCenter.prototype.clearNotificationListeners = function(notificationType) { - try { - this.__notificationListeners[notificationType] = []; - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - } -}; - -/** - * Fires notifications for the argument type. All registered callbacks for this type will be - * called. The notificationData object will be passed on to callbacks called. - * @param {string} notificationType One of enums.NOTIFICATION_TYPES - * @param {Object} notificationData Will be passed to callbacks called - */ -NotificationCenter.prototype.sendNotifications = function(notificationType, notificationData) { - try { - (this.__notificationListeners[notificationType] || []).forEach( - function(listenerEntry) { - var callback = listenerEntry.callback; - try { - callback(notificationData); - } catch (ex) { - this.logger.log( - LOG_LEVEL.ERROR, - jsSdkUtils.sprintf(LOG_MESSAGES.NOTIFICATION_LISTENER_EXCEPTION, MODULE_NAME, notificationType, ex.message) - ); - } - }.bind(this) - ); - } catch (e) { - this.logger.log(LOG_LEVEL.ERROR, e.message); - this.errorHandler.handleError(e); - } -}; - -module.exports = { - /** - * Create an instance of NotificationCenter - * @param {Object} options - * @param {Object} options.logger An instance of a logger to log messages with - * @returns {Object} An instance of NotificationCenter - */ - createNotificationCenter: function(options) { - return new NotificationCenter(options); - }, -}; - - -/***/ }), -/* 43 */ -/***/ (function(module, exports, __webpack_require__) { - -/**************************************************************************** - * Copyright 2017, Optimizely, Inc. and contributors * - * * - * Licensed under the Apache License, Version 2.0 (the "License"); * - * you may not use this file except in compliance with the License. * - * You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, software * - * distributed under the License 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. * - ***************************************************************************/ - -/** - * Provides utility method for validating that the given user profile service implementation is valid. - */ - -var sprintf = __webpack_require__(12).sprintf; - -var ERROR_MESSAGES = __webpack_require__(14).ERROR_MESSAGES; -var MODULE_NAME = 'USER_PROFILE_SERVICE_VALIDATOR'; - -module.exports = { - /** - * Validates user's provided user profile service instance - * @param {Object} userProfileServiceInstance - * @return {boolean} True if the instance is valid - * @throws If the instance is not valid - */ - validate: function(userProfileServiceInstance) { - if (typeof userProfileServiceInstance.lookup !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'lookup'")); - } else if (typeof userProfileServiceInstance.save !== 'function') { - throw new Error(sprintf(ERROR_MESSAGES.INVALID_USER_PROFILE_SERVICE, MODULE_NAME, "Missing function 'save'")); - } - return true; - }, -}; - - -/***/ }), -/* 44 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 fns = __webpack_require__(11); -var sprintf = __webpack_require__(12).sprintf; -var logging = __webpack_require__(1); -var configValidator = __webpack_require__(13); -var datafileManager = __webpack_require__(45); -var enums = __webpack_require__(14); -var projectConfig = __webpack_require__(35); -var optimizelyConfig = __webpack_require__(54); - -var logger = logging.getLogger(); - -var ERROR_MESSAGES = enums.ERROR_MESSAGES; - -var MODULE_NAME = 'PROJECT_CONFIG_MANAGER'; - -/** - * Return an error message derived from a thrown value. If the thrown value is - * an error, return the error's message property. Otherwise, return a default - * provided by the second argument. - * @param {*} maybeError - * @param {String=} defaultMessage - * @return {String} - */ -function getErrorMessage(maybeError, defaultMessage) { - if (maybeError instanceof Error) { - return maybeError.message; - } - return defaultMessage || 'Unknown error'; -} - -/** - * ProjectConfigManager provides project config objects via its methods - * getConfig and onUpdate. It uses a DatafileManager to fetch datafiles. It is - * responsible for parsing and validating datafiles, and converting datafile - * JSON objects into project config objects. - * @param {Object} config - * @param {Object|string=} config.datafile - * @param {Object=} config.datafileOptions - * @param {Object=} config.jsonSchemaValidator - * @param {string=} config.sdkKey - * @param {boolean=} config.skipJSONValidation - */ -function ProjectConfigManager(config) { - try { - this.__initialize(config); - } catch (ex) { - logger.error(ex); - this.__updateListeners = []; - this.__configObj = null; - this.__optimizelyConfigObj = null; - this.__readyPromise = Promise.resolve({ - success: false, - reason: getErrorMessage(ex, 'Error in initialize'), - }); - } -} - -/** - * Initialize internal properties including __updateListeners, __configObj, and - * __readyPromise, using the argument config. Create and subscribe to a datafile - * manager if appropriate. - * @param {Object} config - * @param {Object|string=} config.datafile - * @param {Object=} config.datafileOptions - * @param {Object=} config.jsonSchemaValidator - * @param {string=} config.sdkKey - * @param {boolean=} config.skipJSONValidation - */ -ProjectConfigManager.prototype.__initialize = function(config) { - this.__updateListeners = []; - this.jsonSchemaValidator = config.jsonSchemaValidator; - this.skipJSONValidation = config.skipJSONValidation; - - if (!config.datafile && !config.sdkKey) { - this.__configObj = null; - var datafileAndSdkKeyMissingError = new Error(sprintf(ERROR_MESSAGES.DATAFILE_AND_SDK_KEY_MISSING, MODULE_NAME)); - this.__readyPromise = Promise.resolve({ - success: false, - reason: getErrorMessage(datafileAndSdkKeyMissingError), - }); - logger.error(datafileAndSdkKeyMissingError); - return; - } - - var initialDatafile = this.__getDatafileFromConfig(config); - var projectConfigCreationEx; - if (initialDatafile) { - try { - this.__configObj = projectConfig.tryCreatingProjectConfig({ - datafile: initialDatafile, - jsonSchemaValidator: this.jsonSchemaValidator, - logger: logger, - skipJSONValidation: this.skipJSONValidation, - }); - this.__optimizelyConfigObj = optimizelyConfig.getOptimizelyConfig(this.__configObj); - } catch (ex) { - logger.error(ex); - projectConfigCreationEx = ex; - this.__configObj = null; - } - } else { - this.__configObj = null; - } - - if (config.sdkKey) { - var datafileManagerConfig = { - sdkKey: config.sdkKey, - }; - if (this.__validateDatafileOptions(config.datafileOptions)) { - fns.assign(datafileManagerConfig, config.datafileOptions); - } - if (initialDatafile && this.__configObj) { - datafileManagerConfig.datafile = initialDatafile; - } - this.datafileManager = new datafileManager.HttpPollingDatafileManager(datafileManagerConfig); - this.datafileManager.start(); - this.__readyPromise = this.datafileManager - .onReady() - .then(this.__onDatafileManagerReadyFulfill.bind(this), this.__onDatafileManagerReadyReject.bind(this)); - this.datafileManager.on('update', this.__onDatafileManagerUpdate.bind(this)); - } else if (this.__configObj) { - this.__readyPromise = Promise.resolve({ - success: true, - }); - } else { - this.__readyPromise = Promise.resolve({ - success: false, - reason: getErrorMessage(projectConfigCreationEx, 'Invalid datafile'), - }); - } -}; - -/** - * Respond to datafile manager's onReady promise becoming fulfilled. - * If there are validation or parse failures using the datafile provided by - * DatafileManager, ProjectConfigManager's ready promise is resolved with an - * unsuccessful result. Otherwise, ProjectConfigManager updates its own project - * config object from the new datafile, and its ready promise is resolved with a - * successful result. - */ -ProjectConfigManager.prototype.__onDatafileManagerReadyFulfill = function() { - var newDatafile = this.datafileManager.get(); - var newConfigObj; - try { - newConfigObj = projectConfig.tryCreatingProjectConfig({ - datafile: newDatafile, - jsonSchemaValidator: this.jsonSchemaValidator, - logger: logger, - skipJSONValidation: this.skipJSONValidation, - }); - } catch (ex) { - logger.error(ex); - return { - success: false, - reason: getErrorMessage(ex), - }; - } - this.__handleNewConfigObj(newConfigObj); - return { - success: true, - }; -}; - -/** - * Respond to datafile manager's onReady promise becoming rejected. - * When DatafileManager's onReady promise is rejected, there is no possibility - * of obtaining a datafile. In this case, ProjectConfigManager's ready promise - * is fulfilled with an unsuccessful result. - * @param {Error} err - */ -ProjectConfigManager.prototype.__onDatafileManagerReadyReject = function(err) { - return { - success: false, - reason: getErrorMessage(err, 'Failed to become ready'), - }; -}; - -/** - * Respond to datafile manager's update event. Attempt to update own config - * object using latest datafile from datafile manager. Call own registered - * update listeners if successful - */ -ProjectConfigManager.prototype.__onDatafileManagerUpdate = function() { - var newDatafile = this.datafileManager.get(); - var newConfigObj; - try { - newConfigObj = projectConfig.tryCreatingProjectConfig({ - datafile: newDatafile, - jsonSchemaValidator: this.jsonSchemaValidator, - logger: logger, - skipJSONValidation: this.skipJSONValidation, - }); - } catch (ex) { - logger.error(ex); - } - if (newConfigObj) { - this.__handleNewConfigObj(newConfigObj); - } -}; - -/** - * If the argument config contains a valid datafile object or string, - * return a datafile object based on that provided datafile, otherwise - * return null. - * @param {Object} config - * @param {Object|string=} config.datafile - * @return {Object|null} - */ -ProjectConfigManager.prototype.__getDatafileFromConfig = function(config) { - var initialDatafile = null; - try { - if (config.datafile) { - configValidator.validateDatafile(config.datafile); - if (typeof config.datafile === 'string' || config.datafile instanceof String) { - initialDatafile = JSON.parse(config.datafile); - } else { - initialDatafile = config.datafile; - } - } - } catch (ex) { - logger.error(ex); - } - return initialDatafile; -}; - -/** - * Validate user-provided datafileOptions. It should be an object or undefined. - * @param {*} datafileOptions - * @returns {boolean} - */ -ProjectConfigManager.prototype.__validateDatafileOptions = function(datafileOptions) { - if (typeof datafileOptions === 'undefined') { - return true; - } - - if (typeof datafileOptions === 'object') { - return datafileOptions !== null; - } - - return false; -}; - -/** - * Update internal project config object to be argument object when the argument - * object has a different revision than the current internal project config - * object. If the internal object is updated, call update listeners. - * @param {Object} newConfigObj - */ -ProjectConfigManager.prototype.__handleNewConfigObj = function(newConfigObj) { - var oldConfigObj = this.__configObj; - - var oldRevision = oldConfigObj ? oldConfigObj.revision : 'null'; - if (oldRevision === newConfigObj.revision) { - return; - } - - this.__configObj = newConfigObj; - this.__optimizelyConfigObj = optimizelyConfig.getOptimizelyConfig(newConfigObj); - - this.__updateListeners.forEach(function(listener) { - listener(newConfigObj); - }); -}; - -/** - * Returns the current project config object, or null if no project config object - * is available - * @return {Object|null} - */ -ProjectConfigManager.prototype.getConfig = function() { - return this.__configObj; -}; - -/** - * Returns the optimizely config object - * @return {Object} - */ -ProjectConfigManager.prototype.getOptimizelyConfig = function() { - return this.__optimizelyConfigObj; -}; - -/** - * Returns a Promise that fulfills when this ProjectConfigManager is ready to - * use (meaning it has a valid project config object), or has failed to become - * ready. - * - * Failure can be caused by the following: - * - At least one of sdkKey or datafile is not provided in the constructor argument - * - The provided datafile was invalid - * - The datafile provided by the datafile manager was invalid - * - The datafile manager failed to fetch a datafile - * - * The returned Promise is fulfilled with a result object containing these - * properties: - * - success (boolean): True if this instance is ready to use with a valid - * project config object, or false if it failed to - * become ready - * - reason (string=): If success is false, this is a string property with - * an explanatory message. - * @return {Promise} - */ -ProjectConfigManager.prototype.onReady = function() { - return this.__readyPromise; -}; - -/** - * Add a listener for project config updates. The listener will be called - * whenever this instance has a new project config object available. - * Returns a dispose function that removes the subscription - * @param {Function} listener - * @return {Function} - */ -ProjectConfigManager.prototype.onUpdate = function(listener) { - this.__updateListeners.push(listener); - return function() { - var index = this.__updateListeners.indexOf(listener); - if (index > -1) { - this.__updateListeners.splice(index, 1); - } - }.bind(this); -}; - -/** - * Stop the internal datafile manager and remove all update listeners - */ -ProjectConfigManager.prototype.stop = function() { - if (this.datafileManager) { - this.datafileManager.stop(); - } - this.__updateListeners = []; -}; - -module.exports = { - ProjectConfigManager: ProjectConfigManager, -}; - - -/***/ }), -/* 45 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -var browserDatafileManager_1 = __webpack_require__(46); -exports.HttpPollingDatafileManager = browserDatafileManager_1.default; -var staticDatafileManager_1 = __webpack_require__(53); -exports.StaticDatafileManager = staticDatafileManager_1.default; - - -/***/ }), -/* 46 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 __extends = (this && this.__extends) || (function () { - var extendStatics = function (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 __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var browserRequest_1 = __webpack_require__(47); -var httpPollingDatafileManager_1 = __importDefault(__webpack_require__(49)); -var BrowserDatafileManager = /** @class */ (function (_super) { - __extends(BrowserDatafileManager, _super); - function BrowserDatafileManager() { - return _super !== null && _super.apply(this, arguments) || this; - } - BrowserDatafileManager.prototype.makeGetRequest = function (reqUrl, headers) { - return browserRequest_1.makeGetRequest(reqUrl, headers); - }; - BrowserDatafileManager.prototype.getConfigDefaults = function () { - return { - autoUpdate: false, - }; - }; - return BrowserDatafileManager; -}(httpPollingDatafileManager_1.default)); -exports.default = BrowserDatafileManager; - - -/***/ }), -/* 47 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -var config_1 = __webpack_require__(48); -var js_sdk_logging_1 = __webpack_require__(1); -var logger = js_sdk_logging_1.getLogger('DatafileManager'); -var GET_METHOD = 'GET'; -var READY_STATE_DONE = 4; -function parseHeadersFromXhr(req) { - var allHeadersString = req.getAllResponseHeaders(); - if (allHeadersString === null) { - return {}; - } - var headerLines = allHeadersString.split('\r\n'); - var headers = {}; - headerLines.forEach(function (headerLine) { - var separatorIndex = headerLine.indexOf(': '); - if (separatorIndex > -1) { - var headerName = headerLine.slice(0, separatorIndex); - var headerValue = headerLine.slice(separatorIndex + 2); - if (headerValue.length > 0) { - headers[headerName] = headerValue; - } - } - }); - return headers; -} -function setHeadersInXhr(headers, req) { - Object.keys(headers).forEach(function (headerName) { - var header = headers[headerName]; - req.setRequestHeader(headerName, header); - }); -} -function makeGetRequest(reqUrl, headers) { - var req = new XMLHttpRequest(); - var responsePromise = new Promise(function (resolve, reject) { - req.open(GET_METHOD, reqUrl, true); - setHeadersInXhr(headers, req); - req.onreadystatechange = function () { - if (req.readyState === READY_STATE_DONE) { - var statusCode = req.status; - if (statusCode === 0) { - reject(new Error('Request error')); - return; - } - var headers_1 = parseHeadersFromXhr(req); - var resp = { - statusCode: req.status, - body: req.responseText, - headers: headers_1, - }; - resolve(resp); - } - }; - req.timeout = config_1.REQUEST_TIMEOUT_MS; - req.ontimeout = function () { - logger.error('Request timed out'); - }; - req.send(); - }); - return { - responsePromise: responsePromise, - abort: function () { - req.abort(); - }, - }; -} -exports.makeGetRequest = makeGetRequest; - - -/***/ }), -/* 48 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.DEFAULT_UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes -exports.MIN_UPDATE_INTERVAL = 1000; -exports.DEFAULT_URL_TEMPLATE = "https://cdn.optimizely.com/datafiles/%s.json"; -exports.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT = [0, 8, 16, 32, 64, 128, 256, 512]; -exports.REQUEST_TIMEOUT_MS = 60 * 1000; // 1 minute - - -/***/ }), -/* 49 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 __assign = (this && this.__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 __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -var js_sdk_logging_1 = __webpack_require__(1); -var js_sdk_utils_1 = __webpack_require__(50); -var eventEmitter_1 = __importDefault(__webpack_require__(51)); -var config_1 = __webpack_require__(48); -var backoffController_1 = __importDefault(__webpack_require__(52)); -var logger = js_sdk_logging_1.getLogger('DatafileManager'); -var UPDATE_EVT = 'update'; -function isValidUpdateInterval(updateInterval) { - return updateInterval >= config_1.MIN_UPDATE_INTERVAL; -} -function isSuccessStatusCode(statusCode) { - return statusCode >= 200 && statusCode < 400; -} -var HttpPollingDatafileManager = /** @class */ (function () { - function HttpPollingDatafileManager(config) { - var _this = this; - var configWithDefaultsApplied = __assign({}, this.getConfigDefaults(), config); - var datafile = configWithDefaultsApplied.datafile, _a = configWithDefaultsApplied.autoUpdate, autoUpdate = _a === void 0 ? false : _a, sdkKey = configWithDefaultsApplied.sdkKey, _b = configWithDefaultsApplied.updateInterval, updateInterval = _b === void 0 ? config_1.DEFAULT_UPDATE_INTERVAL : _b, _c = configWithDefaultsApplied.urlTemplate, urlTemplate = _c === void 0 ? config_1.DEFAULT_URL_TEMPLATE : _c; - this.isReadyPromiseSettled = false; - this.readyPromiseResolver = function () { }; - this.readyPromiseRejecter = function () { }; - this.readyPromise = new Promise(function (resolve, reject) { - _this.readyPromiseResolver = resolve; - _this.readyPromiseRejecter = reject; - }); - if (datafile) { - this.currentDatafile = datafile; - this.resolveReadyPromise(); - } - else { - this.currentDatafile = null; - } - this.isStarted = false; - this.datafileUrl = js_sdk_utils_1.sprintf(urlTemplate, sdkKey); - this.emitter = new eventEmitter_1.default(); - this.autoUpdate = autoUpdate; - if (isValidUpdateInterval(updateInterval)) { - this.updateInterval = updateInterval; - } - else { - logger.warn('Invalid updateInterval %s, defaulting to %s', updateInterval, config_1.DEFAULT_UPDATE_INTERVAL); - this.updateInterval = config_1.DEFAULT_UPDATE_INTERVAL; - } - this.currentTimeout = null; - this.currentRequest = null; - this.backoffController = new backoffController_1.default(); - this.syncOnCurrentRequestComplete = false; - } - HttpPollingDatafileManager.prototype.get = function () { - return this.currentDatafile; - }; - HttpPollingDatafileManager.prototype.start = function () { - if (!this.isStarted) { - logger.debug('Datafile manager started'); - this.isStarted = true; - this.backoffController.reset(); - this.syncDatafile(); - } - }; - HttpPollingDatafileManager.prototype.stop = function () { - logger.debug('Datafile manager stopped'); - this.isStarted = false; - if (this.currentTimeout) { - clearTimeout(this.currentTimeout); - this.currentTimeout = null; - } - this.emitter.removeAllListeners(); - if (this.currentRequest) { - this.currentRequest.abort(); - this.currentRequest = null; - } - return Promise.resolve(); - }; - HttpPollingDatafileManager.prototype.onReady = function () { - return this.readyPromise; - }; - HttpPollingDatafileManager.prototype.on = function (eventName, listener) { - return this.emitter.on(eventName, listener); - }; - HttpPollingDatafileManager.prototype.onRequestRejected = function (err) { - if (!this.isStarted) { - return; - } - this.backoffController.countError(); - if (err instanceof Error) { - logger.error('Error fetching datafile: %s', err.message, err); - } - else if (typeof err === 'string') { - logger.error('Error fetching datafile: %s', err); - } - else { - logger.error('Error fetching datafile'); - } - }; - HttpPollingDatafileManager.prototype.onRequestResolved = function (response) { - if (!this.isStarted) { - return; - } - if (typeof response.statusCode !== 'undefined' && - isSuccessStatusCode(response.statusCode)) { - this.backoffController.reset(); - } - else { - this.backoffController.countError(); - } - this.trySavingLastModified(response.headers); - var datafile = this.getNextDatafileFromResponse(response); - if (datafile !== null) { - logger.info('Updating datafile from response'); - this.currentDatafile = datafile; - if (!this.isReadyPromiseSettled) { - this.resolveReadyPromise(); - } - else { - var datafileUpdate = { - datafile: datafile, - }; - this.emitter.emit(UPDATE_EVT, datafileUpdate); - } - } - }; - HttpPollingDatafileManager.prototype.onRequestComplete = function () { - if (!this.isStarted) { - return; - } - this.currentRequest = null; - if (!this.isReadyPromiseSettled && !this.autoUpdate) { - // We will never resolve ready, so reject it - this.rejectReadyPromise(new Error('Failed to become ready')); - } - if (this.autoUpdate && this.syncOnCurrentRequestComplete) { - this.syncDatafile(); - } - this.syncOnCurrentRequestComplete = false; - }; - HttpPollingDatafileManager.prototype.syncDatafile = function () { - var _this = this; - var headers = {}; - if (this.lastResponseLastModified) { - headers['if-modified-since'] = this.lastResponseLastModified; - } - logger.debug('Making datafile request to url %s with headers: %s', this.datafileUrl, function () { return JSON.stringify(headers); }); - this.currentRequest = this.makeGetRequest(this.datafileUrl, headers); - var onRequestComplete = function () { - _this.onRequestComplete(); - }; - var onRequestResolved = function (response) { - _this.onRequestResolved(response); - }; - var onRequestRejected = function (err) { - _this.onRequestRejected(err); - }; - this.currentRequest.responsePromise - .then(onRequestResolved, onRequestRejected) - .then(onRequestComplete, onRequestComplete); - if (this.autoUpdate) { - this.scheduleNextUpdate(); - } - }; - HttpPollingDatafileManager.prototype.resolveReadyPromise = function () { - this.readyPromiseResolver(); - this.isReadyPromiseSettled = true; - }; - HttpPollingDatafileManager.prototype.rejectReadyPromise = function (err) { - this.readyPromiseRejecter(err); - this.isReadyPromiseSettled = true; - }; - HttpPollingDatafileManager.prototype.scheduleNextUpdate = function () { - var _this = this; - var currentBackoffDelay = this.backoffController.getDelay(); - var nextUpdateDelay = Math.max(currentBackoffDelay, this.updateInterval); - logger.debug('Scheduling sync in %s ms', nextUpdateDelay); - this.currentTimeout = setTimeout(function () { - if (_this.currentRequest) { - _this.syncOnCurrentRequestComplete = true; - } - else { - _this.syncDatafile(); - } - }, nextUpdateDelay); - }; - HttpPollingDatafileManager.prototype.getNextDatafileFromResponse = function (response) { - logger.debug('Response status code: %s', response.statusCode); - if (typeof response.statusCode === 'undefined') { - return null; - } - if (response.statusCode === 304) { - return null; - } - if (isSuccessStatusCode(response.statusCode)) { - return this.tryParsingBodyAsJSON(response.body); - } - return null; - }; - HttpPollingDatafileManager.prototype.tryParsingBodyAsJSON = function (body) { - var parseResult; - try { - parseResult = JSON.parse(body); - } - catch (err) { - logger.error('Error parsing response body: %s', err.message, err); - return null; - } - var datafileObj = null; - if (typeof parseResult === 'object' && parseResult !== null) { - datafileObj = parseResult; - } - else { - logger.error('Error parsing response body: was not an object'); - } - return datafileObj; - }; - HttpPollingDatafileManager.prototype.trySavingLastModified = function (headers) { - var lastModifiedHeader = headers['last-modified'] || headers['Last-Modified']; - if (typeof lastModifiedHeader !== 'undefined') { - this.lastResponseLastModified = lastModifiedHeader; - logger.debug('Saved last modified header value from response: %s', this.lastResponseLastModified); - } - }; - return HttpPollingDatafileManager; -}()); -exports.default = HttpPollingDatafileManager; - - -/***/ }), -/* 50 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 uuid_1 = __webpack_require__(6); -function getTimestamp() { - return new Date().getTime(); -} -exports.getTimestamp = getTimestamp; -function generateUUID() { - return uuid_1.v4(); -} -exports.generateUUID = generateUUID; -/** - * Validates a value is a valid TypeScript enum - * - * @export - * @param {object} enumToCheck - * @param {*} value - * @returns {boolean} - */ -function isValidEnum(enumToCheck, value) { - var found = false; - var keys = Object.keys(enumToCheck); - for (var index = 0; index < keys.length; index++) { - if (value === enumToCheck[keys[index]]) { - found = true; - break; - } - } - return found; -} -exports.isValidEnum = isValidEnum; -function groupBy(arr, grouperFn) { - var grouper = {}; - arr.forEach(function (item) { - var key = grouperFn(item); - grouper[key] = grouper[key] || []; - grouper[key].push(item); - }); - return objectValues(grouper); -} -exports.groupBy = groupBy; -function objectValues(obj) { - return Object.keys(obj).map(function (key) { return obj[key]; }); -} -exports.objectValues = objectValues; -function find(arr, cond) { - var found; - for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) { - var item = arr_1[_i]; - if (cond(item)) { - found = item; - break; - } - } - return found; -} -exports.find = find; -function keyBy(arr, keyByFn) { - var map = {}; - arr.forEach(function (item) { - var key = keyByFn(item); - map[key] = item; - }); - return map; -} -exports.keyBy = keyBy; -function sprintf(format) { - var args = []; - for (var _i = 1; _i < arguments.length; _i++) { - args[_i - 1] = arguments[_i]; - } - var i = 0; - return format.replace(/%s/g, function () { - var arg = args[i++]; - var type = typeof arg; - if (type === 'function') { - return arg(); - } - else if (type === 'string') { - return arg; - } - else { - return String(arg); - } - }); -} -exports.sprintf = sprintf; - - -/***/ }), -/* 51 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -var EventEmitter = /** @class */ (function () { - function EventEmitter() { - this.listeners = {}; - this.listenerId = 1; - } - EventEmitter.prototype.on = function (eventName, listener) { - var _this = this; - if (!this.listeners[eventName]) { - this.listeners[eventName] = {}; - } - var currentListenerId = String(this.listenerId); - this.listenerId++; - this.listeners[eventName][currentListenerId] = listener; - return function () { - if (_this.listeners[eventName]) { - delete _this.listeners[eventName][currentListenerId]; - } - }; - }; - EventEmitter.prototype.emit = function (eventName, arg) { - var listeners = this.listeners[eventName]; - if (listeners) { - Object.keys(listeners).forEach(function (listenerId) { - var listener = listeners[listenerId]; - listener(arg); - }); - } - }; - EventEmitter.prototype.removeAllListeners = function () { - this.listeners = {}; - }; - return EventEmitter; -}()); -exports.default = EventEmitter; -// TODO: Create a typed event emitter for use in TS only (not JS) - - -/***/ }), -/* 52 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -var config_1 = __webpack_require__(48); -function randomMilliseconds() { - return Math.round(Math.random() * 1000); -} -var BackoffController = /** @class */ (function () { - function BackoffController() { - this.errorCount = 0; - } - BackoffController.prototype.getDelay = function () { - if (this.errorCount === 0) { - return 0; - } - var baseWaitSeconds = config_1.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT[Math.min(config_1.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT.length - 1, this.errorCount)]; - return baseWaitSeconds * 1000 + randomMilliseconds(); - }; - BackoffController.prototype.countError = function () { - if (this.errorCount < config_1.BACKOFF_BASE_WAIT_SECONDS_BY_ERROR_COUNT.length - 1) { - this.errorCount++; - } - }; - BackoffController.prototype.reset = function () { - this.errorCount = 0; - }; - return BackoffController; -}()); -exports.default = BackoffController; - - -/***/ }), -/* 53 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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. - */ -Object.defineProperty(exports, "__esModule", { value: true }); -var doNothing = function () { }; -var StaticDatafileManager = /** @class */ (function () { - function StaticDatafileManager(datafile) { - this.datafile = datafile; - this.readyPromise = Promise.resolve(); - } - StaticDatafileManager.prototype.get = function () { - return this.datafile; - }; - StaticDatafileManager.prototype.onReady = function () { - return this.readyPromise; - }; - StaticDatafileManager.prototype.start = function () { - }; - StaticDatafileManager.prototype.stop = function () { - return Promise.resolve(); - }; - StaticDatafileManager.prototype.on = function (eventName, listener) { - return doNothing; - }; - return StaticDatafileManager; -}()); -exports.default = StaticDatafileManager; - - -/***/ }), -/* 54 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 projectConfig = __webpack_require__(35); - -// Get Experiment Ids which are part of rollouts -function getRolloutExperimentIds(rollouts) { - return (rollouts || []).reduce(function(experimentIds, rollout) { - rollout.experiments.forEach(function(e) { - experimentIds[e.id] = true; - }); - return experimentIds; - }, {}); -} - -// Gets Map of all experiments except rollouts -function getExperimentsMap(configObj) { - var rolloutExperimentIds = getRolloutExperimentIds(configObj.rollouts); - var featureVariablesMap = (configObj.featureFlags || []).reduce(function(resultMap, feature) { - resultMap[feature.id] = feature.variables; - return resultMap; - }, {}); - return (configObj.experiments || []).reduce(function(experiments, experiment) { - // skip experiments that are part of a rollout - if (!rolloutExperimentIds[experiment.id]) { - experiments[experiment.key] = { - id: experiment.id, - key: experiment.key, - variationsMap: (experiment.variations || []).reduce(function(variations, variation) { - variations[variation.key] = { - id: variation.id, - key: variation.key, - variablesMap: getMergedVariablesMap(configObj, variation, experiment.id, featureVariablesMap), - }; - if (projectConfig.isFeatureExperiment(configObj, experiment.id)) { - variations[variation.key].featureEnabled = variation.featureEnabled; - } - return variations; - }, {}), - }; - } - return experiments; - }, {}); -} - -// Merges feature key and type from feature variables to variation variables. -function getMergedVariablesMap(configObj, variation, experimentId, featureVariablesMap) { - var featureId = configObj.experimentFeatureMap[experimentId]; - var variablesObject = {}; - if (featureId) { - var experimentFeatureVariables = featureVariablesMap[featureId]; - // Temporary variation variables map to get values to merge. - var tempVariablesIdMap = (variation.variables || []).reduce(function(variablesMap, variable) { - variablesMap[variable.id] = { - id: variable.id, - value: variable.value, - }; - return variablesMap; - }, {}); - variablesObject = (experimentFeatureVariables || []).reduce(function(variablesMap, featureVariable) { - var variationVariable = tempVariablesIdMap[featureVariable.id]; - var variableValue = - variation.featureEnabled && variationVariable ? variationVariable.value : featureVariable.defaultValue; - variablesMap[featureVariable.key] = { - id: featureVariable.id, - key: featureVariable.key, - type: featureVariable.type, - value: variableValue, - }; - return variablesMap; - }, {}); - } - return variablesObject; -} - -// Gets map of all experiments -function getFeaturesMap(configObj, allExperiments) { - return (configObj.featureFlags || []).reduce(function(features, feature) { - features[feature.key] = { - id: feature.id, - key: feature.key, - experimentsMap: (feature.experimentIds || []).reduce(function(experiments, experimentId) { - var experimentKey = configObj.experimentIdMap[experimentId].key; - experiments[experimentKey] = allExperiments[experimentKey]; - return experiments; - }, {}), - variablesMap: (feature.variables || []).reduce(function(variables, variable) { - variables[variable.key] = { - id: variable.id, - key: variable.key, - type: variable.type, - value: variable.defaultValue, - }; - return variables; - }, {}), - }; - return features; - }, {}); -} - -module.exports = { - getOptimizelyConfig: function(configObj) { - // Fetch all feature variables from feature flags to merge them with variation variables - var experimentsMap = getExperimentsMap(configObj); - return { - experimentsMap: experimentsMap, - featuresMap: getFeaturesMap(configObj, experimentsMap), - revision: configObj.revision, - }; - }, -}; - - -/***/ }), -/* 55 */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2019, Optimizely - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License 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 fns = __webpack_require__(11); - -/** - * Return true if the argument is a valid event batch size, false otherwise - * @param {*} eventBatchSize - * @returns boolean - */ -function validateEventBatchSize(eventBatchSize) { - return fns.isSafeInteger(eventBatchSize) && eventBatchSize >= 1; -} - -/** - * Return true if the argument is a valid event flush interval, false otherwise - * @param {*} eventFlushInterval - * @returns boolean - */ -function validateEventFlushInterval(eventFlushInterval) { - return fns.isSafeInteger(eventFlushInterval) && eventFlushInterval > 0; -} - -module.exports = { - validateEventBatchSize: validateEventBatchSize, - validateEventFlushInterval: validateEventFlushInterval, -}; - - -/***/ }) -/******/ ]); -}); \ No newline at end of file diff --git a/packages/optimizely-sdk/optimizely.browser.umd.min.js b/packages/optimizely-sdk/optimizely.browser.umd.min.js deleted file mode 100644 index 2d9a18f2c..000000000 --- a/packages/optimizely-sdk/optimizely.browser.umd.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.optimizelySdk=t():e.optimizelySdk=t()}(window,(function(){return function(e){var t={};function r(i){if(t[i])return t[i].exports;var n=t[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=t,r.d=function(e,t,i){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(r.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)r.d(i,n,function(t){return e[t]}.bind(null,n));return i},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=19)}([function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(5);function n(e){return Object.keys(e).map((function(t){return e[t]}))}t.getTimestamp=function(){return(new Date).getTime()},t.generateUUID=function(){return i.v4()},t.isValidEnum=function(e,t){for(var r=!1,i=Object.keys(e),n=0;n>>((3&t)<<3)&255;return n}}},function(e,t){for(var r=[],i=0;i<256;++i)r[i]=(i+256).toString(16).substr(1);e.exports=function(e,t){var i=t||0,n=r;return[n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],"-",n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]],n[e[i++]]].join("")}},function(e,t,r){"use strict";function i(e){for(var r in e)t.hasOwnProperty(r)||(t[r]=e[r])}Object.defineProperty(t,"__esModule",{value:!0}),i(r(14)),i(r(15)),i(r(28)),i(r(16)),i(r(30))},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.areEventContextsEqual=function(e,t){var r=e.context,i=t.context;return r.accountId===i.accountId&&r.projectId===i.projectId&&r.clientName===i.clientName&&r.clientVersion===i.clientVersion&&r.revision===i.revision&&r.anonymizeIP===i.anonymizeIP&&r.botFiltering===i.botFiltering}},function(e,t,r){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var n=r(14),o=r(26),a=r(2),s=r(0),u=i(r(27)),l=a.getLogger("EventProcessor"),c=function(){function e(e){var t=e.dispatcher,r=e.flushInterval,i=void 0===r?3e4:r,a=e.maxQueueSize,s=void 0===a?3e3:a,c=e.notificationCenter,E=this;this.dispatcher=t,i<=0&&(l.warn("Invalid flushInterval "+i+", defaulting to 30000"),i=3e4),(s=Math.floor(s))<1&&(l.warn("Invalid maxQueueSize "+s+", defaulting to 10"),s=10),s=Math.max(1,s),this.queue=s>1?new o.DefaultEventQueue({flushInterval:i,maxQueueSize:s,sink:function(e){return E.drainQueue(e)},batchComparator:n.areEventContextsEqual}):new o.SingleEventQueue({sink:function(e){return E.drainQueue(e)}}),this.notificationCenter=c,this.requestTracker=new u.default}return e.prototype.drainQueue=function(e){var t=this,r=new Promise((function(r){if(l.debug("draining queue with %s events",e.length),0!==e.length){var i=t.formatEvents(e);t.dispatcher.dispatchEvent(i,(function(){r()})),t.notificationCenter&&t.notificationCenter.sendNotifications(s.NOTIFICATION_TYPES.LOG_EVENT,i)}else r()}));return this.requestTracker.trackRequest(r),r},e.prototype.process=function(e){this.queue.enqueue(e)},e.prototype.stop=function(){try{return this.queue.stop(),this.requestTracker.onRequestsComplete()}catch(e){l.error('Error stopping EventProcessor: "%s"',e.message,e)}return Promise.resolve()},e.prototype.start=function(){this.queue.start()},e}();t.AbstractEventProcessor=c},function(e,t,r){"use strict";var i=this&&this.__assign||function(){return(i=Object.assign||function(e){for(var t,r=1,i=arguments.length;r=this.logLevel},e.prototype.getLogLevelName=function(e){switch(e){case o.LogLevel.DEBUG:return"DEBUG";case o.LogLevel.INFO:return"INFO ";case o.LogLevel.WARNING:return"WARN ";case o.LogLevel.ERROR:return"ERROR";default:return"NOTSET"}},e.prototype.consoleLog=function(e,t){switch(e){case o.LogLevel.DEBUG:console.log.apply(console,t);break;case o.LogLevel.INFO:console.info.apply(console,t);break;case o.LogLevel.WARNING:console.warn.apply(console,t);break;case o.LogLevel.ERROR:console.error.apply(console,t);break;default:console.log.apply(console,t)}},e}();t.ConsoleLogHandler=l;var c=o.LogLevel.NOTSET,E=null,f=function(){function e(e){void 0===e&&(e={}),this.messagePrefix="",e.messagePrefix&&(this.messagePrefix=e.messagePrefix)}return e.prototype.log=function(e,t){this.internalLog(s(e),{message:t,splat:[]})},e.prototype.info=function(e){for(var t=[],r=1;rs)&&void 0===e.nsecs&&(d=0),d>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");s=_,u=d,n=f;var I=(1e4*(268435455&(_+=122192928e5))+d)%4294967296;c[l++]=I>>>24&255,c[l++]=I>>>16&255,c[l++]=I>>>8&255,c[l++]=255&I;var h=_/4294967296*1e4&268435455;c[l++]=h>>>8&255,c[l++]=255&h,c[l++]=h>>>24&15|16,c[l++]=h>>>16&255,c[l++]=f>>>8|128,c[l++]=255&f;for(var v=0;v<6;++v)c[l+v]=E[v];return t||a(c)}},function(e,t,r){var i=r(11),n=r(12);e.exports=function(e,t,r){var o=t&&r||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null);var a=(e=e||{}).random||(e.rng||i)();if(a[6]=15&a[6]|64,a[8]=63&a[8]|128,t)for(var s=0;s<16;++s)t[o+s]=a[s];return t||n(a)}},function(e,t){e.exports={handleError:function(){}}},function(e,t){e.exports={dispatchEvent:function(e,t){var i,n=e.url,o=e.params;"POST"===e.httpVerb?((i=new XMLHttpRequest).open("POST",n,!0),i.setRequestHeader("Content-Type","application/json"),i.onreadystatechange=function(){if(4===i.readyState&&t&&"function"==typeof t)try{t(o)}catch(e){}},i.send(JSON.stringify(o))):(n+="?wxhr=true",o&&(n+="&"+r(o)),(i=new XMLHttpRequest).open("GET",n,!0),i.onreadystatechange=function(){if(4===i.readyState&&t&&"function"==typeof t)try{t()}catch(e){}},i.send())}};var r=function(e){return Object.keys(e).map((function(t){return encodeURIComponent(t)+"="+encodeURIComponent(e[t])})).join("&")}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(2).getLogger("EventProcessor"),n=function(){function e(e){var t=e.timeout,r=e.callback;this.timeout=Math.max(t,0),this.callback=r}return e.prototype.start=function(){this.timeoutId=setTimeout(this.callback,this.timeout)},e.prototype.refresh=function(){this.stop(),this.start()},e.prototype.stop=function(){this.timeoutId&&clearTimeout(this.timeoutId)},e}(),o=function(){function e(e){var t=e.sink;this.sink=t}return e.prototype.start=function(){},e.prototype.stop=function(){return Promise.resolve()},e.prototype.enqueue=function(e){this.sink([e])},e}();t.SingleEventQueue=o;var a=function(){function e(e){var t=e.flushInterval,r=e.maxQueueSize,i=e.sink,o=e.batchComparator;this.buffer=[],this.maxQueueSize=Math.max(r,1),this.sink=i,this.batchComparator=o,this.timer=new n({callback:this.flush.bind(this),timeout:t}),this.started=!1}return e.prototype.start=function(){this.started=!0},e.prototype.stop=function(){this.started=!1;var e=this.sink(this.buffer);return this.buffer=[],this.timer.stop(),e},e.prototype.enqueue=function(e){if(this.started){var t=this.buffer[0];t&&!this.batchComparator(t,e)&&this.flush(),0===this.buffer.length&&this.timer.refresh(),this.buffer.push(e),this.buffer.length>=this.maxQueueSize&&this.flush()}else i.warn("Queue is stopped, not accepting event")},e.prototype.flush=function(){this.sink(this.buffer),this.buffer=[],this.timer.stop()},e}();t.DefaultEventQueue=a},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(){this.reqsInFlightCount=0,this.reqsCompleteResolvers=[]}return e.prototype.trackRequest=function(e){var t=this;this.reqsInFlightCount++;var r=function(){t.reqsInFlightCount--,0===t.reqsInFlightCount&&(t.reqsCompleteResolvers.forEach((function(e){return e()})),t.reqsCompleteResolvers=[])};e.then(r,r)},e.prototype.onRequestsComplete=function(){var e=this;return new Promise((function(t){0===e.reqsInFlightCount?t():e.reqsCompleteResolvers.push(t)}))},e}();t.default=i},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)});Object.defineProperty(t,"__esModule",{value:!0});var o=r(2),a=r(29),s=r(0),u=o.getLogger("EventProcessor"),l=function(){function e(e){var t=e.eventDispatcher,r=e.store;this.dispatcher=t,this.store=r}return e.prototype.dispatchEvent=function(e,t){this.send({uuid:s.generateUUID(),timestamp:s.getTimestamp(),request:e},t)},e.prototype.sendPendingEvents=function(){var e=this,t=this.store.values();u.debug("Sending %s pending events from previous page",t.length),t.forEach((function(t){try{e.send(t,(function(){}))}catch(e){}}))},e.prototype.send=function(e,t){var r=this;this.store.set(e.uuid,e),this.dispatcher.dispatchEvent(e.request,(function(i){r.store.remove(e.uuid),t(i)}))},e}();t.PendingEventsDispatcher=l;var c=function(e){function t(t){var r=t.eventDispatcher;return e.call(this,{eventDispatcher:r,store:new a.LocalStorageStore({maxValues:100,key:"fs_optly_pending_events"})})||this}return n(t,e),t}(l);t.LocalStoragePendingEventsDispatcher=c},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(0),n=r(2).getLogger("EventProcessor"),o=function(){function e(e){var t=e.key,r=e.maxValues,i=void 0===r?1e3:r;this.LS_KEY=t,this.maxValues=i}return e.prototype.get=function(e){return this.getMap()[e]||null},e.prototype.set=function(e,t){var r=this.getMap();r[e]=t,this.replace(r)},e.prototype.remove=function(e){var t=this.getMap();delete t[e],this.replace(t)},e.prototype.values=function(){return i.objectValues(this.getMap())},e.prototype.clear=function(){this.replace({})},e.prototype.replace=function(e){try{window.localStorage&&localStorage.setItem(this.LS_KEY,JSON.stringify(e)),this.clean()}catch(e){n.error(e)}},e.prototype.clean=function(){var e=this.getMap(),t=Object.keys(e),r=t.length-this.maxValues;if(!(r<1)){var i=t.map((function(t){return{key:t,value:e[t]}}));i.sort((function(e,t){return e.value.timestamp-t.value.timestamp}));for(var n=0;n0?(n=s.getExperimentFromId(e,t.experimentIds[0],this.logger))&&(o=this.getVariation(e,n.key,r,i)):this.logger.log(f.DEBUG,l(p.FEATURE_HAS_NO_EXPERIMENTS,c,t.key));var u=null;return null!==o&&null!==n&&(u=n.variationKeyMap[o]),{experiment:n,variation:u,decisionSource:_.FEATURE_TEST}},d.prototype._getExperimentInGroup=function(e,t,r){var i=n.bucketUserIntoExperiment(t,r,r,this.logger);if(i){this.logger.log(f.INFO,l(p.USER_BUCKETED_INTO_EXPERIMENT_IN_GROUP,c,r,i,t.id));var o=s.getExperimentFromId(e,i,this.logger);if(o)return o}return this.logger.log(f.INFO,l(p.USER_NOT_BUCKETED_INTO_ANY_EXPERIMENT_IN_GROUP,c,r,t.id)),null},d.prototype._getVariationForRollout=function(e,t,r,i){if(!t.rolloutId)return this.logger.log(f.DEBUG,l(p.NO_ROLLOUT_EXISTS,c,t.key)),{experiment:null,variation:null,decisionSource:_.ROLLOUT};var o=e.rolloutIdMap[t.rolloutId];if(!o)return this.logger.log(f.ERROR,l(E.INVALID_ROLLOUT_ID,c,t.rolloutId,t.key)),{experiment:null,variation:null,decisionSource:_.ROLLOUT};if(0===o.experiments.length)return this.logger.log(f.ERROR,l(p.ROLLOUT_HAS_NO_EXPERIMENTS,c,t.rolloutId)),{experiment:null,variation:null,decisionSource:_.ROLLOUT};var a,s,u,d,g,I=this._getBucketingId(r,i),h=o.experiments.length-1;for(a=0;a0){var r=i(e[0],t);return null===r?null:!r}return null}(o,t);default:return function(e,t){for(var r=!1,n=0;nE},c.lt=function(e,t,r){var n=e.name,l=t[e.name],c=typeof l,E=e.value;if(!i.isSafeInteger(E))return r.log(a.WARNING,o(s.UNEXPECTED_CONDITION_VALUE,u,JSON.stringify(e))),null;if(null===l)return r.log(a.DEBUG,o(s.UNEXPECTED_TYPE_NULL,u,JSON.stringify(e),n)),null;if(!i.isNumber(l))return r.log(a.WARNING,o(s.UNEXPECTED_TYPE,u,JSON.stringify(e),c,n)),null;if(!i.isSafeInteger(l))return r.log(a.WARNING,o(s.OUT_OF_BOUNDS,u,JSON.stringify(e),n)),null;return l>>16)*a&65535)<<16)&4294967295)<<15|u>>>17))*s+(((u>>>16)*s&65535)<<16)&4294967295)<<13|n>>>19))+((5*(n>>>16)&65535)<<16)&4294967295))+((58964+(o>>>16)&65535)<<16);switch(u=0,r){case 3:u^=(255&e.charCodeAt(l+2))<<16;case 2:u^=(255&e.charCodeAt(l+1))<<8;case 1:n^=u=(65535&(u=(u=(65535&(u^=255&e.charCodeAt(l)))*a+(((u>>>16)*a&65535)<<16)&4294967295)<<15|u>>>17))*s+(((u>>>16)*s&65535)<<16)&4294967295}return n^=e.length,n=2246822507*(65535&(n^=n>>>16))+((2246822507*(n>>>16)&65535)<<16)&4294967295,n=3266489909*(65535&(n^=n>>>13))+((3266489909*(n>>>16)&65535)<<16)&4294967295,(n^=n>>>16)>>>0}var r=t;r.v2=function(e,t){for(var r,i=e.length,n=t^i,o=0;i>=4;)r=1540483477*(65535&(r=255&e.charCodeAt(o)|(255&e.charCodeAt(++o))<<8|(255&e.charCodeAt(++o))<<16|(255&e.charCodeAt(++o))<<24))+((1540483477*(r>>>16)&65535)<<16),n=1540483477*(65535&n)+((1540483477*(n>>>16)&65535)<<16)^(r=1540483477*(65535&(r^=r>>>24))+((1540483477*(r>>>16)&65535)<<16)),i-=4,++o;switch(i){case 3:n^=(255&e.charCodeAt(o+2))<<16;case 2:n^=(255&e.charCodeAt(o+1))<<8;case 1:n=1540483477*(65535&(n^=255&e.charCodeAt(o)))+((1540483477*(n>>>16)&65535)<<16)}return n=1540483477*(65535&(n^=n>>>13))+((1540483477*(n>>>16)&65535)<<16),(n^=n>>>15)>>>0},r.v3=t,e.exports=r}()},function(e,t){e.exports={$schema:"http://json-schema.org/draft-04/schema#",type:"object",properties:{projectId:{type:"string",required:!0},accountId:{type:"string",required:!0},groups:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},policy:{type:"string",required:!0},trafficAllocation:{type:"array",items:{type:"object",properties:{entityId:{type:"string",required:!0},endOfRange:{type:"integer",required:!0}}},required:!0},experiments:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0},status:{type:"string",required:!0},layerId:{type:"string",required:!0},variations:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0}}},required:!0},trafficAllocation:{type:"array",items:{type:"object",properties:{entityId:{type:"string",required:!0},endOfRange:{type:"integer",required:!0}}},required:!0},audienceIds:{type:"array",items:{type:"string"},required:!0},forcedVariations:{type:"object",required:!0}}},required:!0}}},required:!0},experiments:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0},status:{type:"string",required:!0},layerId:{type:"string",required:!0},variations:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0}}},required:!0},trafficAllocation:{type:"array",items:{type:"object",properties:{entityId:{type:"string",required:!0},endOfRange:{type:"integer",required:!0}}},required:!0},audienceIds:{type:"array",items:{type:"string"},required:!0},forcedVariations:{type:"object",required:!0}}},required:!0},events:{type:"array",items:{type:"object",properties:{key:{type:"string",required:!0},experimentIds:{type:"array",items:{type:"string",required:!0}},id:{type:"string",required:!0}}},required:!0},audiences:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},name:{type:"string",required:!0},conditions:{type:"string",required:!0}}},required:!0},attributes:{type:"array",items:{type:"object",properties:{id:{type:"string",required:!0},key:{type:"string",required:!0}}},required:!0},version:{type:"string",required:!0},revision:{type:"string",required:!0}}}},function(e,t,r){var i=r(1),n=r(3),o=r(18),a=r(4),s=r(7),u="https://logx.optimizely.com/v1/events";function l(e){var t=e.attributes,r=e.configObj,n=r.anonymizeIP,o=r.botFiltering;null==n&&(n=!1);var u={snapshots:[],visitor_id:e.userId,attributes:[]},l={account_id:r.accountId,project_id:r.projectId,visitors:[u],revision:r.revision,client_name:e.clientEngine,client_version:e.clientVersion,anonymize_ip:n,enrich_decisions:!0};return Object.keys(t||{}).forEach((function(r){var i=t[r];if(s.isAttributeValid(r,i)){var n=a.getAttributeId(e.configObj,r,e.logger);n&&l.visitors[0].attributes.push({entity_id:n,key:r,type:"custom",value:t[r]})}})),"boolean"==typeof o&&l.visitors[0].attributes.push({entity_id:i.CONTROL_ATTRIBUTES.BOT_FILTERING,key:i.CONTROL_ATTRIBUTES.BOT_FILTERING,type:"custom",value:o}),l}e.exports={getImpressionEvent:function(e){var t={httpVerb:"POST"},r=l(e);t.url=u;var i,o,s,c=(i=e.configObj,o=e.experimentId,s=e.variationId,{decisions:[{campaign_id:a.getLayerId(i,o),experiment_id:o,variation_id:s}],events:[{entity_id:a.getLayerId(i,o),timestamp:n.currentTimestamp(),key:"campaign_activated",uuid:n.uuid()}]});return r.visitors[0].snapshots.push(c),t.params=r,t},getConversionEvent:function(e){var t={httpVerb:"POST"},r=l(e);t.url=u;var s=function(e,t,r,s){var u={events:[]},l={entity_id:a.getEventId(e,t),timestamp:n.currentTimestamp(),uuid:n.uuid(),key:t};if(r){var c=o.getRevenueValue(r,s);null!==c&&(l[i.RESERVED_EVENT_KEYWORDS.REVENUE]=c);var E=o.getEventValue(r,s);null!==E&&(l[i.RESERVED_EVENT_KEYWORDS.VALUE]=E),l.tags=r}return u.events.push(l),u}(e.configObj,e.eventKey,e.eventTags,e.logger);return r.visitors[0].snapshots=[s],t.params=r,t}}},function(e,t,r){var i=r(2),n=r(7),o=r(3),a=r(18),s=r(4),u=i.getLogger("EVENT_BUILDER");function l(e,t){var r=[];return Object.keys(t||{}).forEach((function(i){var o=t[i];if(n.isAttributeValid(i,o)){var a=s.getAttributeId(e,i,u);a&&r.push({entityId:a,key:i,value:t[i]})}})),r}t.buildImpressionEvent=function(e){var t=e.configObj,r=e.experimentKey,i=e.variationKey,n=e.userId,a=e.userAttributes,u=e.clientEngine,c=e.clientVersion,E=s.getVariationIdFromExperimentAndVariationKey(t,r,i),f=s.getExperimentId(t,r),p=s.getLayerId(t,f);return{type:"impression",timestamp:o.currentTimestamp(),uuid:o.uuid(),user:{id:n,attributes:l(t,a)},context:{accountId:t.accountId,projectId:t.projectId,revision:t.revision,clientName:u,clientVersion:c,anonymizeIP:t.anonymizeIP||!1,botFiltering:t.botFiltering},layer:{id:p},experiment:{id:f,key:r},variation:{id:E,key:i}}},t.buildConversionEvent=function(e){var t=e.configObj,r=e.userId,i=e.userAttributes,n=e.clientEngine,c=e.clientVersion,E=e.eventKey,f=e.eventTags,p=s.getEventId(t,E);return{type:"conversion",timestamp:o.currentTimestamp(),uuid:o.uuid(),user:{id:r,attributes:l(t,i)},context:{accountId:t.accountId,projectId:t.projectId,revision:t.revision,clientName:n,clientVersion:c,anonymizeIP:t.anonymizeIP||!1,botFiltering:t.botFiltering},event:{id:p,key:E},revenue:a.getRevenueValue(f,u),value:a.getEventValue(f,u),tags:f}}},function(e,t,r){var i=r(0).sprintf,n=r(1).ERROR_MESSAGES;e.exports={validate:function(e){if("object"!=typeof e||Array.isArray(e)||null===e)throw new Error(i(n.INVALID_EVENT_TAGS,"EVENT_TAGS_VALIDATOR"));return!0}}},function(e,t,r){var i=r(1),n=r(0),o=i.LOG_LEVEL,a=i.LOG_MESSAGES;function s(e){this.logger=e.logger,this.errorHandler=e.errorHandler,this.__notificationListeners={},n.objectValues(i.NOTIFICATION_TYPES).forEach(function(e){this.__notificationListeners[e]=[]}.bind(this)),this.__listenerId=1}s.prototype.addNotificationListener=function(e,t){try{if(!(n.objectValues(i.NOTIFICATION_TYPES).indexOf(e)>-1))return-1;this.__notificationListeners[e]||(this.__notificationListeners[e]=[]);var r=!1;if((this.__notificationListeners[e]||[]).forEach((function(e){if(e.callback===t)return r=!0,!1})),r)return-1;this.__notificationListeners[e].push({id:this.__listenerId,callback:t});var a=this.__listenerId;return this.__listenerId+=1,a}catch(e){return this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e),-1}},s.prototype.removeNotificationListener=function(e){try{var t,r;if(Object.keys(this.__notificationListeners).some(function(i){if((this.__notificationListeners[i]||[]).every((function(n,o){return n.id!==e||(t=o,r=i,!1)})),void 0!==t&&void 0!==r)return!0}.bind(this)),void 0!==t&&void 0!==r)return this.__notificationListeners[r].splice(t,1),!0}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}return!1},s.prototype.clearAllNotificationListeners=function(){try{n.objectValues(i.NOTIFICATION_TYPES).forEach(function(e){this.__notificationListeners[e]=[]}.bind(this))}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}},s.prototype.clearNotificationListeners=function(e){try{this.__notificationListeners[e]=[]}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}},s.prototype.sendNotifications=function(e,t){try{(this.__notificationListeners[e]||[]).forEach(function(r){var i=r.callback;try{i(t)}catch(t){this.logger.log(o.ERROR,n.sprintf(a.NOTIFICATION_LISTENER_EXCEPTION,"NOTIFICATION_CENTER",e,t.message))}}.bind(this))}catch(e){this.logger.log(o.ERROR,e.message),this.errorHandler.handleError(e)}},e.exports={createNotificationCenter:function(e){return new s(e)}}},function(e,t,r){var i=r(0).sprintf,n=r(1).ERROR_MESSAGES;e.exports={validate:function(e){if("function"!=typeof e.lookup)throw new Error(i(n.INVALID_USER_PROFILE_SERVICE,"USER_PROFILE_SERVICE_VALIDATOR","Missing function 'lookup'"));if("function"!=typeof e.save)throw new Error(i(n.INVALID_USER_PROFILE_SERVICE,"USER_PROFILE_SERVICE_VALIDATOR","Missing function 'save'"));return!0}}},function(e,t,r){var i=r(3),n=r(0).sprintf,o=r(2),a=r(6),s=r(46),u=r(1),l=r(4),c=r(54),E=o.getLogger(),f=u.ERROR_MESSAGES;function p(e,t){return e instanceof Error?e.message:t||"Unknown error"}function _(e){try{this.__initialize(e)}catch(e){E.error(e),this.__updateListeners=[],this.__configObj=null,this.__optimizelyConfigObj=null,this.__readyPromise=Promise.resolve({success:!1,reason:p(e,"Error in initialize")})}}_.prototype.__initialize=function(e){if(this.__updateListeners=[],this.jsonSchemaValidator=e.jsonSchemaValidator,this.skipJSONValidation=e.skipJSONValidation,!e.datafile&&!e.sdkKey){this.__configObj=null;var t=new Error(n(f.DATAFILE_AND_SDK_KEY_MISSING,"PROJECT_CONFIG_MANAGER"));return this.__readyPromise=Promise.resolve({success:!1,reason:p(t)}),void E.error(t)}var r,o=this.__getDatafileFromConfig(e);if(o)try{this.__configObj=l.tryCreatingProjectConfig({datafile:o,jsonSchemaValidator:this.jsonSchemaValidator,logger:E,skipJSONValidation:this.skipJSONValidation}),this.__optimizelyConfigObj=c.getOptimizelyConfig(this.__configObj)}catch(e){E.error(e),r=e,this.__configObj=null}else this.__configObj=null;if(e.sdkKey){var a={sdkKey:e.sdkKey};this.__validateDatafileOptions(e.datafileOptions)&&i.assign(a,e.datafileOptions),o&&this.__configObj&&(a.datafile=o),this.datafileManager=new s.HttpPollingDatafileManager(a),this.datafileManager.start(),this.__readyPromise=this.datafileManager.onReady().then(this.__onDatafileManagerReadyFulfill.bind(this),this.__onDatafileManagerReadyReject.bind(this)),this.datafileManager.on("update",this.__onDatafileManagerUpdate.bind(this))}else this.__configObj?this.__readyPromise=Promise.resolve({success:!0}):this.__readyPromise=Promise.resolve({success:!1,reason:p(r,"Invalid datafile")})},_.prototype.__onDatafileManagerReadyFulfill=function(){var e,t=this.datafileManager.get();try{e=l.tryCreatingProjectConfig({datafile:t,jsonSchemaValidator:this.jsonSchemaValidator,logger:E,skipJSONValidation:this.skipJSONValidation})}catch(e){return E.error(e),{success:!1,reason:p(e)}}return this.__handleNewConfigObj(e),{success:!0}},_.prototype.__onDatafileManagerReadyReject=function(e){return{success:!1,reason:p(e,"Failed to become ready")}},_.prototype.__onDatafileManagerUpdate=function(){var e,t=this.datafileManager.get();try{e=l.tryCreatingProjectConfig({datafile:t,jsonSchemaValidator:this.jsonSchemaValidator,logger:E,skipJSONValidation:this.skipJSONValidation})}catch(e){E.error(e)}e&&this.__handleNewConfigObj(e)},_.prototype.__getDatafileFromConfig=function(e){var t=null;try{e.datafile&&(a.validateDatafile(e.datafile),t="string"==typeof e.datafile||e.datafile instanceof String?JSON.parse(e.datafile):e.datafile)}catch(e){E.error(e)}return t},_.prototype.__validateDatafileOptions=function(e){return void 0===e||"object"==typeof e&&null!==e},_.prototype.__handleNewConfigObj=function(e){var t=this.__configObj;(t?t.revision:"null")!==e.revision&&(this.__configObj=e,this.__optimizelyConfigObj=c.getOptimizelyConfig(e),this.__updateListeners.forEach((function(t){t(e)})))},_.prototype.getConfig=function(){return this.__configObj},_.prototype.getOptimizelyConfig=function(){return this.__optimizelyConfigObj},_.prototype.onReady=function(){return this.__readyPromise},_.prototype.onUpdate=function(e){return this.__updateListeners.push(e),function(){var t=this.__updateListeners.indexOf(e);t>-1&&this.__updateListeners.splice(t,1)}.bind(this)},_.prototype.stop=function(){this.datafileManager&&this.datafileManager.stop(),this.__updateListeners=[]},e.exports={ProjectConfigManager:_}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(47);t.HttpPollingDatafileManager=i.default;var n=r(53);t.StaticDatafileManager=n.default},function(e,t,r){"use strict";var i,n=this&&this.__extends||(i=function(e,t){return(i=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r])})(e,t)},function(e,t){function r(){this.constructor=e}i(e,t),e.prototype=null===t?Object.create(t):(r.prototype=t.prototype,new r)}),o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var a=r(48),s=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return n(t,e),t.prototype.makeGetRequest=function(e,t){return a.makeGetRequest(e,t)},t.prototype.getConfigDefaults=function(){return{autoUpdate:!1}},t}(o(r(49)).default);t.default=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(8),n=r(2).getLogger("DatafileManager");t.makeGetRequest=function(e,t){var r=new XMLHttpRequest;return{responsePromise:new Promise((function(o,a){r.open("GET",e,!0),function(e,t){Object.keys(e).forEach((function(r){var i=e[r];t.setRequestHeader(r,i)}))}(t,r),r.onreadystatechange=function(){if(4===r.readyState){if(0===r.status)return void a(new Error("Request error"));var e=function(e){var t=e.getAllResponseHeaders();if(null===t)return{};var r=t.split("\r\n"),i={};return r.forEach((function(e){var t=e.indexOf(": ");if(t>-1){var r=e.slice(0,t),n=e.slice(t+2);n.length>0&&(i[r]=n)}})),i}(r),t={statusCode:r.status,body:r.responseText,headers:e};o(t)}},r.timeout=i.REQUEST_TIMEOUT_MS,r.ontimeout=function(){n.error("Request timed out")},r.send()})),abort:function(){r.abort()}}}},function(e,t,r){"use strict";var i=this&&this.__assign||function(){return(i=Object.assign||function(e){for(var t,r=1,i=arguments.length;r=200&&e<400}var f=function(){function e(e){var t=this,r=i({},this.getConfigDefaults(),e),n=r.datafile,o=r.autoUpdate,E=void 0!==o&&o,f=r.sdkKey,p=r.updateInterval,_=void 0===p?u.DEFAULT_UPDATE_INTERVAL:p,d=r.urlTemplate,g=void 0===d?u.DEFAULT_URL_TEMPLATE:d;this.isReadyPromiseSettled=!1,this.readyPromiseResolver=function(){},this.readyPromiseRejecter=function(){},this.readyPromise=new Promise((function(e,r){t.readyPromiseResolver=e,t.readyPromiseRejecter=r})),n?(this.currentDatafile=n,this.resolveReadyPromise()):this.currentDatafile=null,this.isStarted=!1,this.datafileUrl=a.sprintf(g,f),this.emitter=new s.default,this.autoUpdate=E,!function(e){return e>=u.MIN_UPDATE_INTERVAL}(_)?(c.warn("Invalid updateInterval %s, defaulting to %s",_,u.DEFAULT_UPDATE_INTERVAL),this.updateInterval=u.DEFAULT_UPDATE_INTERVAL):this.updateInterval=_,this.currentTimeout=null,this.currentRequest=null,this.backoffController=new l.default,this.syncOnCurrentRequestComplete=!1}return e.prototype.get=function(){return this.currentDatafile},e.prototype.start=function(){this.isStarted||(c.debug("Datafile manager started"),this.isStarted=!0,this.backoffController.reset(),this.syncDatafile())},e.prototype.stop=function(){return c.debug("Datafile manager stopped"),this.isStarted=!1,this.currentTimeout&&(clearTimeout(this.currentTimeout),this.currentTimeout=null),this.emitter.removeAllListeners(),this.currentRequest&&(this.currentRequest.abort(),this.currentRequest=null),Promise.resolve()},e.prototype.onReady=function(){return this.readyPromise},e.prototype.on=function(e,t){return this.emitter.on(e,t)},e.prototype.onRequestRejected=function(e){this.isStarted&&(this.backoffController.countError(),e instanceof Error?c.error("Error fetching datafile: %s",e.message,e):"string"==typeof e?c.error("Error fetching datafile: %s",e):c.error("Error fetching datafile"))},e.prototype.onRequestResolved=function(e){if(this.isStarted){void 0!==e.statusCode&&E(e.statusCode)?this.backoffController.reset():this.backoffController.countError(),this.trySavingLastModified(e.headers);var t=this.getNextDatafileFromResponse(e);if(null!==t)if(c.info("Updating datafile from response"),this.currentDatafile=t,this.isReadyPromiseSettled){var r={datafile:t};this.emitter.emit("update",r)}else this.resolveReadyPromise()}},e.prototype.onRequestComplete=function(){this.isStarted&&(this.currentRequest=null,this.isReadyPromiseSettled||this.autoUpdate||this.rejectReadyPromise(new Error("Failed to become ready")),this.autoUpdate&&this.syncOnCurrentRequestComplete&&this.syncDatafile(),this.syncOnCurrentRequestComplete=!1)},e.prototype.syncDatafile=function(){var e=this,t={};this.lastResponseLastModified&&(t["if-modified-since"]=this.lastResponseLastModified),c.debug("Making datafile request to url %s with headers: %s",this.datafileUrl,(function(){return JSON.stringify(t)})),this.currentRequest=this.makeGetRequest(this.datafileUrl,t);var r=function(){e.onRequestComplete()};this.currentRequest.responsePromise.then((function(t){e.onRequestResolved(t)}),(function(t){e.onRequestRejected(t)})).then(r,r),this.autoUpdate&&this.scheduleNextUpdate()},e.prototype.resolveReadyPromise=function(){this.readyPromiseResolver(),this.isReadyPromiseSettled=!0},e.prototype.rejectReadyPromise=function(e){this.readyPromiseRejecter(e),this.isReadyPromiseSettled=!0},e.prototype.scheduleNextUpdate=function(){var e=this,t=this.backoffController.getDelay(),r=Math.max(t,this.updateInterval);c.debug("Scheduling sync in %s ms",r),this.currentTimeout=setTimeout((function(){e.currentRequest?e.syncOnCurrentRequestComplete=!0:e.syncDatafile()}),r)},e.prototype.getNextDatafileFromResponse=function(e){return c.debug("Response status code: %s",e.statusCode),void 0===e.statusCode||304===e.statusCode?null:E(e.statusCode)?this.tryParsingBodyAsJSON(e.body):null},e.prototype.tryParsingBodyAsJSON=function(e){var t;try{t=JSON.parse(e)}catch(e){return c.error("Error parsing response body: %s",e.message,e),null}var r=null;return"object"==typeof t&&null!==t?r=t:c.error("Error parsing response body: was not an object"),r},e.prototype.trySavingLastModified=function(e){var t=e["last-modified"]||e["Last-Modified"];void 0!==t&&(this.lastResponseLastModified=t,c.debug("Saved last modified header value from response: %s",this.lastResponseLastModified))},e}();t.default=f},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=r(5);function n(e){return Object.keys(e).map((function(t){return e[t]}))}t.getTimestamp=function(){return(new Date).getTime()},t.generateUUID=function(){return i.v4()},t.isValidEnum=function(e,t){for(var r=!1,i=Object.keys(e),n=0;n=1},validateEventFlushInterval:function(e){return i.isSafeInteger(e)&&e>0}}}])})); \ No newline at end of file