@configdirector/react-native-sdk 1.2.0 → 1.3.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
  /**
@@ -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() {
@@ -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
- this.pollingIntervalSeconds = (_options$pollingInter = options.pollingInterval) !== null && _options$pollingInter !== void 0 ? _options$pollingInter : 60;
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, _navigator, _internalClientOption2, _clientOptions$connec6, _clientOptions$hooks, _clientOptions$hooks2, _clientOptions$hooks3, _clientOptions$hooks4, _clientOptions$hooks5;
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: (_navigator = navigator) === null || _navigator === void 0 ? void 0 : _navigator.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,
@@ -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.2.0"
1804
+ sdkVersion: "1.3.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.2.0",
3
+ "version": "1.3.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",