From 7d77faccd80dc99f00d7757578a7e9be9cb757c4 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Wed, 9 Oct 2024 12:17:12 -0300 Subject: [PATCH 1/3] Draft implementation of loadData and getSnapshot methods --- CHANGES.txt | 2 + src/sdkFactory/index.ts | 2 +- src/storages/__tests__/dataLoader.spec.ts | 31 +++++++ src/storages/dataLoader.ts | 94 ++++++++++++++-------- src/storages/inMemory/InMemoryStorageCS.ts | 23 +++++- src/storages/types.ts | 2 - src/types.ts | 17 ++-- 7 files changed, 124 insertions(+), 47 deletions(-) create mode 100644 src/storages/__tests__/dataLoader.spec.ts diff --git a/CHANGES.txt b/CHANGES.txt index 4c333159..0ab19c90 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,6 +1,8 @@ 2.0.0 (October XX, 2024) - Added support for targeting rules based on large segments. - Added `factory.destroy()` method, which invokes the `destroy` method on all SDK clients created by the factory. + - 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. - Updated internal storage factory to emit the SDK_READY_FROM_CACHE event when it corresponds, to clean up the initialization flow. - Updated the handling of timers and async operations by moving them into an `init` factory method to enable lazy initialization of the SDK. This update is intended for the React SDK. - Bugfixing - Fixed an issue with the server-side polling manager that caused dangling timers when the SDK was destroyed before it was ready. diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 41706cc6..c09b6fd6 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -56,7 +56,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. readiness.splits.emit(SDK_SPLITS_CACHE_LOADED); } }); - // @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);` + const clients: Record = {}; const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now); const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage, telemetryTracker }); diff --git a/src/storages/__tests__/dataLoader.spec.ts b/src/storages/__tests__/dataLoader.spec.ts new file mode 100644 index 00000000..c9f77849 --- /dev/null +++ b/src/storages/__tests__/dataLoader.spec.ts @@ -0,0 +1,31 @@ +import { InMemoryStorageFactory } from '../inMemory/InMemoryStorage'; +import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS'; +import { fullSettings } from '../../utils/settingsValidation/__tests__/settings.mocks'; + +import * as dataLoader from '../dataLoader'; + +test('loadData & getSnapshot', () => { + jest.spyOn(dataLoader, 'loadData'); + const onReadyFromCacheCb = jest.fn(); + // @ts-expect-error + const serverStorage = InMemoryStorageFactory({ settings: fullSettings }); + serverStorage.splits.setChangeNumber(123); // @ts-expect-error + serverStorage.splits.addSplits([['split1', { name: 'split1' }]]); + serverStorage.segments.addToSegment('segment1', [fullSettings.core.key as string]); + + const preloadedData = dataLoader.getSnapshot(serverStorage, [fullSettings.core.key as string]); + + // @ts-expect-error + const clientStorage = InMemoryStorageCSFactory({ settings: { ...fullSettings, preloadedData }, onReadyFromCacheCb }); + + // Assert + expect(dataLoader.loadData).toBeCalledTimes(1); + expect(onReadyFromCacheCb).toBeCalledTimes(1); + expect(dataLoader.getSnapshot(clientStorage, [fullSettings.core.key as string])).toEqual(preloadedData); + expect(preloadedData).toEqual({ + since: 123, + splitsData: [{ name: 'split1' }], + mySegmentsData: { [fullSettings.core.key as string]: ['segment1'] }, + segmentsData: undefined + }); +}); diff --git a/src/storages/dataLoader.ts b/src/storages/dataLoader.ts index 24898d68..7b44df91 100644 --- a/src/storages/dataLoader.ts +++ b/src/storages/dataLoader.ts @@ -1,55 +1,85 @@ import { SplitIO } from '../types'; -import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../utils/constants/browser'; -import { DataLoader, ISegmentsCacheSync, ISplitsCacheSync } from './types'; +import { ISegmentsCacheSync, ISplitsCacheSync, IStorageSync } from './types'; +import { setToArray, ISet } from '../utils/lang/sets'; +import { getMatching } from '../utils/key'; /** - * Factory of client-side storage loader + * Storage-agnostic adaptation of `loadDataIntoLocalStorage` function + * (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js) * - * @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader - * and extended with a `mySegmentsData` property. - * @returns function to preload the storage + * @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader and extended with a `mySegmentsData` property. + * @param storage object containing `splits` and `segments` cache (client-side variant) + * @param userKey user key (matching key) of the provided MySegmentsCache + * + * @TODO extend to load largeSegments + * @TODO extend to load data on shared mySegments storages. Be specific when emitting SDK_READY_FROM_CACHE on shared clients. Maybe the serializer should provide the `useSegments` flag. + * @TODO add logs, and input validation in this module, in favor of size reduction. + * @TODO unit tests */ -export function dataLoaderFactory(preloadedData: SplitIO.PreloadedData): DataLoader { - - /** - * Storage-agnostic adaptation of `loadDataIntoLocalStorage` function - * (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js) - * - * @param storage object containing `splits` and `segments` cache (client-side variant) - * @param userId user key string of the provided MySegmentsCache - * - * @TODO extend to support SegmentsCache (server-side variant) by making `userId` optional and adding the corresponding logic. - * @TODO extend to load data on shared mySegments storages. Be specific when emitting SDK_READY_FROM_CACHE on shared clients. Maybe the serializer should provide the `useSegments` flag. - */ - return function loadData(storage: { splits: ISplitsCacheSync, segments: ISegmentsCacheSync }, userId: string) { - // Do not load data if current preloadedData is empty - if (Object.keys(preloadedData).length === 0) return; - - const { lastUpdated = -1, segmentsData = {}, since = -1, splitsData = {} } = preloadedData; +export function loadData(preloadedData: SplitIO.PreloadedData, storage: { splits?: ISplitsCacheSync, segments: ISegmentsCacheSync, largeSegments?: ISegmentsCacheSync }, matchingKey?: string) { + // Do not load data if current preloadedData is empty + if (Object.keys(preloadedData).length === 0) return; + + const { segmentsData = {}, since = -1, splitsData = [] } = preloadedData; + if (storage.splits) { const storedSince = storage.splits.getChangeNumber(); - const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS; - // Do not load data if current localStorage data is more recent, - // or if its `lastUpdated` timestamp is older than the given `expirationTimestamp`, - if (storedSince > since || lastUpdated < expirationTimestamp) return; + // Do not load data if current data is more recent + if (storedSince > since) return; // cleaning up the localStorage data, since some cached splits might need be part of the preloaded data storage.splits.clear(); storage.splits.setChangeNumber(since); // splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data - storage.splits.addSplits(Object.keys(splitsData).map(splitName => JSON.parse(splitsData[splitName]))); + storage.splits.addSplits(splitsData.map(split => ([split.name, split]))); + } - // add mySegments data - let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId]; + if (matchingKey) { // add mySegments data (client-side) + let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[matchingKey]; if (!mySegmentsData) { // segmentsData in an object where the property is the segment name and the pertaining value is a stringified object that contains the `added` array of userIds mySegmentsData = Object.keys(segmentsData).filter(segmentName => { - const userIds = JSON.parse(segmentsData[segmentName]).added; - return Array.isArray(userIds) && userIds.indexOf(userId) > -1; + const matchingKeys = segmentsData[segmentName]; + return matchingKeys.indexOf(matchingKey) > -1; }); } storage.segments.resetSegments({ k: mySegmentsData.map(s => ({ n: s })) }); + } else { // add segments data (server-side) + Object.keys(segmentsData).filter(segmentName => { + const matchingKeys = segmentsData[segmentName]; + storage.segments.addToSegment(segmentName, matchingKeys); + }); + } +} + +export function getSnapshot(storage: IStorageSync, userKeys?: SplitIO.SplitKey[]): SplitIO.PreloadedData { + return { + // lastUpdated: Date.now(), + since: storage.splits.getChangeNumber(), + splitsData: storage.splits.getAll(), + segmentsData: userKeys ? + undefined : // @ts-ignore accessing private prop + Object.keys(storage.segments.segmentCache).reduce((prev, cur) => { // @ts-ignore accessing private prop + prev[cur] = setToArray(storage.segments.segmentCache[cur] as ISet); + return prev; + }, {}), + mySegmentsData: userKeys ? + userKeys.reduce>((prev, userKey) => { + prev[getMatching(userKey)] = storage.shared ? + // Client-side segments + // @ts-ignore accessing private prop + Object.keys(storage.shared(userKey).segments.segmentCache) : + // Server-side segments + // @ts-ignore accessing private prop + Object.keys(storage.segments.segmentCache).reduce((prev, segmentName) => { // @ts-ignore accessing private prop + return storage.segments.segmentCache[segmentName].has(userKey) ? + prev.concat(segmentName) : + prev; + }, []); + return prev; + }, {}) : + undefined }; } diff --git a/src/storages/inMemory/InMemoryStorageCS.ts b/src/storages/inMemory/InMemoryStorageCS.ts index 30667369..670b91f1 100644 --- a/src/storages/inMemory/InMemoryStorageCS.ts +++ b/src/storages/inMemory/InMemoryStorageCS.ts @@ -7,6 +7,8 @@ import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory'; import { DEBUG, LOCALHOST_MODE, NONE, STORAGE_MEMORY } from '../../utils/constants'; import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory'; import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS'; +import { getMatching } from '../../utils/key'; +import { loadData } from '../dataLoader'; /** * InMemory storage factory for standalone client-side SplitFactory @@ -14,7 +16,7 @@ import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS'; * @param params parameters required by EventsCacheSync */ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorageSync { - const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params; + const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation }, preloadedData }, onReadyFromCacheCb } = params; const splits = new SplitsCacheInMemory(__splitFiltersValidation); const segments = new MySegmentsCacheInMemory(); @@ -42,11 +44,18 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag }, // When using shared instanciation with MEMORY we reuse everything but segments (they are unique per key) - shared() { + shared(matchingKey: string) { + const segments = new MySegmentsCacheInMemory(); + const largeSegments = new MySegmentsCacheInMemory(); + + if (preloadedData) { + loadData(preloadedData, { segments, largeSegments }, matchingKey); + } + return { splits: this.splits, - segments: new MySegmentsCacheInMemory(), - largeSegments: new MySegmentsCacheInMemory(), + segments, + largeSegments, impressions: this.impressions, impressionCounts: this.impressionCounts, events: this.events, @@ -72,6 +81,12 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag if (storage.uniqueKeys) storage.uniqueKeys.track = noopTrack; } + + if (preloadedData) { + loadData(preloadedData, storage, getMatching(params.settings.core.key)); + if (splits.getChangeNumber() > -1) onReadyFromCacheCb(); + } + return storage; } diff --git a/src/storages/types.ts b/src/storages/types.ts index 61ab10f2..21945587 100644 --- a/src/storages/types.ts +++ b/src/storages/types.ts @@ -492,8 +492,6 @@ export interface IStorageAsync extends IStorageBase< /** StorageFactory */ -export type DataLoader = (storage: IStorageSync, matchingKey: string) => void - export interface IStorageFactoryParams { settings: ISettings, /** diff --git a/src/types.ts b/src/types.ts index 2a65b297..777b3258 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { ISplitFiltersValidation } from './dtos/types'; +import { ISplit, ISplitFiltersValidation } from './dtos/types'; import { IIntegration, IIntegrationFactoryParams } from './integrations/types'; import { ILogger } from './logger/types'; import { ISdkFactoryContext } from './sdkFactory/types'; @@ -98,6 +98,7 @@ export interface ISettings { eventsFirstPushWindow: number }, readonly storage: IStorageSyncFactory | IStorageAsyncFactory, + readonly preloadedData?: SplitIO.PreloadedData, readonly integrations: Array<{ readonly type: string, (params: IIntegrationFactoryParams): IIntegration | void @@ -771,21 +772,20 @@ export namespace SplitIO { * If this value is older than 10 days ago (expiration time policy), the data is not used to update the storage content. * @TODO configurable expiration time policy? */ - lastUpdated: number, + // lastUpdated: number, /** * Change number of the preloaded data. * If this value is older than the current changeNumber at the storage, the data is not used to update the storage content. */ since: number, /** - * Map of feature flags to their stringified definitions. + * List of feature flag definitions. + * @TODO rename to flags */ - splitsData: { - [splitName: string]: string - }, + splitsData: ISplit[], /** * Optional map of user keys to their list of segments. - * @TODO remove when releasing first version + * @TODO rename to memberships */ mySegmentsData?: { [key: string]: string[] @@ -793,9 +793,10 @@ export namespace SplitIO { /** * Optional map of segments to their stringified definitions. * This property is ignored if `mySegmentsData` was provided. + * @TODO rename to segments */ segmentsData?: { - [segmentName: string]: string + [segmentName: string]: string[] }, } /** From b8b12cddf0351cff789a069391ba1ef42887f19f Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 18 Oct 2024 18:16:35 -0300 Subject: [PATCH 2/3] Update data loader to support memberships --- src/sdkFactory/index.ts | 7 ++- src/storages/__tests__/dataLoader.spec.ts | 4 +- src/storages/dataLoader.ts | 77 ++++++++++++++++------- src/storages/types.ts | 4 ++ src/types.ts | 12 ++-- 5 files changed, 70 insertions(+), 34 deletions(-) diff --git a/src/sdkFactory/index.ts b/src/sdkFactory/index.ts index 5ab47ddf..0e9feda4 100644 --- a/src/sdkFactory/index.ts +++ b/src/sdkFactory/index.ts @@ -7,7 +7,7 @@ import { IBasicClient, SplitIO } from '../types'; import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey'; import { createLoggerAPI } from '../logger/sdkLogger'; import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants'; -import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants'; +import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../readiness/constants'; import { objectAssign } from '../utils/lang/objectAssign'; import { strategyDebugFactory } from '../trackers/strategy/strategyDebug'; import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized'; @@ -43,7 +43,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. const storage = storageFactory({ settings, - onReadyCb: (error) => { + onReadyCb(error) { if (error) { // If storage fails to connect, SDK_READY_TIMED_OUT event is emitted immediately. Review when timeout and non-recoverable errors are reworked readiness.timeout(); @@ -52,6 +52,9 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO. readiness.splits.emit(SDK_SPLITS_ARRIVED); readiness.segments.emit(SDK_SEGMENTS_ARRIVED); }, + onReadyFromCacheCb() { + readiness.splits.emit(SDK_SPLITS_CACHE_LOADED); + } }); const clients: Record = {}; diff --git a/src/storages/__tests__/dataLoader.spec.ts b/src/storages/__tests__/dataLoader.spec.ts index c9f77849..522feb99 100644 --- a/src/storages/__tests__/dataLoader.spec.ts +++ b/src/storages/__tests__/dataLoader.spec.ts @@ -11,7 +11,7 @@ test('loadData & getSnapshot', () => { const serverStorage = InMemoryStorageFactory({ settings: fullSettings }); serverStorage.splits.setChangeNumber(123); // @ts-expect-error serverStorage.splits.addSplits([['split1', { name: 'split1' }]]); - serverStorage.segments.addToSegment('segment1', [fullSettings.core.key as string]); + serverStorage.segments.update('segment1', [fullSettings.core.key as string], [], 123); const preloadedData = dataLoader.getSnapshot(serverStorage, [fullSettings.core.key as string]); @@ -25,7 +25,7 @@ test('loadData & getSnapshot', () => { expect(preloadedData).toEqual({ since: 123, splitsData: [{ name: 'split1' }], - mySegmentsData: { [fullSettings.core.key as string]: ['segment1'] }, + membershipsData: { [fullSettings.core.key as string]: { ms: { k: [{ n: 'segment1' }] }, ls: { k: [] } } }, segmentsData: undefined }); }); diff --git a/src/storages/dataLoader.ts b/src/storages/dataLoader.ts index 7b44df91..4efabcc9 100644 --- a/src/storages/dataLoader.ts +++ b/src/storages/dataLoader.ts @@ -1,7 +1,8 @@ import { SplitIO } from '../types'; import { ISegmentsCacheSync, ISplitsCacheSync, IStorageSync } from './types'; -import { setToArray, ISet } from '../utils/lang/sets'; +import { setToArray } from '../utils/lang/sets'; import { getMatching } from '../utils/key'; +import { IMembershipsResponse, IMySegmentsResponse } from '../dtos/types'; /** * Storage-agnostic adaptation of `loadDataIntoLocalStorage` function @@ -37,19 +38,26 @@ export function loadData(preloadedData: SplitIO.PreloadedData, storage: { splits } if (matchingKey) { // add mySegments data (client-side) - let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[matchingKey]; - if (!mySegmentsData) { - // segmentsData in an object where the property is the segment name and the pertaining value is a stringified object that contains the `added` array of userIds - mySegmentsData = Object.keys(segmentsData).filter(segmentName => { - const matchingKeys = segmentsData[segmentName]; - return matchingKeys.indexOf(matchingKey) > -1; - }); + let membershipsData = preloadedData.membershipsData && preloadedData.membershipsData[matchingKey]; + if (!membershipsData && segmentsData) { + membershipsData = { + ms: { + k: Object.keys(segmentsData).filter(segmentName => { + const segmentKeys = segmentsData[segmentName]; + return segmentKeys.indexOf(matchingKey) > -1; + }).map(segmentName => ({ n: segmentName })) + } + }; } - storage.segments.resetSegments({ k: mySegmentsData.map(s => ({ n: s })) }); + if (membershipsData) { + if (membershipsData.ms) storage.segments.resetSegments(membershipsData.ms); + if (membershipsData.ls && storage.largeSegments) storage.largeSegments.resetSegments(membershipsData.ls); + } + } else { // add segments data (server-side) - Object.keys(segmentsData).filter(segmentName => { - const matchingKeys = segmentsData[segmentName]; - storage.segments.addToSegment(segmentName, matchingKeys); + Object.keys(segmentsData).forEach(segmentName => { + const segmentKeys = segmentsData[segmentName]; + storage.segments.update(segmentName, segmentKeys, [], -1); }); } } @@ -62,22 +70,43 @@ export function getSnapshot(storage: IStorageSync, userKeys?: SplitIO.SplitKey[] segmentsData: userKeys ? undefined : // @ts-ignore accessing private prop Object.keys(storage.segments.segmentCache).reduce((prev, cur) => { // @ts-ignore accessing private prop - prev[cur] = setToArray(storage.segments.segmentCache[cur] as ISet); + prev[cur] = setToArray(storage.segments.segmentCache[cur] as Set); return prev; }, {}), - mySegmentsData: userKeys ? - userKeys.reduce>((prev, userKey) => { - prev[getMatching(userKey)] = storage.shared ? + membershipsData: userKeys ? + userKeys.reduce>((prev, userKey) => { + if (storage.shared) { // Client-side segments // @ts-ignore accessing private prop - Object.keys(storage.shared(userKey).segments.segmentCache) : - // Server-side segments - // @ts-ignore accessing private prop - Object.keys(storage.segments.segmentCache).reduce((prev, segmentName) => { // @ts-ignore accessing private prop - return storage.segments.segmentCache[segmentName].has(userKey) ? - prev.concat(segmentName) : - prev; - }, []); + const sharedStorage = storage.shared(userKey); + prev[getMatching(userKey)] = { + ms: { + // @ts-ignore accessing private prop + k: Object.keys(sharedStorage.segments.segmentCache).map(segmentName => ({ n: segmentName })), + // cn: sharedStorage.segments.getChangeNumber() + }, + ls: sharedStorage.largeSegments ? { + // @ts-ignore accessing private prop + k: Object.keys(sharedStorage.largeSegments.segmentCache).map(segmentName => ({ n: segmentName })), + // cn: sharedStorage.largeSegments.getChangeNumber() + } : undefined + }; + } else { + prev[getMatching(userKey)] = { + ms: { + // Server-side segments + // @ts-ignore accessing private prop + k: Object.keys(storage.segments.segmentCache).reduce((prev, segmentName) => { // @ts-ignore accessing private prop + return storage.segments.segmentCache[segmentName].has(userKey) ? + prev!.concat({ n: segmentName }) : + prev; + }, []) + }, + ls: { + k: [] + } + }; + } return prev; }, {}) : undefined diff --git a/src/storages/types.ts b/src/storages/types.ts index 08a9d387..8be2c731 100644 --- a/src/storages/types.ts +++ b/src/storages/types.ts @@ -495,6 +495,10 @@ export interface IStorageFactoryParams { * It is meant for emitting SDK_READY event in consumer mode, and waiting before using the storage in the synchronizer. */ onReadyCb: (error?: any) => void, + /** + * It is meant for emitting SDK_READY_FROM_CACHE event in standalone mode with preloaded data + */ + onReadyFromCacheCb: () => void, } export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE'; diff --git a/src/types.ts b/src/types.ts index 92a44112..9b77ced5 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,4 @@ -import { ISplit, ISplitFiltersValidation } from './dtos/types'; +import { IMembershipsResponse, ISplit, ISplitFiltersValidation } from './dtos/types'; import { IIntegration, IIntegrationFactoryParams } from './integrations/types'; import { ILogger } from './logger/types'; import { ISdkFactoryContext } from './sdkFactory/types'; @@ -783,15 +783,15 @@ export namespace SplitIO { */ splitsData: ISplit[], /** - * Optional map of user keys to their list of segments. + * Optional map of user keys to their memberships. * @TODO rename to memberships */ - mySegmentsData?: { - [key: string]: string[] + membershipsData?: { + [key: string]: IMembershipsResponse }, /** - * Optional map of segments to their stringified definitions. - * This property is ignored if `mySegmentsData` was provided. + * Optional map of segments to their list of keys. + * This property is ignored if `membershipsData` was provided. * @TODO rename to segments */ segmentsData?: { From 325ecdaf586d6d2d0a9e667890694b42bad2ae25 Mon Sep 17 00:00:00 2001 From: Emiliano Sanchez Date: Fri, 18 Oct 2024 18:25:47 -0300 Subject: [PATCH 3/3] rc --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8bc19544..6cf6d6f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio-commons", - "version": "2.0.0-rc.1", + "version": "2.0.0-rc.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-commons", - "version": "2.0.0-rc.1", + "version": "2.0.0-rc.2", "license": "Apache-2.0", "dependencies": { "tslib": "^2.3.1" diff --git a/package.json b/package.json index 870e561c..4ddeb4c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-commons", - "version": "2.0.0-rc.1", + "version": "2.0.0-rc.2", "description": "Split JavaScript SDK common components", "main": "cjs/index.js", "module": "esm/index.js",