Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@

"globals": {
// global TS types
"EventSource": "readonly", // @TODO remove. Configure as a type declaration
"MessageEvent": "readonly", // @TODO remove. Configure as a type declaration
"Event": "readonly", // @TODO remove. Configure as a type declaration
"NodeJS": "readonly",
"UniversalAnalytics": "readonly" // @TODO remove when moving GA integrations to Browser-SDK
},

Expand Down
27 changes: 17 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@splitsoftware/splitio-commons",
"version": "1.0.1-rc.1",
"version": "1.0.1-rc.4",
"description": "Split Javascript SDK common components",
"main": "cjs/index.js",
"module": "esm/index.js",
Expand Down Expand Up @@ -49,10 +49,9 @@
},
"devDependencies": {
"@types/google.analytics": "0.0.40",
"@types/ioredis": "^4.14.1",
"@types/ioredis": "^4.28.0",
"@types/jest": "^27.0.0",
"@types/lodash": "^4.14.162",
"@types/node": "^14.14.7",
"@types/object-assign": "^4.0.30",
"@typescript-eslint/eslint-plugin": "^4.2.0",
"@typescript-eslint/parser": "^4.2.0",
Expand All @@ -61,7 +60,7 @@
"eslint": "^7.32.0",
"eslint-plugin-compat": "3.7.0",
"fetch-mock": "^9.10.7",
"ioredis": "^4.26.0",
"ioredis": "^4.28.0",
"jest": "^27.2.3",
"jest-localstorage-mock": "^2.4.3",
"js-yaml": "^3.14.0",
Expand Down
2 changes: 1 addition & 1 deletion src/sdkFactory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function sdkFactory(params: ISdkFactoryParams): SplitIO.ICsSDK | SplitIO.
matchingKey: getMatching(settings.core.key),
splitFiltersValidation: settings.sync.__splitFiltersValidation,

// ATM, only used by CustomStorage
// ATM, only used by PluggableStorage
mode: settings.mode,

// Callback used to emit SDK_READY in consumer mode, where `syncManagerFactory` is undefined
Expand Down
4 changes: 2 additions & 2 deletions src/sdkFactory/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ISignalListener } from '../listeners/types';
import { ILogger } from '../logger/types';
import { ISdkReadinessManager } from '../readiness/types';
import { ISdkClientFactoryParams } from '../sdkClient/types';
import { IFetch, ISplitApi } from '../services/types';
import { IFetch, ISplitApi, IEventSourceConstructor } from '../services/types';
import { IStorageAsync, IStorageSync, ISplitsCacheSync, ISplitsCacheAsync, IStorageFactoryParams } from '../storages/types';
import { ISyncManager, ISyncManagerFactoryParams } from '../sync/types';
import { IImpressionObserver } from '../trackers/impressionObserver/types';
Expand All @@ -16,7 +16,7 @@ import { SplitIO, ISettings, IEventEmitter } from '../types';
export interface IPlatform {
getOptions?: () => object
getFetch?: () => (IFetch | undefined)
getEventSource?: () => (typeof EventSource | undefined)
getEventSource?: () => (IEventSourceConstructor | undefined)
EventEmitter: new () => IEventEmitter
}

Expand Down
18 changes: 16 additions & 2 deletions src/services/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ export type IPostMetricsCounters = (body: string) => Promise<IResponse>
export type IPostMetricsTimes = (body: string) => Promise<IResponse>

export interface ISplitApi {
getSdkAPIHealthCheck: IHealthCheckAPI
getEventsAPIHealthCheck: IHealthCheckAPI
getSdkAPIHealthCheck: IHealthCheckAPI
getEventsAPIHealthCheck: IHealthCheckAPI
fetchAuth: IFetchAuth
fetchSplitChanges: IFetchSplitChanges
fetchSegmentChanges: IFetchSegmentChanges
Expand All @@ -62,3 +62,17 @@ export interface ISplitApi {
postMetricsCounters: IPostMetricsCounters
postMetricsTimes: IPostMetricsTimes
}

// Minimal version of EventSource API used by the SDK
interface EventSourceEventMap {
'error': Event
'message': MessageEvent
'open': Event
}

interface IEventSource {
addEventListener<K extends keyof EventSourceEventMap>(type: K, listener: (this: IEventSource, ev: EventSourceEventMap[K]) => any): void
close(): void
}

export type IEventSourceConstructor = new (url: string, eventSourceInitDict?: any) => IEventSource
6 changes: 3 additions & 3 deletions src/storages/pluggable/EventsCachePluggable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ICustomStorageWrapper, IEventsCacheAsync } from '../types';
import { IPluggableStorageWrapper, IEventsCacheAsync } from '../types';
import { IMetadata } from '../../dtos/types';
import { SplitIO } from '../../types';
import { ILogger } from '../../logger/types';
Expand All @@ -8,11 +8,11 @@ import { StoredEventWithMetadata } from '../../sync/submitters/types';
export class EventsCachePluggable implements IEventsCacheAsync {

private readonly log: ILogger;
private readonly wrapper: ICustomStorageWrapper;
private readonly wrapper: IPluggableStorageWrapper;
private readonly key: string;
private readonly metadata: IMetadata;

constructor(log: ILogger, key: string, wrapper: ICustomStorageWrapper, metadata: IMetadata) {
constructor(log: ILogger, key: string, wrapper: IPluggableStorageWrapper, metadata: IMetadata) {
this.log = log;
this.key = key;
this.wrapper = wrapper;
Expand Down
6 changes: 3 additions & 3 deletions src/storages/pluggable/ImpressionsCachePluggable.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ICustomStorageWrapper, IImpressionsCacheAsync } from '../types';
import { IPluggableStorageWrapper, IImpressionsCacheAsync } from '../types';
import { IMetadata } from '../../dtos/types';
import { ImpressionDTO } from '../../types';
import { ILogger } from '../../logger/types';
Expand All @@ -8,10 +8,10 @@ export class ImpressionsCachePluggable implements IImpressionsCacheAsync {

private readonly log: ILogger;
private readonly key: string;
private readonly wrapper: ICustomStorageWrapper;
private readonly wrapper: IPluggableStorageWrapper;
private readonly metadata: IMetadata;

constructor(log: ILogger, key: string, wrapper: ICustomStorageWrapper, metadata: IMetadata) {
constructor(log: ILogger, key: string, wrapper: IPluggableStorageWrapper, metadata: IMetadata) {
this.log = log;
this.key = key;
this.wrapper = wrapper;
Expand Down
6 changes: 3 additions & 3 deletions src/storages/pluggable/SegmentsCachePluggable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* eslint-disable no-unused-vars */
import { isNaNNumber } from '../../utils/lang';
import KeyBuilderSS from '../KeyBuilderSS';
import { ICustomStorageWrapper, ISegmentsCacheAsync } from '../types';
import { IPluggableStorageWrapper, ISegmentsCacheAsync } from '../types';
import { ILogger } from '../../logger/types';
import { LOG_PREFIX } from './constants';
import { _Set } from '../../utils/lang/sets';
Expand All @@ -14,9 +14,9 @@ export class SegmentsCachePluggable implements ISegmentsCacheAsync {

private readonly log: ILogger;
private readonly keys: KeyBuilderSS;
private readonly wrapper: ICustomStorageWrapper;
private readonly wrapper: IPluggableStorageWrapper;

constructor(log: ILogger, keys: KeyBuilderSS, wrapper: ICustomStorageWrapper) {
constructor(log: ILogger, keys: KeyBuilderSS, wrapper: IPluggableStorageWrapper) {
this.log = log;
this.keys = keys;
this.wrapper = wrapper;
Expand Down
8 changes: 4 additions & 4 deletions src/storages/pluggable/SplitsCachePluggable.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { isFiniteNumber, isNaNNumber } from '../../utils/lang';
import KeyBuilder from '../KeyBuilder';
import { ICustomStorageWrapper } from '../types';
import { IPluggableStorageWrapper } from '../types';
import { ILogger } from '../../logger/types';
import { ISplit } from '../../dtos/types';
import { LOG_PREFIX } from './constants';
Expand All @@ -13,15 +13,15 @@ export class SplitsCachePluggable extends AbstractSplitsCacheAsync {

private readonly log: ILogger;
private readonly keys: KeyBuilder;
private readonly wrapper: ICustomStorageWrapper;
private readonly wrapper: IPluggableStorageWrapper;

/**
* Create a SplitsCache that uses a custom storage wrapper.
* Create a SplitsCache that uses a storage wrapper.
* @param log Logger instance.
* @param keys Key builder.
* @param wrapper Adapted wrapper storage.
*/
constructor(log: ILogger, keys: KeyBuilder, wrapper: ICustomStorageWrapper) {
constructor(log: ILogger, keys: KeyBuilder, wrapper: IPluggableStorageWrapper) {
super();
this.log = log;
this.keys = keys;
Expand Down
2 changes: 1 addition & 1 deletion src/storages/pluggable/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('PLUGGABLE STORAGE', () => {
expect(() => PluggableStorage({ wrapper: wrapperMock })).not.toThrow(); // not prefix but valid wrapper is OK

// Throws exception if no object is passed as wrapper
const errorNoValidWrapper = 'Expecting custom storage `wrapper` in options, but no valid wrapper instance was provided.';
const errorNoValidWrapper = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
expect(() => PluggableStorage()).toThrow(errorNoValidWrapper);
expect(() => PluggableStorage({ wrapper: undefined })).toThrow(errorNoValidWrapper);
expect(() => PluggableStorage({ wrapper: 'invalid wrapper' })).toThrow(errorNoValidWrapper);
Expand Down
2 changes: 1 addition & 1 deletion src/storages/pluggable/__tests__/wrapper.mock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { startsWith, toNumber } from '../../../utils/lang';

// Creates an in memory ICustomStorageWrapper implementation with Jest mocks
// Creates an in memory IPluggableStorageWrapper implementation with Jest mocks
export function wrapperMockFactory() {

/** Holds items and list of items */
Expand Down
2 changes: 1 addition & 1 deletion src/storages/pluggable/constants.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const LOG_PREFIX = 'storage:pluggable:';
export const LOG_PREFIX = 'storage:pluggable: ';
6 changes: 3 additions & 3 deletions src/storages/pluggable/inMemoryWrapper.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ICustomStorageWrapper } from '../types';
import { IPluggableStorageWrapper } from '../types';
import { startsWith, toNumber } from '../../utils/lang';
import { ISet, setToArray, _Set } from '../../utils/lang/sets';

/**
* Creates a ICustomStorageWrapper implementation that stores items in memory.
* Creates a IPluggableStorageWrapper implementation that stores items in memory.
* The `_cache` property is the object were items are stored.
* Intended for testing purposes.
*
* @param connDelay delay in millis for `connect` resolve. If not provided, `connect` resolves inmediatelly.
*/
export function inMemoryWrapperFactory(connDelay?: number): ICustomStorageWrapper & { _cache: Record<string, string | string[] | ISet<string>>, _setConnDelay(connDelay: number): void } {
export function inMemoryWrapperFactory(connDelay?: number): IPluggableStorageWrapper & { _cache: Record<string, string | string[] | ISet<string>>, _setConnDelay(connDelay: number): void } {

let _cache: Record<string, string | string[] | ISet<string>> = {};
let _connDelay = connDelay;
Expand Down
12 changes: 6 additions & 6 deletions src/storages/pluggable/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ICustomStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams } from '../types';
import { IPluggableStorageWrapper, IStorageAsync, IStorageAsyncFactory, IStorageFactoryParams } from '../types';

import KeyBuilderSS from '../KeyBuilderSS';
import { SplitsCachePluggable } from './SplitsCachePluggable';
Expand All @@ -8,17 +8,17 @@ import { EventsCachePluggable } from './EventsCachePluggable';
import { wrapperAdapter, METHODS_TO_PROMISE_WRAP } from './wrapperAdapter';
import { isObject } from '../../utils/lang';
import { validatePrefix } from '../KeyBuilder';
import { CONSUMER_PARTIAL_MODE, STORAGE_CUSTOM } from '../../utils/constants';
import { CONSUMER_PARTIAL_MODE, STORAGE_PLUGGABLE } from '../../utils/constants';
import ImpressionsCacheInMemory from '../inMemory/ImpressionsCacheInMemory';
import EventsCacheInMemory from '../inMemory/EventsCacheInMemory';
import ImpressionCountsCacheInMemory from '../inMemory/ImpressionCountsCacheInMemory';

const NO_VALID_WRAPPER = 'Expecting custom storage `wrapper` in options, but no valid wrapper instance was provided.';
const NO_VALID_WRAPPER = 'Expecting pluggable storage `wrapper` in options, but no valid wrapper instance was provided.';
const NO_VALID_WRAPPER_INTERFACE = 'The provided wrapper instance doesn’t follow the expected interface. Check our docs.';

export interface PluggableStorageOptions {
prefix?: string
wrapper: ICustomStorageWrapper
wrapper: IPluggableStorageWrapper
}

/**
Expand All @@ -36,7 +36,7 @@ function validatePluggableStorageOptions(options: any) {
}

// subscription to wrapper connect event in order to emit SDK_READY event
function wrapperConnect(wrapper: ICustomStorageWrapper, onReadyCb: (error?: any) => void) {
function wrapperConnect(wrapper: IPluggableStorageWrapper, onReadyCb: (error?: any) => void) {
wrapper.connect().then(() => {
onReadyCb();
}).catch((e) => {
Expand Down Expand Up @@ -96,6 +96,6 @@ export function PluggableStorage(options: PluggableStorageOptions): IStorageAsyn
};
}

PluggableStorageFactory.type = STORAGE_CUSTOM;
PluggableStorageFactory.type = STORAGE_PLUGGABLE;
return PluggableStorageFactory;
}
8 changes: 4 additions & 4 deletions src/storages/pluggable/wrapperAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ILogger } from '../../logger/types';
import { ICustomStorageWrapper } from '../types';
import { IPluggableStorageWrapper } from '../types';
import { LOG_PREFIX } from './constants';

export const METHODS_TO_PROMISE_WRAP: string[] = [
Expand All @@ -23,14 +23,14 @@ export const METHODS_TO_PROMISE_WRAP: string[] = [
];

/**
* Adapter of the Custom Storage Wrapper.
* Adapter of the Pluggable Storage Wrapper.
* Used to handle exceptions as rejected promises, in order to simplify the error handling on storages.
*
* @param log logger instance
* @param wrapper custom storage wrapper to adapt
* @param wrapper storage wrapper to adapt
* @returns an adapted version of the given storage wrapper
*/
export function wrapperAdapter(log: ILogger, wrapper: ICustomStorageWrapper): ICustomStorageWrapper {
export function wrapperAdapter(log: ILogger, wrapper: IPluggableStorageWrapper): IPluggableStorageWrapper {

const wrapperAdapter: Record<string, Function> = {};

Expand Down
8 changes: 4 additions & 4 deletions src/storages/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { StoredEventWithMetadata, StoredImpressionWithMetadata } from '../sync/s
import { SplitIO, ImpressionDTO, SDKMode } from '../types';

/**
* Interface of a custom storage wrapper.
* Interface of a pluggable storage wrapper.
*/
export interface ICustomStorageWrapper {
export interface IPluggableStorageWrapper {

/** Key-Value operations */

Expand Down Expand Up @@ -430,7 +430,7 @@ export interface IStorageFactoryParams {
matchingKey?: string, /* undefined on server-side SDKs */
splitFiltersValidation?: ISplitFiltersValidation,

// ATM, only used by CustomStorage
// ATM, only used by PluggableStorage
mode?: SDKMode,

// This callback is invoked when the storage is ready to be used. Error-first callback style: if an error is passed,
Expand All @@ -440,7 +440,7 @@ export interface IStorageFactoryParams {
metadata: IMetadata,
}

export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'CUSTOM';
export type StorageType = 'MEMORY' | 'LOCALSTORAGE' | 'REDIS' | 'PLUGGABLE';

export type IStorageSyncFactory = {
type: StorageType,
Expand Down
2 changes: 1 addition & 1 deletion src/sync/polling/updaters/mySegmentsUpdater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function mySegmentsUpdaterFactory(
// mySegmentsPromise = tracker.start(tracker.TaskNames.MY_SEGMENTS_FETCH, startingUp ? metricCollectors : false, mySegmentsPromise);
}

// @TODO if allowing custom storages, handle async execution
// @TODO if allowing pluggable storages, handle async execution
function updateSegments(segmentsData: SegmentsData) {

let shouldNotifyUpdate;
Expand Down
Loading