@splitsoftware/splitio-commons 1.4.2-rc.0 → 1.4.2-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGES.txt +2 -1
- package/cjs/integrations/ga/GaToSplit.js +11 -12
- package/cjs/sync/syncManagerOnline.js +34 -19
- package/cjs/sync/syncTask.js +15 -10
- package/cjs/utils/settingsValidation/index.js +6 -1
- package/esm/integrations/ga/GaToSplit.js +11 -12
- package/esm/sync/syncManagerOnline.js +34 -19
- package/esm/sync/syncTask.js +15 -10
- package/esm/utils/settingsValidation/index.js +6 -1
- package/package.json +1 -1
- package/src/integrations/ga/GaToSplit.ts +8 -14
- package/src/integrations/ga/types.ts +2 -13
- package/src/sdkClient/clientAttributesDecoration.ts +9 -9
- package/src/sync/syncManagerOnline.ts +29 -16
- package/src/sync/syncTask.ts +17 -11
- package/src/types.ts +7 -1
- package/src/utils/settingsValidation/index.ts +7 -1
- package/types/integrations/ga/types.d.ts +2 -13
- package/types/sync/syncTask.d.ts +2 -2
- package/types/types.d.ts +6 -0
- package/types/utils/settingsValidation/index.d.ts +1 -0
- package/cjs/integrations/ga/autoRequire.js +0 -34
- package/esm/integrations/ga/autoRequire.js +0 -30
- package/src/integrations/ga/autoRequire.ts +0 -35
package/CHANGES.txt
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
1.4.2 (June XX, 2022)
|
|
2
|
-
- Added `
|
|
2
|
+
- Added `sync.enabled` property to SDK configuration to allow synchronize splits and segments only once.
|
|
3
3
|
- Updated telemetry to submit data even if user consent is not granted.
|
|
4
|
+
- Updated submitters logic, to avoid duplicating the post of impressions to Split cloud when the SDK is destroyed while performing its periodic post of impressions.
|
|
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
|
|
14
|
-
* @param
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
73
|
-
|
|
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 (
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
123
|
-
|
|
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 (
|
|
130
|
-
mySegmentsSyncTask.
|
|
144
|
+
if (!readinessManager.isReady())
|
|
145
|
+
mySegmentsSyncTask.execute();
|
|
131
146
|
}
|
|
132
147
|
},
|
|
133
148
|
stop: function () {
|
package/cjs/sync/syncTask.js
CHANGED
|
@@ -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
|
|
8
|
-
*
|
|
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
|
-
//
|
|
19
|
-
var
|
|
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
|
|
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
|
-
|
|
36
|
-
|
|
41
|
+
pendingTask = task.apply(void 0, args).then(function (result) {
|
|
42
|
+
pendingTask = undefined;
|
|
37
43
|
return result;
|
|
38
44
|
});
|
|
39
|
-
|
|
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
|
|
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
|
|
11
|
-
* @param
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
70
|
-
|
|
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 (
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
120
|
-
|
|
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 (
|
|
127
|
-
mySegmentsSyncTask.
|
|
141
|
+
if (!readinessManager.isReady())
|
|
142
|
+
mySegmentsSyncTask.execute();
|
|
128
143
|
}
|
|
129
144
|
},
|
|
130
145
|
stop: function () {
|
package/esm/sync/syncTask.js
CHANGED
|
@@ -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
|
|
5
|
-
*
|
|
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
|
-
//
|
|
16
|
-
var
|
|
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
|
|
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
|
-
|
|
33
|
-
|
|
38
|
+
pendingTask = task.apply(void 0, args).then(function (result) {
|
|
39
|
+
pendingTask = undefined;
|
|
34
40
|
return result;
|
|
35
41
|
});
|
|
36
|
-
|
|
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
|
|
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
|
@@ -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
|
|
23
|
-
* @param
|
|
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(
|
|
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(
|
|
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(
|
|
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/
|
|
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/
|
|
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
|
}
|
|
@@ -28,13 +28,13 @@ export function syncManagerOnlineFactory(
|
|
|
28
28
|
*/
|
|
29
29
|
return function (params: ISdkFactoryContextSync): ISyncManagerCS {
|
|
30
30
|
|
|
31
|
-
const { settings, settings: { log, streamingEnabled },
|
|
31
|
+
const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker } = params;
|
|
32
32
|
|
|
33
33
|
/** Polling Manager */
|
|
34
34
|
const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
35
35
|
|
|
36
36
|
/** Push Manager */
|
|
37
|
-
const pushManager = streamingEnabled && pollingManager && pushManagerFactory ?
|
|
37
|
+
const pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
|
|
38
38
|
pushManagerFactory(params, pollingManager) :
|
|
39
39
|
undefined;
|
|
40
40
|
|
|
@@ -89,15 +89,24 @@ export function syncManagerOnlineFactory(
|
|
|
89
89
|
|
|
90
90
|
// start syncing splits and segments
|
|
91
91
|
if (pollingManager) {
|
|
92
|
-
|
|
93
|
-
|
|
92
|
+
|
|
93
|
+
// If synchronization is disabled pushManager and pollingManager should not start
|
|
94
|
+
if (syncEnabled) {
|
|
95
|
+
if (pushManager) {
|
|
96
|
+
// Doesn't call `syncAll` when the syncManager is resuming
|
|
97
|
+
if (startFirstTime) {
|
|
98
|
+
pollingManager.syncAll();
|
|
99
|
+
startFirstTime = false;
|
|
100
|
+
}
|
|
101
|
+
pushManager.start();
|
|
102
|
+
} else {
|
|
103
|
+
pollingManager.start();
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
94
106
|
if (startFirstTime) {
|
|
95
107
|
pollingManager.syncAll();
|
|
96
108
|
startFirstTime = false;
|
|
97
109
|
}
|
|
98
|
-
pushManager.start();
|
|
99
|
-
} else {
|
|
100
|
-
pollingManager.start();
|
|
101
110
|
}
|
|
102
111
|
}
|
|
103
112
|
|
|
@@ -137,18 +146,22 @@ export function syncManagerOnlineFactory(
|
|
|
137
146
|
return {
|
|
138
147
|
isRunning: mySegmentsSyncTask.isRunning,
|
|
139
148
|
start() {
|
|
140
|
-
if (
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
149
|
+
if (syncEnabled) {
|
|
150
|
+
if (pushManager) {
|
|
151
|
+
if (pollingManager!.isRunning()) {
|
|
152
|
+
// if doing polling, we must start the periodic fetch of data
|
|
153
|
+
if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
|
|
154
|
+
} else {
|
|
155
|
+
// if not polling, we must execute the sync task for the initial fetch
|
|
156
|
+
// of segments since `syncAll` was already executed when starting the main client
|
|
157
|
+
mySegmentsSyncTask.execute();
|
|
158
|
+
}
|
|
159
|
+
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
144
160
|
} else {
|
|
145
|
-
|
|
146
|
-
// of segments since `syncAll` was already executed when starting the main client
|
|
147
|
-
mySegmentsSyncTask.execute();
|
|
161
|
+
if (storage.splits.usesSegments()) mySegmentsSyncTask.start();
|
|
148
162
|
}
|
|
149
|
-
pushManager.add(matchingKey, mySegmentsSyncTask);
|
|
150
163
|
} else {
|
|
151
|
-
if (
|
|
164
|
+
if (!readinessManager.isReady()) mySegmentsSyncTask.execute();
|
|
152
165
|
}
|
|
153
166
|
},
|
|
154
167
|
stop() {
|
package/src/sync/syncTask.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { ISyncTask } from './types';
|
|
|
4
4
|
|
|
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
|
|
8
|
-
*
|
|
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 @@ import { ISyncTask } from './types';
|
|
|
15
15
|
*/
|
|
16
16
|
export function syncTaskFactory<Input extends any[], Output = any>(log: ILogger, task: (...args: Input) => Promise<Output>, period: number, taskName = 'task'): ISyncTask<Input, Output> {
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
let
|
|
18
|
+
// Task promise while it is pending. Undefined once the promise is resolved
|
|
19
|
+
let pendingTask: Promise<Output> | undefined;
|
|
20
20
|
// flag that indicates if the task periodic execution has been started/stopped.
|
|
21
21
|
let running = false;
|
|
22
22
|
// Auxiliar counter used to avoid race condition when calling `start` & `stop` intermittently
|
|
@@ -26,14 +26,21 @@ export function syncTaskFactory<Input extends any[], Output = any>(log: ILogger,
|
|
|
26
26
|
// Id of the periodic call timeout
|
|
27
27
|
let timeoutID: any;
|
|
28
28
|
|
|
29
|
-
function execute(...args: Input) {
|
|
30
|
-
executing
|
|
29
|
+
function execute(...args: Input): Promise<Output> {
|
|
30
|
+
// If task is executing, chain the new execution
|
|
31
|
+
if (pendingTask) {
|
|
32
|
+
return pendingTask.then(() => {
|
|
33
|
+
return execute(...args);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Execute task
|
|
31
38
|
log.debug(SYNC_TASK_EXECUTE, [taskName]);
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
pendingTask = task(...args).then(result => {
|
|
40
|
+
pendingTask = undefined;
|
|
34
41
|
return result;
|
|
35
42
|
});
|
|
36
|
-
|
|
43
|
+
return pendingTask;
|
|
37
44
|
}
|
|
38
45
|
|
|
39
46
|
function periodicExecute(currentRunningId: number) {
|
|
@@ -46,11 +53,10 @@ export function syncTaskFactory<Input extends any[], Output = any>(log: ILogger,
|
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
return {
|
|
49
|
-
// @TODO check if we need to queued `execute` calls, to avoid possible race conditions on submitters and updaters with streaming.
|
|
50
56
|
execute,
|
|
51
57
|
|
|
52
58
|
isExecuting() {
|
|
53
|
-
return
|
|
59
|
+
return pendingTask !== undefined;
|
|
54
60
|
},
|
|
55
61
|
|
|
56
62
|
start(...args: Input) {
|
package/src/types.ts
CHANGED
|
@@ -117,7 +117,8 @@ export interface ISettings {
|
|
|
117
117
|
splitFilters: SplitIO.SplitFilter[],
|
|
118
118
|
impressionsMode: SplitIO.ImpressionsMode,
|
|
119
119
|
__splitFiltersValidation: ISplitFiltersValidation,
|
|
120
|
-
localhostMode?: SplitIO.LocalhostFactory
|
|
120
|
+
localhostMode?: SplitIO.LocalhostFactory,
|
|
121
|
+
enabled: boolean
|
|
121
122
|
},
|
|
122
123
|
readonly runtime: {
|
|
123
124
|
ip: string | false
|
|
@@ -214,6 +215,11 @@ interface ISharedSettings {
|
|
|
214
215
|
* @default 'OPTIMIZED'
|
|
215
216
|
*/
|
|
216
217
|
impressionsMode?: SplitIO.ImpressionsMode,
|
|
218
|
+
/**
|
|
219
|
+
* Enables synchronization.
|
|
220
|
+
* @property {boolean} enabled
|
|
221
|
+
*/
|
|
222
|
+
enabled: boolean
|
|
217
223
|
}
|
|
218
224
|
}
|
|
219
225
|
/**
|
|
@@ -83,7 +83,8 @@ export const base = {
|
|
|
83
83
|
splitFilters: undefined,
|
|
84
84
|
// impressions collection mode
|
|
85
85
|
impressionsMode: OPTIMIZED,
|
|
86
|
-
localhostMode: undefined
|
|
86
|
+
localhostMode: undefined,
|
|
87
|
+
enabled: true
|
|
87
88
|
},
|
|
88
89
|
|
|
89
90
|
// Logger
|
|
@@ -191,6 +192,11 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
|
|
|
191
192
|
scheduler.pushRetryBackoffBase = fromSecondsToMillis(scheduler.pushRetryBackoffBase);
|
|
192
193
|
}
|
|
193
194
|
|
|
195
|
+
// validate sync enabled
|
|
196
|
+
if (withDefaults.sync.enabled !== false) { // @ts-ignore, modify readonly prop
|
|
197
|
+
withDefaults.sync.enabled = true;
|
|
198
|
+
}
|
|
199
|
+
|
|
194
200
|
// validate the `splitFilters` settings and parse splits query
|
|
195
201
|
const splitFiltersValidation = validateSplitFilters(log, withDefaults.sync.splitFilters, withDefaults.mode);
|
|
196
202
|
withDefaults.sync.splitFilters = splitFiltersValidation.validFilters;
|
|
@@ -52,23 +52,12 @@ export interface GoogleAnalyticsToSplitOptions {
|
|
|
52
52
|
* If not provided, events are sent using the key and traffic type provided at SDK config
|
|
53
53
|
*/
|
|
54
54
|
identities?: Identity[];
|
|
55
|
-
/**
|
|
56
|
-
* Optional flag to log an error if the `auto-require` script is not detected.
|
|
57
|
-
* The auto-require script automatically requires the `splitTracker` plugin for created trackers,
|
|
58
|
-
* and should be placed right after your Google Analytics, GTM or gtag.js script tag.
|
|
59
|
-
*
|
|
60
|
-
* @see {@link https://help.split.io/hc/en-us/articles/360040838752#google-tag-manager}
|
|
61
|
-
*
|
|
62
|
-
* @property {boolean} autoRequire
|
|
63
|
-
* @default false
|
|
64
|
-
*/
|
|
65
|
-
autoRequire?: boolean;
|
|
66
55
|
}
|
|
67
56
|
/**
|
|
68
57
|
* Enable 'Google Analytics to Split' integration, to track Google Analytics hits as Split events.
|
|
69
58
|
* Used by the browser variant of the isomorphic JS SDK.
|
|
70
59
|
*
|
|
71
|
-
* @see {@link https://help.split.io/hc/en-us/articles/
|
|
60
|
+
* @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#google-analytics-to-split}
|
|
72
61
|
*/
|
|
73
62
|
export interface IGoogleAnalyticsToSplitConfig extends GoogleAnalyticsToSplitOptions {
|
|
74
63
|
type: 'GOOGLE_ANALYTICS_TO_SPLIT';
|
|
@@ -136,7 +125,7 @@ export interface SplitToGoogleAnalyticsOptions {
|
|
|
136
125
|
* Enable 'Split to Google Analytics' integration, to track Split impressions and events as Google Analytics hits.
|
|
137
126
|
* Used by the browser variant of the isomorphic JS SDK.
|
|
138
127
|
*
|
|
139
|
-
* @see {@link https://help.split.io/hc/en-us/articles/
|
|
128
|
+
* @see {@link https://help.split.io/hc/en-us/articles/360020448791-JavaScript-SDK#split-to-google-analytics}
|
|
140
129
|
*/
|
|
141
130
|
export interface ISplitToGoogleAnalyticsConfig extends SplitToGoogleAnalyticsOptions {
|
|
142
131
|
type: 'SPLIT_TO_GOOGLE_ANALYTICS';
|
package/types/sync/syncTask.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { ILogger } from '../logger/types';
|
|
|
2
2
|
import { ISyncTask } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Creates a syncTask that handles the periodic execution of a given task ("start" and "stop" methods).
|
|
5
|
-
* The task can be executed
|
|
6
|
-
*
|
|
5
|
+
* The task can be also executed by calling the "execute" method. Multiple execute calls are chained to run secuentially and avoid race conditions.
|
|
6
|
+
* For example, submitters executed on SDK destroy or full queue, while periodic execution is pending.
|
|
7
7
|
*
|
|
8
8
|
* @param log Logger instance.
|
|
9
9
|
* @param task Task to execute that returns a promise that NEVER REJECTS. Otherwise, periodic execution can result in Unhandled Promise Rejections.
|
package/types/types.d.ts
CHANGED
|
@@ -112,6 +112,7 @@ export interface ISettings {
|
|
|
112
112
|
impressionsMode: SplitIO.ImpressionsMode;
|
|
113
113
|
__splitFiltersValidation: ISplitFiltersValidation;
|
|
114
114
|
localhostMode?: SplitIO.LocalhostFactory;
|
|
115
|
+
enabled: boolean;
|
|
115
116
|
};
|
|
116
117
|
readonly runtime: {
|
|
117
118
|
ip: string | false;
|
|
@@ -208,6 +209,11 @@ interface ISharedSettings {
|
|
|
208
209
|
* @default 'OPTIMIZED'
|
|
209
210
|
*/
|
|
210
211
|
impressionsMode?: SplitIO.ImpressionsMode;
|
|
212
|
+
/**
|
|
213
|
+
* Enables synchronization.
|
|
214
|
+
* @property {boolean} enabled
|
|
215
|
+
*/
|
|
216
|
+
enabled: boolean;
|
|
211
217
|
};
|
|
212
218
|
}
|
|
213
219
|
/**
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.autoRequire = void 0;
|
|
4
|
-
/* eslint-disable no-undef */
|
|
5
|
-
/**
|
|
6
|
-
* Auto-require script to use with GaToSplit integration
|
|
7
|
-
*/
|
|
8
|
-
function autoRequire() {
|
|
9
|
-
(function (i, r, s) {
|
|
10
|
-
i[s] = i[s] || r;
|
|
11
|
-
i[r] = i[r] || function () { i[r].q.push(arguments); };
|
|
12
|
-
i[r].q = i[r].q || [];
|
|
13
|
-
var ts = {}; // Tracker names
|
|
14
|
-
var o = i[r].q.push;
|
|
15
|
-
i[r].q.push = function (v) {
|
|
16
|
-
var result = o.apply(this, arguments);
|
|
17
|
-
if (v && v[0] === 'create') {
|
|
18
|
-
var t = typeof v[2] === 'object' && typeof v[2].name === 'string' ?
|
|
19
|
-
v[2].name : // `ga('create', 'UA-ID', { name: 'trackerName', ... })`
|
|
20
|
-
typeof v[3] === 'object' && typeof v[3].name === 'string' ?
|
|
21
|
-
v[3].name : // `ga('create', 'UA-ID', 'auto', { name: 'trackerName', ... })`
|
|
22
|
-
typeof v[3] === 'string' ?
|
|
23
|
-
v[3] : // `ga('create', 'UA-ID', 'auto', 'trackerName')`
|
|
24
|
-
undefined; // No name tracker, e.g.: `ga('create', 'UA-ID', 'auto')`
|
|
25
|
-
if (!ts[t]) {
|
|
26
|
-
ts[t] = true;
|
|
27
|
-
i[r](t ? t + '.require' : 'require', 'splitTracker'); // Auto-require
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return result;
|
|
31
|
-
};
|
|
32
|
-
})(window, 'ga', 'GoogleAnalyticsObject');
|
|
33
|
-
}
|
|
34
|
-
exports.autoRequire = autoRequire;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-undef */
|
|
2
|
-
/**
|
|
3
|
-
* Auto-require script to use with GaToSplit integration
|
|
4
|
-
*/
|
|
5
|
-
export function autoRequire() {
|
|
6
|
-
(function (i, r, s) {
|
|
7
|
-
i[s] = i[s] || r;
|
|
8
|
-
i[r] = i[r] || function () { i[r].q.push(arguments); };
|
|
9
|
-
i[r].q = i[r].q || [];
|
|
10
|
-
var ts = {}; // Tracker names
|
|
11
|
-
var o = i[r].q.push;
|
|
12
|
-
i[r].q.push = function (v) {
|
|
13
|
-
var result = o.apply(this, arguments);
|
|
14
|
-
if (v && v[0] === 'create') {
|
|
15
|
-
var t = typeof v[2] === 'object' && typeof v[2].name === 'string' ?
|
|
16
|
-
v[2].name : // `ga('create', 'UA-ID', { name: 'trackerName', ... })`
|
|
17
|
-
typeof v[3] === 'object' && typeof v[3].name === 'string' ?
|
|
18
|
-
v[3].name : // `ga('create', 'UA-ID', 'auto', { name: 'trackerName', ... })`
|
|
19
|
-
typeof v[3] === 'string' ?
|
|
20
|
-
v[3] : // `ga('create', 'UA-ID', 'auto', 'trackerName')`
|
|
21
|
-
undefined; // No name tracker, e.g.: `ga('create', 'UA-ID', 'auto')`
|
|
22
|
-
if (!ts[t]) {
|
|
23
|
-
ts[t] = true;
|
|
24
|
-
i[r](t ? t + '.require' : 'require', 'splitTracker'); // Auto-require
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return result;
|
|
28
|
-
};
|
|
29
|
-
})(window, 'ga', 'GoogleAnalyticsObject');
|
|
30
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-undef */
|
|
2
|
-
/**
|
|
3
|
-
* Auto-require script to use with GaToSplit integration
|
|
4
|
-
*/
|
|
5
|
-
export function autoRequire() {
|
|
6
|
-
(function (i: any, r: string, s: string) {
|
|
7
|
-
i[s] = i[s] || r;
|
|
8
|
-
i[r] = i[r] || function () { i[r].q.push(arguments); };
|
|
9
|
-
i[r].q = i[r].q || [];
|
|
10
|
-
|
|
11
|
-
var ts: any = {}; // Tracker names
|
|
12
|
-
var o = i[r].q.push;
|
|
13
|
-
i[r].q.push = function (v: any) {
|
|
14
|
-
var result = o.apply(this, arguments);
|
|
15
|
-
|
|
16
|
-
if (v && v[0] === 'create') {
|
|
17
|
-
var t = typeof v[2] === 'object' && typeof v[2].name === 'string' ?
|
|
18
|
-
v[2].name : // `ga('create', 'UA-ID', { name: 'trackerName', ... })`
|
|
19
|
-
typeof v[3] === 'object' && typeof v[3].name === 'string' ?
|
|
20
|
-
v[3].name : // `ga('create', 'UA-ID', 'auto', { name: 'trackerName', ... })`
|
|
21
|
-
typeof v[3] === 'string' ?
|
|
22
|
-
v[3] : // `ga('create', 'UA-ID', 'auto', 'trackerName')`
|
|
23
|
-
undefined; // No name tracker, e.g.: `ga('create', 'UA-ID', 'auto')`
|
|
24
|
-
|
|
25
|
-
if (!ts[t]) {
|
|
26
|
-
ts[t] = true;
|
|
27
|
-
i[r](t ? t + '.require' : 'require', 'splitTracker'); // Auto-require
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return result;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
})(window, 'ga', 'GoogleAnalyticsObject');
|
|
35
|
-
}
|