@splitsoftware/splitio-commons 1.2.1-rc.8 → 1.3.1-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.
Files changed (98) hide show
  1. package/CHANGES.txt +17 -0
  2. package/cjs/{utils/consent.js → consent/index.js} +1 -1
  3. package/cjs/consent/sdkUserConsent.js +58 -0
  4. package/cjs/listeners/browser.js +1 -1
  5. package/cjs/logger/constants.js +3 -2
  6. package/cjs/logger/messages/info.js +1 -0
  7. package/cjs/readiness/sdkReadinessManager.js +5 -3
  8. package/cjs/sdkClient/client.js +1 -1
  9. package/cjs/sdkClient/clientCS.js +1 -1
  10. package/cjs/sdkClient/sdkClient.js +3 -3
  11. package/cjs/sdkClient/sdkClientMethodCS.js +3 -9
  12. package/cjs/sdkClient/sdkClientMethodCSWithTT.js +3 -13
  13. package/cjs/sdkFactory/index.js +3 -2
  14. package/cjs/services/splitHttpClient.js +12 -11
  15. package/cjs/storages/inRedis/RedisAdapter.js +9 -2
  16. package/cjs/sync/syncManagerOnline.js +1 -1
  17. package/cjs/trackers/impressionsTracker.js +2 -2
  18. package/cjs/utils/inputValidation/attributes.js +1 -1
  19. package/cjs/utils/lang/index.js +4 -2
  20. package/cjs/utils/lang/maps.js +16 -2
  21. package/cjs/utils/settingsValidation/index.js +21 -3
  22. package/esm/{utils/consent.js → consent/index.js} +1 -1
  23. package/esm/consent/sdkUserConsent.js +54 -0
  24. package/esm/listeners/browser.js +1 -1
  25. package/esm/logger/constants.js +1 -0
  26. package/esm/logger/messages/info.js +1 -0
  27. package/esm/readiness/sdkReadinessManager.js +5 -3
  28. package/esm/sdkClient/client.js +1 -1
  29. package/esm/sdkClient/clientCS.js +1 -1
  30. package/esm/sdkClient/sdkClient.js +3 -3
  31. package/esm/sdkClient/sdkClientMethodCS.js +3 -9
  32. package/esm/sdkClient/sdkClientMethodCSWithTT.js +3 -13
  33. package/esm/sdkFactory/index.js +3 -2
  34. package/esm/services/splitHttpClient.js +12 -11
  35. package/esm/storages/inRedis/RedisAdapter.js +9 -2
  36. package/esm/sync/syncManagerOnline.js +1 -1
  37. package/esm/trackers/impressionsTracker.js +2 -2
  38. package/esm/utils/inputValidation/attributes.js +1 -1
  39. package/esm/utils/lang/index.js +4 -2
  40. package/esm/utils/lang/maps.js +14 -1
  41. package/esm/utils/settingsValidation/index.js +21 -3
  42. package/package.json +14 -2
  43. package/src/{utils/consent.ts → consent/index.ts} +1 -1
  44. package/src/consent/sdkUserConsent.ts +58 -0
  45. package/src/evaluator/parser/index.ts +1 -1
  46. package/src/evaluator/types.ts +2 -2
  47. package/src/evaluator/value/index.ts +2 -2
  48. package/src/evaluator/value/sanitize.ts +2 -2
  49. package/src/integrations/pluggable.ts +2 -2
  50. package/src/listeners/browser.ts +1 -1
  51. package/src/logger/constants.ts +1 -0
  52. package/src/logger/messages/info.ts +1 -0
  53. package/src/readiness/sdkReadinessManager.ts +7 -5
  54. package/src/sdkClient/client.ts +3 -4
  55. package/src/sdkClient/clientCS.ts +1 -1
  56. package/src/sdkClient/sdkClient.ts +4 -4
  57. package/src/sdkClient/sdkClientMethod.ts +2 -2
  58. package/src/sdkClient/sdkClientMethodCS.ts +5 -11
  59. package/src/sdkClient/sdkClientMethodCSWithTT.ts +6 -16
  60. package/src/sdkFactory/index.ts +3 -2
  61. package/src/sdkFactory/types.ts +13 -3
  62. package/src/services/splitHttpClient.ts +12 -10
  63. package/src/storages/inRedis/RedisAdapter.ts +8 -2
  64. package/src/sync/syncManagerOnline.ts +1 -1
  65. package/src/trackers/impressionsTracker.ts +4 -4
  66. package/src/types.ts +3 -3
  67. package/src/utils/inputValidation/attributes.ts +1 -2
  68. package/src/utils/lang/index.ts +7 -3
  69. package/src/utils/lang/maps.ts +15 -1
  70. package/src/utils/settingsValidation/index.ts +21 -3
  71. package/src/utils/settingsValidation/types.ts +5 -1
  72. package/types/consent/index.d.ts +2 -0
  73. package/types/consent/sdkUserConsent.d.ts +13 -0
  74. package/types/evaluator/types.d.ts +2 -2
  75. package/types/evaluator/value/index.d.ts +1 -1
  76. package/types/evaluator/value/sanitize.d.ts +1 -1
  77. package/types/logger/constants.d.ts +1 -0
  78. package/types/sdkClient/client.d.ts +2 -2
  79. package/types/sdkClient/sdkClient.d.ts +2 -2
  80. package/types/sdkClient/sdkClientMethod.d.ts +2 -2
  81. package/types/sdkClient/sdkClientMethodCS.d.ts +2 -2
  82. package/types/sdkClient/sdkClientMethodCSWithTT.d.ts +2 -2
  83. package/types/sdkFactory/types.d.ts +12 -3
  84. package/types/storages/inMemory/TelemetryCacheInMemory.d.ts +8 -10
  85. package/types/storages/inRedis/RedisAdapter.d.ts +1 -1
  86. package/types/storages/inRedis/TelemetryCacheInRedis.d.ts +21 -0
  87. package/types/storages/pluggable/TelemetryCachePluggable.d.ts +19 -1
  88. package/types/sync/submitters/telemetrySyncTask.d.ts +16 -6
  89. package/types/types.d.ts +3 -3
  90. package/types/utils/lang/index.d.ts +2 -1
  91. package/types/utils/lang/maps.d.ts +7 -0
  92. package/types/utils/settingsValidation/types.d.ts +5 -1
  93. package/cjs/sdkClient/types.js +0 -2
  94. package/cjs/sdkFactory/userConsentProps.js +0 -37
  95. package/esm/sdkClient/types.js +0 -1
  96. package/esm/sdkFactory/userConsentProps.js +0 -33
  97. package/src/sdkClient/types.ts +0 -21
  98. package/src/sdkFactory/userConsentProps.ts +0 -40
@@ -1,5 +1,4 @@
1
1
  import { clientCSDecorator } from './clientCS';
2
- import { ISdkClientFactoryParams } from './types';
3
2
  import { SplitIO } from '../types';
4
3
  import { validateKey } from '../utils/inputValidation/key';
5
4
  import { getMatching, keyParser } from '../utils/key';
@@ -8,6 +7,7 @@ import { ISyncManagerCS } from '../sync/types';
8
7
  import { objectAssign } from '../utils/lang/objectAssign';
9
8
  import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } from '../logger/constants';
10
9
  import { SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
10
+ import { ISdkFactoryContext } from '../sdkFactory/types';
11
11
 
12
12
  function buildInstanceId(key: SplitIO.SplitKey) {
13
13
  // @ts-ignore
@@ -20,18 +20,13 @@ const method = 'Client instantiation';
20
20
  * Factory of client method for the client-side API variant where TT is ignored and thus
21
21
  * clients don't have a binded TT for the track method.
22
22
  */
23
- export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?: SplitIO.SplitKey) => SplitIO.ICsClient {
23
+ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey) => SplitIO.ICsClient {
24
24
  const { storage, syncManager, sdkReadinessManager, settings: { core: { key }, startup: { readyTimeout }, log } } = params;
25
25
 
26
- // Keeping similar behaviour as in the isomorphic JS SDK: if settings key is invalid,
27
- // `false` value is used as binded key of the default client, but trafficType is ignored
28
- // @TODO handle as a non-recoverable error
29
- const validKey = validateKey(log, key, method);
30
-
31
26
  const mainClientInstance = clientCSDecorator(
32
27
  log,
33
- sdkClientFactory(params) as SplitIO.IClient, // @ts-ignore
34
- validKey
28
+ sdkClientFactory(params) as SplitIO.IClient,
29
+ key
35
30
  );
36
31
 
37
32
  const parsedDefaultKey = keyParser(key);
@@ -81,8 +76,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?
81
76
  storage: sharedStorage || storage,
82
77
  syncManager: sharedSyncManager,
83
78
  signalListener: undefined, // only the main client "destroy" method stops the signal listener
84
- sharedClient: true
85
- })) as SplitIO.IClient,
79
+ }), true) as SplitIO.IClient,
86
80
  validKey
87
81
  );
88
82
 
@@ -1,5 +1,4 @@
1
1
  import { clientCSDecorator } from './clientCS';
2
- import { ISdkClientFactoryParams } from './types';
3
2
  import { SplitIO } from '../types';
4
3
  import { validateKey } from '../utils/inputValidation/key';
5
4
  import { validateTrafficType } from '../utils/inputValidation/trafficType';
@@ -9,6 +8,7 @@ import { ISyncManagerCS } from '../sync/types';
9
8
  import { objectAssign } from '../utils/lang/objectAssign';
10
9
  import { RETRIEVE_CLIENT_DEFAULT, NEW_SHARED_CLIENT, RETRIEVE_CLIENT_EXISTING } from '../logger/constants';
11
10
  import { SDK_SEGMENTS_ARRIVED } from '../readiness/constants';
11
+ import { ISdkFactoryContext } from '../sdkFactory/types';
12
12
 
13
13
  function buildInstanceId(key: SplitIO.SplitKey, trafficType?: string) {
14
14
  // @ts-ignore
@@ -22,23 +22,14 @@ const method = 'Client instantiation';
22
22
  * where clients can have a binded TT for the track method, which is provided via the settings
23
23
  * (default client) or the client method (shared clients).
24
24
  */
25
- export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?: SplitIO.SplitKey, trafficType?: string) => SplitIO.ICsClient {
25
+ export function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey, trafficType?: string) => SplitIO.ICsClient {
26
26
  const { storage, syncManager, sdkReadinessManager, settings: { core: { key, trafficType }, startup: { readyTimeout }, log } } = params;
27
27
 
28
- // Keeping the behaviour as in the isomorphic JS SDK: if settings key or TT are invalid,
29
- // `false` value is used as binded key/TT of the default client, which leads to several issues.
30
- // @TODO update when supporting non-recoverable errors
31
- const validKey = validateKey(log, key, method);
32
- let validTrafficType;
33
- if (trafficType !== undefined) {
34
- validTrafficType = validateTrafficType(log, trafficType, method);
35
- }
36
-
37
28
  const mainClientInstance = clientCSDecorator(
38
29
  log,
39
- sdkClientFactory(params) as SplitIO.IClient, // @ts-ignore
40
- validKey,
41
- validTrafficType
30
+ sdkClientFactory(params) as SplitIO.IClient,
31
+ key,
32
+ trafficType
42
33
  );
43
34
 
44
35
  const parsedDefaultKey = keyParser(key);
@@ -95,8 +86,7 @@ export function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?
95
86
  storage: sharedStorage || storage,
96
87
  syncManager: sharedSyncManager,
97
88
  signalListener: undefined, // only the main client "destroy" method stops the signal listener
98
- sharedClient: true
99
- })) as SplitIO.IClient,
89
+ }), true) as SplitIO.IClient,
100
90
  validKey,
101
91
  validTrafficType
102
92
  );
@@ -81,7 +81,8 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
81
81
  const signalListener = SignalListener && new SignalListener(syncManager, settings, storage, splitApi);
82
82
 
83
83
  // Sdk client and manager
84
- const clientMethod = sdkClientMethodFactory({ eventTracker, impressionsTracker, sdkReadinessManager, settings, storage, syncManager, signalListener });
84
+ const ctx = { eventTracker, impressionsTracker, sdkReadinessManager, settings, storage, syncManager, signalListener };
85
+ const clientMethod = sdkClientMethodFactory(ctx);
85
86
  const managerInstance = sdkManagerFactory(log, storage.splits, sdkReadinessManager);
86
87
 
87
88
  syncManager && syncManager.start();
@@ -104,5 +105,5 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
104
105
  Logger: createLoggerAPI(settings.log),
105
106
 
106
107
  settings,
107
- }, extraProps && extraProps(settings, syncManager));
108
+ }, extraProps && extraProps(ctx));
108
109
  }
@@ -2,13 +2,23 @@ import { IIntegrationManager, IIntegrationFactoryParams } from '../integrations/
2
2
  import { ISignalListener } from '../listeners/types';
3
3
  import { ILogger } from '../logger/types';
4
4
  import { ISdkReadinessManager } from '../readiness/types';
5
- import { ISdkClientFactoryParams } from '../sdkClient/types';
6
5
  import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
7
6
  import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
8
7
  import { ISyncManager, ISyncManagerFactoryParams } from '../sync/types';
9
8
  import { IImpressionObserver } from '../trackers/impressionObserver/types';
9
+ import { IImpressionsTracker, IEventTracker } from '../trackers/types';
10
10
  import { SplitIO, ISettings, IEventEmitter } from '../types';
11
11
 
12
+ export interface ISdkFactoryContext {
13
+ storage: IStorageSync | IStorageAsync,
14
+ sdkReadinessManager: ISdkReadinessManager,
15
+ settings: ISettings
16
+ impressionsTracker: IImpressionsTracker,
17
+ eventTracker: IEventTracker,
18
+ signalListener?: ISignalListener
19
+ syncManager?: ISyncManager,
20
+ }
21
+
12
22
  /**
13
23
  * Environment related dependencies.
14
24
  * These getters are called a fixed number of times per factory instantiation.
@@ -53,7 +63,7 @@ export interface ISdkFactoryParams {
53
63
 
54
64
  // Sdk client method factory (ISDK::client method).
55
65
  // It Allows to distinguish SDK clients with the client-side API (`ICsSDK`) or server-side API (`ISDK` or `IAsyncSDK`).
56
- sdkClientMethodFactory: (params: ISdkClientFactoryParams) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
66
+ sdkClientMethodFactory: (params: ISdkFactoryContext) => ({ (): SplitIO.ICsClient; (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient; } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient))
57
67
 
58
68
  // Optional signal listener constructor. Used to handle special app states, like shutdown, app paused or resumed.
59
69
  // Pass only if `syncManager` (used by Node listener) and `splitApi` (used by Browser listener) are passed.
@@ -70,5 +80,5 @@ export interface ISdkFactoryParams {
70
80
  impressionsObserverFactory?: () => IImpressionObserver
71
81
 
72
82
  // Optional function to assign additional properties to the factory instance
73
- extraProps?: (settings: ISettings, syncManager?: ISyncManager) => object
83
+ extraProps?: (params: ISdkFactoryContext) => object
74
84
  }
@@ -14,24 +14,26 @@ const messageNoFetch = 'Global fetch API is not available.';
14
14
  */
15
15
  export function splitHttpClientFactory(settings: Pick<ISettings, 'log' | 'version' | 'runtime' | 'core'>, getFetch?: () => (IFetch | undefined), getOptions?: () => object): ISplitHttpClient {
16
16
 
17
- const { log, core: { authorizationKey }, version, runtime: { ip, hostname } } = settings;
17
+ const log = settings.log;
18
18
  const options = getOptions && getOptions();
19
19
  const fetch = getFetch && getFetch();
20
20
 
21
21
  // if fetch is not available, log Error
22
22
  if (!fetch) log.error(ERROR_CLIENT_CANNOT_GET_READY, [messageNoFetch]);
23
23
 
24
- const headers: Record<string, string> = {
25
- 'Accept': 'application/json',
26
- 'Content-Type': 'application/json',
27
- 'Authorization': `Bearer ${authorizationKey}`,
28
- 'SplitSDKVersion': version
29
- };
24
+ return function httpClient(url: string, reqOpts: IRequestOptions = {}, logErrorsAsInfo: boolean = false): Promise<IResponse> {
30
25
 
31
- if (ip) headers['SplitSDKMachineIP'] = ip;
32
- if (hostname) headers['SplitSDKMachineName'] = hostname;
26
+ const { core: { authorizationKey }, version, runtime: { ip, hostname } } = settings;
33
27
 
34
- return function httpClient(url: string, reqOpts: IRequestOptions = {}, logErrorsAsInfo: boolean = false): Promise<IResponse> {
28
+ const headers: Record<string, string> = {
29
+ 'Accept': 'application/json',
30
+ 'Content-Type': 'application/json',
31
+ 'Authorization': `Bearer ${authorizationKey}`,
32
+ 'SplitSDKVersion': version
33
+ };
34
+
35
+ if (ip) headers['SplitSDKMachineIP'] = ip;
36
+ if (hostname) headers['SplitSDKMachineName'] = hostname;
35
37
 
36
38
  const request = objectAssign({
37
39
  headers: reqOpts.headers ? objectAssign({}, headers, reqOpts.headers) : headers,
@@ -164,6 +164,12 @@ export class RedisAdapter extends ioredis {
164
164
  } else { // If it IS the string URL, that'll be the first param for ioredis.
165
165
  result.unshift(options.url);
166
166
  }
167
+ if (options.connectionTimeout) {
168
+ merge(opts, { connectTimeout: options.connectionTimeout });
169
+ }
170
+ if (options.tls) {
171
+ merge(opts, { tls: options.tls });
172
+ }
167
173
 
168
174
  return result;
169
175
  }
@@ -171,9 +177,9 @@ export class RedisAdapter extends ioredis {
171
177
  /**
172
178
  * Parses the options into what we care about.
173
179
  */
174
- static _defineOptions({ connectionTimeout, operationTimeout, url, host, port, db, pass }: Record<string, any>) {
180
+ static _defineOptions({ connectionTimeout, operationTimeout, url, host, port, db, pass, tls }: Record<string, any>) {
175
181
  const parsedOptions = {
176
- connectionTimeout, operationTimeout, url, host, port, db, pass
182
+ connectionTimeout, operationTimeout, url, host, port, db, pass, tls
177
183
  };
178
184
 
179
185
  return merge({}, DEFAULT_OPTIONS, parsedOptions);
@@ -6,7 +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 '../utils/consent';
9
+ import { isConsentGranted } from '../consent';
10
10
 
11
11
  /**
12
12
  * Online SyncManager factory.
@@ -28,7 +28,7 @@ export function impressionsTrackerFactory(
28
28
  countsCache?: IImpressionCountsCacheSync
29
29
  ): IImpressionsTracker {
30
30
 
31
- const { log, impressionListener, runtime: { ip, hostname }, version } = settings;
31
+ const { log, impressionListener, runtime: { ip, hostname } } = settings;
32
32
 
33
33
  return {
34
34
  track(impressions: ImpressionDTO[], attributes?: SplitIO.Attributes) {
@@ -74,9 +74,9 @@ export function impressionsTrackerFactory(
74
74
  // copy of impression, to avoid unexpected behaviour if modified by integrations or impressionListener
75
75
  impression: objectAssign({}, impressions[i]),
76
76
  attributes,
77
- ip: ip as string,
78
- hostname: hostname as string,
79
- sdkLanguageVersion: version
77
+ ip,
78
+ hostname,
79
+ sdkLanguageVersion: settings.version
80
80
  };
81
81
 
82
82
  // Wrap in a timeout because we don't want it to be blocking.
package/src/types.ts CHANGED
@@ -398,7 +398,7 @@ interface IBasicClient extends IStatusInterface {
398
398
 
399
399
  // Whether the client implements the client-side API, i.e, with bound key, (true), or the server-side API (false).
400
400
  // Exposed for internal purposes only. Not considered part of the public API, and might be renamed eventually.
401
- isBrowserClient: boolean
401
+ isClientSide: boolean
402
402
  }
403
403
  /**
404
404
  * Common definitions between SDK instances for different environments interface.
@@ -535,8 +535,8 @@ export namespace SplitIO {
535
535
  export type ImpressionData = {
536
536
  impression: ImpressionDTO,
537
537
  attributes?: SplitIO.Attributes,
538
- ip: string,
539
- hostname: string,
538
+ ip: string| false,
539
+ hostname: string | false,
540
540
  sdkLanguageVersion: string
541
541
  };
542
542
  /**
@@ -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 (isObject(maybeAttrs) || maybeAttrs == undefined) // eslint-disable-line eqeqeq
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
  }
@@ -151,10 +151,14 @@ export function isNaNNumber(val: any): boolean {
151
151
  }
152
152
 
153
153
  /**
154
- * Validates if a value is an object with the Object prototype (map 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): boolean {
157
- return obj !== null && typeof obj === 'object' && obj.constructor === 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
  /**
@@ -79,4 +79,18 @@ interface IMapConstructor {
79
79
  readonly prototype: IMap<any, any>;
80
80
  }
81
81
 
82
- export const _Map: IMapConstructor = typeof Map !== 'undefined' ? Map : MapPoly;
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();
@@ -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
@@ -129,9 +131,25 @@ export function settingsValidation(config: unknown, validationParams: ISettingsV
129
131
  // @ts-ignore, modify readonly prop
130
132
  if (storage) withDefaults.storage = storage(withDefaults);
131
133
 
132
- // Although `key` is mandatory according to TS declaration files, it can be omitted in LOCALHOST mode. In that case, the value `localhost_key` is used.
133
- if (withDefaults.mode === LOCALHOST_MODE && withDefaults.core.key === undefined) {
134
- withDefaults.core.key = 'localhost_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
+ }
135
153
  }
136
154
 
137
155
  // Current ip/hostname information
@@ -10,7 +10,11 @@ export interface ISettingsValidationParams {
10
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
- /** Function to define runtime values (`settings.runtime`) */
13
+ /** If true, validates core.key */
14
+ acceptKey?: boolean,
15
+ /** If true, validates core.trafficType */
16
+ acceptTT?: boolean,
17
+ /** Define runtime values (`settings.runtime`) */
14
18
  runtime: (settings: ISettings) => ISettings['runtime'],
15
19
  /** Storage validator (`settings.storage`) */
16
20
  storage?: (settings: ISettings) => ISettings['storage'],
@@ -0,0 +1,2 @@
1
+ import { ISettings } from '../types';
2
+ export declare function isConsentGranted(settings: ISettings): boolean;
@@ -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: SplitIO.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: SplitIO.Attributes): string | number | boolean | (string | number)[] | import("../types").IDependencyMatcherValue | undefined;
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: SplitIO.Attributes): string | number | boolean | (string | number)[] | IDependencyMatcherValue | undefined;
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;
@@ -69,6 +69,7 @@ export declare const EVENTS_TRACKER_SUCCESS = 120;
69
69
  export declare const IMPRESSIONS_TRACKER_SUCCESS = 121;
70
70
  export declare const USER_CONSENT_UPDATED = 122;
71
71
  export declare const USER_CONSENT_NOT_UPDATED = 123;
72
+ export declare const USER_CONSENT_INITIAL = 124;
72
73
  export declare const ENGINE_VALUE_INVALID = 200;
73
74
  export declare const ENGINE_VALUE_NO_ATTRIBUTES = 201;
74
75
  export declare const CLIENT_NO_LISTENER = 202;
@@ -1,6 +1,6 @@
1
- import { IClientFactoryParams } from './types';
2
1
  import { SplitIO } from '../types';
2
+ import { ISdkFactoryContext } from '../sdkFactory/types';
3
3
  /**
4
4
  * Creator of base client with getTreatments and track methods.
5
5
  */
6
- export declare function clientFactory(params: IClientFactoryParams): SplitIO.IClient | SplitIO.IAsyncClient;
6
+ export declare function clientFactory(params: ISdkFactoryContext): SplitIO.IClient | SplitIO.IAsyncClient;
@@ -1,6 +1,6 @@
1
1
  import { SplitIO } from '../types';
2
- import { ISdkClientFactoryParams } from './types';
2
+ import { ISdkFactoryContext } from '../sdkFactory/types';
3
3
  /**
4
4
  * Creates an Sdk client, i.e., a base client with status and destroy interface
5
5
  */
6
- export declare function sdkClientFactory(params: ISdkClientFactoryParams): SplitIO.IClient | SplitIO.IAsyncClient;
6
+ export declare function sdkClientFactory(params: ISdkFactoryContext, isSharedClient?: boolean): SplitIO.IClient | SplitIO.IAsyncClient;
@@ -1,6 +1,6 @@
1
- import { ISdkClientFactoryParams } from './types';
2
1
  import { SplitIO } from '../types';
2
+ import { ISdkFactoryContext } from '../sdkFactory/types';
3
3
  /**
4
4
  * Factory of client method for server-side SDKs (ISDK and IAsyncSDK)
5
5
  */
6
- export declare function sdkClientMethodFactory(params: ISdkClientFactoryParams): () => SplitIO.IClient | SplitIO.IAsyncClient;
6
+ export declare function sdkClientMethodFactory(params: ISdkFactoryContext): () => SplitIO.IClient | SplitIO.IAsyncClient;
@@ -1,7 +1,7 @@
1
- import { ISdkClientFactoryParams } from './types';
2
1
  import { SplitIO } from '../types';
2
+ import { ISdkFactoryContext } from '../sdkFactory/types';
3
3
  /**
4
4
  * Factory of client method for the client-side API variant where TT is ignored and thus
5
5
  * clients don't have a binded TT for the track method.
6
6
  */
7
- export declare function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?: SplitIO.SplitKey) => SplitIO.ICsClient;
7
+ export declare function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey) => SplitIO.ICsClient;
@@ -1,8 +1,8 @@
1
- import { ISdkClientFactoryParams } from './types';
2
1
  import { SplitIO } from '../types';
2
+ import { ISdkFactoryContext } from '../sdkFactory/types';
3
3
  /**
4
4
  * Factory of client method for the client-side (browser) variant of the Isomorphic JS SDK,
5
5
  * where clients can have a binded TT for the track method, which is provided via the settings
6
6
  * (default client) or the client method (shared clients).
7
7
  */
8
- export declare function sdkClientMethodCSFactory(params: ISdkClientFactoryParams): (key?: SplitIO.SplitKey, trafficType?: string) => SplitIO.ICsClient;
8
+ export declare function sdkClientMethodCSFactory(params: ISdkFactoryContext): (key?: SplitIO.SplitKey, trafficType?: string) => SplitIO.ICsClient;
@@ -2,12 +2,21 @@ import { IIntegrationManager, IIntegrationFactoryParams } from '../integrations/
2
2
  import { ISignalListener } from '../listeners/types';
3
3
  import { ILogger } from '../logger/types';
4
4
  import { ISdkReadinessManager } from '../readiness/types';
5
- import { ISdkClientFactoryParams } from '../sdkClient/types';
6
5
  import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
7
6
  import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
8
7
  import { ISyncManager, ISyncManagerFactoryParams } from '../sync/types';
9
8
  import { IImpressionObserver } from '../trackers/impressionObserver/types';
9
+ import { IImpressionsTracker, IEventTracker } from '../trackers/types';
10
10
  import { SplitIO, ISettings, IEventEmitter } from '../types';
11
+ export interface ISdkFactoryContext {
12
+ storage: IStorageSync | IStorageAsync;
13
+ sdkReadinessManager: ISdkReadinessManager;
14
+ settings: ISettings;
15
+ impressionsTracker: IImpressionsTracker;
16
+ eventTracker: IEventTracker;
17
+ signalListener?: ISignalListener;
18
+ syncManager?: ISyncManager;
19
+ }
11
20
  /**
12
21
  * Environment related dependencies.
13
22
  * These getters are called a fixed number of times per factory instantiation.
@@ -28,7 +37,7 @@ export interface ISdkFactoryParams {
28
37
  splitApiFactory?: (settings: ISettings, platform: IPlatform) => ISplitApi;
29
38
  syncManagerFactory?: (params: ISyncManagerFactoryParams) => ISyncManager;
30
39
  sdkManagerFactory: (log: ILogger, splits: ISplitsCacheSync | ISplitsCacheAsync, sdkReadinessManager: ISdkReadinessManager) => SplitIO.IManager | SplitIO.IAsyncManager;
31
- sdkClientMethodFactory: (params: ISdkClientFactoryParams) => ({
40
+ sdkClientMethodFactory: (params: ISdkFactoryContext) => ({
32
41
  (): SplitIO.ICsClient;
33
42
  (key: SplitIO.SplitKey, trafficType?: string | undefined): SplitIO.ICsClient;
34
43
  } | (() => SplitIO.IClient) | (() => SplitIO.IAsyncClient));
@@ -38,5 +47,5 @@ export interface ISdkFactoryParams {
38
47
  serviceApi: ISplitApi | undefined) => ISignalListener;
39
48
  integrationsManagerFactory?: (params: IIntegrationFactoryParams) => IIntegrationManager | undefined;
40
49
  impressionsObserverFactory?: () => IImpressionObserver;
41
- extraProps?: (settings: ISettings, syncManager?: ISyncManager) => object;
50
+ extraProps?: (params: ISdkFactoryContext) => object;
42
51
  }
@@ -1,4 +1,4 @@
1
- import { ImpressionDataType, EventDataType, StreamingEvent, Method, OperationType } from '../../sync/submitters/types';
1
+ import { ImpressionDataType, EventDataType, LastSync, HttpErrors, HttpLatencies, StreamingEvent, Method, OperationType, MethodExceptions, MethodLatencies } from '../../sync/submitters/types';
2
2
  import { TelemetryCacheSync } from '../types';
3
3
  export declare class TelemetryCacheInMemory implements TelemetryCacheSync {
4
4
  private timeUntilReady?;
@@ -17,16 +17,14 @@ export declare class TelemetryCacheInMemory implements TelemetryCacheSync {
17
17
  getEventStats(type: EventDataType): number;
18
18
  recordEventStats(type: EventDataType, count: number): void;
19
19
  private lastSync;
20
- getLastSynchronization(): Record<OperationType, number | undefined>;
20
+ getLastSynchronization(): LastSync;
21
21
  recordSuccessfulSync(resource: OperationType, timeMs: number): void;
22
22
  private httpErrors;
23
- popHttpErrors(): Record<OperationType, {
24
- [statusCode: string]: number;
25
- }>;
26
- recordSyncError(resource: OperationType, status: number): void;
23
+ popHttpErrors(): HttpErrors;
24
+ recordHttpError(resource: OperationType, status: number): void;
27
25
  private httpLatencies;
28
- popHttpLatencies(): Record<OperationType, number[]>;
29
- recordSyncLatency(resource: OperationType, latencyMs: number): void;
26
+ popHttpLatencies(): HttpLatencies;
27
+ recordHttpLatency(resource: OperationType, latencyMs: number): void;
30
28
  private authRejections;
31
29
  popAuthRejections(): number;
32
30
  recordAuthRejections(): void;
@@ -43,9 +41,9 @@ export declare class TelemetryCacheInMemory implements TelemetryCacheSync {
43
41
  getSessionLength(): number | undefined;
44
42
  recordSessionLength(ms: number): void;
45
43
  private exceptions;
46
- popExceptions(): Record<Method, number>;
44
+ popExceptions(): MethodExceptions;
47
45
  recordException(method: Method): void;
48
46
  private latencies;
49
- popLatencies(): Record<Method, number[]>;
47
+ popLatencies(): MethodLatencies;
50
48
  recordLatency(method: Method, latencyMs: number): void;
51
49
  }
@@ -20,5 +20,5 @@ export declare class RedisAdapter extends ioredis {
20
20
  /**
21
21
  * Parses the options into what we care about.
22
22
  */
23
- static _defineOptions({ connectionTimeout, operationTimeout, url, host, port, db, pass }: Record<string, any>): object;
23
+ static _defineOptions({ connectionTimeout, operationTimeout, url, host, port, db, pass, tls }: Record<string, any>): object;
24
24
  }
@@ -0,0 +1,21 @@
1
+ import { ILogger } from '../../logger/types';
2
+ import { Method, MethodExceptions, MethodLatencies } from '../../sync/submitters/types';
3
+ import { KeyBuilderSS } from '../KeyBuilderSS';
4
+ import { TelemetryCacheAsync } from '../types';
5
+ import { Redis } from 'ioredis';
6
+ export declare class TelemetryCacheInRedis implements TelemetryCacheAsync {
7
+ private readonly log;
8
+ private readonly keys;
9
+ private readonly redis;
10
+ /**
11
+ * Create a Telemetry cache that uses a storage wrapper.
12
+ * @param log Logger instance.
13
+ * @param keys Key builder.
14
+ * @param redis Redis client.
15
+ */
16
+ constructor(log: ILogger, keys: KeyBuilderSS, redis: Redis);
17
+ recordLatency(method: Method, latencyMs: number): Promise<number>;
18
+ recordException(method: Method): Promise<number>;
19
+ popExceptions(): Promise<MethodExceptions>;
20
+ popLatencies(): Promise<MethodLatencies>;
21
+ }
@@ -1,2 +1,20 @@
1
- export declare class TelemetryCachePluggable {
1
+ import { ILogger } from '../../logger/types';
2
+ import { Method } from '../../sync/submitters/types';
3
+ import { KeyBuilderSS } from '../KeyBuilderSS';
4
+ import { IPluggableStorageWrapper, TelemetryCacheAsync } from '../types';
5
+ export declare class TelemetryCachePluggable implements TelemetryCacheAsync {
6
+ private readonly log;
7
+ private readonly keys;
8
+ private readonly wrapper;
9
+ /**
10
+ * Create a Telemetry cache that uses a storage wrapper.
11
+ * @param log Logger instance.
12
+ * @param keys Key builder.
13
+ * @param wrapper Adapted wrapper storage.
14
+ */
15
+ constructor(log: ILogger, keys: KeyBuilderSS, wrapper: IPluggableStorageWrapper);
16
+ recordLatency(method: Method, latencyMs: number): Promise<number>;
17
+ recordException(method: Method): Promise<number>;
18
+ popExceptions(): void;
19
+ popLatencies(): void;
2
20
  }