@splitsoftware/splitio-commons 1.2.1-rc.1 → 1.2.1-rc.12
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/cjs/consent/index.js +10 -0
- package/cjs/consent/sdkUserConsent.js +58 -0
- package/cjs/evaluator/Engine.js +6 -6
- package/cjs/evaluator/combiners/and.js +1 -1
- package/cjs/evaluator/combiners/ifelseif.js +2 -2
- package/cjs/evaluator/condition/engineUtils.js +2 -2
- package/cjs/evaluator/condition/index.js +4 -4
- package/cjs/evaluator/index.js +5 -5
- package/cjs/evaluator/matchers/cont_all.js +1 -1
- package/cjs/evaluator/matchers/cont_any.js +1 -1
- package/cjs/evaluator/matchers/cont_str.js +1 -1
- package/cjs/evaluator/matchers/dependency.js +1 -1
- package/cjs/evaluator/matchers/eq_set.js +1 -1
- package/cjs/evaluator/matchers/ew.js +1 -1
- package/cjs/evaluator/matchers/part_of.js +1 -1
- package/cjs/evaluator/matchers/segment.js +1 -1
- package/cjs/evaluator/matchers/sw.js +1 -1
- package/cjs/evaluator/matchers/whitelist.js +1 -1
- package/cjs/evaluator/matchersTransform/index.js +12 -12
- package/cjs/evaluator/parser/index.js +6 -6
- package/cjs/evaluator/treatments/index.js +1 -1
- package/cjs/evaluator/value/index.js +1 -1
- package/cjs/evaluator/value/sanitize.js +4 -4
- package/cjs/integrations/browser.js +3 -3
- package/cjs/integrations/ga/GaToSplit.js +14 -14
- package/cjs/integrations/ga/GoogleAnalyticsToSplit.js +5 -3
- package/cjs/integrations/ga/SplitToGa.js +1 -1
- package/cjs/integrations/ga/SplitToGoogleAnalytics.js +4 -2
- package/cjs/listeners/browser.js +15 -11
- package/cjs/listeners/node.js +1 -1
- package/cjs/logger/constants.js +9 -3
- package/cjs/logger/index.js +2 -2
- package/cjs/logger/messages/debug.js +4 -4
- package/cjs/logger/messages/error.js +5 -4
- package/cjs/logger/messages/info.js +8 -5
- package/cjs/logger/messages/warn.js +1 -1
- package/cjs/logger/sdkLogger.js +1 -1
- package/cjs/readiness/readinessManager.js +2 -2
- package/cjs/readiness/sdkReadinessManager.js +4 -4
- package/cjs/sdkClient/client.js +12 -11
- package/cjs/sdkClient/clientAttributesDecoration.js +4 -4
- package/cjs/sdkClient/clientCS.js +3 -3
- package/cjs/sdkClient/clientInputValidation.js +20 -22
- package/cjs/sdkClient/sdkClient.js +6 -9
- package/cjs/sdkClient/sdkClientMethod.js +1 -1
- package/cjs/sdkClient/sdkClientMethodCS.js +7 -13
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +8 -18
- package/cjs/sdkFactory/index.js +16 -13
- package/cjs/sdkManager/index.js +11 -11
- package/cjs/services/splitApi.js +3 -2
- package/cjs/services/splitHttpClient.js +2 -2
- package/cjs/storages/KeyBuilder.js +2 -6
- package/cjs/storages/KeyBuilderCS.js +13 -3
- package/cjs/storages/KeyBuilderSS.js +1 -1
- package/cjs/storages/findLatencyIndex.js +1 -1
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +24 -4
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +12 -12
- package/cjs/storages/inLocalStorage/index.js +4 -4
- package/cjs/storages/inMemory/AttributesCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
- package/cjs/storages/inMemory/InMemoryStorage.js +1 -1
- package/cjs/storages/inMemory/InMemoryStorageCS.js +1 -1
- package/cjs/storages/inMemory/LatenciesCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +1 -1
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +2 -2
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +5 -5
- package/cjs/storages/inRedis/LatenciesCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/RedisAdapter.js +24 -11
- package/cjs/storages/inRedis/SegmentsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +3 -3
- package/cjs/storages/inRedis/index.js +1 -1
- package/cjs/storages/pluggable/SegmentsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/SplitsCachePluggable.js +3 -3
- package/cjs/storages/pluggable/inMemoryWrapper.js +4 -4
- package/cjs/storages/pluggable/index.js +6 -6
- package/cjs/sync/offline/LocalhostFromFile.js +1 -1
- package/cjs/sync/offline/LocalhostFromObject.js +1 -1
- package/cjs/sync/offline/splitsParser/parseCondition.js +1 -1
- package/cjs/sync/offline/splitsParser/splitsParserFromFile.js +13 -13
- package/cjs/sync/offline/splitsParser/splitsParserFromSettings.js +3 -3
- package/cjs/sync/offline/syncManagerOffline.js +1 -1
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +2 -2
- package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
- package/cjs/sync/polling/pollingManagerCS.js +6 -6
- package/cjs/sync/polling/pollingManagerSS.js +3 -3
- package/cjs/sync/polling/syncTasks/mySegmentsSyncTask.js +1 -1
- package/cjs/sync/polling/syncTasks/segmentsSyncTask.js +1 -1
- package/cjs/sync/polling/syncTasks/splitsSyncTask.js +1 -1
- package/cjs/sync/polling/updaters/mySegmentsUpdater.js +1 -1
- package/cjs/sync/polling/updaters/segmentChangesUpdater.js +2 -2
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -2
- package/cjs/sync/streaming/AuthClient/index.js +3 -3
- package/cjs/sync/streaming/SSEClient/index.js +2 -1
- package/cjs/sync/streaming/SSEHandler/NotificationParser.js +1 -1
- package/cjs/sync/streaming/SSEHandler/index.js +3 -3
- package/cjs/sync/streaming/mySegmentsV2utils.js +1 -1
- package/cjs/sync/streaming/pushManager.js +24 -17
- package/cjs/sync/submitters/eventsSyncTask.js +17 -5
- package/cjs/sync/submitters/impressionCountsSyncTask.js +1 -1
- package/cjs/sync/submitters/impressionsSyncTask.js +15 -3
- package/cjs/sync/submitters/metricsSyncTask.js +3 -3
- package/cjs/sync/submitters/submitterManager.js +4 -4
- package/cjs/sync/submitters/submitterSyncTask.js +1 -1
- package/cjs/sync/syncManagerOnline.js +12 -8
- package/cjs/trackers/eventTracker.js +11 -4
- package/cjs/trackers/impressionObserver/impressionObserverCS.js +1 -1
- package/cjs/trackers/impressionObserver/impressionObserverSS.js +1 -1
- package/cjs/trackers/impressionObserver/utils.js +8 -1
- package/cjs/trackers/impressionsTracker.js +9 -8
- package/cjs/utils/MinEvents.js +2 -1
- package/cjs/utils/constants/index.js +5 -1
- package/cjs/utils/inputValidation/apiKey.js +1 -1
- package/cjs/utils/inputValidation/attribute.js +4 -4
- package/cjs/utils/inputValidation/attributes.js +2 -2
- package/cjs/utils/inputValidation/event.js +1 -1
- package/cjs/utils/inputValidation/eventProperties.js +5 -5
- package/cjs/utils/inputValidation/eventValue.js +1 -1
- package/cjs/utils/inputValidation/key.js +6 -5
- package/cjs/utils/inputValidation/preloadedData.js +8 -8
- package/cjs/utils/inputValidation/split.js +1 -1
- package/cjs/utils/inputValidation/splits.js +2 -2
- package/cjs/utils/inputValidation/trafficType.js +1 -1
- package/cjs/utils/inputValidation/trafficTypeExistance.js +1 -1
- package/cjs/utils/jwt/index.js +1 -1
- package/cjs/utils/key/index.js +3 -3
- package/cjs/utils/lang/index.js +13 -4
- package/cjs/utils/lang/maps.js +16 -2
- package/cjs/utils/murmur3/common.js +1 -1
- package/cjs/utils/murmur3/murmur3.js +10 -10
- package/cjs/utils/murmur3/murmur3_128.js +1 -1
- package/cjs/utils/murmur3/murmur3_128_x86.js +37 -37
- package/cjs/utils/murmur3/murmur3_64.js +1 -1
- package/cjs/utils/settingsValidation/consent.js +16 -0
- package/cjs/utils/settingsValidation/impressionsMode.js +6 -6
- package/cjs/utils/settingsValidation/index.js +32 -14
- package/cjs/utils/settingsValidation/integrations/configurable.js +1 -1
- package/cjs/utils/settingsValidation/integrations/pluggable.js +1 -1
- package/cjs/utils/settingsValidation/localhost/builtin.js +2 -2
- package/cjs/utils/settingsValidation/logger/builtinLogger.js +3 -3
- package/cjs/utils/settingsValidation/logger/commons.js +1 -1
- package/cjs/utils/settingsValidation/logger/pluggableLogger.js +1 -1
- package/cjs/utils/settingsValidation/runtime.js +11 -0
- package/cjs/utils/settingsValidation/splitFilters.js +1 -1
- package/cjs/utils/settingsValidation/storage/storageCS.js +1 -1
- package/cjs/utils/timeTracker/index.js +3 -3
- package/esm/consent/index.js +6 -0
- package/esm/consent/sdkUserConsent.js +54 -0
- package/esm/integrations/ga/GoogleAnalyticsToSplit.js +4 -2
- package/esm/integrations/ga/SplitToGoogleAnalytics.js +4 -2
- package/esm/listeners/browser.js +14 -10
- package/esm/logger/constants.js +6 -2
- package/esm/logger/messages/debug.js +3 -3
- package/esm/logger/messages/error.js +4 -3
- package/esm/logger/messages/info.js +7 -4
- package/esm/sdkClient/client.js +3 -2
- package/esm/sdkClient/clientCS.js +1 -1
- package/esm/sdkClient/clientInputValidation.js +6 -8
- package/esm/sdkClient/sdkClient.js +4 -7
- package/esm/sdkClient/sdkClientMethodCS.js +3 -9
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +3 -13
- package/esm/sdkFactory/index.js +10 -7
- package/esm/services/splitApi.js +2 -1
- package/esm/storages/KeyBuilder.js +2 -6
- package/esm/storages/KeyBuilderCS.js +11 -1
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +23 -3
- package/esm/storages/inLocalStorage/index.js +1 -1
- package/esm/storages/inMemory/ImpressionsCacheInMemory.js +15 -1
- package/esm/storages/inMemory/InMemoryStorage.js +1 -1
- package/esm/storages/inMemory/InMemoryStorageCS.js +1 -1
- package/esm/storages/inRedis/RedisAdapter.js +15 -2
- package/esm/storages/pluggable/index.js +2 -2
- package/esm/sync/offline/splitsParser/splitsParserFromFile.js +1 -1
- package/esm/sync/polling/fetchers/segmentChangesFetcher.js +2 -2
- package/esm/sync/streaming/SSEClient/index.js +2 -1
- package/esm/sync/streaming/pushManager.js +9 -2
- package/esm/sync/submitters/eventsSyncTask.js +18 -6
- package/esm/sync/submitters/impressionsSyncTask.js +13 -1
- package/esm/sync/syncManagerOnline.js +11 -7
- package/esm/trackers/eventTracker.js +8 -1
- package/esm/trackers/impressionObserver/utils.js +7 -1
- package/esm/trackers/impressionsTracker.js +6 -5
- package/esm/utils/constants/index.js +4 -0
- package/esm/utils/inputValidation/attributes.js +1 -1
- package/esm/utils/inputValidation/key.js +2 -1
- package/esm/utils/lang/index.js +12 -4
- package/esm/utils/lang/maps.js +14 -1
- package/esm/utils/settingsValidation/consent.js +12 -0
- package/esm/utils/settingsValidation/impressionsMode.js +7 -7
- package/esm/utils/settingsValidation/index.js +28 -10
- package/esm/utils/settingsValidation/runtime.js +7 -0
- package/package.json +8 -8
- package/src/consent/index.ts +8 -0
- package/src/consent/sdkUserConsent.ts +58 -0
- package/src/evaluator/parser/index.ts +1 -1
- package/src/evaluator/types.ts +2 -2
- package/src/evaluator/value/index.ts +2 -2
- package/src/evaluator/value/sanitize.ts +2 -2
- package/src/integrations/ga/GoogleAnalyticsToSplit.ts +7 -4
- package/src/integrations/ga/SplitToGoogleAnalytics.ts +7 -4
- package/src/integrations/pluggable.ts +2 -2
- package/src/integrations/types.ts +5 -0
- package/src/listeners/browser.ts +13 -9
- package/src/logger/constants.ts +6 -2
- package/src/logger/messages/debug.ts +3 -3
- package/src/logger/messages/error.ts +4 -3
- package/src/logger/messages/info.ts +7 -4
- package/src/logger/types.ts +4 -0
- package/src/sdkClient/client.ts +5 -5
- package/src/sdkClient/clientCS.ts +1 -1
- package/src/sdkClient/clientInputValidation.ts +8 -7
- package/src/sdkClient/sdkClient.ts +6 -9
- package/src/sdkClient/sdkClientMethod.ts +2 -2
- package/src/sdkClient/sdkClientMethodCS.ts +5 -11
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +6 -16
- package/src/sdkFactory/index.ts +11 -8
- package/src/sdkFactory/types.ts +14 -3
- package/src/storages/KeyBuilder.ts +2 -6
- package/src/storages/KeyBuilderCS.ts +13 -1
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +23 -3
- package/src/storages/inLocalStorage/index.ts +1 -1
- package/src/storages/inMemory/ImpressionsCacheInMemory.ts +22 -1
- package/src/storages/inMemory/InMemoryStorage.ts +1 -1
- package/src/storages/inMemory/InMemoryStorageCS.ts +1 -1
- package/src/storages/inRedis/RedisAdapter.ts +8 -2
- package/src/storages/pluggable/index.ts +2 -2
- package/src/storages/types.ts +6 -2
- package/src/sync/offline/splitsParser/splitsParserFromFile.ts +1 -1
- package/src/sync/streaming/SSEClient/index.ts +2 -1
- package/src/sync/streaming/pushManager.ts +11 -2
- package/src/sync/submitters/eventsSyncTask.ts +19 -6
- package/src/sync/submitters/impressionsSyncTask.ts +16 -1
- package/src/sync/syncManagerOnline.ts +13 -7
- package/src/sync/types.ts +4 -1
- package/src/trackers/eventTracker.ts +11 -3
- package/src/trackers/impressionObserver/utils.ts +8 -1
- package/src/trackers/impressionsTracker.ts +7 -8
- package/src/types.ts +22 -1
- package/src/utils/constants/index.ts +5 -0
- package/src/utils/inputValidation/attributes.ts +1 -2
- package/src/utils/lang/index.ts +15 -4
- package/src/utils/lang/maps.ts +15 -1
- package/src/utils/settingsValidation/consent.ts +16 -0
- package/src/utils/settingsValidation/impressionsMode.ts +8 -8
- package/src/utils/settingsValidation/index.ts +29 -10
- package/src/utils/settingsValidation/runtime.ts +9 -0
- package/src/utils/settingsValidation/types.ts +12 -6
- package/types/consent/index.d.ts +2 -0
- package/types/consent/sdkUserConsent.d.ts +13 -0
- package/types/evaluator/types.d.ts +2 -2
- package/types/evaluator/value/index.d.ts +1 -1
- package/types/evaluator/value/sanitize.d.ts +1 -1
- package/types/integrations/ga/GoogleAnalyticsToSplit.d.ts +2 -2
- package/types/integrations/ga/SplitToGoogleAnalytics.d.ts +2 -3
- package/types/integrations/types.d.ts +4 -0
- package/types/logger/constants.d.ts +6 -2
- package/types/logger/types.d.ts +4 -0
- package/types/sdkClient/client.d.ts +2 -2
- package/types/sdkClient/clientAttributesDecoration.d.ts +1 -1
- package/types/sdkClient/clientInputValidation.d.ts +2 -3
- package/types/sdkClient/sdkClient.d.ts +2 -2
- package/types/sdkClient/sdkClientMethod.d.ts +2 -2
- package/types/sdkClient/sdkClientMethodCS.d.ts +2 -2
- package/types/sdkClient/sdkClientMethodCSWithTT.d.ts +2 -2
- package/types/sdkFactory/types.d.ts +12 -3
- package/types/sdkFactory/userConsentProps.d.ts +6 -0
- package/types/storages/KeyBuilderCS.d.ts +2 -0
- package/types/storages/inMemory/ImpressionsCacheInMemory.d.ts +9 -0
- package/types/storages/inRedis/RedisAdapter.d.ts +1 -1
- package/types/storages/types.d.ts +3 -1
- package/types/sync/types.d.ts +3 -0
- package/types/trackers/eventTracker.d.ts +2 -2
- package/types/trackers/impressionObserver/utils.d.ts +4 -0
- package/types/trackers/impressionsTracker.d.ts +2 -3
- package/types/types.d.ts +22 -1
- package/types/utils/consent.d.ts +2 -0
- package/types/utils/constants/index.d.ts +3 -0
- package/types/utils/lang/index.d.ts +6 -1
- package/types/utils/lang/maps.d.ts +7 -0
- package/types/utils/settingsValidation/consent.d.ts +6 -0
- package/types/utils/settingsValidation/impressionsMode.d.ts +1 -1
- package/types/utils/settingsValidation/runtime/browser.d.ts +2 -0
- package/types/utils/settingsValidation/runtime/node.d.ts +2 -0
- package/types/utils/settingsValidation/runtime.d.ts +2 -0
- package/types/utils/settingsValidation/types.d.ts +12 -6
- package/types/utils/settingsValidation/userConsent.d.ts +5 -0
- package/cjs/sdkClient/types.js +0 -2
- package/esm/sdkClient/types.js +0 -1
- package/src/sdkClient/types.ts +0 -21
|
@@ -3,7 +3,9 @@ import { IPostEventsBulk } from '../../services/types';
|
|
|
3
3
|
import { ISyncTask, ITimeTracker } from '../types';
|
|
4
4
|
import { submitterSyncTaskFactory } from './submitterSyncTask';
|
|
5
5
|
import { ILogger } from '../../logger/types';
|
|
6
|
-
import {
|
|
6
|
+
import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
7
|
+
|
|
8
|
+
const DATA_NAME = 'events';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Sync task that periodically posts tracked events
|
|
@@ -18,26 +20,37 @@ export function eventsSyncTaskFactory(
|
|
|
18
20
|
): ISyncTask {
|
|
19
21
|
|
|
20
22
|
// don't retry events.
|
|
21
|
-
const syncTask = submitterSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate,
|
|
23
|
+
const syncTask = submitterSyncTaskFactory(log, postEventsBulk, eventsCache, eventsPushRate, DATA_NAME, latencyTracker);
|
|
22
24
|
|
|
23
|
-
// Set a timer for the first push of events
|
|
25
|
+
// Set a timer for the first push window of events.
|
|
26
|
+
// Not implemented in the base submitter or sync task, since this feature is only used by the events submitter.
|
|
24
27
|
if (eventsFirstPushWindow > 0) {
|
|
28
|
+
let running = false;
|
|
25
29
|
let stopEventPublisherTimeout: ReturnType<typeof setTimeout>;
|
|
26
30
|
const originalStart = syncTask.start;
|
|
27
31
|
syncTask.start = () => {
|
|
32
|
+
running = true;
|
|
28
33
|
stopEventPublisherTimeout = setTimeout(originalStart, eventsFirstPushWindow);
|
|
29
34
|
};
|
|
30
35
|
const originalStop = syncTask.stop;
|
|
31
36
|
syncTask.stop = () => {
|
|
37
|
+
running = false;
|
|
32
38
|
clearTimeout(stopEventPublisherTimeout);
|
|
33
39
|
originalStop();
|
|
34
40
|
};
|
|
41
|
+
syncTask.isRunning = () => {
|
|
42
|
+
return running;
|
|
43
|
+
};
|
|
35
44
|
}
|
|
36
45
|
|
|
37
|
-
// register
|
|
46
|
+
// register events submitter to be executed when events cache is full
|
|
38
47
|
eventsCache.setOnFullQueueCb(() => {
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
if (syncTask.isRunning()) {
|
|
49
|
+
log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
|
|
50
|
+
syncTask.execute();
|
|
51
|
+
}
|
|
52
|
+
// If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
|
|
53
|
+
// Data will be sent when submitter is resumed.
|
|
41
54
|
});
|
|
42
55
|
|
|
43
56
|
return syncTask;
|
|
@@ -6,6 +6,9 @@ import { ImpressionDTO } from '../../types';
|
|
|
6
6
|
import { submitterSyncTaskFactory } from './submitterSyncTask';
|
|
7
7
|
import { ImpressionsPayload } from './types';
|
|
8
8
|
import { ILogger } from '../../logger/types';
|
|
9
|
+
import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
|
|
10
|
+
|
|
11
|
+
const DATA_NAME = 'impressions';
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Converts `impressions` data from cache into request payload.
|
|
@@ -50,5 +53,17 @@ export function impressionsSyncTaskFactory(
|
|
|
50
53
|
): ISyncTask {
|
|
51
54
|
|
|
52
55
|
// retry impressions only once.
|
|
53
|
-
|
|
56
|
+
const syncTask = submitterSyncTaskFactory(log, postTestImpressionsBulk, impressionsCache, impressionsRefreshRate, DATA_NAME, latencyTracker, fromImpressionsCollector.bind(undefined, sendLabels), 1);
|
|
57
|
+
|
|
58
|
+
// register impressions submitter to be executed when impressions cache is full
|
|
59
|
+
impressionsCache.setOnFullQueueCb(() => {
|
|
60
|
+
if (syncTask.isRunning()) {
|
|
61
|
+
log.info(SUBMITTERS_PUSH_FULL_QUEUE, [DATA_NAME]);
|
|
62
|
+
syncTask.execute();
|
|
63
|
+
}
|
|
64
|
+
// If submitter is stopped (e.g., user consent declined or unknown, or app state offline), we don't send the data.
|
|
65
|
+
// Data will be sent when submitter is resumed.
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return syncTask;
|
|
54
69
|
}
|
|
@@ -6,6 +6,7 @@ import { IPushManager } from './streaming/types';
|
|
|
6
6
|
import { IPollingManager, IPollingManagerCS } from './polling/types';
|
|
7
7
|
import { PUSH_SUBSYSTEM_UP, PUSH_SUBSYSTEM_DOWN } from './streaming/constants';
|
|
8
8
|
import { SYNC_START_POLLING, SYNC_CONTINUE_POLLING, SYNC_STOP_POLLING } from '../logger/constants';
|
|
9
|
+
import { isConsentGranted } from '../consent';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Online SyncManager factory.
|
|
@@ -25,7 +26,7 @@ export function syncManagerOnlineFactory(
|
|
|
25
26
|
*/
|
|
26
27
|
return function (params: ISyncManagerFactoryParams): ISyncManagerCS {
|
|
27
28
|
|
|
28
|
-
const { log, streamingEnabled } = params
|
|
29
|
+
const { settings, settings: { log, streamingEnabled } } = params;
|
|
29
30
|
|
|
30
31
|
/** Polling Manager */
|
|
31
32
|
const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
|
|
@@ -39,7 +40,6 @@ export function syncManagerOnlineFactory(
|
|
|
39
40
|
// It is not inyected as push and polling managers, because at the moment it is required
|
|
40
41
|
const submitter = submitterManagerFactory(params);
|
|
41
42
|
|
|
42
|
-
|
|
43
43
|
/** Sync Manager logic */
|
|
44
44
|
|
|
45
45
|
function startPolling() {
|
|
@@ -69,12 +69,18 @@ export function syncManagerOnlineFactory(
|
|
|
69
69
|
let startFirstTime = true; // flag to distinguish calling the `start` method for the first time, to support pausing and resuming the synchronization
|
|
70
70
|
|
|
71
71
|
return {
|
|
72
|
+
// Exposed for fine-grained control of synchronization.
|
|
73
|
+
// E.g.: user consent, app state changes (Page hide, Foreground/Background, Online/Offline).
|
|
74
|
+
pollingManager,
|
|
72
75
|
pushManager,
|
|
76
|
+
submitter,
|
|
73
77
|
|
|
74
78
|
/**
|
|
75
79
|
* Method used to start the syncManager for the first time, or resume it after being stopped.
|
|
76
80
|
*/
|
|
77
81
|
start() {
|
|
82
|
+
running = true;
|
|
83
|
+
|
|
78
84
|
// start syncing splits and segments
|
|
79
85
|
if (pollingManager) {
|
|
80
86
|
if (pushManager) {
|
|
@@ -90,21 +96,21 @@ export function syncManagerOnlineFactory(
|
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
// start periodic data recording (events, impressions, telemetry).
|
|
93
|
-
if (
|
|
94
|
-
running = true;
|
|
99
|
+
if (isConsentGranted(settings)) submitter.start();
|
|
95
100
|
},
|
|
96
101
|
|
|
97
102
|
/**
|
|
98
103
|
* Method used to stop/pause the syncManager.
|
|
99
104
|
*/
|
|
100
105
|
stop() {
|
|
106
|
+
running = false;
|
|
107
|
+
|
|
101
108
|
// stop syncing
|
|
102
109
|
if (pushManager) pushManager.stop();
|
|
103
110
|
if (pollingManager && pollingManager.isRunning()) pollingManager.stop();
|
|
104
111
|
|
|
105
112
|
// stop periodic data recording (events, impressions, telemetry).
|
|
106
|
-
|
|
107
|
-
running = false;
|
|
113
|
+
submitter.stop();
|
|
108
114
|
},
|
|
109
115
|
|
|
110
116
|
isRunning() {
|
|
@@ -112,7 +118,7 @@ export function syncManagerOnlineFactory(
|
|
|
112
118
|
},
|
|
113
119
|
|
|
114
120
|
flush() {
|
|
115
|
-
if (
|
|
121
|
+
if (isConsentGranted(settings)) return submitter.execute();
|
|
116
122
|
else return Promise.resolve();
|
|
117
123
|
},
|
|
118
124
|
|
package/src/sync/types.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { IPlatform } from '../sdkFactory/types';
|
|
|
3
3
|
import { ISplitApi } from '../services/types';
|
|
4
4
|
import { IStorageSync } from '../storages/types';
|
|
5
5
|
import { ISettings } from '../types';
|
|
6
|
+
import { IPollingManager } from './polling/types';
|
|
6
7
|
import { IPushManager } from './streaming/types';
|
|
7
8
|
|
|
8
9
|
export interface ITask<Input extends any[] = []> {
|
|
@@ -43,7 +44,9 @@ export interface ITimeTracker {
|
|
|
43
44
|
|
|
44
45
|
export interface ISyncManager extends ITask {
|
|
45
46
|
flush(): Promise<any>,
|
|
46
|
-
pushManager?: IPushManager
|
|
47
|
+
pushManager?: IPushManager,
|
|
48
|
+
pollingManager?: IPollingManager,
|
|
49
|
+
submitter?: ISyncTask
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
export interface ISyncManagerCS extends ISyncManager {
|
|
@@ -2,9 +2,10 @@ import { objectAssign } from '../utils/lang/objectAssign';
|
|
|
2
2
|
import { thenable } from '../utils/promise/thenable';
|
|
3
3
|
import { IEventsCacheBase } from '../storages/types';
|
|
4
4
|
import { IEventsHandler, IEventTracker } from './types';
|
|
5
|
-
import { SplitIO } from '../types';
|
|
6
|
-
import { ILogger } from '../logger/types';
|
|
5
|
+
import { ISettings, SplitIO } from '../types';
|
|
7
6
|
import { EVENTS_TRACKER_SUCCESS, ERROR_EVENTS_TRACKER } from '../logger/constants';
|
|
7
|
+
import { CONSENT_DECLINED } from '../utils/constants';
|
|
8
|
+
import { isStorageSync } from './impressionObserver/utils';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Event tracker stores events in cache and pass them to the integrations manager if provided.
|
|
@@ -13,11 +14,14 @@ import { EVENTS_TRACKER_SUCCESS, ERROR_EVENTS_TRACKER } from '../logger/constant
|
|
|
13
14
|
* @param integrationsManager optional event handler used for integrations
|
|
14
15
|
*/
|
|
15
16
|
export function eventTrackerFactory(
|
|
16
|
-
|
|
17
|
+
settings: ISettings,
|
|
17
18
|
eventsCache: IEventsCacheBase,
|
|
18
19
|
integrationsManager?: IEventsHandler
|
|
19
20
|
): IEventTracker {
|
|
20
21
|
|
|
22
|
+
const log = settings.log;
|
|
23
|
+
const isSync = isStorageSync(settings);
|
|
24
|
+
|
|
21
25
|
function queueEventsCallback(eventData: SplitIO.EventData, tracked: boolean) {
|
|
22
26
|
const { eventTypeId, trafficTypeName, key, value, timestamp, properties } = eventData;
|
|
23
27
|
// Logging every prop would be too much.
|
|
@@ -44,6 +48,10 @@ export function eventTrackerFactory(
|
|
|
44
48
|
|
|
45
49
|
return {
|
|
46
50
|
track(eventData: SplitIO.EventData, size?: number) {
|
|
51
|
+
if (settings.userConsent === CONSENT_DECLINED) {
|
|
52
|
+
return isSync ? false : Promise.resolve(false);
|
|
53
|
+
}
|
|
54
|
+
|
|
47
55
|
const tracked = eventsCache.track(eventData, size);
|
|
48
56
|
|
|
49
57
|
if (thenable(tracked)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CONSUMER_PARTIAL_MODE, OPTIMIZED, PRODUCER_MODE, STANDALONE_MODE } from '../../utils/constants';
|
|
1
|
+
import { CONSUMER_MODE, CONSUMER_PARTIAL_MODE, OPTIMIZED, PRODUCER_MODE, STANDALONE_MODE } from '../../utils/constants';
|
|
2
2
|
import { ISettings } from '../../types';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -15,3 +15,10 @@ export function shouldBeOptimized(settings: ISettings) {
|
|
|
15
15
|
if (!shouldAddPt(settings)) return false;
|
|
16
16
|
return settings.sync.impressionsMode === OPTIMIZED ? true : false;
|
|
17
17
|
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Storage is async if mode is consumer or partial consumer
|
|
21
|
+
*/
|
|
22
|
+
export function isStorageSync(settings: ISettings) {
|
|
23
|
+
return [CONSUMER_MODE, CONSUMER_PARTIAL_MODE].indexOf(settings.mode) === -1 ? true : false;
|
|
24
|
+
}
|
|
@@ -5,8 +5,8 @@ import { IImpressionCountsCacheSync, IImpressionsCacheBase } from '../storages/t
|
|
|
5
5
|
import { IImpressionsHandler, IImpressionsTracker } from './types';
|
|
6
6
|
import { SplitIO, ImpressionDTO, ISettings } from '../types';
|
|
7
7
|
import { IImpressionObserver } from './impressionObserver/types';
|
|
8
|
-
import { ILogger } from '../logger/types';
|
|
9
8
|
import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIONS_LISTENER } from '../logger/constants';
|
|
9
|
+
import { CONSENT_DECLINED } from '../utils/constants';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Impressions tracker stores impressions in cache and pass them to the listener and integrations manager if provided.
|
|
@@ -19,22 +19,21 @@ import { IMPRESSIONS_TRACKER_SUCCESS, ERROR_IMPRESSIONS_TRACKER, ERROR_IMPRESSIO
|
|
|
19
19
|
* @param countsCache optional cache to save impressions count. If provided, impressions will be deduped (OPTIMIZED mode)
|
|
20
20
|
*/
|
|
21
21
|
export function impressionsTrackerFactory(
|
|
22
|
-
|
|
22
|
+
settings: ISettings,
|
|
23
23
|
impressionsCache: IImpressionsCacheBase,
|
|
24
|
-
|
|
25
|
-
// @TODO consider passing only an optional integrationsManager to handle impressions
|
|
26
|
-
{ runtime: { ip, hostname }, version }: Pick<ISettings, 'version' | 'runtime'>,
|
|
27
|
-
impressionListener?: SplitIO.IImpressionListener,
|
|
28
24
|
integrationsManager?: IImpressionsHandler,
|
|
29
|
-
|
|
30
25
|
// if observer is provided, it implies `shouldAddPreviousTime` flag (i.e., if impressions previous time should be added or not)
|
|
31
26
|
observer?: IImpressionObserver,
|
|
32
27
|
// if countsCache is provided, it implies `isOptimized` flag (i.e., if impressions should be deduped or not)
|
|
33
28
|
countsCache?: IImpressionCountsCacheSync
|
|
34
29
|
): IImpressionsTracker {
|
|
35
30
|
|
|
31
|
+
const { log, impressionListener, runtime: { ip, hostname }, version } = settings;
|
|
32
|
+
|
|
36
33
|
return {
|
|
37
34
|
track(impressions: ImpressionDTO[], attributes?: SplitIO.Attributes) {
|
|
35
|
+
if (settings.userConsent === CONSENT_DECLINED) return;
|
|
36
|
+
|
|
38
37
|
const impressionsCount = impressions.length;
|
|
39
38
|
|
|
40
39
|
const impressionsToStore: ImpressionDTO[] = []; // Track only the impressions that are going to be stored
|
|
@@ -85,7 +84,7 @@ export function impressionsTrackerFactory(
|
|
|
85
84
|
// integrationsManager.handleImpression does not throw errors
|
|
86
85
|
if (integrationsManager) integrationsManager.handleImpression(impressionData);
|
|
87
86
|
|
|
88
|
-
try { // An exception on the listeners should not break the SDK.
|
|
87
|
+
try { // @ts-ignore. An exception on the listeners should not break the SDK.
|
|
89
88
|
if (impressionListener) impressionListener.logImpression(impressionData);
|
|
90
89
|
} catch (err) {
|
|
91
90
|
log.error(ERROR_IMPRESSIONS_LISTENER, [err]);
|
package/src/types.ts
CHANGED
|
@@ -54,6 +54,11 @@ type EventConsts = {
|
|
|
54
54
|
* @typedef {string} SDKMode
|
|
55
55
|
*/
|
|
56
56
|
export type SDKMode = 'standalone' | 'consumer' | 'localhost' | 'consumer_partial';
|
|
57
|
+
/**
|
|
58
|
+
* User consent status.
|
|
59
|
+
* @typedef {string} ConsentStatus
|
|
60
|
+
*/
|
|
61
|
+
export type ConsentStatus = 'GRANTED' | 'DECLINED' | 'UNKNOWN';
|
|
57
62
|
/**
|
|
58
63
|
* Settings interface. This is a representation of the settings the SDK expose, that's why
|
|
59
64
|
* most of it's props are readonly. Only features should be rewritten when localhost mode is active.
|
|
@@ -73,6 +78,7 @@ export interface ISettings {
|
|
|
73
78
|
readonly scheduler: {
|
|
74
79
|
featuresRefreshRate: number,
|
|
75
80
|
impressionsRefreshRate: number,
|
|
81
|
+
impressionsQueueSize: number,
|
|
76
82
|
metricsRefreshRate: number,
|
|
77
83
|
segmentsRefreshRate: number,
|
|
78
84
|
offlineRefreshRate: number,
|
|
@@ -110,6 +116,7 @@ export interface ISettings {
|
|
|
110
116
|
},
|
|
111
117
|
readonly log: ILogger
|
|
112
118
|
readonly impressionListener?: unknown
|
|
119
|
+
readonly userConsent?: ConsentStatus
|
|
113
120
|
}
|
|
114
121
|
/**
|
|
115
122
|
* Log levels.
|
|
@@ -255,6 +262,13 @@ interface INodeBasicSettings extends ISharedSettings {
|
|
|
255
262
|
* @default 300
|
|
256
263
|
*/
|
|
257
264
|
impressionsRefreshRate?: number,
|
|
265
|
+
/**
|
|
266
|
+
* The maximum number of impression items we want to queue. If we queue more values, it will trigger a flush and reset the timer.
|
|
267
|
+
* If you use a 0 here, the queue will have no maximum size.
|
|
268
|
+
* @property {number} impressionsQueueSize
|
|
269
|
+
* @default 30000
|
|
270
|
+
*/
|
|
271
|
+
impressionsQueueSize?: number,
|
|
258
272
|
/**
|
|
259
273
|
* The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds.
|
|
260
274
|
* @property {number} metricsRefreshRate
|
|
@@ -384,7 +398,7 @@ interface IBasicClient extends IStatusInterface {
|
|
|
384
398
|
|
|
385
399
|
// Whether the client implements the client-side API, i.e, with bound key, (true), or the server-side API (false).
|
|
386
400
|
// Exposed for internal purposes only. Not considered part of the public API, and might be renamed eventually.
|
|
387
|
-
|
|
401
|
+
isClientSide: boolean
|
|
388
402
|
}
|
|
389
403
|
/**
|
|
390
404
|
* Common definitions between SDK instances for different environments interface.
|
|
@@ -769,6 +783,13 @@ export namespace SplitIO {
|
|
|
769
783
|
* @default 60
|
|
770
784
|
*/
|
|
771
785
|
impressionsRefreshRate?: number,
|
|
786
|
+
/**
|
|
787
|
+
* The maximum number of impression items we want to queue. If we queue more values, it will trigger a flush and reset the timer.
|
|
788
|
+
* If you use a 0 here, the queue will have no maximum size.
|
|
789
|
+
* @property {number} impressionsQueueSize
|
|
790
|
+
* @default 30000
|
|
791
|
+
*/
|
|
792
|
+
impressionsQueueSize?: number,
|
|
772
793
|
/**
|
|
773
794
|
* The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds.
|
|
774
795
|
* @property {number} metricsRefreshRate
|
|
@@ -32,3 +32,8 @@ export const STORAGE_MEMORY: StorageType = 'MEMORY';
|
|
|
32
32
|
export const STORAGE_LOCALSTORAGE: StorageType = 'LOCALSTORAGE';
|
|
33
33
|
export const STORAGE_REDIS: StorageType = 'REDIS';
|
|
34
34
|
export const STORAGE_PLUGGABLE: StorageType = 'PLUGGABLE';
|
|
35
|
+
|
|
36
|
+
// User consent
|
|
37
|
+
export const CONSENT_GRANTED = 'GRANTED'; // The user has granted consent for tracking events and impressions
|
|
38
|
+
export const CONSENT_DECLINED = 'DECLINED'; // The user has declined consent for tracking events and impressions
|
|
39
|
+
export const CONSENT_UNKNOWN = 'UNKNOWN'; // The user has neither granted nor declined consent for tracking events and impressions
|
|
@@ -6,7 +6,7 @@ import { ERROR_NOT_PLAIN_OBJECT } from '../../logger/constants';
|
|
|
6
6
|
|
|
7
7
|
export function validateAttributes(log: ILogger, maybeAttrs: any, method: string): SplitIO.Attributes | undefined | false {
|
|
8
8
|
// Attributes are optional
|
|
9
|
-
if (
|
|
9
|
+
if (maybeAttrs == undefined || isObject(maybeAttrs)) // eslint-disable-line eqeqeq
|
|
10
10
|
return maybeAttrs;
|
|
11
11
|
|
|
12
12
|
log.error(ERROR_NOT_PLAIN_OBJECT, [method, 'attributes']);
|
|
@@ -23,5 +23,4 @@ export function validateAttributesDeep(log: ILogger, maybeAttributes: Record<str
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
return result;
|
|
26
|
-
|
|
27
26
|
}
|
package/src/utils/lang/index.ts
CHANGED
|
@@ -89,7 +89,7 @@ export function get(obj: any, prop: any, val: any): any {
|
|
|
89
89
|
/**
|
|
90
90
|
* Parses an array into a map of different arrays, grouping by the specified prop value.
|
|
91
91
|
*/
|
|
92
|
-
export function groupBy<T extends Record<string, any
|
|
92
|
+
export function groupBy<T extends Record<string, any>>(source: T[], prop: string): Record<string, T[]> {
|
|
93
93
|
const map: Record<string, any[]> = {};
|
|
94
94
|
|
|
95
95
|
if (Array.isArray(source) && isString(prop)) {
|
|
@@ -151,10 +151,14 @@ export function isNaNNumber(val: any): boolean {
|
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/**
|
|
154
|
-
* Validates if a value is an object
|
|
154
|
+
* Validates if a value is an object created by the Object constructor (plain object).
|
|
155
|
+
* It checks `constructor.name` to avoid false negatives when validating values on a separate VM context, which has its own global built-ins.
|
|
155
156
|
*/
|
|
156
|
-
export function isObject(obj: any)
|
|
157
|
-
return obj !== null && typeof obj === 'object' &&
|
|
157
|
+
export function isObject(obj: any) {
|
|
158
|
+
return obj !== null && typeof obj === 'object' && (
|
|
159
|
+
obj.constructor === Object ||
|
|
160
|
+
(obj.constructor != null && obj.constructor.name === 'Object')
|
|
161
|
+
);
|
|
158
162
|
}
|
|
159
163
|
|
|
160
164
|
/**
|
|
@@ -164,6 +168,13 @@ export function isString(val: any): val is string {
|
|
|
164
168
|
return typeof val === 'string' || val instanceof String;
|
|
165
169
|
}
|
|
166
170
|
|
|
171
|
+
/**
|
|
172
|
+
* String sanitizer. Returns the provided value converted to uppercase if it is a string.
|
|
173
|
+
*/
|
|
174
|
+
export function stringToUpperCase(val: any) {
|
|
175
|
+
return isString(val) ? val.toUpperCase() : val;
|
|
176
|
+
}
|
|
177
|
+
|
|
167
178
|
/**
|
|
168
179
|
* Deep copy version of Object.assign using recursion.
|
|
169
180
|
* There are some assumptions here. It's for internal use and we don't need verbose errors
|
package/src/utils/lang/maps.ts
CHANGED
|
@@ -79,4 +79,18 @@ interface IMapConstructor {
|
|
|
79
79
|
readonly prototype: IMap<any, any>;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
/**
|
|
83
|
+
* return the Map constructor to use. If native Map is not available or it doesn't support the required features (e.g., IE11),
|
|
84
|
+
* a ponyfill with minimal features is returned instead.
|
|
85
|
+
*
|
|
86
|
+
* Exported for testing purposes only.
|
|
87
|
+
*/
|
|
88
|
+
export function __getMapConstructor(): IMapConstructor {
|
|
89
|
+
// eslint-disable-next-line compat/compat
|
|
90
|
+
if (typeof Array.from === 'function' && typeof Map === 'function' && Map.prototype && Map.prototype.values) {
|
|
91
|
+
return Map;
|
|
92
|
+
}
|
|
93
|
+
return MapPoly;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const _Map = __getMapConstructor();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
|
|
2
|
+
import { ILogger } from '../../logger/types';
|
|
3
|
+
import { ConsentStatus } from '../../types';
|
|
4
|
+
import { CONSENT_DECLINED, CONSENT_GRANTED, CONSENT_UNKNOWN } from '../constants';
|
|
5
|
+
import { stringToUpperCase } from '../lang';
|
|
6
|
+
|
|
7
|
+
const userConsentValues = [CONSENT_DECLINED, CONSENT_GRANTED, CONSENT_UNKNOWN];
|
|
8
|
+
|
|
9
|
+
export function validateConsent({ userConsent, log }: { userConsent?: any, log: ILogger }): ConsentStatus {
|
|
10
|
+
userConsent = stringToUpperCase(userConsent);
|
|
11
|
+
|
|
12
|
+
if (userConsentValues.indexOf(userConsent) > -1) return userConsent;
|
|
13
|
+
|
|
14
|
+
log.error(ERROR_INVALID_CONFIG_PARAM, ['userConsent', userConsentValues, CONSENT_GRANTED]);
|
|
15
|
+
return CONSENT_GRANTED;
|
|
16
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ERROR_INVALID_CONFIG_PARAM } from '../../logger/constants';
|
|
2
2
|
import { ILogger } from '../../logger/types';
|
|
3
3
|
import { SplitIO } from '../../types';
|
|
4
4
|
import { DEBUG, OPTIMIZED } from '../constants';
|
|
5
|
+
import { stringToUpperCase } from '../lang';
|
|
5
6
|
|
|
6
|
-
export function validImpressionsMode(log: ILogger, impressionsMode:
|
|
7
|
-
impressionsMode = impressionsMode
|
|
8
|
-
if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) === -1) {
|
|
9
|
-
log.error(ERROR_INVALID_IMPRESSIONS_MODE, [[DEBUG, OPTIMIZED], OPTIMIZED]);
|
|
10
|
-
impressionsMode = OPTIMIZED;
|
|
11
|
-
}
|
|
7
|
+
export function validImpressionsMode(log: ILogger, impressionsMode: any): SplitIO.ImpressionsMode {
|
|
8
|
+
impressionsMode = stringToUpperCase(impressionsMode);
|
|
12
9
|
|
|
13
|
-
|
|
10
|
+
if ([DEBUG, OPTIMIZED].indexOf(impressionsMode) > -1) return impressionsMode;
|
|
11
|
+
|
|
12
|
+
log.error(ERROR_INVALID_CONFIG_PARAM, ['impressionsMode', [DEBUG, OPTIMIZED], OPTIMIZED]);
|
|
13
|
+
return OPTIMIZED;
|
|
14
14
|
}
|
|
@@ -5,6 +5,8 @@ import { STANDALONE_MODE, OPTIMIZED, LOCALHOST_MODE } from '../constants';
|
|
|
5
5
|
import { validImpressionsMode } from './impressionsMode';
|
|
6
6
|
import { ISettingsValidationParams } from './types';
|
|
7
7
|
import { ISettings } from '../../types';
|
|
8
|
+
import { validateKey } from '../inputValidation/key';
|
|
9
|
+
import { validateTrafficType } from '../inputValidation/trafficType';
|
|
8
10
|
|
|
9
11
|
const base = {
|
|
10
12
|
// Define which kind of object you want to retrieve from SplitFactory
|
|
@@ -38,6 +40,8 @@ const base = {
|
|
|
38
40
|
eventsPushRate: 60,
|
|
39
41
|
// how many events will be queued before flushing
|
|
40
42
|
eventsQueueSize: 500,
|
|
43
|
+
// how many impressions will be queued before flushing
|
|
44
|
+
impressionsQueueSize: 30000,
|
|
41
45
|
// backoff base seconds to wait before re attempting to connect to push notifications
|
|
42
46
|
pushRetryBackoffBase: 1,
|
|
43
47
|
},
|
|
@@ -78,11 +82,6 @@ const base = {
|
|
|
78
82
|
localhostMode: undefined
|
|
79
83
|
},
|
|
80
84
|
|
|
81
|
-
runtime: {
|
|
82
|
-
ip: false,
|
|
83
|
-
hostname: false
|
|
84
|
-
},
|
|
85
|
-
|
|
86
85
|
// Logger
|
|
87
86
|
log: undefined
|
|
88
87
|
};
|
|
@@ -100,7 +99,7 @@ function fromSecondsToMillis(n: number) {
|
|
|
100
99
|
*/
|
|
101
100
|
export function settingsValidation(config: unknown, validationParams: ISettingsValidationParams) {
|
|
102
101
|
|
|
103
|
-
const { defaults, runtime, storage, integrations, logger, localhost } = validationParams;
|
|
102
|
+
const { defaults, runtime, storage, integrations, logger, localhost, consent } = validationParams;
|
|
104
103
|
|
|
105
104
|
// creates a settings object merging base, defaults and config objects.
|
|
106
105
|
const withDefaults = merge({}, base, defaults, config) as ISettings;
|
|
@@ -132,14 +131,30 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
|
|
|
132
131
|
// @ts-ignore, modify readonly prop
|
|
133
132
|
if (storage) withDefaults.storage = storage(withDefaults);
|
|
134
133
|
|
|
135
|
-
//
|
|
136
|
-
if (
|
|
137
|
-
withDefaults.core.key
|
|
134
|
+
// Validate key and TT (for client-side)
|
|
135
|
+
if (validationParams.acceptKey) {
|
|
136
|
+
const maybeKey = withDefaults.core.key;
|
|
137
|
+
// Although `key` is required in client-side, it can be omitted in LOCALHOST mode. In that case, the value `localhost_key` is used.
|
|
138
|
+
if (withDefaults.mode === LOCALHOST_MODE && maybeKey === undefined) {
|
|
139
|
+
withDefaults.core.key = 'localhost_key';
|
|
140
|
+
} else {
|
|
141
|
+
// Keeping same behaviour than JS SDK: if settings key or TT are invalid,
|
|
142
|
+
// `false` value is used as binded key/TT of the default client, which leads to some issues.
|
|
143
|
+
// @ts-ignore, @TODO handle invalid keys as a non-recoverable error?
|
|
144
|
+
withDefaults.core.key = validateKey(log, maybeKey, 'Client instantiation');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (validationParams.acceptTT) {
|
|
148
|
+
const maybeTT = withDefaults.core.trafficType;
|
|
149
|
+
if (maybeTT !== undefined) { // @ts-ignore
|
|
150
|
+
withDefaults.core.trafficType = validateTrafficType(log, maybeTT, 'Client instantiation');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
138
153
|
}
|
|
139
154
|
|
|
140
155
|
// Current ip/hostname information
|
|
141
156
|
// @ts-ignore, modify readonly prop
|
|
142
|
-
|
|
157
|
+
withDefaults.runtime = runtime(withDefaults);
|
|
143
158
|
|
|
144
159
|
// ensure a valid list of integrations.
|
|
145
160
|
// `integrations` returns an array of valid integration items.
|
|
@@ -164,5 +179,9 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
|
|
|
164
179
|
// ensure a valid impressionsMode
|
|
165
180
|
withDefaults.sync.impressionsMode = validImpressionsMode(log, withDefaults.sync.impressionsMode);
|
|
166
181
|
|
|
182
|
+
// ensure a valid user consent value
|
|
183
|
+
// @ts-ignore, modify readonly prop
|
|
184
|
+
withDefaults.userConsent = consent(withDefaults);
|
|
185
|
+
|
|
167
186
|
return withDefaults;
|
|
168
187
|
}
|
|
@@ -6,18 +6,24 @@ import { ISettings } from '../../types';
|
|
|
6
6
|
*/
|
|
7
7
|
export interface ISettingsValidationParams {
|
|
8
8
|
/**
|
|
9
|
-
* Object of values to overwrite
|
|
10
|
-
* Version and startup properties are
|
|
9
|
+
* Object of values to overwrite base settings.
|
|
10
|
+
* Version and startup properties are required, because they are not defined in the base settings.
|
|
11
11
|
*/
|
|
12
12
|
defaults: Partial<ISettings> & { version: string } & { startup: ISettings['startup'] },
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
/**
|
|
13
|
+
/** If true, validates core.key */
|
|
14
|
+
acceptKey?: boolean,
|
|
15
|
+
/** If true, validates core.trafficType */
|
|
16
|
+
acceptTT?: boolean,
|
|
17
|
+
/** Define runtime values (`settings.runtime`) */
|
|
18
|
+
runtime: (settings: ISettings) => ISettings['runtime'],
|
|
19
|
+
/** Storage validator (`settings.storage`) */
|
|
16
20
|
storage?: (settings: ISettings) => ISettings['storage'],
|
|
17
|
-
/** Integrations validator */
|
|
21
|
+
/** Integrations validator (`settings.integrations`) */
|
|
18
22
|
integrations?: (settings: ISettings) => ISettings['integrations'],
|
|
19
23
|
/** Logger validator (`settings.debug`) */
|
|
20
24
|
logger: (settings: ISettings) => ISettings['log'],
|
|
21
25
|
/** Localhost mode validator (`settings.sync.localhostMode`) */
|
|
22
26
|
localhost?: (settings: ISettings) => ISettings['sync']['localhostMode'],
|
|
27
|
+
/** User consent validator (`settings.userConsent`) */
|
|
28
|
+
consent: (settings: ISettings) => ISettings['userConsent'],
|
|
23
29
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ISdkFactoryContext } from '../sdkFactory/types';
|
|
2
|
+
/**
|
|
3
|
+
* The public user consent API exposed via SplitFactory, used to control if the SDK tracks and sends impressions and events or not.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createUserConsentAPI(params: ISdkFactoryContext): {
|
|
6
|
+
setStatus(consent: unknown): boolean;
|
|
7
|
+
getStatus(): import("../types").ConsentStatus | undefined;
|
|
8
|
+
Status: {
|
|
9
|
+
GRANTED: string;
|
|
10
|
+
DECLINED: string;
|
|
11
|
+
UNKNOWN: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -5,7 +5,7 @@ import { SplitIO } from '../types';
|
|
|
5
5
|
import { ILogger } from '../logger/types';
|
|
6
6
|
export interface IDependencyMatcherValue {
|
|
7
7
|
key: SplitIO.SplitKey;
|
|
8
|
-
attributes
|
|
8
|
+
attributes?: SplitIO.Attributes;
|
|
9
9
|
}
|
|
10
10
|
export interface IMatcherDto {
|
|
11
11
|
type: number;
|
|
@@ -23,6 +23,6 @@ export interface IEvaluation {
|
|
|
23
23
|
export declare type IEvaluationResult = IEvaluation & {
|
|
24
24
|
treatment: string;
|
|
25
25
|
};
|
|
26
|
-
export declare type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes, storage: IStorageSync | IStorageAsync) => MaybeThenable<IEvaluation>;
|
|
26
|
+
export declare type ISplitEvaluator = (log: ILogger, key: SplitIO.SplitKey, splitName: string, attributes: SplitIO.Attributes | undefined, storage: IStorageSync | IStorageAsync) => MaybeThenable<IEvaluation>;
|
|
27
27
|
export declare type IEvaluator = (key: SplitIO.SplitKey, seed: number, trafficAllocation?: number, trafficAllocationSeed?: number, attributes?: SplitIO.Attributes, splitEvaluator?: ISplitEvaluator) => MaybeThenable<IEvaluation | undefined>;
|
|
28
28
|
export declare type IMatcher = (...args: any) => MaybeThenable<boolean>;
|
|
@@ -4,4 +4,4 @@ import { ILogger } from '../../logger/types';
|
|
|
4
4
|
/**
|
|
5
5
|
* Defines value to be matched (key / attribute).
|
|
6
6
|
*/
|
|
7
|
-
export declare function sanitizeValue(log: ILogger, key: string, matcherDto: IMatcherDto, attributes
|
|
7
|
+
export declare function sanitizeValue(log: ILogger, key: string, matcherDto: IMatcherDto, attributes?: SplitIO.Attributes): string | number | boolean | (string | number)[] | import("../types").IDependencyMatcherValue | undefined;
|
|
@@ -4,4 +4,4 @@ import { ILogger } from '../../logger/types';
|
|
|
4
4
|
/**
|
|
5
5
|
* Sanitize matcher value
|
|
6
6
|
*/
|
|
7
|
-
export declare function sanitize(log: ILogger, matcherTypeID: number, value: string | number | boolean | Array<string | number> | undefined, dataType: string, attributes
|
|
7
|
+
export declare function sanitize(log: ILogger, matcherTypeID: number, value: string | number | boolean | Array<string | number> | undefined, dataType: string, attributes?: SplitIO.Attributes): string | number | boolean | (string | number)[] | IDependencyMatcherValue | undefined;
|