@splitsoftware/splitio-commons 1.4.2-rc.0 → 1.4.2-rc.3

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 (81) hide show
  1. package/CHANGES.txt +4 -3
  2. package/cjs/integrations/ga/GaToSplit.js +11 -12
  3. package/cjs/sync/syncManagerOnline.js +34 -19
  4. package/cjs/sync/syncTask.js +15 -10
  5. package/cjs/utils/settingsValidation/index.js +6 -1
  6. package/esm/integrations/ga/GaToSplit.js +11 -12
  7. package/esm/sync/syncManagerOnline.js +34 -19
  8. package/esm/sync/syncTask.js +15 -10
  9. package/esm/utils/settingsValidation/index.js +6 -1
  10. package/package.json +1 -1
  11. package/src/integrations/ga/GaToSplit.ts +8 -14
  12. package/src/integrations/ga/types.ts +2 -13
  13. package/src/sdkClient/clientAttributesDecoration.ts +9 -9
  14. package/src/sync/syncManagerOnline.ts +29 -16
  15. package/src/sync/syncTask.ts +17 -11
  16. package/src/types.ts +7 -1
  17. package/src/utils/settingsValidation/index.ts +7 -1
  18. package/types/integrations/ga/types.d.ts +2 -13
  19. package/types/logger/browser/{debugLogger.d.ts → DebugLogger.d.ts} +0 -0
  20. package/types/logger/browser/{errorLogger.d.ts → ErrorLogger.d.ts} +0 -0
  21. package/types/logger/browser/{infoLogger.d.ts → InfoLogger.d.ts} +0 -0
  22. package/types/logger/browser/{warnLogger.d.ts → WarnLogger.d.ts} +0 -0
  23. package/types/sync/syncTask.d.ts +2 -2
  24. package/types/types.d.ts +6 -0
  25. package/types/utils/settingsValidation/index.d.ts +1 -0
  26. package/types/utils/timeTracker/index.d.ts +70 -1
  27. package/cjs/integrations/ga/autoRequire.js +0 -34
  28. package/esm/integrations/ga/autoRequire.js +0 -30
  29. package/src/integrations/ga/autoRequire.ts +0 -35
  30. package/src/logger/.DS_Store +0 -0
  31. package/types/integrations/ga/GaToSplitPlugin.d.ts +0 -3
  32. package/types/integrations/ga/SplitToGaPlugin.d.ts +0 -4
  33. package/types/integrations/ga/autoRequire.d.ts +0 -4
  34. package/types/logger/codes.d.ts +0 -2
  35. package/types/logger/codesConstants.d.ts +0 -117
  36. package/types/logger/codesConstantsBrowser.d.ts +0 -2
  37. package/types/logger/codesConstantsNode.d.ts +0 -14
  38. package/types/logger/codesDebug.d.ts +0 -1
  39. package/types/logger/codesDebugBrowser.d.ts +0 -1
  40. package/types/logger/codesDebugNode.d.ts +0 -1
  41. package/types/logger/codesError.d.ts +0 -1
  42. package/types/logger/codesErrorNode.d.ts +0 -1
  43. package/types/logger/codesInfo.d.ts +0 -1
  44. package/types/logger/codesWarn.d.ts +0 -1
  45. package/types/logger/codesWarnNode.d.ts +0 -1
  46. package/types/logger/debugLogger.d.ts +0 -2
  47. package/types/logger/errorLogger.d.ts +0 -2
  48. package/types/logger/infoLogger.d.ts +0 -2
  49. package/types/logger/messages/debugBrowser.d.ts +0 -1
  50. package/types/logger/messages/debugNode.d.ts +0 -1
  51. package/types/logger/messages/errorNode.d.ts +0 -1
  52. package/types/logger/messages/warnNode.d.ts +0 -1
  53. package/types/logger/noopLogger.d.ts +0 -2
  54. package/types/logger/warnLogger.d.ts +0 -2
  55. package/types/sdkFactory/userConsentProps.d.ts +0 -6
  56. package/types/sdkManager/sdkManagerMethod.d.ts +0 -6
  57. package/types/storages/getRegisteredSegments.d.ts +0 -10
  58. package/types/storages/inMemory/index.d.ts +0 -10
  59. package/types/storages/parseSegments.d.ts +0 -6
  60. package/types/sync/polling/syncTasks/splitsSyncTask.copy.d.ts +0 -35
  61. package/types/sync/polling/syncTasks/splitsSyncTask.morelikeoriginal.d.ts +0 -35
  62. package/types/sync/streaming/AuthClient/indexV1.d.ts +0 -12
  63. package/types/sync/streaming/AuthClient/indexV2.d.ts +0 -8
  64. package/types/sync/streaming/pushManagerCS.d.ts +0 -1
  65. package/types/sync/streaming/pushManagerNoUsers.d.ts +0 -13
  66. package/types/sync/streaming/pushManagerSS.d.ts +0 -1
  67. package/types/sync/submitters/telemetrySyncTask.d.ts +0 -0
  68. package/types/sync/syncManagerFromFile.d.ts +0 -2
  69. package/types/sync/syncManagerFromObject.d.ts +0 -2
  70. package/types/sync/syncManagerOffline.d.ts +0 -9
  71. package/types/trackers/telemetryRecorder.d.ts +0 -0
  72. package/types/utils/EventEmitter.d.ts +0 -4
  73. package/types/utils/consent.d.ts +0 -2
  74. package/types/utils/lang/errors.d.ts +0 -10
  75. package/types/utils/murmur3/commons.d.ts +0 -12
  76. package/types/utils/settingsValidation/buildMetadata.d.ts +0 -3
  77. package/types/utils/settingsValidation/localhost/index.d.ts +0 -9
  78. package/types/utils/settingsValidation/logger.d.ts +0 -11
  79. package/types/utils/settingsValidation/runtime/browser.d.ts +0 -2
  80. package/types/utils/settingsValidation/runtime/node.d.ts +0 -2
  81. package/types/utils/settingsValidation/userConsent.d.ts +0 -5
package/CHANGES.txt CHANGED
@@ -1,6 +1,7 @@
1
- 1.4.2 (June XX, 2022)
2
- - Added `autoRequire` configuration for GoogleAnalyticsToSplit integration (See https://help.split.io/hc/en-us/articles/360040838752#google-tag-manager).
3
- - Updated telemetry to submit data even if user consent is not granted.
1
+ 1.5.0 (June 24, 2022)
2
+ - Added a new config option to control the tasks that listen or poll for updates on feature flags and segments, via the new config sync.enabled . Running online Split will always pull the most recent updates upon initialization, this only affects updates fetching on a running instance. Useful when a consistent session experience is a must or to save resources when updates are not being used.
3
+ - Updated telemetry logic to track the anonymous config for user consent flag set to declined or unknown.
4
+ - Updated submitters logic, to avoid duplicating the post of impressions to Split cloud when the SDK is destroyed while its periodic post of impressions is running.
4
5
 
5
6
  1.4.1 (June 13, 2022)
6
7
  - Bugfixing - Updated submitters logic, to avoid dropping impressions and events that are being tracked while POST request is pending.
@@ -10,24 +10,23 @@ var logNameMapper = 'ga-to-split:mapper';
10
10
  /**
11
11
  * Provides a plugin to use with analytics.js, accounting for the possibility
12
12
  * that the global command queue has been renamed or not yet defined.
13
- * @param window Reference to global object.
14
- * @param pluginName The plugin name identifier.
15
- * @param pluginConstructor The plugin constructor function.
16
- * @param log Logger instance.
17
- * @param autoRequire If true, log error when auto-require script is not detected
13
+ * @param {string} pluginName The plugin name identifier.
14
+ * @param {Function} pluginConstructor The plugin constructor function.
18
15
  */
19
- function providePlugin(window, pluginName, pluginConstructor, log, autoRequire) {
16
+ function providePlugin(pluginName, pluginConstructor) {
20
17
  // get reference to global command queue. Init it if not defined yet.
18
+ // @ts-expect-error
21
19
  var gaAlias = window.GoogleAnalyticsObject || 'ga';
22
20
  window[gaAlias] = window[gaAlias] || function () {
23
- (window[gaAlias].q = window[gaAlias].q || []).push(arguments);
21
+ var args = [];
22
+ for (var _i = 0; _i < arguments.length; _i++) {
23
+ args[_i] = arguments[_i];
24
+ }
25
+ (window[gaAlias].q = window[gaAlias].q || []).push(args);
24
26
  };
25
27
  // provides the plugin for use with analytics.js.
28
+ // @ts-expect-error
26
29
  window[gaAlias]('provide', pluginName, pluginConstructor);
27
- if (autoRequire && (!window[gaAlias].q || window[gaAlias].q.push === [].push)) {
28
- // Expecting spy on ga.q push method but not found
29
- log.error('Auto-require script was expected but not provided.');
30
- }
31
30
  }
32
31
  // Default mapping: object used for building the default mapper from hits to Split events
33
32
  var defaultMapping = {
@@ -247,6 +246,6 @@ function GaToSplit(sdkOptions, params) {
247
246
  return SplitTracker;
248
247
  }());
249
248
  // Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
250
- providePlugin(window, 'splitTracker', SplitTracker, log, sdkOptions.autoRequire);
249
+ providePlugin('splitTracker', SplitTracker);
251
250
  }
252
251
  exports.GaToSplit = GaToSplit;
@@ -19,11 +19,11 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
19
19
  * SyncManager factory for modular SDK
20
20
  */
21
21
  return function (params) {
22
- var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, telemetryTracker = params.telemetryTracker;
22
+ var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker;
23
23
  /** Polling Manager */
24
24
  var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
25
25
  /** Push Manager */
26
- var pushManager = streamingEnabled && pollingManager && pushManagerFactory ?
26
+ var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
27
27
  pushManagerFactory(params, pollingManager) :
28
28
  undefined;
29
29
  /** Submitter Manager */
@@ -69,16 +69,25 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
69
69
  running = true;
70
70
  // start syncing splits and segments
71
71
  if (pollingManager) {
72
- if (pushManager) {
73
- // Doesn't call `syncAll` when the syncManager is resuming
72
+ // If synchronization is disabled pushManager and pollingManager should not start
73
+ if (syncEnabled) {
74
+ if (pushManager) {
75
+ // Doesn't call `syncAll` when the syncManager is resuming
76
+ if (startFirstTime) {
77
+ pollingManager.syncAll();
78
+ startFirstTime = false;
79
+ }
80
+ pushManager.start();
81
+ }
82
+ else {
83
+ pollingManager.start();
84
+ }
85
+ }
86
+ else {
74
87
  if (startFirstTime) {
75
88
  pollingManager.syncAll();
76
89
  startFirstTime = false;
77
90
  }
78
- pushManager.start();
79
- }
80
- else {
81
- pollingManager.start();
82
91
  }
83
92
  }
84
93
  // start periodic data recording (events, impressions, telemetry).
@@ -112,22 +121,28 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
112
121
  return {
113
122
  isRunning: mySegmentsSyncTask.isRunning,
114
123
  start: function () {
115
- if (pushManager) {
116
- if (pollingManager.isRunning()) {
117
- // if doing polling, we must start the periodic fetch of data
118
- if (storage.splits.usesSegments())
119
- mySegmentsSyncTask.start();
124
+ if (syncEnabled) {
125
+ if (pushManager) {
126
+ if (pollingManager.isRunning()) {
127
+ // if doing polling, we must start the periodic fetch of data
128
+ if (storage.splits.usesSegments())
129
+ mySegmentsSyncTask.start();
130
+ }
131
+ else {
132
+ // if not polling, we must execute the sync task for the initial fetch
133
+ // of segments since `syncAll` was already executed when starting the main client
134
+ mySegmentsSyncTask.execute();
135
+ }
136
+ pushManager.add(matchingKey, mySegmentsSyncTask);
120
137
  }
121
138
  else {
122
- // if not polling, we must execute the sync task for the initial fetch
123
- // of segments since `syncAll` was already executed when starting the main client
124
- mySegmentsSyncTask.execute();
139
+ if (storage.splits.usesSegments())
140
+ mySegmentsSyncTask.start();
125
141
  }
126
- pushManager.add(matchingKey, mySegmentsSyncTask);
127
142
  }
128
143
  else {
129
- if (storage.splits.usesSegments())
130
- mySegmentsSyncTask.start();
144
+ if (!readinessManager.isReady())
145
+ mySegmentsSyncTask.execute();
131
146
  }
132
147
  },
133
148
  stop: function () {
@@ -4,8 +4,8 @@ exports.syncTaskFactory = void 0;
4
4
  var constants_1 = require("../logger/constants");
5
5
  /**
6
6
  * Creates a syncTask that handles the periodic execution of a given task ("start" and "stop" methods).
7
- * The task can be executed once calling the "execute" method.
8
- * NOTE: Multiple calls to "execute" are not queued. Use "isExecuting" method to handle synchronization.
7
+ * The task can be also executed by calling the "execute" method. Multiple execute calls are chained to run secuentially and avoid race conditions.
8
+ * For example, submitters executed on SDK destroy or full queue, while periodic execution is pending.
9
9
  *
10
10
  * @param log Logger instance.
11
11
  * @param task Task to execute that returns a promise that NEVER REJECTS. Otherwise, periodic execution can result in Unhandled Promise Rejections.
@@ -15,8 +15,8 @@ var constants_1 = require("../logger/constants");
15
15
  */
16
16
  function syncTaskFactory(log, task, period, taskName) {
17
17
  if (taskName === void 0) { taskName = 'task'; }
18
- // Flag that indicates if the task is being executed
19
- var executing = false;
18
+ // Task promise while it is pending. Undefined once the promise is resolved
19
+ var pendingTask;
20
20
  // flag that indicates if the task periodic execution has been started/stopped.
21
21
  var running = false;
22
22
  // Auxiliar counter used to avoid race condition when calling `start` & `stop` intermittently
@@ -30,13 +30,19 @@ function syncTaskFactory(log, task, period, taskName) {
30
30
  for (var _i = 0; _i < arguments.length; _i++) {
31
31
  args[_i] = arguments[_i];
32
32
  }
33
- executing = true;
33
+ // If task is executing, chain the new execution
34
+ if (pendingTask) {
35
+ return pendingTask.then(function () {
36
+ return execute.apply(void 0, args);
37
+ });
38
+ }
39
+ // Execute task
34
40
  log.debug(constants_1.SYNC_TASK_EXECUTE, [taskName]);
35
- return task.apply(void 0, args).then(function (result) {
36
- executing = false;
41
+ pendingTask = task.apply(void 0, args).then(function (result) {
42
+ pendingTask = undefined;
37
43
  return result;
38
44
  });
39
- // No need to handle promise rejection because it is a pre-condition that provided task never rejects.
45
+ return pendingTask;
40
46
  }
41
47
  function periodicExecute(currentRunningId) {
42
48
  return execute.apply(void 0, runningArgs).then(function (result) {
@@ -48,10 +54,9 @@ function syncTaskFactory(log, task, period, taskName) {
48
54
  });
49
55
  }
50
56
  return {
51
- // @TODO check if we need to queued `execute` calls, to avoid possible race conditions on submitters and updaters with streaming.
52
57
  execute: execute,
53
58
  isExecuting: function () {
54
- return executing;
59
+ return pendingTask !== undefined;
55
60
  },
56
61
  start: function () {
57
62
  var args = [];
@@ -73,7 +73,8 @@ exports.base = {
73
73
  splitFilters: undefined,
74
74
  // impressions collection mode
75
75
  impressionsMode: constants_1.OPTIMIZED,
76
- localhostMode: undefined
76
+ localhostMode: undefined,
77
+ enabled: true
77
78
  },
78
79
  // Logger
79
80
  log: undefined
@@ -167,6 +168,10 @@ function settingsValidation(config, validationParams) {
167
168
  // We are not checking if bases are positive numbers. Thus, we might be reauthenticating immediately (`setTimeout` with NaN or negative number)
168
169
  scheduler.pushRetryBackoffBase = fromSecondsToMillis(scheduler.pushRetryBackoffBase);
169
170
  }
171
+ // validate sync enabled
172
+ if (withDefaults.sync.enabled !== false) { // @ts-ignore, modify readonly prop
173
+ withDefaults.sync.enabled = true;
174
+ }
170
175
  // validate the `splitFilters` settings and parse splits query
171
176
  var splitFiltersValidation = (0, splitFilters_1.validateSplitFilters)(log, withDefaults.sync.splitFilters, withDefaults.mode);
172
177
  withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
@@ -7,24 +7,23 @@ var logNameMapper = 'ga-to-split:mapper';
7
7
  /**
8
8
  * Provides a plugin to use with analytics.js, accounting for the possibility
9
9
  * that the global command queue has been renamed or not yet defined.
10
- * @param window Reference to global object.
11
- * @param pluginName The plugin name identifier.
12
- * @param pluginConstructor The plugin constructor function.
13
- * @param log Logger instance.
14
- * @param autoRequire If true, log error when auto-require script is not detected
10
+ * @param {string} pluginName The plugin name identifier.
11
+ * @param {Function} pluginConstructor The plugin constructor function.
15
12
  */
16
- function providePlugin(window, pluginName, pluginConstructor, log, autoRequire) {
13
+ function providePlugin(pluginName, pluginConstructor) {
17
14
  // get reference to global command queue. Init it if not defined yet.
15
+ // @ts-expect-error
18
16
  var gaAlias = window.GoogleAnalyticsObject || 'ga';
19
17
  window[gaAlias] = window[gaAlias] || function () {
20
- (window[gaAlias].q = window[gaAlias].q || []).push(arguments);
18
+ var args = [];
19
+ for (var _i = 0; _i < arguments.length; _i++) {
20
+ args[_i] = arguments[_i];
21
+ }
22
+ (window[gaAlias].q = window[gaAlias].q || []).push(args);
21
23
  };
22
24
  // provides the plugin for use with analytics.js.
25
+ // @ts-expect-error
23
26
  window[gaAlias]('provide', pluginName, pluginConstructor);
24
- if (autoRequire && (!window[gaAlias].q || window[gaAlias].q.push === [].push)) {
25
- // Expecting spy on ga.q push method but not found
26
- log.error('Auto-require script was expected but not provided.');
27
- }
28
27
  }
29
28
  // Default mapping: object used for building the default mapper from hits to Split events
30
29
  var defaultMapping = {
@@ -241,5 +240,5 @@ export function GaToSplit(sdkOptions, params) {
241
240
  return SplitTracker;
242
241
  }());
243
242
  // Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
244
- providePlugin(window, 'splitTracker', SplitTracker, log, sdkOptions.autoRequire);
243
+ providePlugin('splitTracker', SplitTracker);
245
244
  }
@@ -16,11 +16,11 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
16
16
  * SyncManager factory for modular SDK
17
17
  */
18
18
  return function (params) {
19
- var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, telemetryTracker = params.telemetryTracker;
19
+ var settings = params.settings, _a = params.settings, log = _a.log, streamingEnabled = _a.streamingEnabled, syncEnabled = _a.sync.enabled, telemetryTracker = params.telemetryTracker;
20
20
  /** Polling Manager */
21
21
  var pollingManager = pollingManagerFactory && pollingManagerFactory(params);
22
22
  /** Push Manager */
23
- var pushManager = streamingEnabled && pollingManager && pushManagerFactory ?
23
+ var pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
24
24
  pushManagerFactory(params, pollingManager) :
25
25
  undefined;
26
26
  /** Submitter Manager */
@@ -66,16 +66,25 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
66
66
  running = true;
67
67
  // start syncing splits and segments
68
68
  if (pollingManager) {
69
- if (pushManager) {
70
- // Doesn't call `syncAll` when the syncManager is resuming
69
+ // If synchronization is disabled pushManager and pollingManager should not start
70
+ if (syncEnabled) {
71
+ if (pushManager) {
72
+ // Doesn't call `syncAll` when the syncManager is resuming
73
+ if (startFirstTime) {
74
+ pollingManager.syncAll();
75
+ startFirstTime = false;
76
+ }
77
+ pushManager.start();
78
+ }
79
+ else {
80
+ pollingManager.start();
81
+ }
82
+ }
83
+ else {
71
84
  if (startFirstTime) {
72
85
  pollingManager.syncAll();
73
86
  startFirstTime = false;
74
87
  }
75
- pushManager.start();
76
- }
77
- else {
78
- pollingManager.start();
79
88
  }
80
89
  }
81
90
  // start periodic data recording (events, impressions, telemetry).
@@ -109,22 +118,28 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
109
118
  return {
110
119
  isRunning: mySegmentsSyncTask.isRunning,
111
120
  start: function () {
112
- if (pushManager) {
113
- if (pollingManager.isRunning()) {
114
- // if doing polling, we must start the periodic fetch of data
115
- if (storage.splits.usesSegments())
116
- mySegmentsSyncTask.start();
121
+ if (syncEnabled) {
122
+ if (pushManager) {
123
+ if (pollingManager.isRunning()) {
124
+ // if doing polling, we must start the periodic fetch of data
125
+ if (storage.splits.usesSegments())
126
+ mySegmentsSyncTask.start();
127
+ }
128
+ else {
129
+ // if not polling, we must execute the sync task for the initial fetch
130
+ // of segments since `syncAll` was already executed when starting the main client
131
+ mySegmentsSyncTask.execute();
132
+ }
133
+ pushManager.add(matchingKey, mySegmentsSyncTask);
117
134
  }
118
135
  else {
119
- // if not polling, we must execute the sync task for the initial fetch
120
- // of segments since `syncAll` was already executed when starting the main client
121
- mySegmentsSyncTask.execute();
136
+ if (storage.splits.usesSegments())
137
+ mySegmentsSyncTask.start();
122
138
  }
123
- pushManager.add(matchingKey, mySegmentsSyncTask);
124
139
  }
125
140
  else {
126
- if (storage.splits.usesSegments())
127
- mySegmentsSyncTask.start();
141
+ if (!readinessManager.isReady())
142
+ mySegmentsSyncTask.execute();
128
143
  }
129
144
  },
130
145
  stop: function () {
@@ -1,8 +1,8 @@
1
1
  import { SYNC_TASK_EXECUTE, SYNC_TASK_START, SYNC_TASK_STOP } from '../logger/constants';
2
2
  /**
3
3
  * Creates a syncTask that handles the periodic execution of a given task ("start" and "stop" methods).
4
- * The task can be executed once calling the "execute" method.
5
- * NOTE: Multiple calls to "execute" are not queued. Use "isExecuting" method to handle synchronization.
4
+ * The task can be also executed by calling the "execute" method. Multiple execute calls are chained to run secuentially and avoid race conditions.
5
+ * For example, submitters executed on SDK destroy or full queue, while periodic execution is pending.
6
6
  *
7
7
  * @param log Logger instance.
8
8
  * @param task Task to execute that returns a promise that NEVER REJECTS. Otherwise, periodic execution can result in Unhandled Promise Rejections.
@@ -12,8 +12,8 @@ import { SYNC_TASK_EXECUTE, SYNC_TASK_START, SYNC_TASK_STOP } from '../logger/co
12
12
  */
13
13
  export function syncTaskFactory(log, task, period, taskName) {
14
14
  if (taskName === void 0) { taskName = 'task'; }
15
- // Flag that indicates if the task is being executed
16
- var executing = false;
15
+ // Task promise while it is pending. Undefined once the promise is resolved
16
+ var pendingTask;
17
17
  // flag that indicates if the task periodic execution has been started/stopped.
18
18
  var running = false;
19
19
  // Auxiliar counter used to avoid race condition when calling `start` & `stop` intermittently
@@ -27,13 +27,19 @@ export function syncTaskFactory(log, task, period, taskName) {
27
27
  for (var _i = 0; _i < arguments.length; _i++) {
28
28
  args[_i] = arguments[_i];
29
29
  }
30
- executing = true;
30
+ // If task is executing, chain the new execution
31
+ if (pendingTask) {
32
+ return pendingTask.then(function () {
33
+ return execute.apply(void 0, args);
34
+ });
35
+ }
36
+ // Execute task
31
37
  log.debug(SYNC_TASK_EXECUTE, [taskName]);
32
- return task.apply(void 0, args).then(function (result) {
33
- executing = false;
38
+ pendingTask = task.apply(void 0, args).then(function (result) {
39
+ pendingTask = undefined;
34
40
  return result;
35
41
  });
36
- // No need to handle promise rejection because it is a pre-condition that provided task never rejects.
42
+ return pendingTask;
37
43
  }
38
44
  function periodicExecute(currentRunningId) {
39
45
  return execute.apply(void 0, runningArgs).then(function (result) {
@@ -45,10 +51,9 @@ export function syncTaskFactory(log, task, period, taskName) {
45
51
  });
46
52
  }
47
53
  return {
48
- // @TODO check if we need to queued `execute` calls, to avoid possible race conditions on submitters and updaters with streaming.
49
54
  execute: execute,
50
55
  isExecuting: function () {
51
- return executing;
56
+ return pendingTask !== undefined;
52
57
  },
53
58
  start: function () {
54
59
  var args = [];
@@ -70,7 +70,8 @@ export var base = {
70
70
  splitFilters: undefined,
71
71
  // impressions collection mode
72
72
  impressionsMode: OPTIMIZED,
73
- localhostMode: undefined
73
+ localhostMode: undefined,
74
+ enabled: true
74
75
  },
75
76
  // Logger
76
77
  log: undefined
@@ -164,6 +165,10 @@ export function settingsValidation(config, validationParams) {
164
165
  // We are not checking if bases are positive numbers. Thus, we might be reauthenticating immediately (`setTimeout` with NaN or negative number)
165
166
  scheduler.pushRetryBackoffBase = fromSecondsToMillis(scheduler.pushRetryBackoffBase);
166
167
  }
168
+ // validate sync enabled
169
+ if (withDefaults.sync.enabled !== false) { // @ts-ignore, modify readonly prop
170
+ withDefaults.sync.enabled = true;
171
+ }
167
172
  // validate the `splitFilters` settings and parse splits query
168
173
  var splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode);
169
174
  withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.4.2-rc.0",
3
+ "version": "1.4.2-rc.3",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -19,26 +19,20 @@ const logNameMapper = 'ga-to-split:mapper';
19
19
  /**
20
20
  * Provides a plugin to use with analytics.js, accounting for the possibility
21
21
  * that the global command queue has been renamed or not yet defined.
22
- * @param window Reference to global object.
23
- * @param pluginName The plugin name identifier.
24
- * @param pluginConstructor The plugin constructor function.
25
- * @param log Logger instance.
26
- * @param autoRequire If true, log error when auto-require script is not detected
22
+ * @param {string} pluginName The plugin name identifier.
23
+ * @param {Function} pluginConstructor The plugin constructor function.
27
24
  */
28
- function providePlugin(window: any, pluginName: string, pluginConstructor: Function, log: ILogger, autoRequire?: boolean) {
25
+ function providePlugin(pluginName: string, pluginConstructor: Function) {
29
26
  // get reference to global command queue. Init it if not defined yet.
27
+ // @ts-expect-error
30
28
  const gaAlias = window.GoogleAnalyticsObject || 'ga';
31
- window[gaAlias] = window[gaAlias] || function () {
32
- (window[gaAlias].q = window[gaAlias].q || []).push(arguments);
29
+ window[gaAlias] = window[gaAlias] || function (...args: any[]) { // @ts-expect-error
30
+ (window[gaAlias].q = window[gaAlias].q || []).push(args);
33
31
  };
34
32
 
35
33
  // provides the plugin for use with analytics.js.
34
+ // @ts-expect-error
36
35
  window[gaAlias]('provide', pluginName, pluginConstructor);
37
-
38
- if (autoRequire && (!window[gaAlias].q || window[gaAlias].q.push === [].push)) {
39
- // Expecting spy on ga.q push method but not found
40
- log.error('Auto-require script was expected but not provided.');
41
- }
42
36
  }
43
37
 
44
38
  // Default mapping: object used for building the default mapper from hits to Split events
@@ -290,5 +284,5 @@ export function GaToSplit(sdkOptions: GoogleAnalyticsToSplitOptions, params: IIn
290
284
  }
291
285
 
292
286
  // Register the plugin, even if config is invalid, since, if not provided, it will block `ga` command queue.
293
- providePlugin(window, 'splitTracker', SplitTracker, log, sdkOptions.autoRequire);
287
+ providePlugin('splitTracker', SplitTracker);
294
288
  }
@@ -53,24 +53,13 @@ export interface GoogleAnalyticsToSplitOptions {
53
53
  * If not provided, events are sent using the key and traffic type provided at SDK config
54
54
  */
55
55
  identities?: Identity[],
56
- /**
57
- * Optional flag to log an error if the `auto-require` script is not detected.
58
- * The auto-require script automatically requires the `splitTracker` plugin for created trackers,
59
- * and should be placed right after your Google Analytics, GTM or gtag.js script tag.
60
- *
61
- * @see {@link https://help.split.io/hc/en-us/articles/360040838752#google-tag-manager}
62
- *
63
- * @property {boolean} autoRequire
64
- * @default false
65
- */
66
- autoRequire?: boolean,
67
56
  }
68
57
 
69
58
  /**
70
59
  * Enable 'Google Analytics to Split' integration, to track Google Analytics hits as Split events.
71
60
  * Used by the browser variant of the isomorphic JS SDK.
72
61
  *
73
- * @see {@link https://help.split.io/hc/en-us/articles/360040838752#google-analytics-to-split}
62
+ * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#google-analytics-to-split}
74
63
  */
75
64
  export interface IGoogleAnalyticsToSplitConfig extends GoogleAnalyticsToSplitOptions {
76
65
  type: 'GOOGLE_ANALYTICS_TO_SPLIT'
@@ -140,7 +129,7 @@ export interface SplitToGoogleAnalyticsOptions {
140
129
  * Enable 'Split to Google Analytics' integration, to track Split impressions and events as Google Analytics hits.
141
130
  * Used by the browser variant of the isomorphic JS SDK.
142
131
  *
143
- * @see {@link https://help.split.io/hc/en-us/articles/360040838752#split-to-google-analytics}
132
+ * @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#split-to-google-analytics}
144
133
  */
145
134
  export interface ISplitToGoogleAnalyticsConfig extends SplitToGoogleAnalyticsOptions {
146
135
  type: 'SPLIT_TO_GOOGLE_ANALYTICS'
@@ -5,7 +5,7 @@ import { ILogger } from '../logger/types';
5
5
  import { objectAssign } from '../utils/lang/objectAssign';
6
6
 
7
7
  /**
8
- * Add in memory attributes storage methods and combine them with any attribute received from the getTreatment/s call
8
+ * Add in memory attributes storage methods and combine them with any attribute received from the getTreatment/s call
9
9
  */
10
10
  export function clientAttributesDecoration<TClient extends SplitIO.IClient | SplitIO.IAsyncClient>(log: ILogger, client: TClient) {
11
11
 
@@ -52,10 +52,10 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
52
52
  getTreatments: getTreatments,
53
53
  getTreatmentsWithConfig: getTreatmentsWithConfig,
54
54
  track: track,
55
-
55
+
56
56
  /**
57
57
  * Add an attribute to client's in memory attributes storage
58
- *
58
+ *
59
59
  * @param {string} attributeName Attrinute name
60
60
  * @param {string, number, boolean, list} attributeValue Attribute value
61
61
  * @returns {boolean} true if the attribute was stored and false otherways
@@ -70,7 +70,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
70
70
 
71
71
  /**
72
72
  * Returns the attribute with the given key
73
- *
73
+ *
74
74
  * @param {string} attributeName Attribute name
75
75
  * @returns {Object} Attribute with the given key
76
76
  */
@@ -81,7 +81,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
81
81
 
82
82
  /**
83
83
  * Add to client's in memory attributes storage the attributes in 'attributes'
84
- *
84
+ *
85
85
  * @param {Object} attributes Object with attributes to store
86
86
  * @returns true if attributes were stored an false otherways
87
87
  */
@@ -92,7 +92,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
92
92
 
93
93
  /**
94
94
  * Return all the attributes stored in client's in memory attributes storage
95
- *
95
+ *
96
96
  * @returns {Object} returns all the stored attributes
97
97
  */
98
98
  getAttributes(): Record<string, Object> {
@@ -101,8 +101,8 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
101
101
 
102
102
  /**
103
103
  * Removes from client's in memory attributes storage the attribute with the given key
104
- *
105
- * @param {string} attributeName
104
+ *
105
+ * @param {string} attributeName
106
106
  * @returns {boolean} true if attribute was removed and false otherways
107
107
  */
108
108
  removeAttribute(attributeName: string) {
@@ -116,7 +116,7 @@ export function clientAttributesDecoration<TClient extends SplitIO.IClient | Spl
116
116
  clearAttributes() {
117
117
  return attributeStorage.clear();
118
118
  }
119
-
119
+
120
120
  });
121
121
 
122
122
  }