@configdirector/react-native-sdk 1.7.0 → 1.9.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 +6 -4
- package/dist/configdirector-react-native-testing.d.mts +5 -14
- package/dist/configdirector-react-native-testing.mjs +8 -105
- package/dist/configdirector-react-native.d.mts +24 -6
- package/dist/configdirector-react-native.mjs +65 -35
- package/dist/{installedTestClient-LWv5ji8J.mjs → installedTestClient-BluKT8Qj.mjs} +579 -94
- package/dist/{types-P1hoU2Ru.d.mts → types-BBQmjjf5.d.mts} +123 -39
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,9 +10,11 @@ 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
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
Install `@react-native-async-storage/async-storage` as well, so the SDK recognizes the app install
|
|
14
|
+
across app starts. For a context without an `id`, ConfigDirector derives an identifier from an ID
|
|
15
|
+
the SDK stores for the install, so the context keeps that identifier, and counts as one monthly
|
|
16
|
+
active user, however often the app is opened. It is an optional peer dependency and works in Expo
|
|
17
|
+
Go. Without it, every app start looks like a new install and the SDK logs a warning.
|
|
16
18
|
|
|
17
19
|
```bash
|
|
18
20
|
npm install --save @react-native-async-storage/async-storage
|
|
@@ -86,7 +88,7 @@ transform, so a Jest setup must let `transformIgnorePatterns` transform both pac
|
|
|
86
88
|
`jest-expo` requires `@react-native/jest-preset` as a peer dependency, so install it in either case.
|
|
87
89
|
The test client never touches AsyncStorage. A test that builds a real client instead, through
|
|
88
90
|
`createClient` or a provider given an `sdkKey`, logs the warning that AsyncStorage is missing and
|
|
89
|
-
|
|
91
|
+
connects as a new install under either preset; add `@babel/plugin-transform-dynamic-import` to the
|
|
90
92
|
Babel test environment for that client to use the AsyncStorage Jest mock instead.
|
|
91
93
|
|
|
92
94
|
## Documentation
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as NativeJsonValue, d as ConfigDirectorContext, i as ConfigDirectorClient, l as NativeValue, p as ConfigDirectorLogger, u as NativeValues } from "./types-BBQmjjf5.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?:
|
|
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:
|
|
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:
|
|
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.
|
|
@@ -155,4 +146,4 @@ declare const installTestClient: (testClient: TestClient) => (() => void);
|
|
|
155
146
|
*/
|
|
156
147
|
declare const createTestClient: (options?: TestClientOptions) => TestClient;
|
|
157
148
|
//#endregion
|
|
158
|
-
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
|
|
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 { c as createDefaultLogger, d as ConfigDirectorConnectionError, f as ConfigDirectorValidationError, l as nativeValueConfigState, m as _defineProperty, p as Emitter, r as DefaultConfigDirectorClient, s as discardingTelemetryClient, t as INSTALLED_TEST_CLIENT_SLOT } from "./installedTestClient-BluKT8Qj.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 =
|
|
38
|
+
const configState = this.encode(key, value);
|
|
133
39
|
this.configs.set(key, configState);
|
|
134
40
|
this.deliverIfConnected({
|
|
135
41
|
...TEST_ENVIRONMENT,
|
|
@@ -278,19 +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,
|
|
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
|
-
recordInvalidContext: () => {},
|
|
292
|
-
close: async () => {}
|
|
293
|
-
};
|
|
294
197
|
var InMemoryTestClient = class {
|
|
295
198
|
constructor(client, connection) {
|
|
296
199
|
this.client = client;
|
|
@@ -331,7 +234,7 @@ const createTestClient$1 = (sdkOptions, options) => {
|
|
|
331
234
|
var _options$logger, _options$values;
|
|
332
235
|
const logger = (_options$logger = options === null || options === void 0 ? void 0 : options.logger) !== null && _options$logger !== void 0 ? _options$logger : createDefaultLogger();
|
|
333
236
|
const connection = new InMemoryConnection(logger, (_options$values = options === null || options === void 0 ? void 0 : options.values) !== null && _options$values !== void 0 ? _options$values : {});
|
|
334
|
-
return new InMemoryTestClient(new DefaultConfigDirectorClient(
|
|
237
|
+
return new InMemoryTestClient(new DefaultConfigDirectorClient(() => discardingTelemetryClient, TEST_CLIENT_SDK_KEY, sdkOptions, {
|
|
335
238
|
logger,
|
|
336
239
|
connection: { timeout: options === null || options === void 0 ? void 0 : options.timeout }
|
|
337
240
|
}, { transport: connection }), connection);
|
|
@@ -392,7 +295,7 @@ const installTestClient = (testClient) => {
|
|
|
392
295
|
const createTestClient = (options) => {
|
|
393
296
|
return createTestClient$1({
|
|
394
297
|
sdkName: "react-native-sdk",
|
|
395
|
-
sdkVersion: "1.
|
|
298
|
+
sdkVersion: "1.9.0"
|
|
396
299
|
}, options);
|
|
397
300
|
};
|
|
398
301
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as ConfigDirectorLogMessageDecorator,
|
|
1
|
+
import { a as ConfigDirectorClientOptions, d as ConfigDirectorContext, f as ConfigDirectorLogMessageDecorator, g as ConnectionMode, h as ConfigValueType, i as ConfigDirectorClient, m as ConfigDirectorLoggingLevel, n as CachingProvider, o as OfflineValue, p as ConfigDirectorLogger, r as ClientHooks, s as OfflineValues, t as CachingOptions } from "./types-BBQmjjf5.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
|
-
|
|
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 `
|
|
49
|
-
* open and receives config updates as they happen. In `polling` mode configs are fetched once
|
|
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
|
*
|
|
@@ -62,6 +74,12 @@ type ConfigDirectorProviderOptions = {
|
|
|
62
74
|
context?: ConfigDirectorContext;
|
|
63
75
|
logger?: ConfigDirectorLogger;
|
|
64
76
|
hooks?: ClientHooks;
|
|
77
|
+
/**
|
|
78
|
+
* Options for the values the client keeps on the device between launches. The last values received
|
|
79
|
+
* are kept by default and served, with the evaluation reason `cached`, on the next launch of the same
|
|
80
|
+
* context until live values arrive.
|
|
81
|
+
*/
|
|
82
|
+
caching?: CachingOptions;
|
|
65
83
|
netInfoSubscribe?: NetInfoSubscribe;
|
|
66
84
|
};
|
|
67
85
|
/**
|
|
@@ -133,4 +151,4 @@ declare class ConfigDirectorReactContextError extends Error {
|
|
|
133
151
|
//#region src/logger.d.ts
|
|
134
152
|
declare const createConsoleLogger: (level?: ConfigDirectorLoggingLevel) => DefaultConsoleLogger;
|
|
135
153
|
//#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 };
|
|
154
|
+
export { type CachingOptions, type CachingProvider, 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,7 +1,8 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as DEFAULT_CACHING_SIZE_LIMIT_BYTES, c as createDefaultLogger, i as CACHED_VALUES_STORAGE_KEY_PREFIX, m as _defineProperty, n as readInstalledTestClient, o as fetchWithTimeout, r as DefaultConfigDirectorClient, u as isFetchErrorFatal } from "./installedTestClient-BluKT8Qj.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";
|
|
5
|
+
import { bytesToHex } from "@noble/hashes/utils.js";
|
|
5
6
|
import { jsx } from "react/jsx-runtime";
|
|
6
7
|
//#region ../shared/src/telemetry/utils.ts
|
|
7
8
|
const CONFIG_VALUE_MAX_LENGTH = 500;
|
|
@@ -520,8 +521,8 @@ const resolveMetadata = (provided, logger) => {
|
|
|
520
521
|
return metadata;
|
|
521
522
|
};
|
|
522
523
|
//#endregion
|
|
523
|
-
//#region src/
|
|
524
|
-
const
|
|
524
|
+
//#region src/asyncStorage.ts
|
|
525
|
+
const importAsyncStorage = async () => {
|
|
525
526
|
try {
|
|
526
527
|
const { default: storage } = await import("@react-native-async-storage/async-storage");
|
|
527
528
|
return {
|
|
@@ -532,23 +533,10 @@ const lookUpAsyncStorage = async () => {
|
|
|
532
533
|
return { outcome: "not installed" };
|
|
533
534
|
}
|
|
534
535
|
};
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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
|
-
};
|
|
536
|
+
const findAsyncStorage = (logger) => importAsyncStorage().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 looks like a new install to ConfigDirector, a context without an id gets a new identifier each time, and no values are kept on the device between app starts. Install it for the SDK to recognize the install across app starts and to serve the last values when the app starts without a network.");
|
|
538
|
+
return lookup;
|
|
539
|
+
});
|
|
552
540
|
//#endregion
|
|
553
541
|
//#region src/utf8Encoder.ts
|
|
554
542
|
/**
|
|
@@ -590,6 +578,42 @@ const encodeManually = (str) => {
|
|
|
590
578
|
return new Uint8Array(bytes);
|
|
591
579
|
};
|
|
592
580
|
//#endregion
|
|
581
|
+
//#region src/cachingProvider.ts
|
|
582
|
+
const storageKeyFor = (clientSdkKey) => CACHED_VALUES_STORAGE_KEY_PREFIX + bytesToHex(sha256(encodeUtf8(clientSdkKey)));
|
|
583
|
+
const asyncStorageCachingProvider = (asyncStorage) => (clientSdkKey) => {
|
|
584
|
+
const storageKey = storageKeyFor(clientSdkKey);
|
|
585
|
+
return {
|
|
586
|
+
read: async () => {
|
|
587
|
+
const lookup = await asyncStorage;
|
|
588
|
+
return lookup.outcome === "installed" ? lookup.storage.getItem(storageKey) : void 0;
|
|
589
|
+
},
|
|
590
|
+
write: async (value) => {
|
|
591
|
+
const lookup = await asyncStorage;
|
|
592
|
+
if (lookup.outcome === "installed") await lookup.storage.setItem(storageKey, value);
|
|
593
|
+
},
|
|
594
|
+
remove: async () => {
|
|
595
|
+
const lookup = await asyncStorage;
|
|
596
|
+
if (lookup.outcome === "installed") await lookup.storage.removeItem(storageKey);
|
|
597
|
+
},
|
|
598
|
+
sizeLimit: () => DEFAULT_CACHING_SIZE_LIMIT_BYTES
|
|
599
|
+
};
|
|
600
|
+
};
|
|
601
|
+
//#endregion
|
|
602
|
+
//#region src/instanceIdStorage.ts
|
|
603
|
+
const asyncStorageInstanceIdStorage = (asyncStorage) => {
|
|
604
|
+
const installedAsyncStorage = async () => {
|
|
605
|
+
const lookup = await asyncStorage;
|
|
606
|
+
switch (lookup.outcome) {
|
|
607
|
+
case "installed": return lookup.storage;
|
|
608
|
+
case "not installed": throw new Error("@react-native-async-storage/async-storage is not installed");
|
|
609
|
+
}
|
|
610
|
+
};
|
|
611
|
+
return {
|
|
612
|
+
getItem: async (key) => (await installedAsyncStorage()).getItem(key),
|
|
613
|
+
setItem: async (key, value) => (await installedAsyncStorage()).setItem(key, value)
|
|
614
|
+
};
|
|
615
|
+
};
|
|
616
|
+
//#endregion
|
|
593
617
|
//#region src/reactNativeStreamingFetch.ts
|
|
594
618
|
const abortError = (message) => {
|
|
595
619
|
const err = new Error(message);
|
|
@@ -742,19 +766,21 @@ var MinimalUrl = class {
|
|
|
742
766
|
const urlFactory = (input, base) => new MinimalUrl(input, base);
|
|
743
767
|
//#endregion
|
|
744
768
|
//#region src/client.ts
|
|
745
|
-
const createClient = (clientSdkKey, clientOptions) =>
|
|
746
|
-
|
|
769
|
+
const createClient = (clientSdkKey, clientOptions) => createReactNativeClient(clientSdkKey, clientOptions);
|
|
770
|
+
const createReactNativeClient = (clientSdkKey, clientOptions) => {
|
|
771
|
+
var _clientOptions$logger;
|
|
747
772
|
const sdkIdentity = {
|
|
748
773
|
sdkName: "react-native-sdk",
|
|
749
|
-
sdkVersion: "1.
|
|
774
|
+
sdkVersion: "1.9.0"
|
|
750
775
|
};
|
|
751
776
|
const logger = (_clientOptions$logger = clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.logger) !== null && _clientOptions$logger !== void 0 ? _clientOptions$logger : createConsoleLogger("warn");
|
|
752
777
|
const metadata = resolveMetadata(clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.metadata, logger);
|
|
753
|
-
|
|
754
|
-
|
|
778
|
+
const asyncStorage = findAsyncStorage(logger);
|
|
779
|
+
return new DefaultConfigDirectorClient((liveTelemetry) => new ReactNativeTelemetryClient({
|
|
780
|
+
sdkKey: liveTelemetry.clientSdkKey,
|
|
755
781
|
sdkIdentity,
|
|
756
782
|
metaContext: metadata,
|
|
757
|
-
baseUrl:
|
|
783
|
+
baseUrl: liveTelemetry.baseUrl,
|
|
758
784
|
logger,
|
|
759
785
|
urlFactory
|
|
760
786
|
}), clientSdkKey, sdkIdentity, {
|
|
@@ -764,26 +790,29 @@ const createClient = (clientSdkKey, clientOptions) => {
|
|
|
764
790
|
}, {
|
|
765
791
|
fetch: reactNativeStreamingFetch,
|
|
766
792
|
urlFactory,
|
|
767
|
-
instanceIdStorage: asyncStorageInstanceIdStorage(
|
|
793
|
+
instanceIdStorage: asyncStorageInstanceIdStorage(asyncStorage),
|
|
794
|
+
platformCachingProvider: asyncStorageCachingProvider(asyncStorage)
|
|
768
795
|
});
|
|
769
796
|
};
|
|
770
797
|
//#endregion
|
|
771
798
|
//#region src/clientSource.ts
|
|
772
799
|
const buildClient = (options) => {
|
|
773
800
|
var _options$logger;
|
|
774
|
-
return
|
|
801
|
+
return createReactNativeClient(options.sdkKey, {
|
|
775
802
|
connection: {
|
|
776
803
|
url: options.url,
|
|
777
804
|
timeout: options.timeout,
|
|
778
805
|
mode: options.mode,
|
|
779
|
-
pollingInterval: options.pollingInterval
|
|
806
|
+
pollingInterval: options.pollingInterval,
|
|
807
|
+
values: options.values
|
|
780
808
|
},
|
|
781
809
|
metadata: {
|
|
782
810
|
appName: options.appName,
|
|
783
811
|
appVersion: options.appVersion
|
|
784
812
|
},
|
|
785
813
|
logger: (_options$logger = options.logger) !== null && _options$logger !== void 0 ? _options$logger : createConsoleLogger("warn"),
|
|
786
|
-
hooks: options.hooks
|
|
814
|
+
hooks: options.hooks,
|
|
815
|
+
caching: options.caching
|
|
787
816
|
});
|
|
788
817
|
};
|
|
789
818
|
const hasGivenClient = (props) => "client" in props && props.client !== void 0;
|
|
@@ -804,6 +833,7 @@ const resolveClientSource = (props) => {
|
|
|
804
833
|
};
|
|
805
834
|
//#endregion
|
|
806
835
|
//#region src/provider.tsx
|
|
836
|
+
const settledStatusOf = (client) => (client === null || client === void 0 ? void 0 : client.isReady) ? "ready" : "default";
|
|
807
837
|
var ConfigDirectorProvider = class extends Component {
|
|
808
838
|
constructor(props) {
|
|
809
839
|
super(props);
|
|
@@ -871,15 +901,15 @@ var ConfigDirectorProvider = class extends Component {
|
|
|
871
901
|
break;
|
|
872
902
|
case "none": return;
|
|
873
903
|
}
|
|
874
|
-
|
|
904
|
+
this.setState({ status: settledStatusOf(client) });
|
|
875
905
|
}
|
|
876
906
|
async componentDidUpdate(prevProps) {
|
|
877
907
|
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.");
|
|
878
908
|
if (!deepEqual(prevProps.context, this.props.context)) {
|
|
879
|
-
var _this$state$client3, _this$props$context
|
|
909
|
+
var _this$state$client3, _this$props$context;
|
|
880
910
|
this.setState({ status: "loading" });
|
|
881
911
|
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 : {}));
|
|
882
|
-
|
|
912
|
+
this.setState({ status: settledStatusOf(this.state.client) });
|
|
883
913
|
}
|
|
884
914
|
}
|
|
885
915
|
componentWillUnmount() {
|
|
@@ -891,8 +921,8 @@ var ConfigDirectorProvider = class extends Component {
|
|
|
891
921
|
(_this$handlers = this.handlers) === null || _this$handlers === void 0 || _this$handlers.removeAll();
|
|
892
922
|
this.handlers = void 0;
|
|
893
923
|
if (this.ownsClient) {
|
|
894
|
-
var _this$state$
|
|
895
|
-
(_this$state$
|
|
924
|
+
var _this$state$client4;
|
|
925
|
+
(_this$state$client4 = this.state.client) === null || _this$state$client4 === void 0 || _this$state$client4.dispose();
|
|
896
926
|
this.disposedOwnClient = true;
|
|
897
927
|
}
|
|
898
928
|
}
|