@absmartly/javascript-sdk
Version:
A/B Smartly Javascript SDK
1,176 lines (1,142 loc) • 341 kB
JavaScript
(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["absmartly"] = factory();
else
root["absmartly"] = factory();
})(self, function() {
return /******/ (function() { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./js/abort-controller-shim.js":
/*!*************************************!*\
!*** ./js/abort-controller-shim.js ***!
\*************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
__webpack_require__(/*! core-js/modules/es.date.to-primitive.js */ "./node_modules/core-js/modules/es.date.to-primitive.js");
__webpack_require__(/*! core-js/modules/es.number.constructor.js */ "./node_modules/core-js/modules/es.number.constructor.js");
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.AbortController = exports.AbortSignal = void 0;
var AbortSignal = /*#__PURE__*/function () {
function AbortSignal() {
_classCallCheck(this, AbortSignal);
this.aborted = false;
this._events = {};
}
_createClass(AbortSignal, [{
key: "addEventListener",
value: function addEventListener(type, listener) {
var listeners = this._events[type];
if (!listeners) {
listeners = [];
this._events[type] = listeners;
}
listeners.push(listener);
}
}, {
key: "removeEventListener",
value: function removeEventListener(type, listener) {
var listeners = this._events[type];
if (listeners) {
var index = listeners.findIndex(function (x) {
return x === listener;
});
if (index !== -1) {
listeners.splice(index, 1);
if (listeners.length === 0) {
delete this._events[type];
}
}
}
}
}, {
key: "dispatchEvent",
value: function dispatchEvent(evt) {
this["on".concat(evt.type)] && this["on".concat(evt.type)](evt);
var listeners = this._events[evt.type];
if (listeners) {
var _iterator = _createForOfIteratorHelper(listeners),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var listener = _step.value;
listener.call(null, evt);
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
}
}, {
key: "toString",
value: function toString() {
return "[object AbortSignal]";
}
}]);
return AbortSignal;
}();
exports.AbortSignal = AbortSignal;
var AbortController = /*#__PURE__*/function () {
function AbortController() {
_classCallCheck(this, AbortController);
this.signal = new AbortSignal();
}
_createClass(AbortController, [{
key: "abort",
value: function abort() {
var evt;
try {
evt = new Event("abort");
} catch (e) {
evt = {
type: "abort",
bubbles: false,
cancelable: false
};
}
this.signal.aborted = true;
this.signal.dispatchEvent(evt);
}
}, {
key: "toString",
value: function toString() {
return "[object AbortController]";
}
}]);
return AbortController;
}();
exports.AbortController = AbortController;
if (typeof Symbol !== "undefined" && Symbol.toStringTag !== undefined) {
Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, {
configurable: true,
value: "AbortSignal"
});
Object.defineProperty(AbortController.prototype, Symbol.toStringTag, {
configurable: true,
value: "AbortController"
});
}
exports["default"] = AbortController;
/***/ }),
/***/ "./js/abort.js":
/*!*********************!*\
!*** ./js/abort.js ***!
\*********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.AbortController = void 0;
var utils_1 = __webpack_require__(/*! ./utils */ "./js/utils.js");
var abort_controller_shim_1 = __importDefault(__webpack_require__(/*! ./abort-controller-shim */ "./js/abort-controller-shim.js"));
exports.AbortController = (0, utils_1.isLongLivedApp)() && window.AbortController ? window.AbortController : (0, utils_1.isWorker)() && self.AbortController ? self.AbortController : __webpack_require__.g && __webpack_require__.g.AbortController ? __webpack_require__.g.AbortController : abort_controller_shim_1.default;
/***/ }),
/***/ "./js/algorithm.js":
/*!*************************!*\
!*** ./js/algorithm.js ***!
\*************************/
/***/ (function(__unused_webpack_module, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.insertUniqueSorted = void 0;
var insertUniqueSorted = function insertUniqueSorted(arr, value, isSorted) {
var left = 0;
var right = arr.length - 1;
while (left <= right) {
var mid = Math.floor(left + (right - left) / 2);
if (isSorted(arr[mid], value)) {
left = mid + 1;
} else if (isSorted(value, arr[mid])) {
right = mid - 1;
} else {
return;
}
}
arr.splice(left, 0, value);
};
exports.insertUniqueSorted = insertUniqueSorted;
/***/ }),
/***/ "./js/assigner.js":
/*!************************!*\
!*** ./js/assigner.js ***!
\************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
__webpack_require__(/*! core-js/modules/es.date.to-primitive.js */ "./node_modules/core-js/modules/es.date.to-primitive.js");
__webpack_require__(/*! core-js/modules/es.number.constructor.js */ "./node_modules/core-js/modules/es.number.constructor.js");
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.VariantAssigner = void 0;
var utils_1 = __webpack_require__(/*! ./utils */ "./js/utils.js");
var murmur3_32_1 = __webpack_require__(/*! ./murmur3_32 */ "./js/murmur3_32.js");
var VariantAssigner = /*#__PURE__*/function () {
function VariantAssigner(unit) {
_classCallCheck(this, VariantAssigner);
this._unitHash = (0, murmur3_32_1.murmur3_32)((0, utils_1.stringToUint8Array)(unit).buffer);
}
_createClass(VariantAssigner, [{
key: "assign",
value: function assign(split, seedHi, seedLo) {
var prob = this._probability(seedHi, seedLo);
return (0, utils_1.chooseVariant)(split, prob);
}
}, {
key: "_probability",
value: function _probability(seedHi, seedLo) {
var key = this._unitHash;
var buffer = new ArrayBuffer(12);
var view = new DataView(buffer);
view.setUint32(0, seedLo, true);
view.setUint32(4, seedHi, true);
view.setUint32(8, key, true);
return (0, murmur3_32_1.murmur3_32)(buffer) * (1.0 / 0xffffffff);
}
}]);
return VariantAssigner;
}();
exports.VariantAssigner = VariantAssigner;
/***/ }),
/***/ "./js/client.js":
/*!**********************!*\
!*** ./js/client.js ***!
\**********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
__webpack_require__(/*! core-js/modules/es.object.assign.js */ "./node_modules/core-js/modules/es.object.assign.js");
__webpack_require__(/*! core-js/modules/es.date.to-primitive.js */ "./node_modules/core-js/modules/es.date.to-primitive.js");
__webpack_require__(/*! core-js/modules/es.number.constructor.js */ "./node_modules/core-js/modules/es.number.constructor.js");
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", ({
value: true
}));
var fetch_1 = __importDefault(__webpack_require__(/*! ./fetch */ "./js/fetch.js"));
var abort_1 = __webpack_require__(/*! ./abort */ "./js/abort.js");
var errors_1 = __webpack_require__(/*! ./errors */ "./js/errors.js");
var utils_1 = __webpack_require__(/*! ./utils */ "./js/utils.js");
var Client = /*#__PURE__*/function () {
function Client(opts) {
_classCallCheck(this, Client);
this._opts = Object.assign({
agent: "javascript-client",
apiKey: undefined,
application: undefined,
endpoint: undefined,
environment: undefined,
retries: 5,
timeout: 3000,
keepalive: true
}, opts);
for (var _i = 0, _arr = ["agent", "application", "apiKey", "endpoint", "environment"]; _i < _arr.length; _i++) {
var key = _arr[_i];
if (key in this._opts && this._opts[key] !== undefined) {
var value = this._opts[key];
if (typeof value !== "string" || value.length === 0) {
if (key === "application") {
if (value !== null && _typeof(value) === "object" && "name" in value) {
continue;
}
}
throw new Error("Invalid '".concat(key, "' in options argument"));
}
} else {
throw new Error("Missing '".concat(key, "' in options argument"));
}
}
if (typeof this._opts.application === "string") {
this._opts.application = {
name: this._opts.application,
version: 0
};
}
this._delay = 50;
}
_createClass(Client, [{
key: "getContext",
value: function getContext(options) {
return this.getUnauthed(Object.assign(Object.assign({}, options), {
path: "/context",
query: {
application: (0, utils_1.getApplicationName)(this._opts.application),
environment: this._opts.environment
}
}));
}
}, {
key: "createContext",
value: function createContext(params, options) {
var body = {
units: params.units
};
return this.post(Object.assign(Object.assign({}, options), {
path: "/context",
body: body
}));
}
}, {
key: "publish",
value: function publish(params, options) {
var body = {
units: params.units,
hashed: params.hashed,
publishedAt: params.publishedAt || Date.now()
};
if (Array.isArray(params.goals) && params.goals.length > 0) {
body.goals = params.goals;
}
if (Array.isArray(params.exposures) && params.exposures.length > 0) {
body.exposures = params.exposures;
}
if (Array.isArray(params.attributes) && params.attributes.length > 0) {
body.attributes = params.attributes;
}
return this.put(Object.assign(Object.assign({}, options), {
path: "/context",
body: body
}));
}
}, {
key: "request",
value: function request(options) {
var _this = this;
var _a, _b;
var url = "".concat(this._opts.endpoint).concat(options.path);
if (options.query) {
var keys = Object.keys(options.query);
if (keys.length > 0) {
var encoded = keys.map(function (k) {
return options.query ? "".concat(k, "=").concat(encodeURIComponent(options.query[k])) : null;
}).join("&");
url = "".concat(url, "?").concat(encoded);
}
}
var controller = new abort_1.AbortController();
var tryOnce = function tryOnce() {
var opts = {
method: options.method,
body: options.body !== undefined ? JSON.stringify(options.body, null, 0) : undefined,
signal: controller.signal,
keepalive: _this._opts.keepalive
};
if (options.auth) {
opts.headers = {
"Content-Type": "application/json",
"X-API-Key": _this._opts.apiKey,
"X-Agent": _this._opts.agent,
"X-Environment": _this._opts.environment,
"X-Application": (0, utils_1.getApplicationName)(_this._opts.application),
"X-Application-Version": (0, utils_1.getApplicationVersion)(_this._opts.application)
};
}
return (0, fetch_1.default)(url, opts).then(function (response) {
if (!response.ok) {
var bail = response.status >= 400 && response.status < 500;
return response.text().then(function (text) {
var error = new Error(text !== null && text.length > 0 ? text : response.statusText);
error._bail = bail;
return Promise.reject(error);
});
}
return response.json();
});
};
var wait = function wait(ms) {
return new Promise(function (resolve, reject) {
var timeoutId = setTimeout(function () {
delete wait.reject;
resolve();
}, ms);
wait.reject = function (reason) {
clearTimeout(timeoutId);
reject(reason);
};
});
};
var tryWith = function tryWith(retries, timeout) {
var tries = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var waited = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
delete tryWith.timedout;
return tryOnce().catch(function (reason) {
console.warn(reason);
if (reason._bail || retries <= 0) {
throw new Error(reason.message);
} else if (tries >= retries) {
throw new errors_1.RetryError(tries, reason, url);
} else if (waited >= timeout || reason.name === "AbortError") {
if (tryWith.timedout) {
throw new errors_1.TimeoutError(timeout);
}
throw reason;
}
var delay = (1 << tries) * _this._delay + 0.5 * Math.random() * _this._delay;
if (waited + delay > timeout) {
delay = timeout - waited;
}
return wait(delay).then(function () {
return tryWith(retries, timeout, tries + 1, waited + delay);
});
});
};
var abort = function abort() {
if (wait.reject) {
wait.reject(new errors_1.AbortError());
} else {
controller.abort();
}
};
if (options.signal) {
options.signal.addEventListener("abort", abort);
}
var timeout = options.timeout || this._opts.timeout || 0;
var timeoutId = timeout > 0 ? setTimeout(function () {
tryWith.timedout = true;
abort();
}, timeout) : 0;
var finalCleanUp = function finalCleanUp() {
clearTimeout(timeoutId);
if (options.signal) {
options.signal.removeEventListener("abort", abort);
}
};
return tryWith((_a = this._opts.retries) !== null && _a !== void 0 ? _a : 5, (_b = this._opts.timeout) !== null && _b !== void 0 ? _b : 3000).then(function (value) {
finalCleanUp();
return value;
}).catch(function (error) {
finalCleanUp();
throw error;
});
}
}, {
key: "post",
value: function post(options) {
return this.request(Object.assign(Object.assign({}, options), {
auth: true,
method: "POST"
}));
}
}, {
key: "put",
value: function put(options) {
return this.request(Object.assign(Object.assign({}, options), {
auth: true,
method: "PUT"
}));
}
}, {
key: "getUnauthed",
value: function getUnauthed(options) {
return this.request(Object.assign(Object.assign({}, options), {
method: "GET"
}));
}
}]);
return Client;
}();
exports["default"] = Client;
/***/ }),
/***/ "./js/config.js":
/*!**********************!*\
!*** ./js/config.js ***!
\**********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
__webpack_require__(/*! core-js/modules/es.object.entries.js */ "./node_modules/core-js/modules/es.object.entries.js");
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", ({
value: true
}));
exports.mergeConfig = void 0;
var default_1 = __importDefault(__webpack_require__(/*! rfdc/default */ "./node_modules/rfdc/default.js"));
var utils_1 = __webpack_require__(/*! ./utils */ "./js/utils.js");
function mergeConfig(context, previousConfig) {
var merged = (0, default_1.default)(previousConfig);
var keys = context.variableKeys();
var _loop = function _loop() {
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
variableKey = _Object$entries$_i[0],
experimentName = _Object$entries$_i[1];
var target = merged;
var frags = variableKey.split(".");
var _loop2 = function _loop2() {
var frag = frags[index];
if ("_".concat(frag, "_setter") in target) {
console.error("Config key '".concat(frags.slice(0, index + 1).join("."), "' already set by experiment '").concat(target["_".concat(frag, "_setter")], "'."));
target = undefined;
return "break";
}
if (frag in target) {
if (index < frags.length - 1) {
if (!(0, utils_1.isObject)(target[frag])) {
console.warn("Config key '".concat(variableKey, "' for experiment '").concat(experimentName, "' is overriding non-object value at '").concat(frags.slice(0, index + 1).join("."), "' with an object."));
target = target[frag] = {};
} else {
target = target[frag];
}
}
}
if (index === frags.length - 1) {
var defaultValue = target[frag];
Object.defineProperty(target, "_".concat(frag, "_setter"), {
value: experimentName,
writable: false
});
Object.defineProperty(target, frag, {
get: function get() {
return context.variableValue(variableKey, defaultValue);
}
});
}
};
for (var index = 0; index < frags.length; ++index) {
var _ret = _loop2();
if (_ret === "break") break;
}
};
for (var _i = 0, _Object$entries = Object.entries(keys); _i < _Object$entries.length; _i++) {
_loop();
}
return merged;
}
exports.mergeConfig = mergeConfig;
/***/ }),
/***/ "./js/context.js":
/*!***********************!*\
!*** ./js/context.js ***!
\***********************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
"use strict";
__webpack_require__(/*! core-js/modules/es.object.entries.js */ "./node_modules/core-js/modules/es.object.entries.js");
__webpack_require__(/*! core-js/modules/es.object.assign.js */ "./node_modules/core-js/modules/es.object.assign.js");
__webpack_require__(/*! core-js/modules/es.array.find.js */ "./node_modules/core-js/modules/es.array.find.js");
__webpack_require__(/*! core-js/modules/es.number.constructor.js */ "./node_modules/core-js/modules/es.number.constructor.js");
__webpack_require__(/*! core-js/modules/es.date.to-primitive.js */ "./node_modules/core-js/modules/es.date.to-primitive.js");
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e2) { throw _e2; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e3) { didErr = true; err = _e3; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
Object.defineProperty(exports, "__esModule", ({
value: true
}));
var utils_1 = __webpack_require__(/*! ./utils */ "./js/utils.js");
var assigner_1 = __webpack_require__(/*! ./assigner */ "./js/assigner.js");
var matcher_1 = __webpack_require__(/*! ./matcher */ "./js/matcher.js");
var algorithm_1 = __webpack_require__(/*! ./algorithm */ "./js/algorithm.js");
var Context = /*#__PURE__*/function () {
function Context(sdk, options, params, promise) {
var _this = this;
_classCallCheck(this, Context);
this._sdk = sdk;
this._publisher = options.publisher || this._sdk.getContextPublisher();
this._dataProvider = options.dataProvider || this._sdk.getContextDataProvider();
this._eventLogger = options.eventLogger || this._sdk.getEventLogger();
this._opts = options;
this._pending = 0;
this._failed = false;
this._finalized = false;
this._attrs = [];
this._goals = [];
this._exposures = [];
this._overrides = {};
this._cassignments = {};
this._units = {};
this._assigners = {};
this._audienceMatcher = new matcher_1.AudienceMatcher();
if (params.units) {
this.units(params.units);
}
if ((0, utils_1.isPromise)(promise)) {
this._promise = promise.then(function (data) {
_this._init(data);
delete _this._promise;
_this._logEvent("ready", data);
if (_this.pending() > 0) {
_this._setTimeout();
}
}).catch(function (error) {
_this._init({});
_this._failed = true;
delete _this._promise;
_this._logError(error);
});
} else {
promise = promise;
this._init(promise);
this._logEvent("ready", promise);
}
}
_createClass(Context, [{
key: "isReady",
value: function isReady() {
return this._promise === undefined;
}
}, {
key: "isFinalizing",
value: function isFinalizing() {
return !this._finalized && this._finalizing != null;
}
}, {
key: "isFinalized",
value: function isFinalized() {
return this._finalized;
}
}, {
key: "isFailed",
value: function isFailed() {
return this._failed;
}
}, {
key: "ready",
value: function ready() {
var _this2 = this;
if (this.isReady()) {
return Promise.resolve(true);
}
return new Promise(function (resolve) {
var _a;
(_a = _this2._promise) === null || _a === void 0 ? void 0 : _a.then(function () {
return resolve(true);
}).catch(function (e) {
return resolve(e);
});
});
}
}, {
key: "pending",
value: function pending() {
return this._pending;
}
}, {
key: "data",
value: function data() {
this._checkReady();
return this._data;
}
}, {
key: "eventLogger",
value: function eventLogger() {
return this._eventLogger;
}
}, {
key: "publisher",
value: function publisher() {
return this._publisher;
}
}, {
key: "provider",
value: function provider() {
return this._dataProvider;
}
}, {
key: "publish",
value: function publish(requestOptions) {
var _this3 = this;
this._checkReady(true);
return new Promise(function (resolve, reject) {
_this3._flush(function (error) {
if (error) {
reject(error);
} else {
resolve();
}
}, requestOptions);
});
}
}, {
key: "refresh",
value: function refresh(requestOptions) {
var _this4 = this;
this._checkReady(true);
return new Promise(function (resolve, reject) {
_this4._refresh(function (error) {
if (error) {
reject(error);
} else {
resolve();
}
}, requestOptions);
});
}
}, {
key: "getUnit",
value: function getUnit(unitType) {
return this._units[unitType];
}
}, {
key: "unit",
value: function unit(unitType, uid) {
this._checkNotFinalized();
switch (_typeof(uid)) {
case "string":
uid = uid.trim();
if (uid.length === 0) throw new Error("Unit '".concat(unitType, "' UID must not be blank."));
break;
case "number":
break;
default:
throw new Error("Unit '".concat(unitType, "' must be a string or a number."));
}
var previous = this._units[unitType];
if (previous !== undefined && previous !== uid) {
throw new Error("Unit '".concat(unitType, "' UID already set."));
}
this._units[unitType] = uid;
}
}, {
key: "getUnits",
value: function getUnits() {
return this._units;
}
}, {
key: "units",
value: function units(_units) {
var _this5 = this;
Object.entries(_units).forEach(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
unitType = _ref2[0],
uid = _ref2[1];
_this5.unit(unitType, uid);
});
}
}, {
key: "getAttribute",
value: function getAttribute(attrName) {
var result;
this._attrs.forEach(function (attr) {
if (attr.name === attrName) result = attr.value;
});
return result;
}
}, {
key: "attribute",
value: function attribute(attrName, value) {
this._checkNotFinalized();
this._attrs.push({
name: attrName,
value: value,
setAt: Date.now()
});
}
}, {
key: "getAttributes",
value: function getAttributes() {
var attributes = {};
this._attrs.map(function (a) {
return [a.name, a.value];
}).forEach(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
key = _ref4[0],
value = _ref4[1];
attributes[key] = value;
});
return attributes;
}
}, {
key: "attributes",
value: function attributes(attrs) {
var _this6 = this;
Object.entries(attrs).forEach(function (_ref5) {
var _ref6 = _slicedToArray(_ref5, 2),
attrName = _ref6[0],
value = _ref6[1];
_this6.attribute(attrName, value);
});
}
}, {
key: "peek",
value: function peek(experimentName) {
this._checkReady(true);
return this._peek(experimentName).variant;
}
}, {
key: "treatment",
value: function treatment(experimentName) {
this._checkReady(true);
return this._treatment(experimentName).variant;
}
}, {
key: "track",
value: function track(goalName, properties) {
this._checkNotFinalized();
return this._track(goalName, properties);
}
}, {
key: "finalize",
value: function finalize(requestOptions) {
return this._finalize(requestOptions);
}
}, {
key: "experiments",
value: function experiments() {
var _a;
this._checkReady();
return (_a = this._data.experiments) === null || _a === void 0 ? void 0 : _a.map(function (x) {
return x.name;
});
}
}, {
key: "variableValue",
value: function variableValue(key, defaultValue) {
this._checkReady(true);
return this._variableValue(key, defaultValue);
}
}, {
key: "peekVariableValue",
value: function peekVariableValue(key, defaultValue) {
this._checkReady(true);
return this._peekVariable(key, defaultValue);
}
}, {
key: "variableKeys",
value: function variableKeys() {
this._checkReady(true);
var variableExperiments = {};
Object.entries(this._indexVariables).forEach(function (_ref7) {
var _ref8 = _slicedToArray(_ref7, 2),
key = _ref8[0],
values = _ref8[1];
values.forEach(function (value) {
if (variableExperiments[key]) variableExperiments[key].push(value.data.name);else variableExperiments[key] = [value.data.name];
});
});
return variableExperiments;
}
}, {
key: "override",
value: function override(experimentName, variant) {
this._overrides = Object.assign(this._overrides, _defineProperty({}, experimentName, variant));
}
}, {
key: "overrides",
value: function overrides(experimentVariants) {
var _this7 = this;
Object.entries(experimentVariants).forEach(function (_ref9) {
var _ref10 = _slicedToArray(_ref9, 2),
experimentName = _ref10[0],
variant = _ref10[1];
_this7.override(experimentName, variant);
});
}
}, {
key: "customAssignment",
value: function customAssignment(experimentName, variant) {
this._checkNotFinalized();
this._cassignments[experimentName] = variant;
}
}, {
key: "customAssignments",
value: function customAssignments(experimentVariants) {
var _this8 = this;
Object.entries(experimentVariants).forEach(function (_ref11) {
var _ref12 = _slicedToArray(_ref11, 2),
experimentName = _ref12[0],
variant = _ref12[1];
_this8.customAssignment(experimentName, variant);
});
}
}, {
key: "_checkNotFinalized",
value: function _checkNotFinalized() {
if (this.isFinalized()) {
throw new Error("ABSmartly Context is finalized.");
} else if (this.isFinalizing()) {
throw new Error("ABSmartly Context is finalizing.");
}
}
}, {
key: "_checkReady",
value: function _checkReady(expectNotFinalized) {
if (!this.isReady()) {
throw new Error("ABSmartly Context is not yet ready.");
}
if (expectNotFinalized) {
this._checkNotFinalized();
}
}
}, {
key: "_assign",
value: function _assign(experimentName) {
var experimentMatches = function experimentMatches(experiment, assignment) {
return experiment.id === assignment.id && experiment.unitType === assignment.unitType && experiment.iteration === assignment.iteration && experiment.fullOnVariant === assignment.fullOnVariant && (0, utils_1.arrayEqualsShallow)(experiment.trafficSplit, assignment.trafficSplit);
};
var hasCustom = (experimentName in this._cassignments);
var hasOverride = (experimentName in this._overrides);
var experiment = experimentName in this._index ? this._index[experimentName] : null;
if (experimentName in this._assignments) {
var _assignment = this._assignments[experimentName];
if (hasOverride) {
if (_assignment.overridden && _assignment.variant === this._overrides[experimentName]) {
return _assignment;
}
} else if (experiment == null) {
if (!_assignment.assigned) {
return _assignment;
}
} else if (!hasCustom || this._cassignments[experimentName] === _assignment.variant) {
if (experimentMatches(experiment.data, _assignment)) {
return _assignment;
}
}
}
var assignment = {
id: 0,
iteration: 0,
fullOnVariant: 0,
unitType: null,
variant: 0,
overridden: false,
assigned: false,
exposed: false,
eligible: true,
fullOn: false,
custom: false,
audienceMismatch: false
};
this._assignments[experimentName] = assignment;
if (hasOverride) {
if (experiment != null) {
assignment.id = experiment.data.id;
assignment.unitType = experiment.data.unitType;
}
assignment.overridden = true;
assignment.variant = this._overrides[experimentName];
} else {
if (experiment != null) {
var unitType = experiment.data.unitType;
if (experiment.data.audience && experiment.data.audience.length > 0) {
var attrs = {};
this._attrs.forEach(function (attr) {
attrs[attr.name] = attr.value;
});
var result = this._audienceMatcher.evaluate(experiment.data.audience, attrs);
if (typeof result === "boolean") {
assignment.audienceMismatch = !result;
}
}
if (experiment.data.audienceStrict && assignment.audienceMismatch) {
assignment.variant = 0;
} else if (experiment.data.fullOnVariant === 0) {
if (unitType !== null) {
if (unitType in this._units) {
var unit = this._unitHash(unitType);
if (unit !== null) {
var assigner = unitType in this._assigners ? this._assigners[unitType] : this._assigners[unitType] = new assigner_1.VariantAssigner(unit);
var eligible = assigner.assign(experiment.data.trafficSplit, experiment.data.trafficSeedHi, experiment.data.trafficSeedLo) === 1;
assignment.assigned = true;
assignment.eligible = eligible;
if (eligible) {
if (hasCustom) {
assignment.variant = this._cassignments[experimentName];
assignment.custom = true;
} else {
assignment.variant = assigner.assign(experiment.data.split, experiment.data.seedHi, experiment.data.seedLo);
}
} else {
assignment.variant = 0;
}
}
}
}
} else {
assignment.assigned = true;
assignment.eligible = true;
assignment.variant = experiment.data.fullOnVariant;
assignment.fullOn = true;
}
assignment.unitType = unitType;
assignment.id = experiment.data.id;
assignment.iteration = experiment.data.iteration;
assignment.trafficSplit = experiment.data.trafficSplit;
assignment.fullOnVariant = experiment.data.fullOnVariant;
}
}
if (experiment != null && assignment.variant < experiment.data.variants.length) {
assignment.variables = experiment.variables[assignment.variant];
}
return assignment;
}
}, {
key: "_peek",
value: function _peek(experimentName) {
return this._assign(experimentName);
}
}, {
key: "_treatment",
value: function _treatment(experimentName) {
var assignment = this._assign(experimentName);
if (!assignment.exposed) {
assignment.exposed = true;
this._queueExposure(experimentName, assignment);
}
return assignment;
}
}, {
key: "_queueExposure",
value: function _queueExposure(experimentName, assignment) {
var exposureEvent = {
id: assignment.id,
name: experimentName,
exposedAt: Date.now(),
unit: assignment.unitType,
variant: assignment.variant,
assigned: assignment.assigned,
eligible: assignment.eligible,
overridden: assignment.overridden,
fullOn: assignment.fullOn,
custom: assignment.custom,
audienceMismatch: assignment.audienceMismatch
};
this._logEvent("exposure", exposureEvent);
this._exposures.push(exposureEvent);
this._pending++;
this._setTimeout();
}
}, {
key: "_customFieldKeys",
value: function _customFieldKeys() {
var keys = new Set();
if (!this._data.experiments) return [];
var _iterator = _createForOfIteratorHelper(this._data.experiments),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var experiment = _step.value;
if (experiment.customFieldValues != null) {
var _iterator2 = _createForOfIteratorHelper(experiment.customFieldValues),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var customFieldValues = _step2.value;
keys.add(customFieldValues.name);
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return Array.from(keys);
}
}, {
key: "customFieldKeys",
value: function customFieldKeys() {
this._checkReady(true);
return this._customFieldKeys();
}
}, {
key: "_customFieldValue",
value: function _customFieldValue(experimentName, key) {
var _a;
var experiment = this._index[experimentName];
if (experiment != null) {
var field = (_a = experiment.data.customFieldValues) === null || _a === void 0 ? void 0 : _a.find(function (x) {
return x.name === key;
});
if (field != null) {
switch (field.type) {
case "text":
case "string":
return field.value;
case "number":
return Number(field.value);
case "json":
try {
if (field.value === "null") return null;
if (field.value === "") return "";
return JSON.parse(field.value);
} catch (e) {
console.error("Failed to parse JSON custom field value '".concat(key, "' for experiment '").concat(experimentName, "'"));
return null;
}
case "boolean":
return field.value === "true";
default:
console.error("Unknown custom field type '".concat(field.type, "' for experiment '").concat(experimentName, "' and key '").concat(key, "' - you may need to upgrade to the latest SDK version"));
return null;
}
}
}
return null;
}
}, {
key: "customFieldValue",
value: function customFieldValue(experimentName, key) {
this._checkReady(true);
return this._customFieldValue(experimentName, key);
}
}, {
key: "_customFieldValueType",
value: function _customFieldValueType(experimentName, key) {
var _a;
var experiment = this._index[experimentName];
if (experiment != null) {
var field = (_a = experiment.data.customFieldValues) === null || _a === void 0 ? void 0 : _a.find(function (x) {
return x.name === key;
});
if (field != null) {
return f