@configdirector/react-native-sdk 1.2.0 → 1.4.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.
|
@@ -107,7 +107,8 @@ type ConfigDirectorClientOptions = {
|
|
|
107
107
|
* The polling interval in _seconds_ when the `mode` is set to `polling`. This option has no
|
|
108
108
|
* effect when the `mode` is set to `streaming`.
|
|
109
109
|
*
|
|
110
|
-
* Defaults to 60 seconds
|
|
110
|
+
* Defaults to 300 seconds (5 minutes). Values below the minimum of 60 seconds are raised
|
|
111
|
+
* to 60 seconds.
|
|
111
112
|
*/
|
|
112
113
|
pollingInterval?: number;
|
|
113
114
|
/**
|
|
@@ -511,7 +511,7 @@ var StreamingTransport = class {
|
|
|
511
511
|
return new ConfigDirectorConnectionError(`${`Connection failed with status: ${responseStatus !== null && responseStatus !== void 0 ? responseStatus : "unknown"}.`}${error ? ` Error: ${error}` : ""}. This is an unrecoverable error, will not attempt to reconnect.`, status);
|
|
512
512
|
}
|
|
513
513
|
isStatusFatal(status) {
|
|
514
|
-
return !!status && status >= 400 && status < 500;
|
|
514
|
+
return !!status && status >= 400 && status < 500 && status != 429;
|
|
515
515
|
}
|
|
516
516
|
on(name, handler) {
|
|
517
517
|
this.eventEmitter.on(name, handler);
|
|
@@ -757,6 +757,92 @@ const generateInstanceId = () => {
|
|
|
757
757
|
});
|
|
758
758
|
};
|
|
759
759
|
//#endregion
|
|
760
|
+
//#region ../js-client-core/src/instance-id.ts
|
|
761
|
+
const STORAGE_KEY = "configdirector-sdk:instance-id";
|
|
762
|
+
const RECORD_VERSION = 1;
|
|
763
|
+
const MAX_AGE_MS = 360 * 60 * 1e3;
|
|
764
|
+
const CHECKSUM_SALT = "configdirector.instanceId.v1";
|
|
765
|
+
const UUID_V4_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
766
|
+
const fnv1a = (input, offsetBasis) => {
|
|
767
|
+
let hash = offsetBasis;
|
|
768
|
+
for (let i = 0; i < input.length; i++) {
|
|
769
|
+
hash ^= input.charCodeAt(i);
|
|
770
|
+
hash = Math.imul(hash, 16777619);
|
|
771
|
+
}
|
|
772
|
+
return hash >>> 0;
|
|
773
|
+
};
|
|
774
|
+
const checksumFor = (id, createdAt) => {
|
|
775
|
+
const payload = `${CHECKSUM_SALT}|${id}|${createdAt}`;
|
|
776
|
+
const low = fnv1a(payload, 2166136261);
|
|
777
|
+
return fnv1a(`${low}|${payload}`, 16777619).toString(16).padStart(8, "0") + low.toString(16).padStart(8, "0");
|
|
778
|
+
};
|
|
779
|
+
const getLocalStorage = () => {
|
|
780
|
+
try {
|
|
781
|
+
var _localStorage;
|
|
782
|
+
return (_localStorage = globalThis.localStorage) !== null && _localStorage !== void 0 ? _localStorage : void 0;
|
|
783
|
+
} catch {
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
const isUsableRecord = (record) => {
|
|
788
|
+
if (!record || typeof record !== "object") return false;
|
|
789
|
+
const { v, id, createdAt, checksum } = record;
|
|
790
|
+
if (v !== RECORD_VERSION || typeof id !== "string" || typeof checksum !== "string") return false;
|
|
791
|
+
if (typeof createdAt !== "number" || !Number.isInteger(createdAt) || createdAt <= 0) return false;
|
|
792
|
+
if (!UUID_V4_PATTERN.test(id)) return false;
|
|
793
|
+
return checksum === checksumFor(id, createdAt);
|
|
794
|
+
};
|
|
795
|
+
const readStoredInstanceId = (storage, logger) => {
|
|
796
|
+
let raw;
|
|
797
|
+
try {
|
|
798
|
+
raw = storage.getItem(STORAGE_KEY);
|
|
799
|
+
} catch (error) {
|
|
800
|
+
logger === null || logger === void 0 || logger.debug("[ConfigDirectorClient] Could not read the stored instance id, generating a new one", error);
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
if (!raw) return;
|
|
804
|
+
let record;
|
|
805
|
+
try {
|
|
806
|
+
record = JSON.parse(raw);
|
|
807
|
+
} catch {
|
|
808
|
+
logger === null || logger === void 0 || logger.debug("[ConfigDirectorClient] The stored instance id is not valid JSON, generating a new one");
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
if (!isUsableRecord(record)) {
|
|
812
|
+
logger === null || logger === void 0 || logger.debug("[ConfigDirectorClient] The stored instance id failed validation, generating a new one");
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
815
|
+
const age = Date.now() - record.createdAt;
|
|
816
|
+
if (age < 0 || age >= MAX_AGE_MS) {
|
|
817
|
+
logger === null || logger === void 0 || logger.debug("[ConfigDirectorClient] The stored instance id has expired, generating a new one");
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
return record.id;
|
|
821
|
+
};
|
|
822
|
+
const storeInstanceId = (storage, id, logger) => {
|
|
823
|
+
const createdAt = Date.now();
|
|
824
|
+
const record = {
|
|
825
|
+
v: RECORD_VERSION,
|
|
826
|
+
id,
|
|
827
|
+
createdAt,
|
|
828
|
+
checksum: checksumFor(id, createdAt)
|
|
829
|
+
};
|
|
830
|
+
try {
|
|
831
|
+
storage.setItem(STORAGE_KEY, JSON.stringify(record));
|
|
832
|
+
} catch (error) {
|
|
833
|
+
logger === null || logger === void 0 || logger.debug("[ConfigDirectorClient] Could not persist the instance id", error);
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
const resolveInstanceId = (logger) => {
|
|
837
|
+
const storage = getLocalStorage();
|
|
838
|
+
if (!storage) return generateInstanceId();
|
|
839
|
+
const storedInstanceId = readStoredInstanceId(storage, logger);
|
|
840
|
+
if (storedInstanceId) return storedInstanceId;
|
|
841
|
+
const instanceId = generateInstanceId();
|
|
842
|
+
storeInstanceId(storage, instanceId, logger);
|
|
843
|
+
return instanceId;
|
|
844
|
+
};
|
|
845
|
+
//#endregion
|
|
760
846
|
//#region ../shared/src/transport/AbstractPollingTransport.ts
|
|
761
847
|
var AbstractPollingTransport = class {
|
|
762
848
|
constructor() {
|
|
@@ -793,7 +879,7 @@ var AbstractPollingTransport = class {
|
|
|
793
879
|
return new ConfigDirectorConnectionError(`${`Connection failed with status: ${responseStatus !== null && responseStatus !== void 0 ? responseStatus : "unknown"}`}${((_errorBody$trim$lengt = errorBody === null || errorBody === void 0 || (_errorBody$trim = errorBody.trim()) === null || _errorBody$trim === void 0 ? void 0 : _errorBody$trim.length) !== null && _errorBody$trim$lengt !== void 0 ? _errorBody$trim$lengt : 0) > 0 ? ` (${errorBody})` : ""}. This is an unrecoverable error, retry attempts will be ignored.`, status);
|
|
794
880
|
}
|
|
795
881
|
isStatusFatal(status) {
|
|
796
|
-
return !!status && status >= 400 && status < 500;
|
|
882
|
+
return !!status && status >= 400 && status < 500 && status != 429;
|
|
797
883
|
}
|
|
798
884
|
isFetchErrorFatal(fetchError) {
|
|
799
885
|
return (fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) === "NotAllowedError";
|
|
@@ -845,7 +931,9 @@ var PollingTransport = class extends AbstractPollingTransport {
|
|
|
845
931
|
this.options = options;
|
|
846
932
|
this.logger = options.logger;
|
|
847
933
|
this.url = options.resolveUrl("client/polling/v1", options.baseUrl);
|
|
848
|
-
|
|
934
|
+
const requestedInterval = (_options$pollingInter = options.pollingInterval) !== null && _options$pollingInter !== void 0 ? _options$pollingInter : 300;
|
|
935
|
+
if (requestedInterval < 60) this.logger.warn(`[PollingTransport] pollingInterval of ${requestedInterval} seconds is below the minimum of 60 seconds. Using 60 seconds.`);
|
|
936
|
+
this.pollingIntervalSeconds = Math.max(requestedInterval, 60);
|
|
849
937
|
}
|
|
850
938
|
async connect(context, timeout) {
|
|
851
939
|
this.clearPollingInterval();
|
|
@@ -903,11 +991,28 @@ var PollingTransport = class extends AbstractPollingTransport {
|
|
|
903
991
|
}
|
|
904
992
|
};
|
|
905
993
|
//#endregion
|
|
994
|
+
//#region ../js-client-core/src/browser-globals.ts
|
|
995
|
+
const read = (readValue) => {
|
|
996
|
+
try {
|
|
997
|
+
return readValue(globalThis);
|
|
998
|
+
} catch {
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
};
|
|
1002
|
+
const readUserAgent = () => read((globals) => {
|
|
1003
|
+
var _globals$navigator;
|
|
1004
|
+
return (_globals$navigator = globals.navigator) === null || _globals$navigator === void 0 ? void 0 : _globals$navigator.userAgent;
|
|
1005
|
+
});
|
|
1006
|
+
const readHost = () => read((globals) => {
|
|
1007
|
+
var _globals$location;
|
|
1008
|
+
return (_globals$location = globals.location) === null || _globals$location === void 0 ? void 0 : _globals$location.host;
|
|
1009
|
+
});
|
|
1010
|
+
//#endregion
|
|
906
1011
|
//#region ../js-client-core/src/DefaultConfigDirectorClient.ts
|
|
907
1012
|
const MAX_EXPONENTIAL_DELAY = 9;
|
|
908
1013
|
var DefaultConfigDirectorClient = class {
|
|
909
1014
|
constructor(telemetryClient, clientSdkKey, sdkOptions, clientOptions, internalClientOptions) {
|
|
910
|
-
var _clientOptions$logger, _clientOptions$connec, _clientOptions$connec2, _internalClientOption, _this$parseUrl, _clientOptions$connec3, _clientOptions$connec4, _clientOptions$connec5,
|
|
1015
|
+
var _clientOptions$logger, _clientOptions$connec, _clientOptions$connec2, _internalClientOption, _this$parseUrl, _clientOptions$connec3, _clientOptions$connec4, _clientOptions$connec5, _internalClientOption2, _clientOptions$connec6, _clientOptions$hooks, _clientOptions$hooks2, _clientOptions$hooks3, _clientOptions$hooks4, _clientOptions$hooks5;
|
|
911
1016
|
_defineProperty(this, "logger", void 0);
|
|
912
1017
|
_defineProperty(this, "telemetryClient", void 0);
|
|
913
1018
|
_defineProperty(this, "configSet", void 0);
|
|
@@ -923,8 +1028,8 @@ var DefaultConfigDirectorClient = class {
|
|
|
923
1028
|
_defineProperty(this, "currentContext", void 0);
|
|
924
1029
|
_defineProperty(this, "connectionMode", void 0);
|
|
925
1030
|
_defineProperty(this, "instanceId", void 0);
|
|
926
|
-
this.instanceId = generateInstanceId();
|
|
927
1031
|
this.logger = (_clientOptions$logger = clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.logger) !== null && _clientOptions$logger !== void 0 ? _clientOptions$logger : createDefaultLogger();
|
|
1032
|
+
this.instanceId = resolveInstanceId(this.logger);
|
|
928
1033
|
this.timeout = (_clientOptions$connec = clientOptions === null || clientOptions === void 0 || (_clientOptions$connec2 = clientOptions.connection) === null || _clientOptions$connec2 === void 0 ? void 0 : _clientOptions$connec2.timeout) !== null && _clientOptions$connec !== void 0 ? _clientOptions$connec : 3e3;
|
|
929
1034
|
this.validateSdkKeyPresence(clientSdkKey);
|
|
930
1035
|
const urlFactory = (_internalClientOption = internalClientOptions === null || internalClientOptions === void 0 ? void 0 : internalClientOptions.urlFactory) !== null && _internalClientOption !== void 0 ? _internalClientOption : defaultUrlFactory;
|
|
@@ -941,7 +1046,8 @@ var DefaultConfigDirectorClient = class {
|
|
|
941
1046
|
...clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.metadata,
|
|
942
1047
|
sdkName: sdkOptions.sdkName,
|
|
943
1048
|
sdkVersion: sdkOptions.sdkVersion,
|
|
944
|
-
userAgent: (
|
|
1049
|
+
userAgent: readUserAgent(),
|
|
1050
|
+
host: readHost()
|
|
945
1051
|
},
|
|
946
1052
|
logger: this.logger,
|
|
947
1053
|
fetch: internalClientOptions === null || internalClientOptions === void 0 ? void 0 : internalClientOptions.fetch,
|
|
@@ -1298,7 +1404,7 @@ var ClientEventReporter = class {
|
|
|
1298
1404
|
}
|
|
1299
1405
|
}
|
|
1300
1406
|
isStatusFatal(status) {
|
|
1301
|
-
return !!status && status >= 400 && status < 500;
|
|
1407
|
+
return !!status && status >= 400 && status < 500 && status != 429;
|
|
1302
1408
|
}
|
|
1303
1409
|
};
|
|
1304
1410
|
//#endregion
|
|
@@ -1695,7 +1801,7 @@ const createClient = (clientSdkKey, clientOptions) => {
|
|
|
1695
1801
|
var _clientOptions$logger, _clientOptions$connec;
|
|
1696
1802
|
const sdkIdentity = {
|
|
1697
1803
|
sdkName: "react-native-sdk",
|
|
1698
|
-
sdkVersion: "1.
|
|
1804
|
+
sdkVersion: "1.4.0"
|
|
1699
1805
|
};
|
|
1700
1806
|
const logger = (_clientOptions$logger = clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.logger) !== null && _clientOptions$logger !== void 0 ? _clientOptions$logger : createConsoleLogger("warn");
|
|
1701
1807
|
return new DefaultConfigDirectorClient(new ReactNativeTelemetryClient({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@configdirector/react-native-sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "React Native client SDK for ConfigDirector. ConfigDirector is a remote configuration and feature flag service.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ConfigDirector",
|