@splitsoftware/splitio-commons 2.1.1-rc.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGES.txt +5 -1
  2. package/cjs/readiness/readinessManager.js +6 -0
  3. package/cjs/storages/AbstractSplitsCacheAsync.js +0 -7
  4. package/cjs/storages/AbstractSplitsCacheSync.js +0 -7
  5. package/cjs/storages/KeyBuilderCS.js +3 -0
  6. package/cjs/storages/dataLoader.js +3 -2
  7. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +11 -69
  8. package/cjs/storages/inLocalStorage/index.js +5 -3
  9. package/cjs/storages/inLocalStorage/validateCache.js +79 -0
  10. package/cjs/storages/pluggable/index.js +2 -1
  11. package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
  12. package/cjs/sync/polling/updaters/splitChangesUpdater.js +1 -12
  13. package/cjs/sync/syncManagerOnline.js +8 -3
  14. package/cjs/trackers/strategy/strategyDebug.js +2 -0
  15. package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
  16. package/esm/readiness/readinessManager.js +6 -0
  17. package/esm/storages/AbstractSplitsCacheAsync.js +0 -7
  18. package/esm/storages/AbstractSplitsCacheSync.js +0 -7
  19. package/esm/storages/KeyBuilderCS.js +3 -0
  20. package/esm/storages/dataLoader.js +2 -1
  21. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +11 -69
  22. package/esm/storages/inLocalStorage/index.js +5 -3
  23. package/esm/storages/inLocalStorage/validateCache.js +75 -0
  24. package/esm/storages/pluggable/index.js +2 -1
  25. package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +3 -2
  26. package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -13
  27. package/esm/sync/syncManagerOnline.js +8 -3
  28. package/esm/trackers/strategy/strategyDebug.js +2 -0
  29. package/esm/utils/settingsValidation/storage/storageCS.js +1 -1
  30. package/package.json +1 -1
  31. package/src/readiness/readinessManager.ts +5 -0
  32. package/src/storages/AbstractSplitsCacheAsync.ts +0 -8
  33. package/src/storages/AbstractSplitsCacheSync.ts +0 -8
  34. package/src/storages/KeyBuilderCS.ts +4 -0
  35. package/src/storages/dataLoader.ts +3 -1
  36. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +13 -78
  37. package/src/storages/inLocalStorage/index.ts +8 -8
  38. package/src/storages/inLocalStorage/validateCache.ts +91 -0
  39. package/src/storages/pluggable/index.ts +2 -1
  40. package/src/storages/types.ts +1 -4
  41. package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +6 -5
  42. package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -13
  43. package/src/sync/syncManagerOnline.ts +9 -3
  44. package/src/trackers/strategy/strategyDebug.ts +2 -0
  45. package/src/utils/lang/index.ts +1 -1
  46. package/src/utils/settingsValidation/storage/storageCS.ts +1 -1
  47. package/types/splitio.d.ts +28 -1
  48. package/cjs/utils/constants/browser.js +0 -5
  49. package/esm/utils/constants/browser.js +0 -2
  50. package/src/utils/constants/browser.ts +0 -2
@@ -7,22 +7,19 @@ import { KeyBuilderCS, myLargeSegmentsKeyBuilder } from '../KeyBuilderCS';
7
7
  import { isLocalStorageAvailable } from '../../utils/env/isLocalStorageAvailable';
8
8
  import { SplitsCacheInLocal } from './SplitsCacheInLocal';
9
9
  import { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
10
- import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
11
10
  import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
12
11
  import { LOG_PREFIX } from './constants';
13
12
  import { STORAGE_LOCALSTORAGE } from '../../utils/constants';
14
13
  import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
15
14
  import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
16
15
  import { getMatching } from '../../utils/key';
17
-
18
- export interface InLocalStorageOptions {
19
- prefix?: string
20
- }
16
+ import { validateCache } from './validateCache';
17
+ import SplitIO from '../../../types/splitio';
21
18
 
22
19
  /**
23
20
  * InLocal storage factory for standalone client-side SplitFactory
24
21
  */
25
- export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyncFactory {
22
+ export function InLocalStorage(options: SplitIO.InLocalStorageOptions = {}): IStorageSyncFactory {
26
23
 
27
24
  const prefix = validatePrefix(options.prefix);
28
25
 
@@ -37,9 +34,8 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
37
34
  const { settings, settings: { log, scheduler: { impressionsQueueSize, eventsQueueSize } } } = params;
38
35
  const matchingKey = getMatching(settings.core.key);
39
36
  const keys = new KeyBuilderCS(prefix, matchingKey);
40
- const expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
41
37
 
42
- const splits = new SplitsCacheInLocal(settings, keys, expirationTimestamp);
38
+ const splits = new SplitsCacheInLocal(settings, keys);
43
39
  const segments = new MySegmentsCacheInLocal(log, keys);
44
40
  const largeSegments = new MySegmentsCacheInLocal(log, myLargeSegmentsKeyBuilder(prefix, matchingKey));
45
41
 
@@ -53,6 +49,10 @@ export function InLocalStorage(options: InLocalStorageOptions = {}): IStorageSyn
53
49
  telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
54
50
  uniqueKeys: new UniqueKeysCacheInMemoryCS(),
55
51
 
52
+ validateCache() {
53
+ return validateCache(options, settings, keys, splits, segments, largeSegments);
54
+ },
55
+
56
56
  destroy() { },
57
57
 
58
58
  // When using shared instantiation with MEMORY we reuse everything but segments (they are customer per key).
@@ -0,0 +1,91 @@
1
+ import { ISettings } from '../../types';
2
+ import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
3
+ import { getStorageHash } from '../KeyBuilder';
4
+ import { LOG_PREFIX } from './constants';
5
+ import type { SplitsCacheInLocal } from './SplitsCacheInLocal';
6
+ import type { MySegmentsCacheInLocal } from './MySegmentsCacheInLocal';
7
+ import { KeyBuilderCS } from '../KeyBuilderCS';
8
+ import SplitIO from '../../../types/splitio';
9
+
10
+ const DEFAULT_CACHE_EXPIRATION_IN_DAYS = 10;
11
+ const MILLIS_IN_A_DAY = 86400000;
12
+
13
+ /**
14
+ * Validates if cache should be cleared and sets the cache `hash` if needed.
15
+ *
16
+ * @returns `true` if cache should be cleared, `false` otherwise
17
+ */
18
+ function validateExpiration(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS, currentTimestamp: number, isThereCache: boolean) {
19
+ const { log } = settings;
20
+
21
+ // Check expiration
22
+ const lastUpdatedTimestamp = parseInt(localStorage.getItem(keys.buildLastUpdatedKey()) as string, 10);
23
+ if (!isNaNNumber(lastUpdatedTimestamp)) {
24
+ const cacheExpirationInDays = isFiniteNumber(options.expirationDays) && options.expirationDays >= 1 ? options.expirationDays : DEFAULT_CACHE_EXPIRATION_IN_DAYS;
25
+ const expirationTimestamp = currentTimestamp - MILLIS_IN_A_DAY * cacheExpirationInDays;
26
+ if (lastUpdatedTimestamp < expirationTimestamp) {
27
+ log.info(LOG_PREFIX + 'Cache expired more than ' + cacheExpirationInDays + ' days ago. Cleaning up cache');
28
+ return true;
29
+ }
30
+ }
31
+
32
+ // Check hash
33
+ const storageHashKey = keys.buildHashKey();
34
+ const storageHash = localStorage.getItem(storageHashKey);
35
+ const currentStorageHash = getStorageHash(settings);
36
+
37
+ if (storageHash !== currentStorageHash) {
38
+ try {
39
+ localStorage.setItem(storageHashKey, currentStorageHash);
40
+ } catch (e) {
41
+ log.error(LOG_PREFIX + e);
42
+ }
43
+ if (isThereCache) {
44
+ log.info(LOG_PREFIX + 'SDK key, flags filter criteria, or flags spec version has changed. Cleaning up cache');
45
+ return true;
46
+ }
47
+ return false; // No cache to clear
48
+ }
49
+
50
+ // Clear on init
51
+ if (options.clearOnInit) {
52
+ const lastClearTimestamp = parseInt(localStorage.getItem(keys.buildLastClear()) as string, 10);
53
+
54
+ if (isNaNNumber(lastClearTimestamp) || lastClearTimestamp < currentTimestamp - MILLIS_IN_A_DAY) {
55
+ log.info(LOG_PREFIX + 'clearOnInit was set and cache was not cleared in the last 24 hours. Cleaning up cache');
56
+ return true;
57
+ }
58
+ }
59
+ }
60
+
61
+ /**
62
+ * Clean cache if:
63
+ * - it has expired, i.e., its `lastUpdated` timestamp is older than the given `expirationTimestamp`
64
+ * - its hash has changed, i.e., the SDK key, flags filter criteria or flags spec version was modified
65
+ * - `clearOnInit` was set and cache was not cleared in the last 24 hours
66
+ *
67
+ * @returns `true` if cache is ready to be used, `false` otherwise (cache was cleared or there is no cache)
68
+ */
69
+ export function validateCache(options: SplitIO.InLocalStorageOptions, settings: ISettings, keys: KeyBuilderCS, splits: SplitsCacheInLocal, segments: MySegmentsCacheInLocal, largeSegments: MySegmentsCacheInLocal): boolean {
70
+
71
+ const currentTimestamp = Date.now();
72
+ const isThereCache = splits.getChangeNumber() > -1;
73
+
74
+ if (validateExpiration(options, settings, keys, currentTimestamp, isThereCache)) {
75
+ splits.clear();
76
+ segments.clear();
77
+ largeSegments.clear();
78
+
79
+ // Update last clear timestamp
80
+ try {
81
+ localStorage.setItem(keys.buildLastClear(), currentTimestamp + '');
82
+ } catch (e) {
83
+ settings.log.error(LOG_PREFIX + e);
84
+ }
85
+
86
+ return false;
87
+ }
88
+
89
+ // Check if ready from cache
90
+ return isThereCache;
91
+ }
@@ -88,7 +88,8 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
88
88
  // Connects to wrapper and emits SDK_READY event on main client
89
89
  const connectPromise = wrapper.connect().then(() => {
90
90
  if (isSynchronizer) {
91
- // In standalone or producer mode, clear storage if SDK key or feature flag filter has changed
91
+ // @TODO reuse InLocalStorage::validateCache logic
92
+ // In standalone or producer mode, clear storage if SDK key, flags filter criteria or flags spec version was modified
92
93
  return wrapper.get(keys.buildHashKey()).then((hash) => {
93
94
  const currentHash = getStorageHash(settings);
94
95
  if (hash !== currentHash) {
@@ -189,8 +189,6 @@ export interface ISplitsCacheBase {
189
189
  // only for Client-Side. Returns true if the storage is not synchronized yet (getChangeNumber() === -1) or contains a FF using segments or large segments
190
190
  usesSegments(): MaybeThenable<boolean>,
191
191
  clear(): MaybeThenable<boolean | void>,
192
- // should never reject or throw an exception. Instead return false by default, to avoid emitting SDK_READY_FROM_CACHE.
193
- checkCache(): MaybeThenable<boolean>,
194
192
  killLocally(name: string, defaultTreatment: string, changeNumber: number): MaybeThenable<boolean>,
195
193
  getNamesByFlagSets(flagSets: string[]): MaybeThenable<Set<string>[]>
196
194
  }
@@ -205,7 +203,6 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
205
203
  trafficTypeExists(trafficType: string): boolean,
206
204
  usesSegments(): boolean,
207
205
  clear(): void,
208
- checkCache(): boolean,
209
206
  killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean,
210
207
  getNamesByFlagSets(flagSets: string[]): Set<string>[]
211
208
  }
@@ -220,7 +217,6 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
220
217
  trafficTypeExists(trafficType: string): Promise<boolean>,
221
218
  usesSegments(): Promise<boolean>,
222
219
  clear(): Promise<boolean | void>,
223
- checkCache(): Promise<boolean>,
224
220
  killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>,
225
221
  getNamesByFlagSets(flagSets: string[]): Promise<Set<string>[]>
226
222
  }
@@ -451,6 +447,7 @@ export interface IStorageSync extends IStorageBase<
451
447
  IUniqueKeysCacheSync
452
448
  > {
453
449
  // Defined in client-side
450
+ validateCache?: () => boolean, // @TODO support async
454
451
  largeSegments?: ISegmentsCacheSync,
455
452
  }
456
453
 
@@ -1,6 +1,6 @@
1
1
  import { forOwn } from '../../../utils/lang';
2
2
  import { IReadinessManager } from '../../../readiness/types';
3
- import { ISplitsCacheSync } from '../../../storages/types';
3
+ import { IStorageSync } from '../../../storages/types';
4
4
  import { ISplitsParser } from '../splitsParser/types';
5
5
  import { ISplit, ISplitPartial } from '../../../dtos/types';
6
6
  import { syncTaskFactory } from '../../syncTask';
@@ -15,7 +15,7 @@ import { SYNC_OFFLINE_DATA, ERROR_SYNC_OFFLINE_LOADING } from '../../../logger/c
15
15
  */
16
16
  export function fromObjectUpdaterFactory(
17
17
  splitsParser: ISplitsParser,
18
- storage: { splits: ISplitsCacheSync },
18
+ storage: Pick<IStorageSync, 'splits' | 'validateCache'>,
19
19
  readiness: IReadinessManager,
20
20
  settings: ISettings,
21
21
  ): () => Promise<boolean> {
@@ -59,9 +59,10 @@ export function fromObjectUpdaterFactory(
59
59
 
60
60
  if (startingUp) {
61
61
  startingUp = false;
62
- Promise.resolve(splitsCache.checkCache()).then(cacheReady => {
62
+ const isCacheLoaded = storage.validateCache ? storage.validateCache() : false;
63
+ Promise.resolve().then(() => {
63
64
  // Emits SDK_READY_FROM_CACHE
64
- if (cacheReady) readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
65
+ if (isCacheLoaded) readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
65
66
  // Emits SDK_READY
66
67
  readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
67
68
  });
@@ -79,7 +80,7 @@ export function fromObjectUpdaterFactory(
79
80
  */
80
81
  export function fromObjectSyncTaskFactory(
81
82
  splitsParser: ISplitsParser,
82
- storage: { splits: ISplitsCacheSync },
83
+ storage: Pick<IStorageSync, 'splits' | 'validateCache'>,
83
84
  readiness: IReadinessManager,
84
85
  settings: ISettings
85
86
  ): ISyncTask<[], boolean> {
@@ -3,7 +3,7 @@ import { ISplitChangesFetcher } from '../fetchers/types';
3
3
  import { ISplit, ISplitChangesResponse, ISplitFiltersValidation } from '../../../dtos/types';
4
4
  import { ISplitsEventEmitter } from '../../../readiness/types';
5
5
  import { timeout } from '../../../utils/promise/timeout';
6
- import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
6
+ import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
7
7
  import { ILogger } from '../../../logger/types';
8
8
  import { SYNC_SPLITS_FETCH, SYNC_SPLITS_UPDATE, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
9
9
  import { startsWith } from '../../../utils/lang';
@@ -143,7 +143,7 @@ export function splitChangesUpdaterFactory(
143
143
  */
144
144
  function _splitChangesUpdater(since: number, retry = 0): Promise<boolean> {
145
145
  log.debug(SYNC_SPLITS_FETCH, [since]);
146
- const fetcherPromise = Promise.resolve(splitUpdateNotification ?
146
+ return Promise.resolve(splitUpdateNotification ?
147
147
  { splits: [splitUpdateNotification.payload], till: splitUpdateNotification.changeNumber } :
148
148
  splitChangesFetcher(since, noCache, till, _promiseDecorator)
149
149
  )
@@ -154,8 +154,6 @@ export function splitChangesUpdaterFactory(
154
154
 
155
155
  log.debug(SYNC_SPLITS_UPDATE, [mutation.added.length, mutation.removed.length, mutation.segments.length]);
156
156
 
157
- // Write into storage
158
- // @TODO call `setChangeNumber` only if the other storage operations have succeeded, in order to keep storage consistency
159
157
  return Promise.all([
160
158
  splits.update(mutation.added, mutation.removed, splitChanges.till),
161
159
  segments.registerSegments(mutation.segments)
@@ -185,15 +183,6 @@ export function splitChangesUpdaterFactory(
185
183
  }
186
184
  return false;
187
185
  });
188
-
189
- // After triggering the requests, if we have cached splits information let's notify that to emit SDK_READY_FROM_CACHE.
190
- // Wrapping in a promise since checkCache can be async.
191
- if (splitsEventEmitter && startingUp) {
192
- Promise.resolve(splits.checkCache()).then(isCacheReady => {
193
- if (isCacheReady) splitsEventEmitter.emit(SDK_SPLITS_CACHE_LOADED);
194
- });
195
- }
196
- return fetcherPromise;
197
186
  }
198
187
 
199
188
  let sincePromise = Promise.resolve(splits.getChangeNumber()); // `getChangeNumber` never rejects or throws error
@@ -9,6 +9,7 @@ import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '..
9
9
  import { isConsentGranted } from '../consent';
10
10
  import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
11
11
  import { ISdkFactoryContextSync } from '../sdkFactory/types';
12
+ import { SDK_SPLITS_CACHE_LOADED } from '../readiness/constants';
12
13
 
13
14
  /**
14
15
  * Online SyncManager factory.
@@ -28,7 +29,7 @@ export function syncManagerOnlineFactory(
28
29
  */
29
30
  return function (params: ISdkFactoryContextSync): ISyncManagerCS {
30
31
 
31
- const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker } = params;
32
+ const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker, storage, readiness } = params;
32
33
 
33
34
  /** Polling Manager */
34
35
  const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
@@ -87,6 +88,11 @@ export function syncManagerOnlineFactory(
87
88
  start() {
88
89
  running = true;
89
90
 
91
+ if (startFirstTime) {
92
+ const isCacheLoaded = storage.validateCache ? storage.validateCache() : false;
93
+ if (isCacheLoaded) Promise.resolve().then(() => { readiness.splits.emit(SDK_SPLITS_CACHE_LOADED); });
94
+ }
95
+
90
96
  // start syncing splits and segments
91
97
  if (pollingManager) {
92
98
 
@@ -96,7 +102,6 @@ export function syncManagerOnlineFactory(
96
102
  // Doesn't call `syncAll` when the syncManager is resuming
97
103
  if (startFirstTime) {
98
104
  pollingManager.syncAll();
99
- startFirstTime = false;
100
105
  }
101
106
  pushManager.start();
102
107
  } else {
@@ -105,13 +110,14 @@ export function syncManagerOnlineFactory(
105
110
  } else {
106
111
  if (startFirstTime) {
107
112
  pollingManager.syncAll();
108
- startFirstTime = false;
109
113
  }
110
114
  }
111
115
  }
112
116
 
113
117
  // start periodic data recording (events, impressions, telemetry).
114
118
  submitterManager.start(!isConsentGranted(settings));
119
+
120
+ startFirstTime = false;
115
121
  },
116
122
 
117
123
  /**
@@ -14,6 +14,8 @@ export function strategyDebugFactory(
14
14
 
15
15
  return {
16
16
  process(impression: SplitIO.ImpressionDTO) {
17
+ if (impression.properties) return true;
18
+
17
19
  impression.pt = impressionsObserver.testAndSet(impression);
18
20
  return true;
19
21
  }
@@ -120,7 +120,7 @@ export function isBoolean(val: any): boolean {
120
120
  * Unlike `Number.isFinite`, it also tests Number object instances.
121
121
  * Unlike global `isFinite`, it returns false if the value is not a number or Number object instance.
122
122
  */
123
- export function isFiniteNumber(val: any): boolean {
123
+ export function isFiniteNumber(val: any): val is number {
124
124
  if (val instanceof Number) val = val.valueOf();
125
125
  return typeof val === 'number' ?
126
126
  Number.isFinite ? Number.isFinite(val) : isFinite(val) :
@@ -8,7 +8,7 @@ import { IStorageFactoryParams, IStorageSync } from '../../../storages/types';
8
8
 
9
9
  export function __InLocalStorageMockFactory(params: IStorageFactoryParams): IStorageSync {
10
10
  const result = InMemoryStorageCSFactory(params);
11
- result.splits.checkCache = () => true; // to emit SDK_READY_FROM_CACHE
11
+ result.validateCache = () => true; // to emit SDK_READY_FROM_CACHE
12
12
  return result;
13
13
  }
14
14
  __InLocalStorageMockFactory.type = STORAGE_MEMORY;
@@ -782,6 +782,9 @@ declare namespace SplitIO {
782
782
  * Evaluation options object for getTreatment methods.
783
783
  */
784
784
  type EvaluationOptions = {
785
+ /**
786
+ * Optional properties to append to the generated impression object sent to Split backend.
787
+ */
785
788
  properties?: Properties;
786
789
  }
787
790
  /**
@@ -944,6 +947,18 @@ declare namespace SplitIO {
944
947
  * @defaultValue `'SPLITIO'`
945
948
  */
946
949
  prefix?: string;
950
+ /**
951
+ * Number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
952
+ *
953
+ * @defaultValue `10`
954
+ */
955
+ expirationDays?: number;
956
+ /**
957
+ * Optional settings to clear the cache. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
958
+ *
959
+ * @defaultValue `false`
960
+ */
961
+ clearOnInit?: boolean;
947
962
  }
948
963
  /**
949
964
  * Storage for asynchronous (consumer) SDK.
@@ -1267,11 +1282,23 @@ declare namespace SplitIO {
1267
1282
  */
1268
1283
  type?: BrowserStorage;
1269
1284
  /**
1270
- * Optional prefix to prevent any kind of data collision between SDK versions.
1285
+ * Optional prefix to prevent any kind of data collision between SDK versions when using 'LOCALSTORAGE'.
1271
1286
  *
1272
1287
  * @defaultValue `'SPLITIO'`
1273
1288
  */
1274
1289
  prefix?: string;
1290
+ /**
1291
+ * Optional settings for the 'LOCALSTORAGE' storage type. It specifies the number of days before cached data expires if it was not updated. If cache expires, it is cleared on initialization.
1292
+ *
1293
+ * @defaultValue `10`
1294
+ */
1295
+ expirationDays?: number;
1296
+ /**
1297
+ * Optional settings for the 'LOCALSTORAGE' storage type. If set to `true`, the SDK clears the cached data on initialization, unless the cache was cleared within the last 24 hours.
1298
+ *
1299
+ * @defaultValue `false`
1300
+ */
1301
+ clearOnInit?: boolean;
1275
1302
  };
1276
1303
  }
1277
1304
  /**
@@ -1,5 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_CACHE_EXPIRATION_IN_MILLIS = void 0;
4
- // This value might be eventually set via a config parameter
5
- exports.DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days
@@ -1,2 +0,0 @@
1
- // This value might be eventually set via a config parameter
2
- export var DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days
@@ -1,2 +0,0 @@
1
- // This value might be eventually set via a config parameter
2
- export const DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days