From bbf19b186350ca3f1062c382515c1d1d32b08ff7 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 2 Oct 2025 14:06:16 -0300 Subject: [PATCH 1/4] feat: add EventSource polyfill for improved streaming compatibility --- CHANGES.txt | 3 + README.md | 2 +- src/platform/EventSourceXHR/EventSourceXHR.js | 349 ++++++++++++++++++ src/platform/__tests__/getEventSource.spec.ts | 5 +- src/platform/getEventSource.ts | 14 +- types/full/index.d.ts | 2 +- types/index.d.ts | 2 +- 7 files changed, 369 insertions(+), 8 deletions(-) create mode 100644 src/platform/EventSourceXHR/EventSourceXHR.js diff --git a/CHANGES.txt b/CHANGES.txt index 4e5b2ce..39648ea 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,6 @@ +1.4.0 (October 6, 2025) + - Added an EventSource polyfill to fall back when native EventSource modules and the global EventSource object are unavailable, providing out-of-the-box support for streaming on more platforms and in Expo projects. + 1.3.0 (September 22, 2025) - Added the `InLocalStorage` export to the `@splitsoftware/splitio-react-native` package. This export can be used to configure the SDK to use `AsyncStorage` or another storage implementation to persist the SDK rollout plan data across app restarts and speed up the initialization. - Added the `initialRolloutPlan` configuration option, to allow preloading the SDK storage with a snapshot of the rollout plan. diff --git a/README.md b/README.md index 79cb9f0..e470586 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This SDK is designed to work with Split, the platform for controlled rollouts, w [![Twitter Follow](https://img.shields.io/twitter/follow/splitsoftware.svg?style=social&label=Follow&maxAge=1529000)](https://twitter.com/intent/follow?screen_name=splitsoftware) ## Compatibility -The React Native SDK is a library for React Native applications. The library was build with native modules to support streaming in Android and iOS, and therefore it requires linking the native dependency in order to use streaming. For Expo applications, streaming is not supported by default but a polyfill can be used instead. Check our [public documentation](https://developer.harness.io/docs/feature-management-experimentation/sdks-and-infrastructure/client-side-sdks/react-native-sdk/) for installation details. +The React Native SDK is a library for React Native applications. Check our [public documentation](https://developer.harness.io/docs/feature-management-experimentation/sdks-and-infrastructure/client-side-sdks/react-native-sdk/) for installation details. ## Getting started Below is a simple App.jsx example that describes the instantiation and most basic usage of our SDK: diff --git a/src/platform/EventSourceXHR/EventSourceXHR.js b/src/platform/EventSourceXHR/EventSourceXHR.js new file mode 100644 index 0000000..542dfe9 --- /dev/null +++ b/src/platform/EventSourceXHR/EventSourceXHR.js @@ -0,0 +1,349 @@ +/** + * EventSource polyfill based on https://www.npmjs.com/package/react-native-sse + * + * The MIT License + * + * Copyright (c) 2021 Binary Minds + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +const XMLReadyStateMap = ['UNSENT', 'OPENED', 'HEADERS_RECEIVED', 'LOADING', 'DONE']; + +export class EventSourceXHR { + ERROR = -1; + CONNECTING = 0; + OPEN = 1; + CLOSED = 2; + + CRLF = '\r\n'; + LF = '\n'; + CR = '\r'; + + constructor(url, options = {}) { + this.lastEventId = null; + this.status = this.CONNECTING; + + this.eventHandlers = { + open: [], + message: [], + error: [], + done: [], + close: [], + }; + + this.method = options.method || 'GET'; + this.timeout = options.timeout ?? 0; + this.timeoutBeforeConnection = options.timeoutBeforeConnection ?? 500; + this.withCredentials = options.withCredentials || false; + this.body = options.body || undefined; + this.debug = options.debug || false; + this.interval = options.pollingInterval ?? 5000; + this.lineEndingCharacter = options.lineEndingCharacter || null; + + const defaultHeaders = { + 'Accept': 'text/event-stream', + 'Cache-Control': 'no-cache', + 'X-Requested-With': 'XMLHttpRequest', + }; + + this.headers = { + ...defaultHeaders, + ...options.headers, + }; + + this._xhr = null; + this._pollTimer = null; + this._lastIndexProcessed = 0; + + if (!url || (typeof url !== 'string' && typeof url.toString !== 'function')) { + throw new SyntaxError('[EventSource] Invalid URL argument.'); + } + + if (typeof url.toString === 'function') { + this.url = url.toString(); + } else { + this.url = url; + } + + this._pollAgain(this.timeoutBeforeConnection, true); + } + + _pollAgain(time, allowZero) { + if (time > 0 || allowZero) { + this._logDebug(`[EventSource] Will open new connection in ${time} ms.`); + this._pollTimer = setTimeout(() => { + this.open(); + }, time); + } + } + + open() { + try { + this.status = this.CONNECTING; + + this._lastIndexProcessed = 0; + + this._xhr = new XMLHttpRequest(); + this._xhr.open(this.method, this.url, true); + + if (this.withCredentials) { + this._xhr.withCredentials = true; + } + + for (const [key, value] of Object.entries(this.headers)) { + if (value !== undefined && value !== null) { + this._xhr.setRequestHeader(key, value); + } + } + + if (this.lastEventId !== null) { + this._xhr.setRequestHeader('Last-Event-ID', this.lastEventId); + } + + this._xhr.timeout = this.timeout; + + this._xhr.onreadystatechange = () => { + if (this.status === this.CLOSED) { + return; + } + + const xhr = this._xhr; + + this._logDebug( + `[EventSource][onreadystatechange] ReadyState: ${XMLReadyStateMap[xhr.readyState] || 'Unknown'}(${xhr.readyState}), status: ${xhr.status}` + ); + + if (![XMLHttpRequest.DONE, XMLHttpRequest.LOADING].includes(xhr.readyState)) { + return; + } + + if (xhr.status >= 200 && xhr.status < 400) { + if (this.status === this.CONNECTING) { + this.status = this.OPEN; + this.dispatch('open', { type: 'open' }); + this._logDebug('[EventSource][onreadystatechange][OPEN] Connection opened.'); + } + + this._handleEvent(xhr.responseText || ''); + + if (xhr.readyState === XMLHttpRequest.DONE) { + this._logDebug('[EventSource][onreadystatechange][DONE] Operation done.'); + this._pollAgain(this.interval, false); + this.dispatch('done', { type: 'done' }); + } + } else if (xhr.status !== 0) { + this.status = this.ERROR; + this.dispatch('error', { + type: 'error', + message: xhr.responseText, + xhrStatus: xhr.status, + xhrState: xhr.readyState, + }); + + if (xhr.readyState === XMLHttpRequest.DONE) { + this._logDebug('[EventSource][onreadystatechange][ERROR] Response status error.'); + this._pollAgain(this.interval, false); + } + } + }; + + this._xhr.onerror = () => { + if (this.status === this.CLOSED) { + return; + } + + this.status = this.ERROR; + this.dispatch('error', { + type: 'error', + message: this._xhr.responseText, + xhrStatus: this._xhr.status, + xhrState: this._xhr.readyState, + }); + }; + + if (this.body) { + this._xhr.send(this.body); + } else { + this._xhr.send(); + } + + if (this.timeout > 0) { + setTimeout(() => { + if (this._xhr.readyState === XMLHttpRequest.LOADING) { + this.dispatch('error', { type: 'timeout' }); + this.close(); + } + }, this.timeout); + } + } catch (e) { + this.status = this.ERROR; + this.dispatch('error', { + type: 'exception', + message: e.message, + error: e, + }); + } + } + + _logDebug(...msg) { + if (this.debug) { + console.debug(...msg); + } + } + + _handleEvent(response) { + if (this.lineEndingCharacter === null) { + const detectedNewlineChar = this._detectNewlineChar(response); + if (detectedNewlineChar !== null) { + this._logDebug(`[EventSource] Automatically detected lineEndingCharacter: ${JSON.stringify(detectedNewlineChar).slice(1, -1)}`); + this.lineEndingCharacter = detectedNewlineChar; + } else { + console.warn( + "[EventSource] Unable to identify the line ending character. Ensure your server delivers a standard line ending character: \\r\\n, \\n, \\r, or specify your custom character using the 'lineEndingCharacter' option." + ); + return; + } + } + + const indexOfDoubleNewline = this._getLastDoubleNewlineIndex(response); + if (indexOfDoubleNewline <= this._lastIndexProcessed) { + return; + } + + const parts = response.substring(this._lastIndexProcessed, indexOfDoubleNewline).split(this.lineEndingCharacter); + + this._lastIndexProcessed = indexOfDoubleNewline; + + let type; + let id = null; + let data = []; + let retry = 0; + let line = ''; + + for (let i = 0; i < parts.length; i++) { + line = parts[i].trim(); + if (line.startsWith('event')) { + type = line.replace(/event:?\s*/, ''); + } else if (line.startsWith('retry')) { + retry = parseInt(line.replace(/retry:?\s*/, ''), 10); + if (!isNaN(retry)) { + this.interval = retry; + } + } else if (line.startsWith('data')) { + data.push(line.replace(/data:?\s*/, '')); + } else if (line.startsWith('id')) { + id = line.replace(/id:?\s*/, ''); + if (id !== '') { + this.lastEventId = id; + } else { + this.lastEventId = null; + } + } else if (line === '') { + if (data.length > 0) { + const eventType = type || 'message'; + const event = { + type: eventType, + data: data.join('\n'), + url: this.url, + lastEventId: this.lastEventId, + }; + + this.dispatch(eventType, event); + + data = []; + type = undefined; + } + } + } + } + + _detectNewlineChar(response) { + const supportedLineEndings = [this.CRLF, this.LF, this.CR]; + for (const char of supportedLineEndings) { + if (response.includes(char)) { + return char; + } + } + return null; + } + + _getLastDoubleNewlineIndex(response) { + const doubleLineEndingCharacter = this.lineEndingCharacter + this.lineEndingCharacter; + const lastIndex = response.lastIndexOf(doubleLineEndingCharacter); + if (lastIndex === -1) { + return -1; + } + + return lastIndex + doubleLineEndingCharacter.length; + } + + addEventListener(type, listener) { + if (this.eventHandlers[type] === undefined) { + this.eventHandlers[type] = []; + } + + this.eventHandlers[type].push(listener); + } + + removeEventListener(type, listener) { + if (this.eventHandlers[type] !== undefined) { + this.eventHandlers[type] = this.eventHandlers[type].filter((handler) => handler !== listener); + } + } + + removeAllEventListeners(type) { + const availableTypes = Object.keys(this.eventHandlers); + + if (type === undefined) { + for (const eventType of availableTypes) { + this.eventHandlers[eventType] = []; + } + } else { + if (!availableTypes.includes(type)) { + throw Error(`[EventSource] '${type}' type is not supported event type.`); + } + + this.eventHandlers[type] = []; + } + } + + dispatch(type, data) { + const availableTypes = Object.keys(this.eventHandlers); + + if (!availableTypes.includes(type)) { + return; + } + + for (const handler of Object.values(this.eventHandlers[type])) { + handler(data); + } + } + + close() { + if (this.status !== this.CLOSED) { + this.status = this.CLOSED; + this.dispatch('close', { type: 'close' }); + } + + clearTimeout(this._pollTimer); + if (this._xhr) { + this._xhr.abort(); + } + } +} diff --git a/src/platform/__tests__/getEventSource.spec.ts b/src/platform/__tests__/getEventSource.spec.ts index 6511805..7b733ed 100644 --- a/src/platform/__tests__/getEventSource.spec.ts +++ b/src/platform/__tests__/getEventSource.spec.ts @@ -1,6 +1,7 @@ // No mocking RNEventSource native module. import { getEventSource } from '../getEventSource'; +import { EventSourceXHR } from '../EventSourceXHR/EventSourceXHR'; test('Returns global EventSource if native module RNEventSource is not available', () => { const mockEventSource = jest.fn(); @@ -12,6 +13,6 @@ test('Returns global EventSource if native module RNEventSource is not available global.EventSource = original; }); -test('Returns undefined if global EventSource and native module RNEventSource are not available', () => { - expect(getEventSource()).toBe(undefined); +test('Returns EventSourceXHR polyfill if global EventSource and native module RNEventSource are not available', () => { + expect(getEventSource()).toBe(EventSourceXHR); }); diff --git a/src/platform/getEventSource.ts b/src/platform/getEventSource.ts index db0a60c..2bc630f 100644 --- a/src/platform/getEventSource.ts +++ b/src/platform/getEventSource.ts @@ -1,4 +1,6 @@ import reactNative from 'react-native'; +// @ts-expect-error no declaration file provided +import { EventSourceXHR } from './EventSourceXHR/EventSourceXHR'; let _RNEventSource: typeof EventSource | undefined; @@ -8,9 +10,15 @@ try { } catch (e) {} /** - * Returns native implementation of EventSource. If not available (e.g., Expo or other runtime than Android and iOS), - * checks if global EventSource is available and returns it. + * Returns native implementation of EventSource. + * If not available (e.g., incomplete linking, Expo projects or other runtimes than Android and iOS), checks if global EventSource is available and returns it. + * If not available, returns an EventSource polyfill based on XMLHttpRequest. + * + * The EventSource polyfill is the last option because it doesn't work on Android in debug mode in RN below v0.74, + * due to Flipper network interceptor (https://github.com/NepeinAV/rn-eventsource-reborn#eventsource-dont-works-on-android-in-debug-mode). + * In RN 0.74 (https://reactnative.dev/blog/2024/04/22/release-0.74#removal-of-flipper-react-native-plugin) and Expo 51 (https://github.com/expo/expo/issues/27526#issuecomment-2113893318), + * Flipper was removed from new app templates and replaced by the new React Native DevTools, so the Android-debug interception that broke SSE disappears. */ export function getEventSource(): typeof EventSource | undefined { - return _RNEventSource || (typeof EventSource === 'function' ? EventSource : undefined); + return _RNEventSource || (typeof EventSource === 'function' ? EventSource : EventSourceXHR); } diff --git a/types/full/index.d.ts b/types/full/index.d.ts index c97761d..5c6de26 100644 --- a/types/full/index.d.ts +++ b/types/full/index.d.ts @@ -32,7 +32,7 @@ declare module JsSdk { * } * ``` * - * @see {@link https://developer.harness.io/docs/feature-management-experimentation/sdks-and-infrastructure/client-side-sdks/react-native-sdk/#configuring-persistent-cache-for-the-sdk} + * @see {@link https://developer.harness.io/docs/feature-management-experimentation/sdks-and-infrastructure/client-side-sdks/react-native-sdk/#configuring-cache} */ export function InLocalStorage(options?: SplitIO.InLocalStorageOptions): SplitIO.StorageSyncFactory; diff --git a/types/index.d.ts b/types/index.d.ts index 5ccacc6..b9bfaf1 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -32,7 +32,7 @@ declare module JsSdk { * } * ``` * - * @see {@link https://developer.harness.io/docs/feature-management-experimentation/sdks-and-infrastructure/client-side-sdks/react-native-sdk/#configuring-persistent-cache-for-the-sdk} + * @see {@link https://developer.harness.io/docs/feature-management-experimentation/sdks-and-infrastructure/client-side-sdks/react-native-sdk/#configuring-cache} */ export function InLocalStorage(options?: SplitIO.InLocalStorageOptions): SplitIO.StorageSyncFactory; From 136309195df6d570e73b185e1c0303bed1b7151b Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 2 Oct 2025 14:06:58 -0300 Subject: [PATCH 2/4] rc --- package-lock.json | 4 ++-- package.json | 2 +- src/settings/defaults.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index dd19b2f..70bd035 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio-react-native", - "version": "1.3.0", + "version": "1.3.1-rc.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-react-native", - "version": "1.3.0", + "version": "1.3.1-rc.0", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.6.0" diff --git a/package.json b/package.json index 1a6dab7..c1b497c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-react-native", - "version": "1.3.0", + "version": "1.3.1-rc.0", "description": "Split SDK for React Native", "main": "lib/commonjs/index.js", "module": "lib/module/index.js", diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index f4bf3c3..0b7144a 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -1,7 +1,7 @@ import type SplitIO from '@splitsoftware/splitio-commons/types/splitio'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '1.3.0'; +const packageVersion = '1.3.1-rc.0'; export const defaults = { startup: { From e3ca0f96b99ce3889e17ecbfeee32eaeca923d15 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 2 Oct 2025 14:46:22 -0300 Subject: [PATCH 3/4] stable version --- CHANGES.txt | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src/platform/getEventSource.ts | 2 ++ src/settings/defaults.ts | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 39648ea..210f903 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,5 @@ 1.4.0 (October 6, 2025) - - Added an EventSource polyfill to fall back when native EventSource modules and the global EventSource object are unavailable, providing out-of-the-box support for streaming on more platforms and in Expo projects. + - Added an EventSource polyfill to fall back when native EventSource modules and the global EventSource object are unavailable, providing out-of-the-box streaming support on more platforms and in Expo projects. 1.3.0 (September 22, 2025) - Added the `InLocalStorage` export to the `@splitsoftware/splitio-react-native` package. This export can be used to configure the SDK to use `AsyncStorage` or another storage implementation to persist the SDK rollout plan data across app restarts and speed up the initialization. diff --git a/package-lock.json b/package-lock.json index 70bd035..d95ab7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio-react-native", - "version": "1.3.1-rc.0", + "version": "1.4.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-react-native", - "version": "1.3.1-rc.0", + "version": "1.4.0", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.6.0" diff --git a/package.json b/package.json index c1b497c..0798b35 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-react-native", - "version": "1.3.1-rc.0", + "version": "1.4.0", "description": "Split SDK for React Native", "main": "lib/commonjs/index.js", "module": "lib/module/index.js", diff --git a/src/platform/getEventSource.ts b/src/platform/getEventSource.ts index 2bc630f..da542af 100644 --- a/src/platform/getEventSource.ts +++ b/src/platform/getEventSource.ts @@ -18,6 +18,8 @@ try { * due to Flipper network interceptor (https://github.com/NepeinAV/rn-eventsource-reborn#eventsource-dont-works-on-android-in-debug-mode). * In RN 0.74 (https://reactnative.dev/blog/2024/04/22/release-0.74#removal-of-flipper-react-native-plugin) and Expo 51 (https://github.com/expo/expo/issues/27526#issuecomment-2113893318), * Flipper was removed from new app templates and replaced by the new React Native DevTools, so the Android-debug interception that broke SSE disappears. + * + * @TODO breaking change: drop support for RN < 0.74 and remove native EventSource modules */ export function getEventSource(): typeof EventSource | undefined { return _RNEventSource || (typeof EventSource === 'function' ? EventSource : EventSourceXHR); diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index 0b7144a..b2ed60a 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -1,7 +1,7 @@ import type SplitIO from '@splitsoftware/splitio-commons/types/splitio'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '1.3.1-rc.0'; +const packageVersion = '1.4.0'; export const defaults = { startup: { From 85a230cb1878af3f9bf26073b140d12e8fcde6c8 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 7 Oct 2025 13:26:51 -0300 Subject: [PATCH 4/4] Update JS-commons --- CHANGES.txt | 6 ++++-- package-lock.json | 14 +++++++------- package.json | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 210f903..506ff0d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,7 @@ -1.4.0 (October 6, 2025) - - Added an EventSource polyfill to fall back when native EventSource modules and the global EventSource object are unavailable, providing out-of-the-box streaming support on more platforms and in Expo projects. +1.4.0 (October 7, 2025) + - Added an EventSource polyfill to fall back when native EventSource modules and the global EventSource object are unavailable, providing out-of-the-box streaming support on more platforms and Expo projects. + - Added support for custom loggers: added `logger` configuration option and `factory.Logger.setLogger` method to allow the SDK to use a custom logger. + - Updated @splitsoftware/splitio-commons package to version 2.7.0. 1.3.0 (September 22, 2025) - Added the `InLocalStorage` export to the `@splitsoftware/splitio-react-native` package. This export can be used to configure the SDK to use `AsyncStorage` or another storage implementation to persist the SDK rollout plan data across app restarts and speed up the initialization. diff --git a/package-lock.json b/package-lock.json index d95ab7b..ffc2dd3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.4.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.6.0" + "@splitsoftware/splitio-commons": "2.7.0" }, "devDependencies": { "@react-native-community/eslint-config": "^3.2.0", @@ -4887,9 +4887,9 @@ } }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.6.0.tgz", - "integrity": "sha512-0xODXLciIvHSuMlb8eukIB2epb3ZyGOsrwS0cMuTdxEvCqr7Nuc9pWDdJtRuN1UwL/jIjBnpDYAc8s6mpqLX2g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.0.tgz", + "integrity": "sha512-w2aemu5HNVQXX/tbmSuFjpWa/AjS+EBiH6ltHMqfg2MZMWayTFJbfjjQcudAVLR+vLjDw2DuCTp/xj3kKlcf5g==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -21659,9 +21659,9 @@ } }, "@splitsoftware/splitio-commons": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.6.0.tgz", - "integrity": "sha512-0xODXLciIvHSuMlb8eukIB2epb3ZyGOsrwS0cMuTdxEvCqr7Nuc9pWDdJtRuN1UwL/jIjBnpDYAc8s6mpqLX2g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.7.0.tgz", + "integrity": "sha512-w2aemu5HNVQXX/tbmSuFjpWa/AjS+EBiH6ltHMqfg2MZMWayTFJbfjjQcudAVLR+vLjDw2DuCTp/xj3kKlcf5g==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 0798b35..c03e6b4 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ }, "homepage": "https://github.com/splitio/react-native-client#readme", "dependencies": { - "@splitsoftware/splitio-commons": "2.6.0" + "@splitsoftware/splitio-commons": "2.7.0" }, "devDependencies": { "@react-native-community/eslint-config": "^3.2.0",