@configdirector/react-native-sdk 0.2.0 → 0.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.
package/README.md CHANGED
@@ -1,121 +1,12 @@
1
1
  # ConfigDirector React Native SDK
2
2
 
3
- ## Getting started
3
+ This is the React Native SDK for [ConfigDirector](https://www.configdirector.com).
4
4
 
5
- ### 1. Install
5
+ ## Documentation
6
6
 
7
- Install from NPM:
7
+ Refer to the [official documentation for the React Native SDK](https://docs.configdirector.com/sdks/mobile/react-native).
8
8
 
9
- ```bash
10
- npm install --save @configdirector/react-native-sdk
11
- ```
12
-
13
- ### 2. Initialize the provider using your client SDK key
14
-
15
- ```tsx
16
- import { View } from "react-native";
17
- import AwesomeApp from "./AwesomeApp";
18
- import { ConfigDirectorProvider } from "@configdirector/react-native-sdk";
19
-
20
- export default function App() {
21
- return (
22
- <ConfigDirectorProvider
23
- sdkKey={"YOUR-CLIENT-SDK-KEY"}
24
- appName="MyAwesomeApp"
25
- appVersion="1.0.0">
26
- <View>
27
- <AwesomeApp />
28
- </View>
29
- </ConfigDirectorProvider>
30
- );
31
- }
32
- ```
33
-
34
- ### 3. Retrieve config values
35
-
36
- Retrieve a config value with the `useConfigValue` hook:
37
-
38
- ```tsx
39
- import { useConfigValue } from "@configdirector/react-native-sdk";
40
-
41
- function MyComponent() {
42
- const { value } = useConfigValue<string>("my-config", "default value");
43
-
44
- return <p>My config value: {value}</p>;
45
- }
46
-
47
- export default MyComponent;
48
- ```
49
-
50
- You can also determine if the client is still initializing, so rather than transition from the default value to the evaluated value, you can show a loading state until the client is ready and config values are evaluated:
51
-
52
- ```tsx
53
- import { useConfigValue } from "@configdirector/react-native-sdk";
54
-
55
- function MyComponent() {
56
- const { value, loading } = useConfigValue<string>(
57
- "my-config",
58
- "default value",
59
- );
60
-
61
- if (loading) {
62
- return <p>Loading...</p>;
63
- } else {
64
- return <p>My config value: {value}</p>;
65
- }
66
- }
67
-
68
- export default MyComponent;
69
- ```
70
-
71
- ### 4. Updating the user context
72
-
73
- Update the user context with the `useContext` hook:
74
-
75
- ```tsx
76
- import {
77
- useConfigValue,
78
- useContext,
79
- } from "@configdirector/react-native-sdk";
80
-
81
- function MyComponent() {
82
- const { value: myConfigValue } = useConfigValue<string>(
83
- "my-config",
84
- "default value",
85
- );
86
- const { updateContext } = useContext();
87
-
88
- useEffect(() => {
89
- updateContext({
90
- id: "54321",
91
- name: "Another User",
92
- traits: { customProperty: "customValue" },
93
- });
94
- }, []);
95
-
96
- return <p>My config value: {myConfigValue}</p>;
97
- }
98
-
99
- export default MyComponent;
100
- ```
101
-
102
- ## Requirements
103
-
104
- - React Native **0.71 or later** (requires `ReadableStream` support)
105
- - **Hermes** is strongly recommended. JavaScriptCore (JSC) is supported via a built-in UTF-8 fallback, but Hermes is the default engine in RN 0.70+ and provides better performance.
106
-
107
- ## Expo
108
-
109
- This SDK is compatible with both **Expo managed workflow** and **bare workflow**.
110
-
111
- - In the **managed workflow**, Hermes is the default engine — no additional setup needed.
112
- - In the **bare workflow**, ensure Hermes is enabled in your `Podfile` (iOS) and `gradle.properties` (Android), which is the default in Expo SDK 47+.
113
-
114
- Expo SDK 48 (RN 0.71) or later is required.
115
-
116
- ## License
117
-
118
- MIT
9
+ There is also [a quickstart guide for ConfigDirector and any of our SDKs](https://docs.configdirector.com/getting-started/quickstart).
119
10
 
120
11
  ## Getting Help
121
12
 
@@ -61,6 +61,7 @@ type ConfigDirectorMetaContext = {
61
61
  appVersion?: string;
62
62
  appName?: string;
63
63
  };
64
+ type ConnectionMode = "streaming" | "polling" | "one-time";
64
65
  //#endregion
65
66
  //#region ../js-client-core/src/types.d.ts
66
67
  /**
@@ -76,18 +77,26 @@ type ConfigDirectorClientOptions = {
76
77
  */
77
78
  connection?: {
78
79
  /**
79
- * Whether to open a streaming connection or use a one-time pull of configuration state.
80
- * If set to true, the streaming connection will remain open and receive updates whenever
80
+ * The connection mode to be used, one of `streaming` (default), `polling`, or `one-time`.
81
+ * If set to `streaming`, the connection will remain open and receive updates whenever
81
82
  * config state is updated on the ConfigDirector dashboard.
82
- * When set to false, there will be an initial request to retrieve config state during
83
- * initialization, and an additional request whenever {@link ConfigDirectorClient.updateContext}
84
- * is called. But not updates will be received after those requests.
83
+ * When set to `polling`, there will be an initial request to retrieve config state during
84
+ * initialization, and additional requests on a `pollingInterval`.
85
+ * The `one-time` connection mode will only retrieve config state during initialization and
86
+ * context updates. It will not poll for regular updates.
85
87
  *
86
- * Defaults to true (streaming connection)
88
+ * Defaults to `streaming`
87
89
  */
88
- streaming?: boolean;
90
+ mode?: ConnectionMode;
89
91
  /**
90
- * The timeout, in milliseconds, to be used in initialization and when updating the context.
92
+ * The polling interval in _seconds_ when the `mode` is set to `polling`. This option has no
93
+ * effect when the `mode` is set to `streaming` or `one-time`.
94
+ *
95
+ * Defaults to 60 seconds
96
+ */
97
+ pollingInterval?: number;
98
+ /**
99
+ * The timeout, in _milliseconds_, to be used in initialization and when updating the context.
91
100
  * If streaming is enabled, the operation (initialization or context update) may still succeed
92
101
  * after it times out if no unrecoverable errors are encountered (like an invalid SDK key).
93
102
  * If streaming is disabled, if the operation times out, it will not be retried.
@@ -246,7 +255,7 @@ declare class DefaultConsoleLogger implements ConfigDirectorLogger {
246
255
  info(message: string, ...args: any): void;
247
256
  warn(message: string, ...args: any): void;
248
257
  error(message: string, ...args: any): void;
249
- private log;
258
+ protected log(loggerFunction: (...args: any) => void, level: ConfigDirectorLoggingLevel, message: string, ...args: any): void;
250
259
  }
251
260
  //#endregion
252
261
  //#region src/types.d.ts
@@ -679,6 +679,61 @@ const createDefaultLogger = (level, messageDecorator) => {
679
679
  return new DefaultConsoleLogger(level !== null && level !== void 0 ? level : "warn", messageDecorator !== null && messageDecorator !== void 0 ? messageDecorator : new LogMessageDecorator());
680
680
  };
681
681
  //#endregion
682
+ //#region ../shared/src/transport/AbstractPollingTransport.ts
683
+ var AbstractPollingTransport = class {
684
+ constructor() {
685
+ _defineProperty(this, "fatalError", false);
686
+ _defineProperty(this, "pollingInterval", void 0);
687
+ _defineProperty(this, "pollingIntervalSeconds", 60);
688
+ }
689
+ clearPollingInterval() {
690
+ clearInterval(this.pollingInterval);
691
+ }
692
+ schedulePollingInterval(callback) {
693
+ clearInterval(this.pollingInterval);
694
+ if (this.pollingIntervalSeconds <= 0) return;
695
+ this.pollingInterval = setInterval(callback, this.pollingIntervalSeconds * 1e3);
696
+ }
697
+ async handleNonOkResponse(response) {
698
+ if (!response.ok) if (this.isStatusFatal(response.status)) {
699
+ this.fatalError = true;
700
+ throw this.prepareFatalResponseStatusError(response.status, await response.text());
701
+ } else throw new ConfigDirectorConnectionError(`Connection failed with status: ${response.status}`, response.status);
702
+ }
703
+ handleFetchError(fetchError) {
704
+ if (this.isFetchErrorFatal(fetchError)) {
705
+ this.fatalError = true;
706
+ this.close();
707
+ throw new ConfigDirectorConnectionError(`Connection failed with fatal error: ${fetchError}. This is an unrecoverable error, retry attempts will be ignored.`);
708
+ } else if (fetchError instanceof SyntaxError) throw new ConfigDirectorConnectionError(`Failed to parse the response from the server: ${fetchError}`);
709
+ else throw new ConfigDirectorConnectionError(`Connection failed with error: ${fetchError}.`);
710
+ }
711
+ prepareFatalResponseStatusError(responseStatus, errorBody) {
712
+ var _errorBody$trim$lengt, _errorBody$trim;
713
+ const status = responseStatus !== null && responseStatus !== void 0 ? responseStatus : 0;
714
+ 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);
715
+ }
716
+ isStatusFatal(status) {
717
+ return !!status && status >= 400 && status < 500;
718
+ }
719
+ isFetchErrorFatal(fetchError) {
720
+ if ((fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) === "NotAllowedError") return true;
721
+ else if (fetchError instanceof TypeError) return true;
722
+ return false;
723
+ }
724
+ get isConnected() {
725
+ return this.pollingInterval !== void 0;
726
+ }
727
+ close() {
728
+ clearInterval(this.pollingInterval);
729
+ this.pollingInterval = void 0;
730
+ }
731
+ dispose() {
732
+ this.close();
733
+ this.clear();
734
+ }
735
+ };
736
+ //#endregion
682
737
  //#region ../shared/src/fetchWithTimeout.ts
683
738
  const fetchWithTimeout = async (timeout, resource, options, logger) => {
684
739
  const abortController = new AbortController();
@@ -700,22 +755,35 @@ const fetchWithTimeout = async (timeout, resource, options, logger) => {
700
755
  }
701
756
  };
702
757
  //#endregion
703
- //#region ../js-client-core/src/PullTransport.ts
704
- var PullTransport = class {
758
+ //#region ../js-client-core/src/PollingTransport.ts
759
+ var PollingTransport = class extends AbstractPollingTransport {
705
760
  constructor(options) {
761
+ var _options$pollingInter;
762
+ super();
706
763
  this.options = options;
707
764
  _defineProperty(this, "logger", void 0);
708
765
  _defineProperty(this, "eventEmitter", new Emitter());
709
766
  _defineProperty(this, "url", void 0);
710
- _defineProperty(this, "fatalError", false);
767
+ _defineProperty(this, "lastUpdateTimestamp", void 0);
711
768
  this.options = options;
712
769
  this.logger = options.logger;
713
- this.url = options.resolveUrl("client/pull/v1", options.baseUrl);
770
+ this.url = options.resolveUrl("client/polling/v1", options.baseUrl);
771
+ this.pollingIntervalSeconds = (_options$pollingInter = options.pollingInterval) !== null && _options$pollingInter !== void 0 ? _options$pollingInter : 60;
714
772
  }
715
773
  async connect(context, timeout) {
774
+ this.clearPollingInterval();
775
+ await this.fetchConfigs(context, timeout);
776
+ this.schedulePollingInterval(() => {
777
+ this.fetchConfigs(context, timeout).catch((error) => {
778
+ this.logger.error("[PollingTransport] Error during polling:", error);
779
+ });
780
+ });
781
+ return this;
782
+ }
783
+ async fetchConfigs(context, timeout) {
716
784
  if (this.fatalError) {
717
- this.logger.warn("[PullTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.");
718
- return this;
785
+ this.logger.warn("[PollingTransport] There was a prior unrecoverable error. Ignoring attempt to reconnect.");
786
+ return;
719
787
  }
720
788
  try {
721
789
  const response = await fetchWithTimeout(timeout, this.url, {
@@ -724,32 +792,20 @@ var PullTransport = class {
724
792
  body: JSON.stringify({
725
793
  givenContext: context,
726
794
  metaContext: this.options.metaContext,
727
- clientSdkKey: this.options.clientSdkKey
795
+ clientSdkKey: this.options.clientSdkKey,
796
+ lastUpdateTimestamp: this.lastUpdateTimestamp
728
797
  })
729
798
  }, this.logger);
730
- if (!response.ok) if (this.isStatusFatal(response.status)) {
731
- this.fatalError = true;
732
- throw this.prepareFatalResponseStatusError(response.status, await response.text());
733
- } else throw new ConfigDirectorConnectionError(`Connection failed with status: ${response.status}`, response.status);
734
- const json = JSON.parse(await response.text());
735
- this.eventEmitter.emit("configSetReceived", json);
736
- return this;
799
+ await this.handleNonOkResponse(response);
800
+ if (response.status == 200) {
801
+ const json = JSON.parse(await response.text());
802
+ this.lastUpdateTimestamp = json.timestamp;
803
+ this.eventEmitter.emit("configSetReceived", json);
804
+ }
737
805
  } catch (fetchError) {
738
- if (isFetchErrorFatal(fetchError)) {
739
- this.fatalError = true;
740
- throw new ConfigDirectorConnectionError(`Connection failed with fatal error: ${fetchError}. This is an unrecoverable error, retry attempts will be ignored.`);
741
- } else if (fetchError instanceof SyntaxError) throw new ConfigDirectorConnectionError(`Failed to parse the response from the server: ${fetchError}`);
742
- else throw new ConfigDirectorConnectionError(`Connection failed with error: ${fetchError}.`);
806
+ this.handleFetchError(fetchError);
743
807
  }
744
808
  }
745
- prepareFatalResponseStatusError(responseStatus, errorBody) {
746
- var _errorBody$trim$lengt, _errorBody$trim;
747
- const status = responseStatus !== null && responseStatus !== void 0 ? responseStatus : 0;
748
- 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);
749
- }
750
- isStatusFatal(status) {
751
- return !!status && status >= 400 && status < 500;
752
- }
753
809
  on(name, handler) {
754
810
  this.eventEmitter.on(name, handler);
755
811
  }
@@ -759,10 +815,13 @@ var PullTransport = class {
759
815
  clear() {
760
816
  this.eventEmitter.clear();
761
817
  }
762
- close() {}
763
- dispose() {
764
- this.close();
765
- this.clear();
818
+ };
819
+ //#endregion
820
+ //#region ../js-client-core/src/OneTimeTransport.ts
821
+ var OneTimeTransport = class extends PollingTransport {
822
+ constructor(options) {
823
+ super(options);
824
+ this.pollingIntervalSeconds = 0;
766
825
  }
767
826
  };
768
827
  //#endregion
@@ -776,7 +835,7 @@ const CLIENT_BASE_URL = "https://client-sdk-api.configdirector.com";
776
835
  const MAX_EXPONENTIAL_DELAY = 9;
777
836
  var DefaultConfigDirectorClient = class {
778
837
  constructor(telemetryClient, clientSdkKey, sdkOptions, clientOptions, internalClientOptions) {
779
- var _clientOptions$logger, _clientOptions$connec, _clientOptions$connec2, _internalClientOption, _this$parseUrl, _clientOptions$connec3, _clientOptions$connec4, _navigator, _internalClientOption2;
838
+ var _clientOptions$logger, _clientOptions$connec, _clientOptions$connec2, _internalClientOption, _this$parseUrl, _clientOptions$connec3, _clientOptions$connec4, _clientOptions$connec5, _navigator, _internalClientOption2, _clientOptions$connec6;
780
839
  _defineProperty(this, "logger", void 0);
781
840
  _defineProperty(this, "telemetryClient", void 0);
782
841
  _defineProperty(this, "configSet", void 0);
@@ -790,13 +849,13 @@ var DefaultConfigDirectorClient = class {
790
849
  _defineProperty(this, "readyPromise", void 0);
791
850
  _defineProperty(this, "readyResolve", void 0);
792
851
  _defineProperty(this, "currentContext", void 0);
793
- _defineProperty(this, "streaming", void 0);
852
+ _defineProperty(this, "connectionMode", void 0);
794
853
  this.logger = (_clientOptions$logger = clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.logger) !== null && _clientOptions$logger !== void 0 ? _clientOptions$logger : createDefaultLogger();
795
854
  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;
796
855
  const urlFactory = (_internalClientOption = internalClientOptions === null || internalClientOptions === void 0 ? void 0 : internalClientOptions.urlFactory) !== null && _internalClientOption !== void 0 ? _internalClientOption : defaultUrlFactory;
797
856
  const baseUrl = (_this$parseUrl = this.parseUrl(clientOptions === null || clientOptions === void 0 || (_clientOptions$connec3 = clientOptions.connection) === null || _clientOptions$connec3 === void 0 ? void 0 : _clientOptions$connec3.url, urlFactory)) !== null && _this$parseUrl !== void 0 ? _this$parseUrl : CLIENT_BASE_URL;
798
- this.streaming = (clientOptions === null || clientOptions === void 0 || (_clientOptions$connec4 = clientOptions.connection) === null || _clientOptions$connec4 === void 0 ? void 0 : _clientOptions$connec4.streaming) === false ? false : true;
799
- const transportConstructor = this.streaming ? StreamingTransport : PullTransport;
857
+ this.connectionMode = (_clientOptions$connec4 = clientOptions === null || clientOptions === void 0 || (_clientOptions$connec5 = clientOptions.connection) === null || _clientOptions$connec5 === void 0 ? void 0 : _clientOptions$connec5.mode) !== null && _clientOptions$connec4 !== void 0 ? _clientOptions$connec4 : "streaming";
858
+ const transportConstructor = this.getTransportConstructor(this.connectionMode);
800
859
  this.telemetryClient = telemetryClient;
801
860
  this.transport = new transportConstructor({
802
861
  clientSdkKey,
@@ -812,7 +871,8 @@ var DefaultConfigDirectorClient = class {
812
871
  fetch: internalClientOptions === null || internalClientOptions === void 0 ? void 0 : internalClientOptions.fetch,
813
872
  connectionRetryDelay: (_internalClientOption2 = internalClientOptions === null || internalClientOptions === void 0 ? void 0 : internalClientOptions.connectionRetryDelay) !== null && _internalClientOption2 !== void 0 ? _internalClientOption2 : ((attempt) => {
814
873
  return Math.pow(2, Math.min(attempt, MAX_EXPONENTIAL_DELAY)) * 1e3;
815
- })
874
+ }),
875
+ pollingInterval: clientOptions === null || clientOptions === void 0 || (_clientOptions$connec6 = clientOptions.connection) === null || _clientOptions$connec6 === void 0 ? void 0 : _clientOptions$connec6.pollingInterval
816
876
  });
817
877
  this.transport.on("configSetReceived", (configSet) => {
818
878
  var _this$readyResolve;
@@ -833,6 +893,13 @@ var DefaultConfigDirectorClient = class {
833
893
  this.logger.debug("[ConfigDirectorClient] ConfigSet updated from server:", { keys: configKeys });
834
894
  });
835
895
  }
896
+ getTransportConstructor(connectionMode) {
897
+ switch (connectionMode) {
898
+ case "one-time": return OneTimeTransport;
899
+ case "polling": return PollingTransport;
900
+ default: return StreamingTransport;
901
+ }
902
+ }
836
903
  async initialize(context) {
837
904
  this.initializing = true;
838
905
  await this.connectToTransport(context, "initialization");
@@ -866,10 +933,7 @@ var DefaultConfigDirectorClient = class {
866
933
  if (remainingTimeout > 0) await Promise.race([this.readyPromise, new Promise((resolve) => {
867
934
  this.timeoutTimer = setTimeout(() => resolve(), remainingTimeout);
868
935
  })]).finally(() => clearTimeout(this.timeoutTimer));
869
- if (!this.ready) {
870
- const warningDetails = this.streaming ? "The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds." : "Since the client was configured without streaming, configs may not update and always return the default value.";
871
- this.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${caller} after ${this.timeout}ms. ${warningDetails}`);
872
- }
936
+ if (!this.ready) this.logger.warn(`[ConfigDirectorClient] Timed out waiting for ${caller} after ${this.timeout}ms. The client will continue to retry since there were no fatal errors detected. Configs will return the default value until the connection succeeds.`);
873
937
  } catch (error) {
874
938
  this.logger.error(`[ConfigDirectorClient] An error occurred during ${caller}: `, error);
875
939
  }
@@ -1303,6 +1367,11 @@ const encodeManually = (str) => {
1303
1367
  };
1304
1368
  //#endregion
1305
1369
  //#region src/reactNativeStreamingFetch.ts
1370
+ const abortError = (message) => {
1371
+ const err = new Error(message);
1372
+ err.name = "AbortError";
1373
+ return err;
1374
+ };
1306
1375
  /**
1307
1376
  * A fetch-compatible function for React Native that uses XMLHttpRequest to
1308
1377
  * support streaming SSE responses. React Native's built-in fetch accumulates
@@ -1312,7 +1381,7 @@ const encodeManually = (str) => {
1312
1381
  */
1313
1382
  const reactNativeStreamingFetch = (url, init) => {
1314
1383
  var _init$signal;
1315
- if ((_init$signal = init.signal) === null || _init$signal === void 0 ? void 0 : _init$signal.aborted) return Promise.reject(new DOMException("Request was aborted before it was opened", "AbortError"));
1384
+ if ((_init$signal = init.signal) === null || _init$signal === void 0 ? void 0 : _init$signal.aborted) return Promise.reject(abortError("Request was aborted before it was opened"));
1316
1385
  return new Promise((resolve, reject) => {
1317
1386
  var _init$method, _ref;
1318
1387
  const xhr = new XMLHttpRequest();
@@ -1356,7 +1425,7 @@ const reactNativeStreamingFetch = (url, init) => {
1356
1425
  };
1357
1426
  if (init.signal) init.signal.addEventListener("abort", () => {
1358
1427
  xhr.abort();
1359
- if (!responseResolved) reject(new DOMException("Request was aborted", "AbortError"));
1428
+ if (!responseResolved) reject(abortError("Request was aborted"));
1360
1429
  else try {
1361
1430
  streamController.close();
1362
1431
  } catch {}
@@ -1423,7 +1492,7 @@ const createClient = (clientSdkKey, clientOptions) => {
1423
1492
  const logger = (_clientOptions$logger = clientOptions === null || clientOptions === void 0 ? void 0 : clientOptions.logger) !== null && _clientOptions$logger !== void 0 ? _clientOptions$logger : createConsoleLogger("warn");
1424
1493
  return new DefaultConfigDirectorClient(new ReactNativeTelemetryClient(clientSdkKey, (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, logger, urlFactory), clientSdkKey, {
1425
1494
  sdkName: "react-native-sdk",
1426
- sdkVersion: "0.2.0"
1495
+ sdkVersion: "0.3.0"
1427
1496
  }, {
1428
1497
  ...clientOptions,
1429
1498
  logger
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@configdirector/react-native-sdk",
3
- "version": "0.2.0",
3
+ "version": "0.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",
@@ -21,7 +21,7 @@
21
21
  "homepage": "https://www.configdirector.com",
22
22
  "repository": {
23
23
  "type": "git",
24
- "url": "https://github.com/ConfigDirector/js-sdks"
24
+ "url": "git+https://github.com/ConfigDirector/js-sdks.git"
25
25
  },
26
26
  "main": "./dist/configdirector-react-native.mjs",
27
27
  "types": "./dist/configdirector-react-native.d.mts",
@@ -39,7 +39,7 @@
39
39
  ],
40
40
  "scripts": {
41
41
  "example": "yarn workspace @configdirector/react-native-sdk-example",
42
- "clean": "del-cli dist",
42
+ "clean": "rm -fr dist",
43
43
  "build": "tsdown",
44
44
  "prepare": "yarn build",
45
45
  "typecheck": "tsc",
@@ -78,9 +78,9 @@
78
78
  "wtfnode": "^0.10.1"
79
79
  },
80
80
  "peerDependencies": {
81
- "expo": ">=48",
81
+ "expo": ">=52",
82
82
  "react": "*",
83
- "react-native": ">=0.71"
83
+ "react-native": ">=0.75"
84
84
  },
85
85
  "peerDependenciesMeta": {
86
86
  "expo": {