@splitsoftware/splitio-commons 1.17.1-rc.2 → 2.0.0-rc.0
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 +7 -3
- package/cjs/evaluator/index.js +2 -2
- package/cjs/evaluator/matchers/semver_inlist.js +1 -2
- package/cjs/evaluator/matchers/whitelist.js +1 -2
- package/cjs/listeners/browser.js +1 -2
- package/cjs/logger/browser/DebugLogger.js +1 -2
- package/cjs/logger/browser/ErrorLogger.js +1 -2
- package/cjs/logger/browser/InfoLogger.js +1 -2
- package/cjs/logger/browser/WarnLogger.js +1 -2
- package/cjs/logger/index.js +1 -2
- package/cjs/sdkClient/clientCS.js +5 -8
- package/cjs/sdkClient/sdkClientMethodCS.js +1 -1
- package/cjs/sdkFactory/index.js +1 -3
- package/cjs/services/decorateHeaders.js +1 -2
- package/cjs/storages/AbstractSplitsCacheAsync.js +7 -0
- package/cjs/storages/AbstractSplitsCacheSync.js +7 -0
- package/cjs/storages/KeyBuilderCS.js +0 -9
- package/cjs/storages/dataLoader.js +32 -65
- package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +1 -21
- package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +14 -7
- package/cjs/storages/inLocalStorage/index.js +1 -4
- package/cjs/storages/inMemory/InMemoryStorageCS.js +4 -16
- package/cjs/storages/inMemory/SegmentsCacheInMemory.js +3 -4
- package/cjs/storages/inMemory/SplitsCacheInMemory.js +2 -3
- package/cjs/storages/inMemory/UniqueKeysCacheInMemory.js +2 -3
- package/cjs/storages/inMemory/UniqueKeysCacheInMemoryCS.js +2 -3
- package/cjs/storages/inRedis/RedisAdapter.js +2 -3
- package/cjs/storages/inRedis/SplitsCacheInRedis.js +1 -1
- package/cjs/storages/inRedis/TelemetryCacheInRedis.js +3 -4
- package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +1 -2
- package/cjs/storages/pluggable/SplitsCachePluggable.js +1 -1
- package/cjs/storages/pluggable/TelemetryCachePluggable.js +6 -7
- package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +1 -2
- package/cjs/storages/pluggable/inMemoryWrapper.js +7 -8
- package/cjs/sync/offline/syncTasks/fromObjectSyncTask.js +7 -2
- package/cjs/sync/polling/pollingManagerSS.js +3 -3
- package/cjs/sync/polling/updaters/splitChangesUpdater.js +13 -5
- package/cjs/sync/streaming/parseUtils.js +0 -1
- package/cjs/sync/streaming/pushManager.js +2 -3
- package/cjs/utils/LRUCache/index.js +1 -2
- package/cjs/utils/constants/browser.js +1 -4
- package/cjs/utils/lang/index.js +6 -9
- package/cjs/utils/lang/objectAssign.js +12 -77
- package/cjs/utils/lang/sets.js +3 -110
- package/cjs/utils/settingsValidation/index.js +0 -9
- package/cjs/utils/settingsValidation/logger/builtinLogger.js +1 -2
- package/cjs/utils/settingsValidation/storage/storageCS.js +12 -1
- package/esm/evaluator/index.js +3 -3
- package/esm/evaluator/matchers/semver_inlist.js +1 -2
- package/esm/evaluator/matchers/whitelist.js +1 -2
- package/esm/listeners/browser.js +1 -2
- package/esm/logger/browser/DebugLogger.js +1 -2
- package/esm/logger/browser/ErrorLogger.js +1 -2
- package/esm/logger/browser/InfoLogger.js +1 -2
- package/esm/logger/browser/WarnLogger.js +1 -2
- package/esm/logger/index.js +1 -2
- package/esm/sdkClient/clientCS.js +5 -8
- package/esm/sdkClient/sdkClientMethodCS.js +1 -1
- package/esm/sdkFactory/index.js +2 -4
- package/esm/services/decorateHeaders.js +1 -2
- package/esm/storages/AbstractSplitsCacheAsync.js +7 -0
- package/esm/storages/AbstractSplitsCacheSync.js +7 -0
- package/esm/storages/KeyBuilderCS.js +0 -9
- package/esm/storages/dataLoader.js +30 -62
- package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +1 -21
- package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +14 -7
- package/esm/storages/inLocalStorage/index.js +2 -5
- package/esm/storages/inMemory/InMemoryStorageCS.js +4 -16
- package/esm/storages/inMemory/SegmentsCacheInMemory.js +3 -4
- package/esm/storages/inMemory/SplitsCacheInMemory.js +2 -3
- package/esm/storages/inMemory/UniqueKeysCacheInMemory.js +2 -3
- package/esm/storages/inMemory/UniqueKeysCacheInMemoryCS.js +2 -3
- package/esm/storages/inRedis/RedisAdapter.js +2 -3
- package/esm/storages/inRedis/SplitsCacheInRedis.js +2 -2
- package/esm/storages/inRedis/TelemetryCacheInRedis.js +3 -4
- package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +1 -2
- package/esm/storages/pluggable/SplitsCachePluggable.js +2 -2
- package/esm/storages/pluggable/TelemetryCachePluggable.js +6 -7
- package/esm/storages/pluggable/UniqueKeysCachePluggable.js +1 -2
- package/esm/storages/pluggable/inMemoryWrapper.js +7 -8
- package/esm/sync/offline/syncTasks/fromObjectSyncTask.js +8 -3
- package/esm/sync/polling/pollingManagerSS.js +3 -3
- package/esm/sync/polling/updaters/splitChangesUpdater.js +14 -6
- package/esm/sync/streaming/parseUtils.js +0 -1
- package/esm/sync/streaming/pushManager.js +2 -3
- package/esm/utils/LRUCache/index.js +1 -2
- package/esm/utils/constants/browser.js +0 -3
- package/esm/utils/lang/index.js +6 -9
- package/esm/utils/lang/objectAssign.js +12 -77
- package/esm/utils/lang/sets.js +2 -107
- package/esm/utils/settingsValidation/index.js +0 -9
- package/esm/utils/settingsValidation/logger/builtinLogger.js +1 -2
- package/esm/utils/settingsValidation/storage/storageCS.js +10 -0
- package/package.json +2 -2
- package/src/evaluator/index.ts +5 -5
- package/src/evaluator/matchers/semver_inlist.ts +1 -2
- package/src/evaluator/matchers/whitelist.ts +1 -3
- package/src/listeners/browser.ts +1 -2
- package/src/logger/browser/DebugLogger.ts +1 -2
- package/src/logger/browser/ErrorLogger.ts +1 -2
- package/src/logger/browser/InfoLogger.ts +1 -2
- package/src/logger/browser/WarnLogger.ts +1 -2
- package/src/logger/index.ts +3 -4
- package/src/sdkClient/clientCS.ts +5 -8
- package/src/sdkClient/sdkClientMethodCS.ts +1 -1
- package/src/sdkFactory/index.ts +2 -5
- package/src/sdkFactory/types.ts +1 -1
- package/src/services/decorateHeaders.ts +1 -2
- package/src/storages/AbstractSplitsCacheAsync.ts +9 -2
- package/src/storages/AbstractSplitsCacheSync.ts +9 -2
- package/src/storages/KeyBuilderCS.ts +0 -13
- package/src/storages/dataLoader.ts +32 -63
- package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +1 -21
- package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +16 -8
- package/src/storages/inLocalStorage/index.ts +2 -6
- package/src/storages/inMemory/InMemoryStorageCS.ts +4 -19
- package/src/storages/inMemory/SegmentsCacheInMemory.ts +4 -5
- package/src/storages/inMemory/SplitsCacheInMemory.ts +4 -5
- package/src/storages/inMemory/UniqueKeysCacheInMemory.ts +4 -5
- package/src/storages/inMemory/UniqueKeysCacheInMemoryCS.ts +4 -5
- package/src/storages/inRedis/RedisAdapter.ts +3 -4
- package/src/storages/inRedis/SplitsCacheInRedis.ts +3 -3
- package/src/storages/inRedis/TelemetryCacheInRedis.ts +3 -4
- package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +1 -2
- package/src/storages/pluggable/SegmentsCachePluggable.ts +0 -1
- package/src/storages/pluggable/SplitsCachePluggable.ts +3 -3
- package/src/storages/pluggable/TelemetryCachePluggable.ts +6 -7
- package/src/storages/pluggable/UniqueKeysCachePluggable.ts +1 -2
- package/src/storages/pluggable/inMemoryWrapper.ts +8 -9
- package/src/storages/types.ts +9 -5
- package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +7 -3
- package/src/sync/polling/pollingManagerSS.ts +2 -3
- package/src/sync/polling/updaters/splitChangesUpdater.ts +15 -8
- package/src/sync/streaming/parseUtils.ts +0 -1
- package/src/sync/streaming/pushManager.ts +3 -4
- package/src/sync/submitters/types.ts +3 -4
- package/src/types.ts +9 -18
- package/src/utils/LRUCache/index.ts +2 -3
- package/src/utils/constants/browser.ts +0 -4
- package/src/utils/lang/index.ts +6 -7
- package/src/utils/lang/objectAssign.ts +13 -92
- package/src/utils/lang/sets.ts +3 -125
- package/src/utils/settingsValidation/index.ts +0 -10
- package/src/utils/settingsValidation/logger/builtinLogger.ts +1 -2
- package/src/utils/settingsValidation/storage/storageCS.ts +13 -0
- package/src/utils/settingsValidation/types.ts +0 -2
- package/types/logger/index.d.ts +1 -2
- package/types/sdkClient/clientCS.d.ts +2 -3
- package/types/sdkFactory/types.d.ts +1 -1
- package/types/storages/AbstractSplitsCacheAsync.d.ts +6 -2
- package/types/storages/AbstractSplitsCacheSync.d.ts +6 -2
- package/types/storages/KeyBuilderCS.d.ts +0 -2
- package/types/storages/dataLoader.d.ts +6 -17
- package/types/storages/inLocalStorage/SplitsCacheInLocal.d.ts +7 -2
- package/types/storages/inMemory/SplitsCacheInMemory.d.ts +1 -2
- package/types/storages/inMemory/UniqueKeysCacheInMemory.d.ts +2 -3
- package/types/storages/inRedis/SplitsCacheInRedis.d.ts +1 -2
- package/types/storages/pluggable/SplitsCachePluggable.d.ts +1 -2
- package/types/storages/pluggable/inMemoryWrapper.d.ts +1 -2
- package/types/storages/types.d.ts +7 -5
- package/types/sync/polling/updaters/splitChangesUpdater.d.ts +1 -2
- package/types/sync/submitters/types.d.ts +3 -4
- package/types/types.d.ts +9 -17
- package/types/utils/LRUCache/index.d.ts +1 -2
- package/types/utils/constants/browser.d.ts +0 -2
- package/types/utils/lang/objectAssign.d.ts +3 -0
- package/types/utils/lang/sets.d.ts +1 -61
- package/types/utils/settingsValidation/index.d.ts +0 -1
- package/types/utils/settingsValidation/storage/storageCS.d.ts +5 -0
- package/types/utils/settingsValidation/types.d.ts +0 -2
- package/cjs/integrations/browser.js +0 -31
- package/cjs/integrations/ga/GaToSplit.js +0 -257
- package/cjs/integrations/ga/GoogleAnalyticsToSplit.js +0 -14
- package/cjs/integrations/ga/SplitToGa.js +0 -123
- package/cjs/integrations/ga/SplitToGoogleAnalytics.js +0 -14
- package/cjs/integrations/ga/types.js +0 -2
- package/cjs/sdkClient/sdkClientMethodCSWithTT.js +0 -76
- package/cjs/utils/lang/maps.js +0 -96
- package/esm/integrations/browser.js +0 -27
- package/esm/integrations/ga/GaToSplit.js +0 -250
- package/esm/integrations/ga/GoogleAnalyticsToSplit.js +0 -10
- package/esm/integrations/ga/SplitToGa.js +0 -120
- package/esm/integrations/ga/SplitToGoogleAnalytics.js +0 -10
- package/esm/integrations/ga/types.js +0 -1
- package/esm/sdkClient/sdkClientMethodCSWithTT.js +0 -72
- package/esm/utils/lang/maps.js +0 -92
- package/src/integrations/browser.ts +0 -35
- package/src/integrations/ga/GaToSplit.ts +0 -299
- package/src/integrations/ga/GoogleAnalyticsToSplit.ts +0 -14
- package/src/integrations/ga/SplitToGa.ts +0 -135
- package/src/integrations/ga/SplitToGoogleAnalytics.ts +0 -14
- package/src/integrations/ga/autoRequire.js +0 -33
- package/src/integrations/ga/types.ts +0 -153
- package/src/sdkClient/sdkClientMethodCSWithTT.ts +0 -98
- package/src/utils/lang/maps.ts +0 -108
|
@@ -6,7 +6,6 @@ import { findLatencyIndex } from '../findLatencyIndex';
|
|
|
6
6
|
import { getTelemetryConfigStats } from '../../sync/submitters/telemetrySubmitter';
|
|
7
7
|
import { CONSUMER_MODE, STORAGE_PLUGGABLE } from '../../utils/constants';
|
|
8
8
|
import { isString, isNaNNumber } from '../../utils/lang';
|
|
9
|
-
import { _Map } from '../../utils/lang/maps';
|
|
10
9
|
import { MAX_LATENCY_BUCKET_COUNT, newBuckets } from '../inMemory/TelemetryCacheInMemory';
|
|
11
10
|
import { parseLatencyField, parseExceptionField, parseMetadata } from '../utils';
|
|
12
11
|
|
|
@@ -43,7 +42,7 @@ export class TelemetryCachePluggable implements ITelemetryCacheAsync {
|
|
|
43
42
|
return latencyKeys.length ?
|
|
44
43
|
this.wrapper.getMany(latencyKeys).then(latencies => {
|
|
45
44
|
|
|
46
|
-
const result: MultiMethodLatencies = new
|
|
45
|
+
const result: MultiMethodLatencies = new Map();
|
|
47
46
|
|
|
48
47
|
for (let i = 0; i < latencyKeys.length; i++) {
|
|
49
48
|
const field = latencyKeys[i].split('::')[1];
|
|
@@ -77,7 +76,7 @@ export class TelemetryCachePluggable implements ITelemetryCacheAsync {
|
|
|
77
76
|
return Promise.all(latencyKeys.map((latencyKey) => this.wrapper.del(latencyKey))).then(() => result);
|
|
78
77
|
}) :
|
|
79
78
|
// If latencyKeys is empty, return an empty map.
|
|
80
|
-
new
|
|
79
|
+
new Map();
|
|
81
80
|
});
|
|
82
81
|
}
|
|
83
82
|
|
|
@@ -90,7 +89,7 @@ export class TelemetryCachePluggable implements ITelemetryCacheAsync {
|
|
|
90
89
|
return exceptionKeys.length ?
|
|
91
90
|
this.wrapper.getMany(exceptionKeys).then(exceptions => {
|
|
92
91
|
|
|
93
|
-
const result: MultiMethodExceptions = new
|
|
92
|
+
const result: MultiMethodExceptions = new Map();
|
|
94
93
|
|
|
95
94
|
for (let i = 0; i < exceptionKeys.length; i++) {
|
|
96
95
|
const field = exceptionKeys[i].split('::')[1];
|
|
@@ -117,7 +116,7 @@ export class TelemetryCachePluggable implements ITelemetryCacheAsync {
|
|
|
117
116
|
return Promise.all(exceptionKeys.map((exceptionKey) => this.wrapper.del(exceptionKey))).then(() => result);
|
|
118
117
|
}) :
|
|
119
118
|
// If exceptionKeys is empty, return an empty map.
|
|
120
|
-
new
|
|
119
|
+
new Map();
|
|
121
120
|
});
|
|
122
121
|
}
|
|
123
122
|
|
|
@@ -130,7 +129,7 @@ export class TelemetryCachePluggable implements ITelemetryCacheAsync {
|
|
|
130
129
|
return configKeys.length ?
|
|
131
130
|
this.wrapper.getMany(configKeys).then(configs => {
|
|
132
131
|
|
|
133
|
-
const result: MultiConfigs = new
|
|
132
|
+
const result: MultiConfigs = new Map();
|
|
134
133
|
|
|
135
134
|
for (let i = 0; i < configKeys.length; i++) {
|
|
136
135
|
const field = configKeys[i].split('::')[1];
|
|
@@ -154,7 +153,7 @@ export class TelemetryCachePluggable implements ITelemetryCacheAsync {
|
|
|
154
153
|
return Promise.all(configKeys.map((configKey) => this.wrapper.del(configKey))).then(() => result);
|
|
155
154
|
}) :
|
|
156
155
|
// If configKeys is empty, return an empty map.
|
|
157
|
-
new
|
|
156
|
+
new Map();
|
|
158
157
|
});
|
|
159
158
|
}
|
|
160
159
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { IPluggableStorageWrapper, IUniqueKeysCacheBase } from '../types';
|
|
2
2
|
import { UniqueKeysCacheInMemory } from '../inMemory/UniqueKeysCacheInMemory';
|
|
3
|
-
import { setToArray } from '../../utils/lang/sets';
|
|
4
3
|
import { DEFAULT_CACHE_SIZE, REFRESH_RATE } from '../inRedis/constants';
|
|
5
4
|
import { LOG_PREFIX } from './constants';
|
|
6
5
|
import { ILogger } from '../../logger/types';
|
|
@@ -28,7 +27,7 @@ export class UniqueKeysCachePluggable extends UniqueKeysCacheInMemory implements
|
|
|
28
27
|
if (!featureNames.length) return Promise.resolve(false);
|
|
29
28
|
|
|
30
29
|
const uniqueKeysArray = featureNames.map((featureName) => {
|
|
31
|
-
const featureKeys =
|
|
30
|
+
const featureKeys = Array.from(this.uniqueKeysTracker[featureName]);
|
|
32
31
|
const uniqueKeysPayload = {
|
|
33
32
|
f: featureName,
|
|
34
33
|
ks: featureKeys
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { IPluggableStorageWrapper } from '../types';
|
|
2
2
|
import { startsWith, toNumber } from '../../utils/lang';
|
|
3
|
-
import { ISet, setToArray, _Set } from '../../utils/lang/sets';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Creates a IPluggableStorageWrapper implementation that stores items in memory.
|
|
@@ -9,9 +8,9 @@ import { ISet, setToArray, _Set } from '../../utils/lang/sets';
|
|
|
9
8
|
*
|
|
10
9
|
* @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves immediately.
|
|
11
10
|
*/
|
|
12
|
-
export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWrapper & { _cache: Record<string, string | string[] |
|
|
11
|
+
export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWrapper & { _cache: Record<string, string | string[] | Set<string>>, _setConnDelay(connDelay: number): void } {
|
|
13
12
|
|
|
14
|
-
let _cache: Record<string, string | string[] |
|
|
13
|
+
let _cache: Record<string, string | string[] | Set<string>> = {};
|
|
15
14
|
let _connDelay = connDelay;
|
|
16
15
|
|
|
17
16
|
return {
|
|
@@ -84,22 +83,22 @@ export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWra
|
|
|
84
83
|
itemContains(key: string, item: string) {
|
|
85
84
|
const set = _cache[key];
|
|
86
85
|
if (!set) return Promise.resolve(false);
|
|
87
|
-
if (set instanceof
|
|
86
|
+
if (set instanceof Set) return Promise.resolve(set.has(item));
|
|
88
87
|
return Promise.reject('key is not a set');
|
|
89
88
|
},
|
|
90
89
|
addItems(key: string, items: string[]) {
|
|
91
|
-
if (!(key in _cache)) _cache[key] = new
|
|
90
|
+
if (!(key in _cache)) _cache[key] = new Set();
|
|
92
91
|
const set = _cache[key];
|
|
93
|
-
if (set instanceof
|
|
92
|
+
if (set instanceof Set) {
|
|
94
93
|
items.forEach(item => set.add(item));
|
|
95
94
|
return Promise.resolve();
|
|
96
95
|
}
|
|
97
96
|
return Promise.reject('key is not a set');
|
|
98
97
|
},
|
|
99
98
|
removeItems(key: string, items: string[]) {
|
|
100
|
-
if (!(key in _cache)) _cache[key] = new
|
|
99
|
+
if (!(key in _cache)) _cache[key] = new Set();
|
|
101
100
|
const set = _cache[key];
|
|
102
|
-
if (set instanceof
|
|
101
|
+
if (set instanceof Set) {
|
|
103
102
|
items.forEach(item => set.delete(item));
|
|
104
103
|
return Promise.resolve();
|
|
105
104
|
}
|
|
@@ -108,7 +107,7 @@ export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWra
|
|
|
108
107
|
getItems(key: string) {
|
|
109
108
|
const set = _cache[key];
|
|
110
109
|
if (!set) return Promise.resolve([]);
|
|
111
|
-
if (set instanceof
|
|
110
|
+
if (set instanceof Set) return Promise.resolve(Array.from(set));
|
|
112
111
|
return Promise.reject('key is not a set');
|
|
113
112
|
},
|
|
114
113
|
|
package/src/storages/types.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { MaybeThenable, ISplit, IMySegmentsResponse } from '../dtos/types';
|
|
|
2
2
|
import { MySegmentsData } from '../sync/polling/types';
|
|
3
3
|
import { EventDataType, HttpErrors, HttpLatencies, ImpressionDataType, LastSync, Method, MethodExceptions, MethodLatencies, MultiMethodExceptions, MultiMethodLatencies, MultiConfigs, OperationType, StoredEventWithMetadata, StoredImpressionWithMetadata, StreamingEvent, UniqueKeysPayloadCs, UniqueKeysPayloadSs, TelemetryUsageStatsPayload, UpdatesFromSSEEnum } from '../sync/submitters/types';
|
|
4
4
|
import { SplitIO, ImpressionDTO, ISettings } from '../types';
|
|
5
|
-
import { ISet } from '../utils/lang/sets';
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Interface of a pluggable storage wrapper.
|
|
@@ -208,8 +207,10 @@ export interface ISplitsCacheBase {
|
|
|
208
207
|
// only for Client-Side. Returns true if the storage is not synchronized yet (getChangeNumber() === -1) or contains a FF using segments or large segments
|
|
209
208
|
usesSegments(): MaybeThenable<boolean>,
|
|
210
209
|
clear(): MaybeThenable<boolean | void>,
|
|
210
|
+
// should never reject or throw an exception. Instead return false by default, to avoid emitting SDK_READY_FROM_CACHE.
|
|
211
|
+
checkCache(): MaybeThenable<boolean>,
|
|
211
212
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): MaybeThenable<boolean>,
|
|
212
|
-
getNamesByFlagSets(flagSets: string[]): MaybeThenable<
|
|
213
|
+
getNamesByFlagSets(flagSets: string[]): MaybeThenable<Set<string>[]>
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
export interface ISplitsCacheSync extends ISplitsCacheBase {
|
|
@@ -224,8 +225,9 @@ export interface ISplitsCacheSync extends ISplitsCacheBase {
|
|
|
224
225
|
trafficTypeExists(trafficType: string): boolean,
|
|
225
226
|
usesSegments(): boolean,
|
|
226
227
|
clear(): void,
|
|
228
|
+
checkCache(): boolean,
|
|
227
229
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): boolean,
|
|
228
|
-
getNamesByFlagSets(flagSets: string[]):
|
|
230
|
+
getNamesByFlagSets(flagSets: string[]): Set<string>[]
|
|
229
231
|
}
|
|
230
232
|
|
|
231
233
|
export interface ISplitsCacheAsync extends ISplitsCacheBase {
|
|
@@ -240,8 +242,9 @@ export interface ISplitsCacheAsync extends ISplitsCacheBase {
|
|
|
240
242
|
trafficTypeExists(trafficType: string): Promise<boolean>,
|
|
241
243
|
usesSegments(): Promise<boolean>,
|
|
242
244
|
clear(): Promise<boolean | void>,
|
|
245
|
+
checkCache(): Promise<boolean>,
|
|
243
246
|
killLocally(name: string, defaultTreatment: string, changeNumber: number): Promise<boolean>,
|
|
244
|
-
getNamesByFlagSets(flagSets: string[]): Promise<
|
|
247
|
+
getNamesByFlagSets(flagSets: string[]): Promise<Set<string>[]>
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
/** Segments cache */
|
|
@@ -491,6 +494,8 @@ export interface IStorageAsync extends IStorageBase<
|
|
|
491
494
|
|
|
492
495
|
/** StorageFactory */
|
|
493
496
|
|
|
497
|
+
export type DataLoader = (storage: IStorageSync, matchingKey: string) => void
|
|
498
|
+
|
|
494
499
|
export interface IStorageFactoryParams {
|
|
495
500
|
settings: ISettings,
|
|
496
501
|
/**
|
|
@@ -498,7 +503,6 @@ export interface IStorageFactoryParams {
|
|
|
498
503
|
* It is meant for emitting SDK_READY event in consumer mode, and waiting before using the storage in the synchronizer.
|
|
499
504
|
*/
|
|
500
505
|
onReadyCb: (error?: any) => void,
|
|
501
|
-
onReadyFromCacheCb: (error?: any) => void,
|
|
502
506
|
}
|
|
503
507
|
|
|
504
508
|
export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';
|
|
@@ -7,7 +7,7 @@ import { syncTaskFactory } from '../../syncTask';
|
|
|
7
7
|
import { ISyncTask } from '../../types';
|
|
8
8
|
import { ISettings } from '../../../types';
|
|
9
9
|
import { CONTROL } from '../../../utils/constants';
|
|
10
|
-
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
|
|
10
|
+
import { SDK_SPLITS_ARRIVED, SDK_SEGMENTS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
|
|
11
11
|
import { SYNC_OFFLINE_DATA, ERROR_SYNC_OFFLINE_LOADING } from '../../../logger/constants';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -60,8 +60,12 @@ export function fromObjectUpdaterFactory(
|
|
|
60
60
|
|
|
61
61
|
if (startingUp) {
|
|
62
62
|
startingUp = false;
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
Promise.resolve(splitsCache.checkCache()).then(cacheReady => {
|
|
64
|
+
// Emits SDK_READY_FROM_CACHE
|
|
65
|
+
if (cacheReady) readiness.splits.emit(SDK_SPLITS_CACHE_LOADED);
|
|
66
|
+
// Emits SDK_READY
|
|
67
|
+
readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
|
|
68
|
+
});
|
|
65
69
|
}
|
|
66
70
|
return true;
|
|
67
71
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { splitsSyncTaskFactory } from './syncTasks/splitsSyncTask';
|
|
2
2
|
import { segmentsSyncTaskFactory } from './syncTasks/segmentsSyncTask';
|
|
3
3
|
import { IPollingManager, ISegmentsSyncTask, ISplitsSyncTask } from './types';
|
|
4
|
-
import { thenable } from '../../utils/promise/thenable';
|
|
5
4
|
import { POLLING_START, POLLING_STOP, LOG_PREFIX_SYNC_POLLING } from '../../logger/constants';
|
|
6
5
|
import { ISdkFactoryContextSync } from '../../sdkFactory/types';
|
|
7
6
|
|
|
@@ -29,9 +28,9 @@ export function pollingManagerSSFactory(
|
|
|
29
28
|
log.debug(LOG_PREFIX_SYNC_POLLING + `Segments will be refreshed each ${settings.scheduler.segmentsRefreshRate} millis`);
|
|
30
29
|
|
|
31
30
|
const startingUp = splitsSyncTask.start();
|
|
32
|
-
if (
|
|
31
|
+
if (startingUp) {
|
|
33
32
|
startingUp.then(() => {
|
|
34
|
-
segmentsSyncTask.start();
|
|
33
|
+
if (splitsSyncTask.isRunning()) segmentsSyncTask.start();
|
|
35
34
|
});
|
|
36
35
|
}
|
|
37
36
|
},
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { _Set, setToArray, ISet } from '../../../utils/lang/sets';
|
|
2
1
|
import { ISegmentsCacheBase, ISplitsCacheBase } from '../../../storages/types';
|
|
3
2
|
import { ISplitChangesFetcher } from '../fetchers/types';
|
|
4
3
|
import { ISplit, ISplitChangesResponse, ISplitFiltersValidation } from '../../../dtos/types';
|
|
5
4
|
import { ISplitsEventEmitter } from '../../../readiness/types';
|
|
6
5
|
import { timeout } from '../../../utils/promise/timeout';
|
|
7
|
-
import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
|
|
6
|
+
import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/constants';
|
|
8
7
|
import { ILogger } from '../../../logger/types';
|
|
9
8
|
import { SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
|
|
10
9
|
import { startsWith } from '../../../utils/lang';
|
|
@@ -27,8 +26,8 @@ function checkAllSegmentsExist(segments: ISegmentsCacheBase): Promise<boolean> {
|
|
|
27
26
|
* Collect segments from a raw split definition.
|
|
28
27
|
* Exported for testing purposes.
|
|
29
28
|
*/
|
|
30
|
-
export function parseSegments({ conditions }: ISplit):
|
|
31
|
-
let segments = new
|
|
29
|
+
export function parseSegments({ conditions }: ISplit): Set<string> {
|
|
30
|
+
let segments = new Set<string>();
|
|
32
31
|
|
|
33
32
|
for (let i = 0; i < conditions.length; i++) {
|
|
34
33
|
const matchers = conditions[i].matcherGroup.matchers;
|
|
@@ -74,7 +73,7 @@ function matchFilters(featureFlag: ISplit, filters: ISplitFiltersValidation) {
|
|
|
74
73
|
* Exported for testing purposes.
|
|
75
74
|
*/
|
|
76
75
|
export function computeSplitsMutation(entries: ISplit[], filters: ISplitFiltersValidation): ISplitMutations {
|
|
77
|
-
const segments = new
|
|
76
|
+
const segments = new Set<string>();
|
|
78
77
|
const computed = entries.reduce((accum, split) => {
|
|
79
78
|
if (split.status === 'ACTIVE' && matchFilters(split, filters)) {
|
|
80
79
|
accum.added.push([split.name, split]);
|
|
@@ -89,7 +88,7 @@ export function computeSplitsMutation(entries: ISplit[], filters: ISplitFiltersV
|
|
|
89
88
|
return accum;
|
|
90
89
|
}, { added: [], removed: [], segments: [] } as ISplitMutations);
|
|
91
90
|
|
|
92
|
-
computed.segments =
|
|
91
|
+
computed.segments = Array.from(segments);
|
|
93
92
|
|
|
94
93
|
return computed;
|
|
95
94
|
}
|
|
@@ -153,8 +152,7 @@ export function splitChangesUpdaterFactory(
|
|
|
153
152
|
*/
|
|
154
153
|
function _splitChangesUpdater(since: number, retry = 0): Promise<boolean> {
|
|
155
154
|
log.debug(SYNC_SPLITS_FETCH, [since]);
|
|
156
|
-
|
|
157
|
-
return Promise.resolve(splitUpdateNotification ?
|
|
155
|
+
const fetcherPromise = Promise.resolve(splitUpdateNotification ?
|
|
158
156
|
{ splits: [splitUpdateNotification.payload], till: splitUpdateNotification.changeNumber } :
|
|
159
157
|
splitChangesFetcher(since, noCache, till, _promiseDecorator)
|
|
160
158
|
)
|
|
@@ -201,6 +199,15 @@ export function splitChangesUpdaterFactory(
|
|
|
201
199
|
}
|
|
202
200
|
return false;
|
|
203
201
|
});
|
|
202
|
+
|
|
203
|
+
// After triggering the requests, if we have cached splits information let's notify that to emit SDK_READY_FROM_CACHE.
|
|
204
|
+
// Wrapping in a promise since checkCache can be async.
|
|
205
|
+
if (splitsEventEmitter && startingUp) {
|
|
206
|
+
Promise.resolve(splits.checkCache()).then(isCacheReady => {
|
|
207
|
+
if (isCacheReady) splitsEventEmitter.emit(SDK_SPLITS_CACHE_LOADED);
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
return fetcherPromise;
|
|
204
211
|
}
|
|
205
212
|
|
|
206
213
|
let sincePromise = Promise.resolve(splits.getChangeNumber()); // `getChangeNumber` never rejects or throws error
|
|
@@ -13,7 +13,6 @@ function Uint8ArrayToString(myUint8Arr: Uint8Array) { // @ts-ignore
|
|
|
13
13
|
|
|
14
14
|
function StringToUint8Array(myString: string) {
|
|
15
15
|
const charCodes = myString.split('').map((e) => e.charCodeAt(0));
|
|
16
|
-
// eslint-disable-next-line compat/compat
|
|
17
16
|
return new Uint8Array(charCodes);
|
|
18
17
|
}
|
|
19
18
|
|
|
@@ -15,7 +15,6 @@ import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NONRETRYABLE_ERROR,
|
|
|
15
15
|
import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE, STREAMING_PARSING_SPLIT_UPDATE } from '../../logger/constants';
|
|
16
16
|
import { IMembershipMSUpdateData, IMembershipLSUpdateData, KeyList, UpdateStrategy } from './SSEHandler/types';
|
|
17
17
|
import { getDelay, isInBitmap, parseBitmap, parseFFUpdatePayload, parseKeyList } from './parseUtils';
|
|
18
|
-
import { ISet, _Set } from '../../utils/lang/sets';
|
|
19
18
|
import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
|
|
20
19
|
import { IAuthTokenPushEnabled } from './AuthClient/types';
|
|
21
20
|
import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
|
|
@@ -254,11 +253,11 @@ export function pushManagerFactory(
|
|
|
254
253
|
return;
|
|
255
254
|
}
|
|
256
255
|
case UpdateStrategy.KeyList: {
|
|
257
|
-
let keyList: KeyList, added:
|
|
256
|
+
let keyList: KeyList, added: Set<string>, removed: Set<string>;
|
|
258
257
|
try {
|
|
259
258
|
keyList = parseKeyList(parsedData.d!, parsedData.c!);
|
|
260
|
-
added = new
|
|
261
|
-
removed = new
|
|
259
|
+
added = new Set(keyList.a);
|
|
260
|
+
removed = new Set(keyList.r);
|
|
262
261
|
} catch (e) {
|
|
263
262
|
log.warn(STREAMING_PARSING_MEMBERSHIPS_UPDATE, ['KeyList', e]);
|
|
264
263
|
break;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-use-before-define */
|
|
2
2
|
import { IMetadata } from '../../dtos/types';
|
|
3
3
|
import { SplitIO } from '../../types';
|
|
4
|
-
import { IMap } from '../../utils/lang/maps';
|
|
5
4
|
import { ISyncTask } from '../types';
|
|
6
5
|
|
|
7
6
|
export type ImpressionsPayload = {
|
|
@@ -88,11 +87,11 @@ export type StoredEventWithMetadata = {
|
|
|
88
87
|
e: SplitIO.EventData
|
|
89
88
|
}
|
|
90
89
|
|
|
91
|
-
export type MultiMethodLatencies =
|
|
90
|
+
export type MultiMethodLatencies = Map<string, MethodLatencies>
|
|
92
91
|
|
|
93
|
-
export type MultiMethodExceptions =
|
|
92
|
+
export type MultiMethodExceptions = Map<string, MethodExceptions>
|
|
94
93
|
|
|
95
|
-
export type MultiConfigs =
|
|
94
|
+
export type MultiConfigs = Map<string, TelemetryConfigStats>
|
|
96
95
|
|
|
97
96
|
/**
|
|
98
97
|
* Telemetry usage stats
|
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ISplitFiltersValidation } from './dtos/types';
|
|
2
2
|
import { IIntegration, IIntegrationFactoryParams } from './integrations/types';
|
|
3
3
|
import { ILogger } from './logger/types';
|
|
4
4
|
import { ISdkFactoryContext } from './sdkFactory/types';
|
|
@@ -71,7 +71,6 @@ export interface ISettings {
|
|
|
71
71
|
readonly core: {
|
|
72
72
|
authorizationKey: string,
|
|
73
73
|
key: SplitIO.SplitKey,
|
|
74
|
-
trafficType?: string,
|
|
75
74
|
labelsEnabled: boolean,
|
|
76
75
|
IPAddressesEnabled: boolean
|
|
77
76
|
},
|
|
@@ -98,7 +97,6 @@ export interface ISettings {
|
|
|
98
97
|
eventsFirstPushWindow: number
|
|
99
98
|
},
|
|
100
99
|
readonly storage: IStorageSyncFactory | IStorageAsyncFactory,
|
|
101
|
-
readonly preloadedData?: SplitIO.PreloadedData,
|
|
102
100
|
readonly integrations: Array<{
|
|
103
101
|
readonly type: string,
|
|
104
102
|
(params: IIntegrationFactoryParams): IIntegration | void
|
|
@@ -772,20 +770,21 @@ export namespace SplitIO {
|
|
|
772
770
|
* If this value is older than 10 days ago (expiration time policy), the data is not used to update the storage content.
|
|
773
771
|
* @TODO configurable expiration time policy?
|
|
774
772
|
*/
|
|
775
|
-
|
|
773
|
+
lastUpdated: number,
|
|
776
774
|
/**
|
|
777
775
|
* Change number of the preloaded data.
|
|
778
776
|
* If this value is older than the current changeNumber at the storage, the data is not used to update the storage content.
|
|
779
777
|
*/
|
|
780
778
|
since: number,
|
|
781
779
|
/**
|
|
782
|
-
*
|
|
783
|
-
* @TODO rename to flags
|
|
780
|
+
* Map of feature flags to their stringified definitions.
|
|
784
781
|
*/
|
|
785
|
-
splitsData:
|
|
782
|
+
splitsData: {
|
|
783
|
+
[splitName: string]: string
|
|
784
|
+
},
|
|
786
785
|
/**
|
|
787
786
|
* Optional map of user keys to their list of segments.
|
|
788
|
-
* @TODO
|
|
787
|
+
* @TODO remove when releasing first version
|
|
789
788
|
*/
|
|
790
789
|
mySegmentsData?: {
|
|
791
790
|
[key: string]: string[]
|
|
@@ -793,10 +792,9 @@ export namespace SplitIO {
|
|
|
793
792
|
/**
|
|
794
793
|
* Optional map of segments to their stringified definitions.
|
|
795
794
|
* This property is ignored if `mySegmentsData` was provided.
|
|
796
|
-
* @TODO rename to segments
|
|
797
795
|
*/
|
|
798
796
|
segmentsData?: {
|
|
799
|
-
[segmentName: string]: string
|
|
797
|
+
[segmentName: string]: string
|
|
800
798
|
},
|
|
801
799
|
}
|
|
802
800
|
/**
|
|
@@ -924,12 +922,6 @@ export namespace SplitIO {
|
|
|
924
922
|
* @property {SplitKey} key
|
|
925
923
|
*/
|
|
926
924
|
key: SplitKey,
|
|
927
|
-
/**
|
|
928
|
-
* Traffic type associated with the customer identifier. @see {@link https://help.split.io/hc/en-us/articles/360019916311-Traffic-type}
|
|
929
|
-
* If no provided as a setting it will be required on the client.track() calls.
|
|
930
|
-
* @property {string} trafficType
|
|
931
|
-
*/
|
|
932
|
-
trafficType?: string,
|
|
933
925
|
/**
|
|
934
926
|
* Disable labels from being sent to Split backend. Labels may contain sensitive information.
|
|
935
927
|
* @property {boolean} labelsEnabled
|
|
@@ -1038,10 +1030,9 @@ export namespace SplitIO {
|
|
|
1038
1030
|
* Returns a shared client of the SDK, with the given key and optional traffic type.
|
|
1039
1031
|
* @function client
|
|
1040
1032
|
* @param {SplitKey} key The key for the new client instance.
|
|
1041
|
-
* @param {string=} trafficType The traffic type of the provided key.
|
|
1042
1033
|
* @returns {ICsClient} The client instance.
|
|
1043
1034
|
*/
|
|
1044
|
-
client(key: SplitKey
|
|
1035
|
+
client(key: SplitKey): ICsClient,
|
|
1045
1036
|
/**
|
|
1046
1037
|
* Returns a manager instance of the SDK to explore available information.
|
|
1047
1038
|
* @function manager
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { IMap, _Map } from '../lang/maps';
|
|
2
1
|
import { LinkedList, Node } from './LinkedList';
|
|
3
2
|
|
|
4
3
|
export class LRUCache<K, V> {
|
|
5
4
|
maxLen: number;
|
|
6
|
-
items:
|
|
5
|
+
items: Map<K, Node<{ key: K, value: V }>>;
|
|
7
6
|
lru: LinkedList<{ key: K, value: V }>;
|
|
8
7
|
|
|
9
8
|
constructor(maxSize?: number) {
|
|
10
9
|
this.maxLen = maxSize || 1;
|
|
11
|
-
this.items = new
|
|
10
|
+
this.items = new Map();
|
|
12
11
|
this.lru = new LinkedList();
|
|
13
12
|
}
|
|
14
13
|
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
// Integration types
|
|
2
|
-
export const GOOGLE_ANALYTICS_TO_SPLIT = 'GOOGLE_ANALYTICS_TO_SPLIT';
|
|
3
|
-
export const SPLIT_TO_GOOGLE_ANALYTICS = 'SPLIT_TO_GOOGLE_ANALYTICS';
|
|
4
|
-
|
|
5
1
|
// This value might be eventually set via a config parameter
|
|
6
2
|
export const DEFAULT_CACHE_EXPIRATION_IN_MILLIS = 864000000; // 10 days
|
package/src/utils/lang/index.ts
CHANGED
|
@@ -122,10 +122,9 @@ export function isBoolean(val: any): boolean {
|
|
|
122
122
|
*/
|
|
123
123
|
export function isFiniteNumber(val: any): boolean {
|
|
124
124
|
if (val instanceof Number) val = val.valueOf();
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
return false;
|
|
125
|
+
return typeof val === 'number' ?
|
|
126
|
+
Number.isFinite ? Number.isFinite(val) : isFinite(val) :
|
|
127
|
+
false;
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
/**
|
|
@@ -134,9 +133,9 @@ export function isFiniteNumber(val: any): boolean {
|
|
|
134
133
|
*/
|
|
135
134
|
export function isIntegerNumber(val: any): boolean {
|
|
136
135
|
if (val instanceof Number) val = val.valueOf();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
136
|
+
return typeof val === 'number' ?
|
|
137
|
+
Number.isInteger ? Number.isInteger(val) : isFinite(val) && Math.floor(val) === val :
|
|
138
|
+
false;
|
|
140
139
|
}
|
|
141
140
|
|
|
142
141
|
/**
|
|
@@ -1,71 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
the ESM build of the SDK with tools that doesn't support CommonJS by default (e.g. Rollup).
|
|
5
|
-
|
|
6
|
-
object-assign
|
|
7
|
-
(c) Sindre Sorhus
|
|
8
|
-
@license MIT
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/* eslint-disable */
|
|
12
|
-
// @ts-nocheck
|
|
13
|
-
|
|
14
|
-
var getOwnPropertySymbols = Object.getOwnPropertySymbols;
|
|
15
|
-
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
16
|
-
var propIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
17
|
-
|
|
18
|
-
function toObject(val) {
|
|
19
|
-
if (val === null || val === undefined) {
|
|
20
|
-
throw new TypeError('Object.assign cannot be called with null or undefined');
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return Object(val);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function shouldUseNative() {
|
|
27
|
-
try {
|
|
28
|
-
if (!Object.assign) {
|
|
29
|
-
return false;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Detect buggy property enumeration order in older V8 versions.
|
|
33
|
-
|
|
34
|
-
// https://bugs.chromium.org/p/v8/issues/detail?id=4118
|
|
35
|
-
var test1 = new String('abc');
|
|
36
|
-
test1[5] = 'de';
|
|
37
|
-
if (Object.getOwnPropertyNames(test1)[0] === '5') {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
|
42
|
-
var test2 = {};
|
|
43
|
-
for (var i = 0; i < 10; i++) {
|
|
44
|
-
test2['_' + String.fromCharCode(i)] = i;
|
|
45
|
-
}
|
|
46
|
-
var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
|
|
47
|
-
return test2[n];
|
|
48
|
-
});
|
|
49
|
-
if (order2.join('') !== '0123456789') {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// https://bugs.chromium.org/p/v8/issues/detail?id=3056
|
|
54
|
-
var test3 = {};
|
|
55
|
-
'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
|
|
56
|
-
test3[letter] = letter;
|
|
57
|
-
});
|
|
58
|
-
if (Object.keys(Object.assign({}, test3)).join('') !==
|
|
59
|
-
'abcdefghijklmnopqrst') {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return true;
|
|
64
|
-
} catch (err) {
|
|
65
|
-
// We don't expect any of the above to throw, but better to be safe.
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* A tiny polyfill for Object.assign
|
|
3
|
+
*/
|
|
69
4
|
|
|
70
5
|
// https://www.npmjs.com/package/@types/object-assign
|
|
71
6
|
type ObjectAssign = (<T, U>(target: T, source: U) => T & U) &
|
|
@@ -74,31 +9,17 @@ type ObjectAssign = (<T, U>(target: T, source: U) => T & U) &
|
|
|
74
9
|
(<T, U, V, W, Q>(target: T, source1: U, source2: V, source3: W, source4: Q) => T & U & V & W & Q) &
|
|
75
10
|
(<T, U, V, W, Q, R>(target: T, source1: U, source2: V, source3: W, source4: Q, source5: R) => T & U & V & W & Q & R) &
|
|
76
11
|
((target: any, ...sources: any[]) => any);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
87
|
-
for (var key in from) {
|
|
88
|
-
if (hasOwnProperty.call(from, key)) {
|
|
89
|
-
to[key] = from[key];
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (getOwnPropertySymbols) {
|
|
94
|
-
symbols = getOwnPropertySymbols(from);
|
|
95
|
-
for (var i = 0; i < symbols.length; i++) {
|
|
96
|
-
if (propIsEnumerable.call(from, symbols[i])) {
|
|
97
|
-
to[symbols[i]] = from[symbols[i]];
|
|
98
|
-
}
|
|
12
|
+
export const objectAssign: ObjectAssign = Object.assign || function (target: any) {
|
|
13
|
+
if (target === null || target === undefined) throw new TypeError('Object.assign cannot be called with null or undefined');
|
|
14
|
+
target = Object(target);
|
|
15
|
+
|
|
16
|
+
for (let i = 1; i < arguments.length; i++) {
|
|
17
|
+
const source = Object(arguments[i]); // eslint-disable-next-line no-restricted-syntax
|
|
18
|
+
for (const key in source) {
|
|
19
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
20
|
+
target[key] = source[key];
|
|
99
21
|
}
|
|
100
22
|
}
|
|
101
23
|
}
|
|
102
|
-
|
|
103
|
-
return to;
|
|
24
|
+
return target;
|
|
104
25
|
};
|