@launchdarkly/js-client-sdk 0.10.0 → 0.11.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 +25 -0
- package/dist/{common-Cn2MjelZ.d.cts → common-ekJnfmSx.d.cts} +103 -0
- package/dist/{common-Cn2MjelZ.d.ts → common-ekJnfmSx.d.ts} +103 -0
- package/dist/compat.cjs +1 -1
- package/dist/compat.cjs.map +1 -1
- package/dist/compat.d.cts +6 -6
- package/dist/compat.d.ts +6 -6
- package/dist/compat.js +1 -1
- package/dist/compat.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -11
- package/dist/index.d.ts +37 -11
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/package.json +2 -2
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../shared/common/src/AttributeReference.ts","../../../shared/common/src/validators.ts","../../../shared/common/src/internal/context/index.ts","../../../shared/common/src/internal/json/canonicalize.ts","../../../shared/common/src/Context.ts","../../../shared/common/src/ContextFilter.ts","../../../shared/common/src/datasource/Backoff.ts","../../../shared/common/src/api/subsystem/DataSystem/CallbackHandler.ts","../../../shared/common/src/api/subsystem/DataSystem/DataSource.ts","../../../shared/common/src/datasource/dataSourceList.ts","../../../shared/common/src/datasource/errors.ts","../../../shared/common/src/datasource/CompositeDataSource.ts","../../../shared/common/src/datasource/DataSourceErrorKinds.ts","../../../shared/common/src/api/platform/AutoEnv.ts","../../../shared/common/src/api/subsystem/LDEventSender.ts","../../../shared/common/src/logging/format.ts","../../../shared/common/src/logging/BasicLogger.ts","../../../shared/common/src/logging/SafeLogger.ts","../../../shared/common/src/logging/createSafeLogger.ts","../../../shared/common/src/options/OptionMessages.ts","../../../shared/common/src/options/ApplicationTags.ts","../../../shared/common/src/options/ClientContext.ts","../../../shared/common/src/options/ServiceEndpoints.ts","../../../shared/common/src/errors.ts","../../../shared/common/src/utils/cancelableTimedPromise.ts","../../../shared/common/src/utils/clone.ts","../../../shared/common/src/utils/date.ts","../../../shared/common/src/utils/debounce.ts","../../../shared/common/src/utils/isEmptyObject.ts","../../../shared/common/src/utils/deepCompact.ts","../../../shared/common/src/utils/fast-deep-equal/index.ts","../../../shared/common/src/utils/http.ts","../../../shared/common/src/utils/noop.ts","../../../shared/common/src/utils/sleep.ts","../../../shared/common/src/utils/timedPromise.ts","../../../shared/common/src/internal/diagnostics/DiagnosticsManager.ts","../../../shared/common/src/internal/evaluation/ErrorKinds.ts","../../../shared/common/src/internal/events/ClientMessages.ts","../../../shared/common/src/internal/events/EventSender.ts","../../../shared/common/src/internal/events/guards.ts","../../../shared/common/src/internal/events/SummaryCounter.ts","../../../shared/common/src/internal/events/EventSummarizer.ts","../../../shared/common/src/internal/events/LDInvalidSDKKeyError.ts","../../../shared/common/src/internal/events/MultiEventSummarizer.ts","../../../shared/common/src/internal/events/sampling.ts","../../../shared/common/src/internal/events/EventProcessor.ts","../../../shared/common/src/internal/events/InputCustomEvent.ts","../../../shared/common/src/internal/events/InputEvalEvent.ts","../../../shared/common/src/internal/events/InputIdentifyEvent.ts","../../../shared/common/src/internal/events/NullEventProcessor.ts","../../../shared/common/src/internal/evaluation/EventFactoryBase.ts","../../../shared/common/src/internal/fdv2/FDv1PayloadAdaptor.ts","../../../shared/common/src/internal/fdv2/payloadProcessor.ts","../../../shared/common/src/internal/fdv2/payloadStreamReader.ts","../../../shared/common/src/internal/metadata/InitMetadata.ts","../../../shared/common/src/internal/plugins/safeGetName.ts","../../../shared/common/src/internal/plugins/safeGetHooks.ts","../../../shared/common/src/internal/plugins/safeRegisterPlugins.ts","../../../shared/sdk-client/src/datasource/DataSourceStatus.ts","../../../shared/sdk-client/src/datasource/Requestor.ts","../../../shared/sdk-client/src/async/AsyncTaskQueue.ts","../../../shared/sdk-client/src/configuration/validators.ts","../../../shared/sdk-client/src/configuration/Configuration.ts","../../../shared/sdk-client/src/crypto/digest.ts","../../../shared/sdk-client/src/storage/getOrGenerateKey.ts","../../../shared/sdk-client/src/storage/namespaceUtils.ts","../../../shared/sdk-client/src/context/addAutoEnv.ts","../../../shared/sdk-client/src/context/ensureKey.ts","../../../shared/sdk-client/src/diagnostics/createDiagnosticsInitConfig.ts","../../../shared/sdk-client/src/diagnostics/createDiagnosticsManager.ts","../../../shared/sdk-client/src/evaluation/evaluationDetail.ts","../../../shared/sdk-client/src/events/createEventProcessor.ts","../../../shared/sdk-client/src/events/EventFactory.ts","../../../shared/sdk-client/src/flag-manager/ContextIndex.ts","../../../shared/sdk-client/src/flag-manager/FlagPersistence.ts","../../../shared/sdk-client/src/flag-manager/FlagStore.ts","../../../shared/sdk-client/src/flag-manager/calculateChangedKeys.ts","../../../shared/sdk-client/src/flag-manager/FlagUpdater.ts","../../../shared/sdk-client/src/flag-manager/FlagManager.ts","../../../shared/sdk-client/src/HookRunner.ts","../../../shared/sdk-client/src/inspection/getInspectorHook.ts","../../../shared/sdk-client/src/inspection/messages.ts","../../../shared/sdk-client/src/inspection/createSafeInspector.ts","../../../shared/sdk-client/src/inspection/InspectorManager.ts","../../../shared/sdk-client/src/LDEmitter.ts","../../../shared/sdk-client/src/plugins/createPluginEnvironmentMetadata.ts","../../../shared/sdk-client/src/LDClientImpl.ts","../../../shared/sdk-client/src/datasource/DataSourceEventHandler.ts","../../../shared/sdk-client/src/datasource/DataSourceStatusManager.ts","../../../shared/sdk-client/src/polling/PollingProcessor.ts","../../../shared/sdk-client/src/streaming/StreamingProcessor.ts","../../../shared/sdk-client/src/DataManager.ts","../src/BrowserApi.ts","../src/bootstrap.ts","../src/BrowserDataManager.ts","../src/BrowserStateDetector.ts","../src/vendor/escapeStringRegexp.ts","../src/goals/GoalTracker.ts","../src/goals/LocationWatcher.ts","../src/goals/GoalManager.ts","../src/goals/Goals.ts","../src/options.ts","../src/platform/BrowserHasher.ts","../src/platform/randomUuidV4.ts","../src/platform/BrowserCrypto.ts","../src/platform/BrowserEncoding.ts","../src/platform/BrowserInfo.ts","../src/platform/DefaultBrowserEventSource.ts","../src/platform/BrowserRequests.ts","../src/platform/LocalStorage.ts","../src/platform/BrowserPlatform.ts","../src/BrowserClient.ts","../src/common.ts","../src/index.ts"],"sourcesContent":["import { LDContextCommon } from './api/context/LDContextCommon';\n\n/**\n * Converts a literal to a ref string.\n * @param value\n * @returns An escaped literal which can be used as a ref.\n */\nfunction toRefString(value: string): string {\n return `/${value.replace(/~/g, '~0').replace(/\\//g, '~1')}`;\n}\n\n/**\n * Produce a literal from a ref component.\n * @param ref\n * @returns A literal version of the ref.\n */\nfunction unescape(ref: string): string {\n return ref.indexOf('~') ? ref.replace(/~1/g, '/').replace(/~0/g, '~') : ref;\n}\n\nfunction getComponents(reference: string): string[] {\n const referenceWithoutPrefix = reference.startsWith('/') ? reference.substring(1) : reference;\n return referenceWithoutPrefix.split('/').map((component) => unescape(component));\n}\n\nfunction isLiteral(reference: string): boolean {\n return !reference.startsWith('/');\n}\n\nfunction validate(reference: string): boolean {\n return !reference.match(/\\/\\/|(^\\/.*~[^0|^1])|~$/);\n}\n\nexport default class AttributeReference {\n public readonly isValid;\n\n /**\n * When redacting attributes this name can be directly added to the list of\n * redactions.\n */\n public readonly redactionName;\n\n /**\n * For use as invalid references when deserializing Flag/Segment data.\n */\n public static readonly InvalidReference = new AttributeReference('');\n\n private readonly _components: string[];\n\n /**\n * Take an attribute reference string, or literal string, and produce\n * an attribute reference.\n *\n * Legacy user objects would have been created with names not\n * references. So, in that case, we need to use them as a component\n * without escaping them.\n *\n * e.g. A user could contain a custom attribute of `/a` which would\n * become the literal `a` if treated as a reference. Which would cause\n * it to no longer be redacted.\n * @param refOrLiteral The attribute reference string or literal string.\n * @param literal it true the value should be treated as a literal.\n */\n public constructor(refOrLiteral: string, literal: boolean = false) {\n if (!literal) {\n this.redactionName = refOrLiteral;\n if (refOrLiteral === '' || refOrLiteral === '/' || !validate(refOrLiteral)) {\n this.isValid = false;\n this._components = [];\n return;\n }\n\n if (isLiteral(refOrLiteral)) {\n this._components = [refOrLiteral];\n } else if (refOrLiteral.indexOf('/', 1) < 0) {\n this._components = [unescape(refOrLiteral.slice(1))];\n } else {\n this._components = getComponents(refOrLiteral);\n }\n // The items inside of '_meta' are not intended to be addressable.\n // Excluding it as a valid reference means that we can make it non-addressable\n // without having to copy all the attributes out of the context object\n // provided by the user.\n if (this._components[0] === '_meta') {\n this.isValid = false;\n } else {\n this.isValid = true;\n }\n } else {\n const literalVal = refOrLiteral;\n this._components = [literalVal];\n this.isValid = literalVal !== '';\n // Literals which start with '/' need escaped to prevent ambiguity.\n this.redactionName = literalVal.startsWith('/') ? toRefString(literalVal) : literalVal;\n }\n }\n\n public get(target: LDContextCommon) {\n const { _components: components, isValid } = this;\n if (!isValid) {\n return undefined;\n }\n\n let current = target;\n\n // This doesn't use a range based for loops, because those use generators.\n // See `no-restricted-syntax`.\n // It also doesn't use a collection method because this logic is more\n // straightforward with a loop.\n for (let index = 0; index < components.length; index += 1) {\n const component = components[index];\n if (\n current !== null &&\n current !== undefined &&\n // See https://eslint.org/docs/rules/no-prototype-builtins\n Object.prototype.hasOwnProperty.call(current, component) &&\n typeof current === 'object' &&\n // We do not want to allow indexing into an array.\n !Array.isArray(current)\n ) {\n current = current[component];\n } else {\n return undefined;\n }\n }\n return current;\n }\n\n public getComponent(depth: number) {\n return this._components[depth];\n }\n\n public get depth() {\n return this._components.length;\n }\n\n public get isKind(): boolean {\n return this._components.length === 1 && this._components[0] === 'kind';\n }\n\n public compare(other: AttributeReference) {\n return (\n this.depth === other.depth &&\n this._components.every((value, index) => value === other.getComponent(index))\n );\n }\n\n public get components() {\n return [...this._components];\n }\n}\n","/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\n\n// The classes here are static, but needs to be instantiated to\n// support the generic functionality. Which is why we do not care about using\n// `this`\n\n// These validators are also of trivial complexity, so we are allowing more than\n// one per file.\n\n/**\n * Interface for type validation.\n */\nexport interface TypeValidator {\n is(u: unknown): boolean;\n getType(): string;\n}\n\n/**\n * Validate a factory or instance.\n */\nexport class FactoryOrInstance implements TypeValidator {\n is(factoryOrInstance: unknown) {\n if (Array.isArray(factoryOrInstance)) {\n return false;\n }\n const anyFactory = factoryOrInstance as any;\n const typeOfFactory = typeof anyFactory;\n return typeOfFactory === 'function' || typeOfFactory === 'object';\n }\n\n getType(): string {\n return 'factory method or object';\n }\n}\n\n/**\n * Validate a basic type.\n */\nexport class Type<T> implements TypeValidator {\n private _typeName: string;\n\n protected typeOf: string;\n\n constructor(typeName: string, example: T) {\n this._typeName = typeName;\n this.typeOf = typeof example;\n }\n\n is(u: unknown): u is T {\n if (Array.isArray(u)) {\n return false;\n }\n return typeof u === this.typeOf;\n }\n\n getType(): string {\n return this._typeName;\n }\n}\n\n/**\n * Validate an array of the specified type.\n *\n * This does not validate instances of types. All class instances\n * of classes will simply objects.\n */\nexport class TypeArray<T> implements TypeValidator {\n private _typeName: string;\n\n protected typeOf: string;\n\n constructor(typeName: string, example: T) {\n this._typeName = typeName;\n this.typeOf = typeof example;\n }\n\n is(u: unknown): u is T {\n if (Array.isArray(u)) {\n if (u.length > 0) {\n return u.every((val) => typeof val === this.typeOf);\n }\n return true;\n }\n return false;\n }\n\n getType(): string {\n return this._typeName;\n }\n}\n\n/**\n * Validate a value is a number and is greater or eval than a minimum.\n */\nexport class NumberWithMinimum extends Type<number> {\n readonly min: number;\n\n constructor(min: number) {\n super(`number with minimum value of ${min}`, 0);\n this.min = min;\n }\n\n override is(u: unknown): u is number {\n return typeof u === this.typeOf && (u as number) >= this.min;\n }\n}\n\n/**\n * Validate a value is a string and it matches the given expression.\n */\nexport class StringMatchingRegex extends Type<string> {\n readonly expression: RegExp;\n\n constructor(expression: RegExp) {\n super(`string matching ${expression}`, '');\n this.expression = expression;\n }\n\n override is(u: unknown): u is string {\n return typeof u === 'string' && !!(u as string).match(this.expression);\n }\n}\n\n/**\n * Validate a value is a function.\n */\nexport class Function implements TypeValidator {\n is(u: unknown): u is (...args: any[]) => void {\n // We cannot inspect the parameters and there isn't really\n // a generic function type we can instantiate.\n // So the type guard is here just to make TS comfortable\n // calling something after using this guard.\n return typeof u === 'function';\n }\n\n getType(): string {\n return 'function';\n }\n}\n\nexport class NullableBoolean implements TypeValidator {\n is(u: unknown): boolean {\n return typeof u === 'boolean' || typeof u === 'undefined' || u === null;\n }\n\n getType(): string {\n return 'boolean | undefined | null';\n }\n}\n\n// Our reference SDK, Go, parses date/time strings with the time.RFC3339Nano format.\n// This regex should match strings that are valid in that format, and no others.\n// Acceptable:\n// 2019-10-31T23:59:59Z, 2019-10-31T23:59:59.100Z,\n// 2019-10-31T23:59:59-07, 2019-10-31T23:59:59-07:00, etc.\n// Unacceptable: no \"T\", no time zone designation\nconst DATE_REGEX = /^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(\\.\\d\\d*)?(Z|[-+]\\d\\d(:\\d\\d)?)/;\n\n/**\n * Validate a value is a date. Values which are numbers are treated as dates and any string\n * which if compliant with `time.RFC3339Nano` is a date.\n */\nexport class DateValidator implements TypeValidator {\n is(u: unknown): boolean {\n return typeof u === 'number' || (typeof u === 'string' && DATE_REGEX.test(u));\n }\n\n getType(): string {\n return 'date';\n }\n}\n\n/**\n * Validates that a string is a valid kind.\n */\nexport class KindValidator extends StringMatchingRegex {\n constructor() {\n super(/^(\\w|\\.|-)+$/);\n }\n\n override is(u: unknown): u is string {\n return super.is(u) && u !== 'kind';\n }\n}\n\n/**\n * A set of standard type validators.\n */\nexport class TypeValidators {\n static readonly String = new Type<string>('string', '');\n\n static readonly Number = new Type<number>('number', 0);\n\n static readonly ObjectOrFactory = new FactoryOrInstance();\n\n static readonly Object = new Type<object>('object', {});\n\n static readonly StringArray = new TypeArray<string>('string[]', '');\n\n static readonly Boolean = new Type<boolean>('boolean', true);\n\n static readonly Function = new Function();\n\n static createTypeArray<T>(typeName: string, example: T) {\n return new TypeArray<T>(typeName, example);\n }\n\n static numberWithMin(min: number): NumberWithMinimum {\n return new NumberWithMinimum(min);\n }\n\n static stringMatchingRegex(expression: RegExp): StringMatchingRegex {\n return new StringMatchingRegex(expression);\n }\n\n static readonly Date = new DateValidator();\n\n static readonly Kind = new KindValidator();\n static readonly NullableBoolean = new NullableBoolean();\n}\n","/**\n * Internal use only. These functions should only be used as part of the initial validation of\n * the LDContext object. Thereafter, the Context object should be used.\n */\nimport type { LDContext, LDMultiKindContext, LDSingleKindContext, LDUser } from '../../api';\nimport { TypeValidators } from '../../validators';\n\n/**\n * Check if a context is a single kind context.\n * @param context\n * @returns true if the context is a single kind context.\n */\nexport function isSingleKind(context: LDContext): context is LDSingleKindContext {\n if ('kind' in context) {\n return TypeValidators.String.is(context.kind) && context.kind !== 'multi';\n }\n return false;\n}\n\n/**\n * Check if a context is a multi-kind context.\n * @param context\n * @returns true if it is a multi-kind context.\n */\nexport function isMultiKind(context: LDContext): context is LDMultiKindContext {\n if ('kind' in context) {\n return TypeValidators.String.is(context.kind) && context.kind === 'multi';\n }\n return false;\n}\n\n/**\n * Check if a context is a legacy user context.\n * @param context\n * @returns true if it is a legacy user context.\n */\nexport function isLegacyUser(context: LDContext): context is LDUser {\n return !('kind' in context) || context.kind === null || context.kind === undefined;\n}\n","/**\n * Given some object to serialize product a canonicalized JSON string.\n * https://www.rfc-editor.org/rfc/rfc8785.html\n *\n * We do not support custom toJSON methods on objects. Objects should be limited to basic types.\n *\n * @param object The object to serialize.\n */\nexport function canonicalize(object: any, visited: any[] = []): string {\n // For JavaScript the default JSON serialization will produce canonicalized output for basic types.\n if (object === null || typeof object !== 'object') {\n return JSON.stringify(object);\n }\n\n if (visited.includes(object)) {\n throw new Error('Cycle detected');\n }\n\n if (Array.isArray(object)) {\n const values = object\n .map((item) => canonicalize(item, [...visited, object]))\n .map((item) => (item === undefined ? 'null' : item));\n return `[${values.join(',')}]`;\n }\n\n const values = Object.keys(object)\n .sort()\n .map((key) => {\n const value = canonicalize(object[key], [...visited, object]);\n if (value !== undefined) {\n return `${JSON.stringify(key)}:${value}`;\n }\n return undefined;\n })\n .filter((item) => item !== undefined);\n return `{${values.join(',')}}`;\n}\n","/* eslint-disable no-underscore-dangle */\n// eslint-disable-next-line max-classes-per-file\nimport type {\n LDContext,\n LDContextCommon,\n LDMultiKindContext,\n LDSingleKindContext,\n LDUser,\n} from './api';\nimport AttributeReference from './AttributeReference';\nimport { isLegacyUser, isMultiKind, isSingleKind } from './internal/context';\nimport { canonicalize } from './internal/json/canonicalize';\nimport { TypeValidators } from './validators';\n\n// The general strategy for the context is to transform the passed in context\n// as little as possible. We do convert the legacy users to a single kind\n// context, but we do not translate all passed contexts into a rigid structure.\n// The context will have to be copied for events, but we want to avoid any\n// copying that we can.\n// So we validate that the information we are given is correct, and then we\n// just proxy calls with a nicely typed interface.\n// This is to reduce work on the hot-path. Later, for event processing, deeper\n// cloning of the context will be done.\n\n// When no kind is specified, then this kind will be used.\nconst DEFAULT_KIND = 'user';\n\n// The API allows for calling with an `LDContext` which is\n// `LDUser | LDSingleKindContext | LDMultiKindContext`. When ingesting a context\n// first the type must be determined to allow us to put it into a consistent type.\n\n/**\n * The partial URL encoding is needed because : is a valid character in context keys.\n *\n * Partial encoding is the replacement of all colon (:) characters with the URL\n * encoded equivalent (%3A) and all percent (%) characters with the URL encoded\n * equivalent (%25).\n * @param key The key to encode.\n * @returns Partially URL encoded key.\n */\nfunction encodeKey(key: string): string {\n if (key.includes('%') || key.includes(':')) {\n return key.replace(/%/g, '%25').replace(/:/g, '%3A');\n }\n return key;\n}\n\n/**\n * Check if the given value is a LDContextCommon.\n * @param kindOrContext\n * @returns true if it is an LDContextCommon\n *\n * Due to a limitation in the expressiveness of these highly polymorphic types any field\n * in a multi-kind context can either be a context or 'kind'. So we need to re-assure\n * the compiler that it isn't the word multi.\n *\n * Because we do not allow top level values in a multi-kind context we can validate\n * that as well.\n */\nfunction isContextCommon(\n kindOrContext: 'multi' | LDContextCommon,\n): kindOrContext is LDContextCommon {\n return kindOrContext && TypeValidators.Object.is(kindOrContext);\n}\n\n/**\n * Validate a context kind.\n * @param kind\n * @returns true if the kind is valid.\n */\nfunction validKind(kind: string) {\n return TypeValidators.Kind.is(kind);\n}\n\n/**\n * Validate a context key.\n * @param key\n * @returns true if the key is valid.\n */\nfunction validKey(key: string) {\n return TypeValidators.String.is(key) && key !== '';\n}\n\nfunction processPrivateAttributes(\n privateAttributes?: string[],\n literals: boolean = false,\n): AttributeReference[] {\n if (privateAttributes) {\n return privateAttributes.map(\n (privateAttribute) => new AttributeReference(privateAttribute, literals),\n );\n }\n return [];\n}\n\nfunction defined(value: any) {\n return value !== null && value !== undefined;\n}\n\n/**\n * Convert a legacy user to a single kind context.\n * @param user\n * @returns A single kind context.\n */\nfunction legacyToSingleKind(user: LDUser): LDSingleKindContext {\n const singleKindContext: LDSingleKindContext = {\n // Key was coerced to a string for eval and events, so we can do that up-front.\n ...(user.custom || []),\n kind: 'user',\n key: String(user.key),\n };\n\n // For legacy users we never established a difference between null\n // and undefined for inputs. Because anonymous can be used in evaluations\n // we would want it to not possibly match true/false unless defined.\n // Which is different than coercing a null/undefined anonymous as `false`.\n if (defined(user.anonymous)) {\n const anonymous = !!user.anonymous;\n delete singleKindContext.anonymous;\n singleKindContext.anonymous = anonymous;\n }\n\n if (user.name !== null && user.name !== undefined) {\n singleKindContext.name = user.name;\n }\n if (user.ip !== null && user.ip !== undefined) {\n singleKindContext.ip = user.ip;\n }\n if (user.firstName !== null && user.firstName !== undefined) {\n singleKindContext.firstName = user.firstName;\n }\n if (user.lastName !== null && user.lastName !== undefined) {\n singleKindContext.lastName = user.lastName;\n }\n if (user.email !== null && user.email !== undefined) {\n singleKindContext.email = user.email;\n }\n if (user.avatar !== null && user.avatar !== undefined) {\n singleKindContext.avatar = user.avatar;\n }\n if (user.country !== null && user.country !== undefined) {\n singleKindContext.country = user.country;\n }\n if (user.privateAttributeNames !== null && user.privateAttributeNames !== undefined) {\n singleKindContext._meta = {\n privateAttributes: user.privateAttributeNames,\n };\n }\n\n // We are not pulling private attributes over because we will serialize\n // those from attribute references for events.\n\n return singleKindContext;\n}\n\n/**\n * Container for a context/contexts. Because contexts come from external code\n * they must be thoroughly validated and then formed to comply with\n * the type system.\n */\nexport default class Context {\n private _context?: LDContextCommon;\n\n private _isMulti: boolean = false;\n\n private _isUser: boolean = false;\n\n private _wasLegacy: boolean = false;\n\n private _contexts: Record<string, LDContextCommon> = {};\n\n private _privateAttributeReferences?: Record<string, AttributeReference[]>;\n\n private _cachedCanonicalJson?: string;\n\n public readonly kind: string;\n\n /**\n * Is this a valid context. If a valid context cannot be created, then this flag will be true.\n * The validity of a context should be tested before it is used.\n */\n public readonly valid: boolean;\n\n public readonly message?: string;\n\n static readonly UserKind: string = DEFAULT_KIND;\n\n /**\n * Contexts should be created using the static factory method {@link Context.fromLDContext}.\n * @param kind The kind of the context.\n *\n * The factory methods are static functions within the class because they access private\n * implementation details, so they cannot be free functions.\n */\n private constructor(valid: boolean, kind: string, message?: string) {\n this.kind = kind;\n this.valid = valid;\n this.message = message;\n }\n\n private static _contextForError(kind: string, message: string) {\n return new Context(false, kind, message);\n }\n\n private static _getValueFromContext(\n reference: AttributeReference,\n context?: LDContextCommon,\n ): any {\n if (!context || !reference.isValid) {\n return undefined;\n }\n\n if (reference.depth === 1 && reference.getComponent(0) === 'anonymous') {\n return !!context?.anonymous;\n }\n return reference.get(context);\n }\n\n private _contextForKind(kind: string): LDContextCommon | undefined {\n if (this._isMulti) {\n return this._contexts[kind];\n }\n if (this.kind === kind) {\n return this._context;\n }\n return undefined;\n }\n\n private static _fromMultiKindContext(context: LDMultiKindContext): Context {\n const kinds = Object.keys(context).filter((key) => key !== 'kind');\n const kindsValid = kinds.every(validKind);\n\n if (!kinds.length) {\n return Context._contextForError(\n 'multi',\n 'A multi-kind context must contain at least one kind',\n );\n }\n\n if (!kindsValid) {\n return Context._contextForError('multi', 'Context contains invalid kinds');\n }\n\n const privateAttributes: Record<string, AttributeReference[]> = {};\n let contextsAreObjects = true;\n const contexts = kinds.reduce((acc: Record<string, LDContextCommon>, kind) => {\n const singleContext = context[kind];\n if (isContextCommon(singleContext)) {\n acc[kind] = singleContext;\n privateAttributes[kind] = processPrivateAttributes(singleContext._meta?.privateAttributes);\n } else {\n // No early break isn't the most efficient, but it is an error condition.\n contextsAreObjects = false;\n }\n return acc;\n }, {});\n\n if (!contextsAreObjects) {\n return Context._contextForError('multi', 'Context contained contexts that were not objects');\n }\n\n if (!Object.values(contexts).every((part) => validKey(part.key))) {\n return Context._contextForError('multi', 'Context contained invalid keys');\n }\n\n // There was only a single kind in the multi-kind context.\n // So we can just translate this to a single-kind context.\n if (kinds.length === 1) {\n const kind = kinds[0];\n const created = new Context(true, kind);\n created._context = { ...contexts[kind], kind };\n created._privateAttributeReferences = privateAttributes;\n created._isUser = kind === 'user';\n return created;\n }\n\n const created = new Context(true, context.kind);\n created._contexts = contexts;\n created._privateAttributeReferences = privateAttributes;\n\n created._isMulti = true;\n return created;\n }\n\n private static _fromSingleKindContext(context: LDSingleKindContext): Context {\n const { key, kind } = context;\n const kindValid = validKind(kind);\n const keyValid = validKey(key);\n\n if (!kindValid) {\n return Context._contextForError(kind ?? 'unknown', 'The kind was not valid for the context');\n }\n\n if (!keyValid) {\n return Context._contextForError(kind, 'The key for the context was not valid');\n }\n\n // The JSON interfaces uses dangling _.\n // eslint-disable-next-line no-underscore-dangle\n const privateAttributeReferences = processPrivateAttributes(context._meta?.privateAttributes);\n const created = new Context(true, kind);\n created._isUser = kind === 'user';\n created._context = context;\n created._privateAttributeReferences = {\n [kind]: privateAttributeReferences,\n };\n return created;\n }\n\n private static _fromLegacyUser(context: LDUser): Context {\n const keyValid = context.key !== undefined && context.key !== null;\n // For legacy users we allow empty keys.\n if (!keyValid) {\n return Context._contextForError('user', 'The key for the context was not valid');\n }\n const created = new Context(true, 'user');\n created._isUser = true;\n created._wasLegacy = true;\n created._context = legacyToSingleKind(context);\n created._privateAttributeReferences = {\n user: processPrivateAttributes(context.privateAttributeNames, true),\n };\n return created;\n }\n\n /**\n * Attempt to create a {@link Context} from an {@link LDContext}.\n * @param context The input context to create a Context from.\n * @returns a {@link Context}, if the context was not valid, then the returned contexts `valid`\n * property will be false.\n */\n public static fromLDContext(context: LDContext): Context {\n if (!context) {\n return Context._contextForError('unknown', 'No context specified. Returning default value');\n }\n if (isSingleKind(context)) {\n return Context._fromSingleKindContext(context);\n }\n if (isMultiKind(context)) {\n return Context._fromMultiKindContext(context);\n }\n if (isLegacyUser(context)) {\n return Context._fromLegacyUser(context);\n }\n\n return Context._contextForError('unknown', 'Context was not of a valid kind');\n }\n\n /**\n * Creates a {@link LDContext} from a {@link Context}.\n * @param context to be converted\n * @returns an {@link LDContext} if input was valid, otherwise undefined\n */\n public static toLDContext(context: Context): LDContext | undefined {\n if (!context.valid) {\n return undefined;\n }\n\n const contexts = context.getContexts();\n if (!context._isMulti) {\n return contexts[0][1];\n }\n const result: LDMultiKindContext = {\n kind: 'multi',\n };\n contexts.forEach((kindAndContext) => {\n const kind = kindAndContext[0];\n const nestedContext = kindAndContext[1];\n result[kind] = nestedContext;\n });\n return result;\n }\n\n /**\n * Attempt to get a value for the given context kind using the given reference.\n * @param reference The reference to the value to get.\n * @param kind The kind of the context to get the value for.\n * @returns a value or `undefined` if one is not found.\n */\n public valueForKind(reference: AttributeReference, kind: string = DEFAULT_KIND): any | undefined {\n if (reference.isKind) {\n return this.kinds;\n }\n return Context._getValueFromContext(reference, this._contextForKind(kind));\n }\n\n /**\n * Attempt to get a key for the specified kind.\n * @param kind The kind to get a key for.\n * @returns The key for the specified kind, or undefined.\n */\n public key(kind: string = DEFAULT_KIND): string | undefined {\n return this._contextForKind(kind)?.key;\n }\n\n /**\n * True if this is a multi-kind context.\n */\n public get isMultiKind(): boolean {\n return this._isMulti;\n }\n\n /**\n * Get the canonical key for this context.\n */\n public get canonicalKey(): string {\n if (this._isUser) {\n return this._context!.key;\n }\n if (this._isMulti) {\n return Object.keys(this._contexts)\n .sort()\n .map((key) => `${key}:${encodeKey(this._contexts[key].key)}`)\n .join(':');\n }\n return `${this.kind}:${encodeKey(this._context!.key)}`;\n }\n\n /**\n * Get the kinds of this context.\n */\n public get kinds(): string[] {\n if (this._isMulti) {\n return Object.keys(this._contexts);\n }\n return [this.kind];\n }\n\n /**\n * Get the kinds, and their keys, for this context.\n */\n public get kindsAndKeys(): Record<string, string> {\n if (this._isMulti) {\n return Object.entries(this._contexts).reduce(\n (acc: Record<string, string>, [kind, context]) => {\n acc[kind] = context.key;\n return acc;\n },\n {},\n );\n }\n return { [this.kind]: this._context!.key };\n }\n\n /**\n * Get the attribute references.\n *\n * @param kind\n */\n public privateAttributes(kind: string): AttributeReference[] {\n return this._privateAttributeReferences?.[kind] || [];\n }\n\n /**\n * Get the underlying context objects from this context.\n *\n * This method is intended to be used in event generation.\n *\n * The returned objects should not be modified.\n */\n public getContexts(): [string, LDContextCommon][] {\n if (this._isMulti) {\n return Object.entries(this._contexts);\n }\n return [[this.kind, this._context!]];\n }\n\n public get legacy(): boolean {\n return this._wasLegacy;\n }\n\n /**\n * Get the serialized canonical JSON for this context. This is not filtered for use in events.\n *\n * This method will cache the result.\n *\n * @returns The serialized canonical JSON or undefined if it cannot be serialized.\n */\n public canonicalUnfilteredJson(): string | undefined {\n if (!this.valid) {\n return undefined;\n }\n if (this._cachedCanonicalJson) {\n return this._cachedCanonicalJson;\n }\n try {\n this._cachedCanonicalJson = canonicalize(Context.toLDContext(this));\n } catch {\n // Indicated by undefined being returned.\n }\n return this._cachedCanonicalJson;\n }\n}\n","// _meta is part of the specification.\n\n/* eslint-disable no-underscore-dangle */\nimport { LDContextCommon } from './api';\nimport AttributeReference from './AttributeReference';\nimport Context from './Context';\n\n// These attributes cannot be removed via a private attribute.\nconst protectedAttributes = ['key', 'kind', '_meta', 'anonymous'].map(\n (str) => new AttributeReference(str, true),\n);\n\n// Attributes that should be stringified for legacy users.\nconst legacyTopLevelCopyAttributes = [\n 'name',\n 'ip',\n 'firstName',\n 'lastName',\n 'email',\n 'avatar',\n 'country',\n];\n\nfunction compare(a: AttributeReference, b: string[]) {\n return a.depth === b.length && b.every((value, index) => value === a.getComponent(index));\n}\n\nfunction cloneWithRedactions(target: LDContextCommon, references: AttributeReference[]): any {\n const stack: {\n key: string;\n ptr: string[];\n source: any;\n parent: any;\n visited: any[];\n }[] = [];\n const cloned: any = {};\n const excluded: string[] = [];\n\n stack.push(\n ...Object.keys(target).map((key) => ({\n key,\n ptr: [key],\n source: target,\n parent: cloned,\n visited: [target],\n })),\n );\n\n while (stack.length) {\n const item = stack.pop()!;\n const redactRef = references.find((ref) => compare(ref, item.ptr));\n if (!redactRef) {\n const value = item.source[item.key];\n\n // Handle null because it overlaps with object, which we will want to handle later.\n if (value === null) {\n item.parent[item.key] = value;\n } else if (Array.isArray(value)) {\n item.parent[item.key] = [...value];\n } else if (typeof value === 'object') {\n // Arrays and null must already be handled.\n\n // Prevent cycles by not visiting the same object\n // with in the same branch. Different branches\n // may contain the same object.\n //\n // Same object visited twice in different branches.\n // A -> B -> D\n // -> C -> D\n // This is fine, which is why it doesn't just check if the object\n // was visited ever.\n if (!item.visited.includes(value)) {\n item.parent[item.key] = {};\n\n stack.push(\n ...Object.keys(value).map((key) => ({\n key,\n ptr: [...item.ptr, key],\n source: value,\n parent: item.parent[item.key],\n visited: [...item.visited, value],\n })),\n );\n }\n } else {\n item.parent[item.key] = value;\n }\n } else {\n excluded.push(redactRef.redactionName);\n }\n }\n return { cloned, excluded: excluded.sort() };\n}\n\nexport default class ContextFilter {\n constructor(\n private readonly _allAttributesPrivate: boolean,\n private readonly _privateAttributes: AttributeReference[],\n ) {}\n\n filter(context: Context, redactAnonymousAttributes: boolean = false): any {\n const contexts = context.getContexts();\n if (contexts.length === 1) {\n return this._filterSingleKind(\n context,\n contexts[0][1],\n contexts[0][0],\n redactAnonymousAttributes,\n );\n }\n const filteredMulti: any = {\n kind: 'multi',\n };\n contexts.forEach(([kind, single]) => {\n filteredMulti[kind] = this._filterSingleKind(\n context,\n single,\n kind,\n redactAnonymousAttributes,\n );\n });\n return filteredMulti;\n }\n\n private _getAttributesToFilter(\n context: Context,\n single: LDContextCommon,\n kind: string,\n redactAllAttributes: boolean,\n ) {\n return (\n redactAllAttributes\n ? Object.keys(single).map((k) => new AttributeReference(k, true))\n : [...this._privateAttributes, ...context.privateAttributes(kind)]\n ).filter((attr) => !protectedAttributes.some((protectedAttr) => protectedAttr.compare(attr)));\n }\n\n private _filterSingleKind(\n context: Context,\n single: LDContextCommon,\n kind: string,\n redactAnonymousAttributes: boolean,\n ): any {\n const redactAllAttributes =\n this._allAttributesPrivate || (redactAnonymousAttributes && single.anonymous === true);\n const { cloned, excluded } = cloneWithRedactions(\n single,\n this._getAttributesToFilter(context, single, kind, redactAllAttributes),\n );\n\n if (context.legacy) {\n legacyTopLevelCopyAttributes.forEach((name) => {\n if (name in cloned) {\n cloned[name] = String(cloned[name]);\n }\n });\n }\n\n if (excluded.length) {\n if (!cloned._meta) {\n cloned._meta = {};\n }\n cloned._meta.redactedAttributes = excluded;\n }\n if (cloned._meta) {\n delete cloned._meta.privateAttributes;\n if (Object.keys(cloned._meta).length === 0) {\n delete cloned._meta;\n }\n }\n\n return cloned;\n }\n}\n","const MAX_RETRY_DELAY = 30 * 1000; // Maximum retry delay 30 seconds.\nconst JITTER_RATIO = 0.5; // Delay should be 50%-100% of calculated time.\n\nexport interface Backoff {\n success(): void;\n fail(): number;\n}\n\n/**\n * Implements exponential backoff and jitter. This class tracks successful connections and failures\n * and produces a retry delay.\n *\n * It does not start any timers or directly control a connection.\n *\n * The backoff follows an exponential backoff scheme with 50% jitter starting at\n * initialRetryDelayMillis and capping at MAX_RETRY_DELAY. If RESET_INTERVAL has elapsed after a\n * success, without an intervening faulure, then the backoff is reset to initialRetryDelayMillis.\n */\nexport class DefaultBackoff {\n private _retryCount: number = 0;\n private _activeSince?: number;\n private _initialRetryDelayMillis: number;\n /**\n * The exponent at which the backoff delay will exceed the maximum.\n * Beyond this limit the backoff can be set to the max.\n */\n private readonly _maxExponent: number;\n\n constructor(\n initialRetryDelayMillis: number,\n private readonly _retryResetIntervalMillis: number,\n private readonly _random = Math.random,\n ) {\n // Initial retry delay cannot be 0.\n this._initialRetryDelayMillis = Math.max(1, initialRetryDelayMillis);\n this._maxExponent = Math.ceil(Math.log2(MAX_RETRY_DELAY / this._initialRetryDelayMillis));\n }\n\n private _backoff(): number {\n const exponent = Math.min(this._retryCount, this._maxExponent);\n const delay = this._initialRetryDelayMillis * 2 ** exponent;\n return Math.min(delay, MAX_RETRY_DELAY);\n }\n\n private _jitter(computedDelayMillis: number): number {\n return computedDelayMillis - Math.trunc(this._random() * JITTER_RATIO * computedDelayMillis);\n }\n\n /**\n * This function should be called when a connection attempt is successful.\n *\n * @param timeStampMs The time of the success. Used primarily for testing, when not provided\n * the current time is used.\n */\n success(timeStampMs: number = Date.now()): void {\n this._activeSince = timeStampMs;\n }\n\n /**\n * This function should be called when a connection fails. It returns the a delay, in\n * milliseconds, after which a reconnection attempt should be made.\n *\n * @param timeStampMs The time of the success. Used primarily for testing, when not provided\n * the current time is used.\n * @returns The delay before the next connection attempt.\n */\n fail(timeStampMs: number = Date.now()): number {\n // If the last successful connection was active for more than the RESET_INTERVAL, then we\n // return to the initial retry delay.\n if (\n this._activeSince !== undefined &&\n timeStampMs - this._activeSince > this._retryResetIntervalMillis\n ) {\n this._retryCount = 0;\n }\n this._activeSince = undefined;\n const delay = this._jitter(this._backoff());\n this._retryCount += 1;\n return delay;\n }\n}\n","import { DataSourceState } from './DataSource';\n\n/**\n * Handler that connects the current {@link DataSource} to the {@link CompositeDataSource}. A single\n * {@link CallbackHandler} should only be given to one {@link DataSource}. Use {@link disable()} to\n * prevent additional callback events.\n */\nexport class CallbackHandler {\n private _disabled: boolean = false;\n\n constructor(\n private readonly _dataCallback: (basis: boolean, data: any) => void,\n private readonly _statusCallback: (status: DataSourceState, err?: any) => void,\n ) {}\n\n disable() {\n this._disabled = true;\n }\n\n async dataHandler(basis: boolean, data: any) {\n if (this._disabled) {\n return;\n }\n\n this._dataCallback(basis, data);\n }\n\n async statusHandler(status: DataSourceState, err?: any) {\n if (this._disabled) {\n return;\n }\n\n this._statusCallback(status, err);\n }\n}\n","// TODO: refactor client-sdk to use this enum\n/**\n * @experimental\n * This feature is not stable and not subject to any backwards compatibility guarantees or semantic\n * versioning. It is not suitable for production usage.\n */\nexport enum DataSourceState {\n // Positive confirmation of connection/data receipt\n Valid,\n // Spinning up to make first connection attempt\n Initializing,\n // Transient issue, automatic retry is expected\n Interrupted,\n // Data source was closed and will not retry automatically.\n Closed,\n}\n\n/**\n * @experimental\n * This feature is not stable and not subject to any backwards compatibility guarantees or semantic\n * versioning. It is not suitable for production usage.\n */\nexport interface DataSource {\n /**\n * May be called any number of times, if already started, has no effect\n * @param dataCallback that will be called when data arrives, may be called multiple times.\n * @param statusCallback that will be called when data source state changes or an unrecoverable error\n * has been encountered.\n * @param selectorGetter that can be invoked to provide the FDv2 selector/basis if one exists\n */\n start(\n dataCallback: (basis: boolean, data: any) => void,\n statusCallback: (status: DataSourceState, err?: any) => void,\n selectorGetter?: () => string | undefined,\n ): void;\n\n /**\n * May be called any number of times, if already stopped, has no effect. Datasource will not make any additional callbacks after stop returns.\n */\n stop(): void;\n}\n\n/**\n * @experimental\n * This feature is not stable and not subject to any backwards compatibility guarantees or semantic\n * versioning. It is not suitable for production usage.\n */\nexport type LDDataSourceFactory = () => DataSource;\n","/**\n * Helper class for {@link CompositeDataSource} to manage iterating on data sources and removing them on the fly.\n */\nexport class DataSourceList<T> {\n private _list: T[];\n private _circular: boolean;\n private _pos: number;\n\n /**\n * @param circular whether to loop off the end of the list back to the start\n * @param initialList of content\n */\n constructor(circular: boolean, initialList?: T[]) {\n this._list = initialList ? [...initialList] : [];\n this._circular = circular;\n this._pos = 0;\n }\n\n /**\n * Returns the current head and then iterates.\n */\n next(): T | undefined {\n if (this._list.length <= 0 || this._pos >= this._list.length) {\n return undefined;\n }\n\n const result = this._list[this._pos];\n\n if (this._circular) {\n this._pos = (this._pos + 1) % this._list.length;\n } else {\n this._pos += 1;\n }\n\n return result;\n }\n\n /**\n * Replaces all elements with the provided list and resets the position of head to the start.\n *\n * @param input that will replace existing list\n */\n replace(input: T[]): void {\n this._list = [...input];\n this._pos = 0;\n }\n\n /**\n * Removes the provided element from the list. If the removed element was the head, head moves to next. Consider head may be undefined if list is empty after removal.\n *\n * @param element to remove\n * @returns true if element was removed\n */\n remove(element: T): boolean {\n const index = this._list.indexOf(element);\n if (index < 0) {\n return false;\n }\n\n this._list.splice(index, 1);\n if (this._list.length > 0) {\n // if removed item was before head, adjust head\n if (index < this._pos) {\n this._pos -= 1;\n }\n\n if (this._circular && this._pos > this._list.length - 1) {\n this._pos = 0;\n }\n }\n return true;\n }\n\n /**\n * Reset the head position to the start of the list.\n */\n reset() {\n this._pos = 0;\n }\n\n /**\n * @returns the current head position in the list, 0 indexed.\n */\n pos() {\n return this._pos;\n }\n\n /**\n * @returns the current length of the list\n */\n length() {\n return this._list.length;\n }\n\n /**\n * Clears the list and resets head.\n */\n clear() {\n this._list = [];\n this._pos = 0;\n }\n}\n","/* eslint-disable max-classes-per-file */\nimport { DataSourceErrorKind } from './DataSourceErrorKinds';\n\nexport class LDFileDataSourceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyFileDataSourceError';\n }\n}\n\nexport class LDPollingError extends Error {\n public readonly kind: DataSourceErrorKind;\n public readonly status?: number;\n public readonly recoverable: boolean;\n\n constructor(kind: DataSourceErrorKind, message: string, status?: number, recoverable = true) {\n super(message);\n this.kind = kind;\n this.status = status;\n this.name = 'LaunchDarklyPollingError';\n this.recoverable = recoverable;\n }\n}\n\nexport class LDStreamingError extends Error {\n public readonly kind: DataSourceErrorKind;\n public readonly code?: number;\n public readonly recoverable: boolean;\n\n constructor(kind: DataSourceErrorKind, message: string, code?: number, recoverable = true) {\n super(message);\n this.kind = kind;\n this.code = code;\n this.name = 'LaunchDarklyStreamingError';\n this.recoverable = recoverable;\n }\n}\n\n/**\n * This is a short term error and will be removed once FDv2 adoption is sufficient.\n */\nexport class LDFlagDeliveryFallbackError extends Error {\n public readonly kind: DataSourceErrorKind;\n public readonly code?: number;\n public readonly recoverable: boolean;\n\n constructor(kind: DataSourceErrorKind, message: string, code?: number) {\n super(message);\n this.kind = kind;\n this.code = code;\n this.name = 'LDFlagDeliveryFallbackError';\n this.recoverable = false;\n }\n}\n\nexport type StreamingErrorHandler = (err: LDStreamingError) => void;\n","/* eslint-disable no-await-in-loop */\nimport { LDLogger } from '../api/logging';\nimport { CallbackHandler } from '../api/subsystem/DataSystem/CallbackHandler';\nimport {\n DataSource,\n DataSourceState,\n LDDataSourceFactory,\n} from '../api/subsystem/DataSystem/DataSource';\nimport { Backoff, DefaultBackoff } from './Backoff';\nimport { DataSourceList } from './dataSourceList';\nimport { LDFlagDeliveryFallbackError } from './errors';\n\nconst DEFAULT_FALLBACK_TIME_MS = 2 * 60 * 1000;\nconst DEFAULT_RECOVERY_TIME_MS = 5 * 60 * 1000;\n\n/**\n * Represents a transition between data sources.\n */\nexport type Transition = 'switchToSync' | 'fallback' | 'recover' | 'stop';\n\n/**\n * Given a {@link DataSourceState}, how long to wait before transitioning.\n */\nexport type TransitionConditions = {\n [k in DataSourceState]?: { durationMS: number; transition: Transition };\n};\n\ninterface TransitionRequest {\n transition: Transition;\n err?: Error;\n}\n\n/**\n * The {@link CompositeDataSource} can combine a number of {@link DataSystemInitializer}s and {@link DataSystemSynchronizer}s\n * into a single {@link DataSource}, implementing fallback and recovery logic internally to choose where data is sourced from.\n */\nexport class CompositeDataSource implements DataSource {\n // TODO: SDK-856 async notification if initializer takes too long\n\n private _initPhaseActive: boolean;\n private _initFactories: DataSourceList<LDDataSourceFactory>;\n private _syncFactories: DataSourceList<LDDataSourceFactory>;\n private _fdv1Synchronizers: DataSourceList<LDDataSourceFactory>;\n\n private _stopped: boolean = true;\n private _externalTransitionPromise: Promise<TransitionRequest>;\n private _externalTransitionResolve?: (value: TransitionRequest) => void;\n private _cancelTokens: (() => void)[] = [];\n\n /**\n * @param initializers factories to create {@link DataSystemInitializer}s, in priority order.\n * @param synchronizers factories to create {@link DataSystemSynchronizer}s, in priority order.\n * @param fdv1Synchronizers factories to fallback to if we need to fallback to FDv1.\n * @param _logger for logging\n * @param _transitionConditions to control automated transition between datasources. Typically only used for testing.\n * @param _backoff to control delay between transitions. Typically only used for testing.\n */\n constructor(\n initializers: LDDataSourceFactory[],\n synchronizers: LDDataSourceFactory[],\n fdv1Synchronizers: LDDataSourceFactory[],\n private readonly _logger?: LDLogger,\n private readonly _transitionConditions: TransitionConditions = {\n [DataSourceState.Valid]: {\n durationMS: DEFAULT_RECOVERY_TIME_MS,\n transition: 'recover',\n },\n [DataSourceState.Interrupted]: {\n durationMS: DEFAULT_FALLBACK_TIME_MS,\n transition: 'fallback',\n },\n },\n private readonly _backoff: Backoff = new DefaultBackoff(1000, 30000),\n ) {\n this._externalTransitionPromise = new Promise<TransitionRequest>((resolveTransition) => {\n this._externalTransitionResolve = resolveTransition;\n });\n this._initPhaseActive = initializers.length > 0; // init phase if we have initializers\n this._initFactories = new DataSourceList(false, initializers);\n this._syncFactories = new DataSourceList(true, synchronizers);\n this._fdv1Synchronizers = new DataSourceList(true, fdv1Synchronizers);\n }\n\n async start(\n dataCallback: (basis: boolean, data: any) => void,\n statusCallback: (status: DataSourceState, err?: any) => void,\n selectorGetter?: () => string | undefined,\n ): Promise<void> {\n if (!this._stopped) {\n // don't allow multiple simultaneous runs\n this._logger?.info('CompositeDataSource already running. Ignoring call to start.');\n return;\n }\n this._stopped = false;\n\n this._logger?.debug(\n `CompositeDataSource starting with (${this._initFactories.length()} initializers, ${this._syncFactories.length()} synchronizers).`,\n );\n\n // this wrapper turns status updates from underlying data sources into a valid series of status updates for the consumer of this\n // composite data source\n const sanitizedStatusCallback = this._wrapStatusCallbackWithSanitizer(statusCallback);\n sanitizedStatusCallback(DataSourceState.Initializing);\n\n let lastTransition: Transition | undefined;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const {\n dataSource: currentDS,\n isPrimary,\n cullDSFactory,\n } = this._pickDataSource(lastTransition);\n\n const internalTransitionPromise = new Promise<TransitionRequest>((transitionResolve) => {\n if (currentDS) {\n // these local variables are used for handling automatic transition related to data source status (ex: recovering to primary after\n // secondary has been valid for N many seconds)\n let lastState: DataSourceState | undefined;\n let cancelScheduledTransition: () => void = () => {};\n\n // this callback handler can be disabled and ensures only one transition request occurs\n const callbackHandler = new CallbackHandler(\n (basis: boolean, data: any) => {\n this._backoff.success();\n dataCallback(basis, data);\n if (basis && this._initPhaseActive) {\n // transition to sync if we get basis during init\n callbackHandler.disable();\n this._consumeCancelToken(cancelScheduledTransition);\n sanitizedStatusCallback(DataSourceState.Interrupted);\n transitionResolve({ transition: 'switchToSync' });\n }\n },\n (state: DataSourceState, err?: any) => {\n // When we get a status update, we want to fallback if it is an error. We also want to schedule a transition for some\n // time in the future if this status remains for some duration (ex: Recover to primary synchronizer after the secondary\n // synchronizer has been Valid for some time). These scheduled transitions are configurable in the constructor.\n this._logger?.debug(\n `CompositeDataSource received state ${state} from underlying data source. Err is ${err}`,\n );\n if (err || state === DataSourceState.Closed) {\n callbackHandler.disable();\n if (err?.recoverable === false) {\n // don't use this datasource's factory again\n this._logger?.debug(`Culling data source due to err ${err}`);\n cullDSFactory?.();\n\n // this error indicates we should fallback to only using FDv1 synchronizers\n if (err instanceof LDFlagDeliveryFallbackError) {\n this._logger?.debug(`Falling back to FDv1`);\n this._syncFactories = this._fdv1Synchronizers;\n }\n }\n sanitizedStatusCallback(state, err);\n this._consumeCancelToken(cancelScheduledTransition);\n transitionResolve({ transition: 'fallback', err }); // unrecoverable error has occurred, so fallback\n } else {\n sanitizedStatusCallback(state);\n if (state !== lastState) {\n lastState = state;\n this._consumeCancelToken(cancelScheduledTransition); // cancel previously scheduled status transition if one was scheduled\n\n // primary source cannot recover to itself, so exclude it\n const condition = this._lookupTransitionCondition(state, isPrimary);\n if (condition) {\n const { promise, cancel } = this._cancellableDelay(condition.durationMS);\n cancelScheduledTransition = cancel;\n this._cancelTokens.push(cancelScheduledTransition);\n promise.then(() => {\n this._consumeCancelToken(cancel);\n callbackHandler.disable();\n sanitizedStatusCallback(DataSourceState.Interrupted);\n transitionResolve({ transition: condition.transition });\n });\n } else {\n // this data source state does not have a transition condition, so don't schedule any transition\n }\n }\n }\n },\n );\n currentDS.start(\n (basis, data) => callbackHandler.dataHandler(basis, data),\n (status, err) => callbackHandler.statusHandler(status, err),\n selectorGetter,\n );\n } else {\n // we don't have a data source to use!\n transitionResolve({\n transition: 'stop',\n err: {\n name: 'ExhaustedDataSources',\n message: `CompositeDataSource has exhausted all configured initializers and synchronizers.`,\n },\n });\n }\n });\n\n // await transition triggered by internal data source or an external stop request\n let transitionRequest = await Promise.race([\n internalTransitionPromise,\n this._externalTransitionPromise,\n ]);\n\n // stop the underlying datasource before transitioning to next state\n currentDS?.stop();\n\n if (transitionRequest.err && transitionRequest.transition !== 'stop') {\n // if the transition was due to an error we're not in the initializer phase, throttle the transition. Fallback between initializers is not throttled.\n const delay = this._initPhaseActive ? 0 : this._backoff.fail();\n const { promise, cancel: cancelDelay } = this._cancellableDelay(delay);\n this._cancelTokens.push(cancelDelay);\n const delayedTransition = promise.then(() => {\n this._consumeCancelToken(cancelDelay);\n return transitionRequest;\n });\n\n // race the delayed transition and external transition requests to be responsive\n transitionRequest = await Promise.race([\n delayedTransition,\n this._externalTransitionPromise,\n ]);\n\n // consume the delay cancel token (even if it resolved, need to stop tracking its token)\n this._consumeCancelToken(cancelDelay);\n }\n\n lastTransition = transitionRequest.transition;\n if (transitionRequest.transition === 'stop') {\n // exit the loop, this is intentionally not the sanitized status callback\n statusCallback(DataSourceState.Closed, transitionRequest.err);\n break;\n }\n }\n\n // reset so that run can be called again in the future\n this._reset();\n }\n\n async stop() {\n this._cancelTokens.forEach((cancel) => cancel());\n this._cancelTokens = [];\n this._externalTransitionResolve?.({ transition: 'stop' });\n }\n\n private _reset() {\n this._stopped = true;\n this._initPhaseActive = this._initFactories.length() > 0; // init phase if we have initializers;\n this._initFactories.reset();\n this._syncFactories.reset();\n this._fdv1Synchronizers.reset();\n this._externalTransitionPromise = new Promise<TransitionRequest>((tr) => {\n this._externalTransitionResolve = tr;\n });\n // intentionally not resetting the backoff to avoid a code path that could circumvent throttling\n }\n\n /**\n * Determines the next datasource and returns that datasource as well as a closure to cull the\n * datasource from the datasource lists. One example where the cull closure is invoked is if the\n * datasource has an unrecoverable error.\n */\n private _pickDataSource(transition?: Transition): {\n dataSource: DataSource | undefined;\n isPrimary: boolean;\n cullDSFactory: (() => void) | undefined;\n } {\n let factory: LDDataSourceFactory | undefined;\n let isPrimary: boolean;\n switch (transition) {\n case 'switchToSync':\n this._initPhaseActive = false; // one way toggle to false, unless this class is reset()\n this._syncFactories.reset();\n isPrimary = this._syncFactories.pos() === 0;\n factory = this._syncFactories.next();\n break;\n case 'recover':\n if (this._initPhaseActive) {\n this._initFactories.reset();\n isPrimary = this._initFactories.pos() === 0;\n factory = this._initFactories.next();\n } else {\n this._syncFactories.reset();\n isPrimary = this._syncFactories.pos() === 0;\n factory = this._syncFactories.next();\n }\n break;\n case 'fallback':\n default:\n // if asked to fallback after using all init factories, switch to sync factories\n if (this._initPhaseActive && this._initFactories.pos() >= this._initFactories.length()) {\n this._initPhaseActive = false;\n this._syncFactories.reset();\n }\n\n if (this._initPhaseActive) {\n isPrimary = this._initFactories.pos() === 0;\n factory = this._initFactories.next();\n } else {\n isPrimary = this._syncFactories.pos() === 0;\n factory = this._syncFactories.next();\n }\n break;\n }\n\n if (!factory) {\n return { dataSource: undefined, isPrimary, cullDSFactory: undefined };\n }\n\n return {\n dataSource: factory(),\n isPrimary,\n cullDSFactory: () => {\n if (factory) {\n this._syncFactories.remove(factory);\n }\n },\n };\n }\n\n /**\n * @returns the transition condition for the provided data source state or undefined\n * if there is no transition condition\n */\n private _lookupTransitionCondition(\n state: DataSourceState,\n excludeRecover: boolean,\n ): { durationMS: number; transition: Transition } | undefined {\n const condition = this._transitionConditions[state];\n\n // exclude recovery can happen for certain initializers/synchronizers (ex: the primary synchronizer shouldn't recover to itself)\n if (excludeRecover && condition?.transition === 'recover') {\n return undefined;\n }\n\n return condition;\n }\n\n private _cancellableDelay = (delayMS: number) => {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n const promise = new Promise((res, _) => {\n timeout = setTimeout(res, delayMS);\n });\n return {\n promise,\n cancel() {\n if (timeout) {\n clearTimeout(timeout);\n timeout = undefined;\n }\n },\n };\n };\n\n private _consumeCancelToken(cancel: () => void) {\n cancel();\n const index = this._cancelTokens.indexOf(cancel, 0);\n if (index > -1) {\n this._cancelTokens.splice(index, 1);\n }\n }\n\n /**\n * This wrapper will ensure the following:\n *\n * Don't report DataSourceState.Initializing except as first status callback.\n * Map underlying DataSourceState.Closed to interrupted.\n * Don't report the same status and error twice in a row.\n */\n private _wrapStatusCallbackWithSanitizer(\n statusCallback: (status: DataSourceState, err?: any) => void,\n ): (status: DataSourceState, err?: any) => void {\n let alreadyReportedInitializing = false;\n let lastStatus: DataSourceState | undefined;\n let lastErr: any;\n\n return (status: DataSourceState, err?: any) => {\n let sanitized = status;\n // underlying errors, closed state, or off are masked as interrupted while we transition\n if (status === DataSourceState.Closed) {\n sanitized = DataSourceState.Interrupted;\n }\n\n // don't report the same combination of values twice in a row\n if (sanitized === lastStatus && err === lastErr) {\n return;\n }\n\n if (sanitized === DataSourceState.Initializing) {\n // don't report initializing again if that has already been reported\n if (alreadyReportedInitializing) {\n return;\n }\n alreadyReportedInitializing = true;\n }\n\n lastStatus = sanitized;\n lastErr = err;\n statusCallback(sanitized, err);\n };\n }\n}\n","export enum DataSourceErrorKind {\n /// An unexpected error, such as an uncaught exception, further\n /// described by the error message.\n Unknown = 'UNKNOWN',\n\n /// An I/O error such as a dropped connection.\n NetworkError = 'NETWORK_ERROR',\n\n /// The LaunchDarkly service returned an HTTP response with an error\n /// status, available in the status code.\n ErrorResponse = 'ERROR_RESPONSE',\n\n /// The SDK received malformed data from the LaunchDarkly service.\n InvalidData = 'INVALID_DATA',\n}\n","/* eslint-disable import/prefer-default-export */\n/**\n * Enable / disable Auto environment attributes. When enabled, the SDK will automatically\n * provide data about the mobile environment where the application is running. This data makes it simpler to target\n * your mobile customers based on application name or version, or on device characteristics including manufacturer,\n * model, operating system, locale, and so on. We recommend enabling this when you configure the SDK. To learn more,\n * read [Automatic environment attributes](https://docs.launchdarkly.com/sdk/features/environment-attributes).\n * for more documentation.\n */\nexport enum AutoEnvAttributes {\n Disabled,\n Enabled,\n}\n\ninterface AutoEnvCommon {\n /**\n * Unique key for the context kind.\n */\n key: string;\n\n /**\n * Version of the environment attributes schema being used.\n */\n envAttributesVersion: string;\n}\n\nexport interface LDApplication extends AutoEnvCommon {\n /**\n * Unique identifier of the application.\n */\n id?: string;\n name?: string;\n version?: string;\n versionName?: string;\n locale?: string;\n}\n\nexport interface LDDevice extends AutoEnvCommon {\n manufacturer?: string;\n model?: string;\n storageBytes?: string;\n memoryBytes?: string;\n os?: {\n /**\n * The family of operating system.\n */\n family?: string;\n name?: string;\n version?: string;\n };\n}\n","export enum LDEventType {\n AnalyticsEvents,\n DiagnosticEvent,\n}\n\nexport enum LDDeliveryStatus {\n Succeeded,\n Failed,\n FailedAndMustShutDown,\n}\n\nexport interface LDEventSenderResult {\n status: LDDeliveryStatus;\n serverTime?: number;\n error?: any;\n}\n\nexport default interface LDEventSender {\n sendEventData(type: LDEventType, data: any): Promise<LDEventSenderResult>;\n}\n","import { TypeValidators } from '../validators';\n\n/**\n * Attempt to produce a string representation of a value.\n * The format should be roughly comparable to `util.format`\n * aside from object which will be JSON versus the `util.inspect`\n * format.\n * @param val\n * @returns A string representation of the value if possible.\n */\nfunction tryStringify(val: any) {\n if (typeof val === 'string') {\n return val;\n }\n if (val === undefined) {\n return 'undefined';\n }\n if (val === null) {\n return 'null';\n }\n if (Object.prototype.hasOwnProperty.call(val, 'toString')) {\n try {\n return val.toString();\n } catch {\n /* Keep going */\n }\n }\n\n if (typeof val === 'bigint') {\n return `${val}n`;\n }\n try {\n return JSON.stringify(val);\n } catch (error) {\n if (error instanceof TypeError && error.message.indexOf('circular') >= 0) {\n return '[Circular]';\n }\n return '[Not Stringifiable]';\n }\n}\n\n/**\n * Attempt to produce a numeric representation.\n * BigInts have an `n` suffix.\n * @param val\n * @returns The numeric representation or 'NaN' if not numeric.\n */\nfunction toNumber(val: any): string {\n // Symbol has to be treated special because it will\n // throw an exception if an attempt is made to convert it.\n if (typeof val === 'symbol') {\n return 'NaN';\n }\n if (typeof val === 'bigint') {\n return `${val}n`;\n }\n return String(Number(val));\n}\n\n/**\n * Attempt to produce an integer representation.\n * BigInts have an `n` suffix.\n * @param val\n * @returns The integer representation or 'NaN' if not numeric.\n */\nfunction toInt(val: any): string {\n if (typeof val === 'symbol') {\n return 'NaN';\n }\n if (typeof val === 'bigint') {\n return `${val}n`;\n }\n return String(parseInt(val, 10));\n}\n\n/**\n * Attempt to produce a float representation.\n * BigInts have an `n` suffix.\n * @param val\n * @returns The integer representation or 'NaN' if not numeric.\n */\nfunction toFloat(val: any): string {\n if (typeof val === 'symbol') {\n return 'NaN';\n }\n return String(parseFloat(val));\n}\n\n// Based on:\n// https://nodejs.org/api/util.html#utilformatformat-args\n// The result will not match node exactly, but it should get the\n// right information through.\nconst escapes: Record<string, (val: any) => string> = {\n s: (val: any) => tryStringify(val),\n d: (val: any) => toNumber(val),\n i: (val: any) => toInt(val),\n f: (val: any) => toFloat(val),\n j: (val: any) => tryStringify(val),\n o: (val: any) => tryStringify(val),\n // eslint-disable-next-line @typescript-eslint/naming-convention\n O: (val: any) => tryStringify(val),\n c: () => '',\n};\n\n/**\n * A basic formatted for use where `util.format` is not available.\n * This will not be as performant, but it will produce formatted\n * messages.\n *\n * @internal\n *\n * @param args\n * @returns Formatted string.\n */\nexport default function format(...args: any[]): string {\n const formatString = args.shift();\n if (TypeValidators.String.is(formatString)) {\n let out = '';\n let i = 0;\n while (i < formatString.length) {\n const char = formatString.charAt(i);\n if (char === '%') {\n const nextIndex = i + 1;\n if (nextIndex < formatString.length) {\n const nextChar = formatString.charAt(i + 1);\n if (nextChar in escapes && args.length) {\n const value = args.shift();\n // This rule is for math.\n // eslint-disable-next-line no-unsafe-optional-chaining\n out += escapes[nextChar]?.(value);\n } else if (nextChar === '%') {\n out += '%';\n } else {\n out += `%${nextChar}`;\n }\n i += 2;\n }\n } else {\n out += char;\n i += 1;\n }\n }\n // If there are any args left after we exhaust the format string\n // then just stick those on the end.\n if (args.length) {\n if (out.length) {\n out += ' ';\n }\n out += args.map(tryStringify).join(' ');\n }\n return out;\n }\n return args.map(tryStringify).join(' ');\n}\n","import { BasicLoggerOptions, LDLogger, LDLogLevel } from '../api';\nimport format from './format';\n\nenum LogPriority {\n debug = 0,\n info = 1,\n warn = 2,\n error = 3,\n none = 4,\n}\n\nconst LEVEL_NAMES: LDLogLevel[] = ['debug', 'info', 'warn', 'error', 'none'];\n\n/**\n * A basic logger which handles filtering by level.\n *\n * With the default options it will write to `console.error`\n * and it will use the formatting provided by `console.error`.\n * If the destination is overwritten, then it will use an included\n * formatter similar to `util.format`.\n *\n * If a formatter is available, then that should be overridden\n * as well for performance.\n */\nexport default class BasicLogger implements LDLogger {\n private _logLevel: number;\n\n private _name: string;\n\n private _destinations?: Record<number, (line: string) => void>;\n\n private _formatter?: (...args: any[]) => string;\n\n /**\n * This should only be used as a default fallback and not as a convenient\n * solution. In most cases you should construct a new instance with the\n * appropriate options for your specific needs.\n */\n static get() {\n return new BasicLogger({});\n }\n\n constructor(options: BasicLoggerOptions) {\n this._logLevel = LogPriority[options.level ?? 'info'] ?? LogPriority.info;\n this._name = options.name ?? 'LaunchDarkly';\n this._formatter = options.formatter;\n if (typeof options.destination === 'object') {\n this._destinations = {\n [LogPriority.debug]: options.destination.debug,\n [LogPriority.info]: options.destination.info,\n [LogPriority.warn]: options.destination.warn,\n [LogPriority.error]: options.destination.error,\n };\n } else if (typeof options.destination === 'function') {\n const { destination } = options;\n this._destinations = {\n [LogPriority.debug]: destination,\n [LogPriority.info]: destination,\n [LogPriority.warn]: destination,\n [LogPriority.error]: destination,\n };\n }\n }\n\n private _tryFormat(...args: any[]): string {\n try {\n if (this._formatter) {\n // In case the provided formatter fails.\n return this._formatter?.(...args);\n }\n return format(...args);\n } catch {\n return format(...args);\n }\n }\n\n private _tryWrite(destination: (msg: string) => void, msg: string) {\n try {\n destination(msg);\n } catch {\n // eslint-disable-next-line no-console\n console.error(msg);\n }\n }\n\n private _log(level: number, args: any[]) {\n if (level >= this._logLevel) {\n const prefix = `${LEVEL_NAMES[level]}: [${this._name}]`;\n try {\n const destination = this._destinations?.[level];\n if (destination) {\n this._tryWrite(destination, `${prefix} ${this._tryFormat(...args)}`);\n } else {\n // `console.error` has its own formatter.\n // So we don't need to do anything.\n // eslint-disable-next-line no-console\n console.error(...args);\n }\n } catch {\n // If all else fails do not break.\n // eslint-disable-next-line no-console\n console.error(...args);\n }\n }\n }\n\n error(...args: any[]): void {\n this._log(LogPriority.error, args);\n }\n\n warn(...args: any[]): void {\n this._log(LogPriority.warn, args);\n }\n\n info(...args: any[]): void {\n this._log(LogPriority.info, args);\n }\n\n debug(...args: any[]): void {\n this._log(LogPriority.debug, args);\n }\n}\n","import type { LDLogger } from '../api';\nimport { TypeValidators } from '../validators';\n\nconst loggerRequirements = {\n error: TypeValidators.Function,\n warn: TypeValidators.Function,\n info: TypeValidators.Function,\n debug: TypeValidators.Function,\n};\n\n/**\n * The safeLogger logic exists because we allow the application to pass in a custom logger, but\n * there is no guarantee that the logger works correctly and if it ever throws exceptions there\n * could be serious consequences (e.g. an uncaught exception within an error event handler, due\n * to the SDK trying to log the error, can terminate the application). An exception could result\n * from faulty logic in the logger implementation, or it could be that this is not a logger at\n * all but some other kind of object; the former is handled by a catch block that logs an error\n * message to the SDK's default logger, and we can at least partly guard against the latter by\n * checking for the presence of required methods at configuration time.\n */\nexport default class SafeLogger implements LDLogger {\n private _logger: LDLogger;\n\n private _fallback: LDLogger;\n\n /**\n * Construct a safe logger with the specified logger.\n * @param logger The logger to use.\n * @param fallback A fallback logger to use in case an issue is encountered using\n * the provided logger.\n */\n constructor(logger: LDLogger, fallback: LDLogger) {\n Object.entries(loggerRequirements).forEach(([level, validator]) => {\n if (!validator.is((logger as any)[level])) {\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 this._logger = logger;\n this._fallback = fallback;\n }\n\n private _log(level: 'error' | 'warn' | 'info' | 'debug', args: any[]) {\n try {\n this._logger[level](...args);\n } catch {\n // If all else fails do not break.\n this._fallback[level](...args);\n }\n }\n\n error(...args: any[]): void {\n this._log('error', args);\n }\n\n warn(...args: any[]): void {\n this._log('warn', args);\n }\n\n info(...args: any[]): void {\n this._log('info', args);\n }\n\n debug(...args: any[]): void {\n this._log('debug', args);\n }\n}\n","import { LDLogger } from '../api';\nimport BasicLogger from './BasicLogger';\nimport format from './format';\nimport SafeLogger from './SafeLogger';\n\nconst createSafeLogger = (logger?: LDLogger) => {\n const basicLogger = new BasicLogger({\n level: 'info',\n // eslint-disable-next-line no-console\n destination: console.error,\n formatter: format,\n });\n return logger ? new SafeLogger(logger, basicLogger) : basicLogger;\n};\n\nexport default createSafeLogger;\n","/**\n * Messages for issues which can be encountered from processing the configuration options.\n */\nexport default class OptionMessages {\n static deprecated(oldName: string, newName: string): string {\n return `\"${oldName}\" is deprecated, please use \"${newName}\"`;\n }\n\n static optionBelowMinimum(name: string, value: number, min: number): string {\n return `Config option \"${name}\" had invalid value of ${value}, using minimum of ${min} instead`;\n }\n\n static unknownOption(name: string): string {\n return `Ignoring unknown config option \"${name}\"`;\n }\n\n static wrongOptionType(name: string, expectedType: string, actualType: string): string {\n return `Config option \"${name}\" should be of type ${expectedType}, got ${actualType}, using default value`;\n }\n\n static wrongOptionTypeBoolean(name: string, actualType: string): string {\n return `Config option \"${name}\" should be a boolean, got ${actualType}, converting to boolean`;\n }\n\n static invalidTagValue(name: string): string {\n return `Config option \"${name}\" must only contain letters, numbers, ., _ or -.`;\n }\n\n static tagValueTooLong(name: string): string {\n return `Value of \"${name}\" was longer than 64 characters and was discarded.`;\n }\n\n static partialEndpoint(name: string): string {\n return `You have set custom uris without specifying the ${name} URI; connections may not work properly`;\n }\n}\n","import { LDLogger } from '../api';\nimport { TypeValidators } from '../validators';\nimport OptionMessages from './OptionMessages';\n\n/**\n * Expression to validate characters that are allowed in tag keys and values.\n */\nconst allowedTagCharacters = /^(\\w|\\.|-)+$/;\n\nconst regexValidator = TypeValidators.stringMatchingRegex(allowedTagCharacters);\n\nconst tagValidator = {\n is: (u: unknown, name: string): { valid: boolean; message?: string } => {\n if (regexValidator.is(u)) {\n if (u.length > 64) {\n return { valid: false, message: OptionMessages.tagValueTooLong(name) };\n }\n return { valid: true };\n }\n return { valid: false, message: OptionMessages.invalidTagValue(name) };\n },\n};\n\n/**\n * Class for managing tags.\n */\nexport default class ApplicationTags {\n public readonly value?: string;\n\n constructor(options: {\n application?: { id?: string; version?: string; name?: string; versionName?: string };\n logger?: LDLogger;\n }) {\n const tags: Record<string, string[]> = {};\n const application = options?.application;\n const logger = options?.logger;\n\n if (application) {\n Object.entries(application).forEach(([key, value]) => {\n if (value !== null && value !== undefined) {\n const { valid, message } = tagValidator.is(value, `application.${key}`);\n\n if (!valid) {\n logger?.warn(message);\n } else if (key === 'versionName') {\n tags[`application-version-name`] = [value];\n } else {\n tags[`application-${key}`] = [value];\n }\n }\n });\n }\n\n const tagKeys = Object.keys(tags);\n if (tagKeys.length) {\n this.value = tagKeys\n .sort()\n .flatMap((key) => tags[key].sort().map((value) => `${key}/${value}`))\n .join(' ');\n }\n }\n}\n","import { LDClientContext, LDLogger, Platform } from '../api';\nimport ApplicationTags from './ApplicationTags';\nimport ServiceEndpoints from './ServiceEndpoints';\n\n/**\n * Basic configuration applicable to many SDK components for both server and\n * client SDKs.\n */\ninterface BasicConfiguration {\n tags?: ApplicationTags;\n\n logger?: LDLogger;\n\n /**\n * True if the SDK was configured to be completely offline.\n */\n offline?: boolean;\n\n /**\n * The configured SDK key.\n */\n sdkKey: string;\n\n /**\n * Defines the base service URIs used by SDK components.\n */\n serviceEndpoints: ServiceEndpoints;\n\n /**\n * Sets the initial reconnect delay for the streaming connection, in seconds.\n */\n streamInitialReconnectDelay?: number;\n}\n\n/**\n * The client context provides basic configuration and platform support which are required\n * when building SDK components.\n */\nexport default class ClientContext implements LDClientContext {\n basicConfiguration: BasicConfiguration;\n\n constructor(\n sdkKey: string,\n configuration: {\n logger?: LDLogger;\n offline?: boolean;\n serviceEndpoints: ServiceEndpoints;\n tags?: ApplicationTags;\n },\n public readonly platform: Platform,\n ) {\n this.basicConfiguration = {\n tags: configuration.tags,\n logger: configuration.logger,\n offline: configuration.offline,\n serviceEndpoints: configuration.serviceEndpoints,\n sdkKey,\n };\n }\n}\n","function canonicalizeUri(uri: string): string {\n return uri.replace(/\\/+$/, '');\n}\n\nfunction canonicalizePath(path: string): string {\n return path.replace(/^\\/+/, '').replace(/\\?$/, '');\n}\n\n/**\n * Specifies the base service URIs used by SDK components.\n */\nexport default class ServiceEndpoints {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n public static DEFAULT_EVENTS = 'https://events.launchdarkly.com';\n\n public readonly streaming: string;\n public readonly polling: string;\n public readonly events: string;\n public readonly payloadFilterKey?: string;\n\n /** Valid paths are:\n * /bulk\n * /events/bulk/envId\n * /mobile\n */\n public readonly analyticsEventPath: string;\n\n /** Valid paths are:\n * /diagnostic\n * /events/diagnostic/envId\n * /mobile/events/diagnostic\n */\n public readonly diagnosticEventPath: string;\n\n // if true the sdk key will be included as authorization header\n public readonly includeAuthorizationHeader: boolean;\n\n public constructor(\n streaming: string,\n polling: string,\n events: string = ServiceEndpoints.DEFAULT_EVENTS,\n analyticsEventPath: string = '/bulk',\n diagnosticEventPath: string = '/diagnostic',\n includeAuthorizationHeader: boolean = true,\n payloadFilterKey?: string,\n ) {\n this.streaming = canonicalizeUri(streaming);\n this.polling = canonicalizeUri(polling);\n this.events = canonicalizeUri(events);\n this.analyticsEventPath = analyticsEventPath;\n this.diagnosticEventPath = diagnosticEventPath;\n this.includeAuthorizationHeader = includeAuthorizationHeader;\n this.payloadFilterKey = payloadFilterKey;\n }\n}\n\nfunction getWithParams(uri: string, parameters: { key: string; value: string }[] = []) {\n if (parameters.length === 0) {\n return uri;\n }\n\n const parts = parameters.map(({ key, value }) => `${key}=${value}`);\n return `${uri}?${parts.join('&')}`;\n}\n\n/**\n * Get the URI for the streaming endpoint.\n *\n * @param endpoints The service endpoints.\n * @param path The path to the resource, devoid of any query parameters or hrefs.\n * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.\n */\nexport function getStreamingUri(\n endpoints: ServiceEndpoints,\n path: string,\n parameters: { key: string; value: string }[],\n): string {\n const canonicalizedPath = canonicalizePath(path);\n\n const combinedParameters = [...parameters];\n if (endpoints.payloadFilterKey) {\n combinedParameters.push({ key: 'filter', value: endpoints.payloadFilterKey });\n }\n\n return getWithParams(`${endpoints.streaming}/${canonicalizedPath}`, combinedParameters);\n}\n\n/**\n * Get the URI for the polling endpoint.\n *\n * @param endpoints The service endpoints.\n * @param path The path to the resource, devoid of any query parameters or hrefs.\n * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.\n */\nexport function getPollingUri(\n endpoints: ServiceEndpoints,\n path: string,\n parameters: { key: string; value: string }[] = [],\n): string {\n const canonicalizedPath = canonicalizePath(path);\n\n const combinedParameters = [...parameters];\n if (endpoints.payloadFilterKey) {\n combinedParameters.push({ key: 'filter', value: endpoints.payloadFilterKey });\n }\n\n return getWithParams(`${endpoints.polling}/${canonicalizedPath}`, combinedParameters);\n}\n\n/**\n * Get the URI for the events endpoint.\n *\n * @param endpoints The service endpoints.\n * @param path The path to the resource, devoid of any query parameters or hrefs.\n * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.\n */\nexport function getEventsUri(\n endpoints: ServiceEndpoints,\n path: string,\n parameters: { key: string; value: string }[] = [],\n): string {\n const canonicalizedPath = canonicalizePath(path);\n\n return getWithParams(`${endpoints.events}/${canonicalizedPath}`, parameters);\n}\n","// These classes are of trivial complexity. If they become\n// more complex, then they could be independent files.\n/* eslint-disable max-classes-per-file */\n\nexport class LDUnexpectedResponseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyUnexpectedResponseError';\n }\n}\n\nexport class LDClientError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyClientError';\n }\n}\n\nexport class LDTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyTimeoutError';\n }\n}\n\n/**\n * Check if the HTTP error is recoverable. This will return false if a request\n * made with any payload could not recover. If the reason for the failure\n * is payload specific, for instance a payload that is too large, then\n * it could recover with a different payload.\n */\nexport function isHttpRecoverable(status: number) {\n if (status >= 400 && status < 500) {\n return status === 400 || status === 408 || status === 429;\n }\n return true;\n}\n\n/**\n * Returns true if the status could recover for a different payload.\n *\n * When used with event processing this indicates that we should discard\n * the payload, but that a subsequent payload may succeed. Therefore we should\n * not stop event processing.\n */\nexport function isHttpLocallyRecoverable(status: number) {\n if (status === 413) {\n return true;\n }\n return isHttpRecoverable(status);\n}\n","import { LDTimeoutError } from '../errors';\nimport { VoidFunction } from './VoidFunction';\n\n/**\n * Represents a timeout that can be cancelled.\n *\n * When racing a timeout, and another task completes before the timeout,\n * then the timeout should be cancelled. This prevents leaving open handles\n * which can stop the runtime from exiting.\n */\nexport interface CancelableTimeout {\n promise: Promise<void>;\n cancel: VoidFunction;\n}\n\n/**\n * Returns a promise which errors after t seconds.\n *\n * @param t Timeout in seconds.\n * @param taskName Name of task being timed for logging and error reporting.\n */\nexport function cancelableTimedPromise(t: number, taskName: string): CancelableTimeout {\n let timeout: ReturnType<typeof setTimeout>;\n let resolve: VoidFunction;\n const promise = new Promise<void>((_res, reject) => {\n resolve = _res;\n timeout = setTimeout(() => {\n const e = `${taskName} timed out after ${t} seconds.`;\n reject(new LDTimeoutError(e));\n }, t * 1000);\n });\n return {\n promise,\n cancel: () => {\n resolve();\n clearTimeout(timeout);\n },\n };\n}\n","export default function clone<T>(obj: any) {\n if (obj === undefined || obj === null) {\n return obj;\n }\n\n return JSON.parse(JSON.stringify(obj)) as T;\n}\n","// eslint-disable-next-line import/prefer-default-export\nexport function secondsToMillis(sec: number): number {\n return Math.trunc(sec * 1000);\n}\n","/**\n * Wait before calling the same function. Useful for expensive calls.\n * Adapted from https://amitd.co/code/typescript/debounce.\n *\n * @return The debounced function.\n *\n * @example\n *\n * ```js\n * const debouncedFunction = debounce(e => {\n * console.log(e);\n * }, 5000);\n *\n * // Console logs 'Hello world again ' after 5 seconds\n * debouncedFunction('Hello world');\n * debouncedFunction('Hello world again');\n * ```\n * @param fn The function to be debounced.\n * @param delayMs Defaults to 5 seconds.\n */\nconst debounce = <T extends (...args: any[]) => ReturnType<T>>(\n fn: T,\n delayMs: number = 5000,\n): ((...args: Parameters<T>) => void) => {\n let timer: ReturnType<typeof setTimeout>;\n\n return (...args: Parameters<T>) => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn(...args);\n }, delayMs);\n };\n};\n\nexport default debounce;\n","const isEmptyObject = (obj: any) => JSON.stringify(obj) === '{}';\n\nexport default isEmptyObject;\n","import isEmptyObject from './isEmptyObject';\n\n/**\n * Strips all falsy and empty {} from a given object. Returns a new object with only truthy values.\n * Sourced from below but modified to include checks for empty object and ignoring keys.\n * https://www.w3resource.com/javascript-exercises/javascript-array-exercise-47.php\n *\n * @param obj\n * @param ignoreKeys\n */\nconst deepCompact = <T extends Object>(obj?: T, ignoreKeys?: string[]) => {\n if (!obj) {\n return obj;\n }\n\n return Object.entries(obj).reduce((acc: any, [key, value]) => {\n if (Boolean(value) && !isEmptyObject(value) && !ignoreKeys?.includes(key)) {\n acc[key] = typeof value === 'object' ? deepCompact(value, ignoreKeys) : value;\n }\n return acc;\n }, {}) as T;\n};\n\nexport default deepCompact;\n","/* eslint-disable */\n// Ripped from https://github.com/epoberezkin/fast-deep-fastDeepEqual\n\n// {{? it.es6 }}\n// var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';\n// {{?}}\n\nexport default function fastDeepEqual(a: any, b: any) {\n if (a === b) return true;\n\n if (a && b && typeof a == 'object' && typeof b == 'object') {\n if (a.constructor !== b.constructor) return false;\n\n var length, i, keys;\n if (Array.isArray(a)) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0; ) if (!fastDeepEqual(a[i], b[i])) return false;\n return true;\n }\n\n // {{? it.es6 }}\n if (a instanceof Map && b instanceof Map) {\n if (a.size !== b.size) return false;\n for (i of a.entries()) if (!b.has(i[0])) return false;\n for (i of a.entries()) if (!fastDeepEqual(i[1], b.get(i[0]))) return false;\n return true;\n }\n\n if (a instanceof Set && b instanceof Set) {\n if (a.size !== b.size) return false;\n for (i of a.entries()) if (!b.has(i[0])) return false;\n return true;\n }\n\n if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {\n // @ts-ignore\n length = a.length;\n // @ts-ignore\n if (length != b.length) return false;\n for (i = length; i-- !== 0; ) {\n // @ts-ignore\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n // {{?}}\n\n if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;\n if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();\n if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();\n\n keys = Object.keys(a);\n length = keys.length;\n if (length !== Object.keys(b).length) return false;\n\n for (i = length; i-- !== 0; )\n if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;\n\n for (i = length; i-- !== 0; ) {\n var key = keys[i];\n // {{? it.react }}\n // if (key === '_owner' && a.$$typeof) {\n // // React-specific: avoid traversing React elements' _owner.\n // // _owner contains circular references\n // // and is not needed when comparing the actual elements (and not their owners)\n // continue;\n // }\n // {{?}}\n if (!fastDeepEqual(a[key], b[key])) return false;\n }\n\n return true;\n }\n\n // true if both NaN, false otherwise\n return a !== a && b !== b;\n}\n","import { Encoding, HttpErrorResponse, Info } from '../api';\nimport { isHttpRecoverable } from '../errors';\nimport { ApplicationTags } from '../options';\n\nexport type LDHeaders = {\n authorization?: string;\n 'user-agent'?: string;\n 'x-launchdarkly-user-agent'?: string;\n 'x-launchdarkly-wrapper'?: string;\n 'x-launchdarkly-tags'?: string;\n};\n\nexport function defaultHeaders(\n sdkKey: string,\n info: Info,\n tags?: ApplicationTags,\n includeAuthorizationHeader: boolean = true,\n userAgentHeaderName: 'user-agent' | 'x-launchdarkly-user-agent' = 'user-agent',\n): LDHeaders {\n const { userAgentBase, version, wrapperName, wrapperVersion } = info.sdkData();\n\n const headers: LDHeaders = {\n [userAgentHeaderName]: `${userAgentBase ?? 'NodeJSClient'}/${version}`,\n };\n\n // edge sdks sets this to false because they use the clientSideID\n // and they don't need the authorization header\n if (includeAuthorizationHeader) {\n headers.authorization = sdkKey;\n }\n\n if (wrapperName) {\n headers['x-launchdarkly-wrapper'] = wrapperVersion\n ? `${wrapperName}/${wrapperVersion}`\n : wrapperName;\n }\n\n if (tags?.value) {\n headers['x-launchdarkly-tags'] = tags.value;\n }\n\n return headers;\n}\n\nexport function httpErrorMessage(\n err: HttpErrorResponse,\n context: string,\n retryMessage?: string,\n): string {\n let desc;\n if (err.status) {\n desc = `error ${err.status}${err.status === 401 ? ' (invalid SDK key)' : ''}`;\n } else {\n desc = `I/O error (${err.message || 'unknown error'})`;\n }\n const action = retryMessage ?? 'giving up permanently';\n return `Received ${desc} for ${context} - ${action}`;\n}\n\nexport function shouldRetry({ status }: HttpErrorResponse) {\n return status ? isHttpRecoverable(status) : true;\n}\n\n/**\n * In react-native use base64-js to polyfill btoa. This is safe\n * because the react-native repo uses it too. Set the global.btoa to the encode\n * function of base64-js.\n * https://github.com/beatgammit/base64-js\n * https://github.com/axios/axios/issues/2235#issuecomment-512204616\n *\n * Ripped from https://thewoods.blog/base64url/\n */\nexport const base64UrlEncode = (s: string, encoding: Encoding): string =>\n encoding.btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n","export default () => {};\n","const sleep = async (delayMillis: number = 1000) =>\n new Promise((resolve) => {\n setTimeout(resolve, delayMillis);\n });\n\nexport default sleep;\n","import { LDTimeoutError } from '../errors';\n\n/**\n * Returns a promise which errors after t seconds.\n *\n * @param t Timeout in seconds.\n * @param taskName Name of task being timed for logging and error reporting.\n */\nconst timedPromise = (t: number, taskName: string) =>\n new Promise<void>((_res, reject) => {\n setTimeout(() => {\n const e = `${taskName} timed out after ${t} seconds.`;\n reject(new LDTimeoutError(e));\n }, t * 1000);\n });\n\nexport default timedPromise;\n","import { Platform } from '../../api';\nimport { DiagnosticId, DiagnosticInitEvent, DiagnosticStatsEvent, StreamInitData } from './types';\n\nexport default class DiagnosticsManager {\n private readonly _startTime: number;\n private _streamInits: StreamInitData[] = [];\n private readonly _id: DiagnosticId;\n private _dataSinceDate: number;\n\n constructor(\n sdkKey: string,\n private readonly _platform: Platform,\n private readonly _diagnosticInitConfig: any,\n ) {\n this._startTime = Date.now();\n this._dataSinceDate = this._startTime;\n this._id = {\n diagnosticId: _platform.crypto.randomUUID(),\n sdkKeySuffix: sdkKey.length > 6 ? sdkKey.substring(sdkKey.length - 6) : sdkKey,\n };\n }\n\n /**\n * Creates the initial event that is sent by the event processor when the SDK starts up. This will\n * not be repeated during the lifetime of the SDK client.\n */\n createInitEvent(): DiagnosticInitEvent {\n const sdkData = this._platform.info.sdkData();\n const platformData = this._platform.info.platformData();\n\n return {\n kind: 'diagnostic-init',\n id: this._id,\n creationDate: this._startTime,\n sdk: sdkData,\n configuration: this._diagnosticInitConfig,\n platform: {\n name: platformData.name,\n osArch: platformData.os?.arch,\n osName: platformData.os?.name,\n osVersion: platformData.os?.version,\n ...(platformData.additional || {}),\n },\n };\n }\n\n /**\n * Records a stream connection attempt (called by the stream processor).\n *\n * @param timestamp Time of the *beginning* of the connection attempt.\n * @param failed True if the connection failed, or we got a read timeout before receiving a \"put\".\n * @param durationMillis Elapsed time between starting timestamp and when we either gave up/lost\n * the connection or received a successful \"put\".\n */\n recordStreamInit(timestamp: number, failed: boolean, durationMillis: number) {\n const item = { timestamp, failed, durationMillis };\n this._streamInits.push(item);\n }\n\n /**\n * Creates a periodic event containing time-dependent stats, and resets the state of the manager\n * with regard to those stats.\n *\n * Note: the reason droppedEvents, deduplicatedUsers, and eventsInLastBatch are passed into this\n * function, instead of being properties of the DiagnosticsManager, is that the event processor is\n * the one who's calling this function and is also the one who's tracking those stats.\n */\n createStatsEventAndReset(\n droppedEvents: number,\n deduplicatedUsers: number,\n eventsInLastBatch: number,\n ): DiagnosticStatsEvent {\n const currentTime = Date.now();\n const evt: DiagnosticStatsEvent = {\n kind: 'diagnostic',\n id: this._id,\n creationDate: currentTime,\n dataSinceDate: this._dataSinceDate,\n droppedEvents,\n deduplicatedUsers,\n eventsInLastBatch,\n streamInits: this._streamInits,\n };\n\n this._streamInits = [];\n this._dataSinceDate = currentTime;\n return evt;\n }\n}\n","/**\n * Different kinds of error which may be encountered during evaluation.\n */\nenum ErrorKinds {\n MalformedFlag = 'MALFORMED_FLAG',\n UserNotSpecified = 'USER_NOT_SPECIFIED',\n FlagNotFound = 'FLAG_NOT_FOUND',\n ClientNotReady = 'CLIENT_NOT_READY',\n WrongType = 'WRONG_TYPE',\n}\n\nexport default ErrorKinds;\n","/**\n * Messages for issues which can be encountered processing client requests.\n */\nexport default class ClientMessages {\n static readonly MissingContextKeyNoEvent =\n 'Context was unspecified or had no key; event will not be sent';\n\n static invalidMetricValue(badType: string) {\n return (\n 'The track function was called with a non-numeric \"metricValue\"' +\n ` (${badType}), only numeric metric values are supported.`\n );\n }\n}\n","import { Crypto, Requests } from '../../api';\nimport {\n LDDeliveryStatus,\n LDEventSender,\n LDEventSenderResult,\n LDEventType,\n} from '../../api/subsystem';\nimport {\n isHttpLocallyRecoverable,\n isHttpRecoverable,\n LDUnexpectedResponseError,\n} from '../../errors';\nimport { ClientContext, getEventsUri } from '../../options';\nimport { httpErrorMessage, LDHeaders, sleep } from '../../utils';\n\nexport default class EventSender implements LDEventSender {\n private _crypto: Crypto;\n private _defaultHeaders: {\n [key: string]: string;\n };\n private _diagnosticEventsUri: string;\n private _eventsUri: string;\n private _requests: Requests;\n\n constructor(clientContext: ClientContext, baseHeaders: LDHeaders) {\n const { basicConfiguration, platform } = clientContext;\n const {\n serviceEndpoints: { analyticsEventPath, diagnosticEventPath },\n } = basicConfiguration;\n const { crypto, requests } = platform;\n\n this._defaultHeaders = { ...baseHeaders };\n this._eventsUri = getEventsUri(basicConfiguration.serviceEndpoints, analyticsEventPath, []);\n this._diagnosticEventsUri = getEventsUri(\n basicConfiguration.serviceEndpoints,\n diagnosticEventPath,\n [],\n );\n this._requests = requests;\n this._crypto = crypto;\n }\n\n private async _tryPostingEvents(\n events: any,\n uri: string,\n payloadId: string | undefined,\n canRetry: boolean,\n ): Promise<LDEventSenderResult> {\n const tryRes: LDEventSenderResult = {\n status: LDDeliveryStatus.Succeeded,\n };\n\n const headers: Record<string, string> = {\n ...this._defaultHeaders,\n 'content-type': 'application/json',\n };\n\n if (payloadId) {\n headers['x-launchdarkly-payload-id'] = payloadId;\n headers['x-launchDarkly-event-schema'] = '4';\n }\n let error;\n try {\n const { status, headers: resHeaders } = await this._requests.fetch(uri, {\n headers,\n body: JSON.stringify(events),\n compressBodyIfPossible: true,\n method: 'POST',\n // When sending events from browser environments the request should be completed even\n // if the user is navigating away from the page.\n keepalive: true,\n });\n\n const serverDate = Date.parse(resHeaders.get('date') || '');\n if (serverDate) {\n tryRes.serverTime = serverDate;\n }\n\n if (status <= 204) {\n return tryRes;\n }\n\n error = new LDUnexpectedResponseError(\n httpErrorMessage({ status, message: 'some events were dropped' }, 'event posting'),\n );\n\n if (!isHttpRecoverable(status)) {\n // If the HTTP request isn't recoverable. Meaning if we made the same request it\n // would not recover, then we check if a different request could recover.\n // If a different request could not recover, then we shutdown. If a different request could\n // recover, then we just don't retry this specific request.\n if (!isHttpLocallyRecoverable(status)) {\n tryRes.status = LDDeliveryStatus.FailedAndMustShutDown;\n } else {\n tryRes.status = LDDeliveryStatus.Failed;\n }\n tryRes.error = error;\n return tryRes;\n }\n } catch (err) {\n error = err;\n }\n\n // recoverable but not retrying\n if (error && !canRetry) {\n tryRes.status = LDDeliveryStatus.Failed;\n tryRes.error = error;\n return tryRes;\n }\n\n // wait 1 second before retrying\n await sleep();\n\n return this._tryPostingEvents(events, this._eventsUri, payloadId, false);\n }\n\n async sendEventData(type: LDEventType, data: any): Promise<LDEventSenderResult> {\n const payloadId = type === LDEventType.AnalyticsEvents ? this._crypto.randomUUID() : undefined;\n const uri = type === LDEventType.AnalyticsEvents ? this._eventsUri : this._diagnosticEventsUri;\n\n return this._tryPostingEvents(data, uri, payloadId, true);\n }\n}\n","import InputCustomEvent from './InputCustomEvent';\nimport InputEvalEvent from './InputEvalEvent';\nimport InputIdentifyEvent from './InputIdentifyEvent';\nimport InputMigrationEvent from './InputMigrationEvent';\n\nexport function isFeature(u: any): u is InputEvalEvent {\n return u.kind === 'feature';\n}\n\nexport function isCustom(u: any): u is InputCustomEvent {\n return u.kind === 'custom';\n}\n\nexport function isIdentify(u: any): u is InputIdentifyEvent {\n return u.kind === 'identify';\n}\n\nexport function isMigration(u: any): u is InputMigrationEvent {\n return u.kind === 'migration_op';\n}\n","/**\n * @internal\n */\nexport default class SummaryCounter {\n public readonly default: any;\n\n constructor(\n public count: number,\n public key: string,\n public value: any,\n defValue: any,\n public version?: number,\n public variation?: number,\n ) {\n this.default = defValue;\n }\n\n increment() {\n this.count += 1;\n }\n}\n","import Context from '../../Context';\nimport ContextFilter from '../../ContextFilter';\nimport { isFeature } from './guards';\nimport InputEvalEvent from './InputEvalEvent';\nimport InputEvent from './InputEvent';\nimport LDEventSummarizer, {\n FlagCounter,\n FlagSummary,\n SummarizedFlagsEvent,\n} from './LDEventSummarizer';\nimport SummaryCounter from './SummaryCounter';\n\nfunction counterKey(event: InputEvalEvent) {\n return `${event.key}:${\n event.variation !== null && event.variation !== undefined ? event.variation : ''\n }:${event.version !== null && event.version !== undefined ? event.version : ''}`;\n}\n\n/**\n * @internal\n */\nexport default class EventSummarizer implements LDEventSummarizer {\n private _startDate = 0;\n\n private _endDate = 0;\n\n private _counters: Record<string, SummaryCounter> = {};\n\n private _contextKinds: Record<string, Set<string>> = {};\n\n private _context?: Context;\n\n constructor(\n private readonly _singleContext: boolean = false,\n private readonly _contextFilter?: ContextFilter,\n ) {}\n\n summarizeEvent(event: InputEvent) {\n if (isFeature(event) && !event.excludeFromSummaries) {\n if (!this._context) {\n this._context = event.context;\n }\n const countKey = counterKey(event);\n const counter = this._counters[countKey];\n let kinds = this._contextKinds[event.key];\n if (!kinds) {\n kinds = new Set();\n this._contextKinds[event.key] = kinds;\n }\n event.context.kinds.forEach((kind) => kinds.add(kind));\n\n if (counter) {\n counter.increment();\n } else {\n this._counters[countKey] = new SummaryCounter(\n 1,\n event.key,\n event.value,\n event.default,\n event.version,\n event.variation,\n );\n }\n\n if (this._startDate === 0 || event.creationDate < this._startDate) {\n this._startDate = event.creationDate;\n }\n if (event.creationDate > this._endDate) {\n this._endDate = event.creationDate;\n }\n }\n }\n\n getSummary(): SummarizedFlagsEvent {\n const features = Object.values(this._counters).reduce(\n (acc: Record<string, FlagSummary>, counter) => {\n let flagSummary = acc[counter.key];\n if (!flagSummary) {\n flagSummary = {\n default: counter.default,\n counters: [],\n contextKinds: [...this._contextKinds[counter.key]],\n };\n acc[counter.key] = flagSummary;\n }\n\n const counterOut: FlagCounter = {\n value: counter.value,\n count: counter.count,\n };\n if (counter.variation !== undefined && counter.variation !== null) {\n counterOut.variation = counter.variation;\n }\n if (counter.version !== undefined && counter.version !== null) {\n counterOut.version = counter.version;\n } else {\n counterOut.unknown = true;\n }\n flagSummary.counters.push(counterOut);\n\n return acc;\n },\n {},\n );\n\n const event: SummarizedFlagsEvent = {\n startDate: this._startDate,\n endDate: this._endDate,\n features,\n kind: 'summary',\n context:\n this._context !== undefined && this._singleContext\n ? this._contextFilter?.filter(this._context)\n : undefined,\n };\n this._clearSummary();\n return event;\n }\n\n private _clearSummary() {\n this._startDate = 0;\n this._endDate = 0;\n this._counters = {};\n this._contextKinds = {};\n }\n}\n","export default class LDInvalidSDKKeyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyInvalidSDKKeyError';\n }\n}\n","import { LDLogger } from '../../api';\nimport ContextFilter from '../../ContextFilter';\nimport EventSummarizer from './EventSummarizer';\nimport { isFeature } from './guards';\nimport InputEvent from './InputEvent';\nimport { LDMultiEventSummarizer, SummarizedFlagsEvent } from './LDEventSummarizer';\n\nexport default class MultiEventSummarizer implements LDMultiEventSummarizer {\n constructor(\n private readonly _contextFilter: ContextFilter,\n private readonly _logger?: LDLogger,\n ) {}\n private _summarizers: Record<string, EventSummarizer> = {};\n\n summarizeEvent(event: InputEvent) {\n if (isFeature(event)) {\n const key = event.context.canonicalUnfilteredJson();\n if (!key) {\n if (event.context.valid) {\n // The context appeared valid, but it could not be hashed.\n // This is likely because of a cycle in the data.\n this._logger?.error('Unable to serialize context, likely the context contains a cycle.');\n }\n return;\n }\n\n let summarizer = this._summarizers[key];\n if (!summarizer) {\n this._summarizers[key] = new EventSummarizer(true, this._contextFilter);\n summarizer = this._summarizers[key];\n }\n\n summarizer.summarizeEvent(event);\n }\n }\n\n getSummaries(): SummarizedFlagsEvent[] {\n const summarizersToFlush = this._summarizers;\n this._summarizers = {};\n return Object.values(summarizersToFlush).map((summarizer) => summarizer.getSummary());\n }\n}\n","/**\n * The contents of this file are for event sampling. They are not used for\n * any purpose requiring cryptographic security.\n * */\n\nexport default function shouldSample(ratio: number) {\n const truncated = Math.trunc(ratio);\n // A radio of 1 means 1 in 1. So that will always sample. No need\n // to draw a random number.\n if (truncated === 1) {\n return true;\n }\n\n if (truncated === 0) {\n return false;\n }\n\n // Math.random() * truncated) would return 0, 1, ... (ratio - 1).\n // Checking for any number in the range will have approximately a 1 in X\n // chance. So we check for 0 as it is part of any range.\n return Math.floor(Math.random() * truncated) === 0;\n}\n","import { LDEvaluationReason, LDLogger } from '../../api';\nimport { LDDeliveryStatus, LDEventType } from '../../api/subsystem';\nimport LDContextDeduplicator from '../../api/subsystem/LDContextDeduplicator';\nimport LDEventProcessor from '../../api/subsystem/LDEventProcessor';\nimport AttributeReference from '../../AttributeReference';\nimport ContextFilter from '../../ContextFilter';\nimport { ClientContext } from '../../options';\nimport { LDHeaders } from '../../utils';\nimport { DiagnosticsManager } from '../diagnostics';\nimport EventSender from './EventSender';\nimport EventSummarizer from './EventSummarizer';\nimport { isFeature, isIdentify, isMigration } from './guards';\nimport InputEvent from './InputEvent';\nimport InputIdentifyEvent from './InputIdentifyEvent';\nimport InputMigrationEvent from './InputMigrationEvent';\nimport LDEventSummarizer, {\n LDMultiEventSummarizer,\n SummarizedFlagsEvent,\n} from './LDEventSummarizer';\nimport LDInvalidSDKKeyError from './LDInvalidSDKKeyError';\nimport MultiEventSummarizer from './MultiEventSummarizer';\nimport shouldSample from './sampling';\n\ntype FilteredContext = any;\n\n/**\n * Used for both identify and index.\n */\ninterface IdentifyOutputEvent {\n kind: 'identify' | 'index';\n creationDate: number;\n context: FilteredContext;\n samplingRatio?: number;\n}\n\ninterface CustomOutputEvent {\n kind: 'custom';\n creationDate: number;\n key: string;\n context: FilteredContext;\n data?: any;\n metricValue?: number;\n samplingRatio?: number;\n url?: string;\n}\n\ninterface FeatureOutputEvent {\n kind: 'feature' | 'debug';\n creationDate: number;\n key: string;\n value: any;\n default: any;\n prereqOf?: string;\n variation?: number;\n version?: number;\n reason?: LDEvaluationReason;\n context?: FilteredContext;\n contextKeys?: Record<string, string>;\n samplingRatio?: number;\n}\n\ninterface IndexInputEvent extends Omit<InputIdentifyEvent, 'kind'> {\n kind: 'index';\n}\n\ninterface ClickOutputEvent {\n kind: 'click';\n key: string;\n url: string;\n creationDate: number;\n contextKeys: Record<string, string>;\n selector: string;\n samplingRatio?: number;\n}\n\ninterface PageviewOutputEvent {\n kind: 'pageview';\n key: string;\n url: string;\n creationDate: number;\n contextKeys: Record<string, string>;\n samplingRatio?: number;\n}\n\n/**\n * The event processor doesn't need to know anything about the shape of the\n * diagnostic events.\n */\ntype DiagnosticEvent = any;\n\ninterface MigrationOutputEvent extends Omit<InputMigrationEvent, 'samplingRatio' | 'context'> {\n // Make the sampling ratio optional so we can omit it when it is one.\n samplingRatio?: number;\n // Context is optional because contextKeys is supported for backwards compatibility and may be provided instead of context.\n context?: FilteredContext;\n}\n\ntype OutputEvent =\n | IdentifyOutputEvent\n | CustomOutputEvent\n | FeatureOutputEvent\n | SummarizedFlagsEvent\n | DiagnosticEvent\n | MigrationOutputEvent;\n\nexport interface EventProcessorOptions {\n allAttributesPrivate: boolean;\n privateAttributes: string[];\n eventsCapacity: number;\n flushInterval: number;\n diagnosticRecordingInterval: number;\n}\n\nfunction isMultiEventSummarizer(summarizer: unknown): summarizer is LDMultiEventSummarizer {\n return (summarizer as LDMultiEventSummarizer).getSummaries !== undefined;\n}\n\nexport default class EventProcessor implements LDEventProcessor {\n private _eventSender: EventSender;\n private _summarizer: LDMultiEventSummarizer | LDEventSummarizer;\n private _queue: OutputEvent[] = [];\n private _lastKnownPastTime = 0;\n private _droppedEvents = 0;\n private _deduplicatedUsers = 0;\n private _exceededCapacity = false;\n private _eventsInLastBatch = 0;\n private _shutdown = false;\n private _capacity: number;\n private _logger?: LDLogger;\n private _contextFilter: ContextFilter;\n\n // Using any here, because setInterval handles are not the same\n // between node and web.\n private _diagnosticsTimer: any;\n private _flushTimer: any;\n private _flushUsersTimer: any = null;\n\n constructor(\n private readonly _config: EventProcessorOptions,\n clientContext: ClientContext,\n baseHeaders: LDHeaders,\n private readonly _contextDeduplicator?: LDContextDeduplicator,\n private readonly _diagnosticsManager?: DiagnosticsManager,\n start: boolean = true,\n summariesPerContext: boolean = false,\n ) {\n this._capacity = _config.eventsCapacity;\n this._logger = clientContext.basicConfiguration.logger;\n this._eventSender = new EventSender(clientContext, baseHeaders);\n\n this._contextFilter = new ContextFilter(\n _config.allAttributesPrivate,\n _config.privateAttributes.map((ref) => new AttributeReference(ref)),\n );\n\n if (summariesPerContext) {\n this._summarizer = new MultiEventSummarizer(this._contextFilter, this._logger);\n } else {\n this._summarizer = new EventSummarizer();\n }\n\n if (start) {\n this.start();\n }\n }\n\n start() {\n if (this._contextDeduplicator?.flushInterval !== undefined) {\n this._flushUsersTimer = setInterval(() => {\n this._contextDeduplicator?.flush();\n }, this._contextDeduplicator.flushInterval * 1000);\n }\n\n this._flushTimer = setInterval(async () => {\n try {\n await this.flush();\n } catch (e) {\n // Log errors and swallow them\n this._logger?.debug(`Flush failed: ${e}`);\n }\n }, this._config.flushInterval * 1000);\n\n if (this._diagnosticsManager) {\n const initEvent = this._diagnosticsManager!.createInitEvent();\n this._postDiagnosticEvent(initEvent);\n\n this._diagnosticsTimer = setInterval(() => {\n const statsEvent = this._diagnosticsManager!.createStatsEventAndReset(\n this._droppedEvents,\n this._deduplicatedUsers,\n this._eventsInLastBatch,\n );\n\n this._droppedEvents = 0;\n this._deduplicatedUsers = 0;\n\n this._postDiagnosticEvent(statsEvent);\n }, this._config.diagnosticRecordingInterval * 1000);\n }\n\n this._logger?.debug('Started EventProcessor.');\n }\n\n private _postDiagnosticEvent(event: DiagnosticEvent) {\n this._eventSender.sendEventData(LDEventType.DiagnosticEvent, event);\n }\n\n close() {\n clearInterval(this._flushTimer);\n if (this._flushUsersTimer) {\n clearInterval(this._flushUsersTimer);\n }\n if (this._diagnosticsTimer) {\n clearInterval(this._diagnosticsTimer);\n }\n }\n\n async flush(): Promise<void> {\n if (this._shutdown) {\n throw new LDInvalidSDKKeyError(\n 'Events cannot be posted because a permanent error has been encountered. ' +\n 'This is most likely an invalid SDK key. The specific error information ' +\n 'is logged independently.',\n );\n }\n\n const eventsToFlush = this._queue;\n this._queue = [];\n\n if (isMultiEventSummarizer(this._summarizer)) {\n const summaries = this._summarizer.getSummaries();\n\n summaries.forEach((summary) => {\n if (Object.keys(summary.features).length) {\n eventsToFlush.push(summary);\n }\n });\n } else {\n const summary = this._summarizer.getSummary();\n if (Object.keys(summary.features).length) {\n eventsToFlush.push(summary);\n }\n }\n\n if (!eventsToFlush.length) {\n return;\n }\n\n this._eventsInLastBatch = eventsToFlush.length;\n this._logger?.debug('Flushing %d events', eventsToFlush.length);\n await this._tryPostingEvents(eventsToFlush);\n }\n\n sendEvent(inputEvent: InputEvent) {\n if (this._shutdown) {\n return;\n }\n\n if (isMigration(inputEvent)) {\n // These conditions are not combined, because we always want to stop\n // processing at this point for a migration event. It cannot generate\n // an index event or debug event.\n if (shouldSample(inputEvent.samplingRatio)) {\n const migrationEvent: MigrationOutputEvent = {\n ...inputEvent,\n context: inputEvent.context ? this._contextFilter.filter(inputEvent.context) : undefined,\n };\n if (migrationEvent.samplingRatio === 1) {\n delete migrationEvent.samplingRatio;\n }\n this._enqueue(migrationEvent);\n }\n return;\n }\n\n this._summarizer.summarizeEvent(inputEvent);\n\n const isFeatureEvent = isFeature(inputEvent);\n\n const addFullEvent = (isFeatureEvent && inputEvent.trackEvents) || !isFeatureEvent;\n\n const addDebugEvent = this._shouldDebugEvent(inputEvent);\n\n const isIdentifyEvent = isIdentify(inputEvent);\n const shouldNotDeduplicate = this._contextDeduplicator?.processContext(inputEvent.context);\n\n // If there is no cache, then it will never be in the cache.\n if (!shouldNotDeduplicate) {\n if (!isIdentifyEvent) {\n this._deduplicatedUsers += 1;\n }\n }\n\n const addIndexEvent = shouldNotDeduplicate && !isIdentifyEvent;\n\n if (addIndexEvent) {\n this._enqueue(\n this._makeOutputEvent(\n {\n kind: 'index',\n creationDate: inputEvent.creationDate,\n context: inputEvent.context,\n samplingRatio: 1,\n },\n false,\n ),\n );\n }\n if (addFullEvent && shouldSample(inputEvent.samplingRatio)) {\n this._enqueue(this._makeOutputEvent(inputEvent, false));\n }\n if (addDebugEvent && shouldSample(inputEvent.samplingRatio)) {\n this._enqueue(this._makeOutputEvent(inputEvent, true));\n }\n }\n\n private _makeOutputEvent(event: InputEvent | IndexInputEvent, debug: boolean): OutputEvent {\n switch (event.kind) {\n case 'feature': {\n const out: FeatureOutputEvent = {\n kind: debug ? 'debug' : 'feature',\n creationDate: event.creationDate,\n context: this._contextFilter.filter(event.context, !debug),\n key: event.key,\n value: event.value,\n default: event.default,\n };\n if (event.samplingRatio !== 1) {\n out.samplingRatio = event.samplingRatio;\n }\n if (event.prereqOf) {\n out.prereqOf = event.prereqOf;\n }\n if (event.variation !== undefined) {\n out.variation = event.variation;\n }\n if (event.version !== undefined) {\n out.version = event.version;\n }\n if (event.reason) {\n out.reason = event.reason;\n }\n return out;\n }\n case 'index': // Intentional fallthrough.\n case 'identify': {\n const out: IdentifyOutputEvent = {\n kind: event.kind,\n creationDate: event.creationDate,\n context: this._contextFilter.filter(event.context),\n };\n if (event.samplingRatio !== 1) {\n out.samplingRatio = event.samplingRatio;\n }\n return out;\n }\n case 'custom': {\n const out: CustomOutputEvent = {\n kind: 'custom',\n creationDate: event.creationDate,\n key: event.key,\n context: this._contextFilter.filter(event.context),\n };\n\n if (event.samplingRatio !== 1) {\n out.samplingRatio = event.samplingRatio;\n }\n\n if (event.data !== undefined) {\n out.data = event.data;\n }\n if (event.metricValue !== undefined) {\n out.metricValue = event.metricValue;\n }\n\n if (event.url !== undefined) {\n out.url = event.url;\n }\n\n return out;\n }\n case 'click': {\n const out: ClickOutputEvent = {\n kind: 'click',\n creationDate: event.creationDate,\n contextKeys: event.context.kindsAndKeys,\n key: event.key,\n url: event.url,\n selector: event.selector,\n };\n return out;\n }\n case 'pageview': {\n const out: PageviewOutputEvent = {\n kind: 'pageview',\n creationDate: event.creationDate,\n contextKeys: event.context.kindsAndKeys,\n key: event.key,\n url: event.url,\n };\n return out;\n }\n default:\n // This would happen during the addition of a new event type to the SDK.\n return event;\n }\n }\n\n private _enqueue(event: OutputEvent) {\n if (this._queue.length < this._capacity) {\n this._queue.push(event);\n this._exceededCapacity = false;\n } else {\n if (!this._exceededCapacity) {\n this._exceededCapacity = true;\n this._logger?.warn(\n 'Exceeded event queue capacity. Increase capacity to avoid dropping events.',\n );\n }\n this._droppedEvents += 1;\n }\n }\n\n private _shouldDebugEvent(event: InputEvent) {\n return (\n isFeature(event) &&\n event.debugEventsUntilDate &&\n event.debugEventsUntilDate > this._lastKnownPastTime &&\n event.debugEventsUntilDate > Date.now()\n );\n }\n\n private async _tryPostingEvents(events: OutputEvent[] | OutputEvent): Promise<void> {\n const res = await this._eventSender.sendEventData(LDEventType.AnalyticsEvents, events);\n if (res.status === LDDeliveryStatus.FailedAndMustShutDown) {\n this._shutdown = true;\n }\n\n if (res.serverTime) {\n this._lastKnownPastTime = res.serverTime;\n }\n\n if (res.error) {\n throw res.error;\n }\n }\n}\n","import Context from '../../Context';\n\nexport default class InputCustomEvent {\n public readonly kind = 'custom';\n\n public readonly creationDate: number;\n\n constructor(\n public readonly context: Context,\n public readonly key: string,\n public readonly data?: any,\n public readonly metricValue?: number,\n // Currently custom events are not sampled, but this is here to make the handling\n // code more uniform.\n public readonly samplingRatio: number = 1,\n // Browser SDKs can include a URL for custom events.\n public readonly url?: string,\n ) {\n this.creationDate = Date.now();\n this.context = context;\n }\n}\n","import { LDEvaluationReason, LDFlagValue } from '../../api/data';\nimport Context from '../../Context';\n\nexport default class InputEvalEvent {\n public readonly kind = 'feature';\n\n public readonly creationDate: number;\n\n public readonly default: any;\n\n public readonly trackEvents?: boolean;\n\n public readonly debugEventsUntilDate?: number;\n\n public readonly prereqOf?: string;\n\n public readonly reason?: LDEvaluationReason;\n\n public readonly value: any;\n\n public readonly variation?: number;\n\n public readonly version?: number;\n\n public readonly excludeFromSummaries?: boolean;\n\n constructor(\n public readonly withReasons: boolean,\n public readonly context: Context,\n public readonly key: string,\n value: LDFlagValue,\n defValue: any, // default is a reserved keyword in this context.\n version?: number,\n variation?: number,\n trackEvents?: boolean,\n prereqOf?: string,\n reason?: LDEvaluationReason,\n debugEventsUntilDate?: number,\n excludeFromSummaries?: boolean,\n public readonly samplingRatio: number = 1,\n ) {\n this.creationDate = Date.now();\n this.value = value;\n this.default = defValue;\n\n if (version !== undefined) {\n this.version = version;\n }\n\n if (variation !== undefined) {\n this.variation = variation;\n }\n\n if (trackEvents !== undefined) {\n this.trackEvents = trackEvents;\n }\n\n if (prereqOf !== undefined) {\n this.prereqOf = prereqOf;\n }\n\n if (reason !== undefined) {\n this.reason = reason;\n }\n\n if (debugEventsUntilDate !== undefined) {\n this.debugEventsUntilDate = debugEventsUntilDate;\n }\n\n if (excludeFromSummaries !== undefined) {\n this.excludeFromSummaries = excludeFromSummaries;\n }\n }\n}\n","import Context from '../../Context';\n\nexport default class InputIdentifyEvent {\n public readonly kind = 'identify';\n\n public readonly creationDate: number;\n\n constructor(\n public readonly context: Context,\n public readonly samplingRatio: number = 1,\n ) {\n this.creationDate = Date.now();\n }\n}\n","import { LDEventProcessor } from '../../api/subsystem';\n\nexport default class NullEventProcessor implements LDEventProcessor {\n close() {}\n\n async flush(): Promise<void> {\n // empty comment to keep ts and eslint happy\n }\n\n sendEvent() {}\n}\n","import { LDEvaluationReason, LDFlagValue } from '../../api';\nimport Context from '../../Context';\nimport { InputCustomEvent, InputEvalEvent, InputIdentifyEvent } from '../events';\n\nexport type EvalEventArgs = {\n addExperimentData?: boolean;\n context: Context;\n debugEventsUntilDate?: number;\n defaultVal: any;\n excludeFromSummaries?: boolean;\n flagKey: string;\n prereqOfFlagKey?: string;\n reason?: LDEvaluationReason;\n samplingRatio?: number;\n trackEvents: boolean;\n value: LDFlagValue;\n variation?: number;\n version: number;\n};\n\nexport default class EventFactoryBase {\n constructor(private readonly _withReasons: boolean) {}\n\n evalEvent(e: EvalEventArgs): InputEvalEvent {\n return new InputEvalEvent(\n this._withReasons,\n e.context,\n e.flagKey,\n e.value,\n e.defaultVal,\n e.version,\n // Exclude null as a possibility.\n e.variation ?? undefined,\n e.trackEvents || e.addExperimentData,\n e.prereqOfFlagKey,\n this._withReasons || e.addExperimentData ? e.reason : undefined,\n e.debugEventsUntilDate,\n e.excludeFromSummaries,\n e.samplingRatio,\n );\n }\n\n unknownFlagEvent(key: string, defVal: LDFlagValue, context: Context) {\n return new InputEvalEvent(\n this._withReasons,\n context,\n key,\n defVal,\n defVal,\n // This isn't ideal, but the purpose of the factory is to at least\n // handle this situation.\n undefined, // version\n undefined, // variation index\n undefined, // track events\n undefined, // prereqOf\n undefined, // reason\n undefined, // debugEventsUntilDate\n undefined, // exclude from summaries\n undefined, // sampling ratio\n );\n }\n\n /* eslint-disable-next-line class-methods-use-this */\n identifyEvent(context: Context) {\n // Currently sampling for identify events is always 1.\n return new InputIdentifyEvent(context, 1);\n }\n\n /* eslint-disable-next-line class-methods-use-this */\n customEvent(\n key: string,\n context: Context,\n data?: any,\n metricValue?: number,\n samplingRatio: number = 1,\n ) {\n return new InputCustomEvent(\n context,\n key,\n data ?? undefined,\n metricValue ?? undefined,\n samplingRatio,\n );\n }\n}\n","import { PayloadProcessor } from './payloadProcessor';\nimport { Event } from './proto';\n\ninterface fdv1Payload {\n flags: { [name: string]: any };\n segments: { [name: string]: any };\n}\n\nconst PAYLOAD_ID = 'FDv1Fallback';\n\n/**\n * The FDv1PayloadAdaptor is a helper class that converts FDv1 payloads into events that the PayloadProcessor can understand.\n */\nexport interface FDv1PayloadAdaptor {\n /**\n * The PayloadProcessor that will be used to process the events.\n */\n readonly _processor: PayloadProcessor;\n\n /**\n * The selector that will be used to identify the payload.\n */\n _selector: string;\n\n /**\n * The method that will be used to set a selector for the payload that is\n * being processed.\n *\n * @remarks\n * This method probably shouldn't be used in most instances as FDv1 payloads\n * do not have the concept of a selector.\n *\n * @param selector - The selector to set for the payload.\n * @returns this FDv1PayloadAdaptor instance\n */\n useSelector: (selector: string) => FDv1PayloadAdaptor;\n\n /**\n * The method that will be used to process a full transfer changeset.\n *\n * @param data - The data to process.\n */\n processFullTransfer: (data: fdv1Payload) => void;\n}\n\nexport function fdv1PayloadAdaptor(processor: PayloadProcessor): FDv1PayloadAdaptor {\n return {\n _processor: processor,\n _selector: '',\n useSelector(selector: string): FDv1PayloadAdaptor {\n this._selector = selector;\n return this;\n },\n processFullTransfer(data) {\n const events: Array<Event> = [\n {\n event: 'server-intent',\n data: {\n payloads: [\n {\n id: PAYLOAD_ID,\n target: 1,\n intentCode: 'xfer-full',\n reason: 'payload-missing',\n },\n ],\n },\n },\n ];\n\n Object.entries(data?.flags || []).forEach(([key, flag]) => {\n events.push({\n event: 'put-object',\n data: {\n kind: 'flag',\n key,\n version: flag.version || 1,\n object: flag,\n },\n });\n });\n\n Object.entries(data?.segments || []).forEach(([key, segment]) => {\n events.push({\n event: 'put-object',\n data: {\n kind: 'segment',\n key,\n version: segment.version || 1,\n object: segment,\n },\n });\n });\n\n events.push({\n event: 'payload-transferred',\n data: {\n // IMPORTANT: the selector MUST be empty or \"live\" data synchronizers\n // will not work as it would try to resume from a bogus state.\n state: this._selector,\n version: 1,\n id: PAYLOAD_ID,\n },\n });\n\n this._processor.processEvents(events);\n },\n };\n}\n","/* eslint-disable no-underscore-dangle */\nimport { LDLogger } from '../../api';\nimport { DataSourceErrorKind } from '../../datasource';\nimport {\n DeleteObject,\n PayloadIntent,\n PayloadTransferred,\n PutObject,\n ServerIntentData,\n} from './proto';\n\n// Used to define object processing between deserialization and payload listener invocation. This can be\n// used provide object sanitization logic.\nexport interface ObjProcessors {\n [kind: string]: (object: any) => any;\n}\n\n// Represents a collection of events (one case where this is seen is in the polling response)\nexport interface FDv2EventsCollection {\n events: FDv2Event[];\n}\n\n// Represents a single event\nexport interface FDv2Event {\n event: string;\n data: any;\n}\n\n// Represents information for one keyed object.\nexport interface Update {\n kind: string;\n key: string;\n version: number;\n object?: any;\n deleted?: boolean;\n}\n\n// Represents a collection of updates from the FDv2 services. If basis is true, the set of updates represents the\n// complete state of the payload.\nexport interface Payload {\n id: string;\n version: number;\n state?: string;\n basis: boolean;\n updates: Update[];\n}\n\nexport type PayloadListener = (payload: Payload) => void;\n\n/**\n * A FDv2 PayloadProcessor can be used to parse payloads from a stream of FDv2 events. It will send payloads\n * to the PayloadListeners as the payloads are received. Invalid series of events may be dropped silently,\n * but the payload processor will continue to operate.\n */\nexport class PayloadProcessor {\n private _listeners: PayloadListener[] = [];\n\n private _tempId?: string = undefined;\n private _tempBasis: boolean = false;\n private _tempUpdates: Update[] = [];\n\n /**\n * Creates a PayloadProcessor\n *\n * @param _objProcessors defines object processors for each object kind.\n * @param _errorHandler that will be called with parsing errors as they are encountered\n * @param _logger for logging\n */\n constructor(\n private readonly _objProcessors: ObjProcessors,\n private readonly _errorHandler?: (errorKind: DataSourceErrorKind, message: string) => void,\n private readonly _logger?: LDLogger,\n ) {}\n\n addPayloadListener(listener: PayloadListener) {\n this._listeners.push(listener);\n }\n\n removePayloadListener(listener: PayloadListener) {\n const index = this._listeners.indexOf(listener, 0);\n if (index > -1) {\n this._listeners.splice(index, 1);\n }\n }\n\n /**\n * Gives the {@link PayloadProcessor} a series of events that it will statefully, incrementally process.\n * This may lead to listeners being invoked as necessary.\n * @param events to be processed (can be a single element)\n */\n processEvents(events: FDv2Event[]) {\n events.forEach((event) => {\n switch (event.event) {\n case 'server-intent': {\n this._processServerIntent(event.data);\n break;\n }\n case 'put-object': {\n this._processPutObject(event.data);\n break;\n }\n case 'delete-object': {\n this._processDeleteObject(event.data);\n break;\n }\n case 'payload-transferred': {\n this._processPayloadTransferred(event.data);\n break;\n }\n case 'goodbye': {\n this._processGoodbye(event.data);\n break;\n }\n case 'error': {\n this._processError(event.data);\n break;\n }\n default: {\n // no-op, unrecognized\n }\n }\n });\n }\n\n private _processObj(kind: string, jsonObj: any): any {\n return this._objProcessors[kind]?.(jsonObj);\n }\n\n private _processServerIntent = (data: ServerIntentData) => {\n // clear state in prep for handling data\n this._resetAll();\n\n // if there's no payloads, return\n if (!data.payloads.length) {\n return;\n }\n // at the time of writing this, it was agreed upon that SDKs could assume exactly 1 element in this list. In the future, a negotiation of protocol version will be required to remove this assumption.\n const payload = data.payloads[0];\n\n switch (payload?.intentCode) {\n case 'xfer-full':\n this._tempBasis = true;\n break;\n case 'xfer-changes':\n this._tempBasis = false;\n break;\n case 'none':\n this._tempBasis = false;\n this._processIntentNone(payload);\n break;\n default:\n // unrecognized intent code, return\n this._logger?.warn(`Unable to process intent code '${payload?.intentCode}'.`);\n return;\n }\n\n this._tempId = payload?.id;\n };\n\n private _processPutObject = (data: PutObject) => {\n // if the following properties haven't been provided by now, we should ignore the event\n if (\n !this._tempId || // server intent hasn't been received yet.\n !data.kind ||\n !data.key ||\n !data.version ||\n !data.object\n ) {\n return;\n }\n\n const obj = this._processObj(data.kind, data.object);\n if (!obj) {\n this._logger?.warn(`Unable to process object for kind: '${data.kind}'`);\n // ignore unrecognized kinds\n return;\n }\n\n this._tempUpdates.push({\n kind: data.kind,\n key: data.key,\n version: data.version,\n object: obj,\n // intentionally omit deleted for this put\n });\n };\n\n private _processDeleteObject = (data: DeleteObject) => {\n // if the following properties haven't been provided by now, we should ignore the event\n if (!this._tempId || !data.kind || !data.key || !data.version) {\n return;\n }\n\n this._tempUpdates.push({\n kind: data.kind,\n key: data.key,\n version: data.version,\n // intentionally omit object for this delete\n deleted: true,\n });\n };\n\n private _processIntentNone = (intent: PayloadIntent) => {\n // if the following properties aren't present ignore the event\n if (!intent.id || !intent.target) {\n return;\n }\n\n const payload: Payload = {\n id: intent.id,\n version: intent.target,\n basis: false, // intent none is always not a basis\n updates: [], // payload with no updates to hide the intent none concept from the consumer\n // note: state is absent here as that only appears in payload transferred events\n };\n\n this._listeners.forEach((it) => it(payload));\n this._resetAfterEmission();\n };\n\n private _processPayloadTransferred = (data: PayloadTransferred) => {\n // if the following properties haven't been provided by now, we should reset\n if (\n // server intent hasn't been received yet.\n !this._tempId ||\n // selector can be an empty string if we are using a file data initilizer\n data.state === null ||\n data.state === undefined ||\n !data.version\n ) {\n this._resetAll(); // a reset is best defensive action since payload transferred terminates a payload\n return;\n }\n\n const payload: Payload = {\n id: this._tempId!,\n version: data.version,\n state: data.state,\n basis: this._tempBasis,\n updates: this._tempUpdates,\n };\n\n this._listeners.forEach((it) => it(payload));\n this._resetAfterEmission();\n };\n\n private _processGoodbye = (data: any) => {\n this._logger?.info(\n `Goodbye was received from the LaunchDarkly connection with reason: ${data.reason}.`,\n );\n this._resetAll();\n };\n\n private _processError = (data: any) => {\n this._logger?.info(\n `An issue was encountered receiving updates for payload ${this._tempId} with reason: ${data.reason}.`,\n );\n this._resetAfterError();\n };\n\n private _resetAfterEmission() {\n this._tempBasis = false;\n this._tempUpdates = [];\n }\n\n private _resetAfterError() {\n this._tempUpdates = [];\n }\n\n private _resetAll() {\n this._tempId = undefined;\n this._tempBasis = false;\n this._tempUpdates = [];\n }\n}\n","/* eslint-disable no-underscore-dangle */\nimport { EventListener, EventName, LDLogger } from '../../api';\nimport { DataSourceErrorKind } from '../../datasource';\nimport { ObjProcessors, PayloadListener, PayloadProcessor } from './payloadProcessor';\n\n/**\n * Interface for an event stream. Only allows listening to events.\n */\nexport interface EventStream {\n addEventListener(type: EventName, listener: EventListener): void;\n}\n\n/**\n * A FDv2 PayloadStreamReader can be used to parse payloads from a stream of FDv2 events. See {@link PayloadProcessor}\n * for more details.\n */\nexport class PayloadStreamReader {\n private _payloadProcessor: PayloadProcessor;\n\n /**\n * Creates a PayloadStreamReader\n *\n * @param eventStream event stream of FDv2 events\n * @param _objProcessors defines object processors for each object kind.\n * @param _errorHandler that will be called with parsing errors as they are encountered\n * @param _logger for logging\n */\n constructor(\n eventStream: EventStream,\n _objProcessors: ObjProcessors,\n private readonly _errorHandler?: (errorKind: DataSourceErrorKind, message: string) => void,\n private readonly _logger?: LDLogger,\n ) {\n this._attachHandler(eventStream, 'server-intent');\n this._attachHandler(eventStream, 'put-object');\n this._attachHandler(eventStream, 'delete-object');\n this._attachHandler(eventStream, 'payload-transferred');\n this._attachHandler(eventStream, 'goodbye');\n this._attachHandler(eventStream, 'error');\n this._payloadProcessor = new PayloadProcessor(_objProcessors, _errorHandler, _logger);\n }\n\n addPayloadListener(listener: PayloadListener) {\n this._payloadProcessor.addPayloadListener(listener);\n }\n\n removePayloadListener(listener: PayloadListener) {\n this._payloadProcessor.removePayloadListener(listener);\n }\n\n private _attachHandler(stream: EventStream, eventName: string) {\n stream.addEventListener(eventName, async (event?: { data?: string }) => {\n if (event?.data) {\n this._logger?.debug(`Received ${eventName} event. Data is ${event.data}`);\n try {\n this._payloadProcessor.processEvents([\n { event: eventName, data: JSON.parse(event.data) },\n ]);\n } catch {\n this._logger?.error(\n `Stream received data that was unable to be processed in \"${eventName}\" message`,\n );\n this._logger?.debug(`Data follows: ${event.data}`);\n this._errorHandler?.(DataSourceErrorKind.InvalidData, 'Malformed data in EventStream.');\n }\n } else {\n this._errorHandler?.(DataSourceErrorKind.Unknown, 'Event from EventStream missing data.');\n }\n });\n }\n}\n","/**\n * Metadata used to initialize an LDFeatureStore.\n */\nexport interface InitMetadata {\n environmentId: string;\n}\n\n/**\n * Creates an InitMetadata object from initialization headers.\n *\n * @param initHeaders Initialization headers received when establishing\n * a streaming or polling connection to LD.\n * @returns InitMetadata object, or undefined if initHeaders is undefined\n * or missing the required header values.\n */\nexport function initMetadataFromHeaders(initHeaders?: {\n [key: string]: string;\n}): InitMetadata | undefined {\n if (initHeaders) {\n const envIdKey = Object.keys(initHeaders).find((key) => key.toLowerCase() === 'x-ld-envid');\n if (envIdKey) {\n return { environmentId: initHeaders[envIdKey] };\n }\n }\n return undefined;\n}\n","import { LDPluginBase } from '../../api/integrations/plugins';\nimport { LDLogger } from '../../api/logging/LDLogger';\n\nconst UNKNOWN_PLUGIN_NAME = 'unknown plugin';\n\nexport function safeGetName<TClient, THook>(\n logger: LDLogger,\n plugin: LDPluginBase<TClient, THook>,\n) {\n try {\n return plugin.getMetadata().name || UNKNOWN_PLUGIN_NAME;\n } catch {\n logger.error(`Exception thrown getting metadata for plugin. Unable to get plugin name.`);\n return UNKNOWN_PLUGIN_NAME;\n }\n}\n","import { LDPluginBase, LDPluginEnvironmentMetadata } from '../../api/integrations/plugins';\nimport { LDLogger } from '../../api/logging/LDLogger';\nimport { safeGetName } from './safeGetName';\n\nexport function safeGetHooks<TClient, THook>(\n logger: LDLogger,\n environmentMetadata: LDPluginEnvironmentMetadata,\n plugins: LDPluginBase<TClient, THook>[],\n): THook[] {\n const hooks: THook[] = [];\n plugins.forEach((plugin) => {\n try {\n const pluginHooks = plugin.getHooks?.(environmentMetadata);\n if (pluginHooks === undefined) {\n logger.error(`Plugin ${safeGetName(logger, plugin)} returned undefined from getHooks.`);\n } else if (pluginHooks && pluginHooks.length > 0) {\n hooks.push(...pluginHooks);\n }\n } catch (error) {\n logger.error(\n `Exception thrown getting hooks for plugin ${safeGetName(logger, plugin)}. Unable to get hooks.`,\n );\n }\n });\n return hooks;\n}\n","import { LDPluginBase, LDPluginEnvironmentMetadata } from '../../api/integrations/plugins';\nimport { LDLogger } from '../../api/logging/LDLogger';\nimport { safeGetName } from './safeGetName';\n\nexport function safeRegisterPlugins<TClient, THook>(\n logger: LDLogger,\n environmentMetadata: LDPluginEnvironmentMetadata,\n client: TClient,\n plugins: LDPluginBase<TClient, THook>[],\n): void {\n plugins.forEach((plugin) => {\n try {\n plugin.register(client, environmentMetadata);\n } catch (error) {\n logger.error(`Exception thrown registering plugin ${safeGetName(logger, plugin)}.`);\n }\n });\n}\n","import DataSourceStatusErrorInfo from './DataSourceStatusErrorInfo';\n\nexport enum DataSourceState {\n Initializing = 'INITIALIZING',\n Valid = 'VALID',\n Interrupted = 'INTERRUPTED',\n SetOffline = 'SET_OFFLINE',\n Closed = 'CLOSED',\n // TODO: SDK-702 - Implement network availability behaviors\n // NetworkUnavailable,\n}\n\nexport default interface DataSourceStatus {\n /**\n * An enumerated value representing the overall current state of the data source.\n */\n readonly state: DataSourceState;\n\n /**\n * The UNIX epoch timestamp in milliseconds that the value of State most recently changed.\n *\n * The meaning of this depends on the current state:\n * For {@link DataSourceState.Initializing}, it is the time that the datasource started\n * attempting to retrieve data.\n *\n * For {@link DataSourceState.Valid}, it is the time that the data source most\n * recently entered a valid state, after previously having been\n * {@link DataSourceStatus.Initializing} or an invalid state such as\n * {@link DataSourceState.Interrupted}.\n *\n * - For {@link DataSourceState.interrupted}, it is the time that the data source\n * most recently entered an error state, after previously having been\n * {@link DataSourceState.valid}.\n *\n * For {@link DataSourceState.Closed}, it is the time that the data source\n * encountered an unrecoverable error or that the datasource was explicitly closed.\n */\n readonly stateSince: number;\n\n /**\n * The last error encountered. May be absent after application restart.\n */\n readonly lastError?: DataSourceStatusErrorInfo;\n}\n","// eslint-disable-next-line max-classes-per-file\nimport {\n Encoding,\n getPollingUri,\n HttpErrorResponse,\n LDHeaders,\n Requests,\n ServiceEndpoints,\n} from '@launchdarkly/js-sdk-common';\n\nimport { DataSourcePaths } from './DataSourceConfig';\n\nfunction isOk(status: number) {\n return status >= 200 && status <= 299;\n}\n\nexport class LDRequestError extends Error implements HttpErrorResponse {\n public status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.status = status;\n this.name = 'LaunchDarklyRequestError';\n }\n}\n\n/**\n * Note: The requestor is implemented independently from polling such that it can be used to\n * make a one-off request.\n */\nexport default class Requestor {\n constructor(\n private _requests: Requests,\n private readonly _uri: string,\n private readonly _headers: { [key: string]: string },\n private readonly _method: string,\n private readonly _body?: string,\n ) {}\n\n async requestPayload(): Promise<string> {\n let status: number | undefined;\n try {\n const res = await this._requests.fetch(this._uri, {\n method: this._method,\n headers: this._headers,\n body: this._body,\n });\n if (isOk(res.status)) {\n return await res.text();\n }\n // Assigning so it can be thrown after the try/catch.\n status = res.status;\n } catch (err: any) {\n throw new LDRequestError(err?.message);\n }\n throw new LDRequestError(`Unexpected status code: ${status}`, status);\n }\n}\n\nexport function makeRequestor(\n plainContextString: string,\n serviceEndpoints: ServiceEndpoints,\n paths: DataSourcePaths,\n requests: Requests,\n encoding: Encoding,\n baseHeaders?: LDHeaders,\n baseQueryParams?: { key: string; value: string }[],\n withReasons?: boolean,\n useReport?: boolean,\n secureModeHash?: string,\n) {\n let body;\n let method = 'GET';\n const headers: { [key: string]: string } = { ...baseHeaders };\n\n if (useReport) {\n method = 'REPORT';\n headers['content-type'] = 'application/json';\n body = plainContextString; // context is in body for REPORT\n }\n\n const path = useReport\n ? paths.pathReport(encoding, plainContextString)\n : paths.pathGet(encoding, plainContextString);\n\n const parameters: { key: string; value: string }[] = [...(baseQueryParams ?? [])];\n if (withReasons) {\n parameters.push({ key: 'withReasons', value: 'true' });\n }\n if (secureModeHash) {\n parameters.push({ key: 'h', value: secureModeHash });\n }\n\n const uri = getPollingUri(serviceEndpoints, path, parameters);\n return new Requestor(requests, uri, headers, method, body);\n}\n","import { LDLogger } from '@launchdarkly/js-sdk-common';\n\n/**\n * Represents a task that has been shed from the queue.\n * This task will never be executed.\n */\nexport interface ShedTask {\n status: 'shed';\n}\n\n/**\n * Represents a task that has been ran to completion.\n */\nexport interface CompletedTask<TTaskResult> {\n status: 'complete';\n result: TTaskResult;\n}\n\n/**\n * Represents a task that has errored.\n */\nexport interface ErroredTask {\n status: 'error';\n error: Error;\n}\n\n/**\n * Represents the result of a task.\n */\nexport type TaskResult<TTaskResult> = CompletedTask<TTaskResult> | ErroredTask | ShedTask;\n\n/**\n * Represents a pending task. This encapsulates the async function that needs to be executed as well as a promise that represents its state.\n * The promise is not directly the promise associated with the async function, because we will not execute the async function until some point in the future, if at all.\n * */\ninterface PendingTask<TTaskResult> {\n sheddable: boolean;\n execute: () => void;\n shed: () => void;\n promise: Promise<TaskResult<TTaskResult>>;\n}\n\nexport interface Task<TTaskResult, TBeforeResult> {\n /**\n * Method ran before the task is executed or shed.\n */\n before?: () => Promise<TBeforeResult>;\n\n /**\n * Execute the task. This is not ran if the task is shed.\n * @returns The result of the task.\n */\n\n execute: (beforeResult?: TBeforeResult) => Promise<TTaskResult>;\n\n /**\n * Method ran after the task is executed or shed.\n * @param result The result of the task.\n */\n after?: (result: TaskResult<TTaskResult>, beforeResult?: TBeforeResult) => void;\n}\n\nconst duplicateExecutionError = new Error(\n 'Task has already been executed or shed. This is likely an implementation error. The task will not be executed again.',\n);\n\n/**\n * Creates a pending task.\n * @param task The async function to execute.\n * @param sheddable Whether the task can be shed from the queue.\n * @returns A pending task.\n */\nfunction makePending<TTaskResult, TBeforeResult = undefined>(\n task: Task<TTaskResult, TBeforeResult>,\n _logger?: LDLogger,\n sheddable: boolean = false,\n): PendingTask<TTaskResult> {\n let resolveTask: (value: TaskResult<TTaskResult>, beforeResult?: TBeforeResult) => void;\n\n const promise = new Promise<TaskResult<TTaskResult>>((resolve) => {\n resolveTask = (result, beforeResult) => {\n try {\n task.after?.(result, beforeResult);\n } catch (error) {\n _logger?.error(`Error in after callback: ${error}`);\n }\n resolve(result);\n };\n });\n\n const beforePromise = task.before ? task.before() : Promise.resolve(undefined);\n\n let executedOrShed = false;\n return {\n execute: () => {\n if (executedOrShed) {\n // This should never happen. If it does, then it represents an implementation error in the SDK.\n _logger?.error(duplicateExecutionError);\n }\n executedOrShed = true;\n\n beforePromise\n .then((beforeResult) => {\n task\n .execute(beforeResult)\n .then((result) => resolveTask({ status: 'complete', result }, beforeResult))\n .catch((error) => resolveTask({ status: 'error', error }, beforeResult));\n })\n .catch((error) => {\n _logger?.error(error);\n resolveTask({ status: 'error', error }, undefined);\n });\n },\n shed: () => {\n if (executedOrShed) {\n // This should never happen. If it does, then it represents an implementation error in the SDK.\n _logger?.error(duplicateExecutionError);\n }\n executedOrShed = true;\n beforePromise.then((beforeResult) => {\n resolveTask({ status: 'shed' }, beforeResult);\n });\n },\n promise,\n sheddable,\n };\n}\n\n/**\n * An asynchronous task queue with the ability to replace pending tasks.\n *\n * This is useful when you have asynchronous operations which much execute in order, and for cases where intermediate\n * operations can be discarded.\n *\n * For instance, the SDK can only have one active context at a time, if you request identification of many contexts,\n * then the ultimate state will be based on the last request. The intermediate identifies can be discarded.\n *\n * This queue will always begin execution of the first item added to the queue, at that point the item itself is not\n * queued, but active. If another request is made while that item is still active, then it is added to the queue.\n * A third request would then replace the second request if the second request had not yet become active, and it was\n * sheddable.\n *\n * Once a task is active the queue will complete it. It doesn't cancel tasks that it has started, but it can shed tasks\n * that have not started.\n *\n * TTaskResult Is the return type of the task to be executed. Tasks accept no parameters. So if you need parameters\n * you should use a lambda to capture them.\n *\n * Exceptions from tasks are always handled and the execute method will never reject a promise.\n *\n * Queue management should be done synchronously. There should not be asynchronous operations between checking the queue\n * and acting on the results of said check.\n */\nexport function createAsyncTaskQueue<TTaskResult>(logger?: LDLogger) {\n let activeTask: Promise<TaskResult<TTaskResult>> | undefined;\n const queue: PendingTask<TTaskResult>[] = [];\n\n function checkPending() {\n // There is an existing active task, so we don't need to do anything.\n if (activeTask) {\n return;\n }\n\n // There are pending tasks, so we need to execute the next one.\n if (queue.length > 0) {\n const nextTask = queue.shift()!;\n\n activeTask = nextTask.promise.finally(() => {\n activeTask = undefined;\n checkPending();\n });\n\n nextTask.execute();\n }\n }\n\n return {\n /**\n * Execute a task using the queue.\n *\n * @param task The async function to execute.\n * @param sheddable Whether the task can be shed from the queue.\n * @returns A promise that resolves to the result of the task.\n */\n execute<TBeforeResult>(\n task: Task<TTaskResult, TBeforeResult>,\n sheddable: boolean = false,\n ): Promise<TaskResult<TTaskResult>> {\n const pending = makePending(task, logger, sheddable);\n\n if (!activeTask) {\n activeTask = pending.promise.finally(() => {\n activeTask = undefined;\n checkPending();\n });\n pending.execute();\n } else {\n // If the last pending task is sheddable, we need to shed it before adding the new task.\n if (queue[queue.length - 1]?.sheddable) {\n queue.pop()?.shed();\n }\n queue.push(pending);\n }\n\n return pending.promise;\n },\n\n /**\n * Returns the number of pending tasks in the queue.\n * Intended for testing purposes only.\n *\n * @internal\n * @returns The number of pending tasks in the queue.\n */\n pendingCount(): number {\n return queue.length;\n },\n };\n}\n","// eslint-disable-next-line max-classes-per-file\nimport { TypeValidator, TypeValidators } from '@launchdarkly/js-sdk-common';\n\nimport { type LDOptions } from '../api';\n\nconst validators: Record<keyof LDOptions, TypeValidator> = {\n logger: TypeValidators.Object,\n maxCachedContexts: TypeValidators.numberWithMin(0),\n\n baseUri: TypeValidators.String,\n streamUri: TypeValidators.String,\n eventsUri: TypeValidators.String,\n\n capacity: TypeValidators.numberWithMin(1),\n diagnosticRecordingInterval: TypeValidators.numberWithMin(2),\n flushInterval: TypeValidators.numberWithMin(2),\n streamInitialReconnectDelay: TypeValidators.numberWithMin(0),\n\n allAttributesPrivate: TypeValidators.Boolean,\n debug: TypeValidators.Boolean,\n diagnosticOptOut: TypeValidators.Boolean,\n withReasons: TypeValidators.Boolean,\n sendEvents: TypeValidators.Boolean,\n\n pollInterval: TypeValidators.numberWithMin(30),\n\n useReport: TypeValidators.Boolean,\n\n privateAttributes: TypeValidators.StringArray,\n\n applicationInfo: TypeValidators.Object,\n wrapperName: TypeValidators.String,\n wrapperVersion: TypeValidators.String,\n payloadFilterKey: TypeValidators.stringMatchingRegex(/^[a-zA-Z0-9](\\w|\\.|-)*$/),\n hooks: TypeValidators.createTypeArray('Hook[]', {}),\n inspectors: TypeValidators.createTypeArray('LDInspection', {}),\n};\n\nexport default validators;\n","import {\n ApplicationTags,\n createSafeLogger,\n internal,\n LDFlagSet,\n LDLogger,\n LDPluginEnvironmentMetadata,\n NumberWithMinimum,\n OptionMessages,\n SafeLogger,\n ServiceEndpoints,\n TypeValidators,\n} from '@launchdarkly/js-sdk-common';\n\nimport { Hook, type LDOptions } from '../api';\nimport { LDInspection } from '../api/LDInspection';\nimport validators from './validators';\n\nconst DEFAULT_POLLING_INTERVAL: number = 60 * 5;\n\nexport interface LDClientInternalOptions extends internal.LDInternalOptions {\n trackEventModifier?: (event: internal.InputCustomEvent) => internal.InputCustomEvent;\n getImplementationHooks: (environmentMetadata: LDPluginEnvironmentMetadata) => Hook[];\n credentialType: 'clientSideId' | 'mobileKey';\n}\n\nexport interface Configuration {\n readonly logger: LDLogger;\n readonly maxCachedContexts: number;\n readonly capacity: number;\n readonly diagnosticRecordingInterval: number;\n readonly flushInterval: number;\n readonly streamInitialReconnectDelay: number;\n readonly allAttributesPrivate: boolean;\n readonly debug: boolean;\n readonly diagnosticOptOut: boolean;\n readonly sendEvents: boolean;\n readonly sendLDHeaders: boolean;\n readonly useReport: boolean;\n readonly withReasons: boolean;\n readonly privateAttributes: string[];\n readonly tags: ApplicationTags;\n readonly applicationInfo?: {\n id?: string;\n version?: string;\n name?: string;\n versionName?: string;\n };\n readonly bootstrap?: LDFlagSet;\n readonly requestHeaderTransform?: (headers: Map<string, string>) => Map<string, string>;\n readonly stream?: boolean;\n readonly hash?: string;\n readonly wrapperName?: string;\n readonly wrapperVersion?: string;\n readonly serviceEndpoints: ServiceEndpoints;\n readonly pollInterval: number;\n readonly userAgentHeaderName: 'user-agent' | 'x-launchdarkly-user-agent';\n readonly trackEventModifier: (event: internal.InputCustomEvent) => internal.InputCustomEvent;\n readonly hooks: Hook[];\n readonly inspectors: LDInspection[];\n readonly credentialType: 'clientSideId' | 'mobileKey';\n readonly getImplementationHooks: (environmentMetadata: LDPluginEnvironmentMetadata) => Hook[];\n}\n\nconst DEFAULT_POLLING: string = 'https://clientsdk.launchdarkly.com';\nconst DEFAULT_STREAM: string = 'https://clientstream.launchdarkly.com';\n\nexport { DEFAULT_POLLING, DEFAULT_STREAM };\n\nfunction ensureSafeLogger(logger?: LDLogger): LDLogger {\n if (logger instanceof SafeLogger) {\n return logger;\n }\n // Even if logger is not defined this will produce a valid logger.\n return createSafeLogger(logger);\n}\n\nexport default class ConfigurationImpl implements Configuration {\n public readonly logger: LDLogger = createSafeLogger();\n\n // Naming conventions is not followed for these lines because the config validation\n // accesses members based on the keys of the options. (sdk-763)\n // eslint-disable-next-line @typescript-eslint/naming-convention\n private readonly baseUri = DEFAULT_POLLING;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n private readonly eventsUri = ServiceEndpoints.DEFAULT_EVENTS;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n private readonly streamUri = DEFAULT_STREAM;\n\n public readonly maxCachedContexts = 5;\n\n public readonly capacity = 100;\n public readonly diagnosticRecordingInterval = 900;\n public readonly flushInterval = 30;\n public readonly streamInitialReconnectDelay = 1;\n\n public readonly allAttributesPrivate: boolean = false;\n public readonly debug: boolean = false;\n public readonly diagnosticOptOut: boolean = false;\n public readonly sendEvents: boolean = true;\n public readonly sendLDHeaders: boolean = true;\n\n public readonly useReport: boolean = false;\n public readonly withReasons: boolean = false;\n\n public readonly privateAttributes: string[] = [];\n\n public readonly tags: ApplicationTags;\n public readonly applicationInfo?: {\n id?: string;\n version?: string;\n name?: string;\n versionName?: string;\n };\n public readonly bootstrap?: LDFlagSet;\n\n // TODO: implement requestHeaderTransform\n public readonly requestHeaderTransform?: (headers: Map<string, string>) => Map<string, string>;\n public readonly stream?: boolean;\n public readonly hash?: string;\n public readonly wrapperName?: string;\n public readonly wrapperVersion?: string;\n\n public readonly serviceEndpoints: ServiceEndpoints;\n\n public readonly pollInterval: number = DEFAULT_POLLING_INTERVAL;\n\n public readonly userAgentHeaderName: 'user-agent' | 'x-launchdarkly-user-agent';\n\n public readonly hooks: Hook[] = [];\n\n public readonly inspectors: LDInspection[] = [];\n\n public readonly trackEventModifier: (\n event: internal.InputCustomEvent,\n ) => internal.InputCustomEvent;\n\n public readonly credentialType: 'clientSideId' | 'mobileKey';\n public readonly getImplementationHooks: (\n environmentMetadata: LDPluginEnvironmentMetadata,\n ) => Hook[];\n\n // Allow indexing Configuration by a string\n [index: string]: any;\n\n constructor(\n pristineOptions: LDOptions = {},\n internalOptions: LDClientInternalOptions = {\n getImplementationHooks: () => [],\n credentialType: 'mobileKey',\n },\n ) {\n this.logger = ensureSafeLogger(pristineOptions.logger);\n const errors = this._validateTypesAndNames(pristineOptions);\n errors.forEach((e: string) => this.logger.warn(e));\n\n this.serviceEndpoints = new ServiceEndpoints(\n this.streamUri,\n this.baseUri,\n this.eventsUri,\n internalOptions.analyticsEventPath,\n internalOptions.diagnosticEventPath,\n internalOptions.includeAuthorizationHeader,\n pristineOptions.payloadFilterKey,\n );\n this.useReport = pristineOptions.useReport ?? false;\n\n this.tags = new ApplicationTags({ application: this.applicationInfo, logger: this.logger });\n this.userAgentHeaderName = internalOptions.userAgentHeaderName ?? 'user-agent';\n this.trackEventModifier = internalOptions.trackEventModifier ?? ((event) => event);\n\n this.credentialType = internalOptions.credentialType;\n this.getImplementationHooks = internalOptions.getImplementationHooks;\n }\n\n private _validateTypesAndNames(pristineOptions: LDOptions): string[] {\n const errors: string[] = [];\n\n Object.entries(pristineOptions).forEach(([k, v]) => {\n const validator = validators[k as keyof LDOptions];\n\n if (validator) {\n if (!validator.is(v)) {\n const validatorType = validator.getType();\n\n if (validatorType === 'boolean') {\n errors.push(OptionMessages.wrongOptionTypeBoolean(k, typeof v));\n this[k] = !!v;\n } else if (validatorType === 'boolean | undefined | null') {\n errors.push(OptionMessages.wrongOptionTypeBoolean(k, typeof v));\n\n if (typeof v !== 'boolean' && typeof v !== 'undefined' && v !== null) {\n this[k] = !!v;\n }\n } else if (validator instanceof NumberWithMinimum && TypeValidators.Number.is(v)) {\n const { min } = validator as NumberWithMinimum;\n errors.push(OptionMessages.optionBelowMinimum(k, v, min));\n this[k] = min;\n } else {\n errors.push(OptionMessages.wrongOptionType(k, validator.getType(), typeof v));\n }\n } else if (k === 'logger') {\n // Logger already assigned.\n } else {\n // if an option is explicitly null, coerce to undefined\n this[k] = v ?? undefined;\n }\n } else {\n errors.push(OptionMessages.unknownOption(k));\n }\n });\n\n return errors;\n }\n}\n","import { Hasher } from '@launchdarkly/js-sdk-common';\n\nexport default async function digest(hasher: Hasher, encoding: string): Promise<string> {\n if (hasher.digest) {\n return hasher.digest(encoding);\n }\n if (hasher.asyncDigest) {\n return hasher.asyncDigest(encoding);\n }\n // This represents an error in platform implementation.\n throw new Error('Platform must implement digest or asyncDigest');\n}\n","import { Platform } from '@launchdarkly/js-sdk-common';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { namespaceForGeneratedContextKey } from './namespaceUtils';\n\n/**\n * This function will retrieve a previously generated key for the given {@link storageKey} if it\n * exists or generate and store one on the fly if it does not already exist.\n * @param storageKey keyed storage location where the generated key should live. See {@link namespaceForGeneratedContextKey}\n * for related exmaples of generating a storage key and usage.\n * @param platform crypto and storage implementations for necessary operations\n * @returns the generated key\n */\nexport const getOrGenerateKey = async (storageKey: string, { crypto, storage }: Platform) => {\n let generatedKey = await storage?.get(storageKey);\n\n if (!generatedKey) {\n generatedKey = crypto.randomUUID();\n await storage?.set(storageKey, generatedKey);\n }\n\n return generatedKey;\n};\n","import { Context, Crypto } from '@launchdarkly/js-sdk-common';\n\nimport digest from '../crypto/digest';\n\nexport type Namespace = 'LaunchDarkly' | 'AnonymousKeys' | 'ContextKeys' | 'ContextIndex';\n\n/**\n * Hashes the input and encodes it as base64\n */\nfunction hashAndBase64Encode(crypto: Crypto): (input: string) => Promise<string> {\n return async (input) => digest(crypto.createHash('sha256').update(input), 'base64');\n}\n\nconst noop = async (input: string) => input; // no-op transform\n\nexport async function concatNamespacesAndValues(\n parts: { value: Namespace | string; transform: (value: string) => Promise<string> }[],\n): Promise<string> {\n const processedParts = await Promise.all(parts.map((part) => part.transform(part.value))); // use the transform from each part to transform the value\n return processedParts.join('_');\n}\n\nexport async function namespaceForEnvironment(crypto: Crypto, sdkKey: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: 'LaunchDarkly', transform: noop },\n { value: sdkKey, transform: hashAndBase64Encode(crypto) }, // hash sdk key and encode it\n ]);\n}\n\n/**\n * @deprecated prefer {@link namespaceForGeneratedContextKey}. At one time we only generated keys for\n * anonymous contexts and they were namespaced in LaunchDarkly_AnonymousKeys. Eventually we started\n * generating context keys for non-anonymous contexts such as for the Auto Environment Attributes\n * feature and those were namespaced in LaunchDarkly_ContextKeys. This function can be removed\n * when the data under the LaunchDarkly_AnonymousKeys namespace is merged with data under the\n * LaunchDarkly_ContextKeys namespace.\n */\nexport async function namespaceForAnonymousGeneratedContextKey(kind: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: 'LaunchDarkly', transform: noop },\n { value: 'AnonymousKeys', transform: noop },\n { value: kind, transform: noop }, // existing SDKs are not hashing or encoding this kind, though they should have\n ]);\n}\n\nexport async function namespaceForGeneratedContextKey(kind: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: 'LaunchDarkly', transform: noop },\n { value: 'ContextKeys', transform: noop },\n { value: kind, transform: noop }, // existing SDKs are not hashing or encoding this kind, though they should have\n ]);\n}\n\nexport async function namespaceForContextIndex(environmentNamespace: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: environmentNamespace, transform: noop },\n { value: 'ContextIndex', transform: noop },\n ]);\n}\n\nexport async function namespaceForContextData(\n crypto: Crypto,\n environmentNamespace: string,\n context: Context,\n): Promise<string> {\n return concatNamespacesAndValues([\n { value: environmentNamespace, transform: noop }, // use existing namespace as is, don't transform\n { value: context.canonicalKey, transform: hashAndBase64Encode(crypto) }, // hash and encode canonical key\n ]);\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport {\n deepCompact,\n internal,\n LDApplication,\n LDContext,\n LDDevice,\n LDMultiKindContext,\n LDSingleKindContext,\n LDUser,\n Platform,\n} from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\nimport digest from '../crypto/digest';\nimport { getOrGenerateKey } from '../storage/getOrGenerateKey';\nimport { namespaceForGeneratedContextKey } from '../storage/namespaceUtils';\n\nconst { isLegacyUser, isSingleKind, isMultiKind } = internal;\nconst defaultAutoEnvSchemaVersion = '1.0';\n\nexport const toMulti = (c: LDSingleKindContext) => {\n const { kind, ...contextCommon } = c;\n\n return {\n kind: 'multi',\n [kind]: contextCommon,\n };\n};\n\n/**\n * Clones the LDApplication object and populates the key, envAttributesVersion, id and version fields.\n *\n * @param crypto\n * @param info\n * @param applicationInfo\n * @param config\n * @return An LDApplication object with populated key, envAttributesVersion, id and version.\n */\nexport const addApplicationInfo = async (\n { crypto, info }: Platform,\n { applicationInfo }: Configuration,\n): Promise<LDApplication | undefined> => {\n const { ld_application } = info.platformData();\n let app = deepCompact<LDApplication>(ld_application) ?? ({} as LDApplication);\n const id = applicationInfo?.id || app?.id;\n\n if (id) {\n const version = applicationInfo?.version || app?.version;\n const name = applicationInfo?.name || app?.name;\n const versionName = applicationInfo?.versionName || app?.versionName;\n\n app = {\n ...app,\n id,\n // only add props if they are defined\n ...(version ? { version } : {}),\n ...(name ? { name } : {}),\n ...(versionName ? { versionName } : {}),\n };\n\n app.key = await digest(crypto.createHash('sha256').update(id), 'base64');\n app.envAttributesVersion = app.envAttributesVersion || defaultAutoEnvSchemaVersion;\n\n return app;\n }\n\n return undefined;\n};\n\n/**\n * Clones the LDDevice object and populates the key and envAttributesVersion field.\n *\n * @param platform\n * @return An LDDevice object with populated key and envAttributesVersion.\n */\nexport const addDeviceInfo = async (platform: Platform) => {\n const { ld_device, os } = platform.info.platformData();\n const device = deepCompact<LDDevice>(ld_device) ?? ({} as LDDevice);\n\n const name = os?.name || device.os?.name;\n const version = os?.version || device.os?.version;\n const family = device.os?.family;\n\n // only add device.os if there's data\n if (name || version || family) {\n device.os = {\n // only add props if they are defined\n ...(name ? { name } : {}),\n ...(version ? { version } : {}),\n ...(family ? { family } : {}),\n };\n }\n\n // Check if device has any meaningful data before we return it.\n if (Object.keys(device).filter((k) => k !== 'key' && k !== 'envAttributesVersion').length) {\n const ldDeviceNamespace = await namespaceForGeneratedContextKey('ld_device');\n device.key = await getOrGenerateKey(ldDeviceNamespace, platform);\n device.envAttributesVersion = device.envAttributesVersion || defaultAutoEnvSchemaVersion;\n return device;\n }\n\n return undefined;\n};\n\nexport const addAutoEnv = async (\n context: LDContext,\n platform: Platform,\n config: Configuration,\n): Promise<LDContext> => {\n // LDUser is not supported for auto env reporting\n if (isLegacyUser(context)) {\n return context as LDUser;\n }\n\n let ld_application: LDApplication | undefined;\n let ld_device: LDDevice | undefined;\n\n // Check if customer contexts exist. Only override if they are not provided.\n if (\n (isSingleKind(context) && context.kind !== 'ld_application') ||\n (isMultiKind(context) && !context.ld_application)\n ) {\n ld_application = await addApplicationInfo(platform, config);\n } else {\n config.logger.warn(\n 'Not adding ld_application environment attributes because it already exists.',\n );\n }\n\n if (\n (isSingleKind(context) && context.kind !== 'ld_device') ||\n (isMultiKind(context) && !context.ld_device)\n ) {\n ld_device = await addDeviceInfo(platform);\n } else {\n config.logger.warn('Not adding ld_device environment attributes because it already exists.');\n }\n\n // Unable to automatically add environment attributes for kind: {}. {} already exists.\n\n if (ld_application || ld_device) {\n const multi = isSingleKind(context) ? toMulti(context) : context;\n\n return {\n ...multi,\n ...(ld_application ? { ld_application } : {}),\n ...(ld_device ? { ld_device } : {}),\n } as LDMultiKindContext;\n }\n\n return context;\n};\n","import {\n clone,\n internal,\n LDContext,\n LDContextCommon,\n LDMultiKindContext,\n LDSingleKindContext,\n LDUser,\n Platform,\n} from '@launchdarkly/js-sdk-common';\n\nimport { getOrGenerateKey } from '../storage/getOrGenerateKey';\nimport { namespaceForAnonymousGeneratedContextKey } from '../storage/namespaceUtils';\n\nconst { isLegacyUser, isMultiKind, isSingleKind } = internal;\n\n/**\n * This is the root ensureKey function. All other ensureKey functions reduce to this.\n *\n * - ensureKeyCommon // private root function\n * - ensureKeySingle\n * - ensureKeyMulti\n * - ensureKeyLegacy\n * - ensureKey // exported for external use\n *\n * @param kind The LDContext kind\n * @param c The LDContext object\n * @param platform Platform containing crypto and storage needed for storing and querying keys.\n */\nconst ensureKeyCommon = async (kind: string, c: LDContextCommon, platform: Platform) => {\n const { anonymous, key } = c;\n\n if (anonymous && !key) {\n const storageKey = await namespaceForAnonymousGeneratedContextKey(kind);\n // This mutates a cloned copy of the original context from ensureyKey so this is safe.\n // eslint-disable-next-line no-param-reassign\n c.key = await getOrGenerateKey(storageKey, platform);\n }\n};\n\nconst ensureKeySingle = async (c: LDSingleKindContext, platform: Platform) => {\n await ensureKeyCommon(c.kind, c, platform);\n};\n\nconst ensureKeyMulti = async (multiContext: LDMultiKindContext, platform: Platform) => {\n const { kind, ...singleContexts } = multiContext;\n\n return Promise.all(\n Object.entries(singleContexts).map(([k, c]) =>\n ensureKeyCommon(k, c as LDContextCommon, platform),\n ),\n );\n};\n\nconst ensureKeyLegacy = async (c: LDUser, platform: Platform) => {\n await ensureKeyCommon('user', c, platform);\n};\n\n/**\n * Ensure a key is always present in anonymous contexts. Non-anonymous contexts\n * are not processed and will just be returned as is.\n *\n * @param context\n * @param platform\n */\nexport const ensureKey = async (context: LDContext, platform: Platform): Promise<LDContext> => {\n const cloned = clone<LDContext>(context);\n\n if (isSingleKind(cloned)) {\n await ensureKeySingle(cloned as LDSingleKindContext, platform);\n }\n\n if (isMultiKind(cloned)) {\n await ensureKeyMulti(cloned as LDMultiKindContext, platform);\n }\n\n if (isLegacyUser(cloned)) {\n await ensureKeyLegacy(cloned as LDUser, platform);\n }\n\n return cloned;\n};\n","import { secondsToMillis, ServiceEndpoints } from '@launchdarkly/js-sdk-common';\n\nimport { Configuration, DEFAULT_POLLING, DEFAULT_STREAM } from '../configuration';\n\nexport type DiagnosticsInitConfig = {\n // client & server common properties\n customBaseURI: boolean;\n customStreamURI: boolean;\n customEventsURI: boolean;\n eventsCapacity: number;\n eventsFlushIntervalMillis: number;\n reconnectTimeMillis: number;\n diagnosticRecordingIntervalMillis: number;\n allAttributesPrivate: boolean;\n\n // client specific properties\n usingSecureMode: boolean;\n bootstrapMode: boolean;\n};\nconst createDiagnosticsInitConfig = (config: Configuration): DiagnosticsInitConfig => ({\n customBaseURI: config.serviceEndpoints.polling !== DEFAULT_POLLING,\n customStreamURI: config.serviceEndpoints.streaming !== DEFAULT_STREAM,\n customEventsURI: config.serviceEndpoints.events !== ServiceEndpoints.DEFAULT_EVENTS,\n eventsCapacity: config.capacity,\n eventsFlushIntervalMillis: secondsToMillis(config.flushInterval),\n reconnectTimeMillis: secondsToMillis(config.streamInitialReconnectDelay),\n diagnosticRecordingIntervalMillis: secondsToMillis(config.diagnosticRecordingInterval),\n allAttributesPrivate: config.allAttributesPrivate,\n // TODO: Implement when corresponding features are implemented.\n usingSecureMode: false,\n bootstrapMode: false,\n});\n\nexport default createDiagnosticsInitConfig;\n","import { internal, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\nimport createDiagnosticsInitConfig from './createDiagnosticsInitConfig';\n\nconst createDiagnosticsManager = (\n clientSideID: string,\n config: Configuration,\n platform: Platform,\n) => {\n if (config.sendEvents && !config.diagnosticOptOut) {\n return new internal.DiagnosticsManager(\n clientSideID,\n platform,\n createDiagnosticsInitConfig(config),\n );\n }\n\n return undefined;\n};\n\nexport default createDiagnosticsManager;\n","import { internal, LDEvaluationReason, LDFlagValue } from '@launchdarkly/js-sdk-common';\n\nimport { LDEvaluationDetail } from '../api';\n\nexport function createErrorEvaluationDetail(\n errorKind: internal.ErrorKinds,\n def?: LDFlagValue,\n): LDEvaluationDetail {\n return {\n value: def ?? null,\n variationIndex: null,\n reason: { kind: 'ERROR', errorKind },\n };\n}\n\nexport function createSuccessEvaluationDetail(\n value: LDFlagValue,\n variationIndex?: number,\n reason?: LDEvaluationReason,\n): LDEvaluationDetail {\n const res: LDEvaluationDetail = {\n value,\n variationIndex: variationIndex ?? null,\n reason: reason ?? null,\n };\n return res;\n}\n","import { ClientContext, internal, LDHeaders, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\n\nconst createEventProcessor = (\n clientSideID: string,\n config: Configuration,\n platform: Platform,\n baseHeaders: LDHeaders,\n diagnosticsManager?: internal.DiagnosticsManager,\n): internal.EventProcessor | undefined => {\n if (config.sendEvents) {\n return new internal.EventProcessor(\n { ...config, eventsCapacity: config.capacity },\n new ClientContext(clientSideID, config, platform),\n baseHeaders,\n undefined,\n diagnosticsManager,\n false,\n true,\n );\n }\n\n return undefined;\n};\n\nexport default createEventProcessor;\n","import { Context, internal, LDEvaluationReason, LDFlagValue } from '@launchdarkly/js-sdk-common';\n\nimport { Flag } from '../types';\n\n/**\n * @internal\n */\nexport default class EventFactory extends internal.EventFactoryBase {\n evalEventClient(\n flagKey: string,\n value: LDFlagValue,\n defaultVal: any,\n flag: Flag,\n context: Context,\n reason?: LDEvaluationReason,\n ): internal.InputEvalEvent {\n const { trackEvents, debugEventsUntilDate, trackReason, flagVersion, version, variation } =\n flag;\n\n return super.evalEvent({\n addExperimentData: trackReason,\n context,\n debugEventsUntilDate,\n defaultVal,\n flagKey,\n reason,\n trackEvents: !!trackEvents,\n value,\n variation,\n version: flagVersion ?? version,\n });\n }\n}\n","/**\n * An index for tracking the most recently used contexts by timestamp with the ability to\n * update entry timestamps and prune out least used contexts above a max capacity provided.\n */\nexport default class ContextIndex {\n container: IndexContainer = { index: new Array<IndexEntry>() };\n\n /**\n * Creates a {@link ContextIndex} from its JSON representation (likely retrieved from persistence).\n * @param json representation of the {@link ContextIndex}\n * @returns the {@link ContextIndex}\n */\n static fromJson(json: string): ContextIndex {\n const contextIndex = new ContextIndex();\n try {\n contextIndex.container = JSON.parse(json);\n } catch (e) {\n /* ignoring error and returning empty index */\n }\n\n return contextIndex;\n }\n\n /**\n * @returns the JSON representation of the {@link ContextIndex} (like for saving to persistence)\n */\n toJson(): string {\n return JSON.stringify(this.container);\n }\n\n /**\n * Notice that a context has been used and when it was used. This will update an existing record\n * with the given timestamp, or create a new record if one doesn't exist.\n * @param id of the corresponding context\n * @param timestamp in millis since epoch\n */\n notice(id: string, timestamp: number) {\n const entry = this.container.index.find((it) => it.id === id);\n if (entry === undefined) {\n this.container.index.push({ id, timestamp });\n } else {\n entry.timestamp = timestamp;\n }\n }\n\n /**\n * Prune the index to the specified max size and then return the IDs\n * @param maxContexts the maximum number of contexts to retain after this prune\n * @returns an array of removed entries\n */\n prune(maxContexts: number): Array<IndexEntry> {\n const clampedMax = Math.max(maxContexts, 0); // clamp to [0, infinity)\n if (this.container.index.length > clampedMax) {\n // sort by timestamp so that older timestamps appear first in the array\n this.container.index.sort((a, b) => a.timestamp - b.timestamp);\n // delete the first N many elements above capacity. splice returns removed elements\n return this.container.index.splice(0, this.container.index.length - clampedMax);\n }\n return [];\n }\n}\n\nexport interface IndexContainer {\n index: Array<IndexEntry>;\n}\n\ninterface IndexEntry {\n id: string;\n timestamp: number;\n}\n","import { Context, LDLogger, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { namespaceForContextData, namespaceForContextIndex } from '../storage/namespaceUtils';\nimport { Flags } from '../types';\nimport ContextIndex from './ContextIndex';\nimport FlagStore from './FlagStore';\nimport FlagUpdater from './FlagUpdater';\nimport { ItemDescriptor } from './ItemDescriptor';\n\n/**\n * This class handles persisting and loading flag values from a persistent\n * store. It intercepts updates and forwards them to the flag updater and\n * then persists changes after the updater has completed.\n */\nexport default class FlagPersistence {\n private _contextIndex: ContextIndex | undefined;\n private _indexKey?: string;\n private _indexKeyPromise: Promise<string>;\n\n constructor(\n private readonly _platform: Platform,\n private readonly _environmentNamespace: string,\n private readonly _maxCachedContexts: number,\n private readonly _flagStore: FlagStore,\n private readonly _flagUpdater: FlagUpdater,\n private readonly _logger: LDLogger,\n private readonly _timeStamper: () => number = () => Date.now(),\n ) {\n this._indexKeyPromise = namespaceForContextIndex(this._environmentNamespace);\n }\n\n /**\n * Inits flag persistence for the provided context with the provided flags. This will result\n * in the underlying {@link FlagUpdater} switching its active context.\n */\n async init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void> {\n this._flagUpdater.init(context, newFlags);\n await this._storeCache(context);\n }\n\n /**\n * Upserts a flag into the {@link FlagUpdater} and stores that to persistence if the upsert\n * was successful / accepted. An upsert may be rejected if the provided context is not\n * the active context.\n */\n async upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean> {\n if (this._flagUpdater.upsert(context, key, item)) {\n await this._storeCache(context);\n return true;\n }\n return false;\n }\n\n /**\n * Loads the flags from persistence for the provided context and gives those to the\n * {@link FlagUpdater} this {@link FlagPersistence} was constructed with.\n */\n async loadCached(context: Context): Promise<boolean> {\n const storageKey = await namespaceForContextData(\n this._platform.crypto,\n this._environmentNamespace,\n context,\n );\n let flagsJson = await this._platform.storage?.get(storageKey);\n if (flagsJson === null || flagsJson === undefined) {\n // Fallback: in version <10.3.1 flag data was stored under the canonical key, check\n // to see if data is present and migrate the data if present.\n flagsJson = await this._platform.storage?.get(context.canonicalKey);\n if (flagsJson === null || flagsJson === undefined) {\n // return false indicating cache did not load if flag json is still absent\n return false;\n }\n\n // migrate data from version <10.3.1 and cleanup data that was under canonical key\n await this._platform.storage?.set(storageKey, flagsJson);\n await this._platform.storage?.clear(context.canonicalKey);\n }\n\n try {\n const flags: Flags = JSON.parse(flagsJson);\n\n // mapping flags to item descriptors\n const descriptors = Object.entries(flags).reduce(\n (acc: { [k: string]: ItemDescriptor }, [key, flag]) => {\n acc[key] = { version: flag.version, flag };\n return acc;\n },\n {},\n );\n\n this._flagUpdater.initCached(context, descriptors);\n this._logger.debug('Loaded cached flag evaluations from persistent storage');\n return true;\n } catch (e: any) {\n this._logger.warn(\n `Could not load cached flag evaluations from persistent storage: ${e.message}`,\n );\n return false;\n }\n }\n\n private async _loadIndex(): Promise<ContextIndex> {\n if (this._contextIndex !== undefined) {\n return this._contextIndex;\n }\n\n const json = await this._platform.storage?.get(await this._indexKeyPromise);\n if (!json) {\n this._contextIndex = new ContextIndex();\n return this._contextIndex;\n }\n\n try {\n this._contextIndex = ContextIndex.fromJson(json);\n this._logger.debug('Loaded context index from persistent storage');\n } catch (e: any) {\n this._logger.warn(`Could not load index from persistent storage: ${e.message}`);\n this._contextIndex = new ContextIndex();\n }\n return this._contextIndex;\n }\n\n private async _storeCache(context: Context): Promise<void> {\n const index = await this._loadIndex();\n const storageKey = await namespaceForContextData(\n this._platform.crypto,\n this._environmentNamespace,\n context,\n );\n index.notice(storageKey, this._timeStamper());\n\n const pruned = index.prune(this._maxCachedContexts);\n await Promise.all(pruned.map(async (it) => this._platform.storage?.clear(it.id)));\n\n // store index\n await this._platform.storage?.set(await this._indexKeyPromise, index.toJson());\n const allFlags = this._flagStore.getAll();\n\n // mapping item descriptors to flags\n const flags = Object.entries(allFlags).reduce((acc: Flags, [key, descriptor]) => {\n if (descriptor.flag !== null && descriptor.flag !== undefined) {\n acc[key] = descriptor.flag;\n }\n return acc;\n }, {});\n\n const jsonAll = JSON.stringify(flags);\n // store flag data\n await this._platform.storage?.set(storageKey, jsonAll);\n }\n}\n","import { ItemDescriptor } from './ItemDescriptor';\n\n/**\n * This interface exists for testing purposes\n */\nexport default interface FlagStore {\n init(newFlags: { [key: string]: ItemDescriptor }): void;\n insertOrUpdate(key: string, update: ItemDescriptor): void;\n get(key: string): ItemDescriptor | undefined;\n getAll(): { [key: string]: ItemDescriptor };\n}\n\n/**\n * In memory flag store.\n */\nexport class DefaultFlagStore implements FlagStore {\n private _flags: { [key: string]: ItemDescriptor } = {};\n\n init(newFlags: { [key: string]: ItemDescriptor }) {\n this._flags = Object.entries(newFlags).reduce(\n (acc: { [k: string]: ItemDescriptor }, [key, flag]) => {\n acc[key] = flag;\n return acc;\n },\n {},\n );\n }\n\n insertOrUpdate(key: string, update: ItemDescriptor) {\n this._flags[key] = update;\n }\n\n get(key: string): ItemDescriptor | undefined {\n if (Object.prototype.hasOwnProperty.call(this._flags, key)) {\n return this._flags[key];\n }\n return undefined;\n }\n\n getAll(): { [key: string]: ItemDescriptor } {\n return this._flags;\n }\n}\n","import { fastDeepEqual } from '@launchdarkly/js-sdk-common';\n\nexport default function calculateChangedKeys(\n existingObject: { [k: string]: any },\n newObject: { [k: string]: any },\n) {\n const changedKeys: string[] = [];\n\n // property deleted or updated\n Object.entries(existingObject).forEach(([k, f]) => {\n const subObject = newObject[k];\n if (!subObject || !fastDeepEqual(f, subObject)) {\n changedKeys.push(k);\n }\n });\n\n // property added\n Object.keys(newObject).forEach((k) => {\n if (!existingObject[k]) {\n changedKeys.push(k);\n }\n });\n\n return changedKeys;\n}\n","import { Context, LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport calculateChangedKeys from './calculateChangedKeys';\nimport FlagStore from './FlagStore';\nimport { ItemDescriptor } from './ItemDescriptor';\n\nexport type FlagChangeType = 'init' | 'patch';\n\n/**\n * This callback indicates that the details associated with one or more flags\n * have changed.\n *\n * This could be the value of the flag, but it could also include changes\n * to the evaluation reason, such as being included in an experiment.\n *\n * It can include new or deleted flags as well, so an evaluation may result\n * in a FLAG_NOT_FOUND reason.\n *\n * This event does not include the value of the flag. It is expected that you\n * will call a variation method for flag values which you require.\n */\nexport type FlagsChangeCallback = (\n context: Context,\n flagKeys: Array<string>,\n type: FlagChangeType,\n) => void;\n\n/**\n * The flag updater handles logic required during the flag update process.\n * It handles versions checking to handle out of order flag updates and\n * also handles flag comparisons for change notification.\n */\nexport default class FlagUpdater {\n private _flagStore: FlagStore;\n private _logger: LDLogger;\n private _activeContextKey: string | undefined;\n private _changeCallbacks = new Array<FlagsChangeCallback>();\n\n constructor(flagStore: FlagStore, logger: LDLogger) {\n this._flagStore = flagStore;\n this._logger = logger;\n }\n\n init(context: Context, newFlags: { [key: string]: ItemDescriptor }) {\n this._activeContextKey = context.canonicalKey;\n const oldFlags = this._flagStore.getAll();\n this._flagStore.init(newFlags);\n const changed = calculateChangedKeys(oldFlags, newFlags);\n if (changed.length > 0) {\n this._changeCallbacks.forEach((callback) => {\n try {\n callback(context, changed, 'init');\n } catch (err) {\n /* intentionally empty */\n }\n });\n }\n }\n\n initCached(context: Context, newFlags: { [key: string]: ItemDescriptor }) {\n if (this._activeContextKey === context.canonicalKey) {\n return;\n }\n\n this.init(context, newFlags);\n }\n\n upsert(context: Context, key: string, item: ItemDescriptor): boolean {\n if (this._activeContextKey !== context.canonicalKey) {\n this._logger.warn('Received an update for an inactive context.');\n return false;\n }\n\n const currentValue = this._flagStore.get(key);\n if (currentValue !== undefined && currentValue.version >= item.version) {\n // this is an out of order update that can be ignored\n return false;\n }\n\n this._flagStore.insertOrUpdate(key, item);\n this._changeCallbacks.forEach((callback) => {\n try {\n callback(context, [key], 'patch');\n } catch (err) {\n /* intentionally empty */\n }\n });\n return true;\n }\n\n on(callback: FlagsChangeCallback): void {\n this._changeCallbacks.push(callback);\n }\n\n off(callback: FlagsChangeCallback): void {\n const index = this._changeCallbacks.indexOf(callback);\n if (index > -1) {\n this._changeCallbacks.splice(index, 1);\n }\n }\n}\n","import { Context, LDLogger, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { namespaceForEnvironment } from '../storage/namespaceUtils';\nimport FlagPersistence from './FlagPersistence';\nimport { DefaultFlagStore } from './FlagStore';\nimport FlagUpdater, { FlagsChangeCallback } from './FlagUpdater';\nimport { ItemDescriptor } from './ItemDescriptor';\n\n/**\n * Top level manager of flags for the client. LDClient should be using this\n * interface and not any of the specific instances managed by it. Updates from\n * data sources should be directed to the [init] and [upsert] methods of this\n * interface.\n */\nexport interface FlagManager {\n /**\n * Attempts to get a flag by key from the current flags.\n */\n get(key: string): ItemDescriptor | undefined;\n\n /**\n * Gets all the current flags.\n */\n getAll(): { [key: string]: ItemDescriptor };\n\n /**\n * Initializes the flag manager with data from a data source.\n * Persistence initialization is handled by {@link FlagPersistence}\n */\n init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void>;\n\n /**\n * Attempt to update a flag. If the flag is for the wrong context, or\n * it is of an older version, then an update will not be performed.\n */\n upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean>;\n\n /**\n * Asynchronously load cached values from persistence.\n */\n loadCached(context: Context): Promise<boolean>;\n\n /**\n * Update in-memory storage with the specified flags, but do not persistent them to cache\n * storage.\n */\n setBootstrap(context: Context, newFlags: { [key: string]: ItemDescriptor }): void;\n\n /**\n * Register a flag change callback.\n */\n on(callback: FlagsChangeCallback): void;\n\n /**\n * Unregister a flag change callback.\n */\n off(callback: FlagsChangeCallback): void;\n}\n\nexport default class DefaultFlagManager implements FlagManager {\n private _flagStore = new DefaultFlagStore();\n private _flagUpdater: FlagUpdater;\n private _flagPersistencePromise: Promise<FlagPersistence>;\n\n /**\n * @param platform implementation of various platform provided functionality\n * @param sdkKey that will be used to distinguish different environments\n * @param maxCachedContexts that specifies the max number of contexts that will be cached in persistence\n * @param logger used for logging various messages\n * @param timeStamper exists for testing purposes\n */\n constructor(\n platform: Platform,\n sdkKey: string,\n maxCachedContexts: number,\n logger: LDLogger,\n timeStamper: () => number = () => Date.now(),\n ) {\n this._flagUpdater = new FlagUpdater(this._flagStore, logger);\n this._flagPersistencePromise = this._initPersistence(\n platform,\n sdkKey,\n maxCachedContexts,\n logger,\n timeStamper,\n );\n }\n\n private async _initPersistence(\n platform: Platform,\n sdkKey: string,\n maxCachedContexts: number,\n logger: LDLogger,\n timeStamper: () => number = () => Date.now(),\n ): Promise<FlagPersistence> {\n const environmentNamespace = await namespaceForEnvironment(platform.crypto, sdkKey);\n\n return new FlagPersistence(\n platform,\n environmentNamespace,\n maxCachedContexts,\n this._flagStore,\n this._flagUpdater,\n logger,\n timeStamper,\n );\n }\n\n get(key: string): ItemDescriptor | undefined {\n return this._flagStore.get(key);\n }\n\n getAll(): { [key: string]: ItemDescriptor } {\n return this._flagStore.getAll();\n }\n\n setBootstrap(context: Context, newFlags: { [key: string]: ItemDescriptor }): void {\n // Bypasses the persistence as we do not want to put these flags into any cache.\n // Generally speaking persistence likely *SHOULD* be disabled when using bootstrap.\n this._flagUpdater.init(context, newFlags);\n }\n\n async init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void> {\n return (await this._flagPersistencePromise).init(context, newFlags);\n }\n\n async upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean> {\n return (await this._flagPersistencePromise).upsert(context, key, item);\n }\n\n async loadCached(context: Context): Promise<boolean> {\n return (await this._flagPersistencePromise).loadCached(context);\n }\n\n on(callback: FlagsChangeCallback): void {\n this._flagUpdater.on(callback);\n }\n\n off(callback: FlagsChangeCallback): void {\n this._flagUpdater.off(callback);\n }\n}\n","import { LDContext, LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport {\n EvaluationSeriesContext,\n EvaluationSeriesData,\n Hook,\n IdentifySeriesContext,\n IdentifySeriesData,\n IdentifySeriesResult,\n TrackSeriesContext,\n} from './api/integrations/Hooks';\nimport { LDEvaluationDetail } from './api/LDEvaluationDetail';\n\nconst UNKNOWN_HOOK_NAME = 'unknown hook';\nconst BEFORE_EVALUATION_STAGE_NAME = 'beforeEvaluation';\nconst AFTER_EVALUATION_STAGE_NAME = 'afterEvaluation';\nconst AFTER_TRACK_STAGE_NAME = 'afterTrack';\n\nfunction tryExecuteStage<TData>(\n logger: LDLogger,\n method: string,\n hookName: string,\n stage: () => TData,\n def: TData,\n): TData {\n try {\n return stage();\n } catch (err) {\n logger?.error(`An error was encountered in \"${method}\" of the \"${hookName}\" hook: ${err}`);\n return def;\n }\n}\n\nfunction getHookName(logger: LDLogger, hook: Hook): string {\n try {\n return hook.getMetadata().name || UNKNOWN_HOOK_NAME;\n } catch {\n logger.error(`Exception thrown getting metadata for hook. Unable to get hook name.`);\n return UNKNOWN_HOOK_NAME;\n }\n}\n\nfunction executeBeforeEvaluation(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: EvaluationSeriesContext,\n): EvaluationSeriesData[] {\n return hooks.map((hook) =>\n tryExecuteStage(\n logger,\n BEFORE_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.beforeEvaluation?.(hookContext, {}) ?? {},\n {},\n ),\n );\n}\n\nfunction executeAfterEvaluation(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: EvaluationSeriesContext,\n updatedData: EvaluationSeriesData[],\n result: LDEvaluationDetail,\n) {\n // This iterates in reverse, versus reversing a shallow copy of the hooks,\n // for efficiency.\n for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) {\n const hook = hooks[hookIndex];\n const data = updatedData[hookIndex];\n tryExecuteStage(\n logger,\n AFTER_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.afterEvaluation?.(hookContext, data, result) ?? {},\n {},\n );\n }\n}\n\nfunction executeBeforeIdentify(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: IdentifySeriesContext,\n): IdentifySeriesData[] {\n return hooks.map((hook) =>\n tryExecuteStage(\n logger,\n BEFORE_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.beforeIdentify?.(hookContext, {}) ?? {},\n {},\n ),\n );\n}\n\nfunction executeAfterIdentify(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: IdentifySeriesContext,\n updatedData: IdentifySeriesData[],\n result: IdentifySeriesResult,\n) {\n // This iterates in reverse, versus reversing a shallow copy of the hooks,\n // for efficiency.\n for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) {\n const hook = hooks[hookIndex];\n const data = updatedData[hookIndex];\n tryExecuteStage(\n logger,\n AFTER_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.afterIdentify?.(hookContext, data, result) ?? {},\n {},\n );\n }\n}\n\nfunction executeAfterTrack(logger: LDLogger, hooks: Hook[], hookContext: TrackSeriesContext) {\n // This iterates in reverse, versus reversing a shallow copy of the hooks,\n // for efficiency.\n for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) {\n const hook = hooks[hookIndex];\n tryExecuteStage(\n logger,\n AFTER_TRACK_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.afterTrack?.(hookContext),\n undefined,\n );\n }\n}\n\nexport default class HookRunner {\n private readonly _hooks: Hook[] = [];\n\n constructor(\n private readonly _logger: LDLogger,\n initialHooks: Hook[],\n ) {\n this._hooks.push(...initialHooks);\n }\n\n withEvaluation(\n key: string,\n context: LDContext | undefined,\n defaultValue: unknown,\n method: () => LDEvaluationDetail,\n ): LDEvaluationDetail {\n if (this._hooks.length === 0) {\n return method();\n }\n const hooks: Hook[] = [...this._hooks];\n const hookContext: EvaluationSeriesContext = {\n flagKey: key,\n context,\n defaultValue,\n };\n\n const hookData = executeBeforeEvaluation(this._logger, hooks, hookContext);\n const result = method();\n executeAfterEvaluation(this._logger, hooks, hookContext, hookData, result);\n return result;\n }\n\n identify(\n context: LDContext,\n timeout: number | undefined,\n ): (result: IdentifySeriesResult) => void {\n const hooks: Hook[] = [...this._hooks];\n const hookContext: IdentifySeriesContext = {\n context,\n timeout,\n };\n const hookData = executeBeforeIdentify(this._logger, hooks, hookContext);\n return (result) => {\n executeAfterIdentify(this._logger, hooks, hookContext, hookData, result);\n };\n }\n\n addHook(hook: Hook): void {\n this._hooks.push(hook);\n }\n\n afterTrack(hookContext: TrackSeriesContext): void {\n if (this._hooks.length === 0) {\n return;\n }\n const hooks: Hook[] = [...this._hooks];\n executeAfterTrack(this._logger, hooks, hookContext);\n }\n}\n","import { EvaluationSeriesContext, EvaluationSeriesData, Hook, LDEvaluationDetail } from '../api';\nimport InspectorManager from './InspectorManager';\n\nexport function getInspectorHook(inspectorManager: InspectorManager): Hook {\n return {\n getMetadata() {\n return {\n name: 'LaunchDarkly-Inspector-Adapter',\n };\n },\n afterEvaluation: (\n hookContext: EvaluationSeriesContext,\n data: EvaluationSeriesData,\n detail: LDEvaluationDetail,\n ) => {\n inspectorManager.onFlagUsed(hookContext.flagKey, detail, hookContext.context);\n return data;\n },\n afterIdentify(hookContext, data, _result) {\n inspectorManager.onIdentityChanged(hookContext.context);\n return data;\n },\n };\n}\n","export function invalidInspector(type: string, name: string) {\n return `an inspector: \"${name}\" of an invalid type (${type}) was configured`;\n}\n\nexport function inspectorMethodError(type: string, name: string) {\n return `an inspector: \"${name}\" of type: \"${type}\" generated an exception`;\n}\n","import { LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport { LDInspection } from '../api/LDInspection';\nimport { inspectorMethodError } from './messages';\n\n/**\n * Wrap an inspector ensuring that calling its methods are safe.\n * @param inspector Inspector to wrap.\n */\nexport default function createSafeInspector(\n inspector: LDInspection,\n logger: LDLogger,\n): LDInspection {\n let errorLogged = false;\n const wrapper: LDInspection = {\n method: (...args: any[]) => {\n try {\n // We are proxying arguments here to the underlying method. Typescript doesn't care\n // for this as it cannot validate the parameters are correct, but we are also the caller\n // in this case and will dispatch things with the correct arguments. The dispatch to this\n // will itself happen with a type guard.\n // @ts-ignore\n inspector.method(...args);\n } catch {\n // If something goes wrong in an inspector we want to log that something\n // went wrong. We don't want to flood the logs, so we only log something\n // the first time that something goes wrong.\n // We do not include the exception in the log, because we do not know what\n // kind of data it may contain.\n if (!errorLogged) {\n errorLogged = true;\n logger.warn(inspectorMethodError(wrapper.type, wrapper.name));\n }\n // Prevent errors.\n }\n },\n type: inspector.type,\n name: inspector.name,\n synchronous: inspector.synchronous,\n };\n\n return wrapper;\n}\n","import { LDContext, LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport { LDEvaluationDetail } from '../api';\nimport { LDInspection } from '../api/LDInspection';\nimport createSafeInspector from './createSafeInspector';\nimport { invalidInspector } from './messages';\n\nconst FLAG_USED_TYPE = 'flag-used';\nconst FLAG_DETAILS_CHANGED_TYPE = 'flag-details-changed';\nconst FLAG_DETAIL_CHANGED_TYPE = 'flag-detail-changed';\nconst IDENTITY_CHANGED_TYPE = 'client-identity-changed';\n\nconst VALID__TYPES = [\n FLAG_USED_TYPE,\n FLAG_DETAILS_CHANGED_TYPE,\n FLAG_DETAIL_CHANGED_TYPE,\n IDENTITY_CHANGED_TYPE,\n];\n\nfunction validateInspector(inspector: LDInspection, logger: LDLogger): boolean {\n const valid =\n VALID__TYPES.includes(inspector.type) &&\n inspector.method &&\n typeof inspector.method === 'function';\n\n if (!valid) {\n logger.warn(invalidInspector(inspector.type, inspector.name));\n }\n\n return valid;\n}\n\n/**\n * Manages dispatching of inspection data to registered inspectors.\n */\nexport default class InspectorManager {\n private _safeInspectors: LDInspection[] = [];\n\n constructor(inspectors: LDInspection[], logger: LDLogger) {\n const validInspectors = inspectors.filter((inspector) => validateInspector(inspector, logger));\n this._safeInspectors = validInspectors.map((inspector) =>\n createSafeInspector(inspector, logger),\n );\n }\n\n hasInspectors(): boolean {\n return this._safeInspectors.length !== 0;\n }\n\n /**\n * Notify registered inspectors of a flag being used.\n *\n * @param flagKey The key for the flag.\n * @param detail The LDEvaluationDetail for the flag.\n * @param context The LDContext for the flag.\n */\n onFlagUsed(flagKey: string, detail: LDEvaluationDetail, context?: LDContext) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === FLAG_USED_TYPE) {\n inspector.method(flagKey, detail, context);\n }\n });\n }\n\n /**\n * Notify registered inspectors that the flags have been replaced.\n *\n * @param flags The current flags as a Record<string, LDEvaluationDetail>.\n */\n onFlagsChanged(flags: Record<string, LDEvaluationDetail>) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === FLAG_DETAILS_CHANGED_TYPE) {\n inspector.method(flags);\n }\n });\n }\n\n /**\n * Notify registered inspectors that a flag value has changed.\n *\n * @param flagKey The key for the flag that changed.\n * @param flag An `LDEvaluationDetail` for the flag.\n */\n onFlagChanged(flagKey: string, flag: LDEvaluationDetail) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === FLAG_DETAIL_CHANGED_TYPE) {\n inspector.method(flagKey, flag);\n }\n });\n }\n\n /**\n * Notify the registered inspectors that the context identity has changed.\n *\n * The notification itself will be dispatched asynchronously.\n *\n * @param context The `LDContext` which is now identified.\n */\n onIdentityChanged(context: LDContext) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === IDENTITY_CHANGED_TYPE) {\n inspector.method(context);\n }\n });\n }\n}\n","import { LDLogger } from '@launchdarkly/js-sdk-common';\n\ntype FlagChangeKey = `change:${string}`;\n\n/**\n * Type for name of emitted events. 'change' is used for all flag changes. 'change:flag-name-here' is used\n * for specific flag changes.\n */\nexport type EventName = 'change' | FlagChangeKey | 'dataSourceStatus' | 'error';\n\n/**\n * Implementation Note: There should not be any default listeners for change events in a client\n * implementation. Default listeners mean a client cannot determine when there are actual\n * application developer provided listeners. If we require default listeners, then we should add\n * a system to allow listeners which have counts independent of the primary listener counts.\n */\nexport default class LDEmitter {\n private _listeners: Map<EventName, Function[]> = new Map();\n\n constructor(private _logger?: LDLogger) {}\n\n on(name: EventName, listener: Function) {\n if (!this._listeners.has(name)) {\n this._listeners.set(name, [listener]);\n } else {\n this._listeners.get(name)?.push(listener);\n }\n }\n\n /**\n * Unsubscribe one or all events.\n *\n * @param name\n * @param listener Optional. If unspecified, all listeners for the event will be removed.\n */\n off(name: EventName, listener?: Function) {\n const existingListeners = this._listeners.get(name);\n if (!existingListeners) {\n return;\n }\n\n if (listener) {\n // remove from internal cache\n const updated = existingListeners.filter((fn) => fn !== listener);\n if (updated.length === 0) {\n this._listeners.delete(name);\n } else {\n this._listeners.set(name, updated);\n }\n return;\n }\n\n // listener was not specified, so remove them all for that event\n this._listeners.delete(name);\n }\n\n private _invokeListener(listener: Function, name: EventName, ...detail: any[]) {\n try {\n listener(...detail);\n } catch (err) {\n this._logger?.error(`Encountered error invoking handler for \"${name}\", detail: \"${err}\"`);\n }\n }\n\n emit(name: EventName, ...detail: any[]) {\n const listeners = this._listeners.get(name);\n listeners?.forEach((listener) => this._invokeListener(listener, name, ...detail));\n }\n\n eventNames(): string[] {\n return [...this._listeners.keys()];\n }\n\n listenerCount(name: EventName): number {\n return this._listeners.get(name)?.length ?? 0;\n }\n}\n","import {\n LDPluginApplicationMetadata,\n LDPluginEnvironmentMetadata,\n LDPluginSdkMetadata,\n Platform,\n} from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\n\n/**\n * Mutable utility type to allow building up a readonly object from a mutable one.\n */\ntype Mutable<T> = {\n -readonly [P in keyof T]: Mutable<T[P]>;\n};\n\nexport function createPluginEnvironmentMetadata(\n sdkKey: string,\n platform: Platform,\n config: Configuration,\n): LDPluginEnvironmentMetadata {\n const sdkData = platform.info.sdkData();\n\n let applicationMetadata: Mutable<LDPluginApplicationMetadata> | undefined;\n\n if (config.applicationInfo) {\n if (config.applicationInfo.id) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.id = config.applicationInfo.id;\n }\n if (config.applicationInfo.version) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.version = config.applicationInfo.version;\n }\n if (config.applicationInfo.name) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.name = config.applicationInfo.name;\n }\n if (config.applicationInfo.versionName) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.versionName = config.applicationInfo.versionName;\n }\n }\n\n const sdkMetadata: Mutable<LDPluginSdkMetadata> = {\n name: sdkData.userAgentBase!,\n version: sdkData.version!,\n };\n\n if (sdkData.wrapperName) {\n sdkMetadata.wrapperName = sdkData.wrapperName;\n }\n\n if (sdkData.wrapperVersion) {\n sdkMetadata.wrapperVersion = sdkData.wrapperVersion;\n }\n\n const environmentMetadata: Mutable<LDPluginEnvironmentMetadata> = {\n sdk: sdkMetadata,\n [config.credentialType]: sdkKey,\n };\n if (applicationMetadata) {\n environmentMetadata.application = applicationMetadata;\n }\n\n return environmentMetadata;\n}\n","import {\n AutoEnvAttributes,\n clone,\n Context,\n defaultHeaders,\n internal,\n LDClientError,\n LDContext,\n LDFlagSet,\n LDFlagValue,\n LDHeaders,\n LDLogger,\n LDPluginEnvironmentMetadata,\n LDTimeoutError,\n Platform,\n TypeValidators,\n} from '@launchdarkly/js-sdk-common';\n\nimport {\n Hook,\n LDClient,\n LDClientIdentifyResult,\n LDIdentifyError,\n LDIdentifyResult,\n LDIdentifyShed,\n LDIdentifySuccess,\n LDIdentifyTimeout,\n type LDOptions,\n} from './api';\nimport { LDEvaluationDetail, LDEvaluationDetailTyped } from './api/LDEvaluationDetail';\nimport { LDIdentifyOptions } from './api/LDIdentifyOptions';\nimport { createAsyncTaskQueue } from './async/AsyncTaskQueue';\nimport { Configuration, ConfigurationImpl, LDClientInternalOptions } from './configuration';\nimport { addAutoEnv } from './context/addAutoEnv';\nimport { ensureKey } from './context/ensureKey';\nimport { DataManager, DataManagerFactory } from './DataManager';\nimport createDiagnosticsManager from './diagnostics/createDiagnosticsManager';\nimport {\n createErrorEvaluationDetail,\n createSuccessEvaluationDetail,\n} from './evaluation/evaluationDetail';\nimport createEventProcessor from './events/createEventProcessor';\nimport EventFactory from './events/EventFactory';\nimport DefaultFlagManager, { FlagManager } from './flag-manager/FlagManager';\nimport { FlagChangeType } from './flag-manager/FlagUpdater';\nimport HookRunner from './HookRunner';\nimport { getInspectorHook } from './inspection/getInspectorHook';\nimport InspectorManager from './inspection/InspectorManager';\nimport LDEmitter, { EventName } from './LDEmitter';\nimport { createPluginEnvironmentMetadata } from './plugins/createPluginEnvironmentMetadata';\n\nconst { ClientMessages, ErrorKinds } = internal;\n\nconst DEFAULT_IDENTIFY_TIMEOUT_SECONDS = 5;\n\nexport default class LDClientImpl implements LDClient, LDClientIdentifyResult {\n private readonly _config: Configuration;\n private _uncheckedContext?: LDContext;\n private _checkedContext?: Context;\n private readonly _diagnosticsManager?: internal.DiagnosticsManager;\n private _eventProcessor?: internal.EventProcessor;\n readonly logger: LDLogger;\n\n private readonly _highTimeoutThreshold: number = 15;\n\n private _eventFactoryDefault = new EventFactory(false);\n private _eventFactoryWithReasons = new EventFactory(true);\n protected emitter: LDEmitter;\n private _flagManager: FlagManager;\n\n private _eventSendingEnabled: boolean = false;\n private _baseHeaders: LDHeaders;\n protected dataManager: DataManager;\n protected readonly environmentMetadata: LDPluginEnvironmentMetadata;\n private _hookRunner: HookRunner;\n private _inspectorManager: InspectorManager;\n private _identifyQueue = createAsyncTaskQueue<void>();\n\n /**\n * Creates the client object synchronously. No async, no network calls.\n */\n constructor(\n public readonly sdkKey: string,\n public readonly autoEnvAttributes: AutoEnvAttributes,\n public readonly platform: Platform,\n options: LDOptions,\n dataManagerFactory: DataManagerFactory,\n internalOptions?: LDClientInternalOptions,\n ) {\n if (!sdkKey) {\n throw new Error('You must configure the client with a client-side SDK key');\n }\n\n if (!platform.encoding) {\n throw new Error('Platform must implement Encoding because btoa is required.');\n }\n\n this._config = new ConfigurationImpl(options, internalOptions);\n this.logger = this._config.logger;\n\n this._baseHeaders = defaultHeaders(\n this.sdkKey,\n this.platform.info,\n this._config.tags,\n this._config.serviceEndpoints.includeAuthorizationHeader,\n this._config.userAgentHeaderName,\n );\n\n this._flagManager = new DefaultFlagManager(\n this.platform,\n sdkKey,\n this._config.maxCachedContexts,\n this._config.logger,\n );\n this._diagnosticsManager = createDiagnosticsManager(sdkKey, this._config, platform);\n this._eventProcessor = createEventProcessor(\n sdkKey,\n this._config,\n platform,\n this._baseHeaders,\n this._diagnosticsManager,\n );\n this.emitter = new LDEmitter();\n this.emitter.on('error', (c: LDContext, err: any) => {\n this.logger.error(`error: ${err}, context: ${JSON.stringify(c)}`);\n });\n\n this._flagManager.on((context, flagKeys, type) => {\n this._handleInspectionChanged(flagKeys, type);\n const ldContext = Context.toLDContext(context);\n this.emitter.emit('change', ldContext, flagKeys);\n flagKeys.forEach((it) => {\n this.emitter.emit(`change:${it}`, ldContext);\n });\n });\n\n this.dataManager = dataManagerFactory(\n this._flagManager,\n this._config,\n this._baseHeaders,\n this.emitter,\n this._diagnosticsManager,\n );\n\n const hooks: Hook[] = [...this._config.hooks];\n\n this.environmentMetadata = createPluginEnvironmentMetadata(\n this.sdkKey,\n this.platform,\n this._config,\n );\n\n this._config.getImplementationHooks(this.environmentMetadata).forEach((hook) => {\n hooks.push(hook);\n });\n\n this._hookRunner = new HookRunner(this.logger, hooks);\n this._inspectorManager = new InspectorManager(this._config.inspectors, this.logger);\n if (this._inspectorManager.hasInspectors()) {\n this._hookRunner.addHook(getInspectorHook(this._inspectorManager));\n }\n }\n\n allFlags(): LDFlagSet {\n // extracting all flag values\n const result = Object.entries(this._flagManager.getAll()).reduce(\n (acc: LDFlagSet, [key, descriptor]) => {\n if (descriptor.flag !== null && descriptor.flag !== undefined && !descriptor.flag.deleted) {\n acc[key] = descriptor.flag.value;\n }\n return acc;\n },\n {},\n );\n return result;\n }\n\n async close(): Promise<void> {\n await this.flush();\n this._eventProcessor?.close();\n this.dataManager.close();\n this.logger.debug('Closed event processor and data source.');\n }\n\n async flush(): Promise<{ error?: Error; result: boolean }> {\n try {\n await this._eventProcessor?.flush();\n this.logger.debug('Successfully flushed event processor.');\n } catch (e) {\n this.logger.error(`Error flushing event processor: ${e}.`);\n return { error: e as Error, result: false };\n }\n\n return { result: true };\n }\n\n getContext(): LDContext | undefined {\n // The LDContext returned here may have been modified by the SDK (for example: adding auto env attributes).\n // We are returning an LDContext here to maintain a consistent representation of context to the consuming\n // code. We are returned the unchecked context so that if a consumer identifies with an invalid context\n // and then calls getContext, they get back the same context they provided, without any assertion about\n // validity.\n return this._uncheckedContext ? clone<LDContext>(this._uncheckedContext) : undefined;\n }\n\n protected getInternalContext(): Context | undefined {\n return this._checkedContext;\n }\n\n private _createIdentifyPromise(): {\n identifyPromise: Promise<void>;\n identifyResolve: () => void;\n identifyReject: (err: Error) => void;\n } {\n let res: any;\n let rej: any;\n\n const basePromise = new Promise<void>((resolve, reject) => {\n res = resolve;\n rej = reject;\n });\n\n return { identifyPromise: basePromise, identifyResolve: res, identifyReject: rej };\n }\n\n /**\n * Identifies a context to LaunchDarkly. See {@link LDClient.identify}.\n *\n * If used with the `sheddable` option set to true, then the identify operation will be sheddable. This means that if\n * multiple identify operations are done, without waiting for the previous one to complete, then intermediate\n * operations may be discarded.\n *\n * It is recommended to use the `identifyResult` method instead when the operation is sheddable. In a future release,\n * all identify operations will default to being sheddable.\n *\n * @param pristineContext The LDContext object to be identified.\n * @param identifyOptions Optional configuration. See {@link LDIdentifyOptions}.\n * @returns A Promise which resolves when the flag values for the specified\n * context are available. It rejects when:\n *\n * 1. The context is unspecified or has no key.\n *\n * 2. The identify timeout is exceeded. In client SDKs this defaults to 5s.\n * You can customize this timeout with {@link LDIdentifyOptions | identifyOptions}.\n *\n * 3. A network error is encountered during initialization.\n */\n async identify(pristineContext: LDContext, identifyOptions?: LDIdentifyOptions): Promise<void> {\n // In order to manage customization in the derived classes it is important that `identify` MUST be implemented in\n // terms of `identifyResult`. So that the logic of the identification process can be extended in one place.\n const result = await this.identifyResult(pristineContext, identifyOptions);\n if (result.status === 'error') {\n throw result.error;\n } else if (result.status === 'timeout') {\n const timeoutError = new LDTimeoutError(\n `identify timed out after ${result.timeout} seconds.`,\n );\n this.logger.error(timeoutError.message);\n throw timeoutError;\n }\n // If completed or shed, then we are done.\n }\n\n async identifyResult(\n pristineContext: LDContext,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<LDIdentifyResult> {\n const identifyTimeout = identifyOptions?.timeout ?? DEFAULT_IDENTIFY_TIMEOUT_SECONDS;\n const noTimeout = identifyOptions?.timeout === undefined && identifyOptions?.noTimeout === true;\n\n // When noTimeout is specified, and a timeout is not specified, then this condition cannot\n // be encountered. (Our default would need to be greater)\n if (identifyTimeout > this._highTimeoutThreshold) {\n this.logger.warn(\n 'The identify function was called with a timeout greater than ' +\n `${this._highTimeoutThreshold} seconds. We recommend a timeout of less than ` +\n `${this._highTimeoutThreshold} seconds.`,\n );\n }\n\n const callSitePromise = this._identifyQueue\n .execute(\n {\n before: async () => {\n let context = await ensureKey(pristineContext, this.platform);\n if (this.autoEnvAttributes === AutoEnvAttributes.Enabled) {\n context = await addAutoEnv(context, this.platform, this._config);\n }\n const checkedContext = Context.fromLDContext(context);\n if (checkedContext.valid) {\n const afterIdentify = this._hookRunner.identify(context, identifyOptions?.timeout);\n return {\n context,\n checkedContext,\n afterIdentify,\n };\n }\n return {\n context,\n checkedContext,\n };\n },\n execute: async (beforeResult) => {\n const { context, checkedContext } = beforeResult!;\n if (!checkedContext.valid) {\n const error = new Error('Context was unspecified or had no key');\n this.emitter.emit('error', context, error);\n return Promise.reject(error);\n }\n this._uncheckedContext = context;\n this._checkedContext = checkedContext;\n\n this._eventProcessor?.sendEvent(\n this._eventFactoryDefault.identifyEvent(this._checkedContext),\n );\n const { identifyPromise, identifyResolve, identifyReject } =\n this._createIdentifyPromise();\n this.logger.debug(`Identifying ${JSON.stringify(this._checkedContext)}`);\n\n await this.dataManager.identify(\n identifyResolve,\n identifyReject,\n checkedContext,\n identifyOptions,\n );\n\n return identifyPromise;\n },\n after: async (res, beforeResult) => {\n if (res.status === 'complete') {\n beforeResult?.afterIdentify?.({ status: 'completed' });\n } else if (res.status === 'shed') {\n beforeResult?.afterIdentify?.({ status: 'shed' });\n } else if (res.status === 'error') {\n beforeResult?.afterIdentify?.({ status: 'error' });\n }\n },\n },\n identifyOptions?.sheddable ?? false,\n )\n .then((res) => {\n if (res.status === 'error') {\n return { status: 'error', error: res.error } as LDIdentifyError;\n }\n if (res.status === 'shed') {\n return { status: 'shed' } as LDIdentifyShed;\n }\n return { status: 'completed' } as LDIdentifySuccess;\n });\n\n if (noTimeout) {\n return callSitePromise;\n }\n\n const timeoutPromise = new Promise<LDIdentifyTimeout>((resolve) => {\n setTimeout(() => {\n resolve({ status: 'timeout', timeout: identifyTimeout } as LDIdentifyTimeout);\n }, identifyTimeout * 1000);\n });\n return Promise.race([callSitePromise, timeoutPromise]);\n }\n\n on(eventName: EventName, listener: Function): void {\n this.emitter.on(eventName, listener);\n }\n\n off(eventName: EventName, listener: Function): void {\n this.emitter.off(eventName, listener);\n }\n\n track(key: string, data?: any, metricValue?: number): void {\n if (!this._checkedContext || !this._checkedContext.valid) {\n this.logger.warn(ClientMessages.MissingContextKeyNoEvent);\n return;\n }\n\n // 0 is valid, so do not truthy check the metric value\n if (metricValue !== undefined && !TypeValidators.Number.is(metricValue)) {\n this.logger?.warn(ClientMessages.invalidMetricValue(typeof metricValue));\n }\n\n this._eventProcessor?.sendEvent(\n this._config.trackEventModifier(\n this._eventFactoryDefault.customEvent(key, this._checkedContext!, data, metricValue),\n ),\n );\n\n this._hookRunner.afterTrack({\n key,\n // The context is pre-checked above, so we know it can be unwrapped.\n context: this._uncheckedContext!,\n data,\n metricValue,\n });\n }\n\n private _variationInternal(\n flagKey: string,\n defaultValue: any,\n eventFactory: EventFactory,\n typeChecker?: (value: any) => [boolean, string],\n ): LDEvaluationDetail {\n if (!this._uncheckedContext) {\n this.logger.debug(ClientMessages.MissingContextKeyNoEvent);\n return createErrorEvaluationDetail(ErrorKinds.UserNotSpecified, defaultValue);\n }\n\n const evalContext = Context.fromLDContext(this._uncheckedContext);\n const foundItem = this._flagManager.get(flagKey);\n\n if (foundItem === undefined || foundItem.flag.deleted) {\n const defVal = defaultValue ?? null;\n const error = new LDClientError(\n `Unknown feature flag \"${flagKey}\"; returning default value ${defVal}.`,\n );\n this.emitter.emit('error', this._uncheckedContext, error);\n this._eventProcessor?.sendEvent(\n this._eventFactoryDefault.unknownFlagEvent(flagKey, defVal, evalContext),\n );\n return createErrorEvaluationDetail(ErrorKinds.FlagNotFound, defaultValue);\n }\n\n const { reason, value, variation, prerequisites } = foundItem.flag;\n\n if (typeChecker) {\n const [matched, type] = typeChecker(value);\n if (!matched) {\n this._eventProcessor?.sendEvent(\n eventFactory.evalEventClient(\n flagKey,\n defaultValue, // track default value on type errors\n defaultValue,\n foundItem.flag,\n evalContext,\n reason,\n ),\n );\n const error = new LDClientError(\n `Wrong type \"${type}\" for feature flag \"${flagKey}\"; returning default value`,\n );\n this.emitter.emit('error', this._uncheckedContext, error);\n return createErrorEvaluationDetail(ErrorKinds.WrongType, defaultValue);\n }\n }\n\n const successDetail = createSuccessEvaluationDetail(value, variation, reason);\n if (value === undefined || value === null) {\n this.logger.debug('Result value is null. Providing default value.');\n successDetail.value = defaultValue;\n }\n\n prerequisites?.forEach((prereqKey) => {\n this._variationInternal(prereqKey, undefined, this._eventFactoryDefault);\n });\n this._eventProcessor?.sendEvent(\n eventFactory.evalEventClient(\n flagKey,\n value,\n defaultValue,\n foundItem.flag,\n evalContext,\n reason,\n ),\n );\n return successDetail;\n }\n\n variation(flagKey: string, defaultValue?: LDFlagValue): LDFlagValue {\n const { value } = this._hookRunner.withEvaluation(\n flagKey,\n this._uncheckedContext,\n defaultValue,\n () => this._variationInternal(flagKey, defaultValue, this._eventFactoryDefault),\n );\n return value;\n }\n variationDetail(flagKey: string, defaultValue?: LDFlagValue): LDEvaluationDetail {\n return this._hookRunner.withEvaluation(flagKey, this._uncheckedContext, defaultValue, () =>\n this._variationInternal(flagKey, defaultValue, this._eventFactoryWithReasons),\n );\n }\n\n private _typedEval<T>(\n key: string,\n defaultValue: T,\n eventFactory: EventFactory,\n typeChecker: (value: unknown) => [boolean, string],\n ): LDEvaluationDetailTyped<T> {\n return this._hookRunner.withEvaluation(key, this._uncheckedContext, defaultValue, () =>\n this._variationInternal(key, defaultValue, eventFactory, typeChecker),\n );\n }\n\n boolVariation(key: string, defaultValue: boolean): boolean {\n return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [\n TypeValidators.Boolean.is(value),\n TypeValidators.Boolean.getType(),\n ]).value;\n }\n\n jsonVariation(key: string, defaultValue: unknown): unknown {\n return this.variation(key, defaultValue);\n }\n\n numberVariation(key: string, defaultValue: number): number {\n return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [\n TypeValidators.Number.is(value),\n TypeValidators.Number.getType(),\n ]).value;\n }\n\n stringVariation(key: string, defaultValue: string): string {\n return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [\n TypeValidators.String.is(value),\n TypeValidators.String.getType(),\n ]).value;\n }\n\n boolVariationDetail(key: string, defaultValue: boolean): LDEvaluationDetailTyped<boolean> {\n return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [\n TypeValidators.Boolean.is(value),\n TypeValidators.Boolean.getType(),\n ]);\n }\n\n numberVariationDetail(key: string, defaultValue: number): LDEvaluationDetailTyped<number> {\n return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [\n TypeValidators.Number.is(value),\n TypeValidators.Number.getType(),\n ]);\n }\n\n stringVariationDetail(key: string, defaultValue: string): LDEvaluationDetailTyped<string> {\n return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [\n TypeValidators.String.is(value),\n TypeValidators.String.getType(),\n ]);\n }\n\n jsonVariationDetail(key: string, defaultValue: unknown): LDEvaluationDetailTyped<unknown> {\n return this.variationDetail(key, defaultValue);\n }\n\n addHook(hook: Hook): void {\n this._hookRunner.addHook(hook);\n }\n\n /**\n * Enable/Disable event sending.\n * @param enabled True to enable event processing, false to disable.\n * @param flush True to flush while disabling. Useful to flush on certain state transitions.\n */\n protected setEventSendingEnabled(enabled: boolean, flush: boolean): void {\n if (this._eventSendingEnabled === enabled) {\n return;\n }\n this._eventSendingEnabled = enabled;\n\n if (enabled) {\n this.logger.debug('Starting event processor');\n this._eventProcessor?.start();\n } else if (flush) {\n this.logger?.debug('Flushing event processor before disabling.');\n // Disable and flush.\n this.flush().then(() => {\n // While waiting for the flush event sending could be re-enabled, in which case\n // we do not want to close the event processor.\n if (!this._eventSendingEnabled) {\n this.logger?.debug('Stopping event processor.');\n this._eventProcessor?.close();\n }\n });\n } else {\n // Just disabled.\n this.logger?.debug('Stopping event processor.');\n this._eventProcessor?.close();\n }\n }\n\n protected sendEvent(event: internal.InputEvent): void {\n this._eventProcessor?.sendEvent(event);\n }\n\n private _handleInspectionChanged(flagKeys: Array<string>, type: FlagChangeType) {\n if (!this._inspectorManager.hasInspectors()) {\n return;\n }\n\n const details: Record<string, LDEvaluationDetail> = {};\n flagKeys.forEach((flagKey) => {\n const item = this._flagManager.get(flagKey);\n if (item?.flag && !item.flag.deleted) {\n const { reason, value, variation } = item.flag;\n details[flagKey] = createSuccessEvaluationDetail(value, variation, reason);\n } else {\n details[flagKey] = {\n value: undefined,\n // For backwards compatibility purposes reason and variationIndex are null instead of\n // being undefined.\n reason: null,\n variationIndex: null,\n };\n }\n });\n if (type === 'init') {\n this._inspectorManager.onFlagsChanged(details);\n } else if (type === 'patch') {\n Object.entries(details).forEach(([flagKey, detail]) => {\n this._inspectorManager.onFlagChanged(flagKey, detail);\n });\n }\n }\n}\n","import { Context, LDLogger, LDPollingError, LDStreamingError } from '@launchdarkly/js-sdk-common';\n\nimport { FlagManager } from '../flag-manager/FlagManager';\nimport { ItemDescriptor } from '../flag-manager/ItemDescriptor';\nimport { DeleteFlag, Flags, PatchFlag } from '../types';\nimport { DataSourceState } from './DataSourceStatus';\nimport DataSourceStatusManager from './DataSourceStatusManager';\n\nexport default class DataSourceEventHandler {\n constructor(\n private readonly _flagManager: FlagManager,\n private readonly _statusManager: DataSourceStatusManager,\n private readonly _logger: LDLogger,\n ) {}\n\n async handlePut(context: Context, flags: Flags) {\n this._logger.debug(`Got PUT: ${Object.keys(flags)}`);\n\n // mapping flags to item descriptors\n const descriptors = Object.entries(flags).reduce(\n (acc: { [k: string]: ItemDescriptor }, [key, flag]) => {\n acc[key] = { version: flag.version, flag };\n return acc;\n },\n {},\n );\n await this._flagManager.init(context, descriptors);\n this._statusManager.requestStateUpdate(DataSourceState.Valid);\n }\n\n async handlePatch(context: Context, patchFlag: PatchFlag) {\n this._logger.debug(`Got PATCH ${JSON.stringify(patchFlag, null, 2)}`);\n this._flagManager.upsert(context, patchFlag.key, {\n version: patchFlag.version,\n flag: patchFlag,\n });\n }\n\n async handleDelete(context: Context, deleteFlag: DeleteFlag) {\n this._logger.debug(`Got DELETE ${JSON.stringify(deleteFlag, null, 2)}`);\n\n this._flagManager.upsert(context, deleteFlag.key, {\n version: deleteFlag.version,\n flag: {\n ...deleteFlag,\n deleted: true,\n // props below are set to sensible defaults. they are irrelevant\n // because this flag has been deleted.\n flagVersion: 0,\n value: undefined,\n variation: 0,\n trackEvents: false,\n },\n });\n }\n\n handleStreamingError(error: LDStreamingError) {\n this._statusManager.reportError(error.kind, error.message, error.code, error.recoverable);\n }\n\n handlePollingError(error: LDPollingError) {\n this._statusManager.reportError(error.kind, error.message, error.status, error.recoverable);\n }\n}\n","import { DataSourceErrorKind } from '@launchdarkly/js-sdk-common';\n\nimport LDEmitter from '../LDEmitter';\nimport DataSourceStatus, { DataSourceState } from './DataSourceStatus';\nimport DataSourceStatusErrorInfo from './DataSourceStatusErrorInfo';\n\n/**\n * Tracks the current data source status and emits updates when the status changes.\n */\nexport default class DataSourceStatusManager {\n private _state: DataSourceState;\n private _stateSinceMillis: number; // UNIX epoch timestamp in milliseconds\n private _errorInfo?: DataSourceStatusErrorInfo;\n private _timeStamper: () => number;\n\n constructor(\n private readonly _emitter: LDEmitter,\n timeStamper: () => number = () => Date.now(),\n ) {\n this._state = DataSourceState.Closed;\n this._stateSinceMillis = timeStamper();\n this._timeStamper = timeStamper;\n }\n\n get status(): DataSourceStatus {\n return {\n state: this._state,\n stateSince: this._stateSinceMillis,\n lastError: this._errorInfo,\n };\n }\n\n /**\n * Updates the state of the manager.\n *\n * @param requestedState to track\n * @param isError to indicate that the state update is a result of an error occurring.\n */\n private _updateState(requestedState: DataSourceState, isError = false) {\n const newState =\n requestedState === DataSourceState.Interrupted && this._state === DataSourceState.Initializing // don't go to interrupted from initializing (recoverable errors when initializing are not noteworthy)\n ? DataSourceState.Initializing\n : requestedState;\n\n const changedState = this._state !== newState;\n if (changedState) {\n this._state = newState;\n this._stateSinceMillis = this._timeStamper();\n }\n\n if (changedState || isError) {\n this._emitter.emit('dataSourceStatus', this.status);\n }\n }\n\n /**\n * Requests the manager move to the provided state. This request may be ignored\n * if the current state cannot transition to the requested state.\n * @param state that is requested\n */\n requestStateUpdate(state: DataSourceState) {\n this._updateState(state);\n }\n\n /**\n * Reports a datasource error to this manager. Since the {@link DataSourceStatus} includes error\n * information, it is possible that that a {@link DataSourceStatus} update is emitted with\n * the same {@link DataSourceState}.\n *\n * @param kind of the error\n * @param message for the error\n * @param statusCode of the error if there was one\n * @param recoverable to indicate that the error is anticipated to be recoverable\n */\n reportError(\n kind: DataSourceErrorKind,\n message: string,\n statusCode?: number,\n recoverable: boolean = false,\n ) {\n const errorInfo: DataSourceStatusErrorInfo = {\n kind,\n message,\n statusCode,\n time: this._timeStamper(),\n };\n this._errorInfo = errorInfo;\n this._updateState(recoverable ? DataSourceState.Interrupted : DataSourceState.Closed, true);\n }\n\n // TODO: SDK-702 - Implement network availability behaviors\n // setNetworkUnavailable() {\n // this.updateState(DataSourceState.NetworkUnavailable);\n // }\n}\n","import {\n DataSourceErrorKind,\n httpErrorMessage,\n HttpErrorResponse,\n isHttpRecoverable,\n LDLogger,\n LDPollingError,\n subsystem,\n} from '@launchdarkly/js-sdk-common';\n\nimport Requestor, { LDRequestError } from '../datasource/Requestor';\nimport { Flags } from '../types';\n\nexport type PollingErrorHandler = (err: LDPollingError) => void;\n\nfunction reportClosed(logger?: LDLogger) {\n logger?.debug(`Poll completed after the processor was closed. Skipping processing.`);\n}\n\n/**\n * @internal\n */\nexport default class PollingProcessor implements subsystem.LDStreamProcessor {\n private _stopped = false;\n\n private _timeoutHandle: any;\n\n constructor(\n private readonly _requestor: Requestor,\n private readonly _pollIntervalSeconds: number,\n private readonly _dataHandler: (flags: Flags) => void,\n private readonly _errorHandler?: PollingErrorHandler,\n private readonly _logger?: LDLogger,\n ) {}\n\n private async _poll() {\n if (this._stopped) {\n return;\n }\n\n const reportJsonError = (data: string) => {\n this._logger?.error('Polling received invalid data');\n this._logger?.debug(`Invalid JSON follows: ${data}`);\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.InvalidData,\n 'Malformed JSON data in polling response',\n ),\n );\n };\n\n this._logger?.debug('Polling LaunchDarkly for feature flag updates');\n const startTime = Date.now();\n try {\n const res = await this._requestor.requestPayload();\n try {\n // If the processor has been stopped, we discard the response.\n // This response could be for a no longer active context.\n if (this._stopped) {\n reportClosed(this._logger);\n return;\n }\n const flags = JSON.parse(res);\n try {\n this._dataHandler?.(flags);\n } catch (err) {\n this._logger?.error(`Exception from data handler: ${err}`);\n }\n } catch {\n reportJsonError(res);\n }\n } catch (err) {\n // If the processor has been stopped, we discard this error.\n // The original caller would consider this connection no longer active.\n if (this._stopped) {\n reportClosed(this._logger);\n return;\n }\n const requestError = err as LDRequestError;\n if (requestError.status !== undefined) {\n if (!isHttpRecoverable(requestError.status)) {\n this._logger?.error(httpErrorMessage(err as HttpErrorResponse, 'polling request'));\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.ErrorResponse,\n requestError.message,\n requestError.status,\n ),\n );\n return;\n }\n }\n this._logger?.error(\n httpErrorMessage(err as HttpErrorResponse, 'polling request', 'will retry'),\n );\n }\n\n const elapsed = Date.now() - startTime;\n const sleepFor = Math.max(this._pollIntervalSeconds * 1000 - elapsed, 0);\n\n this._logger?.debug('Elapsed: %d ms, sleeping for %d ms', elapsed, sleepFor);\n\n this._timeoutHandle = setTimeout(() => {\n this._poll();\n }, sleepFor);\n }\n\n start() {\n this._poll();\n }\n\n stop() {\n if (this._timeoutHandle) {\n clearTimeout(this._timeoutHandle);\n this._timeoutHandle = undefined;\n }\n this._stopped = true;\n }\n\n close() {\n this.stop();\n }\n}\n","import {\n DataSourceErrorKind,\n Encoding,\n EventName,\n EventSource,\n getStreamingUri,\n httpErrorMessage,\n HttpErrorResponse,\n internal,\n LDLogger,\n LDPollingError,\n LDStreamingError,\n ProcessStreamResponse,\n Requests,\n shouldRetry,\n StreamingErrorHandler,\n subsystem,\n} from '@launchdarkly/js-sdk-common';\n\nimport { StreamingDataSourceConfig } from '../datasource/DataSourceConfig';\nimport Requestor, { LDRequestError } from '../datasource/Requestor';\n\nconst reportJsonError = (\n type: string,\n data: string,\n logger?: LDLogger,\n errorHandler?: StreamingErrorHandler,\n) => {\n logger?.error(`Stream received invalid data in \"${type}\" message`);\n logger?.debug(`Invalid JSON follows: ${data}`);\n errorHandler?.(\n new LDStreamingError(DataSourceErrorKind.InvalidData, 'Malformed JSON data in event stream'),\n );\n};\n\nfunction reportEventClosed(eventName: string, logger?: LDLogger) {\n logger?.debug(`Received ${eventName} event after processor was closed. Skipping processing.`);\n}\n\nfunction reportPingClosed(logger?: LDLogger) {\n logger?.debug('Ping completed after processor was closed. Skipping processing.');\n}\n\nclass StreamingProcessor implements subsystem.LDStreamProcessor {\n private readonly _headers: { [key: string]: string | string[] };\n private readonly _streamUri: string;\n\n private _eventSource?: EventSource;\n private _connectionAttemptStartTime?: number;\n private _stopped = false;\n\n constructor(\n private readonly _plainContextString: string,\n private readonly _dataSourceConfig: StreamingDataSourceConfig,\n private readonly _listeners: Map<EventName, ProcessStreamResponse>,\n private readonly _requests: Requests,\n encoding: Encoding,\n private readonly _pollingRequestor: Requestor,\n private readonly _diagnosticsManager?: internal.DiagnosticsManager,\n private readonly _errorHandler?: StreamingErrorHandler,\n private readonly _logger?: LDLogger,\n ) {\n let path: string;\n if (_dataSourceConfig.useReport && !_requests.getEventSourceCapabilities().customMethod) {\n path = _dataSourceConfig.paths.pathPing(encoding, _plainContextString);\n } else {\n path = _dataSourceConfig.useReport\n ? _dataSourceConfig.paths.pathReport(encoding, _plainContextString)\n : _dataSourceConfig.paths.pathGet(encoding, _plainContextString);\n }\n const parameters: { key: string; value: string }[] = [\n ...(_dataSourceConfig.queryParameters ?? []),\n ];\n if (this._dataSourceConfig.withReasons) {\n parameters.push({ key: 'withReasons', value: 'true' });\n }\n\n this._requests = _requests;\n this._headers = { ..._dataSourceConfig.baseHeaders };\n this._logger = _logger;\n this._streamUri = getStreamingUri(_dataSourceConfig.serviceEndpoints, path, parameters);\n }\n\n private _logConnectionStarted() {\n this._connectionAttemptStartTime = Date.now();\n }\n\n private _logConnectionResult(success: boolean) {\n if (this._connectionAttemptStartTime && this._diagnosticsManager) {\n this._diagnosticsManager.recordStreamInit(\n this._connectionAttemptStartTime,\n !success,\n Date.now() - this._connectionAttemptStartTime,\n );\n }\n\n this._connectionAttemptStartTime = undefined;\n }\n\n /**\n * This is a wrapper around the passed errorHandler which adds additional\n * diagnostics and logging logic.\n *\n * @param err The error to be logged and handled.\n * @return boolean whether to retry the connection.\n *\n * @private\n */\n private _retryAndHandleError(err: HttpErrorResponse) {\n if (!shouldRetry(err)) {\n this._logConnectionResult(false);\n this._errorHandler?.(\n new LDStreamingError(DataSourceErrorKind.ErrorResponse, err.message, err.status, false),\n );\n this._logger?.error(httpErrorMessage(err, 'streaming request'));\n return false;\n }\n\n this._logger?.warn(httpErrorMessage(err, 'streaming request', 'will retry'));\n this._logConnectionResult(false);\n this._logConnectionStarted();\n return true;\n }\n\n start() {\n this._logConnectionStarted();\n\n let methodAndBodyOverrides;\n if (this._dataSourceConfig.useReport) {\n // REPORT will include a body, so content type is required.\n this._headers['content-type'] = 'application/json';\n\n // orverrides default method with REPORT and adds body.\n methodAndBodyOverrides = { method: 'REPORT', body: this._plainContextString };\n } else {\n // no method or body override\n methodAndBodyOverrides = {};\n }\n\n // TLS is handled by the platform implementation.\n const eventSource = this._requests.createEventSource(this._streamUri, {\n headers: this._headers, // adds content-type header required when body will be present\n ...methodAndBodyOverrides,\n errorFilter: (error: HttpErrorResponse) => this._retryAndHandleError(error),\n initialRetryDelayMillis: this._dataSourceConfig.initialRetryDelayMillis,\n readTimeoutMillis: 5 * 60 * 1000,\n retryResetIntervalMillis: 60 * 1000,\n });\n this._eventSource = eventSource;\n\n eventSource.onclose = () => {\n this._logger?.info('Closed LaunchDarkly stream connection');\n };\n\n eventSource.onerror = () => {\n // The work is done by `errorFilter`.\n };\n\n eventSource.onopen = () => {\n this._logger?.info('Opened LaunchDarkly stream connection');\n };\n\n eventSource.onretrying = (e) => {\n this._logger?.info(`Will retry stream connection in ${e.delayMillis} milliseconds`);\n };\n\n this._listeners.forEach(({ deserializeData, processJson }, eventName) => {\n eventSource.addEventListener(eventName, (event) => {\n // If an event comes in after the processor has been stopped, we skip processing it.\n // This event could be for a context which is no longer active.\n if (this._stopped) {\n reportEventClosed(eventName, this._logger);\n return;\n }\n\n this._logger?.debug(`Received ${eventName} event`);\n\n if (event?.data) {\n this._logConnectionResult(true);\n const { data } = event;\n const dataJson = deserializeData(data);\n\n if (!dataJson) {\n reportJsonError(eventName, data, this._logger, this._errorHandler);\n return;\n }\n processJson(dataJson);\n } else {\n this._errorHandler?.(\n new LDStreamingError(\n DataSourceErrorKind.InvalidData,\n 'Unexpected payload from event stream',\n ),\n );\n }\n });\n });\n\n // here we set up a listener that will poll when ping is received\n eventSource.addEventListener('ping', async () => {\n this._logger?.debug('Got PING, going to poll LaunchDarkly for feature flag updates');\n try {\n const res = await this._pollingRequestor.requestPayload();\n try {\n // If the ping completes after the processor has been stopped, then we discard it.\n // This event could be for a context which is no longer active.\n if (this._stopped) {\n reportPingClosed(this._logger);\n return;\n }\n const payload = JSON.parse(res);\n try {\n // forward the payload on to the PUT listener\n this._listeners.get('put')?.processJson(payload);\n } catch (err) {\n this._logger?.error(`Exception from data handler: ${err}`);\n }\n } catch {\n this._logger?.error('Polling after ping received invalid data');\n this._logger?.debug(`Invalid JSON follows: ${res}`);\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.InvalidData,\n 'Malformed JSON data in ping polling response',\n ),\n );\n }\n } catch (err) {\n if (this._stopped) {\n // If the ping errors after the processor has been stopped, then we discard it.\n // The original caller would consider this connection no longer active.\n reportPingClosed(this._logger);\n return;\n }\n const requestError = err as LDRequestError;\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.ErrorResponse,\n requestError.message,\n requestError.status,\n ),\n );\n }\n });\n }\n\n stop() {\n this._eventSource?.close();\n this._eventSource = undefined;\n this._stopped = true;\n }\n\n close() {\n this.stop();\n }\n}\n\nexport default StreamingProcessor;\n","import {\n Context,\n EventName,\n internal,\n LDContext,\n LDHeaders,\n LDLogger,\n Platform,\n ProcessStreamResponse,\n subsystem,\n} from '@launchdarkly/js-sdk-common';\n\nimport { LDIdentifyOptions } from './api/LDIdentifyOptions';\nimport { Configuration } from './configuration/Configuration';\nimport DataSourceEventHandler from './datasource/DataSourceEventHandler';\nimport { DataSourceState } from './datasource/DataSourceStatus';\nimport DataSourceStatusManager from './datasource/DataSourceStatusManager';\nimport Requestor from './datasource/Requestor';\nimport { FlagManager } from './flag-manager/FlagManager';\nimport LDEmitter from './LDEmitter';\nimport PollingProcessor from './polling/PollingProcessor';\nimport { DataSourcePaths, StreamingProcessor } from './streaming';\nimport { DeleteFlag, Flags, PatchFlag } from './types';\n\nexport interface DataManager {\n /**\n * This function handles the data management aspects of the identification process.\n *\n * Implementation Note: The identifyResolve and identifyReject function resolve or reject the\n * identify function at LDClient level. It is likely in individual implementations that these\n * functions will be passed to other components, such as a datasource, do indicate when the\n * identify process has been completed. The data manager identify function should return once\n * everything has been set in motion to complete the identification process.\n *\n * @param identifyResolve Called to reject the identify operation.\n * @param identifyReject Called to complete the identify operation.\n * @param context The context being identified.\n * @param identifyOptions Options for identification.\n */\n identify(\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n context: Context,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<void>;\n\n /**\n * Closes the data manager. Any active connections are closed.\n */\n close(): void;\n}\n\n/**\n * Factory interface for constructing data managers.\n */\nexport interface DataManagerFactory {\n (\n flagManager: FlagManager,\n configuration: Configuration,\n baseHeaders: LDHeaders,\n emitter: LDEmitter,\n diagnosticsManager?: internal.DiagnosticsManager,\n ): DataManager;\n}\n\nexport interface ConnectionParams {\n queryParameters?: { key: string; value: string }[];\n}\n\nexport abstract class BaseDataManager implements DataManager {\n protected updateProcessor?: subsystem.LDStreamProcessor;\n protected readonly logger: LDLogger;\n protected context?: Context;\n private _connectionParams?: ConnectionParams;\n protected readonly dataSourceStatusManager: DataSourceStatusManager;\n private readonly _dataSourceEventHandler: DataSourceEventHandler;\n protected closed = false;\n\n constructor(\n protected readonly platform: Platform,\n protected readonly flagManager: FlagManager,\n protected readonly credential: string,\n protected readonly config: Configuration,\n protected readonly getPollingPaths: () => DataSourcePaths,\n protected readonly getStreamingPaths: () => DataSourcePaths,\n protected readonly baseHeaders: LDHeaders,\n protected readonly emitter: LDEmitter,\n protected readonly diagnosticsManager?: internal.DiagnosticsManager,\n ) {\n this.logger = config.logger;\n this.dataSourceStatusManager = new DataSourceStatusManager(emitter);\n this._dataSourceEventHandler = new DataSourceEventHandler(\n flagManager,\n this.dataSourceStatusManager,\n this.config.logger,\n );\n }\n\n /**\n * Set additional connection parameters for requests polling/streaming.\n */\n protected setConnectionParams(connectionParams?: ConnectionParams) {\n this._connectionParams = connectionParams;\n }\n\n abstract identify(\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n context: Context,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<void>;\n\n protected createPollingProcessor(\n context: LDContext,\n checkedContext: Context,\n requestor: Requestor,\n identifyResolve?: () => void,\n identifyReject?: (err: Error) => void,\n ) {\n const processor = new PollingProcessor(\n requestor,\n this.config.pollInterval,\n async (flags) => {\n await this._dataSourceEventHandler.handlePut(checkedContext, flags);\n identifyResolve?.();\n },\n (err) => {\n this.emitter.emit('error', context, err);\n this._dataSourceEventHandler.handlePollingError(err);\n identifyReject?.(err);\n },\n this.logger,\n );\n\n this.updateProcessor = this._decorateProcessorWithStatusReporting(\n processor,\n this.dataSourceStatusManager,\n );\n }\n\n protected createStreamingProcessor(\n context: LDContext,\n checkedContext: Context,\n pollingRequestor: Requestor,\n identifyResolve?: () => void,\n identifyReject?: (err: Error) => void,\n ) {\n const processor = new StreamingProcessor(\n JSON.stringify(context),\n {\n credential: this.credential,\n serviceEndpoints: this.config.serviceEndpoints,\n paths: this.getStreamingPaths(),\n baseHeaders: this.baseHeaders,\n initialRetryDelayMillis: this.config.streamInitialReconnectDelay * 1000,\n withReasons: this.config.withReasons,\n useReport: this.config.useReport,\n queryParameters: this._connectionParams?.queryParameters,\n },\n this.createStreamListeners(checkedContext, identifyResolve),\n this.platform.requests,\n this.platform.encoding!,\n pollingRequestor,\n this.diagnosticsManager,\n (e) => {\n this.emitter.emit('error', context, e);\n this._dataSourceEventHandler.handleStreamingError(e);\n identifyReject?.(e);\n },\n this.logger,\n );\n\n this.updateProcessor = this._decorateProcessorWithStatusReporting(\n processor,\n this.dataSourceStatusManager,\n );\n }\n\n protected createStreamListeners(\n context: Context,\n identifyResolve?: () => void,\n ): Map<EventName, ProcessStreamResponse> {\n const listeners = new Map<EventName, ProcessStreamResponse>();\n\n listeners.set('put', {\n deserializeData: JSON.parse,\n processJson: async (flags: Flags) => {\n await this._dataSourceEventHandler.handlePut(context, flags);\n identifyResolve?.();\n },\n });\n\n listeners.set('patch', {\n deserializeData: JSON.parse,\n processJson: async (patchFlag: PatchFlag) => {\n this._dataSourceEventHandler.handlePatch(context, patchFlag);\n },\n });\n\n listeners.set('delete', {\n deserializeData: JSON.parse,\n processJson: async (deleteFlag: DeleteFlag) => {\n this._dataSourceEventHandler.handleDelete(context, deleteFlag);\n },\n });\n\n return listeners;\n }\n\n private _decorateProcessorWithStatusReporting(\n processor: subsystem.LDStreamProcessor,\n statusManager: DataSourceStatusManager,\n ): subsystem.LDStreamProcessor {\n return {\n start: () => {\n // update status before starting processor to ensure potential errors are reported after initializing\n statusManager.requestStateUpdate(DataSourceState.Initializing);\n processor.start();\n },\n stop: () => {\n processor.stop();\n statusManager.requestStateUpdate(DataSourceState.Closed);\n },\n close: () => {\n processor.close();\n statusManager.requestStateUpdate(DataSourceState.Closed);\n },\n };\n }\n\n public close() {\n this.updateProcessor?.close();\n this.closed = true;\n }\n}\n","/**\n * All access to browser specific APIs should be limited to this file.\n * Care should be taken to ensure that any given method will work in the service worker API. So if\n * something isn't available in the service worker API attempt to provide reasonable defaults.\n */\n\nexport function isDocument() {\n return typeof document !== undefined;\n}\n\nexport function isWindow() {\n return typeof window !== undefined;\n}\n\n/**\n * Register an event handler on the document. If there is no document, such as when running in\n * a service worker, then no operation is performed.\n *\n * @param type The event type to register a handler for.\n * @param listener The handler to register.\n * @param options Event registration options.\n * @returns a function which unregisters the handler.\n */\nexport function addDocumentEventListener(\n type: string,\n listener: (this: Document, ev: Event) => any,\n options?: boolean | AddEventListenerOptions,\n): () => void {\n if (isDocument()) {\n document.addEventListener(type, listener, options);\n return () => {\n document.removeEventListener(type, listener, options);\n };\n }\n // No document, so no need to unregister anything.\n return () => {};\n}\n\n/**\n * Register an event handler on the window. If there is no window, such as when running in\n * a service worker, then no operation is performed.\n *\n * @param type The event type to register a handler for.\n * @param listener The handler to register.\n * @param options Event registration options.\n * @returns a function which unregisters the handler.\n */\nexport function addWindowEventListener(\n type: string,\n listener: (this: Document, ev: Event) => any,\n options?: boolean | AddEventListenerOptions,\n): () => void {\n if (isDocument()) {\n window.addEventListener(type, listener, options);\n return () => {\n window.removeEventListener(type, listener, options);\n };\n }\n // No document, so no need to unregister anything.\n return () => {};\n}\n\n/**\n * For non-window code this will always be an empty string.\n */\nexport function getHref(): string {\n if (isWindow()) {\n return window.location.href;\n }\n return '';\n}\n\n/**\n * For non-window code this will always be an empty string.\n */\nexport function getLocationSearch(): string {\n if (isWindow()) {\n return window.location.search;\n }\n return '';\n}\n\n/**\n * For non-window code this will always be an empty string.\n */\nexport function getLocationHash(): string {\n if (isWindow()) {\n return window.location.hash;\n }\n return '';\n}\n\nexport function getCrypto(): Crypto {\n if (typeof crypto !== undefined) {\n return crypto;\n }\n // This would indicate running in an environment that doesn't have window.crypto or self.crypto.\n throw Error('Access to a web crypto API is required');\n}\n\n/**\n * Get the visibility state. For non-documents this will always be 'invisible'.\n *\n * @returns The document visibility.\n */\nexport function getVisibility(): string {\n if (isDocument()) {\n return document.visibilityState;\n }\n return 'visibile';\n}\n\nexport function querySelectorAll(selector: string): NodeListOf<Element> | undefined {\n if (isDocument()) {\n return document.querySelectorAll(selector);\n }\n return undefined;\n}\n","import { Flag, ItemDescriptor, LDLogger } from '@launchdarkly/js-client-sdk-common';\n\nexport function readFlagsFromBootstrap(\n logger: LDLogger,\n data: any,\n): { [key: string]: ItemDescriptor } {\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(\n 'LaunchDarkly client was initialized with bootstrap data that did not include flag' +\n ' metadata. Events may not be sent correctly.',\n );\n }\n if (data[validKey] === false) {\n logger.warn(\n 'LaunchDarkly bootstrap data is not available because the back end could not read the flags.',\n );\n }\n const ret: { [key: string]: ItemDescriptor } = {};\n keys.forEach((key) => {\n if (key !== metadataKey && key !== validKey) {\n let flag: Flag;\n if (metadata && metadata[key]) {\n flag = {\n value: data[key],\n ...metadata[key],\n };\n } else {\n flag = {\n value: data[key],\n version: 0,\n };\n }\n ret[key] = {\n version: flag.version,\n flag,\n };\n }\n });\n return ret;\n}\n","import {\n BaseDataManager,\n Configuration,\n Context,\n DataSourceErrorKind,\n DataSourcePaths,\n DataSourceState,\n FlagManager,\n httpErrorMessage,\n internal,\n LDEmitter,\n LDHeaders,\n LDIdentifyOptions,\n makeRequestor,\n Platform,\n shouldRetry,\n sleep,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { readFlagsFromBootstrap } from './bootstrap';\nimport { BrowserIdentifyOptions } from './BrowserIdentifyOptions';\nimport { ValidatedOptions } from './options';\n\nconst logTag = '[BrowserDataManager]';\n\nexport default class BrowserDataManager extends BaseDataManager {\n // If streaming is forced on or off, then we follow that setting.\n // Otherwise we automatically manage streaming state.\n private _forcedStreaming?: boolean = undefined;\n private _automaticStreamingState: boolean = false;\n private _secureModeHash?: string;\n\n // +-----------+-----------+---------------+\n // | forced | automatic | state |\n // +-----------+-----------+---------------+\n // | true | false | streaming |\n // | true | true | streaming |\n // | false | true | not streaming |\n // | false | false | not streaming |\n // | undefined | true | streaming |\n // | undefined | false | not streaming |\n // +-----------+-----------+---------------+\n\n constructor(\n platform: Platform,\n flagManager: FlagManager,\n credential: string,\n config: Configuration,\n private readonly _browserConfig: ValidatedOptions,\n getPollingPaths: () => DataSourcePaths,\n getStreamingPaths: () => DataSourcePaths,\n baseHeaders: LDHeaders,\n emitter: LDEmitter,\n diagnosticsManager?: internal.DiagnosticsManager,\n ) {\n super(\n platform,\n flagManager,\n credential,\n config,\n getPollingPaths,\n getStreamingPaths,\n baseHeaders,\n emitter,\n diagnosticsManager,\n );\n this._forcedStreaming = _browserConfig.streaming;\n }\n\n private _debugLog(message: any, ...args: any[]) {\n this.logger.debug(`${logTag} ${message}`, ...args);\n }\n\n override async identify(\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n context: Context,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<void> {\n if (this.closed) {\n this._debugLog('Identify called after data manager was closed.');\n return;\n }\n\n this.context = context;\n const browserIdentifyOptions = identifyOptions as BrowserIdentifyOptions | undefined;\n if (browserIdentifyOptions?.hash) {\n this.setConnectionParams({\n queryParameters: [{ key: 'h', value: browserIdentifyOptions.hash }],\n });\n } else {\n this.setConnectionParams();\n }\n this._secureModeHash = browserIdentifyOptions?.hash;\n\n if (browserIdentifyOptions?.bootstrap) {\n this._finishIdentifyFromBootstrap(context, browserIdentifyOptions.bootstrap, identifyResolve);\n } else {\n if (await this.flagManager.loadCached(context)) {\n this._debugLog('Identify - Flags loaded from cache. Continuing to initialize via a poll.');\n }\n\n await this._finishIdentifyFromPoll(context, identifyResolve, identifyReject);\n }\n this._updateStreamingState();\n }\n\n /**\n * A helper function for the initial poll request. This is mainly here to facilitate\n * the retry logic.\n *\n * @param context - LDContext to request payload for.\n * @returns Payload as a string.\n */\n private async _requestPayload(context: Context): Promise<string> {\n const plainContextString = JSON.stringify(Context.toLDContext(context));\n const pollingRequestor = makeRequestor(\n plainContextString,\n this.config.serviceEndpoints,\n this.getPollingPaths(),\n this.platform.requests,\n this.platform.encoding!,\n this.baseHeaders,\n [],\n this.config.withReasons,\n this.config.useReport,\n this._secureModeHash,\n );\n\n // NOTE: We are currently hardcoding in 3 retries for the initial\n // poll. We can make this configurable in the future.\n const maxRetries = 3;\n\n let lastError: any;\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n try {\n // eslint-disable-next-line no-await-in-loop\n return await pollingRequestor.requestPayload();\n } catch (e: any) {\n if (!shouldRetry(e)) {\n throw e;\n }\n lastError = e;\n // NOTE: current we are hardcoding the retry interval to 1 second.\n // We can make this configurable in the future.\n if (attempt < maxRetries) {\n this._debugLog(httpErrorMessage(e, 'initial poll request', 'will retry'));\n // eslint-disable-next-line no-await-in-loop\n await sleep(1000);\n }\n }\n }\n\n throw lastError;\n }\n\n private async _finishIdentifyFromPoll(\n context: Context,\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n ) {\n try {\n this.dataSourceStatusManager.requestStateUpdate(DataSourceState.Initializing);\n\n const payload = await this._requestPayload(context);\n\n try {\n const listeners = this.createStreamListeners(context, identifyResolve);\n const putListener = listeners.get('put');\n putListener!.processJson(putListener!.deserializeData(payload));\n } catch (e: any) {\n this.dataSourceStatusManager.reportError(\n DataSourceErrorKind.InvalidData,\n e.message ?? 'Could not parse poll response',\n );\n }\n } catch (e: any) {\n this.dataSourceStatusManager.reportError(\n DataSourceErrorKind.NetworkError,\n e.message ?? 'unexpected network error',\n e.status,\n );\n identifyReject(e);\n }\n }\n\n private _finishIdentifyFromBootstrap(\n context: Context,\n bootstrap: unknown,\n identifyResolve: () => void,\n ) {\n this.flagManager.setBootstrap(context, readFlagsFromBootstrap(this.logger, bootstrap));\n this._debugLog('Identify - Initialization completed from bootstrap');\n identifyResolve();\n }\n\n setForcedStreaming(streaming?: boolean) {\n this._forcedStreaming = streaming;\n this._updateStreamingState();\n }\n\n setAutomaticStreamingState(streaming: boolean) {\n this._automaticStreamingState = streaming;\n this._updateStreamingState();\n }\n\n private _updateStreamingState() {\n const shouldBeStreaming =\n this._forcedStreaming ||\n (this._automaticStreamingState && this._forcedStreaming === undefined);\n\n this._debugLog(\n `Updating streaming state. forced(${this._forcedStreaming}) automatic(${this._automaticStreamingState})`,\n );\n\n if (shouldBeStreaming) {\n this._startDataSource();\n } else {\n this._stopDataSource();\n }\n }\n\n private _stopDataSource() {\n if (this.updateProcessor) {\n this._debugLog('Stopping update processor.');\n }\n this.updateProcessor?.close();\n this.updateProcessor = undefined;\n }\n\n private _startDataSource() {\n if (this.updateProcessor) {\n this._debugLog('Update processor already active. Not changing state.');\n return;\n }\n\n if (!this.context) {\n this._debugLog('Context not set, not starting update processor.');\n return;\n }\n\n this._debugLog('Starting update processor.');\n this._setupConnection(this.context);\n }\n\n private _setupConnection(\n context: Context,\n identifyResolve?: () => void,\n identifyReject?: (err: Error) => void,\n ) {\n const rawContext = Context.toLDContext(context)!;\n\n this.updateProcessor?.close();\n\n const plainContextString = JSON.stringify(Context.toLDContext(context));\n const pollingRequestor = makeRequestor(\n plainContextString,\n this.config.serviceEndpoints,\n this.getPollingPaths(),\n this.platform.requests,\n this.platform.encoding!,\n this.baseHeaders,\n [],\n this.config.withReasons,\n this.config.useReport,\n this._secureModeHash,\n );\n\n this.createStreamingProcessor(\n rawContext,\n context,\n pollingRequestor,\n identifyResolve,\n identifyReject,\n );\n\n this.updateProcessor!.start();\n }\n}\n","import { addDocumentEventListener, addWindowEventListener, getVisibility } from './BrowserApi';\n\nexport function registerStateDetection(requestFlush: () => void): () => void {\n // When the visibility of the page changes to hidden we want to flush any pending events.\n //\n // This is handled with visibility, instead of beforeunload/unload\n // because those events are not compatible with the bfcache and are unlikely\n // to be called in many situations. For more information see: https://developer.chrome.com/blog/page-lifecycle-api/\n //\n // Redundancy is included by using both the visibilitychange handler as well as\n // pagehide, because different browsers, and versions have different bugs with each.\n // This also may provide more opportunity for the events to get flushed.\n //\n const handleVisibilityChange = () => {\n if (getVisibility() === 'hidden') {\n requestFlush();\n }\n };\n\n const removeDocListener = addDocumentEventListener('visibilitychange', handleVisibilityChange);\n const removeWindowListener = addWindowEventListener('pagehide', requestFlush);\n\n return () => {\n removeDocListener();\n removeWindowListener();\n };\n}\n","// From here: https://github.com/sindresorhus/escape-string-regexp\n\n// This is vendored to reduce the complexity of the built and test setup.\n// The NPM package for escape-string-regexp is ESM only, and that introduces\n// complexity to the jest configuration which works best/easiest with CJS.\n\n/**\n * MIT License\n *\n * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Escape regular expression especial characters.\n *\n * @param string The regular expression to escape.\n * @returns The escaped expression.\n */\nexport default function escapeStringRegexp(string: string) {\n if (typeof string !== 'string') {\n throw new TypeError('Expected a string');\n }\n\n // Escape characters with special meaning either inside or outside character sets.\n // Use a simple backslash escape when it’s always valid, and a `\\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.\n return string.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&').replace(/-/g, '\\\\x2d');\n}\n","import {\n addDocumentEventListener,\n getHref,\n getLocationHash,\n getLocationSearch,\n querySelectorAll,\n} from '../BrowserApi';\nimport escapeStringRegexp from '../vendor/escapeStringRegexp';\nimport { ClickGoal, Goal, Matcher } from './Goals';\n\ntype EventHandler = (goal: Goal) => void;\n\nexport function matchesUrl(matcher: Matcher, href: string, search: string, hash: string) {\n /**\n * Hash fragments are included when they include forward slashes to allow for applications that\n * use path-like hashes. (http://example.com/url/path#/additional/path)\n *\n * When they do not include a forward slash they are considered anchors and are not included\n * in matching.\n */\n const keepHash = (matcher.kind === 'substring' || matcher.kind === 'regex') && hash.includes('/');\n // For most matching purposes we want the \"canonical\" URL, which in this context means the\n // excluding the query parameters and hash (unless the hash is path-like).\n const canonicalUrl = (keepHash ? href : href.replace(hash, '')).replace(search, '');\n\n switch (matcher.kind) {\n case 'exact':\n return new RegExp(`^${escapeStringRegexp(matcher.url)}/?$`).test(href);\n case 'canonical':\n return new RegExp(`^${escapeStringRegexp(matcher.url)}/?$`).test(canonicalUrl);\n case 'substring':\n return new RegExp(`.*${escapeStringRegexp(matcher.substring)}.*$`).test(canonicalUrl);\n case 'regex':\n return new RegExp(matcher.pattern).test(canonicalUrl);\n default:\n return false;\n }\n}\n\nfunction findGoalsForClick(event: Event, clickGoals: ClickGoal[]) {\n const matches: ClickGoal[] = [];\n\n clickGoals.forEach((goal) => {\n let target: Node | null = event.target as Node;\n const { selector } = goal;\n const elements = querySelectorAll(selector);\n\n // Traverse from the target of the event up the page hierarchy.\n // If there are no element that match the selector, then no need to check anything.\n while (target && elements?.length) {\n // The elements are a NodeList, so it doesn't have the array functions. For performance we\n // do not convert it to an array.\n for (let elementIndex = 0; elementIndex < elements.length; elementIndex += 1) {\n if (target === elements[elementIndex]) {\n matches.push(goal);\n // The same element should not be in the list multiple times.\n // Multiple objects in the hierarchy can match the selector, so we don't break the outer\n // loop.\n break;\n }\n }\n target = target.parentNode as Node;\n }\n });\n\n return matches;\n}\n\n/**\n * Tracks the goals on an individual \"page\" (combination of route, query params, and hash).\n */\nexport default class GoalTracker {\n private _cleanup?: () => void;\n constructor(goals: Goal[], onEvent: EventHandler) {\n const goalsMatchingUrl = goals.filter((goal) =>\n goal.urls?.some((matcher) =>\n matchesUrl(matcher, getHref(), getLocationSearch(), getLocationHash()),\n ),\n );\n\n const pageviewGoals = goalsMatchingUrl.filter((goal) => goal.kind === 'pageview');\n const clickGoals = goalsMatchingUrl.filter((goal) => goal.kind === 'click') as ClickGoal[];\n\n pageviewGoals.forEach((event) => onEvent(event));\n\n if (clickGoals.length) {\n // Click handler is not a member function in order to avoid having to bind it for the event\n // handler and then track a reference to that bound handler.\n const clickHandler = (event: Event) => {\n findGoalsForClick(event, clickGoals).forEach((clickGoal) => {\n onEvent(clickGoal);\n });\n };\n this._cleanup = addDocumentEventListener('click', clickHandler);\n }\n }\n\n /**\n * Close the tracker which stops listening to any events.\n */\n close() {\n this._cleanup?.();\n }\n}\n","import { addWindowEventListener, getHref } from '../BrowserApi';\n\nexport const LOCATION_WATCHER_INTERVAL_MS = 300;\n\n// Using any for the timer handle because the type is not the same for all\n// platforms and we only need to use it opaquely.\nexport type IntervalHandle = any;\n\nexport interface LocationWatcher {\n close(): void;\n}\n\n/**\n * Watches the browser URL and detects changes.\n *\n * This is used to detect URL changes for generating pageview events.\n *\n * @internal\n */\nexport class DefaultLocationWatcher {\n private _previousLocation?: string;\n private _watcherHandle: IntervalHandle;\n private _cleanupListeners?: () => void;\n\n /**\n * @param callback Callback that is executed whenever a URL change is detected.\n */\n constructor(callback: () => void) {\n this._previousLocation = getHref();\n const checkUrl = () => {\n const currentLocation = getHref();\n\n if (currentLocation !== this._previousLocation) {\n this._previousLocation = currentLocation;\n callback();\n }\n };\n /** The location is watched via polling and popstate events because it is possible to miss\n * navigation at certain points with just popstate. It is also to miss events with polling\n * because they can happen within the polling interval.\n * Details on when popstate is called:\n * https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event#when_popstate_is_sent\n */\n this._watcherHandle = setInterval(checkUrl, LOCATION_WATCHER_INTERVAL_MS);\n\n const removeListener = addWindowEventListener('popstate', checkUrl);\n\n this._cleanupListeners = () => {\n removeListener();\n };\n }\n\n /**\n * Stop watching for location changes.\n */\n close(): void {\n if (this._watcherHandle) {\n clearInterval(this._watcherHandle);\n }\n this._cleanupListeners?.();\n }\n}\n","import { LDUnexpectedResponseError, Requests } from '@launchdarkly/js-client-sdk-common';\n\nimport { getHref } from '../BrowserApi';\nimport { Goal } from './Goals';\nimport GoalTracker from './GoalTracker';\nimport { DefaultLocationWatcher, LocationWatcher } from './LocationWatcher';\n\nexport default class GoalManager {\n private _goals?: Goal[] = [];\n private _url: string;\n private _watcher?: LocationWatcher;\n private _tracker?: GoalTracker;\n private _isTracking = false;\n\n constructor(\n credential: string,\n private readonly _requests: Requests,\n baseUrl: string,\n private readonly _reportError: (err: Error) => void,\n private readonly _reportGoal: (url: string, goal: Goal) => void,\n locationWatcherFactory: (cb: () => void) => LocationWatcher = (cb) =>\n new DefaultLocationWatcher(cb),\n ) {\n // TODO: Generate URL in a better way.\n this._url = `${baseUrl}/sdk/goals/${credential}`;\n\n this._watcher = locationWatcherFactory(() => {\n this._createTracker();\n });\n }\n\n public async initialize(): Promise<void> {\n await this._fetchGoals();\n // If tracking has been started before goal fetching completes, we need to\n // create the tracker so it can start watching for events.\n this._createTracker();\n }\n\n public startTracking() {\n this._isTracking = true;\n this._createTracker();\n }\n\n private _createTracker() {\n if (!this._isTracking) {\n return;\n }\n this._tracker?.close();\n if (this._goals && this._goals.length) {\n this._tracker = new GoalTracker(this._goals, (goal) => {\n this._reportGoal(getHref(), goal);\n });\n }\n }\n\n private async _fetchGoals(): Promise<void> {\n try {\n const res = await this._requests.fetch(this._url);\n this._goals = await res.json();\n } catch (err) {\n this._reportError(new LDUnexpectedResponseError(`Encountered error fetching goals: ${err}`));\n }\n }\n\n close(): void {\n this._watcher?.close();\n this._tracker?.close();\n }\n}\n","export type GoalKind = 'click' | 'pageview';\n\nexport type MatcherKind = 'exact' | 'canonical' | 'substring' | 'regex';\n\nexport interface ExactMatcher {\n kind: 'exact';\n url: string;\n}\n\nexport interface SubstringMatcher {\n kind: 'substring';\n substring: string;\n}\n\nexport interface CanonicalMatcher {\n kind: 'canonical';\n url: string;\n}\n\nexport interface RegexMatcher {\n kind: 'regex';\n pattern: string;\n}\n\nexport type Matcher = ExactMatcher | SubstringMatcher | CanonicalMatcher | RegexMatcher;\n\nexport interface PageViewGoal {\n key: string;\n kind: 'pageview';\n urls?: Matcher[];\n}\n\nexport interface ClickGoal {\n key: string;\n kind: 'click';\n urls?: Matcher[];\n selector: string;\n}\n\nexport type Goal = PageViewGoal | ClickGoal;\n\nexport function isClick(goal: Goal): goal is ClickGoal {\n return goal.kind === 'click';\n}\n","import {\n LDLogger,\n LDOptions as LDOptionsBase,\n OptionMessages,\n TypeValidator,\n TypeValidators,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { LDPlugin } from './LDPlugin';\n\nconst DEFAULT_FLUSH_INTERVAL_SECONDS = 2;\n\n/**\n * Initialization options for the LaunchDarkly browser SDK.\n */\nexport interface BrowserOptions extends Omit<LDOptionsBase, 'initialConnectionMode'> {\n /**\n * Whether the client should make a request to LaunchDarkly for Experimentation metrics (goals).\n *\n * This is true by default, meaning that this request will be made on every page load.\n * Set it to false if you are not using Experimentation and want to skip the request.\n */\n fetchGoals?: boolean;\n\n /**\n * A function which, if present, can change the URL in analytics events to something other\n * than the actual browser URL. It will be called with the current browser URL as a parameter,\n * and returns the value that should be stored in the event's `url` property.\n *\n * It may be useful to customize the `url` to provide specific meaning, incorporate\n * client-side routing concerns, or redact tokens or other info.\n */\n eventUrlTransformer?: (url: string) => string;\n\n /**\n * Whether or not to open a streaming connection to LaunchDarkly for live flag updates.\n *\n * If this is true, the client will always attempt to maintain a streaming connection; if false,\n * it never will. If you leave the value undefined (the default), the client will open a streaming\n * connection if you subscribe to `\"change\"` or `\"change:flag-key\"` events.\n *\n * This is equivalent to calling `client.setStreaming()` with the same value.\n */\n streaming?: boolean;\n\n /**\n * Determines if the SDK responds to entering different visibility states, such as foreground and background.\n * An example is flushing buffered events when going to the background.\n *\n * This is true by default. Generally speaking the SDK will be able to most reliably deliver\n * events with this setting on.\n *\n * It may be useful to disable for environments where not all window/document objects are\n * available, such as when running the SDK in a browser extension.\n */\n automaticBackgroundHandling?: boolean;\n\n /**\n * A list of plugins to be used with the SDK.\n *\n * Plugin support is currently experimental and subject to change.\n */\n plugins?: LDPlugin[];\n}\n\nexport interface ValidatedOptions {\n fetchGoals: boolean;\n eventUrlTransformer: (url: string) => string;\n streaming?: boolean;\n automaticBackgroundHandling?: boolean;\n plugins: LDPlugin[];\n}\n\nconst optDefaults = {\n fetchGoals: true,\n eventUrlTransformer: (url: string) => url,\n streaming: undefined,\n plugins: [],\n};\n\nconst validators: { [Property in keyof BrowserOptions]: TypeValidator | undefined } = {\n fetchGoals: TypeValidators.Boolean,\n eventUrlTransformer: TypeValidators.Function,\n streaming: TypeValidators.Boolean,\n plugins: TypeValidators.createTypeArray('LDPlugin', {}),\n};\n\nfunction withBrowserDefaults(opts: BrowserOptions): BrowserOptions {\n const output = { ...opts };\n output.flushInterval ??= DEFAULT_FLUSH_INTERVAL_SECONDS;\n return output;\n}\n\nexport function filterToBaseOptionsWithDefaults(opts: BrowserOptions): LDOptionsBase {\n const baseOptions: LDOptionsBase = withBrowserDefaults(opts);\n\n // Remove any browser specific configuration keys so we don't get warnings from\n // the base implementation for unknown configuration.\n Object.keys(optDefaults).forEach((key) => {\n delete (baseOptions as any)[key];\n });\n return baseOptions;\n}\n\nexport default function validateBrowserOptions(\n opts: BrowserOptions,\n logger: LDLogger,\n): ValidatedOptions {\n const output: ValidatedOptions = { ...optDefaults };\n\n Object.entries(validators).forEach((entry) => {\n const [key, validator] = entry as [keyof BrowserOptions, TypeValidator];\n const value = opts[key];\n if (value !== undefined) {\n if (validator.is(value)) {\n output[key as keyof ValidatedOptions] = value as any;\n } else {\n logger.warn(OptionMessages.wrongOptionType(key, validator.getType(), typeof value));\n }\n }\n });\n\n return output;\n}\n","import { Hasher } from '@launchdarkly/js-client-sdk-common';\n\nexport default class BrowserHasher implements Hasher {\n private _data: string[] = [];\n private _algorithm: string;\n constructor(\n private readonly _webcrypto: Crypto,\n algorithm: string,\n ) {\n switch (algorithm) {\n case 'sha1':\n this._algorithm = 'SHA-1';\n break;\n case 'sha256':\n this._algorithm = 'SHA-256';\n break;\n default:\n throw new Error(`Algorithm is not supported ${algorithm}`);\n }\n }\n\n async asyncDigest(encoding: string): Promise<string> {\n const combinedData = this._data.join('');\n const encoded = new TextEncoder().encode(combinedData);\n const digestedBuffer = await this._webcrypto.subtle.digest(this._algorithm, encoded);\n switch (encoding) {\n case 'base64':\n return btoa(String.fromCharCode(...new Uint8Array(digestedBuffer)));\n case 'hex':\n // Convert the buffer to an array of uint8 values, then convert each of those to hex.\n // The map function on a Uint8Array directly only maps to other Uint8Arrays.\n return [...new Uint8Array(digestedBuffer)]\n .map((val) => val.toString(16).padStart(2, '0'))\n .join('');\n default:\n throw new Error(`Encoding is not supported ${encoding}`);\n }\n }\n\n update(data: string): Hasher {\n this._data.push(data);\n return this as Hasher;\n }\n}\n","// The implementation in this file generates UUIDs in v4 format and is suitable\n// for use as a UUID in LaunchDarkly events. It is not a rigorous implementation.\n\n// It uses crypto.randomUUID when available.\n// If crypto.randomUUID is not available, then it uses random values and forms\n// the UUID itself.\n// When possible it uses crypto.getRandomValues, but it can use Math.random\n// if crypto.getRandomValues is not available.\n\n// UUIDv4 Struct definition.\n// https://www.rfc-archive.org/getrfc.php?rfc=4122\n// Appendix A. Appendix A - Sample Implementation\nconst timeLow = {\n start: 0,\n end: 3,\n};\nconst timeMid = {\n start: 4,\n end: 5,\n};\nconst timeHiAndVersion = {\n start: 6,\n end: 7,\n};\nconst clockSeqHiAndReserved = {\n start: 8,\n end: 8,\n};\nconst clockSeqLow = {\n start: 9,\n end: 9,\n};\nconst nodes = {\n start: 10,\n end: 15,\n};\n\nfunction getRandom128bit(): number[] {\n if (crypto && crypto.getRandomValues) {\n const typedArray = new Uint8Array(16);\n crypto.getRandomValues(typedArray);\n return [...typedArray.values()];\n }\n const values = [];\n for (let index = 0; index < 16; index += 1) {\n // Math.random is 0-1 with inclusive min and exclusive max.\n values.push(Math.floor(Math.random() * 256));\n }\n return values;\n}\n\nfunction hex(bytes: number[], range: { start: number; end: number }): string {\n let strVal = '';\n for (let index = range.start; index <= range.end; index += 1) {\n strVal += bytes[index].toString(16).padStart(2, '0');\n }\n return strVal;\n}\n\n/**\n * Given a list of 16 random bytes generate a UUID in v4 format.\n *\n * Note: The input bytes are modified to conform to the requirements of UUID v4.\n *\n * @param bytes A list of 16 bytes.\n * @returns A UUID v4 string.\n */\nexport function formatDataAsUuidV4(bytes: number[]): string {\n // https://www.rfc-archive.org/getrfc.php?rfc=4122\n // 4.4. Algorithms for Creating a UUID from Truly Random or\n // Pseudo-Random Numbers\n\n // Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and\n // one, respectively.\n // eslint-disable-next-line no-bitwise, no-param-reassign\n bytes[clockSeqHiAndReserved.start] = (bytes[clockSeqHiAndReserved.start] | 0x80) & 0xbf;\n // Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to\n // the 4-bit version number from Section 4.1.3.\n // eslint-disable-next-line no-bitwise, no-param-reassign\n bytes[timeHiAndVersion.start] = (bytes[timeHiAndVersion.start] & 0x0f) | 0x40;\n\n return (\n `${hex(bytes, timeLow)}-${hex(bytes, timeMid)}-${hex(bytes, timeHiAndVersion)}-` +\n `${hex(bytes, clockSeqHiAndReserved)}${hex(bytes, clockSeqLow)}-${hex(bytes, nodes)}`\n );\n}\n\nexport function fallbackUuidV4(): string {\n const bytes = getRandom128bit();\n return formatDataAsUuidV4(bytes);\n}\n\nexport default function randomUuidV4(): string {\n if (typeof crypto !== undefined && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n return fallbackUuidV4();\n}\n","import { Crypto } from '@launchdarkly/js-client-sdk-common';\n\nimport { getCrypto } from '../BrowserApi';\nimport BrowserHasher from './BrowserHasher';\nimport randomUuidV4 from './randomUuidV4';\n\nexport default class BrowserCrypto implements Crypto {\n createHash(algorithm: string): BrowserHasher {\n return new BrowserHasher(getCrypto(), algorithm);\n }\n\n randomUUID(): string {\n return randomUuidV4();\n }\n}\n","import { Encoding } from '@launchdarkly/js-client-sdk-common';\n\nfunction bytesToBase64(bytes: Uint8Array) {\n const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join('');\n return btoa(binString);\n}\n\n/**\n * Implementation Note: This btoa handles unicode characters, which the base btoa in the browser\n * does not.\n * Background: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem\n */\n\nexport default class BrowserEncoding implements Encoding {\n btoa(data: string): string {\n return bytesToBase64(new TextEncoder().encode(data));\n }\n}\n","import { Info, PlatformData, SdkData } from '@launchdarkly/js-client-sdk-common';\n\nexport default class BrowserInfo implements Info {\n constructor(private readonly _config: { wrapperName?: string; wrapperVersion?: string }) {}\n\n platformData(): PlatformData {\n return {\n name: 'JS', // Name maintained from previous 3.x implementation.\n };\n }\n\n sdkData(): SdkData {\n const data: SdkData = {\n name: '@launchdarkly/js-client-sdk',\n version: '0.10.0', // x-release-please-version\n userAgentBase: 'JSClient',\n };\n\n if (this._config.wrapperName) {\n data.wrapperName = this._config.wrapperName;\n }\n\n if (this._config.wrapperVersion) {\n data.wrapperVersion = this._config.wrapperVersion;\n }\n\n return data;\n }\n}\n","import {\n DefaultBackoff,\n EventListener,\n EventName,\n EventSourceInitDict,\n HttpErrorResponse,\n EventSource as LDEventSource,\n} from '@launchdarkly/js-client-sdk-common';\n\n/**\n * Implementation Notes:\n *\n * This event source does not support a read-timeout.\n * This event source does not support customized verbs.\n * This event source does not support headers.\n */\n\n/**\n * Browser event source implementation which extends the built-in event\n * source with additional reconnection logic.\n */\nexport default class DefaultBrowserEventSource implements LDEventSource {\n private _es?: EventSource;\n private _backoff: DefaultBackoff;\n private _errorFilter: (err: HttpErrorResponse) => boolean;\n\n // The type of the handle can be platform specific and we treat is opaquely.\n private _reconnectTimeoutHandle?: any;\n\n private _listeners: Record<string, EventListener[]> = {};\n\n constructor(\n private readonly _url: string,\n options: EventSourceInitDict,\n ) {\n this._backoff = new DefaultBackoff(\n options.initialRetryDelayMillis,\n options.retryResetIntervalMillis,\n );\n this._errorFilter = options.errorFilter;\n this._openConnection();\n }\n\n onclose: (() => void) | undefined;\n\n onerror: ((err?: HttpErrorResponse) => void) | undefined;\n\n onopen: (() => void) | undefined;\n\n onretrying: ((e: { delayMillis: number }) => void) | undefined;\n\n private _openConnection() {\n this._es = new EventSource(this._url);\n this._es.onopen = () => {\n this._backoff.success();\n this.onopen?.();\n };\n // The error could be from a polyfill, or from the browser event source, so we are loose on the\n // typing.\n this._es.onerror = (err: any) => {\n this._handleError(err);\n this.onerror?.(err);\n };\n Object.entries(this._listeners).forEach(([eventName, listeners]) => {\n listeners.forEach((listener) => {\n this._es?.addEventListener(eventName, listener);\n });\n });\n }\n\n addEventListener(type: EventName, listener: EventListener): void {\n this._listeners[type] ??= [];\n this._listeners[type].push(listener);\n this._es?.addEventListener(type, listener);\n }\n\n close(): void {\n // Ensure any pending retry attempts are not done.\n clearTimeout(this._reconnectTimeoutHandle);\n this._reconnectTimeoutHandle = undefined;\n\n // Close the event source and notify any listeners.\n this._es?.close();\n this.onclose?.();\n }\n\n private _tryConnect(delayMs: number) {\n this.onretrying?.({ delayMillis: delayMs });\n this._reconnectTimeoutHandle = setTimeout(() => {\n this._openConnection();\n }, delayMs);\n }\n\n private _handleError(err: any): void {\n this.close();\n\n // The event source may not produce a status. But the LaunchDarkly\n // polyfill can. If we can get the status, then we should stop retrying\n // on certain error codes.\n if (err.status && typeof err.status === 'number' && !this._errorFilter(err)) {\n // If we encounter an unrecoverable condition, then we do not want to\n // retry anymore.\n return;\n }\n\n this._tryConnect(this._backoff.fail());\n }\n}\n","import {\n EventSourceCapabilities,\n EventSourceInitDict,\n EventSource as LDEventSource,\n Options,\n Requests,\n Response,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport DefaultBrowserEventSource from './DefaultBrowserEventSource';\n\nexport default class BrowserRequests implements Requests {\n fetch(url: string, options?: Options): Promise<Response> {\n // @ts-ignore\n return fetch(url, options);\n }\n\n createEventSource(url: string, eventSourceInitDict: EventSourceInitDict): LDEventSource {\n return new DefaultBrowserEventSource(url, eventSourceInitDict);\n }\n\n getEventSourceCapabilities(): EventSourceCapabilities {\n return {\n customMethod: false,\n readTimeout: false,\n headers: false,\n };\n }\n}\n","import type { LDLogger, Storage } from '@launchdarkly/js-client-sdk-common';\n\nexport function isLocalStorageSupported() {\n // Checking a symbol using typeof is safe, but directly accessing a symbol\n // which is not defined would be an error.\n return typeof localStorage !== 'undefined';\n}\n\n/**\n * Implementation of Storage using localStorage for the browser.\n *\n * The Storage API is async, and localStorage is synchronous. This is fine,\n * and none of the methods need to internally await their operations.\n */\nexport default class PlatformStorage implements Storage {\n constructor(private readonly _logger?: LDLogger) {}\n async clear(key: string): Promise<void> {\n try {\n localStorage.removeItem(key);\n } catch (error) {\n this._logger?.error(`Error clearing key from localStorage: ${key}, reason: ${error}`);\n }\n }\n\n async get(key: string): Promise<string | null> {\n try {\n const value = localStorage.getItem(key);\n return value ?? null;\n } catch (error) {\n this._logger?.error(`Error getting key from localStorage: ${key}, reason: ${error}`);\n return null;\n }\n }\n\n async set(key: string, value: string): Promise<void> {\n try {\n localStorage.setItem(key, value);\n } catch (error) {\n this._logger?.error(`Error setting key in localStorage: ${key}, reason: ${error}`);\n }\n }\n}\n","import {\n Crypto,\n Encoding,\n Info,\n LDLogger,\n Platform,\n Requests,\n Storage,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { BrowserOptions } from '../options';\nimport BrowserCrypto from './BrowserCrypto';\nimport BrowserEncoding from './BrowserEncoding';\nimport BrowserInfo from './BrowserInfo';\nimport BrowserRequests from './BrowserRequests';\nimport LocalStorage, { isLocalStorageSupported } from './LocalStorage';\n\nexport default class BrowserPlatform implements Platform {\n encoding: Encoding = new BrowserEncoding();\n info: Info;\n // fileSystem?: Filesystem;\n crypto: Crypto = new BrowserCrypto();\n requests: Requests = new BrowserRequests();\n storage?: Storage;\n\n constructor(logger: LDLogger, options: BrowserOptions) {\n if (isLocalStorageSupported()) {\n this.storage = new LocalStorage(logger);\n }\n this.info = new BrowserInfo(options);\n }\n}\n","import {\n AutoEnvAttributes,\n base64UrlEncode,\n BasicLogger,\n Configuration,\n Encoding,\n FlagManager,\n Hook,\n internal,\n LDClientImpl,\n LDContext,\n LDEmitter,\n LDEmitterEventName,\n LDFlagValue,\n LDHeaders,\n LDIdentifyResult,\n LDPluginEnvironmentMetadata,\n Platform,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { getHref } from './BrowserApi';\nimport BrowserDataManager from './BrowserDataManager';\nimport { BrowserIdentifyOptions as LDIdentifyOptions } from './BrowserIdentifyOptions';\nimport { registerStateDetection } from './BrowserStateDetector';\nimport GoalManager from './goals/GoalManager';\nimport { Goal, isClick } from './goals/Goals';\nimport { LDClient } from './LDClient';\nimport { LDPlugin } from './LDPlugin';\nimport validateBrowserOptions, { BrowserOptions, filterToBaseOptionsWithDefaults } from './options';\nimport BrowserPlatform from './platform/BrowserPlatform';\n\nclass BrowserClientImpl extends LDClientImpl {\n private readonly _goalManager?: GoalManager;\n private readonly _plugins?: LDPlugin[];\n\n constructor(\n clientSideId: string,\n autoEnvAttributes: AutoEnvAttributes,\n options: BrowserOptions = {},\n overridePlatform?: Platform,\n ) {\n const { logger: customLogger, debug } = options;\n // Overrides the default logger from the common implementation.\n const logger =\n customLogger ??\n new BasicLogger({\n destination: {\n // eslint-disable-next-line no-console\n debug: console.debug,\n // eslint-disable-next-line no-console\n info: console.info,\n // eslint-disable-next-line no-console\n warn: console.warn,\n // eslint-disable-next-line no-console\n error: console.error,\n },\n level: debug ? 'debug' : 'info',\n });\n\n // TODO: Use the already-configured baseUri from the SDK config. SDK-560\n const baseUrl = options.baseUri ?? 'https://clientsdk.launchdarkly.com';\n\n const platform = overridePlatform ?? new BrowserPlatform(logger, options);\n // Only the browser-specific options are in validatedBrowserOptions.\n const validatedBrowserOptions = validateBrowserOptions(options, logger);\n // The base options are in baseOptionsWithDefaults.\n const baseOptionsWithDefaults = filterToBaseOptionsWithDefaults({ ...options, logger });\n const { eventUrlTransformer } = validatedBrowserOptions;\n\n super(\n clientSideId,\n autoEnvAttributes,\n platform,\n baseOptionsWithDefaults,\n (\n flagManager: FlagManager,\n configuration: Configuration,\n baseHeaders: LDHeaders,\n emitter: LDEmitter,\n diagnosticsManager?: internal.DiagnosticsManager,\n ) =>\n new BrowserDataManager(\n platform,\n flagManager,\n clientSideId,\n configuration,\n validatedBrowserOptions,\n () => ({\n pathGet(encoding: Encoding, _plainContextString: string): string {\n return `/sdk/evalx/${clientSideId}/contexts/${base64UrlEncode(_plainContextString, encoding)}`;\n },\n pathReport(_encoding: Encoding, _plainContextString: string): string {\n return `/sdk/evalx/${clientSideId}/context`;\n },\n pathPing(_encoding: Encoding, _plainContextString: string): string {\n // Note: if you are seeing this error, it is a coding error. This DataSourcePaths implementation is for polling endpoints. /ping is not currently\n // used in a polling situation. It is probably the case that this was called by streaming logic erroneously.\n throw new Error('Ping for polling unsupported.');\n },\n }),\n () => ({\n pathGet(encoding: Encoding, _plainContextString: string): string {\n return `/eval/${clientSideId}/${base64UrlEncode(_plainContextString, encoding)}`;\n },\n pathReport(_encoding: Encoding, _plainContextString: string): string {\n return `/eval/${clientSideId}`;\n },\n pathPing(_encoding: Encoding, _plainContextString: string): string {\n return `/ping/${clientSideId}`;\n },\n }),\n baseHeaders,\n emitter,\n diagnosticsManager,\n ),\n {\n analyticsEventPath: `/events/bulk/${clientSideId}`,\n diagnosticEventPath: `/events/diagnostic/${clientSideId}`,\n includeAuthorizationHeader: false,\n highTimeoutThreshold: 5,\n userAgentHeaderName: 'x-launchdarkly-user-agent',\n trackEventModifier: (event: internal.InputCustomEvent) =>\n new internal.InputCustomEvent(\n event.context,\n event.key,\n event.data,\n event.metricValue,\n event.samplingRatio,\n eventUrlTransformer(getHref()),\n ),\n getImplementationHooks: (environmentMetadata: LDPluginEnvironmentMetadata) =>\n internal.safeGetHooks(logger, environmentMetadata, validatedBrowserOptions.plugins),\n credentialType: 'clientSideId',\n },\n );\n\n this.setEventSendingEnabled(true, false);\n\n this._plugins = validatedBrowserOptions.plugins;\n\n if (validatedBrowserOptions.fetchGoals) {\n this._goalManager = new GoalManager(\n clientSideId,\n platform.requests,\n baseUrl,\n (err) => {\n // TODO: May need to emit. SDK-561\n logger.error(err.message);\n },\n (url: string, goal: Goal) => {\n const context = this.getInternalContext();\n if (!context) {\n return;\n }\n const transformedUrl = eventUrlTransformer(url);\n if (isClick(goal)) {\n this.sendEvent({\n kind: 'click',\n url: transformedUrl,\n samplingRatio: 1,\n key: goal.key,\n creationDate: Date.now(),\n context,\n selector: goal.selector,\n });\n } else {\n this.sendEvent({\n kind: 'pageview',\n url: transformedUrl,\n samplingRatio: 1,\n key: goal.key,\n creationDate: Date.now(),\n context,\n });\n }\n },\n );\n\n // This is intentionally not awaited. If we want to add a \"goalsready\" event, or\n // \"waitForGoalsReady\", then we would make an async immediately invoked function expression\n // which emits the event, and assign its promise to a member. The \"waitForGoalsReady\" function\n // would return that promise.\n this._goalManager.initialize();\n\n if (validatedBrowserOptions.automaticBackgroundHandling) {\n registerStateDetection(() => this.flush());\n }\n }\n }\n\n registerPlugins(client: LDClient): void {\n internal.safeRegisterPlugins(\n this.logger,\n this.environmentMetadata,\n client,\n this._plugins || [],\n );\n }\n\n override async identify(context: LDContext, identifyOptions?: LDIdentifyOptions): Promise<void> {\n return super.identify(context, identifyOptions);\n }\n\n override async identifyResult(\n context: LDContext,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<LDIdentifyResult> {\n const identifyOptionsWithUpdatedDefaults = {\n ...identifyOptions,\n };\n if (identifyOptions?.sheddable === undefined) {\n identifyOptionsWithUpdatedDefaults.sheddable = true;\n }\n const res = await super.identifyResult(context, identifyOptionsWithUpdatedDefaults);\n this._goalManager?.startTracking();\n return res;\n }\n\n setStreaming(streaming?: boolean): void {\n // With FDv2 we may want to consider if we support connection mode directly.\n // Maybe with an extension to connection mode for 'automatic'.\n const browserDataManager = this.dataManager as BrowserDataManager;\n browserDataManager.setForcedStreaming(streaming);\n }\n\n private _updateAutomaticStreamingState() {\n const browserDataManager = this.dataManager as BrowserDataManager;\n // This will need changed if support for listening to individual flag change\n // events it added.\n browserDataManager.setAutomaticStreamingState(!!this.emitter.listenerCount('change'));\n }\n\n override on(eventName: LDEmitterEventName, listener: Function): void {\n super.on(eventName, listener);\n this._updateAutomaticStreamingState();\n }\n\n override off(eventName: LDEmitterEventName, listener: Function): void {\n super.off(eventName, listener);\n this._updateAutomaticStreamingState();\n }\n}\n\nexport function makeClient(\n clientSideId: string,\n autoEnvAttributes: AutoEnvAttributes,\n options: BrowserOptions = {},\n overridePlatform?: Platform,\n): LDClient {\n const impl = new BrowserClientImpl(clientSideId, autoEnvAttributes, options, overridePlatform);\n\n // Return a PIMPL style implementation. This decouples the interface from the interface of the implementation.\n // In the future we should consider updating the common SDK code to not use inheritance and instead compose\n // the leaf-implementation.\n // The purpose for this in the short-term is to have a signature for identify that is different than the class implementation.\n // Using an object with PIMPL here also allows us to completely hide the underlying implementation, where with a class\n // it is trivial to access what should be protected (or even private) fields.\n const client: LDClient = {\n variation: (key: string, defaultValue?: LDFlagValue) => impl.variation(key, defaultValue),\n variationDetail: (key: string, defaultValue?: LDFlagValue) =>\n impl.variationDetail(key, defaultValue),\n boolVariation: (key: string, defaultValue: boolean) => impl.boolVariation(key, defaultValue),\n boolVariationDetail: (key: string, defaultValue: boolean) =>\n impl.boolVariationDetail(key, defaultValue),\n numberVariation: (key: string, defaultValue: number) => impl.numberVariation(key, defaultValue),\n numberVariationDetail: (key: string, defaultValue: number) =>\n impl.numberVariationDetail(key, defaultValue),\n stringVariation: (key: string, defaultValue: string) => impl.stringVariation(key, defaultValue),\n stringVariationDetail: (key: string, defaultValue: string) =>\n impl.stringVariationDetail(key, defaultValue),\n jsonVariation: (key: string, defaultValue: unknown) => impl.jsonVariation(key, defaultValue),\n jsonVariationDetail: (key: string, defaultValue: unknown) =>\n impl.jsonVariationDetail(key, defaultValue),\n track: (key: string, data?: any, metricValue?: number) => impl.track(key, data, metricValue),\n on: (key: LDEmitterEventName, callback: (...args: any[]) => void) => impl.on(key, callback),\n off: (key: LDEmitterEventName, callback: (...args: any[]) => void) => impl.off(key, callback),\n flush: () => impl.flush(),\n setStreaming: (streaming?: boolean) => impl.setStreaming(streaming),\n identify: (pristineContext: LDContext, identifyOptions?: LDIdentifyOptions) =>\n impl.identifyResult(pristineContext, identifyOptions),\n getContext: () => impl.getContext(),\n close: () => impl.close(),\n allFlags: () => impl.allFlags(),\n addHook: (hook: Hook) => impl.addHook(hook),\n logger: impl.logger,\n };\n\n impl.registerPlugins(client);\n\n return client;\n}\n","import { BasicLogger, BasicLoggerOptions, LDLogger } from '@launchdarkly/js-client-sdk-common';\n\nimport { BrowserIdentifyOptions as LDIdentifyOptions } from './BrowserIdentifyOptions';\n\n// The exported LDIdentifyOptions and LDOptions are the browser specific implementations.\n// These shadow the common implementations.\nexport type { LDIdentifyOptions };\n\nexport type {\n AutoEnvAttributes,\n BasicLogger,\n BasicLoggerOptions,\n EvaluationSeriesContext,\n EvaluationSeriesData,\n Hook,\n HookMetadata,\n IdentifySeriesContext,\n IdentifySeriesData,\n IdentifySeriesResult,\n IdentifySeriesStatus,\n LDContext,\n LDContextCommon,\n LDContextMeta,\n LDEvaluationDetail,\n LDEvaluationDetailTyped,\n LDEvaluationReason,\n LDFlagSet,\n LDFlagValue,\n LDTimeoutError,\n LDInspection,\n LDLogger,\n LDLogLevel,\n LDMultiKindContext,\n LDSingleKindContext,\n TrackSeriesContext,\n LDPluginBase,\n LDPluginEnvironmentMetadata,\n LDPluginSdkMetadata,\n LDPluginApplicationMetadata,\n LDPluginMetadata,\n LDIdentifyResult,\n LDIdentifySuccess,\n LDIdentifyError,\n LDIdentifyTimeout,\n LDIdentifyShed,\n} from '@launchdarkly/js-client-sdk-common';\n\n/**\n * Provides a basic {@link LDLogger} implementation.\n *\n * This logging implementation uses a basic format that includes only the log level\n * and the message text. By default this uses log level 'info' and the output is\n * written to `console.error`.\n *\n * To use the logger created by this function, put it into {@link LDOptions.logger}. If\n * you do not set {@link LDOptions.logger} to anything, the SDK uses a default logger\n * that will log \"info\" level and higher priorty messages and it will log messages to\n * console.info, console.warn, and console.error.\n *\n * @param options Configuration for the logger. If no options are specified, the\n * logger uses `{ level: 'info' }`.\n *\n * @example\n * This example shows how to use `basicLogger` in your SDK options to enable console\n * logging only at `warn` and `error` levels.\n * ```javascript\n * const ldOptions = {\n * logger: basicLogger({ level: 'warn' }),\n * };\n * ```\n *\n * @example\n * This example shows how to use `basicLogger` in your SDK options to cause all\n * log output to go to `console.log`\n * ```javascript\n * const ldOptions = {\n * logger: basicLogger({ destination: console.log }),\n * };\n * ```\n *\n * * @example\n * The configuration also allows you to control the destination for each log level.\n * ```javascript\n * const ldOptions = {\n * logger: basicLogger({\n * destination: {\n * debug: console.debug,\n * info: console.info,\n * warn: console.warn,\n * error:console.error\n * }\n * }),\n * };\n * ```\n */\nexport function basicLogger(options: BasicLoggerOptions): LDLogger {\n return new BasicLogger(options);\n}\n","/**\n * This is the API reference for the LaunchDarkly Client-Side SDK for JavaScript.\n *\n * This SDK is intended for use in browser environments.\n *\n * In typical usage, you will call {@link initialize} once at startup time to obtain an instance of\n * {@link LDClient}, which provides access to all of the SDK's functionality.\n *\n * For more information, see the [SDK Reference Guide](https://docs.launchdarkly.com/sdk/client-side/javascript).\n *\n * @packageDocumentation\n */\nimport { AutoEnvAttributes } from '@launchdarkly/js-client-sdk-common';\n\nimport { makeClient } from './BrowserClient';\nimport { LDClient } from './LDClient';\nimport { BrowserOptions as LDOptions } from './options';\n\nexport * from './common';\nexport type { LDClient, LDOptions };\nexport type { LDPlugin } from './LDPlugin';\n\n/**\n * Creates an instance of the LaunchDarkly client.\n *\n * Usage:\n * ```\n * import { initialize } from 'launchdarkly-js-client-sdk';\n * const client = initialize(clientSideId, options);\n * ```\n *\n * @param clientSideId\n * The client-side ID, also known as the environment ID.\n * @param options\n * Optional configuration settings.\n * @return\n * The new client instance.\n */\nexport function initialize(clientSideId: string, options?: LDOptions): LDClient {\n // AutoEnvAttributes are not supported yet in the browser SDK.\n return makeClient(clientSideId, AutoEnvAttributes.Disabled, options);\n}\n"],"mappings":"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","names":["toRefString","value","unescape","ref","getComponents","reference","component","isLiteral","validate","AttributeReference","refOrLiteral","literal","literalVal","_components","target","components","isValid","current","index","depth","other","FactoryOrInstance","factoryOrInstance","typeOfFactory","Type","typeName","example","_typeName","u","TypeArray","val","NumberWithMinimum","min","StringMatchingRegex","expression","Function","NullableBoolean","DATE_REGEX","DateValidator","KindValidator","TypeValidators","isSingleKind","context","isMultiKind","isLegacyUser","canonicalize","object","visited","item","key","DEFAULT_KIND","encodeKey","isContextCommon","kindOrContext","validKind","kind","validKey","processPrivateAttributes","privateAttributes","literals","privateAttribute","defined","legacyToSingleKind","user","singleKindContext","__spreadProps","__spreadValues","anonymous","Context","_Context","valid","message","_isMulti","_isUser","_wasLegacy","_contexts","_contextForError","_getValueFromContext","_contextForKind","_context","_fromMultiKindContext","kinds","kindsValid","contextsAreObjects","contexts","acc","_a","singleContext","part","created","_privateAttributeReferences","_fromSingleKindContext","kindValid","keyValid","privateAttributeReferences","_fromLegacyUser","result","kindAndContext","nestedContext","_cachedCanonicalJson","e","protectedAttributes","str","legacyTopLevelCopyAttributes","compare","a","b","cloneWithRedactions","references","stack","cloned","excluded","redactRef","ContextFilter","_allAttributesPrivate","_privateAttributes","redactAnonymousAttributes","_filterSingleKind","filteredMulti","single","_getAttributesToFilter","redactAllAttributes","k","attr","protectedAttr","name","MAX_RETRY_DELAY","JITTER_RATIO","DefaultBackoff","initialRetryDelayMillis","_retryResetIntervalMillis","_random","_retryCount","_initialRetryDelayMillis","_maxExponent","_backoff","exponent","delay","_jitter","computedDelayMillis","timeStampMs","_activeSince","DataSourceState","LDPollingError","kind","message","status","recoverable","LDStreamingError","code","DEFAULT_FALLBACK_TIME_MS","DEFAULT_RECOVERY_TIME_MS","DataSourceErrorKind","AutoEnvAttributes","LDEventType","LDDeliveryStatus","tryStringify","val","e","error","toNumber","toInt","toFloat","escapes","format","args","_a","formatString","TypeValidators","out","i","char","nextChar","value","LogPriority","LEVEL_NAMES","BasicLogger","_BasicLogger","options","_b","_c","_logLevel","_name","_formatter","_destinations","destination","_tryFormat","_tryWrite","msg","_log","level","prefix","loggerRequirements","SafeLogger","logger","fallback","validator","_logger","_fallback","createSafeLogger","basicLogger","OptionMessages","oldName","newName","name","min","expectedType","actualType","allowedTagCharacters","regexValidator","tagValidator","u","ApplicationTags","tags","application","key","valid","message","tagKeys","ClientContext","sdkKey","configuration","platform","canonicalizeUri","uri","canonicalizePath","path","ServiceEndpoints","_ServiceEndpoints","streaming","polling","events","analyticsEventPath","diagnosticEventPath","includeAuthorizationHeader","payloadFilterKey","getWithParams","parameters","parts","getStreamingUri","endpoints","canonicalizedPath","combinedParameters","getPollingUri","getEventsUri","LDUnexpectedResponseError","LDClientError","LDTimeoutError","isHttpRecoverable","status","isHttpLocallyRecoverable","clone","obj","secondsToMillis","sec","isEmptyObject","obj","deepCompact","ignoreKeys","acc","key","value","fastDeepEqual","a","b","length","i","keys","defaultHeaders","sdkKey","info","tags","includeAuthorizationHeader","userAgentHeaderName","userAgentBase","version","wrapperName","wrapperVersion","headers","httpErrorMessage","err","context","retryMessage","desc","action","shouldRetry","status","isHttpRecoverable","base64UrlEncode","s","encoding","sleep","delayMillis","resolve","DiagnosticsManager","sdkKey","_platform","_diagnosticInitConfig","_streamInits","_startTime","_dataSinceDate","_id","_a","_b","_c","sdkData","platformData","__spreadValues","timestamp","failed","durationMillis","item","droppedEvents","deduplicatedUsers","eventsInLastBatch","currentTime","evt","ErrorKinds","ErrorKinds$1","ClientMessages","badType","EventSender","clientContext","baseHeaders","basicConfiguration","platform","analyticsEventPath","diagnosticEventPath","crypto","requests","_defaultHeaders","_eventsUri","getEventsUri","_diagnosticEventsUri","_requests","_crypto","_tryPostingEvents","events","uri","payloadId","canRetry","tryRes","LDDeliveryStatus","headers","__spreadProps","error","status","resHeaders","serverDate","LDUnexpectedResponseError","httpErrorMessage","isHttpRecoverable","isHttpLocallyRecoverable","err","sleep","type","data","LDEventType","isFeature","u","isIdentify","isMigration","SummaryCounter","count","key","value","defValue","version","variation","counterKey","event","EventSummarizer","_singleContext","_contextFilter","_startDate","_endDate","_counters","_contextKinds","_context","countKey","counter","kinds","kind","features","acc","flagSummary","counterOut","_clearSummary","LDInvalidSDKKeyError","message","MultiEventSummarizer","_logger","_summarizers","summarizer","summarizersToFlush","shouldSample","ratio","truncated","isMultiEventSummarizer","EventProcessor","_config","_contextDeduplicator","_diagnosticsManager","start","summariesPerContext","_queue","_lastKnownPastTime","_droppedEvents","_deduplicatedUsers","_exceededCapacity","_eventsInLastBatch","_shutdown","_flushUsersTimer","_capacity","_eventSender","ContextFilter","ref","AttributeReference","_summarizer","_flushTimer","e","initEvent","_postDiagnosticEvent","_diagnosticsTimer","statsEvent","eventsToFlush","summary","inputEvent","migrationEvent","_enqueue","isFeatureEvent","addFullEvent","addDebugEvent","_shouldDebugEvent","isIdentifyEvent","shouldNotDeduplicate","_makeOutputEvent","debug","out","res","InputCustomEvent","context","metricValue","samplingRatio","url","InputEvalEvent","withReasons","trackEvents","prereqOf","reason","debugEventsUntilDate","excludeFromSummaries","InputIdentifyEvent","NullEventProcessor","EventFactoryBase","_withReasons","defVal","PAYLOAD_ID","fdv1PayloadAdaptor","processor","_processor","_selector","selector","flag","segment","PayloadProcessor","_objProcessors","_errorHandler","_listeners","_tempId","_tempBasis","_tempUpdates","_processServerIntent","_resetAll","payload","_processIntentNone","_processPutObject","obj","_processObj","_processDeleteObject","intent","it","_resetAfterEmission","_processPayloadTransferred","_processGoodbye","_processError","_resetAfterError","listener","index","jsonObj","PayloadStreamReader","eventStream","_attachHandler","_payloadProcessor","stream","eventName","_d","_e","DataSourceErrorKind","initMetadataFromHeaders","initHeaders","envIdKey","UNKNOWN_PLUGIN_NAME","safeGetName","logger","plugin","safeGetHooks","environmentMetadata","plugins","hooks","pluginHooks","safeRegisterPlugins","client","DataSourceState","isOk","status","LDRequestError","message","Requestor","_requests","_uri","_headers","_method","_body","res","err","makeRequestor","plainContextString","serviceEndpoints","paths","requests","encoding","baseHeaders","baseQueryParams","withReasons","useReport","secureModeHash","body","method","headers","__spreadValues","path","parameters","uri","getPollingUri","duplicateExecutionError","makePending","task","_logger","sheddable","resolveTask","promise","resolve","result","beforeResult","_a","error","beforePromise","executedOrShed","createAsyncTaskQueue","logger","activeTask","queue","checkPending","nextTask","pending","_b","validators","TypeValidators","DEFAULT_POLLING_INTERVAL","DEFAULT_POLLING","DEFAULT_STREAM","ensureSafeLogger","SafeLogger","createSafeLogger","ConfigurationImpl","pristineOptions","internalOptions","ServiceEndpoints","_validateTypesAndNames","e","ApplicationTags","_c","event","errors","k","v","validator","validatorType","OptionMessages","NumberWithMinimum","min","digest","hasher","getOrGenerateKey","storageKey","crypto","storage","generatedKey","hashAndBase64Encode","input","noop","concatNamespacesAndValues","parts","part","namespaceForEnvironment","sdkKey","namespaceForAnonymousGeneratedContextKey","kind","namespaceForGeneratedContextKey","namespaceForContextIndex","environmentNamespace","namespaceForContextData","context","isLegacyUser","isSingleKind","isMultiKind","index","defaultAutoEnvSchemaVersion","toMulti","c","contextCommon","__objRest","addApplicationInfo","info","applicationInfo","ld_application","app","deepCompact","id","version","name","versionName","__spreadProps","addDeviceInfo","platform","ld_device","os","device","family","_d","ldDeviceNamespace","addAutoEnv","config","multi","ensureKeyCommon","anonymous","key","ensureKeySingle","ensureKeyMulti","multiContext","singleContexts","ensureKeyLegacy","ensureKey","cloned","clone","createDiagnosticsInitConfig","secondsToMillis","createDiagnosticsManager","clientSideID","createErrorEvaluationDetail","errorKind","def","createSuccessEvaluationDetail","value","variationIndex","reason","createEventProcessor","diagnosticsManager","ClientContext","EventFactory","flagKey","defaultVal","flag","trackEvents","debugEventsUntilDate","trackReason","flagVersion","variation","ContextIndex","_ContextIndex","json","contextIndex","timestamp","entry","it","maxContexts","clampedMax","a","b","FlagPersistence","_platform","_environmentNamespace","_maxCachedContexts","_flagStore","_flagUpdater","_timeStamper","_indexKeyPromise","newFlags","_storeCache","item","flagsJson","flags","descriptors","acc","_loadIndex","_contextIndex","pruned","allFlags","descriptor","jsonAll","DefaultFlagStore","_flags","update","calculateChangedKeys","existingObject","newObject","changedKeys","f","subObject","fastDeepEqual","FlagUpdater","flagStore","_changeCallbacks","_activeContextKey","oldFlags","changed","callback","currentValue","DefaultFlagManager","maxCachedContexts","timeStamper","_flagPersistencePromise","_initPersistence","UNKNOWN_HOOK_NAME","BEFORE_EVALUATION_STAGE_NAME","AFTER_EVALUATION_STAGE_NAME","AFTER_TRACK_STAGE_NAME","tryExecuteStage","hookName","stage","getHookName","hook","executeBeforeEvaluation","hooks","hookContext","executeAfterEvaluation","updatedData","hookIndex","data","executeBeforeIdentify","executeAfterIdentify","executeAfterTrack","HookRunner","initialHooks","_hooks","defaultValue","hookData","timeout","getInspectorHook","inspectorManager","detail","_result","invalidInspector","type","inspectorMethodError","createSafeInspector","inspector","errorLogged","wrapper","args","FLAG_USED_TYPE","FLAG_DETAILS_CHANGED_TYPE","FLAG_DETAIL_CHANGED_TYPE","IDENTITY_CHANGED_TYPE","VALID__TYPES","validateInspector","valid","InspectorManager","inspectors","_safeInspectors","validInspectors","LDEmitter","_listeners","listener","existingListeners","updated","fn","_invokeListener","listeners","createPluginEnvironmentMetadata","sdkData","applicationMetadata","sdkMetadata","environmentMetadata","ClientMessages","ErrorKinds","DEFAULT_IDENTIFY_TIMEOUT_SECONDS","LDClientImpl","autoEnvAttributes","options","dataManagerFactory","_highTimeoutThreshold","_eventFactoryDefault","_eventFactoryWithReasons","_eventSendingEnabled","_identifyQueue","_config","_baseHeaders","defaultHeaders","_flagManager","_diagnosticsManager","_eventProcessor","flagKeys","_handleInspectionChanged","ldContext","Context","_hookRunner","_inspectorManager","_uncheckedContext","_checkedContext","_createIdentifyPromise","rej","reject","pristineContext","identifyOptions","timeoutError","LDTimeoutError","identifyTimeout","noTimeout","callSitePromise","AutoEnvAttributes","checkedContext","afterIdentify","identifyPromise","identifyResolve","identifyReject","timeoutPromise","eventName","metricValue","_variationInternal","eventFactory","typeChecker","evalContext","foundItem","defVal","LDClientError","prerequisites","matched","successDetail","prereqKey","_typedEval","enabled","flush","details","DataSourceEventHandler","_statusManager","patchFlag","deleteFlag","DataSourceStatusManager","_emitter","_state","_stateSinceMillis","_errorInfo","_updateState","requestedState","isError","newState","changedState","state","statusCode","recoverable","errorInfo","reportClosed","PollingProcessor","_requestor","_pollIntervalSeconds","_dataHandler","_errorHandler","_stopped","_poll","reportJsonError","LDPollingError","DataSourceErrorKind","startTime","requestError","isHttpRecoverable","httpErrorMessage","_e","_f","elapsed","sleepFor","_g","_timeoutHandle","errorHandler","LDStreamingError","reportEventClosed","reportPingClosed","StreamingProcessor","_plainContextString","_dataSourceConfig","_pollingRequestor","_streamUri","getStreamingUri","_logConnectionStarted","_connectionAttemptStartTime","_logConnectionResult","success","_retryAndHandleError","shouldRetry","methodAndBodyOverrides","eventSource","_eventSource","deserializeData","processJson","dataJson","payload","BaseDataManager","flagManager","credential","getPollingPaths","getStreamingPaths","emitter","_dataSourceEventHandler","connectionParams","_connectionParams","requestor","processor","_decorateProcessorWithStatusReporting","pollingRequestor","statusManager","isDocument","isWindow","addDocumentEventListener","type","listener","options","addWindowEventListener","getHref","getLocationSearch","getLocationHash","getCrypto","getVisibility","querySelectorAll","selector","readFlagsFromBootstrap","logger","data","keys","metadataKey","validKey","metadata","ret","key","flag","__spreadValues","logTag","BrowserDataManager","BaseDataManager","platform","flagManager","credential","config","_browserConfig","getPollingPaths","getStreamingPaths","baseHeaders","emitter","diagnosticsManager","_forcedStreaming","_automaticStreamingState","_debugLog","message","args","identifyResolve","identifyReject","context","identifyOptions","browserIdentifyOptions","_secureModeHash","_finishIdentifyFromBootstrap","_finishIdentifyFromPoll","_updateStreamingState","_requestPayload","plainContextString","Context","pollingRequestor","makeRequestor","maxRetries","lastError","attempt","e","shouldRetry","httpErrorMessage","sleep","_a","_b","DataSourceState","payload","putListener","DataSourceErrorKind","bootstrap","readFlagsFromBootstrap","streaming","shouldBeStreaming","_startDataSource","_stopDataSource","_setupConnection","rawContext","registerStateDetection","requestFlush","removeDocListener","addDocumentEventListener","getVisibility","removeWindowListener","addWindowEventListener","escapeStringRegexp","string","matchesUrl","matcher","href","search","hash","canonicalUrl","escapeStringRegexp","findGoalsForClick","event","clickGoals","matches","goal","target","selector","elements","querySelectorAll","elementIndex","GoalTracker","goals","onEvent","goalsMatchingUrl","_a","getHref","getLocationSearch","getLocationHash","pageviewGoals","clickHandler","clickGoal","_cleanup","addDocumentEventListener","LOCATION_WATCHER_INTERVAL_MS","DefaultLocationWatcher","callback","_previousLocation","getHref","checkUrl","currentLocation","_watcherHandle","removeListener","addWindowEventListener","_cleanupListeners","_a","GoalManager","credential","_requests","baseUrl","_reportError","_reportGoal","locationWatcherFactory","cb","DefaultLocationWatcher","_goals","_isTracking","_url","_watcher","_createTracker","_fetchGoals","_a","_tracker","GoalTracker","goal","getHref","res","err","LDUnexpectedResponseError","_b","isClick","goal","DEFAULT_FLUSH_INTERVAL_SECONDS","optDefaults","url","validators","TypeValidators","withBrowserDefaults","opts","_a","output","__spreadValues","filterToBaseOptionsWithDefaults","baseOptions","key","validateBrowserOptions","logger","entry","validator","value","OptionMessages","BrowserHasher","_webcrypto","algorithm","_data","_algorithm","encoding","combinedData","encoded","digestedBuffer","val","data","timeLow","timeMid","timeHiAndVersion","clockSeqHiAndReserved","clockSeqLow","nodes","getRandom128bit","typedArray","values","index","hex","bytes","range","strVal","formatDataAsUuidV4","fallbackUuidV4","randomUuidV4","BrowserCrypto","algorithm","BrowserHasher","getCrypto","randomUuidV4","bytesToBase64","bytes","binString","byte","BrowserEncoding","data","BrowserInfo","_config","data","DefaultBrowserEventSource","_url","options","_listeners","_backoff","DefaultBackoff","_errorFilter","_openConnection","_es","_a","err","_handleError","eventName","listeners","listener","type","_b","_c","_reconnectTimeoutHandle","_tryConnect","delayMs","BrowserRequests","url","options","eventSourceInitDict","DefaultBrowserEventSource","isLocalStorageSupported","PlatformStorage","_logger","key","_a","error","value","BrowserPlatform","logger","options","BrowserEncoding","BrowserCrypto","BrowserRequests","isLocalStorageSupported","PlatformStorage","BrowserInfo","BrowserClientImpl","LDClientImpl","clientSideId","autoEnvAttributes","options","overridePlatform","_a","customLogger","debug","logger","BasicLogger","baseUrl","platform","BrowserPlatform","validatedBrowserOptions","validateBrowserOptions","baseOptionsWithDefaults","filterToBaseOptionsWithDefaults","__spreadProps","__spreadValues","eventUrlTransformer","flagManager","configuration","baseHeaders","emitter","diagnosticsManager","BrowserDataManager","encoding","_plainContextString","base64UrlEncode","_encoding","event","index","getHref","environmentMetadata","_plugins","_goalManager","GoalManager","err","url","goal","context","transformedUrl","isClick","registerStateDetection","client","identifyOptions","identifyOptionsWithUpdatedDefaults","res","streaming","_updateAutomaticStreamingState","eventName","listener","makeClient","impl","key","defaultValue","data","metricValue","callback","pristineContext","hook","basicLogger","options","BasicLogger","initialize","clientSideId","options","makeClient","AutoEnvAttributes"]}
|
|
1
|
+
{"version":3,"sources":["../../../shared/common/src/AttributeReference.ts","../../../shared/common/src/validators.ts","../../../shared/common/src/internal/context/index.ts","../../../shared/common/src/internal/json/canonicalize.ts","../../../shared/common/src/Context.ts","../../../shared/common/src/ContextFilter.ts","../../../shared/common/src/datasource/Backoff.ts","../../../shared/common/src/api/subsystem/DataSystem/CallbackHandler.ts","../../../shared/common/src/api/subsystem/DataSystem/DataSource.ts","../../../shared/common/src/datasource/dataSourceList.ts","../../../shared/common/src/datasource/errors.ts","../../../shared/common/src/datasource/CompositeDataSource.ts","../../../shared/common/src/datasource/DataSourceErrorKinds.ts","../../../shared/common/src/api/platform/AutoEnv.ts","../../../shared/common/src/api/subsystem/LDEventSender.ts","../../../shared/common/src/logging/format.ts","../../../shared/common/src/logging/BasicLogger.ts","../../../shared/common/src/logging/SafeLogger.ts","../../../shared/common/src/logging/createSafeLogger.ts","../../../shared/common/src/options/OptionMessages.ts","../../../shared/common/src/options/ApplicationTags.ts","../../../shared/common/src/options/ClientContext.ts","../../../shared/common/src/options/ServiceEndpoints.ts","../../../shared/common/src/errors.ts","../../../shared/common/src/utils/cancelableTimedPromise.ts","../../../shared/common/src/utils/clone.ts","../../../shared/common/src/utils/date.ts","../../../shared/common/src/utils/debounce.ts","../../../shared/common/src/utils/isEmptyObject.ts","../../../shared/common/src/utils/deepCompact.ts","../../../shared/common/src/utils/fast-deep-equal/index.ts","../../../shared/common/src/utils/http.ts","../../../shared/common/src/utils/noop.ts","../../../shared/common/src/utils/sleep.ts","../../../shared/common/src/utils/timedPromise.ts","../../../shared/common/src/internal/diagnostics/DiagnosticsManager.ts","../../../shared/common/src/internal/evaluation/ErrorKinds.ts","../../../shared/common/src/internal/events/ClientMessages.ts","../../../shared/common/src/internal/events/EventSender.ts","../../../shared/common/src/internal/events/guards.ts","../../../shared/common/src/internal/events/SummaryCounter.ts","../../../shared/common/src/internal/events/EventSummarizer.ts","../../../shared/common/src/internal/events/LDInvalidSDKKeyError.ts","../../../shared/common/src/internal/events/MultiEventSummarizer.ts","../../../shared/common/src/internal/events/sampling.ts","../../../shared/common/src/internal/events/EventProcessor.ts","../../../shared/common/src/internal/events/InputCustomEvent.ts","../../../shared/common/src/internal/events/InputEvalEvent.ts","../../../shared/common/src/internal/events/InputIdentifyEvent.ts","../../../shared/common/src/internal/events/NullEventProcessor.ts","../../../shared/common/src/internal/evaluation/EventFactoryBase.ts","../../../shared/common/src/internal/fdv2/FDv1PayloadAdaptor.ts","../../../shared/common/src/internal/fdv2/payloadProcessor.ts","../../../shared/common/src/internal/fdv2/payloadStreamReader.ts","../../../shared/common/src/internal/metadata/InitMetadata.ts","../../../shared/common/src/internal/plugins/safeGetName.ts","../../../shared/common/src/internal/plugins/safeGetHooks.ts","../../../shared/common/src/internal/plugins/safeRegisterPlugins.ts","../../../shared/sdk-client/src/datasource/DataSourceStatus.ts","../../../shared/sdk-client/src/datasource/Requestor.ts","../../../shared/sdk-client/src/async/AsyncTaskQueue.ts","../../../shared/sdk-client/src/configuration/validators.ts","../../../shared/sdk-client/src/configuration/Configuration.ts","../../../shared/sdk-client/src/crypto/digest.ts","../../../shared/sdk-client/src/storage/getOrGenerateKey.ts","../../../shared/sdk-client/src/storage/namespaceUtils.ts","../../../shared/sdk-client/src/context/addAutoEnv.ts","../../../shared/sdk-client/src/context/createActiveContextTracker.ts","../../../shared/sdk-client/src/context/ensureKey.ts","../../../shared/sdk-client/src/diagnostics/createDiagnosticsInitConfig.ts","../../../shared/sdk-client/src/diagnostics/createDiagnosticsManager.ts","../../../shared/sdk-client/src/evaluation/evaluationDetail.ts","../../../shared/sdk-client/src/events/createEventProcessor.ts","../../../shared/sdk-client/src/events/EventFactory.ts","../../../shared/sdk-client/src/flag-manager/ContextIndex.ts","../../../shared/sdk-client/src/flag-manager/FlagPersistence.ts","../../../shared/sdk-client/src/flag-manager/FlagStore.ts","../../../shared/sdk-client/src/flag-manager/calculateChangedKeys.ts","../../../shared/sdk-client/src/flag-manager/FlagUpdater.ts","../../../shared/sdk-client/src/flag-manager/FlagManager.ts","../../../shared/sdk-client/src/HookRunner.ts","../../../shared/sdk-client/src/inspection/getInspectorHook.ts","../../../shared/sdk-client/src/inspection/messages.ts","../../../shared/sdk-client/src/inspection/createSafeInspector.ts","../../../shared/sdk-client/src/inspection/InspectorManager.ts","../../../shared/sdk-client/src/LDEmitter.ts","../../../shared/sdk-client/src/plugins/createPluginEnvironmentMetadata.ts","../../../shared/sdk-client/src/LDClientImpl.ts","../../../shared/sdk-client/src/plugins/safeRegisterDebugOverridePlugins.ts","../../../shared/sdk-client/src/datasource/DataSourceEventHandler.ts","../../../shared/sdk-client/src/datasource/DataSourceStatusManager.ts","../../../shared/sdk-client/src/polling/PollingProcessor.ts","../../../shared/sdk-client/src/streaming/StreamingProcessor.ts","../../../shared/sdk-client/src/DataManager.ts","../src/bootstrap.ts","../src/BrowserApi.ts","../src/BrowserDataManager.ts","../src/BrowserStateDetector.ts","../src/vendor/escapeStringRegexp.ts","../src/goals/GoalTracker.ts","../src/goals/LocationWatcher.ts","../src/goals/GoalManager.ts","../src/goals/Goals.ts","../src/options.ts","../src/platform/BrowserHasher.ts","../src/platform/randomUuidV4.ts","../src/platform/BrowserCrypto.ts","../src/platform/BrowserEncoding.ts","../src/platform/BrowserInfo.ts","../src/platform/DefaultBrowserEventSource.ts","../src/platform/BrowserRequests.ts","../src/platform/LocalStorage.ts","../src/platform/BrowserPlatform.ts","../src/BrowserClient.ts","../src/common.ts","../src/index.ts"],"sourcesContent":["import { LDContextCommon } from './api/context/LDContextCommon';\n\n/**\n * Converts a literal to a ref string.\n * @param value\n * @returns An escaped literal which can be used as a ref.\n */\nfunction toRefString(value: string): string {\n return `/${value.replace(/~/g, '~0').replace(/\\//g, '~1')}`;\n}\n\n/**\n * Produce a literal from a ref component.\n * @param ref\n * @returns A literal version of the ref.\n */\nfunction unescape(ref: string): string {\n return ref.indexOf('~') ? ref.replace(/~1/g, '/').replace(/~0/g, '~') : ref;\n}\n\nfunction getComponents(reference: string): string[] {\n const referenceWithoutPrefix = reference.startsWith('/') ? reference.substring(1) : reference;\n return referenceWithoutPrefix.split('/').map((component) => unescape(component));\n}\n\nfunction isLiteral(reference: string): boolean {\n return !reference.startsWith('/');\n}\n\nfunction validate(reference: string): boolean {\n return !reference.match(/\\/\\/|(^\\/.*~[^0|^1])|~$/);\n}\n\nexport default class AttributeReference {\n public readonly isValid;\n\n /**\n * When redacting attributes this name can be directly added to the list of\n * redactions.\n */\n public readonly redactionName;\n\n /**\n * For use as invalid references when deserializing Flag/Segment data.\n */\n public static readonly InvalidReference = new AttributeReference('');\n\n private readonly _components: string[];\n\n /**\n * Take an attribute reference string, or literal string, and produce\n * an attribute reference.\n *\n * Legacy user objects would have been created with names not\n * references. So, in that case, we need to use them as a component\n * without escaping them.\n *\n * e.g. A user could contain a custom attribute of `/a` which would\n * become the literal `a` if treated as a reference. Which would cause\n * it to no longer be redacted.\n * @param refOrLiteral The attribute reference string or literal string.\n * @param literal it true the value should be treated as a literal.\n */\n public constructor(refOrLiteral: string, literal: boolean = false) {\n if (!literal) {\n this.redactionName = refOrLiteral;\n if (refOrLiteral === '' || refOrLiteral === '/' || !validate(refOrLiteral)) {\n this.isValid = false;\n this._components = [];\n return;\n }\n\n if (isLiteral(refOrLiteral)) {\n this._components = [refOrLiteral];\n } else if (refOrLiteral.indexOf('/', 1) < 0) {\n this._components = [unescape(refOrLiteral.slice(1))];\n } else {\n this._components = getComponents(refOrLiteral);\n }\n // The items inside of '_meta' are not intended to be addressable.\n // Excluding it as a valid reference means that we can make it non-addressable\n // without having to copy all the attributes out of the context object\n // provided by the user.\n if (this._components[0] === '_meta') {\n this.isValid = false;\n } else {\n this.isValid = true;\n }\n } else {\n const literalVal = refOrLiteral;\n this._components = [literalVal];\n this.isValid = literalVal !== '';\n // Literals which start with '/' need escaped to prevent ambiguity.\n this.redactionName = literalVal.startsWith('/') ? toRefString(literalVal) : literalVal;\n }\n }\n\n public get(target: LDContextCommon) {\n const { _components: components, isValid } = this;\n if (!isValid) {\n return undefined;\n }\n\n let current = target;\n\n // This doesn't use a range based for loops, because those use generators.\n // See `no-restricted-syntax`.\n // It also doesn't use a collection method because this logic is more\n // straightforward with a loop.\n for (let index = 0; index < components.length; index += 1) {\n const component = components[index];\n if (\n current !== null &&\n current !== undefined &&\n // See https://eslint.org/docs/rules/no-prototype-builtins\n Object.prototype.hasOwnProperty.call(current, component) &&\n typeof current === 'object' &&\n // We do not want to allow indexing into an array.\n !Array.isArray(current)\n ) {\n current = current[component];\n } else {\n return undefined;\n }\n }\n return current;\n }\n\n public getComponent(depth: number) {\n return this._components[depth];\n }\n\n public get depth() {\n return this._components.length;\n }\n\n public get isKind(): boolean {\n return this._components.length === 1 && this._components[0] === 'kind';\n }\n\n public compare(other: AttributeReference) {\n return (\n this.depth === other.depth &&\n this._components.every((value, index) => value === other.getComponent(index))\n );\n }\n\n public get components() {\n return [...this._components];\n }\n}\n","/* eslint-disable class-methods-use-this */\n/* eslint-disable max-classes-per-file */\n\n// The classes here are static, but needs to be instantiated to\n// support the generic functionality. Which is why we do not care about using\n// `this`\n\n// These validators are also of trivial complexity, so we are allowing more than\n// one per file.\n\n/**\n * Interface for type validation.\n */\nexport interface TypeValidator {\n is(u: unknown): boolean;\n getType(): string;\n}\n\n/**\n * Validate a factory or instance.\n */\nexport class FactoryOrInstance implements TypeValidator {\n is(factoryOrInstance: unknown) {\n if (Array.isArray(factoryOrInstance)) {\n return false;\n }\n const anyFactory = factoryOrInstance as any;\n const typeOfFactory = typeof anyFactory;\n return typeOfFactory === 'function' || typeOfFactory === 'object';\n }\n\n getType(): string {\n return 'factory method or object';\n }\n}\n\n/**\n * Validate a basic type.\n */\nexport class Type<T> implements TypeValidator {\n private _typeName: string;\n\n protected typeOf: string;\n\n constructor(typeName: string, example: T) {\n this._typeName = typeName;\n this.typeOf = typeof example;\n }\n\n is(u: unknown): u is T {\n if (Array.isArray(u)) {\n return false;\n }\n return typeof u === this.typeOf;\n }\n\n getType(): string {\n return this._typeName;\n }\n}\n\n/**\n * Validate an array of the specified type.\n *\n * This does not validate instances of types. All class instances\n * of classes will simply objects.\n */\nexport class TypeArray<T> implements TypeValidator {\n private _typeName: string;\n\n protected typeOf: string;\n\n constructor(typeName: string, example: T) {\n this._typeName = typeName;\n this.typeOf = typeof example;\n }\n\n is(u: unknown): u is T {\n if (Array.isArray(u)) {\n if (u.length > 0) {\n return u.every((val) => typeof val === this.typeOf);\n }\n return true;\n }\n return false;\n }\n\n getType(): string {\n return this._typeName;\n }\n}\n\n/**\n * Validate a value is a number and is greater or eval than a minimum.\n */\nexport class NumberWithMinimum extends Type<number> {\n readonly min: number;\n\n constructor(min: number) {\n super(`number with minimum value of ${min}`, 0);\n this.min = min;\n }\n\n override is(u: unknown): u is number {\n return typeof u === this.typeOf && (u as number) >= this.min;\n }\n}\n\n/**\n * Validate a value is a string and it matches the given expression.\n */\nexport class StringMatchingRegex extends Type<string> {\n readonly expression: RegExp;\n\n constructor(expression: RegExp) {\n super(`string matching ${expression}`, '');\n this.expression = expression;\n }\n\n override is(u: unknown): u is string {\n return typeof u === 'string' && !!(u as string).match(this.expression);\n }\n}\n\n/**\n * Validate a value is a function.\n */\nexport class Function implements TypeValidator {\n is(u: unknown): u is (...args: any[]) => void {\n // We cannot inspect the parameters and there isn't really\n // a generic function type we can instantiate.\n // So the type guard is here just to make TS comfortable\n // calling something after using this guard.\n return typeof u === 'function';\n }\n\n getType(): string {\n return 'function';\n }\n}\n\nexport class NullableBoolean implements TypeValidator {\n is(u: unknown): boolean {\n return typeof u === 'boolean' || typeof u === 'undefined' || u === null;\n }\n\n getType(): string {\n return 'boolean | undefined | null';\n }\n}\n\n// Our reference SDK, Go, parses date/time strings with the time.RFC3339Nano format.\n// This regex should match strings that are valid in that format, and no others.\n// Acceptable:\n// 2019-10-31T23:59:59Z, 2019-10-31T23:59:59.100Z,\n// 2019-10-31T23:59:59-07, 2019-10-31T23:59:59-07:00, etc.\n// Unacceptable: no \"T\", no time zone designation\nconst DATE_REGEX = /^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d(\\.\\d\\d*)?(Z|[-+]\\d\\d(:\\d\\d)?)/;\n\n/**\n * Validate a value is a date. Values which are numbers are treated as dates and any string\n * which if compliant with `time.RFC3339Nano` is a date.\n */\nexport class DateValidator implements TypeValidator {\n is(u: unknown): boolean {\n return typeof u === 'number' || (typeof u === 'string' && DATE_REGEX.test(u));\n }\n\n getType(): string {\n return 'date';\n }\n}\n\n/**\n * Validates that a string is a valid kind.\n */\nexport class KindValidator extends StringMatchingRegex {\n constructor() {\n super(/^(\\w|\\.|-)+$/);\n }\n\n override is(u: unknown): u is string {\n return super.is(u) && u !== 'kind';\n }\n}\n\n/**\n * A set of standard type validators.\n */\nexport class TypeValidators {\n static readonly String = new Type<string>('string', '');\n\n static readonly Number = new Type<number>('number', 0);\n\n static readonly ObjectOrFactory = new FactoryOrInstance();\n\n static readonly Object = new Type<object>('object', {});\n\n static readonly StringArray = new TypeArray<string>('string[]', '');\n\n static readonly Boolean = new Type<boolean>('boolean', true);\n\n static readonly Function = new Function();\n\n static createTypeArray<T>(typeName: string, example: T) {\n return new TypeArray<T>(typeName, example);\n }\n\n static numberWithMin(min: number): NumberWithMinimum {\n return new NumberWithMinimum(min);\n }\n\n static stringMatchingRegex(expression: RegExp): StringMatchingRegex {\n return new StringMatchingRegex(expression);\n }\n\n static readonly Date = new DateValidator();\n\n static readonly Kind = new KindValidator();\n static readonly NullableBoolean = new NullableBoolean();\n}\n","/**\n * Internal use only. These functions should only be used as part of the initial validation of\n * the LDContext object. Thereafter, the Context object should be used.\n */\nimport type { LDContext, LDMultiKindContext, LDSingleKindContext, LDUser } from '../../api';\nimport { TypeValidators } from '../../validators';\n\n/**\n * Check if a context is a single kind context.\n * @param context\n * @returns true if the context is a single kind context.\n */\nexport function isSingleKind(context: LDContext): context is LDSingleKindContext {\n if ('kind' in context) {\n return TypeValidators.String.is(context.kind) && context.kind !== 'multi';\n }\n return false;\n}\n\n/**\n * Check if a context is a multi-kind context.\n * @param context\n * @returns true if it is a multi-kind context.\n */\nexport function isMultiKind(context: LDContext): context is LDMultiKindContext {\n if ('kind' in context) {\n return TypeValidators.String.is(context.kind) && context.kind === 'multi';\n }\n return false;\n}\n\n/**\n * Check if a context is a legacy user context.\n * @param context\n * @returns true if it is a legacy user context.\n */\nexport function isLegacyUser(context: LDContext): context is LDUser {\n return !('kind' in context) || context.kind === null || context.kind === undefined;\n}\n","/**\n * Given some object to serialize product a canonicalized JSON string.\n * https://www.rfc-editor.org/rfc/rfc8785.html\n *\n * We do not support custom toJSON methods on objects. Objects should be limited to basic types.\n *\n * @param object The object to serialize.\n */\nexport function canonicalize(object: any, visited: any[] = []): string {\n // For JavaScript the default JSON serialization will produce canonicalized output for basic types.\n if (object === null || typeof object !== 'object') {\n return JSON.stringify(object);\n }\n\n if (visited.includes(object)) {\n throw new Error('Cycle detected');\n }\n\n if (Array.isArray(object)) {\n const values = object\n .map((item) => canonicalize(item, [...visited, object]))\n .map((item) => (item === undefined ? 'null' : item));\n return `[${values.join(',')}]`;\n }\n\n const values = Object.keys(object)\n .sort()\n .map((key) => {\n const value = canonicalize(object[key], [...visited, object]);\n if (value !== undefined) {\n return `${JSON.stringify(key)}:${value}`;\n }\n return undefined;\n })\n .filter((item) => item !== undefined);\n return `{${values.join(',')}}`;\n}\n","/* eslint-disable no-underscore-dangle */\n// eslint-disable-next-line max-classes-per-file\nimport type {\n LDContext,\n LDContextCommon,\n LDMultiKindContext,\n LDSingleKindContext,\n LDUser,\n} from './api';\nimport AttributeReference from './AttributeReference';\nimport { isLegacyUser, isMultiKind, isSingleKind } from './internal/context';\nimport { canonicalize } from './internal/json/canonicalize';\nimport { TypeValidators } from './validators';\n\n// The general strategy for the context is to transform the passed in context\n// as little as possible. We do convert the legacy users to a single kind\n// context, but we do not translate all passed contexts into a rigid structure.\n// The context will have to be copied for events, but we want to avoid any\n// copying that we can.\n// So we validate that the information we are given is correct, and then we\n// just proxy calls with a nicely typed interface.\n// This is to reduce work on the hot-path. Later, for event processing, deeper\n// cloning of the context will be done.\n\n// When no kind is specified, then this kind will be used.\nconst DEFAULT_KIND = 'user';\n\n// The API allows for calling with an `LDContext` which is\n// `LDUser | LDSingleKindContext | LDMultiKindContext`. When ingesting a context\n// first the type must be determined to allow us to put it into a consistent type.\n\n/**\n * The partial URL encoding is needed because : is a valid character in context keys.\n *\n * Partial encoding is the replacement of all colon (:) characters with the URL\n * encoded equivalent (%3A) and all percent (%) characters with the URL encoded\n * equivalent (%25).\n * @param key The key to encode.\n * @returns Partially URL encoded key.\n */\nfunction encodeKey(key: string): string {\n if (key.includes('%') || key.includes(':')) {\n return key.replace(/%/g, '%25').replace(/:/g, '%3A');\n }\n return key;\n}\n\n/**\n * Check if the given value is a LDContextCommon.\n * @param kindOrContext\n * @returns true if it is an LDContextCommon\n *\n * Due to a limitation in the expressiveness of these highly polymorphic types any field\n * in a multi-kind context can either be a context or 'kind'. So we need to re-assure\n * the compiler that it isn't the word multi.\n *\n * Because we do not allow top level values in a multi-kind context we can validate\n * that as well.\n */\nfunction isContextCommon(\n kindOrContext: 'multi' | LDContextCommon,\n): kindOrContext is LDContextCommon {\n return kindOrContext && TypeValidators.Object.is(kindOrContext);\n}\n\n/**\n * Validate a context kind.\n * @param kind\n * @returns true if the kind is valid.\n */\nfunction validKind(kind: string) {\n return TypeValidators.Kind.is(kind);\n}\n\n/**\n * Validate a context key.\n * @param key\n * @returns true if the key is valid.\n */\nfunction validKey(key: string) {\n return TypeValidators.String.is(key) && key !== '';\n}\n\nfunction processPrivateAttributes(\n privateAttributes?: string[],\n literals: boolean = false,\n): AttributeReference[] {\n if (privateAttributes) {\n return privateAttributes.map(\n (privateAttribute) => new AttributeReference(privateAttribute, literals),\n );\n }\n return [];\n}\n\nfunction defined(value: any) {\n return value !== null && value !== undefined;\n}\n\n/**\n * Convert a legacy user to a single kind context.\n * @param user\n * @returns A single kind context.\n */\nfunction legacyToSingleKind(user: LDUser): LDSingleKindContext {\n const singleKindContext: LDSingleKindContext = {\n // Key was coerced to a string for eval and events, so we can do that up-front.\n ...(user.custom || []),\n kind: 'user',\n key: String(user.key),\n };\n\n // For legacy users we never established a difference between null\n // and undefined for inputs. Because anonymous can be used in evaluations\n // we would want it to not possibly match true/false unless defined.\n // Which is different than coercing a null/undefined anonymous as `false`.\n if (defined(user.anonymous)) {\n const anonymous = !!user.anonymous;\n delete singleKindContext.anonymous;\n singleKindContext.anonymous = anonymous;\n }\n\n if (user.name !== null && user.name !== undefined) {\n singleKindContext.name = user.name;\n }\n if (user.ip !== null && user.ip !== undefined) {\n singleKindContext.ip = user.ip;\n }\n if (user.firstName !== null && user.firstName !== undefined) {\n singleKindContext.firstName = user.firstName;\n }\n if (user.lastName !== null && user.lastName !== undefined) {\n singleKindContext.lastName = user.lastName;\n }\n if (user.email !== null && user.email !== undefined) {\n singleKindContext.email = user.email;\n }\n if (user.avatar !== null && user.avatar !== undefined) {\n singleKindContext.avatar = user.avatar;\n }\n if (user.country !== null && user.country !== undefined) {\n singleKindContext.country = user.country;\n }\n if (user.privateAttributeNames !== null && user.privateAttributeNames !== undefined) {\n singleKindContext._meta = {\n privateAttributes: user.privateAttributeNames,\n };\n }\n\n // We are not pulling private attributes over because we will serialize\n // those from attribute references for events.\n\n return singleKindContext;\n}\n\n/**\n * Container for a context/contexts. Because contexts come from external code\n * they must be thoroughly validated and then formed to comply with\n * the type system.\n */\nexport default class Context {\n private _context?: LDContextCommon;\n\n private _isMulti: boolean = false;\n\n private _isUser: boolean = false;\n\n private _wasLegacy: boolean = false;\n\n private _contexts: Record<string, LDContextCommon> = {};\n\n private _privateAttributeReferences?: Record<string, AttributeReference[]>;\n\n private _cachedCanonicalJson?: string;\n\n public readonly kind: string;\n\n /**\n * Is this a valid context. If a valid context cannot be created, then this flag will be true.\n * The validity of a context should be tested before it is used.\n */\n public readonly valid: boolean;\n\n public readonly message?: string;\n\n static readonly UserKind: string = DEFAULT_KIND;\n\n /**\n * Contexts should be created using the static factory method {@link Context.fromLDContext}.\n * @param kind The kind of the context.\n *\n * The factory methods are static functions within the class because they access private\n * implementation details, so they cannot be free functions.\n */\n private constructor(valid: boolean, kind: string, message?: string) {\n this.kind = kind;\n this.valid = valid;\n this.message = message;\n }\n\n private static _contextForError(kind: string, message: string) {\n return new Context(false, kind, message);\n }\n\n private static _getValueFromContext(\n reference: AttributeReference,\n context?: LDContextCommon,\n ): any {\n if (!context || !reference.isValid) {\n return undefined;\n }\n\n if (reference.depth === 1 && reference.getComponent(0) === 'anonymous') {\n return !!context?.anonymous;\n }\n return reference.get(context);\n }\n\n private _contextForKind(kind: string): LDContextCommon | undefined {\n if (this._isMulti) {\n return this._contexts[kind];\n }\n if (this.kind === kind) {\n return this._context;\n }\n return undefined;\n }\n\n private static _fromMultiKindContext(context: LDMultiKindContext): Context {\n const kinds = Object.keys(context).filter((key) => key !== 'kind');\n const kindsValid = kinds.every(validKind);\n\n if (!kinds.length) {\n return Context._contextForError(\n 'multi',\n 'A multi-kind context must contain at least one kind',\n );\n }\n\n if (!kindsValid) {\n return Context._contextForError('multi', 'Context contains invalid kinds');\n }\n\n const privateAttributes: Record<string, AttributeReference[]> = {};\n let contextsAreObjects = true;\n const contexts = kinds.reduce((acc: Record<string, LDContextCommon>, kind) => {\n const singleContext = context[kind];\n if (isContextCommon(singleContext)) {\n acc[kind] = singleContext;\n privateAttributes[kind] = processPrivateAttributes(singleContext._meta?.privateAttributes);\n } else {\n // No early break isn't the most efficient, but it is an error condition.\n contextsAreObjects = false;\n }\n return acc;\n }, {});\n\n if (!contextsAreObjects) {\n return Context._contextForError('multi', 'Context contained contexts that were not objects');\n }\n\n if (!Object.values(contexts).every((part) => validKey(part.key))) {\n return Context._contextForError('multi', 'Context contained invalid keys');\n }\n\n // There was only a single kind in the multi-kind context.\n // So we can just translate this to a single-kind context.\n if (kinds.length === 1) {\n const kind = kinds[0];\n const created = new Context(true, kind);\n created._context = { ...contexts[kind], kind };\n created._privateAttributeReferences = privateAttributes;\n created._isUser = kind === 'user';\n return created;\n }\n\n const created = new Context(true, context.kind);\n created._contexts = contexts;\n created._privateAttributeReferences = privateAttributes;\n\n created._isMulti = true;\n return created;\n }\n\n private static _fromSingleKindContext(context: LDSingleKindContext): Context {\n const { key, kind } = context;\n const kindValid = validKind(kind);\n const keyValid = validKey(key);\n\n if (!kindValid) {\n return Context._contextForError(kind ?? 'unknown', 'The kind was not valid for the context');\n }\n\n if (!keyValid) {\n return Context._contextForError(kind, 'The key for the context was not valid');\n }\n\n // The JSON interfaces uses dangling _.\n // eslint-disable-next-line no-underscore-dangle\n const privateAttributeReferences = processPrivateAttributes(context._meta?.privateAttributes);\n const created = new Context(true, kind);\n created._isUser = kind === 'user';\n created._context = context;\n created._privateAttributeReferences = {\n [kind]: privateAttributeReferences,\n };\n return created;\n }\n\n private static _fromLegacyUser(context: LDUser): Context {\n const keyValid = context.key !== undefined && context.key !== null;\n // For legacy users we allow empty keys.\n if (!keyValid) {\n return Context._contextForError('user', 'The key for the context was not valid');\n }\n const created = new Context(true, 'user');\n created._isUser = true;\n created._wasLegacy = true;\n created._context = legacyToSingleKind(context);\n created._privateAttributeReferences = {\n user: processPrivateAttributes(context.privateAttributeNames, true),\n };\n return created;\n }\n\n /**\n * Attempt to create a {@link Context} from an {@link LDContext}.\n * @param context The input context to create a Context from.\n * @returns a {@link Context}, if the context was not valid, then the returned contexts `valid`\n * property will be false.\n */\n public static fromLDContext(context: LDContext): Context {\n if (!context) {\n return Context._contextForError('unknown', 'No context specified. Returning default value');\n }\n if (isSingleKind(context)) {\n return Context._fromSingleKindContext(context);\n }\n if (isMultiKind(context)) {\n return Context._fromMultiKindContext(context);\n }\n if (isLegacyUser(context)) {\n return Context._fromLegacyUser(context);\n }\n\n return Context._contextForError('unknown', 'Context was not of a valid kind');\n }\n\n /**\n * Creates a {@link LDContext} from a {@link Context}.\n * @param context to be converted\n * @returns an {@link LDContext} if input was valid, otherwise undefined\n */\n public static toLDContext(context: Context): LDContext | undefined {\n if (!context.valid) {\n return undefined;\n }\n\n const contexts = context.getContexts();\n if (!context._isMulti) {\n return contexts[0][1];\n }\n const result: LDMultiKindContext = {\n kind: 'multi',\n };\n contexts.forEach((kindAndContext) => {\n const kind = kindAndContext[0];\n const nestedContext = kindAndContext[1];\n result[kind] = nestedContext;\n });\n return result;\n }\n\n /**\n * Attempt to get a value for the given context kind using the given reference.\n * @param reference The reference to the value to get.\n * @param kind The kind of the context to get the value for.\n * @returns a value or `undefined` if one is not found.\n */\n public valueForKind(reference: AttributeReference, kind: string = DEFAULT_KIND): any | undefined {\n if (reference.isKind) {\n return this.kinds;\n }\n return Context._getValueFromContext(reference, this._contextForKind(kind));\n }\n\n /**\n * Attempt to get a key for the specified kind.\n * @param kind The kind to get a key for.\n * @returns The key for the specified kind, or undefined.\n */\n public key(kind: string = DEFAULT_KIND): string | undefined {\n return this._contextForKind(kind)?.key;\n }\n\n /**\n * True if this is a multi-kind context.\n */\n public get isMultiKind(): boolean {\n return this._isMulti;\n }\n\n /**\n * Get the canonical key for this context.\n */\n public get canonicalKey(): string {\n if (this._isUser) {\n return this._context!.key;\n }\n if (this._isMulti) {\n return Object.keys(this._contexts)\n .sort()\n .map((key) => `${key}:${encodeKey(this._contexts[key].key)}`)\n .join(':');\n }\n return `${this.kind}:${encodeKey(this._context!.key)}`;\n }\n\n /**\n * Get the kinds of this context.\n */\n public get kinds(): string[] {\n if (this._isMulti) {\n return Object.keys(this._contexts);\n }\n return [this.kind];\n }\n\n /**\n * Get the kinds, and their keys, for this context.\n */\n public get kindsAndKeys(): Record<string, string> {\n if (this._isMulti) {\n return Object.entries(this._contexts).reduce(\n (acc: Record<string, string>, [kind, context]) => {\n acc[kind] = context.key;\n return acc;\n },\n {},\n );\n }\n return { [this.kind]: this._context!.key };\n }\n\n /**\n * Get the attribute references.\n *\n * @param kind\n */\n public privateAttributes(kind: string): AttributeReference[] {\n return this._privateAttributeReferences?.[kind] || [];\n }\n\n /**\n * Get the underlying context objects from this context.\n *\n * This method is intended to be used in event generation.\n *\n * The returned objects should not be modified.\n */\n public getContexts(): [string, LDContextCommon][] {\n if (this._isMulti) {\n return Object.entries(this._contexts);\n }\n return [[this.kind, this._context!]];\n }\n\n public get legacy(): boolean {\n return this._wasLegacy;\n }\n\n /**\n * Get the serialized canonical JSON for this context. This is not filtered for use in events.\n *\n * This method will cache the result.\n *\n * @returns The serialized canonical JSON or undefined if it cannot be serialized.\n */\n public canonicalUnfilteredJson(): string | undefined {\n if (!this.valid) {\n return undefined;\n }\n if (this._cachedCanonicalJson) {\n return this._cachedCanonicalJson;\n }\n try {\n this._cachedCanonicalJson = canonicalize(Context.toLDContext(this));\n } catch {\n // Indicated by undefined being returned.\n }\n return this._cachedCanonicalJson;\n }\n}\n","// _meta is part of the specification.\n\n/* eslint-disable no-underscore-dangle */\nimport { LDContextCommon } from './api';\nimport AttributeReference from './AttributeReference';\nimport Context from './Context';\n\n// These attributes cannot be removed via a private attribute.\nconst protectedAttributes = ['key', 'kind', '_meta', 'anonymous'].map(\n (str) => new AttributeReference(str, true),\n);\n\n// Attributes that should be stringified for legacy users.\nconst legacyTopLevelCopyAttributes = [\n 'name',\n 'ip',\n 'firstName',\n 'lastName',\n 'email',\n 'avatar',\n 'country',\n];\n\nfunction compare(a: AttributeReference, b: string[]) {\n return a.depth === b.length && b.every((value, index) => value === a.getComponent(index));\n}\n\nfunction cloneWithRedactions(target: LDContextCommon, references: AttributeReference[]): any {\n const stack: {\n key: string;\n ptr: string[];\n source: any;\n parent: any;\n visited: any[];\n }[] = [];\n const cloned: any = {};\n const excluded: string[] = [];\n\n stack.push(\n ...Object.keys(target).map((key) => ({\n key,\n ptr: [key],\n source: target,\n parent: cloned,\n visited: [target],\n })),\n );\n\n while (stack.length) {\n const item = stack.pop()!;\n const redactRef = references.find((ref) => compare(ref, item.ptr));\n if (!redactRef) {\n const value = item.source[item.key];\n\n // Handle null because it overlaps with object, which we will want to handle later.\n if (value === null) {\n item.parent[item.key] = value;\n } else if (Array.isArray(value)) {\n item.parent[item.key] = [...value];\n } else if (typeof value === 'object') {\n // Arrays and null must already be handled.\n\n // Prevent cycles by not visiting the same object\n // with in the same branch. Different branches\n // may contain the same object.\n //\n // Same object visited twice in different branches.\n // A -> B -> D\n // -> C -> D\n // This is fine, which is why it doesn't just check if the object\n // was visited ever.\n if (!item.visited.includes(value)) {\n item.parent[item.key] = {};\n\n stack.push(\n ...Object.keys(value).map((key) => ({\n key,\n ptr: [...item.ptr, key],\n source: value,\n parent: item.parent[item.key],\n visited: [...item.visited, value],\n })),\n );\n }\n } else {\n item.parent[item.key] = value;\n }\n } else {\n excluded.push(redactRef.redactionName);\n }\n }\n return { cloned, excluded: excluded.sort() };\n}\n\nexport default class ContextFilter {\n constructor(\n private readonly _allAttributesPrivate: boolean,\n private readonly _privateAttributes: AttributeReference[],\n ) {}\n\n filter(context: Context, redactAnonymousAttributes: boolean = false): any {\n const contexts = context.getContexts();\n if (contexts.length === 1) {\n return this._filterSingleKind(\n context,\n contexts[0][1],\n contexts[0][0],\n redactAnonymousAttributes,\n );\n }\n const filteredMulti: any = {\n kind: 'multi',\n };\n contexts.forEach(([kind, single]) => {\n filteredMulti[kind] = this._filterSingleKind(\n context,\n single,\n kind,\n redactAnonymousAttributes,\n );\n });\n return filteredMulti;\n }\n\n private _getAttributesToFilter(\n context: Context,\n single: LDContextCommon,\n kind: string,\n redactAllAttributes: boolean,\n ) {\n return (\n redactAllAttributes\n ? Object.keys(single).map((k) => new AttributeReference(k, true))\n : [...this._privateAttributes, ...context.privateAttributes(kind)]\n ).filter((attr) => !protectedAttributes.some((protectedAttr) => protectedAttr.compare(attr)));\n }\n\n private _filterSingleKind(\n context: Context,\n single: LDContextCommon,\n kind: string,\n redactAnonymousAttributes: boolean,\n ): any {\n const redactAllAttributes =\n this._allAttributesPrivate || (redactAnonymousAttributes && single.anonymous === true);\n const { cloned, excluded } = cloneWithRedactions(\n single,\n this._getAttributesToFilter(context, single, kind, redactAllAttributes),\n );\n\n if (context.legacy) {\n legacyTopLevelCopyAttributes.forEach((name) => {\n if (name in cloned) {\n cloned[name] = String(cloned[name]);\n }\n });\n }\n\n if (excluded.length) {\n if (!cloned._meta) {\n cloned._meta = {};\n }\n cloned._meta.redactedAttributes = excluded;\n }\n if (cloned._meta) {\n delete cloned._meta.privateAttributes;\n if (Object.keys(cloned._meta).length === 0) {\n delete cloned._meta;\n }\n }\n\n return cloned;\n }\n}\n","const MAX_RETRY_DELAY = 30 * 1000; // Maximum retry delay 30 seconds.\nconst JITTER_RATIO = 0.5; // Delay should be 50%-100% of calculated time.\n\nexport interface Backoff {\n success(): void;\n fail(): number;\n}\n\n/**\n * Implements exponential backoff and jitter. This class tracks successful connections and failures\n * and produces a retry delay.\n *\n * It does not start any timers or directly control a connection.\n *\n * The backoff follows an exponential backoff scheme with 50% jitter starting at\n * initialRetryDelayMillis and capping at MAX_RETRY_DELAY. If RESET_INTERVAL has elapsed after a\n * success, without an intervening faulure, then the backoff is reset to initialRetryDelayMillis.\n */\nexport class DefaultBackoff {\n private _retryCount: number = 0;\n private _activeSince?: number;\n private _initialRetryDelayMillis: number;\n /**\n * The exponent at which the backoff delay will exceed the maximum.\n * Beyond this limit the backoff can be set to the max.\n */\n private readonly _maxExponent: number;\n\n constructor(\n initialRetryDelayMillis: number,\n private readonly _retryResetIntervalMillis: number,\n private readonly _random = Math.random,\n ) {\n // Initial retry delay cannot be 0.\n this._initialRetryDelayMillis = Math.max(1, initialRetryDelayMillis);\n this._maxExponent = Math.ceil(Math.log2(MAX_RETRY_DELAY / this._initialRetryDelayMillis));\n }\n\n private _backoff(): number {\n const exponent = Math.min(this._retryCount, this._maxExponent);\n const delay = this._initialRetryDelayMillis * 2 ** exponent;\n return Math.min(delay, MAX_RETRY_DELAY);\n }\n\n private _jitter(computedDelayMillis: number): number {\n return computedDelayMillis - Math.trunc(this._random() * JITTER_RATIO * computedDelayMillis);\n }\n\n /**\n * This function should be called when a connection attempt is successful.\n *\n * @param timeStampMs The time of the success. Used primarily for testing, when not provided\n * the current time is used.\n */\n success(timeStampMs: number = Date.now()): void {\n this._activeSince = timeStampMs;\n }\n\n /**\n * This function should be called when a connection fails. It returns the a delay, in\n * milliseconds, after which a reconnection attempt should be made.\n *\n * @param timeStampMs The time of the success. Used primarily for testing, when not provided\n * the current time is used.\n * @returns The delay before the next connection attempt.\n */\n fail(timeStampMs: number = Date.now()): number {\n // If the last successful connection was active for more than the RESET_INTERVAL, then we\n // return to the initial retry delay.\n if (\n this._activeSince !== undefined &&\n timeStampMs - this._activeSince > this._retryResetIntervalMillis\n ) {\n this._retryCount = 0;\n }\n this._activeSince = undefined;\n const delay = this._jitter(this._backoff());\n this._retryCount += 1;\n return delay;\n }\n}\n","import { DataSourceState } from './DataSource';\n\n/**\n * Handler that connects the current {@link DataSource} to the {@link CompositeDataSource}. A single\n * {@link CallbackHandler} should only be given to one {@link DataSource}. Use {@link disable()} to\n * prevent additional callback events.\n */\nexport class CallbackHandler {\n private _disabled: boolean = false;\n\n constructor(\n private readonly _dataCallback: (basis: boolean, data: any) => void,\n private readonly _statusCallback: (status: DataSourceState, err?: any) => void,\n ) {}\n\n disable() {\n this._disabled = true;\n }\n\n async dataHandler(basis: boolean, data: any) {\n if (this._disabled) {\n return;\n }\n\n this._dataCallback(basis, data);\n }\n\n async statusHandler(status: DataSourceState, err?: any) {\n if (this._disabled) {\n return;\n }\n\n this._statusCallback(status, err);\n }\n}\n","// TODO: refactor client-sdk to use this enum\n/**\n * @experimental\n * This feature is not stable and not subject to any backwards compatibility guarantees or semantic\n * versioning. It is not suitable for production usage.\n */\nexport enum DataSourceState {\n // Positive confirmation of connection/data receipt\n Valid,\n // Spinning up to make first connection attempt\n Initializing,\n // Transient issue, automatic retry is expected\n Interrupted,\n // Data source was closed and will not retry automatically.\n Closed,\n}\n\n/**\n * @experimental\n * This feature is not stable and not subject to any backwards compatibility guarantees or semantic\n * versioning. It is not suitable for production usage.\n */\nexport interface DataSource {\n /**\n * May be called any number of times, if already started, has no effect\n * @param dataCallback that will be called when data arrives, may be called multiple times.\n * @param statusCallback that will be called when data source state changes or an unrecoverable error\n * has been encountered.\n * @param selectorGetter that can be invoked to provide the FDv2 selector/basis if one exists\n */\n start(\n dataCallback: (basis: boolean, data: any) => void,\n statusCallback: (status: DataSourceState, err?: any) => void,\n selectorGetter?: () => string | undefined,\n ): void;\n\n /**\n * May be called any number of times, if already stopped, has no effect. Datasource will not make any additional callbacks after stop returns.\n */\n stop(): void;\n}\n\n/**\n * @experimental\n * This feature is not stable and not subject to any backwards compatibility guarantees or semantic\n * versioning. It is not suitable for production usage.\n */\nexport type LDDataSourceFactory = () => DataSource;\n","/**\n * Helper class for {@link CompositeDataSource} to manage iterating on data sources and removing them on the fly.\n */\nexport class DataSourceList<T> {\n private _list: T[];\n private _circular: boolean;\n private _pos: number;\n\n /**\n * @param circular whether to loop off the end of the list back to the start\n * @param initialList of content\n */\n constructor(circular: boolean, initialList?: T[]) {\n this._list = initialList ? [...initialList] : [];\n this._circular = circular;\n this._pos = 0;\n }\n\n /**\n * Returns the current head and then iterates.\n */\n next(): T | undefined {\n if (this._list.length <= 0 || this._pos >= this._list.length) {\n return undefined;\n }\n\n const result = this._list[this._pos];\n\n if (this._circular) {\n this._pos = (this._pos + 1) % this._list.length;\n } else {\n this._pos += 1;\n }\n\n return result;\n }\n\n /**\n * Replaces all elements with the provided list and resets the position of head to the start.\n *\n * @param input that will replace existing list\n */\n replace(input: T[]): void {\n this._list = [...input];\n this._pos = 0;\n }\n\n /**\n * Removes the provided element from the list. If the removed element was the head, head moves to next. Consider head may be undefined if list is empty after removal.\n *\n * @param element to remove\n * @returns true if element was removed\n */\n remove(element: T): boolean {\n const index = this._list.indexOf(element);\n if (index < 0) {\n return false;\n }\n\n this._list.splice(index, 1);\n if (this._list.length > 0) {\n // if removed item was before head, adjust head\n if (index < this._pos) {\n this._pos -= 1;\n }\n\n if (this._circular && this._pos > this._list.length - 1) {\n this._pos = 0;\n }\n }\n return true;\n }\n\n /**\n * Reset the head position to the start of the list.\n */\n reset() {\n this._pos = 0;\n }\n\n /**\n * @returns the current head position in the list, 0 indexed.\n */\n pos() {\n return this._pos;\n }\n\n /**\n * @returns the current length of the list\n */\n length() {\n return this._list.length;\n }\n\n /**\n * Clears the list and resets head.\n */\n clear() {\n this._list = [];\n this._pos = 0;\n }\n}\n","/* eslint-disable max-classes-per-file */\nimport { DataSourceErrorKind } from './DataSourceErrorKinds';\n\nexport class LDFileDataSourceError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyFileDataSourceError';\n }\n}\n\nexport class LDPollingError extends Error {\n public readonly kind: DataSourceErrorKind;\n public readonly status?: number;\n public readonly recoverable: boolean;\n\n constructor(kind: DataSourceErrorKind, message: string, status?: number, recoverable = true) {\n super(message);\n this.kind = kind;\n this.status = status;\n this.name = 'LaunchDarklyPollingError';\n this.recoverable = recoverable;\n }\n}\n\nexport class LDStreamingError extends Error {\n public readonly kind: DataSourceErrorKind;\n public readonly code?: number;\n public readonly recoverable: boolean;\n\n constructor(kind: DataSourceErrorKind, message: string, code?: number, recoverable = true) {\n super(message);\n this.kind = kind;\n this.code = code;\n this.name = 'LaunchDarklyStreamingError';\n this.recoverable = recoverable;\n }\n}\n\n/**\n * This is a short term error and will be removed once FDv2 adoption is sufficient.\n */\nexport class LDFlagDeliveryFallbackError extends Error {\n public readonly kind: DataSourceErrorKind;\n public readonly code?: number;\n public readonly recoverable: boolean;\n\n constructor(kind: DataSourceErrorKind, message: string, code?: number) {\n super(message);\n this.kind = kind;\n this.code = code;\n this.name = 'LDFlagDeliveryFallbackError';\n this.recoverable = false;\n }\n}\n\nexport type StreamingErrorHandler = (err: LDStreamingError) => void;\n","/* eslint-disable no-await-in-loop */\nimport { LDLogger } from '../api/logging';\nimport { CallbackHandler } from '../api/subsystem/DataSystem/CallbackHandler';\nimport {\n DataSource,\n DataSourceState,\n LDDataSourceFactory,\n} from '../api/subsystem/DataSystem/DataSource';\nimport { Backoff, DefaultBackoff } from './Backoff';\nimport { DataSourceList } from './dataSourceList';\nimport { LDFlagDeliveryFallbackError } from './errors';\n\nconst DEFAULT_FALLBACK_TIME_MS = 2 * 60 * 1000;\nconst DEFAULT_RECOVERY_TIME_MS = 5 * 60 * 1000;\n\n/**\n * Represents a transition between data sources.\n */\nexport type Transition = 'switchToSync' | 'fallback' | 'recover' | 'stop';\n\n/**\n * Given a {@link DataSourceState}, how long to wait before transitioning.\n */\nexport type TransitionConditions = {\n [k in DataSourceState]?: { durationMS: number; transition: Transition };\n};\n\ninterface TransitionRequest {\n transition: Transition;\n err?: Error;\n}\n\n/**\n * The {@link CompositeDataSource} can combine a number of {@link DataSystemInitializer}s and {@link DataSystemSynchronizer}s\n * into a single {@link DataSource}, implementing fallback and recovery logic internally to choose where data is sourced from.\n */\nexport class CompositeDataSource implements DataSource {\n // TODO: SDK-856 async notification if initializer takes too long\n\n private _initPhaseActive: boolean;\n private _initFactories: DataSourceList<LDDataSourceFactory>;\n private _syncFactories: DataSourceList<LDDataSourceFactory>;\n private _fdv1Synchronizers: DataSourceList<LDDataSourceFactory>;\n\n private _stopped: boolean = true;\n private _externalTransitionPromise: Promise<TransitionRequest>;\n private _externalTransitionResolve?: (value: TransitionRequest) => void;\n private _cancelTokens: (() => void)[] = [];\n\n /**\n * @param initializers factories to create {@link DataSystemInitializer}s, in priority order.\n * @param synchronizers factories to create {@link DataSystemSynchronizer}s, in priority order.\n * @param fdv1Synchronizers factories to fallback to if we need to fallback to FDv1.\n * @param _logger for logging\n * @param _transitionConditions to control automated transition between datasources. Typically only used for testing.\n * @param _backoff to control delay between transitions. Typically only used for testing.\n */\n constructor(\n initializers: LDDataSourceFactory[],\n synchronizers: LDDataSourceFactory[],\n fdv1Synchronizers: LDDataSourceFactory[],\n private readonly _logger?: LDLogger,\n private readonly _transitionConditions: TransitionConditions = {\n [DataSourceState.Valid]: {\n durationMS: DEFAULT_RECOVERY_TIME_MS,\n transition: 'recover',\n },\n [DataSourceState.Interrupted]: {\n durationMS: DEFAULT_FALLBACK_TIME_MS,\n transition: 'fallback',\n },\n },\n private readonly _backoff: Backoff = new DefaultBackoff(1000, 30000),\n ) {\n this._externalTransitionPromise = new Promise<TransitionRequest>((resolveTransition) => {\n this._externalTransitionResolve = resolveTransition;\n });\n this._initPhaseActive = initializers.length > 0; // init phase if we have initializers\n this._initFactories = new DataSourceList(false, initializers);\n this._syncFactories = new DataSourceList(true, synchronizers);\n this._fdv1Synchronizers = new DataSourceList(true, fdv1Synchronizers);\n }\n\n async start(\n dataCallback: (basis: boolean, data: any) => void,\n statusCallback: (status: DataSourceState, err?: any) => void,\n selectorGetter?: () => string | undefined,\n ): Promise<void> {\n if (!this._stopped) {\n // don't allow multiple simultaneous runs\n this._logger?.info('CompositeDataSource already running. Ignoring call to start.');\n return;\n }\n this._stopped = false;\n\n this._logger?.debug(\n `CompositeDataSource starting with (${this._initFactories.length()} initializers, ${this._syncFactories.length()} synchronizers).`,\n );\n\n // this wrapper turns status updates from underlying data sources into a valid series of status updates for the consumer of this\n // composite data source\n const sanitizedStatusCallback = this._wrapStatusCallbackWithSanitizer(statusCallback);\n sanitizedStatusCallback(DataSourceState.Initializing);\n\n let lastTransition: Transition | undefined;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const {\n dataSource: currentDS,\n isPrimary,\n cullDSFactory,\n } = this._pickDataSource(lastTransition);\n\n const internalTransitionPromise = new Promise<TransitionRequest>((transitionResolve) => {\n if (currentDS) {\n // these local variables are used for handling automatic transition related to data source status (ex: recovering to primary after\n // secondary has been valid for N many seconds)\n let lastState: DataSourceState | undefined;\n let cancelScheduledTransition: () => void = () => {};\n\n // this callback handler can be disabled and ensures only one transition request occurs\n const callbackHandler = new CallbackHandler(\n (basis: boolean, data: any) => {\n this._backoff.success();\n dataCallback(basis, data);\n if (basis && this._initPhaseActive) {\n // transition to sync if we get basis during init\n callbackHandler.disable();\n this._consumeCancelToken(cancelScheduledTransition);\n sanitizedStatusCallback(DataSourceState.Interrupted);\n transitionResolve({ transition: 'switchToSync' });\n }\n },\n (state: DataSourceState, err?: any) => {\n // When we get a status update, we want to fallback if it is an error. We also want to schedule a transition for some\n // time in the future if this status remains for some duration (ex: Recover to primary synchronizer after the secondary\n // synchronizer has been Valid for some time). These scheduled transitions are configurable in the constructor.\n this._logger?.debug(\n `CompositeDataSource received state ${state} from underlying data source. Err is ${err}`,\n );\n if (err || state === DataSourceState.Closed) {\n callbackHandler.disable();\n if (err?.recoverable === false) {\n // don't use this datasource's factory again\n this._logger?.debug(`Culling data source due to err ${err}`);\n cullDSFactory?.();\n\n // this error indicates we should fallback to only using FDv1 synchronizers\n if (err instanceof LDFlagDeliveryFallbackError) {\n this._logger?.debug(`Falling back to FDv1`);\n this._syncFactories = this._fdv1Synchronizers;\n }\n }\n sanitizedStatusCallback(state, err);\n this._consumeCancelToken(cancelScheduledTransition);\n transitionResolve({ transition: 'fallback', err }); // unrecoverable error has occurred, so fallback\n } else {\n sanitizedStatusCallback(state);\n if (state !== lastState) {\n lastState = state;\n this._consumeCancelToken(cancelScheduledTransition); // cancel previously scheduled status transition if one was scheduled\n\n // primary source cannot recover to itself, so exclude it\n const condition = this._lookupTransitionCondition(state, isPrimary);\n if (condition) {\n const { promise, cancel } = this._cancellableDelay(condition.durationMS);\n cancelScheduledTransition = cancel;\n this._cancelTokens.push(cancelScheduledTransition);\n promise.then(() => {\n this._consumeCancelToken(cancel);\n callbackHandler.disable();\n sanitizedStatusCallback(DataSourceState.Interrupted);\n transitionResolve({ transition: condition.transition });\n });\n } else {\n // this data source state does not have a transition condition, so don't schedule any transition\n }\n }\n }\n },\n );\n currentDS.start(\n (basis, data) => callbackHandler.dataHandler(basis, data),\n (status, err) => callbackHandler.statusHandler(status, err),\n selectorGetter,\n );\n } else {\n // we don't have a data source to use!\n transitionResolve({\n transition: 'stop',\n err: {\n name: 'ExhaustedDataSources',\n message: `CompositeDataSource has exhausted all configured initializers and synchronizers.`,\n },\n });\n }\n });\n\n // await transition triggered by internal data source or an external stop request\n let transitionRequest = await Promise.race([\n internalTransitionPromise,\n this._externalTransitionPromise,\n ]);\n\n // stop the underlying datasource before transitioning to next state\n currentDS?.stop();\n\n if (transitionRequest.err && transitionRequest.transition !== 'stop') {\n // if the transition was due to an error we're not in the initializer phase, throttle the transition. Fallback between initializers is not throttled.\n const delay = this._initPhaseActive ? 0 : this._backoff.fail();\n const { promise, cancel: cancelDelay } = this._cancellableDelay(delay);\n this._cancelTokens.push(cancelDelay);\n const delayedTransition = promise.then(() => {\n this._consumeCancelToken(cancelDelay);\n return transitionRequest;\n });\n\n // race the delayed transition and external transition requests to be responsive\n transitionRequest = await Promise.race([\n delayedTransition,\n this._externalTransitionPromise,\n ]);\n\n // consume the delay cancel token (even if it resolved, need to stop tracking its token)\n this._consumeCancelToken(cancelDelay);\n }\n\n lastTransition = transitionRequest.transition;\n if (transitionRequest.transition === 'stop') {\n // exit the loop, this is intentionally not the sanitized status callback\n statusCallback(DataSourceState.Closed, transitionRequest.err);\n break;\n }\n }\n\n // reset so that run can be called again in the future\n this._reset();\n }\n\n async stop() {\n this._cancelTokens.forEach((cancel) => cancel());\n this._cancelTokens = [];\n this._externalTransitionResolve?.({ transition: 'stop' });\n }\n\n private _reset() {\n this._stopped = true;\n this._initPhaseActive = this._initFactories.length() > 0; // init phase if we have initializers;\n this._initFactories.reset();\n this._syncFactories.reset();\n this._fdv1Synchronizers.reset();\n this._externalTransitionPromise = new Promise<TransitionRequest>((tr) => {\n this._externalTransitionResolve = tr;\n });\n // intentionally not resetting the backoff to avoid a code path that could circumvent throttling\n }\n\n /**\n * Determines the next datasource and returns that datasource as well as a closure to cull the\n * datasource from the datasource lists. One example where the cull closure is invoked is if the\n * datasource has an unrecoverable error.\n */\n private _pickDataSource(transition?: Transition): {\n dataSource: DataSource | undefined;\n isPrimary: boolean;\n cullDSFactory: (() => void) | undefined;\n } {\n let factory: LDDataSourceFactory | undefined;\n let isPrimary: boolean;\n switch (transition) {\n case 'switchToSync':\n this._initPhaseActive = false; // one way toggle to false, unless this class is reset()\n this._syncFactories.reset();\n isPrimary = this._syncFactories.pos() === 0;\n factory = this._syncFactories.next();\n break;\n case 'recover':\n if (this._initPhaseActive) {\n this._initFactories.reset();\n isPrimary = this._initFactories.pos() === 0;\n factory = this._initFactories.next();\n } else {\n this._syncFactories.reset();\n isPrimary = this._syncFactories.pos() === 0;\n factory = this._syncFactories.next();\n }\n break;\n case 'fallback':\n default:\n // if asked to fallback after using all init factories, switch to sync factories\n if (this._initPhaseActive && this._initFactories.pos() >= this._initFactories.length()) {\n this._initPhaseActive = false;\n this._syncFactories.reset();\n }\n\n if (this._initPhaseActive) {\n isPrimary = this._initFactories.pos() === 0;\n factory = this._initFactories.next();\n } else {\n isPrimary = this._syncFactories.pos() === 0;\n factory = this._syncFactories.next();\n }\n break;\n }\n\n if (!factory) {\n return { dataSource: undefined, isPrimary, cullDSFactory: undefined };\n }\n\n return {\n dataSource: factory(),\n isPrimary,\n cullDSFactory: () => {\n if (factory) {\n this._syncFactories.remove(factory);\n }\n },\n };\n }\n\n /**\n * @returns the transition condition for the provided data source state or undefined\n * if there is no transition condition\n */\n private _lookupTransitionCondition(\n state: DataSourceState,\n excludeRecover: boolean,\n ): { durationMS: number; transition: Transition } | undefined {\n const condition = this._transitionConditions[state];\n\n // exclude recovery can happen for certain initializers/synchronizers (ex: the primary synchronizer shouldn't recover to itself)\n if (excludeRecover && condition?.transition === 'recover') {\n return undefined;\n }\n\n return condition;\n }\n\n private _cancellableDelay = (delayMS: number) => {\n let timeout: ReturnType<typeof setTimeout> | undefined;\n const promise = new Promise((res, _) => {\n timeout = setTimeout(res, delayMS);\n });\n return {\n promise,\n cancel() {\n if (timeout) {\n clearTimeout(timeout);\n timeout = undefined;\n }\n },\n };\n };\n\n private _consumeCancelToken(cancel: () => void) {\n cancel();\n const index = this._cancelTokens.indexOf(cancel, 0);\n if (index > -1) {\n this._cancelTokens.splice(index, 1);\n }\n }\n\n /**\n * This wrapper will ensure the following:\n *\n * Don't report DataSourceState.Initializing except as first status callback.\n * Map underlying DataSourceState.Closed to interrupted.\n * Don't report the same status and error twice in a row.\n */\n private _wrapStatusCallbackWithSanitizer(\n statusCallback: (status: DataSourceState, err?: any) => void,\n ): (status: DataSourceState, err?: any) => void {\n let alreadyReportedInitializing = false;\n let lastStatus: DataSourceState | undefined;\n let lastErr: any;\n\n return (status: DataSourceState, err?: any) => {\n let sanitized = status;\n // underlying errors, closed state, or off are masked as interrupted while we transition\n if (status === DataSourceState.Closed) {\n sanitized = DataSourceState.Interrupted;\n }\n\n // don't report the same combination of values twice in a row\n if (sanitized === lastStatus && err === lastErr) {\n return;\n }\n\n if (sanitized === DataSourceState.Initializing) {\n // don't report initializing again if that has already been reported\n if (alreadyReportedInitializing) {\n return;\n }\n alreadyReportedInitializing = true;\n }\n\n lastStatus = sanitized;\n lastErr = err;\n statusCallback(sanitized, err);\n };\n }\n}\n","export enum DataSourceErrorKind {\n /// An unexpected error, such as an uncaught exception, further\n /// described by the error message.\n Unknown = 'UNKNOWN',\n\n /// An I/O error such as a dropped connection.\n NetworkError = 'NETWORK_ERROR',\n\n /// The LaunchDarkly service returned an HTTP response with an error\n /// status, available in the status code.\n ErrorResponse = 'ERROR_RESPONSE',\n\n /// The SDK received malformed data from the LaunchDarkly service.\n InvalidData = 'INVALID_DATA',\n}\n","/* eslint-disable import/prefer-default-export */\n/**\n * Enable / disable Auto environment attributes. When enabled, the SDK will automatically\n * provide data about the mobile environment where the application is running. This data makes it simpler to target\n * your mobile customers based on application name or version, or on device characteristics including manufacturer,\n * model, operating system, locale, and so on. We recommend enabling this when you configure the SDK. To learn more,\n * read [Automatic environment attributes](https://docs.launchdarkly.com/sdk/features/environment-attributes).\n * for more documentation.\n */\nexport enum AutoEnvAttributes {\n Disabled,\n Enabled,\n}\n\ninterface AutoEnvCommon {\n /**\n * Unique key for the context kind.\n */\n key: string;\n\n /**\n * Version of the environment attributes schema being used.\n */\n envAttributesVersion: string;\n}\n\nexport interface LDApplication extends AutoEnvCommon {\n /**\n * Unique identifier of the application.\n */\n id?: string;\n name?: string;\n version?: string;\n versionName?: string;\n locale?: string;\n}\n\nexport interface LDDevice extends AutoEnvCommon {\n manufacturer?: string;\n model?: string;\n storageBytes?: string;\n memoryBytes?: string;\n os?: {\n /**\n * The family of operating system.\n */\n family?: string;\n name?: string;\n version?: string;\n };\n}\n","export enum LDEventType {\n AnalyticsEvents,\n DiagnosticEvent,\n}\n\nexport enum LDDeliveryStatus {\n Succeeded,\n Failed,\n FailedAndMustShutDown,\n}\n\nexport interface LDEventSenderResult {\n status: LDDeliveryStatus;\n serverTime?: number;\n error?: any;\n}\n\nexport default interface LDEventSender {\n sendEventData(type: LDEventType, data: any): Promise<LDEventSenderResult>;\n}\n","import { TypeValidators } from '../validators';\n\n/**\n * Attempt to produce a string representation of a value.\n * The format should be roughly comparable to `util.format`\n * aside from object which will be JSON versus the `util.inspect`\n * format.\n * @param val\n * @returns A string representation of the value if possible.\n */\nfunction tryStringify(val: any) {\n if (typeof val === 'string') {\n return val;\n }\n if (val === undefined) {\n return 'undefined';\n }\n if (val === null) {\n return 'null';\n }\n if (Object.prototype.hasOwnProperty.call(val, 'toString')) {\n try {\n return val.toString();\n } catch {\n /* Keep going */\n }\n }\n\n if (typeof val === 'bigint') {\n return `${val}n`;\n }\n try {\n return JSON.stringify(val);\n } catch (error) {\n if (error instanceof TypeError && error.message.indexOf('circular') >= 0) {\n return '[Circular]';\n }\n return '[Not Stringifiable]';\n }\n}\n\n/**\n * Attempt to produce a numeric representation.\n * BigInts have an `n` suffix.\n * @param val\n * @returns The numeric representation or 'NaN' if not numeric.\n */\nfunction toNumber(val: any): string {\n // Symbol has to be treated special because it will\n // throw an exception if an attempt is made to convert it.\n if (typeof val === 'symbol') {\n return 'NaN';\n }\n if (typeof val === 'bigint') {\n return `${val}n`;\n }\n return String(Number(val));\n}\n\n/**\n * Attempt to produce an integer representation.\n * BigInts have an `n` suffix.\n * @param val\n * @returns The integer representation or 'NaN' if not numeric.\n */\nfunction toInt(val: any): string {\n if (typeof val === 'symbol') {\n return 'NaN';\n }\n if (typeof val === 'bigint') {\n return `${val}n`;\n }\n return String(parseInt(val, 10));\n}\n\n/**\n * Attempt to produce a float representation.\n * BigInts have an `n` suffix.\n * @param val\n * @returns The integer representation or 'NaN' if not numeric.\n */\nfunction toFloat(val: any): string {\n if (typeof val === 'symbol') {\n return 'NaN';\n }\n return String(parseFloat(val));\n}\n\n// Based on:\n// https://nodejs.org/api/util.html#utilformatformat-args\n// The result will not match node exactly, but it should get the\n// right information through.\nconst escapes: Record<string, (val: any) => string> = {\n s: (val: any) => tryStringify(val),\n d: (val: any) => toNumber(val),\n i: (val: any) => toInt(val),\n f: (val: any) => toFloat(val),\n j: (val: any) => tryStringify(val),\n o: (val: any) => tryStringify(val),\n // eslint-disable-next-line @typescript-eslint/naming-convention\n O: (val: any) => tryStringify(val),\n c: () => '',\n};\n\n/**\n * A basic formatted for use where `util.format` is not available.\n * This will not be as performant, but it will produce formatted\n * messages.\n *\n * @internal\n *\n * @param args\n * @returns Formatted string.\n */\nexport default function format(...args: any[]): string {\n const formatString = args.shift();\n if (TypeValidators.String.is(formatString)) {\n let out = '';\n let i = 0;\n while (i < formatString.length) {\n const char = formatString.charAt(i);\n if (char === '%') {\n const nextIndex = i + 1;\n if (nextIndex < formatString.length) {\n const nextChar = formatString.charAt(i + 1);\n if (nextChar in escapes && args.length) {\n const value = args.shift();\n // This rule is for math.\n // eslint-disable-next-line no-unsafe-optional-chaining\n out += escapes[nextChar]?.(value);\n } else if (nextChar === '%') {\n out += '%';\n } else {\n out += `%${nextChar}`;\n }\n i += 2;\n }\n } else {\n out += char;\n i += 1;\n }\n }\n // If there are any args left after we exhaust the format string\n // then just stick those on the end.\n if (args.length) {\n if (out.length) {\n out += ' ';\n }\n out += args.map(tryStringify).join(' ');\n }\n return out;\n }\n return args.map(tryStringify).join(' ');\n}\n","import { BasicLoggerOptions, LDLogger, LDLogLevel } from '../api';\nimport format from './format';\n\nenum LogPriority {\n debug = 0,\n info = 1,\n warn = 2,\n error = 3,\n none = 4,\n}\n\nconst LEVEL_NAMES: LDLogLevel[] = ['debug', 'info', 'warn', 'error', 'none'];\n\n/**\n * A basic logger which handles filtering by level.\n *\n * With the default options it will write to `console.error`\n * and it will use the formatting provided by `console.error`.\n * If the destination is overwritten, then it will use an included\n * formatter similar to `util.format`.\n *\n * If a formatter is available, then that should be overridden\n * as well for performance.\n */\nexport default class BasicLogger implements LDLogger {\n private _logLevel: number;\n\n private _name: string;\n\n private _destinations?: Record<number, (line: string) => void>;\n\n private _formatter?: (...args: any[]) => string;\n\n /**\n * This should only be used as a default fallback and not as a convenient\n * solution. In most cases you should construct a new instance with the\n * appropriate options for your specific needs.\n */\n static get() {\n return new BasicLogger({});\n }\n\n constructor(options: BasicLoggerOptions) {\n this._logLevel = LogPriority[options.level ?? 'info'] ?? LogPriority.info;\n this._name = options.name ?? 'LaunchDarkly';\n this._formatter = options.formatter;\n if (typeof options.destination === 'object') {\n this._destinations = {\n [LogPriority.debug]: options.destination.debug,\n [LogPriority.info]: options.destination.info,\n [LogPriority.warn]: options.destination.warn,\n [LogPriority.error]: options.destination.error,\n };\n } else if (typeof options.destination === 'function') {\n const { destination } = options;\n this._destinations = {\n [LogPriority.debug]: destination,\n [LogPriority.info]: destination,\n [LogPriority.warn]: destination,\n [LogPriority.error]: destination,\n };\n }\n }\n\n private _tryFormat(...args: any[]): string {\n try {\n if (this._formatter) {\n // In case the provided formatter fails.\n return this._formatter?.(...args);\n }\n return format(...args);\n } catch {\n return format(...args);\n }\n }\n\n private _tryWrite(destination: (msg: string) => void, msg: string) {\n try {\n destination(msg);\n } catch {\n // eslint-disable-next-line no-console\n console.error(msg);\n }\n }\n\n private _log(level: number, args: any[]) {\n if (level >= this._logLevel) {\n const prefix = `${LEVEL_NAMES[level]}: [${this._name}]`;\n try {\n const destination = this._destinations?.[level];\n if (destination) {\n this._tryWrite(destination, `${prefix} ${this._tryFormat(...args)}`);\n } else {\n // `console.error` has its own formatter.\n // So we don't need to do anything.\n // eslint-disable-next-line no-console\n console.error(...args);\n }\n } catch {\n // If all else fails do not break.\n // eslint-disable-next-line no-console\n console.error(...args);\n }\n }\n }\n\n error(...args: any[]): void {\n this._log(LogPriority.error, args);\n }\n\n warn(...args: any[]): void {\n this._log(LogPriority.warn, args);\n }\n\n info(...args: any[]): void {\n this._log(LogPriority.info, args);\n }\n\n debug(...args: any[]): void {\n this._log(LogPriority.debug, args);\n }\n}\n","import type { LDLogger } from '../api';\nimport { TypeValidators } from '../validators';\n\nconst loggerRequirements = {\n error: TypeValidators.Function,\n warn: TypeValidators.Function,\n info: TypeValidators.Function,\n debug: TypeValidators.Function,\n};\n\n/**\n * The safeLogger logic exists because we allow the application to pass in a custom logger, but\n * there is no guarantee that the logger works correctly and if it ever throws exceptions there\n * could be serious consequences (e.g. an uncaught exception within an error event handler, due\n * to the SDK trying to log the error, can terminate the application). An exception could result\n * from faulty logic in the logger implementation, or it could be that this is not a logger at\n * all but some other kind of object; the former is handled by a catch block that logs an error\n * message to the SDK's default logger, and we can at least partly guard against the latter by\n * checking for the presence of required methods at configuration time.\n */\nexport default class SafeLogger implements LDLogger {\n private _logger: LDLogger;\n\n private _fallback: LDLogger;\n\n /**\n * Construct a safe logger with the specified logger.\n * @param logger The logger to use.\n * @param fallback A fallback logger to use in case an issue is encountered using\n * the provided logger.\n */\n constructor(logger: LDLogger, fallback: LDLogger) {\n Object.entries(loggerRequirements).forEach(([level, validator]) => {\n if (!validator.is((logger as any)[level])) {\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 this._logger = logger;\n this._fallback = fallback;\n }\n\n private _log(level: 'error' | 'warn' | 'info' | 'debug', args: any[]) {\n try {\n this._logger[level](...args);\n } catch {\n // If all else fails do not break.\n this._fallback[level](...args);\n }\n }\n\n error(...args: any[]): void {\n this._log('error', args);\n }\n\n warn(...args: any[]): void {\n this._log('warn', args);\n }\n\n info(...args: any[]): void {\n this._log('info', args);\n }\n\n debug(...args: any[]): void {\n this._log('debug', args);\n }\n}\n","import { LDLogger } from '../api';\nimport BasicLogger from './BasicLogger';\nimport format from './format';\nimport SafeLogger from './SafeLogger';\n\nconst createSafeLogger = (logger?: LDLogger) => {\n const basicLogger = new BasicLogger({\n level: 'info',\n // eslint-disable-next-line no-console\n destination: console.error,\n formatter: format,\n });\n return logger ? new SafeLogger(logger, basicLogger) : basicLogger;\n};\n\nexport default createSafeLogger;\n","/**\n * Messages for issues which can be encountered from processing the configuration options.\n */\nexport default class OptionMessages {\n static deprecated(oldName: string, newName: string): string {\n return `\"${oldName}\" is deprecated, please use \"${newName}\"`;\n }\n\n static optionBelowMinimum(name: string, value: number, min: number): string {\n return `Config option \"${name}\" had invalid value of ${value}, using minimum of ${min} instead`;\n }\n\n static unknownOption(name: string): string {\n return `Ignoring unknown config option \"${name}\"`;\n }\n\n static wrongOptionType(name: string, expectedType: string, actualType: string): string {\n return `Config option \"${name}\" should be of type ${expectedType}, got ${actualType}, using default value`;\n }\n\n static wrongOptionTypeBoolean(name: string, actualType: string): string {\n return `Config option \"${name}\" should be a boolean, got ${actualType}, converting to boolean`;\n }\n\n static invalidTagValue(name: string): string {\n return `Config option \"${name}\" must only contain letters, numbers, ., _ or -.`;\n }\n\n static tagValueTooLong(name: string): string {\n return `Value of \"${name}\" was longer than 64 characters and was discarded.`;\n }\n\n static partialEndpoint(name: string): string {\n return `You have set custom uris without specifying the ${name} URI; connections may not work properly`;\n }\n}\n","import { LDLogger } from '../api';\nimport { TypeValidators } from '../validators';\nimport OptionMessages from './OptionMessages';\n\n/**\n * Expression to validate characters that are allowed in tag keys and values.\n */\nconst allowedTagCharacters = /^(\\w|\\.|-)+$/;\n\nconst regexValidator = TypeValidators.stringMatchingRegex(allowedTagCharacters);\n\nconst tagValidator = {\n is: (u: unknown, name: string): { valid: boolean; message?: string } => {\n if (regexValidator.is(u)) {\n if (u.length > 64) {\n return { valid: false, message: OptionMessages.tagValueTooLong(name) };\n }\n return { valid: true };\n }\n return { valid: false, message: OptionMessages.invalidTagValue(name) };\n },\n};\n\n/**\n * Class for managing tags.\n */\nexport default class ApplicationTags {\n public readonly value?: string;\n\n constructor(options: {\n application?: { id?: string; version?: string; name?: string; versionName?: string };\n logger?: LDLogger;\n }) {\n const tags: Record<string, string[]> = {};\n const application = options?.application;\n const logger = options?.logger;\n\n if (application) {\n Object.entries(application).forEach(([key, value]) => {\n if (value !== null && value !== undefined) {\n const { valid, message } = tagValidator.is(value, `application.${key}`);\n\n if (!valid) {\n logger?.warn(message);\n } else if (key === 'versionName') {\n tags[`application-version-name`] = [value];\n } else {\n tags[`application-${key}`] = [value];\n }\n }\n });\n }\n\n const tagKeys = Object.keys(tags);\n if (tagKeys.length) {\n this.value = tagKeys\n .sort()\n .flatMap((key) => tags[key].sort().map((value) => `${key}/${value}`))\n .join(' ');\n }\n }\n}\n","import { LDClientContext, LDLogger, Platform } from '../api';\nimport ApplicationTags from './ApplicationTags';\nimport ServiceEndpoints from './ServiceEndpoints';\n\n/**\n * Basic configuration applicable to many SDK components for both server and\n * client SDKs.\n */\ninterface BasicConfiguration {\n tags?: ApplicationTags;\n\n logger?: LDLogger;\n\n /**\n * True if the SDK was configured to be completely offline.\n */\n offline?: boolean;\n\n /**\n * The configured SDK key.\n */\n sdkKey: string;\n\n /**\n * Defines the base service URIs used by SDK components.\n */\n serviceEndpoints: ServiceEndpoints;\n\n /**\n * Sets the initial reconnect delay for the streaming connection, in seconds.\n */\n streamInitialReconnectDelay?: number;\n}\n\n/**\n * The client context provides basic configuration and platform support which are required\n * when building SDK components.\n */\nexport default class ClientContext implements LDClientContext {\n basicConfiguration: BasicConfiguration;\n\n constructor(\n sdkKey: string,\n configuration: {\n logger?: LDLogger;\n offline?: boolean;\n serviceEndpoints: ServiceEndpoints;\n tags?: ApplicationTags;\n },\n public readonly platform: Platform,\n ) {\n this.basicConfiguration = {\n tags: configuration.tags,\n logger: configuration.logger,\n offline: configuration.offline,\n serviceEndpoints: configuration.serviceEndpoints,\n sdkKey,\n };\n }\n}\n","function canonicalizeUri(uri: string): string {\n return uri.replace(/\\/+$/, '');\n}\n\nfunction canonicalizePath(path: string): string {\n return path.replace(/^\\/+/, '').replace(/\\?$/, '');\n}\n\n/**\n * Specifies the base service URIs used by SDK components.\n */\nexport default class ServiceEndpoints {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n public static DEFAULT_EVENTS = 'https://events.launchdarkly.com';\n\n public readonly streaming: string;\n public readonly polling: string;\n public readonly events: string;\n public readonly payloadFilterKey?: string;\n\n /** Valid paths are:\n * /bulk\n * /events/bulk/envId\n * /mobile\n */\n public readonly analyticsEventPath: string;\n\n /** Valid paths are:\n * /diagnostic\n * /events/diagnostic/envId\n * /mobile/events/diagnostic\n */\n public readonly diagnosticEventPath: string;\n\n // if true the sdk key will be included as authorization header\n public readonly includeAuthorizationHeader: boolean;\n\n public constructor(\n streaming: string,\n polling: string,\n events: string = ServiceEndpoints.DEFAULT_EVENTS,\n analyticsEventPath: string = '/bulk',\n diagnosticEventPath: string = '/diagnostic',\n includeAuthorizationHeader: boolean = true,\n payloadFilterKey?: string,\n ) {\n this.streaming = canonicalizeUri(streaming);\n this.polling = canonicalizeUri(polling);\n this.events = canonicalizeUri(events);\n this.analyticsEventPath = analyticsEventPath;\n this.diagnosticEventPath = diagnosticEventPath;\n this.includeAuthorizationHeader = includeAuthorizationHeader;\n this.payloadFilterKey = payloadFilterKey;\n }\n}\n\nfunction getWithParams(uri: string, parameters: { key: string; value: string }[] = []) {\n if (parameters.length === 0) {\n return uri;\n }\n\n const parts = parameters.map(({ key, value }) => `${key}=${value}`);\n return `${uri}?${parts.join('&')}`;\n}\n\n/**\n * Get the URI for the streaming endpoint.\n *\n * @param endpoints The service endpoints.\n * @param path The path to the resource, devoid of any query parameters or hrefs.\n * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.\n */\nexport function getStreamingUri(\n endpoints: ServiceEndpoints,\n path: string,\n parameters: { key: string; value: string }[],\n): string {\n const canonicalizedPath = canonicalizePath(path);\n\n const combinedParameters = [...parameters];\n if (endpoints.payloadFilterKey) {\n combinedParameters.push({ key: 'filter', value: endpoints.payloadFilterKey });\n }\n\n return getWithParams(`${endpoints.streaming}/${canonicalizedPath}`, combinedParameters);\n}\n\n/**\n * Get the URI for the polling endpoint.\n *\n * @param endpoints The service endpoints.\n * @param path The path to the resource, devoid of any query parameters or hrefs.\n * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.\n */\nexport function getPollingUri(\n endpoints: ServiceEndpoints,\n path: string,\n parameters: { key: string; value: string }[] = [],\n): string {\n const canonicalizedPath = canonicalizePath(path);\n\n const combinedParameters = [...parameters];\n if (endpoints.payloadFilterKey) {\n combinedParameters.push({ key: 'filter', value: endpoints.payloadFilterKey });\n }\n\n return getWithParams(`${endpoints.polling}/${canonicalizedPath}`, combinedParameters);\n}\n\n/**\n * Get the URI for the events endpoint.\n *\n * @param endpoints The service endpoints.\n * @param path The path to the resource, devoid of any query parameters or hrefs.\n * @param parameters The query parameters. These query parameters must already have the appropriate encoding applied. This function WILL NOT apply it for you.\n */\nexport function getEventsUri(\n endpoints: ServiceEndpoints,\n path: string,\n parameters: { key: string; value: string }[] = [],\n): string {\n const canonicalizedPath = canonicalizePath(path);\n\n return getWithParams(`${endpoints.events}/${canonicalizedPath}`, parameters);\n}\n","// These classes are of trivial complexity. If they become\n// more complex, then they could be independent files.\n/* eslint-disable max-classes-per-file */\n\nexport class LDUnexpectedResponseError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyUnexpectedResponseError';\n }\n}\n\nexport class LDClientError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyClientError';\n }\n}\n\nexport class LDTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyTimeoutError';\n }\n}\n\n/**\n * Check if the HTTP error is recoverable. This will return false if a request\n * made with any payload could not recover. If the reason for the failure\n * is payload specific, for instance a payload that is too large, then\n * it could recover with a different payload.\n */\nexport function isHttpRecoverable(status: number) {\n if (status >= 400 && status < 500) {\n return status === 400 || status === 408 || status === 429;\n }\n return true;\n}\n\n/**\n * Returns true if the status could recover for a different payload.\n *\n * When used with event processing this indicates that we should discard\n * the payload, but that a subsequent payload may succeed. Therefore we should\n * not stop event processing.\n */\nexport function isHttpLocallyRecoverable(status: number) {\n if (status === 413) {\n return true;\n }\n return isHttpRecoverable(status);\n}\n","import { LDTimeoutError } from '../errors';\nimport { VoidFunction } from './VoidFunction';\n\n/**\n * Represents a timeout that can be cancelled.\n *\n * When racing a timeout, and another task completes before the timeout,\n * then the timeout should be cancelled. This prevents leaving open handles\n * which can stop the runtime from exiting.\n */\nexport interface CancelableTimeout {\n promise: Promise<void>;\n cancel: VoidFunction;\n}\n\n/**\n * Returns a promise which errors after t seconds.\n *\n * @param t Timeout in seconds.\n * @param taskName Name of task being timed for logging and error reporting.\n */\nexport function cancelableTimedPromise(t: number, taskName: string): CancelableTimeout {\n let timeout: ReturnType<typeof setTimeout>;\n let resolve: VoidFunction;\n const promise = new Promise<void>((_res, reject) => {\n resolve = _res;\n timeout = setTimeout(() => {\n const e = `${taskName} timed out after ${t} seconds.`;\n reject(new LDTimeoutError(e));\n }, t * 1000);\n });\n return {\n promise,\n cancel: () => {\n resolve();\n clearTimeout(timeout);\n },\n };\n}\n","export default function clone<T>(obj: any) {\n if (obj === undefined || obj === null) {\n return obj;\n }\n\n return JSON.parse(JSON.stringify(obj)) as T;\n}\n","// eslint-disable-next-line import/prefer-default-export\nexport function secondsToMillis(sec: number): number {\n return Math.trunc(sec * 1000);\n}\n","/**\n * Wait before calling the same function. Useful for expensive calls.\n * Adapted from https://amitd.co/code/typescript/debounce.\n *\n * @return The debounced function.\n *\n * @example\n *\n * ```js\n * const debouncedFunction = debounce(e => {\n * console.log(e);\n * }, 5000);\n *\n * // Console logs 'Hello world again ' after 5 seconds\n * debouncedFunction('Hello world');\n * debouncedFunction('Hello world again');\n * ```\n * @param fn The function to be debounced.\n * @param delayMs Defaults to 5 seconds.\n */\nconst debounce = <T extends (...args: any[]) => ReturnType<T>>(\n fn: T,\n delayMs: number = 5000,\n): ((...args: Parameters<T>) => void) => {\n let timer: ReturnType<typeof setTimeout>;\n\n return (...args: Parameters<T>) => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n fn(...args);\n }, delayMs);\n };\n};\n\nexport default debounce;\n","const isEmptyObject = (obj: any) => JSON.stringify(obj) === '{}';\n\nexport default isEmptyObject;\n","import isEmptyObject from './isEmptyObject';\n\n/**\n * Strips all falsy and empty {} from a given object. Returns a new object with only truthy values.\n * Sourced from below but modified to include checks for empty object and ignoring keys.\n * https://www.w3resource.com/javascript-exercises/javascript-array-exercise-47.php\n *\n * @param obj\n * @param ignoreKeys\n */\nconst deepCompact = <T extends Object>(obj?: T, ignoreKeys?: string[]) => {\n if (!obj) {\n return obj;\n }\n\n return Object.entries(obj).reduce((acc: any, [key, value]) => {\n if (Boolean(value) && !isEmptyObject(value) && !ignoreKeys?.includes(key)) {\n acc[key] = typeof value === 'object' ? deepCompact(value, ignoreKeys) : value;\n }\n return acc;\n }, {}) as T;\n};\n\nexport default deepCompact;\n","/* eslint-disable */\n// Ripped from https://github.com/epoberezkin/fast-deep-fastDeepEqual\n\n// {{? it.es6 }}\n// var envHasBigInt64Array = typeof BigInt64Array !== 'undefined';\n// {{?}}\n\nexport default function fastDeepEqual(a: any, b: any) {\n if (a === b) return true;\n\n if (a && b && typeof a == 'object' && typeof b == 'object') {\n if (a.constructor !== b.constructor) return false;\n\n var length, i, keys;\n if (Array.isArray(a)) {\n length = a.length;\n if (length != b.length) return false;\n for (i = length; i-- !== 0; ) if (!fastDeepEqual(a[i], b[i])) return false;\n return true;\n }\n\n // {{? it.es6 }}\n if (a instanceof Map && b instanceof Map) {\n if (a.size !== b.size) return false;\n for (i of a.entries()) if (!b.has(i[0])) return false;\n for (i of a.entries()) if (!fastDeepEqual(i[1], b.get(i[0]))) return false;\n return true;\n }\n\n if (a instanceof Set && b instanceof Set) {\n if (a.size !== b.size) return false;\n for (i of a.entries()) if (!b.has(i[0])) return false;\n return true;\n }\n\n if (ArrayBuffer.isView(a) && ArrayBuffer.isView(b)) {\n // @ts-ignore\n length = a.length;\n // @ts-ignore\n if (length != b.length) return false;\n for (i = length; i-- !== 0; ) {\n // @ts-ignore\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n // {{?}}\n\n if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;\n if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();\n if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();\n\n keys = Object.keys(a);\n length = keys.length;\n if (length !== Object.keys(b).length) return false;\n\n for (i = length; i-- !== 0; )\n if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;\n\n for (i = length; i-- !== 0; ) {\n var key = keys[i];\n // {{? it.react }}\n // if (key === '_owner' && a.$$typeof) {\n // // React-specific: avoid traversing React elements' _owner.\n // // _owner contains circular references\n // // and is not needed when comparing the actual elements (and not their owners)\n // continue;\n // }\n // {{?}}\n if (!fastDeepEqual(a[key], b[key])) return false;\n }\n\n return true;\n }\n\n // true if both NaN, false otherwise\n return a !== a && b !== b;\n}\n","import { Encoding, HttpErrorResponse, Info } from '../api';\nimport { isHttpRecoverable } from '../errors';\nimport { ApplicationTags } from '../options';\n\nexport type LDHeaders = {\n authorization?: string;\n 'user-agent'?: string;\n 'x-launchdarkly-user-agent'?: string;\n 'x-launchdarkly-wrapper'?: string;\n 'x-launchdarkly-tags'?: string;\n};\n\nexport function defaultHeaders(\n sdkKey: string,\n info: Info,\n tags?: ApplicationTags,\n includeAuthorizationHeader: boolean = true,\n userAgentHeaderName: 'user-agent' | 'x-launchdarkly-user-agent' = 'user-agent',\n): LDHeaders {\n const { userAgentBase, version, wrapperName, wrapperVersion } = info.sdkData();\n\n const headers: LDHeaders = {\n [userAgentHeaderName]: `${userAgentBase ?? 'NodeJSClient'}/${version}`,\n };\n\n // edge sdks sets this to false because they use the clientSideID\n // and they don't need the authorization header\n if (includeAuthorizationHeader) {\n headers.authorization = sdkKey;\n }\n\n if (wrapperName) {\n headers['x-launchdarkly-wrapper'] = wrapperVersion\n ? `${wrapperName}/${wrapperVersion}`\n : wrapperName;\n }\n\n if (tags?.value) {\n headers['x-launchdarkly-tags'] = tags.value;\n }\n\n return headers;\n}\n\nexport function httpErrorMessage(\n err: HttpErrorResponse,\n context: string,\n retryMessage?: string,\n): string {\n let desc;\n if (err.status) {\n desc = `error ${err.status}${err.status === 401 ? ' (invalid SDK key)' : ''}`;\n } else {\n desc = `I/O error (${err.message || 'unknown error'})`;\n }\n const action = retryMessage ?? 'giving up permanently';\n return `Received ${desc} for ${context} - ${action}`;\n}\n\nexport function shouldRetry({ status }: HttpErrorResponse) {\n return status ? isHttpRecoverable(status) : true;\n}\n\n/**\n * In react-native use base64-js to polyfill btoa. This is safe\n * because the react-native repo uses it too. Set the global.btoa to the encode\n * function of base64-js.\n * https://github.com/beatgammit/base64-js\n * https://github.com/axios/axios/issues/2235#issuecomment-512204616\n *\n * Ripped from https://thewoods.blog/base64url/\n */\nexport const base64UrlEncode = (s: string, encoding: Encoding): string =>\n encoding.btoa(s).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n","export default () => {};\n","const sleep = async (delayMillis: number = 1000) =>\n new Promise((resolve) => {\n setTimeout(resolve, delayMillis);\n });\n\nexport default sleep;\n","import { LDTimeoutError } from '../errors';\n\n/**\n * Returns a promise which errors after t seconds.\n *\n * @param t Timeout in seconds.\n * @param taskName Name of task being timed for logging and error reporting.\n */\nconst timedPromise = (t: number, taskName: string) =>\n new Promise<void>((_res, reject) => {\n setTimeout(() => {\n const e = `${taskName} timed out after ${t} seconds.`;\n reject(new LDTimeoutError(e));\n }, t * 1000);\n });\n\nexport default timedPromise;\n","import { Platform } from '../../api';\nimport { DiagnosticId, DiagnosticInitEvent, DiagnosticStatsEvent, StreamInitData } from './types';\n\nexport default class DiagnosticsManager {\n private readonly _startTime: number;\n private _streamInits: StreamInitData[] = [];\n private readonly _id: DiagnosticId;\n private _dataSinceDate: number;\n\n constructor(\n sdkKey: string,\n private readonly _platform: Platform,\n private readonly _diagnosticInitConfig: any,\n ) {\n this._startTime = Date.now();\n this._dataSinceDate = this._startTime;\n this._id = {\n diagnosticId: _platform.crypto.randomUUID(),\n sdkKeySuffix: sdkKey.length > 6 ? sdkKey.substring(sdkKey.length - 6) : sdkKey,\n };\n }\n\n /**\n * Creates the initial event that is sent by the event processor when the SDK starts up. This will\n * not be repeated during the lifetime of the SDK client.\n */\n createInitEvent(): DiagnosticInitEvent {\n const sdkData = this._platform.info.sdkData();\n const platformData = this._platform.info.platformData();\n\n return {\n kind: 'diagnostic-init',\n id: this._id,\n creationDate: this._startTime,\n sdk: sdkData,\n configuration: this._diagnosticInitConfig,\n platform: {\n name: platformData.name,\n osArch: platformData.os?.arch,\n osName: platformData.os?.name,\n osVersion: platformData.os?.version,\n ...(platformData.additional || {}),\n },\n };\n }\n\n /**\n * Records a stream connection attempt (called by the stream processor).\n *\n * @param timestamp Time of the *beginning* of the connection attempt.\n * @param failed True if the connection failed, or we got a read timeout before receiving a \"put\".\n * @param durationMillis Elapsed time between starting timestamp and when we either gave up/lost\n * the connection or received a successful \"put\".\n */\n recordStreamInit(timestamp: number, failed: boolean, durationMillis: number) {\n const item = { timestamp, failed, durationMillis };\n this._streamInits.push(item);\n }\n\n /**\n * Creates a periodic event containing time-dependent stats, and resets the state of the manager\n * with regard to those stats.\n *\n * Note: the reason droppedEvents, deduplicatedUsers, and eventsInLastBatch are passed into this\n * function, instead of being properties of the DiagnosticsManager, is that the event processor is\n * the one who's calling this function and is also the one who's tracking those stats.\n */\n createStatsEventAndReset(\n droppedEvents: number,\n deduplicatedUsers: number,\n eventsInLastBatch: number,\n ): DiagnosticStatsEvent {\n const currentTime = Date.now();\n const evt: DiagnosticStatsEvent = {\n kind: 'diagnostic',\n id: this._id,\n creationDate: currentTime,\n dataSinceDate: this._dataSinceDate,\n droppedEvents,\n deduplicatedUsers,\n eventsInLastBatch,\n streamInits: this._streamInits,\n };\n\n this._streamInits = [];\n this._dataSinceDate = currentTime;\n return evt;\n }\n}\n","/**\n * Different kinds of error which may be encountered during evaluation.\n */\nenum ErrorKinds {\n MalformedFlag = 'MALFORMED_FLAG',\n UserNotSpecified = 'USER_NOT_SPECIFIED',\n FlagNotFound = 'FLAG_NOT_FOUND',\n ClientNotReady = 'CLIENT_NOT_READY',\n WrongType = 'WRONG_TYPE',\n}\n\nexport default ErrorKinds;\n","/**\n * Messages for issues which can be encountered processing client requests.\n */\nexport default class ClientMessages {\n static readonly MissingContextKeyNoEvent =\n 'Context was unspecified or had no key; event will not be sent';\n\n static invalidMetricValue(badType: string) {\n return (\n 'The track function was called with a non-numeric \"metricValue\"' +\n ` (${badType}), only numeric metric values are supported.`\n );\n }\n}\n","import { Crypto, Requests } from '../../api';\nimport {\n LDDeliveryStatus,\n LDEventSender,\n LDEventSenderResult,\n LDEventType,\n} from '../../api/subsystem';\nimport {\n isHttpLocallyRecoverable,\n isHttpRecoverable,\n LDUnexpectedResponseError,\n} from '../../errors';\nimport { ClientContext, getEventsUri } from '../../options';\nimport { httpErrorMessage, LDHeaders, sleep } from '../../utils';\n\nexport default class EventSender implements LDEventSender {\n private _crypto: Crypto;\n private _defaultHeaders: {\n [key: string]: string;\n };\n private _diagnosticEventsUri: string;\n private _eventsUri: string;\n private _requests: Requests;\n\n constructor(clientContext: ClientContext, baseHeaders: LDHeaders) {\n const { basicConfiguration, platform } = clientContext;\n const {\n serviceEndpoints: { analyticsEventPath, diagnosticEventPath },\n } = basicConfiguration;\n const { crypto, requests } = platform;\n\n this._defaultHeaders = { ...baseHeaders };\n this._eventsUri = getEventsUri(basicConfiguration.serviceEndpoints, analyticsEventPath, []);\n this._diagnosticEventsUri = getEventsUri(\n basicConfiguration.serviceEndpoints,\n diagnosticEventPath,\n [],\n );\n this._requests = requests;\n this._crypto = crypto;\n }\n\n private async _tryPostingEvents(\n events: any,\n uri: string,\n payloadId: string | undefined,\n canRetry: boolean,\n ): Promise<LDEventSenderResult> {\n const tryRes: LDEventSenderResult = {\n status: LDDeliveryStatus.Succeeded,\n };\n\n const headers: Record<string, string> = {\n ...this._defaultHeaders,\n 'content-type': 'application/json',\n };\n\n if (payloadId) {\n headers['x-launchdarkly-payload-id'] = payloadId;\n headers['x-launchDarkly-event-schema'] = '4';\n }\n let error;\n try {\n const { status, headers: resHeaders } = await this._requests.fetch(uri, {\n headers,\n body: JSON.stringify(events),\n compressBodyIfPossible: true,\n method: 'POST',\n // When sending events from browser environments the request should be completed even\n // if the user is navigating away from the page.\n keepalive: true,\n });\n\n const serverDate = Date.parse(resHeaders.get('date') || '');\n if (serverDate) {\n tryRes.serverTime = serverDate;\n }\n\n if (status <= 204) {\n return tryRes;\n }\n\n error = new LDUnexpectedResponseError(\n httpErrorMessage({ status, message: 'some events were dropped' }, 'event posting'),\n );\n\n if (!isHttpRecoverable(status)) {\n // If the HTTP request isn't recoverable. Meaning if we made the same request it\n // would not recover, then we check if a different request could recover.\n // If a different request could not recover, then we shutdown. If a different request could\n // recover, then we just don't retry this specific request.\n if (!isHttpLocallyRecoverable(status)) {\n tryRes.status = LDDeliveryStatus.FailedAndMustShutDown;\n } else {\n tryRes.status = LDDeliveryStatus.Failed;\n }\n tryRes.error = error;\n return tryRes;\n }\n } catch (err) {\n error = err;\n }\n\n // recoverable but not retrying\n if (error && !canRetry) {\n tryRes.status = LDDeliveryStatus.Failed;\n tryRes.error = error;\n return tryRes;\n }\n\n // wait 1 second before retrying\n await sleep();\n\n return this._tryPostingEvents(events, this._eventsUri, payloadId, false);\n }\n\n async sendEventData(type: LDEventType, data: any): Promise<LDEventSenderResult> {\n const payloadId = type === LDEventType.AnalyticsEvents ? this._crypto.randomUUID() : undefined;\n const uri = type === LDEventType.AnalyticsEvents ? this._eventsUri : this._diagnosticEventsUri;\n\n return this._tryPostingEvents(data, uri, payloadId, true);\n }\n}\n","import InputCustomEvent from './InputCustomEvent';\nimport InputEvalEvent from './InputEvalEvent';\nimport InputIdentifyEvent from './InputIdentifyEvent';\nimport InputMigrationEvent from './InputMigrationEvent';\n\nexport function isFeature(u: any): u is InputEvalEvent {\n return u.kind === 'feature';\n}\n\nexport function isCustom(u: any): u is InputCustomEvent {\n return u.kind === 'custom';\n}\n\nexport function isIdentify(u: any): u is InputIdentifyEvent {\n return u.kind === 'identify';\n}\n\nexport function isMigration(u: any): u is InputMigrationEvent {\n return u.kind === 'migration_op';\n}\n","/**\n * @internal\n */\nexport default class SummaryCounter {\n public readonly default: any;\n\n constructor(\n public count: number,\n public key: string,\n public value: any,\n defValue: any,\n public version?: number,\n public variation?: number,\n ) {\n this.default = defValue;\n }\n\n increment() {\n this.count += 1;\n }\n}\n","import Context from '../../Context';\nimport ContextFilter from '../../ContextFilter';\nimport { isFeature } from './guards';\nimport InputEvalEvent from './InputEvalEvent';\nimport InputEvent from './InputEvent';\nimport LDEventSummarizer, {\n FlagCounter,\n FlagSummary,\n SummarizedFlagsEvent,\n} from './LDEventSummarizer';\nimport SummaryCounter from './SummaryCounter';\n\nfunction counterKey(event: InputEvalEvent) {\n return `${event.key}:${\n event.variation !== null && event.variation !== undefined ? event.variation : ''\n }:${event.version !== null && event.version !== undefined ? event.version : ''}`;\n}\n\n/**\n * @internal\n */\nexport default class EventSummarizer implements LDEventSummarizer {\n private _startDate = 0;\n\n private _endDate = 0;\n\n private _counters: Record<string, SummaryCounter> = {};\n\n private _contextKinds: Record<string, Set<string>> = {};\n\n private _context?: Context;\n\n constructor(\n private readonly _singleContext: boolean = false,\n private readonly _contextFilter?: ContextFilter,\n ) {}\n\n summarizeEvent(event: InputEvent) {\n if (isFeature(event) && !event.excludeFromSummaries) {\n if (!this._context) {\n this._context = event.context;\n }\n const countKey = counterKey(event);\n const counter = this._counters[countKey];\n let kinds = this._contextKinds[event.key];\n if (!kinds) {\n kinds = new Set();\n this._contextKinds[event.key] = kinds;\n }\n event.context.kinds.forEach((kind) => kinds.add(kind));\n\n if (counter) {\n counter.increment();\n } else {\n this._counters[countKey] = new SummaryCounter(\n 1,\n event.key,\n event.value,\n event.default,\n event.version,\n event.variation,\n );\n }\n\n if (this._startDate === 0 || event.creationDate < this._startDate) {\n this._startDate = event.creationDate;\n }\n if (event.creationDate > this._endDate) {\n this._endDate = event.creationDate;\n }\n }\n }\n\n getSummary(): SummarizedFlagsEvent {\n const features = Object.values(this._counters).reduce(\n (acc: Record<string, FlagSummary>, counter) => {\n let flagSummary = acc[counter.key];\n if (!flagSummary) {\n flagSummary = {\n default: counter.default,\n counters: [],\n contextKinds: [...this._contextKinds[counter.key]],\n };\n acc[counter.key] = flagSummary;\n }\n\n const counterOut: FlagCounter = {\n value: counter.value,\n count: counter.count,\n };\n if (counter.variation !== undefined && counter.variation !== null) {\n counterOut.variation = counter.variation;\n }\n if (counter.version !== undefined && counter.version !== null) {\n counterOut.version = counter.version;\n } else {\n counterOut.unknown = true;\n }\n flagSummary.counters.push(counterOut);\n\n return acc;\n },\n {},\n );\n\n const event: SummarizedFlagsEvent = {\n startDate: this._startDate,\n endDate: this._endDate,\n features,\n kind: 'summary',\n context:\n this._context !== undefined && this._singleContext\n ? this._contextFilter?.filter(this._context)\n : undefined,\n };\n this._clearSummary();\n return event;\n }\n\n private _clearSummary() {\n this._startDate = 0;\n this._endDate = 0;\n this._counters = {};\n this._contextKinds = {};\n }\n}\n","export default class LDInvalidSDKKeyError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LaunchDarklyInvalidSDKKeyError';\n }\n}\n","import { LDLogger } from '../../api';\nimport ContextFilter from '../../ContextFilter';\nimport EventSummarizer from './EventSummarizer';\nimport { isFeature } from './guards';\nimport InputEvent from './InputEvent';\nimport { LDMultiEventSummarizer, SummarizedFlagsEvent } from './LDEventSummarizer';\n\nexport default class MultiEventSummarizer implements LDMultiEventSummarizer {\n constructor(\n private readonly _contextFilter: ContextFilter,\n private readonly _logger?: LDLogger,\n ) {}\n private _summarizers: Record<string, EventSummarizer> = {};\n\n summarizeEvent(event: InputEvent) {\n if (isFeature(event)) {\n const key = event.context.canonicalUnfilteredJson();\n if (!key) {\n if (event.context.valid) {\n // The context appeared valid, but it could not be hashed.\n // This is likely because of a cycle in the data.\n this._logger?.error('Unable to serialize context, likely the context contains a cycle.');\n }\n return;\n }\n\n let summarizer = this._summarizers[key];\n if (!summarizer) {\n this._summarizers[key] = new EventSummarizer(true, this._contextFilter);\n summarizer = this._summarizers[key];\n }\n\n summarizer.summarizeEvent(event);\n }\n }\n\n getSummaries(): SummarizedFlagsEvent[] {\n const summarizersToFlush = this._summarizers;\n this._summarizers = {};\n return Object.values(summarizersToFlush).map((summarizer) => summarizer.getSummary());\n }\n}\n","/**\n * The contents of this file are for event sampling. They are not used for\n * any purpose requiring cryptographic security.\n * */\n\nexport default function shouldSample(ratio: number) {\n const truncated = Math.trunc(ratio);\n // A radio of 1 means 1 in 1. So that will always sample. No need\n // to draw a random number.\n if (truncated === 1) {\n return true;\n }\n\n if (truncated === 0) {\n return false;\n }\n\n // Math.random() * truncated) would return 0, 1, ... (ratio - 1).\n // Checking for any number in the range will have approximately a 1 in X\n // chance. So we check for 0 as it is part of any range.\n return Math.floor(Math.random() * truncated) === 0;\n}\n","import { LDEvaluationReason, LDLogger } from '../../api';\nimport { LDDeliveryStatus, LDEventType } from '../../api/subsystem';\nimport LDContextDeduplicator from '../../api/subsystem/LDContextDeduplicator';\nimport LDEventProcessor from '../../api/subsystem/LDEventProcessor';\nimport AttributeReference from '../../AttributeReference';\nimport ContextFilter from '../../ContextFilter';\nimport { ClientContext } from '../../options';\nimport { LDHeaders } from '../../utils';\nimport { DiagnosticsManager } from '../diagnostics';\nimport EventSender from './EventSender';\nimport EventSummarizer from './EventSummarizer';\nimport { isFeature, isIdentify, isMigration } from './guards';\nimport InputEvent from './InputEvent';\nimport InputIdentifyEvent from './InputIdentifyEvent';\nimport InputMigrationEvent from './InputMigrationEvent';\nimport LDEventSummarizer, {\n LDMultiEventSummarizer,\n SummarizedFlagsEvent,\n} from './LDEventSummarizer';\nimport LDInvalidSDKKeyError from './LDInvalidSDKKeyError';\nimport MultiEventSummarizer from './MultiEventSummarizer';\nimport shouldSample from './sampling';\n\ntype FilteredContext = any;\n\n/**\n * Used for both identify and index.\n */\ninterface IdentifyOutputEvent {\n kind: 'identify' | 'index';\n creationDate: number;\n context: FilteredContext;\n samplingRatio?: number;\n}\n\ninterface CustomOutputEvent {\n kind: 'custom';\n creationDate: number;\n key: string;\n context: FilteredContext;\n data?: any;\n metricValue?: number;\n samplingRatio?: number;\n url?: string;\n}\n\ninterface FeatureOutputEvent {\n kind: 'feature' | 'debug';\n creationDate: number;\n key: string;\n value: any;\n default: any;\n prereqOf?: string;\n variation?: number;\n version?: number;\n reason?: LDEvaluationReason;\n context?: FilteredContext;\n contextKeys?: Record<string, string>;\n samplingRatio?: number;\n}\n\ninterface IndexInputEvent extends Omit<InputIdentifyEvent, 'kind'> {\n kind: 'index';\n}\n\ninterface ClickOutputEvent {\n kind: 'click';\n key: string;\n url: string;\n creationDate: number;\n contextKeys: Record<string, string>;\n selector: string;\n samplingRatio?: number;\n}\n\ninterface PageviewOutputEvent {\n kind: 'pageview';\n key: string;\n url: string;\n creationDate: number;\n contextKeys: Record<string, string>;\n samplingRatio?: number;\n}\n\n/**\n * The event processor doesn't need to know anything about the shape of the\n * diagnostic events.\n */\ntype DiagnosticEvent = any;\n\ninterface MigrationOutputEvent extends Omit<InputMigrationEvent, 'samplingRatio' | 'context'> {\n // Make the sampling ratio optional so we can omit it when it is one.\n samplingRatio?: number;\n // Context is optional because contextKeys is supported for backwards compatibility and may be provided instead of context.\n context?: FilteredContext;\n}\n\ntype OutputEvent =\n | IdentifyOutputEvent\n | CustomOutputEvent\n | FeatureOutputEvent\n | SummarizedFlagsEvent\n | DiagnosticEvent\n | MigrationOutputEvent;\n\nexport interface EventProcessorOptions {\n allAttributesPrivate: boolean;\n privateAttributes: string[];\n eventsCapacity: number;\n flushInterval: number;\n diagnosticRecordingInterval: number;\n}\n\nfunction isMultiEventSummarizer(summarizer: unknown): summarizer is LDMultiEventSummarizer {\n return (summarizer as LDMultiEventSummarizer).getSummaries !== undefined;\n}\n\nexport default class EventProcessor implements LDEventProcessor {\n private _eventSender: EventSender;\n private _summarizer: LDMultiEventSummarizer | LDEventSummarizer;\n private _queue: OutputEvent[] = [];\n private _lastKnownPastTime = 0;\n private _droppedEvents = 0;\n private _deduplicatedUsers = 0;\n private _exceededCapacity = false;\n private _eventsInLastBatch = 0;\n private _shutdown = false;\n private _capacity: number;\n private _logger?: LDLogger;\n private _contextFilter: ContextFilter;\n\n // Using any here, because setInterval handles are not the same\n // between node and web.\n private _diagnosticsTimer: any;\n private _flushTimer: any;\n private _flushUsersTimer: any = null;\n\n constructor(\n private readonly _config: EventProcessorOptions,\n clientContext: ClientContext,\n baseHeaders: LDHeaders,\n private readonly _contextDeduplicator?: LDContextDeduplicator,\n private readonly _diagnosticsManager?: DiagnosticsManager,\n start: boolean = true,\n summariesPerContext: boolean = false,\n ) {\n this._capacity = _config.eventsCapacity;\n this._logger = clientContext.basicConfiguration.logger;\n this._eventSender = new EventSender(clientContext, baseHeaders);\n\n this._contextFilter = new ContextFilter(\n _config.allAttributesPrivate,\n _config.privateAttributes.map((ref) => new AttributeReference(ref)),\n );\n\n if (summariesPerContext) {\n this._summarizer = new MultiEventSummarizer(this._contextFilter, this._logger);\n } else {\n this._summarizer = new EventSummarizer();\n }\n\n if (start) {\n this.start();\n }\n }\n\n start() {\n if (this._contextDeduplicator?.flushInterval !== undefined) {\n this._flushUsersTimer = setInterval(() => {\n this._contextDeduplicator?.flush();\n }, this._contextDeduplicator.flushInterval * 1000);\n }\n\n this._flushTimer = setInterval(async () => {\n try {\n await this.flush();\n } catch (e) {\n // Log errors and swallow them\n this._logger?.debug(`Flush failed: ${e}`);\n }\n }, this._config.flushInterval * 1000);\n\n if (this._diagnosticsManager) {\n const initEvent = this._diagnosticsManager!.createInitEvent();\n this._postDiagnosticEvent(initEvent);\n\n this._diagnosticsTimer = setInterval(() => {\n const statsEvent = this._diagnosticsManager!.createStatsEventAndReset(\n this._droppedEvents,\n this._deduplicatedUsers,\n this._eventsInLastBatch,\n );\n\n this._droppedEvents = 0;\n this._deduplicatedUsers = 0;\n\n this._postDiagnosticEvent(statsEvent);\n }, this._config.diagnosticRecordingInterval * 1000);\n }\n\n this._logger?.debug('Started EventProcessor.');\n }\n\n private _postDiagnosticEvent(event: DiagnosticEvent) {\n this._eventSender.sendEventData(LDEventType.DiagnosticEvent, event);\n }\n\n close() {\n clearInterval(this._flushTimer);\n if (this._flushUsersTimer) {\n clearInterval(this._flushUsersTimer);\n }\n if (this._diagnosticsTimer) {\n clearInterval(this._diagnosticsTimer);\n }\n }\n\n async flush(): Promise<void> {\n if (this._shutdown) {\n throw new LDInvalidSDKKeyError(\n 'Events cannot be posted because a permanent error has been encountered. ' +\n 'This is most likely an invalid SDK key. The specific error information ' +\n 'is logged independently.',\n );\n }\n\n const eventsToFlush = this._queue;\n this._queue = [];\n\n if (isMultiEventSummarizer(this._summarizer)) {\n const summaries = this._summarizer.getSummaries();\n\n summaries.forEach((summary) => {\n if (Object.keys(summary.features).length) {\n eventsToFlush.push(summary);\n }\n });\n } else {\n const summary = this._summarizer.getSummary();\n if (Object.keys(summary.features).length) {\n eventsToFlush.push(summary);\n }\n }\n\n if (!eventsToFlush.length) {\n return;\n }\n\n this._eventsInLastBatch = eventsToFlush.length;\n this._logger?.debug('Flushing %d events', eventsToFlush.length);\n await this._tryPostingEvents(eventsToFlush);\n }\n\n sendEvent(inputEvent: InputEvent) {\n if (this._shutdown) {\n return;\n }\n\n if (isMigration(inputEvent)) {\n // These conditions are not combined, because we always want to stop\n // processing at this point for a migration event. It cannot generate\n // an index event or debug event.\n if (shouldSample(inputEvent.samplingRatio)) {\n const migrationEvent: MigrationOutputEvent = {\n ...inputEvent,\n context: inputEvent.context ? this._contextFilter.filter(inputEvent.context) : undefined,\n };\n if (migrationEvent.samplingRatio === 1) {\n delete migrationEvent.samplingRatio;\n }\n this._enqueue(migrationEvent);\n }\n return;\n }\n\n this._summarizer.summarizeEvent(inputEvent);\n\n const isFeatureEvent = isFeature(inputEvent);\n\n const addFullEvent = (isFeatureEvent && inputEvent.trackEvents) || !isFeatureEvent;\n\n const addDebugEvent = this._shouldDebugEvent(inputEvent);\n\n const isIdentifyEvent = isIdentify(inputEvent);\n const shouldNotDeduplicate = this._contextDeduplicator?.processContext(inputEvent.context);\n\n // If there is no cache, then it will never be in the cache.\n if (!shouldNotDeduplicate) {\n if (!isIdentifyEvent) {\n this._deduplicatedUsers += 1;\n }\n }\n\n const addIndexEvent = shouldNotDeduplicate && !isIdentifyEvent;\n\n if (addIndexEvent) {\n this._enqueue(\n this._makeOutputEvent(\n {\n kind: 'index',\n creationDate: inputEvent.creationDate,\n context: inputEvent.context,\n samplingRatio: 1,\n },\n false,\n ),\n );\n }\n if (addFullEvent && shouldSample(inputEvent.samplingRatio)) {\n this._enqueue(this._makeOutputEvent(inputEvent, false));\n }\n if (addDebugEvent && shouldSample(inputEvent.samplingRatio)) {\n this._enqueue(this._makeOutputEvent(inputEvent, true));\n }\n }\n\n private _makeOutputEvent(event: InputEvent | IndexInputEvent, debug: boolean): OutputEvent {\n switch (event.kind) {\n case 'feature': {\n const out: FeatureOutputEvent = {\n kind: debug ? 'debug' : 'feature',\n creationDate: event.creationDate,\n context: this._contextFilter.filter(event.context, !debug),\n key: event.key,\n value: event.value,\n default: event.default,\n };\n if (event.samplingRatio !== 1) {\n out.samplingRatio = event.samplingRatio;\n }\n if (event.prereqOf) {\n out.prereqOf = event.prereqOf;\n }\n if (event.variation !== undefined) {\n out.variation = event.variation;\n }\n if (event.version !== undefined) {\n out.version = event.version;\n }\n if (event.reason) {\n out.reason = event.reason;\n }\n return out;\n }\n case 'index': // Intentional fallthrough.\n case 'identify': {\n const out: IdentifyOutputEvent = {\n kind: event.kind,\n creationDate: event.creationDate,\n context: this._contextFilter.filter(event.context),\n };\n if (event.samplingRatio !== 1) {\n out.samplingRatio = event.samplingRatio;\n }\n return out;\n }\n case 'custom': {\n const out: CustomOutputEvent = {\n kind: 'custom',\n creationDate: event.creationDate,\n key: event.key,\n context: this._contextFilter.filter(event.context),\n };\n\n if (event.samplingRatio !== 1) {\n out.samplingRatio = event.samplingRatio;\n }\n\n if (event.data !== undefined) {\n out.data = event.data;\n }\n if (event.metricValue !== undefined) {\n out.metricValue = event.metricValue;\n }\n\n if (event.url !== undefined) {\n out.url = event.url;\n }\n\n return out;\n }\n case 'click': {\n const out: ClickOutputEvent = {\n kind: 'click',\n creationDate: event.creationDate,\n contextKeys: event.context.kindsAndKeys,\n key: event.key,\n url: event.url,\n selector: event.selector,\n };\n return out;\n }\n case 'pageview': {\n const out: PageviewOutputEvent = {\n kind: 'pageview',\n creationDate: event.creationDate,\n contextKeys: event.context.kindsAndKeys,\n key: event.key,\n url: event.url,\n };\n return out;\n }\n default:\n // This would happen during the addition of a new event type to the SDK.\n return event;\n }\n }\n\n private _enqueue(event: OutputEvent) {\n if (this._queue.length < this._capacity) {\n this._queue.push(event);\n this._exceededCapacity = false;\n } else {\n if (!this._exceededCapacity) {\n this._exceededCapacity = true;\n this._logger?.warn(\n 'Exceeded event queue capacity. Increase capacity to avoid dropping events.',\n );\n }\n this._droppedEvents += 1;\n }\n }\n\n private _shouldDebugEvent(event: InputEvent) {\n return (\n isFeature(event) &&\n event.debugEventsUntilDate &&\n event.debugEventsUntilDate > this._lastKnownPastTime &&\n event.debugEventsUntilDate > Date.now()\n );\n }\n\n private async _tryPostingEvents(events: OutputEvent[] | OutputEvent): Promise<void> {\n const res = await this._eventSender.sendEventData(LDEventType.AnalyticsEvents, events);\n if (res.status === LDDeliveryStatus.FailedAndMustShutDown) {\n this._shutdown = true;\n }\n\n if (res.serverTime) {\n this._lastKnownPastTime = res.serverTime;\n }\n\n if (res.error) {\n throw res.error;\n }\n }\n}\n","import Context from '../../Context';\n\nexport default class InputCustomEvent {\n public readonly kind = 'custom';\n\n public readonly creationDate: number;\n\n constructor(\n public readonly context: Context,\n public readonly key: string,\n public readonly data?: any,\n public readonly metricValue?: number,\n // Currently custom events are not sampled, but this is here to make the handling\n // code more uniform.\n public readonly samplingRatio: number = 1,\n // Browser SDKs can include a URL for custom events.\n public readonly url?: string,\n ) {\n this.creationDate = Date.now();\n this.context = context;\n }\n}\n","import { LDEvaluationReason, LDFlagValue } from '../../api/data';\nimport Context from '../../Context';\n\nexport default class InputEvalEvent {\n public readonly kind = 'feature';\n\n public readonly creationDate: number;\n\n public readonly default: any;\n\n public readonly trackEvents?: boolean;\n\n public readonly debugEventsUntilDate?: number;\n\n public readonly prereqOf?: string;\n\n public readonly reason?: LDEvaluationReason;\n\n public readonly value: any;\n\n public readonly variation?: number;\n\n public readonly version?: number;\n\n public readonly excludeFromSummaries?: boolean;\n\n constructor(\n public readonly withReasons: boolean,\n public readonly context: Context,\n public readonly key: string,\n value: LDFlagValue,\n defValue: any, // default is a reserved keyword in this context.\n version?: number,\n variation?: number,\n trackEvents?: boolean,\n prereqOf?: string,\n reason?: LDEvaluationReason,\n debugEventsUntilDate?: number,\n excludeFromSummaries?: boolean,\n public readonly samplingRatio: number = 1,\n ) {\n this.creationDate = Date.now();\n this.value = value;\n this.default = defValue;\n\n if (version !== undefined) {\n this.version = version;\n }\n\n if (variation !== undefined) {\n this.variation = variation;\n }\n\n if (trackEvents !== undefined) {\n this.trackEvents = trackEvents;\n }\n\n if (prereqOf !== undefined) {\n this.prereqOf = prereqOf;\n }\n\n if (reason !== undefined) {\n this.reason = reason;\n }\n\n if (debugEventsUntilDate !== undefined) {\n this.debugEventsUntilDate = debugEventsUntilDate;\n }\n\n if (excludeFromSummaries !== undefined) {\n this.excludeFromSummaries = excludeFromSummaries;\n }\n }\n}\n","import Context from '../../Context';\n\nexport default class InputIdentifyEvent {\n public readonly kind = 'identify';\n\n public readonly creationDate: number;\n\n constructor(\n public readonly context: Context,\n public readonly samplingRatio: number = 1,\n ) {\n this.creationDate = Date.now();\n }\n}\n","import { LDEventProcessor } from '../../api/subsystem';\n\nexport default class NullEventProcessor implements LDEventProcessor {\n close() {}\n\n async flush(): Promise<void> {\n // empty comment to keep ts and eslint happy\n }\n\n sendEvent() {}\n}\n","import { LDEvaluationReason, LDFlagValue } from '../../api';\nimport Context from '../../Context';\nimport { InputCustomEvent, InputEvalEvent, InputIdentifyEvent } from '../events';\n\nexport type EvalEventArgs = {\n addExperimentData?: boolean;\n context: Context;\n debugEventsUntilDate?: number;\n defaultVal: any;\n excludeFromSummaries?: boolean;\n flagKey: string;\n prereqOfFlagKey?: string;\n reason?: LDEvaluationReason;\n samplingRatio?: number;\n trackEvents: boolean;\n value: LDFlagValue;\n variation?: number;\n version: number;\n};\n\nexport default class EventFactoryBase {\n constructor(private readonly _withReasons: boolean) {}\n\n evalEvent(e: EvalEventArgs): InputEvalEvent {\n return new InputEvalEvent(\n this._withReasons,\n e.context,\n e.flagKey,\n e.value,\n e.defaultVal,\n e.version,\n // Exclude null as a possibility.\n e.variation ?? undefined,\n e.trackEvents || e.addExperimentData,\n e.prereqOfFlagKey,\n this._withReasons || e.addExperimentData ? e.reason : undefined,\n e.debugEventsUntilDate,\n e.excludeFromSummaries,\n e.samplingRatio,\n );\n }\n\n unknownFlagEvent(key: string, defVal: LDFlagValue, context: Context) {\n return new InputEvalEvent(\n this._withReasons,\n context,\n key,\n defVal,\n defVal,\n // This isn't ideal, but the purpose of the factory is to at least\n // handle this situation.\n undefined, // version\n undefined, // variation index\n undefined, // track events\n undefined, // prereqOf\n undefined, // reason\n undefined, // debugEventsUntilDate\n undefined, // exclude from summaries\n undefined, // sampling ratio\n );\n }\n\n /* eslint-disable-next-line class-methods-use-this */\n identifyEvent(context: Context) {\n // Currently sampling for identify events is always 1.\n return new InputIdentifyEvent(context, 1);\n }\n\n /* eslint-disable-next-line class-methods-use-this */\n customEvent(\n key: string,\n context: Context,\n data?: any,\n metricValue?: number,\n samplingRatio: number = 1,\n ) {\n return new InputCustomEvent(\n context,\n key,\n data ?? undefined,\n metricValue ?? undefined,\n samplingRatio,\n );\n }\n}\n","import { PayloadProcessor } from './payloadProcessor';\nimport { Event } from './proto';\n\ninterface fdv1Payload {\n flags: { [name: string]: any };\n segments: { [name: string]: any };\n}\n\nconst PAYLOAD_ID = 'FDv1Fallback';\n\n/**\n * The FDv1PayloadAdaptor is a helper class that converts FDv1 payloads into events that the PayloadProcessor can understand.\n */\nexport interface FDv1PayloadAdaptor {\n /**\n * The PayloadProcessor that will be used to process the events.\n */\n readonly _processor: PayloadProcessor;\n\n /**\n * The selector that will be used to identify the payload.\n */\n _selector: string;\n\n /**\n * The method that will be used to set a selector for the payload that is\n * being processed.\n *\n * @remarks\n * This method probably shouldn't be used in most instances as FDv1 payloads\n * do not have the concept of a selector.\n *\n * @param selector - The selector to set for the payload.\n * @returns this FDv1PayloadAdaptor instance\n */\n useSelector: (selector: string) => FDv1PayloadAdaptor;\n\n /**\n * The method that will be used to process a full transfer changeset.\n *\n * @param data - The data to process.\n */\n processFullTransfer: (data: fdv1Payload) => void;\n}\n\nexport function fdv1PayloadAdaptor(processor: PayloadProcessor): FDv1PayloadAdaptor {\n return {\n _processor: processor,\n _selector: '',\n useSelector(selector: string): FDv1PayloadAdaptor {\n this._selector = selector;\n return this;\n },\n processFullTransfer(data) {\n const events: Array<Event> = [\n {\n event: 'server-intent',\n data: {\n payloads: [\n {\n id: PAYLOAD_ID,\n target: 1,\n intentCode: 'xfer-full',\n reason: 'payload-missing',\n },\n ],\n },\n },\n ];\n\n Object.entries(data?.flags || []).forEach(([key, flag]) => {\n events.push({\n event: 'put-object',\n data: {\n kind: 'flag',\n key,\n version: flag.version || 1,\n object: flag,\n },\n });\n });\n\n Object.entries(data?.segments || []).forEach(([key, segment]) => {\n events.push({\n event: 'put-object',\n data: {\n kind: 'segment',\n key,\n version: segment.version || 1,\n object: segment,\n },\n });\n });\n\n events.push({\n event: 'payload-transferred',\n data: {\n // IMPORTANT: the selector MUST be empty or \"live\" data synchronizers\n // will not work as it would try to resume from a bogus state.\n state: this._selector,\n version: 1,\n id: PAYLOAD_ID,\n },\n });\n\n this._processor.processEvents(events);\n },\n };\n}\n","/* eslint-disable no-underscore-dangle */\nimport { LDLogger } from '../../api';\nimport { DataSourceErrorKind } from '../../datasource';\nimport {\n DeleteObject,\n PayloadIntent,\n PayloadTransferred,\n PutObject,\n ServerIntentData,\n} from './proto';\n\n// Used to define object processing between deserialization and payload listener invocation. This can be\n// used provide object sanitization logic.\nexport interface ObjProcessors {\n [kind: string]: (object: any) => any;\n}\n\n// Represents a collection of events (one case where this is seen is in the polling response)\nexport interface FDv2EventsCollection {\n events: FDv2Event[];\n}\n\n// Represents a single event\nexport interface FDv2Event {\n event: string;\n data: any;\n}\n\n// Represents information for one keyed object.\nexport interface Update {\n kind: string;\n key: string;\n version: number;\n object?: any;\n deleted?: boolean;\n}\n\n// Represents a collection of updates from the FDv2 services. If basis is true, the set of updates represents the\n// complete state of the payload.\nexport interface Payload {\n id: string;\n version: number;\n state?: string;\n basis: boolean;\n updates: Update[];\n}\n\nexport type PayloadListener = (payload: Payload) => void;\n\n/**\n * A FDv2 PayloadProcessor can be used to parse payloads from a stream of FDv2 events. It will send payloads\n * to the PayloadListeners as the payloads are received. Invalid series of events may be dropped silently,\n * but the payload processor will continue to operate.\n */\nexport class PayloadProcessor {\n private _listeners: PayloadListener[] = [];\n\n private _tempId?: string = undefined;\n private _tempBasis: boolean = false;\n private _tempUpdates: Update[] = [];\n\n /**\n * Creates a PayloadProcessor\n *\n * @param _objProcessors defines object processors for each object kind.\n * @param _errorHandler that will be called with parsing errors as they are encountered\n * @param _logger for logging\n */\n constructor(\n private readonly _objProcessors: ObjProcessors,\n private readonly _errorHandler?: (errorKind: DataSourceErrorKind, message: string) => void,\n private readonly _logger?: LDLogger,\n ) {}\n\n addPayloadListener(listener: PayloadListener) {\n this._listeners.push(listener);\n }\n\n removePayloadListener(listener: PayloadListener) {\n const index = this._listeners.indexOf(listener, 0);\n if (index > -1) {\n this._listeners.splice(index, 1);\n }\n }\n\n /**\n * Gives the {@link PayloadProcessor} a series of events that it will statefully, incrementally process.\n * This may lead to listeners being invoked as necessary.\n * @param events to be processed (can be a single element)\n */\n processEvents(events: FDv2Event[]) {\n events.forEach((event) => {\n switch (event.event) {\n case 'server-intent': {\n this._processServerIntent(event.data);\n break;\n }\n case 'put-object': {\n this._processPutObject(event.data);\n break;\n }\n case 'delete-object': {\n this._processDeleteObject(event.data);\n break;\n }\n case 'payload-transferred': {\n this._processPayloadTransferred(event.data);\n break;\n }\n case 'goodbye': {\n this._processGoodbye(event.data);\n break;\n }\n case 'error': {\n this._processError(event.data);\n break;\n }\n default: {\n // no-op, unrecognized\n }\n }\n });\n }\n\n private _processObj(kind: string, jsonObj: any): any {\n return this._objProcessors[kind]?.(jsonObj);\n }\n\n private _processServerIntent = (data: ServerIntentData) => {\n // clear state in prep for handling data\n this._resetAll();\n\n // if there's no payloads, return\n if (!data.payloads.length) {\n return;\n }\n // at the time of writing this, it was agreed upon that SDKs could assume exactly 1 element in this list. In the future, a negotiation of protocol version will be required to remove this assumption.\n const payload = data.payloads[0];\n\n switch (payload?.intentCode) {\n case 'xfer-full':\n this._tempBasis = true;\n break;\n case 'xfer-changes':\n this._tempBasis = false;\n break;\n case 'none':\n this._tempBasis = false;\n this._processIntentNone(payload);\n break;\n default:\n // unrecognized intent code, return\n this._logger?.warn(`Unable to process intent code '${payload?.intentCode}'.`);\n return;\n }\n\n this._tempId = payload?.id;\n };\n\n private _processPutObject = (data: PutObject) => {\n // if the following properties haven't been provided by now, we should ignore the event\n if (\n !this._tempId || // server intent hasn't been received yet.\n !data.kind ||\n !data.key ||\n !data.version ||\n !data.object\n ) {\n return;\n }\n\n const obj = this._processObj(data.kind, data.object);\n if (!obj) {\n this._logger?.warn(`Unable to process object for kind: '${data.kind}'`);\n // ignore unrecognized kinds\n return;\n }\n\n this._tempUpdates.push({\n kind: data.kind,\n key: data.key,\n version: data.version,\n object: obj,\n // intentionally omit deleted for this put\n });\n };\n\n private _processDeleteObject = (data: DeleteObject) => {\n // if the following properties haven't been provided by now, we should ignore the event\n if (!this._tempId || !data.kind || !data.key || !data.version) {\n return;\n }\n\n this._tempUpdates.push({\n kind: data.kind,\n key: data.key,\n version: data.version,\n // intentionally omit object for this delete\n deleted: true,\n });\n };\n\n private _processIntentNone = (intent: PayloadIntent) => {\n // if the following properties aren't present ignore the event\n if (!intent.id || !intent.target) {\n return;\n }\n\n const payload: Payload = {\n id: intent.id,\n version: intent.target,\n basis: false, // intent none is always not a basis\n updates: [], // payload with no updates to hide the intent none concept from the consumer\n // note: state is absent here as that only appears in payload transferred events\n };\n\n this._listeners.forEach((it) => it(payload));\n this._resetAfterEmission();\n };\n\n private _processPayloadTransferred = (data: PayloadTransferred) => {\n // if the following properties haven't been provided by now, we should reset\n if (\n // server intent hasn't been received yet.\n !this._tempId ||\n // selector can be an empty string if we are using a file data initilizer\n data.state === null ||\n data.state === undefined ||\n !data.version\n ) {\n this._resetAll(); // a reset is best defensive action since payload transferred terminates a payload\n return;\n }\n\n const payload: Payload = {\n id: this._tempId!,\n version: data.version,\n state: data.state,\n basis: this._tempBasis,\n updates: this._tempUpdates,\n };\n\n this._listeners.forEach((it) => it(payload));\n this._resetAfterEmission();\n };\n\n private _processGoodbye = (data: any) => {\n this._logger?.info(\n `Goodbye was received from the LaunchDarkly connection with reason: ${data.reason}.`,\n );\n this._resetAll();\n };\n\n private _processError = (data: any) => {\n this._logger?.info(\n `An issue was encountered receiving updates for payload ${this._tempId} with reason: ${data.reason}.`,\n );\n this._resetAfterError();\n };\n\n private _resetAfterEmission() {\n this._tempBasis = false;\n this._tempUpdates = [];\n }\n\n private _resetAfterError() {\n this._tempUpdates = [];\n }\n\n private _resetAll() {\n this._tempId = undefined;\n this._tempBasis = false;\n this._tempUpdates = [];\n }\n}\n","/* eslint-disable no-underscore-dangle */\nimport { EventListener, EventName, LDLogger } from '../../api';\nimport { DataSourceErrorKind } from '../../datasource';\nimport { ObjProcessors, PayloadListener, PayloadProcessor } from './payloadProcessor';\n\n/**\n * Interface for an event stream. Only allows listening to events.\n */\nexport interface EventStream {\n addEventListener(type: EventName, listener: EventListener): void;\n}\n\n/**\n * A FDv2 PayloadStreamReader can be used to parse payloads from a stream of FDv2 events. See {@link PayloadProcessor}\n * for more details.\n */\nexport class PayloadStreamReader {\n private _payloadProcessor: PayloadProcessor;\n\n /**\n * Creates a PayloadStreamReader\n *\n * @param eventStream event stream of FDv2 events\n * @param _objProcessors defines object processors for each object kind.\n * @param _errorHandler that will be called with parsing errors as they are encountered\n * @param _logger for logging\n */\n constructor(\n eventStream: EventStream,\n _objProcessors: ObjProcessors,\n private readonly _errorHandler?: (errorKind: DataSourceErrorKind, message: string) => void,\n private readonly _logger?: LDLogger,\n ) {\n this._attachHandler(eventStream, 'server-intent');\n this._attachHandler(eventStream, 'put-object');\n this._attachHandler(eventStream, 'delete-object');\n this._attachHandler(eventStream, 'payload-transferred');\n this._attachHandler(eventStream, 'goodbye');\n this._attachHandler(eventStream, 'error');\n this._payloadProcessor = new PayloadProcessor(_objProcessors, _errorHandler, _logger);\n }\n\n addPayloadListener(listener: PayloadListener) {\n this._payloadProcessor.addPayloadListener(listener);\n }\n\n removePayloadListener(listener: PayloadListener) {\n this._payloadProcessor.removePayloadListener(listener);\n }\n\n private _attachHandler(stream: EventStream, eventName: string) {\n stream.addEventListener(eventName, async (event?: { data?: string }) => {\n if (event?.data) {\n this._logger?.debug(`Received ${eventName} event. Data is ${event.data}`);\n try {\n this._payloadProcessor.processEvents([\n { event: eventName, data: JSON.parse(event.data) },\n ]);\n } catch {\n this._logger?.error(\n `Stream received data that was unable to be processed in \"${eventName}\" message`,\n );\n this._logger?.debug(`Data follows: ${event.data}`);\n this._errorHandler?.(DataSourceErrorKind.InvalidData, 'Malformed data in EventStream.');\n }\n } else {\n this._errorHandler?.(DataSourceErrorKind.Unknown, 'Event from EventStream missing data.');\n }\n });\n }\n}\n","/**\n * Metadata used to initialize an LDFeatureStore.\n */\nexport interface InitMetadata {\n environmentId: string;\n}\n\n/**\n * Creates an InitMetadata object from initialization headers.\n *\n * @param initHeaders Initialization headers received when establishing\n * a streaming or polling connection to LD.\n * @returns InitMetadata object, or undefined if initHeaders is undefined\n * or missing the required header values.\n */\nexport function initMetadataFromHeaders(initHeaders?: {\n [key: string]: string;\n}): InitMetadata | undefined {\n if (initHeaders) {\n const envIdKey = Object.keys(initHeaders).find((key) => key.toLowerCase() === 'x-ld-envid');\n if (envIdKey) {\n return { environmentId: initHeaders[envIdKey] };\n }\n }\n return undefined;\n}\n","import { LDPluginBase } from '../../api/integrations/plugins';\nimport { LDLogger } from '../../api/logging/LDLogger';\n\nconst UNKNOWN_PLUGIN_NAME = 'unknown plugin';\n\nexport function safeGetName<TClient, THook>(\n logger: LDLogger,\n plugin: LDPluginBase<TClient, THook>,\n) {\n try {\n return plugin.getMetadata().name || UNKNOWN_PLUGIN_NAME;\n } catch {\n logger.error(`Exception thrown getting metadata for plugin. Unable to get plugin name.`);\n return UNKNOWN_PLUGIN_NAME;\n }\n}\n","import { LDPluginBase, LDPluginEnvironmentMetadata } from '../../api/integrations/plugins';\nimport { LDLogger } from '../../api/logging/LDLogger';\nimport { safeGetName } from './safeGetName';\n\nexport function safeGetHooks<TClient, THook>(\n logger: LDLogger,\n environmentMetadata: LDPluginEnvironmentMetadata,\n plugins: LDPluginBase<TClient, THook>[],\n): THook[] {\n const hooks: THook[] = [];\n plugins.forEach((plugin) => {\n try {\n const pluginHooks = plugin.getHooks?.(environmentMetadata);\n if (pluginHooks === undefined) {\n logger.error(`Plugin ${safeGetName(logger, plugin)} returned undefined from getHooks.`);\n } else if (pluginHooks && pluginHooks.length > 0) {\n hooks.push(...pluginHooks);\n }\n } catch (error) {\n logger.error(\n `Exception thrown getting hooks for plugin ${safeGetName(logger, plugin)}. Unable to get hooks.`,\n );\n }\n });\n return hooks;\n}\n","import { LDPluginBase, LDPluginEnvironmentMetadata } from '../../api/integrations/plugins';\nimport { LDLogger } from '../../api/logging/LDLogger';\nimport { safeGetName } from './safeGetName';\n\nexport function safeRegisterPlugins<TClient, THook>(\n logger: LDLogger,\n environmentMetadata: LDPluginEnvironmentMetadata,\n client: TClient,\n plugins: LDPluginBase<TClient, THook>[],\n): void {\n plugins.forEach((plugin) => {\n try {\n plugin.register(client, environmentMetadata);\n } catch (error) {\n logger.error(`Exception thrown registering plugin ${safeGetName(logger, plugin)}.`);\n }\n });\n}\n","import DataSourceStatusErrorInfo from './DataSourceStatusErrorInfo';\n\nexport enum DataSourceState {\n Initializing = 'INITIALIZING',\n Valid = 'VALID',\n Interrupted = 'INTERRUPTED',\n SetOffline = 'SET_OFFLINE',\n Closed = 'CLOSED',\n // TODO: SDK-702 - Implement network availability behaviors\n // NetworkUnavailable,\n}\n\nexport default interface DataSourceStatus {\n /**\n * An enumerated value representing the overall current state of the data source.\n */\n readonly state: DataSourceState;\n\n /**\n * The UNIX epoch timestamp in milliseconds that the value of State most recently changed.\n *\n * The meaning of this depends on the current state:\n * For {@link DataSourceState.Initializing}, it is the time that the datasource started\n * attempting to retrieve data.\n *\n * For {@link DataSourceState.Valid}, it is the time that the data source most\n * recently entered a valid state, after previously having been\n * {@link DataSourceStatus.Initializing} or an invalid state such as\n * {@link DataSourceState.Interrupted}.\n *\n * - For {@link DataSourceState.interrupted}, it is the time that the data source\n * most recently entered an error state, after previously having been\n * {@link DataSourceState.valid}.\n *\n * For {@link DataSourceState.Closed}, it is the time that the data source\n * encountered an unrecoverable error or that the datasource was explicitly closed.\n */\n readonly stateSince: number;\n\n /**\n * The last error encountered. May be absent after application restart.\n */\n readonly lastError?: DataSourceStatusErrorInfo;\n}\n","// eslint-disable-next-line max-classes-per-file\nimport {\n Encoding,\n getPollingUri,\n HttpErrorResponse,\n LDHeaders,\n Requests,\n ServiceEndpoints,\n} from '@launchdarkly/js-sdk-common';\n\nimport { DataSourcePaths } from './DataSourceConfig';\n\nfunction isOk(status: number) {\n return status >= 200 && status <= 299;\n}\n\nexport class LDRequestError extends Error implements HttpErrorResponse {\n public status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.status = status;\n this.name = 'LaunchDarklyRequestError';\n }\n}\n\n/**\n * Note: The requestor is implemented independently from polling such that it can be used to\n * make a one-off request.\n */\nexport default class Requestor {\n constructor(\n private _requests: Requests,\n private readonly _uri: string,\n private readonly _headers: { [key: string]: string },\n private readonly _method: string,\n private readonly _body?: string,\n ) {}\n\n async requestPayload(): Promise<string> {\n let status: number | undefined;\n try {\n const res = await this._requests.fetch(this._uri, {\n method: this._method,\n headers: this._headers,\n body: this._body,\n });\n if (isOk(res.status)) {\n return await res.text();\n }\n // Assigning so it can be thrown after the try/catch.\n status = res.status;\n } catch (err: any) {\n throw new LDRequestError(err?.message);\n }\n throw new LDRequestError(`Unexpected status code: ${status}`, status);\n }\n}\n\nexport function makeRequestor(\n plainContextString: string,\n serviceEndpoints: ServiceEndpoints,\n paths: DataSourcePaths,\n requests: Requests,\n encoding: Encoding,\n baseHeaders?: LDHeaders,\n baseQueryParams?: { key: string; value: string }[],\n withReasons?: boolean,\n useReport?: boolean,\n secureModeHash?: string,\n) {\n let body;\n let method = 'GET';\n const headers: { [key: string]: string } = { ...baseHeaders };\n\n if (useReport) {\n method = 'REPORT';\n headers['content-type'] = 'application/json';\n body = plainContextString; // context is in body for REPORT\n }\n\n const path = useReport\n ? paths.pathReport(encoding, plainContextString)\n : paths.pathGet(encoding, plainContextString);\n\n const parameters: { key: string; value: string }[] = [...(baseQueryParams ?? [])];\n if (withReasons) {\n parameters.push({ key: 'withReasons', value: 'true' });\n }\n if (secureModeHash) {\n parameters.push({ key: 'h', value: secureModeHash });\n }\n\n const uri = getPollingUri(serviceEndpoints, path, parameters);\n return new Requestor(requests, uri, headers, method, body);\n}\n","import { LDLogger } from '@launchdarkly/js-sdk-common';\n\n/**\n * Represents a task that has been shed from the queue.\n * This task will never be executed.\n */\nexport interface ShedTask {\n status: 'shed';\n}\n\n/**\n * Represents a task that has been ran to completion.\n */\nexport interface CompletedTask<TTaskResult> {\n status: 'complete';\n result: TTaskResult;\n}\n\n/**\n * Represents a task that has errored.\n */\nexport interface ErroredTask {\n status: 'error';\n error: Error;\n}\n\n/**\n * Represents the result of a task.\n */\nexport type TaskResult<TTaskResult> = CompletedTask<TTaskResult> | ErroredTask | ShedTask;\n\n/**\n * Represents a pending task. This encapsulates the async function that needs to be executed as well as a promise that represents its state.\n * The promise is not directly the promise associated with the async function, because we will not execute the async function until some point in the future, if at all.\n * */\ninterface PendingTask<TTaskResult> {\n sheddable: boolean;\n execute: () => void;\n shed: () => void;\n promise: Promise<TaskResult<TTaskResult>>;\n}\n\nexport interface Task<TTaskResult, TBeforeResult> {\n /**\n * Method ran before the task is executed or shed.\n */\n before?: () => Promise<TBeforeResult>;\n\n /**\n * Execute the task. This is not ran if the task is shed.\n * @returns The result of the task.\n */\n\n execute: (beforeResult?: TBeforeResult) => Promise<TTaskResult>;\n\n /**\n * Method ran after the task is executed or shed.\n * @param result The result of the task.\n */\n after?: (result: TaskResult<TTaskResult>, beforeResult?: TBeforeResult) => void;\n}\n\nconst duplicateExecutionError = new Error(\n 'Task has already been executed or shed. This is likely an implementation error. The task will not be executed again.',\n);\n\n/**\n * Creates a pending task.\n * @param task The async function to execute.\n * @param sheddable Whether the task can be shed from the queue.\n * @returns A pending task.\n */\nfunction makePending<TTaskResult, TBeforeResult = undefined>(\n task: Task<TTaskResult, TBeforeResult>,\n _logger?: LDLogger,\n sheddable: boolean = false,\n): PendingTask<TTaskResult> {\n let resolveTask: (value: TaskResult<TTaskResult>, beforeResult?: TBeforeResult) => void;\n\n const promise = new Promise<TaskResult<TTaskResult>>((resolve) => {\n resolveTask = (result, beforeResult) => {\n try {\n task.after?.(result, beforeResult);\n } catch (error) {\n _logger?.error(`Error in after callback: ${error}`);\n }\n resolve(result);\n };\n });\n\n const beforePromise = task.before ? task.before() : Promise.resolve(undefined);\n\n let executedOrShed = false;\n return {\n execute: () => {\n if (executedOrShed) {\n // This should never happen. If it does, then it represents an implementation error in the SDK.\n _logger?.error(duplicateExecutionError);\n }\n executedOrShed = true;\n\n beforePromise\n .then((beforeResult) => {\n task\n .execute(beforeResult)\n .then((result) => resolveTask({ status: 'complete', result }, beforeResult))\n .catch((error) => resolveTask({ status: 'error', error }, beforeResult));\n })\n .catch((error) => {\n _logger?.error(error);\n resolveTask({ status: 'error', error }, undefined);\n });\n },\n shed: () => {\n if (executedOrShed) {\n // This should never happen. If it does, then it represents an implementation error in the SDK.\n _logger?.error(duplicateExecutionError);\n }\n executedOrShed = true;\n beforePromise.then((beforeResult) => {\n resolveTask({ status: 'shed' }, beforeResult);\n });\n },\n promise,\n sheddable,\n };\n}\n\n/**\n * An asynchronous task queue with the ability to replace pending tasks.\n *\n * This is useful when you have asynchronous operations which much execute in order, and for cases where intermediate\n * operations can be discarded.\n *\n * For instance, the SDK can only have one active context at a time, if you request identification of many contexts,\n * then the ultimate state will be based on the last request. The intermediate identifies can be discarded.\n *\n * This queue will always begin execution of the first item added to the queue, at that point the item itself is not\n * queued, but active. If another request is made while that item is still active, then it is added to the queue.\n * A third request would then replace the second request if the second request had not yet become active, and it was\n * sheddable.\n *\n * Once a task is active the queue will complete it. It doesn't cancel tasks that it has started, but it can shed tasks\n * that have not started.\n *\n * TTaskResult Is the return type of the task to be executed. Tasks accept no parameters. So if you need parameters\n * you should use a lambda to capture them.\n *\n * Exceptions from tasks are always handled and the execute method will never reject a promise.\n *\n * Queue management should be done synchronously. There should not be asynchronous operations between checking the queue\n * and acting on the results of said check.\n */\nexport function createAsyncTaskQueue<TTaskResult>(logger?: LDLogger) {\n let activeTask: Promise<TaskResult<TTaskResult>> | undefined;\n const queue: PendingTask<TTaskResult>[] = [];\n\n function checkPending() {\n // There is an existing active task, so we don't need to do anything.\n if (activeTask) {\n return;\n }\n\n // There are pending tasks, so we need to execute the next one.\n if (queue.length > 0) {\n const nextTask = queue.shift()!;\n\n activeTask = nextTask.promise.finally(() => {\n activeTask = undefined;\n checkPending();\n });\n\n nextTask.execute();\n }\n }\n\n return {\n /**\n * Execute a task using the queue.\n *\n * @param task The async function to execute.\n * @param sheddable Whether the task can be shed from the queue.\n * @returns A promise that resolves to the result of the task.\n */\n execute<TBeforeResult>(\n task: Task<TTaskResult, TBeforeResult>,\n sheddable: boolean = false,\n ): Promise<TaskResult<TTaskResult>> {\n const pending = makePending(task, logger, sheddable);\n\n if (!activeTask) {\n activeTask = pending.promise.finally(() => {\n activeTask = undefined;\n checkPending();\n });\n pending.execute();\n } else {\n // If the last pending task is sheddable, we need to shed it before adding the new task.\n if (queue[queue.length - 1]?.sheddable) {\n queue.pop()?.shed();\n }\n queue.push(pending);\n }\n\n return pending.promise;\n },\n\n /**\n * Returns the number of pending tasks in the queue.\n * Intended for testing purposes only.\n *\n * @internal\n * @returns The number of pending tasks in the queue.\n */\n pendingCount(): number {\n return queue.length;\n },\n };\n}\n","// eslint-disable-next-line max-classes-per-file\nimport { TypeValidator, TypeValidators } from '@launchdarkly/js-sdk-common';\n\nimport { type LDOptions } from '../api';\n\nconst validators: Record<keyof LDOptions, TypeValidator> = {\n logger: TypeValidators.Object,\n maxCachedContexts: TypeValidators.numberWithMin(0),\n\n baseUri: TypeValidators.String,\n streamUri: TypeValidators.String,\n eventsUri: TypeValidators.String,\n\n capacity: TypeValidators.numberWithMin(1),\n diagnosticRecordingInterval: TypeValidators.numberWithMin(2),\n flushInterval: TypeValidators.numberWithMin(2),\n streamInitialReconnectDelay: TypeValidators.numberWithMin(0),\n\n allAttributesPrivate: TypeValidators.Boolean,\n debug: TypeValidators.Boolean,\n diagnosticOptOut: TypeValidators.Boolean,\n withReasons: TypeValidators.Boolean,\n sendEvents: TypeValidators.Boolean,\n\n pollInterval: TypeValidators.numberWithMin(30),\n\n useReport: TypeValidators.Boolean,\n\n privateAttributes: TypeValidators.StringArray,\n\n applicationInfo: TypeValidators.Object,\n wrapperName: TypeValidators.String,\n wrapperVersion: TypeValidators.String,\n payloadFilterKey: TypeValidators.stringMatchingRegex(/^[a-zA-Z0-9](\\w|\\.|-)*$/),\n hooks: TypeValidators.createTypeArray('Hook[]', {}),\n inspectors: TypeValidators.createTypeArray('LDInspection', {}),\n};\n\nexport default validators;\n","import {\n ApplicationTags,\n createSafeLogger,\n internal,\n LDFlagSet,\n LDLogger,\n LDPluginEnvironmentMetadata,\n NumberWithMinimum,\n OptionMessages,\n SafeLogger,\n ServiceEndpoints,\n TypeValidators,\n} from '@launchdarkly/js-sdk-common';\n\nimport { Hook, type LDOptions } from '../api';\nimport { LDInspection } from '../api/LDInspection';\nimport validators from './validators';\n\nconst DEFAULT_POLLING_INTERVAL: number = 60 * 5;\n\nexport interface LDClientInternalOptions extends internal.LDInternalOptions {\n trackEventModifier?: (event: internal.InputCustomEvent) => internal.InputCustomEvent;\n getImplementationHooks: (environmentMetadata: LDPluginEnvironmentMetadata) => Hook[];\n credentialType: 'clientSideId' | 'mobileKey';\n}\n\nexport interface Configuration {\n readonly logger: LDLogger;\n readonly maxCachedContexts: number;\n readonly capacity: number;\n readonly diagnosticRecordingInterval: number;\n readonly flushInterval: number;\n readonly streamInitialReconnectDelay: number;\n readonly allAttributesPrivate: boolean;\n readonly debug: boolean;\n readonly diagnosticOptOut: boolean;\n readonly sendEvents: boolean;\n readonly sendLDHeaders: boolean;\n readonly useReport: boolean;\n readonly withReasons: boolean;\n readonly privateAttributes: string[];\n readonly tags: ApplicationTags;\n readonly applicationInfo?: {\n id?: string;\n version?: string;\n name?: string;\n versionName?: string;\n };\n readonly bootstrap?: LDFlagSet;\n readonly requestHeaderTransform?: (headers: Map<string, string>) => Map<string, string>;\n readonly stream?: boolean;\n readonly hash?: string;\n readonly wrapperName?: string;\n readonly wrapperVersion?: string;\n readonly serviceEndpoints: ServiceEndpoints;\n readonly pollInterval: number;\n readonly userAgentHeaderName: 'user-agent' | 'x-launchdarkly-user-agent';\n readonly trackEventModifier: (event: internal.InputCustomEvent) => internal.InputCustomEvent;\n readonly hooks: Hook[];\n readonly inspectors: LDInspection[];\n readonly credentialType: 'clientSideId' | 'mobileKey';\n readonly getImplementationHooks: (environmentMetadata: LDPluginEnvironmentMetadata) => Hook[];\n}\n\nconst DEFAULT_POLLING: string = 'https://clientsdk.launchdarkly.com';\nconst DEFAULT_STREAM: string = 'https://clientstream.launchdarkly.com';\n\nexport { DEFAULT_POLLING, DEFAULT_STREAM };\n\nfunction ensureSafeLogger(logger?: LDLogger): LDLogger {\n if (logger instanceof SafeLogger) {\n return logger;\n }\n // Even if logger is not defined this will produce a valid logger.\n return createSafeLogger(logger);\n}\n\nexport default class ConfigurationImpl implements Configuration {\n public readonly logger: LDLogger = createSafeLogger();\n\n // Naming conventions is not followed for these lines because the config validation\n // accesses members based on the keys of the options. (sdk-763)\n // eslint-disable-next-line @typescript-eslint/naming-convention\n private readonly baseUri = DEFAULT_POLLING;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n private readonly eventsUri = ServiceEndpoints.DEFAULT_EVENTS;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n private readonly streamUri = DEFAULT_STREAM;\n\n public readonly maxCachedContexts = 5;\n\n public readonly capacity = 100;\n public readonly diagnosticRecordingInterval = 900;\n public readonly flushInterval = 30;\n public readonly streamInitialReconnectDelay = 1;\n\n public readonly allAttributesPrivate: boolean = false;\n public readonly debug: boolean = false;\n public readonly diagnosticOptOut: boolean = false;\n public readonly sendEvents: boolean = true;\n public readonly sendLDHeaders: boolean = true;\n\n public readonly useReport: boolean = false;\n public readonly withReasons: boolean = false;\n\n public readonly privateAttributes: string[] = [];\n\n public readonly tags: ApplicationTags;\n public readonly applicationInfo?: {\n id?: string;\n version?: string;\n name?: string;\n versionName?: string;\n };\n public readonly bootstrap?: LDFlagSet;\n\n // TODO: implement requestHeaderTransform\n public readonly requestHeaderTransform?: (headers: Map<string, string>) => Map<string, string>;\n public readonly stream?: boolean;\n public readonly hash?: string;\n public readonly wrapperName?: string;\n public readonly wrapperVersion?: string;\n\n public readonly serviceEndpoints: ServiceEndpoints;\n\n public readonly pollInterval: number = DEFAULT_POLLING_INTERVAL;\n\n public readonly userAgentHeaderName: 'user-agent' | 'x-launchdarkly-user-agent';\n\n public readonly hooks: Hook[] = [];\n\n public readonly inspectors: LDInspection[] = [];\n\n public readonly trackEventModifier: (\n event: internal.InputCustomEvent,\n ) => internal.InputCustomEvent;\n\n public readonly credentialType: 'clientSideId' | 'mobileKey';\n public readonly getImplementationHooks: (\n environmentMetadata: LDPluginEnvironmentMetadata,\n ) => Hook[];\n\n // Allow indexing Configuration by a string\n [index: string]: any;\n\n constructor(\n pristineOptions: LDOptions = {},\n internalOptions: LDClientInternalOptions = {\n getImplementationHooks: () => [],\n credentialType: 'mobileKey',\n },\n ) {\n this.logger = ensureSafeLogger(pristineOptions.logger);\n const errors = this._validateTypesAndNames(pristineOptions);\n errors.forEach((e: string) => this.logger.warn(e));\n\n this.serviceEndpoints = new ServiceEndpoints(\n this.streamUri,\n this.baseUri,\n this.eventsUri,\n internalOptions.analyticsEventPath,\n internalOptions.diagnosticEventPath,\n internalOptions.includeAuthorizationHeader,\n pristineOptions.payloadFilterKey,\n );\n this.useReport = pristineOptions.useReport ?? false;\n\n this.tags = new ApplicationTags({ application: this.applicationInfo, logger: this.logger });\n this.userAgentHeaderName = internalOptions.userAgentHeaderName ?? 'user-agent';\n this.trackEventModifier = internalOptions.trackEventModifier ?? ((event) => event);\n\n this.credentialType = internalOptions.credentialType;\n this.getImplementationHooks = internalOptions.getImplementationHooks;\n }\n\n private _validateTypesAndNames(pristineOptions: LDOptions): string[] {\n const errors: string[] = [];\n\n Object.entries(pristineOptions).forEach(([k, v]) => {\n const validator = validators[k as keyof LDOptions];\n\n if (validator) {\n if (!validator.is(v)) {\n const validatorType = validator.getType();\n\n if (validatorType === 'boolean') {\n errors.push(OptionMessages.wrongOptionTypeBoolean(k, typeof v));\n this[k] = !!v;\n } else if (validatorType === 'boolean | undefined | null') {\n errors.push(OptionMessages.wrongOptionTypeBoolean(k, typeof v));\n\n if (typeof v !== 'boolean' && typeof v !== 'undefined' && v !== null) {\n this[k] = !!v;\n }\n } else if (validator instanceof NumberWithMinimum && TypeValidators.Number.is(v)) {\n const { min } = validator as NumberWithMinimum;\n errors.push(OptionMessages.optionBelowMinimum(k, v, min));\n this[k] = min;\n } else {\n errors.push(OptionMessages.wrongOptionType(k, validator.getType(), typeof v));\n }\n } else if (k === 'logger') {\n // Logger already assigned.\n } else {\n // if an option is explicitly null, coerce to undefined\n this[k] = v ?? undefined;\n }\n } else {\n errors.push(OptionMessages.unknownOption(k));\n }\n });\n\n return errors;\n }\n}\n","import { Hasher } from '@launchdarkly/js-sdk-common';\n\nexport default async function digest(hasher: Hasher, encoding: string): Promise<string> {\n if (hasher.digest) {\n return hasher.digest(encoding);\n }\n if (hasher.asyncDigest) {\n return hasher.asyncDigest(encoding);\n }\n // This represents an error in platform implementation.\n throw new Error('Platform must implement digest or asyncDigest');\n}\n","import { Platform } from '@launchdarkly/js-sdk-common';\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport { namespaceForGeneratedContextKey } from './namespaceUtils';\n\n/**\n * This function will retrieve a previously generated key for the given {@link storageKey} if it\n * exists or generate and store one on the fly if it does not already exist.\n * @param storageKey keyed storage location where the generated key should live. See {@link namespaceForGeneratedContextKey}\n * for related exmaples of generating a storage key and usage.\n * @param platform crypto and storage implementations for necessary operations\n * @returns the generated key\n */\nexport const getOrGenerateKey = async (storageKey: string, { crypto, storage }: Platform) => {\n let generatedKey = await storage?.get(storageKey);\n\n if (!generatedKey) {\n generatedKey = crypto.randomUUID();\n await storage?.set(storageKey, generatedKey);\n }\n\n return generatedKey;\n};\n","import { Context, Crypto } from '@launchdarkly/js-sdk-common';\n\nimport digest from '../crypto/digest';\n\nexport type Namespace = 'LaunchDarkly' | 'AnonymousKeys' | 'ContextKeys' | 'ContextIndex';\n\n/**\n * Hashes the input and encodes it as base64\n */\nfunction hashAndBase64Encode(crypto: Crypto): (input: string) => Promise<string> {\n return async (input) => digest(crypto.createHash('sha256').update(input), 'base64');\n}\n\nconst noop = async (input: string) => input; // no-op transform\n\nexport async function concatNamespacesAndValues(\n parts: { value: Namespace | string; transform: (value: string) => Promise<string> }[],\n): Promise<string> {\n const processedParts = await Promise.all(parts.map((part) => part.transform(part.value))); // use the transform from each part to transform the value\n return processedParts.join('_');\n}\n\nexport async function namespaceForEnvironment(crypto: Crypto, sdkKey: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: 'LaunchDarkly', transform: noop },\n { value: sdkKey, transform: hashAndBase64Encode(crypto) }, // hash sdk key and encode it\n ]);\n}\n\n/**\n * @deprecated prefer {@link namespaceForGeneratedContextKey}. At one time we only generated keys for\n * anonymous contexts and they were namespaced in LaunchDarkly_AnonymousKeys. Eventually we started\n * generating context keys for non-anonymous contexts such as for the Auto Environment Attributes\n * feature and those were namespaced in LaunchDarkly_ContextKeys. This function can be removed\n * when the data under the LaunchDarkly_AnonymousKeys namespace is merged with data under the\n * LaunchDarkly_ContextKeys namespace.\n */\nexport async function namespaceForAnonymousGeneratedContextKey(kind: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: 'LaunchDarkly', transform: noop },\n { value: 'AnonymousKeys', transform: noop },\n { value: kind, transform: noop }, // existing SDKs are not hashing or encoding this kind, though they should have\n ]);\n}\n\nexport async function namespaceForGeneratedContextKey(kind: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: 'LaunchDarkly', transform: noop },\n { value: 'ContextKeys', transform: noop },\n { value: kind, transform: noop }, // existing SDKs are not hashing or encoding this kind, though they should have\n ]);\n}\n\nexport async function namespaceForContextIndex(environmentNamespace: string): Promise<string> {\n return concatNamespacesAndValues([\n { value: environmentNamespace, transform: noop },\n { value: 'ContextIndex', transform: noop },\n ]);\n}\n\nexport async function namespaceForContextData(\n crypto: Crypto,\n environmentNamespace: string,\n context: Context,\n): Promise<string> {\n return concatNamespacesAndValues([\n { value: environmentNamespace, transform: noop }, // use existing namespace as is, don't transform\n { value: context.canonicalKey, transform: hashAndBase64Encode(crypto) }, // hash and encode canonical key\n ]);\n}\n","/* eslint-disable @typescript-eslint/naming-convention */\nimport {\n deepCompact,\n internal,\n LDApplication,\n LDContext,\n LDDevice,\n LDMultiKindContext,\n LDSingleKindContext,\n LDUser,\n Platform,\n} from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\nimport digest from '../crypto/digest';\nimport { getOrGenerateKey } from '../storage/getOrGenerateKey';\nimport { namespaceForGeneratedContextKey } from '../storage/namespaceUtils';\n\nconst { isLegacyUser, isSingleKind, isMultiKind } = internal;\nconst defaultAutoEnvSchemaVersion = '1.0';\n\nexport const toMulti = (c: LDSingleKindContext) => {\n const { kind, ...contextCommon } = c;\n\n return {\n kind: 'multi',\n [kind]: contextCommon,\n };\n};\n\n/**\n * Clones the LDApplication object and populates the key, envAttributesVersion, id and version fields.\n *\n * @param crypto\n * @param info\n * @param applicationInfo\n * @param config\n * @return An LDApplication object with populated key, envAttributesVersion, id and version.\n */\nexport const addApplicationInfo = async (\n { crypto, info }: Platform,\n { applicationInfo }: Configuration,\n): Promise<LDApplication | undefined> => {\n const { ld_application } = info.platformData();\n let app = deepCompact<LDApplication>(ld_application) ?? ({} as LDApplication);\n const id = applicationInfo?.id || app?.id;\n\n if (id) {\n const version = applicationInfo?.version || app?.version;\n const name = applicationInfo?.name || app?.name;\n const versionName = applicationInfo?.versionName || app?.versionName;\n\n app = {\n ...app,\n id,\n // only add props if they are defined\n ...(version ? { version } : {}),\n ...(name ? { name } : {}),\n ...(versionName ? { versionName } : {}),\n };\n\n app.key = await digest(crypto.createHash('sha256').update(id), 'base64');\n app.envAttributesVersion = app.envAttributesVersion || defaultAutoEnvSchemaVersion;\n\n return app;\n }\n\n return undefined;\n};\n\n/**\n * Clones the LDDevice object and populates the key and envAttributesVersion field.\n *\n * @param platform\n * @return An LDDevice object with populated key and envAttributesVersion.\n */\nexport const addDeviceInfo = async (platform: Platform) => {\n const { ld_device, os } = platform.info.platformData();\n const device = deepCompact<LDDevice>(ld_device) ?? ({} as LDDevice);\n\n const name = os?.name || device.os?.name;\n const version = os?.version || device.os?.version;\n const family = device.os?.family;\n\n // only add device.os if there's data\n if (name || version || family) {\n device.os = {\n // only add props if they are defined\n ...(name ? { name } : {}),\n ...(version ? { version } : {}),\n ...(family ? { family } : {}),\n };\n }\n\n // Check if device has any meaningful data before we return it.\n if (Object.keys(device).filter((k) => k !== 'key' && k !== 'envAttributesVersion').length) {\n const ldDeviceNamespace = await namespaceForGeneratedContextKey('ld_device');\n device.key = await getOrGenerateKey(ldDeviceNamespace, platform);\n device.envAttributesVersion = device.envAttributesVersion || defaultAutoEnvSchemaVersion;\n return device;\n }\n\n return undefined;\n};\n\nexport const addAutoEnv = async (\n context: LDContext,\n platform: Platform,\n config: Configuration,\n): Promise<LDContext> => {\n // LDUser is not supported for auto env reporting\n if (isLegacyUser(context)) {\n return context as LDUser;\n }\n\n let ld_application: LDApplication | undefined;\n let ld_device: LDDevice | undefined;\n\n // Check if customer contexts exist. Only override if they are not provided.\n if (\n (isSingleKind(context) && context.kind !== 'ld_application') ||\n (isMultiKind(context) && !context.ld_application)\n ) {\n ld_application = await addApplicationInfo(platform, config);\n } else {\n config.logger.warn(\n 'Not adding ld_application environment attributes because it already exists.',\n );\n }\n\n if (\n (isSingleKind(context) && context.kind !== 'ld_device') ||\n (isMultiKind(context) && !context.ld_device)\n ) {\n ld_device = await addDeviceInfo(platform);\n } else {\n config.logger.warn('Not adding ld_device environment attributes because it already exists.');\n }\n\n // Unable to automatically add environment attributes for kind: {}. {} already exists.\n\n if (ld_application || ld_device) {\n const multi = isSingleKind(context) ? toMulti(context) : context;\n\n return {\n ...multi,\n ...(ld_application ? { ld_application } : {}),\n ...(ld_device ? { ld_device } : {}),\n } as LDMultiKindContext;\n }\n\n return context;\n};\n","import { Context, LDContext } from '@launchdarkly/js-sdk-common';\n\n/**\n * ActiveContextTracker is an internal class that helps tracks the current active context\n * used by the client.\n */\nexport interface ActiveContextTracker {\n /**\n * Set the active context and unwrapped context. This will only be called when the passed in context\n * is checked and valid.\n *\n * @param unwrappedContext - The unwrapped context, which is the context as it was passed in to the SDK.\n * @param context - The active context, which is the context as it was checked and validated.\n */\n set(unwrappedContext: LDContext, context: Context): void;\n\n /**\n * Get the active context.\n *\n * @returns The active context or undefined if it has not been set.\n */\n getContext(): Context | undefined;\n\n /**\n * Get the unwrapped context.\n *\n * @returns The unwrapped context or undefined if it has not been set.\n */\n getUnwrappedContext(): LDContext | undefined;\n\n /**\n * Create a new identification promise. To allow other parts of the SDK to track the identification process.\n */\n newIdentificationPromise(): {\n identifyPromise: Promise<void>;\n identifyResolve: () => void;\n identifyReject: (err: Error) => void;\n };\n\n /**\n * Check if the active context is set. Regardless of whether it is valid or not.\n *\n * @returns True if the active context is set, false otherwise.\n */\n hasContext(): boolean;\n\n /**\n * Check if the active context is valid.\n *\n * @returns True if the active context is valid, false otherwise.\n */\n hasValidContext(): boolean;\n}\n\nexport function createActiveContextTracker(): ActiveContextTracker {\n let unwrappedContext: LDContext | undefined;\n let context: Context | undefined;\n\n return {\n set(_unwrappedContext: LDContext, _context: Context) {\n unwrappedContext = _unwrappedContext;\n context = _context;\n },\n getContext() {\n return context;\n },\n getUnwrappedContext() {\n return unwrappedContext;\n },\n newIdentificationPromise() {\n let res: () => void;\n let rej: (err: Error) => void;\n\n const basePromise = new Promise<void>((resolve, reject) => {\n res = resolve;\n rej = reject;\n });\n\n return { identifyPromise: basePromise, identifyResolve: res!, identifyReject: rej! };\n },\n hasContext() {\n return context !== undefined;\n },\n hasValidContext() {\n return this.hasContext() && context!.valid;\n },\n };\n}\n","import {\n clone,\n internal,\n LDContext,\n LDContextCommon,\n LDMultiKindContext,\n LDSingleKindContext,\n LDUser,\n Platform,\n} from '@launchdarkly/js-sdk-common';\n\nimport { getOrGenerateKey } from '../storage/getOrGenerateKey';\nimport { namespaceForAnonymousGeneratedContextKey } from '../storage/namespaceUtils';\n\nconst { isLegacyUser, isMultiKind, isSingleKind } = internal;\n\n/**\n * This is the root ensureKey function. All other ensureKey functions reduce to this.\n *\n * - ensureKeyCommon // private root function\n * - ensureKeySingle\n * - ensureKeyMulti\n * - ensureKeyLegacy\n * - ensureKey // exported for external use\n *\n * @param kind The LDContext kind\n * @param c The LDContext object\n * @param platform Platform containing crypto and storage needed for storing and querying keys.\n */\nconst ensureKeyCommon = async (kind: string, c: LDContextCommon, platform: Platform) => {\n const { anonymous, key } = c;\n\n if (anonymous && !key) {\n const storageKey = await namespaceForAnonymousGeneratedContextKey(kind);\n // This mutates a cloned copy of the original context from ensureyKey so this is safe.\n // eslint-disable-next-line no-param-reassign\n c.key = await getOrGenerateKey(storageKey, platform);\n }\n};\n\nconst ensureKeySingle = async (c: LDSingleKindContext, platform: Platform) => {\n await ensureKeyCommon(c.kind, c, platform);\n};\n\nconst ensureKeyMulti = async (multiContext: LDMultiKindContext, platform: Platform) => {\n const { kind, ...singleContexts } = multiContext;\n\n return Promise.all(\n Object.entries(singleContexts).map(([k, c]) =>\n ensureKeyCommon(k, c as LDContextCommon, platform),\n ),\n );\n};\n\nconst ensureKeyLegacy = async (c: LDUser, platform: Platform) => {\n await ensureKeyCommon('user', c, platform);\n};\n\n/**\n * Ensure a key is always present in anonymous contexts. Non-anonymous contexts\n * are not processed and will just be returned as is.\n *\n * @param context\n * @param platform\n */\nexport const ensureKey = async (context: LDContext, platform: Platform): Promise<LDContext> => {\n const cloned = clone<LDContext>(context);\n\n if (isSingleKind(cloned)) {\n await ensureKeySingle(cloned as LDSingleKindContext, platform);\n }\n\n if (isMultiKind(cloned)) {\n await ensureKeyMulti(cloned as LDMultiKindContext, platform);\n }\n\n if (isLegacyUser(cloned)) {\n await ensureKeyLegacy(cloned as LDUser, platform);\n }\n\n return cloned;\n};\n","import { secondsToMillis, ServiceEndpoints } from '@launchdarkly/js-sdk-common';\n\nimport { Configuration, DEFAULT_POLLING, DEFAULT_STREAM } from '../configuration';\n\nexport type DiagnosticsInitConfig = {\n // client & server common properties\n customBaseURI: boolean;\n customStreamURI: boolean;\n customEventsURI: boolean;\n eventsCapacity: number;\n eventsFlushIntervalMillis: number;\n reconnectTimeMillis: number;\n diagnosticRecordingIntervalMillis: number;\n allAttributesPrivate: boolean;\n\n // client specific properties\n usingSecureMode: boolean;\n bootstrapMode: boolean;\n};\nconst createDiagnosticsInitConfig = (config: Configuration): DiagnosticsInitConfig => ({\n customBaseURI: config.serviceEndpoints.polling !== DEFAULT_POLLING,\n customStreamURI: config.serviceEndpoints.streaming !== DEFAULT_STREAM,\n customEventsURI: config.serviceEndpoints.events !== ServiceEndpoints.DEFAULT_EVENTS,\n eventsCapacity: config.capacity,\n eventsFlushIntervalMillis: secondsToMillis(config.flushInterval),\n reconnectTimeMillis: secondsToMillis(config.streamInitialReconnectDelay),\n diagnosticRecordingIntervalMillis: secondsToMillis(config.diagnosticRecordingInterval),\n allAttributesPrivate: config.allAttributesPrivate,\n // TODO: Implement when corresponding features are implemented.\n usingSecureMode: false,\n bootstrapMode: false,\n});\n\nexport default createDiagnosticsInitConfig;\n","import { internal, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\nimport createDiagnosticsInitConfig from './createDiagnosticsInitConfig';\n\nconst createDiagnosticsManager = (\n clientSideID: string,\n config: Configuration,\n platform: Platform,\n) => {\n if (config.sendEvents && !config.diagnosticOptOut) {\n return new internal.DiagnosticsManager(\n clientSideID,\n platform,\n createDiagnosticsInitConfig(config),\n );\n }\n\n return undefined;\n};\n\nexport default createDiagnosticsManager;\n","import { internal, LDEvaluationReason, LDFlagValue } from '@launchdarkly/js-sdk-common';\n\nimport { LDEvaluationDetail } from '../api';\n\nexport function createErrorEvaluationDetail(\n errorKind: internal.ErrorKinds,\n def?: LDFlagValue,\n): LDEvaluationDetail {\n return {\n value: def ?? null,\n variationIndex: null,\n reason: { kind: 'ERROR', errorKind },\n };\n}\n\nexport function createSuccessEvaluationDetail(\n value: LDFlagValue,\n variationIndex?: number,\n reason?: LDEvaluationReason,\n): LDEvaluationDetail {\n const res: LDEvaluationDetail = {\n value,\n variationIndex: variationIndex ?? null,\n reason: reason ?? null,\n };\n return res;\n}\n","import { ClientContext, internal, LDHeaders, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\n\nconst createEventProcessor = (\n clientSideID: string,\n config: Configuration,\n platform: Platform,\n baseHeaders: LDHeaders,\n diagnosticsManager?: internal.DiagnosticsManager,\n): internal.EventProcessor | undefined => {\n if (config.sendEvents) {\n return new internal.EventProcessor(\n { ...config, eventsCapacity: config.capacity },\n new ClientContext(clientSideID, config, platform),\n baseHeaders,\n undefined,\n diagnosticsManager,\n false,\n true,\n );\n }\n\n return undefined;\n};\n\nexport default createEventProcessor;\n","import { Context, internal, LDEvaluationReason, LDFlagValue } from '@launchdarkly/js-sdk-common';\n\nimport { Flag } from '../types';\n\n/**\n * @internal\n */\nexport default class EventFactory extends internal.EventFactoryBase {\n evalEventClient(\n flagKey: string,\n value: LDFlagValue,\n defaultVal: any,\n flag: Flag,\n context: Context,\n reason?: LDEvaluationReason,\n ): internal.InputEvalEvent {\n const { trackEvents, debugEventsUntilDate, trackReason, flagVersion, version, variation } =\n flag;\n\n return super.evalEvent({\n addExperimentData: trackReason,\n context,\n debugEventsUntilDate,\n defaultVal,\n flagKey,\n reason,\n trackEvents: !!trackEvents,\n value,\n variation,\n version: flagVersion ?? version,\n });\n }\n}\n","/**\n * An index for tracking the most recently used contexts by timestamp with the ability to\n * update entry timestamps and prune out least used contexts above a max capacity provided.\n */\nexport default class ContextIndex {\n container: IndexContainer = { index: new Array<IndexEntry>() };\n\n /**\n * Creates a {@link ContextIndex} from its JSON representation (likely retrieved from persistence).\n * @param json representation of the {@link ContextIndex}\n * @returns the {@link ContextIndex}\n */\n static fromJson(json: string): ContextIndex {\n const contextIndex = new ContextIndex();\n try {\n contextIndex.container = JSON.parse(json);\n } catch (e) {\n /* ignoring error and returning empty index */\n }\n\n return contextIndex;\n }\n\n /**\n * @returns the JSON representation of the {@link ContextIndex} (like for saving to persistence)\n */\n toJson(): string {\n return JSON.stringify(this.container);\n }\n\n /**\n * Notice that a context has been used and when it was used. This will update an existing record\n * with the given timestamp, or create a new record if one doesn't exist.\n * @param id of the corresponding context\n * @param timestamp in millis since epoch\n */\n notice(id: string, timestamp: number) {\n const entry = this.container.index.find((it) => it.id === id);\n if (entry === undefined) {\n this.container.index.push({ id, timestamp });\n } else {\n entry.timestamp = timestamp;\n }\n }\n\n /**\n * Prune the index to the specified max size and then return the IDs\n * @param maxContexts the maximum number of contexts to retain after this prune\n * @returns an array of removed entries\n */\n prune(maxContexts: number): Array<IndexEntry> {\n const clampedMax = Math.max(maxContexts, 0); // clamp to [0, infinity)\n if (this.container.index.length > clampedMax) {\n // sort by timestamp so that older timestamps appear first in the array\n this.container.index.sort((a, b) => a.timestamp - b.timestamp);\n // delete the first N many elements above capacity. splice returns removed elements\n return this.container.index.splice(0, this.container.index.length - clampedMax);\n }\n return [];\n }\n}\n\nexport interface IndexContainer {\n index: Array<IndexEntry>;\n}\n\ninterface IndexEntry {\n id: string;\n timestamp: number;\n}\n","import { Context, LDLogger, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { namespaceForContextData, namespaceForContextIndex } from '../storage/namespaceUtils';\nimport { Flags } from '../types';\nimport ContextIndex from './ContextIndex';\nimport FlagStore from './FlagStore';\nimport FlagUpdater from './FlagUpdater';\nimport { ItemDescriptor } from './ItemDescriptor';\n\n/**\n * This class handles persisting and loading flag values from a persistent\n * store. It intercepts updates and forwards them to the flag updater and\n * then persists changes after the updater has completed.\n */\nexport default class FlagPersistence {\n private _contextIndex: ContextIndex | undefined;\n private _indexKey?: string;\n private _indexKeyPromise: Promise<string>;\n\n constructor(\n private readonly _platform: Platform,\n private readonly _environmentNamespace: string,\n private readonly _maxCachedContexts: number,\n private readonly _flagStore: FlagStore,\n private readonly _flagUpdater: FlagUpdater,\n private readonly _logger: LDLogger,\n private readonly _timeStamper: () => number = () => Date.now(),\n ) {\n this._indexKeyPromise = namespaceForContextIndex(this._environmentNamespace);\n }\n\n /**\n * Inits flag persistence for the provided context with the provided flags. This will result\n * in the underlying {@link FlagUpdater} switching its active context.\n */\n async init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void> {\n this._flagUpdater.init(context, newFlags);\n await this._storeCache(context);\n }\n\n /**\n * Upserts a flag into the {@link FlagUpdater} and stores that to persistence if the upsert\n * was successful / accepted. An upsert may be rejected if the provided context is not\n * the active context.\n */\n async upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean> {\n if (this._flagUpdater.upsert(context, key, item)) {\n await this._storeCache(context);\n return true;\n }\n return false;\n }\n\n /**\n * Loads the flags from persistence for the provided context and gives those to the\n * {@link FlagUpdater} this {@link FlagPersistence} was constructed with.\n */\n async loadCached(context: Context): Promise<boolean> {\n const storageKey = await namespaceForContextData(\n this._platform.crypto,\n this._environmentNamespace,\n context,\n );\n let flagsJson = await this._platform.storage?.get(storageKey);\n if (flagsJson === null || flagsJson === undefined) {\n // Fallback: in version <10.3.1 flag data was stored under the canonical key, check\n // to see if data is present and migrate the data if present.\n flagsJson = await this._platform.storage?.get(context.canonicalKey);\n if (flagsJson === null || flagsJson === undefined) {\n // return false indicating cache did not load if flag json is still absent\n return false;\n }\n\n // migrate data from version <10.3.1 and cleanup data that was under canonical key\n await this._platform.storage?.set(storageKey, flagsJson);\n await this._platform.storage?.clear(context.canonicalKey);\n }\n\n try {\n const flags: Flags = JSON.parse(flagsJson);\n\n // mapping flags to item descriptors\n const descriptors = Object.entries(flags).reduce(\n (acc: { [k: string]: ItemDescriptor }, [key, flag]) => {\n acc[key] = { version: flag.version, flag };\n return acc;\n },\n {},\n );\n\n this._flagUpdater.initCached(context, descriptors);\n this._logger.debug('Loaded cached flag evaluations from persistent storage');\n return true;\n } catch (e: any) {\n this._logger.warn(\n `Could not load cached flag evaluations from persistent storage: ${e.message}`,\n );\n return false;\n }\n }\n\n private async _loadIndex(): Promise<ContextIndex> {\n if (this._contextIndex !== undefined) {\n return this._contextIndex;\n }\n\n const json = await this._platform.storage?.get(await this._indexKeyPromise);\n if (!json) {\n this._contextIndex = new ContextIndex();\n return this._contextIndex;\n }\n\n try {\n this._contextIndex = ContextIndex.fromJson(json);\n this._logger.debug('Loaded context index from persistent storage');\n } catch (e: any) {\n this._logger.warn(`Could not load index from persistent storage: ${e.message}`);\n this._contextIndex = new ContextIndex();\n }\n return this._contextIndex;\n }\n\n private async _storeCache(context: Context): Promise<void> {\n const index = await this._loadIndex();\n const storageKey = await namespaceForContextData(\n this._platform.crypto,\n this._environmentNamespace,\n context,\n );\n index.notice(storageKey, this._timeStamper());\n\n const pruned = index.prune(this._maxCachedContexts);\n await Promise.all(pruned.map(async (it) => this._platform.storage?.clear(it.id)));\n\n // store index\n await this._platform.storage?.set(await this._indexKeyPromise, index.toJson());\n const allFlags = this._flagStore.getAll();\n\n // mapping item descriptors to flags\n const flags = Object.entries(allFlags).reduce((acc: Flags, [key, descriptor]) => {\n if (descriptor.flag !== null && descriptor.flag !== undefined) {\n acc[key] = descriptor.flag;\n }\n return acc;\n }, {});\n\n const jsonAll = JSON.stringify(flags);\n // store flag data\n await this._platform.storage?.set(storageKey, jsonAll);\n }\n}\n","import { ItemDescriptor } from './ItemDescriptor';\n\n/**\n * This interface exists for testing purposes\n */\nexport default interface FlagStore {\n init(newFlags: { [key: string]: ItemDescriptor }): void;\n insertOrUpdate(key: string, update: ItemDescriptor): void;\n get(key: string): ItemDescriptor | undefined;\n getAll(): { [key: string]: ItemDescriptor };\n}\n\n/**\n * In memory flag store.\n */\nexport class DefaultFlagStore implements FlagStore {\n private _flags: { [key: string]: ItemDescriptor } = {};\n\n init(newFlags: { [key: string]: ItemDescriptor }) {\n this._flags = Object.entries(newFlags).reduce(\n (acc: { [k: string]: ItemDescriptor }, [key, flag]) => {\n acc[key] = flag;\n return acc;\n },\n {},\n );\n }\n\n insertOrUpdate(key: string, update: ItemDescriptor) {\n this._flags[key] = update;\n }\n\n get(key: string): ItemDescriptor | undefined {\n if (Object.prototype.hasOwnProperty.call(this._flags, key)) {\n return this._flags[key];\n }\n return undefined;\n }\n\n getAll(): { [key: string]: ItemDescriptor } {\n return this._flags;\n }\n}\n","import { fastDeepEqual } from '@launchdarkly/js-sdk-common';\n\nexport default function calculateChangedKeys(\n existingObject: { [k: string]: any },\n newObject: { [k: string]: any },\n) {\n const changedKeys: string[] = [];\n\n // property deleted or updated\n Object.entries(existingObject).forEach(([k, f]) => {\n const subObject = newObject[k];\n if (!subObject || !fastDeepEqual(f, subObject)) {\n changedKeys.push(k);\n }\n });\n\n // property added\n Object.keys(newObject).forEach((k) => {\n if (!existingObject[k]) {\n changedKeys.push(k);\n }\n });\n\n return changedKeys;\n}\n","import { Context, LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport calculateChangedKeys from './calculateChangedKeys';\nimport FlagStore from './FlagStore';\nimport { ItemDescriptor } from './ItemDescriptor';\n\nexport type FlagChangeType = 'init' | 'patch' | 'override';\n\n/**\n * This callback indicates that the details associated with one or more flags\n * have changed.\n *\n * This could be the value of the flag, but it could also include changes\n * to the evaluation reason, such as being included in an experiment.\n *\n * It can include new or deleted flags as well, so an evaluation may result\n * in a FLAG_NOT_FOUND reason.\n *\n * This event does not include the value of the flag. It is expected that you\n * will call a variation method for flag values which you require.\n */\nexport type FlagsChangeCallback = (\n context: Context,\n flagKeys: Array<string>,\n type: FlagChangeType,\n) => void;\n\n/**\n * The flag updater handles logic required during the flag update process.\n * It handles versions checking to handle out of order flag updates and\n * also handles flag comparisons for change notification.\n */\nexport default class FlagUpdater {\n private _flagStore: FlagStore;\n private _logger: LDLogger;\n private _activeContext: Context | undefined;\n private _changeCallbacks = new Array<FlagsChangeCallback>();\n\n constructor(flagStore: FlagStore, logger: LDLogger) {\n this._flagStore = flagStore;\n this._logger = logger;\n }\n\n handleFlagChanges(keys: string[], type: FlagChangeType): void {\n if (this._activeContext) {\n this._changeCallbacks.forEach((callback) => {\n try {\n callback(this._activeContext!, keys, type);\n } catch (err) {\n /* intentionally empty */\n }\n });\n } else {\n this._logger.warn(\n 'Received a change event without an active context. Changes will not be propagated.',\n );\n }\n }\n\n init(context: Context, newFlags: { [key: string]: ItemDescriptor }) {\n this._activeContext = context;\n const oldFlags = this._flagStore.getAll();\n this._flagStore.init(newFlags);\n const changed = calculateChangedKeys(oldFlags, newFlags);\n if (changed.length > 0) {\n this.handleFlagChanges(changed, 'init');\n }\n }\n\n initCached(context: Context, newFlags: { [key: string]: ItemDescriptor }) {\n if (this._activeContext?.canonicalKey === context.canonicalKey) {\n return;\n }\n\n this.init(context, newFlags);\n }\n\n upsert(context: Context, key: string, item: ItemDescriptor): boolean {\n if (this._activeContext?.canonicalKey !== context.canonicalKey) {\n this._logger.warn('Received an update for an inactive context.');\n return false;\n }\n\n const currentValue = this._flagStore.get(key);\n if (currentValue !== undefined && currentValue.version >= item.version) {\n // this is an out of order update that can be ignored\n return false;\n }\n\n this._flagStore.insertOrUpdate(key, item);\n this.handleFlagChanges([key], 'patch');\n return true;\n }\n\n on(callback: FlagsChangeCallback): void {\n this._changeCallbacks.push(callback);\n }\n\n off(callback: FlagsChangeCallback): void {\n const index = this._changeCallbacks.indexOf(callback);\n if (index > -1) {\n this._changeCallbacks.splice(index, 1);\n }\n }\n}\n","import { Context, LDFlagValue, LDLogger, Platform } from '@launchdarkly/js-sdk-common';\n\nimport { namespaceForEnvironment } from '../storage/namespaceUtils';\nimport FlagPersistence from './FlagPersistence';\nimport { DefaultFlagStore } from './FlagStore';\nimport FlagUpdater, { FlagsChangeCallback } from './FlagUpdater';\nimport { ItemDescriptor } from './ItemDescriptor';\n\n/**\n * Top level manager of flags for the client. LDClient should be using this\n * interface and not any of the specific instances managed by it. Updates from\n * data sources should be directed to the [init] and [upsert] methods of this\n * interface.\n */\nexport interface FlagManager {\n /**\n * Attempts to get a flag by key from the current flags.\n */\n get(key: string): ItemDescriptor | undefined;\n\n /**\n * Gets all the current flags.\n */\n getAll(): { [key: string]: ItemDescriptor };\n\n /**\n * Initializes the flag manager with data from a data source.\n * Persistence initialization is handled by {@link FlagPersistence}\n */\n init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void>;\n\n /**\n * Attempt to update a flag. If the flag is for the wrong context, or\n * it is of an older version, then an update will not be performed.\n */\n upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean>;\n\n /**\n * Asynchronously load cached values from persistence.\n */\n loadCached(context: Context): Promise<boolean>;\n\n /**\n * Updates in-memory storage with the specified flags without a context\n * or persistent storage. Flags set in this way are considered emphemeral and\n * should be replaced as soon as initialization is done.\n *\n * @param newFlags - cached flags\n */\n presetFlags(newFlags: { [key: string]: ItemDescriptor }): void;\n\n /**\n * Update in-memory storage with the specified flags, but do not persistent them to cache\n * storage.\n */\n setBootstrap(context: Context, newFlags: { [key: string]: ItemDescriptor }): void;\n\n /**\n * Register a flag change callback.\n */\n on(callback: FlagsChangeCallback): void;\n\n /**\n * Unregister a flag change callback.\n */\n off(callback: FlagsChangeCallback): void;\n\n /**\n * Obtain debug override functions that allows plugins\n * to manipulate the outcome of the flags managed by\n * this manager\n *\n * @experimental This function is experimental and intended for use by LaunchDarkly tools at this time.\n */\n getDebugOverride?(): LDDebugOverride;\n}\n\n/**\n * Debug interface for plugins that need to override flag values during development.\n * This interface provides methods to temporarily override flag values that take\n * precedence over the actual flag values from LaunchDarkly. These overrides are\n * useful for testing, development, and debugging scenarios.\n *\n * @experimental This interface is experimental and intended for use by LaunchDarkly tools at this time.\n * The API may change in future versions.\n */\nexport interface LDDebugOverride {\n /**\n * Set an override value for a flag that takes precedence over the real flag value.\n *\n * @param flagKey The flag key.\n * @param value The override value.\n */\n setOverride(flagKey: string, value: LDFlagValue): void;\n\n /**\n * Remove an override value for a flag, reverting to the real flag value.\n *\n * @param flagKey The flag key.\n */\n removeOverride(flagKey: string): void;\n\n /**\n * Clear all override values, reverting all flags to their real values.\n */\n clearAllOverrides(): void;\n\n /**\n * Get all currently active flag overrides.\n *\n * @returns\n * An object containing all active overrides as key-value pairs,\n * where keys are flag keys and values are the overridden flag values.\n * Returns an empty object if no overrides are active.\n */\n getAllOverrides(): { [key: string]: ItemDescriptor };\n}\n\nexport default class DefaultFlagManager implements FlagManager {\n private _flagStore = new DefaultFlagStore();\n private _flagUpdater: FlagUpdater;\n private _flagPersistencePromise: Promise<FlagPersistence>;\n private _overrides?: { [key: string]: LDFlagValue };\n\n /**\n * @param platform implementation of various platform provided functionality\n * @param sdkKey that will be used to distinguish different environments\n * @param maxCachedContexts that specifies the max number of contexts that will be cached in persistence\n * @param logger used for logging various messages\n * @param timeStamper exists for testing purposes\n */\n constructor(\n platform: Platform,\n sdkKey: string,\n maxCachedContexts: number,\n logger: LDLogger,\n timeStamper: () => number = () => Date.now(),\n ) {\n this._flagUpdater = new FlagUpdater(this._flagStore, logger);\n this._flagPersistencePromise = this._initPersistence(\n platform,\n sdkKey,\n maxCachedContexts,\n logger,\n timeStamper,\n );\n }\n\n private async _initPersistence(\n platform: Platform,\n sdkKey: string,\n maxCachedContexts: number,\n logger: LDLogger,\n timeStamper: () => number = () => Date.now(),\n ): Promise<FlagPersistence> {\n const environmentNamespace = await namespaceForEnvironment(platform.crypto, sdkKey);\n\n return new FlagPersistence(\n platform,\n environmentNamespace,\n maxCachedContexts,\n this._flagStore,\n this._flagUpdater,\n logger,\n timeStamper,\n );\n }\n\n get(key: string): ItemDescriptor | undefined {\n if (this._overrides && Object.prototype.hasOwnProperty.call(this._overrides, key)) {\n return this._convertValueToOverrideDescripter(this._overrides[key]);\n }\n\n return this._flagStore.get(key);\n }\n\n getAll(): { [key: string]: ItemDescriptor } {\n if (this._overrides) {\n return {\n ...this._flagStore.getAll(),\n ...Object.entries(this._overrides).reduce(\n (acc: { [key: string]: ItemDescriptor }, [key, value]) => {\n acc[key] = this._convertValueToOverrideDescripter(value);\n return acc;\n },\n {},\n ),\n };\n }\n return this._flagStore.getAll();\n }\n\n presetFlags(newFlags: { [key: string]: ItemDescriptor }): void {\n this._flagStore.init(newFlags);\n }\n\n setBootstrap(context: Context, newFlags: { [key: string]: ItemDescriptor }): void {\n // Bypasses the persistence as we do not want to put these flags into any cache.\n // Generally speaking persistence likely *SHOULD* be disabled when using bootstrap.\n this._flagUpdater.init(context, newFlags);\n }\n\n async init(context: Context, newFlags: { [key: string]: ItemDescriptor }): Promise<void> {\n return (await this._flagPersistencePromise).init(context, newFlags);\n }\n\n async upsert(context: Context, key: string, item: ItemDescriptor): Promise<boolean> {\n return (await this._flagPersistencePromise).upsert(context, key, item);\n }\n\n async loadCached(context: Context): Promise<boolean> {\n return (await this._flagPersistencePromise).loadCached(context);\n }\n\n on(callback: FlagsChangeCallback): void {\n this._flagUpdater.on(callback);\n }\n\n off(callback: FlagsChangeCallback): void {\n this._flagUpdater.off(callback);\n }\n\n private _convertValueToOverrideDescripter(value: LDFlagValue): ItemDescriptor {\n return {\n flag: {\n value,\n version: 0,\n },\n version: 0,\n };\n }\n\n setOverride(key: string, value: LDFlagValue) {\n if (!this._overrides) {\n this._overrides = {};\n }\n this._overrides[key] = value;\n this._flagUpdater.handleFlagChanges([key], 'override');\n }\n\n removeOverride(flagKey: string) {\n if (!this._overrides || !Object.prototype.hasOwnProperty.call(this._overrides, flagKey)) {\n return; // No override to remove\n }\n\n delete this._overrides[flagKey];\n\n // If no more overrides, reset to undefined for performance\n if (Object.keys(this._overrides).length === 0) {\n this._overrides = undefined;\n }\n\n this._flagUpdater.handleFlagChanges([flagKey], 'override');\n }\n\n clearAllOverrides() {\n if (this._overrides) {\n const clearedOverrides = { ...this._overrides };\n this._overrides = undefined; // Reset to undefined\n this._flagUpdater.handleFlagChanges(Object.keys(clearedOverrides), 'override');\n }\n }\n\n getAllOverrides() {\n if (!this._overrides) {\n return {};\n }\n const result = {} as { [key: string]: ItemDescriptor };\n Object.entries(this._overrides).forEach(([key, value]) => {\n result[key] = this._convertValueToOverrideDescripter(value);\n });\n return result;\n }\n\n getDebugOverride(): LDDebugOverride {\n return {\n setOverride: this.setOverride.bind(this),\n removeOverride: this.removeOverride.bind(this),\n clearAllOverrides: this.clearAllOverrides.bind(this),\n getAllOverrides: this.getAllOverrides.bind(this),\n };\n }\n}\n","import { LDContext, LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport {\n EvaluationSeriesContext,\n EvaluationSeriesData,\n Hook,\n IdentifySeriesContext,\n IdentifySeriesData,\n IdentifySeriesResult,\n TrackSeriesContext,\n} from './api/integrations/Hooks';\nimport { LDEvaluationDetail } from './api/LDEvaluationDetail';\n\nconst UNKNOWN_HOOK_NAME = 'unknown hook';\nconst BEFORE_EVALUATION_STAGE_NAME = 'beforeEvaluation';\nconst AFTER_EVALUATION_STAGE_NAME = 'afterEvaluation';\nconst AFTER_TRACK_STAGE_NAME = 'afterTrack';\n\nfunction tryExecuteStage<TData>(\n logger: LDLogger,\n method: string,\n hookName: string,\n stage: () => TData,\n def: TData,\n): TData {\n try {\n return stage();\n } catch (err) {\n logger?.error(`An error was encountered in \"${method}\" of the \"${hookName}\" hook: ${err}`);\n return def;\n }\n}\n\nfunction getHookName(logger: LDLogger, hook: Hook): string {\n try {\n return hook.getMetadata().name || UNKNOWN_HOOK_NAME;\n } catch {\n logger.error(`Exception thrown getting metadata for hook. Unable to get hook name.`);\n return UNKNOWN_HOOK_NAME;\n }\n}\n\nfunction executeBeforeEvaluation(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: EvaluationSeriesContext,\n): EvaluationSeriesData[] {\n return hooks.map((hook) =>\n tryExecuteStage(\n logger,\n BEFORE_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.beforeEvaluation?.(hookContext, {}) ?? {},\n {},\n ),\n );\n}\n\nfunction executeAfterEvaluation(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: EvaluationSeriesContext,\n updatedData: EvaluationSeriesData[],\n result: LDEvaluationDetail,\n) {\n // This iterates in reverse, versus reversing a shallow copy of the hooks,\n // for efficiency.\n for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) {\n const hook = hooks[hookIndex];\n const data = updatedData[hookIndex];\n tryExecuteStage(\n logger,\n AFTER_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.afterEvaluation?.(hookContext, data, result) ?? {},\n {},\n );\n }\n}\n\nfunction executeBeforeIdentify(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: IdentifySeriesContext,\n): IdentifySeriesData[] {\n return hooks.map((hook) =>\n tryExecuteStage(\n logger,\n BEFORE_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.beforeIdentify?.(hookContext, {}) ?? {},\n {},\n ),\n );\n}\n\nfunction executeAfterIdentify(\n logger: LDLogger,\n hooks: Hook[],\n hookContext: IdentifySeriesContext,\n updatedData: IdentifySeriesData[],\n result: IdentifySeriesResult,\n) {\n // This iterates in reverse, versus reversing a shallow copy of the hooks,\n // for efficiency.\n for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) {\n const hook = hooks[hookIndex];\n const data = updatedData[hookIndex];\n tryExecuteStage(\n logger,\n AFTER_EVALUATION_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.afterIdentify?.(hookContext, data, result) ?? {},\n {},\n );\n }\n}\n\nfunction executeAfterTrack(logger: LDLogger, hooks: Hook[], hookContext: TrackSeriesContext) {\n // This iterates in reverse, versus reversing a shallow copy of the hooks,\n // for efficiency.\n for (let hookIndex = hooks.length - 1; hookIndex >= 0; hookIndex -= 1) {\n const hook = hooks[hookIndex];\n tryExecuteStage(\n logger,\n AFTER_TRACK_STAGE_NAME,\n getHookName(logger, hook),\n () => hook?.afterTrack?.(hookContext),\n undefined,\n );\n }\n}\n\nexport default class HookRunner {\n private readonly _hooks: Hook[] = [];\n\n constructor(\n private readonly _logger: LDLogger,\n initialHooks: Hook[],\n ) {\n this._hooks.push(...initialHooks);\n }\n\n withEvaluation(\n key: string,\n context: LDContext | undefined,\n defaultValue: unknown,\n method: () => LDEvaluationDetail,\n ): LDEvaluationDetail {\n if (this._hooks.length === 0) {\n return method();\n }\n const hooks: Hook[] = [...this._hooks];\n const hookContext: EvaluationSeriesContext = {\n flagKey: key,\n context,\n defaultValue,\n };\n\n const hookData = executeBeforeEvaluation(this._logger, hooks, hookContext);\n const result = method();\n executeAfterEvaluation(this._logger, hooks, hookContext, hookData, result);\n return result;\n }\n\n identify(\n context: LDContext,\n timeout: number | undefined,\n ): (result: IdentifySeriesResult) => void {\n const hooks: Hook[] = [...this._hooks];\n const hookContext: IdentifySeriesContext = {\n context,\n timeout,\n };\n const hookData = executeBeforeIdentify(this._logger, hooks, hookContext);\n return (result) => {\n executeAfterIdentify(this._logger, hooks, hookContext, hookData, result);\n };\n }\n\n addHook(hook: Hook): void {\n this._hooks.push(hook);\n }\n\n afterTrack(hookContext: TrackSeriesContext): void {\n if (this._hooks.length === 0) {\n return;\n }\n const hooks: Hook[] = [...this._hooks];\n executeAfterTrack(this._logger, hooks, hookContext);\n }\n}\n","import { EvaluationSeriesContext, EvaluationSeriesData, Hook, LDEvaluationDetail } from '../api';\nimport InspectorManager from './InspectorManager';\n\nexport function getInspectorHook(inspectorManager: InspectorManager): Hook {\n return {\n getMetadata() {\n return {\n name: 'LaunchDarkly-Inspector-Adapter',\n };\n },\n afterEvaluation: (\n hookContext: EvaluationSeriesContext,\n data: EvaluationSeriesData,\n detail: LDEvaluationDetail,\n ) => {\n inspectorManager.onFlagUsed(hookContext.flagKey, detail, hookContext.context);\n return data;\n },\n afterIdentify(hookContext, data, _result) {\n inspectorManager.onIdentityChanged(hookContext.context);\n return data;\n },\n };\n}\n","export function invalidInspector(type: string, name: string) {\n return `an inspector: \"${name}\" of an invalid type (${type}) was configured`;\n}\n\nexport function inspectorMethodError(type: string, name: string) {\n return `an inspector: \"${name}\" of type: \"${type}\" generated an exception`;\n}\n","import { LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport { LDInspection } from '../api/LDInspection';\nimport { inspectorMethodError } from './messages';\n\n/**\n * Wrap an inspector ensuring that calling its methods are safe.\n * @param inspector Inspector to wrap.\n */\nexport default function createSafeInspector(\n inspector: LDInspection,\n logger: LDLogger,\n): LDInspection {\n let errorLogged = false;\n const wrapper: LDInspection = {\n method: (...args: any[]) => {\n try {\n // We are proxying arguments here to the underlying method. Typescript doesn't care\n // for this as it cannot validate the parameters are correct, but we are also the caller\n // in this case and will dispatch things with the correct arguments. The dispatch to this\n // will itself happen with a type guard.\n // @ts-ignore\n inspector.method(...args);\n } catch {\n // If something goes wrong in an inspector we want to log that something\n // went wrong. We don't want to flood the logs, so we only log something\n // the first time that something goes wrong.\n // We do not include the exception in the log, because we do not know what\n // kind of data it may contain.\n if (!errorLogged) {\n errorLogged = true;\n logger.warn(inspectorMethodError(wrapper.type, wrapper.name));\n }\n // Prevent errors.\n }\n },\n type: inspector.type,\n name: inspector.name,\n synchronous: inspector.synchronous,\n };\n\n return wrapper;\n}\n","import { LDContext, LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport { LDEvaluationDetail } from '../api';\nimport { LDInspection } from '../api/LDInspection';\nimport createSafeInspector from './createSafeInspector';\nimport { invalidInspector } from './messages';\n\nconst FLAG_USED_TYPE = 'flag-used';\nconst FLAG_DETAILS_CHANGED_TYPE = 'flag-details-changed';\nconst FLAG_DETAIL_CHANGED_TYPE = 'flag-detail-changed';\nconst IDENTITY_CHANGED_TYPE = 'client-identity-changed';\n\nconst VALID__TYPES = [\n FLAG_USED_TYPE,\n FLAG_DETAILS_CHANGED_TYPE,\n FLAG_DETAIL_CHANGED_TYPE,\n IDENTITY_CHANGED_TYPE,\n];\n\nfunction validateInspector(inspector: LDInspection, logger: LDLogger): boolean {\n const valid =\n VALID__TYPES.includes(inspector.type) &&\n inspector.method &&\n typeof inspector.method === 'function';\n\n if (!valid) {\n logger.warn(invalidInspector(inspector.type, inspector.name));\n }\n\n return valid;\n}\n\n/**\n * Manages dispatching of inspection data to registered inspectors.\n */\nexport default class InspectorManager {\n private _safeInspectors: LDInspection[] = [];\n\n constructor(inspectors: LDInspection[], logger: LDLogger) {\n const validInspectors = inspectors.filter((inspector) => validateInspector(inspector, logger));\n this._safeInspectors = validInspectors.map((inspector) =>\n createSafeInspector(inspector, logger),\n );\n }\n\n hasInspectors(): boolean {\n return this._safeInspectors.length !== 0;\n }\n\n /**\n * Notify registered inspectors of a flag being used.\n *\n * @param flagKey The key for the flag.\n * @param detail The LDEvaluationDetail for the flag.\n * @param context The LDContext for the flag.\n */\n onFlagUsed(flagKey: string, detail: LDEvaluationDetail, context?: LDContext) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === FLAG_USED_TYPE) {\n inspector.method(flagKey, detail, context);\n }\n });\n }\n\n /**\n * Notify registered inspectors that the flags have been replaced.\n *\n * @param flags The current flags as a Record<string, LDEvaluationDetail>.\n */\n onFlagsChanged(flags: Record<string, LDEvaluationDetail>) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === FLAG_DETAILS_CHANGED_TYPE) {\n inspector.method(flags);\n }\n });\n }\n\n /**\n * Notify registered inspectors that a flag value has changed.\n *\n * @param flagKey The key for the flag that changed.\n * @param flag An `LDEvaluationDetail` for the flag.\n */\n onFlagChanged(flagKey: string, flag: LDEvaluationDetail) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === FLAG_DETAIL_CHANGED_TYPE) {\n inspector.method(flagKey, flag);\n }\n });\n }\n\n /**\n * Notify the registered inspectors that the context identity has changed.\n *\n * The notification itself will be dispatched asynchronously.\n *\n * @param context The `LDContext` which is now identified.\n */\n onIdentityChanged(context: LDContext) {\n this._safeInspectors.forEach((inspector) => {\n if (inspector.type === IDENTITY_CHANGED_TYPE) {\n inspector.method(context);\n }\n });\n }\n}\n","import { LDLogger } from '@launchdarkly/js-sdk-common';\n\ntype FlagChangeKey = `change:${string}`;\n\n/**\n * Type for name of emitted events. 'change' is used for all flag changes. 'change:flag-name-here' is used\n * for specific flag changes.\n */\nexport type EventName = 'change' | FlagChangeKey | 'dataSourceStatus' | 'error' | 'initialized';\n\n/**\n * Implementation Note: There should not be any default listeners for change events in a client\n * implementation. Default listeners mean a client cannot determine when there are actual\n * application developer provided listeners. If we require default listeners, then we should add\n * a system to allow listeners which have counts independent of the primary listener counts.\n */\nexport default class LDEmitter {\n private _listeners: Map<EventName, Function[]> = new Map();\n\n constructor(private _logger?: LDLogger) {}\n\n on(name: EventName, listener: Function) {\n if (!this._listeners.has(name)) {\n this._listeners.set(name, [listener]);\n } else {\n this._listeners.get(name)?.push(listener);\n }\n }\n\n /**\n * Unsubscribe one or all events.\n *\n * @param name\n * @param listener Optional. If unspecified, all listeners for the event will be removed.\n */\n off(name: EventName, listener?: Function) {\n const existingListeners = this._listeners.get(name);\n if (!existingListeners) {\n return;\n }\n\n if (listener) {\n // remove from internal cache\n const updated = existingListeners.filter((fn) => fn !== listener);\n if (updated.length === 0) {\n this._listeners.delete(name);\n } else {\n this._listeners.set(name, updated);\n }\n return;\n }\n\n // listener was not specified, so remove them all for that event\n this._listeners.delete(name);\n }\n\n private _invokeListener(listener: Function, name: EventName, ...detail: any[]) {\n try {\n listener(...detail);\n } catch (err) {\n this._logger?.error(`Encountered error invoking handler for \"${name}\", detail: \"${err}\"`);\n }\n }\n\n emit(name: EventName, ...detail: any[]) {\n const listeners = this._listeners.get(name);\n listeners?.forEach((listener) => this._invokeListener(listener, name, ...detail));\n }\n\n eventNames(): string[] {\n return [...this._listeners.keys()];\n }\n\n listenerCount(name: EventName): number {\n return this._listeners.get(name)?.length ?? 0;\n }\n}\n","import {\n LDPluginApplicationMetadata,\n LDPluginEnvironmentMetadata,\n LDPluginSdkMetadata,\n Platform,\n} from '@launchdarkly/js-sdk-common';\n\nimport { Configuration } from '../configuration';\n\n/**\n * Mutable utility type to allow building up a readonly object from a mutable one.\n */\ntype Mutable<T> = {\n -readonly [P in keyof T]: Mutable<T[P]>;\n};\n\nexport function createPluginEnvironmentMetadata(\n sdkKey: string,\n platform: Platform,\n config: Configuration,\n): LDPluginEnvironmentMetadata {\n const sdkData = platform.info.sdkData();\n\n let applicationMetadata: Mutable<LDPluginApplicationMetadata> | undefined;\n\n if (config.applicationInfo) {\n if (config.applicationInfo.id) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.id = config.applicationInfo.id;\n }\n if (config.applicationInfo.version) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.version = config.applicationInfo.version;\n }\n if (config.applicationInfo.name) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.name = config.applicationInfo.name;\n }\n if (config.applicationInfo.versionName) {\n applicationMetadata = applicationMetadata ?? {};\n applicationMetadata.versionName = config.applicationInfo.versionName;\n }\n }\n\n const sdkMetadata: Mutable<LDPluginSdkMetadata> = {\n name: sdkData.userAgentBase!,\n version: sdkData.version!,\n };\n\n if (sdkData.wrapperName) {\n sdkMetadata.wrapperName = sdkData.wrapperName;\n }\n\n if (sdkData.wrapperVersion) {\n sdkMetadata.wrapperVersion = sdkData.wrapperVersion;\n }\n\n const environmentMetadata: Mutable<LDPluginEnvironmentMetadata> = {\n sdk: sdkMetadata,\n [config.credentialType]: sdkKey,\n };\n if (applicationMetadata) {\n environmentMetadata.application = applicationMetadata;\n }\n\n return environmentMetadata;\n}\n","import {\n AutoEnvAttributes,\n clone,\n Context,\n defaultHeaders,\n internal,\n LDClientError,\n LDContext,\n LDFlagSet,\n LDFlagValue,\n LDHeaders,\n LDLogger,\n LDPluginEnvironmentMetadata,\n LDTimeoutError,\n Platform,\n TypeValidators,\n} from '@launchdarkly/js-sdk-common';\n\nimport {\n Hook,\n LDClient,\n LDClientIdentifyResult,\n LDIdentifyError,\n LDIdentifyResult,\n LDIdentifyShed,\n LDIdentifySuccess,\n LDIdentifyTimeout,\n type LDOptions,\n} from './api';\nimport { LDEvaluationDetail, LDEvaluationDetailTyped } from './api/LDEvaluationDetail';\nimport { LDIdentifyOptions } from './api/LDIdentifyOptions';\nimport { createAsyncTaskQueue } from './async/AsyncTaskQueue';\nimport { Configuration, ConfigurationImpl, LDClientInternalOptions } from './configuration';\nimport { addAutoEnv } from './context/addAutoEnv';\nimport {\n ActiveContextTracker,\n createActiveContextTracker,\n} from './context/createActiveContextTracker';\nimport { ensureKey } from './context/ensureKey';\nimport { DataManager, DataManagerFactory } from './DataManager';\nimport createDiagnosticsManager from './diagnostics/createDiagnosticsManager';\nimport {\n createErrorEvaluationDetail,\n createSuccessEvaluationDetail,\n} from './evaluation/evaluationDetail';\nimport createEventProcessor from './events/createEventProcessor';\nimport EventFactory from './events/EventFactory';\nimport DefaultFlagManager, { FlagManager, LDDebugOverride } from './flag-manager/FlagManager';\nimport { FlagChangeType } from './flag-manager/FlagUpdater';\nimport { ItemDescriptor } from './flag-manager/ItemDescriptor';\nimport HookRunner from './HookRunner';\nimport { getInspectorHook } from './inspection/getInspectorHook';\nimport InspectorManager from './inspection/InspectorManager';\nimport LDEmitter, { EventName } from './LDEmitter';\nimport { createPluginEnvironmentMetadata } from './plugins/createPluginEnvironmentMetadata';\n\nconst { ClientMessages, ErrorKinds } = internal;\n\nconst DEFAULT_IDENTIFY_TIMEOUT_SECONDS = 5;\n\nexport default class LDClientImpl implements LDClient, LDClientIdentifyResult {\n private readonly _config: Configuration;\n private readonly _diagnosticsManager?: internal.DiagnosticsManager;\n private _eventProcessor?: internal.EventProcessor;\n readonly logger: LDLogger;\n\n private _activeContextTracker: ActiveContextTracker = createActiveContextTracker();\n\n private readonly _highTimeoutThreshold: number = 15;\n\n private _eventFactoryDefault = new EventFactory(false);\n private _eventFactoryWithReasons = new EventFactory(true);\n protected emitter: LDEmitter;\n private _flagManager: FlagManager;\n\n private _eventSendingEnabled: boolean = false;\n private _baseHeaders: LDHeaders;\n protected dataManager: DataManager;\n protected readonly environmentMetadata: LDPluginEnvironmentMetadata;\n private _hookRunner: HookRunner;\n private _inspectorManager: InspectorManager;\n private _identifyQueue = createAsyncTaskQueue<void>();\n\n /**\n * Creates the client object synchronously. No async, no network calls.\n */\n constructor(\n public readonly sdkKey: string,\n public readonly autoEnvAttributes: AutoEnvAttributes,\n public readonly platform: Platform,\n options: LDOptions,\n dataManagerFactory: DataManagerFactory,\n internalOptions?: LDClientInternalOptions,\n ) {\n if (!sdkKey) {\n throw new Error('You must configure the client with a client-side SDK key');\n }\n\n if (!platform.encoding) {\n throw new Error('Platform must implement Encoding because btoa is required.');\n }\n\n this._config = new ConfigurationImpl(options, internalOptions);\n this.logger = this._config.logger;\n\n this._baseHeaders = defaultHeaders(\n this.sdkKey,\n this.platform.info,\n this._config.tags,\n this._config.serviceEndpoints.includeAuthorizationHeader,\n this._config.userAgentHeaderName,\n );\n\n this._flagManager = new DefaultFlagManager(\n this.platform,\n sdkKey,\n this._config.maxCachedContexts,\n this._config.logger,\n );\n this._diagnosticsManager = createDiagnosticsManager(sdkKey, this._config, platform);\n this._eventProcessor = createEventProcessor(\n sdkKey,\n this._config,\n platform,\n this._baseHeaders,\n this._diagnosticsManager,\n );\n this.emitter = new LDEmitter();\n this.emitter.on('error', (c: LDContext, err: any) => {\n this.logger.error(`error: ${err}, context: ${JSON.stringify(c)}`);\n });\n\n this._flagManager.on((context, flagKeys, type) => {\n this._handleInspectionChanged(flagKeys, type);\n const ldContext = Context.toLDContext(context);\n this.emitter.emit('change', ldContext, flagKeys);\n flagKeys.forEach((it) => {\n this.emitter.emit(`change:${it}`, ldContext);\n });\n });\n\n this.dataManager = dataManagerFactory(\n this._flagManager,\n this._config,\n this._baseHeaders,\n this.emitter,\n this._diagnosticsManager,\n );\n\n const hooks: Hook[] = [...this._config.hooks];\n\n this.environmentMetadata = createPluginEnvironmentMetadata(\n this.sdkKey,\n this.platform,\n this._config,\n );\n\n this._config.getImplementationHooks(this.environmentMetadata).forEach((hook) => {\n hooks.push(hook);\n });\n\n this._hookRunner = new HookRunner(this.logger, hooks);\n this._inspectorManager = new InspectorManager(this._config.inspectors, this.logger);\n if (this._inspectorManager.hasInspectors()) {\n this._hookRunner.addHook(getInspectorHook(this._inspectorManager));\n }\n }\n\n allFlags(): LDFlagSet {\n // extracting all flag values\n const result = Object.entries(this._flagManager.getAll()).reduce(\n (acc: LDFlagSet, [key, descriptor]) => {\n if (descriptor.flag !== null && descriptor.flag !== undefined && !descriptor.flag.deleted) {\n acc[key] = descriptor.flag.value;\n }\n return acc;\n },\n {},\n );\n return result;\n }\n\n async close(): Promise<void> {\n await this.flush();\n this._eventProcessor?.close();\n this.dataManager.close();\n this.logger.debug('Closed event processor and data source.');\n }\n\n async flush(): Promise<{ error?: Error; result: boolean }> {\n try {\n await this._eventProcessor?.flush();\n this.logger.debug('Successfully flushed event processor.');\n } catch (e) {\n this.logger.error(`Error flushing event processor: ${e}.`);\n return { error: e as Error, result: false };\n }\n\n return { result: true };\n }\n\n getContext(): LDContext | undefined {\n // The LDContext returned here may have been modified by the SDK (for example: adding auto env attributes).\n // We are returning an LDContext here to maintain a consistent representation of context to the consuming\n // code. We are returned the unchecked context so that if a consumer identifies with an invalid context\n // and then calls getContext, they get back the same context they provided, without any assertion about\n // validity.\n return this._activeContextTracker.hasContext()\n ? clone<LDContext>(this._activeContextTracker.getUnwrappedContext())\n : undefined;\n }\n\n protected getInternalContext(): Context | undefined {\n return this._activeContextTracker.getContext();\n }\n\n /**\n * Preset flags are used to set the flags before the client is initialized. This is useful for\n * when client has precached flags that are ready to evaluate without full initialization.\n * @param newFlags - The flags to preset.\n */\n protected presetFlags(newFlags: { [key: string]: ItemDescriptor }) {\n this._flagManager.presetFlags(newFlags);\n }\n\n /**\n * Identifies a context to LaunchDarkly. See {@link LDClient.identify}.\n *\n * If used with the `sheddable` option set to true, then the identify operation will be sheddable. This means that if\n * multiple identify operations are done, without waiting for the previous one to complete, then intermediate\n * operations may be discarded.\n *\n * It is recommended to use the `identifyResult` method instead when the operation is sheddable. In a future release,\n * all identify operations will default to being sheddable.\n *\n * @param pristineContext The LDContext object to be identified.\n * @param identifyOptions Optional configuration. See {@link LDIdentifyOptions}.\n * @returns A Promise which resolves when the flag values for the specified\n * context are available. It rejects when:\n *\n * 1. The context is unspecified or has no key.\n *\n * 2. The identify timeout is exceeded. In client SDKs this defaults to 5s.\n * You can customize this timeout with {@link LDIdentifyOptions | identifyOptions}.\n *\n * 3. A network error is encountered during initialization.\n */\n async identify(pristineContext: LDContext, identifyOptions?: LDIdentifyOptions): Promise<void> {\n // In order to manage customization in the derived classes it is important that `identify` MUST be implemented in\n // terms of `identifyResult`. So that the logic of the identification process can be extended in one place.\n const result = await this.identifyResult(pristineContext, identifyOptions);\n if (result.status === 'error') {\n throw result.error;\n } else if (result.status === 'timeout') {\n const timeoutError = new LDTimeoutError(\n `identify timed out after ${result.timeout} seconds.`,\n );\n this.logger.error(timeoutError.message);\n throw timeoutError;\n }\n // If completed or shed, then we are done.\n }\n\n async identifyResult(\n pristineContext: LDContext,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<LDIdentifyResult> {\n const identifyTimeout = identifyOptions?.timeout ?? DEFAULT_IDENTIFY_TIMEOUT_SECONDS;\n const noTimeout = identifyOptions?.timeout === undefined && identifyOptions?.noTimeout === true;\n\n // When noTimeout is specified, and a timeout is not specified, then this condition cannot\n // be encountered. (Our default would need to be greater)\n if (identifyTimeout > this._highTimeoutThreshold) {\n this.logger.warn(\n 'The identify function was called with a timeout greater than ' +\n `${this._highTimeoutThreshold} seconds. We recommend a timeout of less than ` +\n `${this._highTimeoutThreshold} seconds.`,\n );\n }\n\n const callSitePromise = this._identifyQueue\n .execute(\n {\n before: async () => {\n let context = await ensureKey(pristineContext, this.platform);\n if (this.autoEnvAttributes === AutoEnvAttributes.Enabled) {\n context = await addAutoEnv(context, this.platform, this._config);\n }\n const checkedContext = Context.fromLDContext(context);\n if (checkedContext.valid) {\n const afterIdentify = this._hookRunner.identify(context, identifyOptions?.timeout);\n return {\n context,\n checkedContext,\n afterIdentify,\n };\n }\n return {\n context,\n checkedContext,\n };\n },\n execute: async (beforeResult) => {\n const { context, checkedContext } = beforeResult!;\n if (!checkedContext.valid) {\n const error = new Error('Context was unspecified or had no key');\n this.emitter.emit('error', context, error);\n return Promise.reject(error);\n }\n this._activeContextTracker.set(context, checkedContext);\n\n this._eventProcessor?.sendEvent(\n this._eventFactoryDefault.identifyEvent(checkedContext),\n );\n const { identifyPromise, identifyResolve, identifyReject } =\n this._activeContextTracker.newIdentificationPromise();\n this.logger.debug(`Identifying ${JSON.stringify(checkedContext)}`);\n\n await this.dataManager.identify(\n identifyResolve,\n identifyReject,\n checkedContext,\n identifyOptions,\n );\n\n return identifyPromise;\n },\n after: async (res, beforeResult) => {\n if (res.status === 'complete') {\n beforeResult?.afterIdentify?.({ status: 'completed' });\n } else if (res.status === 'shed') {\n beforeResult?.afterIdentify?.({ status: 'shed' });\n } else if (res.status === 'error') {\n beforeResult?.afterIdentify?.({ status: 'error' });\n }\n },\n },\n identifyOptions?.sheddable ?? false,\n )\n .then((res) => {\n if (res.status === 'error') {\n return { status: 'error', error: res.error } as LDIdentifyError;\n }\n if (res.status === 'shed') {\n return { status: 'shed' } as LDIdentifyShed;\n }\n this.emitter.emit('initialized');\n return { status: 'completed' } as LDIdentifySuccess;\n });\n\n if (noTimeout) {\n return callSitePromise;\n }\n\n const timeoutPromise = new Promise<LDIdentifyTimeout>((resolve) => {\n setTimeout(() => {\n resolve({ status: 'timeout', timeout: identifyTimeout } as LDIdentifyTimeout);\n }, identifyTimeout * 1000);\n });\n return Promise.race([callSitePromise, timeoutPromise]);\n }\n\n on(eventName: EventName, listener: Function): void {\n this.emitter.on(eventName, listener);\n }\n\n off(eventName: EventName, listener: Function): void {\n this.emitter.off(eventName, listener);\n }\n\n track(key: string, data?: any, metricValue?: number): void {\n if (!this._activeContextTracker.hasValidContext()) {\n this.logger.warn(ClientMessages.MissingContextKeyNoEvent);\n return;\n }\n\n // 0 is valid, so do not truthy check the metric value\n if (metricValue !== undefined && !TypeValidators.Number.is(metricValue)) {\n this.logger?.warn(ClientMessages.invalidMetricValue(typeof metricValue));\n }\n\n this._eventProcessor?.sendEvent(\n this._config.trackEventModifier(\n this._eventFactoryDefault.customEvent(\n key,\n this._activeContextTracker.getContext()!,\n data,\n metricValue,\n ),\n ),\n );\n\n this._hookRunner.afterTrack({\n key,\n // The context is pre-checked above, so we know it can be unwrapped.\n context: this._activeContextTracker.getUnwrappedContext()!,\n data,\n metricValue,\n });\n }\n\n private _variationInternal(\n flagKey: string,\n defaultValue: any,\n eventFactory: EventFactory,\n typeChecker?: (value: any) => [boolean, string],\n ): LDEvaluationDetail {\n // We are letting evaulations happen without a context. The main case for this\n // is when cached data is loaded, but the client is not fully initialized. In this\n // case, we will write out a warning for each evaluation attempt.\n\n // NOTE: we will be changing this behavior soon once we have a tracker on the\n // client initialization state.\n const hasContext = this._activeContextTracker.hasContext();\n if (!hasContext) {\n this.logger?.warn(\n 'Flag evaluation called before client is fully initialized, data from this evaulation could be stale.',\n );\n }\n\n const evalContext = this._activeContextTracker.getContext()!;\n const foundItem = this._flagManager.get(flagKey);\n\n if (foundItem === undefined || foundItem.flag.deleted) {\n const defVal = defaultValue ?? null;\n const error = new LDClientError(\n `Unknown feature flag \"${flagKey}\"; returning default value ${defVal}.`,\n );\n\n this.emitter.emit('error', this._activeContextTracker.getUnwrappedContext(), error);\n if (hasContext) {\n this._eventProcessor?.sendEvent(\n this._eventFactoryDefault.unknownFlagEvent(flagKey, defVal, evalContext),\n );\n }\n return createErrorEvaluationDetail(ErrorKinds.FlagNotFound, defaultValue);\n }\n\n const { reason, value, variation, prerequisites } = foundItem.flag;\n\n if (typeChecker) {\n const [matched, type] = typeChecker(value);\n if (!matched) {\n if (hasContext) {\n this._eventProcessor?.sendEvent(\n eventFactory.evalEventClient(\n flagKey,\n defaultValue, // track default value on type errors\n defaultValue,\n foundItem.flag,\n evalContext,\n reason,\n ),\n );\n }\n const error = new LDClientError(\n `Wrong type \"${type}\" for feature flag \"${flagKey}\"; returning default value`,\n );\n this.emitter.emit('error', this._activeContextTracker.getUnwrappedContext(), error);\n return createErrorEvaluationDetail(ErrorKinds.WrongType, defaultValue);\n }\n }\n\n const successDetail = createSuccessEvaluationDetail(value, variation, reason);\n if (value === undefined || value === null) {\n this.logger.debug('Result value is null. Providing default value.');\n successDetail.value = defaultValue;\n }\n\n prerequisites?.forEach((prereqKey) => {\n this._variationInternal(prereqKey, undefined, this._eventFactoryDefault);\n });\n if (hasContext) {\n this._eventProcessor?.sendEvent(\n eventFactory.evalEventClient(\n flagKey,\n value,\n defaultValue,\n foundItem.flag,\n evalContext,\n reason,\n ),\n );\n }\n return successDetail;\n }\n\n variation(flagKey: string, defaultValue?: LDFlagValue): LDFlagValue {\n const { value } = this._hookRunner.withEvaluation(\n flagKey,\n this._activeContextTracker.getUnwrappedContext(),\n defaultValue,\n () => this._variationInternal(flagKey, defaultValue, this._eventFactoryDefault),\n );\n return value;\n }\n variationDetail(flagKey: string, defaultValue?: LDFlagValue): LDEvaluationDetail {\n return this._hookRunner.withEvaluation(\n flagKey,\n this._activeContextTracker.getUnwrappedContext(),\n defaultValue,\n () => this._variationInternal(flagKey, defaultValue, this._eventFactoryWithReasons),\n );\n }\n\n private _typedEval<T>(\n key: string,\n defaultValue: T,\n eventFactory: EventFactory,\n typeChecker: (value: unknown) => [boolean, string],\n ): LDEvaluationDetailTyped<T> {\n return this._hookRunner.withEvaluation(\n key,\n this._activeContextTracker.getUnwrappedContext(),\n defaultValue,\n () => this._variationInternal(key, defaultValue, eventFactory, typeChecker),\n );\n }\n\n boolVariation(key: string, defaultValue: boolean): boolean {\n return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [\n TypeValidators.Boolean.is(value),\n TypeValidators.Boolean.getType(),\n ]).value;\n }\n\n jsonVariation(key: string, defaultValue: unknown): unknown {\n return this.variation(key, defaultValue);\n }\n\n numberVariation(key: string, defaultValue: number): number {\n return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [\n TypeValidators.Number.is(value),\n TypeValidators.Number.getType(),\n ]).value;\n }\n\n stringVariation(key: string, defaultValue: string): string {\n return this._typedEval(key, defaultValue, this._eventFactoryDefault, (value) => [\n TypeValidators.String.is(value),\n TypeValidators.String.getType(),\n ]).value;\n }\n\n boolVariationDetail(key: string, defaultValue: boolean): LDEvaluationDetailTyped<boolean> {\n return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [\n TypeValidators.Boolean.is(value),\n TypeValidators.Boolean.getType(),\n ]);\n }\n\n numberVariationDetail(key: string, defaultValue: number): LDEvaluationDetailTyped<number> {\n return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [\n TypeValidators.Number.is(value),\n TypeValidators.Number.getType(),\n ]);\n }\n\n stringVariationDetail(key: string, defaultValue: string): LDEvaluationDetailTyped<string> {\n return this._typedEval(key, defaultValue, this._eventFactoryWithReasons, (value) => [\n TypeValidators.String.is(value),\n TypeValidators.String.getType(),\n ]);\n }\n\n jsonVariationDetail(key: string, defaultValue: unknown): LDEvaluationDetailTyped<unknown> {\n return this.variationDetail(key, defaultValue);\n }\n\n addHook(hook: Hook): void {\n this._hookRunner.addHook(hook);\n }\n\n /**\n * Enable/Disable event sending.\n * @param enabled True to enable event processing, false to disable.\n * @param flush True to flush while disabling. Useful to flush on certain state transitions.\n */\n protected setEventSendingEnabled(enabled: boolean, flush: boolean): void {\n if (this._eventSendingEnabled === enabled) {\n return;\n }\n this._eventSendingEnabled = enabled;\n\n if (enabled) {\n this.logger.debug('Starting event processor');\n this._eventProcessor?.start();\n } else if (flush) {\n this.logger?.debug('Flushing event processor before disabling.');\n // Disable and flush.\n this.flush().then(() => {\n // While waiting for the flush event sending could be re-enabled, in which case\n // we do not want to close the event processor.\n if (!this._eventSendingEnabled) {\n this.logger?.debug('Stopping event processor.');\n this._eventProcessor?.close();\n }\n });\n } else {\n // Just disabled.\n this.logger?.debug('Stopping event processor.');\n this._eventProcessor?.close();\n }\n }\n\n protected sendEvent(event: internal.InputEvent): void {\n this._eventProcessor?.sendEvent(event);\n }\n\n protected getDebugOverrides(): LDDebugOverride | undefined {\n return this._flagManager.getDebugOverride?.();\n }\n\n private _handleInspectionChanged(flagKeys: Array<string>, type: FlagChangeType) {\n if (!this._inspectorManager.hasInspectors()) {\n return;\n }\n\n const details: Record<string, LDEvaluationDetail> = {};\n flagKeys.forEach((flagKey) => {\n const item = this._flagManager.get(flagKey);\n if (item?.flag && !item.flag.deleted) {\n const { reason, value, variation } = item.flag;\n details[flagKey] = createSuccessEvaluationDetail(value, variation, reason);\n } else {\n details[flagKey] = {\n value: undefined,\n // For backwards compatibility purposes reason and variationIndex are null instead of\n // being undefined.\n reason: null,\n variationIndex: null,\n };\n }\n });\n if (type === 'init') {\n this._inspectorManager.onFlagsChanged(details);\n } else if (type === 'patch') {\n Object.entries(details).forEach(([flagKey, detail]) => {\n this._inspectorManager.onFlagChanged(flagKey, detail);\n });\n }\n }\n}\n","import { internal, LDLogger } from '@launchdarkly/js-sdk-common';\n\nimport { LDPluginBase } from '../api';\nimport { LDDebugOverride } from '../flag-manager/FlagManager';\n\n/**\n * Safe register debug override plugins.\n *\n * @param logger The logger to use for logging errors.\n * @param debugOverride The debug override to register.\n * @param plugins The plugins to register.\n */\nexport function safeRegisterDebugOverridePlugins<TClient, THook>(\n logger: LDLogger,\n debugOverride: LDDebugOverride,\n plugins: LDPluginBase<TClient, THook>[],\n): void {\n plugins.forEach((plugin) => {\n try {\n plugin.registerDebug?.(debugOverride);\n } catch (error) {\n logger.error(`Exception thrown registering plugin ${internal.safeGetName(logger, plugin)}.`);\n }\n });\n}\n","import { Context, LDLogger, LDPollingError, LDStreamingError } from '@launchdarkly/js-sdk-common';\n\nimport { FlagManager } from '../flag-manager/FlagManager';\nimport { ItemDescriptor } from '../flag-manager/ItemDescriptor';\nimport { DeleteFlag, Flags, PatchFlag } from '../types';\nimport { DataSourceState } from './DataSourceStatus';\nimport DataSourceStatusManager from './DataSourceStatusManager';\n\nexport default class DataSourceEventHandler {\n constructor(\n private readonly _flagManager: FlagManager,\n private readonly _statusManager: DataSourceStatusManager,\n private readonly _logger: LDLogger,\n ) {}\n\n async handlePut(context: Context, flags: Flags) {\n this._logger.debug(`Got PUT: ${Object.keys(flags)}`);\n\n // mapping flags to item descriptors\n const descriptors = Object.entries(flags).reduce(\n (acc: { [k: string]: ItemDescriptor }, [key, flag]) => {\n acc[key] = { version: flag.version, flag };\n return acc;\n },\n {},\n );\n await this._flagManager.init(context, descriptors);\n this._statusManager.requestStateUpdate(DataSourceState.Valid);\n }\n\n async handlePatch(context: Context, patchFlag: PatchFlag) {\n this._logger.debug(`Got PATCH ${JSON.stringify(patchFlag, null, 2)}`);\n this._flagManager.upsert(context, patchFlag.key, {\n version: patchFlag.version,\n flag: patchFlag,\n });\n }\n\n async handleDelete(context: Context, deleteFlag: DeleteFlag) {\n this._logger.debug(`Got DELETE ${JSON.stringify(deleteFlag, null, 2)}`);\n\n this._flagManager.upsert(context, deleteFlag.key, {\n version: deleteFlag.version,\n flag: {\n ...deleteFlag,\n deleted: true,\n // props below are set to sensible defaults. they are irrelevant\n // because this flag has been deleted.\n flagVersion: 0,\n value: undefined,\n variation: 0,\n trackEvents: false,\n },\n });\n }\n\n handleStreamingError(error: LDStreamingError) {\n this._statusManager.reportError(error.kind, error.message, error.code, error.recoverable);\n }\n\n handlePollingError(error: LDPollingError) {\n this._statusManager.reportError(error.kind, error.message, error.status, error.recoverable);\n }\n}\n","import { DataSourceErrorKind } from '@launchdarkly/js-sdk-common';\n\nimport LDEmitter from '../LDEmitter';\nimport DataSourceStatus, { DataSourceState } from './DataSourceStatus';\nimport DataSourceStatusErrorInfo from './DataSourceStatusErrorInfo';\n\n/**\n * Tracks the current data source status and emits updates when the status changes.\n */\nexport default class DataSourceStatusManager {\n private _state: DataSourceState;\n private _stateSinceMillis: number; // UNIX epoch timestamp in milliseconds\n private _errorInfo?: DataSourceStatusErrorInfo;\n private _timeStamper: () => number;\n\n constructor(\n private readonly _emitter: LDEmitter,\n timeStamper: () => number = () => Date.now(),\n ) {\n this._state = DataSourceState.Closed;\n this._stateSinceMillis = timeStamper();\n this._timeStamper = timeStamper;\n }\n\n get status(): DataSourceStatus {\n return {\n state: this._state,\n stateSince: this._stateSinceMillis,\n lastError: this._errorInfo,\n };\n }\n\n /**\n * Updates the state of the manager.\n *\n * @param requestedState to track\n * @param isError to indicate that the state update is a result of an error occurring.\n */\n private _updateState(requestedState: DataSourceState, isError = false) {\n const newState =\n requestedState === DataSourceState.Interrupted && this._state === DataSourceState.Initializing // don't go to interrupted from initializing (recoverable errors when initializing are not noteworthy)\n ? DataSourceState.Initializing\n : requestedState;\n\n const changedState = this._state !== newState;\n if (changedState) {\n this._state = newState;\n this._stateSinceMillis = this._timeStamper();\n }\n\n if (changedState || isError) {\n this._emitter.emit('dataSourceStatus', this.status);\n }\n }\n\n /**\n * Requests the manager move to the provided state. This request may be ignored\n * if the current state cannot transition to the requested state.\n * @param state that is requested\n */\n requestStateUpdate(state: DataSourceState) {\n this._updateState(state);\n }\n\n /**\n * Reports a datasource error to this manager. Since the {@link DataSourceStatus} includes error\n * information, it is possible that that a {@link DataSourceStatus} update is emitted with\n * the same {@link DataSourceState}.\n *\n * @param kind of the error\n * @param message for the error\n * @param statusCode of the error if there was one\n * @param recoverable to indicate that the error is anticipated to be recoverable\n */\n reportError(\n kind: DataSourceErrorKind,\n message: string,\n statusCode?: number,\n recoverable: boolean = false,\n ) {\n const errorInfo: DataSourceStatusErrorInfo = {\n kind,\n message,\n statusCode,\n time: this._timeStamper(),\n };\n this._errorInfo = errorInfo;\n this._updateState(recoverable ? DataSourceState.Interrupted : DataSourceState.Closed, true);\n }\n\n // TODO: SDK-702 - Implement network availability behaviors\n // setNetworkUnavailable() {\n // this.updateState(DataSourceState.NetworkUnavailable);\n // }\n}\n","import {\n DataSourceErrorKind,\n httpErrorMessage,\n HttpErrorResponse,\n isHttpRecoverable,\n LDLogger,\n LDPollingError,\n subsystem,\n} from '@launchdarkly/js-sdk-common';\n\nimport Requestor, { LDRequestError } from '../datasource/Requestor';\nimport { Flags } from '../types';\n\nexport type PollingErrorHandler = (err: LDPollingError) => void;\n\nfunction reportClosed(logger?: LDLogger) {\n logger?.debug(`Poll completed after the processor was closed. Skipping processing.`);\n}\n\n/**\n * @internal\n */\nexport default class PollingProcessor implements subsystem.LDStreamProcessor {\n private _stopped = false;\n\n private _timeoutHandle: any;\n\n constructor(\n private readonly _requestor: Requestor,\n private readonly _pollIntervalSeconds: number,\n private readonly _dataHandler: (flags: Flags) => void,\n private readonly _errorHandler?: PollingErrorHandler,\n private readonly _logger?: LDLogger,\n ) {}\n\n private async _poll() {\n if (this._stopped) {\n return;\n }\n\n const reportJsonError = (data: string) => {\n this._logger?.error('Polling received invalid data');\n this._logger?.debug(`Invalid JSON follows: ${data}`);\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.InvalidData,\n 'Malformed JSON data in polling response',\n ),\n );\n };\n\n this._logger?.debug('Polling LaunchDarkly for feature flag updates');\n const startTime = Date.now();\n try {\n const res = await this._requestor.requestPayload();\n try {\n // If the processor has been stopped, we discard the response.\n // This response could be for a no longer active context.\n if (this._stopped) {\n reportClosed(this._logger);\n return;\n }\n const flags = JSON.parse(res);\n try {\n this._dataHandler?.(flags);\n } catch (err) {\n this._logger?.error(`Exception from data handler: ${err}`);\n }\n } catch {\n reportJsonError(res);\n }\n } catch (err) {\n // If the processor has been stopped, we discard this error.\n // The original caller would consider this connection no longer active.\n if (this._stopped) {\n reportClosed(this._logger);\n return;\n }\n const requestError = err as LDRequestError;\n if (requestError.status !== undefined) {\n if (!isHttpRecoverable(requestError.status)) {\n this._logger?.error(httpErrorMessage(err as HttpErrorResponse, 'polling request'));\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.ErrorResponse,\n requestError.message,\n requestError.status,\n ),\n );\n return;\n }\n }\n this._logger?.error(\n httpErrorMessage(err as HttpErrorResponse, 'polling request', 'will retry'),\n );\n }\n\n const elapsed = Date.now() - startTime;\n const sleepFor = Math.max(this._pollIntervalSeconds * 1000 - elapsed, 0);\n\n this._logger?.debug('Elapsed: %d ms, sleeping for %d ms', elapsed, sleepFor);\n\n this._timeoutHandle = setTimeout(() => {\n this._poll();\n }, sleepFor);\n }\n\n start() {\n this._poll();\n }\n\n stop() {\n if (this._timeoutHandle) {\n clearTimeout(this._timeoutHandle);\n this._timeoutHandle = undefined;\n }\n this._stopped = true;\n }\n\n close() {\n this.stop();\n }\n}\n","import {\n DataSourceErrorKind,\n Encoding,\n EventName,\n EventSource,\n getStreamingUri,\n httpErrorMessage,\n HttpErrorResponse,\n internal,\n LDLogger,\n LDPollingError,\n LDStreamingError,\n ProcessStreamResponse,\n Requests,\n shouldRetry,\n StreamingErrorHandler,\n subsystem,\n} from '@launchdarkly/js-sdk-common';\n\nimport { StreamingDataSourceConfig } from '../datasource/DataSourceConfig';\nimport Requestor, { LDRequestError } from '../datasource/Requestor';\n\nconst reportJsonError = (\n type: string,\n data: string,\n logger?: LDLogger,\n errorHandler?: StreamingErrorHandler,\n) => {\n logger?.error(`Stream received invalid data in \"${type}\" message`);\n logger?.debug(`Invalid JSON follows: ${data}`);\n errorHandler?.(\n new LDStreamingError(DataSourceErrorKind.InvalidData, 'Malformed JSON data in event stream'),\n );\n};\n\nfunction reportEventClosed(eventName: string, logger?: LDLogger) {\n logger?.debug(`Received ${eventName} event after processor was closed. Skipping processing.`);\n}\n\nfunction reportPingClosed(logger?: LDLogger) {\n logger?.debug('Ping completed after processor was closed. Skipping processing.');\n}\n\nclass StreamingProcessor implements subsystem.LDStreamProcessor {\n private readonly _headers: { [key: string]: string | string[] };\n private readonly _streamUri: string;\n\n private _eventSource?: EventSource;\n private _connectionAttemptStartTime?: number;\n private _stopped = false;\n\n constructor(\n private readonly _plainContextString: string,\n private readonly _dataSourceConfig: StreamingDataSourceConfig,\n private readonly _listeners: Map<EventName, ProcessStreamResponse>,\n private readonly _requests: Requests,\n encoding: Encoding,\n private readonly _pollingRequestor: Requestor,\n private readonly _diagnosticsManager?: internal.DiagnosticsManager,\n private readonly _errorHandler?: StreamingErrorHandler,\n private readonly _logger?: LDLogger,\n ) {\n let path: string;\n if (_dataSourceConfig.useReport && !_requests.getEventSourceCapabilities().customMethod) {\n path = _dataSourceConfig.paths.pathPing(encoding, _plainContextString);\n } else {\n path = _dataSourceConfig.useReport\n ? _dataSourceConfig.paths.pathReport(encoding, _plainContextString)\n : _dataSourceConfig.paths.pathGet(encoding, _plainContextString);\n }\n const parameters: { key: string; value: string }[] = [\n ...(_dataSourceConfig.queryParameters ?? []),\n ];\n if (this._dataSourceConfig.withReasons) {\n parameters.push({ key: 'withReasons', value: 'true' });\n }\n\n this._requests = _requests;\n this._headers = { ..._dataSourceConfig.baseHeaders };\n this._logger = _logger;\n this._streamUri = getStreamingUri(_dataSourceConfig.serviceEndpoints, path, parameters);\n }\n\n private _logConnectionStarted() {\n this._connectionAttemptStartTime = Date.now();\n }\n\n private _logConnectionResult(success: boolean) {\n if (this._connectionAttemptStartTime && this._diagnosticsManager) {\n this._diagnosticsManager.recordStreamInit(\n this._connectionAttemptStartTime,\n !success,\n Date.now() - this._connectionAttemptStartTime,\n );\n }\n\n this._connectionAttemptStartTime = undefined;\n }\n\n /**\n * This is a wrapper around the passed errorHandler which adds additional\n * diagnostics and logging logic.\n *\n * @param err The error to be logged and handled.\n * @return boolean whether to retry the connection.\n *\n * @private\n */\n private _retryAndHandleError(err: HttpErrorResponse) {\n if (!shouldRetry(err)) {\n this._logConnectionResult(false);\n this._errorHandler?.(\n new LDStreamingError(DataSourceErrorKind.ErrorResponse, err.message, err.status, false),\n );\n this._logger?.error(httpErrorMessage(err, 'streaming request'));\n return false;\n }\n\n this._logger?.warn(httpErrorMessage(err, 'streaming request', 'will retry'));\n this._logConnectionResult(false);\n this._logConnectionStarted();\n return true;\n }\n\n start() {\n this._logConnectionStarted();\n\n let methodAndBodyOverrides;\n if (this._dataSourceConfig.useReport) {\n // REPORT will include a body, so content type is required.\n this._headers['content-type'] = 'application/json';\n\n // orverrides default method with REPORT and adds body.\n methodAndBodyOverrides = { method: 'REPORT', body: this._plainContextString };\n } else {\n // no method or body override\n methodAndBodyOverrides = {};\n }\n\n // TLS is handled by the platform implementation.\n const eventSource = this._requests.createEventSource(this._streamUri, {\n headers: this._headers, // adds content-type header required when body will be present\n ...methodAndBodyOverrides,\n errorFilter: (error: HttpErrorResponse) => this._retryAndHandleError(error),\n initialRetryDelayMillis: this._dataSourceConfig.initialRetryDelayMillis,\n readTimeoutMillis: 5 * 60 * 1000,\n retryResetIntervalMillis: 60 * 1000,\n });\n this._eventSource = eventSource;\n\n eventSource.onclose = () => {\n this._logger?.info('Closed LaunchDarkly stream connection');\n };\n\n eventSource.onerror = () => {\n // The work is done by `errorFilter`.\n };\n\n eventSource.onopen = () => {\n this._logger?.info('Opened LaunchDarkly stream connection');\n };\n\n eventSource.onretrying = (e) => {\n this._logger?.info(`Will retry stream connection in ${e.delayMillis} milliseconds`);\n };\n\n this._listeners.forEach(({ deserializeData, processJson }, eventName) => {\n eventSource.addEventListener(eventName, (event) => {\n // If an event comes in after the processor has been stopped, we skip processing it.\n // This event could be for a context which is no longer active.\n if (this._stopped) {\n reportEventClosed(eventName, this._logger);\n return;\n }\n\n this._logger?.debug(`Received ${eventName} event`);\n\n if (event?.data) {\n this._logConnectionResult(true);\n const { data } = event;\n const dataJson = deserializeData(data);\n\n if (!dataJson) {\n reportJsonError(eventName, data, this._logger, this._errorHandler);\n return;\n }\n processJson(dataJson);\n } else {\n this._errorHandler?.(\n new LDStreamingError(\n DataSourceErrorKind.InvalidData,\n 'Unexpected payload from event stream',\n ),\n );\n }\n });\n });\n\n // here we set up a listener that will poll when ping is received\n eventSource.addEventListener('ping', async () => {\n this._logger?.debug('Got PING, going to poll LaunchDarkly for feature flag updates');\n try {\n const res = await this._pollingRequestor.requestPayload();\n try {\n // If the ping completes after the processor has been stopped, then we discard it.\n // This event could be for a context which is no longer active.\n if (this._stopped) {\n reportPingClosed(this._logger);\n return;\n }\n const payload = JSON.parse(res);\n try {\n // forward the payload on to the PUT listener\n this._listeners.get('put')?.processJson(payload);\n } catch (err) {\n this._logger?.error(`Exception from data handler: ${err}`);\n }\n } catch {\n this._logger?.error('Polling after ping received invalid data');\n this._logger?.debug(`Invalid JSON follows: ${res}`);\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.InvalidData,\n 'Malformed JSON data in ping polling response',\n ),\n );\n }\n } catch (err) {\n if (this._stopped) {\n // If the ping errors after the processor has been stopped, then we discard it.\n // The original caller would consider this connection no longer active.\n reportPingClosed(this._logger);\n return;\n }\n const requestError = err as LDRequestError;\n this._errorHandler?.(\n new LDPollingError(\n DataSourceErrorKind.ErrorResponse,\n requestError.message,\n requestError.status,\n ),\n );\n }\n });\n }\n\n stop() {\n this._eventSource?.close();\n this._eventSource = undefined;\n this._stopped = true;\n }\n\n close() {\n this.stop();\n }\n}\n\nexport default StreamingProcessor;\n","import {\n Context,\n EventName,\n internal,\n LDContext,\n LDHeaders,\n LDLogger,\n Platform,\n ProcessStreamResponse,\n subsystem,\n} from '@launchdarkly/js-sdk-common';\n\nimport { LDIdentifyOptions } from './api/LDIdentifyOptions';\nimport { Configuration } from './configuration/Configuration';\nimport DataSourceEventHandler from './datasource/DataSourceEventHandler';\nimport { DataSourceState } from './datasource/DataSourceStatus';\nimport DataSourceStatusManager from './datasource/DataSourceStatusManager';\nimport Requestor from './datasource/Requestor';\nimport { FlagManager } from './flag-manager/FlagManager';\nimport LDEmitter from './LDEmitter';\nimport PollingProcessor from './polling/PollingProcessor';\nimport { DataSourcePaths, StreamingProcessor } from './streaming';\nimport { DeleteFlag, Flags, PatchFlag } from './types';\n\nexport interface DataManager {\n /**\n * This function handles the data management aspects of the identification process.\n *\n * Implementation Note: The identifyResolve and identifyReject function resolve or reject the\n * identify function at LDClient level. It is likely in individual implementations that these\n * functions will be passed to other components, such as a datasource, do indicate when the\n * identify process has been completed. The data manager identify function should return once\n * everything has been set in motion to complete the identification process.\n *\n * @param identifyResolve Called to reject the identify operation.\n * @param identifyReject Called to complete the identify operation.\n * @param context The context being identified.\n * @param identifyOptions Options for identification.\n */\n identify(\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n context: Context,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<void>;\n\n /**\n * Closes the data manager. Any active connections are closed.\n */\n close(): void;\n}\n\n/**\n * Factory interface for constructing data managers.\n */\nexport interface DataManagerFactory {\n (\n flagManager: FlagManager,\n configuration: Configuration,\n baseHeaders: LDHeaders,\n emitter: LDEmitter,\n diagnosticsManager?: internal.DiagnosticsManager,\n ): DataManager;\n}\n\nexport interface ConnectionParams {\n queryParameters?: { key: string; value: string }[];\n}\n\nexport abstract class BaseDataManager implements DataManager {\n protected updateProcessor?: subsystem.LDStreamProcessor;\n protected readonly logger: LDLogger;\n protected context?: Context;\n private _connectionParams?: ConnectionParams;\n protected readonly dataSourceStatusManager: DataSourceStatusManager;\n private readonly _dataSourceEventHandler: DataSourceEventHandler;\n protected closed = false;\n\n constructor(\n protected readonly platform: Platform,\n protected readonly flagManager: FlagManager,\n protected readonly credential: string,\n protected readonly config: Configuration,\n protected readonly getPollingPaths: () => DataSourcePaths,\n protected readonly getStreamingPaths: () => DataSourcePaths,\n protected readonly baseHeaders: LDHeaders,\n protected readonly emitter: LDEmitter,\n protected readonly diagnosticsManager?: internal.DiagnosticsManager,\n ) {\n this.logger = config.logger;\n this.dataSourceStatusManager = new DataSourceStatusManager(emitter);\n this._dataSourceEventHandler = new DataSourceEventHandler(\n flagManager,\n this.dataSourceStatusManager,\n this.config.logger,\n );\n }\n\n /**\n * Set additional connection parameters for requests polling/streaming.\n */\n protected setConnectionParams(connectionParams?: ConnectionParams) {\n this._connectionParams = connectionParams;\n }\n\n abstract identify(\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n context: Context,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<void>;\n\n protected createPollingProcessor(\n context: LDContext,\n checkedContext: Context,\n requestor: Requestor,\n identifyResolve?: () => void,\n identifyReject?: (err: Error) => void,\n ) {\n const processor = new PollingProcessor(\n requestor,\n this.config.pollInterval,\n async (flags) => {\n await this._dataSourceEventHandler.handlePut(checkedContext, flags);\n identifyResolve?.();\n },\n (err) => {\n this.emitter.emit('error', context, err);\n this._dataSourceEventHandler.handlePollingError(err);\n identifyReject?.(err);\n },\n this.logger,\n );\n\n this.updateProcessor = this._decorateProcessorWithStatusReporting(\n processor,\n this.dataSourceStatusManager,\n );\n }\n\n protected createStreamingProcessor(\n context: LDContext,\n checkedContext: Context,\n pollingRequestor: Requestor,\n identifyResolve?: () => void,\n identifyReject?: (err: Error) => void,\n ) {\n const processor = new StreamingProcessor(\n JSON.stringify(context),\n {\n credential: this.credential,\n serviceEndpoints: this.config.serviceEndpoints,\n paths: this.getStreamingPaths(),\n baseHeaders: this.baseHeaders,\n initialRetryDelayMillis: this.config.streamInitialReconnectDelay * 1000,\n withReasons: this.config.withReasons,\n useReport: this.config.useReport,\n queryParameters: this._connectionParams?.queryParameters,\n },\n this.createStreamListeners(checkedContext, identifyResolve),\n this.platform.requests,\n this.platform.encoding!,\n pollingRequestor,\n this.diagnosticsManager,\n (e) => {\n this.emitter.emit('error', context, e);\n this._dataSourceEventHandler.handleStreamingError(e);\n identifyReject?.(e);\n },\n this.logger,\n );\n\n this.updateProcessor = this._decorateProcessorWithStatusReporting(\n processor,\n this.dataSourceStatusManager,\n );\n }\n\n protected createStreamListeners(\n context: Context,\n identifyResolve?: () => void,\n ): Map<EventName, ProcessStreamResponse> {\n const listeners = new Map<EventName, ProcessStreamResponse>();\n\n listeners.set('put', {\n deserializeData: JSON.parse,\n processJson: async (flags: Flags) => {\n await this._dataSourceEventHandler.handlePut(context, flags);\n identifyResolve?.();\n },\n });\n\n listeners.set('patch', {\n deserializeData: JSON.parse,\n processJson: async (patchFlag: PatchFlag) => {\n this._dataSourceEventHandler.handlePatch(context, patchFlag);\n },\n });\n\n listeners.set('delete', {\n deserializeData: JSON.parse,\n processJson: async (deleteFlag: DeleteFlag) => {\n this._dataSourceEventHandler.handleDelete(context, deleteFlag);\n },\n });\n\n return listeners;\n }\n\n private _decorateProcessorWithStatusReporting(\n processor: subsystem.LDStreamProcessor,\n statusManager: DataSourceStatusManager,\n ): subsystem.LDStreamProcessor {\n return {\n start: () => {\n // update status before starting processor to ensure potential errors are reported after initializing\n statusManager.requestStateUpdate(DataSourceState.Initializing);\n processor.start();\n },\n stop: () => {\n processor.stop();\n statusManager.requestStateUpdate(DataSourceState.Closed);\n },\n close: () => {\n processor.close();\n statusManager.requestStateUpdate(DataSourceState.Closed);\n },\n };\n }\n\n public close() {\n this.updateProcessor?.close();\n this.closed = true;\n }\n}\n","import { Flag, ItemDescriptor, LDLogger } from '@launchdarkly/js-client-sdk-common';\n\nexport function readFlagsFromBootstrap(\n logger: LDLogger,\n data: any,\n): { [key: string]: ItemDescriptor } {\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(\n 'LaunchDarkly client was initialized with bootstrap data that did not include flag' +\n ' metadata. Events may not be sent correctly.',\n );\n }\n if (data[validKey] === false) {\n logger.warn(\n 'LaunchDarkly bootstrap data is not available because the back end could not read the flags.',\n );\n }\n const ret: { [key: string]: ItemDescriptor } = {};\n keys.forEach((key) => {\n if (key !== metadataKey && key !== validKey) {\n let flag: Flag;\n if (metadata && metadata[key]) {\n flag = {\n value: data[key],\n ...metadata[key],\n };\n } else {\n flag = {\n value: data[key],\n version: 0,\n };\n }\n ret[key] = {\n version: flag.version,\n flag,\n };\n }\n });\n return ret;\n}\n","/**\n * All access to browser specific APIs should be limited to this file.\n * Care should be taken to ensure that any given method will work in the service worker API. So if\n * something isn't available in the service worker API attempt to provide reasonable defaults.\n */\n\nexport function isDocument() {\n return typeof document !== undefined;\n}\n\nexport function isWindow() {\n return typeof window !== undefined;\n}\n\n/**\n * Register an event handler on the document. If there is no document, such as when running in\n * a service worker, then no operation is performed.\n *\n * @param type The event type to register a handler for.\n * @param listener The handler to register.\n * @param options Event registration options.\n * @returns a function which unregisters the handler.\n */\nexport function addDocumentEventListener(\n type: string,\n listener: (this: Document, ev: Event) => any,\n options?: boolean | AddEventListenerOptions,\n): () => void {\n if (isDocument()) {\n document.addEventListener(type, listener, options);\n return () => {\n document.removeEventListener(type, listener, options);\n };\n }\n // No document, so no need to unregister anything.\n return () => {};\n}\n\n/**\n * Register an event handler on the window. If there is no window, such as when running in\n * a service worker, then no operation is performed.\n *\n * @param type The event type to register a handler for.\n * @param listener The handler to register.\n * @param options Event registration options.\n * @returns a function which unregisters the handler.\n */\nexport function addWindowEventListener(\n type: string,\n listener: (this: Document, ev: Event) => any,\n options?: boolean | AddEventListenerOptions,\n): () => void {\n if (isDocument()) {\n window.addEventListener(type, listener, options);\n return () => {\n window.removeEventListener(type, listener, options);\n };\n }\n // No document, so no need to unregister anything.\n return () => {};\n}\n\n/**\n * For non-window code this will always be an empty string.\n */\nexport function getHref(): string {\n if (isWindow()) {\n return window.location.href;\n }\n return '';\n}\n\n/**\n * For non-window code this will always be an empty string.\n */\nexport function getLocationSearch(): string {\n if (isWindow()) {\n return window.location.search;\n }\n return '';\n}\n\n/**\n * For non-window code this will always be an empty string.\n */\nexport function getLocationHash(): string {\n if (isWindow()) {\n return window.location.hash;\n }\n return '';\n}\n\nexport function getCrypto(): Crypto {\n if (typeof crypto !== undefined) {\n return crypto;\n }\n // This would indicate running in an environment that doesn't have window.crypto or self.crypto.\n throw Error('Access to a web crypto API is required');\n}\n\n/**\n * Get the visibility state. For non-documents this will always be 'invisible'.\n *\n * @returns The document visibility.\n */\nexport function getVisibility(): string {\n if (isDocument()) {\n return document.visibilityState;\n }\n return 'visibile';\n}\n\nexport function querySelectorAll(selector: string): NodeListOf<Element> | undefined {\n if (isDocument()) {\n return document.querySelectorAll(selector);\n }\n return undefined;\n}\n","import {\n BaseDataManager,\n Configuration,\n Context,\n DataSourceErrorKind,\n DataSourcePaths,\n DataSourceState,\n FlagManager,\n httpErrorMessage,\n internal,\n LDEmitter,\n LDHeaders,\n LDIdentifyOptions,\n makeRequestor,\n Platform,\n shouldRetry,\n sleep,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { readFlagsFromBootstrap } from './bootstrap';\nimport { BrowserIdentifyOptions } from './BrowserIdentifyOptions';\nimport { ValidatedOptions } from './options';\n\nconst logTag = '[BrowserDataManager]';\n\nexport default class BrowserDataManager extends BaseDataManager {\n // If streaming is forced on or off, then we follow that setting.\n // Otherwise we automatically manage streaming state.\n private _forcedStreaming?: boolean = undefined;\n private _automaticStreamingState: boolean = false;\n private _secureModeHash?: string;\n\n // +-----------+-----------+---------------+\n // | forced | automatic | state |\n // +-----------+-----------+---------------+\n // | true | false | streaming |\n // | true | true | streaming |\n // | false | true | not streaming |\n // | false | false | not streaming |\n // | undefined | true | streaming |\n // | undefined | false | not streaming |\n // +-----------+-----------+---------------+\n\n constructor(\n platform: Platform,\n flagManager: FlagManager,\n credential: string,\n config: Configuration,\n private readonly _browserConfig: ValidatedOptions,\n getPollingPaths: () => DataSourcePaths,\n getStreamingPaths: () => DataSourcePaths,\n baseHeaders: LDHeaders,\n emitter: LDEmitter,\n diagnosticsManager?: internal.DiagnosticsManager,\n ) {\n super(\n platform,\n flagManager,\n credential,\n config,\n getPollingPaths,\n getStreamingPaths,\n baseHeaders,\n emitter,\n diagnosticsManager,\n );\n this._forcedStreaming = _browserConfig.streaming;\n }\n\n private _debugLog(message: any, ...args: any[]) {\n this.logger.debug(`${logTag} ${message}`, ...args);\n }\n\n override async identify(\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n context: Context,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<void> {\n if (this.closed) {\n this._debugLog('Identify called after data manager was closed.');\n return;\n }\n\n this.context = context;\n const browserIdentifyOptions = identifyOptions as BrowserIdentifyOptions | undefined;\n if (browserIdentifyOptions?.hash) {\n this.setConnectionParams({\n queryParameters: [{ key: 'h', value: browserIdentifyOptions.hash }],\n });\n } else {\n this.setConnectionParams();\n }\n this._secureModeHash = browserIdentifyOptions?.hash;\n\n if (browserIdentifyOptions?.bootstrap) {\n this._finishIdentifyFromBootstrap(context, browserIdentifyOptions.bootstrap, identifyResolve);\n } else {\n if (await this.flagManager.loadCached(context)) {\n this._debugLog('Identify - Flags loaded from cache. Continuing to initialize via a poll.');\n }\n\n await this._finishIdentifyFromPoll(context, identifyResolve, identifyReject);\n }\n this._updateStreamingState();\n }\n\n /**\n * A helper function for the initial poll request. This is mainly here to facilitate\n * the retry logic.\n *\n * @param context - LDContext to request payload for.\n * @returns Payload as a string.\n */\n private async _requestPayload(context: Context): Promise<string> {\n const plainContextString = JSON.stringify(Context.toLDContext(context));\n const pollingRequestor = makeRequestor(\n plainContextString,\n this.config.serviceEndpoints,\n this.getPollingPaths(),\n this.platform.requests,\n this.platform.encoding!,\n this.baseHeaders,\n [],\n this.config.withReasons,\n this.config.useReport,\n this._secureModeHash,\n );\n\n // NOTE: We are currently hardcoding in 3 retries for the initial\n // poll. We can make this configurable in the future.\n const maxRetries = 3;\n\n let lastError: any;\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n try {\n // eslint-disable-next-line no-await-in-loop\n return await pollingRequestor.requestPayload();\n } catch (e: any) {\n if (!shouldRetry(e)) {\n throw e;\n }\n lastError = e;\n // NOTE: current we are hardcoding the retry interval to 1 second.\n // We can make this configurable in the future.\n if (attempt < maxRetries) {\n this._debugLog(httpErrorMessage(e, 'initial poll request', 'will retry'));\n // eslint-disable-next-line no-await-in-loop\n await sleep(1000);\n }\n }\n }\n\n throw lastError;\n }\n\n private async _finishIdentifyFromPoll(\n context: Context,\n identifyResolve: () => void,\n identifyReject: (err: Error) => void,\n ) {\n try {\n this.dataSourceStatusManager.requestStateUpdate(DataSourceState.Initializing);\n\n const payload = await this._requestPayload(context);\n\n try {\n const listeners = this.createStreamListeners(context, identifyResolve);\n const putListener = listeners.get('put');\n putListener!.processJson(putListener!.deserializeData(payload));\n } catch (e: any) {\n this.dataSourceStatusManager.reportError(\n DataSourceErrorKind.InvalidData,\n e.message ?? 'Could not parse poll response',\n );\n }\n } catch (e: any) {\n this.dataSourceStatusManager.reportError(\n DataSourceErrorKind.NetworkError,\n e.message ?? 'unexpected network error',\n e.status,\n );\n identifyReject(e);\n }\n }\n\n private _finishIdentifyFromBootstrap(\n context: Context,\n bootstrap: unknown,\n identifyResolve: () => void,\n ) {\n this.flagManager.setBootstrap(context, readFlagsFromBootstrap(this.logger, bootstrap));\n this._debugLog('Identify - Initialization completed from bootstrap');\n identifyResolve();\n }\n\n setForcedStreaming(streaming?: boolean) {\n this._forcedStreaming = streaming;\n this._updateStreamingState();\n }\n\n setAutomaticStreamingState(streaming: boolean) {\n this._automaticStreamingState = streaming;\n this._updateStreamingState();\n }\n\n private _updateStreamingState() {\n const shouldBeStreaming =\n this._forcedStreaming ||\n (this._automaticStreamingState && this._forcedStreaming === undefined);\n\n this._debugLog(\n `Updating streaming state. forced(${this._forcedStreaming}) automatic(${this._automaticStreamingState})`,\n );\n\n if (shouldBeStreaming) {\n this._startDataSource();\n } else {\n this._stopDataSource();\n }\n }\n\n private _stopDataSource() {\n if (this.updateProcessor) {\n this._debugLog('Stopping update processor.');\n }\n this.updateProcessor?.close();\n this.updateProcessor = undefined;\n }\n\n private _startDataSource() {\n if (this.updateProcessor) {\n this._debugLog('Update processor already active. Not changing state.');\n return;\n }\n\n if (!this.context) {\n this._debugLog('Context not set, not starting update processor.');\n return;\n }\n\n this._debugLog('Starting update processor.');\n this._setupConnection(this.context);\n }\n\n private _setupConnection(\n context: Context,\n identifyResolve?: () => void,\n identifyReject?: (err: Error) => void,\n ) {\n const rawContext = Context.toLDContext(context)!;\n\n this.updateProcessor?.close();\n\n const plainContextString = JSON.stringify(Context.toLDContext(context));\n const pollingRequestor = makeRequestor(\n plainContextString,\n this.config.serviceEndpoints,\n this.getPollingPaths(),\n this.platform.requests,\n this.platform.encoding!,\n this.baseHeaders,\n [],\n this.config.withReasons,\n this.config.useReport,\n this._secureModeHash,\n );\n\n this.createStreamingProcessor(\n rawContext,\n context,\n pollingRequestor,\n identifyResolve,\n identifyReject,\n );\n\n this.updateProcessor!.start();\n }\n}\n","import { addDocumentEventListener, addWindowEventListener, getVisibility } from './BrowserApi';\n\nexport function registerStateDetection(requestFlush: () => void): () => void {\n // When the visibility of the page changes to hidden we want to flush any pending events.\n //\n // This is handled with visibility, instead of beforeunload/unload\n // because those events are not compatible with the bfcache and are unlikely\n // to be called in many situations. For more information see: https://developer.chrome.com/blog/page-lifecycle-api/\n //\n // Redundancy is included by using both the visibilitychange handler as well as\n // pagehide, because different browsers, and versions have different bugs with each.\n // This also may provide more opportunity for the events to get flushed.\n //\n const handleVisibilityChange = () => {\n if (getVisibility() === 'hidden') {\n requestFlush();\n }\n };\n\n const removeDocListener = addDocumentEventListener('visibilitychange', handleVisibilityChange);\n const removeWindowListener = addWindowEventListener('pagehide', requestFlush);\n\n return () => {\n removeDocListener();\n removeWindowListener();\n };\n}\n","// From here: https://github.com/sindresorhus/escape-string-regexp\n\n// This is vendored to reduce the complexity of the built and test setup.\n// The NPM package for escape-string-regexp is ESM only, and that introduces\n// complexity to the jest configuration which works best/easiest with CJS.\n\n/**\n * MIT License\n *\n * Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n *\n */\n\n/**\n * Escape regular expression especial characters.\n *\n * @param string The regular expression to escape.\n * @returns The escaped expression.\n */\nexport default function escapeStringRegexp(string: string) {\n if (typeof string !== 'string') {\n throw new TypeError('Expected a string');\n }\n\n // Escape characters with special meaning either inside or outside character sets.\n // Use a simple backslash escape when it’s always valid, and a `\\xnn` escape when the simpler form would be disallowed by Unicode patterns’ stricter grammar.\n return string.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&').replace(/-/g, '\\\\x2d');\n}\n","import {\n addDocumentEventListener,\n getHref,\n getLocationHash,\n getLocationSearch,\n querySelectorAll,\n} from '../BrowserApi';\nimport escapeStringRegexp from '../vendor/escapeStringRegexp';\nimport { ClickGoal, Goal, Matcher } from './Goals';\n\ntype EventHandler = (goal: Goal) => void;\n\nexport function matchesUrl(matcher: Matcher, href: string, search: string, hash: string) {\n /**\n * Hash fragments are included when they include forward slashes to allow for applications that\n * use path-like hashes. (http://example.com/url/path#/additional/path)\n *\n * When they do not include a forward slash they are considered anchors and are not included\n * in matching.\n */\n const keepHash = (matcher.kind === 'substring' || matcher.kind === 'regex') && hash.includes('/');\n // For most matching purposes we want the \"canonical\" URL, which in this context means the\n // excluding the query parameters and hash (unless the hash is path-like).\n const canonicalUrl = (keepHash ? href : href.replace(hash, '')).replace(search, '');\n\n switch (matcher.kind) {\n case 'exact':\n return new RegExp(`^${escapeStringRegexp(matcher.url)}/?$`).test(href);\n case 'canonical':\n return new RegExp(`^${escapeStringRegexp(matcher.url)}/?$`).test(canonicalUrl);\n case 'substring':\n return new RegExp(`.*${escapeStringRegexp(matcher.substring)}.*$`).test(canonicalUrl);\n case 'regex':\n return new RegExp(matcher.pattern).test(canonicalUrl);\n default:\n return false;\n }\n}\n\nfunction findGoalsForClick(event: Event, clickGoals: ClickGoal[]) {\n const matches: ClickGoal[] = [];\n\n clickGoals.forEach((goal) => {\n let target: Node | null = event.target as Node;\n const { selector } = goal;\n const elements = querySelectorAll(selector);\n\n // Traverse from the target of the event up the page hierarchy.\n // If there are no element that match the selector, then no need to check anything.\n while (target && elements?.length) {\n // The elements are a NodeList, so it doesn't have the array functions. For performance we\n // do not convert it to an array.\n for (let elementIndex = 0; elementIndex < elements.length; elementIndex += 1) {\n if (target === elements[elementIndex]) {\n matches.push(goal);\n // The same element should not be in the list multiple times.\n // Multiple objects in the hierarchy can match the selector, so we don't break the outer\n // loop.\n break;\n }\n }\n target = target.parentNode as Node;\n }\n });\n\n return matches;\n}\n\n/**\n * Tracks the goals on an individual \"page\" (combination of route, query params, and hash).\n */\nexport default class GoalTracker {\n private _cleanup?: () => void;\n constructor(goals: Goal[], onEvent: EventHandler) {\n const goalsMatchingUrl = goals.filter((goal) =>\n goal.urls?.some((matcher) =>\n matchesUrl(matcher, getHref(), getLocationSearch(), getLocationHash()),\n ),\n );\n\n const pageviewGoals = goalsMatchingUrl.filter((goal) => goal.kind === 'pageview');\n const clickGoals = goalsMatchingUrl.filter((goal) => goal.kind === 'click') as ClickGoal[];\n\n pageviewGoals.forEach((event) => onEvent(event));\n\n if (clickGoals.length) {\n // Click handler is not a member function in order to avoid having to bind it for the event\n // handler and then track a reference to that bound handler.\n const clickHandler = (event: Event) => {\n findGoalsForClick(event, clickGoals).forEach((clickGoal) => {\n onEvent(clickGoal);\n });\n };\n this._cleanup = addDocumentEventListener('click', clickHandler);\n }\n }\n\n /**\n * Close the tracker which stops listening to any events.\n */\n close() {\n this._cleanup?.();\n }\n}\n","import { addWindowEventListener, getHref } from '../BrowserApi';\n\nexport const LOCATION_WATCHER_INTERVAL_MS = 300;\n\n// Using any for the timer handle because the type is not the same for all\n// platforms and we only need to use it opaquely.\nexport type IntervalHandle = any;\n\nexport interface LocationWatcher {\n close(): void;\n}\n\n/**\n * Watches the browser URL and detects changes.\n *\n * This is used to detect URL changes for generating pageview events.\n *\n * @internal\n */\nexport class DefaultLocationWatcher {\n private _previousLocation?: string;\n private _watcherHandle: IntervalHandle;\n private _cleanupListeners?: () => void;\n\n /**\n * @param callback Callback that is executed whenever a URL change is detected.\n */\n constructor(callback: () => void) {\n this._previousLocation = getHref();\n const checkUrl = () => {\n const currentLocation = getHref();\n\n if (currentLocation !== this._previousLocation) {\n this._previousLocation = currentLocation;\n callback();\n }\n };\n /** The location is watched via polling and popstate events because it is possible to miss\n * navigation at certain points with just popstate. It is also to miss events with polling\n * because they can happen within the polling interval.\n * Details on when popstate is called:\n * https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event#when_popstate_is_sent\n */\n this._watcherHandle = setInterval(checkUrl, LOCATION_WATCHER_INTERVAL_MS);\n\n const removeListener = addWindowEventListener('popstate', checkUrl);\n\n this._cleanupListeners = () => {\n removeListener();\n };\n }\n\n /**\n * Stop watching for location changes.\n */\n close(): void {\n if (this._watcherHandle) {\n clearInterval(this._watcherHandle);\n }\n this._cleanupListeners?.();\n }\n}\n","import { LDUnexpectedResponseError, Requests } from '@launchdarkly/js-client-sdk-common';\n\nimport { getHref } from '../BrowserApi';\nimport { Goal } from './Goals';\nimport GoalTracker from './GoalTracker';\nimport { DefaultLocationWatcher, LocationWatcher } from './LocationWatcher';\n\nexport default class GoalManager {\n private _goals?: Goal[] = [];\n private _url: string;\n private _watcher?: LocationWatcher;\n private _tracker?: GoalTracker;\n private _isTracking = false;\n\n constructor(\n credential: string,\n private readonly _requests: Requests,\n baseUrl: string,\n private readonly _reportError: (err: Error) => void,\n private readonly _reportGoal: (url: string, goal: Goal) => void,\n locationWatcherFactory: (cb: () => void) => LocationWatcher = (cb) =>\n new DefaultLocationWatcher(cb),\n ) {\n // TODO: Generate URL in a better way.\n this._url = `${baseUrl}/sdk/goals/${credential}`;\n\n this._watcher = locationWatcherFactory(() => {\n this._createTracker();\n });\n }\n\n public async initialize(): Promise<void> {\n await this._fetchGoals();\n // If tracking has been started before goal fetching completes, we need to\n // create the tracker so it can start watching for events.\n this._createTracker();\n }\n\n public startTracking() {\n this._isTracking = true;\n this._createTracker();\n }\n\n private _createTracker() {\n if (!this._isTracking) {\n return;\n }\n this._tracker?.close();\n if (this._goals && this._goals.length) {\n this._tracker = new GoalTracker(this._goals, (goal) => {\n this._reportGoal(getHref(), goal);\n });\n }\n }\n\n private async _fetchGoals(): Promise<void> {\n try {\n const res = await this._requests.fetch(this._url);\n this._goals = await res.json();\n } catch (err) {\n this._reportError(new LDUnexpectedResponseError(`Encountered error fetching goals: ${err}`));\n }\n }\n\n close(): void {\n this._watcher?.close();\n this._tracker?.close();\n }\n}\n","export type GoalKind = 'click' | 'pageview';\n\nexport type MatcherKind = 'exact' | 'canonical' | 'substring' | 'regex';\n\nexport interface ExactMatcher {\n kind: 'exact';\n url: string;\n}\n\nexport interface SubstringMatcher {\n kind: 'substring';\n substring: string;\n}\n\nexport interface CanonicalMatcher {\n kind: 'canonical';\n url: string;\n}\n\nexport interface RegexMatcher {\n kind: 'regex';\n pattern: string;\n}\n\nexport type Matcher = ExactMatcher | SubstringMatcher | CanonicalMatcher | RegexMatcher;\n\nexport interface PageViewGoal {\n key: string;\n kind: 'pageview';\n urls?: Matcher[];\n}\n\nexport interface ClickGoal {\n key: string;\n kind: 'click';\n urls?: Matcher[];\n selector: string;\n}\n\nexport type Goal = PageViewGoal | ClickGoal;\n\nexport function isClick(goal: Goal): goal is ClickGoal {\n return goal.kind === 'click';\n}\n","import {\n LDLogger,\n LDOptions as LDOptionsBase,\n OptionMessages,\n TypeValidator,\n TypeValidators,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { LDPlugin } from './LDPlugin';\n\nconst DEFAULT_FLUSH_INTERVAL_SECONDS = 2;\n\n/**\n * Initialization options for the LaunchDarkly browser SDK.\n */\nexport interface BrowserOptions extends Omit<LDOptionsBase, 'initialConnectionMode'> {\n /**\n * Whether the client should make a request to LaunchDarkly for Experimentation metrics (goals).\n *\n * This is true by default, meaning that this request will be made on every page load.\n * Set it to false if you are not using Experimentation and want to skip the request.\n */\n fetchGoals?: boolean;\n\n /**\n * A function which, if present, can change the URL in analytics events to something other\n * than the actual browser URL. It will be called with the current browser URL as a parameter,\n * and returns the value that should be stored in the event's `url` property.\n *\n * It may be useful to customize the `url` to provide specific meaning, incorporate\n * client-side routing concerns, or redact tokens or other info.\n */\n eventUrlTransformer?: (url: string) => string;\n\n /**\n * Whether or not to open a streaming connection to LaunchDarkly for live flag updates.\n *\n * If this is true, the client will always attempt to maintain a streaming connection; if false,\n * it never will. If you leave the value undefined (the default), the client will open a streaming\n * connection if you subscribe to `\"change\"` or `\"change:flag-key\"` events.\n *\n * This is equivalent to calling `client.setStreaming()` with the same value.\n */\n streaming?: boolean;\n\n /**\n * Determines if the SDK responds to entering different visibility states, such as foreground and background.\n * An example is flushing buffered events when going to the background.\n *\n * This is true by default. Generally speaking the SDK will be able to most reliably deliver\n * events with this setting on.\n *\n * It may be useful to disable for environments where not all window/document objects are\n * available, such as when running the SDK in a browser extension.\n */\n automaticBackgroundHandling?: boolean;\n\n /**\n * A list of plugins to be used with the SDK.\n *\n * Plugin support is currently experimental and subject to change.\n */\n plugins?: LDPlugin[];\n}\n\nexport interface ValidatedOptions {\n fetchGoals: boolean;\n eventUrlTransformer: (url: string) => string;\n streaming?: boolean;\n automaticBackgroundHandling?: boolean;\n plugins: LDPlugin[];\n}\n\nconst optDefaults = {\n fetchGoals: true,\n eventUrlTransformer: (url: string) => url,\n streaming: undefined,\n plugins: [],\n};\n\nconst validators: { [Property in keyof BrowserOptions]: TypeValidator | undefined } = {\n fetchGoals: TypeValidators.Boolean,\n eventUrlTransformer: TypeValidators.Function,\n streaming: TypeValidators.Boolean,\n plugins: TypeValidators.createTypeArray('LDPlugin', {}),\n};\n\nfunction withBrowserDefaults(opts: BrowserOptions): BrowserOptions {\n const output = { ...opts };\n output.flushInterval ??= DEFAULT_FLUSH_INTERVAL_SECONDS;\n return output;\n}\n\nexport function filterToBaseOptionsWithDefaults(opts: BrowserOptions): LDOptionsBase {\n const baseOptions: LDOptionsBase = withBrowserDefaults(opts);\n\n // Remove any browser specific configuration keys so we don't get warnings from\n // the base implementation for unknown configuration.\n Object.keys(optDefaults).forEach((key) => {\n delete (baseOptions as any)[key];\n });\n return baseOptions;\n}\n\nexport default function validateBrowserOptions(\n opts: BrowserOptions,\n logger: LDLogger,\n): ValidatedOptions {\n const output: ValidatedOptions = { ...optDefaults };\n\n Object.entries(validators).forEach((entry) => {\n const [key, validator] = entry as [keyof BrowserOptions, TypeValidator];\n const value = opts[key];\n if (value !== undefined) {\n if (validator.is(value)) {\n output[key as keyof ValidatedOptions] = value as any;\n } else {\n logger.warn(OptionMessages.wrongOptionType(key, validator.getType(), typeof value));\n }\n }\n });\n\n return output;\n}\n","import { Hasher } from '@launchdarkly/js-client-sdk-common';\n\nexport default class BrowserHasher implements Hasher {\n private _data: string[] = [];\n private _algorithm: string;\n constructor(\n private readonly _webcrypto: Crypto,\n algorithm: string,\n ) {\n switch (algorithm) {\n case 'sha1':\n this._algorithm = 'SHA-1';\n break;\n case 'sha256':\n this._algorithm = 'SHA-256';\n break;\n default:\n throw new Error(`Algorithm is not supported ${algorithm}`);\n }\n }\n\n async asyncDigest(encoding: string): Promise<string> {\n const combinedData = this._data.join('');\n const encoded = new TextEncoder().encode(combinedData);\n const digestedBuffer = await this._webcrypto.subtle.digest(this._algorithm, encoded);\n switch (encoding) {\n case 'base64':\n return btoa(String.fromCharCode(...new Uint8Array(digestedBuffer)));\n case 'hex':\n // Convert the buffer to an array of uint8 values, then convert each of those to hex.\n // The map function on a Uint8Array directly only maps to other Uint8Arrays.\n return [...new Uint8Array(digestedBuffer)]\n .map((val) => val.toString(16).padStart(2, '0'))\n .join('');\n default:\n throw new Error(`Encoding is not supported ${encoding}`);\n }\n }\n\n update(data: string): Hasher {\n this._data.push(data);\n return this as Hasher;\n }\n}\n","// The implementation in this file generates UUIDs in v4 format and is suitable\n// for use as a UUID in LaunchDarkly events. It is not a rigorous implementation.\n\n// It uses crypto.randomUUID when available.\n// If crypto.randomUUID is not available, then it uses random values and forms\n// the UUID itself.\n// When possible it uses crypto.getRandomValues, but it can use Math.random\n// if crypto.getRandomValues is not available.\n\n// UUIDv4 Struct definition.\n// https://www.rfc-archive.org/getrfc.php?rfc=4122\n// Appendix A. Appendix A - Sample Implementation\nconst timeLow = {\n start: 0,\n end: 3,\n};\nconst timeMid = {\n start: 4,\n end: 5,\n};\nconst timeHiAndVersion = {\n start: 6,\n end: 7,\n};\nconst clockSeqHiAndReserved = {\n start: 8,\n end: 8,\n};\nconst clockSeqLow = {\n start: 9,\n end: 9,\n};\nconst nodes = {\n start: 10,\n end: 15,\n};\n\nfunction getRandom128bit(): number[] {\n if (crypto && crypto.getRandomValues) {\n const typedArray = new Uint8Array(16);\n crypto.getRandomValues(typedArray);\n return [...typedArray.values()];\n }\n const values = [];\n for (let index = 0; index < 16; index += 1) {\n // Math.random is 0-1 with inclusive min and exclusive max.\n values.push(Math.floor(Math.random() * 256));\n }\n return values;\n}\n\nfunction hex(bytes: number[], range: { start: number; end: number }): string {\n let strVal = '';\n for (let index = range.start; index <= range.end; index += 1) {\n strVal += bytes[index].toString(16).padStart(2, '0');\n }\n return strVal;\n}\n\n/**\n * Given a list of 16 random bytes generate a UUID in v4 format.\n *\n * Note: The input bytes are modified to conform to the requirements of UUID v4.\n *\n * @param bytes A list of 16 bytes.\n * @returns A UUID v4 string.\n */\nexport function formatDataAsUuidV4(bytes: number[]): string {\n // https://www.rfc-archive.org/getrfc.php?rfc=4122\n // 4.4. Algorithms for Creating a UUID from Truly Random or\n // Pseudo-Random Numbers\n\n // Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and\n // one, respectively.\n // eslint-disable-next-line no-bitwise, no-param-reassign\n bytes[clockSeqHiAndReserved.start] = (bytes[clockSeqHiAndReserved.start] | 0x80) & 0xbf;\n // Set the four most significant bits (bits 12 through 15) of the time_hi_and_version field to\n // the 4-bit version number from Section 4.1.3.\n // eslint-disable-next-line no-bitwise, no-param-reassign\n bytes[timeHiAndVersion.start] = (bytes[timeHiAndVersion.start] & 0x0f) | 0x40;\n\n return (\n `${hex(bytes, timeLow)}-${hex(bytes, timeMid)}-${hex(bytes, timeHiAndVersion)}-` +\n `${hex(bytes, clockSeqHiAndReserved)}${hex(bytes, clockSeqLow)}-${hex(bytes, nodes)}`\n );\n}\n\nexport function fallbackUuidV4(): string {\n const bytes = getRandom128bit();\n return formatDataAsUuidV4(bytes);\n}\n\nexport default function randomUuidV4(): string {\n if (typeof crypto !== undefined && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n\n return fallbackUuidV4();\n}\n","import { Crypto } from '@launchdarkly/js-client-sdk-common';\n\nimport { getCrypto } from '../BrowserApi';\nimport BrowserHasher from './BrowserHasher';\nimport randomUuidV4 from './randomUuidV4';\n\nexport default class BrowserCrypto implements Crypto {\n createHash(algorithm: string): BrowserHasher {\n return new BrowserHasher(getCrypto(), algorithm);\n }\n\n randomUUID(): string {\n return randomUuidV4();\n }\n}\n","import { Encoding } from '@launchdarkly/js-client-sdk-common';\n\nfunction bytesToBase64(bytes: Uint8Array) {\n const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join('');\n return btoa(binString);\n}\n\n/**\n * Implementation Note: This btoa handles unicode characters, which the base btoa in the browser\n * does not.\n * Background: https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem\n */\n\nexport default class BrowserEncoding implements Encoding {\n btoa(data: string): string {\n return bytesToBase64(new TextEncoder().encode(data));\n }\n}\n","import { Info, PlatformData, SdkData } from '@launchdarkly/js-client-sdk-common';\n\nexport default class BrowserInfo implements Info {\n constructor(private readonly _config: { wrapperName?: string; wrapperVersion?: string }) {}\n\n platformData(): PlatformData {\n return {\n name: 'JS', // Name maintained from previous 3.x implementation.\n };\n }\n\n sdkData(): SdkData {\n const data: SdkData = {\n name: '@launchdarkly/js-client-sdk',\n version: '0.11.0', // x-release-please-version\n userAgentBase: 'JSClient',\n };\n\n if (this._config.wrapperName) {\n data.wrapperName = this._config.wrapperName;\n }\n\n if (this._config.wrapperVersion) {\n data.wrapperVersion = this._config.wrapperVersion;\n }\n\n return data;\n }\n}\n","import {\n DefaultBackoff,\n EventListener,\n EventName,\n EventSourceInitDict,\n HttpErrorResponse,\n EventSource as LDEventSource,\n} from '@launchdarkly/js-client-sdk-common';\n\n/**\n * Implementation Notes:\n *\n * This event source does not support a read-timeout.\n * This event source does not support customized verbs.\n * This event source does not support headers.\n */\n\n/**\n * Browser event source implementation which extends the built-in event\n * source with additional reconnection logic.\n */\nexport default class DefaultBrowserEventSource implements LDEventSource {\n private _es?: EventSource;\n private _backoff: DefaultBackoff;\n private _errorFilter: (err: HttpErrorResponse) => boolean;\n\n // The type of the handle can be platform specific and we treat is opaquely.\n private _reconnectTimeoutHandle?: any;\n\n private _listeners: Record<string, EventListener[]> = {};\n\n constructor(\n private readonly _url: string,\n options: EventSourceInitDict,\n ) {\n this._backoff = new DefaultBackoff(\n options.initialRetryDelayMillis,\n options.retryResetIntervalMillis,\n );\n this._errorFilter = options.errorFilter;\n this._openConnection();\n }\n\n onclose: (() => void) | undefined;\n\n onerror: ((err?: HttpErrorResponse) => void) | undefined;\n\n onopen: (() => void) | undefined;\n\n onretrying: ((e: { delayMillis: number }) => void) | undefined;\n\n private _openConnection() {\n this._es = new EventSource(this._url);\n this._es.onopen = () => {\n this._backoff.success();\n this.onopen?.();\n };\n // The error could be from a polyfill, or from the browser event source, so we are loose on the\n // typing.\n this._es.onerror = (err: any) => {\n this._handleError(err);\n this.onerror?.(err);\n };\n Object.entries(this._listeners).forEach(([eventName, listeners]) => {\n listeners.forEach((listener) => {\n this._es?.addEventListener(eventName, listener);\n });\n });\n }\n\n addEventListener(type: EventName, listener: EventListener): void {\n this._listeners[type] ??= [];\n this._listeners[type].push(listener);\n this._es?.addEventListener(type, listener);\n }\n\n close(): void {\n // Ensure any pending retry attempts are not done.\n clearTimeout(this._reconnectTimeoutHandle);\n this._reconnectTimeoutHandle = undefined;\n\n // Close the event source and notify any listeners.\n this._es?.close();\n this.onclose?.();\n }\n\n private _tryConnect(delayMs: number) {\n this.onretrying?.({ delayMillis: delayMs });\n this._reconnectTimeoutHandle = setTimeout(() => {\n this._openConnection();\n }, delayMs);\n }\n\n private _handleError(err: any): void {\n this.close();\n\n // The event source may not produce a status. But the LaunchDarkly\n // polyfill can. If we can get the status, then we should stop retrying\n // on certain error codes.\n if (err.status && typeof err.status === 'number' && !this._errorFilter(err)) {\n // If we encounter an unrecoverable condition, then we do not want to\n // retry anymore.\n return;\n }\n\n this._tryConnect(this._backoff.fail());\n }\n}\n","import {\n EventSourceCapabilities,\n EventSourceInitDict,\n EventSource as LDEventSource,\n Options,\n Requests,\n Response,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport DefaultBrowserEventSource from './DefaultBrowserEventSource';\n\nexport default class BrowserRequests implements Requests {\n fetch(url: string, options?: Options): Promise<Response> {\n // @ts-ignore\n return fetch(url, options);\n }\n\n createEventSource(url: string, eventSourceInitDict: EventSourceInitDict): LDEventSource {\n return new DefaultBrowserEventSource(url, eventSourceInitDict);\n }\n\n getEventSourceCapabilities(): EventSourceCapabilities {\n return {\n customMethod: false,\n readTimeout: false,\n headers: false,\n };\n }\n}\n","import type { LDLogger, Storage } from '@launchdarkly/js-client-sdk-common';\n\nexport function isLocalStorageSupported() {\n // Checking a symbol using typeof is safe, but directly accessing a symbol\n // which is not defined would be an error.\n return typeof localStorage !== 'undefined';\n}\n\n/**\n * Implementation of Storage using localStorage for the browser.\n *\n * The Storage API is async, and localStorage is synchronous. This is fine,\n * and none of the methods need to internally await their operations.\n */\nexport default class PlatformStorage implements Storage {\n constructor(private readonly _logger?: LDLogger) {}\n async clear(key: string): Promise<void> {\n try {\n localStorage.removeItem(key);\n } catch (error) {\n this._logger?.error(`Error clearing key from localStorage: ${key}, reason: ${error}`);\n }\n }\n\n async get(key: string): Promise<string | null> {\n try {\n const value = localStorage.getItem(key);\n return value ?? null;\n } catch (error) {\n this._logger?.error(`Error getting key from localStorage: ${key}, reason: ${error}`);\n return null;\n }\n }\n\n async set(key: string, value: string): Promise<void> {\n try {\n localStorage.setItem(key, value);\n } catch (error) {\n this._logger?.error(`Error setting key in localStorage: ${key}, reason: ${error}`);\n }\n }\n}\n","import {\n Crypto,\n Encoding,\n Info,\n LDLogger,\n Platform,\n Requests,\n Storage,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { BrowserOptions } from '../options';\nimport BrowserCrypto from './BrowserCrypto';\nimport BrowserEncoding from './BrowserEncoding';\nimport BrowserInfo from './BrowserInfo';\nimport BrowserRequests from './BrowserRequests';\nimport LocalStorage, { isLocalStorageSupported } from './LocalStorage';\n\nexport default class BrowserPlatform implements Platform {\n encoding: Encoding = new BrowserEncoding();\n info: Info;\n // fileSystem?: Filesystem;\n crypto: Crypto = new BrowserCrypto();\n requests: Requests = new BrowserRequests();\n storage?: Storage;\n\n constructor(logger: LDLogger, options: BrowserOptions) {\n if (isLocalStorageSupported()) {\n this.storage = new LocalStorage(logger);\n }\n this.info = new BrowserInfo(options);\n }\n}\n","import {\n AutoEnvAttributes,\n base64UrlEncode,\n BasicLogger,\n cancelableTimedPromise,\n Configuration,\n Encoding,\n FlagManager,\n Hook,\n internal,\n LDClientImpl,\n LDContext,\n LDEmitter,\n LDEmitterEventName,\n LDFlagValue,\n LDHeaders,\n LDIdentifyResult,\n LDPluginEnvironmentMetadata,\n Platform,\n safeRegisterDebugOverridePlugins,\n} from '@launchdarkly/js-client-sdk-common';\n\nimport { readFlagsFromBootstrap } from './bootstrap';\nimport { getHref } from './BrowserApi';\nimport BrowserDataManager from './BrowserDataManager';\nimport { BrowserIdentifyOptions as LDIdentifyOptions } from './BrowserIdentifyOptions';\nimport { registerStateDetection } from './BrowserStateDetector';\nimport GoalManager from './goals/GoalManager';\nimport { Goal, isClick } from './goals/Goals';\nimport {\n LDClient,\n LDStartOptions,\n LDWaitForInitializationComplete,\n LDWaitForInitializationFailed,\n LDWaitForInitializationOptions,\n LDWaitForInitializationResult,\n LDWaitForInitializationTimeout,\n} from './LDClient';\nimport { LDPlugin } from './LDPlugin';\nimport validateBrowserOptions, { BrowserOptions, filterToBaseOptionsWithDefaults } from './options';\nimport BrowserPlatform from './platform/BrowserPlatform';\n\nclass BrowserClientImpl extends LDClientImpl {\n private readonly _goalManager?: GoalManager;\n private readonly _plugins?: LDPlugin[];\n\n // The initialized promise is used to track the initialization state of the client.\n // This is separate from the start promise because the start promise could time out before\n // the initialization is complete.\n private _initializedPromise?: Promise<LDWaitForInitializationResult>;\n private _initResolve?: (result: LDWaitForInitializationResult) => void;\n private _initializeResult?: LDWaitForInitializationResult;\n\n private _initialContext?: LDContext;\n\n // NOTE: This also keeps track of when we tried to initialize the client.\n private _startPromise?: Promise<LDWaitForInitializationResult>;\n\n constructor(\n clientSideId: string,\n autoEnvAttributes: AutoEnvAttributes,\n options: BrowserOptions = {},\n overridePlatform?: Platform,\n ) {\n const { logger: customLogger, debug } = options;\n // Overrides the default logger from the common implementation.\n const logger =\n customLogger ??\n new BasicLogger({\n destination: {\n // eslint-disable-next-line no-console\n debug: console.debug,\n // eslint-disable-next-line no-console\n info: console.info,\n // eslint-disable-next-line no-console\n warn: console.warn,\n // eslint-disable-next-line no-console\n error: console.error,\n },\n level: debug ? 'debug' : 'info',\n });\n\n // TODO: Use the already-configured baseUri from the SDK config. SDK-560\n const baseUrl = options.baseUri ?? 'https://clientsdk.launchdarkly.com';\n\n const platform = overridePlatform ?? new BrowserPlatform(logger, options);\n // Only the browser-specific options are in validatedBrowserOptions.\n const validatedBrowserOptions = validateBrowserOptions(options, logger);\n // The base options are in baseOptionsWithDefaults.\n const baseOptionsWithDefaults = filterToBaseOptionsWithDefaults({ ...options, logger });\n const { eventUrlTransformer } = validatedBrowserOptions;\n\n super(\n clientSideId,\n autoEnvAttributes,\n platform,\n baseOptionsWithDefaults,\n (\n flagManager: FlagManager,\n configuration: Configuration,\n baseHeaders: LDHeaders,\n emitter: LDEmitter,\n diagnosticsManager?: internal.DiagnosticsManager,\n ) =>\n new BrowserDataManager(\n platform,\n flagManager,\n clientSideId,\n configuration,\n validatedBrowserOptions,\n () => ({\n pathGet(encoding: Encoding, _plainContextString: string): string {\n return `/sdk/evalx/${clientSideId}/contexts/${base64UrlEncode(_plainContextString, encoding)}`;\n },\n pathReport(_encoding: Encoding, _plainContextString: string): string {\n return `/sdk/evalx/${clientSideId}/context`;\n },\n pathPing(_encoding: Encoding, _plainContextString: string): string {\n // Note: if you are seeing this error, it is a coding error. This DataSourcePaths implementation is for polling endpoints. /ping is not currently\n // used in a polling situation. It is probably the case that this was called by streaming logic erroneously.\n throw new Error('Ping for polling unsupported.');\n },\n }),\n () => ({\n pathGet(encoding: Encoding, _plainContextString: string): string {\n return `/eval/${clientSideId}/${base64UrlEncode(_plainContextString, encoding)}`;\n },\n pathReport(_encoding: Encoding, _plainContextString: string): string {\n return `/eval/${clientSideId}`;\n },\n pathPing(_encoding: Encoding, _plainContextString: string): string {\n return `/ping/${clientSideId}`;\n },\n }),\n baseHeaders,\n emitter,\n diagnosticsManager,\n ),\n {\n analyticsEventPath: `/events/bulk/${clientSideId}`,\n diagnosticEventPath: `/events/diagnostic/${clientSideId}`,\n includeAuthorizationHeader: false,\n highTimeoutThreshold: 5,\n userAgentHeaderName: 'x-launchdarkly-user-agent',\n trackEventModifier: (event: internal.InputCustomEvent) =>\n new internal.InputCustomEvent(\n event.context,\n event.key,\n event.data,\n event.metricValue,\n event.samplingRatio,\n eventUrlTransformer(getHref()),\n ),\n getImplementationHooks: (environmentMetadata: LDPluginEnvironmentMetadata) =>\n internal.safeGetHooks(logger, environmentMetadata, validatedBrowserOptions.plugins),\n credentialType: 'clientSideId',\n },\n );\n\n this.setEventSendingEnabled(true, false);\n\n this._plugins = validatedBrowserOptions.plugins;\n\n if (validatedBrowserOptions.fetchGoals) {\n this._goalManager = new GoalManager(\n clientSideId,\n platform.requests,\n baseUrl,\n (err) => {\n // TODO: May need to emit. SDK-561\n logger.error(err.message);\n },\n (url: string, goal: Goal) => {\n const context = this.getInternalContext();\n if (!context) {\n return;\n }\n const transformedUrl = eventUrlTransformer(url);\n if (isClick(goal)) {\n this.sendEvent({\n kind: 'click',\n url: transformedUrl,\n samplingRatio: 1,\n key: goal.key,\n creationDate: Date.now(),\n context,\n selector: goal.selector,\n });\n } else {\n this.sendEvent({\n kind: 'pageview',\n url: transformedUrl,\n samplingRatio: 1,\n key: goal.key,\n creationDate: Date.now(),\n context,\n });\n }\n },\n );\n\n // This is intentionally not awaited. If we want to add a \"goalsready\" event, or\n // \"waitForGoalsReady\", then we would make an async immediately invoked function expression\n // which emits the event, and assign its promise to a member. The \"waitForGoalsReady\" function\n // would return that promise.\n this._goalManager.initialize();\n\n if (validatedBrowserOptions.automaticBackgroundHandling) {\n registerStateDetection(() => this.flush());\n }\n }\n }\n\n registerPlugins(client: LDClient): void {\n internal.safeRegisterPlugins(\n this.logger,\n this.environmentMetadata,\n client,\n this._plugins || [],\n );\n\n const override = this.getDebugOverrides();\n if (override) {\n safeRegisterDebugOverridePlugins(this.logger, override, this._plugins || []);\n }\n }\n\n setInitialContext(context: LDContext): void {\n this._initialContext = context;\n }\n\n override async identify(context: LDContext, identifyOptions?: LDIdentifyOptions): Promise<void> {\n return super.identify(context, identifyOptions);\n }\n\n override async identifyResult(\n context: LDContext,\n identifyOptions?: LDIdentifyOptions,\n ): Promise<LDIdentifyResult> {\n if (!this._startPromise) {\n this.logger.error(\n 'Client must be started before it can identify a context, did you forget to call start()?',\n );\n return { status: 'error', error: new Error('Identify called before start') };\n }\n\n const identifyOptionsWithUpdatedDefaults = {\n ...identifyOptions,\n };\n if (identifyOptions?.sheddable === undefined) {\n identifyOptionsWithUpdatedDefaults.sheddable = true;\n }\n\n const res = await super.identifyResult(context, identifyOptionsWithUpdatedDefaults);\n if (res.status === 'completed') {\n this._initializeResult = { status: 'complete' };\n this._initResolve?.(this._initializeResult);\n } else if (res.status === 'error') {\n this._initializeResult = { status: 'failed', error: res.error };\n this._initResolve?.(this._initializeResult);\n }\n\n this._goalManager?.startTracking();\n return res;\n }\n\n start(options?: LDStartOptions): Promise<LDWaitForInitializationResult> {\n if (this._initializeResult) {\n return Promise.resolve(this._initializeResult);\n }\n if (this._startPromise) {\n return this._startPromise;\n }\n if (!this._initialContext) {\n this.logger.error('Initial context not set');\n return Promise.resolve({ status: 'failed', error: new Error('Initial context not set') });\n }\n\n // When we get to this point, we assume this is the first time that start is being\n // attempted. This line should only be called once during the lifetime of the client.\n const identifyOptions = {\n ...(options?.identifyOptions ?? {}),\n\n // Initial identify operations are not sheddable.\n sheddable: false,\n };\n\n // If the bootstrap data is provided in the start options, and the identify options do not have bootstrap data,\n // then use the bootstrap data from the start options.\n if (options?.bootstrap && !identifyOptions.bootstrap) {\n identifyOptions.bootstrap = options.bootstrap;\n }\n\n if (identifyOptions?.bootstrap) {\n try {\n const bootstrapData = readFlagsFromBootstrap(this.logger, identifyOptions.bootstrap);\n this.presetFlags(bootstrapData);\n } catch (error) {\n this.logger.error('Failed to bootstrap data', error);\n }\n }\n\n if (!this._initializedPromise) {\n this._initializedPromise = new Promise((resolve) => {\n this._initResolve = resolve;\n });\n }\n\n this._startPromise = this._promiseWithTimeout(this._initializedPromise, options?.timeout ?? 5);\n\n this.identifyResult(this._initialContext!, identifyOptions);\n return this._startPromise;\n }\n\n waitForInitialization(\n options?: LDWaitForInitializationOptions,\n ): Promise<LDWaitForInitializationResult> {\n const timeout = options?.timeout ?? 5;\n\n // If initialization has already completed (successfully or failed), return the result immediately.\n if (this._initializeResult) {\n return Promise.resolve(this._initializeResult);\n }\n\n // It waitForInitialization was previously called, then return the promise with a timeout.\n // This condition should only be triggered if waitForInitialization was called multiple times.\n if (this._initializedPromise) {\n return this._promiseWithTimeout(this._initializedPromise, timeout);\n }\n\n if (!this._initializedPromise) {\n this._initializedPromise = new Promise((resolve) => {\n this._initResolve = resolve;\n });\n }\n\n return this._promiseWithTimeout(this._initializedPromise, timeout);\n }\n\n /**\n * Apply a timeout promise to a base promise. This is for use with waitForInitialization.\n *\n * @param basePromise The promise to race against a timeout.\n * @param timeout The timeout in seconds.\n * @param logger A logger to log when the timeout expires.\n * @returns\n */\n private _promiseWithTimeout(\n basePromise: Promise<LDWaitForInitializationResult>,\n timeout: number,\n ): Promise<LDWaitForInitializationResult> {\n const cancelableTimeout = cancelableTimedPromise(timeout, 'waitForInitialization');\n return Promise.race([\n basePromise.then((res: LDWaitForInitializationResult) => {\n cancelableTimeout.cancel();\n return res;\n }),\n cancelableTimeout.promise\n // If the promise resolves without error, then the initialization completed successfully.\n // NOTE: this should never return as the resolution would only be triggered by the basePromise\n // being resolved.\n .then(() => ({ status: 'complete' }) as LDWaitForInitializationComplete)\n .catch(() => ({ status: 'timeout' }) as LDWaitForInitializationTimeout),\n ]).catch((reason) => {\n this.logger?.error(reason.message);\n return { status: 'failed', error: reason as Error } as LDWaitForInitializationFailed;\n });\n }\n\n setStreaming(streaming?: boolean): void {\n // With FDv2 we may want to consider if we support connection mode directly.\n // Maybe with an extension to connection mode for 'automatic'.\n const browserDataManager = this.dataManager as BrowserDataManager;\n browserDataManager.setForcedStreaming(streaming);\n }\n\n private _updateAutomaticStreamingState() {\n const browserDataManager = this.dataManager as BrowserDataManager;\n // This will need changed if support for listening to individual flag change\n // events it added.\n browserDataManager.setAutomaticStreamingState(!!this.emitter.listenerCount('change'));\n }\n\n override on(eventName: LDEmitterEventName, listener: Function): void {\n super.on(eventName, listener);\n this._updateAutomaticStreamingState();\n }\n\n override off(eventName: LDEmitterEventName, listener: Function): void {\n super.off(eventName, listener);\n this._updateAutomaticStreamingState();\n }\n}\n\nexport function makeClient(\n clientSideId: string,\n initialContext: LDContext,\n autoEnvAttributes: AutoEnvAttributes,\n options: BrowserOptions = {},\n overridePlatform?: Platform,\n): LDClient {\n const impl = new BrowserClientImpl(clientSideId, autoEnvAttributes, options, overridePlatform);\n impl.setInitialContext(initialContext);\n\n // Return a PIMPL style implementation. This decouples the interface from the interface of the implementation.\n // In the future we should consider updating the common SDK code to not use inheritance and instead compose\n // the leaf-implementation.\n // The purpose for this in the short-term is to have a signature for identify that is different than the class implementation.\n // Using an object with PIMPL here also allows us to completely hide the underlying implementation, where with a class\n // it is trivial to access what should be protected (or even private) fields.\n const client: LDClient = {\n variation: (key: string, defaultValue?: LDFlagValue) => impl.variation(key, defaultValue),\n variationDetail: (key: string, defaultValue?: LDFlagValue) =>\n impl.variationDetail(key, defaultValue),\n boolVariation: (key: string, defaultValue: boolean) => impl.boolVariation(key, defaultValue),\n boolVariationDetail: (key: string, defaultValue: boolean) =>\n impl.boolVariationDetail(key, defaultValue),\n numberVariation: (key: string, defaultValue: number) => impl.numberVariation(key, defaultValue),\n numberVariationDetail: (key: string, defaultValue: number) =>\n impl.numberVariationDetail(key, defaultValue),\n stringVariation: (key: string, defaultValue: string) => impl.stringVariation(key, defaultValue),\n stringVariationDetail: (key: string, defaultValue: string) =>\n impl.stringVariationDetail(key, defaultValue),\n jsonVariation: (key: string, defaultValue: unknown) => impl.jsonVariation(key, defaultValue),\n jsonVariationDetail: (key: string, defaultValue: unknown) =>\n impl.jsonVariationDetail(key, defaultValue),\n track: (key: string, data?: any, metricValue?: number) => impl.track(key, data, metricValue),\n on: (key: LDEmitterEventName, callback: (...args: any[]) => void) => impl.on(key, callback),\n off: (key: LDEmitterEventName, callback: (...args: any[]) => void) => impl.off(key, callback),\n flush: () => impl.flush(),\n setStreaming: (streaming?: boolean) => impl.setStreaming(streaming),\n identify: (pristineContext: LDContext, identifyOptions?: LDIdentifyOptions) =>\n impl.identifyResult(pristineContext, identifyOptions),\n getContext: () => impl.getContext(),\n close: () => impl.close(),\n allFlags: () => impl.allFlags(),\n addHook: (hook: Hook) => impl.addHook(hook),\n waitForInitialization: (waitOptions?: LDWaitForInitializationOptions) =>\n impl.waitForInitialization(waitOptions),\n logger: impl.logger,\n start: (startOptions?: LDStartOptions) => impl.start(startOptions),\n };\n\n impl.registerPlugins(client);\n\n return client;\n}\n","import { BasicLogger, BasicLoggerOptions, LDLogger } from '@launchdarkly/js-client-sdk-common';\n\nimport { BrowserIdentifyOptions as LDIdentifyOptions } from './BrowserIdentifyOptions';\n\n// The exported LDIdentifyOptions and LDOptions are the browser specific implementations.\n// These shadow the common implementations.\nexport type { LDIdentifyOptions };\n\nexport type {\n AutoEnvAttributes,\n BasicLogger,\n BasicLoggerOptions,\n EvaluationSeriesContext,\n EvaluationSeriesData,\n Hook,\n HookMetadata,\n IdentifySeriesContext,\n IdentifySeriesData,\n IdentifySeriesResult,\n IdentifySeriesStatus,\n LDContext,\n LDContextCommon,\n LDContextMeta,\n LDEvaluationDetail,\n LDEvaluationDetailTyped,\n LDEvaluationReason,\n LDFlagSet,\n LDFlagValue,\n LDTimeoutError,\n LDInspection,\n LDLogger,\n LDLogLevel,\n LDMultiKindContext,\n LDSingleKindContext,\n TrackSeriesContext,\n LDPluginBase,\n LDPluginEnvironmentMetadata,\n LDPluginSdkMetadata,\n LDPluginApplicationMetadata,\n LDPluginMetadata,\n LDIdentifyResult,\n LDIdentifySuccess,\n LDIdentifyError,\n LDIdentifyTimeout,\n LDIdentifyShed,\n LDDebugOverride,\n} from '@launchdarkly/js-client-sdk-common';\n\n/**\n * Provides a basic {@link LDLogger} implementation.\n *\n * This logging implementation uses a basic format that includes only the log level\n * and the message text. By default this uses log level 'info' and the output is\n * written to `console.error`.\n *\n * To use the logger created by this function, put it into {@link LDOptions.logger}. If\n * you do not set {@link LDOptions.logger} to anything, the SDK uses a default logger\n * that will log \"info\" level and higher priorty messages and it will log messages to\n * console.info, console.warn, and console.error.\n *\n * @param options Configuration for the logger. If no options are specified, the\n * logger uses `{ level: 'info' }`.\n *\n * @example\n * This example shows how to use `basicLogger` in your SDK options to enable console\n * logging only at `warn` and `error` levels.\n * ```javascript\n * const ldOptions = {\n * logger: basicLogger({ level: 'warn' }),\n * };\n * ```\n *\n * @example\n * This example shows how to use `basicLogger` in your SDK options to cause all\n * log output to go to `console.log`\n * ```javascript\n * const ldOptions = {\n * logger: basicLogger({ destination: console.log }),\n * };\n * ```\n *\n * * @example\n * The configuration also allows you to control the destination for each log level.\n * ```javascript\n * const ldOptions = {\n * logger: basicLogger({\n * destination: {\n * debug: console.debug,\n * info: console.info,\n * warn: console.warn,\n * error:console.error\n * }\n * }),\n * };\n * ```\n */\nexport function basicLogger(options: BasicLoggerOptions): LDLogger {\n return new BasicLogger(options);\n}\n","/**\n * This is the API reference for the LaunchDarkly Client-Side SDK for JavaScript.\n *\n * This SDK is intended for use in browser environments.\n *\n * In typical usage, you will call {@link createClient} once at startup time to obtain an instance of\n * {@link LDClient}, which provides access to all of the SDK's functionality.\n *\n * For more information, see the [SDK Reference Guide](https://docs.launchdarkly.com/sdk/client-side/javascript).\n *\n * @packageDocumentation\n */\nimport { AutoEnvAttributes, LDContext } from '@launchdarkly/js-client-sdk-common';\n\nimport { makeClient } from './BrowserClient';\nimport { LDClient } from './LDClient';\nimport { BrowserOptions as LDOptions } from './options';\n\nexport * from './common';\nexport type { LDClient, LDOptions };\nexport type { LDPlugin } from './LDPlugin';\n\n/**\n * Creates an instance of the LaunchDarkly client. Note that the client will not be ready to\n * use until {@link LDClient.start} is called.\n *\n * Usage:\n * ```\n * import { createClient } from 'launchdarkly-js-client-sdk';\n * const client = createClient(clientSideId, context, options);\n *\n * // Attach event listeners and add any additional logic here\n *\n * // Then start the client\n * client.start();\n * ```\n * @remarks\n * The client will not automatically start until {@link LDClient.start} is called in order to\n * synchronize the registering of event listeners and other initialization logic that should be\n * done before the client initiates its connection to LaunchDarkly.\n *\n * @param clientSideId\n * The client-side ID, also known as the environment ID.\n * @param pristineContext\n * The initial context used to identify the user. @see {@link LDContext}\n * @param options\n * Optional configuration settings. @see {@link LDOptions}\n * @returns\n * The new client instance. @see {@link LDClient}\n */\nexport function createClient(\n clientSideId: string,\n pristineContext: LDContext,\n options?: LDOptions,\n): LDClient {\n // AutoEnvAttributes are not supported yet in the browser SDK.\n const client = makeClient(clientSideId, pristineContext, AutoEnvAttributes.Disabled, options);\n\n return client;\n}\n"],"mappings":"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","names":["toRefString","value","unescape","ref","getComponents","reference","component","isLiteral","validate","AttributeReference","refOrLiteral","literal","literalVal","_components","target","components","isValid","current","index","depth","other","FactoryOrInstance","factoryOrInstance","typeOfFactory","Type","typeName","example","_typeName","u","TypeArray","val","NumberWithMinimum","min","StringMatchingRegex","expression","Function","NullableBoolean","DATE_REGEX","DateValidator","KindValidator","TypeValidators","isSingleKind","context","isMultiKind","isLegacyUser","canonicalize","object","visited","item","key","DEFAULT_KIND","encodeKey","isContextCommon","kindOrContext","validKind","kind","validKey","processPrivateAttributes","privateAttributes","literals","privateAttribute","defined","legacyToSingleKind","user","singleKindContext","__spreadProps","__spreadValues","anonymous","Context","_Context","valid","message","_isMulti","_isUser","_wasLegacy","_contexts","_contextForError","_getValueFromContext","_contextForKind","_context","_fromMultiKindContext","kinds","kindsValid","contextsAreObjects","contexts","acc","_a","singleContext","part","created","_privateAttributeReferences","_fromSingleKindContext","kindValid","keyValid","privateAttributeReferences","_fromLegacyUser","result","kindAndContext","nestedContext","_cachedCanonicalJson","e","protectedAttributes","str","legacyTopLevelCopyAttributes","compare","a","b","cloneWithRedactions","references","stack","cloned","excluded","redactRef","ContextFilter","_allAttributesPrivate","_privateAttributes","redactAnonymousAttributes","_filterSingleKind","filteredMulti","single","_getAttributesToFilter","redactAllAttributes","k","attr","protectedAttr","name","MAX_RETRY_DELAY","JITTER_RATIO","DefaultBackoff","initialRetryDelayMillis","_retryResetIntervalMillis","_random","_retryCount","_initialRetryDelayMillis","_maxExponent","_backoff","exponent","delay","_jitter","computedDelayMillis","timeStampMs","_activeSince","DataSourceState","LDPollingError","kind","message","status","recoverable","LDStreamingError","code","DEFAULT_FALLBACK_TIME_MS","DEFAULT_RECOVERY_TIME_MS","DataSourceErrorKind","AutoEnvAttributes","LDEventType","LDDeliveryStatus","tryStringify","val","e","error","toNumber","toInt","toFloat","escapes","format","args","_a","formatString","TypeValidators","out","i","char","nextChar","value","LogPriority","LEVEL_NAMES","BasicLogger","_BasicLogger","options","_b","_c","_logLevel","_name","_formatter","_destinations","destination","_tryFormat","_tryWrite","msg","_log","level","prefix","loggerRequirements","SafeLogger","logger","fallback","validator","_logger","_fallback","createSafeLogger","basicLogger","OptionMessages","oldName","newName","name","min","expectedType","actualType","allowedTagCharacters","regexValidator","tagValidator","u","ApplicationTags","tags","application","key","valid","message","tagKeys","ClientContext","sdkKey","configuration","platform","canonicalizeUri","uri","canonicalizePath","path","ServiceEndpoints","_ServiceEndpoints","streaming","polling","events","analyticsEventPath","diagnosticEventPath","includeAuthorizationHeader","payloadFilterKey","getWithParams","parameters","parts","getStreamingUri","endpoints","canonicalizedPath","combinedParameters","getPollingUri","getEventsUri","LDUnexpectedResponseError","LDClientError","LDTimeoutError","isHttpRecoverable","status","isHttpLocallyRecoverable","cancelableTimedPromise","t","taskName","timeout","resolve","_res","reject","clone","obj","secondsToMillis","sec","isEmptyObject","obj","deepCompact","ignoreKeys","acc","key","value","fastDeepEqual","a","b","length","i","keys","defaultHeaders","sdkKey","info","tags","includeAuthorizationHeader","userAgentHeaderName","userAgentBase","version","wrapperName","wrapperVersion","headers","httpErrorMessage","err","context","retryMessage","desc","action","shouldRetry","status","isHttpRecoverable","base64UrlEncode","s","encoding","sleep","delayMillis","resolve","DiagnosticsManager","sdkKey","_platform","_diagnosticInitConfig","_streamInits","_startTime","_dataSinceDate","_id","_a","_b","_c","sdkData","platformData","__spreadValues","timestamp","failed","durationMillis","item","droppedEvents","deduplicatedUsers","eventsInLastBatch","currentTime","evt","ErrorKinds","ErrorKinds$1","ClientMessages","badType","EventSender","clientContext","baseHeaders","basicConfiguration","platform","analyticsEventPath","diagnosticEventPath","crypto","requests","_defaultHeaders","_eventsUri","getEventsUri","_diagnosticEventsUri","_requests","_crypto","_tryPostingEvents","events","uri","payloadId","canRetry","tryRes","LDDeliveryStatus","headers","__spreadProps","error","status","resHeaders","serverDate","LDUnexpectedResponseError","httpErrorMessage","isHttpRecoverable","isHttpLocallyRecoverable","err","sleep","type","data","LDEventType","isFeature","u","isIdentify","isMigration","SummaryCounter","count","key","value","defValue","version","variation","counterKey","event","EventSummarizer","_singleContext","_contextFilter","_startDate","_endDate","_counters","_contextKinds","_context","countKey","counter","kinds","kind","features","acc","flagSummary","counterOut","_clearSummary","LDInvalidSDKKeyError","message","MultiEventSummarizer","_logger","_summarizers","summarizer","summarizersToFlush","shouldSample","ratio","truncated","isMultiEventSummarizer","EventProcessor","_config","_contextDeduplicator","_diagnosticsManager","start","summariesPerContext","_queue","_lastKnownPastTime","_droppedEvents","_deduplicatedUsers","_exceededCapacity","_eventsInLastBatch","_shutdown","_flushUsersTimer","_capacity","_eventSender","ContextFilter","ref","AttributeReference","_summarizer","_flushTimer","e","initEvent","_postDiagnosticEvent","_diagnosticsTimer","statsEvent","eventsToFlush","summary","inputEvent","migrationEvent","_enqueue","isFeatureEvent","addFullEvent","addDebugEvent","_shouldDebugEvent","isIdentifyEvent","shouldNotDeduplicate","_makeOutputEvent","debug","out","res","InputCustomEvent","context","metricValue","samplingRatio","url","InputEvalEvent","withReasons","trackEvents","prereqOf","reason","debugEventsUntilDate","excludeFromSummaries","InputIdentifyEvent","NullEventProcessor","EventFactoryBase","_withReasons","defVal","PAYLOAD_ID","fdv1PayloadAdaptor","processor","_processor","_selector","selector","flag","segment","PayloadProcessor","_objProcessors","_errorHandler","_listeners","_tempId","_tempBasis","_tempUpdates","_processServerIntent","_resetAll","payload","_processIntentNone","_processPutObject","obj","_processObj","_processDeleteObject","intent","it","_resetAfterEmission","_processPayloadTransferred","_processGoodbye","_processError","_resetAfterError","listener","index","jsonObj","PayloadStreamReader","eventStream","_attachHandler","_payloadProcessor","stream","eventName","_d","_e","DataSourceErrorKind","initMetadataFromHeaders","initHeaders","envIdKey","UNKNOWN_PLUGIN_NAME","safeGetName","logger","plugin","safeGetHooks","environmentMetadata","plugins","hooks","pluginHooks","safeRegisterPlugins","client","DataSourceState","isOk","status","LDRequestError","message","Requestor","_requests","_uri","_headers","_method","_body","res","err","makeRequestor","plainContextString","serviceEndpoints","paths","requests","encoding","baseHeaders","baseQueryParams","withReasons","useReport","secureModeHash","body","method","headers","__spreadValues","path","parameters","uri","getPollingUri","duplicateExecutionError","makePending","task","_logger","sheddable","resolveTask","promise","resolve","result","beforeResult","_a","error","beforePromise","executedOrShed","createAsyncTaskQueue","logger","activeTask","queue","checkPending","nextTask","pending","_b","validators","TypeValidators","DEFAULT_POLLING_INTERVAL","DEFAULT_POLLING","DEFAULT_STREAM","ensureSafeLogger","SafeLogger","createSafeLogger","ConfigurationImpl","pristineOptions","internalOptions","ServiceEndpoints","_validateTypesAndNames","e","ApplicationTags","_c","event","errors","k","v","validator","validatorType","OptionMessages","NumberWithMinimum","min","digest","hasher","getOrGenerateKey","storageKey","crypto","storage","generatedKey","hashAndBase64Encode","input","noop","concatNamespacesAndValues","parts","part","namespaceForEnvironment","sdkKey","namespaceForAnonymousGeneratedContextKey","kind","namespaceForGeneratedContextKey","namespaceForContextIndex","environmentNamespace","namespaceForContextData","context","isLegacyUser","isSingleKind","isMultiKind","index","defaultAutoEnvSchemaVersion","toMulti","c","contextCommon","__objRest","addApplicationInfo","info","applicationInfo","ld_application","app","deepCompact","id","version","name","versionName","__spreadProps","addDeviceInfo","platform","ld_device","os","device","family","_d","ldDeviceNamespace","addAutoEnv","config","multi","createActiveContextTracker","unwrappedContext","_unwrappedContext","_context","rej","reject","ensureKeyCommon","anonymous","key","ensureKeySingle","ensureKeyMulti","multiContext","singleContexts","ensureKeyLegacy","ensureKey","cloned","clone","createDiagnosticsInitConfig","secondsToMillis","createDiagnosticsManager","clientSideID","createErrorEvaluationDetail","errorKind","def","createSuccessEvaluationDetail","value","variationIndex","reason","createEventProcessor","diagnosticsManager","ClientContext","EventFactory","flagKey","defaultVal","flag","trackEvents","debugEventsUntilDate","trackReason","flagVersion","variation","ContextIndex","_ContextIndex","json","contextIndex","timestamp","entry","it","maxContexts","clampedMax","a","b","FlagPersistence","_platform","_environmentNamespace","_maxCachedContexts","_flagStore","_flagUpdater","_timeStamper","_indexKeyPromise","newFlags","_storeCache","item","flagsJson","flags","descriptors","acc","_loadIndex","_contextIndex","pruned","allFlags","descriptor","jsonAll","DefaultFlagStore","_flags","update","calculateChangedKeys","existingObject","newObject","changedKeys","f","subObject","fastDeepEqual","FlagUpdater","flagStore","_changeCallbacks","keys","type","_activeContext","callback","oldFlags","changed","currentValue","DefaultFlagManager","maxCachedContexts","timeStamper","_flagPersistencePromise","_initPersistence","_overrides","_convertValueToOverrideDescripter","clearedOverrides","UNKNOWN_HOOK_NAME","BEFORE_EVALUATION_STAGE_NAME","AFTER_EVALUATION_STAGE_NAME","AFTER_TRACK_STAGE_NAME","tryExecuteStage","hookName","stage","getHookName","hook","executeBeforeEvaluation","hooks","hookContext","executeAfterEvaluation","updatedData","hookIndex","data","executeBeforeIdentify","executeAfterIdentify","executeAfterTrack","HookRunner","initialHooks","_hooks","defaultValue","hookData","timeout","getInspectorHook","inspectorManager","detail","_result","invalidInspector","inspectorMethodError","createSafeInspector","inspector","errorLogged","wrapper","args","FLAG_USED_TYPE","FLAG_DETAILS_CHANGED_TYPE","FLAG_DETAIL_CHANGED_TYPE","IDENTITY_CHANGED_TYPE","VALID__TYPES","validateInspector","valid","InspectorManager","inspectors","_safeInspectors","validInspectors","LDEmitter","_listeners","listener","existingListeners","updated","fn","_invokeListener","listeners","createPluginEnvironmentMetadata","sdkData","applicationMetadata","sdkMetadata","environmentMetadata","ClientMessages","ErrorKinds","DEFAULT_IDENTIFY_TIMEOUT_SECONDS","LDClientImpl","autoEnvAttributes","options","dataManagerFactory","_activeContextTracker","_highTimeoutThreshold","_eventFactoryDefault","_eventFactoryWithReasons","_eventSendingEnabled","_identifyQueue","_config","_baseHeaders","defaultHeaders","_flagManager","_diagnosticsManager","_eventProcessor","flagKeys","_handleInspectionChanged","ldContext","Context","_hookRunner","_inspectorManager","pristineContext","identifyOptions","timeoutError","LDTimeoutError","identifyTimeout","noTimeout","callSitePromise","AutoEnvAttributes","checkedContext","afterIdentify","identifyPromise","identifyResolve","identifyReject","timeoutPromise","eventName","metricValue","_variationInternal","eventFactory","typeChecker","hasContext","evalContext","foundItem","defVal","LDClientError","prerequisites","matched","successDetail","prereqKey","_typedEval","enabled","flush","details","safeRegisterDebugOverridePlugins","debugOverride","plugins","plugin","DataSourceEventHandler","_statusManager","patchFlag","deleteFlag","DataSourceStatusManager","_emitter","_state","_stateSinceMillis","_errorInfo","_updateState","requestedState","isError","newState","changedState","state","statusCode","recoverable","errorInfo","reportClosed","PollingProcessor","_requestor","_pollIntervalSeconds","_dataHandler","_errorHandler","_stopped","_poll","reportJsonError","LDPollingError","DataSourceErrorKind","startTime","requestError","isHttpRecoverable","httpErrorMessage","_e","_f","elapsed","sleepFor","_g","_timeoutHandle","errorHandler","LDStreamingError","reportEventClosed","reportPingClosed","StreamingProcessor","_plainContextString","_dataSourceConfig","_pollingRequestor","_streamUri","getStreamingUri","_logConnectionStarted","_connectionAttemptStartTime","_logConnectionResult","success","_retryAndHandleError","shouldRetry","methodAndBodyOverrides","eventSource","_eventSource","deserializeData","processJson","dataJson","payload","BaseDataManager","flagManager","credential","getPollingPaths","getStreamingPaths","emitter","_dataSourceEventHandler","connectionParams","_connectionParams","requestor","processor","_decorateProcessorWithStatusReporting","pollingRequestor","statusManager","readFlagsFromBootstrap","logger","data","keys","metadataKey","validKey","metadata","ret","key","flag","__spreadValues","isDocument","isWindow","addDocumentEventListener","type","listener","options","addWindowEventListener","getHref","getLocationSearch","getLocationHash","getCrypto","getVisibility","querySelectorAll","selector","logTag","BrowserDataManager","BaseDataManager","platform","flagManager","credential","config","_browserConfig","getPollingPaths","getStreamingPaths","baseHeaders","emitter","diagnosticsManager","_forcedStreaming","_automaticStreamingState","_debugLog","message","args","identifyResolve","identifyReject","context","identifyOptions","browserIdentifyOptions","_secureModeHash","_finishIdentifyFromBootstrap","_finishIdentifyFromPoll","_updateStreamingState","_requestPayload","plainContextString","Context","pollingRequestor","makeRequestor","maxRetries","lastError","attempt","e","shouldRetry","httpErrorMessage","sleep","_a","_b","DataSourceState","payload","putListener","DataSourceErrorKind","bootstrap","readFlagsFromBootstrap","streaming","shouldBeStreaming","_startDataSource","_stopDataSource","_setupConnection","rawContext","registerStateDetection","requestFlush","removeDocListener","addDocumentEventListener","getVisibility","removeWindowListener","addWindowEventListener","escapeStringRegexp","string","matchesUrl","matcher","href","search","hash","canonicalUrl","escapeStringRegexp","findGoalsForClick","event","clickGoals","matches","goal","target","selector","elements","querySelectorAll","elementIndex","GoalTracker","goals","onEvent","goalsMatchingUrl","_a","getHref","getLocationSearch","getLocationHash","pageviewGoals","clickHandler","clickGoal","_cleanup","addDocumentEventListener","LOCATION_WATCHER_INTERVAL_MS","DefaultLocationWatcher","callback","_previousLocation","getHref","checkUrl","currentLocation","_watcherHandle","removeListener","addWindowEventListener","_cleanupListeners","_a","GoalManager","credential","_requests","baseUrl","_reportError","_reportGoal","locationWatcherFactory","cb","DefaultLocationWatcher","_goals","_isTracking","_url","_watcher","_createTracker","_fetchGoals","_a","_tracker","GoalTracker","goal","getHref","res","err","LDUnexpectedResponseError","_b","isClick","goal","DEFAULT_FLUSH_INTERVAL_SECONDS","optDefaults","url","validators","TypeValidators","withBrowserDefaults","opts","_a","output","__spreadValues","filterToBaseOptionsWithDefaults","baseOptions","key","validateBrowserOptions","logger","entry","validator","value","OptionMessages","BrowserHasher","_webcrypto","algorithm","_data","_algorithm","encoding","combinedData","encoded","digestedBuffer","val","data","timeLow","timeMid","timeHiAndVersion","clockSeqHiAndReserved","clockSeqLow","nodes","getRandom128bit","typedArray","values","index","hex","bytes","range","strVal","formatDataAsUuidV4","fallbackUuidV4","randomUuidV4","BrowserCrypto","algorithm","BrowserHasher","getCrypto","randomUuidV4","bytesToBase64","bytes","binString","byte","BrowserEncoding","data","BrowserInfo","_config","data","DefaultBrowserEventSource","_url","options","_listeners","_backoff","DefaultBackoff","_errorFilter","_openConnection","_es","_a","err","_handleError","eventName","listeners","listener","type","_b","_c","_reconnectTimeoutHandle","_tryConnect","delayMs","BrowserRequests","url","options","eventSourceInitDict","DefaultBrowserEventSource","isLocalStorageSupported","PlatformStorage","_logger","key","_a","error","value","BrowserPlatform","logger","options","BrowserEncoding","BrowserCrypto","BrowserRequests","isLocalStorageSupported","PlatformStorage","BrowserInfo","BrowserClientImpl","LDClientImpl","clientSideId","autoEnvAttributes","options","overridePlatform","_a","customLogger","debug","logger","BasicLogger","baseUrl","platform","BrowserPlatform","validatedBrowserOptions","validateBrowserOptions","baseOptionsWithDefaults","filterToBaseOptionsWithDefaults","__spreadProps","__spreadValues","eventUrlTransformer","flagManager","configuration","baseHeaders","emitter","diagnosticsManager","BrowserDataManager","encoding","_plainContextString","base64UrlEncode","_encoding","event","index","getHref","environmentMetadata","_plugins","_goalManager","GoalManager","err","url","goal","context","transformedUrl","isClick","registerStateDetection","client","override","safeRegisterDebugOverridePlugins","_initialContext","identifyOptions","_b","_c","_startPromise","identifyOptionsWithUpdatedDefaults","res","_initializeResult","_initResolve","bootstrapData","readFlagsFromBootstrap","error","_initializedPromise","resolve","_promiseWithTimeout","timeout","basePromise","cancelableTimeout","cancelableTimedPromise","reason","streaming","_updateAutomaticStreamingState","eventName","listener","makeClient","initialContext","impl","key","defaultValue","data","metricValue","callback","pristineContext","hook","waitOptions","startOptions","basicLogger","options","BasicLogger","createClient","clientSideId","pristineContext","options","makeClient","AutoEnvAttributes"]}
|