@splitsoftware/splitio-commons 1.6.2-rc.12 → 1.6.2-rc.13

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 (58) hide show
  1. package/cjs/listeners/browser.js +9 -11
  2. package/cjs/sdkFactory/index.js +7 -24
  3. package/cjs/storages/inLocalStorage/index.js +14 -10
  4. package/cjs/storages/inMemory/InMemoryStorage.js +10 -7
  5. package/cjs/storages/inMemory/InMemoryStorageCS.js +10 -7
  6. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +57 -34
  7. package/cjs/storages/inRedis/index.js +4 -2
  8. package/cjs/storages/pluggable/index.js +4 -2
  9. package/cjs/sync/submitters/submitterManager.js +1 -1
  10. package/cjs/sync/submitters/telemetrySubmitter.js +4 -40
  11. package/cjs/trackers/impressionObserver/utils.js +1 -17
  12. package/cjs/trackers/uniqueKeysTracker.js +1 -1
  13. package/cjs/utils/settingsValidation/index.js +7 -1
  14. package/esm/listeners/browser.js +9 -11
  15. package/esm/sdkFactory/index.js +7 -24
  16. package/esm/storages/inLocalStorage/index.js +15 -11
  17. package/esm/storages/inMemory/InMemoryStorage.js +10 -7
  18. package/esm/storages/inMemory/InMemoryStorageCS.js +10 -7
  19. package/esm/storages/inMemory/TelemetryCacheInMemory.js +58 -35
  20. package/esm/storages/inRedis/index.js +4 -2
  21. package/esm/storages/pluggable/index.js +4 -2
  22. package/esm/sync/submitters/submitterManager.js +1 -1
  23. package/esm/sync/submitters/telemetrySubmitter.js +4 -39
  24. package/esm/trackers/impressionObserver/utils.js +1 -15
  25. package/esm/trackers/uniqueKeysTracker.js +1 -1
  26. package/esm/utils/settingsValidation/index.js +7 -1
  27. package/package.json +2 -1
  28. package/src/listeners/browser.ts +9 -13
  29. package/src/sdkClient/sdkClient.ts +1 -1
  30. package/src/sdkFactory/index.ts +7 -29
  31. package/src/sdkFactory/types.ts +2 -2
  32. package/src/storages/inLocalStorage/index.ts +16 -11
  33. package/src/storages/inMemory/InMemoryStorage.ts +11 -7
  34. package/src/storages/inMemory/InMemoryStorageCS.ts +11 -7
  35. package/src/storages/inMemory/TelemetryCacheInMemory.ts +66 -33
  36. package/src/storages/inRedis/TelemetryCacheInRedis.ts +1 -1
  37. package/src/storages/inRedis/index.ts +4 -1
  38. package/src/storages/pluggable/TelemetryCachePluggable.ts +1 -1
  39. package/src/storages/pluggable/index.ts +4 -2
  40. package/src/storages/types.ts +41 -60
  41. package/src/sync/submitters/submitter.ts +2 -2
  42. package/src/sync/submitters/submitterManager.ts +1 -1
  43. package/src/sync/submitters/telemetrySubmitter.ts +5 -41
  44. package/src/sync/submitters/types.ts +5 -5
  45. package/src/trackers/impressionObserver/utils.ts +1 -16
  46. package/src/trackers/strategy/strategyNone.ts +9 -9
  47. package/src/trackers/strategy/strategyOptimized.ts +9 -9
  48. package/src/trackers/uniqueKeysTracker.ts +6 -6
  49. package/src/utils/settingsValidation/index.ts +5 -1
  50. package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +19 -8
  51. package/types/storages/types.d.ts +31 -41
  52. package/types/sync/submitters/submitter.d.ts +2 -2
  53. package/types/sync/submitters/telemetrySubmitter.d.ts +2 -10
  54. package/types/sync/submitters/types.d.ts +6 -6
  55. package/types/trackers/impressionObserver/utils.d.ts +0 -8
  56. package/types/trackers/strategy/strategyNone.d.ts +2 -2
  57. package/types/trackers/strategy/strategyOptimized.d.ts +2 -2
  58. package/types/trackers/uniqueKeysTracker.d.ts +1 -1
@@ -4,7 +4,6 @@ import { OPTIMIZED, DEBUG, NONE } from '../utils/constants';
4
4
  import { objectAssign } from '../utils/lang/objectAssign';
5
5
  import { CLEANUP_REGISTERING, CLEANUP_DEREGISTERING } from '../logger/constants';
6
6
  import { isConsentGranted } from '../consent';
7
- import { telemetryCacheStatsAdapter } from '../sync/submitters/telemetrySubmitter';
8
7
  var VISIBILITYCHANGE_EVENT = 'visibilitychange';
9
8
  var PAGEHIDE_EVENT = 'pagehide';
10
9
  var UNLOAD_EVENT = 'unload';
@@ -68,25 +67,25 @@ var BrowserSignalListener = /** @class */ (function () {
68
67
  BrowserSignalListener.prototype.flushData = function () {
69
68
  if (!this.syncManager)
70
69
  return; // In consumer mode there is not sync manager and data to flush
70
+ var _a = this.settings.urls, events = _a.events, telemetry = _a.telemetry;
71
71
  // Flush impressions & events data if there is user consent
72
72
  if (isConsentGranted(this.settings)) {
73
- var eventsUrl = this.settings.urls.events;
74
73
  var sim = this.settings.sync.impressionsMode;
75
74
  var extraMetadata = {
76
75
  // sim stands for Sync/Split Impressions Mode
77
76
  sim: sim === OPTIMIZED ? OPTIMIZED : sim === DEBUG ? DEBUG : NONE
78
77
  };
79
- this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
80
- this._flushData(eventsUrl + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
78
+ this._flushData(events + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
79
+ this._flushData(events + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
81
80
  if (this.storage.impressionCounts)
82
- this._flushData(eventsUrl + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, fromImpressionCountsCollector);
81
+ this._flushData(events + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, fromImpressionCountsCollector);
82
+ // @ts-ignore
83
+ if (this.storage.uniqueKeys)
84
+ this._flushData(telemetry + '/v1/keys/cs/beacon', this.storage.uniqueKeys, this.serviceApi.postUniqueKeysBulkCs);
83
85
  }
84
86
  // Flush telemetry data
85
- if (this.storage.telemetry) {
86
- var telemetryUrl = this.settings.urls.telemetry;
87
- var telemetryCacheAdapter = telemetryCacheStatsAdapter(this.storage.telemetry, this.storage.splits, this.storage.segments);
88
- this._flushData(telemetryUrl + '/v1/metrics/usage/beacon', telemetryCacheAdapter, this.serviceApi.postMetricsUsage);
89
- }
87
+ if (this.storage.telemetry)
88
+ this._flushData(telemetry + '/v1/metrics/usage/beacon', this.storage.telemetry, this.serviceApi.postMetricsUsage);
90
89
  };
91
90
  BrowserSignalListener.prototype.flushDataIfHidden = function () {
92
91
  // Precondition: document defined
@@ -100,7 +99,6 @@ var BrowserSignalListener = /** @class */ (function () {
100
99
  if (!this._sendBeacon(url, dataPayload, extraMetadata)) {
101
100
  postService(JSON.stringify(dataPayload)).catch(function () { }); // no-op just to catch a possible exception
102
101
  }
103
- cache.clear();
104
102
  }
105
103
  };
106
104
  /**
@@ -2,12 +2,9 @@ import { sdkReadinessManagerFactory } from '../readiness/sdkReadinessManager';
2
2
  import { impressionsTrackerFactory } from '../trackers/impressionsTracker';
3
3
  import { eventTrackerFactory } from '../trackers/eventTracker';
4
4
  import { telemetryTrackerFactory } from '../trackers/telemetryTracker';
5
- import { getMatching } from '../utils/key';
6
- import { shouldBeOptimized } from '../trackers/impressionObserver/utils';
7
5
  import { validateAndTrackApiKey } from '../utils/inputValidation/apiKey';
8
6
  import { createLoggerAPI } from '../logger/sdkLogger';
9
7
  import { NEW_FACTORY, RETRIEVE_MANAGER } from '../logger/constants';
10
- import { metadataBuilder } from '../storages/metadataBuilder';
11
8
  import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
12
9
  import { objectAssign } from '../utils/lang/objectAssign';
13
10
  import { strategyDebugFactory } from '../trackers/strategy/strategyDebug';
@@ -20,43 +17,29 @@ import { NONE, OPTIMIZED } from '../utils/constants';
20
17
  */
21
18
  export function sdkFactory(params) {
22
19
  var settings = params.settings, platform = params.platform, storageFactory = params.storageFactory, splitApiFactory = params.splitApiFactory, extraProps = params.extraProps, syncManagerFactory = params.syncManagerFactory, SignalListener = params.SignalListener, impressionsObserverFactory = params.impressionsObserverFactory, integrationsManagerFactory = params.integrationsManagerFactory, sdkManagerFactory = params.sdkManagerFactory, sdkClientMethodFactory = params.sdkClientMethodFactory, filterAdapterFactory = params.filterAdapterFactory;
23
- var log = settings.log;
20
+ var log = settings.log, impressionsMode = settings.sync.impressionsMode;
24
21
  // @TODO handle non-recoverable errors, such as, global `fetch` not available, invalid API Key, etc.
25
22
  // On non-recoverable errors, we should mark the SDK as destroyed and not start synchronization.
26
23
  // We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
27
24
  validateAndTrackApiKey(log, settings.core.authorizationKey);
28
25
  var sdkReadinessManager = sdkReadinessManagerFactory(log, platform.EventEmitter, settings.startup.readyTimeout);
29
26
  var readiness = sdkReadinessManager.readinessManager;
30
- // @TODO consider passing the settings object, so that each storage access only what it needs
31
- var storageFactoryParams = {
32
- impressionsQueueSize: settings.scheduler.impressionsQueueSize,
33
- eventsQueueSize: settings.scheduler.eventsQueueSize,
34
- optimize: shouldBeOptimized(settings),
35
- // ATM, only used by InLocalStorage
36
- matchingKey: getMatching(settings.core.key),
37
- splitFiltersValidation: settings.sync.__splitFiltersValidation,
38
- // ATM, only used by PluggableStorage
39
- mode: settings.mode,
40
- impressionsMode: settings.sync.impressionsMode,
41
- // Callback used to emit SDK_READY in consumer mode, where `syncManagerFactory` is undefined,
42
- // or partial consumer mode, where it only has submitters, and therefore it doesn't emit readiness events.
27
+ var storage = storageFactory({
28
+ settings: settings,
43
29
  onReadyCb: function (error) {
44
30
  if (error)
45
31
  return; // Don't emit SDK_READY if storage failed to connect. Error message is logged by wrapperAdapter
46
32
  readiness.splits.emit(SDK_SPLITS_ARRIVED);
47
33
  readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
48
34
  },
49
- metadata: metadataBuilder(settings),
50
- log: log
51
- };
52
- var storage = storageFactory(storageFactoryParams);
35
+ });
53
36
  // @TODO add support for dataloader: `if (params.dataLoader) params.dataLoader(storage);`
54
37
  var telemetryTracker = telemetryTrackerFactory(storage.telemetry, platform.now);
55
38
  var integrationsManager = integrationsManagerFactory && integrationsManagerFactory({ settings: settings, storage: storage, telemetryTracker: telemetryTracker });
56
39
  var observer = impressionsObserverFactory();
57
- var uniqueKeysTracker = storageFactoryParams.impressionsMode === NONE ? uniqueKeysTrackerFactory(log, storage.uniqueKeys, filterAdapterFactory && filterAdapterFactory()) : undefined;
40
+ var uniqueKeysTracker = impressionsMode === NONE ? uniqueKeysTrackerFactory(log, storage.uniqueKeys, filterAdapterFactory && filterAdapterFactory()) : undefined;
58
41
  var strategy;
59
- switch (storageFactoryParams.impressionsMode) {
42
+ switch (impressionsMode) {
60
43
  case OPTIMIZED:
61
44
  strategy = strategyOptimizedFactory(observer, storage.impressionCounts);
62
45
  break;
@@ -91,7 +74,7 @@ export function sdkFactory(params) {
91
74
  return managerInstance;
92
75
  },
93
76
  // Logger wrapper API
94
- Logger: createLoggerAPI(settings.log),
77
+ Logger: createLoggerAPI(log),
95
78
  settings: settings,
96
79
  }, extraProps && extraProps(ctx));
97
80
  }
@@ -11,9 +11,10 @@ import { SplitsCacheInMemory } from '../inMemory/SplitsCacheInMemory';
11
11
  import { DEFAULT_CACHE_EXPIRATION_IN_MILLIS } from '../../utils/constants/browser';
12
12
  import { InMemoryStorageCSFactory } from '../inMemory/InMemoryStorageCS';
13
13
  import { LOG_PREFIX } from './constants';
14
- import { NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
14
+ import { DEBUG, NONE, STORAGE_LOCALSTORAGE } from '../../utils/constants';
15
15
  import { shouldRecordTelemetry, TelemetryCacheInMemory } from '../inMemory/TelemetryCacheInMemory';
16
16
  import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
17
+ import { getMatching } from '../../utils/key';
17
18
  /**
18
19
  * InLocal storage factory for standalone client-side SplitFactory
19
20
  */
@@ -23,20 +24,23 @@ export function InLocalStorage(options) {
23
24
  function InLocalStorageCSFactory(params) {
24
25
  // Fallback to InMemoryStorage if LocalStorage API is not available
25
26
  if (!isLocalStorageAvailable()) {
26
- params.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
27
+ params.settings.log.warn(LOG_PREFIX + 'LocalStorage API is unavailable. Falling back to default MEMORY storage');
27
28
  return InMemoryStorageCSFactory(params);
28
29
  }
29
- var log = params.log;
30
- var keys = new KeyBuilderCS(prefix, params.matchingKey);
30
+ var settings = params.settings, _a = params.settings, log = _a.log, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, _c = _a.sync, impressionsMode = _c.impressionsMode, __splitFiltersValidation = _c.__splitFiltersValidation;
31
+ var matchingKey = getMatching(settings.core.key);
32
+ var keys = new KeyBuilderCS(prefix, matchingKey);
31
33
  var expirationTimestamp = Date.now() - DEFAULT_CACHE_EXPIRATION_IN_MILLIS;
34
+ var splits = new SplitsCacheInLocal(log, keys, expirationTimestamp, __splitFiltersValidation);
35
+ var segments = new MySegmentsCacheInLocal(log, keys);
32
36
  return {
33
- splits: new SplitsCacheInLocal(log, keys, expirationTimestamp, params.splitFiltersValidation),
34
- segments: new MySegmentsCacheInLocal(log, keys),
35
- impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
36
- impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory() : undefined,
37
- events: new EventsCacheInMemory(params.eventsQueueSize),
38
- telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
39
- uniqueKeys: params.impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
37
+ splits: splits,
38
+ segments: segments,
39
+ impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
40
+ impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
41
+ events: new EventsCacheInMemory(eventsQueueSize),
42
+ telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
43
+ uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
40
44
  destroy: function () {
41
45
  var _a;
42
46
  this.splits = new SplitsCacheInMemory();
@@ -12,14 +12,17 @@ import { UniqueKeysCacheInMemory } from './UniqueKeysCacheInMemory';
12
12
  * @param params parameters required by EventsCacheSync
13
13
  */
14
14
  export function InMemoryStorageFactory(params) {
15
+ var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, impressionsMode = _a.sync.impressionsMode;
16
+ var splits = new SplitsCacheInMemory();
17
+ var segments = new SegmentsCacheInMemory();
15
18
  return {
16
- splits: new SplitsCacheInMemory(),
17
- segments: new SegmentsCacheInMemory(),
18
- impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
19
- impressionCounts: params.impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
20
- events: new EventsCacheInMemory(params.eventsQueueSize),
21
- telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
22
- uniqueKeys: params.impressionsMode === NONE ? new UniqueKeysCacheInMemory() : undefined,
19
+ splits: splits,
20
+ segments: segments,
21
+ impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
22
+ impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
23
+ events: new EventsCacheInMemory(eventsQueueSize),
24
+ telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
25
+ uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemory() : undefined,
23
26
  // When using MEMORY we should clean all the caches to leave them empty
24
27
  destroy: function () {
25
28
  var _a;
@@ -12,14 +12,17 @@ import { UniqueKeysCacheInMemoryCS } from './UniqueKeysCacheInMemoryCS';
12
12
  * @param params parameters required by EventsCacheSync
13
13
  */
14
14
  export function InMemoryStorageCSFactory(params) {
15
+ var _a = params.settings, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize, impressionsMode = _a.sync.impressionsMode;
16
+ var splits = new SplitsCacheInMemory();
17
+ var segments = new MySegmentsCacheInMemory();
15
18
  return {
16
- splits: new SplitsCacheInMemory(),
17
- segments: new MySegmentsCacheInMemory(),
18
- impressions: new ImpressionsCacheInMemory(params.impressionsQueueSize),
19
- impressionCounts: params.impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
20
- events: new EventsCacheInMemory(params.eventsQueueSize),
21
- telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory() : undefined,
22
- uniqueKeys: params.impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
19
+ splits: splits,
20
+ segments: segments,
21
+ impressions: new ImpressionsCacheInMemory(impressionsQueueSize),
22
+ impressionCounts: impressionsMode !== DEBUG ? new ImpressionCountsCacheInMemory() : undefined,
23
+ events: new EventsCacheInMemory(eventsQueueSize),
24
+ telemetry: shouldRecordTelemetry(params) ? new TelemetryCacheInMemory(splits, segments) : undefined,
25
+ uniqueKeys: impressionsMode === NONE ? new UniqueKeysCacheInMemoryCS() : undefined,
23
26
  // When using MEMORY we should clean all the caches to leave them empty
24
27
  destroy: function () {
25
28
  var _a;
@@ -1,4 +1,4 @@
1
- import { LOCALHOST_MODE } from '../../utils/constants';
1
+ import { DEDUPED, DROPPED, LOCALHOST_MODE, QUEUED } from '../../utils/constants';
2
2
  import { findLatencyIndex } from '../findLatencyIndex';
3
3
  var MAX_STREAMING_EVENTS = 20;
4
4
  var MAX_TAGS = 10;
@@ -13,29 +13,55 @@ var ACCEPTANCE_RANGE = 0.001;
13
13
  * Record telemetry if mode is not localhost.
14
14
  * All factory instances track telemetry on server-side, and 0.1% on client-side.
15
15
  */
16
- export function shouldRecordTelemetry(params) {
17
- return params.mode !== LOCALHOST_MODE && (params.matchingKey === undefined || Math.random() <= ACCEPTANCE_RANGE);
16
+ export function shouldRecordTelemetry(_a) {
17
+ var settings = _a.settings;
18
+ return settings.mode !== LOCALHOST_MODE && (settings.core.key === undefined || Math.random() <= ACCEPTANCE_RANGE);
18
19
  }
19
20
  var TelemetryCacheInMemory = /** @class */ (function () {
20
- function TelemetryCacheInMemory() {
21
+ function TelemetryCacheInMemory(splits, segments) {
22
+ this.splits = splits;
23
+ this.segments = segments;
24
+ // isEmpty flag
25
+ this.e = true;
21
26
  this.notReadyUsage = 0;
27
+ /** Usage stats */
22
28
  this.impressionStats = [0, 0, 0];
23
29
  this.eventStats = [0, 0];
24
- // @ts-expect-error
25
30
  this.lastSync = {};
26
- // @ts-expect-error
27
31
  this.httpErrors = {};
28
- // @ts-expect-error
29
32
  this.httpLatencies = {};
30
33
  this.authRejections = 0;
31
34
  this.tokenRefreshes = 0;
32
35
  this.streamingEvents = [];
33
36
  this.tags = [];
34
- // @ts-expect-error
35
37
  this.exceptions = {};
36
- // @ts-expect-error
37
38
  this.latencies = {};
38
39
  }
40
+ TelemetryCacheInMemory.prototype.isEmpty = function () { return this.e; };
41
+ TelemetryCacheInMemory.prototype.clear = function () { };
42
+ TelemetryCacheInMemory.prototype.pop = function () {
43
+ this.e = true;
44
+ return {
45
+ lS: this.getLastSynchronization(),
46
+ mL: this.popLatencies(),
47
+ mE: this.popExceptions(),
48
+ hE: this.popHttpErrors(),
49
+ hL: this.popHttpLatencies(),
50
+ tR: this.popTokenRefreshes(),
51
+ aR: this.popAuthRejections(),
52
+ iQ: this.getImpressionStats(QUEUED),
53
+ iDe: this.getImpressionStats(DEDUPED),
54
+ iDr: this.getImpressionStats(DROPPED),
55
+ spC: this.splits && this.splits.getSplitNames().length,
56
+ seC: this.segments && this.segments.getRegisteredSegments().length,
57
+ skC: this.segments && this.segments.getKeysCount(),
58
+ sL: this.getSessionLength(),
59
+ eQ: this.getEventStats(QUEUED),
60
+ eD: this.getEventStats(DROPPED),
61
+ sE: this.popStreamingEvents(),
62
+ t: this.popTags(),
63
+ };
64
+ };
39
65
  TelemetryCacheInMemory.prototype.getTimeUntilReady = function () {
40
66
  return this.timeUntilReady;
41
67
  };
@@ -59,44 +85,41 @@ var TelemetryCacheInMemory = /** @class */ (function () {
59
85
  };
60
86
  TelemetryCacheInMemory.prototype.recordImpressionStats = function (type, count) {
61
87
  this.impressionStats[type] += count;
88
+ this.e = false;
62
89
  };
63
90
  TelemetryCacheInMemory.prototype.getEventStats = function (type) {
64
91
  return this.eventStats[type];
65
92
  };
66
93
  TelemetryCacheInMemory.prototype.recordEventStats = function (type, count) {
67
94
  this.eventStats[type] += count;
95
+ this.e = false;
68
96
  };
69
97
  TelemetryCacheInMemory.prototype.getLastSynchronization = function () {
70
98
  return this.lastSync;
71
99
  };
72
100
  TelemetryCacheInMemory.prototype.recordSuccessfulSync = function (resource, timeMs) {
73
101
  this.lastSync[resource] = timeMs;
102
+ this.e = false;
74
103
  };
75
104
  TelemetryCacheInMemory.prototype.popHttpErrors = function () {
76
- var result = this.httpErrors; // @ts-expect-error
105
+ var result = this.httpErrors;
77
106
  this.httpErrors = {};
78
107
  return result;
79
108
  };
80
109
  TelemetryCacheInMemory.prototype.recordHttpError = function (resource, status) {
81
- if (!this.httpErrors[resource])
82
- this.httpErrors[resource] = {};
83
- if (!this.httpErrors[resource][status]) {
84
- this.httpErrors[resource][status] = 1;
85
- }
86
- else {
87
- this.httpErrors[resource][status]++;
88
- }
110
+ var statusErrors = (this.httpErrors[resource] = this.httpErrors[resource] || {});
111
+ statusErrors[status] = (statusErrors[status] || 0) + 1;
112
+ this.e = false;
89
113
  };
90
114
  TelemetryCacheInMemory.prototype.popHttpLatencies = function () {
91
- var result = this.httpLatencies; // @ts-expect-error
115
+ var result = this.httpLatencies;
92
116
  this.httpLatencies = {};
93
117
  return result;
94
118
  };
95
119
  TelemetryCacheInMemory.prototype.recordHttpLatency = function (resource, latencyMs) {
96
- if (!this.httpLatencies[resource]) {
97
- this.httpLatencies[resource] = newBuckets();
98
- }
99
- this.httpLatencies[resource][findLatencyIndex(latencyMs)]++;
120
+ var latencyBuckets = (this.httpLatencies[resource] = this.httpLatencies[resource] || newBuckets());
121
+ latencyBuckets[findLatencyIndex(latencyMs)]++;
122
+ this.e = false;
100
123
  };
101
124
  TelemetryCacheInMemory.prototype.popAuthRejections = function () {
102
125
  var result = this.authRejections;
@@ -105,6 +128,7 @@ var TelemetryCacheInMemory = /** @class */ (function () {
105
128
  };
106
129
  TelemetryCacheInMemory.prototype.recordAuthRejections = function () {
107
130
  this.authRejections++;
131
+ this.e = false;
108
132
  };
109
133
  TelemetryCacheInMemory.prototype.popTokenRefreshes = function () {
110
134
  var result = this.tokenRefreshes;
@@ -113,6 +137,7 @@ var TelemetryCacheInMemory = /** @class */ (function () {
113
137
  };
114
138
  TelemetryCacheInMemory.prototype.recordTokenRefreshes = function () {
115
139
  this.tokenRefreshes++;
140
+ this.e = false;
116
141
  };
117
142
  TelemetryCacheInMemory.prototype.popStreamingEvents = function () {
118
143
  return this.streamingEvents.splice(0);
@@ -121,6 +146,7 @@ var TelemetryCacheInMemory = /** @class */ (function () {
121
146
  if (this.streamingEvents.length < MAX_STREAMING_EVENTS) {
122
147
  this.streamingEvents.push(streamingEvent);
123
148
  }
149
+ this.e = false;
124
150
  };
125
151
  TelemetryCacheInMemory.prototype.popTags = function () {
126
152
  return this.tags.splice(0);
@@ -129,36 +155,33 @@ var TelemetryCacheInMemory = /** @class */ (function () {
129
155
  if (this.tags.length < MAX_TAGS) {
130
156
  this.tags.push(tag);
131
157
  }
158
+ this.e = false;
132
159
  };
133
160
  TelemetryCacheInMemory.prototype.getSessionLength = function () {
134
161
  return this.sessionLength;
135
162
  };
136
163
  TelemetryCacheInMemory.prototype.recordSessionLength = function (ms) {
137
164
  this.sessionLength = ms;
165
+ this.e = false;
138
166
  };
139
167
  TelemetryCacheInMemory.prototype.popExceptions = function () {
140
- var result = this.exceptions; // @ts-expect-error
168
+ var result = this.exceptions;
141
169
  this.exceptions = {};
142
170
  return result;
143
171
  };
144
172
  TelemetryCacheInMemory.prototype.recordException = function (method) {
145
- if (!this.exceptions[method]) {
146
- this.exceptions[method] = 1;
147
- }
148
- else {
149
- this.exceptions[method]++;
150
- }
173
+ this.exceptions[method] = (this.exceptions[method] || 0) + 1;
174
+ this.e = false;
151
175
  };
152
176
  TelemetryCacheInMemory.prototype.popLatencies = function () {
153
- var result = this.latencies; // @ts-expect-error
177
+ var result = this.latencies;
154
178
  this.latencies = {};
155
179
  return result;
156
180
  };
157
181
  TelemetryCacheInMemory.prototype.recordLatency = function (method, latencyMs) {
158
- if (!this.latencies[method]) {
159
- this.latencies[method] = newBuckets();
160
- }
161
- this.latencies[method][findLatencyIndex(latencyMs)]++;
182
+ var latencyBuckets = (this.latencies[method] = this.latencies[method] || newBuckets());
183
+ latencyBuckets[findLatencyIndex(latencyMs)]++;
184
+ this.e = false;
162
185
  };
163
186
  return TelemetryCacheInMemory;
164
187
  }());
@@ -9,6 +9,7 @@ import { DEBUG, NONE, STORAGE_REDIS } from '../../utils/constants';
9
9
  import { TelemetryCacheInRedis } from './TelemetryCacheInRedis';
10
10
  import { UniqueKeysCacheInRedis } from './UniqueKeysCacheInRedis';
11
11
  import { ImpressionCountsCacheInRedis } from './ImpressionCountsCacheInRedis';
12
+ import { metadataBuilder } from '../metadataBuilder';
12
13
  /**
13
14
  * InRedis storage factory for consumer server-side SplitFactory, that uses `Ioredis` Redis client for Node.
14
15
  * @see {@link https://www.npmjs.com/package/ioredis}
@@ -16,8 +17,9 @@ import { ImpressionCountsCacheInRedis } from './ImpressionCountsCacheInRedis';
16
17
  export function InRedisStorage(options) {
17
18
  if (options === void 0) { options = {}; }
18
19
  var prefix = validatePrefix(options.prefix);
19
- function InRedisStorageFactory(_a) {
20
- var log = _a.log, metadata = _a.metadata, onReadyCb = _a.onReadyCb, impressionsMode = _a.impressionsMode;
20
+ function InRedisStorageFactory(params) {
21
+ var onReadyCb = params.onReadyCb, settings = params.settings, _a = params.settings, log = _a.log, impressionsMode = _a.sync.impressionsMode;
22
+ var metadata = metadataBuilder(settings);
21
23
  var keys = new KeyBuilderSS(prefix, metadata);
22
24
  var redisClient = new RedisAdapter(log, options.options || {});
23
25
  var telemetry = new TelemetryCacheInRedis(log, keys, redisClient);
@@ -17,6 +17,7 @@ import { ImpressionCountsCachePluggable } from './ImpressionCountsCachePluggable
17
17
  import { UniqueKeysCachePluggable } from './UniqueKeysCachePluggable';
18
18
  import { UniqueKeysCacheInMemory } from '../inMemory/UniqueKeysCacheInMemory';
19
19
  import { UniqueKeysCacheInMemoryCS } from '../inMemory/UniqueKeysCacheInMemoryCS';
20
+ import { metadataBuilder } from '../metadataBuilder';
20
21
  var NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
21
22
  var NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';
22
23
  /**
@@ -49,7 +50,8 @@ export function PluggableStorage(options) {
49
50
  validatePluggableStorageOptions(options);
50
51
  var prefix = validatePrefix(options.prefix);
51
52
  function PluggableStorageFactory(params) {
52
- var log = params.log, metadata = params.metadata, onReadyCb = params.onReadyCb, mode = params.mode, eventsQueueSize = params.eventsQueueSize, impressionsQueueSize = params.impressionsQueueSize, impressionsMode = params.impressionsMode, matchingKey = params.matchingKey;
53
+ var onReadyCb = params.onReadyCb, settings = params.settings, _a = params.settings, log = _a.log, mode = _a.mode, impressionsMode = _a.sync.impressionsMode, _b = _a.scheduler, impressionsQueueSize = _b.impressionsQueueSize, eventsQueueSize = _b.eventsQueueSize;
54
+ var metadata = metadataBuilder(settings);
53
55
  var keys = new KeyBuilderSS(prefix, metadata);
54
56
  var wrapper = wrapperAdapter(log, options.wrapper);
55
57
  var isSyncronizer = mode === undefined; // If mode is not defined, the synchronizer is running
@@ -66,7 +68,7 @@ export function PluggableStorage(options) {
66
68
  undefined;
67
69
  var uniqueKeysCache = impressionsMode === NONE || isSyncronizer ?
68
70
  isPartialConsumer ?
69
- matchingKey === undefined ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
71
+ settings.core.key === undefined ? new UniqueKeysCacheInMemory() : new UniqueKeysCacheInMemoryCS() :
70
72
  new UniqueKeysCachePluggable(log, keys.buildUniqueKeysKey(), wrapper) :
71
73
  undefined;
72
74
  // Connects to wrapper and emits SDK_READY event on main client
@@ -12,7 +12,7 @@ export function submitterManagerFactory(params) {
12
12
  if (impressionCountsSubmitter)
13
13
  submitters.push(impressionCountsSubmitter);
14
14
  var telemetrySubmitter = telemetrySubmitterFactory(params);
15
- if (params.uniqueKeysTracker)
15
+ if (params.storage.uniqueKeys)
16
16
  submitters.push(uniqueKeysSubmitterFactory(params));
17
17
  return {
18
18
  // `onlyTelemetry` true if SDK is created with userConsent not GRANTED
@@ -1,44 +1,11 @@
1
1
  var _a, _b, _c;
2
2
  import { submitterFactory, firstPushWindowDecorator } from './submitter';
3
- import { QUEUED, DEDUPED, DROPPED, CONSUMER_MODE, CONSUMER_ENUM, STANDALONE_MODE, CONSUMER_PARTIAL_MODE, STANDALONE_ENUM, CONSUMER_PARTIAL_ENUM, OPTIMIZED, DEBUG, NONE, DEBUG_ENUM, OPTIMIZED_ENUM, NONE_ENUM, CONSENT_GRANTED, CONSENT_DECLINED, CONSENT_UNKNOWN } from '../../utils/constants';
3
+ import { CONSUMER_MODE, CONSUMER_ENUM, STANDALONE_MODE, CONSUMER_PARTIAL_MODE, STANDALONE_ENUM, CONSUMER_PARTIAL_ENUM, OPTIMIZED, DEBUG, NONE, DEBUG_ENUM, OPTIMIZED_ENUM, NONE_ENUM, CONSENT_GRANTED, CONSENT_DECLINED, CONSENT_UNKNOWN } from '../../utils/constants';
4
4
  import { SDK_READY, SDK_READY_FROM_CACHE } from '../../readiness/constants';
5
5
  import { base } from '../../utils/settingsValidation';
6
6
  import { usedKeysMap } from '../../utils/inputValidation/apiKey';
7
7
  import { timer } from '../../utils/timeTracker/timer';
8
8
  import { objectAssign } from '../../utils/lang/objectAssign';
9
- import { isStorageSync } from '../../trackers/impressionObserver/utils';
10
- /**
11
- * Converts data from telemetry cache into /metrics/usage request payload.
12
- */
13
- export function telemetryCacheStatsAdapter(telemetry, splits, segments) {
14
- return {
15
- isEmpty: function () { return false; },
16
- clear: function () { },
17
- // @TODO consider moving inside telemetry cache for code size reduction
18
- pop: function () {
19
- return {
20
- lS: telemetry.getLastSynchronization(),
21
- mL: telemetry.popLatencies(),
22
- mE: telemetry.popExceptions(),
23
- hE: telemetry.popHttpErrors(),
24
- hL: telemetry.popHttpLatencies(),
25
- tR: telemetry.popTokenRefreshes(),
26
- aR: telemetry.popAuthRejections(),
27
- iQ: telemetry.getImpressionStats(QUEUED),
28
- iDe: telemetry.getImpressionStats(DEDUPED),
29
- iDr: telemetry.getImpressionStats(DROPPED),
30
- spC: splits && splits.getSplitNames().length,
31
- seC: segments && segments.getRegisteredSegments().length,
32
- skC: segments && segments.getKeysCount(),
33
- sL: telemetry.getSessionLength(),
34
- eQ: telemetry.getEventStats(QUEUED),
35
- eD: telemetry.getEventStats(DROPPED),
36
- sE: telemetry.popStreamingEvents(),
37
- t: telemetry.popTags(),
38
- };
39
- }
40
- };
41
- }
42
9
  var OPERATION_MODE_MAP = (_a = {},
43
10
  _a[STANDALONE_MODE] = STANDALONE_ENUM,
44
11
  _a[CONSUMER_MODE] = CONSUMER_ENUM,
@@ -116,14 +83,12 @@ export function telemetryCacheConfigAdapter(telemetry, settings) {
116
83
  * Submitter that periodically posts telemetry data
117
84
  */
118
85
  export function telemetrySubmitterFactory(params) {
119
- var _a = params.storage, splits = _a.splits, segments = _a.segments, telemetry = _a.telemetry, now = params.platform.now;
86
+ var telemetry = params.storage.telemetry, now = params.platform.now;
120
87
  if (!telemetry || !now)
121
88
  return; // No submitter created if telemetry cache is not defined
122
- var settings = params.settings, _b = params.settings, log = _b.log, telemetryRefreshRate = _b.scheduler.telemetryRefreshRate, splitApi = params.splitApi, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
89
+ var settings = params.settings, _a = params.settings, log = _a.log, telemetryRefreshRate = _a.scheduler.telemetryRefreshRate, splitApi = params.splitApi, readiness = params.readiness, sdkReadinessManager = params.sdkReadinessManager;
123
90
  var startTime = timer(now);
124
- var submitter = firstPushWindowDecorator(submitterFactory(log, splitApi.postMetricsUsage,
125
- // @TODO cannot provide splits and segments cache if they are async, because `submitterFactory` expects a sync storage source
126
- isStorageSync(params.settings) ? telemetryCacheStatsAdapter(telemetry, splits, segments) : telemetryCacheStatsAdapter(telemetry), telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
91
+ var submitter = firstPushWindowDecorator(submitterFactory(log, splitApi.postMetricsUsage, telemetry, telemetryRefreshRate, 'telemetry stats', undefined, 0, true), telemetryRefreshRate);
127
92
  readiness.gate.once(SDK_READY_FROM_CACHE, function () {
128
93
  telemetry.recordTimeUntilReadyFromCache(startTime());
129
94
  });
@@ -1,18 +1,4 @@
1
- import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE, OPTIMIZED, PRODUCER_MODE, STANDALONE_MODE } from '../../utils/constants';
2
- /**
3
- * Checks if impressions previous time should be added or not.
4
- */
5
- export function shouldAddPt(settings) {
6
- return [PRODUCER_MODE, STANDALONE_MODE, CONSUMER_PARTIAL_MODE].indexOf(settings.mode) > -1 ? true : false;
7
- }
8
- /**
9
- * Checks if it should dedupe impressions or not.
10
- */
11
- export function shouldBeOptimized(settings) {
12
- if (!shouldAddPt(settings))
13
- return false;
14
- return settings.sync.impressionsMode === OPTIMIZED ? true : false;
15
- }
1
+ import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE } from '../../utils/constants';
16
2
  /**
17
3
  * Storage is async if mode is consumer or partial consumer
18
4
  */
@@ -7,7 +7,7 @@ var noopFilterAdapter = {
7
7
  /**
8
8
  * Trackes uniques keys
9
9
  * Unique Keys Tracker will be in charge of checking if the MTK was already sent to the BE in the last period
10
- * or schedule to be sent; if not it will be added in an internal cache and sent in the next post.
10
+ * or schedule to be sent; if not it will be added in an internal cache and sent in the next post.
11
11
  *
12
12
  * @param log Logger instance
13
13
  * @param uniqueKeysCache cache to save unique keys
@@ -129,8 +129,8 @@ export function settingsValidation(config, validationParams) {
129
129
  if (storage)
130
130
  withDefaults.storage = storage(withDefaults);
131
131
  // Validate key and TT (for client-side)
132
+ var maybeKey = withDefaults.core.key;
132
133
  if (validationParams.acceptKey) {
133
- var maybeKey = withDefaults.core.key;
134
134
  // Although `key` is required in client-side, it can be omitted in LOCALHOST mode. In that case, the value `localhost_key` is used.
135
135
  if (withDefaults.mode === LOCALHOST_MODE && maybeKey === undefined) {
136
136
  withDefaults.core.key = 'localhost_key';
@@ -148,6 +148,12 @@ export function settingsValidation(config, validationParams) {
148
148
  }
149
149
  }
150
150
  }
151
+ else {
152
+ // On server-side, key is undefined and used to distinguish from client-side
153
+ if (maybeKey !== undefined)
154
+ log.warn('Provided `key` is ignored in server-side SDK.'); // @ts-ignore
155
+ withDefaults.core.key = undefined;
156
+ }
151
157
  // Current ip/hostname information
152
158
  // @ts-ignore, modify readonly prop
153
159
  withDefaults.runtime = runtime(withDefaults);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.6.2-rc.12",
3
+ "version": "1.6.2-rc.13",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -24,6 +24,7 @@
24
24
  "build:cjs": "rimraf cjs && tsc -m CommonJS --outDir cjs",
25
25
  "test": "jest",
26
26
  "test:coverage": "jest --coverage",
27
+ "all": "npm run check && npm run build && npm run test",
27
28
  "publish:rc": "npm run check && npm run test && npm run build && npm publish --tag rc",
28
29
  "publish:stable": "npm run check && npm run test && npm run build && npm publish"
29
30
  },