@splitsoftware/splitio-commons 1.2.1-rc.5 → 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 (33) hide show
  1. package/cjs/logger/constants.js +3 -2
  2. package/cjs/logger/messages/debug.js +3 -3
  3. package/cjs/logger/messages/error.js +2 -2
  4. package/cjs/logger/messages/info.js +4 -3
  5. package/cjs/sdkFactory/userConsentProps.js +11 -8
  6. package/cjs/storages/KeyBuilder.js +1 -5
  7. package/cjs/sync/submitters/eventsSyncTask.js +8 -1
  8. package/cjs/utils/lang/index.js +8 -1
  9. package/cjs/utils/settingsValidation/consent.js +2 -2
  10. package/cjs/utils/settingsValidation/impressionsMode.js +2 -2
  11. package/esm/logger/constants.js +1 -0
  12. package/esm/logger/messages/debug.js +3 -3
  13. package/esm/logger/messages/error.js +2 -2
  14. package/esm/logger/messages/info.js +4 -3
  15. package/esm/sdkFactory/userConsentProps.js +12 -9
  16. package/esm/storages/KeyBuilder.js +2 -6
  17. package/esm/sync/submitters/eventsSyncTask.js +8 -1
  18. package/esm/utils/lang/index.js +6 -0
  19. package/esm/utils/settingsValidation/consent.js +2 -2
  20. package/esm/utils/settingsValidation/impressionsMode.js +2 -2
  21. package/package.json +1 -1
  22. package/src/logger/constants.ts +1 -0
  23. package/src/logger/messages/debug.ts +3 -3
  24. package/src/logger/messages/error.ts +2 -2
  25. package/src/logger/messages/info.ts +4 -3
  26. package/src/sdkFactory/userConsentProps.ts +12 -9
  27. package/src/storages/KeyBuilder.ts +2 -6
  28. package/src/sync/submitters/eventsSyncTask.ts +8 -1
  29. package/src/utils/lang/index.ts +8 -1
  30. package/src/utils/settingsValidation/consent.ts +2 -1
  31. package/src/utils/settingsValidation/impressionsMode.ts +2 -1
  32. package/types/logger/constants.d.ts +1 -0
  33. package/types/utils/lang/index.d.ts +4 -0
@@ -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_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.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 = 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.
@@ -73,6 +73,7 @@ exports.SYNC_STOP_POLLING = 119;
73
73
  exports.EVENTS_TRACKER_SUCCESS = 120;
74
74
  exports.IMPRESSIONS_TRACKER_SUCCESS = 121;
75
75
  exports.USER_CONSENT_UPDATED = 122;
76
+ exports.USER_CONSENT_NOT_UPDATED = 123;
76
77
  exports.ENGINE_VALUE_INVALID = 200;
77
78
  exports.ENGINE_VALUE_NO_ATTRIBUTES = 201;
78
79
  exports.CLIENT_NO_LISTENER = 202;
@@ -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,7 +31,7 @@ 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: you must provide a boolean param.'],
34
+ [c.ERROR_NOT_BOOLEAN, '%s: provided param must be a boolean value.'],
35
35
  // initialization / settings validation
36
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".'],
37
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.'],
@@ -12,11 +12,12 @@ 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, 'User consent changed from %s to %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).'],
20
21
  // synchronizer
21
22
  [c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
22
23
  [c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.userConsentProps = void 0;
4
4
  var constants_1 = require("../logger/constants");
5
5
  var constants_2 = require("../utils/constants");
6
+ var lang_1 = require("../utils/lang");
6
7
  // Extend client-side factory instances with user consent getter/setter
7
8
  function userConsentProps(settings, syncManager) {
8
9
  var log = settings.log;
@@ -10,19 +11,21 @@ function userConsentProps(settings, syncManager) {
10
11
  setUserConsent: function (consent) {
11
12
  var _a, _b;
12
13
  // validate input param
13
- if (typeof consent !== 'boolean') {
14
- log.error(constants_1.ERROR_NOT_BOOLEAN, ['setUserConsent']);
14
+ if (!(0, lang_1.isBoolean)(consent)) {
15
+ log.warn(constants_1.ERROR_NOT_BOOLEAN, ['setUserConsent']);
15
16
  return false;
16
17
  }
17
18
  var newConsentStatus = consent ? constants_2.CONSENT_GRANTED : constants_2.CONSENT_DECLINED;
18
- if (settings.userConsent !== newConsentStatus) {
19
- // resume/pause submitters
19
+ if (settings.userConsent !== newConsentStatus) { // @ts-ignore, modify readonly prop
20
+ settings.userConsent = newConsentStatus;
20
21
  if (consent)
21
- (_a = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _a === void 0 ? void 0 : _a.start();
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
22
23
  else
23
- (_b = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _b === void 0 ? void 0 : _b.stop();
24
- log.info(constants_1.USER_CONSENT_UPDATED, [settings.userConsent, newConsentStatus]); // @ts-ignore, modify readonly prop
25
- settings.userConsent = newConsentStatus;
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]);
26
29
  }
27
30
  return true;
28
31
  },
@@ -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 () {
@@ -10,18 +10,25 @@ var DATA_NAME = 'events';
10
10
  function eventsSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, eventsFirstPushWindow, latencyTracker) {
11
11
  // don't retry events.
12
12
  var syncTask = (0, submitterSyncTask_1.submitterSyncTaskFactory)(log, postEventsBulk, eventsCache, eventsPushRate, DATA_NAME, latencyTracker);
13
- // Set a timer for the first push of events,
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.
14
15
  if (eventsFirstPushWindow > 0) {
16
+ var running_1 = false;
15
17
  var stopEventPublisherTimeout_1;
16
18
  var originalStart_1 = syncTask.start;
17
19
  syncTask.start = function () {
20
+ running_1 = true;
18
21
  stopEventPublisherTimeout_1 = setTimeout(originalStart_1, eventsFirstPushWindow);
19
22
  };
20
23
  var originalStop_1 = syncTask.stop;
21
24
  syncTask.stop = function () {
25
+ running_1 = false;
22
26
  clearTimeout(stopEventPublisherTimeout_1);
23
27
  originalStop_1();
24
28
  };
29
+ syncTask.isRunning = function () {
30
+ return running_1;
31
+ };
25
32
  }
26
33
  // register events submitter to be executed when events cache is full
27
34
  eventsCache.setOnFullQueueCb(function () {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.uniqueId = exports.uniqAsStrings = exports.uniq = exports.toString = exports.toNumber = exports.startsWith = exports.merge = exports.isString = exports.isObject = exports.isNaNNumber = exports.isIntegerNumber = exports.isFiniteNumber = exports.isBoolean = exports.groupBy = exports.get = exports.forOwn = exports.findIndex = exports.find = exports.endsWith = void 0;
3
+ exports.uniqueId = exports.uniqAsStrings = exports.uniq = exports.toString = exports.toNumber = exports.startsWith = exports.merge = exports.stringToUpperCase = exports.isString = exports.isObject = exports.isNaNNumber = exports.isIntegerNumber = exports.isFiniteNumber = exports.isBoolean = exports.groupBy = exports.get = exports.forOwn = exports.findIndex = exports.find = exports.endsWith = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  /**
6
6
  * Checks if the target string ends with the sub string.
@@ -167,6 +167,13 @@ function isString(val) {
167
167
  return typeof val === 'string' || val instanceof String;
168
168
  }
169
169
  exports.isString = isString;
170
+ /**
171
+ * String sanitizer. Returns the provided value converted to uppercase if it is a string.
172
+ */
173
+ function stringToUpperCase(val) {
174
+ return isString(val) ? val.toUpperCase() : val;
175
+ }
176
+ exports.stringToUpperCase = stringToUpperCase;
170
177
  /**
171
178
  * Deep copy version of Object.assign using recursion.
172
179
  * There are some assumptions here. It's for internal use and we don't need verbose errors
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateConsent = void 0;
4
4
  var constants_1 = require("../../logger/constants");
5
5
  var constants_2 = require("../constants");
6
+ var lang_1 = require("../lang");
6
7
  var userConsentValues = [constants_2.CONSENT_DECLINED, constants_2.CONSENT_GRANTED, constants_2.CONSENT_UNKNOWN];
7
8
  function validateConsent(_a) {
8
9
  var userConsent = _a.userConsent, log = _a.log;
9
- if (typeof userConsent === 'string')
10
- userConsent = userConsent.toUpperCase();
10
+ userConsent = (0, lang_1.stringToUpperCase)(userConsent);
11
11
  if (userConsentValues.indexOf(userConsent) > -1)
12
12
  return userConsent;
13
13
  log.error(constants_1.ERROR_INVALID_CONFIG_PARAM, ['userConsent', userConsentValues, constants_2.CONSENT_GRANTED]);
@@ -3,9 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validImpressionsMode = void 0;
4
4
  var constants_1 = require("../../logger/constants");
5
5
  var constants_2 = require("../constants");
6
+ var lang_1 = require("../lang");
6
7
  function validImpressionsMode(log, impressionsMode) {
7
- if (typeof impressionsMode === 'string')
8
- impressionsMode = impressionsMode.toUpperCase();
8
+ impressionsMode = (0, lang_1.stringToUpperCase)(impressionsMode);
9
9
  if ([constants_2.DEBUG, constants_2.OPTIMIZED].indexOf(impressionsMode) > -1)
10
10
  return impressionsMode;
11
11
  log.error(constants_1.ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [constants_2.DEBUG, constants_2.OPTIMIZED], constants_2.OPTIMIZED]);
@@ -68,6 +68,7 @@ export var SYNC_STOP_POLLING = 119;
68
68
  export var EVENTS_TRACKER_SUCCESS = 120;
69
69
  export var IMPRESSIONS_TRACKER_SUCCESS = 121;
70
70
  export var USER_CONSENT_UPDATED = 122;
71
+ export var USER_CONSENT_NOT_UPDATED = 123;
71
72
  export var ENGINE_VALUE_INVALID = 200;
72
73
  export var ENGINE_VALUE_NO_ATTRIBUTES = 201;
73
74
  export var CLIENT_NO_LISTENER = 202;
@@ -30,9 +30,9 @@ export var codesDebug = codesInfo.concat([
30
30
  // SDK
31
31
  [c.CLEANUP_REGISTERING, c.LOG_PREFIX_CLEANUP + 'Registering cleanup handler %s'],
32
32
  [c.CLEANUP_DEREGISTERING, c.LOG_PREFIX_CLEANUP + 'Deregistering cleanup handler %s'],
33
- [c.RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'],
34
- [c.RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'],
35
- [c.RETRIEVE_MANAGER, ' Retrieving manager instance.'],
33
+ [c.RETRIEVE_CLIENT_DEFAULT, 'Retrieving default SDK client.'],
34
+ [c.RETRIEVE_CLIENT_EXISTING, 'Retrieving existing SDK client.'],
35
+ [c.RETRIEVE_MANAGER, 'Retrieving manager instance.'],
36
36
  // synchronizer
37
37
  [c.SYNC_OFFLINE_DATA, c.LOG_PREFIX_SYNC_OFFLINE + 'Splits data: \n%s'],
38
38
  [c.SYNC_SPLITS_FETCH, c.LOG_PREFIX_SYNC_SPLITS + 'Spin up split update using since = %s'],
@@ -4,7 +4,7 @@ export var codesError = [
4
4
  [c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid Split, no valid rules found'],
5
5
  // SDK
6
6
  [c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'],
7
- [c.ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'],
7
+ [c.ERROR_CLIENT_CANNOT_GET_READY, 'The SDK will not get ready. Reason: %s'],
8
8
  [c.ERROR_IMPRESSIONS_TRACKER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Could not store impressions bulk with %s impression(s). Error: %s'],
9
9
  [c.ERROR_IMPRESSIONS_LISTENER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Impression listener logImpression method threw: %s.'],
10
10
  [c.ERROR_EVENTS_TRACKER, c.LOG_PREFIX_EVENTS_TRACKER + 'Failed to queue %s'],
@@ -27,7 +27,7 @@ export var codesError = [
27
27
  [c.ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'],
28
28
  [c.ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'],
29
29
  [c.ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'],
30
- [c.ERROR_NOT_BOOLEAN, '%s: you must provide a boolean param.'],
30
+ [c.ERROR_NOT_BOOLEAN, '%s: provided param must be a boolean value.'],
31
31
  // initialization / settings validation
32
32
  [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".'],
33
33
  [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.'],
@@ -8,11 +8,12 @@ export var codesInfo = codesWarn.concat([
8
8
  // SDK
9
9
  [c.IMPRESSION, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Split: %s. Key: %s. Evaluation: %s. Label: %s'],
10
10
  [c.IMPRESSION_QUEUEING, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Queueing corresponding impression.'],
11
- [c.NEW_SHARED_CLIENT, ' New shared client instance created.'],
12
- [c.NEW_FACTORY, ' New Split SDK instance created.'],
11
+ [c.NEW_SHARED_CLIENT, 'New shared client instance created.'],
12
+ [c.NEW_FACTORY, 'New Split SDK instance created.'],
13
13
  [c.EVENTS_TRACKER_SUCCESS, c.LOG_PREFIX_EVENTS_TRACKER + 'Successfully queued %s'],
14
14
  [c.IMPRESSIONS_TRACKER_SUCCESS, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Successfully stored %s impression(s).'],
15
- [c.USER_CONSENT_UPDATED, 'User consent changed from %s to %s.'],
15
+ [c.USER_CONSENT_UPDATED, 'setUserConsent: consent status changed from %s to %s.'],
16
+ [c.USER_CONSENT_NOT_UPDATED, 'setUserConsent: call had no effect because it was the current consent status (%s).'],
16
17
  // synchronizer
17
18
  [c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
18
19
  [c.POLLING_START, c.LOG_PREFIX_SYNC_POLLING + 'Starting polling'],
@@ -1,5 +1,6 @@
1
- import { ERROR_NOT_BOOLEAN, USER_CONSENT_UPDATED } from '../logger/constants';
1
+ import { ERROR_NOT_BOOLEAN, USER_CONSENT_UPDATED, USER_CONSENT_NOT_UPDATED } from '../logger/constants';
2
2
  import { CONSENT_GRANTED, CONSENT_DECLINED } from '../utils/constants';
3
+ import { isBoolean } from '../utils/lang';
3
4
  // Extend client-side factory instances with user consent getter/setter
4
5
  export function userConsentProps(settings, syncManager) {
5
6
  var log = settings.log;
@@ -7,19 +8,21 @@ export function userConsentProps(settings, syncManager) {
7
8
  setUserConsent: function (consent) {
8
9
  var _a, _b;
9
10
  // validate input param
10
- if (typeof consent !== 'boolean') {
11
- log.error(ERROR_NOT_BOOLEAN, ['setUserConsent']);
11
+ if (!isBoolean(consent)) {
12
+ log.warn(ERROR_NOT_BOOLEAN, ['setUserConsent']);
12
13
  return false;
13
14
  }
14
15
  var newConsentStatus = consent ? CONSENT_GRANTED : CONSENT_DECLINED;
15
- if (settings.userConsent !== newConsentStatus) {
16
- // resume/pause submitters
16
+ if (settings.userConsent !== newConsentStatus) { // @ts-ignore, modify readonly prop
17
+ settings.userConsent = newConsentStatus;
17
18
  if (consent)
18
- (_a = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _a === void 0 ? void 0 : _a.start();
19
+ (_a = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _a === void 0 ? void 0 : _a.start(); // resumes submitters if transitioning to GRANTED
19
20
  else
20
- (_b = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _b === void 0 ? void 0 : _b.stop();
21
- log.info(USER_CONSENT_UPDATED, [settings.userConsent, newConsentStatus]); // @ts-ignore, modify readonly prop
22
- settings.userConsent = newConsentStatus;
21
+ (_b = syncManager === null || syncManager === void 0 ? void 0 : syncManager.submitter) === null || _b === void 0 ? void 0 : _b.stop(); // pauses submitters if transitioning to DECLINED
22
+ log.info(USER_CONSENT_UPDATED, [settings.userConsent, newConsentStatus]);
23
+ }
24
+ else {
25
+ log.info(USER_CONSENT_NOT_UPDATED, [newConsentStatus]);
23
26
  }
24
27
  return true;
25
28
  },
@@ -1,12 +1,8 @@
1
- import { endsWith, startsWith } from '../utils/lang';
1
+ import { startsWith } from '../utils/lang';
2
2
  var everythingAtTheEnd = /[^.]+$/;
3
3
  var DEFAULT_PREFIX = 'SPLITIO';
4
4
  export function validatePrefix(prefix) {
5
- return prefix && typeof prefix === 'string' ?
6
- endsWith(prefix, '.' + DEFAULT_PREFIX) ?
7
- prefix : // suffix already appended
8
- prefix + '.' + DEFAULT_PREFIX : // append suffix
9
- DEFAULT_PREFIX; // use default prefix if none is provided
5
+ return prefix ? prefix + '.SPLITIO' : 'SPLITIO';
10
6
  }
11
7
  var KeyBuilder = /** @class */ (function () {
12
8
  function KeyBuilder(prefix) {
@@ -7,18 +7,25 @@ var DATA_NAME = 'events';
7
7
  export function eventsSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, eventsFirstPushWindow, latencyTracker) {
8
8
  // don't retry events.
9
9
  var syncTask = submitterSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, DATA_NAME, latencyTracker);
10
- // Set a timer for the first push of events,
10
+ // Set a timer for the first push window of events.
11
+ // Not implemented in the base submitter or sync task, since this feature is only used by the events submitter.
11
12
  if (eventsFirstPushWindow > 0) {
13
+ var running_1 = false;
12
14
  var stopEventPublisherTimeout_1;
13
15
  var originalStart_1 = syncTask.start;
14
16
  syncTask.start = function () {
17
+ running_1 = true;
15
18
  stopEventPublisherTimeout_1 = setTimeout(originalStart_1, eventsFirstPushWindow);
16
19
  };
17
20
  var originalStop_1 = syncTask.stop;
18
21
  syncTask.stop = function () {
22
+ running_1 = false;
19
23
  clearTimeout(stopEventPublisherTimeout_1);
20
24
  originalStop_1();
21
25
  };
26
+ syncTask.isRunning = function () {
27
+ return running_1;
28
+ };
22
29
  }
23
30
  // register events submitter to be executed when events cache is full
24
31
  eventsCache.setOnFullQueueCb(function () {
@@ -152,6 +152,12 @@ export function isObject(obj) {
152
152
  export function isString(val) {
153
153
  return typeof val === 'string' || val instanceof String;
154
154
  }
155
+ /**
156
+ * String sanitizer. Returns the provided value converted to uppercase if it is a string.
157
+ */
158
+ export function stringToUpperCase(val) {
159
+ return isString(val) ? val.toUpperCase() : val;
160
+ }
155
161
  /**
156
162
  * Deep copy version of Object.assign using recursion.
157
163
  * There are some assumptions here. It's for internal use and we don't need verbose errors
@@ -1,10 +1,10 @@
1
1
  import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
2
2
  import { CONSENT_DECLINED, CONSENT_GRANTED, CONSENT_UNKNOWN } from '../constants';
3
+ import { stringToUpperCase } from '../lang';
3
4
  var userConsentValues = [CONSENT_DECLINED, CONSENT_GRANTED, CONSENT_UNKNOWN];
4
5
  export function validateConsent(_a) {
5
6
  var userConsent = _a.userConsent, log = _a.log;
6
- if (typeof userConsent === 'string')
7
- userConsent = userConsent.toUpperCase();
7
+ userConsent = stringToUpperCase(userConsent);
8
8
  if (userConsentValues.indexOf(userConsent) > -1)
9
9
  return userConsent;
10
10
  log.error(ERROR_INVALID_CONFIG_PARAM, ['userConsent', userConsentValues, CONSENT_GRANTED]);
@@ -1,8 +1,8 @@
1
1
  import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
2
2
  import { DEBUG, OPTIMIZED } from '../constants';
3
+ import { stringToUpperCase } from '../lang';
3
4
  export function validImpressionsMode(log, impressionsMode) {
4
- if (typeof impressionsMode === 'string')
5
- impressionsMode = impressionsMode.toUpperCase();
5
+ impressionsMode = stringToUpperCase(impressionsMode);
6
6
  if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) > -1)
7
7
  return impressionsMode;
8
8
  log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED], OPTIMIZED]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.2.1-rc.5",
3
+ "version": "1.2.1-rc.6",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -69,6 +69,7 @@ export const SYNC_STOP_POLLING = 119;
69
69
  export const EVENTS_TRACKER_SUCCESS = 120;
70
70
  export const IMPRESSIONS_TRACKER_SUCCESS = 121;
71
71
  export const USER_CONSENT_UPDATED = 122;
72
+ export const USER_CONSENT_NOT_UPDATED = 123;
72
73
 
73
74
  export const ENGINE_VALUE_INVALID = 200;
74
75
  export const ENGINE_VALUE_NO_ATTRIBUTES = 201;
@@ -31,9 +31,9 @@ export const codesDebug: [number, string][] = codesInfo.concat([
31
31
  // SDK
32
32
  [c.CLEANUP_REGISTERING, c.LOG_PREFIX_CLEANUP + 'Registering cleanup handler %s'],
33
33
  [c.CLEANUP_DEREGISTERING, c.LOG_PREFIX_CLEANUP + 'Deregistering cleanup handler %s'],
34
- [c.RETRIEVE_CLIENT_DEFAULT, ' Retrieving default SDK client.'],
35
- [c.RETRIEVE_CLIENT_EXISTING, ' Retrieving existing SDK client.'],
36
- [c.RETRIEVE_MANAGER, ' Retrieving manager instance.'],
34
+ [c.RETRIEVE_CLIENT_DEFAULT, 'Retrieving default SDK client.'],
35
+ [c.RETRIEVE_CLIENT_EXISTING, 'Retrieving existing SDK client.'],
36
+ [c.RETRIEVE_MANAGER, 'Retrieving manager instance.'],
37
37
  // synchronizer
38
38
  [c.SYNC_OFFLINE_DATA, c.LOG_PREFIX_SYNC_OFFLINE + 'Splits data: \n%s'],
39
39
  [c.SYNC_SPLITS_FETCH, c.LOG_PREFIX_SYNC_SPLITS + 'Spin up split update using since = %s'],
@@ -5,7 +5,7 @@ export const codesError: [number, string][] = [
5
5
  [c.ERROR_ENGINE_COMBINER_IFELSEIF, c.LOG_PREFIX_ENGINE_COMBINER + 'Invalid Split, no valid rules found'],
6
6
  // SDK
7
7
  [c.ERROR_LOGLEVEL_INVALID, 'logger: Invalid Log Level - No changes to the logs will be applied.'],
8
- [c.ERROR_CLIENT_CANNOT_GET_READY, ' The SDK will not get ready. Reason: %s'],
8
+ [c.ERROR_CLIENT_CANNOT_GET_READY, 'The SDK will not get ready. Reason: %s'],
9
9
  [c.ERROR_IMPRESSIONS_TRACKER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Could not store impressions bulk with %s impression(s). Error: %s'],
10
10
  [c.ERROR_IMPRESSIONS_LISTENER, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Impression listener logImpression method threw: %s.'],
11
11
  [c.ERROR_EVENTS_TRACKER, c.LOG_PREFIX_EVENTS_TRACKER + 'Failed to queue %s'],
@@ -28,7 +28,7 @@ export const codesError: [number, string][] = [
28
28
  [c.ERROR_INVALID, '%s: you passed an invalid %s. It must be a non-empty string.'],
29
29
  [c.ERROR_EMPTY, '%s: you passed an empty %s. It must be a non-empty string.'],
30
30
  [c.ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'],
31
- [c.ERROR_NOT_BOOLEAN, '%s: you must provide a boolean param.'],
31
+ [c.ERROR_NOT_BOOLEAN, '%s: provided param must be a boolean value.'],
32
32
  // initialization / settings validation
33
33
  [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".'],
34
34
  [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.'],
@@ -10,11 +10,12 @@ export const codesInfo: [number, string][] = codesWarn.concat([
10
10
  // SDK
11
11
  [c.IMPRESSION, c.LOG_PREFIX_IMPRESSIONS_TRACKER +'Split: %s. Key: %s. Evaluation: %s. Label: %s'],
12
12
  [c.IMPRESSION_QUEUEING, c.LOG_PREFIX_IMPRESSIONS_TRACKER +'Queueing corresponding impression.'],
13
- [c.NEW_SHARED_CLIENT, ' New shared client instance created.'],
14
- [c.NEW_FACTORY, ' New Split SDK instance created.'],
13
+ [c.NEW_SHARED_CLIENT, 'New shared client instance created.'],
14
+ [c.NEW_FACTORY, 'New Split SDK instance created.'],
15
15
  [c.EVENTS_TRACKER_SUCCESS, c.LOG_PREFIX_EVENTS_TRACKER + 'Successfully queued %s'],
16
16
  [c.IMPRESSIONS_TRACKER_SUCCESS, c.LOG_PREFIX_IMPRESSIONS_TRACKER + 'Successfully stored %s impression(s).'],
17
- [c.USER_CONSENT_UPDATED, 'User consent changed from %s to %s.'],
17
+ [c.USER_CONSENT_UPDATED, 'setUserConsent: consent status changed from %s to %s.'],
18
+ [c.USER_CONSENT_NOT_UPDATED, 'setUserConsent: call had no effect because it was the current consent status (%s).'],
18
19
 
19
20
  // synchronizer
20
21
  [c.POLLING_SMART_PAUSING, c.LOG_PREFIX_SYNC_POLLING + 'Turning segments data polling %s.'],
@@ -1,7 +1,8 @@
1
- import { ERROR_NOT_BOOLEAN, USER_CONSENT_UPDATED } from '../logger/constants';
1
+ import { ERROR_NOT_BOOLEAN, USER_CONSENT_UPDATED, USER_CONSENT_NOT_UPDATED } from '../logger/constants';
2
2
  import { ISyncManager } from '../sync/types';
3
3
  import { ISettings } from '../types';
4
4
  import { CONSENT_GRANTED, CONSENT_DECLINED } from '../utils/constants';
5
+ import { isBoolean } from '../utils/lang';
5
6
 
6
7
  // Extend client-side factory instances with user consent getter/setter
7
8
  export function userConsentProps(settings: ISettings, syncManager?: ISyncManager) {
@@ -11,20 +12,22 @@ export function userConsentProps(settings: ISettings, syncManager?: ISyncManager
11
12
  return {
12
13
  setUserConsent(consent: unknown) {
13
14
  // validate input param
14
- if (typeof consent !== 'boolean') {
15
- log.error(ERROR_NOT_BOOLEAN, ['setUserConsent']);
15
+ if (!isBoolean(consent)) {
16
+ log.warn(ERROR_NOT_BOOLEAN, ['setUserConsent']);
16
17
  return false;
17
18
  }
18
19
 
19
20
  const newConsentStatus = consent ? CONSENT_GRANTED : CONSENT_DECLINED;
20
21
 
21
- if (settings.userConsent !== newConsentStatus) {
22
- // resume/pause submitters
23
- if (consent) syncManager?.submitter?.start();
24
- else syncManager?.submitter?.stop();
25
-
26
- log.info(USER_CONSENT_UPDATED, [settings.userConsent, newConsentStatus]); // @ts-ignore, modify readonly prop
22
+ if (settings.userConsent !== newConsentStatus) { // @ts-ignore, modify readonly prop
27
23
  settings.userConsent = newConsentStatus;
24
+
25
+ if (consent) syncManager?.submitter?.start(); // resumes submitters if transitioning to GRANTED
26
+ else syncManager?.submitter?.stop(); // pauses submitters if transitioning to DECLINED
27
+
28
+ log.info(USER_CONSENT_UPDATED, [settings.userConsent, newConsentStatus]);
29
+ } else {
30
+ log.info(USER_CONSENT_NOT_UPDATED, [newConsentStatus]);
28
31
  }
29
32
 
30
33
  return true;
@@ -1,15 +1,11 @@
1
- import { endsWith, startsWith } from '../utils/lang';
1
+ import { startsWith } from '../utils/lang';
2
2
 
3
3
  const everythingAtTheEnd = /[^.]+$/;
4
4
 
5
5
  const DEFAULT_PREFIX = 'SPLITIO';
6
6
 
7
7
  export function validatePrefix(prefix: unknown) {
8
- return prefix && typeof prefix === 'string' ?
9
- 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
 
15
11
  export class KeyBuilder {
@@ -22,18 +22,25 @@ export function eventsSyncTaskFactory(
22
22
  // don't retry events.
23
23
  const syncTask = submitterSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, DATA_NAME, latencyTracker);
24
24
 
25
- // Set a timer for the first push of events,
25
+ // Set a timer for the first push window of events.
26
+ // Not implemented in the base submitter or sync task, since this feature is only used by the events submitter.
26
27
  if (eventsFirstPushWindow > 0) {
28
+ let running = false;
27
29
  let stopEventPublisherTimeout: ReturnType<typeof setTimeout>;
28
30
  const originalStart = syncTask.start;
29
31
  syncTask.start = () => {
32
+ running = true;
30
33
  stopEventPublisherTimeout = setTimeout(originalStart, eventsFirstPushWindow);
31
34
  };
32
35
  const originalStop = syncTask.stop;
33
36
  syncTask.stop = () => {
37
+ running = false;
34
38
  clearTimeout(stopEventPublisherTimeout);
35
39
  originalStop();
36
40
  };
41
+ syncTask.isRunning = () => {
42
+ return running;
43
+ };
37
44
  }
38
45
 
39
46
  // register events submitter to be executed when events cache is full
@@ -89,7 +89,7 @@ export function get(obj: any, prop: any, val: any): any {
89
89
  /**
90
90
  * Parses an array into a map of different arrays, grouping by the specified prop value.
91
91
  */
92
- export function groupBy<T extends Record<string, any> >(source: T[], prop: string): Record<string, T[]> {
92
+ export function groupBy<T extends Record<string, any>>(source: T[], prop: string): Record<string, T[]> {
93
93
  const map: Record<string, any[]> = {};
94
94
 
95
95
  if (Array.isArray(source) && isString(prop)) {
@@ -164,6 +164,13 @@ export function isString(val: any): val is string {
164
164
  return typeof val === 'string' || val instanceof String;
165
165
  }
166
166
 
167
+ /**
168
+ * String sanitizer. Returns the provided value converted to uppercase if it is a string.
169
+ */
170
+ export function stringToUpperCase(val: any) {
171
+ return isString(val) ? val.toUpperCase() : val;
172
+ }
173
+
167
174
  /**
168
175
  * Deep copy version of Object.assign using recursion.
169
176
  * There are some assumptions here. It's for internal use and we don't need verbose errors
@@ -1,11 +1,12 @@
1
1
  import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { CONSENT_DECLINED, CONSENT_GRANTED, CONSENT_UNKNOWN } from '../constants';
4
+ import { stringToUpperCase } from '../lang';
4
5
 
5
6
  const userConsentValues = [CONSENT_DECLINED, CONSENT_GRANTED, CONSENT_UNKNOWN];
6
7
 
7
8
  export function validateConsent({ userConsent, log }: { userConsent: any, log: ILogger }) {
8
- if (typeof userConsent === 'string') userConsent = userConsent.toUpperCase();
9
+ userConsent = stringToUpperCase(userConsent);
9
10
 
10
11
  if (userConsentValues.indexOf(userConsent) > -1) return userConsent;
11
12
 
@@ -2,9 +2,10 @@ import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
2
2
  import { ILogger } from '../../logger/types';
3
3
  import { SplitIO } from '../../types';
4
4
  import { DEBUG, OPTIMIZED } from '../constants';
5
+ import { stringToUpperCase } from '../lang';
5
6
 
6
7
  export function validImpressionsMode(log: ILogger, impressionsMode: any): SplitIO.ImpressionsMode {
7
- if (typeof impressionsMode === 'string') impressionsMode = impressionsMode.toUpperCase();
8
+ impressionsMode = stringToUpperCase(impressionsMode);
8
9
 
9
10
  if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) > -1) return impressionsMode;
10
11
 
@@ -68,6 +68,7 @@ export declare const SYNC_STOP_POLLING = 119;
68
68
  export declare const EVENTS_TRACKER_SUCCESS = 120;
69
69
  export declare const IMPRESSIONS_TRACKER_SUCCESS = 121;
70
70
  export declare const USER_CONSENT_UPDATED = 122;
71
+ export declare const USER_CONSENT_NOT_UPDATED = 123;
71
72
  export declare const ENGINE_VALUE_INVALID = 200;
72
73
  export declare const ENGINE_VALUE_NO_ATTRIBUTES = 201;
73
74
  export declare const CLIENT_NO_LISTENER = 202;
@@ -62,6 +62,10 @@ export declare function isObject(obj: any): boolean;
62
62
  * Checks if a given value is a string.
63
63
  */
64
64
  export declare function isString(val: any): val is string;
65
+ /**
66
+ * String sanitizer. Returns the provided value converted to uppercase if it is a string.
67
+ */
68
+ export declare function stringToUpperCase(val: any): any;
65
69
  /**
66
70
  * Deep copy version of Object.assign using recursion.
67
71
  * There are some assumptions here. It's for internal use and we don't need verbose errors