@configdirector/react-web-sdk 1.10.1 → 1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"configdirector-react-client.mjs","names":["createJsSdkLogger","this","useReactContext"],"sources":["../src/context.tsx","../../shared/src/telemetry/utils.ts","../../shared/src/telemetry/InvalidContextSubmissions.ts","../../js-browser-client/src/telemetry/WebWorkerTelemetryClient.ts","../../shared/src/base62-encoder.ts","../../shared/src/value-id.ts","../../js-browser-client/src/telemetry/value-id-generator.ts","../../js-browser-client/src/local-storage-caching-provider.ts","../../js-browser-client/src/sha256-hex-digest.ts","../../js-browser-client/src/BrowserConfigDirectorClient.ts","../src/logger.ts","../../shared/src/deepEqual.ts","../../js-client-core/src/mountAction.ts","../src/client.ts","../src/clientSource.ts","../src/withProvider.tsx","../../js-client-core/src/clientHandlers.ts","../src/provider.tsx","../src/errors.ts","../src/hooks.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ConfigDirectorContextData } from \"./types\";\n\nconst createReactContext = () => React.createContext<ConfigDirectorContextData>({status: \"loading\"});\nexport const reactContext = createReactContext();\n","import type { ConfigType, ConfigValueType } from \"../types\";\nimport type { ValueIdGenerator, DroppedEvents } from \"./types\";\n\nconst CONFIG_VALUE_MAX_LENGTH = 500;\n\nexport type TelemetryValue = {\n value?: string;\n valueId?: string;\n type?: ConfigType;\n};\n\nexport type TelemetryEvaluationValue<TV extends ConfigValueType> = {\n value: TV;\n valueId?: string | null | undefined;\n type?: ConfigType;\n};\n\nexport const compactTelemetryValue = async (\n tv: TelemetryValue,\n valueIdGenerator: ValueIdGenerator,\n): Promise<TelemetryValue> => {\n if (tv.valueId) {\n return { valueId: tv.valueId };\n }\n if (tv.value) {\n if (tv.value.length <= CONFIG_VALUE_MAX_LENGTH && tv.type != \"json\") {\n return { value: tv.value };\n }\n\n return { valueId: await valueIdGenerator(tv.value) };\n }\n\n return tv;\n};\n\nexport const mapToTelemetryValue = <TV extends ConfigValueType>(\n ev: TelemetryEvaluationValue<TV>,\n): TelemetryValue => {\n if (ev.type === \"json\" || (ev.type == null && typeof ev.value === \"object\")) {\n if (ev.valueId) {\n return { valueId: ev.valueId, type: \"json\" };\n }\n try {\n const json = JSON.stringify(ev.value);\n return { value: json, type: \"json\" };\n } catch {\n return { value: ev.value.toString(), type: \"json\" };\n }\n }\n\n const stringValue = ev.value?.toString();\n if (stringValue && stringValue.length <= CONFIG_VALUE_MAX_LENGTH) {\n return { value: stringValue };\n }\n\n return ev.valueId ? { valueId: ev.valueId } : { value: stringValue };\n};\n\nexport const djb2Hash = (data: string): string => {\n const hash = djb2(new TextEncoder().encode(data));\n return hash.toString(16).padStart(8, \"0\");\n};\n\nconst djb2 = (bytes: Uint8Array): number => {\n let hash = 5381;\n for (let i = 0; i < bytes.length; i++) {\n hash = (hash << 5) + hash + (bytes[i] ?? 0);\n hash = hash >>> 0;\n }\n return hash;\n};\n\nexport const isEventListEmpty = <T extends Record<string | symbol, any[]>>(eventList: T): boolean => {\n const keys = Object.keys(eventList);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((eventList[key]?.length ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n\nexport const isDroppedEventsEmpty = (droppedEvents?: DroppedEvents): boolean => {\n if (!droppedEvents) {\n return true;\n }\n const keys = Object.keys(droppedEvents);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((droppedEvents[key] ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n","import type { InvalidContextEvent } from \"./telemetry-events\";\nimport type { AggregatedEvent } from \"./types\";\n\nexport const DISTINCT_KIND_SAMPLE_LIMIT = 20;\n\nexport type InvalidContextRecording =\n | \"new-kind-sample\"\n | \"known-kind-sample\"\n | \"first-beyond-sample-limit\"\n | \"beyond-sample-limit\";\n\nexport class InvalidContextSubmissions {\n private readonly countsByKindSample = new Map<string, number>();\n private countBeyondSampleLimit = 0;\n private startTime: Date | undefined;\n\n public record(kindSample: string): InvalidContextRecording {\n this.startTime ??= new Date();\n return this.add(kindSample, 1);\n }\n\n public absorb(entries: AggregatedEvent<InvalidContextEvent>[]): void {\n for (const entry of entries) {\n if (this.startTime === undefined || entry.startTime < this.startTime) {\n this.startTime = entry.startTime;\n }\n this.add(entry.event.kindSample, entry.count);\n }\n }\n\n private add(kindSample: string | undefined, count: number): InvalidContextRecording {\n if (kindSample !== undefined) {\n const knownCount = this.countsByKindSample.get(kindSample);\n if (knownCount !== undefined) {\n this.countsByKindSample.set(kindSample, knownCount + count);\n return \"known-kind-sample\";\n }\n if (this.countsByKindSample.size < DISTINCT_KIND_SAMPLE_LIMIT) {\n this.countsByKindSample.set(kindSample, count);\n return \"new-kind-sample\";\n }\n }\n const firstBeyondSampleLimit = this.countBeyondSampleLimit === 0;\n this.countBeyondSampleLimit += count;\n return firstBeyondSampleLimit ? \"first-beyond-sample-limit\" : \"beyond-sample-limit\";\n }\n\n public takeSnapshot(): AggregatedEvent<InvalidContextEvent>[] {\n const endTime = new Date();\n const startTime = this.startTime ?? endTime;\n const entryOf = (count: number, kindSample?: string): AggregatedEvent<InvalidContextEvent> => ({\n startTime,\n endTime,\n count,\n event: { reason: \"invalid-context-kind\", kindSample },\n });\n const sampledEntries = Array.from(this.countsByKindSample, ([kindSample, count]) =>\n entryOf(count, kindSample),\n );\n const entries =\n this.countBeyondSampleLimit > 0\n ? [...sampledEntries, entryOf(this.countBeyondSampleLimit)]\n : sampledEntries;\n this.clear();\n return entries;\n }\n\n private clear() {\n this.countsByKindSample.clear();\n this.countBeyondSampleLimit = 0;\n this.startTime = undefined;\n }\n}\n","import type {\n ClientSession,\n ConfigDirectorContext,\n ConfigDirectorLogger,\n ConfigValueType,\n} from \"@js-client-core/types\";\nimport type {\n ClientTelemetryEventCollectorOptions,\n TelemetryClient,\n EvaluatedConfigEvent,\n} from \"@js-client-core/telemetry\";\nimport type {\n TelemetryClientSessionEvent,\n TelemetryCloseEvent,\n TelemetryEvaluatedConfigEvent,\n TelemetryFlushEvent,\n TelemetryInitializeEvent,\n TelemetryInvalidContextSubmissionsEvent,\n TelemetryUpdateContextEvent,\n TelemetryWorkerResponseEvent,\n} from \"./types\";\nimport type { TelemetryValue } from \"@shared/telemetry/utils\";\nimport { mapToTelemetryValue } from \"@shared/telemetry/utils\";\nimport { InvalidContextSubmissions } from \"@shared/telemetry/InvalidContextSubmissions\";\n\nconst DEFAULT_WORKER_CLOSE_TIMEOUT = 6_000;\n\nexport type WebWorkerTelemetryClientOptions = ClientTelemetryEventCollectorOptions & {\n workerCloseTimeout?: number;\n};\n\nexport class WebWorkerTelemetryClient implements TelemetryClient {\n private readonly logger: ConfigDirectorLogger;\n private readonly initializeMessage: TelemetryInitializeEvent;\n private readonly clientSession: Promise<ClientSession>;\n private worker: Worker | undefined;\n private turnedOff = false;\n private readonly pendingEvaluations: TelemetryEvaluatedConfigEvent[] = [];\n private readonly pendingEvaluationLimit: number;\n private readonly pendingInvalidContextSubmissions = new InvalidContextSubmissions();\n private closePromise: Promise<void> | undefined;\n private closeResolve: (() => void) | undefined;\n private closeTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly workerCloseTimeout: number;\n private readonly visibilityHandler: () => void;\n\n constructor(options: WebWorkerTelemetryClientOptions) {\n this.logger = options.logger;\n this.workerCloseTimeout = options.workerCloseTimeout ?? DEFAULT_WORKER_CLOSE_TIMEOUT;\n this.pendingEvaluationLimit = options.evaluationQueueLimit ?? 1_000;\n this.clientSession = options.clientSession;\n\n this.initializeMessage = {\n type: \"Initialize\",\n payload: {\n sdkKey: options.sdkKey,\n sdkIdentity: options.sdkIdentity,\n metaContext: options.metaContext,\n baseUrl: options.baseUrl.toString(),\n evaluationQueueLimit: this.pendingEvaluationLimit,\n initialFlushIntervalDelay: options.initialFlushIntervalDelay ?? 5_000,\n flushIntervalDelay: options.flushIntervalDelay ?? 30_000,\n },\n };\n\n this.visibilityHandler = () => {\n if (document.visibilityState === \"hidden\") {\n this.flush();\n }\n };\n }\n\n private createWorkerOrTurnOff(): Worker | undefined {\n if (typeof Worker === \"undefined\") {\n this.turnOff(\n \"[WebWorkerTelemetryClient] Telemetry is off because Web Workers are not available in this environment.\",\n );\n return undefined;\n }\n try {\n return new Worker(new URL(\"./worker.ts\", import.meta.url), { type: \"module\" });\n } catch (error) {\n this.turnOff(\n \"[WebWorkerTelemetryClient] Telemetry is off because the telemetry Web Worker could not be created: \",\n error,\n );\n return undefined;\n }\n }\n\n private turnOff(warning: string, ...details: unknown[]) {\n this.turnedOff = true;\n this.pendingEvaluations.length = 0;\n this.logger.warn(warning, ...details);\n }\n\n private startWorker(): Worker | undefined {\n if (this.worker || this.turnedOff) {\n return this.worker;\n }\n const worker = this.createWorkerOrTurnOff();\n if (!worker) {\n return undefined;\n }\n worker.onmessage = (message: MessageEvent<TelemetryWorkerResponseEvent>) => {\n this.handleWorkerEvent(message.data);\n };\n worker.postMessage(this.initializeMessage);\n this.forwardClientSession(worker);\n this.worker = worker;\n\n try {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n } catch (error) {\n this.logger.warn(\"[TelemetryEventCollector] Could not configure 'visibilitychange' listener: \", error);\n }\n\n for (const evaluation of this.pendingEvaluations) {\n worker.postMessage(evaluation);\n }\n this.pendingEvaluations.length = 0;\n this.forwardInvalidContextSubmissions(worker);\n return worker;\n }\n\n private forwardClientSession(worker: Worker) {\n void this.clientSession.then((clientSession) => {\n const clientSessionMessage: TelemetryClientSessionEvent = {\n type: \"ClientSession\",\n payload: clientSession,\n };\n worker.postMessage(clientSessionMessage);\n });\n }\n\n private forwardInvalidContextSubmissions(worker: Worker | undefined) {\n if (!worker) {\n return;\n }\n const entries = this.pendingInvalidContextSubmissions.takeSnapshot();\n if (entries.length === 0) {\n return;\n }\n const submissionsMessage: TelemetryInvalidContextSubmissionsEvent = {\n type: \"InvalidContextSubmissions\",\n payload: { entries },\n };\n worker.postMessage(submissionsMessage);\n }\n\n public async updateContext(value: ConfigDirectorContext | undefined) {\n if (this.closePromise) {\n return;\n }\n const updateContextMessage: TelemetryUpdateContextEvent = {\n type: \"UpdateContext\",\n payload: {\n context: value,\n },\n };\n this.startWorker()?.postMessage(updateContextMessage);\n }\n\n public evaluatedConfig<T extends ConfigValueType>(event: EvaluatedConfigEvent<T>): void {\n if (this.turnedOff) {\n return;\n }\n const evaluatedConfigMessage: TelemetryEvaluatedConfigEvent = {\n type: \"EvaluatedConfigEvent\",\n payload: this.sanitizeEvaluatedConfigEvent(event),\n };\n if (this.worker) {\n this.worker.postMessage(evaluatedConfigMessage);\n return;\n }\n if (this.pendingEvaluations.length >= this.pendingEvaluationLimit) {\n this.pendingEvaluations.shift();\n }\n this.pendingEvaluations.push(evaluatedConfigMessage);\n }\n\n public recordInvalidContext(kindSample: string): void {\n this.pendingInvalidContextSubmissions.record(kindSample);\n this.forwardInvalidContextSubmissions(this.worker);\n }\n\n private sanitizeEvaluatedConfigEvent<T extends ConfigValueType>(\n event: EvaluatedConfigEvent<T>,\n ): EvaluatedConfigEvent<TelemetryValue> {\n return {\n ...event,\n defaultValue: mapToTelemetryValue({ value: event.defaultValue, type: event.type }),\n evaluatedValue: mapToTelemetryValue({\n value: event.evaluatedValue,\n valueId: event.evaluatedValueId,\n type: event.type,\n }),\n };\n }\n\n private handleWorkerEvent(event: TelemetryWorkerResponseEvent) {\n if (event.type === \"Closed\") {\n this.finishClose();\n return;\n }\n if (!event.payload?.level || !event.payload?.message) {\n return;\n }\n const { level, message, args } = event.payload;\n\n switch (level) {\n case \"debug\":\n this.logger.debug(message, ...args);\n break;\n case \"info\":\n this.logger.info(message, ...args);\n break;\n case \"warn\":\n this.logger.warn(message, ...args);\n break;\n case \"error\":\n this.logger.error(message, ...args);\n break;\n }\n }\n\n private flush() {\n const flushMessage: TelemetryFlushEvent = {\n type: \"Flush\",\n };\n this.worker?.postMessage(flushMessage);\n }\n\n public close(): Promise<void> {\n if (this.closePromise) {\n return this.closePromise;\n }\n\n return this.performClose();\n }\n\n private performClose(): Promise<void> {\n const worker = this.worker;\n if (!worker) {\n this.pendingEvaluations.length = 0;\n this.closePromise = Promise.resolve();\n return this.closePromise;\n }\n try {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n } catch (error) {\n this.logger.warn(\"[WebWorkerTelemetryClient] Could not remove 'visibilitychange' listener: \", error);\n }\n this.closePromise = new Promise<void>((resolve) => {\n this.closeResolve = resolve;\n this.closeTimer = setTimeout(() => {\n this.logger.warn(\n \"[WebWorkerTelemetryClient] Timed out waiting for the telemetry worker to close. Terminating the worker.\",\n );\n this.finishClose();\n }, this.workerCloseTimeout);\n const closeMessage: TelemetryCloseEvent = { type: \"Close\" };\n worker.postMessage(closeMessage);\n });\n return this.closePromise;\n }\n\n private finishClose() {\n clearTimeout(this.closeTimer);\n this.closeTimer = undefined;\n this.worker?.terminate();\n this.closeResolve?.();\n }\n}\n","const BASE62 = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\nexport const toBase62 = (buf: Uint8Array, length: number): string => {\n const ZERO = BigInt(0);\n const BASE = BigInt(62);\n const hex = Array.from(buf)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n let n = BigInt(\"0x\" + hex);\n let result = \"\";\n while (n > ZERO) {\n result = BASE62[Number(n % BASE)] + result;\n n /= BASE;\n }\n return result.padStart(length, \"0\");\n};\n","export const DIGEST_BYTES = 16;\nexport const BASE62_LENGTH = Math.ceil((DIGEST_BYTES * 8) / Math.log2(62));\n","import { toBase62 } from \"@shared/base62-encoder\";\nimport { DIGEST_BYTES, BASE62_LENGTH } from \"@shared/value-id\";\n\nconst encoder = new TextEncoder();\n\nexport const generateValueId = async (\n v: string | number | boolean | null | undefined,\n): Promise<string | undefined> => {\n if (typeof crypto === \"undefined\" || crypto.subtle == null) {\n return undefined;\n }\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encoder.encode(v?.toString() ?? \"\"));\n return toBase62(new Uint8Array(hashBuffer, 0, DIGEST_BYTES), BASE62_LENGTH);\n};\n","import type { CachingProvider } from \"@js-client-core/index\";\nimport { CACHED_VALUES_STORAGE_KEY_PREFIX, DEFAULT_CACHING_SIZE_LIMIT_BYTES } from \"@js-client-core/cached-values\";\nimport { localStorageIfAvailable } from \"@js-client-core/browser-globals\";\n\nexport const localStorageCachingProvider = (clientSdkKeyDigest: Promise<string>): CachingProvider | undefined => {\n const storage = localStorageIfAvailable();\n if (!storage) {\n return undefined;\n }\n const storageKey = clientSdkKeyDigest.then((digest) => CACHED_VALUES_STORAGE_KEY_PREFIX + digest);\n return {\n read: async () => storage.getItem(await storageKey),\n write: async (value) => storage.setItem(await storageKey, value),\n remove: async () => storage.removeItem(await storageKey),\n sizeLimit: () => DEFAULT_CACHING_SIZE_LIMIT_BYTES,\n };\n};\n","import type { Sha256HexDigest } from \"@js-client-core/types\";\n\nconst toHex = (bytes: Uint8Array): string =>\n Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n\nexport const sha256HexDigestIfAvailable = (): Sha256HexDigest | undefined => {\n if (typeof crypto === \"undefined\" || crypto.subtle == null) {\n return undefined;\n }\n return async (text) => {\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(text));\n return toHex(new Uint8Array(digest));\n };\n};\n","import {\n type ConfigDirectorClientOptions,\n type ConfigDirectorClient,\n type IdentifyingSdkOptions,\n type OfflineClientOptions,\n} from \"@js-client-core/index\";\nimport { WebWorkerTelemetryClient } from \"./telemetry/WebWorkerTelemetryClient\";\nimport { DefaultConfigDirectorClient } from \"@js-client-core/DefaultConfigDirectorClient\";\nimport { defaultUrlFactory } from \"@shared/url\";\nimport { generateValueId } from \"./telemetry/value-id-generator\";\nimport { localStorageCachingProvider } from \"./local-storage-caching-provider\";\nimport { sha256HexDigestIfAvailable } from \"./sha256-hex-digest\";\n\n/**\n * Creates a browser client. With a client SDK key it connects to ConfigDirector; with\n * {@link OfflineClientOptions} alone it runs in `offline` mode and serves `connection.values`. An\n * absent key with `clientOptions` is the same as the options alone when their mode is `offline`,\n * and fails like a missing key otherwise.\n */\nexport const createBrowserClient = (\n clientSdkKeyOrOptions: string | OfflineClientOptions | undefined,\n sdkOptions: IdentifyingSdkOptions,\n clientOptions?: ConfigDirectorClientOptions,\n): ConfigDirectorClient => {\n return DefaultConfigDirectorClient.from(\n ({ clientSdkKey, baseUrl, logger, metadata, clientSession }) =>\n new WebWorkerTelemetryClient({\n sdkKey: clientSdkKey,\n sdkIdentity: {\n sdkName: sdkOptions.sdkName,\n sdkVersion: sdkOptions.sdkVersion,\n },\n metaContext: {\n appName: metadata?.appName,\n appVersion: metadata?.appVersion,\n },\n logger,\n baseUrl,\n urlFactory: defaultUrlFactory,\n valueIdGenerator: generateValueId,\n clientSession,\n }),\n clientSdkKeyOrOptions,\n sdkOptions,\n clientOptions,\n { sha256HexDigest: sha256HexDigestIfAvailable(), platformCachingProvider: localStorageCachingProvider },\n );\n};\n","import type {\n ConfigDirectorLogMessageDecorator,\n ConfigDirectorLogger} from \"@js-browser-client/index\";\nimport {\n type ConfigDirectorLoggingLevel,\n createDefaultLogger as createJsSdkLogger,\n} from \"@js-browser-client/index\";\n\nclass MessageDecorator implements ConfigDirectorLogMessageDecorator {\n decorateMessage(message: string): string {\n return `[ConfigDirector:react-web-sdk] ${message}`;\n }\n}\n\nexport const createConsoleLogger = (level: ConfigDirectorLoggingLevel): ConfigDirectorLogger => {\n return createJsSdkLogger(level, new MessageDecorator());\n};\n","export const deepEqual = (left: unknown, right: unknown): boolean => {\n if (Object.is(left, right)) {\n return true;\n }\n if (typeof left !== \"object\" || typeof right !== \"object\" || left === null || right === null) {\n return false;\n }\n if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) {\n return false;\n }\n if (left instanceof Date && right instanceof Date) {\n return left.getTime() === right.getTime();\n }\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((item, index) => deepEqual(item, right[index]));\n }\n if (!isPlainObject(left) || !isPlainObject(right)) {\n return false;\n }\n const leftKeys = Object.keys(left);\n const rightKeys = Object.keys(right);\n return (\n leftKeys.length === rightKeys.length &&\n leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key]))\n );\n};\n\nconst isPlainObject = (value: object): value is Record<string, unknown> => {\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n","import type { ConfigDirectorClient, ConfigDirectorContext } from \"./types\";\nimport { deepEqual } from \"@shared/deepEqual\";\n\nexport type MountAction = \"initialize\" | \"updateContext\" | \"none\";\n\nexport const decideMountAction = (\n client: ConfigDirectorClient,\n context: ConfigDirectorContext | undefined,\n): MountAction => {\n if (client.isInitializing) {\n return \"none\";\n }\n if (!client.isReady) {\n return \"initialize\";\n }\n if (context !== undefined && !deepEqual(context, client.context)) {\n return \"updateContext\";\n }\n return \"none\";\n};\n","import type {\n ConfigDirectorClient,\n ConfigDirectorClientOptions} from \"@js-browser-client/index\";\nimport {\n createBrowserClient,\n} from \"@js-browser-client/index\";\n\nexport const createClient = (\n clientSdkKey: string | undefined,\n clientOptions?: ConfigDirectorClientOptions,\n): ConfigDirectorClient => {\n return createBrowserClient(\n clientSdkKey,\n { sdkName: \"react-web-sdk\", sdkVersion: \"__VERSION__\" },\n clientOptions,\n );\n};\n\n","import type { ConfigDirectorClient } from \"@js-browser-client/index\";\nimport { readInstalledTestClient } from \"@js-client-core/installedTestClient\";\nimport { createClient } from \"./client\";\nimport { createConsoleLogger } from \"./logger\";\nimport type { ConfigDirectorProviderOptions, ConfigDirectorProviderProps } from \"./types\";\n\nexport type ClientSource = { client: ConfigDirectorClient; owned: boolean };\n\nexport const buildClient = (options: ConfigDirectorProviderOptions): ConfigDirectorClient =>\n createClient(options.sdkKey, {\n connection: {\n url: options.url,\n timeout: options.timeout,\n mode: options.mode,\n pollingInterval: options.pollingInterval,\n values: options.values,\n },\n metadata: { appName: options.appName, appVersion: options.appVersion },\n logger: options.logger ?? createConsoleLogger(\"warn\"),\n hooks: options.hooks,\n caching: options.caching,\n });\n\nexport const hasGivenClient = (props: ConfigDirectorProviderProps): props is { client: ConfigDirectorClient } =>\n \"client\" in props && props.client !== undefined;\n\nexport const resolveClientSource = (props: ConfigDirectorProviderProps): ClientSource => {\n if (hasGivenClient(props)) {\n return { client: props.client, owned: false };\n }\n const installed = readInstalledTestClient();\n if (installed) {\n return { client: installed, owned: false };\n }\n return { client: buildClient(props), owned: true };\n};\n","import { useEffect, useState, type ReactNode } from \"react\";\nimport { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport { readInstalledTestClient } from \"@js-client-core/installedTestClient\";\nimport { decideMountAction } from \"@js-client-core/mountAction\";\nimport type { ConfigDirectorContext } from \"@js-browser-client/index\";\nimport { buildClient } from \"./clientSource\";\nimport type { ConfigDirectorProviderOptions, ConfigDirectorProviderState } from \"./types\";\n\nexport const withProvider = async (options: ConfigDirectorProviderOptions) => {\n const client =\n readInstalledTestClient() ?? buildClient({ ...options, logger: options.logger ?? createConsoleLogger(\"debug\") });\n switch (decideMountAction(client, options.context)) {\n case \"initialize\":\n await client.initialize(options.context);\n break;\n case \"updateContext\":\n await client.updateContext(options.context as ConfigDirectorContext);\n break;\n case \"none\":\n break;\n }\n\n const ConfigDirectorProvider = ({ children }: { children: ReactNode }) => {\n const [data, setData] = useState<ConfigDirectorProviderState>(() => ({\n client,\n status: client.isReady ? \"ready\" : \"default\",\n }));\n\n useEffect(() => {\n const onConfigsUpdated = () => {\n setData((prevState) => ({ ...prevState, updatedAt: new Date() }));\n };\n const onClientReady = () => {\n setData((prevState) => (prevState.status === \"ready\" ? prevState : { ...prevState, status: \"ready\" }));\n };\n client.on(\"configsUpdated\", onConfigsUpdated);\n client.on(\"clientReady\", onClientReady);\n if (client.isReady) {\n onClientReady();\n }\n return () => {\n client.off(\"configsUpdated\", onConfigsUpdated);\n client.off(\"clientReady\", onClientReady);\n };\n }, []);\n\n return <reactContext.Provider value={data}>{children}</reactContext.Provider>;\n };\n\n return ConfigDirectorProvider;\n};\n","import type { ClientEvents, ClientHooks, ConfigDirectorClient } from \"./types\";\n\ntype Registration = { event: keyof ClientEvents; handler: (payload: any) => void };\n\nexport class ClientHandlers {\n private registrations: Registration[] = [];\n\n constructor(private readonly client: ConfigDirectorClient) {}\n\n public on<T extends keyof ClientEvents>(event: T, handler: (payload: ClientEvents[T]) => void) {\n this.client.on(event, handler);\n this.registrations.push({ event, handler });\n }\n\n public registerHooks(hooks: ClientHooks | undefined) {\n for (const [event, handlerOrHandlers] of Object.entries(hooks ?? {})) {\n const handlers = Array.isArray(handlerOrHandlers) ? handlerOrHandlers : [handlerOrHandlers];\n for (const handler of handlers) {\n if (typeof handler === \"function\") {\n this.on(event as keyof ClientEvents, handler as (payload: unknown) => void);\n }\n }\n }\n }\n\n public removeAll() {\n for (const { event, handler } of this.registrations) {\n this.client.off(event, handler);\n }\n this.registrations = [];\n }\n}\n","import { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport { Component, type PropsWithChildren } from \"react\";\nimport type { ConfigDirectorClient, ConfigDirectorContext } from \"@js-browser-client/index\";\nimport { decideMountAction } from \"@js-client-core/mountAction\";\nimport { deepEqual } from \"@shared/deepEqual\";\nimport { buildClient, hasGivenClient, resolveClientSource } from \"./clientSource\";\nimport { ClientHandlers } from \"@js-client-core/clientHandlers\";\nimport type {\n ClientStatus,\n ConfigDirectorProviderOptions,\n ConfigDirectorProviderProps,\n ConfigDirectorProviderState,\n} from \"./types\";\n\nconst settledStatusOf = (client: ConfigDirectorClient | undefined): ClientStatus =>\n client?.isReady ? \"ready\" : \"default\";\n\nexport class ConfigDirectorProvider extends Component<\n PropsWithChildren<ConfigDirectorProviderProps>,\n ConfigDirectorProviderState\n> {\n private readonly ownsClient: boolean;\n private disposedOwnClient = false;\n private handlers: ClientHandlers | undefined;\n\n constructor(props: ConfigDirectorProviderProps) {\n super(props);\n const source = resolveClientSource(props);\n this.ownsClient = source.owned;\n this.state = { client: source.client, status: source.client.isReady ? \"ready\" : \"loading\" };\n }\n\n override async componentDidMount(): Promise<void> {\n let client = this.state.client as ConfigDirectorClient;\n if (this.ownsClient && this.disposedOwnClient) {\n client = buildClient(this.props as ConfigDirectorProviderOptions);\n this.disposedOwnClient = false;\n this.setState({ client, status: \"loading\" });\n }\n this.handlers = new ClientHandlers(client);\n this.handlers.on(\"configsUpdated\", () => {\n this.setState({ updatedAt: new Date() });\n });\n this.handlers.on(\"clientReady\", () => {\n this.setState({ status: \"ready\" });\n });\n if (!this.ownsClient) {\n this.handlers.registerHooks(this.props.hooks);\n }\n await this.connect(client, this.props.context);\n }\n\n private async connect(client: ConfigDirectorClient, context: ConfigDirectorContext | undefined): Promise<void> {\n switch (decideMountAction(client, context)) {\n case \"initialize\":\n await client.initialize(context);\n break;\n case \"updateContext\":\n this.setState({ status: \"loading\" });\n await client.updateContext(context as ConfigDirectorContext);\n break;\n case \"none\":\n return;\n }\n this.setState({ status: settledStatusOf(client) });\n }\n\n override async componentDidUpdate(prevProps: PropsWithChildren<ConfigDirectorProviderProps>): Promise<void> {\n if (hasGivenClient(prevProps) && hasGivenClient(this.props) && prevProps.client !== this.props.client) {\n createConsoleLogger(\"warn\").warn(\n \"The client prop of ConfigDirectorProvider changed after it mounted and is ignored. Remount the provider, for example with a new key, to use another client.\",\n );\n }\n if (!deepEqual(prevProps.context, this.props.context)) {\n this.setState({ status: \"loading\" });\n await this.state.client?.updateContext(this.props.context ?? {});\n this.setState({ status: settledStatusOf(this.state.client) });\n }\n }\n\n override componentWillUnmount(): void {\n this.handlers?.removeAll();\n this.handlers = undefined;\n if (this.ownsClient) {\n this.state.client?.dispose();\n this.disposedOwnClient = true;\n }\n }\n\n override render() {\n return <reactContext.Provider value={this.state}>{this.props.children}</reactContext.Provider>;\n }\n}\n","export class ConfigDirectorReactContextError extends Error {\n public override readonly name: string = \"ConfigDirectorReactContextError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ConfigDirectorReactContextError.prototype);\n }\n}\n","\"use client\";\n\nimport { useContext as useReactContext } from \"react\";\nimport { reactContext } from \"./context\";\nimport type {\n ConfigDirectorContext,\n ConfigValueType,\n} from \"@js-browser-client/index\";\nimport { ConfigDirectorReactContextError } from \"./errors\";\nimport type { ClientStatus } from \"./types\";\n\nconst noContextError = () => {\n return new ConfigDirectorReactContextError(\"The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.\");\n};\n\nconst useConfigValue = <T extends ConfigValueType>(\n key: string,\n defaultValue: T,\n): {\n value: T;\n readyStatus: ClientStatus;\n loading: boolean;\n} => {\n const configDirectorReactContext = useReactContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const value = configDirectorReactContext.client.getValue(key, defaultValue);\n\n return { value, readyStatus: configDirectorReactContext.status, loading: configDirectorReactContext.status === \"loading\" };\n};\n\nconst useContext = () => {\n const configDirectorReactContext = useReactContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const updateContext = async (context: ConfigDirectorContext) => {\n await configDirectorReactContext.client?.updateContext(context);\n };\n\n return { updateContext };\n};\n\nconst useClient = () => {\n const configDirectorReactContext = useReactContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n return { client: configDirectorReactContext.client };\n};\n\nexport { useConfigValue, useContext, useClient };\n"],"mappings":"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"}
1
+ {"version":3,"file":"configdirector-react-client.mjs","names":["createJsSdkLogger","this","useReactContext"],"sources":["../src/context.tsx","../../shared/src/telemetry/utils.ts","../../shared/src/telemetry/InvalidContextSubmissions.ts","../../shared/src/telemetry/TrackedEventQueue.ts","../../js-browser-client/src/telemetry/WebWorkerTelemetryClient.ts","../../shared/src/base62-encoder.ts","../../shared/src/value-id.ts","../../js-browser-client/src/telemetry/value-id-generator.ts","../../js-browser-client/src/local-storage-caching-provider.ts","../../js-browser-client/src/sha256-hex-digest.ts","../../js-browser-client/src/BrowserConfigDirectorClient.ts","../src/logger.ts","../../shared/src/deepEqual.ts","../../js-client-core/src/mountAction.ts","../src/client.ts","../src/clientSource.ts","../src/withProvider.tsx","../../js-client-core/src/clientHandlers.ts","../src/provider.tsx","../src/errors.ts","../src/hooks.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ConfigDirectorContextData } from \"./types\";\n\nconst createReactContext = () => React.createContext<ConfigDirectorContextData>({status: \"loading\"});\nexport const reactContext = createReactContext();\n","import type { ConfigType, ConfigValueType } from \"../types\";\nimport type { ValueIdGenerator, DroppedEvents } from \"./types\";\n\nconst CONFIG_VALUE_MAX_LENGTH = 500;\n\nexport type TelemetryValue = {\n value?: string;\n valueId?: string;\n type?: ConfigType;\n};\n\nexport type TelemetryEvaluationValue<TV extends ConfigValueType> = {\n value: TV;\n valueId?: string | null | undefined;\n type?: ConfigType;\n};\n\nexport const compactTelemetryValue = async (\n tv: TelemetryValue,\n valueIdGenerator: ValueIdGenerator,\n): Promise<TelemetryValue> => {\n if (tv.valueId) {\n return { valueId: tv.valueId };\n }\n if (tv.value) {\n if (tv.value.length <= CONFIG_VALUE_MAX_LENGTH && tv.type != \"json\") {\n return { value: tv.value };\n }\n\n return { valueId: await valueIdGenerator(tv.value) };\n }\n\n return tv;\n};\n\nexport const mapToTelemetryValue = <TV extends ConfigValueType>(\n ev: TelemetryEvaluationValue<TV>,\n): TelemetryValue => {\n if (ev.type === \"json\" || (ev.type == null && typeof ev.value === \"object\")) {\n if (ev.valueId) {\n return { valueId: ev.valueId, type: \"json\" };\n }\n try {\n const json = JSON.stringify(ev.value);\n return { value: json, type: \"json\" };\n } catch {\n return { value: ev.value.toString(), type: \"json\" };\n }\n }\n\n const stringValue = ev.value?.toString();\n if (stringValue && stringValue.length <= CONFIG_VALUE_MAX_LENGTH) {\n return { value: stringValue };\n }\n\n return ev.valueId ? { valueId: ev.valueId } : { value: stringValue };\n};\n\nexport const djb2Hash = (data: string): string => {\n const hash = djb2(new TextEncoder().encode(data));\n return hash.toString(16).padStart(8, \"0\");\n};\n\nconst djb2 = (bytes: Uint8Array): number => {\n let hash = 5381;\n for (let i = 0; i < bytes.length; i++) {\n hash = (hash << 5) + hash + (bytes[i] ?? 0);\n hash = hash >>> 0;\n }\n return hash;\n};\n\nexport const isEventListEmpty = <T extends Record<string | symbol, any[]>>(eventList: T): boolean => {\n const keys = Object.keys(eventList);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((eventList[key]?.length ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n\nexport const isDroppedEventsEmpty = (droppedEvents?: DroppedEvents): boolean => {\n if (!droppedEvents) {\n return true;\n }\n const keys = Object.keys(droppedEvents);\n if (keys.length == 0) {\n return true;\n }\n\n for (const key of keys) {\n if ((droppedEvents[key] ?? 0) > 0) {\n return false;\n }\n }\n\n return true;\n};\n","import type { InvalidContextEvent } from \"./telemetry-events\";\nimport type { AggregatedEvent } from \"./types\";\n\nexport const DISTINCT_KIND_SAMPLE_LIMIT = 20;\n\nexport type InvalidContextRecording =\n | \"new-kind-sample\"\n | \"known-kind-sample\"\n | \"first-beyond-sample-limit\"\n | \"beyond-sample-limit\";\n\nexport class InvalidContextSubmissions {\n private readonly countsByKindSample = new Map<string, number>();\n private countBeyondSampleLimit = 0;\n private startTime: Date | undefined;\n\n public record(kindSample: string): InvalidContextRecording {\n this.startTime ??= new Date();\n return this.add(kindSample, 1);\n }\n\n public absorb(entries: AggregatedEvent<InvalidContextEvent>[]): void {\n for (const entry of entries) {\n if (this.startTime === undefined || entry.startTime < this.startTime) {\n this.startTime = entry.startTime;\n }\n this.add(entry.event.kindSample, entry.count);\n }\n }\n\n private add(kindSample: string | undefined, count: number): InvalidContextRecording {\n if (kindSample !== undefined) {\n const knownCount = this.countsByKindSample.get(kindSample);\n if (knownCount !== undefined) {\n this.countsByKindSample.set(kindSample, knownCount + count);\n return \"known-kind-sample\";\n }\n if (this.countsByKindSample.size < DISTINCT_KIND_SAMPLE_LIMIT) {\n this.countsByKindSample.set(kindSample, count);\n return \"new-kind-sample\";\n }\n }\n const firstBeyondSampleLimit = this.countBeyondSampleLimit === 0;\n this.countBeyondSampleLimit += count;\n return firstBeyondSampleLimit ? \"first-beyond-sample-limit\" : \"beyond-sample-limit\";\n }\n\n public takeSnapshot(): AggregatedEvent<InvalidContextEvent>[] {\n const endTime = new Date();\n const startTime = this.startTime ?? endTime;\n const entryOf = (count: number, kindSample?: string): AggregatedEvent<InvalidContextEvent> => ({\n startTime,\n endTime,\n count,\n event: { reason: \"invalid-context-kind\", kindSample },\n });\n const sampledEntries = Array.from(this.countsByKindSample, ([kindSample, count]) =>\n entryOf(count, kindSample),\n );\n const entries =\n this.countBeyondSampleLimit > 0\n ? [...sampledEntries, entryOf(this.countBeyondSampleLimit)]\n : sampledEntries;\n this.clear();\n return entries;\n }\n\n private clear() {\n this.countsByKindSample.clear();\n this.countBeyondSampleLimit = 0;\n this.startTime = undefined;\n }\n}\n","import { TRACKED_EVENTS_PER_BATCH } from \"./tracked-events\";\nimport type { TrackedEventAdmission, TrackedEventEntry, TrackedEventWarning } from \"./tracked-events\";\n\nexport class TrackedEventQueue {\n private entries: TrackedEventEntry[] = [];\n private readonly warningsRaisedThisBatch = new Set<TrackedEventWarning>();\n\n public add(admission: TrackedEventAdmission): TrackedEventWarning[] {\n return this.warningsOfKeeping(admission).filter((warning) => this.isFirstThisBatch(warning));\n }\n\n public absorb(entries: TrackedEventEntry[]): void {\n this.entries.push(...entries);\n }\n\n public takeBatch(): TrackedEventEntry[] {\n const batch = this.entries;\n this.clear();\n return batch;\n }\n\n public clear(): void {\n this.entries = [];\n this.warningsRaisedThisBatch.clear();\n }\n\n private warningsOfKeeping(admission: TrackedEventAdmission): TrackedEventWarning[] {\n switch (admission.outcome) {\n case \"dropped\":\n return admission.warnings;\n case \"admitted\":\n if (this.entries.length >= TRACKED_EVENTS_PER_BATCH) {\n return [\"batch-already-full\"];\n }\n this.entries.push(admission.entry);\n return admission.warnings;\n }\n }\n\n private isFirstThisBatch(warning: TrackedEventWarning): boolean {\n if (this.warningsRaisedThisBatch.has(warning)) {\n return false;\n }\n this.warningsRaisedThisBatch.add(warning);\n return true;\n }\n}\n","import type {\n ClientSession,\n ConfigDirectorContext,\n ConfigDirectorLogger,\n ConfigValueType,\n} from \"@js-client-core/types\";\nimport type {\n ClientTelemetryEventCollectorOptions,\n TelemetryClient,\n EvaluatedConfigEvent,\n} from \"@js-client-core/telemetry\";\nimport type {\n TelemetryClientSessionEvent,\n TelemetryCloseEvent,\n TelemetryEvaluatedConfigEvent,\n TelemetryFlushEvent,\n TelemetryInitializeEvent,\n TelemetryInvalidContextSubmissionsEvent,\n TelemetryTrackedEventEntriesEvent,\n TelemetryTrackedEventEvent,\n TelemetryUpdateContextEvent,\n TelemetryWorkerResponseEvent,\n} from \"./types\";\nimport type { TelemetryValue } from \"@shared/telemetry/utils\";\nimport { mapToTelemetryValue } from \"@shared/telemetry/utils\";\nimport { InvalidContextSubmissions } from \"@shared/telemetry/InvalidContextSubmissions\";\nimport { TrackedEventQueue } from \"@shared/telemetry/TrackedEventQueue\";\nimport { logBatchWarnings } from \"@shared/telemetry/tracked-events\";\nimport type { TrackedEventAdmission } from \"@shared/telemetry/tracked-events\";\n\nconst DEFAULT_WORKER_CLOSE_TIMEOUT = 6_000;\n\nexport type WebWorkerTelemetryClientOptions = ClientTelemetryEventCollectorOptions & {\n workerCloseTimeout?: number;\n};\n\nexport class WebWorkerTelemetryClient implements TelemetryClient {\n private readonly logger: ConfigDirectorLogger;\n private readonly initializeMessage: TelemetryInitializeEvent;\n private readonly clientSession: Promise<ClientSession>;\n private worker: Worker | undefined;\n private turnedOff = false;\n private readonly pendingEvaluations: TelemetryEvaluatedConfigEvent[] = [];\n private readonly pendingEvaluationLimit: number;\n private readonly pendingInvalidContextSubmissions = new InvalidContextSubmissions();\n private readonly pendingTrackedEvents = new TrackedEventQueue();\n private closePromise: Promise<void> | undefined;\n private closeResolve: (() => void) | undefined;\n private closeTimer: ReturnType<typeof setTimeout> | undefined;\n private readonly workerCloseTimeout: number;\n private readonly visibilityHandler: () => void;\n\n constructor(options: WebWorkerTelemetryClientOptions) {\n this.logger = options.logger;\n this.workerCloseTimeout = options.workerCloseTimeout ?? DEFAULT_WORKER_CLOSE_TIMEOUT;\n this.pendingEvaluationLimit = options.evaluationQueueLimit ?? 1_000;\n this.clientSession = options.clientSession;\n\n this.initializeMessage = {\n type: \"Initialize\",\n payload: {\n sdkKey: options.sdkKey,\n sdkIdentity: options.sdkIdentity,\n metaContext: options.metaContext,\n baseUrl: options.baseUrl.toString(),\n evaluationQueueLimit: this.pendingEvaluationLimit,\n initialFlushIntervalDelay: options.initialFlushIntervalDelay ?? 5_000,\n flushIntervalDelay: options.flushIntervalDelay ?? 30_000,\n },\n };\n\n this.visibilityHandler = () => {\n if (document.visibilityState === \"hidden\") {\n this.flush();\n }\n };\n }\n\n private createWorkerOrTurnOff(): Worker | undefined {\n if (typeof Worker === \"undefined\") {\n this.turnOff(\n \"[WebWorkerTelemetryClient] Telemetry is off because Web Workers are not available in this environment.\",\n );\n return undefined;\n }\n try {\n return new Worker(new URL(\"./worker.ts\", import.meta.url), { type: \"module\" });\n } catch (error) {\n this.turnOff(\n \"[WebWorkerTelemetryClient] Telemetry is off because the telemetry Web Worker could not be created: \",\n error,\n );\n return undefined;\n }\n }\n\n private turnOff(warning: string, ...details: unknown[]) {\n this.turnedOff = true;\n this.pendingEvaluations.length = 0;\n this.pendingTrackedEvents.clear();\n this.logger.warn(warning, ...details);\n }\n\n private startWorker(): Worker | undefined {\n if (this.worker || this.turnedOff) {\n return this.worker;\n }\n const worker = this.createWorkerOrTurnOff();\n if (!worker) {\n return undefined;\n }\n worker.onmessage = (message: MessageEvent<TelemetryWorkerResponseEvent>) => {\n this.handleWorkerEvent(message.data);\n };\n worker.postMessage(this.initializeMessage);\n this.forwardClientSession(worker);\n this.worker = worker;\n\n try {\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n } catch (error) {\n this.logger.warn(\"[TelemetryEventCollector] Could not configure 'visibilitychange' listener: \", error);\n }\n\n for (const evaluation of this.pendingEvaluations) {\n worker.postMessage(evaluation);\n }\n this.pendingEvaluations.length = 0;\n this.forwardInvalidContextSubmissions(worker);\n this.forwardPendingTrackedEvents(worker);\n return worker;\n }\n\n private forwardPendingTrackedEvents(worker: Worker) {\n const entries = this.pendingTrackedEvents.takeBatch();\n if (entries.length === 0) {\n return;\n }\n const entriesMessage: TelemetryTrackedEventEntriesEvent = {\n type: \"TrackedEventEntries\",\n payload: { entries },\n };\n worker.postMessage(entriesMessage);\n }\n\n private forwardClientSession(worker: Worker) {\n void this.clientSession.then((clientSession) => {\n const clientSessionMessage: TelemetryClientSessionEvent = {\n type: \"ClientSession\",\n payload: clientSession,\n };\n worker.postMessage(clientSessionMessage);\n });\n }\n\n private forwardInvalidContextSubmissions(worker: Worker | undefined) {\n if (!worker) {\n return;\n }\n const entries = this.pendingInvalidContextSubmissions.takeSnapshot();\n if (entries.length === 0) {\n return;\n }\n const submissionsMessage: TelemetryInvalidContextSubmissionsEvent = {\n type: \"InvalidContextSubmissions\",\n payload: { entries },\n };\n worker.postMessage(submissionsMessage);\n }\n\n public async updateContext(value: ConfigDirectorContext | undefined) {\n if (this.closePromise) {\n return;\n }\n const updateContextMessage: TelemetryUpdateContextEvent = {\n type: \"UpdateContext\",\n payload: {\n context: value,\n },\n };\n this.startWorker()?.postMessage(updateContextMessage);\n }\n\n public evaluatedConfig<T extends ConfigValueType>(event: EvaluatedConfigEvent<T>): void {\n if (this.turnedOff) {\n return;\n }\n const evaluatedConfigMessage: TelemetryEvaluatedConfigEvent = {\n type: \"EvaluatedConfigEvent\",\n payload: this.sanitizeEvaluatedConfigEvent(event),\n };\n if (this.worker) {\n this.worker.postMessage(evaluatedConfigMessage);\n return;\n }\n if (this.pendingEvaluations.length >= this.pendingEvaluationLimit) {\n this.pendingEvaluations.shift();\n }\n this.pendingEvaluations.push(evaluatedConfigMessage);\n }\n\n public recordInvalidContext(kindSample: string): void {\n this.pendingInvalidContextSubmissions.record(kindSample);\n this.forwardInvalidContextSubmissions(this.worker);\n }\n\n public trackedEvent(admission: TrackedEventAdmission): void {\n if (this.turnedOff || this.closePromise) {\n return;\n }\n if (this.worker) {\n const trackedEventMessage: TelemetryTrackedEventEvent = { type: \"TrackedEvent\", payload: admission };\n this.worker.postMessage(trackedEventMessage);\n return;\n }\n logBatchWarnings(this.logger, this.pendingTrackedEvents.add(admission));\n }\n\n private sanitizeEvaluatedConfigEvent<T extends ConfigValueType>(\n event: EvaluatedConfigEvent<T>,\n ): EvaluatedConfigEvent<TelemetryValue> {\n return {\n ...event,\n defaultValue: mapToTelemetryValue({ value: event.defaultValue, type: event.type }),\n evaluatedValue: mapToTelemetryValue({\n value: event.evaluatedValue,\n valueId: event.evaluatedValueId,\n type: event.type,\n }),\n };\n }\n\n private handleWorkerEvent(event: TelemetryWorkerResponseEvent) {\n if (event.type === \"Closed\") {\n this.finishClose();\n return;\n }\n if (!event.payload?.level || !event.payload?.message) {\n return;\n }\n const { level, message, args } = event.payload;\n\n switch (level) {\n case \"debug\":\n this.logger.debug(message, ...args);\n break;\n case \"info\":\n this.logger.info(message, ...args);\n break;\n case \"warn\":\n this.logger.warn(message, ...args);\n break;\n case \"error\":\n this.logger.error(message, ...args);\n break;\n }\n }\n\n private flush() {\n const flushMessage: TelemetryFlushEvent = {\n type: \"Flush\",\n };\n this.worker?.postMessage(flushMessage);\n }\n\n public close(): Promise<void> {\n if (this.closePromise) {\n return this.closePromise;\n }\n\n return this.performClose();\n }\n\n private performClose(): Promise<void> {\n const worker = this.worker;\n if (!worker) {\n this.pendingEvaluations.length = 0;\n this.pendingTrackedEvents.clear();\n this.closePromise = Promise.resolve();\n return this.closePromise;\n }\n try {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n } catch (error) {\n this.logger.warn(\"[WebWorkerTelemetryClient] Could not remove 'visibilitychange' listener: \", error);\n }\n this.closePromise = new Promise<void>((resolve) => {\n this.closeResolve = resolve;\n this.closeTimer = setTimeout(() => {\n this.logger.warn(\n \"[WebWorkerTelemetryClient] Timed out waiting for the telemetry worker to close. Terminating the worker.\",\n );\n this.finishClose();\n }, this.workerCloseTimeout);\n const closeMessage: TelemetryCloseEvent = { type: \"Close\" };\n worker.postMessage(closeMessage);\n });\n return this.closePromise;\n }\n\n private finishClose() {\n clearTimeout(this.closeTimer);\n this.closeTimer = undefined;\n this.worker?.terminate();\n this.closeResolve?.();\n }\n}\n","const BASE62 = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\nexport const toBase62 = (buf: Uint8Array, length: number): string => {\n const ZERO = BigInt(0);\n const BASE = BigInt(62);\n const hex = Array.from(buf)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n let n = BigInt(\"0x\" + hex);\n let result = \"\";\n while (n > ZERO) {\n result = BASE62[Number(n % BASE)] + result;\n n /= BASE;\n }\n return result.padStart(length, \"0\");\n};\n","export const DIGEST_BYTES = 16;\nexport const BASE62_LENGTH = Math.ceil((DIGEST_BYTES * 8) / Math.log2(62));\n","import { toBase62 } from \"@shared/base62-encoder\";\nimport { DIGEST_BYTES, BASE62_LENGTH } from \"@shared/value-id\";\n\nconst encoder = new TextEncoder();\n\nexport const generateValueId = async (\n v: string | number | boolean | null | undefined,\n): Promise<string | undefined> => {\n if (typeof crypto === \"undefined\" || crypto.subtle == null) {\n return undefined;\n }\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", encoder.encode(v?.toString() ?? \"\"));\n return toBase62(new Uint8Array(hashBuffer, 0, DIGEST_BYTES), BASE62_LENGTH);\n};\n","import type { CachingProvider } from \"@js-client-core/index\";\nimport { CACHED_VALUES_STORAGE_KEY_PREFIX, DEFAULT_CACHING_SIZE_LIMIT_BYTES } from \"@js-client-core/cached-values\";\nimport { localStorageIfAvailable } from \"@js-client-core/browser-globals\";\n\nexport const localStorageCachingProvider = (clientSdkKeyDigest: Promise<string>): CachingProvider | undefined => {\n const storage = localStorageIfAvailable();\n if (!storage) {\n return undefined;\n }\n const storageKey = clientSdkKeyDigest.then((digest) => CACHED_VALUES_STORAGE_KEY_PREFIX + digest);\n return {\n read: async () => storage.getItem(await storageKey),\n write: async (value) => storage.setItem(await storageKey, value),\n remove: async () => storage.removeItem(await storageKey),\n sizeLimit: () => DEFAULT_CACHING_SIZE_LIMIT_BYTES,\n };\n};\n","import type { Sha256HexDigest } from \"@js-client-core/types\";\n\nconst toHex = (bytes: Uint8Array): string =>\n Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n\nexport const sha256HexDigestIfAvailable = (): Sha256HexDigest | undefined => {\n if (typeof crypto === \"undefined\" || crypto.subtle == null) {\n return undefined;\n }\n return async (text) => {\n const digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(text));\n return toHex(new Uint8Array(digest));\n };\n};\n","import {\n type ConfigDirectorClientOptions,\n type ConfigDirectorClient,\n type IdentifyingSdkOptions,\n type OfflineClientOptions,\n} from \"@js-client-core/index\";\nimport { WebWorkerTelemetryClient } from \"./telemetry/WebWorkerTelemetryClient\";\nimport { DefaultConfigDirectorClient } from \"@js-client-core/DefaultConfigDirectorClient\";\nimport { defaultUrlFactory } from \"@shared/url\";\nimport { generateValueId } from \"./telemetry/value-id-generator\";\nimport { localStorageCachingProvider } from \"./local-storage-caching-provider\";\nimport { sha256HexDigestIfAvailable } from \"./sha256-hex-digest\";\n\n/**\n * Creates a browser client. With a client SDK key it connects to ConfigDirector; with\n * {@link OfflineClientOptions} alone it runs in `offline` mode and serves `connection.values`. An\n * absent key with `clientOptions` is the same as the options alone when their mode is `offline`,\n * and fails like a missing key otherwise.\n */\nexport const createBrowserClient = (\n clientSdkKeyOrOptions: string | OfflineClientOptions | undefined,\n sdkOptions: IdentifyingSdkOptions,\n clientOptions?: ConfigDirectorClientOptions,\n): ConfigDirectorClient => {\n return DefaultConfigDirectorClient.from(\n ({ clientSdkKey, baseUrl, logger, metadata, clientSession }) =>\n new WebWorkerTelemetryClient({\n sdkKey: clientSdkKey,\n sdkIdentity: {\n sdkName: sdkOptions.sdkName,\n sdkVersion: sdkOptions.sdkVersion,\n },\n metaContext: {\n appName: metadata?.appName,\n appVersion: metadata?.appVersion,\n },\n logger,\n baseUrl,\n urlFactory: defaultUrlFactory,\n valueIdGenerator: generateValueId,\n clientSession,\n }),\n clientSdkKeyOrOptions,\n sdkOptions,\n clientOptions,\n { sha256HexDigest: sha256HexDigestIfAvailable(), platformCachingProvider: localStorageCachingProvider },\n );\n};\n","import type {\n ConfigDirectorLogMessageDecorator,\n ConfigDirectorLogger} from \"@js-browser-client/index\";\nimport {\n type ConfigDirectorLoggingLevel,\n createDefaultLogger as createJsSdkLogger,\n} from \"@js-browser-client/index\";\n\nclass MessageDecorator implements ConfigDirectorLogMessageDecorator {\n decorateMessage(message: string): string {\n return `[ConfigDirector:react-web-sdk] ${message}`;\n }\n}\n\nexport const createConsoleLogger = (level: ConfigDirectorLoggingLevel): ConfigDirectorLogger => {\n return createJsSdkLogger(level, new MessageDecorator());\n};\n","export const deepEqual = (left: unknown, right: unknown): boolean => {\n if (Object.is(left, right)) {\n return true;\n }\n if (typeof left !== \"object\" || typeof right !== \"object\" || left === null || right === null) {\n return false;\n }\n if (Object.getPrototypeOf(left) !== Object.getPrototypeOf(right)) {\n return false;\n }\n if (left instanceof Date && right instanceof Date) {\n return left.getTime() === right.getTime();\n }\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((item, index) => deepEqual(item, right[index]));\n }\n if (!isPlainObject(left) || !isPlainObject(right)) {\n return false;\n }\n const leftKeys = Object.keys(left);\n const rightKeys = Object.keys(right);\n return (\n leftKeys.length === rightKeys.length &&\n leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key]))\n );\n};\n\nconst isPlainObject = (value: object): value is Record<string, unknown> => {\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n","import type { ConfigDirectorClient, ConfigDirectorContext } from \"./types\";\nimport { deepEqual } from \"@shared/deepEqual\";\n\nexport type MountAction = \"initialize\" | \"updateContext\" | \"none\";\n\nexport const decideMountAction = (\n client: ConfigDirectorClient,\n context: ConfigDirectorContext | undefined,\n): MountAction => {\n if (client.isInitializing) {\n return \"none\";\n }\n if (!client.isReady) {\n return \"initialize\";\n }\n if (context !== undefined && !deepEqual(context, client.context)) {\n return \"updateContext\";\n }\n return \"none\";\n};\n","import type {\n ConfigDirectorClient,\n ConfigDirectorClientOptions} from \"@js-browser-client/index\";\nimport {\n createBrowserClient,\n} from \"@js-browser-client/index\";\n\nexport const createClient = (\n clientSdkKey: string | undefined,\n clientOptions?: ConfigDirectorClientOptions,\n): ConfigDirectorClient => {\n return createBrowserClient(\n clientSdkKey,\n { sdkName: \"react-web-sdk\", sdkVersion: \"__VERSION__\" },\n clientOptions,\n );\n};\n\n","import type { ConfigDirectorClient } from \"@js-browser-client/index\";\nimport { readInstalledTestClient } from \"@js-client-core/installedTestClient\";\nimport { createClient } from \"./client\";\nimport { createConsoleLogger } from \"./logger\";\nimport type { ConfigDirectorProviderOptions, ConfigDirectorProviderProps } from \"./types\";\n\nexport type ClientSource = { client: ConfigDirectorClient; owned: boolean };\n\nexport const buildClient = (options: ConfigDirectorProviderOptions): ConfigDirectorClient =>\n createClient(options.sdkKey, {\n connection: {\n url: options.url,\n timeout: options.timeout,\n mode: options.mode,\n pollingInterval: options.pollingInterval,\n values: options.values,\n },\n metadata: { appName: options.appName, appVersion: options.appVersion },\n logger: options.logger ?? createConsoleLogger(\"warn\"),\n hooks: options.hooks,\n caching: options.caching,\n });\n\nexport const hasGivenClient = (props: ConfigDirectorProviderProps): props is { client: ConfigDirectorClient } =>\n \"client\" in props && props.client !== undefined;\n\nexport const resolveClientSource = (props: ConfigDirectorProviderProps): ClientSource => {\n if (hasGivenClient(props)) {\n return { client: props.client, owned: false };\n }\n const installed = readInstalledTestClient();\n if (installed) {\n return { client: installed, owned: false };\n }\n return { client: buildClient(props), owned: true };\n};\n","import { useEffect, useState, type ReactNode } from \"react\";\nimport { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport { readInstalledTestClient } from \"@js-client-core/installedTestClient\";\nimport { decideMountAction } from \"@js-client-core/mountAction\";\nimport type { ConfigDirectorContext } from \"@js-browser-client/index\";\nimport { buildClient } from \"./clientSource\";\nimport type { ConfigDirectorProviderOptions, ConfigDirectorProviderState } from \"./types\";\n\nexport const withProvider = async (options: ConfigDirectorProviderOptions) => {\n const client =\n readInstalledTestClient() ?? buildClient({ ...options, logger: options.logger ?? createConsoleLogger(\"debug\") });\n switch (decideMountAction(client, options.context)) {\n case \"initialize\":\n await client.initialize(options.context);\n break;\n case \"updateContext\":\n await client.updateContext(options.context as ConfigDirectorContext);\n break;\n case \"none\":\n break;\n }\n\n const ConfigDirectorProvider = ({ children }: { children: ReactNode }) => {\n const [data, setData] = useState<ConfigDirectorProviderState>(() => ({\n client,\n status: client.isReady ? \"ready\" : \"default\",\n }));\n\n useEffect(() => {\n const onConfigsUpdated = () => {\n setData((prevState) => ({ ...prevState, updatedAt: new Date() }));\n };\n const onClientReady = () => {\n setData((prevState) => (prevState.status === \"ready\" ? prevState : { ...prevState, status: \"ready\" }));\n };\n client.on(\"configsUpdated\", onConfigsUpdated);\n client.on(\"clientReady\", onClientReady);\n if (client.isReady) {\n onClientReady();\n }\n return () => {\n client.off(\"configsUpdated\", onConfigsUpdated);\n client.off(\"clientReady\", onClientReady);\n };\n }, []);\n\n return <reactContext.Provider value={data}>{children}</reactContext.Provider>;\n };\n\n return ConfigDirectorProvider;\n};\n","import type { ClientEvents, ClientHooks, ConfigDirectorClient } from \"./types\";\n\ntype Registration = { event: keyof ClientEvents; handler: (payload: any) => void };\n\nexport class ClientHandlers {\n private registrations: Registration[] = [];\n\n constructor(private readonly client: ConfigDirectorClient) {}\n\n public on<T extends keyof ClientEvents>(event: T, handler: (payload: ClientEvents[T]) => void) {\n this.client.on(event, handler);\n this.registrations.push({ event, handler });\n }\n\n public registerHooks(hooks: ClientHooks | undefined) {\n for (const [event, handlerOrHandlers] of Object.entries(hooks ?? {})) {\n const handlers = Array.isArray(handlerOrHandlers) ? handlerOrHandlers : [handlerOrHandlers];\n for (const handler of handlers) {\n if (typeof handler === \"function\") {\n this.on(event as keyof ClientEvents, handler as (payload: unknown) => void);\n }\n }\n }\n }\n\n public removeAll() {\n for (const { event, handler } of this.registrations) {\n this.client.off(event, handler);\n }\n this.registrations = [];\n }\n}\n","import { reactContext } from \"./context\";\nimport { createConsoleLogger } from \"./logger\";\nimport { Component, type PropsWithChildren } from \"react\";\nimport type { ConfigDirectorClient, ConfigDirectorContext } from \"@js-browser-client/index\";\nimport { decideMountAction } from \"@js-client-core/mountAction\";\nimport { deepEqual } from \"@shared/deepEqual\";\nimport { buildClient, hasGivenClient, resolveClientSource } from \"./clientSource\";\nimport { ClientHandlers } from \"@js-client-core/clientHandlers\";\nimport type {\n ClientStatus,\n ConfigDirectorProviderOptions,\n ConfigDirectorProviderProps,\n ConfigDirectorProviderState,\n} from \"./types\";\n\nconst settledStatusOf = (client: ConfigDirectorClient | undefined): ClientStatus =>\n client?.isReady ? \"ready\" : \"default\";\n\nexport class ConfigDirectorProvider extends Component<\n PropsWithChildren<ConfigDirectorProviderProps>,\n ConfigDirectorProviderState\n> {\n private readonly ownsClient: boolean;\n private disposedOwnClient = false;\n private handlers: ClientHandlers | undefined;\n\n constructor(props: ConfigDirectorProviderProps) {\n super(props);\n const source = resolveClientSource(props);\n this.ownsClient = source.owned;\n this.state = { client: source.client, status: source.client.isReady ? \"ready\" : \"loading\" };\n }\n\n override async componentDidMount(): Promise<void> {\n let client = this.state.client as ConfigDirectorClient;\n if (this.ownsClient && this.disposedOwnClient) {\n client = buildClient(this.props as ConfigDirectorProviderOptions);\n this.disposedOwnClient = false;\n this.setState({ client, status: \"loading\" });\n }\n this.handlers = new ClientHandlers(client);\n this.handlers.on(\"configsUpdated\", () => {\n this.setState({ updatedAt: new Date() });\n });\n this.handlers.on(\"clientReady\", () => {\n this.setState({ status: \"ready\" });\n });\n if (!this.ownsClient) {\n this.handlers.registerHooks(this.props.hooks);\n }\n await this.connect(client, this.props.context);\n }\n\n private async connect(client: ConfigDirectorClient, context: ConfigDirectorContext | undefined): Promise<void> {\n switch (decideMountAction(client, context)) {\n case \"initialize\":\n await client.initialize(context);\n break;\n case \"updateContext\":\n this.setState({ status: \"loading\" });\n await client.updateContext(context as ConfigDirectorContext);\n break;\n case \"none\":\n return;\n }\n this.setState({ status: settledStatusOf(client) });\n }\n\n override async componentDidUpdate(prevProps: PropsWithChildren<ConfigDirectorProviderProps>): Promise<void> {\n if (hasGivenClient(prevProps) && hasGivenClient(this.props) && prevProps.client !== this.props.client) {\n createConsoleLogger(\"warn\").warn(\n \"The client prop of ConfigDirectorProvider changed after it mounted and is ignored. Remount the provider, for example with a new key, to use another client.\",\n );\n }\n if (!deepEqual(prevProps.context, this.props.context)) {\n this.setState({ status: \"loading\" });\n await this.state.client?.updateContext(this.props.context ?? {});\n this.setState({ status: settledStatusOf(this.state.client) });\n }\n }\n\n override componentWillUnmount(): void {\n this.handlers?.removeAll();\n this.handlers = undefined;\n if (this.ownsClient) {\n this.state.client?.dispose();\n this.disposedOwnClient = true;\n }\n }\n\n override render() {\n return <reactContext.Provider value={this.state}>{this.props.children}</reactContext.Provider>;\n }\n}\n","export class ConfigDirectorReactContextError extends Error {\n public override readonly name: string = \"ConfigDirectorReactContextError\";\n\n constructor(message: string) {\n super(message);\n\n Object.setPrototypeOf(this, ConfigDirectorReactContextError.prototype);\n }\n}\n","\"use client\";\n\nimport { useContext as useReactContext } from \"react\";\nimport { reactContext } from \"./context\";\nimport type {\n ConfigDirectorContext,\n ConfigValueType,\n} from \"@js-browser-client/index\";\nimport { ConfigDirectorReactContextError } from \"./errors\";\nimport type { ClientStatus } from \"./types\";\n\nconst noContextError = () => {\n return new ConfigDirectorReactContextError(\"The ConfigDirector client was not found in the React context. Please make sure the component using this hook is inside the context of a ConfigDirectorProvider.\");\n};\n\nconst useConfigValue = <T extends ConfigValueType>(\n key: string,\n defaultValue: T,\n): {\n value: T;\n readyStatus: ClientStatus;\n loading: boolean;\n} => {\n const configDirectorReactContext = useReactContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const value = configDirectorReactContext.client.getValue(key, defaultValue);\n\n return { value, readyStatus: configDirectorReactContext.status, loading: configDirectorReactContext.status === \"loading\" };\n};\n\nconst useContext = () => {\n const configDirectorReactContext = useReactContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n const updateContext = async (context: ConfigDirectorContext) => {\n await configDirectorReactContext.client?.updateContext(context);\n };\n\n return { updateContext };\n};\n\nconst useClient = () => {\n const configDirectorReactContext = useReactContext(reactContext);\n if (!configDirectorReactContext?.client) {\n throw noContextError();\n }\n\n return { client: configDirectorReactContext.client };\n};\n\nexport { useConfigValue, useContext, useClient };\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ const e=e=>e>=55296&&e<=56319,t=e=>e>=56320&&e<=57343,n=n=>{let r=0;for(let i=0;i<n.length;i++){let a=n.charCodeAt(i);a<=127?r+=1:a<=2047?r+=2:e(a)&&i+1<n.length&&t(n.charCodeAt(i+1))?(r+=4,i++):r+=3}return r},r=e=>{var t;let n=e!=null&&e.anonymous||e==null?void 0:e.id;return n===void 0?{}:{contextKind:(t=e==null?void 0:e.kind)==null?`user`:t,contextIdentifier:n}};function i(e){"@babel/helpers - typeof";return i=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},i(e)}function a(e,t){if(i(e)!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(i(r)!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function o(e){var t=a(e,`string`);return i(t)==`symbol`?t:t+``}function s(e,t,n){return(t=o(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function l(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?c(Object(n),!0).forEach(function(t){s(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):c(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}const u=1e3,d=1024,f={"name-outside-the-character-limit":`[ConfigDirectorClient] A tracked event was not reported because its name does not have 1 to 150 characters.`,"value-not-a-finite-number":`[ConfigDirectorClient] A tracked event was reported without its value because the value is not a finite number.`,"details-not-reportable":`[ConfigDirectorClient] A tracked event was reported without its details because they are not an object, have more than 20 top-level keys, are larger than ${d} bytes as JSON, or cannot be written as JSON.`,"batch-already-full":`[ConfigDirectorClient] A tracked event was not reported because ${u} tracked events are already waiting for the next telemetry batch.`},p=(e,t)=>{for(let n of t)e.warn(`${f[n]} Further tracked events like it are not logged until the next telemetry batch is sent.`)},m=e=>e!=null,h=e=>typeof e==`object`&&!!e&&!Array.isArray(e),g=e=>typeof e==`string`&&e.length>=1&&e.length<=300&&Array.from(e).length<=150,_=e=>m(e)?typeof e==`number`&&Number.isFinite(e)?{status:`reportable`,fields:{value:e}}:{status:`left-out`,warning:`value-not-a-finite-number`}:{status:`not-given`},ee=e=>{if(h(e))try{let t=JSON.stringify(e);if(typeof t!=`string`||n(t)>d)return;let r=JSON.parse(t);return h(r)&&Object.keys(r).length<=20?r:void 0}catch(e){return}},te=e=>{if(!m(e))return{status:`not-given`};let t=ee(e);return t===void 0?{status:`left-out`,warning:`details-not-reportable`}:{status:`reportable`,fields:{details:t}}},v=e=>e.status===`reportable`?e.fields:void 0,ne=(...e)=>e.flatMap(e=>e.status===`left-out`?[e.warning]:[]),re=e=>{var t,n;if(!g(e.name))return{outcome:`dropped`,warnings:[`name-outside-the-character-limit`]};let i=_((t=e.options)==null?void 0:t.value),a=te((n=e.options)==null?void 0:n.details);return{outcome:`admitted`,entry:l(l(l(l({name:e.name},r(e.context)),v(i)),v(a)),{},{happenedAt:e.happenedAt.toISOString()}),warnings:ne(i,a)}};var y=class{constructor(){this.handlerMap=new Map}on(e,t){let n=this.handlerMap.get(e);n?n.push(t):this.handlerMap.set(e,[t])}once(e,t){let n=this;function r(i){n.off(e,r),t.apply(n,i)}this.on(e,r)}off(e,t){let n=this.handlerMap.get(e);if(n)if(t){let e=n.indexOf(t);e>=0&&n.splice(e,1)}else this.handlerMap.set(e,[])}clear(){this.handlerMap.clear()}emit(e,t){let n=this.handlerMap.get(e);n&&n.slice().map(e=>e(t))}},b=class e extends Error{constructor(t,n){super(t),this.name=`ConfigDirectorConnectionError`,this.status=n,Object.setPrototypeOf(this,e.prototype)}},x=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorValidationError`,Object.setPrototypeOf(this,e.prototype)}},S=class e extends Error{constructor(t){super(t),this.name=`ConfigDirectorInitializationError`,Object.setPrototypeOf(this,e.prototype)}},ie=class e extends Error{constructor(t){super(t),this.name=`StreamClosedError`,Object.setPrototypeOf(this,e.prototype)}},ae=class e extends Error{constructor(t){super(t),this.name=`MissingResponseBodyError`,Object.setPrototypeOf(this,e.prototype)}},oe=class e extends Error{constructor(t){super(t),this.name=`InvalidOptionError`,Object.setPrototypeOf(this,e.prototype)}},se=class e extends Error{constructor(t){super(t),this.name=`ValueOutOfRangeError`,Object.setPrototypeOf(this,e.prototype)}},ce=class{constructor(e){var t;this.isFirstChunk=!0,this.bufferedInput=``,this.currentEvent={data:``},this.currentEvent={data:``},this.onEvent=(t=e.onEvent)==null?(()=>{}):t,this.onRetry=e.onRetry,this.onComment=e.onComment}parse(e){let t=e;this.isFirstChunk&&(this.isFirstChunk=!1,t.startsWith(``)?t=t.slice(1):t.startsWith(``)&&(t=t.slice(3)));let n=this.scanLines(this.bufferedInput+t);for(let e of n)this.dispatchLine(e)}finish(){this.bufferedInput=``}scanLines(e){let t=[],n=0,r=0;for(;r<e.length;){let i=e[r];i===`\r`||i===`
2
+ `?(t.push(e.slice(n,r)),i===`\r`&&e[r+1]===`
3
+ `&&r++,r++,n=r):r++}return this.bufferedInput=e.slice(n),t}dispatchLine(e){if(e.startsWith(`:`)){var t;(t=this.onComment)==null||t.call(this,this.extractValue(e,1));return}if(e===``){this.emitEvent();return}this.applyField(this.parseField(e))}emitEvent(){let e=this.currentEvent.data.endsWith(`
4
+ `)?this.currentEvent.data.slice(0,-1):this.currentEvent.data;e!==``&&this.onEvent(l(l({},this.currentEvent),{},{id:this.lastEventId,data:e})),this.currentEvent={data:``}}applyField(e){switch(e.field){case`event`:this.currentEvent.type=e.value;break;case`data`:this.currentEvent.data+=e.value+`
5
+ `;break;case`id`:e.value.includes(`\0`)||(this.lastEventId=e.value);break;case`retry`:if(/^\d+$/.test(e.value)){var t;(t=this.onRetry)==null||t.call(this,Number.parseInt(e.value,10))}break;default:break}}parseField(e){let t=e.indexOf(`:`);return t===-1?{field:e,value:``}:{field:e.slice(0,t),value:this.extractValue(e,t+1)}}extractValue(e,t){return e[t]===` `?e.slice(t+1):e.slice(t)}};let C=function(e){return e.OPEN=`open`,e.CLOSED=`closed`,e.CONNECTING=`connecting`,e}({});var le=class{constructor(e){var t,n;this.DEFAULT_SHOULD_RECONNECT=()=>!0,this.DEFAULT_CALCULATE_RECONNECT_DELAY=()=>this.serverReconnectionTime,this.reconnectAttempt=0,this.abortController=new AbortController,this._readyState=C.CLOSED,this.serverReconnectionTime=2e3,this.url=e.url.toString(),this.lastEventId=e.lastEventId,this.headers=l({Accept:`text/event-stream`},e.headers);let r=e.body;this.body=typeof r==`function`?r:()=>r,this.requestOptions={method:(t=e.method)==null?`GET`:t,mode:e.mode,credentials:e.credentials,redirect:e.redirect,referrer:e.referrer,referrerPolicy:e.referrerPolicy},this._fetch=(n=e.fetch)==null?((e,t)=>fetch(e,t)):n,this._onError=this.resolveCallback(e.onError,()=>{},`onError`),this._onConnect=this.resolveCallback(e.onConnect,()=>{},`onConnect`),this._onDisconnect=this.resolveCallback(e.onDisconnect,()=>{},`onDisconnect`),this._onMessage=this.resolveCallback(e.onMessage,()=>{},`onMessage`),this._onComment=this.resolveCallback(e.onComment,()=>{},`onComment`),this._shouldReconnect=this.resolveCallback(e.shouldReconnect,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`),this._calculateReconnectDelay=this.resolveCallback(e.calculateReconnectDelay,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`calculateReconnectDelay`)}set onError(e){this._onError=this.resolveCallback(e,()=>{},`onError`)}set onMessage(e){this._onMessage=this.resolveCallback(e,()=>{},`onMessage`)}set onComment(e){this._onComment=this.resolveCallback(e,()=>{},`onComment`)}set onConnect(e){this._onConnect=this.resolveCallback(e,()=>{},`onConnect`)}set onDisconnect(e){this._onDisconnect=this.resolveCallback(e,()=>{},`onDisconnect`)}set shouldReconnect(e){this._shouldReconnect=this.resolveCallback(e,this.DEFAULT_SHOULD_RECONNECT,`shouldReconnect`)}set calculateReconnectDelay(e){this._calculateReconnectDelay=this.resolveCallback(e,this.DEFAULT_CALCULATE_RECONNECT_DELAY,`shouldReconnect`)}get readyState(){return this._readyState}connect(){this._readyState===C.CLOSED&&(this.reconnectAttempt=0,this.initiateConnection())}close(){clearTimeout(this.reconnectTimeout),this._readyState=C.CLOSED,this.abortController.abort()}initiateConnection(){this.abortController=new AbortController,this._readyState=C.CONNECTING,this._fetch(this.url,l(l({},this.requestOptions),{},{body:this.body(),headers:this.buildRequestHeaders(),signal:this.abortController.signal,cache:`no-store`})).then(e=>this.handleFetchResponse(e)).catch(e=>{if(e.name===`AbortError`||this.abortController.signal.aborted){this.close();return}this._onError(e),this.scheduleReconnect({error:e})})}async handleFetchResponse(e){var t=this;let{body:n,status:r}=e;if(r===204){t.disconnected();return}if(r>=400){t.scheduleReconnect({status:r});return}if(!n)throw new ae(`The server response did not have a body`);t._readyState=C.OPEN,t._onConnect(),t.reconnectAttempt=0;let i=new ce({onEvent:e=>{typeof e.id==`string`&&(t.lastEventId=e.id),t._onMessage(e)},onComment:e=>t._onComment(e),onRetry:e=>t.serverReconnectionTime=e});await t.readResponseStream(n,i),t.scheduleReconnect({status:r,error:new ie(`The server response stream was closed`)})}async readResponseStream(e,t){let n=e.getReader(),r=new TextDecoder,i=!1;for(;!i;){let e=await n.read();e.value&&t.parse(r.decode(e.value,{stream:!0})),i=e.done}t.finish()}disconnected(){clearTimeout(this.reconnectTimeout),this._readyState=C.CLOSED,this._onDisconnect()}buildRequestHeaders(){let e=this.lastEventId?{"Last-Event-ID":this.lastEventId}:void 0;return l(l({},this.headers),e)}scheduleReconnect(e){if(this.abortController.signal.aborted)return;clearTimeout(this.reconnectTimeout),this.reconnectAttempt+=1;let t={attempt:this.reconnectAttempt,status:e.status,error:e.error,serverReconnectionTime:this.serverReconnectionTime};if(!this._shouldReconnect(t)){this.disconnected();return}this._readyState=C.CONNECTING;let n=this._calculateReconnectDelay(t);(!Number.isFinite(n)||n<1||n>1e3*60*60)&&(this._onError(new se(`The calculated reconnect delay is out of range: ${n}. Defaulting to ${this.serverReconnectionTime}`)),n=this.serverReconnectionTime),this.reconnectTimeout=setTimeout(()=>this.initiateConnection(),n)}resolveCallback(e,t,n){if(e==null)return t;if(typeof e!=`function`)throw new oe(`${n} must be a function`);return e}};const ue=e=>new le(e);var de=class{constructor(e){this.options=e,this.eventEmitter=new y,this.connectionGeneration=0,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/sse/v1`,e.baseUrl)}async connect(e,t){var n=this;let r=++n.connectionGeneration,i=await n.options.clientSession;if(r!==n.connectionGeneration)return n;n.eventSource&&n.close();let a=new Promise((t,r)=>{n.eventSource=ue({url:n.url,method:`POST`,headers:{"Content-Type":`application/json`},fetch:n.options.fetch,body:JSON.stringify({givenContext:e,metaContext:n.options.metaContext,clientSdkKey:n.options.clientSdkKey,instanceId:i.instanceId,ephemeral:i.ephemeral}),onMessage:({data:e})=>{n.dispatchMessage(e)},onConnect:()=>{n.logger.debug(`[StreamingTransport] Connected`),t(n)},shouldReconnect:e=>{let t=!n.isStatusFatal(e.status);if(!t){let t=n.prepareFatalError(e.status,e.error);n.eventEmitter.emit(`connectionError`,t),r(t)}return t},calculateReconnectDelay:e=>{let t=n.options.connectionRetryDelay(e.attempt),r=`[StreamingTransport] Scheduling reconnect attempt #${e.attempt} in ${t}ms.`;return e.attempt<=5?n.logger.info(r):n.logger.warn(r),t},onError:e=>{n.logger.debug(`[StreamingTransport] Error: `,e)},onDisconnect:()=>{n.logger.debug(`[StreamingTransport] Disconnected`)}}),n.eventSource.connect()});return clearTimeout(n.timeoutTimer),n.timeoutTimer=void 0,Promise.race([a,new Promise(e=>{n.timeoutTimer=setTimeout(()=>e(n),t)})]).finally(()=>clearTimeout(n.timeoutTimer))}dispatchMessage(e){try{let t=JSON.parse(e);this.eventEmitter.emit(`configSetReceived`,t)}catch(e){this.logger.error(`[StreamingTransport] Error parsing and dispatching config data update: `,e)}}prepareFatalError(e,t){let n=e==null?0:e;return new b(`${`Connection failed with status: ${e==null?`unknown`:e}.`}${t?` Error: ${t}`:``}. This is an unrecoverable error, will not attempt to reconnect.`,n)}isStatusFatal(e){return!!e&&e>=400&&e<500&&e!=429}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}close(){var e;this.connectionGeneration++,(e=this.eventSource)==null||e.close(),clearTimeout(this.timeoutTimer)}dispose(){this.close(),this.clear()}};const fe=(e,t)=>{if(e.trim().length==0)throw new x(`Invalid config key. The key of a value cannot be empty.`);return pe(e,t)},pe=(e,t)=>{switch(typeof t){case`boolean`:return{type:`boolean`,value:t?`true`:`false`};case`number`:return me(e,t);case`string`:return{type:`string`,value:t};case`object`:if(t!==null)return w(e,t,``),{type:`json`,value:JSON.stringify(t)}}throw new x(`Invalid value for '${e}': ${E(t)}. Use a boolean, a number, a string, a plain object, or an array.`)},me=(e,t)=>{if(!Number.isFinite(t))throw new x(`Invalid value for '${e}': ${E(t)} is not a finite number.`);if(Number.isInteger(t)){if(!Number.isSafeInteger(t))throw new x(`Invalid value for '${e}': ${t} is not a safe integer, so the SDK could not read it back exactly.`);return{type:`integer`,value:String(t)}}return{type:`float`,value:he(t)}},he=e=>{let t=String(e),n=t.indexOf(`e-`);if(n<0)return t;let r=t.startsWith(`-`)?`-`:``,[i=``,a=``]=t.slice(r.length,n).split(`.`),o=Number(t.slice(n+2))-i.length;return`${r}0.${`0`.repeat(o)}${i}${a}`},w=(e,t,n)=>{if(!(t===null||typeof t==`boolean`||typeof t==`string`)){if(typeof t==`number`){if(!Number.isFinite(t))throw T(e,n,`${E(t)} is not a finite number`);return}if(Array.isArray(t)){t.forEach((t,r)=>w(e,t,`${n}[${r}]`));return}if(ge(t)){for(let[r,i]of Object.entries(t))w(e,i,n?`${n}.${r}`:r);return}throw T(e,n,`${E(t)} cannot be encoded as JSON`)}},T=(e,t,n)=>new x(`Invalid value for '${e}'${t?` at '${t}'`:``}: ${n}. JSON contents can hold booleans, finite numbers, strings, null, arrays, and plain objects.`),ge=e=>{if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null},E=e=>{if(e===null)return`null`;if(typeof e==`function`)return`a function`;if(typeof e==`object`){var t,n;return`a ${(t=(n=e.constructor)==null?void 0:n.name)==null?`object`:t} instance`}return typeof e==`symbol`?`a symbol`:String(e)},D=(e,t,n,r)=>{let i=fe(t,n);return{id:e,key:t,type:i.type,value:i.value,valueId:r}},_e={environmentId:`offline`,projectId:`offline`};var O=class{constructor(e){this.source=e,this.emitter=new y,this.on=(e,t)=>this.emitter.on(e,t),this.off=(e,t)=>this.emitter.off(e,t)}async connect(){var e=this;let t=k(e.source);return e.emitter.emit(`configSetReceived`,l(l({},_e),{},{kind:`full`,configs:t})),e}clear(){this.emitter.clear()}close(){}dispose(){this.clear()}};const k=e=>{switch(e.kind){case`in-code-defaults`:return{};case`values`:return A(e.values);case`rejected`:throw new S(e.message)}},A=e=>{try{return Object.fromEntries(Object.entries(e).map(([e,t])=>[e,D(`offline:${e}`,e,t,void 0)]))}catch(e){throw e instanceof x?new S(`The offline values could not be loaded. ${e.message}`):e}},j=(e,t,n)=>{var r;if((t==null?void 0:t.mode)===`offline`)return{kind:`stay-offline`,source:N(t)};let i=(r=t==null?void 0:t.mode)==null?`streaming`:r;if(!e||e.trim().length==0)throw new x(`No client SDK key was provided, the client cannot be instantiated without a valid client SDK key`);return(t==null?void 0:t.values)===void 0?{kind:`connect`,mode:i,clientSdkKey:e,baseUrl:M(t==null?void 0:t.url,n)}:{kind:`stay-offline`,source:{kind:`rejected`,message:`The connection option 'values' applies only when the connection mode is 'offline', but the mode is '${i}'.`}}},M=(e,t)=>{if(!e)return`https://client-sdk-api.configdirector.com`;try{return t(e)}catch(t){throw new x(`Invalid base URL '${e}'. Parsing failed: ${t}`)}},N=e=>e.values===void 0?{kind:`in-code-defaults`}:{kind:`values`,values:e.values},P={variation:void 0,ruleId:void 0,shareId:void 0},F=e=>{let t=e.variation;if(t!=null)return t.name?{id:t.id,name:t.name}:{id:t.id}},I=e=>{var t,n;return{variation:F(e),ruleId:(t=e.ruleId)==null?void 0:t,shareId:(n=e.shareId)==null?void 0:n}},L=e=>{let t=typeof e;if(t===`object`)try{var n,r;return(n=(r=e.constructor)==null?void 0:r.name)==null?t:n}catch(e){return t}else if(t===`function`)try{let n=e.name;return n?`function: ${n}`:t}catch(e){return t}return t},R=e=>e===`number`||e===`bigint`,ve=new Set([`boolean`,`integer`,`float`]),ye=(e,t)=>{let n=be(e,t);return l(l({},n),n.usedDefault?P:I(e))},be=(e,t)=>{let n=e.value,r=L(t);if(n==null||n===``)return{parsedValue:t,parsedValueId:void 0,requestedType:r,usedDefault:!0,reason:`value-missing`};if(e.type===`json`)return Te(n,t,r,e.valueId);if(typeof t==`string`)return ve.has(e.type)?{parsedValue:t,parsedValueId:void 0,requestedType:r,usedDefault:!0,reason:`type-mismatch`}:{parsedValue:n,parsedValueId:e.valueId,requestedType:r,usedDefault:!1,reason:`found-match`};if(typeof t==`boolean`&&(e.type===`boolean`||e.type===`string`||e.type===`enum`)){let i=xe(n),a=typeof i==`boolean`;return{parsedValue:a?i:t,parsedValueId:a?e.valueId:void 0,requestedType:r,usedDefault:!a,reason:a?`found-match`:`invalid-boolean`}}if(R(typeof t)&&e.type===`integer`){let i=Se(n),a=typeof i==`number`;return{parsedValue:a?i:t,parsedValueId:a?e.valueId:void 0,requestedType:r,usedDefault:!a,reason:a?`found-match`:`invalid-number`}}if(R(typeof t)&&(e.type===`float`||e.type===`enum`||e.type===`string`)){let i=Ce(n),a=typeof i==`number`;return{parsedValue:a?i:t,parsedValueId:a?e.valueId:void 0,requestedType:r,usedDefault:!a,reason:a?`found-match`:`invalid-number`}}return{parsedValue:t,parsedValueId:void 0,requestedType:r,usedDefault:!0,reason:`type-mismatch`}},xe=e=>{if(!e)return;let t=e.toLowerCase();if(!(t!=`true`&&t!=`false`))return t===`true`},Se=e=>{let t=z(e);return t==null?void 0:Math.trunc(t)},Ce=e=>z(e),z=e=>{if(!e||!we(e))return;let t=Number(e);if(!(isNaN(t)||!isFinite(t)))return t},we=e=>{for(let t of e)if(!(t>=`0`&&t<=`9`)&&!`+-.eE`.includes(t))return!1;return!0},Te=(e,t,n,r)=>{if(typeof t==`string`)return{parsedValue:e,parsedValueId:r,requestedType:n,usedDefault:!1,reason:`found-match`};try{let i=JSON.parse(e);return Ee(i,t)?{parsedValue:i,parsedValueId:r,requestedType:n,usedDefault:!1,reason:`found-match`}:{parsedValue:t,parsedValueId:void 0,requestedType:n,usedDefault:!0,reason:`type-mismatch`}}catch(e){return{parsedValue:t,parsedValueId:void 0,requestedType:n,usedDefault:!0,reason:`invalid-json`}}},Ee=(e,t)=>e===null?!1:B(e)===B(t),B=e=>{if(Array.isArray(e))return`array`;let t=typeof e;return t===`bigint`?`number`:t},V={off:-1,error:0,warn:1,info:2,debug:3},De=()=>{let e={year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,timeZoneName:`short`};try{return new Intl.DateTimeFormat(void 0,l(l({},e),{},{fractionalSecondDigits:3}))}catch(t){return new Intl.DateTimeFormat(void 0,e)}};var Oe=class{constructor(e,t){this.level=e,this.decorator=t,this.level=e,this.decorator=t,this.dateFormatter=De()}debug(e,...t){this.log(console.debug,`debug`,e,...t)}info(e,...t){this.log(console.info,`info`,e,...t)}warn(e,...t){this.log(console.warn,`warn`,e,...t)}error(e,...t){this.log(console.error,`error`,e,...t)}log(e,t,n,...r){if(V[this.level]>=V[t]){var i;e(`[${this.dateFormatter.format(new Date)}] ${(i=this.decorator)==null?void 0:i.decorateMessage(n)}`,...r)}}},ke=class{decorateMessage(e){return`[ConfigDirector:js-client-sdk] ${e}`}};const H=(e,t)=>new Oe(e==null?`warn`:e,t==null?new ke:t),U={updateContext:async()=>{},evaluatedConfig:()=>{},recordInvalidContext:()=>{},trackedEvent:()=>{},close:async()=>{}},W=(e,t)=>new URL(e,t==null?void 0:t.toString()),Ae=(e,t)=>e===void 0?{seconds:t.defaultSeconds,warning:void 0}:e>=t.minimumSeconds?{seconds:e,warning:void 0}:{seconds:t.minimumSeconds,warning:`pollingInterval of ${e} seconds is below the minimum of ${t.minimumSeconds} seconds. Using ${t.minimumSeconds} seconds.`},je=()=>typeof crypto<`u`&&typeof crypto.randomUUID==`function`?crypto.randomUUID():`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`.replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e===`x`?t:t&3|8).toString(16)}),G=e=>{try{return e(globalThis)}catch(e){return}},Me=()=>G(e=>{var t;return(t=e.navigator)==null?void 0:t.userAgent}),Ne=()=>G(e=>{var t;return(t=e.location)==null?void 0:t.host}),K=()=>{try{var e;return(e=globalThis.localStorage)==null?void 0:e}catch(e){return}},q=`configdirector-sdk:instance-id`,J=1e3,Pe=/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/,Y=(e,t)=>{let n=t;for(let t=0;t<e.length;t++)n^=e.charCodeAt(t),n=Math.imul(n,16777619);return n>>>0},X=(e,t)=>{let n=`configdirector.instanceId.v1|${e}|${t}`,r=Y(n,2166136261);return Y(`${r}|${n}`,16777619).toString(16).padStart(8,`0`)+r.toString(16).padStart(8,`0`)},Fe=e=>{if(!e||typeof e!=`object`)return!1;let{v:t,id:n,createdAt:r,checksum:i}=e;return t!==1||typeof n!=`string`||typeof i!=`string`||typeof r!=`number`||!Number.isInteger(r)||r<=0||!Pe.test(n)?!1:i===X(n,r)},Ie=async(e,t)=>{let n;try{n=await e.getItem(q)}catch(e){return t.debug(`[ConfigDirectorClient] Could not read the stored instance id, using an ephemeral one`,e),{outcome:`failed`}}if(typeof n!=`string`||n===``)return{outcome:`nothing usable`};let r;try{r=JSON.parse(n)}catch(e){return t.debug(`[ConfigDirectorClient] The stored instance id is not valid JSON, generating a new one`),{outcome:`nothing usable`}}return Fe(r)?{outcome:`stored`,instanceId:r.id}:(t.debug(`[ConfigDirectorClient] The stored instance id failed validation, generating a new one`),{outcome:`nothing usable`})},Le=async(e,t,n)=>{let r=Date.now(),i={v:1,id:t,createdAt:r,checksum:X(t,r)};try{return await e.setItem(q,JSON.stringify(i)),!0}catch(e){return n.debug(`[ConfigDirectorClient] Could not persist the instance id, using it as an ephemeral one`,e),!1}},Re=async(e,t,n,r)=>{let i=await Ie(e,r);switch(i.outcome){case`stored`:return{instanceId:i.instanceId};case`failed`:return{instanceId:t,ephemeral:!0};case`nothing usable`:break}return n.passed?{instanceId:t,ephemeral:!0}:await Le(e,t,r)?{instanceId:t}:{instanceId:t,ephemeral:!0}},ze=(e,t=K())=>{let n=je();if(!t)return e.debug(`[ConfigDirectorClient] No instance id storage is available, using an ephemeral instance id`),Promise.resolve({instanceId:n,ephemeral:!0});let r={passed:!1},i,a=new Promise(t=>{i=setTimeout(()=>{r.passed=!0,e.warn(`[ConfigDirectorClient] The instance id storage did not respond within ${J}ms, using an ephemeral instance id`),t({instanceId:n,ephemeral:!0})},J)});return Promise.race([Re(t,n,r,e),a]).finally(()=>clearTimeout(i))};var Be=class{constructor(){this.fatalError=!1}clearPollingInterval(){clearInterval(this.pollingInterval)}schedulePollingInterval(e){clearInterval(this.pollingInterval),!(this.pollingIntervalSeconds<=0)&&(this.pollingInterval=setInterval(e,this.pollingIntervalSeconds*1e3))}async handleNonOkResponse(e){var t=this;if(!e.ok)throw t.isStatusFatal(e.status)?(t.fatalError=!0,t.close(),t.prepareFatalResponseStatusError(e.status,await e.text())):new b(`Connection failed with status: ${e.status}`,e.status)}handleFetchError(e){throw this.isFetchErrorFatal(e)?(this.fatalError=!0,this.close(),new b(`Connection failed with fatal error: ${e}. This is an unrecoverable error, retry attempts will be ignored.`)):e instanceof SyntaxError?new b(`Failed to parse the response from the server: ${e}`):new b(`Connection failed with error: ${e}.`)}prepareFatalResponseStatusError(e,t){var n,r;let i=e==null?0:e;return new b(`${`Connection failed with status: ${e==null?`unknown`:e}`}${((n=t==null||(r=t.trim())==null?void 0:r.length)==null?0:n)>0?` (${t})`:``}. This is an unrecoverable error, retry attempts will be ignored.`,i)}isStatusFatal(e){return!!e&&e>=400&&e<500&&e!=429}isFetchErrorFatal(e){return(e==null?void 0:e.name)===`NotAllowedError`}get isConnected(){return this.pollingInterval!==void 0}close(){clearInterval(this.pollingInterval),this.pollingInterval=void 0}dispose(){this.close(),this.clear()}};const Ve=async(e,t,n,r)=>{let i=new AbortController,a=setTimeout(()=>{r.debug(`[fetchWithTimeout] Reached timeout, aborting request`),i.abort()},e);try{let e=await fetch(typeof t==`string`||t instanceof Request?t:t.toString(),l(l({},n),{},{signal:i.signal}));return clearTimeout(a),e}catch(e){throw r.warn(`[fetchWithTimeout] Fetch error: `,e),clearTimeout(a),e}};var He=class extends Be{constructor(e){var t;super(),this.options=e,this.eventEmitter=new y,this.connectionGeneration=0,this.options=e,this.logger=e.logger,this.url=e.resolveUrl(`client/polling/v1`,e.baseUrl),this.pollingIntervalSeconds=(t=e.pollingInterval)==null?60:t}async connect(e,t){var n=this;n.endCurrentConnection();let r=n.connectionGeneration,i=await n.options.clientSession;if(r!==n.connectionGeneration)return n;try{await n.fetchConfigs(e,t,i)}finally{n.fatalError||n.schedulePollingInterval(()=>{n.fetchConfigs(e,t,i).catch(e=>{n.logger.error(`[PollingTransport] Error during polling:`,e)})})}return n}close(){this.endCurrentConnection(),super.close()}endCurrentConnection(){this.connectionGeneration++,this.clearPollingInterval(),this.lastUpdateTimestamp=void 0}async fetchConfigs(e,t,n){var r=this;if(r.fatalError){r.logger.warn(`[PollingTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.`);return}try{let i=await Ve(t,r.url,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({givenContext:e,metaContext:r.options.metaContext,clientSdkKey:r.options.clientSdkKey,instanceId:n.instanceId,ephemeral:n.ephemeral,lastUpdateTimestamp:r.lastUpdateTimestamp})},r.logger);if(await r.handleNonOkResponse(i),i.status==200){let e=JSON.parse(await i.text());r.lastUpdateTimestamp=e.timestamp,r.eventEmitter.emit(`configSetReceived`,e)}}catch(e){try{r.handleFetchError(e)}catch(e){throw r.fatalError&&r.eventEmitter.emit(`connectionError`,e),e}}}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.eventEmitter.clear()}};const Ue=e=>e>=`a`&&e<=`z`||e>=`0`&&e<=`9`||e===`-`||e===`_`,We=e=>{if(e.length<1||e.length>64)return!1;for(let t of e)if(!Ue(t))return!1;return!0},Ge=e=>e==null||typeof e==`string`&&We(e),Ke=e=>{if(typeof e==`string`)return e;try{return String(e)}catch(t){return Object.prototype.toString.call(e)}},qe=(e,t)=>{let n=``,r=0;for(let i of e){if(r===t)break;n+=i,r+=1}return n},Je=e=>{let t=e==null?void 0:e.kind;return Ge(t)?{outcome:`admitted`,context:e}:{outcome:`ignored`,kindSample:qe(Ke(t),128)}},Ye=`configdirector-sdk:cached-values:`,Xe=256*1024,Ze=(e,t,n,r)=>{var i;if(e.kind===`stay-offline`)return{kind:`no cache`,reason:`offline mode`};if((t==null?void 0:t.enabled)===!1)return{kind:`no cache`,reason:`turned off`};if(!n)return{kind:`no cache`,reason:`no SHA-256 available`};let a=n(e.clientSdkKey),o=(i=t==null?void 0:t.provider)==null?r==null?void 0:r(a):i;return o?{kind:`cache`,provider:o,clientSdkKeyDigest:a}:{kind:`no cache`,reason:`no provider available`}},Z=(e,t)=>{var n;let r=(n=e==null?void 0:e.kind)==null?`user`:n;return(e==null?void 0:e.id)==null?{contextKind:r,anonymousInstanceId:t}:{contextKind:r,contextId:e.id}},Qe=(e,t)=>e.contextKind===t.contextKind?`contextId`in e&&`contextId`in t?e.contextId===t.contextId:`anonymousInstanceId`in e&&`anonymousInstanceId`in t?e.anonymousInstanceId===t.anonymousInstanceId:!1:!1,$e=(e,t,n)=>n?`live values already arrived`:Qe(e.contextTag,t)?`adopt`:`context mismatch`,et=e=>{if(!e||typeof e!=`object`)return!1;let{contextKind:t,contextId:n,anonymousInstanceId:r}=e;return typeof t==`string`?typeof n==`string`||typeof r==`string`:!1},tt=e=>!e||typeof e!=`object`||Array.isArray(e)?!1:Object.values(e).every(e=>e&&typeof e==`object`&&typeof e.id==`string`&&typeof e.key==`string`),nt=(e,t)=>{if(!t||typeof t!=`object`)return!1;let n=t;return n.formatVersion===2&&n.clientSdkKeyDigest===e&&et(n.contextTag)&&typeof n.environmentId==`string`&&typeof n.projectId==`string`&&tt(n.configs)&&typeof n.receivedAt==`number`},rt=e=>!!e&&typeof e==`object`&&e.formatVersion===1,Q=(e,t)=>{let n;try{n=JSON.parse(e)}catch(e){return{outcome:`unreadable`}}return nt(t,n)?{outcome:`stored`,cachedValues:n}:rt(n)?{outcome:`first format`}:{outcome:`unreadable`}};var it=class{constructor(e,t,n){this.provider=e,this.clientSdkKeyDigest=t,this.logger=n,this.warned=new Set,this.writing=!1}read(){return this.pendingRead!=null||(this.pendingRead=this.readEntry()),this.pendingRead}replace(e){this.queuedCachedValues=e,this.writeQueued()}async readEntry(){var e=this;let t;try{t=await e.provider.read()}catch(t){return e.warnOnce(`read failed`,`Could not read the values kept on the device, starting without them:`,t),{outcome:`failed`}}if(t==null||t===``)return{outcome:`nothing stored`};let n=Q(t,await e.clientSdkKeyDigest);switch(n.outcome){case`stored`:return n;case`first format`:return await e.removeEntry(),n;case`unreadable`:return e.warnOnce(`unreadable`,`The values kept on the device could not be read and were removed, starting without them`),await e.removeEntry(),n}}async writeQueued(){var e=this;if(!e.writing){e.writing=!0;try{for(;e.queuedCachedValues;){let t=e.queuedCachedValues;e.queuedCachedValues=void 0,await e.writeEntry(t)}}finally{e.writing=!1}}}async writeEntry(e){var t=this;let r=l({formatVersion:2,clientSdkKeyDigest:await t.clientSdkKeyDigest},e),i=JSON.stringify(r),a=n(i),o=t.provider.sizeLimit();if(a>o){t.warnOnce(`over the size limit`,`The values received (${a} bytes) exceed the caching provider's limit of ${o} bytes, so no values are kept on the device`),await t.removeEntry();return}try{await t.provider.write(i)}catch(e){t.warnOnce(`write failed`,`Could not keep the values on the device:`,e)}}async removeEntry(){var e=this;try{await e.provider.remove()}catch(t){e.warnOnce(`remove failed`,`Could not remove the values kept on the device:`,t)}}warnOnce(e,t,...n){this.warned.has(e)||(this.warned.add(e),this.logger.warn(`[ConfigDirectorClient] ${t}`,...n))}},at=class e{static from(t,n,r,i,a){return typeof n==`object`?new e(t,void 0,r,n,a):new e(t,n,r,i,a)}constructor(e,t,n,r,i){var a,o,s,c,u,d,f,p,m,h,g;this.handlersMap=new Map,this.eventEmitter=new y,this.ready=!1,this.initializing=!1,this.hasReceivedConfigSet=!1,this.servingCachedValues=!1,this.cachedValuesAdoptionStarted=!1,this.logger=(a=r==null?void 0:r.logger)==null?H():a,this.clientSession=ze(this.logger,i==null?void 0:i.instanceIdStorage),this.timeout=(o=r==null||(s=r.connection)==null?void 0:s.timeout)==null?3e3:o;let _=(c=i==null?void 0:i.urlFactory)==null?W:c;this.connectionPlan=j(t,r==null?void 0:r.connection,_),this.cachedValuesStore=this.buildCachedValuesStore(Ze(this.connectionPlan,r==null?void 0:r.caching,i==null?void 0:i.sha256HexDigest,i==null?void 0:i.platformCachingProvider)),this.telemetryClient=this.buildTelemetryClient(e,r),this.transport=(u=i==null?void 0:i.transport)==null?this.buildTransport(n,r,_,i):u,this.transport.on(`configSetReceived`,e=>{var t;this.hasReceivedConfigSet=!0,this.servingCachedValues=!1,(t=this.readyResolve)==null||t.call(this);let n=this.findKeysRemovedBy(e);!this.configSet||e.kind==`full`?this.configSet=e:this.configSet.configs=l(l({},this.configSet.configs),e.configs),this.keepValuesOnTheDevice(this.configSet);let r=Object.keys(e.configs);this.emit(`configsUpdated`,{keys:r,removedKeys:n}),this.updateWatchers([...r,...n]),this.logger.debug(`[ConfigDirectorClient] ConfigSet updated from server:`,{keys:r,removedKeys:n})}),this.transport.on(`connectionError`,e=>{this.initializing=!1,this.logger.error(`[ConfigDirectorClient] The connection encountered an unrecoverable error and will not be retried. Configs will no longer receive updates.`,e),this.emit(`connectionError`,{error:e})}),this.registerHandler(`clientReady`,r==null||(d=r.hooks)==null?void 0:d.clientReady),this.registerHandler(`configEvaluated`,r==null||(f=r.hooks)==null?void 0:f.configEvaluated),this.registerHandler(`configsUpdated`,r==null||(p=r.hooks)==null?void 0:p.configsUpdated),this.registerHandler(`contextUpdated`,r==null||(m=r.hooks)==null?void 0:m.contextUpdated),this.registerHandler(`connectionError`,r==null||(h=r.hooks)==null?void 0:h.connectionError),this.registerHandler(`cachedValuesLoaded`,r==null||(g=r.hooks)==null?void 0:g.cachedValuesLoaded)}buildCachedValuesStore(e){switch(e.kind){case`no cache`:this.logger.debug(`[ConfigDirectorClient] No values are kept on the device: ${e.reason}`);return;case`cache`:{let t=new it(e.provider,e.clientSdkKeyDigest,this.logger);return t.read(),t}}}startCachedValuesAdoption(){let e=this.cachedValuesStore;!e||this.cachedValuesAdoptionStarted||(this.cachedValuesAdoptionStarted=!0,this.adoptCachedValues(e))}async adoptCachedValues(e){var t=this;let n=await e.read();switch(n.outcome){case`nothing stored`:case`first format`:case`unreadable`:case`failed`:return;case`stored`:break}let{instanceId:r}=await t.clientSession,i=Z(t.submittedContext,r),a=$e(n.cachedValues,i,t.hasReceivedConfigSet);switch(a){case`adopt`:t.serveCachedValues(n.cachedValues);return;case`live values already arrived`:case`context mismatch`:t.logger.debug(`[ConfigDirectorClient] The values kept on the device were not adopted: ${a}`);return}}serveCachedValues(e){let{environmentId:t,projectId:n,configs:r}=e;this.configSet={environmentId:t,projectId:n,configs:r,kind:`full`},this.servingCachedValues=!0;let i=Object.keys(r);this.emit(`cachedValuesLoaded`,{}),this.emit(`configsUpdated`,{keys:i,removedKeys:[]}),this.updateWatchers(i),this.logger.debug(`[ConfigDirectorClient] Serving the values kept on the device until live values arrive:`,{keys:i})}keepValuesOnTheDevice(e){let t=this.cachedValuesStore;if(!t)return;let n=this.submittedContext,r=Date.now();this.clientSession.then(({instanceId:i})=>t.replace({contextTag:Z(n,i),environmentId:e.environmentId,projectId:e.projectId,configs:e.configs,receivedAt:r}))}servedReason(e){return this.servingCachedValues&&e===`found-match`?`cached`:e}registerHandler(e,t){if(!t)return;let n=Array.isArray(t)?t:[t];for(let t of n)typeof t==`function`&&this.on(e,t)}pollingIntervalFor(e,t){if(e!==`polling`)return;let n=Ae(t,{defaultSeconds:60,minimumSeconds:30});return n.warning&&this.logger.warn(`[ConfigDirectorClient] ${n.warning}`),n.seconds}buildTelemetryClient(e,t){let n=this.connectionPlan;switch(n.kind){case`stay-offline`:return U;case`connect`:return e({clientSdkKey:n.clientSdkKey,baseUrl:n.baseUrl,logger:this.logger,metadata:t==null?void 0:t.metadata,clientSession:this.clientSession})}}buildTransport(e,t,n,r){let i=this.connectionPlan;switch(i.kind){case`stay-offline`:return new O(i.source);case`connect`:var a,o;return new(this.getTransportConstructor(i.mode))({clientSession:this.clientSession,clientSdkKey:i.clientSdkKey,baseUrl:i.baseUrl,resolveUrl:n,metaContext:l(l({},t==null?void 0:t.metadata),{},{sdkName:e.sdkName,sdkVersion:e.sdkVersion,userAgent:Me(),host:Ne()}),logger:this.logger,fetch:r==null?void 0:r.fetch,connectionRetryDelay:(a=r==null?void 0:r.connectionRetryDelay)==null?(e=>2**Math.min(e,9)*1e3):a,pollingInterval:this.pollingIntervalFor(i.mode,t==null||(o=t.connection)==null?void 0:o.pollingInterval)})}}getTransportConstructor(e){switch(e){case`polling`:return He;case`streaming`:return de}}async initialize(e){var t=this;t.hasReceivedConfigSet||(t.initializing=!0),await t.submitContext(e,`initialization`)}async updateContext(e){var t=this;switch(t.connectionPlan.kind){case`connect`:await t.submitContext(e,`context update`);return;case`stay-offline`:t.storeContext(t.admittedContextFor(e,`context update`));return}}storeContext(e){this.currentContext=e,this.emit(`contextUpdated`,{context:e})}async submitContext(e,t){var n=this;await n.connectToTransport(n.admittedContextFor(e,t),t)}admittedContextFor(e,t){let n=Je(e);switch(n.outcome){case`admitted`:return n.context;case`ignored`:this.logger.error(`[ConfigDirectorClient] Ignored the context supplied for ${t} because its kind '${n.kindSample}' is invalid; continuing as if no context was supplied. A context kind has 1 to 64 characters, using only lowercase letters, digits, '-' and '_'.`),this.telemetryClient.recordInvalidContext(n.kindSample);return}}get context(){return this.currentContext}async connectToTransport(e,t){var n=this;n.submittedContext=e,t===`initialization`&&n.startCachedValuesAdoption();try{n.ready=!1,n.readyPromise=new Promise(e=>{n.readyResolve=e}).then(e=>{e||(n.ready=!0,n.initializing=!1,n.emit(`clientReady`,{action:t}),n.logger.debug(`[ConfigDirectorClient] Received initial payload from the server, client is ready`))});let r=new Date().getTime();await n.transport.connect(e==null?{}:e,n.timeout,t),n.currentContext=e,n.telemetryClient.updateContext(e).catch(e=>n.logger.warn(`[ConfigDirectorClient] Telemetry could not update the context: `,e)),n.emit(`contextUpdated`,{context:e});let i=new Date().getTime()-r,a=n.timeout-i;clearTimeout(n.timeoutTimer),n.timeoutTimer=void 0,a>0&&await Promise.race([n.readyPromise,new Promise(e=>{n.timeoutTimer=setTimeout(()=>e(),a)})]).finally(()=>clearTimeout(n.timeoutTimer)),n.ready||n.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${t} after ${n.timeout}ms. ${n.timeoutWarningDetails()}`)}catch(e){if(e instanceof S)throw n.initializing=!1,e;n.logger.error(`[ConfigDirectorClient] An error occurred during ${t}: `,e)}}timeoutWarningDetails(){switch(this.connectionPlan.kind){case`connect`:return`The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.`;case`stay-offline`:return`The offline values were not delivered, so configs return the default value.`}}findKeysRemovedBy(e){return!this.configSet||e.kind!=`full`?[]:Object.keys(this.configSet.configs).filter(t=>!Object.prototype.hasOwnProperty.call(e.configs,t))}updateWatchers(e){e.forEach(e=>this.updateWatchersForConfig(e))}updateWatchersForConfig(e){var t,n;let r=(t=this.configSet)==null?void 0:t.configs[e];(n=this.handlersMap.get(e))==null||n.forEach(t=>{let n=this.evaluationOf(e,r,t.defaultValue).value;t.handler(n)})}watch(e,t,n){this.validateDefaultValue(t);let r=this.handlersMap.get(e),i={handler:n,defaultValue:t,requestedType:typeof t};return r?r.push(i):this.handlersMap.set(e,[i]),()=>this.unwatch(e,n)}unwatch(e,t){let n=this.handlersMap.get(e);if(n)if(t){let e=n.findIndex(e=>e.handler==t);e>=0&&(n==null||n.splice(e,1))}else n.splice(0)}getValue(e,t){return this.evaluate(e,t).value}evaluate(e,t){var n;this.validateDefaultValue(t);let r=(n=this.configSet)==null?void 0:n.configs[e];return this.evaluationOf(e,r,t)}evaluationOf(e,t,n){var r,i,a;if(!t){var o;this.logger.debug(`[ConfigDirectorClient] No config state found for '${e}', returning default value '${n}'`);let t=this.isReady?`config-state-missing`:`client-not-ready`;this.telemetryClient.evaluatedConfig({contextId:(o=this.currentContext)==null?void 0:o.id,key:e,defaultValue:n,requestedType:L(n),evaluatedValue:n,usedDefault:!0,evaluationReason:t});let r={key:e,value:n,isDefaultValue:!0,reason:t,context:this.context};return this.dispatchEvaluationEvent(r),r}let s=ye(t,n),c=this.servedReason(s.reason);this.telemetryClient.evaluatedConfig({contextId:(r=this.currentContext)==null?void 0:r.id,type:t.type,key:e,defaultValue:n,requestedType:s.requestedType,evaluatedValue:s.parsedValue,evaluatedValueId:s.parsedValueId,usedDefault:s.usedDefault,evaluationReason:c,ruleId:s.ruleId,shareId:s.shareId,variationId:(i=s.variation)==null?void 0:i.id});let l={key:e,value:s.parsedValue,valueId:(a=s.parsedValueId)==null?void 0:a,variation:s.variation,isDefaultValue:s.usedDefault,reason:c,context:this.context};return this.dispatchEvaluationEvent(l),this.logger.debug(`[ConfigDirectorClient] Evaluated '${e}' to '${s.parsedValue}'`),l}dispatchEvaluationEvent(e){setTimeout(()=>this.emit(`configEvaluated`,{evaluation:e}),0)}emit(e,t){try{this.eventEmitter.emit(e,t)}catch(t){this.logger.error(`[ConfigDirectorClient] Error executing event handlers for '${e}'`,t)}}validateDefaultValue(e){if(e==null)throw new x(`Invalid default value. The default value for a config must be defined and non-null.`);if(typeof e==`function`)throw new x(`Invalid default value. The default value for a config cannot be a function.`)}get isReady(){return this.ready}get isInitializing(){return this.initializing}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}clear(){this.logger.debug(`[ConfigDirectorClient] clear() has been called, removing all observers`),this.eventEmitter.clear(),this.handlersMap.clear()}unwatchAll(){this.handlersMap.clear()}track(e,t){try{let n=this.currentContext;this.telemetryClient.trackedEvent(re({name:e,context:n,options:t,happenedAt:new Date}),n)}catch(e){this.logger.warn(`[ConfigDirectorClient] A tracked event was not reported because it could not be read: `,e)}}pauseNetwork(){switch(this.connectionPlan.kind){case`stay-offline`:return;case`connect`:this.logger.debug(`[ConfigDirectorClient] pauseNetwork() called, pausing transport connection`),clearTimeout(this.timeoutTimer),this.timeoutTimer=void 0,this.transport.close(),this.ready=!1;return}}async resumeNetwork(){var e=this;switch(e.connectionPlan.kind){case`stay-offline`:return;case`connect`:await e.connectToTransport(e.currentContext,`network resume`);return}}async close(){var e=this,t;e.logger.debug(`[ConfigDirectorClient] close() has been called, closing connection to server`),clearTimeout(e.timeoutTimer),(t=e.readyResolve)==null||t.call(e,!0),e.telemetryClient.close().catch(t=>e.logger.warn(`[ConfigDirectorClient] Telemetry could not close: `,t)),e.transport.close(),e.ready=!1,e.initializing=!1}dispose(){this.clear(),this.close()}};const $=Symbol.for(`@configdirector/installed-test-client`),ot=()=>globalThis[$];export{l as _,Xe as a,U as c,b as d,x as f,f as g,p as h,Ye as i,H as l,u as m,ot as n,K as o,y as p,at as r,W as s,$ as t,D as u};
6
+ //# sourceMappingURL=installedTestClient-CtAa-JtW.mjs.map