@splitsoftware/splitio-commons 1.0.1-rc.1 → 1.0.1-rc.5

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 (88) hide show
  1. package/cjs/evaluator/index.js +3 -4
  2. package/cjs/logger/constants.js +4 -4
  3. package/cjs/logger/messages/error.js +2 -1
  4. package/cjs/logger/messages/warn.js +0 -1
  5. package/cjs/sdkFactory/index.js +1 -1
  6. package/cjs/storages/inRedis/index.js +1 -2
  7. package/cjs/storages/pluggable/SplitsCachePluggable.js +1 -1
  8. package/cjs/storages/pluggable/constants.js +1 -1
  9. package/cjs/storages/pluggable/inMemoryWrapper.js +3 -3
  10. package/cjs/storages/pluggable/index.js +6 -6
  11. package/cjs/storages/pluggable/wrapperAdapter.js +3 -3
  12. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +1 -1
  13. package/cjs/sync/streaming/SSEClient/index.js +0 -1
  14. package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +0 -1
  15. package/cjs/utils/MinEventEmitter.js +5 -5
  16. package/cjs/utils/MinEvents.js +13 -15
  17. package/cjs/utils/constants/index.js +2 -2
  18. package/cjs/utils/env/isNode.js +4 -1
  19. package/cjs/utils/settingsValidation/storage/storageCS.js +11 -8
  20. package/esm/evaluator/index.js +3 -4
  21. package/esm/logger/constants.js +3 -3
  22. package/esm/logger/messages/error.js +2 -1
  23. package/esm/logger/messages/warn.js +0 -1
  24. package/esm/sdkFactory/index.js +1 -1
  25. package/esm/storages/inRedis/index.js +1 -2
  26. package/esm/storages/pluggable/SplitsCachePluggable.js +1 -1
  27. package/esm/storages/pluggable/constants.js +1 -1
  28. package/esm/storages/pluggable/inMemoryWrapper.js +3 -3
  29. package/esm/storages/pluggable/index.js +7 -7
  30. package/esm/storages/pluggable/wrapperAdapter.js +3 -3
  31. package/esm/sync/polling/updaters/mySegmentsUpdater.js +1 -1
  32. package/esm/sync/streaming/SSEClient/index.js +0 -1
  33. package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +0 -1
  34. package/esm/utils/MinEventEmitter.js +5 -5
  35. package/esm/utils/MinEvents.js +2 -5
  36. package/esm/utils/constants/index.js +1 -1
  37. package/esm/utils/env/isNode.js +4 -1
  38. package/esm/utils/settingsValidation/storage/storageCS.js +13 -10
  39. package/package.json +3 -4
  40. package/src/evaluator/index.ts +3 -4
  41. package/src/logger/constants.ts +3 -3
  42. package/src/logger/messages/error.ts +2 -1
  43. package/src/logger/messages/warn.ts +0 -1
  44. package/src/sdkFactory/index.ts +1 -1
  45. package/src/sdkFactory/types.ts +2 -2
  46. package/src/services/splitApi.ts +4 -1
  47. package/src/services/types.ts +16 -2
  48. package/src/storages/inRedis/index.ts +1 -1
  49. package/src/storages/pluggable/EventsCachePluggable.ts +3 -3
  50. package/src/storages/pluggable/ImpressionsCachePluggable.ts +3 -3
  51. package/src/storages/pluggable/SegmentsCachePluggable.ts +3 -3
  52. package/src/storages/pluggable/SplitsCachePluggable.ts +4 -4
  53. package/src/storages/pluggable/constants.ts +1 -1
  54. package/src/storages/pluggable/inMemoryWrapper.ts +5 -5
  55. package/src/storages/pluggable/index.ts +10 -10
  56. package/src/storages/pluggable/wrapperAdapter.ts +5 -5
  57. package/src/storages/types.ts +7 -7
  58. package/src/sync/polling/updaters/mySegmentsUpdater.ts +1 -1
  59. package/src/sync/streaming/SSEClient/index.ts +5 -5
  60. package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +0 -1
  61. package/src/trackers/impressionObserver/ImpressionObserver.ts +1 -1
  62. package/src/types.ts +10 -9
  63. package/src/utils/MinEventEmitter.ts +10 -10
  64. package/src/utils/MinEvents.ts +2 -7
  65. package/src/utils/constants/index.ts +1 -1
  66. package/src/utils/env/isNode.ts +4 -1
  67. package/src/utils/settingsValidation/storage/storageCS.ts +12 -8
  68. package/types/logger/constants.d.ts +3 -3
  69. package/types/sdkFactory/types.d.ts +2 -2
  70. package/types/services/splitApi.d.ts +1 -1
  71. package/types/services/types.d.ts +11 -0
  72. package/types/storages/pluggable/EventsCachePluggable.d.ts +2 -2
  73. package/types/storages/pluggable/ImpressionsCachePluggable.d.ts +2 -2
  74. package/types/storages/pluggable/SegmentsCachePluggable.d.ts +2 -2
  75. package/types/storages/pluggable/SplitsCachePluggable.d.ts +3 -3
  76. package/types/storages/pluggable/constants.d.ts +1 -1
  77. package/types/storages/pluggable/inMemoryWrapper.d.ts +3 -3
  78. package/types/storages/pluggable/index.d.ts +2 -2
  79. package/types/storages/pluggable/wrapperAdapter.d.ts +4 -4
  80. package/types/storages/types.d.ts +6 -6
  81. package/types/sync/streaming/SSEClient/index.d.ts +4 -3
  82. package/types/trackers/impressionObserver/ImpressionObserver.d.ts +1 -1
  83. package/types/types.d.ts +10 -10
  84. package/types/utils/MinEventEmitter.d.ts +6 -6
  85. package/types/utils/MinEvents.d.ts +3 -2
  86. package/types/utils/constants/index.d.ts +1 -1
  87. package/types/utils/env/isNode.d.ts +4 -0
  88. package/types/utils/settingsValidation/storage/storageCS.d.ts +3 -1
@@ -19,7 +19,7 @@ export function mySegmentsUpdaterFactory(log, mySegmentsFetcher, splitsCache, my
19
19
  // NOTE: We only collect metrics on startup.
20
20
  // mySegmentsPromise = tracker.start(tracker.TaskNames.MY_SEGMENTS_FETCH, startingUp ? metricCollectors : false, mySegmentsPromise);
21
21
  }
22
- // @TODO if allowing custom storages, handle async execution
22
+ // @TODO if allowing pluggable storages, handle async execution
23
23
  function updateSegments(segmentsData) {
24
24
  var shouldNotifyUpdate;
25
25
  if (Array.isArray(segmentsData)) {
@@ -32,7 +32,6 @@ var SSEClient = /** @class */ (function () {
32
32
  * @throws 'EventSource API is not available. ' if EventSource is not available.
33
33
  */
34
34
  function SSEClient(settings, useHeaders, getEventSource) {
35
- // @ts-expect-error
36
35
  this.eventSource = getEventSource && getEventSource();
37
36
  // if eventSource is not available, throw an exception
38
37
  if (!this.eventSource)
@@ -67,7 +67,6 @@ var SplitsUpdateWorker = /** @class */ (function () {
67
67
  */
68
68
  SplitsUpdateWorker.prototype.killSplit = function (_a) {
69
69
  var changeNumber = _a.changeNumber, splitName = _a.splitName, defaultTreatment = _a.defaultTreatment;
70
- // @TODO handle retry due to errors in storage, once we allow the definition of custom async storages
71
70
  if (this.splitsCache.killLocally(splitName, defaultTreatment, changeNumber)) {
72
71
  // trigger an SDK_UPDATE if Split was killed locally
73
72
  this.splitsEventEmitter.emit(SDK_SPLITS_ARRIVED, true);
@@ -33,13 +33,13 @@ var EventEmitter = /** @class */ (function () {
33
33
  EventEmitter.prototype.once = function (type, listener) {
34
34
  return this.registerListener(type, listener, true);
35
35
  };
36
- // eslint-disable-next-line
37
- EventEmitter.prototype.removeListener = function (type, listener) {
36
+ // @ts-ignore
37
+ EventEmitter.prototype.removeListener = function ( /* type: string, listener: (...args: any[]) => void */) {
38
38
  throw new Error('Method not implemented.');
39
39
  };
40
- // alias of removeListener
41
- EventEmitter.prototype.off = function (type, listener) {
42
- return this.removeListener(type, listener);
40
+ // @ts-ignore alias of removeListener
41
+ EventEmitter.prototype.off = function ( /* type: string, listener: (...args: any[]) => void */) {
42
+ return this.removeListener( /* type, listener */);
43
43
  };
44
44
  EventEmitter.prototype.emit = function (type) {
45
45
  var args = [];
@@ -35,12 +35,9 @@ var ReflectApply = R && typeof R.apply === 'function'
35
35
  : function ReflectApply(target, receiver, args) {
36
36
  return Function.prototype.apply.call(target, receiver, args);
37
37
  };
38
- function EventEmitter() {
38
+ export var EventEmitter = function EventEmitter() {
39
39
  EventEmitter.init.call(this);
40
- }
41
- export default EventEmitter;
42
- // Backwards-compat with node 0.10.x
43
- EventEmitter.EventEmitter = EventEmitter;
40
+ };
44
41
  EventEmitter.prototype._events = undefined;
45
42
  EventEmitter.prototype._eventsCount = 0;
46
43
  function checkListener(listener) {
@@ -23,4 +23,4 @@ export var CONSUMER_PARTIAL_MODE = 'consumer_partial';
23
23
  export var STORAGE_MEMORY = 'MEMORY';
24
24
  export var STORAGE_LOCALSTORAGE = 'LOCALSTORAGE';
25
25
  export var STORAGE_REDIS = 'REDIS';
26
- export var STORAGE_CUSTOM = 'CUSTOM';
26
+ export var STORAGE_PLUGGABLE = 'PLUGGABLE';
@@ -1,3 +1,6 @@
1
- // We check for version truthiness since most shims will have that as empty string.
1
+ /**
2
+ * 'true' if running in Node.js, or 'false' otherwise.
3
+ * We check for version truthiness since most shims will have that as empty string.
4
+ */
2
5
  // eslint-disable-next-line no-undef
3
6
  export var isNode = typeof process !== 'undefined' && typeof process.version !== 'undefined' && !!process.version ? true : false;
@@ -1,6 +1,6 @@
1
1
  import { InMemoryStorageCSFactory } from '../../../storages/inMemory/InMemoryStorageCS';
2
- import { WARN_STORAGE_INVALID } from '../../../logger/constants';
3
- import { LOCALHOST_MODE, STANDALONE_MODE, STORAGE_CUSTOM, STORAGE_LOCALSTORAGE, STORAGE_MEMORY } from '../../../utils/constants';
2
+ import { ERROR_STORAGE_INVALID } from '../../../logger/constants';
3
+ import { LOCALHOST_MODE, STANDALONE_MODE, STORAGE_PLUGGABLE, STORAGE_LOCALSTORAGE, STORAGE_MEMORY } from '../../../utils/constants';
4
4
  export function __InLocalStorageMockFactory(params) {
5
5
  var result = InMemoryStorageCSFactory(params);
6
6
  result.splits.checkCache = function () { return true; }; // to emit SDK_READY_FROM_CACHE
@@ -12,29 +12,32 @@ __InLocalStorageMockFactory.type = STORAGE_MEMORY;
12
12
  *
13
13
  * @param {any} settings config object provided by the user to initialize the sdk
14
14
  *
15
- * @returns {Object} valid storage factory. It might be the default `InMemoryStorageCSFactory` if the provided storage is invalid.
15
+ * @returns {Object} valid storage factory. Default to `InMemoryStorageCSFactory` if the provided storage is invalid or not compatible with the sdk mode if mode is standalone or localhost
16
+ *
17
+ * @throws error if mode is consumer and the provided storage is not compatible
16
18
  */
17
19
  export function validateStorageCS(settings) {
18
20
  var _a = settings.storage, storage = _a === void 0 ? InMemoryStorageCSFactory : _a, log = settings.log, mode = settings.mode;
19
21
  // If an invalid storage is provided, fallback into MEMORY
20
- if (typeof storage !== 'function' || [STORAGE_MEMORY, STORAGE_LOCALSTORAGE, STORAGE_CUSTOM].indexOf(storage.type) === -1) {
22
+ if (typeof storage !== 'function' || [STORAGE_MEMORY, STORAGE_LOCALSTORAGE, STORAGE_PLUGGABLE].indexOf(storage.type) === -1) {
21
23
  storage = InMemoryStorageCSFactory;
22
- log.warn(WARN_STORAGE_INVALID);
24
+ log.error(ERROR_STORAGE_INVALID);
23
25
  }
24
26
  // In localhost mode with InLocalStorage, fallback to a mock InLocalStorage to emit SDK_READY_FROM_CACHE
25
27
  if (mode === LOCALHOST_MODE && storage.type === STORAGE_LOCALSTORAGE) {
26
28
  return __InLocalStorageMockFactory;
27
29
  }
28
- // @TODO check behaviour
29
30
  if ([LOCALHOST_MODE, STANDALONE_MODE].indexOf(mode) === -1) {
30
31
  // Consumer modes require an async storage
31
- if (storage.type !== STORAGE_CUSTOM)
32
- throw new Error('A CustomStorage instance is required on consumer modes');
32
+ if (storage.type !== STORAGE_PLUGGABLE)
33
+ throw new Error('A PluggableStorage instance is required on consumer mode');
33
34
  }
34
35
  else {
35
36
  // Standalone and localhost modes require a sync storage
36
- if (storage.type === STORAGE_CUSTOM)
37
- throw new Error('A CustomStorage instance cannot be used on standalone and localhost modes');
37
+ if (storage.type === STORAGE_PLUGGABLE) {
38
+ storage = InMemoryStorageCSFactory;
39
+ log.error(ERROR_STORAGE_INVALID, [' It requires consumer mode.']);
40
+ }
38
41
  }
39
42
  // return default InMemory storage if provided one is not valid
40
43
  return storage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "1.0.1-rc.1",
3
+ "version": "1.0.1-rc.5",
4
4
  "description": "Split Javascript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -49,10 +49,9 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/google.analytics": "0.0.40",
52
- "@types/ioredis": "^4.14.1",
52
+ "@types/ioredis": "^4.28.0",
53
53
  "@types/jest": "^27.0.0",
54
54
  "@types/lodash": "^4.14.162",
55
- "@types/node": "^14.14.7",
56
55
  "@types/object-assign": "^4.0.30",
57
56
  "@typescript-eslint/eslint-plugin": "^4.2.0",
58
57
  "@typescript-eslint/parser": "^4.2.0",
@@ -61,7 +60,7 @@
61
60
  "eslint": "^7.32.0",
62
61
  "eslint-plugin-compat": "3.7.0",
63
62
  "fetch-mock": "^9.10.7",
64
- "ioredis": "^4.26.0",
63
+ "ioredis": "^4.28.0",
65
64
  "jest": "^27.2.3",
66
65
  "jest-localstorage-mock": "^2.4.3",
67
66
  "js-yaml": "^3.14.0",
@@ -1,7 +1,6 @@
1
1
  import Engine from './Engine';
2
2
  import thenable from '../utils/promise/thenable';
3
3
  import * as LabelsConstants from '../utils/labels';
4
- import { get } from '../utils/lang';
5
4
  import { CONTROL } from '../utils/constants';
6
5
  import { ISplit, MaybeThenable } from '../dtos/types';
7
6
  import { IStorageAsync, IStorageSync } from '../storages/types';
@@ -106,17 +105,17 @@ function getEvaluation(
106
105
  const split = Engine.parse(log, splitJSON, storage);
107
106
  evaluation = split.getTreatment(key, attributes, evaluateFeature);
108
107
 
109
- // If the storage is async, evaluation and changeNumber will return a thenable
108
+ // If the storage is async and the evaluated split uses segment, evaluation is thenable
110
109
  if (thenable(evaluation)) {
111
110
  return evaluation.then(result => {
112
111
  result.changeNumber = split.getChangeNumber();
113
- result.config = get(splitJSON, `configurations.${result.treatment}`, null);
112
+ result.config = splitJSON.configurations && splitJSON.configurations[result.treatment] || null;
114
113
 
115
114
  return result;
116
115
  });
117
116
  } else {
118
117
  evaluation.changeNumber = split.getChangeNumber(); // Always sync and optional
119
- evaluation.config = get(splitJSON, `configurations.${evaluation.treatment}`, null);
118
+ evaluation.config = splitJSON.configurations && splitJSON.configurations[evaluation.treatment] || null;
120
119
  }
121
120
  }
122
121
 
@@ -91,9 +91,8 @@ export const WARN_INTEGRATION_INVALID = 218;
91
91
  export const WARN_SPLITS_FILTER_IGNORED = 219;
92
92
  export const WARN_SPLITS_FILTER_INVALID = 220;
93
93
  export const WARN_SPLITS_FILTER_EMPTY = 221;
94
- export const WARN_STORAGE_INVALID = 222;
95
- export const WARN_API_KEY = 223;
96
- export const STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = 224;
94
+ export const WARN_API_KEY = 222;
95
+ export const STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2 = 223;
97
96
 
98
97
  export const ERROR_ENGINE_COMBINER_IFELSEIF = 300;
99
98
  export const ERROR_LOGLEVEL_INVALID = 301;
@@ -119,6 +118,7 @@ export const ERROR_EMPTY_ARRAY = 320;
119
118
  export const ERROR_INVALID_IMPRESSIONS_MODE = 321;
120
119
  export const ERROR_HTTP = 322;
121
120
  export const ERROR_LOCALHOST_MODULE_REQUIRED = 323;
121
+ export const ERROR_STORAGE_INVALID = 324;
122
122
 
123
123
  // Log prefixes (a.k.a. tags or categories)
124
124
  export const LOG_PREFIX_SETTINGS = 'settings';
@@ -30,5 +30,6 @@ export const codesError: [number, string][] = [
30
30
  [c.ERROR_EMPTY_ARRAY, '%s: %s must be a non-empty array.'],
31
31
  // initialization / settings validation
32
32
  [c.ERROR_INVALID_IMPRESSIONS_MODE, c.LOG_PREFIX_SETTINGS + ': you passed an invalid "impressionsMode". It should be one of the following values: %s. Defaulting to "%s" mode.'],
33
- [c.ERROR_LOCALHOST_MODULE_REQUIRED, c.LOG_PREFIX_SETTINGS + ': an invalid value was received for "sync.localhostMode" config. A valid entity should be provided for localhost mode.']
33
+ [c.ERROR_LOCALHOST_MODULE_REQUIRED, c.LOG_PREFIX_SETTINGS + ': an invalid value was received for "sync.localhostMode" config. A valid entity should be provided for localhost mode.'],
34
+ [c.ERROR_STORAGE_INVALID, c.LOG_PREFIX_SETTINGS+': The provided storage is invalid.%s Fallbacking into default MEMORY storage'],
34
35
  ];
@@ -29,7 +29,6 @@ export const codesWarn: [number, string][] = codesError.concat([
29
29
  [c.WARN_SPLITS_FILTER_IGNORED, c.LOG_PREFIX_SETTINGS+': split filters have been configured but will have no effect if mode is not "%s", since synchronization is being deferred to an external tool.'],
30
30
  [c.WARN_SPLITS_FILTER_INVALID, c.LOG_PREFIX_SETTINGS+': split filter at position %s is invalid. It must be an object with a valid filter type ("byName" or "byPrefix") and a list of "values".'],
31
31
  [c.WARN_SPLITS_FILTER_EMPTY, c.LOG_PREFIX_SETTINGS+': splitFilters configuration must be a non-empty array of filter objects.'],
32
- [c.WARN_STORAGE_INVALID, c.LOG_PREFIX_SETTINGS+': The provided storage is invalid. Fallbacking into default MEMORY storage'],
33
32
  [c.WARN_API_KEY, c.LOG_PREFIX_SETTINGS+': You already have %s. We recommend keeping only one instance of the factory at all times (Singleton pattern) and reusing it throughout your application'],
34
33
 
35
34
  [c.STREAMING_PARSING_MY_SEGMENTS_UPDATE_V2, c.LOG_PREFIX_SYNC_STREAMING + 'Fetching MySegments due to an error processing %s notification: %s'],
@@ -40,7 +40,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
40
40
  matchingKey: getMatching(settings.core.key),
41
41
  splitFiltersValidation: settings.sync.__splitFiltersValidation,
42
42
 
43
- // ATM, only used by CustomStorage. true for partial consumer mode
43
+ // ATM, only used by PluggableStorage
44
44
  mode: settings.mode,
45
45
 
46
46
  // Callback used to emit SDK_READY in consumer mode, where `syncManagerFactory` is undefined
@@ -3,7 +3,7 @@ import { ISignalListener } from '../listeners/types';
3
3
  import { ILogger } from '../logger/types';
4
4
  import { ISdkReadinessManager } from '../readiness/types';
5
5
  import { ISdkClientFactoryParams } from '../sdkClient/types';
6
- import { IFetch, ISplitApi } from '../services/types';
6
+ import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
7
7
  import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
8
8
  import { ISyncManager, ISyncManagerFactoryParams } from '../sync/types';
9
9
  import { IImpressionObserver } from '../trackers/impressionObserver/types';
@@ -16,7 +16,7 @@ import { SplitIO, ISettings, IEventEmitter } from '../types';
16
16
  export interface IPlatform {
17
17
  getOptions?: () => object
18
18
  getFetch?: () => (IFetch | undefined)
19
- getEventSource?: () => (typeof EventSource | undefined)
19
+ getEventSource?: () => (IEventSourceConstructor | undefined)
20
20
  EventEmitter: new () => IEventEmitter
21
21
  }
22
22
 
@@ -16,7 +16,10 @@ function userKeyToQueryParam(userKey: string) {
16
16
  * @param settings validated settings object
17
17
  * @param platform object containing environment-specific `getFetch` and `getOptions` dependencies
18
18
  */
19
- export function splitApiFactory(settings: ISettings, platform: Pick<IPlatform, 'getFetch' | 'getOptions'>): ISplitApi {
19
+ export function splitApiFactory(
20
+ settings: Pick<ISettings, 'urls' | 'sync' | 'log' | 'version' | 'runtime' | 'core'>,
21
+ platform: Pick<IPlatform, 'getFetch' | 'getOptions'>
22
+ ): ISplitApi {
20
23
 
21
24
  const urls = settings.urls;
22
25
  const filterQueryString = settings.sync.__splitFiltersValidation && settings.sync.__splitFiltersValidation.queryString;
@@ -50,8 +50,8 @@ export type IPostMetricsCounters = (body: string) => Promise<IResponse>
50
50
  export type IPostMetricsTimes = (body: string) => Promise<IResponse>
51
51
 
52
52
  export interface ISplitApi {
53
- getSdkAPIHealthCheck: IHealthCheckAPI
54
- getEventsAPIHealthCheck: IHealthCheckAPI
53
+ getSdkAPIHealthCheck: IHealthCheckAPI
54
+ getEventsAPIHealthCheck: IHealthCheckAPI
55
55
  fetchAuth: IFetchAuth
56
56
  fetchSplitChanges: IFetchSplitChanges
57
57
  fetchSegmentChanges: IFetchSegmentChanges
@@ -62,3 +62,17 @@ export interface ISplitApi {
62
62
  postMetricsCounters: IPostMetricsCounters
63
63
  postMetricsTimes: IPostMetricsTimes
64
64
  }
65
+
66
+ // Minimal version of EventSource API used by the SDK
67
+ interface EventSourceEventMap {
68
+ 'error': Event
69
+ 'message': MessageEvent
70
+ 'open': Event
71
+ }
72
+
73
+ interface IEventSource {
74
+ addEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: IEventSource, ev: EventSourceEventMap[K]) => any): void
75
+ close(): void
76
+ }
77
+
78
+ export type IEventSourceConstructor = new (url: string, eventSourceInitDict?: any) => IEventSource
@@ -30,7 +30,7 @@ export function InRedisStorage(options: InRedisStorageOptions = {}): IStorageAsy
30
30
 
31
31
  // subscription to Redis connect event in order to emit SDK_READY event on consumer mode
32
32
  redisClient.on('connect', () => {
33
- if (onReadyCb) onReadyCb();
33
+ onReadyCb();
34
34
  });
35
35
 
36
36
  return {
@@ -1,4 +1,4 @@
1
- import { ICustomStorageWrapper, IEventsCacheAsync } from '../types';
1
+ import { IPluggableStorageWrapper, IEventsCacheAsync } from '../types';
2
2
  import { IMetadata } from '../../dtos/types';
3
3
  import { SplitIO } from '../../types';
4
4
  import { ILogger } from '../../logger/types';
@@ -8,11 +8,11 @@ import { StoredEventWithMetadata } from '../../sync/submitters/types';
8
8
  export class EventsCachePluggable implements IEventsCacheAsync {
9
9
 
10
10
  private readonly log: ILogger;
11
- private readonly wrapper: ICustomStorageWrapper;
11
+ private readonly wrapper: IPluggableStorageWrapper;
12
12
  private readonly key: string;
13
13
  private readonly metadata: IMetadata;
14
14
 
15
- constructor(log: ILogger, key: string, wrapper: ICustomStorageWrapper, metadata: IMetadata) {
15
+ constructor(log: ILogger, key: string, wrapper: IPluggableStorageWrapper, metadata: IMetadata) {
16
16
  this.log = log;
17
17
  this.key = key;
18
18
  this.wrapper = wrapper;
@@ -1,4 +1,4 @@
1
- import { ICustomStorageWrapper, IImpressionsCacheAsync } from '../types';
1
+ import { IPluggableStorageWrapper, IImpressionsCacheAsync } from '../types';
2
2
  import { IMetadata } from '../../dtos/types';
3
3
  import { ImpressionDTO } from '../../types';
4
4
  import { ILogger } from '../../logger/types';
@@ -8,10 +8,10 @@ export class ImpressionsCachePluggable implements IImpressionsCacheAsync {
8
8
 
9
9
  private readonly log: ILogger;
10
10
  private readonly key: string;
11
- private readonly wrapper: ICustomStorageWrapper;
11
+ private readonly wrapper: IPluggableStorageWrapper;
12
12
  private readonly metadata: IMetadata;
13
13
 
14
- constructor(log: ILogger, key: string, wrapper: ICustomStorageWrapper, metadata: IMetadata) {
14
+ constructor(log: ILogger, key: string, wrapper: IPluggableStorageWrapper, metadata: IMetadata) {
15
15
  this.log = log;
16
16
  this.key = key;
17
17
  this.wrapper = wrapper;
@@ -2,7 +2,7 @@
2
2
  /* eslint-disable no-unused-vars */
3
3
  import { isNaNNumber } from '../../utils/lang';
4
4
  import KeyBuilderSS from '../KeyBuilderSS';
5
- import { ICustomStorageWrapper, ISegmentsCacheAsync } from '../types';
5
+ import { IPluggableStorageWrapper, ISegmentsCacheAsync } from '../types';
6
6
  import { ILogger } from '../../logger/types';
7
7
  import { LOG_PREFIX } from './constants';
8
8
  import { _Set } from '../../utils/lang/sets';
@@ -14,9 +14,9 @@ export class SegmentsCachePluggable implements ISegmentsCacheAsync {
14
14
 
15
15
  private readonly log: ILogger;
16
16
  private readonly keys: KeyBuilderSS;
17
- private readonly wrapper: ICustomStorageWrapper;
17
+ private readonly wrapper: IPluggableStorageWrapper;
18
18
 
19
- constructor(log: ILogger, keys: KeyBuilderSS, wrapper: ICustomStorageWrapper) {
19
+ constructor(log: ILogger, keys: KeyBuilderSS, wrapper: IPluggableStorageWrapper) {
20
20
  this.log = log;
21
21
  this.keys = keys;
22
22
  this.wrapper = wrapper;
@@ -1,6 +1,6 @@
1
1
  import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
2
2
  import KeyBuilder from '../KeyBuilder';
3
- import { ICustomStorageWrapper } from '../types';
3
+ import { IPluggableStorageWrapper } from '../types';
4
4
  import { ILogger } from '../../logger/types';
5
5
  import { ISplit } from '../../dtos/types';
6
6
  import { LOG_PREFIX } from './constants';
@@ -13,15 +13,15 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {
13
13
 
14
14
  private readonly log: ILogger;
15
15
  private readonly keys: KeyBuilder;
16
- private readonly wrapper: ICustomStorageWrapper;
16
+ private readonly wrapper: IPluggableStorageWrapper;
17
17
 
18
18
  /**
19
- * Create a SplitsCache that uses a custom storage wrapper.
19
+ * Create a SplitsCache that uses a storage wrapper.
20
20
  * @param log Logger instance.
21
21
  * @param keys Key builder.
22
22
  * @param wrapper Adapted wrapper storage.
23
23
  */
24
- constructor(log: ILogger, keys: KeyBuilder, wrapper: ICustomStorageWrapper) {
24
+ constructor(log: ILogger, keys: KeyBuilder, wrapper: IPluggableStorageWrapper) {
25
25
  super();
26
26
  this.log = log;
27
27
  this.keys = keys;
@@ -1 +1 @@
1
- export const LOG_PREFIX = 'storage:pluggable:';
1
+ export const LOG_PREFIX = 'storage:pluggable: ';
@@ -1,15 +1,15 @@
1
- import { ICustomStorageWrapper } from '../types';
1
+ import { IPluggableStorageWrapper } from '../types';
2
2
  import { startsWith, toNumber } from '../../utils/lang';
3
3
  import { ISet, setToArray, _Set } from '../../utils/lang/sets';
4
4
 
5
5
  /**
6
- * Creates a ICustomStorageWrapper implementation that stores items in memory.
6
+ * Creates a IPluggableStorageWrapper implementation that stores items in memory.
7
7
  * The `_cache` property is the object were items are stored.
8
8
  * Intended for testing purposes.
9
9
  *
10
10
  * @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves inmediatelly.
11
11
  */
12
- export function inMemoryWrapperFactory(connDelay?: number): ICustomStorageWrapper & { _cache: Record<string, string | string[] | ISet<string>>, _setConnDelay(connDelay: number): void } {
12
+ export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWrapper & { _cache: Record<string, string | string[] | ISet<string>>, _setConnDelay(connDelay: number): void } {
13
13
 
14
14
  let _cache: Record<string, string | string[] | ISet<string>> = {};
15
15
  let _connDelay = connDelay;
@@ -112,7 +112,7 @@ export function inMemoryWrapperFactory(connDelay?: number): ICustomStorageWrappe
112
112
  return Promise.reject('key is not a set');
113
113
  },
114
114
 
115
- // always connects and close
115
+ // always connects and disconnects
116
116
  connect() {
117
117
  if (typeof _connDelay === 'number') {
118
118
  return new Promise(res => setTimeout(res, _connDelay));
@@ -120,7 +120,7 @@ export function inMemoryWrapperFactory(connDelay?: number): ICustomStorageWrappe
120
120
  return Promise.resolve();
121
121
  }
122
122
  },
123
- close() { return Promise.resolve(); },
123
+ disconnect() { return Promise.resolve(); },
124
124
 
125
125
  // for testing
126
126
  _setConnDelay(connDelay: number) {
@@ -1,4 +1,4 @@
1
- import { ICustomStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams } from '../types';
1
+ import { IPluggableStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams } from '../types';
2
2
 
3
3
  import KeyBuilderSS from '../KeyBuilderSS';
4
4
  import { SplitsCachePluggable } from './SplitsCachePluggable';
@@ -8,17 +8,17 @@ import { EventsCachePluggable } from './EventsCachePluggable';
8
8
  import { wrapperAdapter, METHODS_TO_PROMISE_WRAP } from './wrapperAdapter';
9
9
  import { isObject } from '../../utils/lang';
10
10
  import { validatePrefix } from '../KeyBuilder';
11
- import { CONSUMER_PARTIAL_MODE, STORAGE_CUSTOM } from '../../utils/constants';
11
+ import { CONSUMER_PARTIAL_MODE, STORAGE_PLUGGABLE } from '../../utils/constants';
12
12
  import ImpressionsCacheInMemory from '../inMemory/ImpressionsCacheInMemory';
13
13
  import EventsCacheInMemory from '../inMemory/EventsCacheInMemory';
14
14
  import ImpressionCountsCacheInMemory from '../inMemory/ImpressionCountsCacheInMemory';
15
15
 
16
- const NO_VALID_WRAPPER = 'Expecting custom storage `wrapper` in options, but no valid wrapper instance was provided.';
16
+ const NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
17
17
  const NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';
18
18
 
19
19
  export interface PluggableStorageOptions {
20
20
  prefix?: string
21
- wrapper: ICustomStorageWrapper
21
+ wrapper: IPluggableStorageWrapper
22
22
  }
23
23
 
24
24
  /**
@@ -36,7 +36,7 @@ function validatePluggableStorageOptions(options: any) {
36
36
  }
37
37
 
38
38
  // subscription to wrapper connect event in order to emit SDK_READY event
39
- function wrapperConnect(wrapper: ICustomStorageWrapper, onReadyCb: (error?: any) => void) {
39
+ function wrapperConnect(wrapper: IPluggableStorageWrapper, onReadyCb: (error?: any) => void) {
40
40
  wrapper.connect().then(() => {
41
41
  onReadyCb();
42
42
  }).catch((e) => {
@@ -68,7 +68,7 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
68
68
  const wrapper = wrapperAdapter(log, options.wrapper);
69
69
  const isPartialConsumer = mode === CONSUMER_PARTIAL_MODE;
70
70
 
71
- // emit SDK_READY event on main client
71
+ // Connects to wrapper and emits SDK_READY event on main client
72
72
  wrapperConnect(wrapper, onReadyCb);
73
73
 
74
74
  return {
@@ -79,9 +79,9 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
79
79
  events: isPartialConsumer ? promisifyEventsTrack(new EventsCacheInMemory(eventsQueueSize)) : new EventsCachePluggable(log, keys.buildEventsKey(), wrapper, metadata),
80
80
  // @TODO add telemetry cache when required
81
81
 
82
- // Disconnect the underlying storage, to release its resources (such as open files, database connections, etc).
82
+ // Disconnect the underlying storage
83
83
  destroy() {
84
- return wrapper.close();
84
+ return wrapper.disconnect();
85
85
  },
86
86
 
87
87
  // emits SDK_READY event on shared clients and returns a reference to the storage
@@ -89,13 +89,13 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
89
89
  wrapperConnect(wrapper, onReadyCb);
90
90
  return {
91
91
  ...this,
92
- // no-op destroy, to close the wrapper only when the main client is destroyed
92
+ // no-op destroy, to disconnect the wrapper only when the main client is destroyed
93
93
  destroy() { }
94
94
  };
95
95
  }
96
96
  };
97
97
  }
98
98
 
99
- PluggableStorageFactory.type = STORAGE_CUSTOM;
99
+ PluggableStorageFactory.type = STORAGE_PLUGGABLE;
100
100
  return PluggableStorageFactory;
101
101
  }
@@ -1,5 +1,5 @@
1
1
  import { ILogger } from '../../logger/types';
2
- import { ICustomStorageWrapper } from '../types';
2
+ import { IPluggableStorageWrapper } from '../types';
3
3
  import { LOG_PREFIX } from './constants';
4
4
 
5
5
  export const METHODS_TO_PROMISE_WRAP: string[] = [
@@ -19,18 +19,18 @@ export const METHODS_TO_PROMISE_WRAP: string[] = [
19
19
  'removeItems',
20
20
  'getItems',
21
21
  'connect',
22
- 'close'
22
+ 'disconnect'
23
23
  ];
24
24
 
25
25
  /**
26
- * Adapter of the Custom Storage Wrapper.
26
+ * Adapter of the Pluggable Storage Wrapper.
27
27
  * Used to handle exceptions as rejected promises, in order to simplify the error handling on storages.
28
28
  *
29
29
  * @param log logger instance
30
- * @param wrapper custom storage wrapper to adapt
30
+ * @param wrapper storage wrapper to adapt
31
31
  * @returns an adapted version of the given storage wrapper
32
32
  */
33
- export function wrapperAdapter(log: ILogger, wrapper: ICustomStorageWrapper): ICustomStorageWrapper {
33
+ export function wrapperAdapter(log: ILogger, wrapper: IPluggableStorageWrapper): IPluggableStorageWrapper {
34
34
 
35
35
  const wrapperAdapter: Record<string, Function> = {};
36
36
 
@@ -4,9 +4,9 @@ import { StoredEventWithMetadata, StoredImpressionWithMetadata } from '../sync/s
4
4
  import { SplitIO, ImpressionDTO, SDKMode } from '../types';
5
5
 
6
6
  /**
7
- * Interface of a custom storage wrapper.
7
+ * Interface of a pluggable storage wrapper.
8
8
  */
9
- export interface ICustomStorageWrapper {
9
+ export interface IPluggableStorageWrapper {
10
10
 
11
11
  /** Key-Value operations */
12
12
 
@@ -177,15 +177,15 @@ export interface ICustomStorageWrapper {
177
177
  */
178
178
  connect: () => Promise<void>
179
179
  /**
180
- * Disconnects the underlying storage.
180
+ * Disconnects from the underlying storage.
181
181
  * It is meant for storages that requires to be closed, in order to release resources. Otherwise it can just return a resolved promise.
182
182
  * Note: will be called once on SplitFactory main client destroy.
183
183
  *
184
- * @function close
184
+ * @function disconnect
185
185
  * @returns {Promise<void>} A promise that resolves when the operation ends.
186
186
  * The promise never rejects.
187
187
  */
188
- close: () => Promise<void>
188
+ disconnect: () => Promise<void>
189
189
  }
190
190
 
191
191
  /** Splits cache */
@@ -430,7 +430,7 @@ export interface IStorageFactoryParams {
430
430
  matchingKey?: string, /* undefined on server-side SDKs */
431
431
  splitFiltersValidation?: ISplitFiltersValidation,
432
432
 
433
- // ATM, only used by CustomStorage. True for partial consumer mode
433
+ // ATM, only used by PluggableStorage
434
434
  mode?: SDKMode,
435
435
 
436
436
  // This callback is invoked when the storage is ready to be used. Error-first callback style: if an error is passed,
@@ -440,7 +440,7 @@ export interface IStorageFactoryParams {
440
440
  metadata: IMetadata,
441
441
  }
442
442
 
443
- export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'CUSTOM';
443
+ export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';
444
444
 
445
445
  export type IStorageSyncFactory = {
446
446
  type: StorageType,
@@ -38,7 +38,7 @@ export function mySegmentsUpdaterFactory(
38
38
  // mySegmentsPromise = tracker.start(tracker.TaskNames.MY_SEGMENTS_FETCH, startingUp ? metricCollectors : false, mySegmentsPromise);
39
39
  }
40
40
 
41
- // @TODO if allowing custom storages, handle async execution
41
+ // @TODO if allowing pluggable storages, handle async execution
42
42
  function updateSegments(segmentsData: SegmentsData) {
43
43
 
44
44
  let shouldNotifyUpdate;