@splitsoftware/splitio-commons 3.1.1-rc.6 → 3.1.1-rc.7
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 +0 -1
- package/cjs/sdkClient/sdkLifecycle.js +2 -1
- package/cjs/services/secureSplitHttpClient.js +7 -5
- package/cjs/services/serviceApi.js +6 -6
- package/cjs/sync/submitters/submitterManager.js +30 -53
- package/cjs/sync/syncManagerOnline.js +2 -4
- package/esm/sdkClient/sdkLifecycle.js +2 -1
- package/esm/services/secureSplitHttpClient.js +7 -5
- package/esm/services/serviceApi.js +6 -6
- package/esm/sync/submitters/submitterManager.js +30 -53
- package/esm/sync/syncManagerOnline.js +2 -4
- package/package.json +1 -1
- package/src/sdkClient/sdkLifecycle.ts +2 -1
- package/src/services/secureSplitHttpClient.ts +5 -5
- package/src/services/serviceApi.ts +6 -6
- package/src/services/types.ts +2 -2
- package/src/sync/submitters/submitterManager.ts +32 -58
- package/src/sync/syncManagerOnline.ts +1 -3
package/CHANGES.txt
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
3.2.0 (September 18, 2026)
|
|
2
2
|
- Added support for AI configs.
|
|
3
|
-
- Updated submitters to allow starting and executing them when the Configs SDK is ready.
|
|
4
3
|
- Removed Configs SDK-related types and modules and moved them to the Configs SDK repository.
|
|
5
4
|
|
|
6
5
|
3.1.0 (July 23, 2026)
|
|
@@ -61,8 +61,9 @@ function sdkLifecycleFactory(params, isSharedClient) {
|
|
|
61
61
|
}
|
|
62
62
|
// Stop background jobs
|
|
63
63
|
syncManager && syncManager.stop();
|
|
64
|
-
serviceApi && serviceApi.stop();
|
|
65
64
|
return __flush().then(function () {
|
|
65
|
+
// Stop the service API (the auth provider backoff retries specifically) after the final flush, so it can still authenticate using the still-valid cached credential
|
|
66
|
+
serviceApi && serviceApi.stop();
|
|
66
67
|
// Cleanup storage
|
|
67
68
|
return storage.destroy();
|
|
68
69
|
});
|
|
@@ -10,18 +10,20 @@ var tslib_1 = require("tslib");
|
|
|
10
10
|
* @param authProvider - `authProviderFactory` to use for authentication
|
|
11
11
|
*/
|
|
12
12
|
function secureSplitHttpClientFactory(splitHttpClient, authProvider) {
|
|
13
|
-
function makeRequest(url, options, latencyTracker, logErrorsAsInfo, token) {
|
|
14
|
-
return splitHttpClient(url, tslib_1.__assign(tslib_1.__assign({}, options), { headers: tslib_1.__assign(tslib_1.__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }), latencyTracker, logErrorsAsInfo,
|
|
13
|
+
function makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, token) {
|
|
14
|
+
return splitHttpClient(url, token ? tslib_1.__assign(tslib_1.__assign({}, options), { headers: tslib_1.__assign(tslib_1.__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }) : options, latencyTracker, logErrorsAsInfo, newVersionHeader);
|
|
15
15
|
}
|
|
16
|
-
var httpClient = function (url, options, latencyTracker, logErrorsAsInfo) {
|
|
16
|
+
var httpClient = function (url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt) {
|
|
17
|
+
if (newVersionHeader === void 0) { newVersionHeader = true; }
|
|
18
|
+
if (useJwt === void 0) { useJwt = true; }
|
|
17
19
|
return authProvider.credential().then(function (credential) {
|
|
18
|
-
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, credential.token)
|
|
20
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt ? credential.token : undefined)
|
|
19
21
|
.catch(function (error) {
|
|
20
22
|
if (error.statusCode === 401) {
|
|
21
23
|
// retry once for 401, in case the token has just expired
|
|
22
24
|
authProvider.invalidate();
|
|
23
25
|
return authProvider.credential().then(function (newCredential) {
|
|
24
|
-
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newCredential.token);
|
|
26
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt ? newCredential.token : undefined);
|
|
25
27
|
});
|
|
26
28
|
}
|
|
27
29
|
throw error;
|
|
@@ -84,7 +84,7 @@ function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
84
84
|
*/
|
|
85
85
|
postEventsBulk: function (body, headers) {
|
|
86
86
|
var url = "".concat(urls.events, "/api/events/bulk");
|
|
87
|
-
return
|
|
87
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(constants_1.EVENTS), false, false, false);
|
|
88
88
|
},
|
|
89
89
|
/**
|
|
90
90
|
* Post impressions.
|
|
@@ -94,12 +94,12 @@ function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
94
94
|
*/
|
|
95
95
|
postTestImpressionsBulk: function (body, headers) {
|
|
96
96
|
var url = "".concat(urls.events, "/api/testImpressions/bulk");
|
|
97
|
-
return
|
|
97
|
+
return secureSplitHttpClient(url, {
|
|
98
98
|
// Adding extra headers to send impressions in OPTIMIZED or DEBUG modes.
|
|
99
99
|
method: 'POST',
|
|
100
100
|
body: body,
|
|
101
101
|
headers: (0, objectAssign_1.objectAssign)({ SplitSDKImpressionsMode: SplitSDKImpressionsMode }, headers)
|
|
102
|
-
}, telemetryTracker.trackHttp(constants_1.IMPRESSIONS));
|
|
102
|
+
}, telemetryTracker.trackHttp(constants_1.IMPRESSIONS), false, false, false);
|
|
103
103
|
},
|
|
104
104
|
/**
|
|
105
105
|
* Post impressions counts.
|
|
@@ -109,7 +109,7 @@ function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
109
109
|
*/
|
|
110
110
|
postTestImpressionsCount: function (body, headers) {
|
|
111
111
|
var url = "".concat(urls.events, "/api/testImpressions/count");
|
|
112
|
-
return
|
|
112
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(constants_1.IMPRESSIONS_COUNT), false, false, false);
|
|
113
113
|
},
|
|
114
114
|
/**
|
|
115
115
|
* Post unique keys for client side.
|
|
@@ -119,7 +119,7 @@ function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
119
119
|
*/
|
|
120
120
|
postUniqueKeysBulkCs: function (body, headers) {
|
|
121
121
|
var url = "".concat(urls.telemetry, "/api/v1/keys/cs");
|
|
122
|
-
return
|
|
122
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(constants_1.TELEMETRY), false, false, false);
|
|
123
123
|
},
|
|
124
124
|
/**
|
|
125
125
|
* Post unique keys for server side.
|
|
@@ -129,7 +129,7 @@ function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
129
129
|
*/
|
|
130
130
|
postUniqueKeysBulkSs: function (body, headers) {
|
|
131
131
|
var url = "".concat(urls.telemetry, "/api/v1/keys/ss");
|
|
132
|
-
return
|
|
132
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(constants_1.TELEMETRY), false, false, false);
|
|
133
133
|
},
|
|
134
134
|
postMetricsConfig: function (body, headers) {
|
|
135
135
|
var url = "".concat(urls.telemetry, "/api/v1/metrics/config");
|
|
@@ -6,64 +6,41 @@ var impressionsSubmitter_1 = require("./impressionsSubmitter");
|
|
|
6
6
|
var impressionCountsSubmitter_1 = require("./impressionCountsSubmitter");
|
|
7
7
|
var telemetrySubmitter_1 = require("./telemetrySubmitter");
|
|
8
8
|
var uniqueKeysSubmitter_1 = require("./uniqueKeysSubmitter");
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
(0, impressionsSubmitter_1.impressionsSubmitterFactory)(params),
|
|
21
|
-
(0, eventsSubmitter_1.eventsSubmitterFactory)(params),
|
|
22
|
-
(0, impressionCountsSubmitter_1.impressionCountsSubmitterFactory)(params),
|
|
23
|
-
(0, uniqueKeysSubmitter_1.uniqueKeysSubmitterFactory)(params)
|
|
24
|
-
];
|
|
25
|
-
var telemetrySubmitter = (0, telemetrySubmitter_1.telemetrySubmitterFactory)(params);
|
|
26
|
-
var isRunning = false;
|
|
27
|
-
function startSubmitters(onlyTelemetry) {
|
|
28
|
-
if (!isRunning)
|
|
29
|
-
return;
|
|
9
|
+
function submitterManagerFactory(params) {
|
|
10
|
+
var submitters = [
|
|
11
|
+
(0, impressionsSubmitter_1.impressionsSubmitterFactory)(params),
|
|
12
|
+
(0, eventsSubmitter_1.eventsSubmitterFactory)(params),
|
|
13
|
+
(0, impressionCountsSubmitter_1.impressionCountsSubmitterFactory)(params),
|
|
14
|
+
(0, uniqueKeysSubmitter_1.uniqueKeysSubmitterFactory)(params)
|
|
15
|
+
];
|
|
16
|
+
var telemetrySubmitter = (0, telemetrySubmitter_1.telemetrySubmitterFactory)(params);
|
|
17
|
+
return {
|
|
18
|
+
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
19
|
+
start: function (onlyTelemetry) {
|
|
30
20
|
if (!onlyTelemetry)
|
|
31
21
|
submitters.forEach(function (submitter) { return submitter.start(); });
|
|
32
22
|
if (telemetrySubmitter)
|
|
33
23
|
telemetrySubmitter.start();
|
|
24
|
+
},
|
|
25
|
+
// `allExceptTelemetry` true if userConsent is changed to DECLINED
|
|
26
|
+
stop: function (allExceptTelemetry) {
|
|
27
|
+
submitters.forEach(function (submitter) { return submitter.stop(); });
|
|
28
|
+
if (!allExceptTelemetry && telemetrySubmitter)
|
|
29
|
+
telemetrySubmitter.stop();
|
|
30
|
+
},
|
|
31
|
+
isRunning: function () {
|
|
32
|
+
return submitters.some(function (submitter) { return submitter.isRunning(); });
|
|
33
|
+
},
|
|
34
|
+
// Flush data. Called with `onlyTelemetry` true if SDK is destroyed with userConsent not GRANTED
|
|
35
|
+
execute: function (onlyTelemetry) {
|
|
36
|
+
var promises = onlyTelemetry ? [] : submitters.map(function (submitter) { return submitter.execute(); });
|
|
37
|
+
if (telemetrySubmitter)
|
|
38
|
+
promises.push(telemetrySubmitter.execute());
|
|
39
|
+
return Promise.all(promises).then(function () { });
|
|
40
|
+
},
|
|
41
|
+
isExecuting: function () {
|
|
42
|
+
return submitters.some(function (submitter) { return submitter.isExecuting(); });
|
|
34
43
|
}
|
|
35
|
-
return {
|
|
36
|
-
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
37
|
-
start: function (onlyTelemetry) {
|
|
38
|
-
isRunning = true;
|
|
39
|
-
if (!startWhenReady || readiness.isReady())
|
|
40
|
-
startSubmitters(onlyTelemetry);
|
|
41
|
-
else
|
|
42
|
-
readiness.gate.once(constants_1.SDK_READY, function () { return startSubmitters(onlyTelemetry); });
|
|
43
|
-
},
|
|
44
|
-
// `allExceptTelemetry` true if userConsent is changed to DECLINED
|
|
45
|
-
stop: function (allExceptTelemetry) {
|
|
46
|
-
isRunning = false;
|
|
47
|
-
submitters.forEach(function (submitter) { return submitter.stop(); });
|
|
48
|
-
if (!allExceptTelemetry && telemetrySubmitter)
|
|
49
|
-
telemetrySubmitter.stop();
|
|
50
|
-
},
|
|
51
|
-
isRunning: function () {
|
|
52
|
-
return isRunning;
|
|
53
|
-
},
|
|
54
|
-
// Flush data. Called with `onlyTelemetry` true if SDK is destroyed with userConsent not GRANTED
|
|
55
|
-
execute: function (onlyTelemetry) {
|
|
56
|
-
if (startWhenReady && !readiness.isReady())
|
|
57
|
-
return Promise.resolve();
|
|
58
|
-
var promises = onlyTelemetry ? [] : submitters.map(function (submitter) { return submitter.execute(); });
|
|
59
|
-
if (telemetrySubmitter)
|
|
60
|
-
promises.push(telemetrySubmitter.execute());
|
|
61
|
-
return Promise.all(promises).then(function () { });
|
|
62
|
-
},
|
|
63
|
-
isExecuting: function () {
|
|
64
|
-
return submitters.some(function (submitter) { return submitter.isExecuting(); });
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
44
|
};
|
|
68
45
|
}
|
|
69
46
|
exports.submitterManagerFactory = submitterManagerFactory;
|
|
@@ -15,10 +15,8 @@ var AbstractDefinitionsCacheSync_1 = require("../storages/AbstractDefinitionsCac
|
|
|
15
15
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
16
16
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
17
17
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
18
|
-
* @param submitterManagerFactory - specify the submitter manager factory to use
|
|
19
18
|
*/
|
|
20
|
-
function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory
|
|
21
|
-
if (_submitterManagerFactory === void 0) { _submitterManagerFactory = (0, submitterManager_1.submitterManagerFactory)(); }
|
|
19
|
+
function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
22
20
|
/**
|
|
23
21
|
* SyncManager factory for modular SDK
|
|
24
22
|
*/
|
|
@@ -32,7 +30,7 @@ function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory, _su
|
|
|
32
30
|
undefined;
|
|
33
31
|
/** Submitter Manager */
|
|
34
32
|
// It is not injected as push and polling managers, because at the moment it is required
|
|
35
|
-
var submitterManager =
|
|
33
|
+
var submitterManager = (0, submitterManager_1.submitterManagerFactory)(params);
|
|
36
34
|
/** Sync Manager logic */
|
|
37
35
|
function startPolling() {
|
|
38
36
|
if (pollingManager.isRunning()) {
|
|
@@ -58,8 +58,9 @@ export function sdkLifecycleFactory(params, isSharedClient) {
|
|
|
58
58
|
}
|
|
59
59
|
// Stop background jobs
|
|
60
60
|
syncManager && syncManager.stop();
|
|
61
|
-
serviceApi && serviceApi.stop();
|
|
62
61
|
return __flush().then(function () {
|
|
62
|
+
// Stop the service API (the auth provider backoff retries specifically) after the final flush, so it can still authenticate using the still-valid cached credential
|
|
63
|
+
serviceApi && serviceApi.stop();
|
|
63
64
|
// Cleanup storage
|
|
64
65
|
return storage.destroy();
|
|
65
66
|
});
|
|
@@ -7,18 +7,20 @@ import { __assign } from "tslib";
|
|
|
7
7
|
* @param authProvider - `authProviderFactory` to use for authentication
|
|
8
8
|
*/
|
|
9
9
|
export function secureSplitHttpClientFactory(splitHttpClient, authProvider) {
|
|
10
|
-
function makeRequest(url, options, latencyTracker, logErrorsAsInfo, token) {
|
|
11
|
-
return splitHttpClient(url, __assign(__assign({}, options), { headers: __assign(__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }), latencyTracker, logErrorsAsInfo,
|
|
10
|
+
function makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, token) {
|
|
11
|
+
return splitHttpClient(url, token ? __assign(__assign({}, options), { headers: __assign(__assign({}, options === null || options === void 0 ? void 0 : options.headers), { Authorization: "Bearer ".concat(token) }) }) : options, latencyTracker, logErrorsAsInfo, newVersionHeader);
|
|
12
12
|
}
|
|
13
|
-
var httpClient = function (url, options, latencyTracker, logErrorsAsInfo) {
|
|
13
|
+
var httpClient = function (url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt) {
|
|
14
|
+
if (newVersionHeader === void 0) { newVersionHeader = true; }
|
|
15
|
+
if (useJwt === void 0) { useJwt = true; }
|
|
14
16
|
return authProvider.credential().then(function (credential) {
|
|
15
|
-
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, credential.token)
|
|
17
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt ? credential.token : undefined)
|
|
16
18
|
.catch(function (error) {
|
|
17
19
|
if (error.statusCode === 401) {
|
|
18
20
|
// retry once for 401, in case the token has just expired
|
|
19
21
|
authProvider.invalidate();
|
|
20
22
|
return authProvider.credential().then(function (newCredential) {
|
|
21
|
-
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newCredential.token);
|
|
23
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt ? newCredential.token : undefined);
|
|
22
24
|
});
|
|
23
25
|
}
|
|
24
26
|
throw error;
|
|
@@ -81,7 +81,7 @@ export function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
81
81
|
*/
|
|
82
82
|
postEventsBulk: function (body, headers) {
|
|
83
83
|
var url = "".concat(urls.events, "/api/events/bulk");
|
|
84
|
-
return
|
|
84
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(EVENTS), false, false, false);
|
|
85
85
|
},
|
|
86
86
|
/**
|
|
87
87
|
* Post impressions.
|
|
@@ -91,12 +91,12 @@ export function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
91
91
|
*/
|
|
92
92
|
postTestImpressionsBulk: function (body, headers) {
|
|
93
93
|
var url = "".concat(urls.events, "/api/testImpressions/bulk");
|
|
94
|
-
return
|
|
94
|
+
return secureSplitHttpClient(url, {
|
|
95
95
|
// Adding extra headers to send impressions in OPTIMIZED or DEBUG modes.
|
|
96
96
|
method: 'POST',
|
|
97
97
|
body: body,
|
|
98
98
|
headers: objectAssign({ SplitSDKImpressionsMode: SplitSDKImpressionsMode }, headers)
|
|
99
|
-
}, telemetryTracker.trackHttp(IMPRESSIONS));
|
|
99
|
+
}, telemetryTracker.trackHttp(IMPRESSIONS), false, false, false);
|
|
100
100
|
},
|
|
101
101
|
/**
|
|
102
102
|
* Post impressions counts.
|
|
@@ -106,7 +106,7 @@ export function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
106
106
|
*/
|
|
107
107
|
postTestImpressionsCount: function (body, headers) {
|
|
108
108
|
var url = "".concat(urls.events, "/api/testImpressions/count");
|
|
109
|
-
return
|
|
109
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(IMPRESSIONS_COUNT), false, false, false);
|
|
110
110
|
},
|
|
111
111
|
/**
|
|
112
112
|
* Post unique keys for client side.
|
|
@@ -116,7 +116,7 @@ export function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
116
116
|
*/
|
|
117
117
|
postUniqueKeysBulkCs: function (body, headers) {
|
|
118
118
|
var url = "".concat(urls.telemetry, "/api/v1/keys/cs");
|
|
119
|
-
return
|
|
119
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(TELEMETRY), false, false, false);
|
|
120
120
|
},
|
|
121
121
|
/**
|
|
122
122
|
* Post unique keys for server side.
|
|
@@ -126,7 +126,7 @@ export function serviceApiFactory(settings, platform, telemetryTracker) {
|
|
|
126
126
|
*/
|
|
127
127
|
postUniqueKeysBulkSs: function (body, headers) {
|
|
128
128
|
var url = "".concat(urls.telemetry, "/api/v1/keys/ss");
|
|
129
|
-
return
|
|
129
|
+
return secureSplitHttpClient(url, { method: 'POST', body: body, headers: headers }, telemetryTracker.trackHttp(TELEMETRY), false, false, false);
|
|
130
130
|
},
|
|
131
131
|
postMetricsConfig: function (body, headers) {
|
|
132
132
|
var url = "".concat(urls.telemetry, "/api/v1/metrics/config");
|
|
@@ -3,63 +3,40 @@ import { impressionsSubmitterFactory } from './impressionsSubmitter';
|
|
|
3
3
|
import { impressionCountsSubmitterFactory } from './impressionCountsSubmitter';
|
|
4
4
|
import { telemetrySubmitterFactory } from './telemetrySubmitter';
|
|
5
5
|
import { uniqueKeysSubmitterFactory } from './uniqueKeysSubmitter';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
impressionsSubmitterFactory(params),
|
|
18
|
-
eventsSubmitterFactory(params),
|
|
19
|
-
impressionCountsSubmitterFactory(params),
|
|
20
|
-
uniqueKeysSubmitterFactory(params)
|
|
21
|
-
];
|
|
22
|
-
var telemetrySubmitter = telemetrySubmitterFactory(params);
|
|
23
|
-
var isRunning = false;
|
|
24
|
-
function startSubmitters(onlyTelemetry) {
|
|
25
|
-
if (!isRunning)
|
|
26
|
-
return;
|
|
6
|
+
export function submitterManagerFactory(params) {
|
|
7
|
+
var submitters = [
|
|
8
|
+
impressionsSubmitterFactory(params),
|
|
9
|
+
eventsSubmitterFactory(params),
|
|
10
|
+
impressionCountsSubmitterFactory(params),
|
|
11
|
+
uniqueKeysSubmitterFactory(params)
|
|
12
|
+
];
|
|
13
|
+
var telemetrySubmitter = telemetrySubmitterFactory(params);
|
|
14
|
+
return {
|
|
15
|
+
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
16
|
+
start: function (onlyTelemetry) {
|
|
27
17
|
if (!onlyTelemetry)
|
|
28
18
|
submitters.forEach(function (submitter) { return submitter.start(); });
|
|
29
19
|
if (telemetrySubmitter)
|
|
30
20
|
telemetrySubmitter.start();
|
|
21
|
+
},
|
|
22
|
+
// `allExceptTelemetry` true if userConsent is changed to DECLINED
|
|
23
|
+
stop: function (allExceptTelemetry) {
|
|
24
|
+
submitters.forEach(function (submitter) { return submitter.stop(); });
|
|
25
|
+
if (!allExceptTelemetry && telemetrySubmitter)
|
|
26
|
+
telemetrySubmitter.stop();
|
|
27
|
+
},
|
|
28
|
+
isRunning: function () {
|
|
29
|
+
return submitters.some(function (submitter) { return submitter.isRunning(); });
|
|
30
|
+
},
|
|
31
|
+
// Flush data. Called with `onlyTelemetry` true if SDK is destroyed with userConsent not GRANTED
|
|
32
|
+
execute: function (onlyTelemetry) {
|
|
33
|
+
var promises = onlyTelemetry ? [] : submitters.map(function (submitter) { return submitter.execute(); });
|
|
34
|
+
if (telemetrySubmitter)
|
|
35
|
+
promises.push(telemetrySubmitter.execute());
|
|
36
|
+
return Promise.all(promises).then(function () { });
|
|
37
|
+
},
|
|
38
|
+
isExecuting: function () {
|
|
39
|
+
return submitters.some(function (submitter) { return submitter.isExecuting(); });
|
|
31
40
|
}
|
|
32
|
-
return {
|
|
33
|
-
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
34
|
-
start: function (onlyTelemetry) {
|
|
35
|
-
isRunning = true;
|
|
36
|
-
if (!startWhenReady || readiness.isReady())
|
|
37
|
-
startSubmitters(onlyTelemetry);
|
|
38
|
-
else
|
|
39
|
-
readiness.gate.once(SDK_READY, function () { return startSubmitters(onlyTelemetry); });
|
|
40
|
-
},
|
|
41
|
-
// `allExceptTelemetry` true if userConsent is changed to DECLINED
|
|
42
|
-
stop: function (allExceptTelemetry) {
|
|
43
|
-
isRunning = false;
|
|
44
|
-
submitters.forEach(function (submitter) { return submitter.stop(); });
|
|
45
|
-
if (!allExceptTelemetry && telemetrySubmitter)
|
|
46
|
-
telemetrySubmitter.stop();
|
|
47
|
-
},
|
|
48
|
-
isRunning: function () {
|
|
49
|
-
return isRunning;
|
|
50
|
-
},
|
|
51
|
-
// Flush data. Called with `onlyTelemetry` true if SDK is destroyed with userConsent not GRANTED
|
|
52
|
-
execute: function (onlyTelemetry) {
|
|
53
|
-
if (startWhenReady && !readiness.isReady())
|
|
54
|
-
return Promise.resolve();
|
|
55
|
-
var promises = onlyTelemetry ? [] : submitters.map(function (submitter) { return submitter.execute(); });
|
|
56
|
-
if (telemetrySubmitter)
|
|
57
|
-
promises.push(telemetrySubmitter.execute());
|
|
58
|
-
return Promise.all(promises).then(function () { });
|
|
59
|
-
},
|
|
60
|
-
isExecuting: function () {
|
|
61
|
-
return submitters.some(function (submitter) { return submitter.isExecuting(); });
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
41
|
};
|
|
65
42
|
}
|
|
@@ -12,10 +12,8 @@ import { usesSegmentsSync } from '../storages/AbstractDefinitionsCacheSync';
|
|
|
12
12
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
13
13
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
14
14
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
15
|
-
* @param submitterManagerFactory - specify the submitter manager factory to use
|
|
16
15
|
*/
|
|
17
|
-
export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory
|
|
18
|
-
if (_submitterManagerFactory === void 0) { _submitterManagerFactory = submitterManagerFactory(); }
|
|
16
|
+
export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFactory) {
|
|
19
17
|
/**
|
|
20
18
|
* SyncManager factory for modular SDK
|
|
21
19
|
*/
|
|
@@ -29,7 +27,7 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
|
|
|
29
27
|
undefined;
|
|
30
28
|
/** Submitter Manager */
|
|
31
29
|
// It is not injected as push and polling managers, because at the moment it is required
|
|
32
|
-
var submitterManager =
|
|
30
|
+
var submitterManager = submitterManagerFactory(params);
|
|
33
31
|
/** Sync Manager logic */
|
|
34
32
|
function startPolling() {
|
|
35
33
|
if (pollingManager.isRunning()) {
|
package/package.json
CHANGED
|
@@ -69,9 +69,10 @@ export function sdkLifecycleFactory(params: ISdkFactoryContext, isSharedClient?:
|
|
|
69
69
|
|
|
70
70
|
// Stop background jobs
|
|
71
71
|
syncManager && syncManager.stop();
|
|
72
|
-
serviceApi && serviceApi.stop();
|
|
73
72
|
|
|
74
73
|
return __flush().then(() => {
|
|
74
|
+
// Stop the service API (the auth provider backoff retries specifically) after the final flush, so it can still authenticate using the still-valid cached credential
|
|
75
|
+
serviceApi && serviceApi.stop();
|
|
75
76
|
// Cleanup storage
|
|
76
77
|
return storage.destroy();
|
|
77
78
|
});
|
|
@@ -10,19 +10,19 @@ import { IAuthProvider } from './authProvider';
|
|
|
10
10
|
*/
|
|
11
11
|
export function secureSplitHttpClientFactory(splitHttpClient: ISplitHttpClient, authProvider: IAuthProvider): ISecureSplitHttpClient {
|
|
12
12
|
|
|
13
|
-
function makeRequest(url: string, options: IRequestOptions | undefined, latencyTracker
|
|
14
|
-
return splitHttpClient(url, { ...options, headers: { ...options?.headers, Authorization: `Bearer ${token}` } }, latencyTracker, logErrorsAsInfo,
|
|
13
|
+
function makeRequest(url: string, options: IRequestOptions | undefined, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean, newVersionHeader?: boolean, token?: string): Promise<IResponse> {
|
|
14
|
+
return splitHttpClient(url, token ? { ...options, headers: { ...options?.headers, Authorization: `Bearer ${token}` } } : options, latencyTracker, logErrorsAsInfo, newVersionHeader);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
const httpClient = function (url: string, options?: IRequestOptions, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean): Promise<IResponse> {
|
|
17
|
+
const httpClient = function (url: string, options?: IRequestOptions, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean, newVersionHeader = true, useJwt = true): Promise<IResponse> {
|
|
18
18
|
return authProvider.credential().then(credential => {
|
|
19
|
-
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, credential.token)
|
|
19
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt ? credential.token : undefined)
|
|
20
20
|
.catch((error: NetworkError) => {
|
|
21
21
|
if (error.statusCode === 401) {
|
|
22
22
|
// retry once for 401, in case the token has just expired
|
|
23
23
|
authProvider.invalidate();
|
|
24
24
|
return authProvider.credential().then(newCredential => {
|
|
25
|
-
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newCredential.token);
|
|
25
|
+
return makeRequest(url, options, latencyTracker, logErrorsAsInfo, newVersionHeader, useJwt ? newCredential.token : undefined);
|
|
26
26
|
});
|
|
27
27
|
}
|
|
28
28
|
throw error;
|
|
@@ -102,7 +102,7 @@ export function serviceApiFactory(
|
|
|
102
102
|
*/
|
|
103
103
|
postEventsBulk(body: string, headers?: Record<string, string>) {
|
|
104
104
|
const url = `${urls.events}/api/events/bulk`;
|
|
105
|
-
return
|
|
105
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(EVENTS), false, false, false);
|
|
106
106
|
},
|
|
107
107
|
|
|
108
108
|
/**
|
|
@@ -113,10 +113,10 @@ export function serviceApiFactory(
|
|
|
113
113
|
*/
|
|
114
114
|
postTestImpressionsBulk(body: string, headers?: Record<string, string>) {
|
|
115
115
|
const url = `${urls.events}/api/testImpressions/bulk`;
|
|
116
|
-
return
|
|
116
|
+
return secureSplitHttpClient(url, {
|
|
117
117
|
// Adding extra headers to send impressions in OPTIMIZED or DEBUG modes.
|
|
118
118
|
method: 'POST', body, headers: objectAssign({ SplitSDKImpressionsMode }, headers)
|
|
119
|
-
}, telemetryTracker.trackHttp(IMPRESSIONS));
|
|
119
|
+
}, telemetryTracker.trackHttp(IMPRESSIONS), false, false, false);
|
|
120
120
|
},
|
|
121
121
|
|
|
122
122
|
/**
|
|
@@ -127,7 +127,7 @@ export function serviceApiFactory(
|
|
|
127
127
|
*/
|
|
128
128
|
postTestImpressionsCount(body: string, headers?: Record<string, string>) {
|
|
129
129
|
const url = `${urls.events}/api/testImpressions/count`;
|
|
130
|
-
return
|
|
130
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(IMPRESSIONS_COUNT), false, false, false);
|
|
131
131
|
},
|
|
132
132
|
|
|
133
133
|
/**
|
|
@@ -138,7 +138,7 @@ export function serviceApiFactory(
|
|
|
138
138
|
*/
|
|
139
139
|
postUniqueKeysBulkCs(body: string, headers?: Record<string, string>) {
|
|
140
140
|
const url = `${urls.telemetry}/api/v1/keys/cs`;
|
|
141
|
-
return
|
|
141
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), false, false, false);
|
|
142
142
|
},
|
|
143
143
|
|
|
144
144
|
/**
|
|
@@ -149,7 +149,7 @@ export function serviceApiFactory(
|
|
|
149
149
|
*/
|
|
150
150
|
postUniqueKeysBulkSs(body: string, headers?: Record<string, string>) {
|
|
151
151
|
const url = `${urls.telemetry}/api/v1/keys/ss`;
|
|
152
|
-
return
|
|
152
|
+
return secureSplitHttpClient(url, { method: 'POST', body, headers }, telemetryTracker.trackHttp(TELEMETRY), false, false, false);
|
|
153
153
|
},
|
|
154
154
|
|
|
155
155
|
postMetricsConfig(body: string, headers?: Record<string, string>) {
|
package/src/services/types.ts
CHANGED
|
@@ -35,7 +35,7 @@ export type IHealthCheckAPI = () => Promise<boolean>
|
|
|
35
35
|
|
|
36
36
|
export type ISplitHttpClient = (url: string, options?: IRequestOptions, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean, newVersionHeader?: boolean) => Promise<IResponse>
|
|
37
37
|
|
|
38
|
-
export type ISecureSplitHttpClient =
|
|
38
|
+
export type ISecureSplitHttpClient = ((url: string, options?: IRequestOptions, latencyTracker?: (error?: NetworkError) => void, logErrorsAsInfo?: boolean, newVersionHeader?: boolean, useJwt?: boolean) => Promise<IResponse>) & { stop(): void }
|
|
39
39
|
|
|
40
40
|
export type IFetchDefinitionChanges = (since: number, noCache?: boolean, till?: number, rbSince?: number) => Promise<IResponse>
|
|
41
41
|
|
|
@@ -73,7 +73,7 @@ export interface IServiceApi {
|
|
|
73
73
|
postTestImpressionsCount: IPostTestImpressionsCount
|
|
74
74
|
postMetricsConfig: IPostMetricsConfig
|
|
75
75
|
postMetricsUsage: IPostMetricsUsage
|
|
76
|
-
// lifecycle
|
|
76
|
+
// lifecycle: stops authProvider backoff retries
|
|
77
77
|
stop(): void
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -5,70 +5,44 @@ import { telemetrySubmitterFactory } from './telemetrySubmitter';
|
|
|
5
5
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
6
6
|
import { ISubmitterManager } from './types';
|
|
7
7
|
import { uniqueKeysSubmitterFactory } from './uniqueKeysSubmitter';
|
|
8
|
-
import { SDK_READY } from '../../readiness/constants';
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
* Creates a submitter manager.
|
|
12
|
-
*
|
|
13
|
-
* @param startWhenReady - If true, the submitters will only start and execute the underlying submitters when the SDK is ready.
|
|
14
|
-
* `true` for Configs SDK, `false` for Flags SDKs.
|
|
15
|
-
*/
|
|
16
|
-
export function submitterManagerFactory(startWhenReady?: boolean) {
|
|
9
|
+
export function submitterManagerFactory(params: ISdkFactoryContextSync): ISubmitterManager {
|
|
17
10
|
|
|
18
|
-
|
|
11
|
+
const submitters = [
|
|
12
|
+
impressionsSubmitterFactory(params),
|
|
13
|
+
eventsSubmitterFactory(params),
|
|
14
|
+
impressionCountsSubmitterFactory(params),
|
|
15
|
+
uniqueKeysSubmitterFactory(params)
|
|
16
|
+
];
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const submitters = [
|
|
23
|
-
impressionsSubmitterFactory(params),
|
|
24
|
-
eventsSubmitterFactory(params),
|
|
25
|
-
impressionCountsSubmitterFactory(params),
|
|
26
|
-
uniqueKeysSubmitterFactory(params)
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
const telemetrySubmitter = telemetrySubmitterFactory(params);
|
|
30
|
-
let isRunning = false;
|
|
31
|
-
|
|
32
|
-
function startSubmitters(onlyTelemetry?: boolean) {
|
|
33
|
-
if (!isRunning) return;
|
|
18
|
+
const telemetrySubmitter = telemetrySubmitterFactory(params);
|
|
34
19
|
|
|
20
|
+
return {
|
|
21
|
+
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
22
|
+
start(onlyTelemetry?: boolean) {
|
|
35
23
|
if (!onlyTelemetry) submitters.forEach(submitter => submitter.start());
|
|
36
24
|
if (telemetrySubmitter) telemetrySubmitter.start();
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
// `allExceptTelemetry` true if userConsent is changed to DECLINED
|
|
28
|
+
stop(allExceptTelemetry?: boolean) {
|
|
29
|
+
submitters.forEach(submitter => submitter.stop());
|
|
30
|
+
if (!allExceptTelemetry && telemetrySubmitter) telemetrySubmitter.stop();
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
isRunning() {
|
|
34
|
+
return submitters.some(submitter => submitter.isRunning());
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
// Flush data. Called with `onlyTelemetry` true if SDK is destroyed with userConsent not GRANTED
|
|
38
|
+
execute(onlyTelemetry?: boolean) {
|
|
39
|
+
const promises = onlyTelemetry ? [] : submitters.map(submitter => submitter.execute());
|
|
40
|
+
if (telemetrySubmitter) promises.push(telemetrySubmitter.execute());
|
|
41
|
+
return Promise.all(promises).then(() => { });
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
isExecuting() {
|
|
45
|
+
return submitters.some(submitter => submitter.isExecuting());
|
|
37
46
|
}
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
// `onlyTelemetry` true if SDK is created with userConsent not GRANTED
|
|
41
|
-
start(onlyTelemetry?: boolean) {
|
|
42
|
-
isRunning = true;
|
|
43
|
-
|
|
44
|
-
if (!startWhenReady || readiness.isReady()) startSubmitters(onlyTelemetry);
|
|
45
|
-
else readiness.gate.once(SDK_READY, () => startSubmitters(onlyTelemetry));
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
// `allExceptTelemetry` true if userConsent is changed to DECLINED
|
|
49
|
-
stop(allExceptTelemetry?: boolean) {
|
|
50
|
-
isRunning = false;
|
|
51
|
-
|
|
52
|
-
submitters.forEach(submitter => submitter.stop());
|
|
53
|
-
if (!allExceptTelemetry && telemetrySubmitter) telemetrySubmitter.stop();
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
isRunning() {
|
|
57
|
-
return isRunning;
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
// Flush data. Called with `onlyTelemetry` true if SDK is destroyed with userConsent not GRANTED
|
|
61
|
-
execute(onlyTelemetry?: boolean) {
|
|
62
|
-
if (startWhenReady && !readiness.isReady()) return Promise.resolve();
|
|
63
|
-
|
|
64
|
-
const promises = onlyTelemetry ? [] : submitters.map(submitter => submitter.execute());
|
|
65
|
-
if (telemetrySubmitter) promises.push(telemetrySubmitter.execute());
|
|
66
|
-
return Promise.all(promises).then(() => { });
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
isExecuting() {
|
|
70
|
-
return submitters.some(submitter => submitter.isExecuting());
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
47
|
};
|
|
74
48
|
}
|
|
@@ -19,12 +19,10 @@ import { usesSegmentsSync } from '../storages/AbstractDefinitionsCacheSync';
|
|
|
19
19
|
* @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
|
|
20
20
|
* `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
|
|
21
21
|
* @param pushManagerFactory - optional to build a SyncManager with or without streaming support
|
|
22
|
-
* @param submitterManagerFactory - specify the submitter manager factory to use
|
|
23
22
|
*/
|
|
24
23
|
export function syncManagerOnlineFactory(
|
|
25
24
|
pollingManagerFactory?: (params: ISdkFactoryContextSync) => IPollingManager,
|
|
26
25
|
pushManagerFactory?: (params: ISdkFactoryContextSync, pollingManager: IPollingManager) => IPushManager | undefined,
|
|
27
|
-
_submitterManagerFactory = submitterManagerFactory(),
|
|
28
26
|
): (params: ISdkFactoryContextSync) => ISyncManagerCS {
|
|
29
27
|
|
|
30
28
|
/**
|
|
@@ -44,7 +42,7 @@ export function syncManagerOnlineFactory(
|
|
|
44
42
|
|
|
45
43
|
/** Submitter Manager */
|
|
46
44
|
// It is not injected as push and polling managers, because at the moment it is required
|
|
47
|
-
const submitterManager =
|
|
45
|
+
const submitterManager = submitterManagerFactory(params);
|
|
48
46
|
|
|
49
47
|
/** Sync Manager logic */
|
|
50
48
|
|