@optimizely/optimizely-sdk
Version:
JavaScript SDK for Optimizely X Full Stack
1,367 lines (1,277 loc) • 345 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.optimizelySdk = {}));
}(this, (function (exports) { 'use strict';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(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);
};
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function unwrapExports (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var errorHandler = createCommonjsModule(function (module, exports) {
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;
});
unwrapExports(errorHandler);
var errorHandler_1 = errorHandler.NoopErrorHandler;
var errorHandler_2 = errorHandler.setErrorHandler;
var errorHandler_3 = errorHandler.getErrorHandler;
var errorHandler_4 = errorHandler.resetErrorHandler;
var models = createCommonjsModule(function (module, exports) {
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 = {}));
});
unwrapExports(models);
var models_1 = models.LogLevel;
var rngBrowser = createCommonjsModule(function (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
// 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;
};
}
});
/**
* 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('');
}
var bytesToUuid_1 = bytesToUuid;
// **`v1()` - Generate time-based UUID**
//
// Inspired by https://github.com/LiosK/UUID.js
// and http://docs.python.org/library/uuid.html
var _nodeId;
var _clockseq;
// Previous uuid creation time
var _lastMSecs = 0;
var _lastNSecs = 0;
// See https://github.com/uuidjs/uuid for API details
function v1(options, buf, offset) {
var i = buf && offset || 0;
var b = buf || [];
options = options || {};
var node = options.node || _nodeId;
var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;
// node and clockseq need to be initialized to random values if they're not
// specified. We do this lazily to minimize issues related to insufficient
// system entropy. See #189
if (node == null || clockseq == null) {
var seedBytes = rngBrowser();
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_1(b);
}
var v1_1 = v1;
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 || rngBrowser)();
// 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_1(rnds);
}
var v4_1 = v4;
var uuid = v4_1;
uuid.v1 = v1_1;
uuid.v4 = v4_1;
var uuid_1 = uuid;
var lib = createCommonjsModule(function (module, exports) {
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.
*/
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;
});
unwrapExports(lib);
var lib_1 = lib.getTimestamp;
var lib_2 = lib.generateUUID;
var lib_3 = lib.isValidEnum;
var lib_4 = lib.groupBy;
var lib_5 = lib.objectValues;
var lib_6 = lib.find;
var lib_7 = lib.keyBy;
var lib_8 = lib.sprintf;
var logger = createCommonjsModule(function (module, exports) {
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 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.LogLevel.NOTSET;
if (config.logLevel !== undefined && lib.isValidEnum(models.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 (!lib.isValidEnum(models.LogLevel, level) || level === undefined) {
this.logLevel = models.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.LogLevel.DEBUG:
return 'DEBUG';
case models.LogLevel.INFO:
return 'INFO ';
case models.LogLevel.WARNING:
return 'WARN ';
case models.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.LogLevel.DEBUG:
console.log.apply(console, logArguments);
break;
case models.LogLevel.INFO:
console.info.apply(console, logArguments);
break;
case models.LogLevel.WARNING:
console.warn.apply(console, logArguments);
break;
case models.LogLevel.ERROR:
console.error.apply(console, logArguments);
break;
default:
console.log.apply(console, logArguments);
}
};
return ConsoleLogHandler;
}());
exports.ConsoleLogHandler = ConsoleLogHandler;
var globalLogLevel = models.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.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.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.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.LogLevel.ERROR, message, splat);
};
OptimizelyLogger.prototype.format = function (data) {
return "" + (this.messagePrefix ? this.messagePrefix + ': ' : '') + lib.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.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 (!lib.isValidEnum(models.LogLevel, level) || level === undefined) {
globalLogLevel = models.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.LogLevel.NOTSET;
}
exports.resetLogger = resetLogger;
});
unwrapExports(logger);
var logger_1 = logger.ConsoleLogHandler;
var logger_2 = logger.getLogger;
var logger_3 = logger.setLogHandler;
var logger_4 = logger.setLogLevel;
var logger_5 = logger.getLogLevel;
var logger_6 = logger.resetLogger;
var lib$1 = createCommonjsModule(function (module, exports) {
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(errorHandler);
__export(models);
__export(logger);
});
unwrapExports(lib$1);
var lib_1$1 = lib$1.ConsoleLogHandler;
var lib_2$1 = lib$1.getLogger;
var lib_3$1 = lib$1.setLogLevel;
var lib_4$1 = lib$1.LogLevel;
var lib_5$1 = lib$1.setLogHandler;
var lib_6$1 = lib$1.setErrorHandler;
var lib_7$1 = lib$1.getErrorHandler;
var events = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.areEventContextsEqual = void 0;
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;
});
unwrapExports(events);
var events_1 = events.areEventContextsEqual;
var eventQueue = createCommonjsModule(function (module, exports) {
/**
* 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.DefaultEventQueue = exports.SingleEventQueue = void 0;
var logger = lib$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;
});
unwrapExports(eventQueue);
var eventQueue_1 = eventQueue.DefaultEventQueue;
var eventQueue_2 = eventQueue.SingleEventQueue;
var lib$2 = createCommonjsModule(function (module, exports) {
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.
*/
function generateUUID() {
return uuid_1.v4();
}
exports.generateUUID = generateUUID;
function getTimestamp() {
return new Date().getTime();
}
exports.getTimestamp = getTimestamp;
/**
* 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: <list of parameters to callback>
*
* 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 = {}));
});
unwrapExports(lib$2);
var lib_1$2 = lib$2.generateUUID;
var lib_2$2 = lib$2.getTimestamp;
var lib_3$2 = lib$2.isValidEnum;
var lib_4$2 = lib$2.groupBy;
var lib_5$2 = lib$2.objectValues;
var lib_6$2 = lib$2.objectEntries;
var lib_7$2 = lib$2.find;
var lib_8$1 = lib$2.keyBy;
var lib_9 = lib$2.sprintf;
var lib_10 = lib$2.NOTIFICATION_TYPES;
var eventProcessor = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendEventNotification = exports.getQueue = exports.validateAndGetBatchSize = exports.validateAndGetFlushInterval = exports.DEFAULT_BATCH_SIZE = exports.DEFAULT_FLUSH_INTERVAL = void 0;
exports.DEFAULT_FLUSH_INTERVAL = 30000; // Unit is ms - default flush interval is 30s
exports.DEFAULT_BATCH_SIZE = 10;
var logger = lib$1.getLogger('EventProcessor');
function validateAndGetFlushInterval(flushInterval) {
if (flushInterval <= 0) {
logger.warn("Invalid flushInterval " + flushInterval + ", defaulting to " + exports.DEFAULT_FLUSH_INTERVAL);
flushInterval = exports.DEFAULT_FLUSH_INTERVAL;
}
return flushInterval;
}
exports.validateAndGetFlushInterval = validateAndGetFlushInterval;
function validateAndGetBatchSize(batchSize) {
batchSize = Math.floor(batchSize);
if (batchSize < 1) {
logger.warn("Invalid batchSize " + batchSize + ", defaulting to " + exports.DEFAULT_BATCH_SIZE);
batchSize = exports.DEFAULT_BATCH_SIZE;
}
batchSize = Math.max(1, batchSize);
return batchSize;
}
exports.validateAndGetBatchSize = validateAndGetBatchSize;
function getQueue(batchSize, flushInterval, sink, batchComparator) {
var queue;
if (batchSize > 1) {
queue = new eventQueue.DefaultEventQueue({
flushInterval: flushInterval,
maxQueueSize: batchSize,
sink: sink,
batchComparator: batchComparator,
});
}
else {
queue = new eventQueue.SingleEventQueue({ sink: sink });
}
return queue;
}
exports.getQueue = getQueue;
function sendEventNotification(notificationCenter, event) {
if (notificationCenter) {
notificationCenter.sendNotifications(lib$2.NOTIFICATION_TYPES.LOG_EVENT, event);
}
}
exports.sendEventNotification = sendEventNotification;
});
unwrapExports(eventProcessor);
var eventProcessor_1 = eventProcessor.sendEventNotification;
var eventProcessor_2 = eventProcessor.getQueue;
var eventProcessor_3 = eventProcessor.validateAndGetBatchSize;
var eventProcessor_4 = eventProcessor.validateAndGetFlushInterval;
var eventProcessor_5 = eventProcessor.DEFAULT_BATCH_SIZE;
var eventProcessor_6 = eventProcessor.DEFAULT_FLUSH_INTERVAL;
var eventDispatcher = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
});
unwrapExports(eventDispatcher);
var managed = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
});
unwrapExports(managed);
var pendingEventsStore = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.LocalStorageStore = void 0;
/**
* 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 logger = lib$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 lib$2.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;
});
unwrapExports(pendingEventsStore);
var pendingEventsStore_1 = pendingEventsStore.LocalStorageStore;
var pendingEventsDispatcher = createCommonjsModule(function (module, exports) {
var __extends = (commonjsGlobal && commonjsGlobal.__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 (Object.prototype.hasOwnProperty.call(b, 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 });
exports.LocalStoragePendingEventsDispatcher = exports.PendingEventsDispatcher = void 0;
/**
* 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 logger = lib$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: lib$2.generateUUID(),
timestamp: lib$2.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.LocalStorageStore({
// TODO make this configurable
maxValues: 100,
key: 'fs_optly_pending_events',
}),
}) || this;
}
return LocalStoragePendingEventsDispatcher;
}(PendingEventsDispatcher));
exports.LocalStoragePendingEventsDispatcher = LocalStoragePendingEventsDispatcher;
});
unwrapExports(pendingEventsDispatcher);
var pendingEventsDispatcher_1 = pendingEventsDispatcher.LocalStoragePendingEventsDispatcher;
var pendingEventsDispatcher_2 = pendingEventsDispatcher.PendingEventsDispatcher;
var buildEventV1 = createCommonjsModule(function (module, exports) {
var __assign = (commonjsGlobal && commonjsGlobal.__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 });
exports.formatEvents = exports.buildConversionEventV1 = exports.buildImpressionEventV1 = exports.makeBatchedEventV1 = void 0;
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 {ProcessableEvent[]} events
* @returns {EventV1}
*/
function makeBatchedEventV1(events) {
var visitors = [];