@configdirector/react-native-sdk 1.6.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,6 +10,16 @@ React Native SDK for [ConfigDirector](https://www.configdirector.com), remote co
10
10
  npm install --save @configdirector/react-native-sdk
11
11
  ```
12
12
 
13
+ Install `@react-native-async-storage/async-storage` as well, so the SDK can keep the same client
14
+ session for six hours across app starts. It is an optional peer dependency and works in Expo Go.
15
+ Without it, every app start begins a new client session and the SDK logs a warning.
16
+
17
+ ```bash
18
+ npm install --save @react-native-async-storage/async-storage
19
+ # or in an Expo project
20
+ npx expo install @react-native-async-storage/async-storage
21
+ ```
22
+
13
23
  ## Retrieve a value
14
24
 
15
25
  ```tsx
@@ -74,6 +84,10 @@ package's files are `.mjs` files, which the `jest-expo` and `@react-native/jest-
74
84
  transform, so a Jest setup must let `transformIgnorePatterns` transform both packages and add a
75
85
  `transform` entry for `.mjs` files; the documentation shows the configuration for both presets.
76
86
  `jest-expo` requires `@react-native/jest-preset` as a peer dependency, so install it in either case.
87
+ The test client never touches AsyncStorage. A test that builds a real client instead, through
88
+ `createClient` or a provider given an `sdkKey`, logs the warning that AsyncStorage is missing and
89
+ starts a new client session under either preset; add `@babel/plugin-transform-dynamic-import` to the
90
+ Babel test environment for that client to use the AsyncStorage Jest mock instead.
77
91
 
78
92
  ## Documentation
79
93
 
@@ -1,4 +1,4 @@
1
- import { i as ConfigDirectorContext, n as ConfigDirectorClient, o as ConfigDirectorLogger } from "./types-fcPMBgiX.mjs";
1
+ import { c as NativeValues, d as ConfigDirectorLogger, l as ConfigDirectorContext, n as ConfigDirectorClient, o as NativeJsonValue, s as NativeValue } from "./types-DoORnGTD.mjs";
2
2
 
3
3
  //#region ../shared/src/errors.d.ts
4
4
  declare class ConfigDirectorConnectionError extends Error {
@@ -11,15 +11,6 @@ declare class ConfigDirectorValidationError extends Error {
11
11
  constructor(message: string);
12
12
  }
13
13
  //#endregion
14
- //#region ../shared/src/testing/values.d.ts
15
- type TestJsonValue = boolean | number | string | null | TestJsonValue[] | {
16
- [key: string]: TestJsonValue;
17
- };
18
- type TestValue = boolean | number | string | TestJsonValue[] | {
19
- [key: string]: TestJsonValue;
20
- };
21
- type TestValues = Record<string, TestValue>;
22
- //#endregion
23
14
  //#region ../js-client-core/src/testing/TestClient.d.ts
24
15
  /**
25
16
  * Options for {@link createTestClient}. Every option is optional.
@@ -30,7 +21,7 @@ type TestClientOptions = {
30
21
  * config type follows from each value: a boolean, an integral number (`integer`), any other
31
22
  * number (`float`), a string, or a plain object or array (`json`).
32
23
  */
33
- values?: TestValues;
24
+ values?: NativeValues;
34
25
  /**
35
26
  * The connection timeout of the SDK client, in milliseconds. It bounds how long a held
36
27
  * `initialize` or `updateContext` waits. Defaults to the SDK's production timeout.
@@ -59,7 +50,7 @@ interface TestClient {
59
50
  * Stores `value` under `key` and, when the client is connected, delivers it as an update, so
60
51
  * reads, watchers, and `configsUpdated` handlers see it.
61
52
  */
62
- setValue(key: string, value: TestValue): void;
53
+ setValue(key: string, value: NativeValue): void;
63
54
  /**
64
55
  * Removes `key` and, when the client is connected, delivers a full update without it, so reads
65
56
  * fall back to the in-code default value and watchers of `key` receive that default.
@@ -69,7 +60,7 @@ interface TestClient {
69
60
  * Replaces every stored value with `values`, disarms any armed hold or failure, and, when the
70
61
  * client is connected, delivers the new values as a full update.
71
62
  */
72
- replaceValues(values: TestValues): void;
63
+ replaceValues(values: NativeValues): void;
73
64
  /**
74
65
  * Makes the next `initialize` wait until {@link completeInitialization} or
75
66
  * {@link failInitialization} is called, or until the client's timeout elapses.
@@ -102,7 +93,8 @@ interface TestClient {
102
93
  failContextUpdate(): void;
103
94
  /**
104
95
  * The context of every `initialize` and `updateContext` call, in call order. `initialize` without
105
- * a context records an empty context. Resumes are not recorded.
96
+ * a context records an empty context, and so does a call whose context has an invalid kind, since
97
+ * the client connects without it. Resumes are not recorded.
106
98
  */
107
99
  readonly contextUpdates: ConfigDirectorContext[];
108
100
  }
@@ -154,4 +146,4 @@ declare const installTestClient: (testClient: TestClient) => (() => void);
154
146
  */
155
147
  declare const createTestClient: (options?: TestClientOptions) => TestClient;
156
148
  //#endregion
157
- export { ConfigDirectorConnectionError, ConfigDirectorValidationError, type TestClient, type TestClientOptions, type TestJsonValue, type TestValue, type TestValues, createTestClient, installTestClient };
149
+ export { ConfigDirectorConnectionError, ConfigDirectorValidationError, type TestClient, type TestClientOptions, type NativeJsonValue as TestJsonValue, type NativeValue as TestValue, type NativeValues as TestValues, createTestClient, installTestClient };
@@ -1,98 +1,4 @@
1
- import { c as ConfigDirectorConnectionError, d as _defineProperty, l as ConfigDirectorValidationError, o as createDefaultLogger, r as DefaultConfigDirectorClient, t as INSTALLED_TEST_CLIENT_SLOT, u as Emitter } from "./installedTestClient-CTPtIG6o.mjs";
2
- //#region ../shared/src/testing/values.ts
3
- const encodeTestValue$1 = (key, value) => {
4
- if (key.trim().length == 0) throw new ConfigDirectorValidationError("Invalid config key. The key of a test value cannot be empty.");
5
- return encode(key, value);
6
- };
7
- const encode = (key, value) => {
8
- switch (typeof value) {
9
- case "boolean": return {
10
- type: "boolean",
11
- value: value ? "true" : "false"
12
- };
13
- case "number": return encodeNumber(key, value);
14
- case "string": return {
15
- type: "string",
16
- value
17
- };
18
- case "object": if (value !== null) {
19
- assertJsonContents(key, value, "");
20
- return {
21
- type: "json",
22
- value: JSON.stringify(value)
23
- };
24
- }
25
- }
26
- throw new ConfigDirectorValidationError(`Invalid test value for '${key}': ${describe(value)}. Use a boolean, a number, a string, a plain object, or an array.`);
27
- };
28
- const encodeNumber = (key, value) => {
29
- if (!Number.isFinite(value)) throw new ConfigDirectorValidationError(`Invalid test value for '${key}': ${describe(value)} is not a finite number.`);
30
- if (Number.isInteger(value)) {
31
- if (!Number.isSafeInteger(value)) throw new ConfigDirectorValidationError(`Invalid test value for '${key}': ${value} is not a safe integer, so the SDK could not read it back exactly.`);
32
- return {
33
- type: "integer",
34
- value: String(value)
35
- };
36
- }
37
- return {
38
- type: "float",
39
- value: toPlainDecimal(value)
40
- };
41
- };
42
- const toPlainDecimal = (value) => {
43
- const text = String(value);
44
- const exponentIndex = text.indexOf("e-");
45
- if (exponentIndex < 0) return text;
46
- const sign = text.startsWith("-") ? "-" : "";
47
- const [integerDigits = "", fractionDigits = ""] = text.slice(sign.length, exponentIndex).split(".");
48
- const leadingZeros = Number(text.slice(exponentIndex + 2)) - integerDigits.length;
49
- return `${sign}0.${"0".repeat(leadingZeros)}${integerDigits}${fractionDigits}`;
50
- };
51
- const assertJsonContents = (key, value, path) => {
52
- if (value === null || typeof value === "boolean" || typeof value === "string") return;
53
- if (typeof value === "number") {
54
- if (!Number.isFinite(value)) throw invalidJsonContents(key, path, `${describe(value)} is not a finite number`);
55
- return;
56
- }
57
- if (Array.isArray(value)) {
58
- value.forEach((item, index) => assertJsonContents(key, item, `${path}[${index}]`));
59
- return;
60
- }
61
- if (isPlainObject(value)) {
62
- for (const [property, item] of Object.entries(value)) assertJsonContents(key, item, path ? `${path}.${property}` : property);
63
- return;
64
- }
65
- throw invalidJsonContents(key, path, `${describe(value)} cannot be encoded as JSON`);
66
- };
67
- const invalidJsonContents = (key, path, problem) => new ConfigDirectorValidationError(`Invalid test value for '${key}'${path ? ` at '${path}'` : ""}: ${problem}. JSON contents can hold booleans, finite numbers, strings, null, arrays, and plain objects.`);
68
- const isPlainObject = (value) => {
69
- if (typeof value !== "object" || value === null) return false;
70
- const prototype = Object.getPrototypeOf(value);
71
- return prototype === Object.prototype || prototype === null;
72
- };
73
- const describe = (value) => {
74
- if (value === null) return "null";
75
- if (typeof value === "function") return "a function";
76
- if (typeof value === "object") {
77
- var _value$constructor$na, _value$constructor;
78
- return `a ${(_value$constructor$na = (_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name) !== null && _value$constructor$na !== void 0 ? _value$constructor$na : "object"} instance`;
79
- }
80
- if (typeof value === "symbol") return "a symbol";
81
- return String(value);
82
- };
83
- //#endregion
84
- //#region ../js-client-core/src/testing/values.ts
85
- const encodeTestValue = (key, value, revision) => {
86
- const encoded = encodeTestValue$1(key, value);
87
- return {
88
- id: `test-config:${key}`,
89
- key,
90
- type: encoded.type,
91
- value: encoded.value,
92
- valueId: `test-value:${key}:${revision}`
93
- };
94
- };
95
- //#endregion
1
+ import { a as discardingTelemetryClient, d as Emitter, f as _defineProperty, l as ConfigDirectorConnectionError, o as createDefaultLogger, r as DefaultConfigDirectorClient, s as nativeValueConfigState, t as INSTALLED_TEST_CLIENT_SLOT, u as ConfigDirectorValidationError } from "./installedTestClient-CKjaEilj.mjs";
96
2
  //#region ../js-client-core/src/testing/InMemoryConnection.ts
97
3
  const TEST_ENVIRONMENT = {
98
4
  environmentId: "test-environment",
@@ -129,7 +35,7 @@ var InMemoryConnection = class {
129
35
  return [...this.recordedContexts];
130
36
  }
131
37
  setValue(key, value) {
132
- const configState = encodeTestValue(key, value, ++this.revision);
38
+ const configState = this.encode(key, value);
133
39
  this.configs.set(key, configState);
134
40
  this.deliverIfConnected({
135
41
  ...TEST_ENVIRONMENT,
@@ -278,18 +184,16 @@ var InMemoryConnection = class {
278
184
  }
279
185
  encodeAll(values) {
280
186
  const encoded = /* @__PURE__ */ new Map();
281
- for (const [key, value] of Object.entries(values)) encoded.set(key, encodeTestValue(key, value, ++this.revision));
187
+ for (const [key, value] of Object.entries(values)) encoded.set(key, this.encode(key, value));
282
188
  return encoded;
283
189
  }
190
+ encode(key, value) {
191
+ return nativeValueConfigState(`test-config:${key}`, key, value, `test-value:${key}:${++this.revision}`);
192
+ }
284
193
  };
285
194
  //#endregion
286
195
  //#region ../js-client-core/src/testing/TestClient.ts
287
196
  const TEST_CLIENT_SDK_KEY = "test-client";
288
- const noopTelemetryClient = {
289
- updateContext: async () => {},
290
- evaluatedConfig: () => {},
291
- close: async () => {}
292
- };
293
197
  var InMemoryTestClient = class {
294
198
  constructor(client, connection) {
295
199
  this.client = client;
@@ -330,7 +234,7 @@ const createTestClient$1 = (sdkOptions, options) => {
330
234
  var _options$logger, _options$values;
331
235
  const logger = (_options$logger = options === null || options === void 0 ? void 0 : options.logger) !== null && _options$logger !== void 0 ? _options$logger : createDefaultLogger();
332
236
  const connection = new InMemoryConnection(logger, (_options$values = options === null || options === void 0 ? void 0 : options.values) !== null && _options$values !== void 0 ? _options$values : {});
333
- return new InMemoryTestClient(new DefaultConfigDirectorClient(noopTelemetryClient, TEST_CLIENT_SDK_KEY, sdkOptions, {
237
+ return new InMemoryTestClient(new DefaultConfigDirectorClient(() => discardingTelemetryClient, TEST_CLIENT_SDK_KEY, sdkOptions, {
334
238
  logger,
335
239
  connection: { timeout: options === null || options === void 0 ? void 0 : options.timeout }
336
240
  }, { transport: connection }), connection);
@@ -391,7 +295,7 @@ const installTestClient = (testClient) => {
391
295
  const createTestClient = (options) => {
392
296
  return createTestClient$1({
393
297
  sdkName: "react-native-sdk",
394
- sdkVersion: "1.6.1"
298
+ sdkVersion: "1.8.0"
395
299
  }, options);
396
300
  };
397
301
  //#endregion
@@ -1,4 +1,4 @@
1
- import { a as ConfigDirectorLogMessageDecorator, c as ConfigValueType, i as ConfigDirectorContext, l as ConnectionMode, n as ConfigDirectorClient, o as ConfigDirectorLogger, r as ConfigDirectorClientOptions, s as ConfigDirectorLoggingLevel, t as ClientHooks } from "./types-fcPMBgiX.mjs";
1
+ import { a as OfflineValues, d as ConfigDirectorLogger, f as ConfigDirectorLoggingLevel, i as OfflineValue, l as ConfigDirectorContext, m as ConnectionMode, n as ConfigDirectorClient, p as ConfigValueType, r as ConfigDirectorClientOptions, t as ClientHooks, u as ConfigDirectorLogMessageDecorator } from "./types-DoORnGTD.mjs";
2
2
  import { Component, PropsWithChildren } from "react";
3
3
  import * as _$react_jsx_runtime0 from "react/jsx-runtime";
4
4
 
@@ -39,19 +39,31 @@ type NetInfoState = {
39
39
  */
40
40
  type NetInfoSubscribe = (callback: (state: NetInfoState) => void) => () => void;
41
41
  type ConfigDirectorProviderOptions = {
42
- sdkKey: string;
42
+ /**
43
+ * Your ConfigDirector client SDK key. Required unless `mode` is `offline`.
44
+ */
45
+ sdkKey?: string;
43
46
  appName?: string;
44
47
  appVersion?: string;
45
48
  url?: string;
46
49
  timeout?: number;
47
50
  /**
48
- * The connection mode, one of `streaming` or `polling`. In `streaming` mode the connection stays
49
- * open and receives config updates as they happen. In `polling` mode configs are fetched once during
50
- * initialization and then again on every `pollingInterval`.
51
+ * The connection mode, one of `streaming`, `polling` or `offline`. In `streaming` mode the connection
52
+ * stays open and receives config updates as they happen. In `polling` mode configs are fetched once
53
+ * during initialization and then again on every `pollingInterval`. In `offline` mode the client never
54
+ * connects to ConfigDirector and sends nothing: it serves `values` to every context, or the in-code
55
+ * default values when none are given, and needs no `sdkKey`.
51
56
  *
52
57
  * Defaults to `streaming`.
53
58
  */
54
59
  mode?: ConnectionMode;
60
+ /**
61
+ * The values to serve in `offline` mode, keyed by config key. The config type of each value follows
62
+ * from the value: a boolean, an integral number (`integer`), any other number (`float`), a string, or
63
+ * a plain object or array (`json`). Can be given only in `offline` mode; otherwise the client fails
64
+ * to initialize.
65
+ */
66
+ values?: OfflineValues;
55
67
  /**
56
68
  * The polling interval in seconds when `mode` is `polling`. Has no effect in `streaming` mode.
57
69
  *
@@ -133,4 +145,4 @@ declare class ConfigDirectorReactContextError extends Error {
133
145
  //#region src/logger.d.ts
134
146
  declare const createConsoleLogger: (level?: ConfigDirectorLoggingLevel) => DefaultConsoleLogger;
135
147
  //#endregion
136
- export { type ClientStatus, type ConfigDirectorClient, type ConfigDirectorClientOptions, type ConfigDirectorContext, type ConfigDirectorLogger, type ConfigDirectorLoggingLevel, ConfigDirectorProvider, type ConfigDirectorProviderClientProps, type ConfigDirectorProviderOptions, type ConfigDirectorProviderProps, ConfigDirectorReactContextError, type ConnectionMode, type NetInfoSubscribe, createClient, createConsoleLogger, useClient, useConfigValue, useContext };
148
+ export { type ClientStatus, type ConfigDirectorClient, type ConfigDirectorClientOptions, type ConfigDirectorContext, type ConfigDirectorLogger, type ConfigDirectorLoggingLevel, ConfigDirectorProvider, type ConfigDirectorProviderClientProps, type ConfigDirectorProviderOptions, type ConfigDirectorProviderProps, ConfigDirectorReactContextError, type ConnectionMode, type NetInfoSubscribe, type OfflineValue, type OfflineValues, createClient, createConsoleLogger, useClient, useConfigValue, useContext };
@@ -1,4 +1,4 @@
1
- import { a as CLIENT_BASE_URL, d as _defineProperty, i as fetchWithTimeout, n as readInstalledTestClient, o as createDefaultLogger, r as DefaultConfigDirectorClient, s as isFetchErrorFatal } from "./installedTestClient-CTPtIG6o.mjs";
1
+ import { c as isFetchErrorFatal, f as _defineProperty, i as fetchWithTimeout, n as readInstalledTestClient, o as createDefaultLogger, r as DefaultConfigDirectorClient } from "./installedTestClient-CKjaEilj.mjs";
2
2
  import React, { Component, useContext as useContext$1 } from "react";
3
3
  import { AppState, NativeModules } from "react-native";
4
4
  import { sha256 } from "@noble/hashes/sha2.js";
@@ -285,6 +285,63 @@ var EvaluatedConfigEventPreprocessor = class {
285
285
  };
286
286
  }
287
287
  };
288
+ var InvalidContextSubmissions = class {
289
+ constructor() {
290
+ _defineProperty(this, "countsByKindSample", /* @__PURE__ */ new Map());
291
+ _defineProperty(this, "countBeyondSampleLimit", 0);
292
+ _defineProperty(this, "startTime", void 0);
293
+ }
294
+ record(kindSample) {
295
+ var _this$startTime;
296
+ (_this$startTime = this.startTime) !== null && _this$startTime !== void 0 || (this.startTime = /* @__PURE__ */ new Date());
297
+ return this.add(kindSample, 1);
298
+ }
299
+ absorb(entries) {
300
+ for (const entry of entries) {
301
+ if (this.startTime === void 0 || entry.startTime < this.startTime) this.startTime = entry.startTime;
302
+ this.add(entry.event.kindSample, entry.count);
303
+ }
304
+ }
305
+ add(kindSample, count) {
306
+ if (kindSample !== void 0) {
307
+ const knownCount = this.countsByKindSample.get(kindSample);
308
+ if (knownCount !== void 0) {
309
+ this.countsByKindSample.set(kindSample, knownCount + count);
310
+ return "known-kind-sample";
311
+ }
312
+ if (this.countsByKindSample.size < 20) {
313
+ this.countsByKindSample.set(kindSample, count);
314
+ return "new-kind-sample";
315
+ }
316
+ }
317
+ const firstBeyondSampleLimit = this.countBeyondSampleLimit === 0;
318
+ this.countBeyondSampleLimit += count;
319
+ return firstBeyondSampleLimit ? "first-beyond-sample-limit" : "beyond-sample-limit";
320
+ }
321
+ takeSnapshot() {
322
+ var _this$startTime2;
323
+ const endTime = /* @__PURE__ */ new Date();
324
+ const startTime = (_this$startTime2 = this.startTime) !== null && _this$startTime2 !== void 0 ? _this$startTime2 : endTime;
325
+ const entryOf = (count, kindSample) => ({
326
+ startTime,
327
+ endTime,
328
+ count,
329
+ event: {
330
+ reason: "invalid-context-kind",
331
+ kindSample
332
+ }
333
+ });
334
+ const sampledEntries = Array.from(this.countsByKindSample, ([kindSample, count]) => entryOf(count, kindSample));
335
+ const entries = this.countBeyondSampleLimit > 0 ? [...sampledEntries, entryOf(this.countBeyondSampleLimit)] : sampledEntries;
336
+ this.clear();
337
+ return entries;
338
+ }
339
+ clear() {
340
+ this.countsByKindSample.clear();
341
+ this.countBeyondSampleLimit = 0;
342
+ this.startTime = void 0;
343
+ }
344
+ };
288
345
  //#endregion
289
346
  //#region ../js-client-core/src/telemetry/ClientTelemetryEventCollector.ts
290
347
  var ClientTelemetryEventCollector = class extends TelemetryEventCollector {
@@ -293,6 +350,7 @@ var ClientTelemetryEventCollector = class extends TelemetryEventCollector {
293
350
  _defineProperty(this, "evaluationEventSnapshotPreprocessor", void 0);
294
351
  _defineProperty(this, "reporter", void 0);
295
352
  _defineProperty(this, "_context", void 0);
353
+ _defineProperty(this, "invalidContextSubmissions", new InvalidContextSubmissions());
296
354
  this.reporter = new ClientEventReporter(options);
297
355
  this.evaluationEventSnapshotPreprocessor = new EvaluatedConfigEventPreprocessor(options.valueIdGenerator);
298
356
  }
@@ -306,6 +364,12 @@ var ClientTelemetryEventCollector = class extends TelemetryEventCollector {
306
364
  if (!this.collectEvents) return;
307
365
  this.evaluationEventQueue.push(event);
308
366
  }
367
+ recordInvalidContext(kindSample) {
368
+ this.invalidContextSubmissions.record(kindSample);
369
+ }
370
+ absorbInvalidContextSubmissions(entries) {
371
+ this.invalidContextSubmissions.absorb(entries);
372
+ }
309
373
  async forceFlush() {
310
374
  this.cancelScheduledFlush();
311
375
  await this.flushAndScheduleNext();
@@ -320,7 +384,10 @@ var ClientTelemetryEventCollector = class extends TelemetryEventCollector {
320
384
  return await ((_this$reporter = this.reporter) === null || _this$reporter === void 0 ? void 0 : _this$reporter.report({
321
385
  context: this._context,
322
386
  discreteEvents: {},
323
- aggregatedEvents: { evaluatedConfig: this.aggregator.aggregate(evaluationSnapshot) },
387
+ aggregatedEvents: {
388
+ evaluatedConfig: this.aggregator.aggregate(evaluationSnapshot),
389
+ invalidContext: this.invalidContextSubmissions.takeSnapshot()
390
+ },
324
391
  droppedEvents: { evaluatedConfig: evaluationSnapshot.droppedCount }
325
392
  }));
326
393
  }
@@ -453,6 +520,36 @@ const resolveMetadata = (provided, logger) => {
453
520
  return metadata;
454
521
  };
455
522
  //#endregion
523
+ //#region src/instanceIdStorage.ts
524
+ const lookUpAsyncStorage = async () => {
525
+ try {
526
+ const { default: storage } = await import("@react-native-async-storage/async-storage");
527
+ return {
528
+ outcome: "installed",
529
+ storage
530
+ };
531
+ } catch {
532
+ return { outcome: "not installed" };
533
+ }
534
+ };
535
+ const asyncStorageInstanceIdStorage = (logger) => {
536
+ const asyncStorageLookup = lookUpAsyncStorage().then((lookup) => {
537
+ if (lookup.outcome === "not installed") logger.warn("The ConfigDirector SDK could not find @react-native-async-storage/async-storage, so every app start counts as a new client session. Install it for the SDK to keep the client session for six hours across app starts.");
538
+ return lookup;
539
+ });
540
+ const installedAsyncStorage = async () => {
541
+ const lookup = await asyncStorageLookup;
542
+ switch (lookup.outcome) {
543
+ case "installed": return lookup.storage;
544
+ case "not installed": throw new Error("@react-native-async-storage/async-storage is not installed");
545
+ }
546
+ };
547
+ return {
548
+ getItem: async (key) => (await installedAsyncStorage()).getItem(key),
549
+ setItem: async (key, value) => (await installedAsyncStorage()).setItem(key, value)
550
+ };
551
+ };
552
+ //#endregion
456
553
  //#region src/utf8Encoder.ts
457
554
  /**
458
555
  * Encodes a string to a UTF-8 byte sequence.
@@ -607,6 +704,9 @@ var ReactNativeTelemetryClient = class {
607
704
  evaluatedConfig(event) {
608
705
  this.collector.evaluatedConfig(this.sanitizeEvaluatedConfigEvent(event));
609
706
  }
707
+ recordInvalidContext(kindSample) {
708
+ this.collector.recordInvalidContext(kindSample);
709
+ }
610
710
  async close() {
611
711
  await this.collector.close();
612
712
  }
@@ -642,19 +742,20 @@ var MinimalUrl = class {
642
742
  const urlFactory = (input, base) => new MinimalUrl(input, base);
643
743
  //#endregion
644
744
  //#region src/client.ts
645
- const createClient = (clientSdkKey, clientOptions) => {
646
- var _clientOptions$logger, _clientOptions$connec;
745
+ const createClient = (clientSdkKey, clientOptions) => createReactNativeClient(clientSdkKey, clientOptions);
746
+ const createReactNativeClient = (clientSdkKey, clientOptions) => {
747
+ var _clientOptions$logger;
647
748
  const sdkIdentity = {
648
749
  sdkName: "react-native-sdk",
649
- sdkVersion: "1.6.1"
750
+ sdkVersion: "1.8.0"
650
751
  };
651
752
  const logger = (_clientOptions$logger = clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.logger) !== null && _clientOptions$logger !== void 0 ? _clientOptions$logger : createConsoleLogger("warn");
652
753
  const metadata = resolveMetadata(clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.metadata, logger);
653
- return new DefaultConfigDirectorClient(new ReactNativeTelemetryClient({
654
- sdkKey: clientSdkKey,
754
+ return new DefaultConfigDirectorClient((liveTelemetry) => new ReactNativeTelemetryClient({
755
+ sdkKey: liveTelemetry.clientSdkKey,
655
756
  sdkIdentity,
656
757
  metaContext: metadata,
657
- baseUrl: (clientOptions === null || clientOptions === void 0 || (_clientOptions$connec = clientOptions.connection) === null || _clientOptions$connec === void 0 ? void 0 : _clientOptions$connec.url) ? urlFactory(clientOptions.connection.url) : CLIENT_BASE_URL,
758
+ baseUrl: liveTelemetry.baseUrl,
658
759
  logger,
659
760
  urlFactory
660
761
  }), clientSdkKey, sdkIdentity, {
@@ -663,19 +764,21 @@ const createClient = (clientSdkKey, clientOptions) => {
663
764
  metadata
664
765
  }, {
665
766
  fetch: reactNativeStreamingFetch,
666
- urlFactory
767
+ urlFactory,
768
+ instanceIdStorage: asyncStorageInstanceIdStorage(logger)
667
769
  });
668
770
  };
669
771
  //#endregion
670
772
  //#region src/clientSource.ts
671
773
  const buildClient = (options) => {
672
774
  var _options$logger;
673
- return createClient(options.sdkKey, {
775
+ return createReactNativeClient(options.sdkKey, {
674
776
  connection: {
675
777
  url: options.url,
676
778
  timeout: options.timeout,
677
779
  mode: options.mode,
678
- pollingInterval: options.pollingInterval
780
+ pollingInterval: options.pollingInterval,
781
+ values: options.values
679
782
  },
680
783
  metadata: {
681
784
  appName: options.appName,
@@ -703,6 +806,7 @@ const resolveClientSource = (props) => {
703
806
  };
704
807
  //#endregion
705
808
  //#region src/provider.tsx
809
+ const settledStatusOf = (client) => (client === null || client === void 0 ? void 0 : client.isReady) ? "ready" : "default";
706
810
  var ConfigDirectorProvider = class extends Component {
707
811
  constructor(props) {
708
812
  super(props);
@@ -770,15 +874,15 @@ var ConfigDirectorProvider = class extends Component {
770
874
  break;
771
875
  case "none": return;
772
876
  }
773
- if (!client.isReady) this.setState({ status: "default" });
877
+ this.setState({ status: settledStatusOf(client) });
774
878
  }
775
879
  async componentDidUpdate(prevProps) {
776
880
  if (hasGivenClient(prevProps) && hasGivenClient(this.props) && prevProps.client !== this.props.client) createConsoleLogger("warn").warn("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.");
777
881
  if (!deepEqual(prevProps.context, this.props.context)) {
778
- var _this$state$client3, _this$props$context, _this$state$client4;
882
+ var _this$state$client3, _this$props$context;
779
883
  this.setState({ status: "loading" });
780
884
  await ((_this$state$client3 = this.state.client) === null || _this$state$client3 === void 0 ? void 0 : _this$state$client3.updateContext((_this$props$context = this.props.context) !== null && _this$props$context !== void 0 ? _this$props$context : {}));
781
- if (!((_this$state$client4 = this.state.client) === null || _this$state$client4 === void 0 ? void 0 : _this$state$client4.isReady)) this.setState({ status: "default" });
885
+ this.setState({ status: settledStatusOf(this.state.client) });
782
886
  }
783
887
  }
784
888
  componentWillUnmount() {
@@ -790,8 +894,8 @@ var ConfigDirectorProvider = class extends Component {
790
894
  (_this$handlers = this.handlers) === null || _this$handlers === void 0 || _this$handlers.removeAll();
791
895
  this.handlers = void 0;
792
896
  if (this.ownsClient) {
793
- var _this$state$client5;
794
- (_this$state$client5 = this.state.client) === null || _this$state$client5 === void 0 || _this$state$client5.dispose();
897
+ var _this$state$client4;
898
+ (_this$state$client4 = this.state.client) === null || _this$state$client4 === void 0 || _this$state$client4.dispose();
795
899
  this.disposedOwnClient = true;
796
900
  }
797
901
  }