@statsig/client-core 3.25.0-beta.1 → 3.25.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statsig/client-core",
3
- "version": "3.25.0-beta.1",
3
+ "version": "3.25.1",
4
4
  "license": "ISC",
5
5
  "homepage": "https://github.com/statsig-io/js-client-monorepo",
6
6
  "repository": {
@@ -9,6 +9,7 @@ export declare abstract class DataAdapterCore {
9
9
  private _sdkKey;
10
10
  private _inMemoryCache;
11
11
  private _lastModifiedStoreKey;
12
+ private _cacheLimit;
12
13
  protected constructor(_adapterName: string, _cacheSuffix: string);
13
14
  attach(sdkKey: string, options: AnyStatsigOptions | null, _network: NetworkCore | null): void;
14
15
  getDataSync(user?: StatsigUser | undefined): DataAdapterResult | null;
@@ -16,12 +16,14 @@ const StatsigUser_1 = require("./StatsigUser");
16
16
  const StorageProvider_1 = require("./StorageProvider");
17
17
  const TypedJsonParse_1 = require("./TypedJsonParse");
18
18
  const CACHE_LIMIT = 10;
19
+ const MAX_CACHE_WRITE_ATTEMPTS = 8;
19
20
  class DataAdapterCore {
20
21
  constructor(_adapterName, _cacheSuffix) {
21
22
  this._adapterName = _adapterName;
22
23
  this._cacheSuffix = _cacheSuffix;
23
24
  this._options = null;
24
25
  this._sdkKey = null;
26
+ this._cacheLimit = CACHE_LIMIT;
25
27
  this._lastModifiedStoreKey = `statsig.last_modified_time.${_cacheSuffix}`;
26
28
  this._inMemoryCache = new InMemoryCache();
27
29
  }
@@ -38,7 +40,7 @@ class DataAdapterCore {
38
40
  }
39
41
  const cache = this._loadFromCache(cacheKey);
40
42
  if (cache && this._getIsCacheValueValid(cache)) {
41
- this._inMemoryCache.add(cacheKey, cache);
43
+ this._inMemoryCache.add(cacheKey, cache, this._cacheLimit);
42
44
  return this._inMemoryCache.get(cacheKey, normalized);
43
45
  }
44
46
  return null;
@@ -46,7 +48,7 @@ class DataAdapterCore {
46
48
  setData(data, user) {
47
49
  const normalized = user && (0, StatsigUser_1._normalizeUser)(user, this._options);
48
50
  const cacheKey = this._getCacheKey(normalized);
49
- this._inMemoryCache.add(cacheKey, _makeDataAdapterResult('Bootstrap', data, null, normalized));
51
+ this._inMemoryCache.add(cacheKey, _makeDataAdapterResult('Bootstrap', data, null, normalized), this._cacheLimit);
50
52
  }
51
53
  _getIsCacheValueValid(current) {
52
54
  return (current.stableID == null ||
@@ -74,7 +76,7 @@ class DataAdapterCore {
74
76
  const cacheKey = this._getCacheKey(normalized);
75
77
  const result = yield this._getDataAsyncImpl(null, normalized, options);
76
78
  if (result) {
77
- this._inMemoryCache.add(cacheKey, Object.assign(Object.assign({}, result), { source: 'Prefetch' }));
79
+ this._inMemoryCache.add(cacheKey, Object.assign(Object.assign({}, result), { source: 'Prefetch' }), this._cacheLimit);
78
80
  }
79
81
  });
80
82
  }
@@ -103,7 +105,7 @@ class DataAdapterCore {
103
105
  return null;
104
106
  }
105
107
  const cacheKey = this._getCacheKey(user);
106
- this._inMemoryCache.add(cacheKey, result);
108
+ this._inMemoryCache.add(cacheKey, result, this._cacheLimit);
107
109
  this._writeToCache(cacheKey, result);
108
110
  return result;
109
111
  });
@@ -125,15 +127,30 @@ class DataAdapterCore {
125
127
  return result ? Object.assign(Object.assign({}, result), { source: 'Cache' }) : null;
126
128
  }
127
129
  _writeToCache(cacheKey, result) {
128
- StorageProvider_1.Storage.setItem(cacheKey, JSON.stringify(result));
130
+ const resultString = JSON.stringify(result);
131
+ for (let i = 0; i < MAX_CACHE_WRITE_ATTEMPTS; i++) {
132
+ try {
133
+ StorageProvider_1.Storage.setItem(cacheKey, resultString);
134
+ break;
135
+ }
136
+ catch (error) {
137
+ if (!(error instanceof Error) ||
138
+ error.name !== 'QuotaExceededError' ||
139
+ this._cacheLimit <= 1) {
140
+ throw error;
141
+ }
142
+ this._cacheLimit = Math.ceil(this._cacheLimit / 2);
143
+ this._runLocalStorageCacheEviction(cacheKey, this._cacheLimit - 1);
144
+ }
145
+ }
129
146
  this._runLocalStorageCacheEviction(cacheKey);
130
147
  }
131
- _runLocalStorageCacheEviction(cacheKey) {
148
+ _runLocalStorageCacheEviction(cacheKey, cacheLimit = this._cacheLimit) {
132
149
  var _a;
133
150
  const lastModifiedTimeMap = (_a = (0, StorageProvider_1._getObjectFromStorage)(this._lastModifiedStoreKey)) !== null && _a !== void 0 ? _a : {};
134
151
  lastModifiedTimeMap[cacheKey] = Date.now();
135
- const evictable = _getEvictableKey(lastModifiedTimeMap, CACHE_LIMIT);
136
- if (evictable) {
152
+ const evictableKeys = _getEvictableKeys(lastModifiedTimeMap, cacheLimit);
153
+ for (const evictable of evictableKeys) {
137
154
  delete lastModifiedTimeMap[evictable];
138
155
  StorageProvider_1.Storage.removeItem(evictable);
139
156
  }
@@ -166,10 +183,10 @@ class InMemoryCache {
166
183
  }
167
184
  return result;
168
185
  }
169
- add(cacheKey, value) {
170
- const oldest = _getEvictableKey(this._data, CACHE_LIMIT - 1);
171
- if (oldest) {
172
- delete this._data[oldest];
186
+ add(cacheKey, value, cacheLimit) {
187
+ const evictableKeys = _getEvictableKeys(this._data, cacheLimit - 1);
188
+ for (const evictable of evictableKeys) {
189
+ delete this._data[evictable];
173
190
  }
174
191
  this._data[cacheKey] = value;
175
192
  }
@@ -177,17 +194,22 @@ class InMemoryCache {
177
194
  this._data = Object.assign(Object.assign({}, this._data), values);
178
195
  }
179
196
  }
180
- function _getEvictableKey(data, limit) {
197
+ function _getEvictableKeys(data, limit) {
181
198
  const keys = Object.keys(data);
182
199
  if (keys.length <= limit) {
183
- return null;
200
+ return [];
201
+ }
202
+ if (limit === 0) {
203
+ return keys;
184
204
  }
185
- return keys.reduce((prevKey, currKey) => {
186
- const prev = data[prevKey];
187
- const current = data[currKey];
188
- if (typeof prev === 'object' && typeof current === 'object') {
189
- return current.receivedAt < prev.receivedAt ? currKey : prevKey;
205
+ return keys
206
+ .sort((keyA, keyB) => {
207
+ const valueA = data[keyA];
208
+ const valueB = data[keyB];
209
+ if (typeof valueA === 'object' && typeof valueB === 'object') {
210
+ return valueA.receivedAt - valueB.receivedAt;
190
211
  }
191
- return current < prev ? currKey : prevKey;
192
- });
212
+ return valueA - valueB;
213
+ })
214
+ .slice(0, keys.length - limit);
193
215
  }
@@ -68,6 +68,15 @@ class EventLogger {
68
68
  this._network.setLogEventCompressionMode(mode);
69
69
  }
70
70
  setLoggingEnabled(loggingEnabled) {
71
+ if (this._loggingEnabled === 'disabled' && loggingEnabled !== 'disabled') {
72
+ // load any pre consented events into memory
73
+ const storageKey = this._getStorageKey();
74
+ const events = (0, StorageProvider_1._getObjectFromStorage)(storageKey);
75
+ if (events) {
76
+ this._queue.push(...events);
77
+ }
78
+ StorageProvider_1.Storage.removeItem(storageKey);
79
+ }
71
80
  this._loggingEnabled = loggingEnabled;
72
81
  }
73
82
  enqueue(event) {
@@ -1,4 +1,4 @@
1
- export declare const SDK_VERSION = "3.25.0-beta.1";
1
+ export declare const SDK_VERSION = "3.25.1";
2
2
  export type StatsigMetadata = {
3
3
  readonly [key: string]: string | undefined | null;
4
4
  readonly appVersion?: string;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StatsigMetadataProvider = exports.SDK_VERSION = void 0;
4
- exports.SDK_VERSION = '3.25.0-beta.1';
4
+ exports.SDK_VERSION = '3.25.1';
5
5
  let metadata = {
6
6
  sdkVersion: exports.SDK_VERSION,
7
7
  sdkType: 'js-mono', // js-mono is overwritten by Precomp and OnDevice clients