From 170c81c9970c9a668e8616279c7872e94c7c8d21 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 1 Oct 2024 21:14:06 -0300 Subject: [PATCH 01/13] Added getState method to NodeJS factory instances --- package-lock.json | 18 +++--- package.json | 4 +- .../browserSuites/ready-from-cache.spec.js | 58 +++++++++++++++++++ .../browserSuites/ready-promise.spec.js | 2 +- src/__tests__/nodeSuites/evaluations.spec.js | 13 +++++ src/__tests__/offline/browser.spec.js | 2 - src/factory/browser.js | 7 +-- src/factory/node.js | 13 ++++- src/settings/defaults/version.js | 2 +- src/settings/storage/browser.js | 18 +----- types/splitio.d.ts | 11 +++- 11 files changed, 110 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4fce49522..75be96c43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.2", + "version": "10.28.1-rc.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.2", + "version": "10.28.1-rc.3", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "1.17.1-rc.1", + "@splitsoftware/splitio-commons": "1.17.1-rc.2", "@types/google.analytics": "0.0.40", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", @@ -872,9 +872,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "1.17.1-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.1.tgz", - "integrity": "sha512-mmDcWW2iyqQF/FzLgPoRA3KXpvswk/sDIhQGWTg3WPkapnA+e4WXb+U/TSGGB/Ig88NlM76FlxMDkrHnBayDXg==", + "version": "1.17.1-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.2.tgz", + "integrity": "sha512-ItqKJbUvHsR5Ff6sGjJFlGCcTrQHve9eObISaHOXGPsEaMCRdke8rhQh/bo4L8W2nn5YaY4DbuXJ9w59PA1khQ==", "dependencies": { "tslib": "^2.3.1" }, @@ -8528,9 +8528,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.17.1-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.1.tgz", - "integrity": "sha512-mmDcWW2iyqQF/FzLgPoRA3KXpvswk/sDIhQGWTg3WPkapnA+e4WXb+U/TSGGB/Ig88NlM76FlxMDkrHnBayDXg==", + "version": "1.17.1-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.2.tgz", + "integrity": "sha512-ItqKJbUvHsR5Ff6sGjJFlGCcTrQHve9eObISaHOXGPsEaMCRdke8rhQh/bo4L8W2nn5YaY4DbuXJ9w59PA1khQ==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index ed707f03c..f8b6025ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.2", + "version": "10.28.1-rc.3", "description": "Split SDK", "files": [ "README.md", @@ -40,7 +40,7 @@ "node": ">=6" }, "dependencies": { - "@splitsoftware/splitio-commons": "1.17.1-rc.1", + "@splitsoftware/splitio-commons": "1.17.1-rc.2", "@types/google.analytics": "0.0.40", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index b0ffd6706..c13f06bb9 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -478,6 +478,64 @@ export default function (fetchMock, assert) { }); }); + assert.test(t => { // Testing when we start with preloaded data and MEMORY storage type (is ready from cache immediately) + const testUrls = { + sdk: 'https://sdk.baseurl/readyFromCacheWithPreloadedData', + events: 'https://events.baseurl/readyFromCacheWithPreloadedData' + }; + + t.plan(5); + + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=25', { status: 200, body: { ...splitChangesMock1, since: 25 } }); + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); + fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: membershipsNicolas }); + fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas2%40split.io', { status: 200, body: { 'ms': {} } }); + + fetchMock.postOnce(testUrls.events + '/testImpressions/bulk', 200); + fetchMock.postOnce(testUrls.events + '/testImpressions/count', 200); + + const splitio = SplitFactory({ + ...baseConfig, + storage: { + type: 'MEMORY', + }, + urls: testUrls, + preloadedData: { + since: 25, + splitsData: [JSON.parse(alwaysOnSplitInverted)] + } + }); + + const client = splitio.client(); + const client2 = splitio.client('nicolas2@split.io'); + + t.equal(client.__getStatus().isReadyFromCache, true, 'Client is ready from cache'); + + t.equal(client.getTreatment('always_on'), 'off', 'It should evaluate treatments with data from cache instead of control due to Input Validation'); + t.equal(client2.getTreatment('always_on'), 'off', 'It should evaluate treatments with data from cache instead of control due to Input Validation'); + + client.on(client.Event.SDK_READY_TIMED_OUT, () => { + t.fail('It should not timeout in this scenario.'); + t.end(); + }); + + client.on(client.Event.SDK_READY_FROM_CACHE, () => { + t.fail('SDK is ready from cache immediately. SDK_READY_FROM_CACHE not emitted.'); + t.end(); + }); + + client.on(client.Event.SDK_READY, () => { + t.equal(client.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); + }); + client2.on(client2.Event.SDK_READY, () => { + t.equal(client2.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); + + splitio.destroy().then(() => { + t.end(); + }); + }); + }); + /** Fetch specific splits **/ assert.test(t => { // Testing when we start with cached data but without storage hash (JS SDK <=v10.24.0 and Browser SDK <=v0.12.0), and a valid split filter config diff --git a/src/__tests__/browserSuites/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js index ebcd5843c..cb13c8107 100644 --- a/src/__tests__/browserSuites/ready-promise.spec.js +++ b/src/__tests__/browserSuites/ready-promise.spec.js @@ -561,7 +561,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { }); }, 0); }); - }, fromSecondsToMillis(0.2)); + }, fromSecondsToMillis(0.25)); }, 'Validate that warning messages are properly sent'); diff --git a/src/__tests__/nodeSuites/evaluations.spec.js b/src/__tests__/nodeSuites/evaluations.spec.js index f5cf6aa53..d870d2526 100644 --- a/src/__tests__/nodeSuites/evaluations.spec.js +++ b/src/__tests__/nodeSuites/evaluations.spec.js @@ -1,4 +1,5 @@ import { SplitFactory } from '../../'; +import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; const SDK_INSTANCES_TO_TEST = 4; @@ -265,6 +266,18 @@ export default async function (config, key, assert) { getTreatmentsTests(client, i); getTreatmentsWithConfigTests(client, i); + // getState method + const serverSideState = splitio.getState(); + assert.equal(serverSideState.since, 1457552620999); + assert.equal(serverSideState.splitsData.length, splitChangesMock1.splits.length); + assert.deepEqual(serverSideState.segmentsData, { employees: [], splitters: [], developers: [] }); + assert.deepEqual(serverSideState.mySegmentsData, undefined); + const clientSideState = splitio.getState(['user1']); + assert.equal(clientSideState.since, 1457552620999); + assert.equal(clientSideState.splitsData.length, splitChangesMock1.splits.length); + assert.deepEqual(clientSideState.segmentsData, undefined); + assert.deepEqual(clientSideState.mySegmentsData, { user1: [] }); + await client.destroy(); tested++; diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index bce2020eb..5c99786c0 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -112,8 +112,6 @@ tape('Browser offline mode', function (assert) { }); const sdkReadyFromCache = (client) => () => { - assert.equal(factory.settings.storage.type, 'MEMORY', 'In localhost mode, storage must fallback to memory storage'); - const clientStatus = client.__getStatus(); assert.equal(clientStatus.isReadyFromCache, true, 'If ready from cache, READY_FROM_CACHE status must be true'); assert.equal(clientStatus.isReady, false, 'READY status must not be set before READY_FROM_CACHE'); diff --git a/src/factory/browser.js b/src/factory/browser.js index 9b877a36d..e9793f056 100644 --- a/src/factory/browser.js +++ b/src/factory/browser.js @@ -8,7 +8,6 @@ import { sdkManagerFactory } from '@splitsoftware/splitio-commons/src/sdkManager import { sdkClientMethodCSFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethodCSWithTT'; import { impressionObserverCSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverCS'; import { integrationsManagerFactory } from '@splitsoftware/splitio-commons/src/integrations/browser'; -import { __InLocalStorageMockFactory } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/storage/storageCS'; import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory'; import { LOCALHOST_MODE, STORAGE_LOCALSTORAGE } from '@splitsoftware/splitio-commons/src/utils/constants'; import { createUserConsentAPI } from '@splitsoftware/splitio-commons/src/consent/sdkUserConsent'; @@ -20,10 +19,8 @@ const syncManagerOnlineCSFactory = syncManagerOnlineFactory(pollingManagerCSFact function getStorage(settings) { return settings.storage.type === STORAGE_LOCALSTORAGE ? - InLocalStorage(settings.storage) - : settings.storage.__originalType === STORAGE_LOCALSTORAGE ? - __InLocalStorageMockFactory - : InMemoryStorageCSFactory; + InLocalStorage(settings.storage) : + InMemoryStorageCSFactory; } /** diff --git a/src/factory/node.js b/src/factory/node.js index d8141037a..07ecd973d 100644 --- a/src/factory/node.js +++ b/src/factory/node.js @@ -4,6 +4,7 @@ import { pushManagerFactory } from '@splitsoftware/splitio-commons/src/sync/stre import { pollingManagerSSFactory } from '@splitsoftware/splitio-commons/src/sync/polling/pollingManagerSS'; import { InRedisStorage } from '@splitsoftware/splitio-commons/src/storages/inRedis'; import { InMemoryStorageFactory } from '@splitsoftware/splitio-commons/src/storages/inMemory/InMemoryStorage'; +import { getSnapshot } from '@splitsoftware/splitio-commons/src/storages/dataLoader'; import { sdkManagerFactory } from '@splitsoftware/splitio-commons/src/sdkManager'; import { sdkClientMethodFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethod'; import { impressionObserverSSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverSS'; @@ -47,7 +48,17 @@ function getModules(settings) { impressionsObserverFactory: impressionObserverSSFactory, - filterAdapterFactory: bloomFilterFactory + filterAdapterFactory: bloomFilterFactory, + + extraProps: (params) => { + if (params.settings.mode !== CONSUMER_MODE) { + return { + getState(userKeys) { + return getSnapshot(params.storage, userKeys); + } + }; + } + } }; switch (settings.mode) { diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 1e30feddf..470a9c327 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '10.28.1-rc.2'; +export const packageVersion = '10.28.1-rc.3'; diff --git a/src/settings/storage/browser.js b/src/settings/storage/browser.js index 10a9e3eea..bcd644cce 100644 --- a/src/settings/storage/browser.js +++ b/src/settings/storage/browser.js @@ -1,36 +1,23 @@ import { isLocalStorageAvailable } from '@splitsoftware/splitio-commons/src/utils/env/isLocalStorageAvailable'; -import { LOCALHOST_MODE, STORAGE_MEMORY } from '@splitsoftware/splitio-commons/src/utils/constants'; +import { STORAGE_MEMORY } from '@splitsoftware/splitio-commons/src/utils/constants'; const STORAGE_LOCALSTORAGE = 'LOCALSTORAGE'; export function validateStorage(settings) { let { log, - mode, storage: { type, options = {}, prefix } = { type: STORAGE_MEMORY }, } = settings; - let __originalType; - - const fallbackToMemory = () => { - __originalType = type; - type = STORAGE_MEMORY; - }; - - // In localhost mode, fallback to Memory storage and track original type to emit SDK_READY_FROM_CACHE if corresponds. - // ATM, other mode settings (e.g., 'consumer') are ignored in client-side API, and so treated as standalone. - if (mode === LOCALHOST_MODE && type === STORAGE_LOCALSTORAGE) { - fallbackToMemory(); - } // If an invalid storage type is provided OR we want to use LOCALSTORAGE and // it's not available, fallback into MEMORY if (type !== STORAGE_MEMORY && type !== STORAGE_LOCALSTORAGE || type === STORAGE_LOCALSTORAGE && !isLocalStorageAvailable()) { - fallbackToMemory(); + type = STORAGE_MEMORY; log.error('Invalid or unavailable storage. Fallback into MEMORY storage'); } @@ -38,6 +25,5 @@ export function validateStorage(settings) { type, options, prefix, - __originalType }; } diff --git a/types/splitio.d.ts b/types/splitio.d.ts index 27a1dcade..9229cba3e 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -94,6 +94,7 @@ interface ISettings { options: Object, type: StorageType }, + readonly preloadedData?: SplitIO.PreloadedData, readonly urls: { events: string, sdk: string, @@ -953,6 +954,10 @@ declare namespace SplitIO { * @typedef {string} ConsentStatus */ type ConsentStatus = 'GRANTED' | 'DECLINED' | 'UNKNOWN'; + /** + * Defines the format of rollout plan data to preload on the factory storage (cache). + */ + type PreloadedData = Object; /** * Settings interface for SDK instances created on the browser * @interface IBrowserSettings @@ -1385,7 +1390,11 @@ declare namespace SplitIO { * @function manager * @returns {IManager} The manager instance. */ - manager(): IManager + manager(): IManager, + /** + * @TODO add description + */ + getState(): PreloadedData, } /** * This represents the interface for the SDK instance with synchronous storage. From aa5651da474253482dd1d223eab26d9b60b00a22 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 1 Oct 2024 21:17:59 -0300 Subject: [PATCH 02/13] Fix ts test --- ts-tests/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/ts-tests/index.ts b/ts-tests/index.ts index c7f84d29d..70c57e02d 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -163,7 +163,6 @@ browserSettings = { } }; // With sync settings should return ISDK, if settings have async storage it should return IAsyncSDK -SDK = SplitFactory(browserSettings); SDK = SplitFactory(nodeSettings); AsyncSDK = SplitFactory(asyncSettings); BrowserSDK = SplitFactory(browserSettings); From cc4a5a1ad4ae62c30c50efc2bd88a3fb315b9052 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 3 Oct 2024 10:35:12 -0300 Subject: [PATCH 03/13] Update ts test --- ts-tests/index.ts | 1 + types/splitio.d.ts | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 70c57e02d..f3f0a926b 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -195,6 +195,7 @@ SDK.settings.features = { 'split_x': 'on' }; // Browser // Client and Manager client = SDK.client(); manager = SDK.manager(); +manager = BrowserSDK.manager(); // Today async clients are only possible on Node. Shared client creation not available here. asyncClient = AsyncSDK.client(); asyncManager = AsyncSDK.manager(); diff --git a/types/splitio.d.ts b/types/splitio.d.ts index 9229cba3e..991685399 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -1120,6 +1120,10 @@ declare namespace SplitIO { */ prefix?: string }, + /** + * @TODO Add description. Should be inside storage? + */ + preloadedData?: SplitIO.PreloadedData, /** * List of URLs that the SDK will use as base for it's synchronization functionalities, applicable only when running as standalone. * Do not change these settings unless you're working an advanced use case, like connecting to the Split proxy. @@ -1394,7 +1398,7 @@ declare namespace SplitIO { /** * @TODO add description */ - getState(): PreloadedData, + getState(keys?: SplitKey[]): PreloadedData, } /** * This represents the interface for the SDK instance with synchronous storage. @@ -1416,6 +1420,12 @@ declare namespace SplitIO { * @returns {IBrowserClient} The client instance. */ client(key: SplitKey, trafficType?: string): IBrowserClient + /** + * Returns a manager instance of the SDK to explore available information. + * @function manager + * @returns {IManager} The manager instance. + */ + manager(): IManager, /** * User consent API. * @property UserConsent From 58f55942df3db87c37edba029bf3d1a783e4f419 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 3 Oct 2024 12:27:18 -0300 Subject: [PATCH 04/13] Upgrade JS-commons with SdkFactory with init method --- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- .../browserSuites/push-fallback.spec.js | 4 ++-- src/settings/defaults/version.js | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 75be96c43..b510d72d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.3", + "version": "10.28.1-rc.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.3", + "version": "10.28.1-rc.4", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "1.17.1-rc.2", + "@splitsoftware/splitio-commons": "1.17.1-rc.3", "@types/google.analytics": "0.0.40", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", @@ -872,9 +872,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "1.17.1-rc.2", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.2.tgz", - "integrity": "sha512-ItqKJbUvHsR5Ff6sGjJFlGCcTrQHve9eObISaHOXGPsEaMCRdke8rhQh/bo4L8W2nn5YaY4DbuXJ9w59PA1khQ==", + "version": "1.17.1-rc.3", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.3.tgz", + "integrity": "sha512-cPjTdDtYHejjefNvyNUZrvhYSwe6ElWoCdU5l05XmMMHv4TJiDVWMP3opes6FulI0hYKjC6za0gqlR3H+kXEUg==", "dependencies": { "tslib": "^2.3.1" }, @@ -8528,9 +8528,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "1.17.1-rc.2", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.2.tgz", - "integrity": "sha512-ItqKJbUvHsR5Ff6sGjJFlGCcTrQHve9eObISaHOXGPsEaMCRdke8rhQh/bo4L8W2nn5YaY4DbuXJ9w59PA1khQ==", + "version": "1.17.1-rc.3", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.1-rc.3.tgz", + "integrity": "sha512-cPjTdDtYHejjefNvyNUZrvhYSwe6ElWoCdU5l05XmMMHv4TJiDVWMP3opes6FulI0hYKjC6za0gqlR3H+kXEUg==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index f8b6025ee..2193414df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "10.28.1-rc.3", + "version": "10.28.1-rc.4", "description": "Split SDK", "files": [ "README.md", @@ -40,7 +40,7 @@ "node": ">=6" }, "dependencies": { - "@splitsoftware/splitio-commons": "1.17.1-rc.2", + "@splitsoftware/splitio-commons": "1.17.1-rc.3", "@types/google.analytics": "0.0.40", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", diff --git a/src/__tests__/browserSuites/push-fallback.spec.js b/src/__tests__/browserSuites/push-fallback.spec.js index dc8df88b9..35827c465 100644 --- a/src/__tests__/browserSuites/push-fallback.spec.js +++ b/src/__tests__/browserSuites/push-fallback.spec.js @@ -287,12 +287,12 @@ export function testFallback(fetchMock, assert) { // Periodic fetch due to polling (memberships is not fetched due to smart pausing) fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=1457552649999'), function () { const lapse = Date.now() - start; - assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate), 'fetch due to fourth fallback to polling'); + assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate, 100), 'fetch due to fourth fallback to polling'); return { status: 200, body: splitChangesMock3 }; }); fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=1457552669999'), function () { const lapse = Date.now() - start; - assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate * 2), 'fetch due to fourth fallback to polling'); + assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate * 2, 100), 'fetch due to fourth fallback to polling'); return { status: 200, body: { splits: [], since: 1457552669999, till: 1457552669999 } }; }); diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 470a9c327..384a95183 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '10.28.1-rc.3'; +export const packageVersion = '10.28.1-rc.4'; From 0107c1c7aa1a0cfef5f4f367a79e12cfb7bcb30c Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 4 Oct 2024 16:35:02 -0300 Subject: [PATCH 05/13] Add tests for lazy init --- CHANGES.txt | 2 + src/__tests__/nodeSuites/lazy-init.spec.js | 89 ++++++++++++++++++++++ src/__tests__/online/node.spec.js | 9 ++- 3 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 src/__tests__/nodeSuites/lazy-init.spec.js diff --git a/CHANGES.txt b/CHANGES.txt index f5569d556..337575965 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,6 @@ 10.29.0 (September XX, 2024) + - Added `factory.getState()` method for standalone server-side SDKs, which returns the rollout plan snapshot from the storage. + - Added `preloadedData` configuration option for standalone client-side SDKs, which allows preloading the SDK storage with a snapshot of the rollout plan. - Added `factory.destroy()` method, which invokes the `destroy` method on all SDK clients created by the factory. - Updated @splitsoftware/splitio-commons package to version 1.18.0 that includes minor updates: - Added support for targeting rules based on large segments for browsers. diff --git a/src/__tests__/nodeSuites/lazy-init.spec.js b/src/__tests__/nodeSuites/lazy-init.spec.js new file mode 100644 index 000000000..68e92e8f5 --- /dev/null +++ b/src/__tests__/nodeSuites/lazy-init.spec.js @@ -0,0 +1,89 @@ +import { SplitFactory as SplitFactorySS } from '../../factory/node'; +import { SplitFactory as SplitFactoryCS } from '../../factory/browser'; + +// Tests should finish without dangling timers or requests +export default function (settings, fetchMock, t) { + + t.test('Server-side', async (assert) => { + let splitio; + + for (let i = 0; i < 100; i++) { + splitio = SplitFactorySS({ + core: { + authorizationKey: 'fake-token-' + i, + }, + urls: { + sdk: 'https://not-called/api', + events: 'https://not-called/api', + auth: 'https://not-called/api', + } + }, (modules) => { + modules.lazyInit = true; + }); + + const manager = splitio.manager(); + assert.deepEqual(manager.names(), [], 'We should not have done any request yet'); + + const client = splitio.client(); + assert.equal(client.getTreatment('user-1', 'split_test'), 'control', 'We should get control'); + assert.equal(client.track('user-1', 'user', 'my_event'), true, 'We should track the event'); + } + + fetchMock.getOnce('https://not-called/api/splitChanges?s=1.1&since=-1', { status: 200, body: { splits: [], since: -1, till: 1457552620999 } }); + fetchMock.getOnce('https://not-called/api/splitChanges?s=1.1&since=1457552620999', { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } }); + fetchMock.postOnce('https://not-called/api/testImpressions/bulk', 200); + fetchMock.postOnce('https://not-called/api/events/bulk', 200); + + splitio.init(); + await splitio.client().ready(); + assert.true(splitio.client().__getStatus().isReady, 'Split SDK is ready'); + await splitio.destroy(); + + assert.end(); + }); + + t.test('Client-side', async (assert) => { + let splitio; + + for (let i = 0; i < 100; i++) { + splitio = SplitFactoryCS({ + core: { + authorizationKey: 'fake-token-' + i, + key: 'user-' + i, + }, + urls: { + sdk: 'https://not-called/api', + events: 'https://not-called/api', + auth: 'https://not-called/api', + } + }, (modules) => { + modules.lazyInit = true; + }); + + const manager = splitio.manager(); + assert.deepEqual(manager.names(), [], 'We should not have done any request yet'); + + const client = splitio.client(); + assert.equal(client.getTreatment('split_test'), 'control', 'We should get control'); + assert.equal(client.track('user', 'my_event'), true, 'We should track the event'); + + const otherClient = splitio.client('other-user'); + assert.equal(otherClient.getTreatment('split_test'), 'control', 'We should get control'); + assert.equal(otherClient.track('user', 'my_event'), true, 'We should track the event'); + } + + fetchMock.getOnce('https://not-called/api/splitChanges?s=1.2&since=-1', { status: 200, body: { splits: [], since: -1, till: 1457552620999 } }); + fetchMock.getOnce('https://not-called/api/splitChanges?s=1.2&since=1457552620999', { status: 200, body: { splits: [], since: 1457552620999, till: 1457552620999 } }); + fetchMock.getOnce('https://not-called/api/memberships/user-99', { status: 200, body: {} }); + fetchMock.getOnce('https://not-called/api/memberships/other-user', { status: 200, body: {} }); + fetchMock.postOnce('https://not-called/api/testImpressions/bulk', 200); + fetchMock.postOnce('https://not-called/api/events/bulk', 200); + + splitio.init(); + await splitio.client().ready(); + assert.true(splitio.client().__getStatus().isReady, 'Split SDK is ready'); + await splitio.destroy(); + + assert.end(); + }); +} diff --git a/src/__tests__/online/node.spec.js b/src/__tests__/online/node.spec.js index 94ca9d830..a3e4fcac7 100644 --- a/src/__tests__/online/node.spec.js +++ b/src/__tests__/online/node.spec.js @@ -3,6 +3,9 @@ import fetchMock from '../testUtils/nodeFetchMock'; import { url } from '../testUtils'; import { settingsFactory } from '../../settings/node'; +import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; +import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; + import evaluationsSuite from '../nodeSuites/evaluations.spec'; import evaluationsSemverSuite from '../nodeSuites/evaluations-semver.spec'; import eventsSuite from '../nodeSuites/events.spec'; @@ -18,10 +21,8 @@ import ipAddressesSettingDebug from '../nodeSuites/ip-addresses-setting.debug.sp import readinessSuite from '../nodeSuites/readiness.spec'; import readyPromiseSuite from '../nodeSuites/ready-promise.spec'; import { fetchSpecificSplits, fetchSpecificSplitsForFlagSets } from '../nodeSuites/fetch-specific-splits.spec'; - -import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; -import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; import flagSets from '../nodeSuites/flag-sets.spec'; +import lazyInitSuite from '../nodeSuites/lazy-init.spec'; const config = { core: { @@ -94,5 +95,7 @@ tape('## Node JS - E2E CI Tests ##', async function (assert) { /* Validate flag sets */ assert.test('E2E / Flag sets', flagSets.bind(null, fetchMock)); + assert.test('E2E / SplitFactory with lazy init', lazyInitSuite.bind(null, settings, fetchMock)); + assert.end(); }); From 6c485bb13434cd84d77a87c2257f722770dde1a1 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 18 Oct 2024 16:57:48 -0300 Subject: [PATCH 06/13] Fixes --- .../browserSuites/push-fallback.spec.js | 4 ++-- src/__tests__/offline/browser.spec.js | 2 ++ src/settings/storage/browser.js | 18 ++++++++++++++++-- types/splitio.d.ts | 12 ------------ 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/__tests__/browserSuites/push-fallback.spec.js b/src/__tests__/browserSuites/push-fallback.spec.js index 35827c465..dc8df88b9 100644 --- a/src/__tests__/browserSuites/push-fallback.spec.js +++ b/src/__tests__/browserSuites/push-fallback.spec.js @@ -287,12 +287,12 @@ export function testFallback(fetchMock, assert) { // Periodic fetch due to polling (memberships is not fetched due to smart pausing) fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=1457552649999'), function () { const lapse = Date.now() - start; - assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate, 100), 'fetch due to fourth fallback to polling'); + assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate), 'fetch due to fourth fallback to polling'); return { status: 200, body: splitChangesMock3 }; }); fetchMock.getOnce(url(settings, '/splitChanges?s=1.2&since=1457552669999'), function () { const lapse = Date.now() - start; - assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate * 2, 100), 'fetch due to fourth fallback to polling'); + assert.true(nearlyEqual(lapse, MILLIS_STREAMING_DISABLED_CONTROL + settings.scheduler.featuresRefreshRate * 2), 'fetch due to fourth fallback to polling'); return { status: 200, body: { splits: [], since: 1457552669999, till: 1457552669999 } }; }); diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index 5c99786c0..bce2020eb 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -112,6 +112,8 @@ tape('Browser offline mode', function (assert) { }); const sdkReadyFromCache = (client) => () => { + assert.equal(factory.settings.storage.type, 'MEMORY', 'In localhost mode, storage must fallback to memory storage'); + const clientStatus = client.__getStatus(); assert.equal(clientStatus.isReadyFromCache, true, 'If ready from cache, READY_FROM_CACHE status must be true'); assert.equal(clientStatus.isReady, false, 'READY status must not be set before READY_FROM_CACHE'); diff --git a/src/settings/storage/browser.js b/src/settings/storage/browser.js index bcd644cce..10a9e3eea 100644 --- a/src/settings/storage/browser.js +++ b/src/settings/storage/browser.js @@ -1,23 +1,36 @@ import { isLocalStorageAvailable } from '@splitsoftware/splitio-commons/src/utils/env/isLocalStorageAvailable'; -import { STORAGE_MEMORY } from '@splitsoftware/splitio-commons/src/utils/constants'; +import { LOCALHOST_MODE, STORAGE_MEMORY } from '@splitsoftware/splitio-commons/src/utils/constants'; const STORAGE_LOCALSTORAGE = 'LOCALSTORAGE'; export function validateStorage(settings) { let { log, + mode, storage: { type, options = {}, prefix } = { type: STORAGE_MEMORY }, } = settings; + let __originalType; + + const fallbackToMemory = () => { + __originalType = type; + type = STORAGE_MEMORY; + }; + + // In localhost mode, fallback to Memory storage and track original type to emit SDK_READY_FROM_CACHE if corresponds. + // ATM, other mode settings (e.g., 'consumer') are ignored in client-side API, and so treated as standalone. + if (mode === LOCALHOST_MODE && type === STORAGE_LOCALSTORAGE) { + fallbackToMemory(); + } // If an invalid storage type is provided OR we want to use LOCALSTORAGE and // it's not available, fallback into MEMORY if (type !== STORAGE_MEMORY && type !== STORAGE_LOCALSTORAGE || type === STORAGE_LOCALSTORAGE && !isLocalStorageAvailable()) { - type = STORAGE_MEMORY; + fallbackToMemory(); log.error('Invalid or unavailable storage. Fallback into MEMORY storage'); } @@ -25,5 +38,6 @@ export function validateStorage(settings) { type, options, prefix, + __originalType }; } diff --git a/types/splitio.d.ts b/types/splitio.d.ts index ec0e0a9ba..16f7f330c 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -1261,18 +1261,6 @@ declare namespace SplitIO { * @returns {IManager} The manager instance. */ manager(): IManager, - /** - * Returns a manager instance of the SDK to explore available information. - * @function manager - * @returns {IManager} The manager instance. - */ - manager(): IManager, - /** - * Returns a manager instance of the SDK to explore available information. - * @function manager - * @returns {IManager} The manager instance. - */ - manager(): IManager, /** * User consent API. * @property UserConsent From 0bf00837c4b3b5c58ccb88a2613f68f4d3604911 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 18 Oct 2024 18:23:42 -0300 Subject: [PATCH 07/13] prepare rc --- package-lock.json | 14 +++++++------- package.json | 2 +- src/__tests__/nodeSuites/evaluations.spec.js | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index f0c4ffe5e..f97c9bdbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "11.0.0-rc.1", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.1", + "@splitsoftware/splitio-commons": "2.0.0-rc.2", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", @@ -870,9 +870,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.1.tgz", - "integrity": "sha512-tjIDgNnrwOKphYtWKNv0HOU7LJQ+0ljgbmknhi3H7MDptvnwG7o8DHKtoAtuljcEqVjosLmhgzOxzTY9MGZruw==", + "version": "2.0.0-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.2.tgz", + "integrity": "sha512-QfCg2D5hjg+iuQiEYpsMEjtJ/dcYUsbcXJbvj7BH9t9DfVEplCv09oJcsC6CTFTSeA958y7yqe2EvTy/HVSM5g==", "dependencies": { "tslib": "^2.3.1" }, @@ -8587,9 +8587,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.0.0-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.1.tgz", - "integrity": "sha512-tjIDgNnrwOKphYtWKNv0HOU7LJQ+0ljgbmknhi3H7MDptvnwG7o8DHKtoAtuljcEqVjosLmhgzOxzTY9MGZruw==", + "version": "2.0.0-rc.2", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.0-rc.2.tgz", + "integrity": "sha512-QfCg2D5hjg+iuQiEYpsMEjtJ/dcYUsbcXJbvj7BH9t9DfVEplCv09oJcsC6CTFTSeA958y7yqe2EvTy/HVSM5g==", "requires": { "tslib": "^2.3.1" } diff --git a/package.json b/package.json index 8a0c2cd88..d01506afe 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.0.0-rc.1", + "@splitsoftware/splitio-commons": "2.0.0-rc.2", "@types/ioredis": "^4.28.0", "bloom-filters": "^3.0.0", "ioredis": "^4.28.0", diff --git a/src/__tests__/nodeSuites/evaluations.spec.js b/src/__tests__/nodeSuites/evaluations.spec.js index d870d2526..87b53536c 100644 --- a/src/__tests__/nodeSuites/evaluations.spec.js +++ b/src/__tests__/nodeSuites/evaluations.spec.js @@ -271,12 +271,12 @@ export default async function (config, key, assert) { assert.equal(serverSideState.since, 1457552620999); assert.equal(serverSideState.splitsData.length, splitChangesMock1.splits.length); assert.deepEqual(serverSideState.segmentsData, { employees: [], splitters: [], developers: [] }); - assert.deepEqual(serverSideState.mySegmentsData, undefined); + assert.deepEqual(serverSideState.membershipsData, undefined); const clientSideState = splitio.getState(['user1']); assert.equal(clientSideState.since, 1457552620999); assert.equal(clientSideState.splitsData.length, splitChangesMock1.splits.length); assert.deepEqual(clientSideState.segmentsData, undefined); - assert.deepEqual(clientSideState.mySegmentsData, { user1: [] }); + assert.deepEqual(clientSideState.membershipsData, { user1: { ms: { k: [] }, ls: { k: [] } } }); await client.destroy(); From 80b74d00c9dd565d0ca4a91f4e7f12bd5c60ea10 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 22 Oct 2024 14:37:02 -0300 Subject: [PATCH 08/13] Update type declarations for the factory prop in React SDK --- types/splitio.d.ts | 88 ++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/types/splitio.d.ts b/types/splitio.d.ts index 596fd9a80..43898742b 100644 --- a/types/splitio.d.ts +++ b/types/splitio.d.ts @@ -8,28 +8,6 @@ import { RequestOptions } from "http"; export as namespace SplitIO; export = SplitIO; -/** - * NodeJS.EventEmitter interface - * @see {@link https://nodejs.org/api/events.html} - */ -interface EventEmitter { - addListener(event: string | symbol, listener: (...args: any[]) => void): this; - on(event: string | symbol, listener: (...args: any[]) => void): this; - once(event: string | symbol, listener: (...args: any[]) => void): this; - removeListener(event: string | symbol, listener: (...args: any[]) => void): this; - off(event: string | symbol, listener: (...args: any[]) => void): this; - removeAllListeners(event?: string | symbol): this; - setMaxListeners(n: number): this; - getMaxListeners(): number; - listeners(event: string | symbol): Function[]; - rawListeners(event: string | symbol): Function[]; - emit(event: string | symbol, ...args: any[]): boolean; - listenerCount(type: string | symbol): number; - // Added in Node 6... - prependListener(event: string | symbol, listener: (...args: any[]) => void): this; - prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; - eventNames(): Array; -} /** * @typedef {Object} EventConsts * @property {string} SDK_READY The ready event. @@ -429,10 +407,9 @@ interface INodeBasicSettings extends ISharedSettings { } /** * Common API for entities that expose status handlers. - * @interface IStatusInterface - * @extends EventEmitter + * @typedef IStatusInterface */ -interface IStatusInterface extends EventEmitter { +type IStatusInterface = TEventEmitter & { /** * Constant object containing the SDK events for you to use. * @property {EventConsts} Event @@ -460,10 +437,9 @@ interface IStatusInterface extends EventEmitter { } /** * Common definitions between clients for different environments interface. - * @interface IBasicClient - * @extends IStatusInterface + * @typedef IBasicClient */ -interface IBasicClient extends IStatusInterface { +type IBasicClient = IStatusInterface & { /** * Destroys the client instance. * In 'standalone' mode, this method will flush any pending impressions and events, and stop the synchronization of feature flag definitions with the backend. @@ -502,6 +478,42 @@ interface IBasicSDK { * For the SDK package information see {@link https://www.npmjs.com/package/@splitsoftware/splitio} */ declare namespace SplitIO { + /** + * EventEmitter interface based on a subset of the NodeJS.EventEmitter methods. Used by the JavaScript Browser SDK and React Native SDK. + */ + interface IEventEmitter { + addListener(event: string, listener: (...args: any[]) => void): this + on(event: string, listener: (...args: any[]) => void): this + once(event: string, listener: (...args: any[]) => void): this + removeListener(event: string, listener: (...args: any[]) => void): this + off(event: string, listener: (...args: any[]) => void): this + removeAllListeners(event?: string): this + emit(event: string, ...args: any[]): boolean + } + + /** + * NodeJS.EventEmitter interface. Used by the JavaScript SDK for both flavours: server-side (NodeJS) and client-side (Browser). + * + * @see {@link https://nodejs.org/api/events.html} + */ + interface EventEmitter extends IEventEmitter { + addListener(event: string | symbol, listener: (...args: any[]) => void): this; + on(event: string | symbol, listener: (...args: any[]) => void): this; + once(event: string | symbol, listener: (...args: any[]) => void): this; + removeListener(event: string | symbol, listener: (...args: any[]) => void): this; + off(event: string | symbol, listener: (...args: any[]) => void): this; + removeAllListeners(event?: string | symbol): this; + emit(event: string | symbol, ...args: any[]): boolean; + setMaxListeners(n: number): this; + getMaxListeners(): number; + listeners(event: string | symbol): Function[]; + rawListeners(event: string | symbol): Function[]; + listenerCount(type: string | symbol): number; + // Added in Node 6... + prependListener(event: string | symbol, listener: (...args: any[]) => void): this; + prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; + eventNames(): Array; + } /** * Feature flag treatment value, returned by getTreatment. * @typedef {string} Treatment @@ -1224,30 +1236,30 @@ declare namespace SplitIO { manager(): IManager } /** - * This represents the interface for the SDK instance with synchronous storage. + * This represents the interface for the SDK instance with synchronous storage and client-side API. * @interface IBrowserSDK * @extends IBasicSDK */ - interface IBrowserSDK extends IBasicSDK { + interface IBrowserSDK extends IBasicSDK { /** * Returns the default client instance of the SDK. * @function client * @returns {IBrowserClient} The client instance. */ - client(): IBrowserClient, + client(): IBrowserClient, /** * Returns a shared client of the SDK. * @function client * @param {SplitKey} key The key for the new client instance. * @returns {IBrowserClient} The client instance. */ - client(key: SplitKey): IBrowserClient + client(key: SplitKey): IBrowserClient /** * Returns a manager instance of the SDK to explore available information. * @function manager * @returns {IManager} The manager instance. */ - manager(): IManager, + manager(): IManager, /** * User consent API. * @property UserConsent @@ -1379,10 +1391,9 @@ declare namespace SplitIO { * This represents the interface for the Client instance on client-side, where the user key is bound to the instance on creation and does not need to be provided on each method call. * This interface is the default when importing the SDK in the Browser, or when importing the 'client' sub-package (e.g., `import { SplitFactory } from '@splitsoftware/splitio/client'`). * - * @interface IBrowserClient - * @extends IBasicClient + * @typedef IBrowserClient */ - interface IBrowserClient extends IBasicClient { + type IBrowserClient = IBasicClient & { /** * Returns a Treatment value, which is the treatment string for the given feature. * @@ -1613,10 +1624,9 @@ declare namespace SplitIO { } /** * Representation of a manager instance with synchronous storage of the SDK. - * @interface IManager - * @extends IStatusInterface + * @typedef IManager */ - interface IManager extends IStatusInterface { + type IManager = IStatusInterface & { /** * Get the array of feature flag names. * @function names From 9f6e3e38d3d59444d436d8fd697543a712143f54 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 22 Oct 2024 16:02:23 -0300 Subject: [PATCH 09/13] rc --- package-lock.json | 4 ++-- package.json | 2 +- src/settings/defaults/version.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index f97c9bdbf..095e5bd70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.1", + "version": "11.0.0-rc.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.1", + "version": "11.0.0-rc.2", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.0.0-rc.2", diff --git a/package.json b/package.json index d01506afe..e7028d5c4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.0.0-rc.1", + "version": "11.0.0-rc.2", "description": "Split SDK", "files": [ "README.md", diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index b631429a8..51ecb327e 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.0.0-rc.1'; +export const packageVersion = '11.0.0-rc.2'; From da48da4a355b213b315233259adfe49347c76642 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Tue, 26 Aug 2025 09:52:13 -0300 Subject: [PATCH 10/13] rc --- CHANGES.txt | 3 +- package-lock.json | 727 +++++++++++++----- package.json | 6 +- .../browserSuites/ready-from-cache.spec.js | 5 +- src/__tests__/nodeSuites/evaluations.spec.js | 18 +- src/factory/node.js | 6 +- src/settings/defaults/version.js | 2 +- 7 files changed, 548 insertions(+), 219 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 88c84fd05..54afaabb7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,5 @@ 11.5.0 (August XX, 2025) - - Added support for targeting rules based on large segments for browsers. - - Added `factory.getState()` method for standalone server-side SDKs, which returns the rollout plan snapshot from the storage. + - Added `factory.getCache()` method for standalone server-side SDKs, which returns the rollout plan snapshot from the storage. - Added `preloadedData` configuration option for standalone client-side SDKs, which allows preloading the SDK storage with a snapshot of the rollout plan. 11.4.1 (June 3, 2025) diff --git a/package-lock.json b/package-lock.json index 64194baa7..20533ce2d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.4.1", + "version": "11.5.0-rc.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.4.1", + "version": "11.5.0-rc.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.4.1", + "@splitsoftware/splitio-commons": "2.5.0-rc.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.4.1.tgz", - "integrity": "sha512-VcbWpPykfx19LTJ0yeZbV0u3PUIt8MuiZ2a8zqkNf9KnDnhau/XxS/ctoO5jYrg4Nk2rCi0fpt1TkTstqzbaYA==", + "version": "2.5.0-rc.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.0.tgz", + "integrity": "sha512-XqWSH2za4lkeeZCAk2hQIi6XrAcEGqBAdKRvZXFzRRSjQUZy3OLEqQOC4RaFuEmnOilhYSWtu1kchbXrr+4YiQ==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -888,10 +888,14 @@ "dev": true }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -1099,10 +1103,11 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1345,16 +1350,47 @@ } }, "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -1472,13 +1508,17 @@ } }, "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/cliui": { @@ -2069,6 +2109,21 @@ "ignored": "bin/ignored" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/duplexer3": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", @@ -2253,13 +2308,11 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2279,6 +2332,35 @@ "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "dev": true }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -2899,22 +2981,32 @@ } }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -3007,16 +3099,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3025,6 +3123,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -3129,12 +3241,13 @@ } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3194,23 +3307,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3219,12 +3321,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -3805,16 +3908,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", - "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -4174,6 +4274,16 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -4819,21 +4929,57 @@ "dev": true }, "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", + "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", "dev": true, + "license": "MIT", "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "create-hash": "~1.1.3", + "create-hmac": "^1.1.7", + "ripemd160": "=2.0.1", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.11", + "to-buffer": "^1.2.0" }, "engines": { "node": ">=0.12" } }, + "node_modules/pbkdf2/node_modules/create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" + } + }, + "node_modules/pbkdf2/node_modules/hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1" + } + }, + "node_modules/pbkdf2/node_modules/ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^2.0.0", + "inherits": "^2.0.1" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -4922,6 +5068,16 @@ "node": ">=8" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5805,16 +5961,24 @@ "dev": true }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "dev": true, + "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shallow-clone": { @@ -6510,17 +6674,37 @@ } }, "node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-buffer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", + "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", "dev": true, + "license": "MIT", "dependencies": { - "rimraf": "^3.0.0" + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" }, "engines": { - "node": ">=8.17.0" + "node": ">= 0.4" } }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6685,6 +6869,21 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/typescript": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", @@ -7118,17 +7317,19 @@ "dev": true }, "node_modules/which-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", - "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7539,9 +7740,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.4.1.tgz", - "integrity": "sha512-VcbWpPykfx19LTJ0yeZbV0u3PUIt8MuiZ2a8zqkNf9KnDnhau/XxS/ctoO5jYrg4Nk2rCi0fpt1TkTstqzbaYA==", + "version": "2.5.0-rc.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.0.tgz", + "integrity": "sha512-XqWSH2za4lkeeZCAk2hQIi6XrAcEGqBAdKRvZXFzRRSjQUZy3OLEqQOC4RaFuEmnOilhYSWtu1kchbXrr+4YiQ==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -8007,10 +8208,13 @@ "dev": true }, "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "babel-polyfill": { "version": "6.26.0", @@ -8172,9 +8376,9 @@ } }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -8375,16 +8579,35 @@ "dev": true }, "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "requires": { + "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "set-function-length": "^1.2.2" + } + }, + "call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" } }, "callsites": { @@ -8455,13 +8678,13 @@ "dev": true }, "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" } }, "cliui": { @@ -8948,6 +9171,17 @@ "minimatch": "^3.0.4" } }, + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + } + }, "duplexer3": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", @@ -9098,13 +9332,10 @@ } }, "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.4" - } + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true }, "es-errors": { "version": "1.3.0", @@ -9118,6 +9349,27 @@ "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "dev": true }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" + } + }, + "es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + } + }, "es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -9598,22 +9850,24 @@ "dev": true }, "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "requires": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" } }, "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", "dev": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, @@ -9678,16 +9932,31 @@ "dev": true }, "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "requires": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" } }, "get-stream": { @@ -9766,13 +10035,10 @@ } }, "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true }, "graceful-fs": { "version": "4.2.11", @@ -9816,25 +10082,19 @@ "es-define-property": "^1.0.0" } }, - "has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true - }, "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" } }, "hash-base": { @@ -10223,16 +10483,12 @@ } }, "is-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz", - "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.16" } }, "is-weakref": { @@ -10528,6 +10784,12 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -11051,16 +11313,50 @@ "dev": true }, "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.3.tgz", + "integrity": "sha512-wfRLBZ0feWRhCIkoMB6ete7czJcnNnqRpcoWQBLqatqXXmelSRqfdDK4F3u9T2s2cXas/hQJcryI/4lAL+XTlA==", "dev": true, "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "create-hash": "~1.1.3", + "create-hmac": "^1.1.7", + "ripemd160": "=2.0.1", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.11", + "to-buffer": "^1.2.0" + }, + "dependencies": { + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha512-snRpch/kwQhcdlnZKYanNF1m0RDlrCdSKQaH87w1FCFPVPNCQ/Il9QJKAX2jVBZddRdaHBMC+zXa9Gw9tmkNUA==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "sha.js": "^2.4.0" + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha512-0TROgQ1/SxE6KmxWSvXHvRj90/Xo1JvZShofnYF+f6ZsGtR4eES7WfrQzPalmyagfKZCXpVnitiRebZulWsbiw==", + "dev": true, + "requires": { + "inherits": "^2.0.1" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha512-J7f4wutN8mdbV08MJnXibYpCOPHR+yzy+iQ/AsjMv2j8cLavQ8VGagDFUwwTAdF8FmRKVeNpbTTEwNHCW1g94w==", + "dev": true, + "requires": { + "hash-base": "^2.0.0", + "inherits": "^2.0.1" + } + } } }, "pend": { @@ -11129,6 +11425,12 @@ } } }, + "possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -11795,13 +12097,14 @@ "dev": true }, "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" } }, "shallow-clone": { @@ -12336,12 +12639,28 @@ } }, "tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true + }, + "to-buffer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz", + "integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==", "dev": true, "requires": { - "rimraf": "^3.0.0" + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, "to-regex-range": { @@ -12457,6 +12776,17 @@ "mime-types": "~2.1.24" } }, + "typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + } + }, "typescript": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", @@ -12750,17 +13080,18 @@ "dev": true }, "which-typed-array": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz", - "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-abstract": "^1.20.0", - "for-each": "^0.3.3", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.9" + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" } }, "wildcard": { diff --git a/package.json b/package.json index 1eea899a8..66366dd75 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.4.1", + "version": "11.5.0-rc.0", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.4.1", + "@splitsoftware/splitio-commons": "2.5.0-rc.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -111,7 +111,7 @@ "test-ts-decls": "tsc --build ts-tests", "test": "npm run test-node && npm run test-browser", "all": "npm run check && npm run build && npm run test-ts-decls && npm run test", - "publish:rc": "npm run check && npm run build && npm publish --tag canary", + "publish:rc": "npm run check && npm run build && npm publish --tag rc", "publish:stable": "npm run check && npm run build && npm publish" }, "greenkeeper": { diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 4df088b64..bfaa57bb5 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -480,8 +480,7 @@ export default function (fetchMock, assert) { t.plan(5); - fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=25', { status: 200, body: { ...splitChangesMock1, since: 25 } }); - fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.2&since=1457552620999', { status: 200, body: splitChangesMock2 }); + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.3&since=25&rbSince=-1', { status: 200, body: { ff: { ...splitChangesMock1.ff, s: 25 } } }); fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: membershipsNicolas }); fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas2%40split.io', { status: 200, body: { 'ms': {} } }); @@ -496,7 +495,7 @@ export default function (fetchMock, assert) { urls: testUrls, preloadedData: { since: 25, - splitsData: [JSON.parse(alwaysOnSplitInverted)] + flags: [JSON.parse(alwaysOnSplitInverted)] } }); diff --git a/src/__tests__/nodeSuites/evaluations.spec.js b/src/__tests__/nodeSuites/evaluations.spec.js index a26a4c0ef..5085aabc2 100644 --- a/src/__tests__/nodeSuites/evaluations.spec.js +++ b/src/__tests__/nodeSuites/evaluations.spec.js @@ -281,17 +281,17 @@ export default async function (config, key, assert) { getTreatmentsTests(client, i); getTreatmentsWithConfigTests(client, i); - // getState method - const serverSideState = splitio.getState(); + // getCache method + const serverSideState = splitio.getCache(); assert.equal(serverSideState.since, 1457552620999); - assert.equal(serverSideState.splitsData.length, splitChangesMock1.splits.length); - assert.deepEqual(serverSideState.segmentsData, { employees: [], splitters: [], developers: [] }); - assert.deepEqual(serverSideState.membershipsData, undefined); - const clientSideState = splitio.getState(['user1']); + assert.equal(serverSideState.flags.length, splitChangesMock1.ff.d.length); + assert.deepEqual(serverSideState.segments, { employees: [], splitters: [], developers: [], segment_excluded_by_rbs: ['emi@split.io'] }); + assert.deepEqual(serverSideState.memberships, undefined); + const clientSideState = splitio.getCache(['user1']); assert.equal(clientSideState.since, 1457552620999); - assert.equal(clientSideState.splitsData.length, splitChangesMock1.splits.length); - assert.deepEqual(clientSideState.segmentsData, undefined); - assert.deepEqual(clientSideState.membershipsData, { user1: { ms: { k: [] }, ls: { k: [] } } }); + assert.equal(clientSideState.flags.length, splitChangesMock1.ff.d.length); + assert.deepEqual(clientSideState.segments, undefined); + assert.deepEqual(clientSideState.memberships, { user1: { ms: { k: [] }, ls: { k: [] } } }); await client.destroy(); diff --git a/src/factory/node.js b/src/factory/node.js index 1a7b03f9b..9bae4ea16 100644 --- a/src/factory/node.js +++ b/src/factory/node.js @@ -4,7 +4,7 @@ import { pushManagerFactory } from '@splitsoftware/splitio-commons/src/sync/stre import { pollingManagerSSFactory } from '@splitsoftware/splitio-commons/src/sync/polling/pollingManagerSS'; import { InRedisStorage } from '@splitsoftware/splitio-commons/src/storages/inRedis'; import { InMemoryStorageFactory } from '@splitsoftware/splitio-commons/src/storages/inMemory/InMemoryStorage'; -import { getSnapshot } from '@splitsoftware/splitio-commons/src/storages/dataLoader'; +import { getCache } from '@splitsoftware/splitio-commons/src/storages/dataLoader'; import { sdkManagerFactory } from '@splitsoftware/splitio-commons/src/sdkManager'; import { sdkClientMethodFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethod'; import { impressionObserverSSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverSS'; @@ -54,8 +54,8 @@ function getModules(settings) { extraProps: (params) => { if (params.settings.mode !== CONSUMER_MODE) { return { - getState(userKeys) { - return getSnapshot(params.storage, userKeys); + getCache(userKeys) { + return getCache(params.settings.log, params.storage, userKeys); } }; } diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index b0d629843..b1820cbf7 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.4.1'; +export const packageVersion = '11.5.0-rc.0'; From 34e0170fc78ef3179cdd45530797803c107027fb Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Thu, 4 Sep 2025 12:07:21 -0300 Subject: [PATCH 11/13] Update tests --- CHANGES.txt | 4 +- .../browserSuites/ready-from-cache.spec.js | 46 +++++++++++++++---- src/__tests__/nodeSuites/evaluations.spec.js | 34 +++++++++----- src/factory/node.js | 6 +-- ts-tests/index.ts | 5 ++ 5 files changed, 69 insertions(+), 26 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 54afaabb7..272491e60 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,6 @@ 11.5.0 (August XX, 2025) - - Added `factory.getCache()` method for standalone server-side SDKs, which returns the rollout plan snapshot from the storage. - - Added `preloadedData` configuration option for standalone client-side SDKs, which allows preloading the SDK storage with a snapshot of the rollout plan. + - Added `factory.getRolloutPlan()` method for standalone server-side SDKs, which returns the rollout plan snapshot from the storage. + - Added `initialRolloutPlan` configuration option for standalone client-side SDKs, which allows preloading the SDK storage with a snapshot of the rollout plan. 11.4.1 (June 3, 2025) - Updated @splitsoftware/splitio-commons package to version 2.4.1, which improves the Proxy fallback to flag spec version 1.2 by handling the case when the Proxy does not return an end-of-stream marker in 400 status code responses. diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index bfaa57bb5..7467421ee 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -20,6 +20,25 @@ const alwaysOnSplitInverted = JSON.stringify({ 'killed': false, 'defaultTreatment': 'off', 'conditions': [ + { + 'matcherGroup': { + 'combiner': 'AND', + 'matchers': [ + { + 'matcherType': 'IN_SEGMENT', + 'userDefinedSegmentMatcherData': { + 'segmentName': 'employees' + }, + } + ] + }, + 'partitions': [ + { + 'treatment': 'on', + 'size': 100 + } + ] + }, { 'matcherGroup': { 'combiner': 'AND', @@ -472,17 +491,17 @@ export default function (fetchMock, assert) { }); }); - assert.test(t => { // Testing when we start with preloaded data and MEMORY storage type (is ready from cache immediately) + assert.test(t => { // Testing when we start with initial rollout plan data and MEMORY storage type (is ready from cache immediately) const testUrls = { - sdk: 'https://sdk.baseurl/readyFromCacheWithPreloadedData', - events: 'https://events.baseurl/readyFromCacheWithPreloadedData' + sdk: 'https://sdk.baseurl/readyFromCacheWithInitialRolloutPlan', + events: 'https://events.baseurl/readyFromCacheWithInitialRolloutPlan' }; t.plan(5); fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.3&since=25&rbSince=-1', { status: 200, body: { ff: { ...splitChangesMock1.ff, s: 25 } } }); fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas%40split.io', { status: 200, body: membershipsNicolas }); - fetchMock.getOnce(testUrls.sdk + '/memberships/nicolas2%40split.io', { status: 200, body: { 'ms': {} } }); + fetchMock.getOnce(testUrls.sdk + '/memberships/emi%40split.io', { status: 200, body: { 'ms': {} } }); fetchMock.postOnce(testUrls.events + '/testImpressions/bulk', 200); fetchMock.postOnce(testUrls.events + '/testImpressions/count', 200); @@ -493,19 +512,26 @@ export default function (fetchMock, assert) { type: 'MEMORY', }, urls: testUrls, - preloadedData: { - since: 25, - flags: [JSON.parse(alwaysOnSplitInverted)] + initialRolloutPlan: { + splitChanges: { + ff: { + t: 25, + d: [JSON.parse(alwaysOnSplitInverted)] + } + }, + memberships: { + 'emi@split.io': { ms: { k: [{ n: 'employees' }] } } + } } }); const client = splitio.client(); - const client2 = splitio.client('nicolas2@split.io'); + const client2 = splitio.client('emi@split.io'); t.equal(client.__getStatus().isReadyFromCache, true, 'Client is ready from cache'); - t.equal(client.getTreatment('always_on'), 'off', 'It should evaluate treatments with data from cache instead of control due to Input Validation'); - t.equal(client2.getTreatment('always_on'), 'off', 'It should evaluate treatments with data from cache instead of control due to Input Validation'); + t.equal(client.getTreatment('always_on'), 'off', 'It should evaluate treatments with data from cache. Key without memberships'); + t.equal(client2.getTreatment('always_on'), 'on', 'It should evaluate treatments with data from cache. Key with memberships'); client.on(client.Event.SDK_READY_TIMED_OUT, () => { t.fail('It should not timeout in this scenario.'); diff --git a/src/__tests__/nodeSuites/evaluations.spec.js b/src/__tests__/nodeSuites/evaluations.spec.js index 5085aabc2..695e2a7a8 100644 --- a/src/__tests__/nodeSuites/evaluations.spec.js +++ b/src/__tests__/nodeSuites/evaluations.spec.js @@ -281,17 +281,29 @@ export default async function (config, key, assert) { getTreatmentsTests(client, i); getTreatmentsWithConfigTests(client, i); - // getCache method - const serverSideState = splitio.getCache(); - assert.equal(serverSideState.since, 1457552620999); - assert.equal(serverSideState.flags.length, splitChangesMock1.ff.d.length); - assert.deepEqual(serverSideState.segments, { employees: [], splitters: [], developers: [], segment_excluded_by_rbs: ['emi@split.io'] }); - assert.deepEqual(serverSideState.memberships, undefined); - const clientSideState = splitio.getCache(['user1']); - assert.equal(clientSideState.since, 1457552620999); - assert.equal(clientSideState.flags.length, splitChangesMock1.ff.d.length); - assert.deepEqual(clientSideState.segments, undefined); - assert.deepEqual(clientSideState.memberships, { user1: { ms: { k: [] }, ls: { k: [] } } }); + // getRolloutPlan method + const expectedRolloutPlan = { + splitChanges: splitChangesMock1, + segmentChanges: [ + { name: 'employees', added: [], removed: [], till: 1 }, + { name: 'splitters', added: [], removed: [], till: 1 }, + { name: 'developers', added: [], removed: [], till: 1 }, + { name: 'segment_excluded_by_rbs', added: ['emi@split.io'], removed: [], till: 1 } + ], + memberships: { 'emi@split.io': { ms: { k: [{ n: 'segment_excluded_by_rbs' }] }, ls: { k: [] } } } + }; + + const rolloutPlan = splitio.getRolloutPlan(); + assert.deepEqual(rolloutPlan, { ...expectedRolloutPlan, segmentChanges: undefined, memberships: undefined }); + + const rolloutPlanWithMemberships = splitio.getRolloutPlan({ keys: ['emi@split.io'] }); + assert.deepEqual(rolloutPlanWithMemberships, { ...expectedRolloutPlan, segmentChanges: undefined }); + + const rolloutPlanWithSegments = splitio.getRolloutPlan({ exposeSegments: true }); + assert.deepEqual(rolloutPlanWithSegments, { ...expectedRolloutPlan, memberships: undefined }); + + const rolloutPlanWithMembershipsAndSegments = splitio.getRolloutPlan({ keys: [{ matchingKey: 'emi@split.io', bucketingKey: 'bucketingKey' }], exposeSegments: true }); + assert.deepEqual(rolloutPlanWithMembershipsAndSegments, expectedRolloutPlan); await client.destroy(); diff --git a/src/factory/node.js b/src/factory/node.js index 9bae4ea16..fa712f58e 100644 --- a/src/factory/node.js +++ b/src/factory/node.js @@ -4,7 +4,7 @@ import { pushManagerFactory } from '@splitsoftware/splitio-commons/src/sync/stre import { pollingManagerSSFactory } from '@splitsoftware/splitio-commons/src/sync/polling/pollingManagerSS'; import { InRedisStorage } from '@splitsoftware/splitio-commons/src/storages/inRedis'; import { InMemoryStorageFactory } from '@splitsoftware/splitio-commons/src/storages/inMemory/InMemoryStorage'; -import { getCache } from '@splitsoftware/splitio-commons/src/storages/dataLoader'; +import { getRolloutPlan } from '@splitsoftware/splitio-commons/src/storages/dataLoader'; import { sdkManagerFactory } from '@splitsoftware/splitio-commons/src/sdkManager'; import { sdkClientMethodFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethod'; import { impressionObserverSSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverSS'; @@ -54,8 +54,8 @@ function getModules(settings) { extraProps: (params) => { if (params.settings.mode !== CONSUMER_MODE) { return { - getCache(userKeys) { - return getCache(params.settings.log, params.storage, userKeys); + getRolloutPlan(userKeys) { + return getRolloutPlan(params.settings.log, params.storage, userKeys); } }; } diff --git a/ts-tests/index.ts b/ts-tests/index.ts index 52ecade7e..ad9527b8a 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -687,3 +687,8 @@ let fullAsyncSettings: SplitIO.INodeAsyncSettings = { fullBrowserSettings.debug = 'ERROR'; fullNodeSettings.debug = 'WARN'; fullAsyncSettings.debug = 'INFO'; + +// Preload rollout plan +let rolloutPlanSnapshot: SplitIO.RolloutPlan = SDK.getRolloutPlan(); +rolloutPlanSnapshot = SDK.getRolloutPlan({ keys: ['key1', { matchingKey: 'key2', bucketingKey: 'bucketingKey' }], exposeSegments: true }); +browserSettings.initialRolloutPlan = rolloutPlanSnapshot; From 88be475c8ed5e5bf261bcc276535c30040f0fdf2 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 5 Sep 2025 16:20:31 -0300 Subject: [PATCH 12/13] rc --- CHANGES.txt | 2 +- package-lock.json | 18 +++--- package.json | 4 +- .../browserSuites/ready-from-cache.spec.js | 6 +- src/__tests__/nodeSuites/evaluations.spec.js | 8 +-- src/__tests__/nodeSuites/readiness.spec.js | 59 +++++++++++++++++++ src/factory/node.js | 2 +- src/settings/defaults/version.js | 2 +- 8 files changed, 80 insertions(+), 21 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 272491e60..7f691bded 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -11.5.0 (August XX, 2025) +11.5.0 (September 9, 2025) - Added `factory.getRolloutPlan()` method for standalone server-side SDKs, which returns the rollout plan snapshot from the storage. - Added `initialRolloutPlan` configuration option for standalone client-side SDKs, which allows preloading the SDK storage with a snapshot of the rollout plan. diff --git a/package-lock.json b/package-lock.json index 20533ce2d..b4e529f74 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.5.0-rc.0", + "version": "11.5.0-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.5.0-rc.0", + "version": "11.5.0-rc.1", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.5.0-rc.0", + "@splitsoftware/splitio-commons": "2.5.0-rc.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.5.0-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.0.tgz", - "integrity": "sha512-XqWSH2za4lkeeZCAk2hQIi6XrAcEGqBAdKRvZXFzRRSjQUZy3OLEqQOC4RaFuEmnOilhYSWtu1kchbXrr+4YiQ==", + "version": "2.5.0-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.1.tgz", + "integrity": "sha512-LryFJfBi+gFgOnGVrOK23GMsS83p51eyzRImHb+v8ydeJrFGKRY00+QLGqqutZLRqcC83XbJnsCJ4JtB6RZGhA==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -7740,9 +7740,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.5.0-rc.0", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.0.tgz", - "integrity": "sha512-XqWSH2za4lkeeZCAk2hQIi6XrAcEGqBAdKRvZXFzRRSjQUZy3OLEqQOC4RaFuEmnOilhYSWtu1kchbXrr+4YiQ==", + "version": "2.5.0-rc.1", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.1.tgz", + "integrity": "sha512-LryFJfBi+gFgOnGVrOK23GMsS83p51eyzRImHb+v8ydeJrFGKRY00+QLGqqutZLRqcC83XbJnsCJ4JtB6RZGhA==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 66366dd75..9038bee21 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.5.0-rc.0", + "version": "11.5.0-rc.1", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.5.0-rc.0", + "@splitsoftware/splitio-commons": "2.5.0-rc.1", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index 7467421ee..9383e360b 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -10,7 +10,7 @@ import membershipsNicolas from '../mocks/memberships.nicolas@split.io.json'; const DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days -const alwaysOnSplitInverted = JSON.stringify({ +export const alwaysOnSplitInverted = JSON.stringify({ 'environment': null, 'trafficTypeId': null, 'trafficTypeName': null, @@ -491,7 +491,7 @@ export default function (fetchMock, assert) { }); }); - assert.test(t => { // Testing when we start with initial rollout plan data and MEMORY storage type (is ready from cache immediately) + assert.test(t => { // Testing when we start with initial rollout plan data and sync storage type (is ready from cache immediately) const testUrls = { sdk: 'https://sdk.baseurl/readyFromCacheWithInitialRolloutPlan', events: 'https://events.baseurl/readyFromCacheWithInitialRolloutPlan' @@ -509,7 +509,7 @@ export default function (fetchMock, assert) { const splitio = SplitFactory({ ...baseConfig, storage: { - type: 'MEMORY', + type: 'MEMORY', // LOCALSTORAGE is supported too }, urls: testUrls, initialRolloutPlan: { diff --git a/src/__tests__/nodeSuites/evaluations.spec.js b/src/__tests__/nodeSuites/evaluations.spec.js index 695e2a7a8..d366814f7 100644 --- a/src/__tests__/nodeSuites/evaluations.spec.js +++ b/src/__tests__/nodeSuites/evaluations.spec.js @@ -285,10 +285,10 @@ export default async function (config, key, assert) { const expectedRolloutPlan = { splitChanges: splitChangesMock1, segmentChanges: [ - { name: 'employees', added: [], removed: [], till: 1 }, - { name: 'splitters', added: [], removed: [], till: 1 }, - { name: 'developers', added: [], removed: [], till: 1 }, - { name: 'segment_excluded_by_rbs', added: ['emi@split.io'], removed: [], till: 1 } + { name: 'employees', added: [], removed: [], till: 1, since: -1 }, + { name: 'splitters', added: [], removed: [], till: 1, since: -1 }, + { name: 'developers', added: [], removed: [], till: 1, since: -1 }, + { name: 'segment_excluded_by_rbs', added: ['emi@split.io'], removed: [], till: 1, since: -1 } ], memberships: { 'emi@split.io': { ms: { k: [{ n: 'segment_excluded_by_rbs' }] }, ls: { k: [] } } } }; diff --git a/src/__tests__/nodeSuites/readiness.spec.js b/src/__tests__/nodeSuites/readiness.spec.js index 03372d16f..ebce11039 100644 --- a/src/__tests__/nodeSuites/readiness.spec.js +++ b/src/__tests__/nodeSuites/readiness.spec.js @@ -2,6 +2,7 @@ import { SplitFactory } from '../../'; import splitChangesMock1 from '../mocks/splitchanges.since.-1.json'; import splitChangesMock2 from '../mocks/splitchanges.since.1457552620999.json'; +import { alwaysOnSplitInverted } from '../browserSuites/ready-from-cache.spec'; const readyTimeout = 0.1; @@ -55,4 +56,62 @@ export default function (fetchMock, assert) { }); }); + assert.test(t => { // Testing when we start with initial rollout plan data (is ready from cache immediately) + const testUrls = { + sdk: 'https://sdk.baseurl/readinessSuite2', + events: 'https://events.baseurl/readinessSuite2' + }; + + fetchMock.getOnce(testUrls.sdk + '/splitChanges?s=1.3&since=25&rbSince=-1', { status: 200, body: { ff: { ...splitChangesMock1.ff, s: 25 } } }); + fetchMock.getOnce(testUrls.sdk + '/segmentChanges/employees?since=100', { status: 200, body: { name: 'employees', added: [], removed: [], since: 100, till: 100 } }); + fetchMock.getOnce(testUrls.sdk + '/segmentChanges/splitters?since=-1', { status: 200, body: { name: 'splitters', added: [], removed: [], since: -1, till: 100 } }); + fetchMock.getOnce(testUrls.sdk + '/segmentChanges/splitters?since=100', { status: 200, body: { name: 'splitters', added: [], removed: [], since: 100, till: 100 } }); + fetchMock.getOnce(testUrls.sdk + '/segmentChanges/developers?since=-1', { status: 200, body: { name: 'developers', added: [], removed: [], since: -1, till: 100 } }); + fetchMock.getOnce(testUrls.sdk + '/segmentChanges/developers?since=100', { status: 200, body: { name: 'developers', added: [], removed: [], since: 100, till: 100 } }); + fetchMock.postOnce(testUrls.events + '/testImpressions/bulk', 200); + fetchMock.postOnce(testUrls.events + '/testImpressions/count', 200); + + const splitio = SplitFactory({ + ...baseConfig, + urls: testUrls, + initialRolloutPlan: { + splitChanges: { + ff: { + t: 25, + d: [JSON.parse(alwaysOnSplitInverted)] + } + }, + segmentChanges: [{ + name: 'employees', added: ['emi@split.io'], removed: [], till: 100 + }] + } + }); + + const client = splitio.client(); + + t.equal(client.__getStatus().isReadyFromCache, true, 'Client is ready from cache'); + + t.equal(client.getTreatment('nicolas@split.io', 'always_on'), 'off', 'It should evaluate treatments with data from cache. Key not in segment'); + t.equal(client.getTreatment('emi@split.io', 'always_on'), 'on', 'It should evaluate treatments with data from cache. Key in segment'); + + client.on(client.Event.SDK_READY_TIMED_OUT, () => { + t.fail('It should not timeout in this scenario.'); + t.end(); + }); + + client.on(client.Event.SDK_READY_FROM_CACHE, () => { + t.fail('SDK is ready from cache immediately. SDK_READY_FROM_CACHE not emitted.'); + t.end(); + }); + + client.on(client.Event.SDK_READY, () => { + t.equal(client.getTreatment('nicolas@split.io', 'always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); + t.equal(client.getTreatment('emi@split.io', 'always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); + + splitio.destroy().then(() => { + t.end(); + }); + }); + }); + } diff --git a/src/factory/node.js b/src/factory/node.js index fa712f58e..2e0979f80 100644 --- a/src/factory/node.js +++ b/src/factory/node.js @@ -4,7 +4,7 @@ import { pushManagerFactory } from '@splitsoftware/splitio-commons/src/sync/stre import { pollingManagerSSFactory } from '@splitsoftware/splitio-commons/src/sync/polling/pollingManagerSS'; import { InRedisStorage } from '@splitsoftware/splitio-commons/src/storages/inRedis'; import { InMemoryStorageFactory } from '@splitsoftware/splitio-commons/src/storages/inMemory/InMemoryStorage'; -import { getRolloutPlan } from '@splitsoftware/splitio-commons/src/storages/dataLoader'; +import { getRolloutPlan } from '@splitsoftware/splitio-commons/src/storages/getRolloutPlan'; import { sdkManagerFactory } from '@splitsoftware/splitio-commons/src/sdkManager'; import { sdkClientMethodFactory } from '@splitsoftware/splitio-commons/src/sdkClient/sdkClientMethod'; import { impressionObserverSSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverSS'; diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index b1820cbf7..495d493a4 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.5.0-rc.0'; +export const packageVersion = '11.5.0-rc.1'; From 5d192ee50454589678452f797f3cff6e70099f6f Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 10 Sep 2025 16:30:24 -0300 Subject: [PATCH 13/13] stable version --- CHANGES.txt | 7 ++++--- package-lock.json | 18 +++++++++--------- package.json | 4 ++-- src/factory/node.js | 3 ++- src/settings/defaults/version.js | 2 +- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 7f691bded..735f452b5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,7 @@ -11.5.0 (September 9, 2025) - - Added `factory.getRolloutPlan()` method for standalone server-side SDKs, which returns the rollout plan snapshot from the storage. - - Added `initialRolloutPlan` configuration option for standalone client-side SDKs, which allows preloading the SDK storage with a snapshot of the rollout plan. +11.5.0 (September 10, 2025) + - Added `factory.getRolloutPlan()` method for standalone server-side SDK (Node.js), which returns the rollout plan snapshot from the storage. + - Added `initialRolloutPlan` configuration option for standalone client-side SDK (Browser), which allows preloading the SDK storage with a snapshot of the rollout plan. + - Updated @splitsoftware/splitio-commons package to version 2.5.0. 11.4.1 (June 3, 2025) - Updated @splitsoftware/splitio-commons package to version 2.4.1, which improves the Proxy fallback to flag spec version 1.2 by handling the case when the Proxy does not return an end-of-stream marker in 400 status code responses. diff --git a/package-lock.json b/package-lock.json index b4e529f74..3db49900d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.5.0-rc.1", + "version": "11.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.5.0-rc.1", + "version": "11.5.0", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.5.0-rc.1", + "@splitsoftware/splitio-commons": "2.5.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -351,9 +351,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.5.0-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.1.tgz", - "integrity": "sha512-LryFJfBi+gFgOnGVrOK23GMsS83p51eyzRImHb+v8ydeJrFGKRY00+QLGqqutZLRqcC83XbJnsCJ4JtB6RZGhA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0.tgz", + "integrity": "sha512-46PN2ix62/eHi4LpuBlS/hN1zcuKzLRTznHaUawehDWz3faSvHLTgIN/AplhJ5p43gSuan/5GyQ9dny/ig0eaQ==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -7740,9 +7740,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.5.0-rc.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0-rc.1.tgz", - "integrity": "sha512-LryFJfBi+gFgOnGVrOK23GMsS83p51eyzRImHb+v8ydeJrFGKRY00+QLGqqutZLRqcC83XbJnsCJ4JtB6RZGhA==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.5.0.tgz", + "integrity": "sha512-46PN2ix62/eHi4LpuBlS/hN1zcuKzLRTznHaUawehDWz3faSvHLTgIN/AplhJ5p43gSuan/5GyQ9dny/ig0eaQ==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" diff --git a/package.json b/package.json index 9038bee21..2ce4da374 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.5.0-rc.1", + "version": "11.5.0", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.5.0-rc.1", + "@splitsoftware/splitio-commons": "2.5.0", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/factory/node.js b/src/factory/node.js index 2e0979f80..6054c3467 100644 --- a/src/factory/node.js +++ b/src/factory/node.js @@ -10,6 +10,7 @@ import { sdkClientMethodFactory } from '@splitsoftware/splitio-commons/src/sdkCl import { impressionObserverSSFactory } from '@splitsoftware/splitio-commons/src/trackers/impressionObserver/impressionObserverSS'; import { sdkFactory } from '@splitsoftware/splitio-commons/src/sdkFactory'; import { CONSUMER_MODE, LOCALHOST_MODE } from '@splitsoftware/splitio-commons/src/utils/constants'; +import { isConsumerMode } from '@splitsoftware/splitio-commons/src/utils/settingsValidation/mode'; import { localhostFromFileFactory } from '../sync/offline/LocalhostFromFile'; import { settingsFactory } from '../settings/node'; @@ -52,7 +53,7 @@ function getModules(settings) { filterAdapterFactory: bloomFilterFactory, extraProps: (params) => { - if (params.settings.mode !== CONSUMER_MODE) { + if (!isConsumerMode(params.settings.mode)) { return { getRolloutPlan(userKeys) { return getRolloutPlan(params.settings.log, params.storage, userKeys); diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index 495d493a4..937adff92 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.5.0-rc.1'; +export const packageVersion = '11.5.0';