UNPKG

@amplitude/experiment-js-client

Version:
1,325 lines (1,315 loc) 213 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Experiment = {})); })(this, (function (exports) { 'use strict'; /** * @deprecated Update your version of the amplitude analytics-js SDK to 8.17.0+ and for seamless * integration with the amplitude analytics SDK. */ var AmplitudeUserProvider = /** @class */ (function () { function AmplitudeUserProvider(amplitudeInstance) { this.amplitudeInstance = amplitudeInstance; } AmplitudeUserProvider.prototype.getUser = function () { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k; return { device_id: (_b = (_a = this.amplitudeInstance) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.deviceId, user_id: (_d = (_c = this.amplitudeInstance) === null || _c === void 0 ? void 0 : _c.options) === null || _d === void 0 ? void 0 : _d.userId, version: (_f = (_e = this.amplitudeInstance) === null || _e === void 0 ? void 0 : _e.options) === null || _f === void 0 ? void 0 : _f.versionName, language: (_h = (_g = this.amplitudeInstance) === null || _g === void 0 ? void 0 : _g.options) === null || _h === void 0 ? void 0 : _h.language, platform: (_k = (_j = this.amplitudeInstance) === null || _j === void 0 ? void 0 : _j.options) === null || _k === void 0 ? void 0 : _k.platform, os: this.getOs(), device_model: this.getDeviceModel(), }; }; AmplitudeUserProvider.prototype.getOs = function () { var _a, _b, _c, _d, _e, _f; return [ (_c = (_b = (_a = this.amplitudeInstance) === null || _a === void 0 ? void 0 : _a._ua) === null || _b === void 0 ? void 0 : _b.browser) === null || _c === void 0 ? void 0 : _c.name, (_f = (_e = (_d = this.amplitudeInstance) === null || _d === void 0 ? void 0 : _d._ua) === null || _e === void 0 ? void 0 : _e.browser) === null || _f === void 0 ? void 0 : _f.major, ] .filter(function (e) { return e !== null && e !== undefined; }) .join(' '); }; AmplitudeUserProvider.prototype.getDeviceModel = function () { var _a, _b, _c; return (_c = (_b = (_a = this.amplitudeInstance) === null || _a === void 0 ? void 0 : _a._ua) === null || _b === void 0 ? void 0 : _b.os) === null || _c === void 0 ? void 0 : _c.name; }; return AmplitudeUserProvider; }()); /** * @deprecated Update your version of the amplitude analytics-js SDK to 8.17.0+ and for seamless * integration with the amplitude analytics SDK. */ var AmplitudeAnalyticsProvider = /** @class */ (function () { function AmplitudeAnalyticsProvider(amplitudeInstance) { this.amplitudeInstance = amplitudeInstance; } AmplitudeAnalyticsProvider.prototype.track = function (event) { this.amplitudeInstance.logEvent(event.name, event.properties); }; AmplitudeAnalyticsProvider.prototype.setUserProperty = function (event) { var _a; var _b; // if the variant has a value, set the user property and log an event this.amplitudeInstance.setUserProperties((_a = {}, _a[event.userProperty] = (_b = event.variant) === null || _b === void 0 ? void 0 : _b.value, _a)); }; AmplitudeAnalyticsProvider.prototype.unsetUserProperty = function (event) { var _a; // if the variant does not have a value, unset the user property this.amplitudeInstance['_logEvent']('$identify', null, null, { $unset: (_a = {}, _a[event.userProperty] = '-', _a), }); }; return AmplitudeAnalyticsProvider; }()); /****************************************************************************** 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$2 = function () { __assign$2 = 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$2.apply(this, arguments); }; function __awaiter$1(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator$1(thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function __values$2(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read$2(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spreadArray$1(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /****************************************************************************** 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. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ 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); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign$1 = function () { __assign$1 = 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$1.apply(this, arguments); }; function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } function __values$1(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read$1(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var EvaluationOperator = { IS: 'is', IS_NOT: 'is not', CONTAINS: 'contains', DOES_NOT_CONTAIN: 'does not contain', LESS_THAN: 'less', LESS_THAN_EQUALS: 'less or equal', GREATER_THAN: 'greater', GREATER_THAN_EQUALS: 'greater or equal', VERSION_LESS_THAN: 'version less', VERSION_LESS_THAN_EQUALS: 'version less or equal', VERSION_GREATER_THAN: 'version greater', VERSION_GREATER_THAN_EQUALS: 'version greater or equal', SET_IS: 'set is', SET_IS_NOT: 'set is not', SET_CONTAINS: 'set contains', SET_DOES_NOT_CONTAIN: 'set does not contain', SET_CONTAINS_ANY: 'set contains any', SET_DOES_NOT_CONTAIN_ANY: 'set does not contain any', REGEX_MATCH: 'regex match', REGEX_DOES_NOT_MATCH: 'regex does not match' }; var stringToUtf8ByteArray = function (str) { var out = []; var p = 0; for (var i = 0; i < str.length; i++) { var c = str.charCodeAt(i); if (c < 128) { out[p++] = c; } else if (c < 2048) { out[p++] = c >> 6 | 192; out[p++] = c & 63 | 128; } else if ((c & 0xfc00) == 0xd800 && i + 1 < str.length && (str.charCodeAt(i + 1) & 0xfc00) == 0xdc00) { // Surrogate Pair c = 0x10000 + ((c & 0x03ff) << 10) + (str.charCodeAt(++i) & 0x03ff); out[p++] = c >> 18 | 240; out[p++] = c >> 12 & 63 | 128; out[p++] = c >> 6 & 63 | 128; out[p++] = c & 63 | 128; } else { out[p++] = c >> 12 | 224; out[p++] = c >> 6 & 63 | 128; out[p++] = c & 63 | 128; } } return Uint8Array.from(out); }; var C1_32 = -0x3361d2af; var C2_32 = 0x1b873593; var R1_32 = 15; var R2_32 = 13; var M_32 = 5; var N_32 = -0x19ab949c; var hash32x86 = function (input, seed) { if (seed === void 0) { seed = 0; } var data = stringToUtf8ByteArray(input); var length = data.length; var nBlocks = length >> 2; var hash = seed; // body for (var i = 0; i < nBlocks; i++) { var index_1 = i << 2; var k = readIntLe(data, index_1); hash = mix32(k, hash); } // tail var index = nBlocks << 2; var k1 = 0; switch (length - index) { case 3: k1 ^= data[index + 2] << 16; k1 ^= data[index + 1] << 8; k1 ^= data[index]; k1 = Math.imul(k1, C1_32); k1 = rotateLeft(k1, R1_32); k1 = Math.imul(k1, C2_32); hash ^= k1; break; case 2: k1 ^= data[index + 1] << 8; k1 ^= data[index]; k1 = Math.imul(k1, C1_32); k1 = rotateLeft(k1, R1_32); k1 = Math.imul(k1, C2_32); hash ^= k1; break; case 1: k1 ^= data[index]; k1 = Math.imul(k1, C1_32); k1 = rotateLeft(k1, R1_32); k1 = Math.imul(k1, C2_32); hash ^= k1; break; } hash ^= length; return fmix32(hash) >>> 0; }; var mix32 = function (k, hash) { var kResult = k; var hashResult = hash; kResult = Math.imul(kResult, C1_32); kResult = rotateLeft(kResult, R1_32); kResult = Math.imul(kResult, C2_32); hashResult ^= kResult; hashResult = rotateLeft(hashResult, R2_32); hashResult = Math.imul(hashResult, M_32); return hashResult + N_32 | 0; }; var fmix32 = function (hash) { var hashResult = hash; hashResult ^= hashResult >>> 16; hashResult = Math.imul(hashResult, -0x7a143595); hashResult ^= hashResult >>> 13; hashResult = Math.imul(hashResult, -0x3d4d51cb); hashResult ^= hashResult >>> 16; return hashResult; }; var rotateLeft = function (x, n, width) { if (width === void 0) { width = 32; } if (n > width) n = n % width; var mask = 0xffffffff << width - n >>> 0; var r = (x & mask) >>> 0 >>> width - n >>> 0; return (x << n | r) >>> 0; }; var readIntLe = function (data, index) { if (index === void 0) { index = 0; } var n = data[index] << 24 | data[index + 1] << 16 | data[index + 2] << 8 | data[index + 3]; return reverseBytes(n); }; var reverseBytes = function (n) { return (n & -0x1000000) >>> 24 | (n & 0x00ff0000) >>> 8 | (n & 0x0000ff00) << 8 | (n & 0x000000ff) << 24; }; var select = function (selectable, selector) { var e_1, _a; if (!selector || selector.length === 0) { return undefined; } try { for (var selector_1 = __values$1(selector), selector_1_1 = selector_1.next(); !selector_1_1.done; selector_1_1 = selector_1.next()) { var selectorElement = selector_1_1.value; if (!selectorElement || !selectable || typeof selectable !== 'object') { return undefined; } selectable = selectable[selectorElement]; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (selector_1_1 && !selector_1_1.done && (_a = selector_1.return)) _a.call(selector_1); } finally { if (e_1) throw e_1.error; } } if (!selectable) { return undefined; } else { return selectable; } }; // major and minor should be non-negative numbers separated by a dot var MAJOR_MINOR_REGEX = '(\\d+)\\.(\\d+)'; // patch should be a non-negative number var PATCH_REGEX = '(\\d+)'; // prerelease is optional. If provided, it should be a hyphen followed by a // series of dot separated identifiers where an identifer can contain anything in [-0-9a-zA-Z] var PRERELEASE_REGEX = '(-(([-\\w]+\\.?)*))?'; // version pattern should be major.minor(.patchAndPreRelease) where .patchAndPreRelease is optional var VERSION_PATTERN = "^".concat(MAJOR_MINOR_REGEX, "(\\.").concat(PATCH_REGEX).concat(PRERELEASE_REGEX, ")?$"); var SemanticVersion = /** @class */function () { function SemanticVersion(major, minor, patch, preRelease) { if (preRelease === void 0) { preRelease = undefined; } this.major = major; this.minor = minor; this.patch = patch; this.preRelease = preRelease; } SemanticVersion.parse = function (version) { if (!version) { return undefined; } var matchGroup = new RegExp(VERSION_PATTERN).exec(version); if (!matchGroup) { return undefined; } var major = Number(matchGroup[1]); var minor = Number(matchGroup[2]); if (isNaN(major) || isNaN(minor)) { return undefined; } var patch = Number(matchGroup[4]) || 0; var preRelease = matchGroup[5] || undefined; return new SemanticVersion(major, minor, patch, preRelease); }; SemanticVersion.prototype.compareTo = function (other) { if (this.major > other.major) return 1; if (this.major < other.major) return -1; if (this.minor > other.minor) return 1; if (this.minor < other.minor) return -1; if (this.patch > other.patch) return 1; if (this.patch < other.patch) return -1; if (this.preRelease && !other.preRelease) return -1; if (!this.preRelease && other.preRelease) return 1; if (this.preRelease && other.preRelease) { if (this.preRelease > other.preRelease) return 1; if (this.preRelease < other.preRelease) return -1; return 0; } return 0; }; return SemanticVersion; }(); var EvaluationEngine = /** @class */function () { function EvaluationEngine() {} EvaluationEngine.prototype.evaluate = function (context, flags) { var e_1, _a; var results = {}; var target = { context: context, result: results }; try { for (var flags_1 = __values$1(flags), flags_1_1 = flags_1.next(); !flags_1_1.done; flags_1_1 = flags_1.next()) { var flag = flags_1_1.value; // Evaluate flag and update results. var variant = this.evaluateFlag(target, flag); if (variant) { results[flag.key] = variant; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (flags_1_1 && !flags_1_1.done && (_a = flags_1.return)) _a.call(flags_1); } finally { if (e_1) throw e_1.error; } } return results; }; EvaluationEngine.prototype.evaluateFlag = function (target, flag) { var e_2, _a; var result; try { for (var _b = __values$1(flag.segments), _c = _b.next(); !_c.done; _c = _b.next()) { var segment = _c.value; result = this.evaluateSegment(target, flag, segment); if (result) { // Merge all metadata into the result var metadata = __assign$1(__assign$1(__assign$1({}, flag.metadata), segment.metadata), result.metadata); result = __assign$1(__assign$1({}, result), { metadata: metadata }); break; } } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } return result; }; EvaluationEngine.prototype.evaluateSegment = function (target, flag, segment) { if (!segment.conditions) { // Null conditions always match var variantKey = this.bucket(target, segment); if (variantKey !== undefined) { return flag.variants[variantKey]; } else { return undefined; } } var match = this.evaluateConditions(target, segment.conditions); // On match, bucket the user. if (match) { var variantKey = this.bucket(target, segment); if (variantKey !== undefined) { return flag.variants[variantKey]; } else { return undefined; } } return undefined; }; EvaluationEngine.prototype.evaluateConditions = function (target, conditions) { var e_3, _a, e_4, _b; try { // Outer list logic is "or" (||) for (var conditions_1 = __values$1(conditions), conditions_1_1 = conditions_1.next(); !conditions_1_1.done; conditions_1_1 = conditions_1.next()) { var innerConditions = conditions_1_1.value; var match = true; try { for (var innerConditions_1 = (e_4 = void 0, __values$1(innerConditions)), innerConditions_1_1 = innerConditions_1.next(); !innerConditions_1_1.done; innerConditions_1_1 = innerConditions_1.next()) { var condition = innerConditions_1_1.value; match = this.matchCondition(target, condition); if (!match) { break; } } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (innerConditions_1_1 && !innerConditions_1_1.done && (_b = innerConditions_1.return)) _b.call(innerConditions_1); } finally { if (e_4) throw e_4.error; } } if (match) { return true; } } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (conditions_1_1 && !conditions_1_1.done && (_a = conditions_1.return)) _a.call(conditions_1); } finally { if (e_3) throw e_3.error; } } return false; }; EvaluationEngine.prototype.matchCondition = function (target, condition) { var propValue = select(target, condition.selector); // We need special matching for null properties and set type prop values // and operators. All other values are matched as strings, since the // filter values are always strings. if (!propValue) { return this.matchNull(condition.op, condition.values); } else if (this.isSetOperator(condition.op)) { var propValueStringList = this.coerceStringArray(propValue); if (!propValueStringList) { return false; } return this.matchSet(propValueStringList, condition.op, condition.values); } else { var propValueString = this.coerceString(propValue); if (propValueString !== undefined) { return this.matchString(propValueString, condition.op, condition.values); } else { return false; } } }; EvaluationEngine.prototype.getHash = function (key) { return hash32x86(key); }; EvaluationEngine.prototype.bucket = function (target, segment) { var e_5, _a, e_6, _b; if (!segment.bucket) { // A null bucket means the segment is fully rolled out. Select the // default variant. return segment.variant; } // Select the bucketing value. var bucketingValue = this.coerceString(select(target, segment.bucket.selector)); if (!bucketingValue || bucketingValue.length === 0) { // A null or empty bucketing value cannot be bucketed. Select the // default variant. return segment.variant; } // Salt and has the value, and compute the allocation and distribution // values. var keyToHash = "".concat(segment.bucket.salt, "/").concat(bucketingValue); var hash = this.getHash(keyToHash); var allocationValue = hash % 100; var distributionValue = Math.floor(hash / 100); try { for (var _c = __values$1(segment.bucket.allocations), _d = _c.next(); !_d.done; _d = _c.next()) { var allocation = _d.value; var allocationStart = allocation.range[0]; var allocationEnd = allocation.range[1]; if (allocationValue >= allocationStart && allocationValue < allocationEnd) { try { for (var _e = (e_6 = void 0, __values$1(allocation.distributions)), _f = _e.next(); !_f.done; _f = _e.next()) { var distribution = _f.value; var distributionStart = distribution.range[0]; var distributionEnd = distribution.range[1]; if (distributionValue >= distributionStart && distributionValue < distributionEnd) { return distribution.variant; } } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (_f && !_f.done && (_b = _e.return)) _b.call(_e); } finally { if (e_6) throw e_6.error; } } } } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (_d && !_d.done && (_a = _c.return)) _a.call(_c); } finally { if (e_5) throw e_5.error; } } return segment.variant; }; EvaluationEngine.prototype.matchNull = function (op, filterValues) { var containsNone = this.containsNone(filterValues); switch (op) { case EvaluationOperator.IS: case EvaluationOperator.CONTAINS: case EvaluationOperator.LESS_THAN: case EvaluationOperator.LESS_THAN_EQUALS: case EvaluationOperator.GREATER_THAN: case EvaluationOperator.GREATER_THAN_EQUALS: case EvaluationOperator.VERSION_LESS_THAN: case EvaluationOperator.VERSION_LESS_THAN_EQUALS: case EvaluationOperator.VERSION_GREATER_THAN: case EvaluationOperator.VERSION_GREATER_THAN_EQUALS: case EvaluationOperator.SET_IS: case EvaluationOperator.SET_CONTAINS: case EvaluationOperator.SET_CONTAINS_ANY: return containsNone; case EvaluationOperator.IS_NOT: case EvaluationOperator.DOES_NOT_CONTAIN: case EvaluationOperator.SET_DOES_NOT_CONTAIN: case EvaluationOperator.SET_DOES_NOT_CONTAIN_ANY: return !containsNone; default: return false; } }; EvaluationEngine.prototype.matchSet = function (propValues, op, filterValues) { switch (op) { case EvaluationOperator.SET_IS: return this.setEquals(propValues, filterValues); case EvaluationOperator.SET_IS_NOT: return !this.setEquals(propValues, filterValues); case EvaluationOperator.SET_CONTAINS: return this.matchesSetContainsAll(propValues, filterValues); case EvaluationOperator.SET_DOES_NOT_CONTAIN: return !this.matchesSetContainsAll(propValues, filterValues); case EvaluationOperator.SET_CONTAINS_ANY: return this.matchesSetContainsAny(propValues, filterValues); case EvaluationOperator.SET_DOES_NOT_CONTAIN_ANY: return !this.matchesSetContainsAny(propValues, filterValues); default: return false; } }; EvaluationEngine.prototype.matchString = function (propValue, op, filterValues) { var _this = this; switch (op) { case EvaluationOperator.IS: return this.matchesIs(propValue, filterValues); case EvaluationOperator.IS_NOT: return !this.matchesIs(propValue, filterValues); case EvaluationOperator.CONTAINS: return this.matchesContains(propValue, filterValues); case EvaluationOperator.DOES_NOT_CONTAIN: return !this.matchesContains(propValue, filterValues); case EvaluationOperator.LESS_THAN: case EvaluationOperator.LESS_THAN_EQUALS: case EvaluationOperator.GREATER_THAN: case EvaluationOperator.GREATER_THAN_EQUALS: return this.matchesComparable(propValue, op, filterValues, function (value) { return _this.parseNumber(value); }, this.comparator); case EvaluationOperator.VERSION_LESS_THAN: case EvaluationOperator.VERSION_LESS_THAN_EQUALS: case EvaluationOperator.VERSION_GREATER_THAN: case EvaluationOperator.VERSION_GREATER_THAN_EQUALS: return this.matchesComparable(propValue, op, filterValues, function (value) { return SemanticVersion.parse(value); }, this.versionComparator); case EvaluationOperator.REGEX_MATCH: return this.matchesRegex(propValue, filterValues); case EvaluationOperator.REGEX_DOES_NOT_MATCH: return !this.matchesRegex(propValue, filterValues); default: return false; } }; EvaluationEngine.prototype.matchesIs = function (propValue, filterValues) { if (this.containsBooleans(filterValues)) { var lower_1 = propValue.toLowerCase(); if (lower_1 === 'true' || lower_1 === 'false') { return filterValues.some(function (value) { return value.toLowerCase() === lower_1; }); } } return filterValues.some(function (value) { return propValue === value; }); }; EvaluationEngine.prototype.matchesContains = function (propValue, filterValues) { var e_7, _a; try { for (var filterValues_1 = __values$1(filterValues), filterValues_1_1 = filterValues_1.next(); !filterValues_1_1.done; filterValues_1_1 = filterValues_1.next()) { var filterValue = filterValues_1_1.value; if (propValue.toLowerCase().includes(filterValue.toLowerCase())) { return true; } } } catch (e_7_1) { e_7 = { error: e_7_1 }; } finally { try { if (filterValues_1_1 && !filterValues_1_1.done && (_a = filterValues_1.return)) _a.call(filterValues_1); } finally { if (e_7) throw e_7.error; } } return false; }; EvaluationEngine.prototype.matchesComparable = function (propValue, op, filterValues, typeTransformer, typeComparator) { var _this = this; var propValueTransformed = typeTransformer(propValue); var filterValuesTransformed = filterValues.map(function (filterValue) { return typeTransformer(filterValue); }).filter(function (filterValue) { return filterValue !== undefined; }); if (propValueTransformed === undefined || filterValuesTransformed.length === 0) { return filterValues.some(function (filterValue) { return _this.comparator(propValue, op, filterValue); }); } else { return filterValuesTransformed.some(function (filterValueTransformed) { return typeComparator(propValueTransformed, op, filterValueTransformed); }); } }; EvaluationEngine.prototype.comparator = function (propValue, op, filterValue) { switch (op) { case EvaluationOperator.LESS_THAN: case EvaluationOperator.VERSION_LESS_THAN: return propValue < filterValue; case EvaluationOperator.LESS_THAN_EQUALS: case EvaluationOperator.VERSION_LESS_THAN_EQUALS: return propValue <= filterValue; case EvaluationOperator.GREATER_THAN: case EvaluationOperator.VERSION_GREATER_THAN: return propValue > filterValue; case EvaluationOperator.GREATER_THAN_EQUALS: case EvaluationOperator.VERSION_GREATER_THAN_EQUALS: return propValue >= filterValue; default: return false; } }; EvaluationEngine.prototype.versionComparator = function (propValue, op, filterValue) { var compareTo = propValue.compareTo(filterValue); switch (op) { case EvaluationOperator.LESS_THAN: case EvaluationOperator.VERSION_LESS_THAN: return compareTo < 0; case EvaluationOperator.LESS_THAN_EQUALS: case EvaluationOperator.VERSION_LESS_THAN_EQUALS: return compareTo <= 0; case EvaluationOperator.GREATER_THAN: case EvaluationOperator.VERSION_GREATER_THAN: return compareTo > 0; case EvaluationOperator.GREATER_THAN_EQUALS: case EvaluationOperator.VERSION_GREATER_THAN_EQUALS: return compareTo >= 0; default: return false; } }; EvaluationEngine.prototype.matchesRegex = function (propValue, filterValues) { return filterValues.some(function (filterValue) { return Boolean(new RegExp(filterValue).exec(propValue)); }); }; EvaluationEngine.prototype.containsNone = function (filterValues) { return filterValues.some(function (filterValue) { return filterValue === '(none)'; }); }; EvaluationEngine.prototype.containsBooleans = function (filterValues) { return filterValues.some(function (filterValue) { switch (filterValue.toLowerCase()) { case 'true': case 'false': return true; default: return false; } }); }; EvaluationEngine.prototype.parseNumber = function (value) { var _a; return (_a = Number(value)) !== null && _a !== void 0 ? _a : undefined; }; EvaluationEngine.prototype.coerceString = function (value) { if (value === undefined || value === null) { return undefined; } if (typeof value === 'object') { return JSON.stringify(value); } return String(value); }; EvaluationEngine.prototype.coerceStringArray = function (value) { var _this = this; if (Array.isArray(value)) { var anyArray = value; return anyArray.map(function (e) { return _this.coerceString(e); }).filter(Boolean); } var stringValue = String(value); try { var parsedValue = JSON.parse(stringValue); if (Array.isArray(parsedValue)) { var anyArray = value; return anyArray.map(function (e) { return _this.coerceString(e); }).filter(Boolean); } else { var s = this.coerceString(stringValue); return s ? [s] : undefined; } } catch (_a) { var s = this.coerceString(stringValue); return s ? [s] : undefined; } }; EvaluationEngine.prototype.isSetOperator = function (op) { switch (op) { case EvaluationOperator.SET_IS: case EvaluationOperator.SET_IS_NOT: case EvaluationOperator.SET_CONTAINS: case EvaluationOperator.SET_DOES_NOT_CONTAIN: case EvaluationOperator.SET_CONTAINS_ANY: case EvaluationOperator.SET_DOES_NOT_CONTAIN_ANY: return true; default: return false; } }; EvaluationEngine.prototype.setEquals = function (xa, ya) { var xs = new Set(xa); var ys = new Set(ya); return xs.size === ys.size && __spreadArray([], __read$1(ys), false).every(function (y) { return xs.has(y); }); }; EvaluationEngine.prototype.matchesSetContainsAll = function (propValues, filterValues) { var e_8, _a; if (propValues.length < filterValues.length) { return false; } try { for (var filterValues_2 = __values$1(filterValues), filterValues_2_1 = filterValues_2.next(); !filterValues_2_1.done; filterValues_2_1 = filterValues_2.next()) { var filterValue = filterValues_2_1.value; if (!this.matchesIs(filterValue, propValues)) { return false; } } } catch (e_8_1) { e_8 = { error: e_8_1 }; } finally { try { if (filterValues_2_1 && !filterValues_2_1.done && (_a = filterValues_2.return)) _a.call(filterValues_2); } finally { if (e_8) throw e_8.error; } } return true; }; EvaluationEngine.prototype.matchesSetContainsAny = function (propValues, filterValues) { var e_9, _a; try { for (var filterValues_3 = __values$1(filterValues), filterValues_3_1 = filterValues_3.next(); !filterValues_3_1.done; filterValues_3_1 = filterValues_3.next()) { var filterValue = filterValues_3_1.value; if (this.matchesIs(filterValue, propValues)) { return true; } } } catch (e_9_1) { e_9 = { error: e_9_1 }; } finally { try { if (filterValues_3_1 && !filterValues_3_1.done && (_a = filterValues_3.return)) _a.call(filterValues_3); } finally { if (e_9) throw e_9.error; } } return false; }; return EvaluationEngine; }(); var topologicalSort = function (flags, flagKeys) { var e_1, _a; var available = __assign$1({}, flags); var result = []; var startingKeys = flagKeys || Object.keys(available); try { for (var startingKeys_1 = __values$1(startingKeys), startingKeys_1_1 = startingKeys_1.next(); !startingKeys_1_1.done; startingKeys_1_1 = startingKeys_1.next()) { var flagKey = startingKeys_1_1.value; var traversal = parentTraversal(flagKey, available); if (traversal) { result.push.apply(result, __spreadArray([], __read$1(traversal), false)); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (startingKeys_1_1 && !startingKeys_1_1.done && (_a = startingKeys_1.return)) _a.call(startingKeys_1); } finally { if (e_1) throw e_1.error; } } return result; }; var parentTraversal = function (flagKey, available, path) { var e_2, _a; if (path === void 0) { path = []; } var flag = available[flagKey]; if (!flag) { return undefined; } else if (!flag.dependencies || flag.dependencies.length === 0) { delete available[flag.key]; return [flag]; } path.push(flag.key); var result = []; var _loop_1 = function (parentKey) { if (path.some(function (p) { return p === parentKey; })) { throw Error("Detected a cycle between flags ".concat(path)); } var traversal = parentTraversal(parentKey, available, path); if (traversal) { result.push.apply(result, __spreadArray([], __read$1(traversal), false)); } }; try { for (var _b = __values$1(flag.dependencies), _c = _b.next(); !_c.done; _c = _b.next()) { var parentKey = _c.value; _loop_1(parentKey); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_2) throw e_2.error; } } result.push(flag); path.pop(); delete available[flag.key]; return result; }; /** * base64.ts * * Licensed under the BSD 3-Clause License. * http://opensource.org/licenses/BSD-3-Clause * * References: * http://en.wikipedia.org/wiki/Base64 * * @author Dan Kogai (https://github.com/dankogai) */ const version$1 = '3.7.7'; /** * @deprecated use lowercase `version`. */ const VERSION = version$1; const _hasBuffer = typeof Buffer === 'function'; const _TD = typeof TextDecoder === 'function' ? new TextDecoder() : undefined; const _TE = typeof TextEncoder === 'function' ? new TextEncoder() : undefined; const b64ch = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; const b64chs = Array.prototype.slice.call(b64ch); const b64tab = (a => { let tab = {}; a.forEach((c, i) => tab[c] = i); return tab; })(b64chs); const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/; const _fromCC = String.fromCharCode.bind(String); const _U8Afrom = typeof Uint8Array.from === 'function' ? Uint8Array.from.bind(Uint8Array) : it => new Uint8Array(Array.prototype.slice.call(it, 0)); const _mkUriSafe = src => src.replace(/=/g, '').replace(/[+\/]/g, m0 => m0 == '+' ? '-' : '_'); const _tidyB64 = s => s.replace(/[^A-Za-z0-9\+\/]/g, ''); /** * polyfill version of `btoa` */ const btoaPolyfill = bin => { // console.log('polyfilled'); let u32, c0, c1, c2, asc = ''; const pad = bin.length % 3; for (let i = 0; i < bin.length;) { if ((c0 = bin.charCodeAt(i++)) > 255 || (c1 = bin.charCodeAt(i++)) > 255 || (c2 = bin.charCodeAt(i++)) > 255) throw new TypeError('invalid character found'); u32 = c0 << 16 | c1 << 8 | c2; asc += b64chs[u32 >> 18 & 63] + b64chs[u32 >> 12 & 63] + b64chs[u32 >> 6 & 63] + b64chs[u32 & 63]; } return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc; }; /** * does what `window.btoa` of web browsers do. * @param {String} bin binary string * @returns {string} Base64-encoded string */ const _btoa = typeof btoa === 'function' ? bin => btoa(bin) : _hasBuffer ? bin => Buffer.from(bin, 'binary').toString('base64') : btoaPolyfill; const _fromUint8Array = _hasBuffer ? u8a => Buffer.from(u8a).toString('base64') : u8a => { // cf. https://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string/12713326#12713326 const maxargs = 0x1000; let strs = []; for (let i