@splitsoftware/splitio-commons 1.2.1-rc.3 → 1.2.1-rc.6

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 (104) hide show
  1. package/cjs/listeners/browser.js +14 -10
  2. package/cjs/logger/constants.js +7 -4
  3. package/cjs/logger/messages/debug.js +3 -3
  4. package/cjs/logger/messages/error.js +3 -2
  5. package/cjs/logger/messages/info.js +5 -3
  6. package/cjs/sdkClient/client.js +10 -4
  7. package/cjs/sdkFactory/index.js +6 -4
  8. package/cjs/sdkFactory/userConsentProps.js +37 -0
  9. package/cjs/storages/KeyBuilder.js +1 -5
  10. package/cjs/storages/KeyBuilderCS.js +11 -1
  11. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -3
  12. package/cjs/storages/inLocalStorage/index.js +1 -1
  13. package/cjs/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
  14. package/cjs/storages/inMemory/InMemoryStorage.js +1 -1
  15. package/cjs/storages/inMemory/InMemoryStorageCS.js +1 -1
  16. package/cjs/storages/pluggable/index.js +2 -2
  17. package/cjs/sync/submitters/eventsSyncTask.js +17 -5
  18. package/cjs/sync/submitters/impressionsSyncTask.js +13 -1
  19. package/cjs/sync/syncManagerOnline.js +11 -7
  20. package/cjs/utils/consent.js +10 -0
  21. package/cjs/utils/constants/index.js +5 -1
  22. package/cjs/utils/lang/index.js +8 -1
  23. package/cjs/utils/settingsValidation/consent.js +16 -0
  24. package/cjs/utils/settingsValidation/impressionsMode.js +6 -6
  25. package/cjs/utils/settingsValidation/index.js +6 -1
  26. package/cjs/utils/settingsValidation/{runtime/browser.js → runtime.js} +1 -0
  27. package/esm/listeners/browser.js +14 -10
  28. package/esm/logger/constants.js +5 -2
  29. package/esm/logger/messages/debug.js +3 -3
  30. package/esm/logger/messages/error.js +3 -2
  31. package/esm/logger/messages/info.js +5 -3
  32. package/esm/sdkClient/client.js +11 -5
  33. package/esm/sdkFactory/index.js +6 -4
  34. package/esm/sdkFactory/userConsentProps.js +33 -0
  35. package/esm/storages/KeyBuilder.js +2 -6
  36. package/esm/storages/KeyBuilderCS.js +11 -1
  37. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -3
  38. package/esm/storages/inLocalStorage/index.js +1 -1
  39. package/esm/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
  40. package/esm/storages/inMemory/InMemoryStorage.js +1 -1
  41. package/esm/storages/inMemory/InMemoryStorageCS.js +1 -1
  42. package/esm/storages/pluggable/index.js +2 -2
  43. package/esm/sync/submitters/eventsSyncTask.js +18 -6
  44. package/esm/sync/submitters/impressionsSyncTask.js +13 -1
  45. package/esm/sync/syncManagerOnline.js +11 -7
  46. package/esm/utils/consent.js +6 -0
  47. package/esm/utils/constants/index.js +4 -0
  48. package/esm/utils/lang/index.js +6 -0
  49. package/esm/utils/settingsValidation/consent.js +12 -0
  50. package/esm/utils/settingsValidation/impressionsMode.js +7 -7
  51. package/esm/utils/settingsValidation/index.js +6 -1
  52. package/esm/utils/settingsValidation/{runtime/browser.js → runtime.js} +1 -0
  53. package/package.json +1 -2
  54. package/src/listeners/browser.ts +13 -9
  55. package/src/logger/constants.ts +5 -2
  56. package/src/logger/messages/debug.ts +3 -3
  57. package/src/logger/messages/error.ts +3 -2
  58. package/src/logger/messages/info.ts +5 -3
  59. package/src/sdkClient/client.ts +7 -5
  60. package/src/sdkFactory/index.ts +6 -4
  61. package/src/sdkFactory/types.ts +2 -0
  62. package/src/sdkFactory/userConsentProps.ts +40 -0
  63. package/src/storages/KeyBuilder.ts +2 -6
  64. package/src/storages/KeyBuilderCS.ts +13 -1
  65. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +23 -3
  66. package/src/storages/inLocalStorage/index.ts +1 -1
  67. package/src/storages/inMemory/ImpressionsCacheInMemory.ts +22 -1
  68. package/src/storages/inMemory/InMemoryStorage.ts +1 -1
  69. package/src/storages/inMemory/InMemoryStorageCS.ts +1 -1
  70. package/src/storages/pluggable/index.ts +2 -2
  71. package/src/storages/types.ts +5 -1
  72. package/src/sync/submitters/eventsSyncTask.ts +19 -6
  73. package/src/sync/submitters/impressionsSyncTask.ts +16 -1
  74. package/src/sync/syncManagerOnline.ts +13 -7
  75. package/src/sync/types.ts +4 -1
  76. package/src/types.ts +21 -0
  77. package/src/utils/consent.ts +8 -0
  78. package/src/utils/constants/index.ts +5 -0
  79. package/src/utils/lang/index.ts +8 -1
  80. package/src/utils/settingsValidation/consent.ts +15 -0
  81. package/src/utils/settingsValidation/impressionsMode.ts +8 -8
  82. package/src/utils/settingsValidation/index.ts +7 -1
  83. package/src/utils/settingsValidation/runtime.ts +9 -0
  84. package/src/utils/settingsValidation/types.ts +2 -0
  85. package/types/logger/constants.d.ts +5 -2
  86. package/types/sdkFactory/types.d.ts +1 -0
  87. package/types/sdkFactory/userConsentProps.d.ts +6 -0
  88. package/types/storages/KeyBuilderCS.d.ts +2 -0
  89. package/types/storages/inMemory/ImpressionsCacheInMemory.d.ts +9 -0
  90. package/types/storages/types.d.ts +2 -0
  91. package/types/sync/types.d.ts +3 -0
  92. package/types/types.d.ts +21 -0
  93. package/types/utils/consent.d.ts +2 -0
  94. package/types/utils/constants/index.d.ts +3 -0
  95. package/types/utils/lang/index.d.ts +4 -0
  96. package/types/utils/settingsValidation/consent.d.ts +5 -0
  97. package/types/utils/settingsValidation/impressionsMode.d.ts +1 -1
  98. package/types/utils/settingsValidation/runtime.d.ts +2 -0
  99. package/types/utils/settingsValidation/types.d.ts +2 -0
  100. package/types/utils/settingsValidation/userConsent.d.ts +5 -0
  101. package/cjs/utils/settingsValidation/runtime/node.js +0 -22
  102. package/esm/utils/settingsValidation/runtime/node.js +0 -17
  103. package/src/utils/settingsValidation/runtime/browser.ts +0 -8
  104. package/src/utils/settingsValidation/runtime/node.ts +0 -22
@@ -6,6 +6,7 @@ var impressionCountsSyncTask_1 = require("../sync/submitters/impressionCountsSyn
6
6
  var constants_1 = require("../utils/constants");
7
7
  var objectAssign_1 = require("../utils/lang/objectAssign");
8
8
  var constants_2 = require("../logger/constants");
9
+ var consent_1 = require("../utils/consent");
9
10
  // 'unload' event is used instead of 'beforeunload', since 'unload' is not a cancelable event, so no other listeners can stop the event from occurring.
10
11
  var UNLOAD_DOM_EVENT = 'unload';
11
12
  var EVENT_NAME = 'for unload page event.';
@@ -51,15 +52,18 @@ var BrowserSignalListener = /** @class */ (function () {
51
52
  BrowserSignalListener.prototype.flushData = function () {
52
53
  if (!this.syncManager)
53
54
  return; // In consumer mode there is not sync manager and data to flush
54
- var eventsUrl = this.settings.urls.events;
55
- var extraMetadata = {
56
- // sim stands for Sync/Split Impressions Mode
57
- sim: this.settings.sync.impressionsMode === constants_1.OPTIMIZED ? constants_1.OPTIMIZED : constants_1.DEBUG
58
- };
59
- this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
60
- this._flushData(eventsUrl + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
61
- if (this.storage.impressionCounts)
62
- this._flushData(eventsUrl + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, impressionCountsSyncTask_1.fromImpressionCountsCollector);
55
+ // Flush data if there is user consent
56
+ if ((0, consent_1.isConsentGranted)(this.settings)) {
57
+ var eventsUrl = this.settings.urls.events;
58
+ var extraMetadata = {
59
+ // sim stands for Sync/Split Impressions Mode
60
+ sim: this.settings.sync.impressionsMode === constants_1.OPTIMIZED ? constants_1.OPTIMIZED : constants_1.DEBUG
61
+ };
62
+ this._flushData(eventsUrl + '/testImpressions/beacon', this.storage.impressions, this.serviceApi.postTestImpressionsBulk, this.fromImpressionsCollector, extraMetadata);
63
+ this._flushData(eventsUrl + '/events/beacon', this.storage.events, this.serviceApi.postEventsBulk);
64
+ if (this.storage.impressionCounts)
65
+ this._flushData(eventsUrl + '/testImpressions/count/beacon', this.storage.impressionCounts, this.serviceApi.postTestImpressionsCount, impressionCountsSyncTask_1.fromImpressionCountsCollector);
66
+ }
63
67
  // Close streaming connection
64
68
  if (this.syncManager.pushManager)
65
69
  this.syncManager.pushManager.stop();
@@ -69,7 +73,7 @@ var BrowserSignalListener = /** @class */ (function () {
69
73
  if (!cache.isEmpty()) {
70
74
  var dataPayload = fromCacheToPayload ? fromCacheToPayload(cache.state()) : cache.state();
71
75
  if (!this._sendBeacon(url, dataPayload, extraMetadata)) {
72
- postService(JSON.stringify(dataPayload)).catch(function () { }); // no-op just to catch a possible exceptions
76
+ postService(JSON.stringify(dataPayload)).catch(function () { }); // no-op just to catch a possible exception
73
77
  }
74
78
  cache.clear();
75
79
  }
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SYNC_SPLITS_FETCH_RETRY = exports.POLLING_STOP = exports.POLLING_START = exports.POLLING_SMART_PAUSING = exports.NEW_FACTORY = exports.NEW_SHARED_CLIENT = exports.IMPRESSION_QUEUEING = exports.IMPRESSION = exports.CLIENT_READY = exports.CLIENT_READY_FROM_CACHE = exports.SETTINGS_SPLITS_FILTER = exports.SYNC_TASK_STOP = exports.SYNC_TASK_EXECUTE = exports.SYNC_TASK_START = exports.STREAMING_NEW_MESSAGE = exports.SYNC_SPLITS_SEGMENTS = exports.SYNC_SPLITS_REMOVED = exports.SYNC_SPLITS_NEW = exports.SYNC_SPLITS_FETCH = exports.SYNC_OFFLINE_DATA = exports.RETRIEVE_MANAGER = exports.RETRIEVE_CLIENT_EXISTING = exports.RETRIEVE_CLIENT_DEFAULT = exports.CLEANUP_DEREGISTERING = exports.CLEANUP_REGISTERING = exports.ENGINE_SANITIZE = exports.ENGINE_VALUE = exports.ENGINE_MATCHER_WHITELIST = exports.ENGINE_MATCHER_STARTS_WITH = exports.ENGINE_MATCHER_STRING_INVALID = exports.ENGINE_MATCHER_STRING = exports.ENGINE_MATCHER_SEGMENT = exports.ENGINE_MATCHER_PART_OF = exports.ENGINE_MATCHER_LESS = exports.ENGINE_MATCHER_GREATER = exports.ENGINE_MATCHER_ENDS_WITH = exports.ENGINE_MATCHER_EQUAL_TO_SET = exports.ENGINE_MATCHER_EQUAL = exports.ENGINE_MATCHER_DEPENDENCY_PRE = exports.ENGINE_MATCHER_DEPENDENCY = exports.ENGINE_MATCHER_CONTAINS_STRING = exports.ENGINE_MATCHER_CONTAINS_ANY = exports.ENGINE_MATCHER_CONTAINS_ALL = exports.ENGINE_MATCHER_BOOLEAN = exports.ENGINE_MATCHER_BETWEEN = exports.ENGINE_MATCHER_ALL = exports.ENGINE_BUCKET = exports.ENGINE_COMBINER_IFELSEIF_NO_TREATMENT = exports.ENGINE_COMBINER_IFELSEIF = exports.ENGINE_COMBINER_AND = void 0;
4
- exports.ERROR_NOT_FINITE = exports.ERROR_SIZE_EXCEEDED = exports.ERROR_NOT_PLAIN_OBJECT = exports.ERROR_EVENT_TYPE_FORMAT = exports.ERROR_EVENTS_TRACKER = exports.ERROR_IMPRESSIONS_LISTENER = exports.ERROR_IMPRESSIONS_TRACKER = exports.ERROR_STREAMING_AUTH = exports.ERROR_STREAMING_SSE = exports.ERROR_SYNC_OFFLINE_LOADING = exports.ERROR_CLIENT_CANNOT_GET_READY = exports.ERROR_CLIENT_LISTENER = exports.ERROR_LOGLEVEL_INVALID = exports.ERROR_ENGINE_COMBINER_IFELSEIF = exports.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = exports.WARN_API_KEY = exports.WARN_SPLITS_FILTER_EMPTY = exports.WARN_SPLITS_FILTER_INVALID = exports.WARN_SPLITS_FILTER_IGNORED = exports.WARN_INTEGRATION_INVALID = exports.WARN_NOT_EXISTENT_TT = exports.WARN_LOWERCASE_TRAFFIC_TYPE = exports.WARN_NOT_EXISTENT_SPLIT = exports.WARN_TRIMMING = exports.WARN_CONVERTING = exports.WARN_TRIMMING_PROPERTIES = exports.WARN_SETTING_NULL = exports.SUBMITTERS_PUSH_RETRY = exports.SUBMITTERS_PUSH_FAILS = exports.STREAMING_FALLBACK = exports.STREAMING_PARSING_MESSAGE_FAILS = exports.STREAMING_PARSING_ERROR_FAILS = exports.SYNC_SPLITS_FETCH_FAILS = exports.SYNC_MYSEGMENTS_FETCH_RETRY = exports.CLIENT_NOT_READY = exports.CLIENT_NO_LISTENER = exports.ENGINE_VALUE_NO_ATTRIBUTES = exports.ENGINE_VALUE_INVALID = exports.IMPRESSIONS_TRACKER_SUCCESS = exports.EVENTS_TRACKER_SUCCESS = exports.SYNC_STOP_POLLING = exports.SYNC_CONTINUE_POLLING = exports.SYNC_START_POLLING = exports.SUBMITTERS_PUSH = exports.SUBMITTERS_PUSH_FULL_EVENTS_QUEUE = exports.STREAMING_DISCONNECTING = exports.STREAMING_DISABLED = exports.STREAMING_CONNECTING = exports.STREAMING_RECONNECT = exports.STREAMING_REFRESH_TOKEN = void 0;
5
- exports.LOG_PREFIX_CLEANUP = exports.LOG_PREFIX_EVENTS_TRACKER = exports.LOG_PREFIX_IMPRESSIONS_TRACKER = exports.LOG_PREFIX_SYNC_SUBMITTERS = exports.LOG_PREFIX_SYNC_POLLING = exports.LOG_PREFIX_SYNC_MYSEGMENTS = exports.LOG_PREFIX_SYNC_SEGMENTS = exports.LOG_PREFIX_SYNC_SPLITS = exports.LOG_PREFIX_SYNC_STREAMING = exports.LOG_PREFIX_SYNC_OFFLINE = exports.LOG_PREFIX_SYNC_MANAGER = exports.LOG_PREFIX_SYNC = exports.LOG_PREFIX_ENGINE_VALUE = exports.LOG_PREFIX_ENGINE_MATCHER = exports.LOG_PREFIX_ENGINE_COMBINER = exports.LOG_PREFIX_ENGINE = exports.LOG_PREFIX_INSTANTIATION = exports.LOG_PREFIX_SETTINGS = exports.ERROR_STORAGE_INVALID = exports.ERROR_LOCALHOST_MODULE_REQUIRED = exports.ERROR_HTTP = exports.ERROR_INVALID_IMPRESSIONS_MODE = exports.ERROR_EMPTY_ARRAY = exports.ERROR_EMPTY = exports.ERROR_INVALID = exports.ERROR_INVALID_KEY_OBJECT = exports.ERROR_TOO_LONG = exports.ERROR_NULL = exports.ERROR_CLIENT_DESTROYED = void 0;
4
+ exports.ERROR_NOT_PLAIN_OBJECT = exports.ERROR_EVENT_TYPE_FORMAT = exports.ERROR_EVENTS_TRACKER = exports.ERROR_IMPRESSIONS_LISTENER = exports.ERROR_IMPRESSIONS_TRACKER = exports.ERROR_STREAMING_AUTH = exports.ERROR_STREAMING_SSE = exports.ERROR_SYNC_OFFLINE_LOADING = exports.ERROR_CLIENT_CANNOT_GET_READY = exports.ERROR_CLIENT_LISTENER = exports.ERROR_LOGLEVEL_INVALID = exports.ERROR_ENGINE_COMBINER_IFELSEIF = exports.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = exports.WARN_API_KEY = exports.WARN_SPLITS_FILTER_EMPTY = exports.WARN_SPLITS_FILTER_INVALID = exports.WARN_SPLITS_FILTER_IGNORED = exports.WARN_INTEGRATION_INVALID = exports.WARN_NOT_EXISTENT_TT = exports.WARN_LOWERCASE_TRAFFIC_TYPE = exports.WARN_NOT_EXISTENT_SPLIT = exports.WARN_TRIMMING = exports.WARN_CONVERTING = exports.WARN_TRIMMING_PROPERTIES = exports.WARN_SETTING_NULL = exports.SUBMITTERS_PUSH_RETRY = exports.SUBMITTERS_PUSH_FAILS = exports.STREAMING_FALLBACK = exports.STREAMING_PARSING_MESSAGE_FAILS = exports.STREAMING_PARSING_ERROR_FAILS = exports.SYNC_SPLITS_FETCH_FAILS = exports.SYNC_MYSEGMENTS_FETCH_RETRY = exports.CLIENT_NOT_READY = exports.CLIENT_NO_LISTENER = exports.ENGINE_VALUE_NO_ATTRIBUTES = exports.ENGINE_VALUE_INVALID = exports.USER_CONSENT_NOT_UPDATED = exports.USER_CONSENT_UPDATED = exports.IMPRESSIONS_TRACKER_SUCCESS = exports.EVENTS_TRACKER_SUCCESS = exports.SYNC_STOP_POLLING = exports.SYNC_CONTINUE_POLLING = exports.SYNC_START_POLLING = exports.SUBMITTERS_PUSH = exports.SUBMITTERS_PUSH_FULL_QUEUE = exports.STREAMING_DISCONNECTING = exports.STREAMING_DISABLED = exports.STREAMING_CONNECTING = exports.STREAMING_RECONNECT = exports.STREAMING_REFRESH_TOKEN = void 0;
5
+ exports.LOG_PREFIX_CLEANUP = exports.LOG_PREFIX_EVENTS_TRACKER = exports.LOG_PREFIX_IMPRESSIONS_TRACKER = exports.LOG_PREFIX_SYNC_SUBMITTERS = exports.LOG_PREFIX_SYNC_POLLING = exports.LOG_PREFIX_SYNC_MYSEGMENTS = exports.LOG_PREFIX_SYNC_SEGMENTS = exports.LOG_PREFIX_SYNC_SPLITS = exports.LOG_PREFIX_SYNC_STREAMING = exports.LOG_PREFIX_SYNC_OFFLINE = exports.LOG_PREFIX_SYNC_MANAGER = exports.LOG_PREFIX_SYNC = exports.LOG_PREFIX_ENGINE_VALUE = exports.LOG_PREFIX_ENGINE_MATCHER = exports.LOG_PREFIX_ENGINE_COMBINER = exports.LOG_PREFIX_ENGINE = exports.LOG_PREFIX_INSTANTIATION = exports.LOG_PREFIX_SETTINGS = exports.ERROR_NOT_BOOLEAN = exports.ERROR_STORAGE_INVALID = exports.ERROR_LOCALHOST_MODULE_REQUIRED = exports.ERROR_HTTP = exports.ERROR_INVALID_CONFIG_PARAM = exports.ERROR_EMPTY_ARRAY = exports.ERROR_EMPTY = exports.ERROR_INVALID = exports.ERROR_INVALID_KEY_OBJECT = exports.ERROR_TOO_LONG = exports.ERROR_NULL = exports.ERROR_CLIENT_DESTROYED = exports.ERROR_NOT_FINITE = exports.ERROR_SIZE_EXCEEDED = void 0;
6
6
  /**
7
7
  * Message codes used to trim string log messages from commons and client-side API modules,
8
8
  * in order to reduce the minimal SDK size for Browser and eventually other client-side environments.
@@ -65,13 +65,15 @@ exports.STREAMING_RECONNECT = 111;
65
65
  exports.STREAMING_CONNECTING = 112;
66
66
  exports.STREAMING_DISABLED = 113;
67
67
  exports.STREAMING_DISCONNECTING = 114;
68
- exports.SUBMITTERS_PUSH_FULL_EVENTS_QUEUE = 115;
68
+ exports.SUBMITTERS_PUSH_FULL_QUEUE = 115;
69
69
  exports.SUBMITTERS_PUSH = 116;
70
70
  exports.SYNC_START_POLLING = 117;
71
71
  exports.SYNC_CONTINUE_POLLING = 118;
72
72
  exports.SYNC_STOP_POLLING = 119;
73
73
  exports.EVENTS_TRACKER_SUCCESS = 120;
74
74
  exports.IMPRESSIONS_TRACKER_SUCCESS = 121;
75
+ exports.USER_CONSENT_UPDATED = 122;
76
+ exports.USER_CONSENT_NOT_UPDATED = 123;
75
77
  exports.ENGINE_VALUE_INVALID = 200;
76
78
  exports.ENGINE_VALUE_NO_ATTRIBUTES = 201;
77
79
  exports.CLIENT_NO_LISTENER = 202;
@@ -117,10 +119,11 @@ exports.ERROR_INVALID_KEY_OBJECT = 317;
117
119
  exports.ERROR_INVALID = 318;
118
120
  exports.ERROR_EMPTY = 319;
119
121
  exports.ERROR_EMPTY_ARRAY = 320;
120
- exports.ERROR_INVALID_IMPRESSIONS_MODE = 321;
122
+ exports.ERROR_INVALID_CONFIG_PARAM = 321;
121
123
  exports.ERROR_HTTP = 322;
122
124
  exports.ERROR_LOCALHOST_MODULE_REQUIRED = 323;
123
125
  exports.ERROR_STORAGE_INVALID = 324;
126
+ exports.ERROR_NOT_BOOLEAN = 325;
124
127
  // Log prefixes (a.k.a. tags or categories)
125
128
  exports.LOG_PREFIX_SETTINGS = 'settings';
126
129
  exports.LOG_PREFIX_INSTANTIATION = 'Factory instantiation';
@@ -34,9 +34,9 @@ exports.codesDebug = info_1.codesInfo.concat([
34
34
  // SDK
35
35
  [c.CLEANUP_REGISTERING, c.LOG_PREFIX_CLEANUP + 'Registering cleanup handler %s'],
36
36
  [c.CLEANUP_DEREGISTERING, c.LOG_PREFIX_CLEANUP + 'Deregistering cleanup handler %s'],
37
- [c.RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'],
38
- [c.RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'],
39
- [c.RETRIEVE_MANAGER, ' Retrieving manager instance.'],
37
+ [c.RETRIEVE_CLIENT_DEFAULT, 'Retrieving default SDK client.'],
38
+ [c.RETRIEVE_CLIENT_EXISTING, 'Retrieving existing SDK client.'],
39
+ [c.RETRIEVE_MANAGER, 'Retrieving manager instance.'],
40
40
  // synchronizer
41
41
  [c.SYNC_OFFLINE_DATA, c.LOG_PREFIX_SYNC_OFFLINE + 'Splits data: \n%s'],
42
42
  [c.SYNC_SPLITS_FETCH, c.LOG_PREFIX_SYNC_SPLITS + 'Spin up split update using since = %s'],
@@ -8,7 +8,7 @@ exports.codesError = [
8
8
  [c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid Split, no valid rules found'],
9
9
  // SDK
10
10
  [c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'],
11
- [c.ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'],
11
+ [c.ERROR_CLIENT_CANNOT_GET_READY, 'The SDK will not get ready. Reason: %s'],
12
12
  [c.ERROR_IMPRESSIONS_TRACKER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Could not store impressions bulk with %s impression(s). Error: %s'],
13
13
  [c.ERROR_IMPRESSIONS_LISTENER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Impression listener logImpression method threw: %s.'],
14
14
  [c.ERROR_EVENTS_TRACKER, c.LOG_PREFIX_EVENTS_TRACKER + 'Failed to queue %s'],
@@ -31,8 +31,9 @@ exports.codesError = [
31
31
  [c.ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'],
32
32
  [c.ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'],
33
33
  [c.ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'],
34
+ [c.ERROR_NOT_BOOLEAN, '%s: provided param must be a boolean value.'],
34
35
  // initialization / settings validation
35
- [c.ERROR_INVALID_IMPRESSIONS_MODE, c.LOG_PREFIX_SETTINGS + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'],
36
+ [c.ERROR_INVALID_CONFIG_PARAM, c.LOG_PREFIX_SETTINGS + ': you passed an invalid "%s" config param. It should be one of the following values: %s. Defaulting to "%s".'],
36
37
  [c.ERROR_LOCALHOST_MODULE_REQUIRED, c.LOG_PREFIX_SETTINGS + ': an invalid value was received for "sync.localhostMode" config. A valid entity should be provided for localhost mode.'],
37
38
  [c.ERROR_STORAGE_INVALID, c.LOG_PREFIX_SETTINGS + ': The provided storage is invalid.%s Fallbacking into default MEMORY storage'],
38
39
  ];
@@ -12,16 +12,18 @@ exports.codesInfo = warn_1.codesWarn.concat([
12
12
  // SDK
13
13
  [c.IMPRESSION, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Split: %s. Key: %s. Evaluation: %s. Label: %s'],
14
14
  [c.IMPRESSION_QUEUEING, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Queueing corresponding impression.'],
15
- [c.NEW_SHARED_CLIENT, ' New shared client instance created.'],
16
- [c.NEW_FACTORY, ' New Split SDK instance created.'],
15
+ [c.NEW_SHARED_CLIENT, 'New shared client instance created.'],
16
+ [c.NEW_FACTORY, 'New Split SDK instance created.'],
17
17
  [c.EVENTS_TRACKER_SUCCESS, c.LOG_PREFIX_EVENTS_TRACKER + 'Successfully queued %s'],
18
18
  [c.IMPRESSIONS_TRACKER_SUCCESS, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Successfully stored %s impression(s).'],
19
+ [c.USER_CONSENT_UPDATED, 'setUserConsent: consent status changed from %s to %s.'],
20
+ [c.USER_CONSENT_NOT_UPDATED, 'setUserConsent: call had no effect because it was the current consent status (%s).'],
19
21
  // synchronizer
20
22
  [c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
21
23
  [c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
22
24
  [c.POLLING_STOP, c.LOG_PREFIX_SYNC_POLLING + 'Stopping polling'],
23
25
  [c.SYNC_SPLITS_FETCH_RETRY, c.LOG_PREFIX_SYNC_SPLITS + 'Retrying download of splits #%s. Reason: %s'],
24
- [c.SUBMITTERS_PUSH_FULL_EVENTS_QUEUE, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing full events queue and reseting timer.'],
26
+ [c.SUBMITTERS_PUSH_FULL_QUEUE, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Flushing full %s queue and reseting timer.'],
25
27
  [c.SUBMITTERS_PUSH, c.LOG_PREFIX_SYNC_SUBMITTERS + 'Pushing %s %s.'],
26
28
  [c.STREAMING_REFRESH_TOKEN, c.LOG_PREFIX_SYNC_STREAMING + 'Refreshing streaming token in %s seconds, and connecting streaming in %s seconds.'],
27
29
  [c.STREAMING_RECONNECT, c.LOG_PREFIX_SYNC_STREAMING + 'Attempting to reconnect streaming in %s seconds.'],
@@ -14,13 +14,15 @@ var constants_2 = require("../logger/constants");
14
14
  */
15
15
  // @TODO missing time tracking to collect telemetry
16
16
  function clientFactory(params) {
17
- var readinessManager = params.sdkReadinessManager.readinessManager, storage = params.storage, _a = params.settings, log = _a.log, mode = _a.mode, impressionsTracker = params.impressionsTracker, eventTracker = params.eventTracker;
17
+ var readinessManager = params.sdkReadinessManager.readinessManager, storage = params.storage, settings = params.settings, impressionsTracker = params.impressionsTracker, eventTracker = params.eventTracker;
18
+ var log = settings.log, mode = settings.mode;
18
19
  function getTreatment(key, splitName, attributes, withConfig) {
19
20
  if (withConfig === void 0) { withConfig = false; }
20
21
  var wrapUp = function (evaluationResult) {
21
22
  var queue = [];
22
23
  var treatment = processEvaluation(evaluationResult, splitName, key, attributes, withConfig, "getTreatment" + (withConfig ? 'withConfig' : ''), queue);
23
- impressionsTracker.track(queue, attributes);
24
+ if (settings.userConsent !== constants_1.CONSENT_DECLINED)
25
+ impressionsTracker.track(queue, attributes);
24
26
  return treatment;
25
27
  };
26
28
  var evaluation = (0, evaluator_1.evaluateFeature)(log, key, splitName, attributes, storage);
@@ -37,7 +39,8 @@ function clientFactory(params) {
37
39
  Object.keys(evaluationResults).forEach(function (splitName) {
38
40
  treatments[splitName] = processEvaluation(evaluationResults[splitName], splitName, key, attributes, withConfig, "getTreatments" + (withConfig ? 'withConfig' : ''), queue);
39
41
  });
40
- impressionsTracker.track(queue, attributes);
42
+ if (settings.userConsent !== constants_1.CONSENT_DECLINED)
43
+ impressionsTracker.track(queue, attributes);
41
44
  return treatments;
42
45
  };
43
46
  var evaluations = (0, evaluator_1.evaluateFeatures)(log, key, splitNames, attributes, storage);
@@ -91,7 +94,10 @@ function clientFactory(params) {
91
94
  };
92
95
  // This may be async but we only warn, we don't actually care if it is valid or not in terms of queueing the event.
93
96
  (0, trafficTypeExistance_1.validateTrafficTypeExistance)(log, readinessManager, storage.splits, mode, trafficTypeName, 'track');
94
- return eventTracker.track(eventData, size);
97
+ if (settings.userConsent !== constants_1.CONSENT_DECLINED)
98
+ return eventTracker.track(eventData, size);
99
+ else
100
+ return false;
95
101
  }
96
102
  return {
97
103
  getTreatment: getTreatment,
@@ -11,11 +11,12 @@ var sdkLogger_1 = require("../logger/sdkLogger");
11
11
  var constants_1 = require("../logger/constants");
12
12
  var metadataBuilder_1 = require("../storages/metadataBuilder");
13
13
  var constants_2 = require("../readiness/constants");
14
+ var objectAssign_1 = require("../utils/lang/objectAssign");
14
15
  /**
15
16
  * Modular SDK factory
16
17
  */
17
18
  function sdkFactory(params) {
18
- var settings = params.settings, platform = params.platform, storageFactory = params.storageFactory, splitApiFactory = params.splitApiFactory, syncManagerFactory = params.syncManagerFactory, SignalListener = params.SignalListener, impressionsObserverFactory = params.impressionsObserverFactory, impressionListener = params.impressionListener, integrationsManagerFactory = params.integrationsManagerFactory, sdkManagerFactory = params.sdkManagerFactory, sdkClientMethodFactory = params.sdkClientMethodFactory;
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, impressionListener = params.impressionListener, integrationsManagerFactory = params.integrationsManagerFactory, sdkManagerFactory = params.sdkManagerFactory, sdkClientMethodFactory = params.sdkClientMethodFactory;
19
20
  var log = settings.log;
20
21
  // @TODO handle non-recoverable errors: not start sync, mark the SDK as destroyed, etc.
21
22
  // We will just log and allow for the SDK to end up throwing an SDK_TIMEOUT event for devs to handle.
@@ -25,6 +26,7 @@ function sdkFactory(params) {
25
26
  var readinessManager = sdkReadinessManager.readinessManager;
26
27
  // @TODO consider passing the settings object, so that each storage access only what it needs
27
28
  var storageFactoryParams = {
29
+ impressionsQueueSize: settings.scheduler.impressionsQueueSize,
28
30
  eventsQueueSize: settings.scheduler.eventsQueueSize,
29
31
  optimize: (0, utils_1.shouldBeOptimized)(settings),
30
32
  // ATM, only used by InLocalStorage
@@ -67,11 +69,11 @@ function sdkFactory(params) {
67
69
  syncManager && syncManager.start();
68
70
  signalListener && signalListener.start();
69
71
  log.info(constants_1.NEW_FACTORY);
70
- return {
72
+ // @ts-ignore
73
+ return (0, objectAssign_1.objectAssign)({
71
74
  // Split evaluation and event tracking engine
72
75
  client: clientMethod,
73
76
  // Manager API to explore available information
74
- // @ts-ignore
75
77
  manager: function () {
76
78
  log.debug(constants_1.RETRIEVE_MANAGER);
77
79
  return managerInstance;
@@ -79,6 +81,6 @@ function sdkFactory(params) {
79
81
  // Logger wrapper API
80
82
  Logger: (0, sdkLogger_1.createLoggerAPI)(settings.log),
81
83
  settings: settings,
82
- };
84
+ }, extraProps && extraProps(settings, syncManager));
83
85
  }
84
86
  exports.sdkFactory = sdkFactory;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.userConsentProps = void 0;
4
+ var constants_1 = require("../logger/constants");
5
+ var constants_2 = require("../utils/constants");
6
+ var lang_1 = require("../utils/lang");
7
+ // Extend client-side factory instances with user consent getter/setter
8
+ function userConsentProps(settings, syncManager) {
9
+ var log = settings.log;
10
+ return {
11
+ setUserConsent: function (consent) {
12
+ var _a, _b;
13
+ // validate input param
14
+ if (!(0, lang_1.isBoolean)(consent)) {
15
+ log.warn(constants_1.ERROR_NOT_BOOLEAN, ['setUserConsent']);
16
+ return false;
17
+ }
18
+ var newConsentStatus = consent ? constants_2.CONSENT_GRANTED : constants_2.CONSENT_DECLINED;
19
+ if (settings.userConsent !== newConsentStatus) { // @ts-ignore, modify readonly prop
20
+ settings.userConsent = newConsentStatus;
21
+ if (consent)
22
+ (_a = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _a === void 0 ? void 0 : _a.start(); // resumes submitters if transitioning to GRANTED
23
+ else
24
+ (_b = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _b === void 0 ? void 0 : _b.stop(); // pauses submitters if transitioning to DECLINED
25
+ log.info(constants_1.USER_CONSENT_UPDATED, [settings.userConsent, newConsentStatus]);
26
+ }
27
+ else {
28
+ log.info(constants_1.USER_CONSENT_NOT_UPDATED, [newConsentStatus]);
29
+ }
30
+ return true;
31
+ },
32
+ getUserConsent: function () {
33
+ return settings.userConsent;
34
+ }
35
+ };
36
+ }
37
+ exports.userConsentProps = userConsentProps;
@@ -5,11 +5,7 @@ var lang_1 = require("../utils/lang");
5
5
  var everythingAtTheEnd = /[^.]+$/;
6
6
  var DEFAULT_PREFIX = 'SPLITIO';
7
7
  function validatePrefix(prefix) {
8
- return prefix && typeof prefix === 'string' ?
9
- (0, lang_1.endsWith)(prefix, '.' + DEFAULT_PREFIX) ?
10
- prefix : // suffix already appended
11
- prefix + '.' + DEFAULT_PREFIX : // append suffix
12
- DEFAULT_PREFIX; // use default prefix if none is provided
8
+ return prefix ? prefix + '.SPLITIO' : 'SPLITIO';
13
9
  }
14
10
  exports.validatePrefix = validatePrefix;
15
11
  var KeyBuilder = /** @class */ (function () {
@@ -16,9 +16,19 @@ var KeyBuilderCS = /** @class */ (function (_super) {
16
16
  * @override
17
17
  */
18
18
  KeyBuilderCS.prototype.buildSegmentNameKey = function (segmentName) {
19
- return this.matchingKey + "." + this.prefix + ".segment." + segmentName;
19
+ return this.prefix + "." + this.matchingKey + ".segment." + segmentName;
20
20
  };
21
21
  KeyBuilderCS.prototype.extractSegmentName = function (builtSegmentKeyName) {
22
+ var prefix = this.prefix + "." + this.matchingKey + ".segment.";
23
+ if ((0, lang_1.startsWith)(builtSegmentKeyName, prefix))
24
+ return builtSegmentKeyName.substr(prefix.length);
25
+ };
26
+ // @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
27
+ KeyBuilderCS.prototype.buildOldSegmentNameKey = function (segmentName) {
28
+ return this.matchingKey + "." + this.prefix + ".segment." + segmentName;
29
+ };
30
+ // @BREAKING: The key used to start with the matching key instead of the prefix, this was changed on version 10.17.3
31
+ KeyBuilderCS.prototype.extractOldSegmentKey = function (builtSegmentKeyName) {
22
32
  var prefix = this.matchingKey + "." + this.prefix + ".segment.";
23
33
  if ((0, lang_1.startsWith)(builtSegmentKeyName, prefix))
24
34
  return builtSegmentKeyName.substr(prefix.length);
@@ -60,9 +60,29 @@ var MySegmentsCacheInLocal = /** @class */ (function (_super) {
60
60
  var index;
61
61
  // Scan current values from localStorage
62
62
  var storedSegmentNames = Object.keys(localStorage).reduce(function (accum, key) {
63
- var name = _this.keys.extractSegmentName(key);
64
- if (name)
65
- accum.push(name);
63
+ var segmentName = _this.keys.extractSegmentName(key);
64
+ if (segmentName) {
65
+ accum.push(segmentName);
66
+ }
67
+ else {
68
+ // @BREAKING: This is only to clean up "old" keys. Remove this whole else code block.
69
+ segmentName = _this.keys.extractOldSegmentKey(key);
70
+ if (segmentName) { // this was an old segment key, let's clean up.
71
+ var newSegmentKey = _this.keys.buildSegmentNameKey(segmentName);
72
+ try {
73
+ // If the new format key is not there, create it.
74
+ if (!localStorage.getItem(newSegmentKey) && names.indexOf(segmentName) > -1) {
75
+ localStorage.setItem(newSegmentKey, constants_1.DEFINED);
76
+ // we are migrating a segment, let's track it.
77
+ accum.push(segmentName);
78
+ }
79
+ localStorage.removeItem(key); // we migrated the current key, let's delete it.
80
+ }
81
+ catch (e) {
82
+ _this.log.error(e);
83
+ }
84
+ }
85
+ }
66
86
  return accum;
67
87
  }, []);
68
88
  // Extreme fast => everything is empty
@@ -33,7 +33,7 @@ function InLocalStorage(options) {
33
33
  return {
34
34
  splits: new SplitsCacheInLocal_1.SplitsCacheInLocal(log, keys, expirationTimestamp, params.splitFiltersValidation),
35
35
  segments: new MySegmentsCacheInLocal_1.MySegmentsCacheInLocal(log, keys),
36
- impressions: new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(),
36
+ impressions: new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(params.impressionsQueueSize),
37
37
  impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory() : undefined,
38
38
  events: new EventsCacheInMemory_1.EventsCacheInMemory(params.eventsQueueSize),
39
39
  destroy: function () {
@@ -2,15 +2,29 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ImpressionsCacheInMemory = void 0;
4
4
  var ImpressionsCacheInMemory = /** @class */ (function () {
5
- function ImpressionsCacheInMemory() {
5
+ /**
6
+ *
7
+ * @param impressionsQueueSize number of queued impressions to call onFullQueueCb.
8
+ * Default value is 0, that means no maximum value, in case we want to avoid this being triggered.
9
+ */
10
+ function ImpressionsCacheInMemory(impressionsQueueSize) {
11
+ if (impressionsQueueSize === void 0) { impressionsQueueSize = 0; }
12
+ this.maxQueue = impressionsQueueSize;
6
13
  this.queue = [];
7
14
  }
15
+ ImpressionsCacheInMemory.prototype.setOnFullQueueCb = function (cb) {
16
+ this.onFullQueue = cb;
17
+ };
8
18
  /**
9
19
  * Store impressions in sequential order
10
20
  */
11
21
  ImpressionsCacheInMemory.prototype.track = function (data) {
12
22
  var _a;
13
23
  (_a = this.queue).push.apply(_a, data);
24
+ // Check if the cache queue is full and we need to flush it.
25
+ if (this.maxQueue > 0 && this.queue.length >= this.maxQueue && this.onFullQueue) {
26
+ this.onFullQueue();
27
+ }
14
28
  };
15
29
  /**
16
30
  * Clear the data stored on the cache.
@@ -16,7 +16,7 @@ function InMemoryStorageFactory(params) {
16
16
  return {
17
17
  splits: new SplitsCacheInMemory_1.SplitsCacheInMemory(),
18
18
  segments: new SegmentsCacheInMemory_1.SegmentsCacheInMemory(),
19
- impressions: new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(),
19
+ impressions: new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(params.impressionsQueueSize),
20
20
  impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory() : undefined,
21
21
  events: new EventsCacheInMemory_1.EventsCacheInMemory(params.eventsQueueSize),
22
22
  // When using MEMORY we should clean all the caches to leave them empty
@@ -16,7 +16,7 @@ function InMemoryStorageCSFactory(params) {
16
16
  return {
17
17
  splits: new SplitsCacheInMemory_1.SplitsCacheInMemory(),
18
18
  segments: new MySegmentsCacheInMemory_1.MySegmentsCacheInMemory(),
19
- impressions: new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(),
19
+ impressions: new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(params.impressionsQueueSize),
20
20
  impressionCounts: params.optimize ? new ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory() : undefined,
21
21
  events: new EventsCacheInMemory_1.EventsCacheInMemory(params.eventsQueueSize),
22
22
  // When using MEMORY we should clean all the caches to leave them empty
@@ -54,7 +54,7 @@ function PluggableStorage(options) {
54
54
  validatePluggableStorageOptions(options);
55
55
  var prefix = (0, KeyBuilder_1.validatePrefix)(options.prefix);
56
56
  function PluggableStorageFactory(_a) {
57
- var log = _a.log, metadata = _a.metadata, onReadyCb = _a.onReadyCb, mode = _a.mode, eventsQueueSize = _a.eventsQueueSize, optimize = _a.optimize;
57
+ var log = _a.log, metadata = _a.metadata, onReadyCb = _a.onReadyCb, mode = _a.mode, eventsQueueSize = _a.eventsQueueSize, impressionsQueueSize = _a.impressionsQueueSize, optimize = _a.optimize;
58
58
  var keys = new KeyBuilderSS_1.KeyBuilderSS(prefix, metadata);
59
59
  var wrapper = (0, wrapperAdapter_1.wrapperAdapter)(log, options.wrapper);
60
60
  var isPartialConsumer = mode === constants_1.CONSUMER_PARTIAL_MODE;
@@ -63,7 +63,7 @@ function PluggableStorage(options) {
63
63
  return {
64
64
  splits: new SplitsCachePluggable_1.SplitsCachePluggable(log, keys, wrapper),
65
65
  segments: new SegmentsCachePluggable_1.SegmentsCachePluggable(log, keys, wrapper),
66
- impressions: isPartialConsumer ? new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory() : new ImpressionsCachePluggable_1.ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
66
+ impressions: isPartialConsumer ? new ImpressionsCacheInMemory_1.ImpressionsCacheInMemory(impressionsQueueSize) : new ImpressionsCachePluggable_1.ImpressionsCachePluggable(log, keys.buildImpressionsKey(), wrapper, metadata),
67
67
  impressionCounts: optimize ? new ImpressionCountsCacheInMemory_1.ImpressionCountsCacheInMemory() : undefined,
68
68
  events: isPartialConsumer ? promisifyEventsTrack(new EventsCacheInMemory_1.EventsCacheInMemory(eventsQueueSize)) : new EventsCachePluggable_1.EventsCachePluggable(log, keys.buildEventsKey(), wrapper, metadata),
69
69
  // @TODO add telemetry cache when required
@@ -3,29 +3,41 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.eventsSyncTaskFactory = void 0;
4
4
  var submitterSyncTask_1 = require("./submitterSyncTask");
5
5
  var constants_1 = require("../../logger/constants");
6
+ var DATA_NAME = 'events';
6
7
  /**
7
8
  * Sync task that periodically posts tracked events
8
9
  */
9
10
  function eventsSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, eventsFirstPushWindow, latencyTracker) {
10
11
  // don't retry events.
11
- var syncTask = (0, submitterSyncTask_1.submitterSyncTaskFactory)(log, postEventsBulk, eventsCache, eventsPushRate, 'queued events', latencyTracker);
12
- // Set a timer for the first push of events,
12
+ var syncTask = (0, submitterSyncTask_1.submitterSyncTaskFactory)(log, postEventsBulk, eventsCache, eventsPushRate, DATA_NAME, latencyTracker);
13
+ // Set a timer for the first push window of events.
14
+ // Not implemented in the base submitter or sync task, since this feature is only used by the events submitter.
13
15
  if (eventsFirstPushWindow > 0) {
16
+ var running_1 = false;
14
17
  var stopEventPublisherTimeout_1;
15
18
  var originalStart_1 = syncTask.start;
16
19
  syncTask.start = function () {
20
+ running_1 = true;
17
21
  stopEventPublisherTimeout_1 = setTimeout(originalStart_1, eventsFirstPushWindow);
18
22
  };
19
23
  var originalStop_1 = syncTask.stop;
20
24
  syncTask.stop = function () {
25
+ running_1 = false;
21
26
  clearTimeout(stopEventPublisherTimeout_1);
22
27
  originalStop_1();
23
28
  };
29
+ syncTask.isRunning = function () {
30
+ return running_1;
31
+ };
24
32
  }
25
- // register eventsSubmitter to be executed when events cache is full
33
+ // register events submitter to be executed when events cache is full
26
34
  eventsCache.setOnFullQueueCb(function () {
27
- log.info(constants_1.SUBMITTERS_PUSH_FULL_EVENTS_QUEUE);
28
- syncTask.execute();
35
+ if (syncTask.isRunning()) {
36
+ log.info(constants_1.SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
37
+ syncTask.execute();
38
+ }
39
+ // If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
40
+ // Data will be sent when submitter is resumed.
29
41
  });
30
42
  return syncTask;
31
43
  }
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.impressionsSyncTaskFactory = exports.fromImpressionsCollector = void 0;
4
4
  var lang_1 = require("../../utils/lang");
5
5
  var submitterSyncTask_1 = require("./submitterSyncTask");
6
+ var constants_1 = require("../../logger/constants");
7
+ var DATA_NAME = 'impressions';
6
8
  /**
7
9
  * Converts `impressions` data from cache into request payload.
8
10
  */
@@ -36,6 +38,16 @@ exports.fromImpressionsCollector = fromImpressionsCollector;
36
38
  function impressionsSyncTaskFactory(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, sendLabels, latencyTracker) {
37
39
  if (sendLabels === void 0) { sendLabels = false; }
38
40
  // retry impressions only once.
39
- return (0, submitterSyncTask_1.submitterSyncTaskFactory)(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, 'impressions', latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1);
41
+ var syncTask = (0, submitterSyncTask_1.submitterSyncTaskFactory)(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, DATA_NAME, latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1);
42
+ // register impressions submitter to be executed when impressions cache is full
43
+ impressionsCache.setOnFullQueueCb(function () {
44
+ if (syncTask.isRunning()) {
45
+ log.info(constants_1.SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
46
+ syncTask.execute();
47
+ }
48
+ // If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
49
+ // Data will be sent when submitter is resumed.
50
+ });
51
+ return syncTask;
40
52
  }
41
53
  exports.impressionsSyncTaskFactory = impressionsSyncTaskFactory;
@@ -4,6 +4,7 @@ exports.syncManagerOnlineFactory = void 0;
4
4
  var submitterManager_1 = require("./submitters/submitterManager");
5
5
  var constants_1 = require("./streaming/constants");
6
6
  var constants_2 = require("../logger/constants");
7
+ var consent_1 = require("../utils/consent");
7
8
  /**
8
9
  * Online SyncManager factory.
9
10
  * Can be used for server-side API, and client-side API with or without multiple clients.
@@ -17,7 +18,7 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
17
18
  * SyncManager factory for modular SDK
18
19
  */
19
20
  return function (params) {
20
- var _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled;
21
+ var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled;
21
22
  /** Polling Manager */
22
23
  var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
23
24
  /** Push Manager */
@@ -52,11 +53,16 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
52
53
  var running = false; // flag that indicates whether the syncManager has been started (true) or stopped (false)
53
54
  var startFirstTime = true; // flag to distinguish calling the `start` method for the first time, to support pausing and resuming the synchronization
54
55
  return {
56
+ // Exposed for fine-grained control of synchronization.
57
+ // E.g.: user consent, app state changes (Page hide, Foreground/Background, Online/Offline).
58
+ pollingManager: pollingManager,
55
59
  pushManager: pushManager,
60
+ submitter: submitter,
56
61
  /**
57
62
  * Method used to start the syncManager for the first time, or resume it after being stopped.
58
63
  */
59
64
  start: function () {
65
+ running = true;
60
66
  // start syncing splits and segments
61
67
  if (pollingManager) {
62
68
  if (pushManager) {
@@ -72,29 +78,27 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
72
78
  }
73
79
  }
74
80
  // start periodic data recording (events, impressions, telemetry).
75
- if (submitter)
81
+ if ((0, consent_1.isConsentGranted)(settings))
76
82
  submitter.start();
77
- running = true;
78
83
  },
79
84
  /**
80
85
  * Method used to stop/pause the syncManager.
81
86
  */
82
87
  stop: function () {
88
+ running = false;
83
89
  // stop syncing
84
90
  if (pushManager)
85
91
  pushManager.stop();
86
92
  if (pollingManager && pollingManager.isRunning())
87
93
  pollingManager.stop();
88
94
  // stop periodic data recording (events, impressions, telemetry).
89
- if (submitter)
90
- submitter.stop();
91
- running = false;
95
+ submitter.stop();
92
96
  },
93
97
  isRunning: function () {
94
98
  return running;
95
99
  },
96
100
  flush: function () {
97
- if (submitter)
101
+ if ((0, consent_1.isConsentGranted)(settings))
98
102
  return submitter.execute();
99
103
  else
100
104
  return Promise.resolve();
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isConsentGranted = void 0;
4
+ var constants_1 = require("./constants");
5
+ function isConsentGranted(settings) {
6
+ var userConsent = settings.userConsent;
7
+ // undefined userConsent is handled as granted (default)
8
+ return !userConsent || userConsent === constants_1.CONSENT_GRANTED;
9
+ }
10
+ exports.isConsentGranted = isConsentGranted;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.STORAGE_PLUGGABLE = exports.STORAGE_REDIS = exports.STORAGE_LOCALSTORAGE = exports.STORAGE_MEMORY = exports.CONSUMER_PARTIAL_MODE = exports.CONSUMER_MODE = exports.PRODUCER_MODE = exports.STANDALONE_MODE = exports.LOCALHOST_MODE = exports.OPTIMIZED = exports.DEBUG = exports.SPLIT_EVENT = exports.SPLIT_IMPRESSION = exports.NA = exports.UNKNOWN = exports.CONTROL_WITH_CONFIG = exports.CONTROL = void 0;
3
+ exports.CONSENT_UNKNOWN = exports.CONSENT_DECLINED = exports.CONSENT_GRANTED = exports.STORAGE_PLUGGABLE = exports.STORAGE_REDIS = exports.STORAGE_LOCALSTORAGE = exports.STORAGE_MEMORY = exports.CONSUMER_PARTIAL_MODE = exports.CONSUMER_MODE = exports.PRODUCER_MODE = exports.STANDALONE_MODE = exports.LOCALHOST_MODE = exports.OPTIMIZED = exports.DEBUG = exports.SPLIT_EVENT = exports.SPLIT_IMPRESSION = exports.NA = exports.UNKNOWN = exports.CONTROL_WITH_CONFIG = exports.CONTROL = void 0;
4
4
  // Special treatments
5
5
  exports.CONTROL = 'control';
6
6
  exports.CONTROL_WITH_CONFIG = {
@@ -27,3 +27,7 @@ exports.STORAGE_MEMORY = 'MEMORY';
27
27
  exports.STORAGE_LOCALSTORAGE = 'LOCALSTORAGE';
28
28
  exports.STORAGE_REDIS = 'REDIS';
29
29
  exports.STORAGE_PLUGGABLE = 'PLUGGABLE';
30
+ // User consent
31
+ exports.CONSENT_GRANTED = 'GRANTED'; // The user has granted consent for tracking events and impressions
32
+ exports.CONSENT_DECLINED = 'DECLINED'; // The user has declined consent for tracking events and impressions
33
+ exports.CONSENT_UNKNOWN = 'UNKNOWN'; // The user has neither granted nor declined consent for tracking events and impressions