launchdarkly-js-sdk-common 3.4.0 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/dist/ldclient-common.cjs.js +1 -1
- package/dist/ldclient-common.cjs.js.map +1 -1
- package/dist/ldclient-common.es.js +1 -1
- package/dist/ldclient-common.es.js.map +1 -1
- package/dist/ldclient-common.min.js +1 -1
- package/dist/ldclient-common.min.js.map +1 -1
- package/package.json +2 -2
- package/typings.d.ts +96 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ldclient-common.min.js","sources":["../src/errors.js","../node_modules/base64-js/index.js","../node_modules/fast-deep-equal/index.js","../src/utils.js","../node_modules/uuid/lib/bytesToUuid.js","../node_modules/uuid/lib/rng-browser.js","../node_modules/uuid/v1.js","../src/EventSender.js","../src/UserFilter.js","../src/messages.js","../src/EventProcessor.js","../src/EventSummarizer.js","../src/EventEmitter.js","../src/InitializationState.js","../src/Store.js","../src/Stream.js","../src/Requestor.js","../src/promiseCoalescer.js","../src/UserValidator.js","../src/configuration.js","../src/diagnosticEvents.js","../src/consoleLogger.js","../src/index.js","../src/Identity.js"],"sourcesContent":["function createCustomError(name) {\n function CustomError(message, code) {\n Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);\n this.message = message;\n this.code = code;\n }\n\n CustomError.prototype = new Error();\n CustomError.prototype.name = name;\n CustomError.prototype.constructor = CustomError;\n\n return CustomError;\n}\n\nexport const LDUnexpectedResponseError = createCustomError('LaunchDarklyUnexpectedResponseError');\nexport const LDInvalidEnvironmentIdError = createCustomError('LaunchDarklyInvalidEnvironmentIdError');\nexport const LDInvalidUserError = createCustomError('LaunchDarklyInvalidUserError');\nexport const LDInvalidEventKeyError = createCustomError('LaunchDarklyInvalidEventKeyError');\nexport const LDInvalidArgumentError = createCustomError('LaunchDarklyInvalidArgumentError');\nexport const LDFlagFetchError = createCustomError('LaunchDarklyFlagFetchError');\n\nexport function isHttpErrorRecoverable(status) {\n if (status >= 400 && status < 500) {\n return status === 400 || status === 408 || status === 429;\n }\n return true;\n}\n","'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n var len = b64.length\n\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf('=')\n if (validLen === -1) validLen = len\n\n var placeHoldersLen = validLen === len\n ? 0\n : 4 - (validLen % 4)\n\n return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n var tmp\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n var curByte = 0\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0\n ? validLen - 4\n : validLen\n\n for (var i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)]\n arr[curByte++] = (tmp >> 16) & 0xFF\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] +\n lookup[num >> 12 & 0x3F] +\n lookup[num >> 6 & 0x3F] +\n lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xFF0000) +\n ((uint8[i + 1] << 8) & 0xFF00) +\n (uint8[i + 2] & 0xFF)\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(\n uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)\n ))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n parts.push(\n lookup[tmp >> 2] +\n lookup[(tmp << 4) & 0x3F] +\n '=='\n )\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3F] +\n lookup[(tmp << 2) & 0x3F] +\n '='\n )\n }\n\n return parts.join('')\n}\n","'use strict';\n\nvar isArray = Array.isArray;\nvar keyList = Object.keys;\nvar hasProp = Object.prototype.hasOwnProperty;\n\nmodule.exports = function equal(a, b) {\n if (a === b) return true;\n\n if (a && b && typeof a == 'object' && typeof b == 'object') {\n var arrA = isArray(a)\n , arrB = isArray(b)\n , i\n , length\n , key;\n\n if (arrA && arrB) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0;)\n if (!equal(a[i], b[i])) return false;\n return true;\n }\n\n if (arrA != arrB) return false;\n\n var dateA = a instanceof Date\n , dateB = b instanceof Date;\n if (dateA != dateB) return false;\n if (dateA && dateB) return a.getTime() == b.getTime();\n\n var regexpA = a instanceof RegExp\n , regexpB = b instanceof RegExp;\n if (regexpA != regexpB) return false;\n if (regexpA && regexpB) return a.toString() == b.toString();\n\n var keys = keyList(a);\n length = keys.length;\n\n if (length !== keyList(b).length)\n return false;\n\n for (i = length; i-- !== 0;)\n if (!hasProp.call(b, keys[i])) return false;\n\n for (i = length; i-- !== 0;) {\n key = keys[i];\n if (!equal(a[key], b[key])) return false;\n }\n\n return true;\n }\n\n return a!==a && b!==b;\n};\n","import * as base64 from 'base64-js';\nimport fastDeepEqual from 'fast-deep-equal';\n\nconst userAttrsToStringify = ['key', 'secondary', 'ip', 'country', 'email', 'firstName', 'lastName', 'avatar', 'name'];\n\n// See http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html\nexport function btoa(s) {\n const escaped = unescape(encodeURIComponent(s));\n return base64.fromByteArray(stringToBytes(escaped));\n}\n\nfunction stringToBytes(s) {\n const b = [];\n for (let i = 0; i < s.length; i++) {\n b.push(s.charCodeAt(i));\n }\n return b;\n}\n\nexport function base64URLEncode(s) {\n return (\n btoa(s)\n // eslint-disable-next-line\n .replace(/=/g, '')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n );\n}\n\nexport function clone(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n\nexport function deepEquals(a, b) {\n return fastDeepEqual(a, b);\n}\n\n// Events emitted in LDClient's initialize method will happen before the consumer\n// can register a listener, so defer them to next tick.\nexport function onNextTick(cb) {\n setTimeout(cb, 0);\n}\n\n/**\n * Wrap a promise to invoke an optional callback upon resolution or rejection.\n *\n * This function assumes the callback follows the Node.js callback type: (err, value) => void\n *\n * If a callback is provided:\n * - if the promise is resolved, invoke the callback with (null, value)\n * - if the promise is rejected, invoke the callback with (error, null)\n *\n * @param {Promise<any>} promise\n * @param {Function} callback\n * @returns Promise<any> | undefined\n */\nexport function wrapPromiseCallback(promise, callback) {\n const ret = promise.then(\n value => {\n if (callback) {\n setTimeout(() => {\n callback(null, value);\n }, 0);\n }\n return value;\n },\n error => {\n if (callback) {\n setTimeout(() => {\n callback(error, null);\n }, 0);\n } else {\n return Promise.reject(error);\n }\n }\n );\n\n return !callback ? ret : undefined;\n}\n\n/**\n * Takes a map of flag keys to values, and returns the more verbose structure used by the\n * client stream.\n */\nexport function transformValuesToVersionedValues(flags) {\n const ret = {};\n for (const key in flags) {\n if (objectHasOwnProperty(flags, key)) {\n ret[key] = { value: flags[key], version: 0 };\n }\n }\n return ret;\n}\n\n/**\n * Converts the internal flag state map to a simple map of flag keys to values.\n */\nexport function transformVersionedValuesToValues(flagsState) {\n const ret = {};\n for (const key in flagsState) {\n if (objectHasOwnProperty(flagsState, key)) {\n ret[key] = flagsState[key].value;\n }\n }\n return ret;\n}\n\n/**\n * Returns an array of event groups each of which can be safely URL-encoded\n * without hitting the safe maximum URL length of certain browsers.\n *\n * @param {number} maxLength maximum URL length targeted\n * @param {Array[Object}]} events queue of events to divide\n * @returns Array[Array[Object]]\n */\nexport function chunkUserEventsForUrl(maxLength, events) {\n const allEvents = events.slice(0);\n const allChunks = [];\n let remainingSpace = maxLength;\n let chunk;\n\n while (allEvents.length > 0) {\n chunk = [];\n\n while (remainingSpace > 0) {\n const event = allEvents.shift();\n if (!event) {\n break;\n }\n remainingSpace = remainingSpace - base64URLEncode(JSON.stringify(event)).length;\n // If we are over the max size, put this one back on the queue\n // to try in the next round, unless this event alone is larger\n // than the limit, in which case, screw it, and try it anyway.\n if (remainingSpace < 0 && chunk.length > 0) {\n allEvents.unshift(event);\n } else {\n chunk.push(event);\n }\n }\n\n remainingSpace = maxLength;\n allChunks.push(chunk);\n }\n\n return allChunks;\n}\n\nexport function getLDUserAgentString(platform) {\n const version = platform.version || VERSION;\n return platform.userAgent + '/' + version;\n}\n\nexport function getLDHeaders(platform, options) {\n if (options && !options.sendLDHeaders) {\n return {};\n }\n const h = {\n 'X-LaunchDarkly-User-Agent': getLDUserAgentString(platform),\n };\n if (options && options.wrapperName) {\n h['X-LaunchDarkly-Wrapper'] = options.wrapperVersion\n ? options.wrapperName + '/' + options.wrapperVersion\n : options.wrapperName;\n }\n return h;\n}\n\nexport function transformHeaders(headers, options) {\n if (!options || !options.requestHeaderTransform) {\n return headers;\n }\n return options.requestHeaderTransform({ ...headers });\n}\n\nexport function extend(...objects) {\n return objects.reduce((acc, obj) => ({ ...acc, ...obj }), {});\n}\n\nexport function objectHasOwnProperty(object, name) {\n return Object.prototype.hasOwnProperty.call(object, name);\n}\n\nexport function sanitizeUser(user) {\n if (!user) {\n return user;\n }\n let newUser;\n for (const i in userAttrsToStringify) {\n const attr = userAttrsToStringify[i];\n const value = user[attr];\n if (value !== undefined && typeof value !== 'string') {\n newUser = newUser || { ...user };\n newUser[attr] = String(value);\n }\n }\n return newUser || user;\n}\n","/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nvar byteToHex = [];\nfor (var i = 0; i < 256; ++i) {\n byteToHex[i] = (i + 0x100).toString(16).substr(1);\n}\n\nfunction bytesToUuid(buf, offset) {\n var i = offset || 0;\n var bth = byteToHex;\n // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4\n return ([bth[buf[i++]], bth[buf[i++]], \n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]],\n\tbth[buf[i++]], bth[buf[i++]],\n\tbth[buf[i++]], bth[buf[i++]]]).join('');\n}\n\nmodule.exports = bytesToUuid;\n","// Unique ID creation requires a high quality random # generator. In the\n// browser this is a little complicated due to unknown quality of Math.random()\n// and inconsistent support for the `crypto` API. We do the best we can via\n// feature-detection\n\n// getRandomValues needs to be invoked in a context where \"this\" is a Crypto\n// implementation. Also, find the complete implementation of crypto on IE11.\nvar getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||\n (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));\n\nif (getRandomValues) {\n // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto\n var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef\n\n module.exports = function whatwgRNG() {\n getRandomValues(rnds8);\n return rnds8;\n };\n} else {\n // Math.random()-based (RNG)\n //\n // If all else fails, use Math.random(). It's fast, but is of unspecified\n // quality.\n var rnds = new Array(16);\n\n module.exports = function mathRNG() {\n for (var i = 0, r; i < 16; i++) {\n if ((i & 0x03) === 0) r = Math.random() * 0x100000000;\n rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;\n }\n\n return rnds;\n };\n}\n","var rng = require('./lib/rng');\nvar bytesToUuid = require('./lib/bytesToUuid');\n\n// **`v1()` - Generate time-based UUID**\n//\n// Inspired by https://github.com/LiosK/UUID.js\n// and http://docs.python.org/library/uuid.html\n\nvar _nodeId;\nvar _clockseq;\n\n// Previous uuid creation time\nvar _lastMSecs = 0;\nvar _lastNSecs = 0;\n\n// See https://github.com/broofa/node-uuid for API details\nfunction v1(options, buf, offset) {\n var i = buf && offset || 0;\n var b = buf || [];\n\n options = options || {};\n var node = options.node || _nodeId;\n var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;\n\n // node and clockseq need to be initialized to random values if they're not\n // specified. We do this lazily to minimize issues related to insufficient\n // system entropy. See #189\n if (node == null || clockseq == null) {\n var seedBytes = rng();\n if (node == null) {\n // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n node = _nodeId = [\n seedBytes[0] | 0x01,\n seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]\n ];\n }\n if (clockseq == null) {\n // Per 4.2.2, randomize (14 bit) clockseq\n clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;\n }\n }\n\n // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();\n\n // Per 4.2.1.2, use count of uuid's generated during the current clock\n // cycle to simulate higher resolution clock\n var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;\n\n // Time since last uuid creation (in msecs)\n var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;\n\n // Per 4.2.1.2, Bump clockseq on clock regression\n if (dt < 0 && options.clockseq === undefined) {\n clockseq = clockseq + 1 & 0x3fff;\n }\n\n // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n // time interval\n if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n nsecs = 0;\n }\n\n // Per 4.2.1.2 Throw error if too many uuids are requested\n if (nsecs >= 10000) {\n throw new Error('uuid.v1(): Can\\'t create more than 10M uuids/sec');\n }\n\n _lastMSecs = msecs;\n _lastNSecs = nsecs;\n _clockseq = clockseq;\n\n // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n msecs += 12219292800000;\n\n // `time_low`\n var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n b[i++] = tl >>> 24 & 0xff;\n b[i++] = tl >>> 16 & 0xff;\n b[i++] = tl >>> 8 & 0xff;\n b[i++] = tl & 0xff;\n\n // `time_mid`\n var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;\n b[i++] = tmh >>> 8 & 0xff;\n b[i++] = tmh & 0xff;\n\n // `time_high_and_version`\n b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n b[i++] = tmh >>> 16 & 0xff;\n\n // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n b[i++] = clockseq >>> 8 | 0x80;\n\n // `clock_seq_low`\n b[i++] = clockseq & 0xff;\n\n // `node`\n for (var n = 0; n < 6; ++n) {\n b[i + n] = node[n];\n }\n\n return buf ? buf : bytesToUuid(b);\n}\n\nmodule.exports = v1;\n","import * as errors from './errors';\nimport * as utils from './utils';\nimport uuidv1 from 'uuid/v1';\n\nconst MAX_URL_LENGTH = 2000;\n\nexport default function EventSender(platform, environmentId, options) {\n const imageUrlPath = '/a/' + environmentId + '.gif';\n const baseHeaders = utils.extend({ 'Content-Type': 'application/json' }, utils.getLDHeaders(platform, options));\n const httpFallbackPing = platform.httpFallbackPing; // this will be set for us if we're in the browser SDK\n const sender = {};\n\n function getResponseInfo(result) {\n const ret = { status: result.status };\n const dateStr = result.header('date');\n if (dateStr) {\n const time = Date.parse(dateStr);\n if (time) {\n ret.serverTime = time;\n }\n }\n return ret;\n }\n\n sender.sendChunk = (events, url, isDiagnostic, usePost) => {\n const jsonBody = JSON.stringify(events);\n const payloadId = isDiagnostic ? null : uuidv1();\n\n function doPostRequest(canRetry) {\n const headers = isDiagnostic\n ? baseHeaders\n : utils.extend({}, baseHeaders, {\n 'X-LaunchDarkly-Event-Schema': '3',\n 'X-LaunchDarkly-Payload-ID': payloadId,\n });\n return platform\n .httpRequest('POST', url, utils.transformHeaders(headers, options), jsonBody)\n .promise.then(result => {\n if (!result) {\n // This was a response from a fire-and-forget request, so we won't have a status.\n return;\n }\n if (result.status >= 400 && errors.isHttpErrorRecoverable(result.status) && canRetry) {\n return doPostRequest(false);\n } else {\n return getResponseInfo(result);\n }\n })\n .catch(() => {\n if (canRetry) {\n return doPostRequest(false);\n }\n return Promise.reject();\n });\n }\n\n if (usePost) {\n return doPostRequest(true).catch(() => {});\n } else {\n httpFallbackPing && httpFallbackPing(url + imageUrlPath + '?d=' + utils.base64URLEncode(jsonBody));\n return Promise.resolve(); // we don't wait for this request to complete, it's just a one-way ping\n }\n };\n\n sender.sendEvents = function(events, url, isDiagnostic) {\n if (!platform.httpRequest) {\n return Promise.resolve();\n }\n const canPost = platform.httpAllowsPost();\n let chunks;\n if (canPost) {\n // no need to break up events into chunks if we can send a POST\n chunks = [events];\n } else {\n chunks = utils.chunkUserEventsForUrl(MAX_URL_LENGTH - url.length, events);\n }\n const results = [];\n for (let i = 0; i < chunks.length; i++) {\n results.push(sender.sendChunk(chunks[i], url, isDiagnostic, canPost));\n }\n return Promise.all(results);\n };\n\n return sender;\n}\n","import * as utils from './utils';\n\n/**\n * The UserFilter object transforms user objects into objects suitable to be sent as JSON to\n * the server, hiding any private user attributes.\n *\n * @param {Object} the LaunchDarkly client configuration object\n **/\nexport default function UserFilter(config) {\n const filter = {};\n const allAttributesPrivate = config.allAttributesPrivate;\n const privateAttributeNames = config.privateAttributeNames || [];\n const ignoreAttrs = { key: true, custom: true, anonymous: true };\n const allowedTopLevelAttrs = {\n key: true,\n secondary: true,\n ip: true,\n country: true,\n email: true,\n firstName: true,\n lastName: true,\n avatar: true,\n name: true,\n anonymous: true,\n custom: true,\n };\n\n filter.filterUser = function(user) {\n if (!user) {\n return null;\n }\n const userPrivateAttrs = user.privateAttributeNames || [];\n\n const isPrivateAttr = function(name) {\n return (\n !ignoreAttrs[name] &&\n (allAttributesPrivate || userPrivateAttrs.indexOf(name) !== -1 || privateAttributeNames.indexOf(name) !== -1)\n );\n };\n const filterAttrs = function(props, isAttributeAllowed) {\n return Object.keys(props).reduce(\n (acc, name) => {\n const ret = acc;\n if (isAttributeAllowed(name)) {\n if (isPrivateAttr(name)) {\n // add to hidden list\n ret[1][name] = true;\n } else {\n ret[0][name] = props[name];\n }\n }\n return ret;\n },\n [{}, {}]\n );\n };\n const result = filterAttrs(user, key => allowedTopLevelAttrs[key]);\n const filteredProps = result[0];\n let removedAttrs = result[1];\n if (user.custom) {\n const customResult = filterAttrs(user.custom, () => true);\n filteredProps.custom = customResult[0];\n removedAttrs = utils.extend({}, removedAttrs, customResult[1]);\n }\n const removedAttrNames = Object.keys(removedAttrs);\n if (removedAttrNames.length) {\n removedAttrNames.sort();\n filteredProps.privateAttrs = removedAttrNames;\n }\n return filteredProps;\n };\n return filter;\n}\n","import * as errors from './errors';\n\nfunction errorString(err) {\n if (err && err.message) {\n return err.message;\n }\n if (typeof err === 'string' || err instanceof String) {\n return err;\n }\n return JSON.stringify(err);\n}\n\nexport const clientInitialized = function() {\n return 'LaunchDarkly client initialized';\n};\n\nconst docLink =\n ' Please see https://docs.launchdarkly.com/sdk/client-side/javascript#initializing-the-client for instructions on SDK initialization.';\n\nexport const clientNotReady = function() {\n return 'LaunchDarkly client is not ready';\n};\n\nexport const eventCapacityExceeded = function() {\n return 'Exceeded event queue capacity. Increase capacity to avoid dropping events.';\n};\n\nexport const eventWithoutUser = function() {\n return 'Be sure to call `identify` in the LaunchDarkly client: https://docs.launchdarkly.com/sdk/features/identify#javascript';\n};\n\nexport const invalidContentType = function(contentType) {\n return 'Expected application/json content type but got \"' + contentType + '\"';\n};\n\nexport const invalidKey = function() {\n return 'Event key must be a string';\n};\n\nexport const localStorageUnavailable = function() {\n return 'localStorage is unavailable';\n};\n\nexport const localStorageUnavailableForUserId = function() {\n return 'localStorage is unavailable, so anonymous user ID cannot be cached';\n};\n\nexport const networkError = e => 'network error' + (e ? ' (' + e + ')' : '');\n\n// We should remove unknownCustomEventKey in the future - see comments in track() in index.js\nexport const unknownCustomEventKey = function(key) {\n return 'Custom event \"' + key + '\" does not exist';\n};\n\nexport const environmentNotFound = function() {\n return 'Environment not found. Double check that you specified a valid environment/client-side ID.' + docLink;\n};\n\nexport const environmentNotSpecified = function() {\n return 'No environment/client-side ID was specified.' + docLink;\n};\n\nexport const errorFetchingFlags = function(err) {\n return 'Error fetching flag settings: ' + errorString(err);\n};\n\nexport const userNotSpecified = function() {\n return 'No user specified.' + docLink;\n};\n\nexport const invalidUser = function() {\n return 'Invalid user specified.' + docLink;\n};\n\nexport const bootstrapOldFormat = function() {\n return (\n 'LaunchDarkly client was initialized with bootstrap data that did not include flag metadata. ' +\n 'Events may not be sent correctly.' +\n docLink\n );\n};\n\nexport const bootstrapInvalid = function() {\n return 'LaunchDarkly bootstrap data is not available because the back end could not read the flags.';\n};\n\nexport const deprecated = function(oldName, newName) {\n if (newName) {\n return '\"' + oldName + '\" is deprecated, please use \"' + newName + '\"';\n }\n return '\"' + oldName + '\" is deprecated';\n};\n\nexport const httpErrorMessage = function(status, context, retryMessage) {\n return (\n 'Received error ' +\n status +\n (status === 401 ? ' (invalid SDK key)' : '') +\n ' for ' +\n context +\n ' - ' +\n (errors.isHttpErrorRecoverable(status) ? retryMessage : 'giving up permanently')\n );\n};\n\nexport const httpUnavailable = function() {\n return 'Cannot make HTTP requests in this environment.' + docLink;\n};\n\nexport const identifyDisabled = function() {\n return 'identify() has no effect here; it must be called on the main client instance';\n};\n\nexport const streamClosing = function() {\n return 'Closing stream connection';\n};\n\nexport const streamConnecting = function(url) {\n return 'Opening stream connection to ' + url;\n};\n\nexport const streamError = function(err, streamReconnectDelay) {\n return (\n 'Error on stream connection: ' +\n errorString(err) +\n ', will continue retrying every ' +\n streamReconnectDelay +\n ' milliseconds.'\n );\n};\n\nexport const unknownOption = name => 'Ignoring unknown config option \"' + name + '\"';\n\nexport const wrongOptionType = (name, expectedType, actualType) =>\n 'Config option \"' + name + '\" should be of type ' + expectedType + ', got ' + actualType + ', using default value';\n\nexport const wrongOptionTypeBoolean = (name, actualType) =>\n 'Config option \"' + name + '\" should be a boolean, got ' + actualType + ', converting to boolean';\n\nexport const optionBelowMinimum = (name, value, minimum) =>\n 'Config option \"' + name + '\" was set to ' + value + ', changing to minimum value of ' + minimum;\n\nexport const debugPolling = function(url) {\n return 'polling for feature flags at ' + url;\n};\n\nexport const debugStreamPing = function() {\n return 'received ping message from stream';\n};\n\nexport const debugStreamPut = function() {\n return 'received streaming update for all flags';\n};\n\nexport const debugStreamPatch = function(key) {\n return 'received streaming update for flag \"' + key + '\"';\n};\n\nexport const debugStreamPatchIgnored = function(key) {\n return 'received streaming update for flag \"' + key + '\" but ignored due to version check';\n};\n\nexport const debugStreamDelete = function(key) {\n return 'received streaming deletion for flag \"' + key + '\"';\n};\n\nexport const debugStreamDeleteIgnored = function(key) {\n return 'received streaming deletion for flag \"' + key + '\" but ignored due to version check';\n};\n\nexport const debugEnqueueingEvent = function(kind) {\n return 'enqueueing \"' + kind + '\" event';\n};\n\nexport const debugPostingEvents = function(count) {\n return 'sending ' + count + ' events';\n};\n\nexport const debugPostingDiagnosticEvent = function(event) {\n return 'sending diagnostic event (' + event.kind + ')';\n};\n","import EventSender from './EventSender';\nimport EventSummarizer from './EventSummarizer';\nimport UserFilter from './UserFilter';\nimport * as errors from './errors';\nimport * as messages from './messages';\nimport * as utils from './utils';\n\nexport default function EventProcessor(\n platform,\n options,\n environmentId,\n diagnosticsAccumulator = null,\n emitter = null,\n sender = null\n) {\n const processor = {};\n const eventSender = sender || EventSender(platform, environmentId, options);\n const mainEventsUrl = options.eventsUrl + '/events/bulk/' + environmentId;\n const summarizer = EventSummarizer();\n const userFilter = UserFilter(options);\n const inlineUsers = options.inlineUsersInEvents;\n const samplingInterval = options.samplingInterval;\n const eventCapacity = options.eventCapacity;\n const flushInterval = options.flushInterval;\n const logger = options.logger;\n let queue = [];\n let lastKnownPastTime = 0;\n let disabled = false;\n let exceededCapacity = false;\n let flushTimer;\n\n function shouldSampleEvent() {\n return samplingInterval === 0 || Math.floor(Math.random() * samplingInterval) === 0;\n }\n\n function shouldDebugEvent(e) {\n if (e.debugEventsUntilDate) {\n // The \"last known past time\" comes from the last HTTP response we got from the server.\n // In case the client's time is set wrong, at least we know that any expiration date\n // earlier than that point is definitely in the past. If there's any discrepancy, we\n // want to err on the side of cutting off event debugging sooner.\n return e.debugEventsUntilDate > lastKnownPastTime && e.debugEventsUntilDate > new Date().getTime();\n }\n return false;\n }\n\n // Transform an event from its internal format to the format we use when sending a payload.\n function makeOutputEvent(e) {\n const ret = utils.extend({}, e);\n if (e.kind === 'alias') {\n // alias events do not require any transformation\n return ret;\n }\n if (inlineUsers || e.kind === 'identify') {\n // identify events always have an inline user\n ret.user = userFilter.filterUser(e.user);\n } else {\n ret.userKey = e.user.key;\n delete ret['user'];\n }\n if (e.kind === 'feature') {\n delete ret['trackEvents'];\n delete ret['debugEventsUntilDate'];\n }\n return ret;\n }\n\n function addToOutbox(event) {\n if (queue.length < eventCapacity) {\n queue.push(event);\n exceededCapacity = false;\n } else {\n if (!exceededCapacity) {\n exceededCapacity = true;\n logger.warn(messages.eventCapacityExceeded());\n }\n if (diagnosticsAccumulator) {\n // For diagnostic events, we track how many times we had to drop an event due to exceeding the capacity.\n diagnosticsAccumulator.incrementDroppedEvents();\n }\n }\n }\n\n processor.enqueue = function(event) {\n if (disabled) {\n return;\n }\n let addFullEvent = false;\n let addDebugEvent = false;\n\n // Add event to the summary counters if appropriate\n summarizer.summarizeEvent(event);\n\n // Decide whether to add the event to the payload. Feature events may be added twice, once for\n // the event (if tracked) and once for debugging.\n if (event.kind === 'feature') {\n if (shouldSampleEvent()) {\n addFullEvent = !!event.trackEvents;\n addDebugEvent = shouldDebugEvent(event);\n }\n } else {\n addFullEvent = shouldSampleEvent();\n }\n\n if (addFullEvent) {\n addToOutbox(makeOutputEvent(event));\n }\n if (addDebugEvent) {\n const debugEvent = utils.extend({}, event, { kind: 'debug' });\n debugEvent.user = userFilter.filterUser(debugEvent.user);\n delete debugEvent['trackEvents'];\n delete debugEvent['debugEventsUntilDate'];\n addToOutbox(debugEvent);\n }\n };\n\n processor.flush = function() {\n if (disabled) {\n return Promise.resolve();\n }\n const eventsToSend = queue;\n const summary = summarizer.getSummary();\n summarizer.clearSummary();\n if (summary) {\n summary.kind = 'summary';\n eventsToSend.push(summary);\n }\n if (diagnosticsAccumulator) {\n // For diagnostic events, we record how many events were in the queue at the last flush (since \"how\n // many events happened to be in the queue at the moment we decided to send a diagnostic event\" would\n // not be a very useful statistic).\n diagnosticsAccumulator.setEventsInLastBatch(eventsToSend.length);\n }\n if (eventsToSend.length === 0) {\n return Promise.resolve();\n }\n queue = [];\n logger.debug(messages.debugPostingEvents(eventsToSend.length));\n return eventSender.sendEvents(eventsToSend, mainEventsUrl).then(responseInfo => {\n if (responseInfo) {\n if (responseInfo.serverTime) {\n lastKnownPastTime = responseInfo.serverTime;\n }\n if (!errors.isHttpErrorRecoverable(responseInfo.status)) {\n disabled = true;\n }\n if (responseInfo.status >= 400) {\n utils.onNextTick(() => {\n emitter.maybeReportError(\n new errors.LDUnexpectedResponseError(\n messages.httpErrorMessage(responseInfo.status, 'event posting', 'some events were dropped')\n )\n );\n });\n }\n }\n });\n };\n\n processor.start = function() {\n const flushTick = () => {\n processor.flush();\n flushTimer = setTimeout(flushTick, flushInterval);\n };\n flushTimer = setTimeout(flushTick, flushInterval);\n };\n\n processor.stop = function() {\n clearTimeout(flushTimer);\n };\n\n return processor;\n}\n","export default function EventSummarizer() {\n const es = {};\n\n let startDate = 0,\n endDate = 0,\n counters = {};\n\n es.summarizeEvent = function(event) {\n if (event.kind === 'feature') {\n const counterKey =\n event.key +\n ':' +\n (event.variation !== null && event.variation !== undefined ? event.variation : '') +\n ':' +\n (event.version !== null && event.version !== undefined ? event.version : '');\n const counterVal = counters[counterKey];\n if (counterVal) {\n counterVal.count = counterVal.count + 1;\n } else {\n counters[counterKey] = {\n count: 1,\n key: event.key,\n variation: event.variation,\n version: event.version,\n value: event.value,\n default: event.default,\n };\n }\n if (startDate === 0 || event.creationDate < startDate) {\n startDate = event.creationDate;\n }\n if (event.creationDate > endDate) {\n endDate = event.creationDate;\n }\n }\n };\n\n es.getSummary = function() {\n const flagsOut = {};\n let empty = true;\n for (const i in counters) {\n const c = counters[i];\n let flag = flagsOut[c.key];\n if (!flag) {\n flag = {\n default: c.default,\n counters: [],\n };\n flagsOut[c.key] = flag;\n }\n const counterOut = {\n value: c.value,\n count: c.count,\n };\n if (c.variation !== undefined && c.variation !== null) {\n counterOut.variation = c.variation;\n }\n if (c.version) {\n counterOut.version = c.version;\n } else {\n counterOut.unknown = true;\n }\n flag.counters.push(counterOut);\n empty = false;\n }\n return empty\n ? null\n : {\n startDate,\n endDate,\n features: flagsOut,\n };\n };\n\n es.clearSummary = function() {\n startDate = 0;\n endDate = 0;\n counters = {};\n };\n\n return es;\n}\n","export default function EventEmitter(logger) {\n const emitter = {};\n const events = {};\n\n const listeningTo = event => !!events[event];\n\n emitter.on = function(event, handler, context) {\n events[event] = events[event] || [];\n events[event] = events[event].concat({\n handler: handler,\n context: context,\n });\n };\n\n emitter.off = function(event, handler, context) {\n if (!events[event]) {\n return;\n }\n for (let i = 0; i < events[event].length; i++) {\n if (events[event][i].handler === handler && events[event][i].context === context) {\n events[event] = events[event].slice(0, i).concat(events[event].slice(i + 1));\n }\n }\n };\n\n emitter.emit = function(event) {\n if (!events[event]) {\n return;\n }\n // Copy the list of handlers before iterating, in case any handler adds or removes another handler.\n // Any such changes should not affect what we do here-- we want to notify every handler that existed\n // at the moment that the event was fired.\n const copiedHandlers = events[event].slice(0);\n for (let i = 0; i < copiedHandlers.length; i++) {\n copiedHandlers[i].handler.apply(copiedHandlers[i].context, Array.prototype.slice.call(arguments, 1));\n }\n };\n\n emitter.getEvents = function() {\n return Object.keys(events);\n };\n\n emitter.getEventListenerCount = function(event) {\n return events[event] ? events[event].length : 0;\n };\n\n emitter.maybeReportError = function(error) {\n if (!error) {\n return;\n }\n if (listeningTo('error')) {\n this.emit('error', error);\n } else {\n (logger || console).error(error.message);\n }\n };\n return emitter;\n}\n","// This file provides an abstraction of the client's startup state.\n//\n// Startup can either succeed or fail exactly once; calling signalSuccess() or signalFailure()\n// after that point has no effect.\n//\n// On success, we fire both an \"initialized\" event and a \"ready\" event. Both the waitForInitialization()\n// promise and the waitUntilReady() promise are resolved in this case.\n//\n// On failure, we fire both a \"failed\" event (with the error as a parameter) and a \"ready\" event.\n// The waitForInitialization() promise is rejected, but the waitUntilReady() promise is resolved.\n//\n// To complicate things, we must *not* create the waitForInitialization() promise unless it is\n// requested, because otherwise failures would cause an *unhandled* rejection which can be a\n// serious problem in some environments. So we use a somewhat roundabout system for tracking the\n// initialization state and lazily creating this promise.\n\nconst readyEvent = 'ready',\n successEvent = 'initialized',\n failureEvent = 'failed';\n\nfunction InitializationStateTracker(eventEmitter) {\n let succeeded = false,\n failed = false,\n failureValue = null,\n initializationPromise = null;\n\n const readyPromise = new Promise(resolve => {\n const onReady = () => {\n eventEmitter.off(readyEvent, onReady); // we can't use \"once\" because it's not available on some JS platforms\n resolve();\n };\n eventEmitter.on(readyEvent, onReady);\n }).catch(() => {}); // this Promise should never be rejected, but the catch handler is a safety measure\n\n return {\n getInitializationPromise: () => {\n if (initializationPromise) {\n return initializationPromise;\n }\n if (succeeded) {\n return Promise.resolve();\n }\n if (failed) {\n return Promise.reject(failureValue);\n }\n initializationPromise = new Promise((resolve, reject) => {\n const onSuccess = () => {\n eventEmitter.off(successEvent, onSuccess);\n resolve();\n };\n const onFailure = err => {\n eventEmitter.off(failureEvent, onFailure);\n reject(err);\n };\n eventEmitter.on(successEvent, onSuccess);\n eventEmitter.on(failureEvent, onFailure);\n });\n return initializationPromise;\n },\n\n getReadyPromise: () => readyPromise,\n\n signalSuccess: () => {\n if (!succeeded && !failed) {\n succeeded = true;\n eventEmitter.emit(successEvent);\n eventEmitter.emit(readyEvent);\n }\n },\n\n signalFailure: err => {\n if (!succeeded && !failed) {\n failed = true;\n failureValue = err;\n eventEmitter.emit(failureEvent, err);\n eventEmitter.emit(readyEvent);\n }\n eventEmitter.maybeReportError(err); // the \"error\" event can be emitted more than once, unlike the others\n },\n };\n}\n\nmodule.exports = InitializationStateTracker;\n","import * as messages from './messages';\nimport * as utils from './utils';\n\n// The localStorageProvider is provided by the platform object. It should have the following\n// methods, each of which should return a Promise:\n// - get(key): Gets the string value, if any, for the given key\n// - set(key, value): Stores a string value for the given key\n// - remove(key): Removes the given key\nexport default function Store(localStorageProvider, environment, hash, ident, logger) {\n const store = {};\n\n function getFlagsKey() {\n let key = '';\n const user = ident.getUser();\n if (user) {\n key = hash || utils.btoa(JSON.stringify(user));\n }\n return 'ld:' + environment + ':' + key;\n }\n\n // Returns a Promise which will be resolved with a parsed JSON value if a stored value was available,\n // resolved with null if there was no value, or rejected if storage was not available.\n store.loadFlags = () =>\n localStorageProvider\n .get(getFlagsKey())\n .then(dataStr => {\n if (dataStr === null || dataStr === undefined) {\n return null;\n }\n try {\n let data = JSON.parse(dataStr);\n if (data) {\n const schema = data.$schema;\n if (schema === undefined || schema < 1) {\n data = utils.transformValuesToVersionedValues(data);\n } else {\n delete data['$schema'];\n }\n }\n return data;\n } catch (ex) {\n return store.clearFlags().then(() => Promise.reject(ex));\n }\n })\n .catch(err => {\n logger.warn(messages.localStorageUnavailable());\n return Promise.reject(err);\n });\n\n // Returns a Promise which will be resolved with no value if successful, or rejected if storage\n // was not available.\n store.saveFlags = flags => {\n const data = utils.extend({}, flags, { $schema: 1 });\n return localStorageProvider.set(getFlagsKey(), JSON.stringify(data)).catch(err => {\n logger.warn(messages.localStorageUnavailable());\n return Promise.reject(err);\n });\n };\n\n // Returns a Promise which will be resolved with no value if successful, or rejected if storage\n // was not available.\n store.clearFlags = () =>\n localStorageProvider.clear(getFlagsKey()).catch(err => {\n logger.warn(messages.localStorageUnavailable());\n return Promise.reject(err);\n });\n\n return store;\n}\n","import * as messages from './messages';\nimport { base64URLEncode, getLDHeaders, transformHeaders, objectHasOwnProperty } from './utils';\n\n// The underlying event source implementation is abstracted via the platform object, which should\n// have these three properties:\n// eventSourceFactory(): a function that takes a URL and optional config object and returns an object\n// with the same methods as the regular HTML5 EventSource object. The properties in the config\n// object are those supported by the launchdarkly-eventsource package; browser EventSource\n// implementations don't have any config options.\n// eventSourceIsActive(): a function that takes an EventSource-compatible object and returns true if\n// it is in an active state (connected or connecting).\n// eventSourceAllowsReport: true if REPORT is supported.\n\n// The read timeout for the stream is a fixed value that is set to be slightly longer than the expected\n// interval between heartbeats from the LaunchDarkly streaming server. If this amount of time elapses\n// with no new data, the connection will be cycled.\nconst streamReadTimeoutMillis = 5 * 60 * 1000; // 5 minutes\n\nexport default function Stream(platform, config, environment, diagnosticsAccumulator) {\n const baseUrl = config.streamUrl;\n const logger = config.logger;\n const stream = {};\n const evalUrlPrefix = baseUrl + '/eval/' + environment;\n const useReport = config.useReport;\n const withReasons = config.evaluationReasons;\n const streamReconnectDelay = config.streamReconnectDelay;\n const headers = getLDHeaders(platform, config);\n let firstConnectionErrorLogged = false;\n let es = null;\n let reconnectTimeoutReference = null;\n let connectionAttemptStartTime;\n let user = null;\n let hash = null;\n let handlers = null;\n\n stream.connect = function(newUser, newHash, newHandlers) {\n user = newUser;\n hash = newHash;\n handlers = {};\n for (const key in newHandlers || {}) {\n handlers[key] = function(e) {\n // Reset the state for logging the first connection error so that the first\n // connection error following a successful connection will once again be logged.\n // We will decorate *all* handlers to do this to keep this abstraction agnostic\n // for different stream implementations.\n firstConnectionErrorLogged = false;\n logConnectionResult(true);\n newHandlers[key] && newHandlers[key](e);\n };\n }\n tryConnect();\n };\n\n stream.disconnect = function() {\n clearTimeout(reconnectTimeoutReference);\n reconnectTimeoutReference = null;\n closeConnection();\n };\n\n stream.isConnected = function() {\n return !!(es && platform.eventSourceIsActive && platform.eventSourceIsActive(es));\n };\n\n function handleError(err) {\n if (!firstConnectionErrorLogged) {\n logger.warn(messages.streamError(err, streamReconnectDelay));\n firstConnectionErrorLogged = true;\n }\n logConnectionResult(false);\n closeConnection();\n tryConnect(streamReconnectDelay);\n }\n\n function tryConnect(delay) {\n if (!reconnectTimeoutReference) {\n if (delay) {\n reconnectTimeoutReference = setTimeout(openConnection, delay);\n } else {\n openConnection();\n }\n }\n }\n\n function openConnection() {\n reconnectTimeoutReference = null;\n let url;\n let query = '';\n const options = { headers, readTimeoutMillis: streamReadTimeoutMillis };\n if (platform.eventSourceFactory) {\n if (hash !== null && hash !== undefined) {\n query = 'h=' + hash;\n }\n if (useReport) {\n if (platform.eventSourceAllowsReport) {\n url = evalUrlPrefix;\n options.method = 'REPORT';\n options.headers['Content-Type'] = 'application/json';\n options.body = JSON.stringify(user);\n } else {\n // if we can't do REPORT, fall back to the old ping-based stream\n url = baseUrl + '/ping/' + environment;\n query = '';\n }\n } else {\n url = evalUrlPrefix + '/' + base64URLEncode(JSON.stringify(user));\n }\n options.headers = transformHeaders(options.headers, config);\n if (withReasons) {\n query = query + (query ? '&' : '') + 'withReasons=true';\n }\n url = url + (query ? '?' : '') + query;\n\n closeConnection();\n logger.info(messages.streamConnecting(url));\n logConnectionStarted();\n\n es = platform.eventSourceFactory(url, options);\n for (const key in handlers) {\n if (objectHasOwnProperty(handlers, key)) {\n es.addEventListener(key, handlers[key]);\n }\n }\n\n es.onerror = handleError;\n }\n }\n\n function closeConnection() {\n if (es) {\n logger.info(messages.streamClosing());\n es.close();\n es = null;\n }\n }\n\n function logConnectionStarted() {\n connectionAttemptStartTime = new Date().getTime();\n }\n\n function logConnectionResult(success) {\n if (connectionAttemptStartTime && diagnosticsAccumulator) {\n diagnosticsAccumulator.recordStreamInit(\n connectionAttemptStartTime,\n !success,\n new Date().getTime() - connectionAttemptStartTime\n );\n }\n connectionAttemptStartTime = null;\n }\n\n return stream;\n}\n","import * as utils from './utils';\nimport * as errors from './errors';\nimport * as messages from './messages';\nimport promiseCoalescer from './promiseCoalescer';\n\nconst jsonContentType = 'application/json';\n\nfunction getResponseError(result) {\n if (result.status === 404) {\n return new errors.LDInvalidEnvironmentIdError(messages.environmentNotFound());\n } else {\n return new errors.LDFlagFetchError(messages.errorFetchingFlags(result.statusText || String(result.status)));\n }\n}\n\nexport default function Requestor(platform, options, environment) {\n const baseUrl = options.baseUrl;\n const useReport = options.useReport;\n const withReasons = options.evaluationReasons;\n const logger = options.logger;\n\n const requestor = {};\n\n const activeRequests = {}; // map of URLs to promiseCoalescers\n\n function fetchJSON(endpoint, body) {\n if (!platform.httpRequest) {\n return new Promise((resolve, reject) => {\n reject(new errors.LDFlagFetchError(messages.httpUnavailable()));\n });\n }\n\n const method = body ? 'REPORT' : 'GET';\n const headers = utils.getLDHeaders(platform, options);\n if (body) {\n headers['Content-Type'] = jsonContentType;\n }\n\n let coalescer = activeRequests[endpoint];\n if (!coalescer) {\n coalescer = promiseCoalescer(() => {\n // this will be called once there are no more active requests for the same endpoint\n delete activeRequests[endpoint];\n });\n activeRequests[endpoint] = coalescer;\n }\n\n const req = platform.httpRequest(method, endpoint, utils.transformHeaders(headers, options), body);\n const p = req.promise.then(\n result => {\n if (result.status === 200) {\n // We're using substring here because using startsWith would require a polyfill in IE.\n if (\n result.header('content-type') &&\n result.header('content-type').substring(0, jsonContentType.length) === jsonContentType\n ) {\n return JSON.parse(result.body);\n } else {\n const message = messages.invalidContentType(result.header('content-type') || '');\n return Promise.reject(new errors.LDFlagFetchError(message));\n }\n } else {\n return Promise.reject(getResponseError(result));\n }\n },\n e => Promise.reject(new errors.LDFlagFetchError(messages.networkError(e)))\n );\n coalescer.addPromise(p, () => {\n // this will be called if another request for the same endpoint supersedes this one\n req.cancel && req.cancel();\n });\n return coalescer.resultPromise;\n }\n\n // Performs a GET request to an arbitrary path under baseUrl. Returns a Promise which will resolve\n // with the parsed JSON response, or will be rejected if the request failed.\n requestor.fetchJSON = function(path) {\n return fetchJSON(baseUrl + path, null);\n };\n\n // Requests the current state of all flags for the given user from LaunchDarkly. Returns a Promise\n // which will resolve with the parsed JSON response, or will be rejected if the request failed.\n requestor.fetchFlagSettings = function(user, hash) {\n let data;\n let endpoint;\n let query = '';\n let body;\n\n if (useReport) {\n endpoint = [baseUrl, '/sdk/evalx/', environment, '/user'].join('');\n body = JSON.stringify(user);\n } else {\n data = utils.base64URLEncode(JSON.stringify(user));\n endpoint = [baseUrl, '/sdk/evalx/', environment, '/users/', data].join('');\n }\n if (hash) {\n query = 'h=' + hash;\n }\n if (withReasons) {\n query = query + (query ? '&' : '') + 'withReasons=true';\n }\n endpoint = endpoint + (query ? '?' : '') + query;\n logger.debug(messages.debugPolling(endpoint));\n\n return fetchJSON(endpoint, body);\n };\n\n return requestor;\n}\n","// This function allows a series of Promises to be coalesced such that only the most recently\n// added one actually matters. For instance, if several HTTP requests are made to the same\n// endpoint and we want to ensure that whoever made each one always gets the latest data, each\n// can be passed to addPromise (on the same coalescer) and each caller can wait on the\n// coalescer.resultPromise; all three will then receive the result (or error) from the *last*\n// request, and the results of the first two will be discarded.\n//\n// The cancelFn callback, if present, will be called whenever an existing promise is being\n// discarded. This can be used for instance to abort an HTTP request that's now obsolete.\n//\n// The finallyFn callback, if present, is called on completion of the whole thing. This is\n// different from calling coalescer.resultPromise.finally() because it is executed before any\n// other handlers. Its purpose is to tell the caller that this coalescer should no longer be used.\n\nexport default function promiseCoalescer(finallyFn) {\n let currentPromise;\n let currentCancelFn;\n let finalResolve;\n let finalReject;\n\n const coalescer = {};\n\n coalescer.addPromise = (p, cancelFn) => {\n currentPromise = p;\n currentCancelFn && currentCancelFn();\n currentCancelFn = cancelFn;\n\n p.then(\n result => {\n if (currentPromise === p) {\n finalResolve(result);\n finallyFn && finallyFn();\n }\n },\n error => {\n if (currentPromise === p) {\n finalReject(error);\n finallyFn && finallyFn();\n }\n }\n );\n };\n\n coalescer.resultPromise = new Promise((resolve, reject) => {\n finalResolve = resolve;\n finalReject = reject;\n });\n\n return coalescer;\n}\n","import uuidv1 from 'uuid/v1';\n\nimport * as errors from './errors';\nimport * as messages from './messages';\nimport * as utils from './utils';\n\n// Transforms the user object if necessary to make sure it has a valid key.\n// 1. If a key is present, but is not a string, change it to a string.\n// 2. If no key is present, and \"anonymous\" is true, use a UUID as a key. This is cached in local\n// storage if possible.\n// 3. If there is no key (or no user object), return an error.\n\nconst ldUserIdKey = 'ld:$anonUserId';\n\nexport default function UserValidator(localStorageProvider, logger) {\n function getCachedUserId() {\n if (localStorageProvider) {\n return localStorageProvider.get(ldUserIdKey).catch(() => null);\n // Not logging errors here, because if local storage fails for the get, it will presumably fail for the set,\n // so we will end up logging an error in setCachedUserId anyway.\n }\n return Promise.resolve(null);\n }\n\n function setCachedUserId(id) {\n if (localStorageProvider) {\n return localStorageProvider.set(ldUserIdKey, id).catch(() => {\n logger.warn(messages.localStorageUnavailableForUserId());\n });\n }\n return Promise.resolve();\n }\n\n const ret = {};\n\n // Validates the user, returning a Promise that resolves to the validated user, or rejects if there is an error.\n ret.validateUser = user => {\n if (!user) {\n return Promise.reject(new errors.LDInvalidUserError(messages.userNotSpecified()));\n }\n\n const userOut = utils.clone(user);\n if (userOut.key !== null && userOut.key !== undefined) {\n userOut.key = userOut.key.toString();\n return Promise.resolve(userOut);\n }\n if (userOut.anonymous) {\n return getCachedUserId().then(cachedId => {\n if (cachedId) {\n userOut.key = cachedId;\n return userOut;\n } else {\n const id = uuidv1();\n userOut.key = id;\n return setCachedUserId(id).then(() => userOut);\n }\n });\n } else {\n return Promise.reject(new errors.LDInvalidUserError(messages.invalidUser()));\n }\n };\n\n return ret;\n}\n","import * as errors from './errors';\nimport * as messages from './messages';\nimport * as utils from './utils';\n\n// baseOptionDefs should contain an entry for each supported configuration option in the common package.\n// Each entry can have three properties:\n// - \"default\": the default value if any\n// - \"type\": a type constraint used if the type can't be inferred from the default value). The allowable\n// values are \"boolean\", \"string\", \"number\", \"array\", \"object\", \"function\", or several of these OR'd\n// together with \"|\" (\"function|object\").\n// - \"minimum\": minimum value if any for numeric properties\n//\n// The extraOptionDefs parameter to validate() uses the same format.\nexport const baseOptionDefs = {\n baseUrl: { default: 'https://app.launchdarkly.com' },\n streamUrl: { default: 'https://clientstream.launchdarkly.com' },\n eventsUrl: { default: 'https://events.launchdarkly.com' },\n sendEvents: { default: true },\n streaming: { type: 'boolean' }, // default for this is undefined, which is different from false\n sendLDHeaders: { default: true },\n requestHeaderTransform: { type: 'function' },\n inlineUsersInEvents: { default: false },\n allowFrequentDuplicateEvents: { default: false },\n sendEventsOnlyForVariation: { default: false },\n useReport: { default: false },\n evaluationReasons: { default: false },\n eventCapacity: { default: 100, minimum: 1 },\n flushInterval: { default: 2000, minimum: 2000 },\n samplingInterval: { default: 0, minimum: 0 },\n streamReconnectDelay: { default: 1000, minimum: 0 },\n allAttributesPrivate: { default: false },\n privateAttributeNames: { default: [] },\n bootstrap: { type: 'string|object' },\n diagnosticRecordingInterval: { default: 900000, minimum: 2000 },\n diagnosticOptOut: { default: false },\n wrapperName: { type: 'string' },\n wrapperVersion: { type: 'string' },\n stateProvider: { type: 'object' }, // not a public option, used internally\n autoAliasingOptOut: { default: false },\n};\n\nexport function validate(options, emitter, extraOptionDefs, logger) {\n const optionDefs = utils.extend({ logger: { default: logger } }, baseOptionDefs, extraOptionDefs);\n\n const deprecatedOptions = {\n // eslint-disable-next-line camelcase\n all_attributes_private: 'allAttributesPrivate',\n // eslint-disable-next-line camelcase\n private_attribute_names: 'privateAttributeNames',\n samplingInterval: null,\n };\n\n function checkDeprecatedOptions(config) {\n const opts = config;\n Object.keys(deprecatedOptions).forEach(oldName => {\n if (opts[oldName] !== undefined) {\n const newName = deprecatedOptions[oldName];\n logger && logger.warn(messages.deprecated(oldName, newName));\n if (newName) {\n if (opts[newName] === undefined) {\n opts[newName] = opts[oldName];\n }\n delete opts[oldName];\n }\n }\n });\n }\n\n function applyDefaults(config) {\n // This works differently from utils.extend() in that it *will not* override a default value\n // if the provided value is explicitly set to null. This provides backward compatibility\n // since in the past we only used the provided values if they were truthy.\n const ret = utils.extend({}, config);\n Object.keys(optionDefs).forEach(name => {\n if (ret[name] === undefined || ret[name] === null) {\n ret[name] = optionDefs[name] && optionDefs[name].default;\n }\n });\n return ret;\n }\n\n function validateTypesAndNames(config) {\n const ret = utils.extend({}, config);\n const typeDescForValue = value => {\n if (value === null) {\n return 'any';\n }\n if (value === undefined) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return 'array';\n }\n const t = typeof value;\n if (t === 'boolean' || t === 'string' || t === 'number' || t === 'function') {\n return t;\n }\n return 'object';\n };\n Object.keys(config).forEach(name => {\n const value = config[name];\n if (value !== null && value !== undefined) {\n const optionDef = optionDefs[name];\n if (optionDef === undefined) {\n reportArgumentError(messages.unknownOption(name));\n } else {\n const expectedType = optionDef.type || typeDescForValue(optionDef.default);\n if (expectedType !== 'any') {\n const allowedTypes = expectedType.split('|');\n const actualType = typeDescForValue(value);\n if (allowedTypes.indexOf(actualType) < 0) {\n if (expectedType === 'boolean') {\n ret[name] = !!value;\n reportArgumentError(messages.wrongOptionTypeBoolean(name, actualType));\n } else {\n reportArgumentError(messages.wrongOptionType(name, expectedType, actualType));\n ret[name] = optionDef.default;\n }\n } else {\n if (actualType === 'number' && optionDef.minimum !== undefined && value < optionDef.minimum) {\n reportArgumentError(messages.optionBelowMinimum(name, value, optionDef.minimum));\n ret[name] = optionDef.minimum;\n }\n }\n }\n }\n }\n });\n return ret;\n }\n\n function reportArgumentError(message) {\n utils.onNextTick(() => {\n emitter && emitter.maybeReportError(new errors.LDInvalidArgumentError(message));\n });\n }\n\n let config = utils.extend({}, options || {});\n\n checkDeprecatedOptions(config);\n\n config = applyDefaults(config);\n config = validateTypesAndNames(config);\n\n return config;\n}\n","const uuidv1 = require('uuid/v1');\n// Note that in the diagnostic events spec, these IDs are to be generated with UUID v4. However,\n// in JS we were already using v1 for unique user keys, so to avoid bringing in two packages we\n// will use v1 here as well.\n\nconst { baseOptionDefs } = require('./configuration');\nconst messages = require('./messages');\n\nfunction DiagnosticId(sdkKey) {\n const ret = {\n diagnosticId: uuidv1(),\n };\n if (sdkKey) {\n ret.sdkKeySuffix = sdkKey.length > 6 ? sdkKey.substring(sdkKey.length - 6) : sdkKey;\n }\n return ret;\n}\n\n// A stateful object holding statistics that will go into diagnostic events.\n\nfunction DiagnosticsAccumulator(startTime) {\n let dataSinceDate, droppedEvents, eventsInLastBatch, streamInits;\n\n function reset(time) {\n dataSinceDate = time;\n droppedEvents = 0;\n eventsInLastBatch = 0;\n streamInits = [];\n }\n\n reset(startTime);\n\n return {\n getProps: () => ({\n dataSinceDate,\n droppedEvents,\n eventsInLastBatch,\n streamInits,\n // omit deduplicatedUsers for the JS SDKs because they don't deduplicate users\n }),\n setProps: props => {\n dataSinceDate = props.dataSinceDate;\n droppedEvents = props.droppedEvents || 0;\n eventsInLastBatch = props.eventsInLastBatch || 0;\n streamInits = props.streamInits || [];\n },\n incrementDroppedEvents: () => {\n droppedEvents++;\n },\n setEventsInLastBatch: n => {\n eventsInLastBatch = n;\n },\n recordStreamInit: (timestamp, failed, durationMillis) => {\n const info = { timestamp, failed, durationMillis };\n streamInits.push(info);\n },\n reset,\n };\n}\n\n// An object that maintains information that will go into diagnostic events, and knows how to format\n// those events. It is instantiated by the SDK client, and shared with the event processor.\n//\n// The JS-based SDKs have two modes for diagnostic events. By default, the behavior is basically the\n// same as the server-side SDKs: a \"diagnostic-init\" event is sent on startup, and then \"diagnostic\"\n// events with operating statistics are sent periodically. However, in a browser environment this is\n// undesirable because the page may be reloaded frequently. In that case, setting the property\n// \"platform.diagnosticUseCombinedEvent\" to true enables an alternate mode in which a combination of\n// both kinds of event is sent at intervals, relative to the last time this was done (if any) which\n// is cached in local storage.\n\nfunction DiagnosticsManager(platform, accumulator, eventSender, environmentId, config, diagnosticId) {\n const combinedMode = !!platform.diagnosticUseCombinedEvent;\n const localStorageKey = 'ld:' + environmentId + ':$diagnostics';\n const diagnosticEventsUrl = config.eventsUrl + '/events/diagnostic/' + environmentId;\n const periodicInterval = config.diagnosticRecordingInterval;\n const acc = accumulator;\n const initialEventSamplingInterval = 4; // used only in combined mode - see start()\n let streamingEnabled = !!config.streaming;\n let eventSentTime;\n let periodicTimer;\n const manager = {};\n\n function makeInitProperties() {\n return {\n sdk: makeSdkData(),\n configuration: makeConfigData(),\n platform: platform.diagnosticPlatformData,\n };\n }\n\n // Send a diagnostic event and do not wait for completion.\n function sendDiagnosticEvent(event) {\n config.logger && config.logger.debug(messages.debugPostingDiagnosticEvent(event));\n eventSender\n .sendEvents(event, diagnosticEventsUrl, true)\n .then(() => undefined)\n .catch(() => undefined);\n }\n\n function loadProperties(callback) {\n if (!platform.localStorage) {\n return callback(false); // false indicates that local storage is not available\n }\n platform.localStorage\n .get(localStorageKey)\n .then(data => {\n if (data) {\n try {\n const props = JSON.parse(data);\n acc.setProps(props);\n eventSentTime = props.dataSinceDate;\n } catch (e) {\n // disregard malformed cached data\n }\n }\n callback(true);\n })\n .catch(() => {\n callback(false);\n });\n }\n\n function saveProperties() {\n if (platform.localStorage) {\n const props = { ...acc.getProps() };\n platform.localStorage.set(localStorageKey, JSON.stringify(props), () => {});\n }\n }\n\n // Creates the initial event that is sent by the event processor when the SDK starts up. This will not\n // be repeated during the lifetime of the SDK client. In combined mode, we don't send this.\n function createInitEvent() {\n return {\n kind: 'diagnostic-init',\n id: diagnosticId,\n creationDate: acc.getProps().dataSinceDate,\n ...makeInitProperties(),\n };\n }\n\n // Creates a periodic event containing time-dependent stats, and resets the state of the manager with\n // regard to those stats. In combined mode (browser SDK) this also contains the configuration data.\n function createPeriodicEventAndReset() {\n const currentTime = new Date().getTime();\n let ret = {\n kind: combinedMode ? 'diagnostic-combined' : 'diagnostic',\n id: diagnosticId,\n creationDate: currentTime,\n ...acc.getProps(),\n };\n if (combinedMode) {\n ret = { ...ret, ...makeInitProperties() };\n }\n acc.reset(currentTime);\n return ret;\n }\n\n function sendPeriodicEvent() {\n sendDiagnosticEvent(createPeriodicEventAndReset());\n periodicTimer = setTimeout(sendPeriodicEvent, periodicInterval);\n eventSentTime = new Date().getTime();\n if (combinedMode) {\n saveProperties();\n }\n }\n\n function makeSdkData() {\n const sdkData = { ...platform.diagnosticSdkData };\n if (config.wrapperName) {\n sdkData.wrapperName = config.wrapperName;\n }\n if (config.wrapperVersion) {\n sdkData.wrapperVersion = config.wrapperVersion;\n }\n return sdkData;\n }\n\n function makeConfigData() {\n const configData = {\n customBaseURI: config.baseUrl !== baseOptionDefs.baseUrl.default,\n customStreamURI: config.streamUrl !== baseOptionDefs.streamUrl.default,\n customEventsURI: config.eventsUrl !== baseOptionDefs.eventsUrl.default,\n eventsCapacity: config.eventCapacity,\n eventsFlushIntervalMillis: config.flushInterval,\n reconnectTimeMillis: config.streamReconnectDelay,\n streamingDisabled: !streamingEnabled,\n allAttributesPrivate: !!config.allAttributesPrivate,\n inlineUsersInEvents: !!config.inlineUsersInEvents,\n diagnosticRecordingIntervalMillis: config.diagnosticRecordingInterval,\n // The following extra properties are only provided by client-side JS SDKs:\n usingSecureMode: !!config.hash,\n bootstrapMode: !!config.bootstrap,\n fetchGoalsDisabled: !config.fetchGoals,\n allowFrequentDuplicateEvents: !!config.allowFrequentDuplicateEvents,\n sendEventsOnlyForVariation: !!config.sendEventsOnlyForVariation,\n autoAliasingOptOut: !!config.autoAliasingOptOut,\n };\n // Client-side JS SDKs do not have the following properties which other SDKs have:\n // connectTimeoutMillis\n // pollingIntervalMillis\n // samplingInterval\n // socketTimeoutMillis\n // startWaitMillis\n // userKeysCapacity\n // userKeysFlushIntervalMillis\n // usingProxy\n // usingProxyAuthenticator\n // usingRelayDaemon\n\n return configData;\n }\n\n // Called when the SDK is starting up. Either send an init event immediately, or, in the alternate\n // mode, check for cached local storage properties and send an event only if we haven't done so\n // recently.\n manager.start = () => {\n if (combinedMode) {\n loadProperties(localStorageAvailable => {\n if (localStorageAvailable) {\n const nextEventTime = (eventSentTime || 0) + periodicInterval;\n const timeNow = new Date().getTime();\n if (timeNow >= nextEventTime) {\n sendPeriodicEvent();\n } else {\n periodicTimer = setTimeout(sendPeriodicEvent, nextEventTime - timeNow);\n }\n } else {\n // We don't have the ability to cache anything in local storage, so we don't know if we\n // recently sent an event before this page load, but we would still prefer not to send one\n // on *every* page load. So, as a rough heuristic, we'll decide semi-randomly.\n if (Math.floor(Math.random() * initialEventSamplingInterval) === 0) {\n sendPeriodicEvent();\n } else {\n periodicTimer = setTimeout(sendPeriodicEvent, periodicInterval);\n }\n }\n });\n } else {\n sendDiagnosticEvent(createInitEvent());\n periodicTimer = setTimeout(sendPeriodicEvent, periodicInterval);\n }\n };\n\n manager.stop = () => {\n periodicTimer && clearTimeout(periodicTimer);\n };\n\n // Called when streaming mode is turned on or off dynamically.\n manager.setStreaming = enabled => {\n streamingEnabled = enabled;\n };\n\n return manager;\n}\n\nmodule.exports = {\n DiagnosticId,\n DiagnosticsAccumulator,\n DiagnosticsManager,\n};\n","// Default implementation of our internal logging interface, which writes messages to the console.\n// If no minimum level is specified, all messages will be logged. Setting the level to \"none\"\n// disables all logging.\n\n// Note that the global console variable is not guaranteed to be defined at all times in all\n// browsers, so this implementation checks for its existence at the time a message is logged.\n// See: https://www.beyondjava.net/console-log-surprises-with-internet-explorer-11-and-edge\n\nexport default function createConsoleLogger(level, maybePrefix) {\n const allLevels = ['debug', 'info', 'warn', 'error'];\n let prefix;\n if (maybePrefix !== null && maybePrefix !== undefined) {\n prefix = maybePrefix === '' ? '' : maybePrefix + ' ';\n } else {\n prefix = 'LD: ';\n }\n let minLevelIndex = 0;\n if (level) {\n if (level === 'none') {\n minLevelIndex = 100;\n } else {\n minLevelIndex = allLevels.indexOf(level);\n }\n }\n\n const logger = {};\n\n function log(levelIndex, methodName, msg) {\n if (levelIndex >= minLevelIndex && console) {\n const method = console[methodName];\n if (method) {\n const levelName = levelIndex < allLevels.length ? allLevels[levelIndex] : '?';\n method.call(console, prefix + '[' + levelName + '] ' + msg);\n }\n }\n }\n\n logger.debug = msg => log(0, 'log', msg); // eslint-disable-line no-console\n logger.info = msg => log(1, 'info', msg); // eslint-disable-line no-console\n logger.warn = msg => log(2, 'warn', msg); // eslint-disable-line no-console\n logger.error = msg => log(3, 'error', msg); // eslint-disable-line no-console\n\n return logger;\n}\n","import EventProcessor from './EventProcessor';\nimport EventEmitter from './EventEmitter';\nimport EventSender from './EventSender';\nimport InitializationStateTracker from './InitializationState';\nimport Store from './Store';\nimport Stream from './Stream';\nimport Requestor from './Requestor';\nimport Identity from './Identity';\nimport UserValidator from './UserValidator';\nimport * as configuration from './configuration';\nimport * as diagnostics from './diagnosticEvents';\nimport createConsoleLogger from './consoleLogger';\nimport * as utils from './utils';\nimport * as errors from './errors';\nimport * as messages from './messages';\n\nconst changeEvent = 'change';\nconst internalChangeEvent = 'internal-change';\n\n// This is called by the per-platform initialize functions to create the base client object that we\n// may also extend with additional behavior. It returns an object with these properties:\n// client: the actual client object\n// options: the configuration (after any appropriate defaults have been applied)\n// If we need to give the platform-specific clients access to any internals here, we should add those\n// as properties of the return object, not public properties of the client.\n//\n// For definitions of the API in the platform object, see stubPlatform.js in the test code.\n\nexport function initialize(env, user, specifiedOptions, platform, extraOptionDefs) {\n const logger = createLogger();\n const emitter = EventEmitter(logger);\n const initializationStateTracker = InitializationStateTracker(emitter);\n const options = configuration.validate(specifiedOptions, emitter, extraOptionDefs, logger);\n const sendEvents = options.sendEvents;\n let environment = env;\n let hash = options.hash;\n\n const eventSender = EventSender(platform, environment, options);\n\n const diagnosticsEnabled = options.sendEvents && !options.diagnosticOptOut;\n const diagnosticId = diagnosticsEnabled ? diagnostics.DiagnosticId(environment) : null;\n const diagnosticsAccumulator = diagnosticsEnabled ? diagnostics.DiagnosticsAccumulator(new Date().getTime()) : null;\n const diagnosticsManager = diagnosticsEnabled\n ? diagnostics.DiagnosticsManager(platform, diagnosticsAccumulator, eventSender, environment, options, diagnosticId)\n : null;\n\n const stream = Stream(platform, options, environment, diagnosticsAccumulator);\n\n const events =\n options.eventProcessor ||\n EventProcessor(platform, options, environment, diagnosticsAccumulator, emitter, eventSender);\n\n const requestor = Requestor(platform, options, environment);\n\n const seenRequests = {};\n let flags = {};\n let useLocalStorage;\n let streamActive;\n let streamForcedState = options.streaming;\n let subscribedToChangeEvents;\n let inited = false;\n let closed = false;\n let firstEvent = true;\n\n // The \"stateProvider\" object is used in the Electron SDK, to allow one client instance to take partial\n // control of another. If present, it has the following contract:\n // - getInitialState() returns the initial client state if it is already available. The state is an\n // object whose properties are \"environment\", \"user\", and \"flags\".\n // - on(\"init\", listener) triggers an event when the initial client state becomes available, passing\n // the state object to the listener.\n // - on(\"update\", listener) triggers an event when flag values change and/or the current user changes.\n // The parameter is an object that *may* contain \"user\" and/or \"flags\".\n // - enqueueEvent(event) accepts an analytics event object and returns true if the stateProvider will\n // be responsible for delivering it, or false if we still should deliver it ourselves.\n const stateProvider = options.stateProvider;\n\n const ident = Identity(null, onIdentifyChange);\n const userValidator = UserValidator(platform.localStorage, logger);\n let store;\n if (platform.localStorage) {\n store = new Store(platform.localStorage, environment, hash, ident, logger);\n }\n\n function createLogger() {\n if (specifiedOptions && specifiedOptions.logger) {\n return specifiedOptions.logger;\n }\n return (extraOptionDefs && extraOptionDefs.logger && extraOptionDefs.logger.default) || createConsoleLogger('warn');\n }\n\n function readFlagsFromBootstrap(data) {\n // If the bootstrap data came from an older server-side SDK, we'll have just a map of keys to values.\n // Newer SDKs that have an allFlagsState method will provide an extra \"$flagsState\" key that contains\n // the rest of the metadata we want. We do it this way for backward compatibility with older JS SDKs.\n const keys = Object.keys(data);\n const metadataKey = '$flagsState';\n const validKey = '$valid';\n const metadata = data[metadataKey];\n if (!metadata && keys.length) {\n logger.warn(messages.bootstrapOldFormat());\n }\n if (data[validKey] === false) {\n logger.warn(messages.bootstrapInvalid());\n }\n const ret = {};\n keys.forEach(key => {\n if (key !== metadataKey && key !== validKey) {\n let flag = { value: data[key] };\n if (metadata && metadata[key]) {\n flag = utils.extend(flag, metadata[key]);\n } else {\n flag.version = 0;\n }\n ret[key] = flag;\n }\n });\n return ret;\n }\n\n function shouldEnqueueEvent() {\n return sendEvents && !closed && !platform.isDoNotTrack();\n }\n\n function enqueueEvent(event) {\n if (!environment) {\n // We're in paired mode and haven't been initialized with an environment or user yet\n return;\n }\n if (stateProvider && stateProvider.enqueueEvent && stateProvider.enqueueEvent(event)) {\n return; // it'll be handled elsewhere\n }\n if (event.kind !== 'alias') {\n if (!event.user) {\n if (firstEvent) {\n logger.warn(messages.eventWithoutUser());\n firstEvent = false;\n }\n return;\n }\n firstEvent = false;\n }\n if (shouldEnqueueEvent()) {\n logger.debug(messages.debugEnqueueingEvent(event.kind));\n events.enqueue(event);\n }\n }\n\n function onIdentifyChange(user, previousUser) {\n sendIdentifyEvent(user);\n if (!options.autoAliasingOptOut && previousUser && previousUser.anonymous && user && !user.anonymous) {\n alias(user, previousUser);\n }\n }\n\n function sendIdentifyEvent(user) {\n if (stateProvider) {\n // In paired mode, the other client is responsible for sending identify events\n return;\n }\n if (user) {\n enqueueEvent({\n kind: 'identify',\n key: user.key,\n user: user,\n creationDate: new Date().getTime(),\n });\n }\n }\n\n function sendFlagEvent(key, detail, defaultValue, includeReason) {\n const user = ident.getUser();\n const now = new Date();\n const value = detail ? detail.value : null;\n if (!options.allowFrequentDuplicateEvents) {\n const cacheKey = JSON.stringify(value) + (user && user.key ? user.key : '') + key; // see below\n const cached = seenRequests[cacheKey];\n // cache TTL is five minutes\n if (cached && now - cached < 300000) {\n return;\n }\n seenRequests[cacheKey] = now;\n }\n\n const event = {\n kind: 'feature',\n key: key,\n user: user,\n value: value,\n variation: detail ? detail.variationIndex : null,\n default: defaultValue,\n creationDate: now.getTime(),\n };\n if (user && user.anonymous) {\n event.contextKind = userContextKind(user);\n }\n const flag = flags[key];\n if (flag) {\n event.version = flag.flagVersion ? flag.flagVersion : flag.version;\n event.trackEvents = flag.trackEvents;\n event.debugEventsUntilDate = flag.debugEventsUntilDate;\n }\n if ((includeReason || (flag && flag.trackReason)) && detail) {\n event.reason = detail.reason;\n }\n\n enqueueEvent(event);\n }\n\n function identify(user, newHash, onDone) {\n if (closed) {\n return utils.wrapPromiseCallback(Promise.resolve({}), onDone);\n }\n if (stateProvider) {\n // We're being controlled by another client instance, so only that instance is allowed to change the user\n logger.warn(messages.identifyDisabled());\n return utils.wrapPromiseCallback(Promise.resolve(utils.transformVersionedValuesToValues(flags)), onDone);\n }\n const clearFirst = useLocalStorage && store ? store.clearFlags() : Promise.resolve();\n return utils.wrapPromiseCallback(\n clearFirst\n .then(() => userValidator.validateUser(user))\n .then(realUser =>\n requestor\n .fetchFlagSettings(realUser, newHash)\n // the following then() is nested within this one so we can use realUser from the previous closure\n .then(requestedFlags => {\n const flagValueMap = utils.transformVersionedValuesToValues(requestedFlags);\n ident.setUser(realUser);\n hash = newHash;\n if (requestedFlags) {\n return replaceAllFlags(requestedFlags).then(() => flagValueMap);\n } else {\n return flagValueMap;\n }\n })\n )\n .then(flagValueMap => {\n if (streamActive) {\n connectStream();\n }\n return flagValueMap;\n })\n .catch(err => {\n emitter.maybeReportError(err);\n return Promise.reject(err);\n }),\n onDone\n );\n }\n\n function getUser() {\n return ident.getUser();\n }\n\n function flush(onDone) {\n return utils.wrapPromiseCallback(sendEvents ? events.flush() : Promise.resolve(), onDone);\n }\n\n function variation(key, defaultValue) {\n return variationDetailInternal(key, defaultValue, true, false).value;\n }\n\n function variationDetail(key, defaultValue) {\n return variationDetailInternal(key, defaultValue, true, true);\n }\n\n function variationDetailInternal(key, defaultValue, sendEvent, includeReasonInEvent) {\n let detail;\n\n if (flags && utils.objectHasOwnProperty(flags, key) && flags[key] && !flags[key].deleted) {\n const flag = flags[key];\n detail = getFlagDetail(flag);\n if (flag.value === null || flag.value === undefined) {\n detail.value = defaultValue;\n }\n } else {\n detail = { value: defaultValue, variationIndex: null, reason: { kind: 'ERROR', errorKind: 'FLAG_NOT_FOUND' } };\n }\n\n if (sendEvent) {\n sendFlagEvent(key, detail, defaultValue, includeReasonInEvent);\n }\n\n return detail;\n }\n\n function getFlagDetail(flag) {\n return {\n value: flag.value,\n variationIndex: flag.variation === undefined ? null : flag.variation,\n reason: flag.reason || null,\n };\n // Note, the logic above ensures that variationIndex and reason will always be null rather than\n // undefined if we don't have values for them. That's just to avoid subtle errors that depend on\n // whether an object was JSON-encoded with null properties omitted or not.\n }\n\n function allFlags() {\n const results = {};\n\n if (!flags) {\n return results;\n }\n\n for (const key in flags) {\n if (utils.objectHasOwnProperty(flags, key)) {\n results[key] = variationDetailInternal(key, null, !options.sendEventsOnlyForVariation).value;\n }\n }\n\n return results;\n }\n\n function userContextKind(user) {\n return user.anonymous ? 'anonymousUser' : 'user';\n }\n\n function alias(user, previousUser) {\n if (stateProvider) {\n // In paired mode, the other client is responsible for sending alias events\n return;\n }\n\n if (!user || !previousUser) {\n return;\n }\n\n enqueueEvent({\n kind: 'alias',\n key: user.key,\n contextKind: userContextKind(user),\n previousKey: previousUser.key,\n previousContextKind: userContextKind(previousUser),\n creationDate: new Date().getTime(),\n });\n }\n\n function track(key, data, metricValue) {\n if (typeof key !== 'string') {\n emitter.maybeReportError(new errors.LDInvalidEventKeyError(messages.unknownCustomEventKey(key)));\n return;\n }\n\n // The following logic was used only for the JS browser SDK (js-client-sdk) and\n // is no longer needed as of version 2.9.13 of that SDK. The other client-side\n // JS-based SDKs did not define customEventFilter, and now none of them do. We\n // can remove this in the next major version of the common code, when it's OK to\n // make breaking changes to our internal API contracts.\n if (platform.customEventFilter && !platform.customEventFilter(key)) {\n logger.warn(messages.unknownCustomEventKey(key));\n }\n\n const user = ident.getUser();\n const e = {\n kind: 'custom',\n key: key,\n user: user,\n url: platform.getCurrentUrl(),\n creationDate: new Date().getTime(),\n };\n if (user && user.anonymous) {\n e.contextKind = userContextKind(user);\n }\n // Note, check specifically for null/undefined because it is legal to set these fields to a falsey value.\n if (data !== null && data !== undefined) {\n e.data = data;\n }\n if (metricValue !== null && metricValue !== undefined) {\n e.metricValue = metricValue;\n }\n enqueueEvent(e);\n }\n\n function connectStream() {\n streamActive = true;\n if (!ident.getUser()) {\n return;\n }\n stream.connect(ident.getUser(), hash, {\n ping: function() {\n logger.debug(messages.debugStreamPing());\n const userAtTimeOfPingEvent = ident.getUser();\n requestor\n .fetchFlagSettings(userAtTimeOfPingEvent, hash)\n .then(requestedFlags => {\n // Check whether the current user is still the same - we don't want to overwrite the flags if\n // the application has called identify() while this request was in progress\n if (utils.deepEquals(userAtTimeOfPingEvent, ident.getUser())) {\n replaceAllFlags(requestedFlags || {});\n }\n })\n .catch(err => {\n emitter.maybeReportError(new errors.LDFlagFetchError(messages.errorFetchingFlags(err)));\n });\n },\n put: function(e) {\n const data = JSON.parse(e.data);\n logger.debug(messages.debugStreamPut());\n replaceAllFlags(data); // don't wait for this Promise to be resolved\n },\n patch: function(e) {\n const data = JSON.parse(e.data);\n // If both the flag and the patch have a version property, then the patch version must be\n // greater than the flag version for us to accept the patch. If either one has no version\n // then the patch always succeeds.\n const oldFlag = flags[data.key];\n if (!oldFlag || !oldFlag.version || !data.version || oldFlag.version < data.version) {\n logger.debug(messages.debugStreamPatch(data.key));\n const mods = {};\n const newFlag = utils.extend({}, data);\n delete newFlag['key'];\n flags[data.key] = newFlag;\n const newDetail = getFlagDetail(newFlag);\n if (oldFlag) {\n mods[data.key] = { previous: oldFlag.value, current: newDetail };\n } else {\n mods[data.key] = { current: newDetail };\n }\n handleFlagChanges(mods); // don't wait for this Promise to be resolved\n } else {\n logger.debug(messages.debugStreamPatchIgnored(data.key));\n }\n },\n delete: function(e) {\n const data = JSON.parse(e.data);\n if (!flags[data.key] || flags[data.key].version < data.version) {\n logger.debug(messages.debugStreamDelete(data.key));\n const mods = {};\n if (flags[data.key] && !flags[data.key].deleted) {\n mods[data.key] = { previous: flags[data.key].value };\n }\n flags[data.key] = { version: data.version, deleted: true };\n handleFlagChanges(mods); // don't wait for this Promise to be resolved\n } else {\n logger.debug(messages.debugStreamDeleteIgnored(data.key));\n }\n },\n });\n }\n\n function disconnectStream() {\n if (streamActive) {\n stream.disconnect();\n streamActive = false;\n }\n }\n\n // Returns a Promise which will be resolved when we have completely updated the internal flags state,\n // dispatched all change events, and updated local storage if appropriate. This Promise is guaranteed\n // never to have an unhandled rejection.\n function replaceAllFlags(newFlags) {\n const changes = {};\n\n if (!newFlags) {\n return Promise.resolve();\n }\n\n for (const key in flags) {\n if (utils.objectHasOwnProperty(flags, key) && flags[key]) {\n if (newFlags[key] && !utils.deepEquals(newFlags[key].value, flags[key].value)) {\n changes[key] = { previous: flags[key].value, current: getFlagDetail(newFlags[key]) };\n } else if (!newFlags[key] || newFlags[key].deleted) {\n changes[key] = { previous: flags[key].value };\n }\n }\n }\n for (const key in newFlags) {\n if (utils.objectHasOwnProperty(newFlags, key) && newFlags[key] && (!flags[key] || flags[key].deleted)) {\n changes[key] = { current: getFlagDetail(newFlags[key]) };\n }\n }\n\n flags = { ...newFlags };\n return handleFlagChanges(changes).catch(() => {}); // swallow any exceptions from this Promise\n }\n\n // Returns a Promise which will be resolved when we have dispatched all change events and updated\n // local storage if appropriate.\n function handleFlagChanges(changes) {\n const keys = Object.keys(changes);\n\n if (keys.length > 0) {\n const changeEventParams = {};\n keys.forEach(key => {\n const current = changes[key].current;\n const value = current ? current.value : undefined;\n const previous = changes[key].previous;\n emitter.emit(changeEvent + ':' + key, value, previous);\n changeEventParams[key] = current ? { current: value, previous: previous } : { previous: previous };\n });\n\n emitter.emit(changeEvent, changeEventParams);\n emitter.emit(internalChangeEvent, flags);\n\n // By default, we send feature evaluation events whenever we have received new flag values -\n // the client has in effect evaluated these flags just by receiving them. This can be suppressed\n // by setting \"sendEventsOnlyForVariation\". Also, if we have a stateProvider, we don't send these\n // events because we assume they have already been sent by the other client that gave us the flags\n // (when it received them in the first place).\n if (!options.sendEventsOnlyForVariation && !stateProvider) {\n keys.forEach(key => {\n sendFlagEvent(key, changes[key].current);\n });\n }\n }\n\n if (useLocalStorage && store) {\n return store.saveFlags(flags).catch(() => null); // disregard errors\n } else {\n return Promise.resolve();\n }\n }\n\n function on(event, handler, context) {\n if (isChangeEventKey(event)) {\n subscribedToChangeEvents = true;\n if (inited) {\n updateStreamingState();\n }\n emitter.on(event, handler, context);\n } else {\n emitter.on(...arguments);\n }\n }\n\n function off(event) {\n emitter.off(...arguments);\n if (isChangeEventKey(event)) {\n let haveListeners = false;\n emitter.getEvents().forEach(key => {\n if (isChangeEventKey(key) && emitter.getEventListenerCount(key) > 0) {\n haveListeners = true;\n }\n });\n if (!haveListeners) {\n subscribedToChangeEvents = false;\n if (streamActive && streamForcedState === undefined) {\n disconnectStream();\n }\n }\n }\n }\n\n function setStreaming(state) {\n const newState = state === null ? undefined : state;\n if (newState !== streamForcedState) {\n streamForcedState = newState;\n updateStreamingState();\n }\n }\n\n function updateStreamingState() {\n const shouldBeStreaming = streamForcedState || (subscribedToChangeEvents && streamForcedState === undefined);\n if (shouldBeStreaming && !streamActive) {\n connectStream();\n } else if (!shouldBeStreaming && streamActive) {\n disconnectStream();\n }\n if (diagnosticsManager) {\n diagnosticsManager.setStreaming(shouldBeStreaming);\n }\n }\n\n function isChangeEventKey(event) {\n return event === changeEvent || event.substr(0, changeEvent.length + 1) === changeEvent + ':';\n }\n\n if (typeof options.bootstrap === 'string' && options.bootstrap.toUpperCase() === 'LOCALSTORAGE') {\n if (store) {\n useLocalStorage = true;\n } else {\n logger.warn(messages.localStorageUnavailable());\n }\n }\n\n if (typeof options.bootstrap === 'object') {\n // Set the flags as soon as possible before we get into any async code, so application code can read\n // them even if the ready event has not yet fired.\n flags = readFlagsFromBootstrap(options.bootstrap);\n }\n\n if (stateProvider) {\n // The stateProvider option is used in the Electron SDK, to allow a client instance in the main process\n // to control another client instance (i.e. this one) in the renderer process. We can't predict which\n // one will start up first, so the initial state may already be available for us or we may have to wait\n // to receive it.\n const state = stateProvider.getInitialState();\n if (state) {\n initFromStateProvider(state);\n } else {\n stateProvider.on('init', initFromStateProvider);\n }\n stateProvider.on('update', updateFromStateProvider);\n } else {\n finishInit().catch(signalFailedInit);\n }\n\n function finishInit() {\n if (!env) {\n return Promise.reject(new errors.LDInvalidEnvironmentIdError(messages.environmentNotSpecified()));\n }\n return userValidator.validateUser(user).then(realUser => {\n ident.setUser(realUser);\n if (typeof options.bootstrap === 'object') {\n // flags have already been set earlier\n return signalSuccessfulInit();\n } else if (useLocalStorage) {\n return finishInitWithLocalStorage();\n } else {\n return finishInitWithPolling();\n }\n });\n }\n\n function finishInitWithLocalStorage() {\n return store\n .loadFlags()\n .catch(() => null) // treat an error the same as if no flags were available\n .then(storedFlags => {\n if (storedFlags === null || storedFlags === undefined) {\n flags = {};\n return requestor\n .fetchFlagSettings(ident.getUser(), hash)\n .then(requestedFlags => replaceAllFlags(requestedFlags || {}))\n .then(signalSuccessfulInit)\n .catch(err => {\n const initErr = new errors.LDFlagFetchError(messages.errorFetchingFlags(err));\n signalFailedInit(initErr);\n });\n } else {\n // We're reading the flags from local storage. Signal that we're ready,\n // then update localStorage for the next page load. We won't signal changes or update\n // the in-memory flags unless you subscribe for changes\n flags = storedFlags;\n utils.onNextTick(signalSuccessfulInit);\n\n return requestor\n .fetchFlagSettings(ident.getUser(), hash)\n .then(requestedFlags => replaceAllFlags(requestedFlags))\n .catch(err => emitter.maybeReportError(err));\n }\n });\n }\n\n function finishInitWithPolling() {\n return requestor\n .fetchFlagSettings(ident.getUser(), hash)\n .then(requestedFlags => {\n flags = requestedFlags || {};\n // Note, we don't need to call updateSettings here because local storage and change events are not relevant\n signalSuccessfulInit();\n })\n .catch(err => {\n flags = {};\n signalFailedInit(err);\n });\n }\n\n function initFromStateProvider(state) {\n environment = state.environment;\n ident.setUser(state.user);\n flags = { ...state.flags };\n utils.onNextTick(signalSuccessfulInit);\n }\n\n function updateFromStateProvider(state) {\n if (state.user) {\n ident.setUser(state.user);\n }\n if (state.flags) {\n replaceAllFlags(state.flags); // don't wait for this Promise to be resolved\n }\n }\n\n function signalSuccessfulInit() {\n logger.info(messages.clientInitialized());\n inited = true;\n updateStreamingState();\n initializationStateTracker.signalSuccess();\n }\n\n function signalFailedInit(err) {\n initializationStateTracker.signalFailure(err);\n }\n\n function start() {\n if (sendEvents) {\n if (diagnosticsManager) {\n diagnosticsManager.start();\n }\n events.start();\n }\n }\n\n function close(onDone) {\n if (closed) {\n return utils.wrapPromiseCallback(Promise.resolve(), onDone);\n }\n const finishClose = () => {\n closed = true;\n flags = {};\n };\n const p = Promise.resolve()\n .then(() => {\n disconnectStream();\n if (diagnosticsManager) {\n diagnosticsManager.stop();\n }\n if (sendEvents) {\n events.stop();\n return events.flush();\n }\n })\n .then(finishClose)\n .catch(finishClose);\n return utils.wrapPromiseCallback(p, onDone);\n }\n\n function getFlagsInternal() {\n // used by Electron integration\n return flags;\n }\n\n const client = {\n waitForInitialization: () => initializationStateTracker.getInitializationPromise(),\n waitUntilReady: () => initializationStateTracker.getReadyPromise(),\n identify: identify,\n getUser: getUser,\n variation: variation,\n variationDetail: variationDetail,\n track: track,\n alias: alias,\n on: on,\n off: off,\n setStreaming: setStreaming,\n flush: flush,\n allFlags: allFlags,\n close: close,\n };\n\n return {\n client: client, // The client object containing all public methods.\n options: options, // The validated configuration object, including all defaults.\n emitter: emitter, // The event emitter which can be used to log errors or trigger events.\n ident: ident, // The Identity object that manages the current user.\n logger: logger, // The logging abstraction.\n requestor: requestor, // The Requestor object.\n start: start, // Starts the client once the environment is ready.\n enqueueEvent: enqueueEvent, // Puts an analytics event in the queue, if event sending is enabled.\n getFlagsInternal: getFlagsInternal, // Returns flag data structure with all details.\n getEnvironmentId: () => environment, // Gets the environment ID (this may have changed since initialization, if we have a state provider)\n internalChangeEventName: internalChangeEvent, // This event is triggered whenever we have new flag state.\n };\n}\n\nexport const version = VERSION;\nexport { createConsoleLogger };\nexport { errors };\nexport { messages };\nexport { utils };\n","import * as utils from './utils';\n\nexport default function Identity(initialUser, onChange) {\n const ident = {};\n let user;\n\n ident.setUser = function(u) {\n const previousUser = user && utils.clone(user);\n user = utils.sanitizeUser(u);\n if (user && onChange) {\n onChange(utils.clone(user), previousUser);\n }\n };\n\n ident.getUser = function() {\n return user ? utils.clone(user) : null;\n };\n\n if (initialUser) {\n ident.setUser(initialUser);\n }\n\n return ident;\n}\n"],"names":["createCustomError","name","CustomError","message","code","Error","captureStackTrace","this","constructor","prototype","LDUnexpectedResponseError","LDInvalidEnvironmentIdError","LDInvalidUserError","LDInvalidEventKeyError","LDInvalidArgumentError","LDFlagFetchError","isHttpErrorRecoverable","status","uint8","tmp","len","length","extraBytes","parts","i","len2","push","encodeChunk","lookup","join","revLookup","charCodeAt","start","end","num","output","isArray","Array","keyList","Object","keys","hasProp","hasOwnProperty","equal","a","b","key","arrA","arrB","dateA","Date","dateB","getTime","regexpA","RegExp","regexpB","toString","call","userAttrsToStringify","btoa","s","escaped","unescape","encodeURIComponent","base64","stringToBytes","base64URLEncode","replace","clone","obj","JSON","parse","stringify","deepEquals","fastDeepEqual","onNextTick","cb","setTimeout","wrapPromiseCallback","promise","callback","ret","then","value","error","Promise","reject","undefined","transformValuesToVersionedValues","flags","objectHasOwnProperty","version","transformVersionedValuesToValues","flagsState","chunkUserEventsForUrl","maxLength","events","chunk","allEvents","slice","allChunks","remainingSpace","event","shift","unshift","getLDUserAgentString","platform","userAgent","getLDHeaders","options","sendLDHeaders","h","wrapperName","wrapperVersion","transformHeaders","headers","requestHeaderTransform","extend","objects","reduce","acc","object","sanitizeUser","user","newUser","attr","String","getRandomValues","crypto","bind","window","msCrypto","rnds8","Uint8Array","module","rnds","r","Math","random","byteToHex","substr","_nodeId","_clockseq","buf","offset","bth","_lastMSecs","_lastNSecs","node","clockseq","seedBytes","rng","msecs","nsecs","dt","tl","tmh","n","bytesToUuid","MAX_URL_LENGTH","EventSender","environmentId","imageUrlPath","baseHeaders","utils","httpFallbackPing","sender","sendChunk","url","isDiagnostic","usePost","jsonBody","payloadId","uuidv1","doPostRequest","canRetry","httpRequest","result","errors","dateStr","header","time","serverTime","getResponseInfo","catch","resolve","sendEvents","chunks","canPost","httpAllowsPost","results","all","UserFilter","config","filter","allAttributesPrivate","privateAttributeNames","ignoreAttrs","custom","anonymous","allowedTopLevelAttrs","secondary","ip","country","email","firstName","lastName","avatar","filterUser","filterAttrs","props","isAttributeAllowed","userPrivateAttrs","indexOf","isPrivateAttr","filteredProps","removedAttrs","customResult","removedAttrNames","sort","privateAttrs","errorString","err","clientInitialized","eventWithoutUser","unknownCustomEventKey","environmentNotSpecified","docLink","bootstrapOldFormat","bootstrapInvalid","identifyDisabled","debugStreamPing","debugStreamPut","debugStreamPatch","debugStreamPatchIgnored","debugStreamDelete","debugStreamDeleteIgnored","debugEnqueueingEvent","kind","eventCapacityExceeded","invalidContentType","contentType","localStorageUnavailable","localStorageUnavailableForUserId","networkError","e","environmentNotFound","errorFetchingFlags","userNotSpecified","invalidUser","deprecated","oldName","newName","httpErrorMessage","context","retryMessage","httpUnavailable","streamClosing","streamConnecting","streamError","streamReconnectDelay","unknownOption","wrongOptionType","expectedType","actualType","wrongOptionTypeBoolean","optionBelowMinimum","minimum","debugPolling","debugPostingEvents","count","EventProcessor","flushTimer","diagnosticsAccumulator","emitter","processor","eventSender","mainEventsUrl","eventsUrl","summarizer","es","startDate","endDate","counters","summarizeEvent","counterKey","variation","counterVal","default","creationDate","getSummary","flagsOut","empty","c","flag","counterOut","unknown","features","clearSummary","EventSummarizer","userFilter","inlineUsers","inlineUsersInEvents","samplingInterval","eventCapacity","flushInterval","logger","queue","lastKnownPastTime","disabled","exceededCapacity","shouldSampleEvent","floor","addToOutbox","warn","messages","incrementDroppedEvents","enqueue","addFullEvent","addDebugEvent","trackEvents","debugEventsUntilDate","shouldDebugEvent","userKey","makeOutputEvent","debugEvent","flush","eventsToSend","summary","setEventsInLastBatch","debug","responseInfo","maybeReportError","flushTick","stop","clearTimeout","EventEmitter","on","handler","concat","off","emit","copiedHandlers","apply","arguments","getEvents","getEventListenerCount","listeningTo","console","readyEvent","successEvent","failureEvent","eventEmitter","succeeded","failed","failureValue","initializationPromise","readyPromise","onReady","getInitializationPromise","onSuccess","onFailure","getReadyPromise","signalSuccess","signalFailure","Store","localStorageProvider","environment","hash","ident","store","getFlagsKey","getUser","loadFlags","get","dataStr","data","schema","$schema","ex","clearFlags","saveFlags","set","clear","streamReadTimeoutMillis","Stream","connectionAttemptStartTime","baseUrl","streamUrl","stream","evalUrlPrefix","useReport","withReasons","evaluationReasons","firstConnectionErrorLogged","reconnectTimeoutReference","handlers","handleError","logConnectionResult","closeConnection","tryConnect","delay","openConnection","query","readTimeoutMillis","eventSourceFactory","eventSourceAllowsReport","method","body","info","addEventListener","onerror","close","success","recordStreamInit","connect","newHash","newHandlers","disconnect","isConnected","eventSourceIsActive","jsonContentType","Requestor","requestor","activeRequests","fetchJSON","endpoint","coalescer","finallyFn","currentPromise","currentCancelFn","finalResolve","finalReject","p","cancelFn","resultPromise","promiseCoalescer","req","statusText","getResponseError","substring","addPromise","cancel","path","fetchFlagSettings","ldUserIdKey","UserValidator","validateUser","userOut","cachedId","id","setCachedUserId","baseOptionDefs","streaming","type","allowFrequentDuplicateEvents","sendEventsOnlyForVariation","bootstrap","diagnosticRecordingInterval","diagnosticOptOut","stateProvider","autoAliasingOptOut","validate","extraOptionDefs","optionDefs","deprecatedOptions","all_attributes_private","private_attribute_names","reportArgumentError","opts","typeDescForValue","t","forEach","optionDef","allowedTypes","split","sdkKey","diagnosticId","sdkKeySuffix","startTime","dataSinceDate","droppedEvents","eventsInLastBatch","streamInits","reset","getProps","setProps","timestamp","durationMillis","accumulator","eventSentTime","periodicTimer","combinedMode","diagnosticUseCombinedEvent","localStorageKey","diagnosticEventsUrl","periodicInterval","streamingEnabled","manager","makeInitProperties","sdk","sdkData","diagnosticSdkData","makeSdkData","configuration","customBaseURI","customStreamURI","customEventsURI","eventsCapacity","eventsFlushIntervalMillis","reconnectTimeMillis","streamingDisabled","diagnosticRecordingIntervalMillis","usingSecureMode","bootstrapMode","fetchGoalsDisabled","fetchGoals","diagnosticPlatformData","sendDiagnosticEvent","debugPostingDiagnosticEvent","sendPeriodicEvent","currentTime","createPeriodicEventAndReset","localStorage","saveProperties","loadProperties","localStorageAvailable","nextEventTime","timeNow","setStreaming","enabled","createConsoleLogger","level","maybePrefix","prefix","allLevels","minLevelIndex","log","levelIndex","methodName","msg","levelName","changeEvent","internalChangeEvent","env","specifiedOptions","useLocalStorage","streamActive","subscribedToChangeEvents","createLogger","initializationStateTracker","InitializationStateTracker","diagnosticsEnabled","diagnostics","diagnosticsManager","eventProcessor","seenRequests","streamForcedState","inited","closed","firstEvent","initialUser","onChange","setUser","u","previousUser","Identity","enqueueEvent","sendIdentifyEvent","alias","userValidator","isDoNotTrack","sendFlagEvent","detail","defaultValue","includeReason","now","cacheKey","cached","variationIndex","contextKind","userContextKind","flagVersion","trackReason","reason","variationDetailInternal","sendEvent","includeReasonInEvent","deleted","getFlagDetail","errorKind","previousKey","previousContextKind","connectStream","ping","userAtTimeOfPingEvent","requestedFlags","replaceAllFlags","put","patch","oldFlag","mods","newFlag","newDetail","previous","current","handleFlagChanges","delete","disconnectStream","newFlags","changes","changeEventParams","updateStreamingState","shouldBeStreaming","isChangeEventKey","toUpperCase","_typeof","metadataKey","metadata","readFlagsFromBootstrap","state","getInitialState","initFromStateProvider","realUser","signalSuccessfulInit","storedFlags","signalFailedInit","client","waitForInitialization","waitUntilReady","identify","onDone","flagValueMap","variationDetail","track","metricValue","customEventFilter","getCurrentUrl","haveListeners","newState","allFlags","finishClose","getFlagsInternal","getEnvironmentId","internalChangeEventName"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ldclient-common.min.js","sources":["../src/errors.js","../node_modules/base64-js/index.js","../node_modules/fast-deep-equal/index.js","../src/utils.js","../node_modules/uuid/lib/bytesToUuid.js","../node_modules/uuid/lib/rng-browser.js","../node_modules/uuid/v1.js","../src/EventSender.js","../src/UserFilter.js","../src/messages.js","../src/EventProcessor.js","../src/EventSummarizer.js","../src/EventEmitter.js","../src/InitializationState.js","../src/PersistentFlagStore.js","../src/PersistentStorage.js","../src/Stream.js","../src/Requestor.js","../src/promiseCoalescer.js","../src/UserValidator.js","../src/loggers.js","../src/configuration.js","../src/diagnosticEvents.js","../src/index.js","../src/Identity.js"],"sourcesContent":["function createCustomError(name) {\n function CustomError(message, code) {\n Error.captureStackTrace && Error.captureStackTrace(this, this.constructor);\n this.message = message;\n this.code = code;\n }\n\n CustomError.prototype = new Error();\n CustomError.prototype.name = name;\n CustomError.prototype.constructor = CustomError;\n\n return CustomError;\n}\n\nexport const LDUnexpectedResponseError = createCustomError('LaunchDarklyUnexpectedResponseError');\nexport const LDInvalidEnvironmentIdError = createCustomError('LaunchDarklyInvalidEnvironmentIdError');\nexport const LDInvalidUserError = createCustomError('LaunchDarklyInvalidUserError');\nexport const LDInvalidEventKeyError = createCustomError('LaunchDarklyInvalidEventKeyError');\nexport const LDInvalidArgumentError = createCustomError('LaunchDarklyInvalidArgumentError');\nexport const LDFlagFetchError = createCustomError('LaunchDarklyFlagFetchError');\n\nexport function isHttpErrorRecoverable(status) {\n if (status >= 400 && status < 500) {\n return status === 400 || status === 408 || status === 429;\n }\n return true;\n}\n","'use strict'\n\nexports.byteLength = byteLength\nexports.toByteArray = toByteArray\nexports.fromByteArray = fromByteArray\n\nvar lookup = []\nvar revLookup = []\nvar Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array\n\nvar code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\nfor (var i = 0, len = code.length; i < len; ++i) {\n lookup[i] = code[i]\n revLookup[code.charCodeAt(i)] = i\n}\n\n// Support decoding URL-safe base64 strings, as Node.js does.\n// See: https://en.wikipedia.org/wiki/Base64#URL_applications\nrevLookup['-'.charCodeAt(0)] = 62\nrevLookup['_'.charCodeAt(0)] = 63\n\nfunction getLens (b64) {\n var len = b64.length\n\n if (len % 4 > 0) {\n throw new Error('Invalid string. Length must be a multiple of 4')\n }\n\n // Trim off extra bytes after placeholder bytes are found\n // See: https://github.com/beatgammit/base64-js/issues/42\n var validLen = b64.indexOf('=')\n if (validLen === -1) validLen = len\n\n var placeHoldersLen = validLen === len\n ? 0\n : 4 - (validLen % 4)\n\n return [validLen, placeHoldersLen]\n}\n\n// base64 is 4/3 + up to two characters of the original data\nfunction byteLength (b64) {\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction _byteLength (b64, validLen, placeHoldersLen) {\n return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen\n}\n\nfunction toByteArray (b64) {\n var tmp\n var lens = getLens(b64)\n var validLen = lens[0]\n var placeHoldersLen = lens[1]\n\n var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen))\n\n var curByte = 0\n\n // if there are placeholders, only get up to the last complete 4 chars\n var len = placeHoldersLen > 0\n ? validLen - 4\n : validLen\n\n for (var i = 0; i < len; i += 4) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 18) |\n (revLookup[b64.charCodeAt(i + 1)] << 12) |\n (revLookup[b64.charCodeAt(i + 2)] << 6) |\n revLookup[b64.charCodeAt(i + 3)]\n arr[curByte++] = (tmp >> 16) & 0xFF\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 2) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 2) |\n (revLookup[b64.charCodeAt(i + 1)] >> 4)\n arr[curByte++] = tmp & 0xFF\n }\n\n if (placeHoldersLen === 1) {\n tmp =\n (revLookup[b64.charCodeAt(i)] << 10) |\n (revLookup[b64.charCodeAt(i + 1)] << 4) |\n (revLookup[b64.charCodeAt(i + 2)] >> 2)\n arr[curByte++] = (tmp >> 8) & 0xFF\n arr[curByte++] = tmp & 0xFF\n }\n\n return arr\n}\n\nfunction tripletToBase64 (num) {\n return lookup[num >> 18 & 0x3F] +\n lookup[num >> 12 & 0x3F] +\n lookup[num >> 6 & 0x3F] +\n lookup[num & 0x3F]\n}\n\nfunction encodeChunk (uint8, start, end) {\n var tmp\n var output = []\n for (var i = start; i < end; i += 3) {\n tmp =\n ((uint8[i] << 16) & 0xFF0000) +\n ((uint8[i + 1] << 8) & 0xFF00) +\n (uint8[i + 2] & 0xFF)\n output.push(tripletToBase64(tmp))\n }\n return output.join('')\n}\n\nfunction fromByteArray (uint8) {\n var tmp\n var len = uint8.length\n var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes\n var parts = []\n var maxChunkLength = 16383 // must be multiple of 3\n\n // go through the array every three bytes, we'll deal with trailing stuff later\n for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {\n parts.push(encodeChunk(\n uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)\n ))\n }\n\n // pad the end with zeros, but make sure to not forget the extra bytes\n if (extraBytes === 1) {\n tmp = uint8[len - 1]\n parts.push(\n lookup[tmp >> 2] +\n lookup[(tmp << 4) & 0x3F] +\n '=='\n )\n } else if (extraBytes === 2) {\n tmp = (uint8[len - 2] << 8) + uint8[len - 1]\n parts.push(\n lookup[tmp >> 10] +\n lookup[(tmp >> 4) & 0x3F] +\n lookup[(tmp << 2) & 0x3F] +\n '='\n )\n }\n\n return parts.join('')\n}\n","'use strict';\n\nvar isArray = Array.isArray;\nvar keyList = Object.keys;\nvar hasProp = Object.prototype.hasOwnProperty;\n\nmodule.exports = function equal(a, b) {\n if (a === b) return true;\n\n if (a && b && typeof a == 'object' && typeof b == 'object') {\n var arrA = isArray(a)\n , arrB = isArray(b)\n , i\n , length\n , key;\n\n if (arrA && arrB) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0;)\n if (!equal(a[i], b[i])) return false;\n return true;\n }\n\n if (arrA != arrB) return false;\n\n var dateA = a instanceof Date\n , dateB = b instanceof Date;\n if (dateA != dateB) return false;\n if (dateA && dateB) return a.getTime() == b.getTime();\n\n var regexpA = a instanceof RegExp\n , regexpB = b instanceof RegExp;\n if (regexpA != regexpB) return false;\n if (regexpA && regexpB) return a.toString() == b.toString();\n\n var keys = keyList(a);\n length = keys.length;\n\n if (length !== keyList(b).length)\n return false;\n\n for (i = length; i-- !== 0;)\n if (!hasProp.call(b, keys[i])) return false;\n\n for (i = length; i-- !== 0;) {\n key = keys[i];\n if (!equal(a[key], b[key])) return false;\n }\n\n return true;\n }\n\n return a!==a && b!==b;\n};\n","import * as base64 from 'base64-js';\nimport fastDeepEqual from 'fast-deep-equal';\n\nconst userAttrsToStringify = ['key', 'secondary', 'ip', 'country', 'email', 'firstName', 'lastName', 'avatar', 'name'];\n\n// See http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html\nexport function btoa(s) {\n const escaped = unescape(encodeURIComponent(s));\n return base64.fromByteArray(stringToBytes(escaped));\n}\n\nfunction stringToBytes(s) {\n const b = [];\n for (let i = 0; i < s.length; i++) {\n b.push(s.charCodeAt(i));\n }\n return b;\n}\n\nexport function base64URLEncode(s) {\n return (\n btoa(s)\n // eslint-disable-next-line\n .replace(/=/g, '')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n );\n}\n\nexport function clone(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n\nexport function deepEquals(a, b) {\n return fastDeepEqual(a, b);\n}\n\n// Events emitted in LDClient's initialize method will happen before the consumer\n// can register a listener, so defer them to next tick.\nexport function onNextTick(cb) {\n setTimeout(cb, 0);\n}\n\n/**\n * Wrap a promise to invoke an optional callback upon resolution or rejection.\n *\n * This function assumes the callback follows the Node.js callback type: (err, value) => void\n *\n * If a callback is provided:\n * - if the promise is resolved, invoke the callback with (null, value)\n * - if the promise is rejected, invoke the callback with (error, null)\n *\n * @param {Promise<any>} promise\n * @param {Function} callback\n * @returns Promise<any> | undefined\n */\nexport function wrapPromiseCallback(promise, callback) {\n const ret = promise.then(\n value => {\n if (callback) {\n setTimeout(() => {\n callback(null, value);\n }, 0);\n }\n return value;\n },\n error => {\n if (callback) {\n setTimeout(() => {\n callback(error, null);\n }, 0);\n } else {\n return Promise.reject(error);\n }\n }\n );\n\n return !callback ? ret : undefined;\n}\n\n/**\n * Takes a map of flag keys to values, and returns the more verbose structure used by the\n * client stream.\n */\nexport function transformValuesToVersionedValues(flags) {\n const ret = {};\n for (const key in flags) {\n if (objectHasOwnProperty(flags, key)) {\n ret[key] = { value: flags[key], version: 0 };\n }\n }\n return ret;\n}\n\n/**\n * Converts the internal flag state map to a simple map of flag keys to values.\n */\nexport function transformVersionedValuesToValues(flagsState) {\n const ret = {};\n for (const key in flagsState) {\n if (objectHasOwnProperty(flagsState, key)) {\n ret[key] = flagsState[key].value;\n }\n }\n return ret;\n}\n\n/**\n * Returns an array of event groups each of which can be safely URL-encoded\n * without hitting the safe maximum URL length of certain browsers.\n *\n * @param {number} maxLength maximum URL length targeted\n * @param {Array[Object}]} events queue of events to divide\n * @returns Array[Array[Object]]\n */\nexport function chunkUserEventsForUrl(maxLength, events) {\n const allEvents = events.slice(0);\n const allChunks = [];\n let remainingSpace = maxLength;\n let chunk;\n\n while (allEvents.length > 0) {\n chunk = [];\n\n while (remainingSpace > 0) {\n const event = allEvents.shift();\n if (!event) {\n break;\n }\n remainingSpace = remainingSpace - base64URLEncode(JSON.stringify(event)).length;\n // If we are over the max size, put this one back on the queue\n // to try in the next round, unless this event alone is larger\n // than the limit, in which case, screw it, and try it anyway.\n if (remainingSpace < 0 && chunk.length > 0) {\n allEvents.unshift(event);\n } else {\n chunk.push(event);\n }\n }\n\n remainingSpace = maxLength;\n allChunks.push(chunk);\n }\n\n return allChunks;\n}\n\nexport function getLDUserAgentString(platform) {\n const version = platform.version || VERSION;\n return platform.userAgent + '/' + version;\n}\n\nexport function getLDHeaders(platform, options) {\n if (options && !options.sendLDHeaders) {\n return {};\n }\n const h = {\n 'X-LaunchDarkly-User-Agent': getLDUserAgentString(platform),\n };\n if (options && options.wrapperName) {\n h['X-LaunchDarkly-Wrapper'] = options.wrapperVersion\n ? options.wrapperName + '/' + options.wrapperVersion\n : options.wrapperName;\n }\n return h;\n}\n\nexport function transformHeaders(headers, options) {\n if (!options || !options.requestHeaderTransform) {\n return headers;\n }\n return options.requestHeaderTransform({ ...headers });\n}\n\nexport function extend(...objects) {\n return objects.reduce((acc, obj) => ({ ...acc, ...obj }), {});\n}\n\nexport function objectHasOwnProperty(object, name) {\n return Object.prototype.hasOwnProperty.call(object, name);\n}\n\nexport function sanitizeUser(user) {\n if (!user) {\n return user;\n }\n let newUser;\n for (const i in userAttrsToStringify) {\n const attr = userAttrsToStringify[i];\n const value = user[attr];\n if (value !== undefined && typeof value !== 'string') {\n newUser = newUser || { ...user };\n newUser[attr] = String(value);\n }\n }\n return newUser || user;\n}\n","/**\n * Convert array of 16 byte values to UUID string format of the form:\n * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n */\nvar byteToHex = [];\nfor (var i = 0; i < 256; ++i) {\n byteToHex[i] = (i + 0x100).toString(16).substr(1);\n}\n\nfunction bytesToUuid(buf, offset) {\n var i = offset || 0;\n var bth = byteToHex;\n // join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4\n return ([bth[buf[i++]], bth[buf[i++]], \n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]], '-',\n\tbth[buf[i++]], bth[buf[i++]],\n\tbth[buf[i++]], bth[buf[i++]],\n\tbth[buf[i++]], bth[buf[i++]]]).join('');\n}\n\nmodule.exports = bytesToUuid;\n","// Unique ID creation requires a high quality random # generator. In the\n// browser this is a little complicated due to unknown quality of Math.random()\n// and inconsistent support for the `crypto` API. We do the best we can via\n// feature-detection\n\n// getRandomValues needs to be invoked in a context where \"this\" is a Crypto\n// implementation. Also, find the complete implementation of crypto on IE11.\nvar getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||\n (typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));\n\nif (getRandomValues) {\n // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto\n var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef\n\n module.exports = function whatwgRNG() {\n getRandomValues(rnds8);\n return rnds8;\n };\n} else {\n // Math.random()-based (RNG)\n //\n // If all else fails, use Math.random(). It's fast, but is of unspecified\n // quality.\n var rnds = new Array(16);\n\n module.exports = function mathRNG() {\n for (var i = 0, r; i < 16; i++) {\n if ((i & 0x03) === 0) r = Math.random() * 0x100000000;\n rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;\n }\n\n return rnds;\n };\n}\n","var rng = require('./lib/rng');\nvar bytesToUuid = require('./lib/bytesToUuid');\n\n// **`v1()` - Generate time-based UUID**\n//\n// Inspired by https://github.com/LiosK/UUID.js\n// and http://docs.python.org/library/uuid.html\n\nvar _nodeId;\nvar _clockseq;\n\n// Previous uuid creation time\nvar _lastMSecs = 0;\nvar _lastNSecs = 0;\n\n// See https://github.com/broofa/node-uuid for API details\nfunction v1(options, buf, offset) {\n var i = buf && offset || 0;\n var b = buf || [];\n\n options = options || {};\n var node = options.node || _nodeId;\n var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq;\n\n // node and clockseq need to be initialized to random values if they're not\n // specified. We do this lazily to minimize issues related to insufficient\n // system entropy. See #189\n if (node == null || clockseq == null) {\n var seedBytes = rng();\n if (node == null) {\n // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1)\n node = _nodeId = [\n seedBytes[0] | 0x01,\n seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]\n ];\n }\n if (clockseq == null) {\n // Per 4.2.2, randomize (14 bit) clockseq\n clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff;\n }\n }\n\n // UUID timestamps are 100 nano-second units since the Gregorian epoch,\n // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so\n // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs'\n // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00.\n var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime();\n\n // Per 4.2.1.2, use count of uuid's generated during the current clock\n // cycle to simulate higher resolution clock\n var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1;\n\n // Time since last uuid creation (in msecs)\n var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000;\n\n // Per 4.2.1.2, Bump clockseq on clock regression\n if (dt < 0 && options.clockseq === undefined) {\n clockseq = clockseq + 1 & 0x3fff;\n }\n\n // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new\n // time interval\n if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) {\n nsecs = 0;\n }\n\n // Per 4.2.1.2 Throw error if too many uuids are requested\n if (nsecs >= 10000) {\n throw new Error('uuid.v1(): Can\\'t create more than 10M uuids/sec');\n }\n\n _lastMSecs = msecs;\n _lastNSecs = nsecs;\n _clockseq = clockseq;\n\n // Per 4.1.4 - Convert from unix epoch to Gregorian epoch\n msecs += 12219292800000;\n\n // `time_low`\n var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000;\n b[i++] = tl >>> 24 & 0xff;\n b[i++] = tl >>> 16 & 0xff;\n b[i++] = tl >>> 8 & 0xff;\n b[i++] = tl & 0xff;\n\n // `time_mid`\n var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff;\n b[i++] = tmh >>> 8 & 0xff;\n b[i++] = tmh & 0xff;\n\n // `time_high_and_version`\n b[i++] = tmh >>> 24 & 0xf | 0x10; // include version\n b[i++] = tmh >>> 16 & 0xff;\n\n // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant)\n b[i++] = clockseq >>> 8 | 0x80;\n\n // `clock_seq_low`\n b[i++] = clockseq & 0xff;\n\n // `node`\n for (var n = 0; n < 6; ++n) {\n b[i + n] = node[n];\n }\n\n return buf ? buf : bytesToUuid(b);\n}\n\nmodule.exports = v1;\n","import * as errors from './errors';\nimport * as utils from './utils';\nimport uuidv1 from 'uuid/v1';\n\nconst MAX_URL_LENGTH = 2000;\n\nexport default function EventSender(platform, environmentId, options) {\n const imageUrlPath = '/a/' + environmentId + '.gif';\n const baseHeaders = utils.extend({ 'Content-Type': 'application/json' }, utils.getLDHeaders(platform, options));\n const httpFallbackPing = platform.httpFallbackPing; // this will be set for us if we're in the browser SDK\n const sender = {};\n\n function getResponseInfo(result) {\n const ret = { status: result.status };\n const dateStr = result.header('date');\n if (dateStr) {\n const time = Date.parse(dateStr);\n if (time) {\n ret.serverTime = time;\n }\n }\n return ret;\n }\n\n sender.sendChunk = (events, url, isDiagnostic, usePost) => {\n const jsonBody = JSON.stringify(events);\n const payloadId = isDiagnostic ? null : uuidv1();\n\n function doPostRequest(canRetry) {\n const headers = isDiagnostic\n ? baseHeaders\n : utils.extend({}, baseHeaders, {\n 'X-LaunchDarkly-Event-Schema': '3',\n 'X-LaunchDarkly-Payload-ID': payloadId,\n });\n return platform\n .httpRequest('POST', url, utils.transformHeaders(headers, options), jsonBody)\n .promise.then(result => {\n if (!result) {\n // This was a response from a fire-and-forget request, so we won't have a status.\n return;\n }\n if (result.status >= 400 && errors.isHttpErrorRecoverable(result.status) && canRetry) {\n return doPostRequest(false);\n } else {\n return getResponseInfo(result);\n }\n })\n .catch(() => {\n if (canRetry) {\n return doPostRequest(false);\n }\n return Promise.reject();\n });\n }\n\n if (usePost) {\n return doPostRequest(true).catch(() => {});\n } else {\n httpFallbackPing && httpFallbackPing(url + imageUrlPath + '?d=' + utils.base64URLEncode(jsonBody));\n return Promise.resolve(); // we don't wait for this request to complete, it's just a one-way ping\n }\n };\n\n sender.sendEvents = function(events, url, isDiagnostic) {\n if (!platform.httpRequest) {\n return Promise.resolve();\n }\n const canPost = platform.httpAllowsPost();\n let chunks;\n if (canPost) {\n // no need to break up events into chunks if we can send a POST\n chunks = [events];\n } else {\n chunks = utils.chunkUserEventsForUrl(MAX_URL_LENGTH - url.length, events);\n }\n const results = [];\n for (let i = 0; i < chunks.length; i++) {\n results.push(sender.sendChunk(chunks[i], url, isDiagnostic, canPost));\n }\n return Promise.all(results);\n };\n\n return sender;\n}\n","import * as utils from './utils';\n\n/**\n * The UserFilter object transforms user objects into objects suitable to be sent as JSON to\n * the server, hiding any private user attributes.\n *\n * @param {Object} the LaunchDarkly client configuration object\n **/\nexport default function UserFilter(config) {\n const filter = {};\n const allAttributesPrivate = config.allAttributesPrivate;\n const privateAttributeNames = config.privateAttributeNames || [];\n const ignoreAttrs = { key: true, custom: true, anonymous: true };\n const allowedTopLevelAttrs = {\n key: true,\n secondary: true,\n ip: true,\n country: true,\n email: true,\n firstName: true,\n lastName: true,\n avatar: true,\n name: true,\n anonymous: true,\n custom: true,\n };\n\n filter.filterUser = function(user) {\n if (!user) {\n return null;\n }\n const userPrivateAttrs = user.privateAttributeNames || [];\n\n const isPrivateAttr = function(name) {\n return (\n !ignoreAttrs[name] &&\n (allAttributesPrivate || userPrivateAttrs.indexOf(name) !== -1 || privateAttributeNames.indexOf(name) !== -1)\n );\n };\n const filterAttrs = function(props, isAttributeAllowed) {\n return Object.keys(props).reduce(\n (acc, name) => {\n const ret = acc;\n if (isAttributeAllowed(name)) {\n if (isPrivateAttr(name)) {\n // add to hidden list\n ret[1][name] = true;\n } else {\n ret[0][name] = props[name];\n }\n }\n return ret;\n },\n [{}, {}]\n );\n };\n const result = filterAttrs(user, key => allowedTopLevelAttrs[key]);\n const filteredProps = result[0];\n let removedAttrs = result[1];\n if (user.custom) {\n const customResult = filterAttrs(user.custom, () => true);\n filteredProps.custom = customResult[0];\n removedAttrs = utils.extend({}, removedAttrs, customResult[1]);\n }\n const removedAttrNames = Object.keys(removedAttrs);\n if (removedAttrNames.length) {\n removedAttrNames.sort();\n filteredProps.privateAttrs = removedAttrNames;\n }\n return filteredProps;\n };\n return filter;\n}\n","import * as errors from './errors';\n\nfunction errorString(err) {\n if (err && err.message) {\n return err.message;\n }\n if (typeof err === 'string' || err instanceof String) {\n return err;\n }\n return JSON.stringify(err);\n}\n\nexport const clientInitialized = function() {\n return 'LaunchDarkly client initialized';\n};\n\nconst docLink =\n ' Please see https://docs.launchdarkly.com/sdk/client-side/javascript#initializing-the-client for instructions on SDK initialization.';\n\nexport const clientNotReady = function() {\n return 'LaunchDarkly client is not ready';\n};\n\nexport const eventCapacityExceeded = function() {\n return 'Exceeded event queue capacity. Increase capacity to avoid dropping events.';\n};\n\nexport const eventWithoutUser = function() {\n return 'Be sure to call `identify` in the LaunchDarkly client: https://docs.launchdarkly.com/sdk/features/identify#javascript';\n};\n\nexport const invalidContentType = function(contentType) {\n return 'Expected application/json content type but got \"' + contentType + '\"';\n};\n\nexport const invalidKey = function() {\n return 'Event key must be a string';\n};\n\nexport const localStorageUnavailable = function(err) {\n return 'local storage is unavailable: ' + errorString(err);\n};\n\nexport const networkError = e => 'network error' + (e ? ' (' + e + ')' : '');\n\n// We should remove unknownCustomEventKey in the future - see comments in track() in index.js\nexport const unknownCustomEventKey = function(key) {\n return 'Custom event \"' + key + '\" does not exist';\n};\n\nexport const environmentNotFound = function() {\n return 'Environment not found. Double check that you specified a valid environment/client-side ID.' + docLink;\n};\n\nexport const environmentNotSpecified = function() {\n return 'No environment/client-side ID was specified.' + docLink;\n};\n\nexport const errorFetchingFlags = function(err) {\n return 'Error fetching flag settings: ' + errorString(err);\n};\n\nexport const userNotSpecified = function() {\n return 'No user specified.' + docLink;\n};\n\nexport const invalidUser = function() {\n return 'Invalid user specified.' + docLink;\n};\n\nexport const bootstrapOldFormat = function() {\n return (\n 'LaunchDarkly client was initialized with bootstrap data that did not include flag metadata. ' +\n 'Events may not be sent correctly.' +\n docLink\n );\n};\n\nexport const bootstrapInvalid = function() {\n return 'LaunchDarkly bootstrap data is not available because the back end could not read the flags.';\n};\n\nexport const deprecated = function(oldName, newName) {\n if (newName) {\n return '\"' + oldName + '\" is deprecated, please use \"' + newName + '\"';\n }\n return '\"' + oldName + '\" is deprecated';\n};\n\nexport const httpErrorMessage = function(status, context, retryMessage) {\n return (\n 'Received error ' +\n status +\n (status === 401 ? ' (invalid SDK key)' : '') +\n ' for ' +\n context +\n ' - ' +\n (errors.isHttpErrorRecoverable(status) ? retryMessage : 'giving up permanently')\n );\n};\n\nexport const httpUnavailable = function() {\n return 'Cannot make HTTP requests in this environment.' + docLink;\n};\n\nexport const identifyDisabled = function() {\n return 'identify() has no effect here; it must be called on the main client instance';\n};\n\nexport const streamClosing = function() {\n return 'Closing stream connection';\n};\n\nexport const streamConnecting = function(url) {\n return 'Opening stream connection to ' + url;\n};\n\nexport const streamError = function(err, streamReconnectDelay) {\n return (\n 'Error on stream connection: ' +\n errorString(err) +\n ', will continue retrying every ' +\n streamReconnectDelay +\n ' milliseconds.'\n );\n};\n\nexport const unknownOption = name => 'Ignoring unknown config option \"' + name + '\"';\n\nexport const wrongOptionType = (name, expectedType, actualType) =>\n 'Config option \"' + name + '\" should be of type ' + expectedType + ', got ' + actualType + ', using default value';\n\nexport const wrongOptionTypeBoolean = (name, actualType) =>\n 'Config option \"' + name + '\" should be a boolean, got ' + actualType + ', converting to boolean';\n\nexport const optionBelowMinimum = (name, value, minimum) =>\n 'Config option \"' + name + '\" was set to ' + value + ', changing to minimum value of ' + minimum;\n\nexport const debugPolling = function(url) {\n return 'polling for feature flags at ' + url;\n};\n\nexport const debugStreamPing = function() {\n return 'received ping message from stream';\n};\n\nexport const debugStreamPut = function() {\n return 'received streaming update for all flags';\n};\n\nexport const debugStreamPatch = function(key) {\n return 'received streaming update for flag \"' + key + '\"';\n};\n\nexport const debugStreamPatchIgnored = function(key) {\n return 'received streaming update for flag \"' + key + '\" but ignored due to version check';\n};\n\nexport const debugStreamDelete = function(key) {\n return 'received streaming deletion for flag \"' + key + '\"';\n};\n\nexport const debugStreamDeleteIgnored = function(key) {\n return 'received streaming deletion for flag \"' + key + '\" but ignored due to version check';\n};\n\nexport const debugEnqueueingEvent = function(kind) {\n return 'enqueueing \"' + kind + '\" event';\n};\n\nexport const debugPostingEvents = function(count) {\n return 'sending ' + count + ' events';\n};\n\nexport const debugPostingDiagnosticEvent = function(event) {\n return 'sending diagnostic event (' + event.kind + ')';\n};\n","import EventSender from './EventSender';\nimport EventSummarizer from './EventSummarizer';\nimport UserFilter from './UserFilter';\nimport * as errors from './errors';\nimport * as messages from './messages';\nimport * as utils from './utils';\n\nexport default function EventProcessor(\n platform,\n options,\n environmentId,\n diagnosticsAccumulator = null,\n emitter = null,\n sender = null\n) {\n const processor = {};\n const eventSender = sender || EventSender(platform, environmentId, options);\n const mainEventsUrl = options.eventsUrl + '/events/bulk/' + environmentId;\n const summarizer = EventSummarizer();\n const userFilter = UserFilter(options);\n const inlineUsers = options.inlineUsersInEvents;\n const samplingInterval = options.samplingInterval;\n const eventCapacity = options.eventCapacity;\n const flushInterval = options.flushInterval;\n const logger = options.logger;\n let queue = [];\n let lastKnownPastTime = 0;\n let disabled = false;\n let exceededCapacity = false;\n let flushTimer;\n\n function shouldSampleEvent() {\n return samplingInterval === 0 || Math.floor(Math.random() * samplingInterval) === 0;\n }\n\n function shouldDebugEvent(e) {\n if (e.debugEventsUntilDate) {\n // The \"last known past time\" comes from the last HTTP response we got from the server.\n // In case the client's time is set wrong, at least we know that any expiration date\n // earlier than that point is definitely in the past. If there's any discrepancy, we\n // want to err on the side of cutting off event debugging sooner.\n return e.debugEventsUntilDate > lastKnownPastTime && e.debugEventsUntilDate > new Date().getTime();\n }\n return false;\n }\n\n // Transform an event from its internal format to the format we use when sending a payload.\n function makeOutputEvent(e) {\n const ret = utils.extend({}, e);\n if (e.kind === 'alias') {\n // alias events do not require any transformation\n return ret;\n }\n if (inlineUsers || e.kind === 'identify') {\n // identify events always have an inline user\n ret.user = userFilter.filterUser(e.user);\n } else {\n ret.userKey = e.user.key;\n delete ret['user'];\n }\n if (e.kind === 'feature') {\n delete ret['trackEvents'];\n delete ret['debugEventsUntilDate'];\n }\n return ret;\n }\n\n function addToOutbox(event) {\n if (queue.length < eventCapacity) {\n queue.push(event);\n exceededCapacity = false;\n } else {\n if (!exceededCapacity) {\n exceededCapacity = true;\n logger.warn(messages.eventCapacityExceeded());\n }\n if (diagnosticsAccumulator) {\n // For diagnostic events, we track how many times we had to drop an event due to exceeding the capacity.\n diagnosticsAccumulator.incrementDroppedEvents();\n }\n }\n }\n\n processor.enqueue = function(event) {\n if (disabled) {\n return;\n }\n let addFullEvent = false;\n let addDebugEvent = false;\n\n // Add event to the summary counters if appropriate\n summarizer.summarizeEvent(event);\n\n // Decide whether to add the event to the payload. Feature events may be added twice, once for\n // the event (if tracked) and once for debugging.\n if (event.kind === 'feature') {\n if (shouldSampleEvent()) {\n addFullEvent = !!event.trackEvents;\n addDebugEvent = shouldDebugEvent(event);\n }\n } else {\n addFullEvent = shouldSampleEvent();\n }\n\n if (addFullEvent) {\n addToOutbox(makeOutputEvent(event));\n }\n if (addDebugEvent) {\n const debugEvent = utils.extend({}, event, { kind: 'debug' });\n debugEvent.user = userFilter.filterUser(debugEvent.user);\n delete debugEvent['trackEvents'];\n delete debugEvent['debugEventsUntilDate'];\n addToOutbox(debugEvent);\n }\n };\n\n processor.flush = function() {\n if (disabled) {\n return Promise.resolve();\n }\n const eventsToSend = queue;\n const summary = summarizer.getSummary();\n summarizer.clearSummary();\n if (summary) {\n summary.kind = 'summary';\n eventsToSend.push(summary);\n }\n if (diagnosticsAccumulator) {\n // For diagnostic events, we record how many events were in the queue at the last flush (since \"how\n // many events happened to be in the queue at the moment we decided to send a diagnostic event\" would\n // not be a very useful statistic).\n diagnosticsAccumulator.setEventsInLastBatch(eventsToSend.length);\n }\n if (eventsToSend.length === 0) {\n return Promise.resolve();\n }\n queue = [];\n logger.debug(messages.debugPostingEvents(eventsToSend.length));\n return eventSender.sendEvents(eventsToSend, mainEventsUrl).then(responseInfo => {\n if (responseInfo) {\n if (responseInfo.serverTime) {\n lastKnownPastTime = responseInfo.serverTime;\n }\n if (!errors.isHttpErrorRecoverable(responseInfo.status)) {\n disabled = true;\n }\n if (responseInfo.status >= 400) {\n utils.onNextTick(() => {\n emitter.maybeReportError(\n new errors.LDUnexpectedResponseError(\n messages.httpErrorMessage(responseInfo.status, 'event posting', 'some events were dropped')\n )\n );\n });\n }\n }\n });\n };\n\n processor.start = function() {\n const flushTick = () => {\n processor.flush();\n flushTimer = setTimeout(flushTick, flushInterval);\n };\n flushTimer = setTimeout(flushTick, flushInterval);\n };\n\n processor.stop = function() {\n clearTimeout(flushTimer);\n };\n\n return processor;\n}\n","export default function EventSummarizer() {\n const es = {};\n\n let startDate = 0,\n endDate = 0,\n counters = {};\n\n es.summarizeEvent = function(event) {\n if (event.kind === 'feature') {\n const counterKey =\n event.key +\n ':' +\n (event.variation !== null && event.variation !== undefined ? event.variation : '') +\n ':' +\n (event.version !== null && event.version !== undefined ? event.version : '');\n const counterVal = counters[counterKey];\n if (counterVal) {\n counterVal.count = counterVal.count + 1;\n } else {\n counters[counterKey] = {\n count: 1,\n key: event.key,\n variation: event.variation,\n version: event.version,\n value: event.value,\n default: event.default,\n };\n }\n if (startDate === 0 || event.creationDate < startDate) {\n startDate = event.creationDate;\n }\n if (event.creationDate > endDate) {\n endDate = event.creationDate;\n }\n }\n };\n\n es.getSummary = function() {\n const flagsOut = {};\n let empty = true;\n for (const i in counters) {\n const c = counters[i];\n let flag = flagsOut[c.key];\n if (!flag) {\n flag = {\n default: c.default,\n counters: [],\n };\n flagsOut[c.key] = flag;\n }\n const counterOut = {\n value: c.value,\n count: c.count,\n };\n if (c.variation !== undefined && c.variation !== null) {\n counterOut.variation = c.variation;\n }\n if (c.version) {\n counterOut.version = c.version;\n } else {\n counterOut.unknown = true;\n }\n flag.counters.push(counterOut);\n empty = false;\n }\n return empty\n ? null\n : {\n startDate,\n endDate,\n features: flagsOut,\n };\n };\n\n es.clearSummary = function() {\n startDate = 0;\n endDate = 0;\n counters = {};\n };\n\n return es;\n}\n","export default function EventEmitter(logger) {\n const emitter = {};\n const events = {};\n\n const listeningTo = event => !!events[event];\n\n emitter.on = function(event, handler, context) {\n events[event] = events[event] || [];\n events[event] = events[event].concat({\n handler: handler,\n context: context,\n });\n };\n\n emitter.off = function(event, handler, context) {\n if (!events[event]) {\n return;\n }\n for (let i = 0; i < events[event].length; i++) {\n if (events[event][i].handler === handler && events[event][i].context === context) {\n events[event] = events[event].slice(0, i).concat(events[event].slice(i + 1));\n }\n }\n };\n\n emitter.emit = function(event) {\n if (!events[event]) {\n return;\n }\n // Copy the list of handlers before iterating, in case any handler adds or removes another handler.\n // Any such changes should not affect what we do here-- we want to notify every handler that existed\n // at the moment that the event was fired.\n const copiedHandlers = events[event].slice(0);\n for (let i = 0; i < copiedHandlers.length; i++) {\n copiedHandlers[i].handler.apply(copiedHandlers[i].context, Array.prototype.slice.call(arguments, 1));\n }\n };\n\n emitter.getEvents = function() {\n return Object.keys(events);\n };\n\n emitter.getEventListenerCount = function(event) {\n return events[event] ? events[event].length : 0;\n };\n\n emitter.maybeReportError = function(error) {\n if (!error) {\n return;\n }\n if (listeningTo('error')) {\n this.emit('error', error);\n } else {\n (logger || console).error(error.message);\n }\n };\n return emitter;\n}\n","// This file provides an abstraction of the client's startup state.\n//\n// Startup can either succeed or fail exactly once; calling signalSuccess() or signalFailure()\n// after that point has no effect.\n//\n// On success, we fire both an \"initialized\" event and a \"ready\" event. Both the waitForInitialization()\n// promise and the waitUntilReady() promise are resolved in this case.\n//\n// On failure, we fire both a \"failed\" event (with the error as a parameter) and a \"ready\" event.\n// The waitForInitialization() promise is rejected, but the waitUntilReady() promise is resolved.\n//\n// To complicate things, we must *not* create the waitForInitialization() promise unless it is\n// requested, because otherwise failures would cause an *unhandled* rejection which can be a\n// serious problem in some environments. So we use a somewhat roundabout system for tracking the\n// initialization state and lazily creating this promise.\n\nconst readyEvent = 'ready',\n successEvent = 'initialized',\n failureEvent = 'failed';\n\nfunction InitializationStateTracker(eventEmitter) {\n let succeeded = false,\n failed = false,\n failureValue = null,\n initializationPromise = null;\n\n const readyPromise = new Promise(resolve => {\n const onReady = () => {\n eventEmitter.off(readyEvent, onReady); // we can't use \"once\" because it's not available on some JS platforms\n resolve();\n };\n eventEmitter.on(readyEvent, onReady);\n }).catch(() => {}); // this Promise should never be rejected, but the catch handler is a safety measure\n\n return {\n getInitializationPromise: () => {\n if (initializationPromise) {\n return initializationPromise;\n }\n if (succeeded) {\n return Promise.resolve();\n }\n if (failed) {\n return Promise.reject(failureValue);\n }\n initializationPromise = new Promise((resolve, reject) => {\n const onSuccess = () => {\n eventEmitter.off(successEvent, onSuccess);\n resolve();\n };\n const onFailure = err => {\n eventEmitter.off(failureEvent, onFailure);\n reject(err);\n };\n eventEmitter.on(successEvent, onSuccess);\n eventEmitter.on(failureEvent, onFailure);\n });\n return initializationPromise;\n },\n\n getReadyPromise: () => readyPromise,\n\n signalSuccess: () => {\n if (!succeeded && !failed) {\n succeeded = true;\n eventEmitter.emit(successEvent);\n eventEmitter.emit(readyEvent);\n }\n },\n\n signalFailure: err => {\n if (!succeeded && !failed) {\n failed = true;\n failureValue = err;\n eventEmitter.emit(failureEvent, err);\n eventEmitter.emit(readyEvent);\n }\n eventEmitter.maybeReportError(err); // the \"error\" event can be emitted more than once, unlike the others\n },\n };\n}\n\nmodule.exports = InitializationStateTracker;\n","import * as utils from './utils';\n\nexport default function PersistentFlagStore(storage, environment, hash, ident) {\n const store = {};\n\n function getFlagsKey() {\n let key = '';\n const user = ident.getUser();\n if (user) {\n key = hash || utils.btoa(JSON.stringify(user));\n }\n return 'ld:' + environment + ':' + key;\n }\n\n // Returns a Promise which will be resolved with a parsed JSON value if a stored value was available,\n // or resolved with null if there was no value or if storage was not available.\n store.loadFlags = () =>\n storage.get(getFlagsKey()).then(dataStr => {\n if (dataStr === null || dataStr === undefined) {\n return null;\n }\n try {\n let data = JSON.parse(dataStr);\n if (data) {\n const schema = data.$schema;\n if (schema === undefined || schema < 1) {\n data = utils.transformValuesToVersionedValues(data);\n } else {\n delete data['$schema'];\n }\n }\n return data;\n } catch (ex) {\n return store.clearFlags().then(() => null);\n }\n });\n\n // Resolves with true if successful, or false if storage is unavailable. Never rejects.\n store.saveFlags = flags => {\n const data = utils.extend({}, flags, { $schema: 1 });\n return storage.set(getFlagsKey(), JSON.stringify(data));\n };\n\n // Resolves with true if successful, or false if storage is unavailable. Never rejects.\n store.clearFlags = () => storage.clear(getFlagsKey());\n\n return store;\n}\n","import * as messages from './messages';\n\n// The localStorageProvider is provided by the platform object. It should have the following\n// methods, each of which should return a Promise:\n// - get(key): Gets the string value, if any, for the given key\n// - set(key, value): Stores a string value for the given key\n// - remove(key): Removes the given key\n//\n// Storage is just a light wrapper of the localStorageProvider, adding error handling and\n// ensuring that we don't call it if it's unavailable. The get method will simply resolve\n// with an undefined value if there is an error or if there is no localStorageProvider.\n// None of the promises returned by Storage will ever be rejected.\n//\n// It is always possible that the underlying platform storage mechanism might fail or be\n// disabled. If so, it's likely that it will keep failing, so we will only log one warning\n// instead of repetitive warnings.\nexport default function PersistentStorage(localStorageProvider, logger) {\n const storage = {};\n let loggedError = false;\n\n const logError = err => {\n if (!loggedError) {\n loggedError = true;\n logger.warn(messages.localStorageUnavailable(err));\n }\n };\n\n storage.isEnabled = () => !!localStorageProvider;\n\n // Resolves with a value, or undefined if storage is unavailable. Never rejects.\n storage.get = key =>\n new Promise(resolve => {\n if (!localStorageProvider) {\n resolve(undefined);\n return;\n }\n localStorageProvider\n .get(key)\n .then(resolve)\n .catch(err => {\n logError(err);\n resolve(undefined);\n });\n });\n\n // Resolves with true if successful, or false if storage is unavailable. Never rejects.\n storage.set = (key, value) =>\n new Promise(resolve => {\n if (!localStorageProvider) {\n resolve(false);\n return;\n }\n localStorageProvider\n .set(key, value)\n .then(() => resolve(true))\n .catch(err => {\n logError(err);\n resolve(false);\n });\n });\n\n // Resolves with true if successful, or false if storage is unavailable. Never rejects.\n storage.clear = key =>\n new Promise(resolve => {\n if (!localStorageProvider) {\n resolve(false);\n return;\n }\n localStorageProvider\n .clear(key)\n .then(() => resolve(true))\n .catch(err => {\n logError(err);\n resolve(false);\n });\n });\n\n return storage;\n}\n","import * as messages from './messages';\nimport { base64URLEncode, getLDHeaders, transformHeaders, objectHasOwnProperty } from './utils';\n\n// The underlying event source implementation is abstracted via the platform object, which should\n// have these three properties:\n// eventSourceFactory(): a function that takes a URL and optional config object and returns an object\n// with the same methods as the regular HTML5 EventSource object. The properties in the config\n// object are those supported by the launchdarkly-eventsource package; browser EventSource\n// implementations don't have any config options.\n// eventSourceIsActive(): a function that takes an EventSource-compatible object and returns true if\n// it is in an active state (connected or connecting).\n// eventSourceAllowsReport: true if REPORT is supported.\n\n// The read timeout for the stream is a fixed value that is set to be slightly longer than the expected\n// interval between heartbeats from the LaunchDarkly streaming server. If this amount of time elapses\n// with no new data, the connection will be cycled.\nconst streamReadTimeoutMillis = 5 * 60 * 1000; // 5 minutes\n\nexport default function Stream(platform, config, environment, diagnosticsAccumulator) {\n const baseUrl = config.streamUrl;\n const logger = config.logger;\n const stream = {};\n const evalUrlPrefix = baseUrl + '/eval/' + environment;\n const useReport = config.useReport;\n const withReasons = config.evaluationReasons;\n const streamReconnectDelay = config.streamReconnectDelay;\n const headers = getLDHeaders(platform, config);\n let firstConnectionErrorLogged = false;\n let es = null;\n let reconnectTimeoutReference = null;\n let connectionAttemptStartTime;\n let user = null;\n let hash = null;\n let handlers = null;\n\n stream.connect = function(newUser, newHash, newHandlers) {\n user = newUser;\n hash = newHash;\n handlers = {};\n for (const key in newHandlers || {}) {\n handlers[key] = function(e) {\n // Reset the state for logging the first connection error so that the first\n // connection error following a successful connection will once again be logged.\n // We will decorate *all* handlers to do this to keep this abstraction agnostic\n // for different stream implementations.\n firstConnectionErrorLogged = false;\n logConnectionResult(true);\n newHandlers[key] && newHandlers[key](e);\n };\n }\n tryConnect();\n };\n\n stream.disconnect = function() {\n clearTimeout(reconnectTimeoutReference);\n reconnectTimeoutReference = null;\n closeConnection();\n };\n\n stream.isConnected = function() {\n return !!(es && platform.eventSourceIsActive && platform.eventSourceIsActive(es));\n };\n\n function handleError(err) {\n if (!firstConnectionErrorLogged) {\n logger.warn(messages.streamError(err, streamReconnectDelay));\n firstConnectionErrorLogged = true;\n }\n logConnectionResult(false);\n closeConnection();\n tryConnect(streamReconnectDelay);\n }\n\n function tryConnect(delay) {\n if (!reconnectTimeoutReference) {\n if (delay) {\n reconnectTimeoutReference = setTimeout(openConnection, delay);\n } else {\n openConnection();\n }\n }\n }\n\n function openConnection() {\n reconnectTimeoutReference = null;\n let url;\n let query = '';\n const options = { headers, readTimeoutMillis: streamReadTimeoutMillis };\n if (platform.eventSourceFactory) {\n if (hash !== null && hash !== undefined) {\n query = 'h=' + hash;\n }\n if (useReport) {\n if (platform.eventSourceAllowsReport) {\n url = evalUrlPrefix;\n options.method = 'REPORT';\n options.headers['Content-Type'] = 'application/json';\n options.body = JSON.stringify(user);\n } else {\n // if we can't do REPORT, fall back to the old ping-based stream\n url = baseUrl + '/ping/' + environment;\n query = '';\n }\n } else {\n url = evalUrlPrefix + '/' + base64URLEncode(JSON.stringify(user));\n }\n options.headers = transformHeaders(options.headers, config);\n if (withReasons) {\n query = query + (query ? '&' : '') + 'withReasons=true';\n }\n url = url + (query ? '?' : '') + query;\n\n closeConnection();\n logger.info(messages.streamConnecting(url));\n logConnectionStarted();\n\n es = platform.eventSourceFactory(url, options);\n for (const key in handlers) {\n if (objectHasOwnProperty(handlers, key)) {\n es.addEventListener(key, handlers[key]);\n }\n }\n\n es.onerror = handleError;\n }\n }\n\n function closeConnection() {\n if (es) {\n logger.info(messages.streamClosing());\n es.close();\n es = null;\n }\n }\n\n function logConnectionStarted() {\n connectionAttemptStartTime = new Date().getTime();\n }\n\n function logConnectionResult(success) {\n if (connectionAttemptStartTime && diagnosticsAccumulator) {\n diagnosticsAccumulator.recordStreamInit(\n connectionAttemptStartTime,\n !success,\n new Date().getTime() - connectionAttemptStartTime\n );\n }\n connectionAttemptStartTime = null;\n }\n\n return stream;\n}\n","import * as utils from './utils';\nimport * as errors from './errors';\nimport * as messages from './messages';\nimport promiseCoalescer from './promiseCoalescer';\n\nconst jsonContentType = 'application/json';\n\nfunction getResponseError(result) {\n if (result.status === 404) {\n return new errors.LDInvalidEnvironmentIdError(messages.environmentNotFound());\n } else {\n return new errors.LDFlagFetchError(messages.errorFetchingFlags(result.statusText || String(result.status)));\n }\n}\n\nexport default function Requestor(platform, options, environment) {\n const baseUrl = options.baseUrl;\n const useReport = options.useReport;\n const withReasons = options.evaluationReasons;\n const logger = options.logger;\n\n const requestor = {};\n\n const activeRequests = {}; // map of URLs to promiseCoalescers\n\n function fetchJSON(endpoint, body) {\n if (!platform.httpRequest) {\n return new Promise((resolve, reject) => {\n reject(new errors.LDFlagFetchError(messages.httpUnavailable()));\n });\n }\n\n const method = body ? 'REPORT' : 'GET';\n const headers = utils.getLDHeaders(platform, options);\n if (body) {\n headers['Content-Type'] = jsonContentType;\n }\n\n let coalescer = activeRequests[endpoint];\n if (!coalescer) {\n coalescer = promiseCoalescer(() => {\n // this will be called once there are no more active requests for the same endpoint\n delete activeRequests[endpoint];\n });\n activeRequests[endpoint] = coalescer;\n }\n\n const req = platform.httpRequest(method, endpoint, utils.transformHeaders(headers, options), body);\n const p = req.promise.then(\n result => {\n if (result.status === 200) {\n // We're using substring here because using startsWith would require a polyfill in IE.\n if (\n result.header('content-type') &&\n result.header('content-type').substring(0, jsonContentType.length) === jsonContentType\n ) {\n return JSON.parse(result.body);\n } else {\n const message = messages.invalidContentType(result.header('content-type') || '');\n return Promise.reject(new errors.LDFlagFetchError(message));\n }\n } else {\n return Promise.reject(getResponseError(result));\n }\n },\n e => Promise.reject(new errors.LDFlagFetchError(messages.networkError(e)))\n );\n coalescer.addPromise(p, () => {\n // this will be called if another request for the same endpoint supersedes this one\n req.cancel && req.cancel();\n });\n return coalescer.resultPromise;\n }\n\n // Performs a GET request to an arbitrary path under baseUrl. Returns a Promise which will resolve\n // with the parsed JSON response, or will be rejected if the request failed.\n requestor.fetchJSON = function(path) {\n return fetchJSON(baseUrl + path, null);\n };\n\n // Requests the current state of all flags for the given user from LaunchDarkly. Returns a Promise\n // which will resolve with the parsed JSON response, or will be rejected if the request failed.\n requestor.fetchFlagSettings = function(user, hash) {\n let data;\n let endpoint;\n let query = '';\n let body;\n\n if (useReport) {\n endpoint = [baseUrl, '/sdk/evalx/', environment, '/user'].join('');\n body = JSON.stringify(user);\n } else {\n data = utils.base64URLEncode(JSON.stringify(user));\n endpoint = [baseUrl, '/sdk/evalx/', environment, '/users/', data].join('');\n }\n if (hash) {\n query = 'h=' + hash;\n }\n if (withReasons) {\n query = query + (query ? '&' : '') + 'withReasons=true';\n }\n endpoint = endpoint + (query ? '?' : '') + query;\n logger.debug(messages.debugPolling(endpoint));\n\n return fetchJSON(endpoint, body);\n };\n\n return requestor;\n}\n","// This function allows a series of Promises to be coalesced such that only the most recently\n// added one actually matters. For instance, if several HTTP requests are made to the same\n// endpoint and we want to ensure that whoever made each one always gets the latest data, each\n// can be passed to addPromise (on the same coalescer) and each caller can wait on the\n// coalescer.resultPromise; all three will then receive the result (or error) from the *last*\n// request, and the results of the first two will be discarded.\n//\n// The cancelFn callback, if present, will be called whenever an existing promise is being\n// discarded. This can be used for instance to abort an HTTP request that's now obsolete.\n//\n// The finallyFn callback, if present, is called on completion of the whole thing. This is\n// different from calling coalescer.resultPromise.finally() because it is executed before any\n// other handlers. Its purpose is to tell the caller that this coalescer should no longer be used.\n\nexport default function promiseCoalescer(finallyFn) {\n let currentPromise;\n let currentCancelFn;\n let finalResolve;\n let finalReject;\n\n const coalescer = {};\n\n coalescer.addPromise = (p, cancelFn) => {\n currentPromise = p;\n currentCancelFn && currentCancelFn();\n currentCancelFn = cancelFn;\n\n p.then(\n result => {\n if (currentPromise === p) {\n finalResolve(result);\n finallyFn && finallyFn();\n }\n },\n error => {\n if (currentPromise === p) {\n finalReject(error);\n finallyFn && finallyFn();\n }\n }\n );\n };\n\n coalescer.resultPromise = new Promise((resolve, reject) => {\n finalResolve = resolve;\n finalReject = reject;\n });\n\n return coalescer;\n}\n","import uuidv1 from 'uuid/v1';\n\nimport * as errors from './errors';\nimport * as messages from './messages';\nimport * as utils from './utils';\n\n// Transforms the user object if necessary to make sure it has a valid key.\n// 1. If a key is present, but is not a string, change it to a string.\n// 2. If no key is present, and \"anonymous\" is true, use a UUID as a key. This is cached in local\n// storage if possible.\n// 3. If there is no key (or no user object), return an error.\n\nconst ldUserIdKey = 'ld:$anonUserId';\n\nexport default function UserValidator(persistentStorage) {\n function getCachedUserId() {\n return persistentStorage.get(ldUserIdKey);\n }\n\n function setCachedUserId(id) {\n return persistentStorage.set(ldUserIdKey, id);\n }\n\n const ret = {};\n\n // Validates the user, returning a Promise that resolves to the validated user, or rejects if there is an error.\n ret.validateUser = user => {\n if (!user) {\n return Promise.reject(new errors.LDInvalidUserError(messages.userNotSpecified()));\n }\n\n const userOut = utils.clone(user);\n if (userOut.key !== null && userOut.key !== undefined) {\n userOut.key = userOut.key.toString();\n return Promise.resolve(userOut);\n }\n if (userOut.anonymous) {\n return getCachedUserId().then(cachedId => {\n if (cachedId) {\n userOut.key = cachedId;\n return userOut;\n } else {\n const id = uuidv1();\n userOut.key = id;\n return setCachedUserId(id).then(() => userOut);\n }\n });\n } else {\n return Promise.reject(new errors.LDInvalidUserError(messages.invalidUser()));\n }\n };\n\n return ret;\n}\n","const logLevels = ['debug', 'info', 'warn', 'error', 'none'];\n\n/**\n * A simple logger that writes to stderr.\n */\nexport function commonBasicLogger(options, formatFn) {\n if (options && options.destination && typeof options.destination !== 'function') {\n throw new Error('destination for basicLogger was set to a non-function');\n }\n\n function toConsole(methodName) {\n // The global console variable is not guaranteed to be defined at all times in all browsers:\n // https://www.beyondjava.net/console-log-surprises-with-internet-explorer-11-and-edge\n return function(line) {\n if (console && console[methodName]) {\n console[methodName].call(console, line);\n }\n };\n }\n const destinations =\n options && options.destination\n ? [options.destination, options.destination, options.destination, options.destination]\n : [toConsole('log'), toConsole('info'), toConsole('warn'), toConsole('error')];\n const prependLevelToMessage = !!(options && options.destination); // if we're writing to console.warn, etc. we don't need the prefix\n const prefix =\n !options || options.prefix === undefined || options.prefix === null ? '[LaunchDarkly] ' : options.prefix;\n\n let minLevel = 1; // default is 'info'\n if (options && options.level) {\n for (let i = 0; i < logLevels.length; i++) {\n if (logLevels[i] === options.level) {\n minLevel = i;\n }\n }\n }\n\n function write(levelIndex, levelName, args) {\n if (args.length < 1) {\n return;\n }\n let line;\n const fullPrefix = prependLevelToMessage ? levelName + ': ' + prefix : prefix;\n if (args.length === 1 || !formatFn) {\n line = fullPrefix + args[0];\n } else {\n const tempArgs = [...args];\n tempArgs[0] = fullPrefix + tempArgs[0];\n line = formatFn(...tempArgs);\n }\n try {\n destinations[levelIndex](line);\n } catch (err) {\n console &&\n console.log &&\n console.log(\"[LaunchDarkly] Configured logger's \" + levelName + ' method threw an exception: ' + err);\n }\n }\n\n const logger = {};\n for (let i = 0; i < logLevels.length; i++) {\n const levelName = logLevels[i];\n if (levelName !== 'none') {\n if (i < minLevel) {\n logger[levelName] = () => {};\n } else {\n const levelIndex = i;\n logger[levelName] = function() {\n // can't use arrow function with \"arguments\"\n write(levelIndex, levelName, arguments);\n };\n }\n }\n }\n\n return logger;\n}\n\nexport function validateLogger(logger) {\n logLevels.forEach(level => {\n if (level !== 'none' && (!logger[level] || typeof logger[level] !== 'function')) {\n throw new Error('Provided logger instance must support logger.' + level + '(...) method');\n // Note that the SDK normally does not throw exceptions to the application, but that rule\n // does not apply to LDClient.init() which will throw an exception if the parameters are so\n // invalid that we cannot proceed with creating the client. An invalid logger meets those\n // criteria since the SDK calls the logger during nearly all of its operations.\n }\n });\n}\n\n// Deprecated equivalent to commonBasicLogger\nexport function createConsoleLogger(level, maybePrefix) {\n return commonBasicLogger({ level, prefix: maybePrefix });\n}\n","import * as errors from './errors';\nimport { validateLogger } from './loggers';\nimport * as messages from './messages';\nimport * as utils from './utils';\n\n// baseOptionDefs should contain an entry for each supported configuration option in the common package.\n// Each entry can have three properties:\n// - \"default\": the default value if any\n// - \"type\": a type constraint used if the type can't be inferred from the default value). The allowable\n// values are \"boolean\", \"string\", \"number\", \"array\", \"object\", \"function\", or several of these OR'd\n// together with \"|\" (\"function|object\").\n// - \"minimum\": minimum value if any for numeric properties\n//\n// The extraOptionDefs parameter to validate() uses the same format.\nexport const baseOptionDefs = {\n baseUrl: { default: 'https://app.launchdarkly.com' },\n streamUrl: { default: 'https://clientstream.launchdarkly.com' },\n eventsUrl: { default: 'https://events.launchdarkly.com' },\n sendEvents: { default: true },\n streaming: { type: 'boolean' }, // default for this is undefined, which is different from false\n sendLDHeaders: { default: true },\n requestHeaderTransform: { type: 'function' },\n inlineUsersInEvents: { default: false },\n allowFrequentDuplicateEvents: { default: false },\n sendEventsOnlyForVariation: { default: false },\n useReport: { default: false },\n evaluationReasons: { default: false },\n eventCapacity: { default: 100, minimum: 1 },\n flushInterval: { default: 2000, minimum: 2000 },\n samplingInterval: { default: 0, minimum: 0 },\n streamReconnectDelay: { default: 1000, minimum: 0 },\n allAttributesPrivate: { default: false },\n privateAttributeNames: { default: [] },\n bootstrap: { type: 'string|object' },\n diagnosticRecordingInterval: { default: 900000, minimum: 2000 },\n diagnosticOptOut: { default: false },\n wrapperName: { type: 'string' },\n wrapperVersion: { type: 'string' },\n stateProvider: { type: 'object' }, // not a public option, used internally\n autoAliasingOptOut: { default: false },\n};\n\nexport function validate(options, emitter, extraOptionDefs, logger) {\n const optionDefs = utils.extend({ logger: { default: logger } }, baseOptionDefs, extraOptionDefs);\n\n const deprecatedOptions = {\n // eslint-disable-next-line camelcase\n all_attributes_private: 'allAttributesPrivate',\n // eslint-disable-next-line camelcase\n private_attribute_names: 'privateAttributeNames',\n samplingInterval: null,\n };\n\n function checkDeprecatedOptions(config) {\n const opts = config;\n Object.keys(deprecatedOptions).forEach(oldName => {\n if (opts[oldName] !== undefined) {\n const newName = deprecatedOptions[oldName];\n logger && logger.warn(messages.deprecated(oldName, newName));\n if (newName) {\n if (opts[newName] === undefined) {\n opts[newName] = opts[oldName];\n }\n delete opts[oldName];\n }\n }\n });\n }\n\n function applyDefaults(config) {\n // This works differently from utils.extend() in that it *will not* override a default value\n // if the provided value is explicitly set to null. This provides backward compatibility\n // since in the past we only used the provided values if they were truthy.\n const ret = utils.extend({}, config);\n Object.keys(optionDefs).forEach(name => {\n if (ret[name] === undefined || ret[name] === null) {\n ret[name] = optionDefs[name] && optionDefs[name].default;\n }\n });\n return ret;\n }\n\n function validateTypesAndNames(config) {\n const ret = utils.extend({}, config);\n const typeDescForValue = value => {\n if (value === null) {\n return 'any';\n }\n if (value === undefined) {\n return undefined;\n }\n if (Array.isArray(value)) {\n return 'array';\n }\n const t = typeof value;\n if (t === 'boolean' || t === 'string' || t === 'number' || t === 'function') {\n return t;\n }\n return 'object';\n };\n Object.keys(config).forEach(name => {\n const value = config[name];\n if (value !== null && value !== undefined) {\n const optionDef = optionDefs[name];\n if (optionDef === undefined) {\n reportArgumentError(messages.unknownOption(name));\n } else {\n const expectedType = optionDef.type || typeDescForValue(optionDef.default);\n if (expectedType !== 'any') {\n const allowedTypes = expectedType.split('|');\n const actualType = typeDescForValue(value);\n if (allowedTypes.indexOf(actualType) < 0) {\n if (expectedType === 'boolean') {\n ret[name] = !!value;\n reportArgumentError(messages.wrongOptionTypeBoolean(name, actualType));\n } else {\n reportArgumentError(messages.wrongOptionType(name, expectedType, actualType));\n ret[name] = optionDef.default;\n }\n } else {\n if (actualType === 'number' && optionDef.minimum !== undefined && value < optionDef.minimum) {\n reportArgumentError(messages.optionBelowMinimum(name, value, optionDef.minimum));\n ret[name] = optionDef.minimum;\n }\n }\n }\n }\n }\n });\n return ret;\n }\n\n function reportArgumentError(message) {\n utils.onNextTick(() => {\n emitter && emitter.maybeReportError(new errors.LDInvalidArgumentError(message));\n });\n }\n\n let config = utils.extend({}, options || {});\n\n checkDeprecatedOptions(config);\n\n config = applyDefaults(config);\n config = validateTypesAndNames(config);\n validateLogger(config.logger);\n\n return config;\n}\n","const uuidv1 = require('uuid/v1');\n// Note that in the diagnostic events spec, these IDs are to be generated with UUID v4. However,\n// in JS we were already using v1 for unique user keys, so to avoid bringing in two packages we\n// will use v1 here as well.\n\nconst { baseOptionDefs } = require('./configuration');\nconst messages = require('./messages');\n\nfunction DiagnosticId(sdkKey) {\n const ret = {\n diagnosticId: uuidv1(),\n };\n if (sdkKey) {\n ret.sdkKeySuffix = sdkKey.length > 6 ? sdkKey.substring(sdkKey.length - 6) : sdkKey;\n }\n return ret;\n}\n\n// A stateful object holding statistics that will go into diagnostic events.\n\nfunction DiagnosticsAccumulator(startTime) {\n let dataSinceDate, droppedEvents, eventsInLastBatch, streamInits;\n\n function reset(time) {\n dataSinceDate = time;\n droppedEvents = 0;\n eventsInLastBatch = 0;\n streamInits = [];\n }\n\n reset(startTime);\n\n return {\n getProps: () => ({\n dataSinceDate,\n droppedEvents,\n eventsInLastBatch,\n streamInits,\n // omit deduplicatedUsers for the JS SDKs because they don't deduplicate users\n }),\n setProps: props => {\n dataSinceDate = props.dataSinceDate;\n droppedEvents = props.droppedEvents || 0;\n eventsInLastBatch = props.eventsInLastBatch || 0;\n streamInits = props.streamInits || [];\n },\n incrementDroppedEvents: () => {\n droppedEvents++;\n },\n setEventsInLastBatch: n => {\n eventsInLastBatch = n;\n },\n recordStreamInit: (timestamp, failed, durationMillis) => {\n const info = { timestamp, failed, durationMillis };\n streamInits.push(info);\n },\n reset,\n };\n}\n\n// An object that maintains information that will go into diagnostic events, and knows how to format\n// those events. It is instantiated by the SDK client, and shared with the event processor.\n//\n// The JS-based SDKs have two modes for diagnostic events. By default, the behavior is basically the\n// same as the server-side SDKs: a \"diagnostic-init\" event is sent on startup, and then \"diagnostic\"\n// events with operating statistics are sent periodically. However, in a browser environment this is\n// undesirable because the page may be reloaded frequently. In that case, setting the property\n// \"platform.diagnosticUseCombinedEvent\" to true enables an alternate mode in which a combination of\n// both kinds of event is sent at intervals, relative to the last time this was done (if any) which\n// is cached in local storage.\n\nfunction DiagnosticsManager(\n platform,\n persistentStorage,\n accumulator,\n eventSender,\n environmentId,\n config,\n diagnosticId\n) {\n const combinedMode = !!platform.diagnosticUseCombinedEvent;\n const localStorageKey = 'ld:' + environmentId + ':$diagnostics';\n const diagnosticEventsUrl = config.eventsUrl + '/events/diagnostic/' + environmentId;\n const periodicInterval = config.diagnosticRecordingInterval;\n const acc = accumulator;\n const initialEventSamplingInterval = 4; // used only in combined mode - see start()\n let streamingEnabled = !!config.streaming;\n let eventSentTime;\n let periodicTimer;\n const manager = {};\n\n function makeInitProperties() {\n return {\n sdk: makeSdkData(),\n configuration: makeConfigData(),\n platform: platform.diagnosticPlatformData,\n };\n }\n\n // Send a diagnostic event and do not wait for completion.\n function sendDiagnosticEvent(event) {\n config.logger && config.logger.debug(messages.debugPostingDiagnosticEvent(event));\n eventSender\n .sendEvents(event, diagnosticEventsUrl, true)\n .then(() => undefined)\n .catch(() => undefined);\n }\n\n function loadProperties(callback) {\n if (!persistentStorage.isEnabled()) {\n return callback(false); // false indicates that local storage is not available\n }\n persistentStorage\n .get(localStorageKey)\n .then(data => {\n if (data) {\n try {\n const props = JSON.parse(data);\n acc.setProps(props);\n eventSentTime = props.dataSinceDate;\n } catch (e) {\n // disregard malformed cached data\n }\n }\n callback(true);\n })\n .catch(() => {\n callback(false);\n });\n }\n\n function saveProperties() {\n if (persistentStorage.isEnabled()) {\n const props = { ...acc.getProps() };\n persistentStorage.set(localStorageKey, JSON.stringify(props));\n }\n }\n\n // Creates the initial event that is sent by the event processor when the SDK starts up. This will not\n // be repeated during the lifetime of the SDK client. In combined mode, we don't send this.\n function createInitEvent() {\n return {\n kind: 'diagnostic-init',\n id: diagnosticId,\n creationDate: acc.getProps().dataSinceDate,\n ...makeInitProperties(),\n };\n }\n\n // Creates a periodic event containing time-dependent stats, and resets the state of the manager with\n // regard to those stats. In combined mode (browser SDK) this also contains the configuration data.\n function createPeriodicEventAndReset() {\n const currentTime = new Date().getTime();\n let ret = {\n kind: combinedMode ? 'diagnostic-combined' : 'diagnostic',\n id: diagnosticId,\n creationDate: currentTime,\n ...acc.getProps(),\n };\n if (combinedMode) {\n ret = { ...ret, ...makeInitProperties() };\n }\n acc.reset(currentTime);\n return ret;\n }\n\n function sendPeriodicEvent() {\n sendDiagnosticEvent(createPeriodicEventAndReset());\n periodicTimer = setTimeout(sendPeriodicEvent, periodicInterval);\n eventSentTime = new Date().getTime();\n if (combinedMode) {\n saveProperties();\n }\n }\n\n function makeSdkData() {\n const sdkData = { ...platform.diagnosticSdkData };\n if (config.wrapperName) {\n sdkData.wrapperName = config.wrapperName;\n }\n if (config.wrapperVersion) {\n sdkData.wrapperVersion = config.wrapperVersion;\n }\n return sdkData;\n }\n\n function makeConfigData() {\n const configData = {\n customBaseURI: config.baseUrl !== baseOptionDefs.baseUrl.default,\n customStreamURI: config.streamUrl !== baseOptionDefs.streamUrl.default,\n customEventsURI: config.eventsUrl !== baseOptionDefs.eventsUrl.default,\n eventsCapacity: config.eventCapacity,\n eventsFlushIntervalMillis: config.flushInterval,\n reconnectTimeMillis: config.streamReconnectDelay,\n streamingDisabled: !streamingEnabled,\n allAttributesPrivate: !!config.allAttributesPrivate,\n inlineUsersInEvents: !!config.inlineUsersInEvents,\n diagnosticRecordingIntervalMillis: config.diagnosticRecordingInterval,\n // The following extra properties are only provided by client-side JS SDKs:\n usingSecureMode: !!config.hash,\n bootstrapMode: !!config.bootstrap,\n fetchGoalsDisabled: !config.fetchGoals,\n allowFrequentDuplicateEvents: !!config.allowFrequentDuplicateEvents,\n sendEventsOnlyForVariation: !!config.sendEventsOnlyForVariation,\n autoAliasingOptOut: !!config.autoAliasingOptOut,\n };\n // Client-side JS SDKs do not have the following properties which other SDKs have:\n // connectTimeoutMillis\n // pollingIntervalMillis\n // samplingInterval\n // socketTimeoutMillis\n // startWaitMillis\n // userKeysCapacity\n // userKeysFlushIntervalMillis\n // usingProxy\n // usingProxyAuthenticator\n // usingRelayDaemon\n\n return configData;\n }\n\n // Called when the SDK is starting up. Either send an init event immediately, or, in the alternate\n // mode, check for cached local storage properties and send an event only if we haven't done so\n // recently.\n manager.start = () => {\n if (combinedMode) {\n loadProperties(localStorageAvailable => {\n if (localStorageAvailable) {\n const nextEventTime = (eventSentTime || 0) + periodicInterval;\n const timeNow = new Date().getTime();\n if (timeNow >= nextEventTime) {\n sendPeriodicEvent();\n } else {\n periodicTimer = setTimeout(sendPeriodicEvent, nextEventTime - timeNow);\n }\n } else {\n // We don't have the ability to cache anything in local storage, so we don't know if we\n // recently sent an event before this page load, but we would still prefer not to send one\n // on *every* page load. So, as a rough heuristic, we'll decide semi-randomly.\n if (Math.floor(Math.random() * initialEventSamplingInterval) === 0) {\n sendPeriodicEvent();\n } else {\n periodicTimer = setTimeout(sendPeriodicEvent, periodicInterval);\n }\n }\n });\n } else {\n sendDiagnosticEvent(createInitEvent());\n periodicTimer = setTimeout(sendPeriodicEvent, periodicInterval);\n }\n };\n\n manager.stop = () => {\n periodicTimer && clearTimeout(periodicTimer);\n };\n\n // Called when streaming mode is turned on or off dynamically.\n manager.setStreaming = enabled => {\n streamingEnabled = enabled;\n };\n\n return manager;\n}\n\nmodule.exports = {\n DiagnosticId,\n DiagnosticsAccumulator,\n DiagnosticsManager,\n};\n","import EventProcessor from './EventProcessor';\nimport EventEmitter from './EventEmitter';\nimport EventSender from './EventSender';\nimport InitializationStateTracker from './InitializationState';\nimport PersistentFlagStore from './PersistentFlagStore';\nimport PersistentStorage from './PersistentStorage';\nimport Stream from './Stream';\nimport Requestor from './Requestor';\nimport Identity from './Identity';\nimport UserValidator from './UserValidator';\nimport * as configuration from './configuration';\nimport * as diagnostics from './diagnosticEvents';\nimport { commonBasicLogger, createConsoleLogger } from './loggers';\nimport * as utils from './utils';\nimport * as errors from './errors';\nimport * as messages from './messages';\n\nconst changeEvent = 'change';\nconst internalChangeEvent = 'internal-change';\n\n// This is called by the per-platform initialize functions to create the base client object that we\n// may also extend with additional behavior. It returns an object with these properties:\n// client: the actual client object\n// options: the configuration (after any appropriate defaults have been applied)\n// If we need to give the platform-specific clients access to any internals here, we should add those\n// as properties of the return object, not public properties of the client.\n//\n// For definitions of the API in the platform object, see stubPlatform.js in the test code.\n\nexport function initialize(env, user, specifiedOptions, platform, extraOptionDefs) {\n const logger = createLogger();\n const emitter = EventEmitter(logger);\n const initializationStateTracker = InitializationStateTracker(emitter);\n const options = configuration.validate(specifiedOptions, emitter, extraOptionDefs, logger);\n const sendEvents = options.sendEvents;\n let environment = env;\n let hash = options.hash;\n\n const persistentStorage = PersistentStorage(platform.localStorage, logger);\n\n const eventSender = EventSender(platform, environment, options);\n\n const diagnosticsEnabled = options.sendEvents && !options.diagnosticOptOut;\n const diagnosticId = diagnosticsEnabled ? diagnostics.DiagnosticId(environment) : null;\n const diagnosticsAccumulator = diagnosticsEnabled ? diagnostics.DiagnosticsAccumulator(new Date().getTime()) : null;\n const diagnosticsManager = diagnosticsEnabled\n ? diagnostics.DiagnosticsManager(\n platform,\n persistentStorage,\n diagnosticsAccumulator,\n eventSender,\n environment,\n options,\n diagnosticId\n )\n : null;\n\n const stream = Stream(platform, options, environment, diagnosticsAccumulator);\n\n const events =\n options.eventProcessor ||\n EventProcessor(platform, options, environment, diagnosticsAccumulator, emitter, eventSender);\n\n const requestor = Requestor(platform, options, environment);\n\n const seenRequests = {};\n let flags = {};\n let useLocalStorage;\n let streamActive;\n let streamForcedState = options.streaming;\n let subscribedToChangeEvents;\n let inited = false;\n let closed = false;\n let firstEvent = true;\n\n // The \"stateProvider\" object is used in the Electron SDK, to allow one client instance to take partial\n // control of another. If present, it has the following contract:\n // - getInitialState() returns the initial client state if it is already available. The state is an\n // object whose properties are \"environment\", \"user\", and \"flags\".\n // - on(\"init\", listener) triggers an event when the initial client state becomes available, passing\n // the state object to the listener.\n // - on(\"update\", listener) triggers an event when flag values change and/or the current user changes.\n // The parameter is an object that *may* contain \"user\" and/or \"flags\".\n // - enqueueEvent(event) accepts an analytics event object and returns true if the stateProvider will\n // be responsible for delivering it, or false if we still should deliver it ourselves.\n const stateProvider = options.stateProvider;\n\n const ident = Identity(null, onIdentifyChange);\n const userValidator = UserValidator(persistentStorage);\n const persistentFlagStore = persistentStorage.isEnabled()\n ? new PersistentFlagStore(persistentStorage, environment, hash, ident, logger)\n : null;\n\n function createLogger() {\n if (specifiedOptions && specifiedOptions.logger) {\n return specifiedOptions.logger;\n }\n return (extraOptionDefs && extraOptionDefs.logger && extraOptionDefs.logger.default) || createConsoleLogger('warn');\n }\n\n function readFlagsFromBootstrap(data) {\n // If the bootstrap data came from an older server-side SDK, we'll have just a map of keys to values.\n // Newer SDKs that have an allFlagsState method will provide an extra \"$flagsState\" key that contains\n // the rest of the metadata we want. We do it this way for backward compatibility with older JS SDKs.\n const keys = Object.keys(data);\n const metadataKey = '$flagsState';\n const validKey = '$valid';\n const metadata = data[metadataKey];\n if (!metadata && keys.length) {\n logger.warn(messages.bootstrapOldFormat());\n }\n if (data[validKey] === false) {\n logger.warn(messages.bootstrapInvalid());\n }\n const ret = {};\n keys.forEach(key => {\n if (key !== metadataKey && key !== validKey) {\n let flag = { value: data[key] };\n if (metadata && metadata[key]) {\n flag = utils.extend(flag, metadata[key]);\n } else {\n flag.version = 0;\n }\n ret[key] = flag;\n }\n });\n return ret;\n }\n\n function shouldEnqueueEvent() {\n return sendEvents && !closed && !platform.isDoNotTrack();\n }\n\n function enqueueEvent(event) {\n if (!environment) {\n // We're in paired mode and haven't been initialized with an environment or user yet\n return;\n }\n if (stateProvider && stateProvider.enqueueEvent && stateProvider.enqueueEvent(event)) {\n return; // it'll be handled elsewhere\n }\n if (event.kind !== 'alias') {\n if (!event.user) {\n if (firstEvent) {\n logger.warn(messages.eventWithoutUser());\n firstEvent = false;\n }\n return;\n }\n firstEvent = false;\n }\n if (shouldEnqueueEvent()) {\n logger.debug(messages.debugEnqueueingEvent(event.kind));\n events.enqueue(event);\n }\n }\n\n function onIdentifyChange(user, previousUser) {\n sendIdentifyEvent(user);\n if (!options.autoAliasingOptOut && previousUser && previousUser.anonymous && user && !user.anonymous) {\n alias(user, previousUser);\n }\n }\n\n function sendIdentifyEvent(user) {\n if (stateProvider) {\n // In paired mode, the other client is responsible for sending identify events\n return;\n }\n if (user) {\n enqueueEvent({\n kind: 'identify',\n key: user.key,\n user: user,\n creationDate: new Date().getTime(),\n });\n }\n }\n\n function sendFlagEvent(key, detail, defaultValue, includeReason) {\n const user = ident.getUser();\n const now = new Date();\n const value = detail ? detail.value : null;\n if (!options.allowFrequentDuplicateEvents) {\n const cacheKey = JSON.stringify(value) + (user && user.key ? user.key : '') + key; // see below\n const cached = seenRequests[cacheKey];\n // cache TTL is five minutes\n if (cached && now - cached < 300000) {\n return;\n }\n seenRequests[cacheKey] = now;\n }\n\n const event = {\n kind: 'feature',\n key: key,\n user: user,\n value: value,\n variation: detail ? detail.variationIndex : null,\n default: defaultValue,\n creationDate: now.getTime(),\n };\n if (user && user.anonymous) {\n event.contextKind = userContextKind(user);\n }\n const flag = flags[key];\n if (flag) {\n event.version = flag.flagVersion ? flag.flagVersion : flag.version;\n event.trackEvents = flag.trackEvents;\n event.debugEventsUntilDate = flag.debugEventsUntilDate;\n }\n if ((includeReason || (flag && flag.trackReason)) && detail) {\n event.reason = detail.reason;\n }\n\n enqueueEvent(event);\n }\n\n function identify(user, newHash, onDone) {\n if (closed) {\n return utils.wrapPromiseCallback(Promise.resolve({}), onDone);\n }\n if (stateProvider) {\n // We're being controlled by another client instance, so only that instance is allowed to change the user\n logger.warn(messages.identifyDisabled());\n return utils.wrapPromiseCallback(Promise.resolve(utils.transformVersionedValuesToValues(flags)), onDone);\n }\n const clearFirst = useLocalStorage && persistentFlagStore ? persistentFlagStore.clearFlags() : Promise.resolve();\n return utils.wrapPromiseCallback(\n clearFirst\n .then(() => userValidator.validateUser(user))\n .then(realUser =>\n requestor\n .fetchFlagSettings(realUser, newHash)\n // the following then() is nested within this one so we can use realUser from the previous closure\n .then(requestedFlags => {\n const flagValueMap = utils.transformVersionedValuesToValues(requestedFlags);\n ident.setUser(realUser);\n hash = newHash;\n if (requestedFlags) {\n return replaceAllFlags(requestedFlags).then(() => flagValueMap);\n } else {\n return flagValueMap;\n }\n })\n )\n .then(flagValueMap => {\n if (streamActive) {\n connectStream();\n }\n return flagValueMap;\n })\n .catch(err => {\n emitter.maybeReportError(err);\n return Promise.reject(err);\n }),\n onDone\n );\n }\n\n function getUser() {\n return ident.getUser();\n }\n\n function flush(onDone) {\n return utils.wrapPromiseCallback(sendEvents ? events.flush() : Promise.resolve(), onDone);\n }\n\n function variation(key, defaultValue) {\n return variationDetailInternal(key, defaultValue, true, false).value;\n }\n\n function variationDetail(key, defaultValue) {\n return variationDetailInternal(key, defaultValue, true, true);\n }\n\n function variationDetailInternal(key, defaultValue, sendEvent, includeReasonInEvent) {\n let detail;\n\n if (flags && utils.objectHasOwnProperty(flags, key) && flags[key] && !flags[key].deleted) {\n const flag = flags[key];\n detail = getFlagDetail(flag);\n if (flag.value === null || flag.value === undefined) {\n detail.value = defaultValue;\n }\n } else {\n detail = { value: defaultValue, variationIndex: null, reason: { kind: 'ERROR', errorKind: 'FLAG_NOT_FOUND' } };\n }\n\n if (sendEvent) {\n sendFlagEvent(key, detail, defaultValue, includeReasonInEvent);\n }\n\n return detail;\n }\n\n function getFlagDetail(flag) {\n return {\n value: flag.value,\n variationIndex: flag.variation === undefined ? null : flag.variation,\n reason: flag.reason || null,\n };\n // Note, the logic above ensures that variationIndex and reason will always be null rather than\n // undefined if we don't have values for them. That's just to avoid subtle errors that depend on\n // whether an object was JSON-encoded with null properties omitted or not.\n }\n\n function allFlags() {\n const results = {};\n\n if (!flags) {\n return results;\n }\n\n for (const key in flags) {\n if (utils.objectHasOwnProperty(flags, key)) {\n results[key] = variationDetailInternal(key, null, !options.sendEventsOnlyForVariation).value;\n }\n }\n\n return results;\n }\n\n function userContextKind(user) {\n return user.anonymous ? 'anonymousUser' : 'user';\n }\n\n function alias(user, previousUser) {\n if (stateProvider) {\n // In paired mode, the other client is responsible for sending alias events\n return;\n }\n\n if (!user || !previousUser) {\n return;\n }\n\n enqueueEvent({\n kind: 'alias',\n key: user.key,\n contextKind: userContextKind(user),\n previousKey: previousUser.key,\n previousContextKind: userContextKind(previousUser),\n creationDate: new Date().getTime(),\n });\n }\n\n function track(key, data, metricValue) {\n if (typeof key !== 'string') {\n emitter.maybeReportError(new errors.LDInvalidEventKeyError(messages.unknownCustomEventKey(key)));\n return;\n }\n\n // The following logic was used only for the JS browser SDK (js-client-sdk) and\n // is no longer needed as of version 2.9.13 of that SDK. The other client-side\n // JS-based SDKs did not define customEventFilter, and now none of them do. We\n // can remove this in the next major version of the common code, when it's OK to\n // make breaking changes to our internal API contracts.\n if (platform.customEventFilter && !platform.customEventFilter(key)) {\n logger.warn(messages.unknownCustomEventKey(key));\n }\n\n const user = ident.getUser();\n const e = {\n kind: 'custom',\n key: key,\n user: user,\n url: platform.getCurrentUrl(),\n creationDate: new Date().getTime(),\n };\n if (user && user.anonymous) {\n e.contextKind = userContextKind(user);\n }\n // Note, check specifically for null/undefined because it is legal to set these fields to a falsey value.\n if (data !== null && data !== undefined) {\n e.data = data;\n }\n if (metricValue !== null && metricValue !== undefined) {\n e.metricValue = metricValue;\n }\n enqueueEvent(e);\n }\n\n function connectStream() {\n streamActive = true;\n if (!ident.getUser()) {\n return;\n }\n stream.connect(ident.getUser(), hash, {\n ping: function() {\n logger.debug(messages.debugStreamPing());\n const userAtTimeOfPingEvent = ident.getUser();\n requestor\n .fetchFlagSettings(userAtTimeOfPingEvent, hash)\n .then(requestedFlags => {\n // Check whether the current user is still the same - we don't want to overwrite the flags if\n // the application has called identify() while this request was in progress\n if (utils.deepEquals(userAtTimeOfPingEvent, ident.getUser())) {\n replaceAllFlags(requestedFlags || {});\n }\n })\n .catch(err => {\n emitter.maybeReportError(new errors.LDFlagFetchError(messages.errorFetchingFlags(err)));\n });\n },\n put: function(e) {\n const data = JSON.parse(e.data);\n logger.debug(messages.debugStreamPut());\n replaceAllFlags(data); // don't wait for this Promise to be resolved\n },\n patch: function(e) {\n const data = JSON.parse(e.data);\n // If both the flag and the patch have a version property, then the patch version must be\n // greater than the flag version for us to accept the patch. If either one has no version\n // then the patch always succeeds.\n const oldFlag = flags[data.key];\n if (!oldFlag || !oldFlag.version || !data.version || oldFlag.version < data.version) {\n logger.debug(messages.debugStreamPatch(data.key));\n const mods = {};\n const newFlag = utils.extend({}, data);\n delete newFlag['key'];\n flags[data.key] = newFlag;\n const newDetail = getFlagDetail(newFlag);\n if (oldFlag) {\n mods[data.key] = { previous: oldFlag.value, current: newDetail };\n } else {\n mods[data.key] = { current: newDetail };\n }\n handleFlagChanges(mods); // don't wait for this Promise to be resolved\n } else {\n logger.debug(messages.debugStreamPatchIgnored(data.key));\n }\n },\n delete: function(e) {\n const data = JSON.parse(e.data);\n if (!flags[data.key] || flags[data.key].version < data.version) {\n logger.debug(messages.debugStreamDelete(data.key));\n const mods = {};\n if (flags[data.key] && !flags[data.key].deleted) {\n mods[data.key] = { previous: flags[data.key].value };\n }\n flags[data.key] = { version: data.version, deleted: true };\n handleFlagChanges(mods); // don't wait for this Promise to be resolved\n } else {\n logger.debug(messages.debugStreamDeleteIgnored(data.key));\n }\n },\n });\n }\n\n function disconnectStream() {\n if (streamActive) {\n stream.disconnect();\n streamActive = false;\n }\n }\n\n // Returns a Promise which will be resolved when we have completely updated the internal flags state,\n // dispatched all change events, and updated local storage if appropriate. This Promise is guaranteed\n // never to have an unhandled rejection.\n function replaceAllFlags(newFlags) {\n const changes = {};\n\n if (!newFlags) {\n return Promise.resolve();\n }\n\n for (const key in flags) {\n if (utils.objectHasOwnProperty(flags, key) && flags[key]) {\n if (newFlags[key] && !utils.deepEquals(newFlags[key].value, flags[key].value)) {\n changes[key] = { previous: flags[key].value, current: getFlagDetail(newFlags[key]) };\n } else if (!newFlags[key] || newFlags[key].deleted) {\n changes[key] = { previous: flags[key].value };\n }\n }\n }\n for (const key in newFlags) {\n if (utils.objectHasOwnProperty(newFlags, key) && newFlags[key] && (!flags[key] || flags[key].deleted)) {\n changes[key] = { current: getFlagDetail(newFlags[key]) };\n }\n }\n\n flags = { ...newFlags };\n return handleFlagChanges(changes).catch(() => {}); // swallow any exceptions from this Promise\n }\n\n // Returns a Promise which will be resolved when we have dispatched all change events and updated\n // local storage if appropriate.\n function handleFlagChanges(changes) {\n const keys = Object.keys(changes);\n\n if (keys.length > 0) {\n const changeEventParams = {};\n keys.forEach(key => {\n const current = changes[key].current;\n const value = current ? current.value : undefined;\n const previous = changes[key].previous;\n emitter.emit(changeEvent + ':' + key, value, previous);\n changeEventParams[key] = current ? { current: value, previous: previous } : { previous: previous };\n });\n\n emitter.emit(changeEvent, changeEventParams);\n emitter.emit(internalChangeEvent, flags);\n\n // By default, we send feature evaluation events whenever we have received new flag values -\n // the client has in effect evaluated these flags just by receiving them. This can be suppressed\n // by setting \"sendEventsOnlyForVariation\". Also, if we have a stateProvider, we don't send these\n // events because we assume they have already been sent by the other client that gave us the flags\n // (when it received them in the first place).\n if (!options.sendEventsOnlyForVariation && !stateProvider) {\n keys.forEach(key => {\n sendFlagEvent(key, changes[key].current);\n });\n }\n }\n\n if (useLocalStorage && persistentFlagStore) {\n return persistentFlagStore.saveFlags(flags);\n } else {\n return Promise.resolve();\n }\n }\n\n function on(event, handler, context) {\n if (isChangeEventKey(event)) {\n subscribedToChangeEvents = true;\n if (inited) {\n updateStreamingState();\n }\n emitter.on(event, handler, context);\n } else {\n emitter.on(...arguments);\n }\n }\n\n function off(event) {\n emitter.off(...arguments);\n if (isChangeEventKey(event)) {\n let haveListeners = false;\n emitter.getEvents().forEach(key => {\n if (isChangeEventKey(key) && emitter.getEventListenerCount(key) > 0) {\n haveListeners = true;\n }\n });\n if (!haveListeners) {\n subscribedToChangeEvents = false;\n if (streamActive && streamForcedState === undefined) {\n disconnectStream();\n }\n }\n }\n }\n\n function setStreaming(state) {\n const newState = state === null ? undefined : state;\n if (newState !== streamForcedState) {\n streamForcedState = newState;\n updateStreamingState();\n }\n }\n\n function updateStreamingState() {\n const shouldBeStreaming = streamForcedState || (subscribedToChangeEvents && streamForcedState === undefined);\n if (shouldBeStreaming && !streamActive) {\n connectStream();\n } else if (!shouldBeStreaming && streamActive) {\n disconnectStream();\n }\n if (diagnosticsManager) {\n diagnosticsManager.setStreaming(shouldBeStreaming);\n }\n }\n\n function isChangeEventKey(event) {\n return event === changeEvent || event.substr(0, changeEvent.length + 1) === changeEvent + ':';\n }\n\n if (typeof options.bootstrap === 'string' && options.bootstrap.toUpperCase() === 'LOCALSTORAGE') {\n if (persistentFlagStore) {\n useLocalStorage = true;\n } else {\n logger.warn(messages.localStorageUnavailable());\n }\n }\n\n if (typeof options.bootstrap === 'object') {\n // Set the flags as soon as possible before we get into any async code, so application code can read\n // them even if the ready event has not yet fired.\n flags = readFlagsFromBootstrap(options.bootstrap);\n }\n\n if (stateProvider) {\n // The stateProvider option is used in the Electron SDK, to allow a client instance in the main process\n // to control another client instance (i.e. this one) in the renderer process. We can't predict which\n // one will start up first, so the initial state may already be available for us or we may have to wait\n // to receive it.\n const state = stateProvider.getInitialState();\n if (state) {\n initFromStateProvider(state);\n } else {\n stateProvider.on('init', initFromStateProvider);\n }\n stateProvider.on('update', updateFromStateProvider);\n } else {\n finishInit().catch(signalFailedInit);\n }\n\n function finishInit() {\n if (!env) {\n return Promise.reject(new errors.LDInvalidEnvironmentIdError(messages.environmentNotSpecified()));\n }\n return userValidator.validateUser(user).then(realUser => {\n ident.setUser(realUser);\n if (typeof options.bootstrap === 'object') {\n // flags have already been set earlier\n return signalSuccessfulInit();\n } else if (useLocalStorage) {\n return finishInitWithLocalStorage();\n } else {\n return finishInitWithPolling();\n }\n });\n }\n\n function finishInitWithLocalStorage() {\n return persistentFlagStore.loadFlags().then(storedFlags => {\n if (storedFlags === null || storedFlags === undefined) {\n flags = {};\n return requestor\n .fetchFlagSettings(ident.getUser(), hash)\n .then(requestedFlags => replaceAllFlags(requestedFlags || {}))\n .then(signalSuccessfulInit)\n .catch(err => {\n const initErr = new errors.LDFlagFetchError(messages.errorFetchingFlags(err));\n signalFailedInit(initErr);\n });\n } else {\n // We're reading the flags from local storage. Signal that we're ready,\n // then update localStorage for the next page load. We won't signal changes or update\n // the in-memory flags unless you subscribe for changes\n flags = storedFlags;\n utils.onNextTick(signalSuccessfulInit);\n\n return requestor\n .fetchFlagSettings(ident.getUser(), hash)\n .then(requestedFlags => replaceAllFlags(requestedFlags))\n .catch(err => emitter.maybeReportError(err));\n }\n });\n }\n\n function finishInitWithPolling() {\n return requestor\n .fetchFlagSettings(ident.getUser(), hash)\n .then(requestedFlags => {\n flags = requestedFlags || {};\n // Note, we don't need to call updateSettings here because local storage and change events are not relevant\n signalSuccessfulInit();\n })\n .catch(err => {\n flags = {};\n signalFailedInit(err);\n });\n }\n\n function initFromStateProvider(state) {\n environment = state.environment;\n ident.setUser(state.user);\n flags = { ...state.flags };\n utils.onNextTick(signalSuccessfulInit);\n }\n\n function updateFromStateProvider(state) {\n if (state.user) {\n ident.setUser(state.user);\n }\n if (state.flags) {\n replaceAllFlags(state.flags); // don't wait for this Promise to be resolved\n }\n }\n\n function signalSuccessfulInit() {\n logger.info(messages.clientInitialized());\n inited = true;\n updateStreamingState();\n initializationStateTracker.signalSuccess();\n }\n\n function signalFailedInit(err) {\n initializationStateTracker.signalFailure(err);\n }\n\n function start() {\n if (sendEvents) {\n if (diagnosticsManager) {\n diagnosticsManager.start();\n }\n events.start();\n }\n }\n\n function close(onDone) {\n if (closed) {\n return utils.wrapPromiseCallback(Promise.resolve(), onDone);\n }\n const finishClose = () => {\n closed = true;\n flags = {};\n };\n const p = Promise.resolve()\n .then(() => {\n disconnectStream();\n if (diagnosticsManager) {\n diagnosticsManager.stop();\n }\n if (sendEvents) {\n events.stop();\n return events.flush();\n }\n })\n .then(finishClose)\n .catch(finishClose);\n return utils.wrapPromiseCallback(p, onDone);\n }\n\n function getFlagsInternal() {\n // used by Electron integration\n return flags;\n }\n\n const client = {\n waitForInitialization: () => initializationStateTracker.getInitializationPromise(),\n waitUntilReady: () => initializationStateTracker.getReadyPromise(),\n identify: identify,\n getUser: getUser,\n variation: variation,\n variationDetail: variationDetail,\n track: track,\n alias: alias,\n on: on,\n off: off,\n setStreaming: setStreaming,\n flush: flush,\n allFlags: allFlags,\n close: close,\n };\n\n return {\n client: client, // The client object containing all public methods.\n options: options, // The validated configuration object, including all defaults.\n emitter: emitter, // The event emitter which can be used to log errors or trigger events.\n ident: ident, // The Identity object that manages the current user.\n logger: logger, // The logging abstraction.\n requestor: requestor, // The Requestor object.\n start: start, // Starts the client once the environment is ready.\n enqueueEvent: enqueueEvent, // Puts an analytics event in the queue, if event sending is enabled.\n getFlagsInternal: getFlagsInternal, // Returns flag data structure with all details.\n getEnvironmentId: () => environment, // Gets the environment ID (this may have changed since initialization, if we have a state provider)\n internalChangeEventName: internalChangeEvent, // This event is triggered whenever we have new flag state.\n };\n}\n\nexport const version = VERSION;\nexport { commonBasicLogger };\nexport { createConsoleLogger };\nexport { errors };\nexport { messages };\nexport { utils };\n","import * as utils from './utils';\n\nexport default function Identity(initialUser, onChange) {\n const ident = {};\n let user;\n\n ident.setUser = function(u) {\n const previousUser = user && utils.clone(user);\n user = utils.sanitizeUser(u);\n if (user && onChange) {\n onChange(utils.clone(user), previousUser);\n }\n };\n\n ident.getUser = function() {\n return user ? utils.clone(user) : null;\n };\n\n if (initialUser) {\n ident.setUser(initialUser);\n }\n\n return ident;\n}\n"],"names":["createCustomError","name","CustomError","message","code","Error","captureStackTrace","this","constructor","prototype","LDUnexpectedResponseError","LDInvalidEnvironmentIdError","LDInvalidUserError","LDInvalidEventKeyError","LDInvalidArgumentError","LDFlagFetchError","isHttpErrorRecoverable","status","uint8","tmp","len","length","extraBytes","parts","i","len2","push","encodeChunk","lookup","join","revLookup","charCodeAt","start","end","num","output","isArray","Array","keyList","Object","keys","hasProp","hasOwnProperty","equal","a","b","key","arrA","arrB","dateA","Date","dateB","getTime","regexpA","RegExp","regexpB","toString","call","userAttrsToStringify","btoa","s","escaped","unescape","encodeURIComponent","base64","stringToBytes","base64URLEncode","replace","clone","obj","JSON","parse","stringify","deepEquals","fastDeepEqual","onNextTick","cb","setTimeout","wrapPromiseCallback","promise","callback","ret","then","value","error","Promise","reject","undefined","transformValuesToVersionedValues","flags","objectHasOwnProperty","version","transformVersionedValuesToValues","flagsState","chunkUserEventsForUrl","maxLength","events","chunk","allEvents","slice","allChunks","remainingSpace","event","shift","unshift","getLDUserAgentString","platform","userAgent","getLDHeaders","options","sendLDHeaders","h","wrapperName","wrapperVersion","transformHeaders","headers","requestHeaderTransform","extend","objects","reduce","acc","object","sanitizeUser","user","newUser","attr","String","getRandomValues","crypto","bind","window","msCrypto","rnds8","Uint8Array","module","rnds","r","Math","random","byteToHex","substr","_nodeId","_clockseq","buf","offset","bth","_lastMSecs","_lastNSecs","node","clockseq","seedBytes","rng","msecs","nsecs","dt","tl","tmh","n","bytesToUuid","MAX_URL_LENGTH","EventSender","environmentId","imageUrlPath","baseHeaders","utils","httpFallbackPing","sender","sendChunk","url","isDiagnostic","usePost","jsonBody","payloadId","uuidv1","doPostRequest","canRetry","httpRequest","result","errors","dateStr","header","time","serverTime","getResponseInfo","catch","resolve","sendEvents","chunks","canPost","httpAllowsPost","results","all","UserFilter","config","filter","allAttributesPrivate","privateAttributeNames","ignoreAttrs","custom","anonymous","allowedTopLevelAttrs","secondary","ip","country","email","firstName","lastName","avatar","filterUser","filterAttrs","props","isAttributeAllowed","userPrivateAttrs","indexOf","isPrivateAttr","filteredProps","removedAttrs","customResult","removedAttrNames","sort","privateAttrs","errorString","err","clientInitialized","eventWithoutUser","unknownCustomEventKey","environmentNotSpecified","docLink","bootstrapOldFormat","bootstrapInvalid","identifyDisabled","debugStreamPing","debugStreamPut","debugStreamPatch","debugStreamPatchIgnored","debugStreamDelete","debugStreamDeleteIgnored","debugEnqueueingEvent","kind","eventCapacityExceeded","invalidContentType","contentType","localStorageUnavailable","networkError","e","environmentNotFound","errorFetchingFlags","userNotSpecified","invalidUser","deprecated","oldName","newName","httpErrorMessage","context","retryMessage","httpUnavailable","streamClosing","streamConnecting","streamError","streamReconnectDelay","unknownOption","wrongOptionType","expectedType","actualType","wrongOptionTypeBoolean","optionBelowMinimum","minimum","debugPolling","debugPostingEvents","count","EventProcessor","flushTimer","diagnosticsAccumulator","emitter","processor","eventSender","mainEventsUrl","eventsUrl","summarizer","es","startDate","endDate","counters","summarizeEvent","counterKey","variation","counterVal","default","creationDate","getSummary","flagsOut","empty","c","flag","counterOut","unknown","features","clearSummary","EventSummarizer","userFilter","inlineUsers","inlineUsersInEvents","samplingInterval","eventCapacity","flushInterval","logger","queue","lastKnownPastTime","disabled","exceededCapacity","shouldSampleEvent","floor","addToOutbox","warn","messages","incrementDroppedEvents","enqueue","addFullEvent","addDebugEvent","trackEvents","debugEventsUntilDate","shouldDebugEvent","userKey","makeOutputEvent","debugEvent","flush","eventsToSend","summary","setEventsInLastBatch","debug","responseInfo","maybeReportError","flushTick","stop","clearTimeout","EventEmitter","on","handler","concat","off","emit","copiedHandlers","apply","arguments","getEvents","getEventListenerCount","listeningTo","console","readyEvent","successEvent","failureEvent","eventEmitter","succeeded","failed","failureValue","initializationPromise","readyPromise","onReady","getInitializationPromise","onSuccess","onFailure","getReadyPromise","signalSuccess","signalFailure","PersistentFlagStore","storage","environment","hash","ident","store","getFlagsKey","getUser","loadFlags","get","dataStr","data","schema","$schema","ex","clearFlags","saveFlags","set","clear","PersistentStorage","localStorageProvider","logError","loggedError","isEnabled","streamReadTimeoutMillis","Stream","connectionAttemptStartTime","baseUrl","streamUrl","stream","evalUrlPrefix","useReport","withReasons","evaluationReasons","firstConnectionErrorLogged","reconnectTimeoutReference","handlers","handleError","logConnectionResult","closeConnection","tryConnect","delay","openConnection","query","readTimeoutMillis","eventSourceFactory","eventSourceAllowsReport","method","body","info","addEventListener","onerror","close","success","recordStreamInit","connect","newHash","newHandlers","disconnect","isConnected","eventSourceIsActive","jsonContentType","Requestor","requestor","activeRequests","fetchJSON","endpoint","coalescer","finallyFn","currentPromise","currentCancelFn","finalResolve","finalReject","p","cancelFn","resultPromise","promiseCoalescer","req","statusText","getResponseError","substring","addPromise","cancel","path","fetchFlagSettings","ldUserIdKey","UserValidator","persistentStorage","validateUser","userOut","cachedId","id","setCachedUserId","logLevels","commonBasicLogger","formatFn","destination","toConsole","methodName","line","destinations","prependLevelToMessage","prefix","minLevel","level","levelName","levelIndex","args","fullPrefix","tempArgs","log","write","createConsoleLogger","maybePrefix","baseOptionDefs","streaming","type","allowFrequentDuplicateEvents","sendEventsOnlyForVariation","bootstrap","diagnosticRecordingInterval","diagnosticOptOut","stateProvider","autoAliasingOptOut","validate","extraOptionDefs","optionDefs","deprecatedOptions","all_attributes_private","private_attribute_names","reportArgumentError","opts","typeDescForValue","t","forEach","optionDef","allowedTypes","split","validateLogger","sdkKey","diagnosticId","sdkKeySuffix","startTime","dataSinceDate","droppedEvents","eventsInLastBatch","streamInits","reset","getProps","setProps","timestamp","durationMillis","accumulator","eventSentTime","periodicTimer","combinedMode","diagnosticUseCombinedEvent","localStorageKey","diagnosticEventsUrl","periodicInterval","streamingEnabled","manager","makeInitProperties","sdk","sdkData","diagnosticSdkData","makeSdkData","configuration","customBaseURI","customStreamURI","customEventsURI","eventsCapacity","eventsFlushIntervalMillis","reconnectTimeMillis","streamingDisabled","diagnosticRecordingIntervalMillis","usingSecureMode","bootstrapMode","fetchGoalsDisabled","fetchGoals","diagnosticPlatformData","sendDiagnosticEvent","debugPostingDiagnosticEvent","sendPeriodicEvent","currentTime","createPeriodicEventAndReset","saveProperties","loadProperties","localStorageAvailable","nextEventTime","timeNow","setStreaming","enabled","changeEvent","internalChangeEvent","env","specifiedOptions","useLocalStorage","streamActive","subscribedToChangeEvents","createLogger","initializationStateTracker","InitializationStateTracker","localStorage","diagnosticsEnabled","diagnostics","diagnosticsManager","eventProcessor","seenRequests","streamForcedState","inited","closed","firstEvent","initialUser","onChange","setUser","u","previousUser","Identity","enqueueEvent","sendIdentifyEvent","alias","userValidator","persistentFlagStore","isDoNotTrack","sendFlagEvent","detail","defaultValue","includeReason","now","cacheKey","cached","variationIndex","contextKind","userContextKind","flagVersion","trackReason","reason","variationDetailInternal","sendEvent","includeReasonInEvent","deleted","getFlagDetail","errorKind","previousKey","previousContextKind","connectStream","ping","userAtTimeOfPingEvent","requestedFlags","replaceAllFlags","put","patch","oldFlag","mods","newFlag","newDetail","previous","current","handleFlagChanges","delete","disconnectStream","newFlags","changes","changeEventParams","updateStreamingState","shouldBeStreaming","isChangeEventKey","toUpperCase","_typeof","metadataKey","metadata","readFlagsFromBootstrap","state","getInitialState","initFromStateProvider","realUser","signalSuccessfulInit","storedFlags","signalFailedInit","client","waitForInitialization","waitUntilReady","identify","onDone","flagValueMap","variationDetail","track","metricValue","customEventFilter","getCurrentUrl","haveListeners","newState","allFlags","finishClose","getFlagsInternal","getEnvironmentId","internalChangeEventName"],"mappings":"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"}
|