UNPKG

rox-browser

Version:

Rollout.io ROX JS SDK Client

1,409 lines (1,232 loc) 343 kB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("axios")); else if(typeof define === 'function' && define.amd) define(["axios"], factory); else if(typeof exports === 'object') exports["Rox"] = factory(require("axios")); else root["Rox"] = factory(root["axios"]); })(globalThis, (__WEBPACK_EXTERNAL_MODULE__85__) => { return /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ([ /* 0 */, /* 1 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _RoxClient__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2); /* harmony import */ var _FreezeOptions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(51); /* harmony import */ var rox_base__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(54); /* harmony import */ var rox_base__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(16); /* harmony import */ var rox_base__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(39); /* harmony import */ var rox_base__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(30); /* harmony import */ var _RoxStringBrowser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(46); /* harmony import */ var _RoxNumberBrowser__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(55); /* harmony import */ var _RoxFlagBrowser__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(56); /* harmony import */ var _DebuggerUI__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(91); /* harmony import */ var _Overrider__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(52); class Rox { constructor() { this.RoxString = _RoxStringBrowser__WEBPACK_IMPORTED_MODULE_2__["default"]; this.RoxNumber = _RoxNumberBrowser__WEBPACK_IMPORTED_MODULE_3__["default"]; this.setContext = rox_base__WEBPACK_IMPORTED_MODULE_7__.setContext; this.Flag = _RoxFlagBrowser__WEBPACK_IMPORTED_MODULE_4__["default"]; this.showOverrides = _DebuggerUI__WEBPACK_IMPORTED_MODULE_5__.open; this.overrides = _Overrider__WEBPACK_IMPORTED_MODULE_6__; } /** * Initiate connection with ROX servers for the application identified by the application key. The registered containers will be synced and Rox entities will get the appropriate values. * @param {String} appKey application key as appears in ROX dashboard * @param {Object} options optional configuration object */ setup(appKey, options = {}) { rox_base__WEBPACK_IMPORTED_MODULE_8__["default"].setVerboseMode(options.debugLevel); if (options.proxy) { rox_base__WEBPACK_IMPORTED_MODULE_9__["default"].setProxy(options.proxy); } if (options.freeze) { (0,_FreezeOptions__WEBPACK_IMPORTED_MODULE_1__.setDefaultFreezeOption)(options.freeze); } _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setKey(appKey, options); if (options.configuration) { rox_base__WEBPACK_IMPORTED_MODULE_9__["default"].setActive(options.configuration); } else if (options.hosting) { rox_base__WEBPACK_IMPORTED_MODULE_9__["default"].setHosting(options.hosting); } _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setup(options); _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].sendState(); if (options.disableNetworkFetch) { return _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].fetchCacheOnly(); } else { return _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].fetchWithCacheAndProceed(); } } fetch() { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"] && _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].fetch(); } setCustomStringProperty(key, value) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setCustomProperty(key, String, value); } setCustomDateProperty(key, value) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setCustomProperty(key, Date, value); } setCustomNumberProperty(key, value) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setCustomProperty(key, Number, value); } setCustomBooleanProperty(key, value) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setCustomProperty(key, Boolean, value); } setCustomSemverProperty(key, value) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setSemverCustomProperty(key, value); } /** * Register a container of Rox entities by specifying a namespace. * @param {String} name Container name * @param {Object} container Object literal whose properties are Rox entities */ register(name, container) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].register(name, container); } unfreeze(namespace) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].unfreeze(namespace); } get flags() { return rox_base__WEBPACK_IMPORTED_MODULE_10__["default"].flags; } get dynamicApi() { return _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].dynamicApi; } setUserspaceUnhandledErrorHandler(handler) { _RoxClient__WEBPACK_IMPORTED_MODULE_0__["default"].setUserspaceUnhandledErrorHandler(handler); } } const instance = new Rox(); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (instance); /***/ }), /* 2 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var rox_base__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(57); /* harmony import */ var _DeviceProperties__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3); /* harmony import */ var _DefaultSetupOptions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11); /* harmony import */ var _DefaultProperties__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(12); /* harmony import */ var _RoxCache__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5); /* harmony import */ var _RoxCrypto__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(41); /* harmony import */ var _EntitiesProvider__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(45); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ((0,rox_base__WEBPACK_IMPORTED_MODULE_6__.createRoxClient)({ DeviceProperties: _DeviceProperties__WEBPACK_IMPORTED_MODULE_0__["default"], getDefaultCustomProperties: _DefaultProperties__WEBPACK_IMPORTED_MODULE_2__.getDefaultCustomProperties, DefaultSetupOptions: _DefaultSetupOptions__WEBPACK_IMPORTED_MODULE_1__.defaultSetupOptions, RoxCache: _RoxCache__WEBPACK_IMPORTED_MODULE_3__["default"], RoxCrypto: _RoxCrypto__WEBPACK_IMPORTED_MODULE_4__["default"], EntitiesProvider: _EntitiesProvider__WEBPACK_IMPORTED_MODULE_5__["default"] })); /***/ }), /* 3 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var rox_base__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10); /* harmony import */ var _manifest__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4); /* harmony import */ var _RoxCache__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5); /* harmony import */ var uuid_browser_v4__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7); /* harmony import */ var uuid_browser_v4__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(uuid_browser_v4__WEBPACK_IMPORTED_MODULE_2__); const { api_version, lib_version } = _manifest__WEBPACK_IMPORTED_MODULE_0__["default"]; class DeviceProperties extends rox_base__WEBPACK_IMPORTED_MODULE_3__["default"] { getProperties() { const { distinct_id, app_release, platform, realPlatform } = this; return Object.assign({ app_release, api_version, lib_version, distinct_id, platform, realPlatform, customSigningCertificate: '5659eb0ca47811395ef85f0b09be63b7', language: navigator.language, anticache: +Date.now() }, (typeof window === 'undefined' ? {} : { screen_width: window.screen.width, screen_height: window.screen.height, })); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (new DeviceProperties(_RoxCache__WEBPACK_IMPORTED_MODULE_1__["default"], (uuid_browser_v4__WEBPACK_IMPORTED_MODULE_2___default()))); /***/ }), /* 4 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ api_version: '1.9.0', lib_version: '6.0.3' }); /***/ }), /* 5 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var lscache__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6); /* harmony import */ var lscache__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lscache__WEBPACK_IMPORTED_MODULE_0__); class RoxCache { set(key, value, ttl) { lscache__WEBPACK_IMPORTED_MODULE_0___default().set(key, value, ttl); } get(key) { return lscache__WEBPACK_IMPORTED_MODULE_0___default().get(key); } } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (new RoxCache()); /***/ }), /* 6 */ /***/ (function(module, exports) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/** * lscache library * Copyright (c) 2011, Pamela Fox * * 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. */ /* jshint undef:true, browser:true, node:true */ /* global define */ (function (root, factory) { if (true) { // AMD. Register as an anonymous module. !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else {} }(this, function () { // Prefix for all lscache keys var CACHE_PREFIX = 'lscache-'; // Suffix for the key name on the expiration items in localStorage var CACHE_SUFFIX = '-cacheexpiration'; // expiration date radix (set to Base-36 for most space savings) var EXPIRY_RADIX = 10; // time resolution in milliseconds var expiryMilliseconds = 60 * 1000; // ECMAScript max Date (epoch + 1e8 days) var maxDate = calculateMaxDate(expiryMilliseconds); var cachedStorage; var cachedJSON; var cacheBucket = ''; var warnings = false; // Determines if localStorage is supported in the browser; // result is cached for better performance instead of being run each time. // Feature detection is based on how Modernizr does it; // it's not straightforward due to FF4 issues. // It's not run at parse-time as it takes 200ms in Android. function supportsStorage() { var key = '__lscachetest__'; var value = key; if (cachedStorage !== undefined) { return cachedStorage; } // some browsers will throw an error if you try to access local storage (e.g. brave browser) // hence check is inside a try/catch try { if (!localStorage) { return false; } } catch (ex) { return false; } try { setItem(key, value); removeItem(key); cachedStorage = true; } catch (e) { // If we hit the limit, and we don't have an empty localStorage then it means we have support if (isOutOfSpace(e) && localStorage.length) { cachedStorage = true; // just maxed it out and even the set test failed. } else { cachedStorage = false; } } return cachedStorage; } // Check to set if the error is us dealing with being out of space function isOutOfSpace(e) { return e && ( e.name === 'QUOTA_EXCEEDED_ERR' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED' || e.name === 'QuotaExceededError' ); } // Determines if native JSON (de-)serialization is supported in the browser. function supportsJSON() { /*jshint eqnull:true */ if (cachedJSON === undefined) { cachedJSON = (window.JSON != null); } return cachedJSON; } /** * Returns a string where all RegExp special characters are escaped with a \. * @param {String} text * @return {string} */ function escapeRegExpSpecialCharacters(text) { return text.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&'); } /** * Returns the full string for the localStorage expiration item. * @param {String} key * @return {string} */ function expirationKey(key) { return key + CACHE_SUFFIX; } /** * Returns the number of minutes since the epoch. * @return {number} */ function currentTime() { return Math.floor((new Date().getTime())/expiryMilliseconds); } /** * Wrapper functions for localStorage methods */ function getItem(key) { return localStorage.getItem(CACHE_PREFIX + cacheBucket + key); } function setItem(key, value) { // Fix for iPad issue - sometimes throws QUOTA_EXCEEDED_ERR on setItem. localStorage.removeItem(CACHE_PREFIX + cacheBucket + key); localStorage.setItem(CACHE_PREFIX + cacheBucket + key, value); } function removeItem(key) { localStorage.removeItem(CACHE_PREFIX + cacheBucket + key); } function eachKey(fn) { var prefixRegExp = new RegExp('^' + CACHE_PREFIX + escapeRegExpSpecialCharacters(cacheBucket) + '(.*)'); // We first identify which keys to process var keysToProcess = []; var key, i; for (i = 0; i < localStorage.length; i++) { key = localStorage.key(i); key = key && key.match(prefixRegExp); key = key && key[1]; if (key && key.indexOf(CACHE_SUFFIX) < 0) { keysToProcess.push(key); } } // Then we apply the processing function to each key for (i = 0; i < keysToProcess.length; i++) { fn(keysToProcess[i], expirationKey(keysToProcess[i])); } } function flushItem(key) { var exprKey = expirationKey(key); removeItem(key); removeItem(exprKey); } function flushExpiredItem(key) { var exprKey = expirationKey(key); var expr = getItem(exprKey); if (expr) { var expirationTime = parseInt(expr, EXPIRY_RADIX); // Check if we should actually kick item out of storage if (currentTime() >= expirationTime) { removeItem(key); removeItem(exprKey); return true; } } } function warn(message, err) { if (!warnings) return; if (!('console' in window) || typeof window.console.warn !== 'function') return; window.console.warn("lscache - " + message); if (err) window.console.warn("lscache - The error was: " + err.message); } function calculateMaxDate(expiryMilliseconds) { return Math.floor(8.64e15/expiryMilliseconds); } var lscache = { /** * Stores the value in localStorage. Expires after specified number of minutes. * @param {string} key * @param {Object|string} value * @param {number} time * @return {boolean} whether the value was inserted successfully */ set: function(key, value, time) { if (!supportsStorage()) return false; // If we don't get a string value, try to stringify // In future, localStorage may properly support storing non-strings // and this can be removed. if (!supportsJSON()) return false; try { value = JSON.stringify(value); } catch (e) { // Sometimes we can't stringify due to circular refs // in complex objects, so we won't bother storing then. return false; } try { setItem(key, value); } catch (e) { if (isOutOfSpace(e)) { // If we exceeded the quota, then we will sort // by the expire time, and then remove the N oldest var storedKeys = []; var storedKey; eachKey(function(key, exprKey) { var expiration = getItem(exprKey); if (expiration) { expiration = parseInt(expiration, EXPIRY_RADIX); } else { // TODO: Store date added for non-expiring items for smarter removal expiration = maxDate; } storedKeys.push({ key: key, size: (getItem(key) || '').length, expiration: expiration }); }); // Sorts the keys with oldest expiration time last storedKeys.sort(function(a, b) { return (b.expiration-a.expiration); }); var targetSize = (value||'').length; while (storedKeys.length && targetSize > 0) { storedKey = storedKeys.pop(); warn("Cache is full, removing item with key '" + storedKey.key + "'"); flushItem(storedKey.key); targetSize -= storedKey.size; } try { setItem(key, value); } catch (e) { // value may be larger than total quota warn("Could not add item with key '" + key + "', perhaps it's too big?", e); return false; } } else { // If it was some other error, just give up. warn("Could not add item with key '" + key + "'", e); return false; } } // If a time is specified, store expiration info in localStorage if (time) { setItem(expirationKey(key), (currentTime() + time).toString(EXPIRY_RADIX)); } else { // In case they previously set a time, remove that info from localStorage. removeItem(expirationKey(key)); } return true; }, /** * Retrieves specified value from localStorage, if not expired. * @param {string} key * @return {string|Object} */ get: function(key) { if (!supportsStorage()) return null; // Return the de-serialized item if not expired if (flushExpiredItem(key)) { return null; } // Tries to de-serialize stored value if its an object, and returns the normal value otherwise. var value = getItem(key); if (!value || !supportsJSON()) { return value; } try { // We can't tell if its JSON or a string, so we try to parse return JSON.parse(value); } catch (e) { // If we can't parse, it's probably because it isn't an object return value; } }, /** * Removes a value from localStorage. * Equivalent to 'delete' in memcache, but that's a keyword in JS. * @param {string} key */ remove: function(key) { if (!supportsStorage()) return; flushItem(key); }, /** * Returns whether local storage is supported. * Currently exposed for testing purposes. * @return {boolean} */ supported: function() { return supportsStorage(); }, /** * Flushes all lscache items and expiry markers without affecting rest of localStorage */ flush: function() { if (!supportsStorage()) return; eachKey(function(key) { flushItem(key); }); }, /** * Flushes expired lscache items and expiry markers without affecting rest of localStorage */ flushExpired: function() { if (!supportsStorage()) return; eachKey(function(key) { flushExpiredItem(key); }); }, /** * Appends CACHE_PREFIX so lscache will partition data in to different buckets. * @param {string} bucket */ setBucket: function(bucket) { cacheBucket = bucket; }, /** * Resets the string being appended to CACHE_PREFIX so lscache will use the default storage behavior. */ resetBucket: function() { cacheBucket = ''; }, /** * @returns {number} The currently set number of milliseconds each time unit represents in * the set() function's "time" argument. */ getExpiryMilliseconds: function() { return expiryMilliseconds; }, /** * Sets the number of milliseconds each time unit represents in the set() function's * "time" argument. * Sample values: * 1: each time unit = 1 millisecond * 1000: each time unit = 1 second * 60000: each time unit = 1 minute (Default value) * 360000: each time unit = 1 hour * @param {number} milliseconds */ setExpiryMilliseconds: function(milliseconds) { expiryMilliseconds = milliseconds; maxDate = calculateMaxDate(expiryMilliseconds); }, /** * Sets whether to display warnings when an item is removed from the cache or not. */ enableWarnings: function(enabled) { warnings = enabled; } }; // Return the module return lscache; })); /***/ }), /* 7 */ /***/ ((module, __unused_webpack_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; /***/ }), /* 8 */ /***/ ((module) => { // 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 var rng; var crypto = typeof window !== 'undefined' && (window.crypto || window.msCrypto); // for IE 11 if (crypto && crypto.getRandomValues) { // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef rng = function whatwgRNG() { crypto.getRandomValues(rnds8); return rnds8; }; } if (!rng) { // Math.random()-based (RNG) // // If all else fails, use Math.random(). It's fast, but is of unspecified // quality. var rnds = new Array(16); rng = function() { 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; }; } module.exports = rng; /***/ }), /* 9 */ /***/ ((module) => { /** * 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; 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++]]; } module.exports = bytesToUuid; /***/ }), /* 10 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ DeviceProperties) /* harmony export */ }); class DeviceProperties { constructor(cache, uuid) { this.cache = cache; this._uuid = uuid; this.distinct_id = this.generateDistinctId(); this.app_release = '0.0'; this.distinctIdSetExplicitly = false; } setPlatform(platform) { this.platform = platform; } setRealPlatform(realPlatform) { this.realPlatform = realPlatform; } setDistinctId(id) { this.distinctIdSetExplicitly = true; this.distinct_id = id; } setAppRelease(appRelease) { this.app_release = appRelease; } uuid() { return this._uuid(); } generateDistinctId() { let distinct_id = this.cache.get('distinctId'); if (!distinct_id) { distinct_id = this.uuid(); this.cache.set('distinctId', distinct_id); } return distinct_id; } } /***/ }), /* 11 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ defaultSetupOptions: () => (/* binding */ defaultSetupOptions) /* harmony export */ }); const defaultSetupOptions = { distinctId: null, version: '0', configurationFetchedHandler: function () { }, impressionHandler: null, devModeSecret: null, platform: 'Browser', analytics: { flushAt: 20, flushInterval: 1000 } }; /***/ }), /* 12 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getDefaultCustomProperties: () => (/* binding */ getDefaultCustomProperties) /* harmony export */ }); /* harmony import */ var rox_base__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(13); const { CustomProperty } = rox_base__WEBPACK_IMPORTED_MODULE_0__; function getDefaultCustomProperties(deviceProps, appKey) { const _props = deviceProps.getProperties(); return [ new CustomProperty('rox.app_release', CustomProperty.semverTypeName, _props.app_release), new CustomProperty('rox.platform', String, _props.platform), new CustomProperty('rox.screen_width', Number, _props.screen_width), new CustomProperty('rox.screen_height', Number, _props.screen_height), new CustomProperty('rox.language', String, _props.language), new CustomProperty('rox.distinct_id', String, _props.distinct_id), new CustomProperty('rox.internal.realPlatform', String, 'Browser'), new CustomProperty('rox.internal.customPlatform', String, _props.platform), new CustomProperty('rox.internal.appKey', String, appKey), new CustomProperty('rox.internal.distinct_id', String, _props.distinct_id), new CustomProperty('rox.now', Date, () => new Date()), ]; } /***/ }), /* 13 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ CallContextTypes: () => (/* reexport safe */ _RoxStringBase__WEBPACK_IMPORTED_MODULE_5__.callContextTypes), /* harmony export */ CustomProperty: () => (/* reexport safe */ _CustomProperty__WEBPACK_IMPORTED_MODULE_0__["default"]), /* harmony export */ DeploymentConfiguration: () => (/* reexport safe */ _DeploymentConfiguration__WEBPACK_IMPORTED_MODULE_2__["default"]), /* harmony export */ DeviceProperty: () => (/* reexport safe */ _DeviceProperty__WEBPACK_IMPORTED_MODULE_1__["default"]), /* harmony export */ Experiment: () => (/* reexport safe */ _Experiment__WEBPACK_IMPORTED_MODULE_3__["default"]), /* harmony export */ FlagTypes: () => (/* reexport safe */ _RoxStringBase__WEBPACK_IMPORTED_MODULE_5__.FlagTypes), /* harmony export */ RoxStringBase: () => (/* reexport safe */ _RoxStringBase__WEBPACK_IMPORTED_MODULE_5__["default"]), /* harmony export */ TargetGroup: () => (/* reexport safe */ _TargetGroup__WEBPACK_IMPORTED_MODULE_4__["default"]) /* harmony export */ }); /* harmony import */ var _CustomProperty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14); /* harmony import */ var _DeviceProperty__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(17); /* harmony import */ var _DeploymentConfiguration__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(18); /* harmony import */ var _Experiment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(19); /* harmony import */ var _TargetGroup__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20); /* harmony import */ var _RoxStringBase__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(21); /***/ }), /* 14 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ CustomProperty) /* harmony export */ }); /* harmony import */ var _lib_UserspaceUnhandledErrorInvoker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15); const SEM_VER_TYPE = 'Semver'; const _validateName = function (name) { if (typeof name === 'undefined' || name === '') { throw new Error('Custom property must be initialized with a name.'); } }; const _validateExplicitValue = function (type, value) { if (value && value.constructor !== type && value.constructor !== Function) { // add here a condition with a return if we want to validate semver (we usually don't, it's just a string) throw new Error(`Custom property initialized with an invalid type / value combination. (Type: ${type}, Value: ${value})`); } }; const _validateDynamicValue = function (value) { const argsExpected = value.length; if (argsExpected > 1) { throw new Error('Dynamic value of a custom property should be a function with maximum 1 argument'); } }; class CustomProperty { constructor(name, type, value) { if (type === SEM_VER_TYPE) { this._isSemver = true; type = String; } _validateName(name); this._name = name; if (typeof value === 'function') { _validateDynamicValue(value); value.isDynamic = true; this._value = value; } else { _validateExplicitValue(type, value); this._value = () => value; } this._type = type; } get type() { return this.externalType; } get externalType() { if (this._isSemver) { return SEM_VER_TYPE; } if (this._type.name == Date.name) { return CustomProperty.dateTypeName; } return this._type.name; } get name() { return this._name; } getValue(context = {}) { if (this._value && this._value.isDynamic) { try { return this._value(context); } catch (err) { err.isUserError = true; err.trigger = _lib_UserspaceUnhandledErrorInvoker__WEBPACK_IMPORTED_MODULE_0__.ExceptionTrigger.CUSTOM_PROPERTY_GENERATOR; throw err; } } return this._value(context); } static get dateTypeName() { return 'DateTime'; } static get semverTypeName() { return SEM_VER_TYPE; } get value() { return this._value(); } } /***/ }), /* 15 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ExceptionTrigger: () => (/* binding */ ExceptionTrigger), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _RoxLogger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(16); const ExceptionTrigger = { DYNAMIC_PROPERTIES_RULE: 'DYNAMIC_PROPERTIES_RULE', CONFIGURATION_FETCHED_HANDLER: 'CONFIGURATION_FETCHED_HANDLER', IMPRESSION_HANDLER: 'IMPRESSION_HANDLER', CUSTOM_PROPERTY_GENERATOR: 'CUSTOM_PROPERTY_GENERATOR' }; class UserspaceUnhandledErrorInvoker { invoke(exceptionTrigger, error) { if (!this.userUnhandledErrorHandler) { _RoxLogger__WEBPACK_IMPORTED_MODULE_0__["default"].error('User Unhandled Error Occured, no fallback handler was set, exception ignored.', error); return; } try { this.userUnhandledErrorHandler(exceptionTrigger, error); } catch (err) { _RoxLogger__WEBPACK_IMPORTED_MODULE_0__["default"].error('User Unhandled Error Handler itself threw an exception. original exception:' + error, err); } } setHandler(handler) { if (!(handler instanceof Function)) { _RoxLogger__WEBPACK_IMPORTED_MODULE_0__["default"].warn('UserspaceUnhandledErrorHandler must be a function. default will be used.'); return; } this.userUnhandledErrorHandler = handler; } } // wanted to create with new on client.js and pass it as an object, but 'new RoxParser()' appears in too many places :( /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (new UserspaceUnhandledErrorInvoker()); /***/ }), /* 16 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); const levels = { debug: 0, info: 1, warn: 2, error: 3 }; let level = 'error'; class Logger { constructor() { this.debug = (data, ...args) => { if (levels[level] <= levels.debug && console /* console not present on old IEs */) { console.log(data, ...args); // eslint-disable-line no-console } }; this.info = (data, ...args) => { if (levels[level] <= levels.info && console /* console not present on old IEs */) { console.info(data, ...args); // eslint-disable-line no-console } }; this.warn = (data, ...args) => { if (levels[level] <= levels.warn && console /* console not present on old IEs */) { console.warn(data, ...args); // eslint-disable-line no-console } }; this.error = (data, ...args) => { if (console /* console not present on old IEs */) { console.error(data, ...args); // eslint-disable-line no-console } }; this.setVerboseMode = debugLevel => { if (debugLevel === 'verbose') { level = 'debug'; this.debug('Active verbose mode'); } else { level = 'error'; } }; this.setLogger = (newLogger) => { logger = newLogger; }; } } let logger = new Logger(); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (logger); /***/ }), /* 17 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ DeviceProperty) /* harmony export */ }); /* harmony import */ var _CustomProperty__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(14); class DeviceProperty extends _CustomProperty__WEBPACK_IMPORTED_MODULE_0__["default"] { get name() { return `rox.${super.name}`; } } /***/ }), /* 18 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ DeploymentConfiguration) /* harmony export */ }); class DeploymentConfiguration { constructor(condition) { this.condition = condition; } } /***/ }), /* 19 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ Experiment) /* harmony export */ }); class Experiment { constructor(identifier, name, archived, sticky, deploymentConfiguration, flags, labels, stickinessProperty) { this.identifier = identifier; this.name = name; this.archived = archived; this.sticky = sticky; this.deploymentConfiguration = deploymentConfiguration; this.flags = flags; this.labels = labels; this.stickinessProperty = stickinessProperty; } } /***/ }), /* 20 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ TargetGroup) /* harmony export */ }); class TargetGroup { constructor(identifier, condition) { this.identifier = identifier; this.condition = condition; } } /***/ }), /* 21 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FlagTypes: () => (/* binding */ FlagTypes), /* harmony export */ callContextTypes: () => (/* binding */ callContextTypes), /* harmony export */ "default": () => (/* binding */ RoxStringBase) /* harmony export */ }); /* harmony import */ var _lib_ImpressionHandler__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(22); const callContextTypes = { frozenOrCalc: 'frozenValueOrOneTimeEval', oneTimeCalc: 'oneTimeEval', default: 'useFrozen', }; const FlagTypes = { boolean: 'boolean', number: 'number', string: 'string', }; class RoxStringBase { constructor(defaultValue, variations, type) { this._type = type; const stringDefault = this._validateDefault(defaultValue); if (Array.isArray(variations)) { this._validateOptions(variations); this._options = variations.map((v) => v.toString()); } else if (variations === null || variations === undefined) { this._options = []; } else { throw new Error(`RoxStringBase wrong variations type`); } if (this._options.indexOf(stringDefault) === -1) { this._options.push(stringDefault); } this._value = this._defaultValue = stringDefault; this._frozen = false; this._freezable = true; } _validateDefault(defaultValue) { if (typeof defaultValue !== this._type) { throw new Error(`RoxStringBase default value must be of ${this._type} type. Received '${defaultValue}'`); } return defaultValue.toString(); } _validateOptions(variations) { const optionsError = new Error(`RoxStringBase options must be a non-empty array of ${this._type}. Received '${variations}'`); if (!variations.every((option) => typeof option === this._type)) { throw optionsError; } } get defaultValue() { return this._defaultValue; } get overridenValue() { if (this.overrider.hasOverride(this.name)) { return this.overrider.getOverride(this.name); } } get overrider() { throw new Error('Not implemented'); } /* abstract */ // eslint-disable-next-line no-unused-vars getInternalValue(_, __) { throw Error('not implemented'); } get externalType() { switch (this._type) { case FlagTypes.boolean: return Boolean.name; case FlagTypes.number: return Number.name; case FlagTypes.string: return String.name; default: return String.name; } } set name(name) { this._name = name; } get name() { return this._name; } _getNameDetails() { if (!this.name) return; const els = this.name.split('.'); return { name: els.pop(), namespace: els.join('.') || 'default', }; } dump() { const currentValueCall = { type: callContextTypes.frozenOrCalc }; this.getInternalValue(currentValueCall); return { name: this.name, type: this._type, nameDetails: this._getNameDetails(), options: [...this._options], defaultValue: this.defaultValue, originalValue: this._originalValue(), overridingValue: this.overridenValue, value: currentValueCall.result.value, }; } // eslint-disable-next-line no-unused-vars getActiveValue(_, __) { throw new Error('Not implemented'); } _originalValue() { const callContext = { type: callContextTypes.frozenOrCalc }; this.getActiveValue(callContext); return callContext.result.value; } _flagImpression(value, context) { (0,_lib_ImpressionHandler__WEBPACK_IMPORTED_MODULE_0__.invokeImpression)(value, this, context); } static _normalizeString(stringValue) { return stringValue; } static _normalizeNumber(stringValue) { return Number(stringValue); } static _normalizeBoolean(stringValue) { if (typeof stringValue === 'boolean') return stringValue; return stringValue === 'true'; } } /***/ }), /* 22 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ invokeImpression: () => (/* binding */ invokeImpression), /* harmony export */ setAnalytics: () => (/* binding */ setAnalytics), /* harmony export */ setHandler: () => (/* binding */ setHandler) /* harmony export */ }); /* harmony import */ var _RoxLogger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(16); /* harmony import */ var _InternalFlags__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(23); /* harmony import */ var _repositories_ExperimentsRepository__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(31); /* harmony import */ var _repositories_CustomPropertyRepository__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(29); /* harmony import */ var _UserspaceUnhandledErrorInvoker__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(15); let impressionHandler = null; let analytics = null; function invokeImpression(value, flag, context) { const originExperiment = _repositories_ExperimentsRepository__WEBPACK_IMPORTED_MODULE_0__["default"].experimentForFlag(flag); try { if (analytics && (0,_InternalFlags__WEBPACK_IMPORTED_MODULE_1__.isEnabled)('rox.internal.analytics')) { const originalExperimentStickinessPropName = originExperiment && originExperiment.stickinessProperty; let distinctIdProp = originalExperimentStickinessPropName && _repositories_CustomPropertyRepository__WEBPACK_IMPORTED_MODULE_2__["default"].get(originalExperimentStickinessPropName); distinctIdProp = distinctIdProp || _repositories_CustomPropertyRepository__WEBPACK_IMPORTED_MODULE_2__["default"].get(`rox.distinct_id`); const distinctId = distinctIdProp ? distinctIdProp.getValue(context) : ''; analytics.track({ flag: flag.name, value, distinctId, type: 'IMPRESSION', time: new Date().getTime() }); } } catch (err) { _RoxLogger__WEBPACK_IMPORTED_MODULE_3__["default"].error('Failed to send analytics', err); } if (typeof impressionHandler !== 'function') return; const targeting = !!originExperiment; try { impressionHandler({ name: flag.name, value, targeting }, context); } catch (error) { _UserspaceUnhandledErrorInvoker__WEBPACK_IMPORTED_MODULE_4__["default"].invoke(_UserspaceUnhandledErrorInvoker__WEBPACK_IMPORTED_MODULE_4__.ExceptionTrigger.IMPRESSION_HANDLER, error); } } function setHandler(handler) { impressionHandler = handler; } function setAnalytics(a) { analytics = a; } /***/ }), /* 23 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ getNumber: () => (/* binding */ getNumber), /* harmony export */ isEnabled: () => (/* binding */ isEnabled), /* harmony export */ setDefaultsMode: () => (/* binding */ setDefaultsMode), /* harmony export */ value: () => (/* binding */ value) /* harmony export */ }); /* harmony import */ var _parsers_RoxxParser__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(24); /* harmony import */ var _repositories_ExperimentsRepository__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(31); let isDefaultsMode = false; const DEFAULTS = { 'rox.internal.pushUpdates': 'true', 'rox.internal.considerThrottleInPush': 'false', 'rox.internal.throttleFetchInSeconds': '0', 'rox.internal.analytics': 'true', }; function isEnabled(flagName) { const val = value(flagName); if (typeof val === 'boolean') return val; return val === 'true'; } function value(flagName) { if (isDefaultsMode && Object.prototype.hasOwnProperty.call(DEFAULTS, flagName)) { return DEFAULTS[flagName]; } const internalExperiment = _repositories_ExperimentsRepository__WEBPACK_IMPORTED_MODULE_0__["default"].experimentForFlagName(flagName); if (!internalExperiment || !internalExperiment.deploymentConfiguration) return ''; const value = new _parsers_RoxxParser__WEBPACK_IMPORTED_MODULE_1__["default"]().evaluateExpression(internalExperiment.deploymentConfiguration.condition); return value; } function getNumber(flagName) { const val = value(flagName); return parseInt(val) || 0; } function setDefaultsMode(mode) { isDefaultsMode = mode; } /***/ }), /* 24 */ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (/* binding */ RoxxParser) /* harmony export */ }); /* harmony import */ var _RoxxTokenizer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(25); /* harmony import */ var _lib_RoxLogger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16); /* harmony import */ var _lib_RoxxOperators__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(27); /* harmony import */ var _lib_UserspaceUnhandledErrorInvoker__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(15); /* harmony import */ var _config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(39); class RoxxParser { /** * A parser for Roxx expressions. * Roxx expression are polish notation expressions {@link https://en.wikipedia.org/wiki/Polish_notation} * @class * @module RoxxParser * @param {*} cache - Optional token cache object. A default cache object is used if none specified. */ constructor(cache) { this._tokenizer = new _RoxxTokenizer__WEBPACK_IMPORTED_MODULE_0__.RoxxTokenizer(); this._cache = cache || {}; } /** * Given an operator function and stack, return an array of arguments for the operator. * @param {Function} operator * @param {Array} s