@splitsoftware/splitio-commons 2.0.0-rc.2 → 2.0.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGES.txt +1 -3
  2. package/cjs/logger/constants.js +1 -2
  3. package/cjs/logger/messages/error.js +0 -1
  4. package/cjs/sdkFactory/index.js +1 -3
  5. package/cjs/storages/dataLoader.js +37 -99
  6. package/cjs/storages/inMemory/InMemoryStorageCS.js +4 -16
  7. package/cjs/sync/offline/LocalhostFromObject.js +3 -8
  8. package/cjs/utils/settingsValidation/index.js +1 -4
  9. package/esm/logger/constants.js +0 -1
  10. package/esm/logger/messages/error.js +0 -1
  11. package/esm/sdkFactory/index.js +2 -4
  12. package/esm/storages/dataLoader.js +35 -96
  13. package/esm/storages/inMemory/InMemoryStorageCS.js +4 -16
  14. package/esm/sync/offline/LocalhostFromObject.js +2 -6
  15. package/esm/utils/settingsValidation/index.js +1 -4
  16. package/package.json +1 -1
  17. package/src/logger/constants.ts +0 -1
  18. package/src/logger/messages/error.ts +0 -1
  19. package/src/sdkFactory/index.ts +3 -6
  20. package/src/storages/dataLoader.ts +38 -97
  21. package/src/storages/inMemory/InMemoryStorageCS.ts +4 -19
  22. package/src/storages/types.ts +2 -4
  23. package/src/sync/offline/LocalhostFromObject.ts +2 -8
  24. package/src/types.ts +14 -26
  25. package/src/utils/settingsValidation/index.ts +1 -4
  26. package/src/utils/settingsValidation/types.ts +0 -2
  27. package/types/logger/constants.d.ts +0 -1
  28. package/types/storages/dataLoader.d.ts +6 -17
  29. package/types/storages/types.d.ts +1 -4
  30. package/types/sync/offline/LocalhostFromObject.d.ts +1 -2
  31. package/types/types.d.ts +13 -23
  32. package/types/utils/settingsValidation/index.d.ts +0 -1
  33. package/types/utils/settingsValidation/types.d.ts +0 -2
  34. package/cjs/utils/settingsValidation/localhost/builtin.js +0 -18
  35. package/cjs/utils/settingsValidation/localhost/pluggable.js +0 -22
  36. package/esm/utils/settingsValidation/localhost/builtin.js +0 -14
  37. package/esm/utils/settingsValidation/localhost/pluggable.js +0 -18
  38. package/src/utils/settingsValidation/localhost/builtin.ts +0 -16
  39. package/src/utils/settingsValidation/localhost/pluggable.ts +0 -22
  40. package/types/evaluator/matchers/sember_inlist.d.ts +0 -3
  41. package/types/evaluator/matchersTransform/set.d.ts +0 -5
  42. package/types/evaluator/matchersTransform/string.d.ts +0 -7
  43. package/types/integrations/browser.d.ts +0 -12
  44. package/types/integrations/ga/GaToSplit.d.ts +0 -40
  45. package/types/integrations/ga/GoogleAnalyticsToSplit.d.ts +0 -3
  46. package/types/integrations/ga/SplitToGa.d.ts +0 -34
  47. package/types/integrations/ga/SplitToGoogleAnalytics.d.ts +0 -3
  48. package/types/integrations/ga/types.d.ts +0 -148
  49. package/types/sdkClient/sdkClientMethodCSWithTT.d.ts +0 -8
  50. package/types/storages/AbstractSegmentsCacheSync.d.ts +0 -54
  51. package/types/storages/AbstractSplitsCache.d.ts +0 -46
  52. package/types/sync/streaming/mySegmentsV2utils.d.ts +0 -27
  53. package/types/sync/streaming/pushManagerCS_Spec1_3.d.ts +0 -9
  54. package/types/sync/streaming/pushManager_Spec1_3.d.ts +0 -9
  55. package/types/trackers/impressionObserver/utils.d.ts +0 -5
  56. package/types/utils/inputValidation/sdkKey.d.ts +0 -7
  57. package/types/utils/inputValidation/splitExistance.d.ts +0 -7
  58. package/types/utils/inputValidation/trafficTypeExistance.d.ts +0 -9
  59. package/types/utils/lang/maps.d.ts +0 -59
  60. package/types/utils/redis/RedisMock.d.ts +0 -4
  61. package/types/utils/settingsValidation/localhost/builtin.d.ts +0 -16
  62. package/types/utils/settingsValidation/localhost/pluggable.d.ts +0 -16
  63. package/types/utils/settingsValidation/logger/globalLogLevel.d.ts +0 -8
  64. /package/types/utils/{semVer.d.ts → Semver.d.ts} +0 -0
@@ -7,7 +7,7 @@ import { IBasicClient, SplitIO } from '../types';
7
7
  import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey';
8
8
  import { createLoggerAPI } from '../logger/sdkLogger';
9
9
  import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
10
- import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../readiness/constants';
10
+ import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
11
11
  import { objectAssign } from '../utils/lang/objectAssign';
12
12
  import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
13
13
  import { strategyOptimizedFactory } from '../trackers/strategy/strategyOptimized';
@@ -43,7 +43,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
43
43
 
44
44
  const storage = storageFactory({
45
45
  settings,
46
- onReadyCb(error) {
46
+ onReadyCb: (error) => {
47
47
  if (error) {
48
48
  // If storage fails to connect, SDK_READY_TIMED_OUT event is emitted immediately. Review when timeout and non-recoverable errors are reworked
49
49
  readiness.timeout();
@@ -52,11 +52,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
52
52
  readiness.splits.emit(SDK_SPLITS_ARRIVED);
53
53
  readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
54
54
  },
55
- onReadyFromCacheCb() {
56
- readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
57
- }
58
55
  });
59
-
56
+ // @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);`
60
57
  const clients: Record<string, IBasicClient> = {};
61
58
  const telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
62
59
  const integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings, storage, telemetryTracker });
@@ -1,114 +1,55 @@
1
1
  import { SplitIO } from '../types';
2
- import { ISegmentsCacheSync, ISplitsCacheSync, IStorageSync } from './types';
3
- import { setToArray } from '../utils/lang/sets';
4
- import { getMatching } from '../utils/key';
5
- import { IMembershipsResponse, IMySegmentsResponse } from '../dtos/types';
2
+ import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../utils/constants/browser';
3
+ import { DataLoader, ISegmentsCacheSync, ISplitsCacheSync } from './types';
6
4
 
7
5
  /**
8
- * Storage-agnostic adaptation of `loadDataIntoLocalStorage` function
9
- * (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js)
6
+ * Factory of client-side storage loader
10
7
  *
11
- * @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader and extended with a `mySegmentsData` property.
12
- * @param storage object containing `splits` and `segments` cache (client-side variant)
13
- * @param userKey user key (matching key) of the provided MySegmentsCache
14
- *
15
- * @TODO extend to load largeSegments
16
- * @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.
17
- * @TODO add logs, and input validation in this module, in favor of size reduction.
18
- * @TODO unit tests
8
+ * @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader
9
+ * and extended with a `mySegmentsData` property.
10
+ * @returns function to preload the storage
19
11
  */
20
- export function loadData(preloadedData: SplitIO.PreloadedData, storage: { splits?: ISplitsCacheSync, segments: ISegmentsCacheSync, largeSegments?: ISegmentsCacheSync }, matchingKey?: string) {
21
- // Do not load data if current preloadedData is empty
22
- if (Object.keys(preloadedData).length === 0) return;
23
-
24
- const { segmentsData = {}, since = -1, splitsData = [] } = preloadedData;
12
+ export function dataLoaderFactory(preloadedData: SplitIO.PreloadedData): DataLoader {
13
+
14
+ /**
15
+ * Storage-agnostic adaptation of `loadDataIntoLocalStorage` function
16
+ * (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js)
17
+ *
18
+ * @param storage object containing `splits` and `segments` cache (client-side variant)
19
+ * @param userId user key string of the provided MySegmentsCache
20
+ *
21
+ * @TODO extend to support SegmentsCache (server-side variant) by making `userId` optional and adding the corresponding logic.
22
+ * @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.
23
+ */
24
+ return function loadData(storage: { splits: ISplitsCacheSync, segments: ISegmentsCacheSync }, userId: string) {
25
+ // Do not load data if current preloadedData is empty
26
+ if (Object.keys(preloadedData).length === 0) return;
27
+
28
+ const { lastUpdated = -1, segmentsData = {}, since = -1, splitsData = {} } = preloadedData;
25
29
 
26
- if (storage.splits) {
27
30
  const storedSince = storage.splits.getChangeNumber();
31
+ const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
28
32
 
29
- // Do not load data if current data is more recent
30
- if (storedSince > since) return;
33
+ // Do not load data if current localStorage data is more recent,
34
+ // or if its `lastUpdated` timestamp is older than the given `expirationTimestamp`,
35
+ if (storedSince > since || lastUpdated < expirationTimestamp) return;
31
36
 
32
37
  // cleaning up the localStorage data, since some cached splits might need be part of the preloaded data
33
38
  storage.splits.clear();
34
39
  storage.splits.setChangeNumber(since);
35
40
 
36
41
  // splitsData in an object where the property is the split name and the pertaining value is a stringified json of its data
37
- storage.splits.addSplits(splitsData.map(split => ([split.name, split])));
38
- }
39
-
40
- if (matchingKey) { // add mySegments data (client-side)
41
- let membershipsData = preloadedData.membershipsData && preloadedData.membershipsData[matchingKey];
42
- if (!membershipsData && segmentsData) {
43
- membershipsData = {
44
- ms: {
45
- k: Object.keys(segmentsData).filter(segmentName => {
46
- const segmentKeys = segmentsData[segmentName];
47
- return segmentKeys.indexOf(matchingKey) > -1;
48
- }).map(segmentName => ({ n: segmentName }))
49
- }
50
- };
51
- }
52
- if (membershipsData) {
53
- if (membershipsData.ms) storage.segments.resetSegments(membershipsData.ms);
54
- if (membershipsData.ls && storage.largeSegments) storage.largeSegments.resetSegments(membershipsData.ls);
42
+ storage.splits.addSplits(Object.keys(splitsData).map(splitName => JSON.parse(splitsData[splitName])));
43
+
44
+ // add mySegments data
45
+ let mySegmentsData = preloadedData.mySegmentsData && preloadedData.mySegmentsData[userId];
46
+ if (!mySegmentsData) {
47
+ // 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
48
+ mySegmentsData = Object.keys(segmentsData).filter(segmentName => {
49
+ const userIds = JSON.parse(segmentsData[segmentName]).added;
50
+ return Array.isArray(userIds) && userIds.indexOf(userId) > -1;
51
+ });
55
52
  }
56
-
57
- } else { // add segments data (server-side)
58
- Object.keys(segmentsData).forEach(segmentName => {
59
- const segmentKeys = segmentsData[segmentName];
60
- storage.segments.update(segmentName, segmentKeys, [], -1);
61
- });
62
- }
63
- }
64
-
65
- export function getSnapshot(storage: IStorageSync, userKeys?: SplitIO.SplitKey[]): SplitIO.PreloadedData {
66
- return {
67
- // lastUpdated: Date.now(),
68
- since: storage.splits.getChangeNumber(),
69
- splitsData: storage.splits.getAll(),
70
- segmentsData: userKeys ?
71
- undefined : // @ts-ignore accessing private prop
72
- Object.keys(storage.segments.segmentCache).reduce((prev, cur) => { // @ts-ignore accessing private prop
73
- prev[cur] = setToArray(storage.segments.segmentCache[cur] as Set<string>);
74
- return prev;
75
- }, {}),
76
- membershipsData: userKeys ?
77
- userKeys.reduce<Record<string, IMembershipsResponse>>((prev, userKey) => {
78
- if (storage.shared) {
79
- // Client-side segments
80
- // @ts-ignore accessing private prop
81
- const sharedStorage = storage.shared(userKey);
82
- prev[getMatching(userKey)] = {
83
- ms: {
84
- // @ts-ignore accessing private prop
85
- k: Object.keys(sharedStorage.segments.segmentCache).map(segmentName => ({ n: segmentName })),
86
- // cn: sharedStorage.segments.getChangeNumber()
87
- },
88
- ls: sharedStorage.largeSegments ? {
89
- // @ts-ignore accessing private prop
90
- k: Object.keys(sharedStorage.largeSegments.segmentCache).map(segmentName => ({ n: segmentName })),
91
- // cn: sharedStorage.largeSegments.getChangeNumber()
92
- } : undefined
93
- };
94
- } else {
95
- prev[getMatching(userKey)] = {
96
- ms: {
97
- // Server-side segments
98
- // @ts-ignore accessing private prop
99
- k: Object.keys(storage.segments.segmentCache).reduce<IMySegmentsResponse['k']>((prev, segmentName) => { // @ts-ignore accessing private prop
100
- return storage.segments.segmentCache[segmentName].has(userKey) ?
101
- prev!.concat({ n: segmentName }) :
102
- prev;
103
- }, [])
104
- },
105
- ls: {
106
- k: []
107
- }
108
- };
109
- }
110
- return prev;
111
- }, {}) :
112
- undefined
53
+ storage.segments.resetSegments({ k: mySegmentsData.map(s => ({ n: s })) });
113
54
  };
114
55
  }
@@ -7,8 +7,6 @@ import { ImpressionCountsCacheInMemory } from './ImpressionCountsCacheInMemory';
7
7
  import { DEBUG, LOCALHOST_MODE, NONE, STORAGE_MEMORY } from '../../utils/constants';
8
8
  import { shouldRecordTelemetry, TelemetryCacheInMemory } from './TelemetryCacheInMemory';
9
9
  import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
10
- import { getMatching } from '../../utils/key';
11
- import { loadData } from '../dataLoader';
12
10
 
13
11
  /**
14
12
  * InMemory storage factory for standalone client-side SplitFactory
@@ -16,7 +14,7 @@ import { loadData } from '../dataLoader';
16
14
  * @param params parameters required by EventsCacheSync
17
15
  */
18
16
  export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorageSync {
19
- const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation }, preloadedData }, onReadyFromCacheCb } = params;
17
+ const { settings: { scheduler: { impressionsQueueSize, eventsQueueSize, }, sync: { impressionsMode, __splitFiltersValidation } } } = params;
20
18
 
21
19
  const splits = new SplitsCacheInMemory(__splitFiltersValidation);
22
20
  const segments = new MySegmentsCacheInMemory();
@@ -44,18 +42,11 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
44
42
  },
45
43
 
46
44
  // When using shared instantiation with MEMORY we reuse everything but segments (they are unique per key)
47
- shared(matchingKey: string) {
48
- const segments = new MySegmentsCacheInMemory();
49
- const largeSegments = new MySegmentsCacheInMemory();
50
-
51
- if (preloadedData) {
52
- loadData(preloadedData, { segments, largeSegments }, matchingKey);
53
- }
54
-
45
+ shared() {
55
46
  return {
56
47
  splits: this.splits,
57
- segments,
58
- largeSegments,
48
+ segments: new MySegmentsCacheInMemory(),
49
+ largeSegments: new MySegmentsCacheInMemory(),
59
50
  impressions: this.impressions,
60
51
  impressionCounts: this.impressionCounts,
61
52
  events: this.events,
@@ -81,12 +72,6 @@ export function InMemoryStorageCSFactory(params: IStorageFactoryParams): IStorag
81
72
  if (storage.uniqueKeys) storage.uniqueKeys.track = noopTrack;
82
73
  }
83
74
 
84
-
85
- if (preloadedData) {
86
- loadData(preloadedData, storage, getMatching(params.settings.core.key));
87
- if (splits.getChangeNumber() > -1) onReadyFromCacheCb();
88
- }
89
-
90
75
  return storage;
91
76
  }
92
77
 
@@ -488,6 +488,8 @@ export interface IStorageAsync extends IStorageBase<
488
488
 
489
489
  /** StorageFactory */
490
490
 
491
+ export type DataLoader = (storage: IStorageSync, matchingKey: string) => void
492
+
491
493
  export interface IStorageFactoryParams {
492
494
  settings: ISettings,
493
495
  /**
@@ -495,10 +497,6 @@ export interface IStorageFactoryParams {
495
497
  * It is meant for emitting SDK_READY event in consumer mode, and waiting before using the storage in the synchronizer.
496
498
  */
497
499
  onReadyCb: (error?: any) => void,
498
- /**
499
- * It is meant for emitting SDK_READY_FROM_CACHE event in standalone mode with preloaded data
500
- */
501
- onReadyFromCacheCb: () => void,
502
500
  }
503
501
 
504
502
  export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';
@@ -1,12 +1,6 @@
1
1
  import { splitsParserFromSettingsFactory } from './splitsParser/splitsParserFromSettings';
2
2
  import { syncManagerOfflineFactory } from './syncManagerOffline';
3
- import { SplitIO } from '../../types';
4
3
 
5
- // Singleton instance of the factory function for offline SyncManager from object (a.k.a. localhostFromObject)
4
+ // Singleton instance of the factory function for offline SyncManager from object
6
5
  // SDK instances instantiate their SyncManagers with the same factory
7
- const localhostFromObject = syncManagerOfflineFactory(splitsParserFromSettingsFactory) as SplitIO.LocalhostFactory;
8
- localhostFromObject.type = 'LocalhostFromObject';
9
-
10
- export function LocalhostFromObject(): SplitIO.LocalhostFactory {
11
- return localhostFromObject;
12
- }
6
+ export const localhostFromObjectFactory = syncManagerOfflineFactory(splitsParserFromSettingsFactory);
package/src/types.ts CHANGED
@@ -1,11 +1,8 @@
1
- import { IMembershipsResponse, ISplit, ISplitFiltersValidation } from './dtos/types';
1
+ /* eslint-disable no-use-before-define */
2
+ import { ISplitFiltersValidation } from './dtos/types';
2
3
  import { IIntegration, IIntegrationFactoryParams } from './integrations/types';
3
4
  import { ILogger } from './logger/types';
4
- import { ISdkFactoryContext } from './sdkFactory/types';
5
- /* eslint-disable no-use-before-define */
6
-
7
5
  import { IStorageFactoryParams, IStorageSync, IStorageAsync, IStorageSyncFactory, IStorageAsyncFactory } from './storages/types';
8
- import { ISyncManagerCS } from './sync/types';
9
6
 
10
7
  /**
11
8
  * Reduced version of NodeJS.EventEmitter interface with the minimal methods used by the SDK
@@ -97,7 +94,6 @@ export interface ISettings {
97
94
  eventsFirstPushWindow: number
98
95
  },
99
96
  readonly storage: IStorageSyncFactory | IStorageAsyncFactory,
100
- readonly preloadedData?: SplitIO.PreloadedData,
101
97
  readonly integrations: Array<{
102
98
  readonly type: string,
103
99
  (params: IIntegrationFactoryParams): IIntegration | void
@@ -117,7 +113,6 @@ export interface ISettings {
117
113
  splitFilters: SplitIO.SplitFilter[],
118
114
  impressionsMode: SplitIO.ImpressionsMode,
119
115
  __splitFiltersValidation: ISplitFiltersValidation,
120
- localhostMode?: SplitIO.LocalhostFactory,
121
116
  enabled: boolean,
122
117
  flagSpecVersion: string,
123
118
  requestOptions?: {
@@ -667,13 +662,6 @@ export namespace SplitIO {
667
662
  * @typedef {Promise<SplitNames>} SplitNamesAsync
668
663
  */
669
664
  export type SplitNamesAsync = Promise<SplitNames>;
670
- /**
671
- * Localhost mode factory.
672
- */
673
- export type LocalhostFactory = {
674
- type: 'LocalhostFromObject' | 'LocalhostFromFile'
675
- (params: ISdkFactoryContext): ISyncManagerCS
676
- }
677
665
  /**
678
666
  * Impression listener interface. This is the interface that needs to be implemented
679
667
  * by the element you provide to the SDK as impression listener.
@@ -771,31 +759,31 @@ export namespace SplitIO {
771
759
  * If this value is older than 10 days ago (expiration time policy), the data is not used to update the storage content.
772
760
  * @TODO configurable expiration time policy?
773
761
  */
774
- // lastUpdated: number,
762
+ lastUpdated: number,
775
763
  /**
776
764
  * Change number of the preloaded data.
777
765
  * If this value is older than the current changeNumber at the storage, the data is not used to update the storage content.
778
766
  */
779
767
  since: number,
780
768
  /**
781
- * List of feature flag definitions.
782
- * @TODO rename to flags
769
+ * Map of feature flags to their stringified definitions.
783
770
  */
784
- splitsData: ISplit[],
771
+ splitsData: {
772
+ [splitName: string]: string
773
+ },
785
774
  /**
786
- * Optional map of user keys to their memberships.
787
- * @TODO rename to memberships
775
+ * Optional map of user keys to their list of segments.
776
+ * @TODO remove when releasing first version
788
777
  */
789
- membershipsData?: {
790
- [key: string]: IMembershipsResponse
778
+ mySegmentsData?: {
779
+ [key: string]: string[]
791
780
  },
792
781
  /**
793
- * Optional map of segments to their list of keys.
794
- * This property is ignored if `membershipsData` was provided.
795
- * @TODO rename to segments
782
+ * Optional map of segments to their stringified definitions.
783
+ * This property is ignored if `mySegmentsData` was provided.
796
784
  */
797
785
  segmentsData?: {
798
- [segmentName: string]: string[]
786
+ [segmentName: string]: string
799
787
  },
800
788
  }
801
789
  /**
@@ -80,7 +80,6 @@ export const base = {
80
80
  splitFilters: undefined,
81
81
  // impressions collection mode
82
82
  impressionsMode: OPTIMIZED,
83
- localhostMode: undefined,
84
83
  enabled: true,
85
84
  flagSpecVersion: FLAG_SPEC_VERSION
86
85
  },
@@ -102,7 +101,7 @@ function fromSecondsToMillis(n: number) {
102
101
  */
103
102
  export function settingsValidation(config: unknown, validationParams: ISettingsValidationParams) {
104
103
 
105
- const { defaults, runtime, storage, integrations, logger, localhost, consent, flagSpec } = validationParams;
104
+ const { defaults, runtime, storage, integrations, logger, consent, flagSpec } = validationParams;
106
105
 
107
106
  // creates a settings object merging base, defaults and config objects.
108
107
  const withDefaults = merge({}, base, defaults, config) as ISettings;
@@ -180,8 +179,6 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
180
179
  // @ts-ignore, modify readonly prop
181
180
  if (integrations) withDefaults.integrations = integrations(withDefaults);
182
181
 
183
- if (localhost) sync.localhostMode = localhost(withDefaults);
184
-
185
182
  // validate push options
186
183
  if (withDefaults.streamingEnabled !== false) { // @ts-ignore, modify readonly prop
187
184
  withDefaults.streamingEnabled = true;
@@ -20,8 +20,6 @@ export interface ISettingsValidationParams {
20
20
  integrations?: (settings: ISettings) => ISettings['integrations'],
21
21
  /** Logger validator (`settings.debug`) */
22
22
  logger: (settings: ISettings) => ISettings['log'],
23
- /** Localhost mode validator (`settings.sync.localhostMode`) */
24
- localhost?: (settings: ISettings) => ISettings['sync']['localhostMode'],
25
23
  /** User consent validator (`settings.userConsent`) */
26
24
  consent?: (settings: ISettings) => ISettings['userConsent'],
27
25
  /** Flag spec version validation. Configurable by the JS Synchronizer but not by the SDKs */
@@ -106,7 +106,6 @@ export declare const ERROR_EMPTY = 319;
106
106
  export declare const ERROR_EMPTY_ARRAY = 320;
107
107
  export declare const ERROR_INVALID_CONFIG_PARAM = 321;
108
108
  export declare const ERROR_HTTP = 322;
109
- export declare const ERROR_LOCALHOST_MODULE_REQUIRED = 323;
110
109
  export declare const ERROR_STORAGE_INVALID = 324;
111
110
  export declare const ERROR_NOT_BOOLEAN = 325;
112
111
  export declare const ERROR_MIN_CONFIG_PARAM = 326;
@@ -1,21 +1,10 @@
1
1
  import { SplitIO } from '../types';
2
- import { ISegmentsCacheSync, ISplitsCacheSync, IStorageSync } from './types';
2
+ import { DataLoader } from './types';
3
3
  /**
4
- * Storage-agnostic adaptation of `loadDataIntoLocalStorage` function
5
- * (https://github.com/godaddy/split-javascript-data-loader/blob/master/src/load-data.js)
4
+ * Factory of client-side storage loader
6
5
  *
7
- * @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader and extended with a `mySegmentsData` property.
8
- * @param storage object containing `splits` and `segments` cache (client-side variant)
9
- * @param userKey user key (matching key) of the provided MySegmentsCache
10
- *
11
- * @TODO extend to load largeSegments
12
- * @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.
13
- * @TODO add logs, and input validation in this module, in favor of size reduction.
14
- * @TODO unit tests
6
+ * @param preloadedData validated data following the format proposed in https://github.com/godaddy/split-javascript-data-loader
7
+ * and extended with a `mySegmentsData` property.
8
+ * @returns function to preload the storage
15
9
  */
16
- export declare function loadData(preloadedData: SplitIO.PreloadedData, storage: {
17
- splits?: ISplitsCacheSync;
18
- segments: ISegmentsCacheSync;
19
- largeSegments?: ISegmentsCacheSync;
20
- }, matchingKey?: string): void;
21
- export declare function getSnapshot(storage: IStorageSync, userKeys?: SplitIO.SplitKey[]): SplitIO.PreloadedData;
10
+ export declare function dataLoaderFactory(preloadedData: SplitIO.PreloadedData): DataLoader;
@@ -387,6 +387,7 @@ export interface IStorageSync extends IStorageBase<ISplitsCacheSync, ISegmentsCa
387
387
  export interface IStorageAsync extends IStorageBase<ISplitsCacheAsync, ISegmentsCacheAsync, IImpressionsCacheAsync | IImpressionsCacheSync, IImpressionCountsCacheBase, IEventsCacheAsync | IEventsCacheSync, ITelemetryCacheAsync | ITelemetryCacheSync, IUniqueKeysCacheBase> {
388
388
  }
389
389
  /** StorageFactory */
390
+ export declare type DataLoader = (storage: IStorageSync, matchingKey: string) => void;
390
391
  export interface IStorageFactoryParams {
391
392
  settings: ISettings;
392
393
  /**
@@ -394,10 +395,6 @@ export interface IStorageFactoryParams {
394
395
  * It is meant for emitting SDK_READY event in consumer mode, and waiting before using the storage in the synchronizer.
395
396
  */
396
397
  onReadyCb: (error?: any) => void;
397
- /**
398
- * It is meant for emitting SDK_READY_FROM_CACHE event in standalone mode with preloaded data
399
- */
400
- onReadyFromCacheCb: () => void;
401
398
  }
402
399
  export declare type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';
403
400
  export declare type IStorageSyncFactory = {
@@ -1,2 +1 @@
1
- import { SplitIO } from '../../types';
2
- export declare function LocalhostFromObject(): SplitIO.LocalhostFactory;
1
+ export declare const localhostFromObjectFactory: (params: import("../../sdkFactory/types").ISdkFactoryContextSync) => import("../types").ISyncManagerCS;
package/types/types.d.ts CHANGED
@@ -1,9 +1,7 @@
1
- import { IMembershipsResponse, ISplit, ISplitFiltersValidation } from './dtos/types';
1
+ import { ISplitFiltersValidation } from './dtos/types';
2
2
  import { IIntegration, IIntegrationFactoryParams } from './integrations/types';
3
3
  import { ILogger } from './logger/types';
4
- import { ISdkFactoryContext } from './sdkFactory/types';
5
4
  import { IStorageFactoryParams, IStorageSync, IStorageAsync, IStorageSyncFactory, IStorageAsyncFactory } from './storages/types';
6
- import { ISyncManagerCS } from './sync/types';
7
5
  /**
8
6
  * Reduced version of NodeJS.EventEmitter interface with the minimal methods used by the SDK
9
7
  * @see {@link https://nodejs.org/api/events.html}
@@ -91,7 +89,6 @@ export interface ISettings {
91
89
  eventsFirstPushWindow: number;
92
90
  };
93
91
  readonly storage: IStorageSyncFactory | IStorageAsyncFactory;
94
- readonly preloadedData?: SplitIO.PreloadedData;
95
92
  readonly integrations: Array<{
96
93
  readonly type: string;
97
94
  (params: IIntegrationFactoryParams): IIntegration | void;
@@ -111,7 +108,6 @@ export interface ISettings {
111
108
  splitFilters: SplitIO.SplitFilter[];
112
109
  impressionsMode: SplitIO.ImpressionsMode;
113
110
  __splitFiltersValidation: ISplitFiltersValidation;
114
- localhostMode?: SplitIO.LocalhostFactory;
115
111
  enabled: boolean;
116
112
  flagSpecVersion: string;
117
113
  requestOptions?: {
@@ -660,13 +656,6 @@ export declare namespace SplitIO {
660
656
  * @typedef {Promise<SplitNames>} SplitNamesAsync
661
657
  */
662
658
  type SplitNamesAsync = Promise<SplitNames>;
663
- /**
664
- * Localhost mode factory.
665
- */
666
- type LocalhostFactory = {
667
- type: 'LocalhostFromObject' | 'LocalhostFromFile';
668
- (params: ISdkFactoryContext): ISyncManagerCS;
669
- };
670
659
  /**
671
660
  * Impression listener interface. This is the interface that needs to be implemented
672
661
  * by the element you provide to the SDK as impression listener.
@@ -770,30 +759,31 @@ export declare namespace SplitIO {
770
759
  * If this value is older than 10 days ago (expiration time policy), the data is not used to update the storage content.
771
760
  * @TODO configurable expiration time policy?
772
761
  */
762
+ lastUpdated: number;
773
763
  /**
774
764
  * Change number of the preloaded data.
775
765
  * If this value is older than the current changeNumber at the storage, the data is not used to update the storage content.
776
766
  */
777
767
  since: number;
778
768
  /**
779
- * List of feature flag definitions.
780
- * @TODO rename to flags
769
+ * Map of feature flags to their stringified definitions.
781
770
  */
782
- splitsData: ISplit[];
771
+ splitsData: {
772
+ [splitName: string]: string;
773
+ };
783
774
  /**
784
- * Optional map of user keys to their memberships.
785
- * @TODO rename to memberships
775
+ * Optional map of user keys to their list of segments.
776
+ * @TODO remove when releasing first version
786
777
  */
787
- membershipsData?: {
788
- [key: string]: IMembershipsResponse;
778
+ mySegmentsData?: {
779
+ [key: string]: string[];
789
780
  };
790
781
  /**
791
- * Optional map of segments to their list of keys.
792
- * This property is ignored if `membershipsData` was provided.
793
- * @TODO rename to segments
782
+ * Optional map of segments to their stringified definitions.
783
+ * This property is ignored if `mySegmentsData` was provided.
794
784
  */
795
785
  segmentsData?: {
796
- [segmentName: string]: string[];
786
+ [segmentName: string]: string;
797
787
  };
798
788
  }
799
789
  /**
@@ -35,7 +35,6 @@ export declare const base: {
35
35
  sync: {
36
36
  splitFilters: undefined;
37
37
  impressionsMode: string;
38
- localhostMode: undefined;
39
38
  enabled: boolean;
40
39
  flagSpecVersion: string;
41
40
  };
@@ -23,8 +23,6 @@ export interface ISettingsValidationParams {
23
23
  integrations?: (settings: ISettings) => ISettings['integrations'];
24
24
  /** Logger validator (`settings.debug`) */
25
25
  logger: (settings: ISettings) => ISettings['log'];
26
- /** Localhost mode validator (`settings.sync.localhostMode`) */
27
- localhost?: (settings: ISettings) => ISettings['sync']['localhostMode'];
28
26
  /** User consent validator (`settings.userConsent`) */
29
27
  consent?: (settings: ISettings) => ISettings['userConsent'];
30
28
  /** Flag spec version validation. Configurable by the JS Synchronizer but not by the SDKs */
@@ -1,18 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateLocalhostWithDefault = void 0;
4
- var LocalhostFromObject_1 = require("../../../sync/offline/LocalhostFromObject");
5
- var pluggable_1 = require("./pluggable");
6
- /**
7
- * This function validates `settings.sync.localhostMode` object
8
- *
9
- * @param {any} settings config object provided by the user to initialize the sdk
10
- *
11
- * @returns {Object} provided localhost mode module at `settings.sync.localhostMode` if valid, or a default LocalhostFromObject instance if not provided or invalid
12
- */
13
- function validateLocalhostWithDefault(settings) {
14
- if (!settings.sync.localhostMode)
15
- return (0, LocalhostFromObject_1.LocalhostFromObject)();
16
- return (0, pluggable_1.validateLocalhost)(settings) || (0, LocalhostFromObject_1.LocalhostFromObject)();
17
- }
18
- exports.validateLocalhostWithDefault = validateLocalhostWithDefault;
@@ -1,22 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateLocalhost = void 0;
4
- var constants_1 = require("../../../logger/constants");
5
- var constants_2 = require("../../constants");
6
- /**
7
- * This function validates `settings.sync.localhostMode` object
8
- *
9
- * @param {any} settings config object provided by the user to initialize the sdk
10
- *
11
- * @returns {Object | undefined} provided localhost mode module at `settings.sync.localhostMode`, or undefined if it is not provided or invalid
12
- */
13
- function validateLocalhost(settings) {
14
- var localhostMode = settings.sync.localhostMode;
15
- // localhostMode.type is used for internal validation. Not considered part of the public API, and might be updated eventually.
16
- if (settings.mode === constants_2.LOCALHOST_MODE && (typeof localhostMode !== 'function' || localhostMode.type !== 'LocalhostFromObject')) {
17
- settings.log.error(constants_1.ERROR_LOCALHOST_MODULE_REQUIRED);
18
- return undefined;
19
- }
20
- return localhostMode;
21
- }
22
- exports.validateLocalhost = validateLocalhost;
@@ -1,14 +0,0 @@
1
- import { LocalhostFromObject } from '../../../sync/offline/LocalhostFromObject';
2
- import { validateLocalhost } from './pluggable';
3
- /**
4
- * This function validates `settings.sync.localhostMode` object
5
- *
6
- * @param {any} settings config object provided by the user to initialize the sdk
7
- *
8
- * @returns {Object} provided localhost mode module at `settings.sync.localhostMode` if valid, or a default LocalhostFromObject instance if not provided or invalid
9
- */
10
- export function validateLocalhostWithDefault(settings) {
11
- if (!settings.sync.localhostMode)
12
- return LocalhostFromObject();
13
- return validateLocalhost(settings) || LocalhostFromObject();
14
- }
@@ -1,18 +0,0 @@
1
- import { ERROR_LOCALHOST_MODULE_REQUIRED } from '../../../logger/constants';
2
- import { LOCALHOST_MODE } from '../../constants';
3
- /**
4
- * This function validates `settings.sync.localhostMode` object
5
- *
6
- * @param {any} settings config object provided by the user to initialize the sdk
7
- *
8
- * @returns {Object | undefined} provided localhost mode module at `settings.sync.localhostMode`, or undefined if it is not provided or invalid
9
- */
10
- export function validateLocalhost(settings) {
11
- var localhostMode = settings.sync.localhostMode;
12
- // localhostMode.type is used for internal validation. Not considered part of the public API, and might be updated eventually.
13
- if (settings.mode === LOCALHOST_MODE && (typeof localhostMode !== 'function' || localhostMode.type !== 'LocalhostFromObject')) {
14
- settings.log.error(ERROR_LOCALHOST_MODULE_REQUIRED);
15
- return undefined;
16
- }
17
- return localhostMode;
18
- }